diff --git a/CMakeLists.txt b/CMakeLists.txt index b45b788829..bfe5cbf325 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,6 @@ if(CAPSTONE_AARCH64_SUPPORT) arch/AArch64/AArch64GenDisassemblerTables.inc arch/AArch64/AArch64GenInstrInfo.inc arch/AArch64/AArch64GenRegisterInfo.inc - arch/AArch64/AArch64GenRegisterName.inc arch/AArch64/AArch64GenSubtargetInfo.inc arch/AArch64/AArch64GenSystemOperands.inc arch/AArch64/AArch64GenCSMappingInsn.inc diff --git a/arch/AArch64/AArch64GenRegisterName.inc b/arch/AArch64/AArch64GenRegisterName.inc deleted file mode 100644 index 40382d5758..0000000000 --- a/arch/AArch64/AArch64GenRegisterName.inc +++ /dev/null @@ -1,714 +0,0 @@ -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/// getRegisterName - This method is automatically generated by tblgen -/// from the register set description. This returns the assembler name -/// for the specified register. -static const char *getRegisterName(unsigned RegNo, unsigned AltIdx) -{ - - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverlength-strings" -#endif -#ifndef CAPSTONE_DIET - static const char AsmStrsNoRegAltName[] = { - /* 0 */ "D7_D8_D9_D10\0" - /* 13 */ "Q7_Q8_Q9_Q10\0" - /* 26 */ "Z7_Z8_Z9_Z10\0" - /* 39 */ "b10\0" - /* 43 */ "d10\0" - /* 47 */ "h10\0" - /* 51 */ "p10\0" - /* 55 */ "q10\0" - /* 59 */ "s10\0" - /* 63 */ "w10\0" - /* 67 */ "x10\0" - /* 71 */ "z10\0" - /* 75 */ "D17_D18_D19_D20\0" - /* 91 */ "Q17_Q18_Q19_Q20\0" - /* 107 */ "Z17_Z18_Z19_Z20\0" - /* 123 */ "b20\0" - /* 127 */ "d20\0" - /* 131 */ "h20\0" - /* 135 */ "q20\0" - /* 139 */ "s20\0" - /* 143 */ "w20\0" - /* 147 */ "x20\0" - /* 151 */ "z20\0" - /* 155 */ "D27_D28_D29_D30\0" - /* 171 */ "Q27_Q28_Q29_Q30\0" - /* 187 */ "Z27_Z28_Z29_Z30\0" - /* 203 */ "b30\0" - /* 207 */ "d30\0" - /* 211 */ "h30\0" - /* 215 */ "q30\0" - /* 219 */ "s30\0" - /* 223 */ "w30\0" - /* 227 */ "x30\0" - /* 231 */ "z30\0" - /* 235 */ "D29_D30_D31_D0\0" - /* 250 */ "Q29_Q30_Q31_Q0\0" - /* 265 */ "Z29_Z30_Z31_Z0\0" - /* 280 */ "b0\0" - /* 283 */ "d0\0" - /* 286 */ "h0\0" - /* 289 */ "p0\0" - /* 292 */ "q0\0" - /* 295 */ "s0\0" - /* 298 */ "w0\0" - /* 301 */ "x0\0" - /* 304 */ "z0\0" - /* 307 */ "D8_D9_D10_D11\0" - /* 321 */ "Q8_Q9_Q10_Q11\0" - /* 335 */ "W10_W11\0" - /* 343 */ "X4_X5_X6_X7_X8_X9_X10_X11\0" - /* 369 */ "Z8_Z9_Z10_Z11\0" - /* 383 */ "b11\0" - /* 387 */ "d11\0" - /* 391 */ "h11\0" - /* 395 */ "p11\0" - /* 399 */ "q11\0" - /* 403 */ "s11\0" - /* 407 */ "w11\0" - /* 411 */ "x11\0" - /* 415 */ "z11\0" - /* 419 */ "D18_D19_D20_D21\0" - /* 435 */ "Q18_Q19_Q20_Q21\0" - /* 451 */ "W20_W21\0" - /* 459 */ "X14_X15_X16_X17_X18_X19_X20_X21\0" - /* 491 */ "Z18_Z19_Z20_Z21\0" - /* 507 */ "b21\0" - /* 511 */ "d21\0" - /* 515 */ "h21\0" - /* 519 */ "q21\0" - /* 523 */ "s21\0" - /* 527 */ "w21\0" - /* 531 */ "x21\0" - /* 535 */ "z21\0" - /* 539 */ "D28_D29_D30_D31\0" - /* 555 */ "Q28_Q29_Q30_Q31\0" - /* 571 */ "Z28_Z29_Z30_Z31\0" - /* 587 */ "b31\0" - /* 591 */ "d31\0" - /* 595 */ "h31\0" - /* 599 */ "q31\0" - /* 603 */ "s31\0" - /* 607 */ "z31\0" - /* 611 */ "D30_D31_D0_D1\0" - /* 625 */ "Q30_Q31_Q0_Q1\0" - /* 639 */ "W0_W1\0" - /* 645 */ "X0_X1\0" - /* 651 */ "Z30_Z31_Z0_Z1\0" - /* 665 */ "b1\0" - /* 668 */ "d1\0" - /* 671 */ "h1\0" - /* 674 */ "p1\0" - /* 677 */ "q1\0" - /* 680 */ "s1\0" - /* 683 */ "w1\0" - /* 686 */ "x1\0" - /* 689 */ "z1\0" - /* 692 */ "D9_D10_D11_D12\0" - /* 707 */ "Q9_Q10_Q11_Q12\0" - /* 722 */ "Z9_Z10_Z11_Z12\0" - /* 737 */ "b12\0" - /* 741 */ "d12\0" - /* 745 */ "h12\0" - /* 749 */ "p12\0" - /* 753 */ "q12\0" - /* 757 */ "s12\0" - /* 761 */ "w12\0" - /* 765 */ "x12\0" - /* 769 */ "z12\0" - /* 773 */ "D19_D20_D21_D22\0" - /* 789 */ "Q19_Q20_Q21_Q22\0" - /* 805 */ "Z19_Z20_Z21_Z22\0" - /* 821 */ "b22\0" - /* 825 */ "d22\0" - /* 829 */ "h22\0" - /* 833 */ "q22\0" - /* 837 */ "s22\0" - /* 841 */ "w22\0" - /* 845 */ "x22\0" - /* 849 */ "z22\0" - /* 853 */ "D31_D0_D1_D2\0" - /* 866 */ "Q31_Q0_Q1_Q2\0" - /* 879 */ "Z31_Z0_Z1_Z2\0" - /* 892 */ "b2\0" - /* 895 */ "d2\0" - /* 898 */ "h2\0" - /* 901 */ "p2\0" - /* 904 */ "q2\0" - /* 907 */ "s2\0" - /* 910 */ "w2\0" - /* 913 */ "x2\0" - /* 916 */ "z2\0" - /* 919 */ "D10_D11_D12_D13\0" - /* 935 */ "Q10_Q11_Q12_Q13\0" - /* 951 */ "W12_W13\0" - /* 959 */ "X6_X7_X8_X9_X10_X11_X12_X13\0" - /* 987 */ "Z10_Z11_Z12_Z13\0" - /* 1003 */ "b13\0" - /* 1007 */ "d13\0" - /* 1011 */ "h13\0" - /* 1015 */ "p13\0" - /* 1019 */ "q13\0" - /* 1023 */ "s13\0" - /* 1027 */ "w13\0" - /* 1031 */ "x13\0" - /* 1035 */ "z13\0" - /* 1039 */ "D20_D21_D22_D23\0" - /* 1055 */ "Q20_Q21_Q22_Q23\0" - /* 1071 */ "W22_W23\0" - /* 1079 */ "X16_X17_X18_X19_X20_X21_X22_X23\0" - /* 1111 */ "Z20_Z21_Z22_Z23\0" - /* 1127 */ "b23\0" - /* 1131 */ "d23\0" - /* 1135 */ "h23\0" - /* 1139 */ "q23\0" - /* 1143 */ "s23\0" - /* 1147 */ "w23\0" - /* 1151 */ "x23\0" - /* 1155 */ "z23\0" - /* 1159 */ "D0_D1_D2_D3\0" - /* 1171 */ "Q0_Q1_Q2_Q3\0" - /* 1183 */ "W2_W3\0" - /* 1189 */ "X2_X3\0" - /* 1195 */ "Z0_Z1_Z2_Z3\0" - /* 1207 */ "b3\0" - /* 1210 */ "d3\0" - /* 1213 */ "h3\0" - /* 1216 */ "p3\0" - /* 1219 */ "q3\0" - /* 1222 */ "s3\0" - /* 1225 */ "w3\0" - /* 1228 */ "x3\0" - /* 1231 */ "z3\0" - /* 1234 */ "D11_D12_D13_D14\0" - /* 1250 */ "Q11_Q12_Q13_Q14\0" - /* 1266 */ "Z11_Z12_Z13_Z14\0" - /* 1282 */ "b14\0" - /* 1286 */ "d14\0" - /* 1290 */ "h14\0" - /* 1294 */ "p14\0" - /* 1298 */ "q14\0" - /* 1302 */ "s14\0" - /* 1306 */ "w14\0" - /* 1310 */ "x14\0" - /* 1314 */ "z14\0" - /* 1318 */ "D21_D22_D23_D24\0" - /* 1334 */ "Q21_Q22_Q23_Q24\0" - /* 1350 */ "Z21_Z22_Z23_Z24\0" - /* 1366 */ "b24\0" - /* 1370 */ "d24\0" - /* 1374 */ "h24\0" - /* 1378 */ "q24\0" - /* 1382 */ "s24\0" - /* 1386 */ "w24\0" - /* 1390 */ "x24\0" - /* 1394 */ "z24\0" - /* 1398 */ "D1_D2_D3_D4\0" - /* 1410 */ "Q1_Q2_Q3_Q4\0" - /* 1422 */ "Z1_Z2_Z3_Z4\0" - /* 1434 */ "b4\0" - /* 1437 */ "d4\0" - /* 1440 */ "h4\0" - /* 1443 */ "p4\0" - /* 1446 */ "q4\0" - /* 1449 */ "s4\0" - /* 1452 */ "w4\0" - /* 1455 */ "x4\0" - /* 1458 */ "z4\0" - /* 1461 */ "D12_D13_D14_D15\0" - /* 1477 */ "Q12_Q13_Q14_Q15\0" - /* 1493 */ "W14_W15\0" - /* 1501 */ "X8_X9_X10_X11_X12_X13_X14_X15\0" - /* 1531 */ "Z12_Z13_Z14_Z15\0" - /* 1547 */ "b15\0" - /* 1551 */ "d15\0" - /* 1555 */ "h15\0" - /* 1559 */ "p15\0" - /* 1563 */ "q15\0" - /* 1567 */ "s15\0" - /* 1571 */ "w15\0" - /* 1575 */ "x15\0" - /* 1579 */ "z15\0" - /* 1583 */ "D22_D23_D24_D25\0" - /* 1599 */ "Q22_Q23_Q24_Q25\0" - /* 1615 */ "W24_W25\0" - /* 1623 */ "X18_X19_X20_X21_X22_X23_X24_X25\0" - /* 1655 */ "Z22_Z23_Z24_Z25\0" - /* 1671 */ "b25\0" - /* 1675 */ "d25\0" - /* 1679 */ "h25\0" - /* 1683 */ "q25\0" - /* 1687 */ "s25\0" - /* 1691 */ "w25\0" - /* 1695 */ "x25\0" - /* 1699 */ "z25\0" - /* 1703 */ "D2_D3_D4_D5\0" - /* 1715 */ "Q2_Q3_Q4_Q5\0" - /* 1727 */ "W4_W5\0" - /* 1733 */ "X4_X5\0" - /* 1739 */ "Z2_Z3_Z4_Z5\0" - /* 1751 */ "b5\0" - /* 1754 */ "d5\0" - /* 1757 */ "h5\0" - /* 1760 */ "p5\0" - /* 1763 */ "q5\0" - /* 1766 */ "s5\0" - /* 1769 */ "w5\0" - /* 1772 */ "x5\0" - /* 1775 */ "z5\0" - /* 1778 */ "D13_D14_D15_D16\0" - /* 1794 */ "Q13_Q14_Q15_Q16\0" - /* 1810 */ "Z13_Z14_Z15_Z16\0" - /* 1826 */ "b16\0" - /* 1830 */ "d16\0" - /* 1834 */ "h16\0" - /* 1838 */ "q16\0" - /* 1842 */ "s16\0" - /* 1846 */ "w16\0" - /* 1850 */ "x16\0" - /* 1854 */ "z16\0" - /* 1858 */ "D23_D24_D25_D26\0" - /* 1874 */ "Q23_Q24_Q25_Q26\0" - /* 1890 */ "Z23_Z24_Z25_Z26\0" - /* 1906 */ "b26\0" - /* 1910 */ "d26\0" - /* 1914 */ "h26\0" - /* 1918 */ "q26\0" - /* 1922 */ "s26\0" - /* 1926 */ "w26\0" - /* 1930 */ "x26\0" - /* 1934 */ "z26\0" - /* 1938 */ "D3_D4_D5_D6\0" - /* 1950 */ "Q3_Q4_Q5_Q6\0" - /* 1962 */ "Z3_Z4_Z5_Z6\0" - /* 1974 */ "b6\0" - /* 1977 */ "d6\0" - /* 1980 */ "h6\0" - /* 1983 */ "p6\0" - /* 1986 */ "q6\0" - /* 1989 */ "s6\0" - /* 1992 */ "w6\0" - /* 1995 */ "x6\0" - /* 1998 */ "z6\0" - /* 2001 */ "D14_D15_D16_D17\0" - /* 2017 */ "Q14_Q15_Q16_Q17\0" - /* 2033 */ "W16_W17\0" - /* 2041 */ "X10_X11_X12_X13_X14_X15_X16_X17\0" - /* 2073 */ "Z14_Z15_Z16_Z17\0" - /* 2089 */ "b17\0" - /* 2093 */ "d17\0" - /* 2097 */ "h17\0" - /* 2101 */ "q17\0" - /* 2105 */ "s17\0" - /* 2109 */ "w17\0" - /* 2113 */ "x17\0" - /* 2117 */ "z17\0" - /* 2121 */ "D24_D25_D26_D27\0" - /* 2137 */ "Q24_Q25_Q26_Q27\0" - /* 2153 */ "W26_W27\0" - /* 2161 */ "X20_X21_X22_X23_X24_X25_X26_X27\0" - /* 2193 */ "Z24_Z25_Z26_Z27\0" - /* 2209 */ "b27\0" - /* 2213 */ "d27\0" - /* 2217 */ "h27\0" - /* 2221 */ "q27\0" - /* 2225 */ "s27\0" - /* 2229 */ "w27\0" - /* 2233 */ "x27\0" - /* 2237 */ "z27\0" - /* 2241 */ "D4_D5_D6_D7\0" - /* 2253 */ "Q4_Q5_Q6_Q7\0" - /* 2265 */ "W6_W7\0" - /* 2271 */ "X0_X1_X2_X3_X4_X5_X6_X7\0" - /* 2295 */ "Z4_Z5_Z6_Z7\0" - /* 2307 */ "b7\0" - /* 2310 */ "d7\0" - /* 2313 */ "h7\0" - /* 2316 */ "p7\0" - /* 2319 */ "q7\0" - /* 2322 */ "s7\0" - /* 2325 */ "w7\0" - /* 2328 */ "x7\0" - /* 2331 */ "z7\0" - /* 2334 */ "D15_D16_D17_D18\0" - /* 2350 */ "Q15_Q16_Q17_Q18\0" - /* 2366 */ "Z15_Z16_Z17_Z18\0" - /* 2382 */ "b18\0" - /* 2386 */ "d18\0" - /* 2390 */ "h18\0" - /* 2394 */ "q18\0" - /* 2398 */ "s18\0" - /* 2402 */ "w18\0" - /* 2406 */ "x18\0" - /* 2410 */ "z18\0" - /* 2414 */ "D25_D26_D27_D28\0" - /* 2430 */ "Q25_Q26_Q27_Q28\0" - /* 2446 */ "Z25_Z26_Z27_Z28\0" - /* 2462 */ "b28\0" - /* 2466 */ "d28\0" - /* 2470 */ "h28\0" - /* 2474 */ "q28\0" - /* 2478 */ "s28\0" - /* 2482 */ "w28\0" - /* 2486 */ "x28\0" - /* 2490 */ "z28\0" - /* 2494 */ "D5_D6_D7_D8\0" - /* 2506 */ "Q5_Q6_Q7_Q8\0" - /* 2518 */ "Z5_Z6_Z7_Z8\0" - /* 2530 */ "b8\0" - /* 2533 */ "d8\0" - /* 2536 */ "h8\0" - /* 2539 */ "p8\0" - /* 2542 */ "q8\0" - /* 2545 */ "s8\0" - /* 2548 */ "w8\0" - /* 2551 */ "x8\0" - /* 2554 */ "z8\0" - /* 2557 */ "D16_D17_D18_D19\0" - /* 2573 */ "Q16_Q17_Q18_Q19\0" - /* 2589 */ "W18_W19\0" - /* 2597 */ "X12_X13_X14_X15_X16_X17_X18_X19\0" - /* 2629 */ "Z16_Z17_Z18_Z19\0" - /* 2645 */ "b19\0" - /* 2649 */ "d19\0" - /* 2653 */ "h19\0" - /* 2657 */ "q19\0" - /* 2661 */ "s19\0" - /* 2665 */ "w19\0" - /* 2669 */ "x19\0" - /* 2673 */ "z19\0" - /* 2677 */ "D26_D27_D28_D29\0" - /* 2693 */ "Q26_Q27_Q28_Q29\0" - /* 2709 */ "W28_W29\0" - /* 2717 */ "Z26_Z27_Z28_Z29\0" - /* 2733 */ "b29\0" - /* 2737 */ "d29\0" - /* 2741 */ "h29\0" - /* 2745 */ "q29\0" - /* 2749 */ "s29\0" - /* 2753 */ "w29\0" - /* 2757 */ "x29\0" - /* 2761 */ "z29\0" - /* 2765 */ "D6_D7_D8_D9\0" - /* 2777 */ "Q6_Q7_Q8_Q9\0" - /* 2789 */ "W8_W9\0" - /* 2795 */ "X2_X3_X4_X5_X6_X7_X8_X9\0" - /* 2819 */ "Z6_Z7_Z8_Z9\0" - /* 2831 */ "b9\0" - /* 2834 */ "d9\0" - /* 2837 */ "h9\0" - /* 2840 */ "p9\0" - /* 2843 */ "q9\0" - /* 2846 */ "s9\0" - /* 2849 */ "w9\0" - /* 2852 */ "x9\0" - /* 2855 */ "z9\0" - /* 2858 */ "X22_X23_X24_X25_X26_X27_X28_FP\0" - /* 2889 */ "W30_WZR\0" - /* 2897 */ "LR_XZR\0" - /* 2904 */ "za\0" - /* 2907 */ "za0.b\0" - /* 2913 */ "za0.d\0" - /* 2919 */ "za1.d\0" - /* 2925 */ "za2.d\0" - /* 2931 */ "za3.d\0" - /* 2937 */ "za4.d\0" - /* 2943 */ "za5.d\0" - /* 2949 */ "za6.d\0" - /* 2955 */ "za7.d\0" - /* 2961 */ "vg\0" - /* 2964 */ "za0.h\0" - /* 2970 */ "za1.h\0" - /* 2976 */ "z10_hi\0" - /* 2983 */ "z20_hi\0" - /* 2990 */ "z30_hi\0" - /* 2997 */ "z0_hi\0" - /* 3003 */ "z11_hi\0" - /* 3010 */ "z21_hi\0" - /* 3017 */ "z31_hi\0" - /* 3024 */ "z1_hi\0" - /* 3030 */ "z12_hi\0" - /* 3037 */ "z22_hi\0" - /* 3044 */ "z2_hi\0" - /* 3050 */ "z13_hi\0" - /* 3057 */ "z23_hi\0" - /* 3064 */ "z3_hi\0" - /* 3070 */ "z14_hi\0" - /* 3077 */ "z24_hi\0" - /* 3084 */ "z4_hi\0" - /* 3090 */ "z15_hi\0" - /* 3097 */ "z25_hi\0" - /* 3104 */ "z5_hi\0" - /* 3110 */ "z16_hi\0" - /* 3117 */ "z26_hi\0" - /* 3124 */ "z6_hi\0" - /* 3130 */ "z17_hi\0" - /* 3137 */ "z27_hi\0" - /* 3144 */ "z7_hi\0" - /* 3150 */ "z18_hi\0" - /* 3157 */ "z28_hi\0" - /* 3164 */ "z8_hi\0" - /* 3170 */ "z19_hi\0" - /* 3177 */ "z29_hi\0" - /* 3184 */ "z9_hi\0" - /* 3190 */ "wsp\0" - /* 3194 */ "za10.q\0" - /* 3201 */ "za0.q\0" - /* 3207 */ "za11.q\0" - /* 3214 */ "za1.q\0" - /* 3220 */ "za12.q\0" - /* 3227 */ "za2.q\0" - /* 3233 */ "za13.q\0" - /* 3240 */ "za3.q\0" - /* 3246 */ "za14.q\0" - /* 3253 */ "za4.q\0" - /* 3259 */ "za15.q\0" - /* 3266 */ "za5.q\0" - /* 3272 */ "za6.q\0" - /* 3278 */ "za7.q\0" - /* 3284 */ "za8.q\0" - /* 3290 */ "za9.q\0" - /* 3296 */ "ffr\0" - /* 3300 */ "wzr\0" - /* 3304 */ "xzr\0" - /* 3308 */ "za0.s\0" - /* 3314 */ "za1.s\0" - /* 3320 */ "za2.s\0" - /* 3326 */ "za3.s\0" - /* 3332 */ "nzcv\0" -}; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - - static const uint16_t RegAsmOffsetNoRegAltName[] = { - 3296, 2757, 227, 3332, 3191, 2961, 3190, 3300, 3304, 2904, 280, 665, 892, 1207, - 1434, 1751, 1974, 2307, 2530, 2831, 39, 383, 737, 1003, 1282, 1547, 1826, 2089, - 2382, 2645, 123, 507, 821, 1127, 1366, 1671, 1906, 2209, 2462, 2733, 203, 587, - 283, 668, 895, 1210, 1437, 1754, 1977, 2310, 2533, 2834, 43, 387, 741, 1007, - 1286, 1551, 1830, 2093, 2386, 2649, 127, 511, 825, 1131, 1370, 1675, 1910, 2213, - 2466, 2737, 207, 591, 286, 671, 898, 1213, 1440, 1757, 1980, 2313, 2536, 2837, - 47, 391, 745, 1011, 1290, 1555, 1834, 2097, 2390, 2653, 131, 515, 829, 1135, - 1374, 1679, 1914, 2217, 2470, 2741, 211, 595, 289, 674, 901, 1216, 1443, 1760, - 1983, 2316, 2539, 2840, 51, 395, 749, 1015, 1294, 1559, 292, 677, 904, 1219, - 1446, 1763, 1986, 2319, 2542, 2843, 55, 399, 753, 1019, 1298, 1563, 1838, 2101, - 2394, 2657, 135, 519, 833, 1139, 1378, 1683, 1918, 2221, 2474, 2745, 215, 599, - 295, 680, 907, 1222, 1449, 1766, 1989, 2322, 2545, 2846, 59, 403, 757, 1023, - 1302, 1567, 1842, 2105, 2398, 2661, 139, 523, 837, 1143, 1382, 1687, 1922, 2225, - 2478, 2749, 219, 603, 298, 683, 910, 1225, 1452, 1769, 1992, 2325, 2548, 2849, - 63, 407, 761, 1027, 1306, 1571, 1846, 2109, 2402, 2665, 143, 527, 841, 1147, - 1386, 1691, 1926, 2229, 2482, 2753, 223, 301, 686, 913, 1228, 1455, 1772, 1995, - 2328, 2551, 2852, 67, 411, 765, 1031, 1310, 1575, 1850, 2113, 2406, 2669, 147, - 531, 845, 1151, 1390, 1695, 1930, 2233, 2486, 304, 689, 916, 1231, 1458, 1775, - 1998, 2331, 2554, 2855, 71, 415, 769, 1035, 1314, 1579, 1854, 2117, 2410, 2673, - 151, 535, 849, 1155, 1394, 1699, 1934, 2237, 2490, 2761, 231, 607, 2907, 2913, - 2919, 2925, 2931, 2937, 2943, 2949, 2955, 2964, 2970, 3201, 3214, 3227, 3240, 3253, - 3266, 3272, 3278, 3284, 3290, 3194, 3207, 3220, 3233, 3246, 3259, 3308, 3314, 3320, - 3326, 2997, 3024, 3044, 3064, 3084, 3104, 3124, 3144, 3164, 3184, 2976, 3003, 3030, - 3050, 3070, 3090, 3110, 3130, 3150, 3170, 2983, 3010, 3037, 3057, 3077, 3097, 3117, - 3137, 3157, 3177, 2990, 3017, 619, 860, 1165, 1404, 1709, 1944, 2247, 2500, 2771, - 6, 313, 699, 927, 1242, 1469, 1786, 2009, 2342, 2565, 83, 427, 781, 1047, - 1326, 1591, 1866, 2129, 2422, 2685, 163, 547, 243, 1159, 1398, 1703, 1938, 2241, - 2494, 2765, 0, 307, 692, 919, 1234, 1461, 1778, 2001, 2334, 2557, 75, 419, - 773, 1039, 1318, 1583, 1858, 2121, 2414, 2677, 155, 539, 235, 611, 853, 857, - 1162, 1401, 1706, 1941, 2244, 2497, 2768, 3, 310, 695, 923, 1238, 1465, 1782, - 2005, 2338, 2561, 79, 423, 777, 1043, 1322, 1587, 1862, 2125, 2418, 2681, 159, - 543, 239, 615, 633, 873, 1177, 1416, 1721, 1956, 2259, 2512, 2783, 19, 327, - 714, 943, 1258, 1485, 1802, 2025, 2358, 2581, 99, 443, 797, 1063, 1342, 1607, - 1882, 2145, 2438, 2701, 179, 563, 258, 1171, 1410, 1715, 1950, 2253, 2506, 2777, - 13, 321, 707, 935, 1250, 1477, 1794, 2017, 2350, 2573, 91, 435, 789, 1055, - 1334, 1599, 1874, 2137, 2430, 2693, 171, 555, 250, 625, 866, 870, 1174, 1413, - 1718, 1953, 2256, 2509, 2780, 16, 324, 710, 939, 1254, 1481, 1798, 2021, 2354, - 2577, 95, 439, 793, 1059, 1338, 1603, 1878, 2141, 2434, 2697, 175, 559, 254, - 629, 2858, 2271, 2795, 343, 959, 1501, 2041, 2597, 459, 1079, 1623, 2161, 2889, - 639, 1183, 1727, 2265, 2789, 335, 951, 1493, 2033, 2589, 451, 1071, 1615, 2153, - 2709, 2897, 2882, 645, 1189, 1733, 2289, 2813, 361, 979, 1523, 2065, 2621, 483, - 1103, 1647, 2185, 659, 886, 1201, 1428, 1745, 1968, 2301, 2524, 2825, 32, 375, - 729, 995, 1274, 1539, 1818, 2081, 2374, 2637, 115, 499, 813, 1119, 1358, 1663, - 1898, 2201, 2454, 2725, 195, 579, 273, 1195, 1422, 1739, 1962, 2295, 2518, 2819, - 26, 369, 722, 987, 1266, 1531, 1810, 2073, 2366, 2629, 107, 491, 805, 1111, - 1350, 1655, 1890, 2193, 2446, 2717, 187, 571, 265, 651, 879, 883, 1198, 1425, - 1742, 1965, 2298, 2521, 2822, 29, 372, 725, 991, 1270, 1535, 1814, 2077, 2370, - 2633, 111, 495, 809, 1115, 1354, 1659, 1894, 2197, 2450, 2721, 191, 575, 269, - 655, - }; - - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverlength-strings" -#endif - static const char AsmStrsvlist1[] = { - /* 0 */ "\0" -}; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - - static const uint8_t RegAsmOffsetvlist1[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - }; - - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverlength-strings" -#endif - static const char AsmStrsvreg[] = { - /* 0 */ "v10\0" - /* 4 */ "v20\0" - /* 8 */ "v30\0" - /* 12 */ "v0\0" - /* 15 */ "v11\0" - /* 19 */ "v21\0" - /* 23 */ "v31\0" - /* 27 */ "v1\0" - /* 30 */ "v12\0" - /* 34 */ "v22\0" - /* 38 */ "v2\0" - /* 41 */ "v13\0" - /* 45 */ "v23\0" - /* 49 */ "v3\0" - /* 52 */ "v14\0" - /* 56 */ "v24\0" - /* 60 */ "v4\0" - /* 63 */ "v15\0" - /* 67 */ "v25\0" - /* 71 */ "v5\0" - /* 74 */ "v16\0" - /* 78 */ "v26\0" - /* 82 */ "v6\0" - /* 85 */ "v17\0" - /* 89 */ "v27\0" - /* 93 */ "v7\0" - /* 96 */ "v18\0" - /* 100 */ "v28\0" - /* 104 */ "v8\0" - /* 107 */ "v19\0" - /* 111 */ "v29\0" - /* 115 */ "v9\0" -}; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - - static const uint8_t RegAsmOffsetvreg[] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 12, 27, 38, 49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, - 52, 63, 74, 85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, - 100, 111, 8, 23, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12, 27, 38, 49, - 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85, - 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 12, 27, 38, 49, 60, 71, 82, 93, 104, - 115, 0, 15, 30, 41, 52, 63, 74, 85, 96, 107, 4, 19, 34, - 45, 56, 67, 78, 89, 100, 111, 8, 23, 12, 27, 38, 49, 60, - 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85, 96, - 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23, 12, - 27, 38, 49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, - 63, 74, 85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, - 111, 8, 23, 12, 27, 38, 49, 60, 71, 82, 93, 104, 115, 0, - 15, 30, 41, 52, 63, 74, 85, 96, 107, 4, 19, 34, 45, 56, - 67, 78, 89, 100, 111, 8, 23, 12, 27, 38, 49, 60, 71, 82, - 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85, 96, 107, 4, - 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23, 12, 27, 38, - 49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, - 85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, - 23, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, - }; - - switch(AltIdx) { - default: - return (const char *)(sizeof(RegAsmOffsetvreg)/sizeof(RegAsmOffsetvreg[0])); - case AArch64_NoRegAltName: - return AsmStrsNoRegAltName+RegAsmOffsetNoRegAltName[RegNo-1]; - case AArch64_vlist1: - return AsmStrsvlist1+RegAsmOffsetvlist1[RegNo-1]; - case AArch64_vreg: - return AsmStrsvreg+RegAsmOffsetvreg[RegNo-1]; - } -#else - return NULL; -#endif -} diff --git a/suite/autogen_x86imm.py b/suite/autogen_x86imm.py deleted file mode 100755 index a764b81a65..0000000000 --- a/suite/autogen_x86imm.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# By Nguyen Anh Quynh, 2015 -# This tool extract sizes of immediate operands from X86 instruction names. -# Syntax: ./autogen_x86imm.py - -# Gather immediate sizes to put into X86ImmSize.inc -OUTPUT = "../arch/X86/X86ImmSize.inc" - -f = open("../arch/X86/X86GenInstrInfo.inc") -f2 = open(OUTPUT, "w") -for line in f.readlines(): - tmp = line.strip().split("=") - if len(tmp) == 2: # X86_xxx = nnn, - name = tmp[0].strip() - if name == "X86_INSTRUCTION_LIST_END": # no more instructions - break - if name.endswith("_DB"): # pseudo instruction - continue - if "_LOCK_" in name or "BEXTR" in name: # exception - continue - if name.startswith("X86_"): # instruction - if name.endswith("16mi8"): - f2.write("{2, %s},\n" %name) - elif name.endswith("16ri8"): - f2.write("{2, %s},\n" %name) - elif name.endswith("32ri8"): - f2.write("{4, %s},\n" %name) - elif name.endswith("32mi8"): - f2.write("{4, %s},\n" %name) - elif name.endswith("64i32"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64mi32"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64ri32"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64ri8"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64mi8"): - f2.write("{8, %s},\n" %name) - elif name.endswith("16rmi8"): - f2.write("{2, %s},\n" %name) - elif name.endswith("32rmi8"): - f2.write("{4, %s},\n" %name) - elif name.endswith("16rri8"): - f2.write("{2, %s},\n" %name) - elif name.endswith("32rri8"): - f2.write("{4, %s},\n" %name) - elif name.endswith("64rmi8"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64rmi32"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64rri32"): - f2.write("{8, %s},\n" %name) - elif name.endswith("64rri8"): - f2.write("{8, %s},\n" %name) - elif name.endswith("32ri64"): # special case - f2.write("{8, %s},\n" %name) - elif name.endswith("16i8"): # special case - f2.write("{2, %s},\n" %name) - elif name.endswith("32i8"): # special case - f2.write("{4, %s},\n" %name) - elif name.endswith("64i16"): # special case - f2.write("{8, %s},\n" %name) - elif name.endswith("64i8"): # special case - f2.write("{8, %s},\n" %name) - - elif name.endswith("i8") or "i8_" in name: - f2.write("{1, %s},\n" %name) - elif "8ri" in name or "8mi" in name: - f2.write("{1, %s},\n" %name) - - elif name.endswith("i16") or "i16_" in name: - f2.write("{2, %s},\n" %name) - elif "16ri" in name or "16mi" in name: - f2.write("{2, %s},\n" %name) - - elif name.endswith("i32") or "i32_" in name: - f2.write("{4, %s},\n" %name) - elif "32ri" in name or "32mi" in name: - f2.write("{4, %s},\n" %name) - - elif name.endswith("i64") or "i64_" in name: - f2.write("{8, %s},\n" %name) - elif "64ri" in name or "64mi" in name: - f2.write("{8, %s},\n" %name) - -f.close() -f2.close() - -print("Generated %s" %OUTPUT) diff --git a/suite/benchmark.py b/suite/benchmark.py deleted file mode 100755 index ba864d85bd..0000000000 --- a/suite/benchmark.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/python - -# Simple benchmark for Capstone by disassembling random code. By Nguyen Anh Quynh, 2014 -# Syntax: -# ./suite/benchmark.py --> Benchmark all archs -# ./suite/benchmark.py x86 --> Benchmark all X86 (all 16bit, 32bit, 64bit) -# ./suite/benchmark.py x86-32 --> Benchmark X86-32 arch only -# ./suite/benchmark.py arm --> Benchmark all ARM (arm, thumb) -# ./suite/benchmark.py aarch64 --> Benchmark ARM-64 -# ./suite/benchmark.py mips --> Benchmark all Mips (32bit, 64bit) -# ./suite/benchmark.py ppc --> Benchmark PPC - -from capstone import * - -from time import time -from random import randint -import sys - - -# file providing code to disassemble -FILE = '/usr/bin/python' - - -all_tests = ( - (CS_ARCH_X86, CS_MODE_16, "X86-16 (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_32, "X86-32 (ATT syntax)", CS_OPT_SYNTAX_ATT), - (CS_ARCH_X86, CS_MODE_32, "X86-32 (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_64, "X86-64 (Intel syntax)", 0), - (CS_ARCH_ARM, CS_MODE_ARM, "ARM", 0), - (CS_ARCH_ARM, CS_MODE_THUMB, "THUMB (ARM)", 0), - (CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, "MIPS-32 (Big-endian)", 0), - (CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN, "MIPS-64-EL (Little-endian)", 0), - (CS_ARCH_AARCH64, CS_MODE_ARM, "ARM-64 (AArch64)", 0), - (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC", 0), - (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC, print register with number only", CS_OPT_SYNTAX_NOREGNAME), - (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, "Sparc", 0), - (CS_ARCH_SYSZ, 0, "SystemZ", 0), - (CS_ARCH_XCORE, 0, "XCore", 0), - (CS_ARCH_M68K, 0, "M68K", 0), - (CS_ARCH_RISCV, 0, "RISCV", 0), - ) - - -# for debugging -def to_hex(s): - return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK - -def get_code(f, size): - code = f.read(size) - if len(code) != size: # reached end-of-file? - # then reset file position to begin-of-file - f.seek(0) - code = f.read(size) - - return code - - -def cs(md, code): - insns = md.disasm(code, 0) - # uncomment below line to speed up this function 200 times! - # return - for i in insns: - if i.address == 0x100000: - print i - - -def cs_lite(md, code): - insns = md.disasm_lite(code, 0) - for (addr, size, mnem, ops) in insns: - if addr == 0x100000: - print i - - -cfile = open(FILE) - -for (arch, mode, comment, syntax) in all_tests: - try: - request = sys.argv[1] - if not request in comment.lower(): - continue - except: - pass - - print("Platform: %s" %comment) - - try: - md = Cs(arch, mode) - #md.detail = True - - if syntax != 0: - md.syntax = syntax - - # warm up few times - cfile.seek(0) - for i in xrange(3): - code = get_code(cfile, 128) - #print to_hex(code) - #print - cs(md, code) - - # start real benchmark - c_t = 0 - for i in xrange(50000): - code = get_code(cfile, 128) - #print to_hex(code) - #print - - t1 = time() - cs(md, code) - c_t += time() - t1 - - print "Benchmark - full obj:", c_t, "seconds" - print - - cfile.seek(0) - c_t = 0 - for i in xrange(50000): - code = get_code(cfile, 128) - #print to_hex(code) - #print - - t1 = time() - cs_lite(md, code) - c_t += time() - t1 - - print "Benchmark - lite:", c_t, "seconds" - print - except CsError as e: - print("ERROR: %s" %e) diff --git a/suite/benchmark/Makefile b/suite/benchmark/Makefile deleted file mode 100644 index 48bbce2fcf..0000000000 --- a/suite/benchmark/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Sample Makefile for Capstone Disassembly Engine - -LIBNAME = ../../build/libcapstone.a - -all: test_iter_benchmark test_file_benchmark - -test_iter_benchmark: test_iter_benchmark.c - ${CC} $< -O3 -Wall -o $@ -I../../include $(LIBNAME) - -test_file_benchmark: test_file_benchmark.c - ${CC} $< -O3 -Wall -o $@ -I../../include $(LIBNAME) - -# %.o: %.c -# ${CC} -c $< -o $@ - -clean: - rm -rf *.o test_iter_benchmark test_file_benchmark diff --git a/suite/benchmark/README.md b/suite/benchmark/README.md deleted file mode 100644 index 1026d9f710..0000000000 --- a/suite/benchmark/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Benchmark - -## Build capstone - -```bash -mkdir build -cd build -cmake .. - -#This last command is also where you can pass additional CMake configuration flags -#using `-D=`. Then to build use: -cmake --build . --config Release -cd .. -``` - -## Build benchmark - -```bash -cd suite/benchmark -make -``` - -## test_iter_benchmark - -```bash -./test_iter_benchmark -``` - -## test_file_benchmark - -```bash -./test_file_benchmark -``` -The optional `test_file_benchmark` arguments are: - -- `[loop-count]` = optional loop count. Total number of bytes decoded and formatted is ` * [loop-count]` -- `` = offset of the code section (in decimal or 0x hex) -- `` = length of the code section (in decimal or 0x hex) -- `` = 64-bit x86 binary file to decode and format diff --git a/suite/benchmark/load_bin.inc b/suite/benchmark/load_bin.inc deleted file mode 100644 index 5421bd5c3d..0000000000 --- a/suite/benchmark/load_bin.inc +++ /dev/null @@ -1,60 +0,0 @@ -// From https://github.com/athre0z/disas-bench - -#include -#include -#include -#include - - -int read_file_data(uint8_t** buf, const char* filename, size_t file_offset, size_t bin_len) -{ - FILE* f = fopen(filename, "rb"); - if (!f) return 0; - - // Seek to code section - if (fseek(f, (long)file_offset, SEEK_SET)) - { - fclose(f); - return 0; - } - - uint8_t* code = malloc(bin_len); - if (!code) - { - fclose(f); - return 0; - } - - if (fread(code, 1, bin_len, f) != bin_len) - { - fclose(f); - free(code); - return 0; - } - - *buf = code; - - return 1; -} - -int read_file(int argc, char *argv[], uint8_t **buf, size_t *bin_len, size_t *loop_count) -{ - if (argc != 5) - { - fputs("Expected args: \n", stderr); - return 0; - } - - *loop_count = (size_t)strtoull(argv[1], NULL, 0); - size_t file_offset = (size_t)strtoull(argv[2], NULL, 0); - *bin_len = (size_t)strtoull(argv[3], NULL, 0); - const char *filename = argv[4]; - - if (!read_file_data(buf, filename, file_offset, *bin_len)) - { - fprintf(stderr, "Couldn't read `%s`\n", filename); - return 0; - } - - return 1; -} \ No newline at end of file diff --git a/suite/benchmark/test_file_benchmark.c b/suite/benchmark/test_file_benchmark.c deleted file mode 100644 index 3ffe01e63f..0000000000 --- a/suite/benchmark/test_file_benchmark.c +++ /dev/null @@ -1,82 +0,0 @@ -// Modified from https://github.com/athre0z/disas-bench - -#include "./load_bin.inc" -#include - - -int main(int argc, char* argv[]) -{ - csh handle = 0; - cs_insn *insn = NULL; - int ret = 0; - const uint8_t *code_iter = NULL; - size_t code_len_iter = 0; - uint64_t ip = 0; - size_t num_valid_insns = 0; - size_t num_bad_insn = 0; - size_t round; - - if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) - { - fputs("Unable to create Capstone handle\n", stderr); - ret = 1; - goto leave; - } - - uint8_t *code = NULL; - size_t code_len = 0, loop_count = 0; - if (!read_file(argc, argv, &code, &code_len, &loop_count)) - { - ret = 1; - goto leave; - } - - insn = cs_malloc(handle); - if (!insn) - { - fputs("Failed to allocate memory\n", stderr); - ret = 1; - goto leave; - } - - clock_t start_time = clock(); - for (round = 0; round < loop_count; ++round) - { - code_iter = code; - code_len_iter = code_len; - while (code_len_iter > 0) - { - if (!cs_disasm_iter( - handle, - &code_iter, - &code_len_iter, - &ip, - insn - )) - { - ++code_iter; - --code_len_iter; - ++num_bad_insn; - } - else - { - ++num_valid_insns; - } - } - } - clock_t end_time = clock(); - - printf( - "Disassembled %zu instructions (%zu valid, %zu bad), %.2f ms\n", - num_valid_insns + num_bad_insn, - num_valid_insns, - num_bad_insn, - (double)(end_time - start_time) * 1000.0 / CLOCKS_PER_SEC - ); - -leave: - if (insn) cs_free(insn, 1); - if (handle) cs_close(&handle); - if (code) free(code); - return ret; -} \ No newline at end of file diff --git a/suite/benchmark/test_iter_benchmark.c b/suite/benchmark/test_iter_benchmark.c deleted file mode 100644 index 860f2628f9..0000000000 --- a/suite/benchmark/test_iter_benchmark.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Capstone Disassembler Engine */ -/* By bughoho , 2015> */ - -#include -#include -#include - -#include -#include - -static void test() -{ -#define X86_CODE32 "\x53\x8B\xDC\x83\xEC\x08\x83\xE4\xF0\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x83\xEC\x78\xA1\x90\xA3\x4B\x01\x33\xC5 \ -\x89\x45\xFC\x8B\x41\x04\x0F\x28\x05\x80\x30\x20\x01\x0F\x29\x45\xD0\x0F\x28\x05\x50\xAB\x1E\x01\x89\x4D\x90\x89\x45\xB8\x0F\x29 \ -\x45\xE0\x56\x8B\x73\x08\x57\xC7\x06\x00\x00\x00\x00\xC7\x46\x04\x00\x00\x00\x00\xC7\x46\x08\x00\x00\x00\x00\xC7\x46\x0C\x00\x00 \ -\x00\x00\x85\xC0\x0F\x84\xCB\x01\x00\x00\x33\xFF\x8D\x64\x24\x00\x8B\x01\x8B\x0C\x07\x89\x4D\xBC\x85\xC9\x0F\x84\xA6\x01\x00\x00 \ -\x8B\x43\x0C\x0F\x10\x00\x0F\x29\x45\xD0\x0F\x10\x40\x10\x0F\x29\x45\xE0\x8B\x01\x8B\x40\x08\xFF\xD0\xF3\x0F\x10\x65\xD0\x8D\x55 \ -\xD0\xF3\x0F\x10\x55\xD4\xF3\x0F\x10\x6D\xE0\xF3\x0F\x10\x48\x10\xF3\x0F\x10\x00\xF3\x0F\x10\x5D\xE4\xF3\x0F\x59\xCA\x8B\x4D\xBC \ -\xF3\x0F\x59\xC4\x52\x8D\x55\xC0\x52\xF3\x0F\x58\xC8\xF3\x0F\x11\x4D\xD0\xF3\x0F\x10\x48\x10\xF3\x0F\x10\x00\xF3\x0F\x59\xCB\xF3 \ -\x0F\x59\xC5\xF3\x0F\x58\xC8\xF3\x0F\x11\x4D\xE0\x0F\x28\xCC\xF3\x0F\x59\x48\x04\xF3\x0F\x10\x40\x14\xF3\x0F\x59\xC2\xF3\x0F\x58 \ -\xC8\xF3\x0F\x11\x4D\xD4\x0F\x28\xCD\xF3\x0F\x10\x40\x14\xF3\x0F\x59\x48\x04\xC7\x45\xE8\x00\x00\x00\x00\xF3\x0F\x59\xC3\xC7\x45 \ -\xD8\x00\x00\x00\x00\xF3\x0F\x58\xC8\xF3\x0F\x11\x4D\xE4\xF3\x0F\x59\x60\x0C\xF3\x0F\x59\x50\x1C\xF3\x0F\x58\xE2\xF3\x0F\x58\x65 \ -\xDC\xF3\x0F\x11\x65\xDC\xF3\x0F\x59\x68\x0C\xF3\x0F\x59\x58\x1C\xF3\x0F\x58\xEB\xF3\x0F\x58\x6D\xEC\xF3\x0F\x11\x6D\xEC\x8B\x01 \ -\x8B\x80\xF8\x00\x00\x00\xFF\xD0\xF3\x0F\x10\x10\xF3\x0F\x10\x58\x08\x0F\x2F\xD3\xF3\x0F\x10\x40\x04\xF3\x0F\x10\x48\x0C\xF3\x0F \ -\x11\x55\xA0\xF3\x0F\x11\x45\x94\xF3\x0F\x11\x5D\x98\xF3\x0F\x11\x4D\xBC\x0F\x83\x8E\x00\x00\x00\x0F\x2F\xC1\x0F\x83\x85\x00\x00 \ -\x00\x8B\xCE\xE8\xE8\xAC\x86\xFF\xF3\x0F\x10\x65\xA0\x84\xC0\x75\x53\xF3\x0F\x10\x06\x0F\x2F\xC4\x77\x03\x0F\x28\xE0\xF3\x0F\x10 \ -\x5E\x08\xF3\x0F\x10\x45\x98\x0F\x2F\xD8\x77\x03\x0F\x28\xD8\xF3\x0F\x10\x4E\x04\xF3\x0F\x10\x45\x94\x0F\x2F\xC8\x77\x03\x0F\x28 \ -\xC1\xF3\x0F\x10\x4E\x0C\xF3\x0F\x10\x55\xBC\x0F\x2F\xCA\x77\x03\x0F\x28\xCA\xF3\x0F\x11\x46\x04\xF3\x0F\x11\x5E\x08\xF3\x0F\x11" - /* i'm test on the ubuntu 15.04 vmware, - * Sorry I haven't linux under the physical environment, - * so the results may not be accurate. - * - * original version output: - * bug@ubuntu:~/capstone/suite/benchmark$ make - * cc -c -I../../include test_iter_benchmark.c -o test_iter_benchmark.o - * cc test_iter_benchmark.o -O3 -Wall -lcapstone -o test_iter_benchmark - * bug@ubuntu:~/capstone/suite/benchmark$ ./test_iter_benchmark - * time used:6.017613 - * - * rebuild: - * - * bug@ubuntu:~/capstone$ make clean - * bug@ubuntu:~/capstone$ sudo make install - * bug@ubuntu:~/capstone$ cd suite/benchmark/ - * bug@ubuntu:~/capstone/suite/benchmark$ make clean - * bug@ubuntu:~/capstone/suite/benchmark$ make - * - * modified version output: - * bug@ubuntu:~/capstone/suite/benchmark$ ./test_iter_benchmark - * time used:5.003864 - * - * if we don't output format text string,like this: - * //handle->printer(&mci, &ss, handle->printer_info); <-----cs.c line 700 - * bug@ubuntu:~/capstone/suite/benchmark$ ./test_iter_benchmark - * time used:2.059570 - */ - - csh handle; - uint64_t address; - cs_insn *insn; - int i; - cs_err err; - const uint8_t *code; - size_t size; - - err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle); - if (err) { - printf("Failed on cs_open() with error returned: %u\n", err); - return; - } - cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); - cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); - - clock_t start, end; - double timeUsed; - - start = clock(); - int maxcount = 10000000; - insn = cs_malloc(handle); - for (i = 0; i < maxcount;) { - code = (const uint8_t *)X86_CODE32; - address = 0x1000; - size = sizeof(X86_CODE32) - 1; - while(cs_disasm_iter(handle, &code, &size, &address, insn)) { - i++; - } - } - cs_free(insn, 1); - cs_close(&handle); - end = clock(); - timeUsed = (double)(end - start) / CLOCKS_PER_SEC; - printf("time used: %f s\n", timeUsed); -} - -int main() -{ - test(); - - return 0; -} diff --git a/suite/capstone_get_setup.c b/suite/capstone_get_setup.c deleted file mode 100644 index f682b5b326..0000000000 --- a/suite/capstone_get_setup.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - Retrieve architectures compiled in Capstone. - By Nguyen Anh Quynh, 2019. - - Compile this code with: - $ cc -o capstone_get_setup capstone_get_setup.c -lcapstone - - On default Capstone build, this code prints out the below output: - - $ capstone_get_setup - x86=1 arm=1 arm64=1 mips=1 ppc=1 sparc=1 sysz=1 xcore=1 m68k=1 tms320c64x=1 m680x=1 evm=1 wasm=1 mos65xx=1 bpf=1 -*/ - -#include -#include - -int main() -{ - if (cs_support(CS_ARCH_X86)) { - printf("x86=1 "); - } - if (cs_support(CS_ARCH_ARM)) { - printf("arm=1 "); - } - if (cs_support(CS_ARCH_AARCH64)) { - printf("arm64=1 "); - } - if (cs_support(CS_ARCH_MIPS)) { - printf("mips=1 "); - } - if (cs_support(CS_ARCH_PPC)) { - printf("ppc=1 "); - } - if (cs_support(CS_ARCH_SPARC)) { - printf("sparc=1 "); - } - if (cs_support(CS_ARCH_SYSTEMZ)) { - printf("sysz=1 "); - } - if (cs_support(CS_ARCH_XCORE)) { - printf("xcore=1 "); - } - if (cs_support(CS_ARCH_M68K)) { - printf("m68k=1 "); - } - if (cs_support(CS_ARCH_TMS320C64X)) { - printf("tms320c64x=1 "); - } - if (cs_support(CS_ARCH_M680X)) { - printf("m680x=1 "); - } - if (cs_support(CS_ARCH_EVM)) { - printf("evm=1 "); - } - if (cs_support(CS_ARCH_WASM)) { - printf("wasm=1 "); - } - if (cs_support(CS_ARCH_MOS65XX)) { - printf("mos65xx=1 "); - } - if (cs_support(CS_ARCH_BPF)) { - printf("bpf=1 "); - } - if (cs_support(CS_ARCH_RISCV)) { - printf("riscv=1 "); - } - if (cs_support(CS_SUPPORT_DIET)) { - printf("diet=1 "); - } - if (cs_support(CS_SUPPORT_X86_REDUCE)) { - printf("x86_reduce=1 "); - } - if (cs_support(CS_ARCH_TRICORE)) { - printf("tricore=1 "); - } - if (cs_support(CS_ARCH_ALPHA)) { - printf("alpha=1 "); - } - if (cs_support(CS_ARCH_HPPA)) { - printf("hppa=1 "); - } - if (cs_support(CS_ARCH_LOONGARCH)) { - printf("loongarch=1 "); - } - if (cs_support(CS_ARCH_XTENSA)) { - printf("xtensa=1 "); - } - if (cs_support(CS_ARCH_ARC)) { - printf("arc=1 "); - } - printf("\n"); - - return 0; -} diff --git a/suite/check_wheel_bin_arch.py b/suite/check_wheel_bin_arch.py deleted file mode 100755 index 22a1db5a11..0000000000 --- a/suite/check_wheel_bin_arch.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -# Copyright © 2024 Rot127 -# SPDX-License-Identifier: BSD-3 - -import logging as log -import subprocess as sp -import re -import os -import sys -from pathlib import Path - -if len(sys.argv) != 2: - print(f"{sys.argv[0]} ") - exit(-1) - -log.basicConfig( - level=log.INFO, - stream=sys.stdout, - format="%(levelname)-5s - %(message)s", - force=True, -) - -archs = { - "universal2": ["x86_64", "arm64"], - "x86_64": [r"x86[_-]64"], - "arm64": ["arm64"], - "aarch64": ["ARM aarch64"], - "i686": ["Intel 80386"], - "win32": [r"INVALID"], - "amd64": [r"x86[_-]64"], -} - -filename = { - "macosx": "libcapstone.dylib", - "manylinux": "libcapstone.so", - "musllinux": "libcapstone.so", - "win": "capstone.dll", -} - -success = True -wheel_seen = False -for root, dir, files in os.walk(sys.argv[1]): - for file in files: - f = Path(root).joinpath(file) - if f.suffix != ".whl": - continue - wheel_seen = True - target = re.search(r"py3-none-(.+).whl", f"{f}").group(1) - platform = re.search("^(win|manylinux|musllinux|macosx)", target).group(1) - - arch = re.search( - "(universal2|x86_64|arm64|aarch64|i686|win32|amd64)$", target - ).group(1) - log.info(f"Target: {target} - Platform: {platform} - Arch: {archs[arch]}") - - out_dir = f"{platform}__{arch}" - sp.run(["unzip", "-q", f"{f}", "-d", out_dir], check=True) - lib_path = Path(out_dir).joinpath(f"capstone/lib/{filename[platform]}") - result = sp.run(["file", "-b", f"{lib_path}"], capture_output=True, check=True) - stdout = result.stdout.decode("utf8").strip() - if any([not re.search(a, stdout) for a in archs[arch]]): - success = False - log.error(f"The wheel '{file}' is not compiled for '{archs[arch]}'.") - log.error(f"Binary is: {stdout}") - print() - else: - log.info(f"OK: Arch: {arch} - {lib_path}") - log.info(f"Binary is: {stdout}") - log.info(f"Delete {out_dir}") - print() - os.system(f"rm -r {out_dir}") - break - -if not wheel_seen: - log.error("No wheel was checked.") - exit(-1) - -if not success: - log.error("Binary files are compiled for the wrong architecture.") - exit(-1) diff --git a/suite/patch_major_os_version.py b/suite/patch_major_os_version.py deleted file mode 100755 index a4e36b982d..0000000000 --- a/suite/patch_major_os_version.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# By Daniel Pistelli & Nguyen Tan Cong - -# This script is to patch DLL/EXE MajorVersion to 5, -# so they can be loaded by Windows XP. -# This is the problem introduced by compiling on Windows 7, using VS2013. - -import sys, struct - -if len(sys.argv) < 2: - print("Usage: %s " % sys.argv[0]) - sys.exit(0) - -pe_file_path = sys.argv[1] - -with open(pe_file_path, "rb") as f: - b = f.read() - -if not b.startswith("MZ"): - print("Not a PE file") - sys.exit(0) - -e_lfanew = struct.unpack_from(" -# PPC Branch testing suite by kratolp -from __future__ import print_function -import sys -from capstone import * - -CODE32 = b"\x48\x01\x05\x15" # bl .+0x10514 -CODE32 += b"\x4B\xff\xff\xfd" # bl .-0x4 -CODE32 += b"\x48\x00\x00\x0c" # b .+0xc -CODE32 += b"\x41\x80\xff\xd8" # blt .-0x28 -CODE32 += b"\x40\x80\xff\xec" # bge .-0x14 -CODE32 += b"\x41\x84\x01\x6c" # blt cr1, .+0x16c -CODE32 += b"\x41\x82\x00\x10" # beq .+0x10 -CODE32 += b"\x40\x82\x00\x08" # bne .+0x8 -CODE32 += b"\x40\x95\x00\x94" # ble cr5,.+0x94 -CODE32 += b"\x40\x9f\x10\x30" # bns cr5,.+0x94 -CODE32 += b"\x42\x00\xff\xd8" # bdnz .-0x28 -CODE32 += b"\x4d\x82\x00\x20" # beqlr -CODE32 += b"\x4e\x80\x00\x20" # blr -CODE32 += b"\x4a\x00\x00\x02" # ba .0xfe000000 -CODE32 += b"\x41\x80\xff\xda" # blta .0xffffffd8 -CODE32 += b"\x41\x4f\xff\x17" # bdztla 4*cr3+so, .0xffffff14 -CODE32 += b"\x43\x20\x0c\x07" # bdnzla+ .0xc04 -CODE32 += b"\x4c\x00\x04\x20" # bdnzfctr lt - -_python3 = sys.version_info.major == 3 - -all_tests = ( - (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, CODE32, "PPC branch instruction decoding", 0), -) - - -def to_hex(s): - if _python3: - return " ".join("0x{0:02x}".format(c) for c in s) # <-- Python 3 is OK - else: - return " ".join("0x{0:02x}".format(ord(c)) for c in s) - -# ## Test cs_disasm_quick() -def test_cs_disasm_quick(): - for (arch, mode, code, comment, syntax) in all_tests: - print("Platform: %s" % comment) - print("Code: %s" %(to_hex(code))), - print("Disasm:") - for (addr, size, mnemonic, op_str) in cs_disasm_lite(arch, mode, code, 0x1000): - print("0x%x:\t%s\t%s" % (addr, mnemonic, op_str)) - print() - - -if __name__ == '__main__': - test_cs_disasm_quick() diff --git a/suite/python_capstone_setup.py b/suite/python_capstone_setup.py deleted file mode 100755 index 5243932f21..0000000000 --- a/suite/python_capstone_setup.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# this prints out Capstone setup & core+Python-binding versions - -python -c "import capstone; print capstone.debug()" diff --git a/suite/regress.py b/suite/regress.py deleted file mode 100755 index 826a7ca7b0..0000000000 --- a/suite/regress.py +++ /dev/null @@ -1,750 +0,0 @@ -#!/usr/bin/env python3 - -# Capstone Python bindings, by Nguyen Anh Quynnh -from __future__ import print_function -import sys -from capstone import * - -all_tests = ( - # arch, mode, syntax, address, hexcode, expected output - # issue 456 https://github.com/aquynh/capstone/issues/456 - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xfc16, b"\xE8\x35\x64", "call 0x604e"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123fc1b, b"\x66\xE8\x35\x64", "call 0x6054"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x9123fc1b, b"\x66\xE8\x35\x64", "call 0x6054"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xfc26, b"\xE9\x35\x64", "jmp 0x605e"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xfff6, b"\x66\xE9\x35\x64\x93\x53", "jmp 0x53946431"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123fff1, b"\xE9\x35\x64\x93\x53", "jmp 0xe4b7642b"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123fff1, b"\xE9\x35\x64\x93\x53", "jmp 0x64e4b7642b"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xe8\x35\x64\x93\x53", "call 0x5394641c"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xe8\x35\x64", "call 0x641a"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xe9\x35\x64", "jmp 0x641a"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xe9\x35\x64\x93\x53", "jmp 0x5394641c"), - - # AT&T syntax - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_ATT, 0xfc16, b"\xE8\x35\x64", "callw 0x604e"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT, 0x9123fc1b, b"\x66\xE8\x35\x64", "callw 0x6054"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT, 0x9123fc1b, b"\x66\xE8\x35\x64", "callw 0x6054"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_ATT, 0xfc26, b"\xE9\x35\x64", "jmp 0x605e"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_ATT, 0xfff6, b"\x66\xE9\x35\x64\x93\x53", "jmp 0x53946431"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT, 0x9123fff1, b"\xE9\x35\x64\x93\x53", "jmp 0xe4b7642b"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT, 0x649123fff1, b"\xE9\x35\x64\x93\x53", "jmp 0x64e4b7642b"), - - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_ATT, 0xffe1, b"\x66\xe8\x35\x64\x93\x53", "calll 0x5394641c"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT, 0x649123ffe1, b"\x66\xe8\x35\x64", "callw 0x641a"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT, 0x649123ffe1, b"\x66\xe9\x35\x64", "jmp 0x641a"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_ATT, 0xffe1, b"\x66\xe9\x35\x64\x93\x53", "jmp 0x5394641c"), - - # issue 452 https://github.com/aquynh/capstone/issues/452 - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x6C", "insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x6D", "insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x6E", "outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x6F", "outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xA4", "movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xA5", "movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xA6", "cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xA7", "cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAA", "stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAB", "stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAC", "lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAD", "lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAE", "scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xAF", "scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x6C", "insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x6D", "insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x6E", "outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x6F", "outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xA4", "movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xA5", "movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xA6", "cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xA7", "cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAA", "stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAB", "stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAC", "lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAD", "lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAE", "scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xAF", "scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\x6C", "insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\x6D", "insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\x6F", "outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xA4", "movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xA5", "movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xA6", "cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xA7", "cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAA", "stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAB", "stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAD", "lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAE", "scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xAF", "scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\x6C", "repne insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\x6D", "repne insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\x6E", "repne outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\x6F", "repne outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xA4", "repne movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xA5", "repne movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xA6", "repne cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xA7", "repne cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAA", "repne stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAB", "repne stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAC", "repne lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAD", "repne lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAE", "repne scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF2\xAF", "repne scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\x6C", "rep insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\x6D", "rep insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\x6E", "rep outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\x6F", "rep outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xA4", "rep movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xA5", "rep movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xA6", "repe cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xA7", "repe cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAA", "rep stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAB", "rep stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAC", "rep lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAD", "rep lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAE", "repe scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\xF3\xAF", "repe scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\x6C", "insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\x6D", "insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\x6F", "outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xA4", "movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xA5", "movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xA6", "cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xA7", "cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAA", "stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAB", "stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAD", "lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAE", "scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xAF", "scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\x6C", "repne insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\x6D", "repne insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\x6E", "repne outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\x6F", "repne outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xA4", "repne movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xA5", "repne movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xA6", "repne cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xA7", "repne cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAA", "repne stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAB", "repne stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAC", "repne lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAD", "repne lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAE", "repne scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF2\xAF", "repne scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\x6C", "rep insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\x6D", "rep insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\x6E", "rep outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\x6F", "rep outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xA4", "rep movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xA5", "rep movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xA6", "repe cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xA7", "repe cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAA", "rep stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAB", "rep stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAC", "rep lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAD", "rep lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAE", "repe scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\xF3\xAF", "repe scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\x6C", "repne insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\x6D", "repne insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\x6F", "repne outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xA4", "repne movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xA5", "repne movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xA7", "repne cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAA", "repne stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAB", "repne stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAD", "repne lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAE", "repne scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF2\xAF", "repne scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\x6C", "rep insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\x6D", "rep insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\x6F", "rep outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xA4", "rep movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xA5", "rep movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xA7", "repe cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAA", "rep stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAB", "rep stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAD", "rep lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAE", "repe scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x67\xF3\xAF", "repe scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\x6C", "repne insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\x6D", "repne insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\x6F", "repne outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xA4", "repne movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xA5", "repne movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xA7", "repne cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAA", "repne stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAB", "repne stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAD", "repne lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAE", "repne scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF2\xAF", "repne scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\x6C", "rep insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\x6D", "rep insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\x6F", "rep outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xA4", "rep movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xA5", "rep movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xA7", "repe cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAA", "rep stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAB", "rep stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAD", "rep lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAE", "repe scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x67\xF3\xAF", "repe scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x6C", "insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x6D", "insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x6F", "outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xA4", "movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xA5", "movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xA6", "cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xA7", "cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAA", "stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAB", "stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAD", "lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAE", "scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xAF", "scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x6C", "insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x6D", "insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x6F", "outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xA4", "movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xA5", "movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xA6", "cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xA7", "cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAA", "stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAB", "stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAD", "lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAE", "scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xAF", "scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\x6C", "insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\x6D", "insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\x6E", "outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\x6F", "outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xA4", "movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xA5", "movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xA6", "cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xA7", "cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAA", "stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAB", "stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAC", "lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAD", "lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAE", "scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xAF", "scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\x6C", "repne insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\x6D", "repne insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\x6F", "repne outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xA4", "repne movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xA5", "repne movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xA7", "repne cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAA", "repne stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAB", "repne stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAD", "repne lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAE", "repne scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF2\xAF", "repne scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\x6C", "rep insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\x6D", "rep insd dword ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\x6F", "rep outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xA4", "rep movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xA5", "rep movsd dword ptr es:[edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xA7", "repe cmpsd dword ptr [esi], dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAA", "rep stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAB", "rep stosd dword ptr es:[edi], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAD", "rep lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAE", "repe scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\xF3\xAF", "repe scasd eax, dword ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\x6C", "insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\x6D", "insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\x6E", "outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\x6F", "outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xA4", "movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xA5", "movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xA6", "cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xA7", "cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAA", "stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAB", "stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAC", "lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAD", "lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAE", "scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xAF", "scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\x6C", "repne insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\x6D", "repne insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\x6F", "repne outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xA4", "repne movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xA5", "repne movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xA7", "repne cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAA", "repne stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAB", "repne stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAD", "repne lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAE", "repne scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF2\xAF", "repne scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\x6C", "rep insb byte ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\x6D", "rep insw word ptr es:[edi], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\x6F", "rep outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xA4", "rep movsb byte ptr es:[edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xA5", "rep movsw word ptr es:[edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xA7", "repe cmpsw word ptr [esi], word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAA", "rep stosb byte ptr es:[edi], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAB", "rep stosw word ptr es:[edi], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAD", "rep lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAE", "repe scasb al, byte ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\xF3\xAF", "repe scasw ax, word ptr es:[edi]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\x6C", "repne insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\x6D", "repne insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\x6E", "repne outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\x6F", "repne outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xA4", "repne movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xA5", "repne movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xA6", "repne cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xA7", "repne cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAA", "repne stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAB", "repne stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAC", "repne lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAD", "repne lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAE", "repne scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF2\xAF", "repne scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\x6C", "rep insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\x6D", "rep insd dword ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\x6E", "rep outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\x6F", "rep outsd dx, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xA4", "rep movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xA5", "rep movsd dword ptr es:[di], dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xA6", "repe cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xA7", "repe cmpsd dword ptr [si], dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAA", "rep stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAB", "rep stosd dword ptr es:[di], eax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAC", "rep lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAD", "rep lodsd eax, dword ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAE", "repe scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x67\xF3\xAF", "repe scasd eax, dword ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\x6C", "repne insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\x6D", "repne insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\x6E", "repne outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\x6F", "repne outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xA4", "repne movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xA5", "repne movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xA6", "repne cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xA7", "repne cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAA", "repne stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAB", "repne stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAC", "repne lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAD", "repne lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAE", "repne scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF2\xAF", "repne scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\x6C", "rep insb byte ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\x6D", "rep insw word ptr es:[di], dx"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\x6E", "rep outsb dx, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\x6F", "rep outsw dx, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xA4", "rep movsb byte ptr es:[di], byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xA5", "rep movsw word ptr es:[di], word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xA6", "repe cmpsb byte ptr [si], byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xA7", "repe cmpsw word ptr [si], word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAA", "rep stosb byte ptr es:[di], al"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAB", "rep stosw word ptr es:[di], ax"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAC", "rep lodsb al, byte ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAD", "rep lodsw ax, word ptr [si]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAE", "repe scasb al, byte ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x67\xF3\xAF", "repe scasw ax, word ptr es:[di]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x6C", "insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x6D", "insd dword ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x6E", "outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x6F", "outsd dx, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xA4", "movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xA5", "movsd dword ptr [rdi], dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xA6", "cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xA7", "cmpsd dword ptr [rsi], dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAA", "stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAB", "stosd dword ptr [rdi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAC", "lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAD", "lodsd eax, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAE", "scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xAF", "scasd eax, dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x6C", "insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x6D", "insw word ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x6E", "outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x6F", "outsw dx, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xA4", "movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xA5", "movsw word ptr [rdi], word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xA6", "cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xA7", "cmpsw word ptr [rsi], word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAA", "stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAB", "stosw word ptr [rdi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAC", "lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAD", "lodsw ax, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAE", "scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xAF", "scasw ax, word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x6C", "insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x6D", "insd dword ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x6F", "outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xA4", "movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xA5", "movsd dword ptr [edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xA6", "cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xA7", "cmpsd dword ptr [esi], dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAA", "stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAB", "stosd dword ptr [edi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAD", "lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAE", "scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xAF", "scasd eax, dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x6C", "repne insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x6D", "repne insd dword ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x6E", "repne outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x6F", "repne outsd dx, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xA4", "repne movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xA5", "repne movsd dword ptr [rdi], dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xA6", "repne cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xA7", "repne cmpsd dword ptr [rsi], dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAA", "repne stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAB", "repne stosd dword ptr [rdi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAC", "repne lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAD", "repne lodsd eax, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAE", "repne scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\xAF", "repne scasd eax, dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x6C", "rep insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x6D", "rep insd dword ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x6E", "rep outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x6F", "rep outsd dx, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xA4", "rep movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xA5", "rep movsd dword ptr [rdi], dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xA6", "repe cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xA7", "repe cmpsd dword ptr [rsi], dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAA", "rep stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAB", "rep stosd dword ptr [rdi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAC", "rep lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAD", "rep lodsd eax, dword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAE", "repe scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\xAF", "repe scasd eax, dword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x6C", "insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x6D", "insw word ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x6E", "outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x6F", "outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xA4", "movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xA5", "movsw word ptr [edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xA6", "cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xA7", "cmpsw word ptr [esi], word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAA", "stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAB", "stosw word ptr [edi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAD", "lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAE", "scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xAF", "scasw ax, word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x6C", "repne insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x6D", "repne insw word ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x6E", "repne outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x6F", "repne outsw dx, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xA4", "repne movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xA5", "repne movsw word ptr [rdi], word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xA6", "repne cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xA7", "repne cmpsw word ptr [rsi], word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAA", "repne stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAB", "repne stosw word ptr [rdi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAC", "repne lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAD", "repne lodsw ax, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAE", "repne scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\xAF", "repne scasw ax, word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x6C", "rep insb byte ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x6D", "rep insw word ptr [rdi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x6E", "rep outsb dx, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x6F", "rep outsw dx, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xA4", "rep movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xA5", "rep movsw word ptr [rdi], word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xA6", "repe cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xA7", "repe cmpsw word ptr [rsi], word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAA", "rep stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAB", "rep stosw word ptr [rdi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAC", "rep lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAD", "rep lodsw ax, word ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAE", "repe scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\xAF", "repe scasw ax, word ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x6C", "repne insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x6D", "repne insd dword ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x6F", "repne outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xA4", "repne movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xA5", "repne movsd dword ptr [edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xA7", "repne cmpsd dword ptr [esi], dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAA", "repne stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAB", "repne stosd dword ptr [edi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAD", "repne lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAE", "repne scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\xAF", "repne scasd eax, dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x6C", "rep insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x6D", "rep insd dword ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x6F", "rep outsd dx, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xA4", "rep movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xA5", "rep movsd dword ptr [edi], dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xA7", "repe cmpsd dword ptr [esi], dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAA", "rep stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAB", "rep stosd dword ptr [edi], eax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAD", "rep lodsd eax, dword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAE", "repe scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\xAF", "repe scasd eax, dword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x6C", "repne insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x6D", "repne insw word ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x6E", "repne outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x6F", "repne outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xA4", "repne movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xA5", "repne movsw word ptr [edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xA6", "repne cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xA7", "repne cmpsw word ptr [esi], word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAA", "repne stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAB", "repne stosw word ptr [edi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAD", "repne lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAE", "repne scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\xAF", "repne scasw ax, word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x6C", "rep insb byte ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x6D", "rep insw word ptr [edi], dx"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x6E", "rep outsb dx, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x6F", "rep outsw dx, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xA4", "rep movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xA5", "rep movsw word ptr [edi], word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xA6", "repe cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xA7", "repe cmpsw word ptr [esi], word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAA", "rep stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAB", "rep stosw word ptr [edi], ax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAD", "rep lodsw ax, word ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAE", "repe scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\xAF", "repe scasw ax, word ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xA4", "movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xA5", "movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xA6", "cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xA7", "cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAA", "stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAB", "stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAC", "lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAD", "lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAE", "scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x48\xAF", "scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xA4", "movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xA5", "movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xA6", "cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xA7", "cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAA", "stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAB", "stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAC", "lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAD", "lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAE", "scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x48\xAF", "scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xA4", "movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xA5", "movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xA6", "cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xA7", "cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAA", "stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAB", "stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAD", "lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAE", "scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\x48\xAF", "scasq rax, qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xA4", "repne movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xA5", "repne movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xA6", "repne cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xA7", "repne cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAA", "repne stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAB", "repne stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAC", "repne lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAD", "repne lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAE", "repne scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF2\x48\xAF", "repne scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xA4", "rep movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xA5", "rep movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xA6", "repe cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xA7", "repe cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAA", "rep stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAB", "rep stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAC", "rep lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAD", "rep lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAE", "repe scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\xF3\x48\xAF", "repe scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xA4", "movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xA5", "movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xA6", "cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xA7", "cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAA", "stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAB", "stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAC", "lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAD", "lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAE", "scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\x48\xAF", "scasq rax, qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xA4", "repne movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xA5", "repne movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xA6", "repne cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xA7", "repne cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAA", "repne stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAB", "repne stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAC", "repne lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAD", "repne lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAE", "repne scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF2\x48\xAF", "repne scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xA4", "rep movsb byte ptr [rdi], byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xA5", "rep movsq qword ptr [rdi], qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xA6", "repe cmpsb byte ptr [rsi], byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xA7", "repe cmpsq qword ptr [rsi], qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAA", "rep stosb byte ptr [rdi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAB", "rep stosq qword ptr [rdi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAC", "rep lodsb al, byte ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAD", "rep lodsq rax, qword ptr [rsi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAE", "repe scasb al, byte ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\xF3\x48\xAF", "repe scasq rax, qword ptr [rdi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xA4", "repne movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xA5", "repne movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xA6", "repne cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xA7", "repne cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAA", "repne stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAB", "repne stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAD", "repne lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAE", "repne scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF2\x48\xAF", "repne scasq rax, qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xA4", "rep movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xA5", "rep movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xA6", "repe cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xA7", "repe cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAA", "rep stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAB", "rep stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAD", "rep lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAE", "repe scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x67\xF3\x48\xAF", "repe scasq rax, qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xA4", "repne movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xA5", "repne movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xA6", "repne cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xA7", "repne cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAA", "repne stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAB", "repne stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAC", "repne lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAD", "repne lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAE", "repne scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF2\x48\xAF", "repne scasq rax, qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xA4", "rep movsb byte ptr [edi], byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xA5", "rep movsq qword ptr [edi], qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xA6", "repe cmpsb byte ptr [esi], byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xA7", "repe cmpsq qword ptr [esi], qword ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAA", "rep stosb byte ptr [edi], al"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAB", "rep stosq qword ptr [edi], rax"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAC", "rep lodsb al, byte ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAD", "rep lodsq rax, qword ptr [esi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAE", "repe scasb al, byte ptr [edi]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x67\xF3\x48\xAF", "repe scasq rax, qword ptr [edi]"), - - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x0f\x01\x05\xa0\x90\x04\x08", "sgdt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x0f\x01\x05\xa0\x90\x04\x08", "sgdt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x0f\x01\x05\xa0\x90\x04\x08", "sgdt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x0f\x01\x05\xa0\x90\x04\x08", "sgdt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x0f\x01\x05", "sgdt [di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x0f\x01\x05", "sgdt [di]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x0f\x01\x0d\xa0\x90\x04\x08", "sidt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x0f\x01\x0d\xa0\x90\x04\x08", "sidt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x0f\x01\x0d\xa0\x90\x04\x08", "sidt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x0f\x01\x0d\xa0\x90\x04\x08", "sidt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x0f\x01\x0d", "sidt [di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x0f\x01\x0d", "sidt [di]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x0f\x01\x15\xa0\x90\x04\x08", "lgdt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x0f\x01\x15\xa0\x90\x04\x08", "lgdt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x0f\x01\x15\xa0\x90\x04\x08", "lgdt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x0f\x01\x15\xa0\x90\x04\x08", "lgdt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x0f\x01\x15", "lgdt [di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x0f\x01\x15", "lgdt [di]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x0f\x01\x1d\xa0\x90\x04\x08", "lidt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_INTEL, 0x649123ffe1, b"\x66\x0f\x01\x1d\xa0\x90\x04\x08", "lidt [rip + 0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x0f\x01\x1d\xa0\x90\x04\x08", "lidt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0x9123ffe1, b"\x66\x0f\x01\x1d\xa0\x90\x04\x08", "lidt [0x80490a0]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x0f\x01\x1d", "lidt [di]"), - (CS_ARCH_X86, CS_MODE_16, CS_OPT_SYNTAX_INTEL, 0xffe1, b"\x66\x0f\x01\x1d", "lidt [di]"), - - # issues 702 https://github.com/aquynh/capstone/issues/702 - (CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_INTEL, 0, b"\x85\xC8", "test eax, ecx") -) - -_python3 = sys.version_info.major == 3 - - -def to_hex(s): - if _python3: - return " ".join("0x{0:02x}".format(c) for c in s) # <-- Python 3 is OK - else: - return " ".join("0x{0:02x}".format(ord(c)) for c in s) - - -def str_syntax(syntax): - slist = { - 0: "", - CS_OPT_SYNTAX_INTEL: "intel", - CS_OPT_SYNTAX_ATT: "att", - } - - return slist[syntax] - - -def str_arch_mode(a, m): - amlist = { - (CS_ARCH_X86, CS_MODE_16): "X86-16bit", - (CS_ARCH_X86, CS_MODE_32): "X86-32bit", - (CS_ARCH_X86, CS_MODE_64): "X86-64bit", - } - - return amlist[(a, m)] - - -# ## Test cs_disasm_quick() -def test_regression(verbose): - for (arch, mode, syntax, address, code, expected_output) in all_tests: - #print("%s %s: %s = " %(str_arch_mode(arch, mode), str_syntax(syntax), to_hex(code)), end=""), - output = "%s %s: %s = " %(str_arch_mode(arch, mode), str_syntax(syntax), to_hex(code)) - md = Cs(arch, mode) - if syntax != 0: - md.syntax = syntax - insn = list(md.disasm(code, address))[0] - output2 = "%s %s" % (insn.mnemonic, insn.op_str) - if output2 != expected_output: - print(output, output2) - print("\t --> ERROR: expected output = %s" %(expected_output)) - elif verbose: - print(output, output2) - - -if __name__ == '__main__': - import sys - if len(sys.argv) == 2 and sys.argv[1] == "-v": - test_regression(True) # quiet - else: - test_regression(False) # verbose diff --git a/suite/synctools/.gitignore b/suite/synctools/.gitignore deleted file mode 100644 index 22e9d8338b..0000000000 --- a/suite/synctools/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.inc -insn_list.txt - -disassemblertables_reduce2 -disassemblertables2 -ppc_gen_reg -arm64_gen_vreg - -strinforeduce/strinforeduce -strinforeduce/strinforeduce_reduce diff --git a/suite/synctools/Makefile b/suite/synctools/Makefile deleted file mode 100644 index fd4d605c1d..0000000000 --- a/suite/synctools/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: - -x86: - # compile disassembler2 with X86GenDisassemblerTables2.inc - $(CC) disassemblertables2.c -o disassemblertables2 - - # compile disassembler2 with X86GenDisassemblerTables_reduce2.inc - $(CC) -DCAPSTONE_X86_REDUCE disassemblertables2.c -o disassemblertables_reduce2 - -arm64: - $(CC) arm64_gen_vreg.c -o arm64_gen_vreg - -clean: - $(RM) disassemblertables2 disassemblertables_reduce2 arm64_gen_vreg diff --git a/suite/synctools/README b/suite/synctools/README deleted file mode 100644 index 247ee93439..0000000000 --- a/suite/synctools/README +++ /dev/null @@ -1,57 +0,0 @@ -Sync tools to port LLVM inc files to Capstone. - -For X86 -======= -0. cd tablegen/, then follow its README. - -1. Run genall-{full|reduce}.sh, then copy generated .inc files to arch// directory - - $ ./genall-full.sh tablegen ~/projects/tmp/capstone777.git/arch/X86 - $ ./genall-reduce.sh tablegen ~/projects/tmp/capstone777.git/arch/X86 - -2. Run disassemblertables_reduce2 & disassemblertables_reduce2 to generate optimized (index table) X86GenDisassemblerTables2.inc & X86GenDisassemblerTables_reduce2.inc - - # use 2x name to avoid overwriting X86GenDisassemblerTables2.inc & X86GenDisassemblerTables_reduce2.inc - - $ make - $ ./disassemblertables2 > X86GenDisassemblerTables2x.inc - $ ./disassemblertables_reduce2 > X86GenDisassemblerTables_reduce2x.inc - -3. cd strinforeduce/, and follow its README. - -4. Copy all generated .inc files to arch/X86/ - - $ cp X86GenAsmWriter_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenAsmWriter1_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsnName_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsn_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsnOp_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenInstrInfo_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenDisassemblerTables_reduce.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenDisassemblerTables_reduce2x.inc ~/projects/capstone.git/arch/X86/X86GenDisassemblerTables_reduce2.inc - - $ cp X86GenAsmWriter.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenAsmWriter1.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsnName.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsn.inc ~/projects/capstone.git/arch/X86 - $ cp X86MappingInsnOp.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenInstrInfo.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenDisassemblerTables.inc ~/projects/capstone.git/arch/X86 - $ cp X86GenDisassemblerTables2x.inc ~/projects/capstone.git/arch/X86/X86GenDisassemblerTables2.inc - -5. copy insn_list.txt to include/capstone/ - -For non-X86 -=========== - -0. cd tablegen/, then follow its README. - - 1. Run gen-tablegen-arch.sh - -2. Run genall-arch.sh - - ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM ARM - ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM AArch64 - ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM PowerPC - -3. Copy generated *.inc files to arch// diff --git a/suite/synctools/X86DisassemblerDecoderCommon.h b/suite/synctools/X86DisassemblerDecoderCommon.h deleted file mode 100644 index edf68aab86..0000000000 --- a/suite/synctools/X86DisassemblerDecoderCommon.h +++ /dev/null @@ -1,483 +0,0 @@ -/*===-- X86DisassemblerDecoderCommon.h - Disassembler decoder -----*- C -*-===* - * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - * - *===----------------------------------------------------------------------===* - * - * This file is part of the X86 Disassembler. - * It contains common definitions used by both the disassembler and the table - * generator. - * Documentation for the disassembler can be found in X86Disassembler.h. - * - *===----------------------------------------------------------------------===*/ - -/* Capstone Disassembly Engine */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/* - * This header file provides those definitions that need to be shared between - * the decoder and the table generator in a C-friendly manner. - */ - -#ifndef CS_X86_DISASSEMBLERDECODERCOMMON_H -#define CS_X86_DISASSEMBLERDECODERCOMMON_H - -#define INSTRUCTIONS_SYM x86DisassemblerInstrSpecifiers -#define CONTEXTS_SYM x86DisassemblerContexts -#define ONEBYTE_SYM x86DisassemblerOneByteOpcodes -#define TWOBYTE_SYM x86DisassemblerTwoByteOpcodes -#define THREEBYTE38_SYM x86DisassemblerThreeByte38Opcodes -#define THREEBYTE3A_SYM x86DisassemblerThreeByte3AOpcodes -#define XOP8_MAP_SYM x86DisassemblerXOP8Opcodes -#define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes -#define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes -#define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes - - -/* - * Attributes of an instruction that must be known before the opcode can be - * processed correctly. Most of these indicate the presence of particular - * prefixes, but ATTR_64BIT is simply an attribute of the decoding context. - */ -#define ATTRIBUTE_BITS \ - ENUM_ENTRY(ATTR_NONE, 0x00) \ - ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \ - ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \ - ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \ - ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \ - ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \ - ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \ - ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \ - ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \ - ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \ - ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \ - ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \ - ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \ - ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \ - ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) - -#define ENUM_ENTRY(n, v) n = v, -enum attributeBits { - ATTRIBUTE_BITS - ATTR_max -}; -#undef ENUM_ENTRY - -/* - * Combinations of the above attributes that are relevant to instruction - * decode. Although other combinations are possible, they can be reduced to - * these without affecting the ultimately decoded instruction. - */ - -// Class name Rank Rationale for rank assignment -#define INSTRUCTION_CONTEXTS \ - ENUM_ENTRY(IC, 0, "says nothing about the instruction") \ - ENUM_ENTRY(IC_64BIT, 1, "says the instruction applies in " \ - "64-bit mode but no more") \ - ENUM_ENTRY(IC_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_ADSIZE, 3, "requires an ADSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_OPSIZE_ADSIZE, 4, "requires ADSIZE and OPSIZE prefixes") \ - ENUM_ENTRY(IC_XD, 2, "may say something about the opcode " \ - "but not the operands") \ - ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \ - "but not the operands") \ - ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_XD_ADSIZE, 3, "requires an ADSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_XS_ADSIZE, 3, "requires an ADSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\ - "change width; overrides IC_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_REXW_ADSIZE, 6, "requires a REX.W prefix and 0x67 " \ - "prefix") \ - ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \ - "IC_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_XD, 6, "XD instructions are SSE; REX.W is " \ - "secondary") \ - ENUM_ENTRY(IC_64BIT_XS, 6, "Just as meaningful as IC_64BIT_XD") \ - ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_XD_ADSIZE, 3, "Just as meaningful as IC_XD_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_XS_ADSIZE, 3, "Just as meaningful as IC_XS_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_REXW_XS, 7, "OPSIZE could mean a different " \ - "opcode") \ - ENUM_ENTRY(IC_64BIT_REXW_XD, 7, "Just as meaningful as " \ - "IC_64BIT_REXW_XS") \ - ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \ - "else because this changes most " \ - "operands' meaning") \ - ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \ - ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \ - ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \ - ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \ - ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \ - ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \ - ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \ - ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \ - ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \ - ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\ - ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\ - ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") \ - ENUM_ENTRY(IC_VEX_L_W, 4, "requires VEX, L and W") \ - ENUM_ENTRY(IC_VEX_L_W_XS, 5, "requires VEX, L, W and XS prefix") \ - ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \ - ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \ - ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE, 2, "requires EVEX and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W, 3, "requires EVEX and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS, 4, "requires EVEX, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD, 4, "requires EVEX, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE, 4, "requires EVEX, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L, 3, "requires EVEX and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS, 4, "requires EVEX and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD, 4, "requires EVEX and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE, 4, "requires EVEX, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W, 3, "requires EVEX, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS, 4, "requires EVEX, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD, 4, "requires EVEX, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE, 4, "requires EVEX, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2, 3, "requires EVEX and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS, 4, "requires EVEX and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD, 4, "requires EVEX and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE, 4, "requires EVEX, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W, 3, "requires EVEX, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS, 4, "requires EVEX, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD, 4, "requires EVEX, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE, 4, "requires EVEX, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_K, 1, "requires an EVEX_K prefix") \ - ENUM_ENTRY(IC_EVEX_XS_K, 2, "requires EVEX_K and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_K, 2, "requires EVEX_K and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_K, 2, "requires EVEX_K and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_K, 3, "requires EVEX_K and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_K, 4, "requires EVEX_K, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_K, 4, "requires EVEX_K, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_K, 4, "requires EVEX_K, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_K, 3, "requires EVEX_K and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_K, 4, "requires EVEX_K and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_K, 4, "requires EVEX_K and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_K, 4, "requires EVEX_K, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_K, 3, "requires EVEX_K, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_K, 4, "requires EVEX_K, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_K, 4, "requires EVEX_K, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K, 4, "requires EVEX_K, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_K, 3, "requires EVEX_K and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_K, 4, "requires EVEX_K and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_K, 4, "requires EVEX_K and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K, 4, "requires EVEX_K, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_K, 3, "requires EVEX_K, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_K, 4, "requires EVEX_K, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_K, 4, "requires EVEX_K, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K, 4, "requires EVEX_K, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_B, 1, "requires an EVEX_B prefix") \ - ENUM_ENTRY(IC_EVEX_XS_B, 2, "requires EVEX_B and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_B, 2, "requires EVEX_B and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_B, 2, "requires EVEX_B and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_B, 3, "requires EVEX_B and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_B, 4, "requires EVEX_B, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_B, 4, "requires EVEX_B, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_B, 4, "requires EVEX_B, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_B, 3, "requires EVEX_B and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_B, 4, "requires EVEX_B and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_B, 4, "requires EVEX_B and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_B, 4, "requires EVEX_B, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_B, 3, "requires EVEX_B, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_B, 4, "requires EVEX_B, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_B, 4, "requires EVEX_B, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_B, 4, "requires EVEX_B, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_B, 3, "requires EVEX_B and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_B, 4, "requires EVEX_B and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_B, 4, "requires EVEX_B and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_B, 4, "requires EVEX_B, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_B, 3, "requires EVEX_B, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_B, 4, "requires EVEX_B, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_B, 4, "requires EVEX_B, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_B, 4, "requires EVEX_B, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_K_B, 1, "requires EVEX_B and EVEX_K prefix") \ - ENUM_ENTRY(IC_EVEX_XS_K_B, 2, "requires EVEX_B, EVEX_K and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_K_B, 2, "requires EVEX_B, EVEX_K and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_K_B, 2, "requires EVEX_B, EVEX_K and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_K_B, 3, "requires EVEX_B, EVEX_K and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_K_B, 3, "requires EVEX_B, EVEX_K and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_K_B, 3, "requires EVEX_B, EVEX_K, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_K_B, 3, "requires EVEX_B, EVEX_K and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_K_B, 3, "requires EVEX_B, EVEX_K, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_KZ_B, 1, "requires EVEX_B and EVEX_KZ prefix") \ - ENUM_ENTRY(IC_EVEX_XS_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_KZ, 1, "requires an EVEX_KZ prefix") \ - ENUM_ENTRY(IC_EVEX_XS_KZ, 2, "requires EVEX_KZ and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_KZ, 2, "requires EVEX_KZ and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_KZ, 2, "requires EVEX_KZ and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_KZ, 3, "requires EVEX_KZ and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_KZ, 4, "requires EVEX_KZ, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_KZ, 4, "requires EVEX_KZ, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ, 4, "requires EVEX_KZ, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_KZ, 3, "requires EVEX_KZ and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_KZ, 4, "requires EVEX_KZ and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_KZ, 4, "requires EVEX_KZ and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ, 4, "requires EVEX_KZ, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_KZ, 3, "requires EVEX_KZ, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_KZ, 4, "requires EVEX_KZ, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_KZ, 4, "requires EVEX_KZ, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_KZ, 3, "requires EVEX_KZ and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_KZ, 4, "requires EVEX_KZ and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_KZ, 4, "requires EVEX_KZ and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") - -#define ENUM_ENTRY(n, r, d) n, -typedef enum { - INSTRUCTION_CONTEXTS - IC_max -} InstructionContext; -#undef ENUM_ENTRY - -/* - * Opcode types, which determine which decode table to use, both in the Intel - * manual and also for the decoder. - */ -typedef enum { - ONEBYTE = 0, - TWOBYTE = 1, - THREEBYTE_38 = 2, - THREEBYTE_3A = 3, - XOP8_MAP = 4, - XOP9_MAP = 5, - XOPA_MAP = 6, - THREEDNOW_MAP = 7 -} OpcodeType; - -/* - * The following structs are used for the hierarchical decode table. After - * determining the instruction's class (i.e., which IC_* constant applies to - * it), the decoder reads the opcode. Some instructions require specific - * values of the ModR/M byte, so the ModR/M byte indexes into the final table. - * - * If a ModR/M byte is not required, "required" is left unset, and the values - * for each instructionID are identical. - */ - -typedef uint16_t InstrUID; - -/* - * ModRMDecisionType - describes the type of ModR/M decision, allowing the - * consumer to determine the number of entries in it. - * - * MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded - * instruction is the same. - * MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode - * corresponds to one instruction; otherwise, it corresponds to - * a different instruction. - * MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte - * divided by 8 is used to select instruction; otherwise, each - * value of the ModR/M byte could correspond to a different - * instruction. - * MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This - corresponds to instructions that use reg field as opcode - * MODRM_FULL - Potentially, each value of the ModR/M byte could correspond - * to a different instruction. - */ - -#define MODRMTYPES \ - ENUM_ENTRY(MODRM_ONEENTRY) \ -ENUM_ENTRY(MODRM_SPLITRM) \ -ENUM_ENTRY(MODRM_SPLITMISC) \ -ENUM_ENTRY(MODRM_SPLITREG) \ -ENUM_ENTRY(MODRM_FULL) - -#define ENUM_ENTRY(n) n, -typedef enum { - MODRMTYPES - MODRM_max -} ModRMDecisionType; -#undef ENUM_ENTRY - -#define CASE_ENCODING_RM \ - case ENCODING_RM: \ - case ENCODING_RM_CD2: \ - case ENCODING_RM_CD4: \ - case ENCODING_RM_CD8: \ - case ENCODING_RM_CD16: \ - case ENCODING_RM_CD32: \ - case ENCODING_RM_CD64 - -#define CASE_ENCODING_VSIB \ - case ENCODING_VSIB: \ - case ENCODING_VSIB_CD2: \ - case ENCODING_VSIB_CD4: \ - case ENCODING_VSIB_CD8: \ - case ENCODING_VSIB_CD16: \ - case ENCODING_VSIB_CD32: \ - case ENCODING_VSIB_CD64 - -// Physical encodings of instruction operands. - -#define ENCODINGS \ -ENUM_ENTRY(ENCODING_NONE, "") \ -ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \ -ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \ -ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2") \ -ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4") \ -ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8") \ -ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \ -ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \ -ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \ -ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \ -ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \ -ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \ -ENUM_ENTRY(ENCODING_VSIB_CD8, "VSIB operand with CDisp scaling of 8") \ -ENUM_ENTRY(ENCODING_VSIB_CD16,"VSIB operand with CDisp scaling of 16") \ -ENUM_ENTRY(ENCODING_VSIB_CD32,"VSIB operand with CDisp scaling of 32") \ -ENUM_ENTRY(ENCODING_VSIB_CD64,"VSIB operand with CDisp scaling of 64") \ -ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \ -ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.") \ -ENUM_ENTRY(ENCODING_IB, "1-byte immediate") \ -ENUM_ENTRY(ENCODING_IW, "2-byte") \ -ENUM_ENTRY(ENCODING_ID, "4-byte") \ -ENUM_ENTRY(ENCODING_IO, "8-byte") \ -ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \ - "the opcode byte") \ -ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \ -ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \ -ENUM_ENTRY(ENCODING_RO, "(RAX..RDI, R8..R15)") \ -ENUM_ENTRY(ENCODING_FP, "Position on floating-point stack in ModR/M " \ - "byte.") \ -ENUM_ENTRY(ENCODING_Iv, "Immediate of operand size") \ -ENUM_ENTRY(ENCODING_Ia, "Immediate of address size") \ -ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \ -ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \ - "opcode byte") \ -ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \ - "in type") \ -ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \ -ENUM_ENTRY(ENCODING_DI, "Destination index; encoded in prefixes") - -#define ENUM_ENTRY(n, d) n, -typedef enum { - ENCODINGS - ENCODING_max -} OperandEncoding; -#undef ENUM_ENTRY - -/* - * Semantic interpretations of instruction operands. - */ -#define TYPES \ - ENUM_ENTRY(TYPE_NONE, "") \ - ENUM_ENTRY(TYPE_REL, "immediate address") \ - ENUM_ENTRY(TYPE_R8, "1-byte register operand") \ - ENUM_ENTRY(TYPE_R16, "2-byte") \ - ENUM_ENTRY(TYPE_R32, "4-byte") \ - ENUM_ENTRY(TYPE_R64, "8-byte") \ - ENUM_ENTRY(TYPE_IMM, "immediate operand") \ - ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \ - ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \ - ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \ - ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \ - ENUM_ENTRY(TYPE_M, "Memory operand") \ - ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \ - ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \ - ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \ - ENUM_ENTRY(TYPE_SRCIDX, "memory at source index") \ - ENUM_ENTRY(TYPE_DSTIDX, "memory at destination index") \ - ENUM_ENTRY(TYPE_MOFFS, "memory offset (relative to segment base)") \ - ENUM_ENTRY(TYPE_ST, "Position on the floating-point stack") \ - ENUM_ENTRY(TYPE_MM64, "8-byte MMX register") \ - ENUM_ENTRY(TYPE_XMM, "16-byte") \ - ENUM_ENTRY(TYPE_YMM, "32-byte") \ - ENUM_ENTRY(TYPE_ZMM, "64-byte") \ - ENUM_ENTRY(TYPE_VK, "mask register") \ - ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \ - ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \ - ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \ - ENUM_ENTRY(TYPE_BNDR, "MPX bounds register") \ - \ - ENUM_ENTRY(TYPE_Rv, "Register operand of operand size") \ - ENUM_ENTRY(TYPE_RELv, "Immediate address of operand size") \ - ENUM_ENTRY(TYPE_DUP0, "Duplicate of operand 0") \ - ENUM_ENTRY(TYPE_DUP1, "operand 1") \ - ENUM_ENTRY(TYPE_DUP2, "operand 2") \ - ENUM_ENTRY(TYPE_DUP3, "operand 3") \ - ENUM_ENTRY(TYPE_DUP4, "operand 4") \ - -#define ENUM_ENTRY(n, d) n, -typedef enum { - TYPES - TYPE_max -} OperandType; -#undef ENUM_ENTRY - -/* - * The specification for how to extract and interpret one operand. - */ -typedef struct OperandSpecifier { - uint8_t encoding; - uint8_t type; -} OperandSpecifier; - -#define X86_MAX_OPERANDS 6 - -/* - * Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode - * are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode, - * respectively. - */ -typedef enum { - MODE_16BIT, - MODE_32BIT, - MODE_64BIT -} DisassemblerMode; - -#endif diff --git a/suite/synctools/asmwriter.py b/suite/synctools/asmwriter.py deleted file mode 100755 index 7549b64ceb..0000000000 --- a/suite/synctools/asmwriter.py +++ /dev/null @@ -1,886 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenAsmWriter.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -arch = sys.argv[4] -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -f1 = open(sys.argv[2], 'w+') - -f2 = open(sys.argv[3], 'w+') - -f1.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f1.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f1.write("\n") - -f2.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f2.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f2.write("\n") - -need_endif = False -in_getRegisterName = False -in_printAliasInstr = False -fragment_no = None -skip_printing = False - -skip_line = 0 -skip_count = 0 - -def replace_getOp(line): - line2 = line - if 'MI->getOperand(0)' in line: - line2 = line.replace('MI->getOperand(0)', 'MCInst_getOperand(MI, 0)') - elif 'MI->getOperand(1)' in line: - line2 = line.replace('MI->getOperand(1)', 'MCInst_getOperand(MI, 1)') - elif 'MI->getOperand(2)' in line: - line2 = line.replace('MI->getOperand(2)', 'MCInst_getOperand(MI, 2)') - elif 'MI->getOperand(3)' in line: - line2 = line.replace('MI->getOperand(3)', 'MCInst_getOperand(MI, 3)') - elif 'MI->getOperand(4)' in line: - line2 = line.replace('MI->getOperand(4)', 'MCInst_getOperand(MI, 4)') - elif 'MI->getOperand(5)' in line: - line2 = line.replace('MI->getOperand(5)', 'MCInst_getOperand(MI, 5)') - elif 'MI->getOperand(6)' in line: - line2 = line.replace('MI->getOperand(6)', 'MCInst_getOperand(MI, 6)') - elif 'MI->getOperand(7)' in line: - line2 = line.replace('MI->getOperand(7)', 'MCInst_getOperand(MI, 7)') - elif 'MI->getOperand(8)' in line: - line2 = line.replace('MI->getOperand(8)', 'MCInst_getOperand(MI, 8)') - return line2 - -def replace_getReg(line): - line2 = line - if 'MI->getOperand(0).getReg()' in line: - line2 = line.replace('MI->getOperand(0).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 0))') - elif 'MI->getOperand(1).getReg()' in line: - line2 = line.replace('MI->getOperand(1).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 1))') - elif 'MI->getOperand(2).getReg()' in line: - line2 = line.replace('MI->getOperand(2).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 2))') - elif 'MI->getOperand(3).getReg()' in line: - line2 = line.replace('MI->getOperand(3).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 3))') - elif 'MI->getOperand(4).getReg()' in line: - line2 = line.replace('MI->getOperand(4).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 4))') - elif 'MI->getOperand(5).getReg()' in line: - line2 = line.replace('MI->getOperand(5).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 5))') - elif 'MI->getOperand(6).getReg()' in line: - line2 = line.replace('MI->getOperand(6).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 6))') - elif 'MI->getOperand(7).getReg()' in line: - line2 = line.replace('MI->getOperand(7).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 7))') - elif 'MI->getOperand(8).getReg()' in line: - line2 = line.replace('MI->getOperand(8).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 8))') - return line2 - -# extract param between text() -# MRI.getRegClass(AArch64::GPR32spRegClassID).contains(MI->getOperand(1).getReg())) -def extract_paren(line, text): - i = line.index(text) - return line[line.index('(', i)+1 : line.index(')', i)] - - -# extract text between <> -# printSVERegOp<'q'> -def extract_brackets(line): - if '<' in line: - return line[line.index('<')+1 : line.index('>')] - else: - return '' - -# delete text between <>, including <> -# printSVERegOp<'q'> -def del_brackets(line): - if '<' in line: - return line[:line.index('<')] + line[line.index('>') + 1:] - else: - return line - - -def print_line(line): - line = line.replace('::', '_') - line = line.replace('nullptr', 'NULL') - if not skip_printing: - if in_getRegisterName: - f2.write(line + "\n") - else: - f1.write(line + "\n") - - -for line in lines: - line = line.rstrip() - #print("@", line) - - # skip Alias - if arch.upper() == 'X86': - if 'PRINT_ALIAS_INSTR' in line: - # done - break - - if skip_line: - skip_count += 1 - if skip_count <= skip_line: - # skip this line - continue - else: - # skip enough number of lines, reset counters - skip_line = 0 - skip_count = 0 - - if "::printInstruction" in line: - if arch.upper() in ('AARCH64', 'ARM64'): - #print_line("static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)\n{") - print_line("static void printInstruction(MCInst *MI, SStream *O)\n{") - else: - print_line("static void printInstruction(MCInst *MI, SStream *O)\n{") - elif 'LLVM_NO_PROFILE_INSTRUMENT_FUNCTION' in line: - continue - elif 'AArch64InstPrinter::getMnemonic' in line: - print_line("static uint64_t getMnemonic(MCInst *MI, SStream *O, unsigned int opcode) {") - elif 'return {AsmStrs+(Bits' in line: - tmp = line.split(',') - prntStr = tmp[0].split('{')[1] - print_line("\tSStream_concat0(O, " + prntStr + ");") - print_line("\treturn Bits;") - elif 'MnemonicInfo = getMnemonic(' in line: - continue - elif 'O << MnemonicInfo' in line: - continue - elif 'uint64_t Bits = MnemonicInfo' in line: - print_line("\tuint64_t Bits = getMnemonic(MI, O, opcode);") - elif 'const char *AArch64InstPrinter::' in line: - continue - elif 'getRegisterName(' in line: - if 'unsigned AltIdx' in line: - print_line("static const char *getRegisterName(unsigned RegNo, unsigned AltIdx)\n{") - else: - print_line("static const char *getRegisterName(unsigned RegNo)\n{") - elif 'getRegisterName' in line: - in_getRegisterName = True - print_line(line) - elif '::printAliasInstr' in line: - if arch.upper() in ('AARCH64', 'PPC'): - print_line("static char *printAliasInstr(MCInst *MI, SStream *OS, MCRegisterInfo *MRI)\n{") - print_line(' #define GETREGCLASS_CONTAIN(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), MCOperand_getReg(MCInst_getOperand(MI, _reg)))') - else: - print_line("static bool printAliasInstr(MCInst *MI, SStream *OS)\n{") - print_line(" unsigned int I = 0, OpIdx, PrintMethodIdx;") - print_line(" char *tmpString;") - in_printAliasInstr = True - elif 'STI.getFeatureBits()[' in line: - if arch.upper() == 'ARM': - line2 = line.replace('STI.getFeatureBits()[', 'ARM_getFeatureBits(MI->csh->mode, ') - elif arch.upper() == 'AARCH64': - line2 = line.replace('STI.getFeatureBits()[', 'AArch64_getFeatureBits(') - line2 = line2.replace(']', ')') - print_line(line2) - elif 'lookupBTIByEncoding' in line: - line = line.replace('AArch64BTIHint::', '') - line = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)') - print_line(line) - elif 'lookupPSBByEncoding' in line: - line = line.replace('AArch64PSBHint::', '') - line = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)') - print_line(line) - elif ', STI, ' in line: - line2 = line.replace(', STI, ', ', ') - - if 'printSVELogicalImm<' in line: - if 'int16' in line: - line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm16') - line2 = line2.replace('', '') - elif 'int32' in line: - line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm32') - line2 = line2.replace('', '') - else: - line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm64') - line2 = line2.replace('', '') - - if 'MI->getOperand(' in line: - line2 = replace_getOp(line2) - - # C++ template - if 'printPrefetchOp' in line2: - param = extract_brackets(line2) - if param == '': - param = 'false' - line2 = del_brackets(line2) - line2 = line2.replace(', O);', ', O, %s);' %param) - line2 = line2.replace(', OS);', ', OS, %s);' %param) - elif '' in line2: - line2 = line2.replace('', '') - line2 = line2.replace(', O);', ', O, false);') - line2 = line2.replace('STI, ', '') - elif '' in line: - line2 = line2.replace('', '') - line2 = line2.replace(', O);', ', O, true);') - line2 = line2.replace('STI, ', '') - elif 'printAdrLabelOperand' in line: - # C++ template - if '<0>' in line: - line2 = line2.replace('<0>', '') - line2 = line2.replace(', O);', ', O, 0);') - elif '<1>' in line: - line2 = line2.replace('<1>', '') - line2 = line2.replace(', O);', ', O, 1);') - elif '<2>' in line: - line2 = line2.replace('<2>', '') - line2 = line2.replace(', O);', ', O, 2);') - elif 'printImm8OptLsl' in line2: - param = extract_brackets(line2) - line2 = del_brackets(line2) - if '8' in param or '16' in param or '32' in param: - line2 = line2.replace('printImm8OptLsl', 'printImm8OptLsl32') - elif '64' in param: - line2 = line2.replace('printImm8OptLsl', 'printImm8OptLsl64') - elif 'printLogicalImm' in line2: - param = extract_brackets(line2) - line2 = del_brackets(line2) - if '8' in param or '16' in param or '32' in param: - line2 = line2.replace('printLogicalImm', 'printLogicalImm32') - elif '64' in param: - line2 = line2.replace('printLogicalImm', 'printLogicalImm64') - elif 'printSVERegOp' in line2 or 'printGPRSeqPairsClassOperand' in line2 or 'printTypedVectorList' in line2 or 'printPostIncOperand' in line2 or 'printImmScale' in line2 or 'printRegWithShiftExtend' in line2 or 'printUImm12Offset' in line2 or 'printExactFPImm' in line2 or 'printMemExtend' in line2 or 'printZPRasFPR' in line2 or 'printMatrixTileVector' in line2 or 'printMatrix<' in line2 or 'printSImm' in line2: - param = extract_brackets(line2) - if param == '': - param = '0' - line2 = del_brackets(line2) - line2 = line2.replace(', O);', ', O, %s);' %param) - line2 = line2.replace(', OS);', ', OS, %s);' %param) - elif 'printComplexRotationOp' in line: - # printComplexRotationOp<90, 0>(MI, 5, STI, O); - bracket_content = line2[line2.index('<') + 1 : line2.index('>')] - line2 = line2.replace('<' + bracket_content + '>', '') - line2 = line2.replace(' O);', ' O, %s);' %bracket_content) - elif 'printAlignedLabel' in line2 or 'printAdrpLabel' in line2: - line2 = line2.replace('Address, ', '') - - print_line(line2) - elif "static const char AsmStrs[]" in line: - print_line("#ifndef CAPSTONE_DIET") - print_line(" static const char AsmStrs[] = {") - need_endif = True - elif "static const char AsmStrsNoRegAltName[]" in line: - print_line("#ifndef CAPSTONE_DIET") - print_line(" static const char AsmStrsNoRegAltName[] = {") - need_endif = True - elif line == ' O << "\\t";': - print_line(" unsigned int opcode = MCInst_getOpcode(MI);") - print_line(' // printf("opcode = %u\\n", opcode);'); - elif 'MI->getOpcode()' in line: - if 'switch' in line: - line2 = line.replace('MI->getOpcode()', 'MCInst_getOpcode(MI)') - else: - line2 = line.replace('MI->getOpcode()', 'opcode') - print_line(line2) - - elif 'O << ' in line: - if '"' in line: - line2 = line.lower() - line2 = line2.replace('o << ', 'SStream_concat0(O, '); - else: - line2 = line.replace('O << ', 'SStream_concat0(O, '); - line2 = line2.replace("'", '"') - line2 = line2.replace(';', ');') - if '" : "' in line2: # "segment : offset" in X86 - line2 = line2.replace('" : "', '":"') - - # ARM - print_line(line2) - - if '", #0"' in line2: - print_line(' op_addImm(MI, 0);') - - if '", #1"' in line2: - print_line(' op_addImm(MI, 1);') - - # PowerPC - if '", 268"' in line2: - print_line(' op_addImm(MI, 268);') - - elif '", 256"' in line2: - print_line(' op_addImm(MI, 256);') - - elif '", 0, "' in line2 or '", 0"' in line2: - print_line(' op_addImm(MI, 0);') - - elif '", -1"' in line2: - print_line(' op_addImm(MI, -1);') - - - if '], [' in line2 or ']!, [' in line2: - print_line(' set_mem_access(MI, false);') - print_line(' set_mem_access(MI, true);') - - elif "\"[\"" in line2: - # Check for SME_Index specific string of only "[" - print_line(' set_sme_index(MI, true);') - - elif '[' in line2: - if not '[]' in line2: - print_line(' set_mem_access(MI, true);') - - elif ']' in line2: - if not '[]' in line2: - print_line(' set_mem_access(MI, false);') - - if '".f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64);') - elif '".f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32);') - elif '".f16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F16);') - elif '".s64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S64);') - elif '".s32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S32);') - elif '".s16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S16);') - elif '".s8\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S8);') - elif '".u64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U64);') - elif '".u32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U32);') - elif '".u16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U16);') - elif '".u8\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U8);') - elif '".i64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_I64);') - elif '".i32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_I32);') - elif '".i16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_I16);') - elif '".i8\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_I8);') - elif '".f16.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F16F64);') - elif '".f64.f16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64F16);') - elif '".f16.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F16F32);') - elif '".f32.f16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32F16);') - elif '".f64.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64F32);') - elif '".f32.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32F64);') - elif '".s32.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S32F32);') - elif '".f32.s32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32S32);') - elif '".u32.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F32);') - elif '".f32.u32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32U32);') - elif '".p8\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_P8);') - elif '".f64.s16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64S16);') - elif '".s16.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S16F64);') - elif '".f32.s16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32S16);') - elif '".s16.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S16F32);') - elif '".f64.s32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64S32);') - elif '".s32.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_S32F64);') - elif '".f64.u16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64U16);') - elif '".u16.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F64);') - elif '".f32.u16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F32U16);') - elif '".u16.f32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F32);') - elif '".f64.u32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F64U32);') - elif '".u32.f64\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F64);') - elif '".f16.u32\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F16U32);') - elif '".u32.f16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F16);') - elif '".f16.u16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_F16U16);') - elif '".u16.f16\\t"' in line2: - print_line(' ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F16);') - elif '"\\tlr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_LR);') - elif '"\\tapsr_nzcv, fpscr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_APSR_NZCV);') - print_line(' ARM_addReg(MI, ARM_REG_FPSCR);') - elif '"\\tpc, lr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_PC);') - print_line(' ARM_addReg(MI, ARM_REG_LR);') - elif '"\\tfpscr, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPSCR);') - elif '"\\tfpexc, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPEXC);') - elif '"\\tfpinst, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPINST);') - elif '"\\tfpinst2, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPINST2);') - elif '"\\tfpsid, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPSID);') - elif '"\\tsp, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_SP);') - elif '"\\tsp!, "' in line2: - print_line(' ARM_addReg(MI, ARM_REG_SP);') - elif '", apsr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_APSR);') - elif '", spsr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_SPSR);') - elif '", fpscr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPSCR);') - elif '", fpscr"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPSCR);') - elif '", fpexc"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPEXC);') - elif '", fpinst"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPINST);') - elif '", fpinst2"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPINST2);') - elif '", fpsid"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_FPSID);') - elif '", mvfr0"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_MVFR0);') - elif '", mvfr1"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_MVFR1);') - elif '", mvfr2"' in line2: - print_line(' ARM_addReg(MI, ARM_REG_MVFR2);') - elif '.8\\t' in line2: - print_line(' ARM_addVectorDataSize(MI, 8);') - elif '.16\\t' in line2: - print_line(' ARM_addVectorDataSize(MI, 16);') - elif '.32\\t' in line2: - print_line(' ARM_addVectorDataSize(MI, 32);') - elif '.64\\t' in line2: - print_line(' ARM_addVectorDataSize(MI, 64);') - elif '" ^"' in line2: - print_line(' ARM_addUserMode(MI);') - - if '.16b' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_16B);') - elif '.8b' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_8B);') - elif '.4b' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4B);') - elif '.b' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1B);') - elif '.8h' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_8H);') - elif '.4h' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4H);') - elif '.2h' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2H);') - elif '.h' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1H);') - elif '.4s' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4S);') - elif '.2s' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2S);') - elif '.s' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1S);') - elif '.2d' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2D);') - elif '.1d' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1D);') - elif '.1q' in line2: - print_line(' arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1Q);') - - if '#0.0' in line2: - print_line(' arm64_op_addFP(MI, 0);') - elif '#0' in line2: - print_line(' arm64_op_addImm(MI, 0);') - elif '#8' in line2: - print_line(' arm64_op_addImm(MI, 8);') - elif '#16' in line2: - print_line(' arm64_op_addImm(MI, 16);') - elif '#32' in line2: - print_line(' arm64_op_addImm(MI, 32);') - - # X86 - if '", %rax"' in line2 or '", rax"' in line2: - print_line(' op_addReg(MI, X86_REG_RAX);') - elif '", %eax"' in line2 or '", eax"' in line2: - print_line(' op_addReg(MI, X86_REG_EAX);') - elif '", %ax"' in line2 or '", ax"' in line2: - print_line(' op_addReg(MI, X86_REG_AX);') - elif '", %al"' in line2 or '", al"' in line2: - print_line(' op_addReg(MI, X86_REG_AL);') - elif '", %dx"' in line2 or '", dx"' in line2: - print_line(' op_addReg(MI, X86_REG_DX);') - elif '", %st(0)"' in line2 or '", st(0)"' in line2: - print_line(' op_addReg(MI, X86_REG_ST0);') - elif '", 1"' in line2: - print_line(' op_addImm(MI, 1);') - elif '", cl"' in line2: - print_line(' op_addReg(MI, X86_REG_CL);') - elif '"{1to2}, "' in line2: - print_line(' op_addAvxBroadcast(MI, X86_AVX_BCAST_2);') - elif '"{1to4}, "' in line2: - print_line(' op_addAvxBroadcast(MI, X86_AVX_BCAST_4);') - elif '"{1to8}, "' in line2: - print_line(' op_addAvxBroadcast(MI, X86_AVX_BCAST_8);') - elif '"{1to16}, "' in line2: - print_line(' op_addAvxBroadcast(MI, X86_AVX_BCAST_16);') - elif '{z}{sae}' in line2: - print_line(' op_addAvxSae(MI);') - print_line(' op_addAvxZeroOpmask(MI);') - elif ('{z}' in line2): - print_line(' op_addAvxZeroOpmask(MI);') - elif '{sae}' in line2: - print_line(' op_addAvxSae(MI);') - elif 'llvm_unreachable("Invalid command number.");' in line: - line2 = line.replace('llvm_unreachable("Invalid command number.");', '// unreachable') - print_line(line2) - elif ('assert(' in line) or ('assert (' in line): - pass - elif 'Invalid alt name index' in line: - pass - elif '::' in line and 'case ' in line: - #print_line(line2) - print_line(line) - elif 'MI->getNumOperands()' in line: - line2 = line.replace('MI->getNumOperands()', 'MCInst_getNumOperands(MI)') - print_line(line2) - elif 'const MCOperand &MCOp' in line: - line2 = line.replace('const MCOperand &MCOp', 'MCOperand *MCOp') - print_line(line2) - elif 'MI->getOperand(0).isImm()' in line: - line2 = line.replace('MI->getOperand(0).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 0))') - print_line(line2) - elif 'MI->getOperand(1).isImm()' in line: - line2 = line.replace('MI->getOperand(1).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 1))') - print_line(line2) - elif 'MI->getOperand(2).isImm()' in line: - line2 = line.replace('MI->getOperand(2).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 2))') - print_line(line2) - elif 'MI->getOperand(3).isImm()' in line: - line2 = line.replace('MI->getOperand(3).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 3))') - print_line(line2) - elif 'MI->getOperand(4).isImm()' in line: - line2 = line.replace('MI->getOperand(4).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 4))') - print_line(line2) - elif 'MI->getOperand(5).isImm()' in line: - line2 = line.replace('MI->getOperand(5).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 5))') - print_line(line2) - elif 'MI->getOperand(6).isImm()' in line: - line2 = line.replace('MI->getOperand(6).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 6))') - print_line(line2) - elif 'MI->getOperand(7).isImm()' in line: - line2 = line.replace('MI->getOperand(7).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 7))') - print_line(line2) - elif 'MI->getOperand(8).isImm()' in line: - line2 = line.replace('MI->getOperand(8).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 8))') - print_line(line2) - elif 'MI->getOperand(0).getImm()' in line: - line2 = line.replace('MI->getOperand(0).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 0))') - print_line(line2) - elif 'MI->getOperand(1).getImm()' in line: - line2 = line.replace('MI->getOperand(1).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 1))') - print_line(line2) - elif 'MI->getOperand(2).getImm()' in line: - line2 = line.replace('MI->getOperand(2).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 2))') - print_line(line2) - elif 'MI->getOperand(3).getImm()' in line: - line2 = line.replace('MI->getOperand(3).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 3))') - print_line(line2) - elif 'MI->getOperand(4).getImm()' in line: - line2 = line.replace('MI->getOperand(4).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 4))') - print_line(line2) - elif 'MI->getOperand(5).getImm()' in line: - line2 = line.replace('MI->getOperand(5).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 5))') - print_line(line2) - elif 'MI->getOperand(6).getImm()' in line: - line2 = line.replace('MI->getOperand(6).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 6))') - print_line(line2) - elif 'MI->getOperand(7).getImm()' in line: - line2 = line.replace('MI->getOperand(7).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 7))') - print_line(line2) - elif 'MI->getOperand(8).getImm()' in line: - line2 = line.replace('MI->getOperand(8).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 8))') - print_line(line2) - elif 'MRI.getRegClass(' in line: - classid = extract_paren(line, 'getRegClass(') - operand = extract_paren(line, 'getOperand') - line2 = line.replace('MI->getNumOperands()', 'MCInst_getNumOperands(MI)') - line2 = ' GETREGCLASS_CONTAIN(%s, %s)' %(classid, operand) - if line.endswith('())) {'): - line2 += ') {' - elif line.endswith(' {'): - line2 += ' {' - elif line.endswith(' &&'): - line2 += ' &&' - print_line(line2) - elif 'MI->getOperand(' in line and 'isReg' in line: - operand = extract_paren(line, 'getOperand') - line2 = ' MCOperand_isReg(MCInst_getOperand(MI, %s))' %(operand) - # MI->getOperand(1).isReg() && - if line.endswith(' {'): - line2 += ' {' - elif line.endswith(' &&'): - line2 += ' &&' - print_line(line2) - elif 'MI->getOperand(' in line and 'getReg' in line: - line2 = replace_getReg(line) - # one more time - line2 = replace_getReg(line2) - print_line(line2) - elif ' return false;' in line and in_printAliasInstr: - print_line(' return NULL;') - elif 'MCOp.isImm()' in line: - line2 = line.replace('MCOp.isImm()', 'MCOperand_isImm(MCOp)') - print_line(line2) - elif 'MCOp.getImm()' in line: - line2 = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)') - if 'int64_t Val =' in line: - line2 = line2.replace('int64_t Val =', 'Val =') - print_line(line2) - elif 'isSVEMaskOfIdenticalElements<' in line: - if 'int8' in line: - line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements8') - line2 = line2.replace('', '') - elif 'int16' in line: - line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements16') - line2 = line2.replace('', '') - elif 'int32' in line: - line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements32') - line2 = line2.replace('', '') - else: - line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements64') - line2 = line2.replace('', '') - print_line(line2) - elif 'switch (PredicateIndex) {' in line: - print_line(' int64_t Val;') - print_line(line) - elif 'uint32_t(' in line and in_printAliasInstr: - line = line.replace('uint32_t(', '') - line = line.replace(')', '') - print_line(line) - elif '#ifndef NDEBUG' in line and in_printAliasInstr: - print_line(""" - char *AsmString; - const size_t OpToSize = sizeof(OpToPatterns) / sizeof(PatternsForOpcode); - - const unsigned opcode = MCInst_getOpcode(MI); - - // Check for alias - int OpToIndex = 0; - for(int i = 0; i < OpToSize; i++){ - if(OpToPatterns[i].Opcode == opcode){ - OpToIndex = i; - break; - } - } - // Check for match - if(opcode != OpToPatterns[OpToIndex].Opcode) - return NULL; - - const PatternsForOpcode opToPat = OpToPatterns[OpToIndex]; - - // Try all patterns for this opcode - uint32_t AsmStrOffset = ~0U; - int patIdx = opToPat.PatternStart; - while(patIdx < (opToPat.PatternStart + opToPat.NumPatterns)){ - // Check operand count first - if(MCInst_getNumOperands(MI) != Patterns[patIdx].NumOperands) - return NULL; - - // Test all conditions for this pattern - int condIdx = Patterns[patIdx].AliasCondStart; - int opIdx = 0; - bool allPass = true; - while(condIdx < (Patterns[patIdx].AliasCondStart + Patterns[patIdx].NumConds)){ - MCOperand *opnd = MCInst_getOperand(MI, opIdx); - opIdx++; - // Not concerned with any Feature related conditions as STI is disregarded - switch (Conds[condIdx].Kind) - { - case AliasPatternCond_K_Ignore : - // Operand can be anything. - break; - case AliasPatternCond_K_Reg : - // Operand must be a specific register. - allPass = allPass && (MCOperand_isReg(opnd) && MCOperand_getReg(opnd) == Conds[condIdx].Value); - break; - case AliasPatternCond_K_TiedReg : - // Operand must match the register of another operand. - allPass = allPass && (MCOperand_isReg(opnd) && MCOperand_getReg(opnd) == - MCOperand_getReg(MCInst_getOperand(MI, Conds[condIdx].Value))); - break; - case AliasPatternCond_K_Imm : - // Operand must be a specific immediate. - allPass = allPass && (MCOperand_isImm(opnd) && MCOperand_getImm(opnd) == Conds[condIdx].Value); - break; - case AliasPatternCond_K_RegClass : - // Operand must be a register in this class. Value is a register class id. - allPass = allPass && (MCOperand_isReg(opnd) && GETREGCLASS_CONTAIN(Conds[condIdx].Value, (opIdx-1))); - break; - case AliasPatternCond_K_Custom : - // Operand must match some custom criteria. - allPass = allPass && AArch64InstPrinterValidateMCOperand(opnd, Conds[condIdx].Value); - break; - case AliasPatternCond_K_Feature : - case AliasPatternCond_K_NegFeature : - case AliasPatternCond_K_OrFeature : - case AliasPatternCond_K_OrNegFeature : - case AliasPatternCond_K_EndOrFeatures : - default : - break; - } - condIdx++; - } - if(allPass){ - AsmStrOffset = Patterns[patIdx].AsmStrOffset; - break; - } - patIdx++; - } - - // If no alias matched, don't print an alias. - if (AsmStrOffset == ~0U) - return NULL; - - AsmString = cs_strdup(&AsmStrings[AsmStrOffset]); - - tmpString = cs_strdup(AsmString); - - while (AsmString[I] != ' ' && AsmString[I] != '\\t' && - AsmString[I] != '$' && AsmString[I] != '\\0') - ++I; - - tmpString[I] = 0; - SStream_concat0(OS, tmpString); - - if (AsmString[I] != '\\0') { - if (AsmString[I] == ' ' || AsmString[I] == '\\t') { - SStream_concat0(OS, " "); - ++I; - } - - bool isSME = false; - do { - if (AsmString[I] == '$') { - ++I; - if (AsmString[I] == (char)0xff) { - ++I; - OpIdx = AsmString[I++] - 1; - PrintMethodIdx = AsmString[I++] - 1; - printCustomAliasOperand(MI, 0, OpIdx, PrintMethodIdx, OS); - } else - printOperand(MI, (unsigned)(AsmString[I++]) - 1, OS); - } else { - if (AsmString[I] == '[') { - if (AsmString[I-1] != ' ') { - set_sme_index(MI, true); - isSME = true; - } else { - set_mem_access(MI, true); - } - } else if (AsmString[I] == ']') { - if (isSME) { - set_sme_index(MI, false); - isSME = false; - } else { - set_mem_access(MI, false); - } - } - SStream_concat1(OS, AsmString[I++]); - } - } while (AsmString[I] != '\\0'); - } - cs_mem_free(AsmString); - return tmpString; -} - """) - in_printAliasInstr = False - # skip next few lines - skip_printing = True - elif '::printCustomAliasOperand' in line: - # print again - skip_printing = False - print_line('static void printCustomAliasOperand(') - elif 'const MCSubtargetInfo &STI' in line: - pass - elif 'const MCInst *MI' in line: - line2 = line.replace('const MCInst *MI', 'MCInst *MI') - print_line(line2) - elif 'llvm_unreachable("' in line: - if 'default: ' in line: - print_line(' default:') - elif 'llvm_unreachable("Unknown MCOperandPredicate kind")' in line: - print_line(' return false; // never reach') - else: - pass - elif 'raw_ostream &' in line: - line2 = line.replace('raw_ostream &', 'SStream *') - if line2.endswith(' {'): - line2 = line2.replace(' {', '\n{') - print_line(line2) - elif 'printPredicateOperand(' in line and 'STI, ' in line: - line2 = line.replace('STI, ', '') - print_line(line2) - elif '// Fragment ' in line: - # // Fragment 0 encoded into 6 bits for 51 unique commands. - tmp = line.strip().split(' ') - fragment_no = tmp[2] - print_line(line) - elif ('switch ((' in line or 'if ((' in line) and 'Bits' in line: - # switch ((Bits >> 14) & 63) { - bits = line.strip() - bits = bits.replace('switch ', '') - bits = bits.replace('if ', '') - bits = bits.replace('{', '') - bits = bits.strip() - print_line(' // printf("Fragment %s: %%"PRIu64"\\n", %s);' %(fragment_no, bits)) - print_line(line) - elif not skip_printing: - print_line(line) - - if line == ' };': - if need_endif and not in_getRegisterName: - # endif only for AsmStrs when we are not inside getRegisterName() - print_line("#endif") - need_endif = False - elif 'return AsmStrs+RegAsmOffset[RegNo-1];' in line: - if in_getRegisterName: - # return NULL for register name on Diet mode - print_line("#else") - print_line(" return NULL;") - print_line("#endif") - print_line("}") - need_endif = False - in_getRegisterName = False - # skip 1 line - skip_line = 1 - elif line == ' }': - # ARM64 - if in_getRegisterName: - # return NULL for register name on Diet mode - print_line("#else") - print_line(" return NULL;") - print_line("#endif") - print_line("}") - need_endif = False - in_getRegisterName = False - # skip 1 line - skip_line = 1 - elif 'default:' in line: - # ARM64 - if in_getRegisterName: - # get the size of RegAsmOffsetvreg[] - print_line(" return (const char *)(sizeof(RegAsmOffsetvreg)/sizeof(RegAsmOffsetvreg[0]));") - - -f1.close() -f2.close() diff --git a/suite/synctools/compare_mapping_insn.py b/suite/synctools/compare_mapping_insn.py deleted file mode 100755 index 7477be811e..0000000000 --- a/suite/synctools/compare_mapping_insn.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -# compare instructions in 2 files of MappingInsn.inc -# find instructions in MappingInsn1, that does not exist in MappingInsn2 -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -mapping1 = f.readlines() -f.close() - -f = open(sys.argv[2]) -mapping2 = f.readlines() -f.close() - -insn1 = [] -for line in mapping1: - if 'X86_INS_' in line: - tmp = line.split(',') - insn_id = tmp[0].strip() - insn1.append(insn_id) - -insn2 = [] -for line in mapping2: - if 'X86_INS_' in line: - tmp = line.split(',') - insn_id = tmp[0].strip() - insn2.append(insn_id) - -for insn_id in insn1: - if not insn_id in insn2: - print("instruction %s is not in list 2" %insn_id) - - diff --git a/suite/synctools/disassemblertables-arch.py b/suite/synctools/disassemblertables-arch.py deleted file mode 100755 index 505b5b0931..0000000000 --- a/suite/synctools/disassemblertables-arch.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenDisassemblerTables.inc for Capstone disassembler. -# this just adds a header -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -print("/* Capstone Disassembly Engine, http://www.capstone-engine.org */") -print("/* By Nguyen Anh Quynh , 2013-2019 */") -print("/* Automatically generated file, do not edit! */\n") -print('#include "../../MCInst.h"') -print('#include "../../LEB128.h"') -print("") - -print(""" -// Helper function for extracting fields from encoded instructions. - -//#if defined(_MSC_VER) && !defined(__clang__) -//__declspec(noinline) -//#endif - -#define FieldFromInstruction(fname, InsnType) \\ -static InsnType fname(InsnType insn, unsigned startBit, unsigned numBits) \\ -{ \\ - InsnType fieldMask; \\ - if (numBits == sizeof(InsnType) * 8) \\ - fieldMask = (InsnType)(-1LL); \\ - else \\ - fieldMask = (((InsnType)1 << numBits) - 1) << startBit; \\ - return (insn & fieldMask) >> startBit; \\ -} -""") - - -# extract text between <> -# printSVERegOp<'q'> -def extract_brackets(line): - return line[line.index('<')+1 : line.index('>')] - -# delete text between <>, including <> -# printSVERegOp<'q'> -def del_brackets(line): - return line[:line.index('<')] + line[line.index('>') + 1:] - - -# skip printing some lines? -skip_print = True -# adding slash at the end of the line for C macro? -adding_slash = False -# skip LLVM_DEBUG -llvm_debug = False - -def print_line(line): - if skip_print is True: - return - if adding_slash: - # skip blank line - if (len(line.strip()) == 0): - return - # // must be handled - if '//' in line: - line = line.replace('//', '/*') - line += ' */' - print(line + ' \\') - else: - print(line) - - -for line in lines: - line2 = line.rstrip() - - if '#include ' in line2: - continue - - # skip until the first decoder table - elif skip_print and 'static const uint8_t DecoderTable' in line2: - skip_print = False - - elif 'end namespace llvm' in line2: - # done - break - - elif 'llvm_unreachable' in line2: - line2 = line2.replace('llvm_unreachable', '/* llvm_unreachable') - line2 += '*/ ' - if '"Invalid index!"' in line2: - pass - #line2 += '\n return true;' - - elif 'Bits[' in line2: - if sys.argv[2] == 'ARM': - line2 = line2.replace('Bits[', 'ARM_getFeatureBits(MI->csh->mode, ') - line2 = line2.replace(']', ')') - elif sys.argv[2] == 'AArch64': - line2 = line2.replace('Bits[', 'AArch64_getFeatureBits(') - line2 = line2.replace(']', ')') - - elif 'static bool checkDecoderPredicate(unsigned Idx, const FeatureBitset &Bits) {' in line2: - line2 = 'static bool checkDecoderPredicate(unsigned Idx, MCInst *MI)\n{' - - elif 'checkDecoderPredicate(PIdx, ' in line2: - line2 = line2.replace(', Bits)', ', MI)') - - elif 'template ' in line2: - continue - - elif 'static DecodeStatus decodeToMCInst' in line2: - line2 = '#define DecodeToMCInst(fname, fieldname, InsnType) \\\n' + \ - 'static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n' + \ - '\t\tuint64_t Address, bool *Decoder) \\\n{' - adding_slash = True - - elif 'fieldFromInstruction' in line2: - line2 = line2.replace('fieldFromInstruction', 'fieldname') - if 'InsnType FieldValue' in line2: - line2 = line2.replace('InsnType ', '') - if 'insertBits(tmp,' in line2: - line2 = line2.replace('insertBits(', '') - tmpLn = line2.split(',') - line2 = tmpLn[0] + ' |=' + tmpLn[1] + ',' + tmpLn[2] + ',' + tmpLn[3] + ' <<' + tmpLn[4] + ';' - - elif 'DecodeComplete = true;' in line2: - # dead code - continue - - elif 'bool &DecodeComplete) {' in line2: - continue - - elif line2 == '}': - if adding_slash: - adding_slash = False - - elif 'static DecodeStatus decodeInstruction' in line2: - line2 = '#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n' + \ - 'static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \\\n' + \ - '\t\tInsnType insn, uint64_t Address) \\\n{ \\\n' + \ - ' unsigned Start, Len, NumToSkip, PIdx, Opc, DecodeIdx; \\\n' + \ - ' InsnType Val, FieldValue, PositiveMask, NegativeMask; \\\n' + \ - ' bool Pred, Fail, DecodeComplete = true; \\\n' + \ - ' uint32_t ExpectedValue;' - - adding_slash = True - print_line(line2) - # skip printing few lines - skip_print = True - elif 'const MCSubtargetInfo &STI' in line2: - skip_print = False - # skip this line - continue - elif 'Bits = STI.getFeatureBits()' in line2: - # skip this line - continue - elif 'errs() << ' in line2: - continue - elif 'unsigned Start =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'unsigned Len =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'unsigned Len;' in line2: - continue - elif 'MCInst TmpMI;' in line2: - continue - elif 'bool Pred;' in line2: - continue - elif 'bool DecodeComplete;' in line2: - continue - elif 'unsigned NumToSkip =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'unsigned PIdx =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'unsigned Opc =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'unsigned DecodeIdx =' in line2: - line2 = line2.replace('unsigned ', '') - elif 'InsnType Val =' in line2: - line2 = line2.replace('InsnType ', '') - elif 'bool Fail' in line2: - line2 = line2.replace('bool ', '') - elif 'InsnType PositiveMask =' in line2: - line2 = line2.replace('InsnType ', '') - elif 'InsnType NegativeMask =' in line2: - line2 = line2.replace('InsnType ', '') - elif 'InsnType ExpectedValue' in line2: - line2 = line2.replace('InsnType ', '') - elif 'ptrdiff_t Loc = ' in line2: - continue - elif 'LLVM_DEBUG(' in line2: - # just this line? - if ');' in line2: - continue - skip_print = True - llvm_debug = True - continue - elif skip_print and llvm_debug and ');' in line2: - llvm_debug = False - skip_print = False - continue - elif 'decodeToMCInst(' in line2: - line2 = line2.replace('decodeToMCInst', 'decoder') - line2 = line2.replace('DecodeComplete);', '&DecodeComplete);') - line2 = line2.replace(', DisAsm', '') - line2 = line2.replace(', TmpMI', ', MI') - elif 'TmpMI.setOpcode(Opc);' in line2: - line2 = ' MCInst_setOpcode(MI, Opc);' - elif 'MI.setOpcode(Opc);' in line2: - line2 = ' MCInst_setOpcode(MI, Opc);' - elif 'MI.clear();' in line2: - line2 = ' MCInst_clear(MI);' - elif 'assert(' in line2: - line2 = line2.replace('assert(', '/* assert(') - line2 += ' */' - elif 'Check(S, ' in line2: - line2 = line2.replace('Check(S, ', 'Check(&S, ') - if 'DecodeImm8OptLsl<' in line2: - param = extract_brackets(line2) - line2 = del_brackets(line2) - line2 = line2.replace(', Decoder)', ', Decoder, %s)' %param) - elif 'DecodeSImm<' in line2: - param = extract_brackets(line2) - line2 = del_brackets(line2) - line2 = line2.replace(', Decoder)', ', Decoder, %s)' %param) - elif 'DecodeMatrixTile<' in line2: - param = extract_brackets(line2) - line2 = del_brackets(line2) - line2 = line2.replace(', Decoder)', ', Decoder, %s)' %param) - if 'DecodeComplete = false; ' in line2: - line2 = line2.replace('DecodeComplete = false; ', '') - elif 'decodeUImmOperand<' in line2 or 'decodeSImmOperand<' in line2 : - # decodeUImmOperand<5>(MI, tmp, Address, Decoder) - param = extract_brackets(line2) - line2 = del_brackets(line2) - line2 = line2.replace(', Decoder)', ', Decoder, %s)' %param) - elif 'MI.addOperand(MCOperand::createImm(tmp));' in line2: - line2 = ' MCOperand_CreateImm0(MI, tmp);' - elif 'MI = TmpMI;' in line2: - line2 = '' - #line2 = line2.replace('TmpMI', '&TmpMI') - elif 'using TmpType = std::conditional' in line2: - continue - elif 'TmpType tmp;' in line2: - line2 = line2.replace('TmpType', 'InsnType') - - line2 = line2.replace('::', '_') - print_line(line2) - -if sys.argv[2] == 'ARM': - print(""" -FieldFromInstruction(fieldFromInstruction_2, uint16_t) -DecodeToMCInst(decodeToMCInst_2, fieldFromInstruction_2, uint16_t) -DecodeInstruction(decodeInstruction_2, fieldFromInstruction_2, decodeToMCInst_2, uint16_t) - -FieldFromInstruction(fieldFromInstruction_4, uint32_t) -DecodeToMCInst(decodeToMCInst_4, fieldFromInstruction_4, uint32_t) -DecodeInstruction(decodeInstruction_4, fieldFromInstruction_4, decodeToMCInst_4, uint32_t) -""") - -if sys.argv[2] in ('AArch64', 'PPC'): - print(""" -FieldFromInstruction(fieldFromInstruction_4, uint32_t) -DecodeToMCInst(decodeToMCInst_4, fieldFromInstruction_4, uint32_t) -DecodeInstruction(decodeInstruction_4, fieldFromInstruction_4, decodeToMCInst_4, uint32_t) -""") diff --git a/suite/synctools/disassemblertables.py b/suite/synctools/disassemblertables.py deleted file mode 100755 index 1816121b48..0000000000 --- a/suite/synctools/disassemblertables.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenDisassemblerTables.inc for Capstone disassembler. -# for X86, this separate ContextDecision tables into another file -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -f1 = open(sys.argv[2], 'w+') - -f2 = open(sys.argv[3], 'w+') - -f1.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f1.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f1.write("\n") - -f2.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f2.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f2.write("\n") - -# static const struct ContextDecision x86DisassemblerOneByteOpcodes = { - -# static const struct ContextDecision x86DisassemblerXOP8Opcodes = { - -write_to_f2 = False - -for line in lines: - if 'ContextDecision x86DisassemblerOneByteOpcodes = {' in line: - # done with f1, start writing to f2 - write_to_f2 = True - - if write_to_f2: - f2.write(line) - else: - f1.write(line) - -f1.close() -f2.close() diff --git a/suite/synctools/disassemblertables2.c b/suite/synctools/disassemblertables2.c deleted file mode 100644 index f336da103b..0000000000 --- a/suite/synctools/disassemblertables2.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Capstone Disassembly Engine */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -// this tool is to generate arch/X86/X86GenDisassemblerTables2.inc -// NOTE: this requires updated X86GenDisassemblerTables2 & X86GenDisassemblerTables2 -// generatedy by ./disassemblertables.py & disassemblertables_reduce.py - -#include -#include -#include - -// X86DisassemblerDecoderCommon.h is copied from Capstone src -#include "../../arch/X86/X86DisassemblerDecoderCommon.h" - -#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0])) - -/// Specifies whether a ModR/M byte is needed and (if so) which -/// instruction each possible value of the ModR/M byte corresponds to. Once -/// this information is known, we have narrowed down to a single instruction. -struct ModRMDecision { - uint8_t modrm_type; - uint16_t instructionIDs; -}; - -/// Specifies which set of ModR/M->instruction tables to look at -/// given a particular opcode. -struct OpcodeDecision { - struct ModRMDecision modRMDecisions[256]; -}; - -/// Specifies which opcode->instruction tables to look at given -/// a particular context (set of attributes). Since there are many possible -/// contexts, the decoder first uses CONTEXTS_SYM to determine which context -/// applies given a specific set of attributes. Hence there are only IC_max -/// entries in this table, rather than 2^(ATTR_max). -struct ContextDecision { - struct OpcodeDecision opcodeDecisions[IC_max]; -}; - -#ifdef CAPSTONE_X86_REDUCE -#include "X86GenDisassemblerTables_reduce2.inc" -#else -#include "X86GenDisassemblerTables2.inc" -#endif - -static void index_OpcodeDecision(const struct OpcodeDecision *decisions, size_t size, - const struct OpcodeDecision *emptyDecision, unsigned int *index_table, - const char *opcodeTable, - const char *index_opcodeTable) -{ - unsigned int i, count = 0; - - for (i = 0; i < size; i++) { - if (memcmp((const void *)&decisions[i], - emptyDecision, sizeof(*emptyDecision)) != 0) { - // this is a non-zero entry - // index_table entry must be != 0 - index_table[i] = count + 1; - count++; - } else - // empty entry - index_table[i] = 0; - } - - printf("static const unsigned char %s[] = {\n", index_opcodeTable); - - for (i = 0; i < size; i++) { - printf(" %u,\n", index_table[i]); - } - - printf("};\n\n"); - - printf("static const struct OpcodeDecision %s[] = {\n", opcodeTable); - for (i = 0; i < size; i++) { - if (index_table[i]) { - unsigned int j; - const struct OpcodeDecision *decision; - - // print out this non-zero entry - printf(" { {\n"); - decision = &decisions[i]; - - for(j = 0; j < ARR_SIZE(emptyDecision->modRMDecisions); j++) { - const char *modrm; - - switch(decision->modRMDecisions[j].modrm_type) { - default: - modrm = "MODRM_ONEENTRY"; - break; - case 1: - modrm = "MODRM_SPLITRM"; - break; - case 2: - modrm = "MODRM_SPLITMISC"; - break; - case 3: - modrm = "MODRM_SPLITREG"; - break; - case 4: - modrm = "MODRM_FULL"; - break; - } - printf(" { %s, %u },\n", - modrm, decision->modRMDecisions[j].instructionIDs); - } - printf(" } },\n"); - } - } - - printf("};\n\n"); -} - - -int main(int argc, char **argv) -{ - unsigned int index_table[ARR_SIZE(x86DisassemblerOneByteOpcodes.opcodeDecisions)]; - const struct OpcodeDecision emptyDecision; - - memset((void *)&emptyDecision, 0, sizeof(emptyDecision)); - - printf("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n"); - printf("/* By Nguyen Anh Quynh , 2013-2019 */\n"); - printf("\n"); - - index_OpcodeDecision(x86DisassemblerOneByteOpcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerOneByteOpcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerOneByteOpcodes", - "index_x86DisassemblerOneByteOpcodes"); - - index_OpcodeDecision(x86DisassemblerTwoByteOpcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerTwoByteOpcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerTwoByteOpcodes", - "index_x86DisassemblerTwoByteOpcodes"); - - index_OpcodeDecision(x86DisassemblerThreeByte38Opcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerThreeByte38Opcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerThreeByte38Opcodes", - "index_x86DisassemblerThreeByte38Opcodes"); - - index_OpcodeDecision(x86DisassemblerThreeByte3AOpcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerThreeByte3AOpcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerThreeByte3AOpcodes", - "index_x86DisassemblerThreeByte3AOpcodes"); - -#ifndef CAPSTONE_X86_REDUCE - index_OpcodeDecision(x86DisassemblerXOP8Opcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerXOP8Opcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerXOP8Opcodes", - "index_x86DisassemblerXOP8Opcodes"); - - index_OpcodeDecision(x86DisassemblerXOP9Opcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerXOP9Opcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerXOP9Opcodes", - "index_x86DisassemblerXOP9Opcodes"); - - index_OpcodeDecision(x86DisassemblerXOPAOpcodes.opcodeDecisions, - ARR_SIZE(x86DisassemblerXOPAOpcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86DisassemblerXOPAOpcodes", - "index_x86DisassemblerXOPAOpcodes"); - - index_OpcodeDecision(x86Disassembler3DNowOpcodes.opcodeDecisions, - ARR_SIZE(x86Disassembler3DNowOpcodes.opcodeDecisions), - &emptyDecision, index_table, - "x86Disassembler3DNowOpcodes", - "index_x86Disassembler3DNowOpcodes"); -#endif - - return 0; -} diff --git a/suite/synctools/disassemblertables_reduce.py b/suite/synctools/disassemblertables_reduce.py deleted file mode 100755 index 674608c0c2..0000000000 --- a/suite/synctools/disassemblertables_reduce.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenDisassemblerTables.inc for Capstone disassembler. -# this just adds a header -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -f1 = open(sys.argv[2], 'w+') - -f2 = open(sys.argv[3], 'w+') - -f1.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f1.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f1.write("\n") - -f2.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f2.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f2.write("\n") - -# static const struct ContextDecision x86DisassemblerOneByteOpcodes = { - -# static const struct ContextDecision x86DisassemblerXOP8Opcodes = { - -write_to_f2 = False - -for line in lines: - # ignore all tables from XOP onwards - if 'ContextDecision x86DisassemblerXOP8Opcodes = {' in line: - # done - break - - if 'ContextDecision x86DisassemblerOneByteOpcodes = {' in line: - # done with f1, start writing to f2 - write_to_f2 = True - - if write_to_f2: - f2.write(line) - else: - f1.write(line) - -f1.close() -f2.close() diff --git a/suite/synctools/genall-arch.sh b/suite/synctools/genall-arch.sh deleted file mode 100755 index 23cdbc7fcf..0000000000 --- a/suite/synctools/genall-arch.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# generate all ARCH*.inc files for Capstone, by Nguyen Anh Quynh - -# Syntax: genall-arch.sh - -# ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM ARM -# ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM AArch64 -# ./genall-arch.sh tablegen ~/projects/capstone.git/arch/ARM PowerPC - -ARCH=$3 - -echo "Generating ${ARCH}GenAsmWriter.inc" -./asmwriter.py $1/${ARCH}GenAsmWriter.inc ${ARCH}GenAsmWriter.inc ${ARCH}GenRegisterName.inc ${ARCH} - -echo "Generating ${ARCH}MappingInsnName.inc (Copy comments to include/capstone/.h for complete insn list.)" -./mapping_insn_name-arch.py $1/${ARCH}GenAsmMatcher.inc > ${ARCH}MappingInsnName.inc -#./mapping_insn_name-arch.py tablegen/ARMGenAsmMatcher.inc - -echo "Generating ${ARCH}MappingInsn.inc" -./mapping_insn-arch.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsn.inc > ${ARCH}MappingInsn.inc - -echo "Generating ${ARCH}GenInstrInfo.inc" -./instrinfo-arch.py $1/${ARCH}GenInstrInfo.inc ${ARCH} > ${ARCH}GenInstrInfo.inc - -echo "Generating ${ARCH}GenDisassemblerTables.inc" -./disassemblertables-arch.py $1/${ARCH}GenDisassemblerTables.inc ${ARCH} > ${ARCH}GenDisassemblerTables.inc - -echo "Generating ${ARCH}GenRegisterInfo.inc" -./registerinfo.py $1/${ARCH}GenRegisterInfo.inc ${ARCH} > ${ARCH}GenRegisterInfo.inc - -echo "Generating ${ARCH}GenSubtargetInfo.inc" -./subtargetinfo.py $1/${ARCH}GenSubtargetInfo.inc ${ARCH} > ${ARCH}GenSubtargetInfo.inc - -case $3 in - ARM) - # for ARM only - echo "Generating ${ARCH}GenAsmWriter-digit.inc" - ./asmwriter.py $1/${ARCH}GenAsmWriter-digit.inc ${ARCH}GenAsmWriter.inc ${ARCH}GenRegisterName_digit.inc ${ARCH} - echo "Generating ${ARCH}GenSystemRegister.inc" - ./systemregister.py $1/${ARCH}GenSystemRegister.inc > ${ARCH}GenSystemRegister.inc - echo "Generating instruction enum in insn_list.txt (for include/capstone/.h)" - ./insn.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsn.inc > insn_list.txt - # then copy these instructions to include/capstone/.h - echo "Generating ${ARCH}MappingInsnOp.inc" - ./mapping_insn_op-arch.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsnOp.inc > ${ARCH}MappingInsnOp.inc - echo "Generating ${ARCH}GenSystemRegister.inc" - ./systemregister.py $1/${ARCH}GenSystemRegister.inc > ${ARCH}GenSystemRegister.inc - ;; - AArch64) - make arm64 - echo "Generating ${ARCH}GenSystemOperands.inc" - ./systemoperand.py tablegen/AArch64GenSystemOperands.inc AArch64GenSystemOperands.inc AArch64GenSystemOperands_enum.inc - echo "Generating instruction enum in insn_list.txt (for include/capstone/.h)" - ./insn.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsn.inc > insn_list.txt - # then copy these instructions to include/capstone/.h - ./arm64_gen_vreg > AArch64GenRegisterV.inc - echo "Generating ${ARCH}MappingInsnOp.inc" - ./mapping_insn_op-arch.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsnOp.inc > ${ARCH}MappingInsnOp.inc - ;; - PowerPC) - # PowerPC - ./insn3.py $1/${ARCH}GenAsmMatcher.inc > insn_list.txt - # then copy these instructions to include/capstone/arch.h - ;; - *) - echo "Generating instruction enum in insn_list.txt (for include/capstone/.h)" - ./insn.py $1/${ARCH}GenAsmMatcher.inc $1/${ARCH}GenInstrInfo.inc $2/${ARCH}MappingInsn.inc > insn_list.txt - ;; -esac - diff --git a/suite/synctools/genall-full.sh b/suite/synctools/genall-full.sh deleted file mode 100755 index 7cb03c43e5..0000000000 --- a/suite/synctools/genall-full.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# generate all X86*.inc files for Capstone, by Nguyen Anh Quynh - -# Syntax: genall.sh - -# ./genall-full.sh tablegen ~/projects/capstone.git/arch/X86 - -echo "Generating GenAsmWriter.inc" -./asmwriter.py $1/X86GenAsmWriter.inc X86GenAsmWriter.inc X86GenRegisterName.inc X86 - -echo "Generating GenAsmWriter1.inc" -./asmwriter.py $1/X86GenAsmWriter1.inc X86GenAsmWriter1.inc X86GenRegisterName1.inc X86 - -echo "Generating instruction enum in insn_list.txt (for include/capstone/.h)" -./insn.py $1/X86GenAsmMatcher.inc $1/X86GenInstrInfo.inc $2/X86MappingInsn.inc > insn_list.txt -# then copy these instructions to include/capstone/x86.h - -echo "Generating MappingInsnName.inc" -./mapping_insn_name.py $1/X86GenAsmMatcher.inc $1/X86GenInstrInfo.inc $2/X86MappingInsn.inc > X86MappingInsnName.inc - -echo "Generating MappingInsn.inc" -./mapping_insn.py $1/X86GenAsmMatcher.inc $1/X86GenInstrInfo.inc $2/X86MappingInsn.inc > X86MappingInsn.inc - -echo "Generating MappingInsnOp.inc" -./mapping_insn_op.py $1/X86GenAsmMatcher.inc $1/X86GenInstrInfo.inc $2/X86MappingInsnOp.inc > X86MappingInsnOp.inc - -echo "Generating GenInstrInfo.inc" -./instrinfo.py $1/X86GenInstrInfo.inc $1/X86GenAsmMatcher.inc > X86GenInstrInfo.inc - -echo "Generating GenDisassemblerTables.inc & X86GenDisassemblerTables2.inc" -./disassemblertables.py $1/X86GenDisassemblerTables.inc X86GenDisassemblerTables.inc X86GenDisassemblerTables2.inc - -make x86 diff --git a/suite/synctools/genall-reduce.sh b/suite/synctools/genall-reduce.sh deleted file mode 100755 index 6f8aafc4c1..0000000000 --- a/suite/synctools/genall-reduce.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# generate all X86*reduce.inc files for Capstone, by Nguyen Anh Quynh - -# Syntax: genall.sh - -# ./genall-reduce.sh tablegen ~/projects/capstone.git/arch/X86 - -echo "Generating GenAsmWriter_reduce.inc" -./asmwriter.py $1/X86GenAsmWriter_reduce.inc X86GenAsmWriter_reduce.inc X86GenRegisterName.inc X86 - -echo "Generating GenAsmWriter1_reduce.inc" -./asmwriter.py $1/X86GenAsmWriter1_reduce.inc X86GenAsmWriter1_reduce.inc X86GenRegisterName1.inc X86 - -echo "Generating MappingInsnName_reduce.inc" -./mapping_insn_name.py $1/X86GenAsmMatcher_reduce.inc $1/X86GenInstrInfo_reduce.inc $2/X86MappingInsn_reduce.inc > X86MappingInsnName_reduce.inc - -echo "Generating MappingInsn_reduce.inc" -./mapping_insn.py $1/X86GenAsmMatcher_reduce.inc $1/X86GenInstrInfo_reduce.inc $2/X86MappingInsn_reduce.inc > X86MappingInsn_reduce.inc - -echo "Generating MappingInsnOp_reduce.inc" -./mapping_insn_op.py $1/X86GenAsmMatcher.inc $1/X86GenInstrInfo_reduce.inc $2/X86MappingInsnOp_reduce.inc > X86MappingInsnOp_reduce.inc - -echo "Generating GenInstrInfo_reduce.inc" -./instrinfo.py $1/X86GenInstrInfo_reduce.inc $1/X86GenAsmMatcher_reduce.inc > X86GenInstrInfo_reduce.inc - -echo "Generating GenDisassemblerTables_reduce.inc & GenDisassemblerTables_reduce2.inc" -./disassemblertables_reduce.py $1/X86GenDisassemblerTables_reduce.inc X86GenDisassemblerTables_reduce.inc X86GenDisassemblerTables_reduce2.inc - diff --git a/suite/synctools/insn.py b/suite/synctools/insn.py deleted file mode 100755 index 9e4612766c..0000000000 --- a/suite/synctools/insn.py +++ /dev/null @@ -1,324 +0,0 @@ -#!/usr/bin/python -# print list of instructions LLVM inc files, for Capstone disassembler. -# this will be put into capstone/.h -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s MappingInsn.inc" %sys.argv[0]) - sys.exit(1) - -# MappingInsn.inc -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AArch64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, insn_id_list, insn_lines -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - #insn_lines = [] - insn_id_list = {} - arch = None - first_insn = None - - pattern = None - # first we try to find Table1, or Table0 - for line in lines: - if 'MatchEntry MatchTable0[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable0[] = {' - elif 'MatchEntry MatchTable1[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable1[] = {' - # last pattern, done - break - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if pattern in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - if not mnem.startswith('__'): - if not first_insn: - arch, first_insn = _arch, insn_id - if not insn_id in insn_id_list: - # print("***", arch, mnem, insn_id) - insn_id_list[insn_id] = mnem - #insn_lines.append(line) - - #return arch, first_insn, insn_id_list, insn_lines - return arch, first_insn, insn_id_list - -# GenAsmMatcher.inc -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -arch = arch.upper() - -#for line in insn_id_list: -# print(line) - - -insn_list = [] -#{ -# X86_AAA, X86_INS_AAA, -##ifndef CAPSTONE_DIET -# { 0 }, { 0 }, { X86_GRP_NOT64BITMODE, 0 }, 0, 0 -##endif -#}, -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - print(arch, insn_id, mnem, mnem_can_be_wrong) - if not mnem_can_be_wrong: - insn = "%s_INS_%s" %(arch.upper(), mnem.upper()) - if insn in insn_list: - return - print("%s," %insn) - insn_list.append(insn) - return - - insn = "%s_%s" %(arch.upper(), insn_id) - # so mnem can be wrong, we need to verify with MappingInsn.inc - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - tmp = mapping[i].split(',') - if tmp[0].strip() == insn: - insn = tmp[1].strip() - if insn in insn_list: - return - #print("==== get below from MappingInsn.inc file: %s" %insn) - print("%s," %insn) - insn_list.append(insn) - return - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -# GenInstrInfo.inc -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - -count = 0 -last_mnem = None - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if 'INSTRUCTION_LIST_END' in line: - break - else: - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch.upper(), insn, last_mnem, mapping, False) - else: - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch.upper(), insn, last_mnem, mapping, True) diff --git a/suite/synctools/insn3.py b/suite/synctools/insn3.py deleted file mode 100755 index fb7b576c5f..0000000000 --- a/suite/synctools/insn3.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/python -# print list of instructions LLVM inc files, for Capstone disassembler. -# this will be put into capstone/.h -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AARCH64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, first_insn, insn_id_list -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - mnem_list = [] - insn_id_list = {} - arch = None - first_insn = None - - pattern = None - # first we try to find Table1, or Table0 - for line in lines: - if 'MatchEntry MatchTable0[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable0[] = {' - elif 'MatchEntry MatchTable1[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable1[] = {' - # last pattern, done - break - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if pattern in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - # skip pseudo instructions - if not mnem.startswith('__'): - # PPC - if mnem.endswith('-') or mnem.endswith('+'): - mnem = mnem[:-1] - - if not first_insn: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list: - # save this - insn_id_list[insn_id] = mnem - - if not mnem in mnem_list: - print("%s_INS_%s," %(arch, mnem.upper())) - mnem_list.append(mnem) - - #return arch, first_insn, insn_id_list - return arch, first_insn, insn_id_list - -# GenAsmMatcher.inc -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) diff --git a/suite/synctools/insn_check.py b/suite/synctools/insn_check.py deleted file mode 100755 index 6fe5e57b5c..0000000000 --- a/suite/synctools/insn_check.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python -# check MappingInsn.inc to find potential incorrect mapping - for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -# ARM_CMPri, ARM_INS_CMN, -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -for line in lines: - if '_INS_' in line: - tmp = line.strip().split(',') - if len(tmp) == 3 and tmp[2] == '': - id_private = tmp[0].strip() - id_public = tmp[1].strip() - pos = id_public.find('_INS_') - mnem = id_public[pos + len('_INS_'):] - if not mnem in id_private: - print("%s -> %s" %(id_private, id_public)) diff --git a/suite/synctools/instrinfo-arch.py b/suite/synctools/instrinfo-arch.py deleted file mode 100755 index fed572eaa7..0000000000 --- a/suite/synctools/instrinfo-arch.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenInstrInfo.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# return (arch, mnem) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AArch64': - arch = 'ARM64' - return (arch, insn_mnem) - -# get (arch, first insn) from MatchTable -def get_first_insn(filename): - f = open(filename) - lines = f.readlines() - f.close() - count = 0 - for line in lines: - line = line.strip() - - if len(line) == 0: - continue - - # Intel syntax in Table1 - if 'MatchEntry MatchTable1[] = {' in line: - count += 1 - #print(line.strip()) - continue - - if count == 1: - arch, mnem = extract_insn(line) - return (arch, mnem) - - return (None, None) - - -#arch, first_insn = get_first_insn(sys.argv[2]) -#first_insn = first_insn.upper() -#print(arch, first_insn) - -arch = sys.argv[2].upper() - -if arch.upper() == 'AARCH64': - arch = 'AArch64' -elif arch.upper() == 'ARM64': - arch = 'AArch64' - -print(""" -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Target Instruction Enum Values and Descriptors *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifdef GET_INSTRINFO_ENUM -#undef GET_INSTRINFO_ENUM -""") - -enum_count = 0 - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if line == '};': - # done with first enum - break - else: - # skip pseudo instructions - if '__' in line or 'setjmp' in line or 'longjmp' in line or 'Pseudo' in line: - pass - else: - print("\t%s_%s" %(arch, line)) - -print('};\n') - -print("#endif // GET_INSTRINFO_ENUM") - -if arch == 'ARM64': - sys.exit(0) - -print("") -print("#ifdef GET_INSTRINFO_MC_DESC") -print("#undef GET_INSTRINFO_MC_DESC") -print("") -print("#define nullptr 0") -print("") - -in_insts = False - -for line in lines: - if line.strip() == '': - continue - - line = line.rstrip() - - if 'static const MCOperandInfo ' in line: - line2 = line.replace('::', '_') - print(line2) - - elif 'Insts[] = {' in line: - # extern const MCInstrDesc ARMInsts[] = { - line2 = line.replace('extern const ', 'static const ') - print("") - print(line2) - in_insts = True - - elif in_insts: - if line == '};': - print(line) - break - # { 0, 1, 1, 0, 0, 0|(1ULL< " %sys.argv[0]) - sys.exit(1) - - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# return (arch, mnem) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AArch64': - arch = 'ARM64' - return (arch, insn_mnem) - -# get (arch, first insn) from MatchTable -def get_first_insn(filename): - f = open(filename) - lines = f.readlines() - f.close() - count = 0 - for line in lines: - line = line.strip() - - if len(line) == 0: - continue - - # Intel syntax in Table1 - if 'MatchEntry MatchTable1[] = {' in line: - count += 1 - #print(line.strip()) - continue - - if count == 1: - arch, mnem = extract_insn(line) - return (arch, mnem) - - return (None, None) - - -arch, first_insn = get_first_insn(sys.argv[2]) -first_insn = first_insn.upper() -arch = arch.upper() -#print(arch, first_insn) - -print(""" -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Target Instruction Enum Values and Descriptors *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifdef GET_INSTRINFO_ENUM -#undef GET_INSTRINFO_ENUM -""") - -enum_count = 0 -meet_insn = False - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if line == '};': - # done with first enum - break - else: - insn = None - if meet_insn: - # enum items - insn = line - elif line.startswith(first_insn): - insn = line - meet_insn = True - if insn: - print("\t%s_%s" %(arch, line)) - -print('};\n') - -print("#endif // GET_INSTRINFO_ENUM") diff --git a/suite/synctools/mapping_insn-arch.py b/suite/synctools/mapping_insn-arch.py deleted file mode 100755 index 3b77f261bc..0000000000 --- a/suite/synctools/mapping_insn-arch.py +++ /dev/null @@ -1,362 +0,0 @@ -#!/usr/bin/python -# print MappingInsn.inc file from LLVM GenAsmMatcher.inc, for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s MappingInsn.inc" %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - #if arch.upper() == 'AARCH64': - # arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - -# extract all insn lines from GenAsmMatcher -# return arch, first_insn, insn_id_list -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - insn_id_list = {} - arch = None - first_insn = None - - pattern = None - # first we try to find Table1, or Table0 - for line in lines: - if 'MatchEntry MatchTable0[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable0[] = {' - elif 'AArch64::' in line and pattern: - # We do not care about Apple Assembly - break - elif 'MatchEntry MatchTable1[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable1[] = {' - # last pattern, done - break - - for line in lines: - line = line.rstrip() - - # skip empty line - if len(line.strip()) == 0: - continue - - if pattern in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - # skip pseudo instructions - if not mnem.startswith('__'): - # PPC - if mnem.endswith('-') or mnem.endswith('+'): - mnem = mnem[:-1] - - if not first_insn: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list and mnem.upper() in insn_id: - # save this - insn_id_list[insn_id] = mnem - - #return arch, first_insn, insn_id_list - return arch, first_insn, insn_id_list - - -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -#arch = arch.upper() -#print("first insn = %s" %first_insn) - -#for line in insn_id_list: -# print(line) - - -#{ -# X86_AAA, X86_INS_AAA, -##ifndef CAPSTONE_DIET -# { 0 }, { 0 }, { X86_GRP_NOT64BITMODE, 0 }, 0, 0 -##endif -#}, -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - #insn = "%s_%s" %(arch.upper(), insn_id) - insn = "%s_%s" %(arch, insn_id) - arch1 = arch - if arch.upper() == 'AARCH64': - arch1 = 'ARM64' - #if '64' in insn_id: - # is64bit = '1' - #else: - # is64bit = '0' - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - tmp = mapping[i].split(',') - if tmp[0].strip() == insn: - if not mnem_can_be_wrong: - print(''' -{ -\t%s, %s_INS_%s, -#ifndef CAPSTONE_DIET -\t%s -#endif -},'''% (insn, arch1, mnem, mapping[i + 2].strip())) - else: # ATTENTION: mnem can be wrong - if not tmp[1].endswith(mnem): - #print("======== cannot find %s, mapping to %s (instead of %s)" %(insn, tmp[1].strip(), mnem)) - pass - print(''' -{ -\t%s, %s, -#ifndef CAPSTONE_DIET -\t%s -#endif -},'''% (insn, tmp[1].strip(), mapping[i + 2].strip())) - - return - - if mnem_can_be_wrong: - #print("======== CANNOT FIND %s, mapping to %s" %(insn, mnem)) - return - pass - - # this insn does not exist in mapping table - print(''' -{ -\t%s, %s_INS_%s, -#ifndef CAPSTONE_DIET -\t{ 0 }, { 0 }, { 0 }, 0, 0 -#endif -},'''% (insn, arch1, mnem)) - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - -count = 0 -last_mnem = '' - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - # skip pseudo instructions - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - # skip pseudo instructions - if '__' in line or 'setjmp' in line or 'longjmp' in line or 'Pseudo' in line: - continue - elif 'INSTRUCTION_LIST_END' in line: - break - else: - insn = line.split('=')[0].strip() - ''' - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - ''' - - if insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch, insn, insn_id_list[insn].upper(), mapping, False) - else: - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch, insn, last_mnem, mapping, True) diff --git a/suite/synctools/mapping_insn.py b/suite/synctools/mapping_insn.py deleted file mode 100755 index c32ddced0f..0000000000 --- a/suite/synctools/mapping_insn.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/python -# print MappingInsn.inc file from LLVM GenAsmMatcher.inc, for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s MappingInsn.inc" %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AARCH64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, insn_id_list, insn_lines -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - count = 0 - #insn_lines = [] - insn_id_list = {} - arch = None - first_insn = None - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'MatchEntry MatchTable1[] = {' in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - count += 1 - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - if count == 1: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list: - # print("***", arch, mnem, insn_id) - insn_id_list[insn_id] = mnem - #insn_lines.append(line) - - #return arch, first_insn, insn_id_list, insn_lines - return arch, first_insn, insn_id_list - - -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -arch = arch.upper() - -#for line in insn_id_list: -# print(line) - - -#{ -# X86_AAA, X86_INS_AAA, -##ifndef CAPSTONE_DIET -# { 0 }, { 0 }, { X86_GRP_NOT64BITMODE, 0 }, 0, 0 -##endif -#}, -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - insn = "%s_%s" %(arch.upper(), insn_id) - if '64' in insn_id: - is64bit = '1' - else: - is64bit = '0' - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - tmp = mapping[i].split(',') - if tmp[0].strip() == insn: - if not mnem_can_be_wrong: - print(''' -{ -\t%s_%s, %s_INS_%s, %s, -#ifndef CAPSTONE_DIET -\t%s -#endif -},'''% (arch, insn_id, arch, mnem, is64bit, mapping[i + 2].strip())) - else: - if not tmp[1].endswith(mnem): - #print("======== cannot find %s, mapping to %s (instead of %s)" %(insn, tmp[1].strip(), mnem)) - pass - print(''' -{ -\t%s_%s, %s, %s, -#ifndef CAPSTONE_DIET -\t%s -#endif -},'''% (arch, insn_id, tmp[1].strip(), is64bit, mapping[i + 2].strip())) - - return - - if mnem_can_be_wrong: - #print("======== CANNOT FIND %s, mapping to %s" %(insn, mnem)) - pass - - print(''' -{ -\t%s_%s, %s_INS_%s, %s, -#ifndef CAPSTONE_DIET -\t{ 0 }, { 0 }, { 0 }, 0, 0 -#endif -},'''% (arch, insn_id, arch, mnem, is64bit)) - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - - -count = 0 -last_mnem = None - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if 'INSTRUCTION_LIST_END' in line: - break - else: - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch.upper(), insn, insn_id_list[insn].upper(), mapping, False) - else: - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch.upper(), insn, last_mnem, mapping, True) diff --git a/suite/synctools/mapping_insn_name-arch.py b/suite/synctools/mapping_insn_name-arch.py deleted file mode 100755 index 417ea0374f..0000000000 --- a/suite/synctools/mapping_insn_name-arch.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/python -# print list of instructions LLVM inc files, for Capstone disassembler. -# this will be put into capstone/.h -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AARCH64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, first_insn, insn_id_list -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - mnem_list = [] - insn_id_list = {} - arch = None - first_insn = None - - pattern = None - # first we try to find Table1, or Table0 - for line in lines: - if 'MatchEntry MatchTable0[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable0[] = {' - elif 'MatchEntry MatchTable1[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable1[] = {' - # last pattern, done - break - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if pattern in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - # skip pseudo instructions - if not mnem.startswith('__'): - # PPC - if mnem.endswith('-') or mnem.endswith('+'): - mnem = mnem[:-1] - - if not first_insn: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list: - # save this - insn_id_list[insn_id] = mnem - - if not mnem in mnem_list: - print('\t"%s", // %s_INS_%s,' %(mnem.lower(), arch, mnem.upper())) - mnem_list.append(mnem) - - #return arch, first_insn, insn_id_list - return arch, first_insn, insn_id_list - -# GenAsmMatcher.inc -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) diff --git a/suite/synctools/mapping_insn_name.py b/suite/synctools/mapping_insn_name.py deleted file mode 100755 index 5f51c3b12a..0000000000 --- a/suite/synctools/mapping_insn_name.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/python -# print list of instructions LLVM inc files, for Capstone disassembler. -# this will be put into capstone/.h -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s MappingInsn.inc" %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AARCH64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, insn_id_list, insn_lines -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - count = 0 - #insn_lines = [] - insn_id_list = {} - arch = None - first_insn = None - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'MatchEntry MatchTable1[] = {' in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - count += 1 - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - if count == 1: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list: - # print("***", arch, mnem, insn_id) - insn_id_list[insn_id] = mnem - #insn_lines.append(line) - - #return arch, first_insn, insn_id_list, insn_lines - return arch, first_insn, insn_id_list - - -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -arch = arch.upper() - -#for line in insn_id_list: -# print(line) - - -insn_list = [] -#{ -# X86_AAA, X86_INS_AAA, -##ifndef CAPSTONE_DIET -# { 0 }, { 0 }, { X86_GRP_NOT64BITMODE, 0 }, 0, 0 -##endif -#}, -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - if not mnem_can_be_wrong: - insn = "%s_INS_%s" %(arch.upper(), mnem.upper()) - if insn in insn_list: - return - print('\t"%s", // %s' %(mnem.lower(), insn)) - insn_list.append(insn) - return - - insn = "%s_%s" %(arch.upper(), insn_id) - # so mnem can be wrong, we need to verify with MappingInsn.inc - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - tmp = mapping[i].split(',') - if tmp[0].strip() == insn: - insn = tmp[1].strip() - if insn in insn_list: - return - mnem = insn[len("%s_INS_" %(arch)):] - #print("==== get below from MappingInsn.inc file: %s" %insn) - print('\t"%s", // %s' %(mnem.lower(), insn)) - insn_list.append(insn) - return - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - - -count = 0 -last_mnem = None - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if 'INSTRUCTION_LIST_END' in line: - break - else: - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch.upper(), insn, last_mnem, mapping, False) - else: - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch.upper(), insn, last_mnem, mapping, True) diff --git a/suite/synctools/mapping_insn_op-arch.py b/suite/synctools/mapping_insn_op-arch.py deleted file mode 100755 index 060dbc84ee..0000000000 --- a/suite/synctools/mapping_insn_op-arch.py +++ /dev/null @@ -1,379 +0,0 @@ -#!/usr/bin/python -# print MappingInsn.inc file from LLVM GenAsmMatcher.inc, for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - #if arch.upper() == 'AARCH64': - # arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - -# extract all insn lines from GenAsmMatcher -# return arch, first_insn, insn_id_list -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - insn_id_list = {} - arch = None - first_insn = None - - pattern = None - # first we try to find Table1, or Table0 - for line in lines: - if 'MatchEntry MatchTable0[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable0[] = {' - elif 'AArch64::' in line and pattern: - # We do not care about Apple Assembly - break - elif 'MatchEntry MatchTable1[] = {' in line.strip(): - pattern = 'MatchEntry MatchTable1[] = {' - # last pattern, done - break - - for line in lines: - line = line.rstrip() - - # skip empty line - if len(line.strip()) == 0: - continue - - if pattern in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - # skip pseudo instructions - if not mnem.startswith('__'): - if not first_insn: - arch, first_insn = _arch, insn_id - if not insn_id in insn_id_list: - # save this - insn_id_list[insn_id] = mnem - - #return arch, first_insn, insn_id_list - return arch, first_insn, insn_id_list - - -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -#arch = arch.upper() - -#for line in insn_id_list: -# print(line) - -#{ /* X86_AAA, X86_INS_AAA: aaa */ -# X86_EFLAGS_UNDEFINED_OF | X86_EFLAGS_UNDEFINED_SF | X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_MODIFY_AF | X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_MODIFY_CF, -# { 0 } -#}, - -#{ /* ARM_ADCri, ARM_INS_ADC: adc${s}${p} $rd, $rn, $imm */ -# { CS_AC_WRITE, CS_AC_READ, 0 } -#}, - -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - insn = "%s_%s" %(arch, insn_id) - arch1 = arch - if arch.upper() == 'AARCH64': - arch1 = 'ARM64' - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - if mapping[i].startswith('{') and '/*' in mapping[i]: - #print(mapping[i]) - tmp = mapping[i].split('/*') - tmp = tmp[1].strip() - tmp = tmp.split(',') - #print("insn2 = |%s|" %tmp.strip()) - if tmp[0].strip() == insn: - if not mnem_can_be_wrong: - if arch.upper() == 'ARM': - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t%s -},'''% (insn, arch1, mnem, mnem.lower(), mapping[i + 1].strip())) - else: # ARM64 - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t%s -\t%s -},'''% (insn, arch, mnem, mnem.lower(), mapping[i + 1].strip(), mapping[i + 2].strip())) - else: - if arch.upper() == 'ARM': - print(''' -{\t/* %s, %s -\t%s -},'''% (insn, ''.join(tmp[1:]), mapping[i + 1].strip())) - else: # ARM64 - print(''' -{\t/* %s, %s -\t%s -\t%s -},'''% (insn, ''.join(tmp[1:]), mapping[i + 1].strip(), mapping[i + 2].strip())) - - return - - if mnem_can_be_wrong: - #print("======== CANNOT FIND %s, mapping to %s" %(insn, mnem)) - return - pass - - # this insn does not exist in mapping table - if arch.upper() == 'ARM': - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t{ 0 } -},'''% (insn, arch1, mnem, mnem.lower())) - else: - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t0, -\t{ 0 } -},'''% (insn, arch, mnem, mnem.lower())) - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - - -count = 0 -last_mnem = None - - -def is_pseudo_insn(insn, lines): - return False - for line in lines: - tmp = '= %s' %insn - if tmp in line and 'MCID::Pseudo' in line: - return True - return False - - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - # skip pseudo instructions - if '__' in line or 'setjmp' in line or 'longjmp' in line or 'Pseudo' in line: - continue - elif 'INSTRUCTION_LIST_END' in line: - break - else: - insn = line.split('=')[0].strip() - - # skip more pseudo instruction - if is_pseudo_insn(insn, lines): - continue - ''' - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - ''' - - if insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch, insn, insn_id_list[insn].upper(), mapping, False) - else: - #pass - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch, insn, last_mnem, mapping, True) diff --git a/suite/synctools/mapping_insn_op.py b/suite/synctools/mapping_insn_op.py deleted file mode 100755 index 95c46f1be7..0000000000 --- a/suite/synctools/mapping_insn_op.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/python -# print MappingInsn.inc file from LLVM GenAsmMatcher.inc, for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[3]) -mapping = f.readlines() -f.close() - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# lib/Target/X86/X86GenAsmMatcher.inc -# static const MatchEntry MatchTable1[] = { -# { 0 /* aaa */, X86::AAA, Convert_NoOperands, Feature_Not64BitMode, { }, }, - -# extract insn from GenAsmMatcher Table -# return (arch, mnem, insn_id) -def extract_insn(line): - tmp = line.split(',') - insn_raw = tmp[1].strip() - insn_mnem = tmp[0].split(' ')[3] - # X86 mov.s - if '.' in insn_mnem: - tmp = insn_mnem.split('.') - insn_mnem = tmp[0] - tmp = insn_raw.split('::') - arch = tmp[0] - # AArch64 -> ARM64 - if arch.upper() == 'AARCH64': - arch = 'ARM64' - return (arch, insn_mnem, tmp[1]) - - - -# extract all insn lines from GenAsmMatcher -# return arch, insn_id_list, insn_lines -def extract_matcher(filename): - f = open(filename) - lines = f.readlines() - f.close() - - match_count = 0 - count = 0 - #insn_lines = [] - insn_id_list = {} - arch = None - first_insn = None - - # 1st enum is register enum - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'MatchEntry MatchTable1[] = {' in line.strip(): - match_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if match_count == 1: - count += 1 - if line == '};': - # done with first enum - break - else: - _arch, mnem, insn_id = extract_insn(line) - if count == 1: - arch, first_insn = _arch, insn_id - - if not insn_id in insn_id_list: - # print("***", arch, mnem, insn_id) - insn_id_list[insn_id] = mnem - #insn_lines.append(line) - - #return arch, first_insn, insn_id_list, insn_lines - return arch, first_insn, insn_id_list - - -#arch, first_insn, insn_id_list, match_lines = extract_matcher(sys.argv[1]) -arch, first_insn, insn_id_list = extract_matcher(sys.argv[1]) -arch = arch.upper() - -#for line in insn_id_list: -# print(line) - -#{ /* X86_AAA, X86_INS_AAA: aaa */ -# X86_EFLAGS_UNDEFINED_OF | X86_EFLAGS_UNDEFINED_SF | X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_MODIFY_AF | X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_MODIFY_CF, -# { 0 } -#}, -def print_entry(arch, insn_id, mnem, mapping, mnem_can_be_wrong): - insn = "%s_%s" %(arch, insn_id) - # first, try to find this entry in old MappingInsn.inc file - for i in range(len(mapping)): - if mapping[i].startswith('{') and '/*' in mapping[i]: - #print(mapping[i]) - tmp = mapping[i].split('/*') - tmp = tmp[1].strip() - tmp = tmp.split(',') - #print("insn2 = |%s|" %tmp.strip()) - if tmp[0].strip() == insn: - if not mnem_can_be_wrong: - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t%s -\t%s -},'''% (insn, arch, mnem, mnem.lower(), mapping[i + 1].strip(), mapping[i + 2].strip())) - else: - print(''' -{\t/* %s, %s -\t%s -\t%s -},'''% (insn, ''.join(tmp[1:]).strip(), mapping[i + 1].strip(), mapping[i + 2].strip())) - - return - - print(''' -{\t/* %s, %s_INS_%s: %s */ -\t0, -\t{ 0 } -},'''% (insn, arch, mnem, mnem.lower())) - - - -# extract from GenInstrInfo.inc, because the insn id is in order -enum_count = 0 -meet_insn = False - -f = open(sys.argv[2]) -lines = f.readlines() -f.close() - - -count = 0 -last_mnem = None - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - #print(line.strip()) - continue - - line = line.strip() - if enum_count == 1: - if 'INSTRUCTION_LIST_END' in line: - break - else: - insn = None - if meet_insn: - # enum items - insn = line.split('=')[0].strip() - if 'CALLSTACK' in insn or 'TAILJUMP' in insn: - # pseudo instruction - insn = None - elif line.startswith(first_insn): - insn = line.split('=')[0].strip() - meet_insn = True - - if insn: - count += 1 - if insn == 'BSWAP16r_BAD': - last_mnem = 'BSWAP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp32': - last_mnem = 'FCMOVNP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVP_Fp3': - last_mnem = 'FCMOVP' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrm_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVSX16rm16': - last_mnem = 'MOVSX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'MOVZX16rm16': - last_mnem = 'MOVZX' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'ST_Fp32m': - last_mnem = 'FST' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMOVNP_Fp64': - last_mnem = 'FCMOVNU' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSDrr_Int': - last_mnem = 'CMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'CMPSSrm_Int': - last_mnem = 'CMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSDrm_Int': - last_mnem = 'VCMPSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCMPSSrm_Int': - last_mnem = 'VCMPSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPCMOVYrrr_REV': - last_mnem = 'VPCMOV' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESDZm': - last_mnem = 'VRNDSCALESD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VRNDSCALESSZm': - last_mnem = 'VRNDSCALESS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPDZ128rm': - last_mnem = 'VMAXPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCPSZ128rm': - last_mnem = 'VMAXPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSDZrm': - last_mnem = 'VMAXSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMAXCSSZrm': - last_mnem = 'VMAXSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPDZ128rm': - last_mnem = 'VMINPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCPSZ128rm': - last_mnem = 'VMINPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSDZrm': - last_mnem = 'VMINSD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMINCSSZrm': - last_mnem = 'VMINSS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VMOV64toPQIZrm': - last_mnem = 'VMOVQ' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PDYrr_REV': - last_mnem = 'VPERMILPD' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VPERMIL2PSYrr_REV': - last_mnem = 'VPERMILPS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SI64Zrm_Int': - last_mnem = 'VCVTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSD2SSrm_Int': - last_mnem = 'VCVTSD2SS' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTSS2SI64Zrm_Int': - last_mnem = 'VCVTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSD2SI64Zrm_Int': - last_mnem = 'VCVTTSD2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - elif insn == 'VCVTTSS2SI64Zrm_Int': - last_mnem = 'VCVTTSS2SI' - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUBADD'): - if insn[len('VFMSUBADD')].isdigit(): - last_mnem = insn[:len('VFMSUBADD123xy')] - else: - last_mnem = insn[:len('VFMSUBADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADDSUB'): - if insn[len('VFMADDSUB')].isdigit(): - last_mnem = insn[:len('VFMADDSUB123xy')] - else: - last_mnem = insn[:len('VFMADDSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMADD'): - if insn[len('VFMADD')].isdigit(): - last_mnem = insn[:len('VFMADD123PD')] - else: - last_mnem = insn[:len('VFMADDPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFMSUB'): - if insn[len('VFMSUB')].isdigit(): - last_mnem = insn[:len('VFMSUB123PD')] - else: - last_mnem = insn[:len('VFMSUBPD')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMADD'): - if insn[len('VFNMADD')].isdigit(): - last_mnem = insn[:len('VFNMADD123xy')] - else: - last_mnem = insn[:len('VFNMADDSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn.startswith('VFNMSUB'): - if insn[len('VFNMSUB')].isdigit(): - last_mnem = insn[:len('VFNMSUB123xy')] - else: - last_mnem = insn[:len('VFNMSUBSS')] - print_entry(arch.upper(), insn, last_mnem, mapping, False) - - elif insn in insn_id_list: - # trust old mapping table - last_mnem = insn_id_list[insn].upper() - print_entry(arch.upper(), insn, insn_id_list[insn].upper(), mapping, False) - else: - # the last option when we cannot find mnem: use the last good mnem - print_entry(arch.upper(), insn, last_mnem, mapping, True) diff --git a/suite/synctools/mapping_reg.py b/suite/synctools/mapping_reg.py deleted file mode 100755 index 0d061c551e..0000000000 --- a/suite/synctools/mapping_reg.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -# print out all registers from LLVM GenRegisterInfo.inc for Capstone disassembler. -# NOTE: the list then must be filtered, manually. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -arch = sys.argv[2].upper() - -enum_count = 0 - -print("""/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */ -/* By Nguyen Anh Quynh , 2013-2019 */ -""") - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - continue - - if enum_count == 1: - if line == '};': - # done with first enum - break - else: - # enum items - if 'NoRegister' in line or 'TARGET_REGS' in line: - continue - reg = line.strip().split('=')[0].strip() - if reg.startswith('H') or reg.endswith('PH') or reg.endswith('IH') or reg.endswith('WH'): - print("{ %s_%s, 0 }," %(arch, reg)) - elif 'K' in reg or 'BND' in reg: - print("{ %s_%s, 0 }," %(arch, reg)) - elif reg in ('DF', 'SSP', 'R8BH', 'R9BH', 'R10BH', 'R11BH', 'R12BH', 'R13BH', 'R14BH', 'R15BH'): - print("{ %s_%s, 0 }," %(arch, reg)) - else: - print("{ %s_%s, %s_REG_%s }," %(arch, reg, arch, reg)) - diff --git a/suite/synctools/register.py b/suite/synctools/register.py deleted file mode 100755 index 3176f695fd..0000000000 --- a/suite/synctools/register.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/python -# print out all registers from LLVM GenRegisterInfo.inc for Capstone disassembler. -# NOTE: the list then must be filtered, manually. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -arch = sys.argv[2].upper() - -enum_count = 0 - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - continue - - if enum_count == 1: - if line == '};': - # done with first enum - break - else: - # enum items - if 'NoRegister' in line or 'TARGET_REGS' in line: - continue - reg = line.strip().split('=')[0].strip() - if reg.startswith('H') or reg.endswith('PH') or or reg.endswith('IH') or or reg.endswith('WH'): - print(" %s_REG_%s = REMOVE," %(arch, reg)) - elif 'K' in reg or 'BND' in reg: - print(" %s_REG_%s = REMOVE," %(arch, reg)) - elif reg in ('DF', 'SSP', 'R8BH', 'R9BH', 'R10BH', 'R11BH', 'R12BH', 'R13BH', 'R14BH', 'R15BH'): - print(" %s_REG_%s = REMOVE," %(arch, reg)) - else: - print(" %s_REG_%s," %(arch, reg)) - diff --git a/suite/synctools/registerinfo.py b/suite/synctools/registerinfo.py deleted file mode 100755 index 36e6d694be..0000000000 --- a/suite/synctools/registerinfo.py +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenRegisterInfo.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -arch = sys.argv[2] - -print(""" -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\\ -|* *| -|* Target Register Enum Values *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifdef GET_REGINFO_ENUM -#undef GET_REGINFO_ENUM -""") - -enum_count = 0 - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - print(line) - continue - - if enum_count == 1: - if line.strip() == '};': - print(line) - # done with first enum - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - -# 2nd enum is register class -enum_count = 0 -print("\n// Register classes") -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - if enum_count == 2: - print(line) - continue - - if enum_count == 2: - if line.strip() == '};': - # done with 2nd enum - print(line.strip()) - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - -if arch.upper() == 'ARM': - # 3rd enum is Subregister indices - enum_count = 0 - print("\n// Subregister indices") - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - if enum_count == 3: - print(line) - continue - - if enum_count == 3: - if line.strip() == '};': - # done with 2nd enum - print(line.strip()) - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - -if arch.upper() == 'AARCH64': - # 3rd enum is Register alternate name indices - enum_count = 0 - print("\n// Register alternate name indices") - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - enum_count += 1 - if enum_count == 3: - print(line) - continue - - if enum_count == 3: - if line.strip() == '};': - # done with 2nd enum - print(line.strip()) - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - - # 4th enum is Subregister indices - enum_count = 0 - print("\n// Subregister indices") - for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {' or 'enum :' in line.strip(): - enum_count += 1 - if enum_count == 4: - print('enum {') - continue - - if enum_count == 4: - if line.strip() == '};': - # done with 2nd enum - print(line.strip()) - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - -# end of enum -print("") -print("#endif // GET_REGINFO_ENUM") - -print(""" -#ifdef GET_REGINFO_MC_DESC -#undef GET_REGINFO_MC_DESC - -""") - -# extract RegDiffLists -finding_struct = True -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if arch + 'RegDiffLists' in line: - finding_struct = False - print("static const MCPhysReg " + arch + "RegDiffLists[] = {") - continue - - if finding_struct: - continue - else: - print(line) - if line == '};': - # done with this struct - print("") - break - -# extract SubRegIdxLists -finding_struct = True -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if arch + 'SubRegIdxLists' in line: - finding_struct = False - print("static const uint16_t " + arch + "SubRegIdxLists[] = {") - continue - - if finding_struct: - continue - else: - print(line) - if line == '};': - # done with this struct - print("") - break - -# extract RegDesc -finding_struct = True -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if arch + 'RegDesc' in line: - finding_struct = False - print("static const MCRegisterDesc " + arch + "RegDesc[] = {") - continue - - if finding_struct: - continue - else: - print(line) - if line == '};': - # done with this struct - print("") - break - -# extract register classes -finding_struct = True -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'Register classes' in line and 'namespace' in line: - finding_struct = False - continue - - if finding_struct: - continue - else: - if 'const' in line: - line2 = line.replace('const', 'static const') - print(line2) - elif '::' in line: - line2 = line.replace('::', '_') - print(line2) - elif 'end anonymous namespace' in line: - # done with this struct - break - else: - print(line) - -print("\n") - -# extract MCRegisterClasses -finding_struct = True -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'MCRegisterClass ' + arch + 'MCRegisterClasses[] = {' in line: - finding_struct = False - print("static const MCRegisterClass " + arch + "MCRegisterClasses[] = {") - continue - - if finding_struct: - continue - else: - if line == '};': - # done with this struct - print('};\n') - break - elif '::' in line: - line = line.replace('::', '_') - - # { GR8, GR8Bits, 130, 20, sizeof(GR8Bits), X86_GR8RegClassID, 1, 1, 1, 1 }, - tmp = line.split(',') - print(" %s, %s, %s }," %(tmp[0].strip(), tmp[1].strip(), tmp[4].strip())) - -print("#endif // GET_REGINFO_MC_DESC") diff --git a/suite/synctools/strinforeduce/Makefile b/suite/synctools/strinforeduce/Makefile deleted file mode 100644 index d533f9a116..0000000000 --- a/suite/synctools/strinforeduce/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: full reduce - -full: - g++ strinforeduce.cpp -o strinforeduce - -reduce: - g++ -DCAPSTONE_X86_REDUCE strinforeduce.cpp -o strinforeduce_reduce - -clean: - rm -rf strinforeduce strinforeduce_reduce diff --git a/suite/synctools/strinforeduce/README b/suite/synctools/strinforeduce/README deleted file mode 100644 index e4ba5cf9dc..0000000000 --- a/suite/synctools/strinforeduce/README +++ /dev/null @@ -1,15 +0,0 @@ -- Run instroinfo2.py on X86GenInstrInfo.inc & X86GenInstrInfo_reduce.inc - - $ ./instrinfo2.py ../tablegen/X86GenInstrInfo.inc > X86GenInstrInfo.inc - $ ./instrinfo2.py ../tablegen/X86GenInstrInfo_reduce.inc > X86GenInstrInfo_reduce.inc - -- Compile - - $ make - -- Run - - $ ./strinforeduce > X86Lookup16.inc - $ ./strinforeduce_reduce > X86Lookup16_reduce.inc - -- Then copy X86Lookup16*.inc to Capstone dir arch/X86/ diff --git a/suite/synctools/strinforeduce/instrinfo2.py b/suite/synctools/strinforeduce/instrinfo2.py deleted file mode 100755 index 6c52bdcd77..0000000000 --- a/suite/synctools/strinforeduce/instrinfo2.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenInstrInfo.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - - -count = 0 -last_line = None - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -# 1st enum is register enum -for line in lines: - line = line.rstrip() - - # skip all MCPhysReg line - if 'static const MCPhysReg ' in line: - continue - - # skip all MCOperandInfo line - if 'static const MCOperandInfo ' in line: - continue - - # skip InitX86MCInstrInfo() - if 'static inline void InitX86MCInstrInfo' in line: - continue - - if 'II->InitMCInstrInfo' in line: - last_line = line - continue - - # skip the next line after II->InitMCInstrInfo - if last_line: - last_line = None - continue - - - if 'extern const MCInstrDesc ' in line: - count += 1 - continue - - if count == 1: - if line == '};': - # done with first enum - count += 1 - continue - else: - print(line) diff --git a/suite/synctools/strinforeduce/strinforeduce.cpp b/suite/synctools/strinforeduce/strinforeduce.cpp deleted file mode 100644 index e441105201..0000000000 --- a/suite/synctools/strinforeduce/strinforeduce.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// By Martin Tofall, Obsidium Software -#define GET_INSTRINFO_ENUM -#define GET_INSTRINFO_MC_DESC - -#ifdef CAPSTONE_X86_REDUCE -#include "X86GenInstrInfo_reduce.inc" -#else -#include "X86GenInstrInfo.inc" -#endif - -#include -#include -#include -#include - -static const char *x86DisassemblerGetInstrName(unsigned Opcode) -{ - return &llvm::X86InstrNameData[llvm::X86InstrNameIndices[Opcode]]; -} - -static bool is16BitEquivalent(const char* orig, const char* equiv) -{ - size_t i; - - for (i = 0;; i++) { - if (orig[i] == '\0' && equiv[i] == '\0') - return true; - - if (orig[i] == '\0' || equiv[i] == '\0') - return false; - - if (orig[i] != equiv[i]) { - if ((orig[i] == 'Q' || orig[i] == 'L') && equiv[i] == 'W') - continue; - - if ((orig[i] == '6' || orig[i] == '3') && equiv[i] == '1') - continue; - - if ((orig[i] == '4' || orig[i] == '2') && equiv[i] == '6') - continue; - - return false; - } - } -} - -// static const char *header = "#ifdef GET_INSTRINFO_MC_DESC\n#undef GET_INSTRINFO_MC_DESC\n\n" -static const char *header = - "typedef struct x86_op_id_pair {\n"\ - "\tuint16_t first;\n" \ - "\tuint16_t second;\n" \ - "} x86_op_id_pair;\n\n" \ - "static const x86_op_id_pair x86_16_bit_eq_tbl[] = {\n"; -static const char *footer = "};\n\n"; - -static const char *header_lookup = "static const uint16_t x86_16_bit_eq_lookup[] = {\n"; -//static const char *footer_lookup = "};\n\n#endif\n"; -static const char *footer_lookup = "};\n"; - -static bool is16BitEquivalent_old(unsigned id1, unsigned id2) -{ - return (is16BitEquivalent(x86DisassemblerGetInstrName(id1), x86DisassemblerGetInstrName(id2))) != false; -} - -//#include "reduced.h" - -#if 0 -static bool is16BitEquivalent_new(unsigned orig, unsigned equiv) -{ - size_t i; - uint16_t idx; - - if (orig == equiv) - return true; // emulate old behaviour - - if ((idx = x86_16_bit_eq_lookup[orig]) != 0) { - for (i = idx - 1; x86_16_bit_eq_tbl[i].first == orig; ++i) { - if (x86_16_bit_eq_tbl[i].second == equiv) - return true; - } - } - - return false; -} -#endif - -int main() -{ - size_t size_names = sizeof(llvm::X86InstrNameData); - size_t size_indices = sizeof(llvm::X86InstrNameIndices); - size_t size_total = size_names + size_indices; - -#if 1 - printf("%s", header); - - size_t eq_count = 0; - std::string str_lookup; - bool got_i = false; - - for (size_t i = 0; i < llvm::X86::INSTRUCTION_LIST_END; ++i) { - const char *name1 = x86DisassemblerGetInstrName(i); - for (size_t j = 0; j < llvm::X86::INSTRUCTION_LIST_END; ++j) { - const char *name2 = x86DisassemblerGetInstrName(j); - if (i != j && is16BitEquivalent(name1, name2) != false) { - //printf("Found equivalent %d and %d\n", i, j); - printf("\t{ %zu, %zu },\n", i, j); - if (!got_i) { - char buf[16]; - sprintf(buf, "\t%zu,\n", eq_count + 1); - str_lookup += buf; - - got_i = true; - } - ++eq_count; - } - } - - if (!got_i) { - //char buf[32]; - //sprintf(buf, "\t0, //%d\n", i); - //str_lookup += buf; - str_lookup += "\t0,\n"; - } - - // reset got_i - got_i = false; - } - - printf("%s", footer); - printf("%s", header_lookup); - printf("%s", str_lookup.c_str()); - printf("%s", footer_lookup); - - // printf("%zu equivalents total\n", eq_count); - // size_t size_new = eq_count * 4 + llvm::X86::INSTRUCTION_LIST_END * 2; - // printf("before: %zu, after: %zu, %zu bytes saved\n", size_total, size_new, size_total - size_new); -#endif - -#if 0 - for (size_t i = 0; i < llvm::X86::INSTRUCTION_LIST_END; ++i) { - for (size_t j = 0; j < llvm::X86::INSTRUCTION_LIST_END; ++j) { - if (is16BitEquivalent_new(i, j) != is16BitEquivalent_old(i, j)) { - bool old_result = is16BitEquivalent_old(i, j); - bool new_result = is16BitEquivalent_new(i, j); - printf("ERROR!\n"); - } - } - } -#endif - -#if 0 - static const size_t BENCH_LOOPS = 50; - - size_t eq_count = 0; - DWORD time = GetTickCount(); - for (size_t l = 0; l < BENCH_LOOPS; ++l) { - for (size_t i = 0; i < llvm::X86::INSTRUCTION_LIST_END; ++i) { - for (size_t j = 0; j < llvm::X86::INSTRUCTION_LIST_END; ++j) - if (is16BitEquivalent_new(i, j)) - ++eq_count; - } - } - - time = GetTickCount() - time; - printf("new: %f msecs\n", static_cast(time) / static_cast(BENCH_LOOPS)); - - eq_count = 0; - time = GetTickCount(); - for (size_t l = 0; l < BENCH_LOOPS; ++l) { - for (size_t i = 0; i < llvm::X86::INSTRUCTION_LIST_END; ++i) { - for (size_t j = 0; j < llvm::X86::INSTRUCTION_LIST_END; ++j) - if (is16BitEquivalent_old(i, j)) - ++eq_count; - } - } - - time = GetTickCount() - time; - printf("old: %f msecs\n", static_cast(time) / static_cast(BENCH_LOOPS)); -#endif - - return 0; -} - diff --git a/suite/synctools/subtargetinfo.py b/suite/synctools/subtargetinfo.py deleted file mode 100755 index e9e87ca844..0000000000 --- a/suite/synctools/subtargetinfo.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenSubtargetInfo.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -arch = sys.argv[2] - -print(""" -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Subtarget Enumeration Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -""") - -count = 0 - -# 1st enum is subtarget enum -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum {': - count += 1 - print(line) - continue - - if count == 1: - if line.strip() == '};': - # done with first enum - break - else: - # enum items - print(" %s_%s" %(arch, line.strip())) - -print('};\n') diff --git a/suite/synctools/systemoperand.py b/suite/synctools/systemoperand.py deleted file mode 100755 index 32afca6b2c..0000000000 --- a/suite/synctools/systemoperand.py +++ /dev/null @@ -1,1179 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenSystemOperands.inc of AArch64 for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -f1 = open(sys.argv[2], 'w+') - -f2 = open(sys.argv[3], 'w+') - -f1.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f1.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f1.write("\n") - -f2.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n") -f2.write("/* By Nguyen Anh Quynh , 2013-2019 */\n") -f2.write("\n") - -# extract PStateValues enum -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum PStateValues {': - count += 1 - f2.write(line.strip() + "\n") - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - f2.write(line + "\n") - f2.write("\n") - break - else: - # skip pseudo instructions - f2.write(" AArch64PState_%s\n" %(line)) - -def print_line(line): - f1.write(line + "\n") - -# extract ExactFPImmValues enum -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum ExactFPImmValues {': - count += 1 - f2.write(line.strip() + "\n") - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - f2.write(line + "\n") - f2.write("\n") - break - else: - # skip pseudo instructions - f2.write(" AArch64ExactFPImm_%s\n" %(line)) - -# extract ATsList[] -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr AT ATsList[] = {': - count += 1 - print_line('static const AT ATsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - c += 1 - -# lookupATByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupATByEncoding' in line and '{' in line: - count += 1 - print_line('const AT *lookupATByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &ATsList[Index[i].index]; -} -""") - - -# extract DBsList[] -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr DB DBsList[] = {': - count += 1 - print_line('static const DB DBsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - print_line(" %s" %(line)) - -# lookupDBByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupDBByEncoding' in line and '{' in line: - count += 1 - print_line('const DB *lookupDBByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &DBsList[Index[i].index]; -} -""") - - -# extract DCsList[] -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr DC DCsList[] = {': - count += 1 - print_line('static const DC DCsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - c += 1 - -# lookupDCByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupDCByEncoding' in line and '{' in line: - count += 1 - print_line('const DC *lookupDCByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &DCsList[Index[i].index]; -} -""") - - -# extract ICsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr IC ICsList[] = {': - count += 1 - print_line('static const IC ICsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - #tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupICByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupICByEncoding' in line and '{' in line: - count += 1 - print_line('const IC *lookupICByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &ICsList[Index[i].index]; -} -""") - - -# extract TLBIsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr TLBI TLBITable[] = {': - count += 1 - print_line('static const TLBI TLBIsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s, %s }, // %u" %(tmp[0].lower(), tmp[1], tmp[2], c)) - #print_line(" %s" %line.lower()) - c += 1 - -# lookupTLBIByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupTLBIByEncoding' in line and '{' in line: - count += 1 - print_line('const TLBI *lookupTLBIByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &TLBIsList[Index[i].index]; -} -""") - -# extract SVEPRFMsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr SVEPRFM SVEPRFMsList[] = {': - count += 1 - print_line('static const SVEPRFM SVEPRFMsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - #print_line(" %s" %line.lower()) - c += 1 - -# lookupSVEPRFMByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupSVEPRFMByEncoding' in line and '{' in line: - count += 1 - print_line('const SVEPRFM *lookupSVEPRFMByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &SVEPRFMsList[Index[i].index]; -} -""") - - -# extract PRFMsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr PRFM PRFMsList[] = {': - count += 1 - print_line('static const PRFM PRFMsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - #tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupPRFMByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupPRFMByEncoding' in line and '{' in line: - count += 1 - print_line('const PRFM *lookupPRFMByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &PRFMsList[Index[i].index]; -} -""") - - -# extract PSBsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr PSB PSBsList[] = {': - count += 1 - print_line('static const PSB PSBsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - #tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupPSBByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupPSBByEncoding' in line and '{' in line: - count += 1 - print_line('const PSB *lookupPSBByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &PSBsList[Index[i].index]; -} -""") - - -# extract ISBsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr ISB ISBsList[] = {': - count += 1 - print_line('static const ISB ISBsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - #tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupISBByName -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupISBByEncoding' in line and '{' in line: - count += 1 - print_line('const ISB *lookupISBByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &ISBsList[Index[i].index]; -} -""") - - -# extract TSBsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr TSB TSBsList[] = {': - count += 1 - print_line('static const TSB TSBsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - #print_line(" %s" %line.lower()) - c += 1 - -# lookupTSBByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupTSBByEncoding' in line and '{' in line: - count += 1 - print_line('const TSB *lookupTSBByEncoding(uint16_t Encoding)\n{') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - if (Encoding >= ARR_SIZE(TSBsList)) - return NULL; - else - return &TSBsList[Index[Encoding].index]; -} -""") - - -# extract SysRegsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr SysReg SysRegsList[] = {': - count += 1 - print_line('static const SysReg SysRegsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s, %s, %s }, // %u" %(tmp[0].lower(), tmp[2], tmp[3], tmp[4], c)) - #print_line(" %s" %line.lower()) - c += 1 - -# lookupSysRegByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupSysRegByEncoding' in line and '{' in line: - count += 1 - print_line('const SysReg *lookupSysRegByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &SysRegsList[Index[i].index]; -} -""") - -# extract PStatesList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr PState PStatesList[] = {': - count += 1 - print_line('static const PState PStatesList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - #print_line(" %s" %line.lower()) - c += 1 - -# lookupPStateByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupPStateByEncoding' in line and '{' in line: - count += 1 - print_line('const PState *lookupPStateByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &PStatesList[Index[i].index]; -} -""") - -# extract SVEPREDPATsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr SVEPREDPAT SVEPREDPATsList[] = {': - count += 1 - print_line('static const SVEPREDPAT SVEPREDPATsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupSVEPREDPATByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupSVEPREDPATByEncoding' in line and '{' in line: - count += 1 - print_line('const SVEPREDPAT *lookupSVEPREDPATByEncoding(uint16_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &SVEPREDPATsList[Index[i].index]; -} -""") - -# extract SVCRsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr SVCR SVCRsList[] = {': - count += 1 - print_line('static const SVCR SVCRsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - c += 1 - -# lookupSVCRByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupSVCRByEncoding' in line and '{' in line: - count += 1 - print_line('const SVCR *lookupSVCRByEncoding(uint8_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &SVCRsList[Index[i].index]; -} -""") - -# extract BTIsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr BTI BTIsList[] = {': - count += 1 - print_line('static const BTI BTIsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s, // %u" %(tmp[0].lower(), tmp[1], c)) - c += 1 - -# lookupBTIByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupBTIByEncoding' in line and '{' in line: - count += 1 - print_line('const BTI *lookupBTIByEncoding(uint8_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &BTIsList[Index[i].index]; -} -""") - - -# extract DBnXSsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr DBnXS DBnXSsList[] = {': - count += 1 - print_line('static const DBnXS DBnXSsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - print_line(" %s, %s, %s}, // %u" %(tmp[0].lower(), tmp[1], tmp[2], c)) - c += 1 - -# lookupDBnXSByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupDBnXSByEncoding' in line and '{' in line: - count += 1 - print_line('const DBnXS *lookupDBnXSByEncoding(uint8_t Encoding)\n{') - print_line(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), Encoding); - if (i == -1) - return NULL; - else - return &DBnXSsList[Index[i].index]; -} -""") - -# extract ExactFPImmsList -count = 0 -c = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'constexpr ExactFPImm ExactFPImmsList[] = {': - count += 1 - print_line('static const ExactFPImm ExactFPImmsList[] = {') - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - print_line('};\n') - break - else: - # skip pseudo instructions - line = line.replace('::', '_') - #line = line.replace('{}', '{ 0 }') - line = line.replace('{}', '') - tmp = line.split(',') - #print_line(" %s, %s }, // %u" %(tmp[0].lower(), tmp[1], c)) - print_line(" %s" %line.lower()) - c += 1 - -# lookupExactFPImmByEnum -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupExactFPImmByEnum' in line and '{' in line: - count += 1 - print_line('const ExactFPImm *lookupExactFPImmByEnum(uint16_t Encoding)\n{') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print_line(line) - break - else: - # enum items - print_line(line) - -print_line(""" - if (Encoding >= ARR_SIZE(ExactFPImmsList)) - return NULL; - else - return &ExactFPImmsList[Index[Encoding].index]; -} -""") - diff --git a/suite/synctools/systemregister.py b/suite/synctools/systemregister.py deleted file mode 100755 index ed3e94352f..0000000000 --- a/suite/synctools/systemregister.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/python -# convert LLVM GenSystemRegister.inc for Capstone disassembler. -# by Nguyen Anh Quynh, 2019 - -import sys - -if len(sys.argv) == 1: - print("Syntax: %s " %sys.argv[0]) - sys.exit(1) - -f = open(sys.argv[1]) -lines = f.readlines() -f.close() - -#arch = sys.argv[2].upper() - -print(""" -/* Capstone Disassembly Engine, http://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2019 */ - -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* GenSystemRegister Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -""") - -# extract BankedRegValues enum -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if line.strip() == 'enum BankedRegValues {': - count += 1 - print(line.strip()) - continue - - line = line.strip() - if count == 1: - if line == '};': - # done with first enum - break - else: - # skip pseudo instructions - print("\t%s" %(line)) - -print('};\n') - -# extract MClassSysRegsList -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'MClassSysRegsList[]' in line: - count += 1 - print('static const MClassSysReg MClassSysRegsList[] = {') - continue - - if count == 1: - if line.strip() == '};': - # done with first enum - break - else: - # enum items - # { "apsr_g", 0x400, 0x0, 0x400, {ARM::FeatureDSP} }, // 0 - line2 = line.replace('::', '_') - sysreg = line2[line2.index('"') + 1 : line2.index('",')] - tmp = line2.split(',') - print("%s, ARM_SYSREG_%s%s" %(line2[:line2.index('",') + 1], sysreg.upper(), line2[line2.index('",') + 1 :])) - -print('};\n') - -# extract BankedRegsList -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'BankedRegsList[]' in line: - count += 1 - print('static const BankedReg BankedRegsList[] = {') - continue - - if count == 1: - if line.strip() == '};': - # done with first enum - break - else: - # enum items - line2 = line.replace('::', '_') - sysreg = line2[line2.index('"') + 1 : line2.index('",')] - tmp = line2.split(',') - print("%s, ARM_SYSREG_%s%s" %(line2[:line2.index('",') + 1], sysreg.upper(), line2[line2.index('",') + 1 :])) - -print('};\n') - -# lookupMClassSysRegByM2M3Encoding8 -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupMClassSysRegByM2M3Encoding8' in line and '{' in line: - count += 1 - print('const MClassSysReg *lookupMClassSysRegByM2M3Encoding8(uint16_t encoding)\n{') - print(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print(line) - break - else: - # enum items - print(line) - -print(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding); - if (i == -1) - return NULL; - else - return &MClassSysRegsList[Index[i].index]; -} -""") - - -# lookupMClassSysRegByM1Encoding12 -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupMClassSysRegByM1Encoding12' in line and '{' in line: - count += 1 - print('const MClassSysReg *lookupMClassSysRegByM1Encoding12(uint16_t encoding)\n{') - print(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print(line) - break - else: - # enum items - print(line) - -print(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding); - if (i == -1) - return NULL; - else - return &MClassSysRegsList[Index[i].index]; -} -""") - -# lookupBankedRegByEncoding -count = 0 -for line in lines: - line = line.rstrip() - - if len(line.strip()) == 0: - continue - - if 'lookupBankedRegByEncoding' in line and '{' in line: - count += 1 - print('const BankedReg *lookupBankedRegByEncoding(uint8_t encoding)\n{') - print(' unsigned int i;') - continue - - if count == 1 and 'IndexType Index[] = {' in line: - count += 1 - - if count == 2: - if line.strip() == '};': - # done with array, or this function? - print(line) - break - else: - # enum items - print(line) - -print(""" - i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding); - if (i == -1) - return NULL; - else - return &BankedRegsList[Index[i].index]; -} -""") - diff --git a/suite/synctools/tablegen/X86/X86.td b/suite/synctools/tablegen/X86/X86.td deleted file mode 100644 index 63c2dc4da6..0000000000 --- a/suite/synctools/tablegen/X86/X86.td +++ /dev/null @@ -1,1203 +0,0 @@ -//===-- X86.td - Target definition file for the Intel X86 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a target description file for the Intel i386 architecture, referred -// to here as the "X86" architecture. -// -//===----------------------------------------------------------------------===// - -// Get the target-independent interfaces which we are implementing... -// -include "llvm/Target/Target.td" - -//===----------------------------------------------------------------------===// -// X86 Subtarget state -// - -def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", - "64-bit mode (x86_64)">; -def Mode32Bit : SubtargetFeature<"32bit-mode", "In32BitMode", "true", - "32-bit mode (80386)">; -def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true", - "16-bit mode (i8086)">; - -//===----------------------------------------------------------------------===// -// X86 Subtarget features -//===----------------------------------------------------------------------===// - -def FeatureX87 : SubtargetFeature<"x87","HasX87", "true", - "Enable X87 float instructions">; - -def FeatureNOPL : SubtargetFeature<"nopl", "HasNOPL", "true", - "Enable NOPL instruction">; - -def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", - "Enable conditional move instructions">; - -def FeaturePOPCNT : SubtargetFeature<"popcnt", "HasPOPCNT", "true", - "Support POPCNT instruction">; - -def FeatureFXSR : SubtargetFeature<"fxsr", "HasFXSR", "true", - "Support fxsave/fxrestore instructions">; - -def FeatureXSAVE : SubtargetFeature<"xsave", "HasXSAVE", "true", - "Support xsave instructions">; - -def FeatureXSAVEOPT: SubtargetFeature<"xsaveopt", "HasXSAVEOPT", "true", - "Support xsaveopt instructions">; - -def FeatureXSAVEC : SubtargetFeature<"xsavec", "HasXSAVEC", "true", - "Support xsavec instructions">; - -def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true", - "Support xsaves instructions">; - -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions", - // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. - [FeatureCMOV]>; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions", - [FeatureSSE1]>; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions", - [FeatureSSE2]>; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions", - [FeatureSSE3]>; -def FeatureSSE41 : SubtargetFeature<"sse4.1", "X86SSELevel", "SSE41", - "Enable SSE 4.1 instructions", - [FeatureSSSE3]>; -def FeatureSSE42 : SubtargetFeature<"sse4.2", "X86SSELevel", "SSE42", - "Enable SSE 4.2 instructions", - [FeatureSSE41]>; -// The MMX subtarget feature is separate from the rest of the SSE features -// because it's important (for odd compatibility reasons) to be able to -// turn it off explicitly while allowing SSE+ to be on. -def FeatureMMX : SubtargetFeature<"mmx","X863DNowLevel", "MMX", - "Enable MMX instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions", - [FeatureMMX]>; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions", - [Feature3DNow]>; -// All x86-64 hardware has SSE2, but we don't mark SSE2 as an implied -// feature, because SSE2 can be disabled (e.g. for compiling OS kernels) -// without disabling 64-bit mode. -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions", - [FeatureCMOV]>; -def FeatureCMPXCHG16B : SubtargetFeature<"cx16", "HasCmpxchg16b", "true", - "64-bit with cmpxchg16b", - [Feature64Bit]>; -def FeatureSlowSHLD : SubtargetFeature<"slow-shld", "IsSHLDSlow", "true", - "SHLD instruction is slow">; -def FeatureSlowPMULLD : SubtargetFeature<"slow-pmulld", "IsPMULLDSlow", "true", - "PMULLD instruction is slow">; -// FIXME: This should not apply to CPUs that do not have SSE. -def FeatureSlowUAMem16 : SubtargetFeature<"slow-unaligned-mem-16", - "IsUAMem16Slow", "true", - "Slow unaligned 16-byte memory access">; -def FeatureSlowUAMem32 : SubtargetFeature<"slow-unaligned-mem-32", - "IsUAMem32Slow", "true", - "Slow unaligned 32-byte memory access">; -def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true", - "Support SSE 4a instructions", - [FeatureSSE3]>; - -def FeatureAVX : SubtargetFeature<"avx", "X86SSELevel", "AVX", - "Enable AVX instructions", - [FeatureSSE42]>; -def FeatureAVX2 : SubtargetFeature<"avx2", "X86SSELevel", "AVX2", - "Enable AVX2 instructions", - [FeatureAVX]>; -def FeatureFMA : SubtargetFeature<"fma", "HasFMA", "true", - "Enable three-operand fused multiple-add", - [FeatureAVX]>; -def FeatureF16C : SubtargetFeature<"f16c", "HasF16C", "true", - "Support 16-bit floating point conversion instructions", - [FeatureAVX]>; -def FeatureAVX512 : SubtargetFeature<"avx512f", "X86SSELevel", "AVX512F", - "Enable AVX-512 instructions", - [FeatureAVX2, FeatureFMA, FeatureF16C]>; -def FeatureERI : SubtargetFeature<"avx512er", "HasERI", "true", - "Enable AVX-512 Exponential and Reciprocal Instructions", - [FeatureAVX512]>; -def FeatureCDI : SubtargetFeature<"avx512cd", "HasCDI", "true", - "Enable AVX-512 Conflict Detection Instructions", - [FeatureAVX512]>; -def FeatureVPOPCNTDQ : SubtargetFeature<"avx512vpopcntdq", "HasVPOPCNTDQ", - "true", "Enable AVX-512 Population Count Instructions", - [FeatureAVX512]>; -def FeaturePFI : SubtargetFeature<"avx512pf", "HasPFI", "true", - "Enable AVX-512 PreFetch Instructions", - [FeatureAVX512]>; -def FeaturePREFETCHWT1 : SubtargetFeature<"prefetchwt1", "HasPREFETCHWT1", - "true", - "Prefetch with Intent to Write and T1 Hint">; -def FeatureDQI : SubtargetFeature<"avx512dq", "HasDQI", "true", - "Enable AVX-512 Doubleword and Quadword Instructions", - [FeatureAVX512]>; -def FeatureBWI : SubtargetFeature<"avx512bw", "HasBWI", "true", - "Enable AVX-512 Byte and Word Instructions", - [FeatureAVX512]>; -def FeatureVLX : SubtargetFeature<"avx512vl", "HasVLX", "true", - "Enable AVX-512 Vector Length eXtensions", - [FeatureAVX512]>; -def FeatureVBMI : SubtargetFeature<"avx512vbmi", "HasVBMI", "true", - "Enable AVX-512 Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureVBMI2 : SubtargetFeature<"avx512vbmi2", "HasVBMI2", "true", - "Enable AVX-512 further Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureIFMA : SubtargetFeature<"avx512ifma", "HasIFMA", "true", - "Enable AVX-512 Integer Fused Multiple-Add", - [FeatureAVX512]>; -def FeaturePKU : SubtargetFeature<"pku", "HasPKU", "true", - "Enable protection keys">; -def FeatureVNNI : SubtargetFeature<"avx512vnni", "HasVNNI", "true", - "Enable AVX-512 Vector Neural Network Instructions", - [FeatureAVX512]>; -def FeatureBITALG : SubtargetFeature<"avx512bitalg", "HasBITALG", "true", - "Enable AVX-512 Bit Algorithms", - [FeatureBWI]>; -def FeaturePCLMUL : SubtargetFeature<"pclmul", "HasPCLMUL", "true", - "Enable packed carry-less multiplication instructions", - [FeatureSSE2]>; -def FeatureGFNI : SubtargetFeature<"gfni", "HasGFNI", "true", - "Enable Galois Field Arithmetic Instructions", - [FeatureSSE2]>; -def FeatureVPCLMULQDQ : SubtargetFeature<"vpclmulqdq", "HasVPCLMULQDQ", "true", - "Enable vpclmulqdq instructions", - [FeatureAVX, FeaturePCLMUL]>; -def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", - "Enable four-operand fused multiple-add", - [FeatureAVX, FeatureSSE4A]>; -def FeatureXOP : SubtargetFeature<"xop", "HasXOP", "true", - "Enable XOP instructions", - [FeatureFMA4]>; -def FeatureSSEUnalignedMem : SubtargetFeature<"sse-unaligned-mem", - "HasSSEUnalignedMem", "true", - "Allow unaligned memory operands with SSE instructions">; -def FeatureAES : SubtargetFeature<"aes", "HasAES", "true", - "Enable AES instructions", - [FeatureSSE2]>; -def FeatureVAES : SubtargetFeature<"vaes", "HasVAES", "true", - "Promote selected AES instructions to AVX512/AVX registers", - [FeatureAVX, FeatureAES]>; -def FeatureTBM : SubtargetFeature<"tbm", "HasTBM", "true", - "Enable TBM instructions">; -def FeatureLWP : SubtargetFeature<"lwp", "HasLWP", "true", - "Enable LWP instructions">; -def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true", - "Support MOVBE instruction">; -def FeatureRDRAND : SubtargetFeature<"rdrnd", "HasRDRAND", "true", - "Support RDRAND instruction">; -def FeatureFSGSBase : SubtargetFeature<"fsgsbase", "HasFSGSBase", "true", - "Support FS/GS Base instructions">; -def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true", - "Support LZCNT instruction">; -def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true", - "Support BMI instructions">; -def FeatureBMI2 : SubtargetFeature<"bmi2", "HasBMI2", "true", - "Support BMI2 instructions">; -def FeatureRTM : SubtargetFeature<"rtm", "HasRTM", "true", - "Support RTM instructions">; -def FeatureADX : SubtargetFeature<"adx", "HasADX", "true", - "Support ADX instructions">; -def FeatureSHA : SubtargetFeature<"sha", "HasSHA", "true", - "Enable SHA instructions", - [FeatureSSE2]>; -def FeatureSHSTK : SubtargetFeature<"shstk", "HasSHSTK", "true", - "Support CET Shadow-Stack instructions">; -def FeaturePRFCHW : SubtargetFeature<"prfchw", "HasPRFCHW", "true", - "Support PRFCHW instructions">; -def FeatureRDSEED : SubtargetFeature<"rdseed", "HasRDSEED", "true", - "Support RDSEED instruction">; -def FeatureLAHFSAHF : SubtargetFeature<"sahf", "HasLAHFSAHF", "true", - "Support LAHF and SAHF instructions">; -def FeatureMWAITX : SubtargetFeature<"mwaitx", "HasMWAITX", "true", - "Enable MONITORX/MWAITX timer functionality">; -def FeatureCLZERO : SubtargetFeature<"clzero", "HasCLZERO", "true", - "Enable Cache Line Zero">; -def FeatureCLDEMOTE : SubtargetFeature<"cldemote", "HasCLDEMOTE", "true", - "Enable Cache Demote">; -def FeaturePTWRITE : SubtargetFeature<"ptwrite", "HasPTWRITE", "true", - "Support ptwrite instruction">; -def FeatureMPX : SubtargetFeature<"mpx", "HasMPX", "true", - "Support MPX instructions">; -def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true", - "Use LEA for adjusting the stack pointer">; -def FeatureSlowDivide32 : SubtargetFeature<"idivl-to-divb", - "HasSlowDivide32", "true", - "Use 8-bit divide for positive values less than 256">; -def FeatureSlowDivide64 : SubtargetFeature<"idivq-to-divl", - "HasSlowDivide64", "true", - "Use 32-bit divide for positive values less than 2^32">; -def FeaturePadShortFunctions : SubtargetFeature<"pad-short-functions", - "PadShortFunctions", "true", - "Pad short functions">; -def FeatureINVPCID : SubtargetFeature<"invpcid", "HasINVPCID", "true", - "Invalidate Process-Context Identifier">; -def FeatureSGX : SubtargetFeature<"sgx", "HasSGX", "true", - "Enable Software Guard Extensions">; -def FeatureCLFLUSHOPT : SubtargetFeature<"clflushopt", "HasCLFLUSHOPT", "true", - "Flush A Cache Line Optimized">; -def FeatureCLWB : SubtargetFeature<"clwb", "HasCLWB", "true", - "Cache Line Write Back">; -def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", - "Write Back No Invalidate">; -def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", - "Support RDPID instructions">; -def FeatureWAITPKG : SubtargetFeature<"waitpkg", "HasWAITPKG", "true", - "Wait and pause enhancements">; -// On some processors, instructions that implicitly take two memory operands are -// slow. In practice, this means that CALL, PUSH, and POP with memory operands -// should be avoided in favor of a MOV + register CALL/PUSH/POP. -def FeatureSlowTwoMemOps : SubtargetFeature<"slow-two-mem-ops", - "SlowTwoMemOps", "true", - "Two memory operand instructions are slow">; -def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true", - "LEA instruction needs inputs at AG stage">; -def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true", - "LEA instruction with certain arguments is slow">; -def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true", - "LEA instruction with 3 ops or certain registers is slow">; -def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true", - "INC and DEC instructions are slower than ADD and SUB">; -def FeatureSoftFloat - : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software floating point features.">; -def FeaturePOPCNTFalseDeps : SubtargetFeature<"false-deps-popcnt", - "HasPOPCNTFalseDeps", "true", - "POPCNT has a false dependency on dest register">; -def FeatureLZCNTFalseDeps : SubtargetFeature<"false-deps-lzcnt-tzcnt", - "HasLZCNTFalseDeps", "true", - "LZCNT/TZCNT have a false dependency on dest register">; -def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true", - "platform configuration instruction">; -// On recent X86 (port bound) processors, its preferable to combine to a single shuffle -// using a variable mask over multiple fixed shuffles. -def FeatureFastVariableShuffle - : SubtargetFeature<"fast-variable-shuffle", - "HasFastVariableShuffle", - "true", "Shuffles with variable masks are fast">; -// On some X86 processors, there is no performance hazard to writing only the -// lower parts of a YMM or ZMM register without clearing the upper part. -def FeatureFastPartialYMMorZMMWrite - : SubtargetFeature<"fast-partial-ymm-or-zmm-write", - "HasFastPartialYMMorZMMWrite", - "true", "Partial writes to YMM/ZMM registers are fast">; -// FeatureFastScalarFSQRT should be enabled if scalar FSQRT has shorter latency -// than the corresponding NR code. FeatureFastVectorFSQRT should be enabled if -// vector FSQRT has higher throughput than the corresponding NR code. -// The idea is that throughput bound code is likely to be vectorized, so for -// vectorized code we should care about the throughput of SQRT operations. -// But if the code is scalar that probably means that the code has some kind of -// dependency and we should care more about reducing the latency. -def FeatureFastScalarFSQRT - : SubtargetFeature<"fast-scalar-fsqrt", "HasFastScalarFSQRT", - "true", "Scalar SQRT is fast (disable Newton-Raphson)">; -def FeatureFastVectorFSQRT - : SubtargetFeature<"fast-vector-fsqrt", "HasFastVectorFSQRT", - "true", "Vector SQRT is fast (disable Newton-Raphson)">; -// If lzcnt has equivalent latency/throughput to most simple integer ops, it can -// be used to replace test/set sequences. -def FeatureFastLZCNT - : SubtargetFeature< - "fast-lzcnt", "HasFastLZCNT", "true", - "LZCNT instructions are as fast as most simple integer ops">; -// If the target can efficiently decode NOPs upto 11-bytes in length. -def FeatureFast11ByteNOP - : SubtargetFeature< - "fast-11bytenop", "HasFast11ByteNOP", "true", - "Target can quickly decode up to 11 byte NOPs">; -// If the target can efficiently decode NOPs upto 15-bytes in length. -def FeatureFast15ByteNOP - : SubtargetFeature< - "fast-15bytenop", "HasFast15ByteNOP", "true", - "Target can quickly decode up to 15 byte NOPs">; -// Sandy Bridge and newer processors can use SHLD with the same source on both -// inputs to implement rotate to avoid the partial flag update of the normal -// rotate instructions. -def FeatureFastSHLDRotate - : SubtargetFeature< - "fast-shld-rotate", "HasFastSHLDRotate", "true", - "SHLD can be used as a faster rotate">; - -// Ivy Bridge and newer processors have enhanced REP MOVSB and STOSB (aka -// "string operations"). See "REP String Enhancement" in the Intel Software -// Development Manual. This feature essentially means that REP MOVSB will copy -// using the largest available size instead of copying bytes one by one, making -// it at least as fast as REPMOVS{W,D,Q}. -def FeatureERMSB - : SubtargetFeature< - "ermsb", "HasERMSB", "true", - "REP MOVS/STOS are fast">; - -// Sandy Bridge and newer processors have many instructions that can be -// fused with conditional branches and pass through the CPU as a single -// operation. -def FeatureMacroFusion - : SubtargetFeature<"macrofusion", "HasMacroFusion", "true", - "Various instructions can be fused with conditional branches">; - -// Gather is available since Haswell (AVX2 set). So technically, we can -// generate Gathers on all AVX2 processors. But the overhead on HSW is high. -// Skylake Client processor has faster Gathers than HSW and performance is -// similar to Skylake Server (AVX-512). -def FeatureHasFastGather - : SubtargetFeature<"fast-gather", "HasFastGather", "true", - "Indicates if gather is reasonably fast.">; - -def FeaturePrefer256Bit - : SubtargetFeature<"prefer-256-bit", "Prefer256Bit", "true", - "Prefer 256-bit AVX instructions">; - -// Enable mitigation of some aspects of speculative execution related -// vulnerabilities by removing speculatable indirect branches. This disables -// jump-table formation, rewrites explicit `indirectbr` instructions into -// `switch` instructions, and uses a special construct called a "retpoline" to -// prevent speculation of the remaining indirect branches (indirect calls and -// tail calls). -def FeatureRetpoline - : SubtargetFeature<"retpoline", "UseRetpoline", "true", - "Remove speculation of indirect branches from the " - "generated code, either by avoiding them entirely or " - "lowering them with a speculation blocking construct.">; - -// Rely on external thunks for the emitted retpoline calls. This allows users -// to provide their own custom thunk definitions in highly specialized -// environments such as a kernel that does boot-time hot patching. -def FeatureRetpolineExternalThunk - : SubtargetFeature< - "retpoline-external-thunk", "UseRetpolineExternalThunk", "true", - "Enable retpoline, but with an externally provided thunk.", - [FeatureRetpoline]>; - -// Direct Move instructions. -def FeatureMOVDIRI : SubtargetFeature<"movdiri", "HasMOVDIRI", "true", - "Support movdiri instruction">; -def FeatureMOVDIR64B : SubtargetFeature<"movdir64b", "HasMOVDIR64B", "true", - "Support movdir64b instruction">; - -//===----------------------------------------------------------------------===// -// Register File Description -//===----------------------------------------------------------------------===// - -include "X86RegisterInfo.td" -include "X86RegisterBanks.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "X86Schedule.td" -include "X86InstrInfo.td" -include "X86SchedPredicates.td" - -def X86InstrInfo : InstrInfo; - -//===----------------------------------------------------------------------===// -// X86 processors supported. -//===----------------------------------------------------------------------===// - -include "X86ScheduleAtom.td" -include "X86SchedSandyBridge.td" -include "X86SchedHaswell.td" -include "X86SchedBroadwell.td" -include "X86ScheduleSLM.td" -include "X86ScheduleZnver1.td" -include "X86ScheduleBtVer2.td" -include "X86SchedSkylakeClient.td" -include "X86SchedSkylakeServer.td" - -def ProcIntelAtom : SubtargetFeature<"atom", "X86ProcFamily", "IntelAtom", - "Intel Atom processors">; -def ProcIntelSLM : SubtargetFeature<"slm", "X86ProcFamily", "IntelSLM", - "Intel Silvermont processors">; -def ProcIntelGLM : SubtargetFeature<"glm", "X86ProcFamily", "IntelGLM", - "Intel Goldmont processors">; -def ProcIntelGLP : SubtargetFeature<"glp", "X86ProcFamily", "IntelGLP", - "Intel Goldmont Plus processors">; -def ProcIntelTRM : SubtargetFeature<"tremont", "X86ProcFamily", "IntelTRM", - "Intel Tremont processors">; -def ProcIntelHSW : SubtargetFeature<"haswell", "X86ProcFamily", - "IntelHaswell", "Intel Haswell processors">; -def ProcIntelBDW : SubtargetFeature<"broadwell", "X86ProcFamily", - "IntelBroadwell", "Intel Broadwell processors">; -def ProcIntelSKL : SubtargetFeature<"skylake", "X86ProcFamily", - "IntelSkylake", "Intel Skylake processors">; -def ProcIntelKNL : SubtargetFeature<"knl", "X86ProcFamily", - "IntelKNL", "Intel Knights Landing processors">; -def ProcIntelSKX : SubtargetFeature<"skx", "X86ProcFamily", - "IntelSKX", "Intel Skylake Server processors">; -def ProcIntelCNL : SubtargetFeature<"cannonlake", "X86ProcFamily", - "IntelCannonlake", "Intel Cannonlake processors">; -def ProcIntelICL : SubtargetFeature<"icelake-client", "X86ProcFamily", - "IntelIcelakeClient", "Intel Icelake processors">; -def ProcIntelICX : SubtargetFeature<"icelake-server", "X86ProcFamily", - "IntelIcelakeServer", "Intel Icelake Server processors">; - -class Proc Features> - : ProcessorModel; - -def : Proc<"generic", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i386", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i486", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i586", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"pentium", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"pentium-mmx", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; - -def : Proc<"i686", [FeatureX87, FeatureSlowUAMem16, FeatureCMOV]>; -def : Proc<"pentiumpro", [FeatureX87, FeatureSlowUAMem16, FeatureCMOV, - FeatureNOPL]>; - -def : Proc<"pentium2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureCMOV, FeatureFXSR, FeatureNOPL]>; - -foreach P = ["pentium3", "pentium3m"] in { - def : Proc; -} - -// Enable the PostRAScheduler for SSE2 and SSE3 class cpus. -// The intent is to enable it for pentium4 which is the current default -// processor in a vanilla 32-bit clang compilation when no specific -// architecture is specified. This generally gives a nice performance -// increase on silvermont, with largely neutral behavior on other -// contemporary large core processors. -// pentium-m, pentium4m, prescott and nocona are included as a preventative -// measure to avoid performance surprises, in case clang's default cpu -// changes slightly. - -def : ProcessorModel<"pentium-m", GenericPostRAModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureSSE2, FeatureFXSR, FeatureNOPL]>; - -foreach P = ["pentium4", "pentium4m"] in { - def : ProcessorModel; -} - -// Intel Quark. -def : Proc<"lakemont", []>; - -// Intel Core Duo. -def : ProcessorModel<"yonah", SandyBridgeModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, - FeatureFXSR, FeatureNOPL]>; - -// NetBurst. -def : ProcessorModel<"prescott", GenericPostRAModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, - FeatureFXSR, FeatureNOPL]>; -def : ProcessorModel<"nocona", GenericPostRAModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSE3, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B -]>; - -// Intel Core 2 Solo/Duo. -def : ProcessorModel<"core2", SandyBridgeModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSSE3, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureLAHFSAHF, - FeatureMacroFusion -]>; -def : ProcessorModel<"penryn", SandyBridgeModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSE41, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureLAHFSAHF, - FeatureMacroFusion -]>; - -// Atom CPUs. -class BonnellProc : ProcessorModel; -def : BonnellProc<"bonnell">; -def : BonnellProc<"atom">; // Pin the generic name to the baseline. - -class SilvermontProc : ProcessorModel; -def : SilvermontProc<"silvermont">; -def : SilvermontProc<"slm">; // Legacy alias. - -class ProcessorFeatures Inherited, - list NewFeatures> { - list Value = !listconcat(Inherited, NewFeatures); -} - -class ProcModel ProcFeatures, - list OtherFeatures> : - ProcessorModel; - -def GLMFeatures : ProcessorFeatures<[], [ - FeatureX87, - FeatureMMX, - FeatureSSE42, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureMOVBE, - FeaturePOPCNT, - FeaturePCLMUL, - FeatureAES, - FeaturePRFCHW, - FeatureSlowTwoMemOps, - FeatureSlowLEA, - FeatureSlowIncDec, - FeatureLAHFSAHF, - FeatureMPX, - FeatureSHA, - FeatureRDRAND, - FeatureRDSEED, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureXSAVEC, - FeatureXSAVES, - FeatureCLFLUSHOPT, - FeatureFSGSBase -]>; - -class GoldmontProc : ProcModel; -def : GoldmontProc<"goldmont">; - -def GLPFeatures : ProcessorFeatures; - -class GoldmontPlusProc : ProcModel; -def : GoldmontPlusProc<"goldmont-plus">; - -class TremontProc : ProcModel; -def : TremontProc<"tremont">; - -// "Arrandale" along with corei3 and corei5 -class NehalemProc : ProcessorModel; -def : NehalemProc<"nehalem">; -def : NehalemProc<"corei7">; - -// Westmere is a similar machine to nehalem with some additional features. -// Westmere is the corei3/i5/i7 path from nehalem to sandybridge -class WestmereProc : ProcessorModel; -def : WestmereProc<"westmere">; - -// SSE is not listed here since llvm treats AVX as a reimplementation of SSE, -// rather than a superset. -def SNBFeatures : ProcessorFeatures<[], [ - FeatureX87, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeaturePOPCNT, - FeatureAES, - FeatureSlowDivide64, - FeaturePCLMUL, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureLAHFSAHF, - FeatureSlow3OpsLEA, - FeatureFastScalarFSQRT, - FeatureFastSHLDRotate, - FeatureSlowIncDec, - FeatureMacroFusion -]>; - -class SandyBridgeProc : ProcModel; -def : SandyBridgeProc<"sandybridge">; -def : SandyBridgeProc<"corei7-avx">; // Legacy alias. - -def IVBFeatures : ProcessorFeatures; - -class IvyBridgeProc : ProcModel; -def : IvyBridgeProc<"ivybridge">; -def : IvyBridgeProc<"core-avx-i">; // Legacy alias. - -def HSWFeatures : ProcessorFeatures; - -class HaswellProc : ProcModel; -def : HaswellProc<"haswell">; -def : HaswellProc<"core-avx2">; // Legacy alias. - -def BDWFeatures : ProcessorFeatures; -class BroadwellProc : ProcModel; -def : BroadwellProc<"broadwell">; - -def SKLFeatures : ProcessorFeatures; - -class SkylakeClientProc : ProcModel; -def : SkylakeClientProc<"skylake">; - -def KNLFeatures : ProcessorFeatures; - -// FIXME: define KNL model -class KnightsLandingProc : ProcModel; -def : KnightsLandingProc<"knl">; - -class KnightsMillProc : ProcModel; -def : KnightsMillProc<"knm">; // TODO Add AVX5124FMAPS/AVX5124VNNIW features - -def SKXFeatures : ProcessorFeatures; - -class SkylakeServerProc : ProcModel; -def : SkylakeServerProc<"skylake-avx512">; -def : SkylakeServerProc<"skx">; // Legacy alias. - -def CNLFeatures : ProcessorFeatures; - -class CannonlakeProc : ProcModel; -def : CannonlakeProc<"cannonlake">; - -def ICLFeatures : ProcessorFeatures; - -class IcelakeClientProc : ProcModel; -def : IcelakeClientProc<"icelake-client">; - -class IcelakeServerProc : ProcModel; -def : IcelakeServerProc<"icelake-server">; - -// AMD CPUs. - -def : Proc<"k6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"k6-2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"k6-3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; - -foreach P = ["athlon", "athlon-tbird"] in { - def : Proc; -} - -foreach P = ["athlon-4", "athlon-xp", "athlon-mp"] in { - def : Proc; -} - -foreach P = ["k8", "opteron", "athlon64", "athlon-fx"] in { - def : Proc; -} - -foreach P = ["k8-sse3", "opteron-sse3", "athlon64-sse3"] in { - def : Proc; -} - -foreach P = ["amdfam10", "barcelona"] in { - def : Proc; -} - -// Bobcat -def : Proc<"btver1", [ - FeatureX87, - FeatureMMX, - FeatureSSSE3, - FeatureSSE4A, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeaturePRFCHW, - FeatureLZCNT, - FeaturePOPCNT, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast15ByteNOP -]>; - -// Jaguar -def : ProcessorModel<"btver2", BtVer2Model, [ - FeatureX87, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureCMPXCHG16B, - FeaturePRFCHW, - FeatureAES, - FeaturePCLMUL, - FeatureBMI, - FeatureF16C, - FeatureMOVBE, - FeatureLZCNT, - FeatureFastLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast15ByteNOP, - FeatureFastPartialYMMorZMMWrite -]>; - -// Bulldozer -def : Proc<"bdver1", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureLWP, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; -// Piledriver -def : Proc<"bdver2", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; - -// Steamroller -def : Proc<"bdver3", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureFSGSBase, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; - -// Excavator -def : Proc<"bdver4", [ - FeatureX87, - FeatureMMX, - FeatureAVX2, - FeatureFXSR, - FeatureNOPL, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureBMI2, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureFSGSBase, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMWAITX, - FeatureMacroFusion -]>; - -// Znver1 -def: ProcessorModel<"znver1", Znver1Model, [ - FeatureADX, - FeatureAES, - FeatureAVX2, - FeatureBMI, - FeatureBMI2, - FeatureCLFLUSHOPT, - FeatureCLZERO, - FeatureCMPXCHG16B, - FeatureF16C, - FeatureFMA, - FeatureFSGSBase, - FeatureFXSR, - FeatureNOPL, - FeatureFastLZCNT, - FeatureLAHFSAHF, - FeatureLZCNT, - FeatureFast15ByteNOP, - FeatureMacroFusion, - FeatureMMX, - FeatureMOVBE, - FeatureMWAITX, - FeaturePCLMUL, - FeaturePOPCNT, - FeaturePRFCHW, - FeatureRDRAND, - FeatureRDSEED, - FeatureSHA, - FeatureSSE4A, - FeatureSlowSHLD, - FeatureX87, - FeatureXSAVE, - FeatureXSAVEC, - FeatureXSAVEOPT, - FeatureXSAVES]>; - -def : Proc<"geode", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA]>; - -def : Proc<"winchip-c6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"winchip2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3-2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureSSE1, FeatureFXSR]>; - -// We also provide a generic 64-bit specific x86 processor model which tries to -// be good for modern chips without enabling instruction set encodings past the -// basic SSE2 and 64-bit ones. It disables slow things from any mainstream and -// modern 64-bit x86 chip, and enables features that are generally beneficial. -// -// We currently use the Sandy Bridge model as the default scheduling model as -// we use it across Nehalem, Westmere, Sandy Bridge, and Ivy Bridge which -// covers a huge swath of x86 processors. If there are specific scheduling -// knobs which need to be tuned differently for AMD chips, we might consider -// forming a common base for them. -def : ProcessorModel<"x86-64", SandyBridgeModel, [ - FeatureX87, - FeatureMMX, - FeatureSSE2, - FeatureFXSR, - FeatureNOPL, - Feature64Bit, - FeatureSlow3OpsLEA, - FeatureSlowIncDec, - FeatureMacroFusion -]>; - -//===----------------------------------------------------------------------===// -// Calling Conventions -//===----------------------------------------------------------------------===// - -include "X86CallingConv.td" - - -//===----------------------------------------------------------------------===// -// Assembly Parser -//===----------------------------------------------------------------------===// - -def ATTAsmParserVariant : AsmParserVariant { - int Variant = 0; - - // Variant name. - string Name = "att"; - - // Discard comments in assembly strings. - string CommentDelimiter = "#"; - - // Recognize hard coded registers. - string RegisterPrefix = "%"; -} - -def IntelAsmParserVariant : AsmParserVariant { - int Variant = 1; - - // Variant name. - string Name = "intel"; - - // Discard comments in assembly strings. - string CommentDelimiter = ";"; - - // Recognize hard coded registers. - string RegisterPrefix = ""; -} - -//===----------------------------------------------------------------------===// -// Assembly Printers -//===----------------------------------------------------------------------===// - -// The X86 target supports two different syntaxes for emitting machine code. -// This is controlled by the -x86-asm-syntax={att|intel} -def ATTAsmWriter : AsmWriter { - string AsmWriterClassName = "ATTInstPrinter"; - int Variant = 0; -} -def IntelAsmWriter : AsmWriter { - string AsmWriterClassName = "IntelInstPrinter"; - int Variant = 1; -} - -def X86 : Target { - // Information about the instructions... - let InstructionSet = X86InstrInfo; - let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant]; - let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; - let AllowRegisterRenaming = 1; -} - -//===----------------------------------------------------------------------===// -// Pfm Counters -//===----------------------------------------------------------------------===// - -include "X86PfmCounters.td" diff --git a/suite/synctools/tablegen/X86/X86CallingConv.td b/suite/synctools/tablegen/X86/X86CallingConv.td deleted file mode 100644 index fcc9a296de..0000000000 --- a/suite/synctools/tablegen/X86/X86CallingConv.td +++ /dev/null @@ -1,1150 +0,0 @@ -//===-- X86CallingConv.td - Calling Conventions X86 32/64 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This describes the calling conventions for the X86-32 and X86-64 -// architectures. -// -//===----------------------------------------------------------------------===// - -/// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget - : CCIf" - "(State.getMachineFunction().getSubtarget()).", F), - A>; - -/// CCIfNotSubtarget - Match if the current subtarget doesn't has a feature F. -class CCIfNotSubtarget - : CCIf" - "(State.getMachineFunction().getSubtarget()).", F), - A>; - -// Register classes for RegCall -class RC_X86_RegCall { - list GPR_8 = []; - list GPR_16 = []; - list GPR_32 = []; - list GPR_64 = []; - list FP_CALL = [FP0]; - list FP_RET = [FP0, FP1]; - list XMM = []; - list YMM = []; - list ZMM = []; -} - -// RegCall register classes for 32 bits -def RC_X86_32_RegCall : RC_X86_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL]; - let GPR_16 = [AX, CX, DX, DI, SI]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI]; - let GPR_64 = [RAX]; ///< Not actually used, but AssignToReg can't handle [] - ///< \todo Fix AssignToReg to enable empty lists - let XMM = [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]; - let YMM = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7]; - let ZMM = [ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7]; -} - -class RC_X86_64_RegCall : RC_X86_RegCall { - let XMM = [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]; - let YMM = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, - YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15]; - let ZMM = [ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7, - ZMM8, ZMM9, ZMM10, ZMM11, ZMM12, ZMM13, ZMM14, ZMM15]; -} - -def RC_X86_64_RegCall_Win : RC_X86_64_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL, R8B, R9B, R10B, R11B, R12B, R14B, R15B]; - let GPR_16 = [AX, CX, DX, DI, SI, R8W, R9W, R10W, R11W, R12W, R14W, R15W]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI, R8D, R9D, R10D, R11D, R12D, R14D, R15D]; - let GPR_64 = [RAX, RCX, RDX, RDI, RSI, R8, R9, R10, R11, R12, R14, R15]; -} - -def RC_X86_64_RegCall_SysV : RC_X86_64_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL, R8B, R9B, R12B, R13B, R14B, R15B]; - let GPR_16 = [AX, CX, DX, DI, SI, R8W, R9W, R12W, R13W, R14W, R15W]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI, R8D, R9D, R12D, R13D, R14D, R15D]; - let GPR_64 = [RAX, RCX, RDX, RDI, RSI, R8, R9, R12, R13, R14, R15]; -} - -// X86-64 Intel regcall calling convention. -multiclass X86_RegCall_base { -def CC_#NAME : CallingConv<[ - // Handles byval parameters. - CCIfSubtarget<"is64Bit()", CCIfByVal>>, - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // Promote v8i1/v16i1/v32i1 arguments to i32. - CCIfType<[v8i1, v16i1, v32i1], CCPromoteToType>, - - // bool, char, int, enum, long, pointer --> GPR - CCIfType<[i32], CCAssignToReg>, - - // long long, __int64 --> GPR - CCIfType<[i64], CCAssignToReg>, - - // __mmask64 (v64i1) --> GPR64 (for x64) or 2 x GPR32 (for IA32) - CCIfType<[v64i1], CCPromoteToType>, - CCIfSubtarget<"is64Bit()", CCIfType<[i64], - CCAssignToReg>>, - CCIfSubtarget<"is32Bit()", CCIfType<[i64], - CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>, - - // float, double, float128 --> XMM - // In the case of SSE disabled --> save to stack - CCIfType<[f32, f64, f128], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // long double --> FP - CCIfType<[f80], CCAssignToReg>, - - // __m128, __m128i, __m128d --> XMM - // In the case of SSE disabled --> save to stack - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m256, __m256i, __m256d --> YMM - // In the case of SSE disabled --> save to stack - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", CCAssignToReg>>, - - // __m512, __m512i, __m512d --> ZMM - // In the case of SSE disabled --> save to stack - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()",CCAssignToReg>>, - - // If no register was found -> assign to stack - - // In 64 bit, assign 64/32 bit values to 8 byte stack - CCIfSubtarget<"is64Bit()", CCIfType<[i32, i64, f32, f64], - CCAssignToStack<8, 8>>>, - - // In 32 bit, assign 64/32 bit values to 8/4 byte stack - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - CCIfType<[i64, f64], CCAssignToStack<8, 4>>, - - // MMX type gets 8 byte slot in stack , while alignment depends on target - CCIfSubtarget<"is64Bit()", CCIfType<[x86mmx], CCAssignToStack<8, 8>>>, - CCIfType<[x86mmx], CCAssignToStack<8, 4>>, - - // float 128 get stack slots whose size and alignment depends - // on the subtarget. - CCIfType<[f80, f128], CCAssignToStack<0, 0>>, - - // Vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToStack<16, 16>>, - - // 256-bit vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v16i32, v8i64, v16f32, v8f64], CCAssignToStack<64, 64>> -]>; - -def RetCC_#NAME : CallingConv<[ - // Promote i1, v1i1, v8i1 arguments to i8. - CCIfType<[i1, v1i1, v8i1], CCPromoteToType>, - - // Promote v16i1 arguments to i16. - CCIfType<[v16i1], CCPromoteToType>, - - // Promote v32i1 arguments to i32. - CCIfType<[v32i1], CCPromoteToType>, - - // bool, char, int, enum, long, pointer --> GPR - CCIfType<[i8], CCAssignToReg>, - CCIfType<[i16], CCAssignToReg>, - CCIfType<[i32], CCAssignToReg>, - - // long long, __int64 --> GPR - CCIfType<[i64], CCAssignToReg>, - - // __mmask64 (v64i1) --> GPR64 (for x64) or 2 x GPR32 (for IA32) - CCIfType<[v64i1], CCPromoteToType>, - CCIfSubtarget<"is64Bit()", CCIfType<[i64], - CCAssignToReg>>, - CCIfSubtarget<"is32Bit()", CCIfType<[i64], - CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>, - - // long double --> FP - CCIfType<[f80], CCAssignToReg>, - - // float, double, float128 --> XMM - CCIfType<[f32, f64, f128], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m128, __m128i, __m128d --> XMM - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m256, __m256i, __m256d --> YMM - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", CCAssignToReg>>, - - // __m512, __m512i, __m512d --> ZMM - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()", CCAssignToReg>> -]>; -} - -//===----------------------------------------------------------------------===// -// Return Value Calling Conventions -//===----------------------------------------------------------------------===// - -// Return-value conventions common to all X86 CC's. -def RetCC_X86Common : CallingConv<[ - // Scalar values are returned in AX first, then DX. For i8, the ABI - // requires the values to be in AL and AH, however this code uses AL and DL - // instead. This is because using AH for the second register conflicts with - // the way LLVM does multiple return values -- a return of {i16,i8} would end - // up in AX and AH, which overlap. Front-ends wishing to conform to the ABI - // for functions that return two i8 values are currently expected to pack the - // values into an i16 (which uses AX, and thus AL:AH). - // - // For code that doesn't care about the ABI, we allow returning more than two - // integer values in registers. - CCIfType<[v1i1], CCPromoteToType>, - CCIfType<[i1], CCPromoteToType>, - CCIfType<[i8] , CCAssignToReg<[AL, DL, CL]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>, - CCIfType<[i64], CCAssignToReg<[RAX, RDX, RCX]>>, - - // Boolean vectors of AVX-512 are returned in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // Vector types are returned in XMM0 and XMM1, when they fit. XMM2 and XMM3 - // can only be used by ABI non-compliant code. If the target doesn't have XMM - // registers, it won't have vector types. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // 256-bit vectors are returned in YMM0 and XMM1, when they fit. YMM2 and YMM3 - // can only be used by ABI non-compliant code. This vector type is only - // supported while using the AVX target feature. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>, - - // 512-bit vectors are returned in ZMM0 and ZMM1, when they fit. ZMM2 and ZMM3 - // can only be used by ABI non-compliant code. This vector type is only - // supported while using the AVX-512 target feature. - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCAssignToReg<[ZMM0,ZMM1,ZMM2,ZMM3]>>, - - // MMX vector types are always returned in MM0. If the target doesn't have - // MM0, it doesn't support these vector types. - CCIfType<[x86mmx], CCAssignToReg<[MM0]>>, - - // Long double types are always returned in FP0 (even with SSE), - // except on Win64. - CCIfNotSubtarget<"isTargetWin64()", CCIfType<[f80], CCAssignToReg<[FP0, FP1]>>> -]>; - -// X86-32 C return-value convention. -def RetCC_X86_32_C : CallingConv<[ - // The X86-32 calling convention returns FP values in FP0, unless marked - // with "inreg" (used here to distinguish one kind of reg from another, - // weirdly; this is really the sse-regparm calling convention) in which - // case they use XMM0, otherwise it is the same as the common X86 calling - // conv. - CCIfInReg>>>, - CCIfType<[f32,f64], CCAssignToReg<[FP0, FP1]>>, - CCDelegateTo -]>; - -// X86-32 FastCC return-value convention. -def RetCC_X86_32_Fast : CallingConv<[ - // The X86-32 fastcc returns 1, 2, or 3 FP values in XMM0-2 if the target has - // SSE2. - // This can happen when a float, 2 x float, or 3 x float vector is split by - // target lowering, and is returned in 1-3 sse regs. - CCIfType<[f32], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, - CCIfType<[f64], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, - - // For integers, ECX can be used as an extra return register - CCIfType<[i8], CCAssignToReg<[AL, DL, CL]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>, - - // Otherwise, it is the same as the common X86 calling convention. - CCDelegateTo -]>; - -// Intel_OCL_BI return-value convention. -def RetCC_Intel_OCL_BI : CallingConv<[ - // Vector types are returned in XMM0,XMM1,XMMM2 and XMM3. - CCIfType<[f32, f64, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // 256-bit FP vectors - // No more than 4 registers - CCIfType<[v8f32, v4f64, v8i32, v4i64], - CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>, - - // 512-bit FP vectors - CCIfType<[v16f32, v8f64, v16i32, v8i64], - CCAssignToReg<[ZMM0,ZMM1,ZMM2,ZMM3]>>, - - // i32, i64 in the standard way - CCDelegateTo -]>; - -// X86-32 HiPE return-value convention. -def RetCC_X86_32_HiPE : CallingConv<[ - // Promote all types to i32 - CCIfType<[i8, i16], CCPromoteToType>, - - // Return: HP, P, VAL1, VAL2 - CCIfType<[i32], CCAssignToReg<[ESI, EBP, EAX, EDX]>> -]>; - -// X86-32 Vectorcall return-value convention. -def RetCC_X86_32_VectorCall : CallingConv<[ - // Floating Point types are returned in XMM0,XMM1,XMMM2 and XMM3. - CCIfType<[f32, f64, f128], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // Return integers in the standard way. - CCDelegateTo -]>; - -// X86-64 C return-value convention. -def RetCC_X86_64_C : CallingConv<[ - // The X86-64 calling convention always returns FP values in XMM0. - CCIfType<[f32], CCAssignToReg<[XMM0, XMM1]>>, - CCIfType<[f64], CCAssignToReg<[XMM0, XMM1]>>, - CCIfType<[f128], CCAssignToReg<[XMM0, XMM1]>>, - - // MMX vector types are always returned in XMM0. - CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1]>>, - - CCIfSwiftError>>, - - CCDelegateTo -]>; - -// X86-Win64 C return-value convention. -def RetCC_X86_Win64_C : CallingConv<[ - // The X86-Win64 calling convention always returns __m64 values in RAX. - CCIfType<[x86mmx], CCBitConvertToType>, - - // Otherwise, everything is the same as 'normal' X86-64 C CC. - CCDelegateTo -]>; - -// X86-64 vectorcall return-value convention. -def RetCC_X86_64_Vectorcall : CallingConv<[ - // Vectorcall calling convention always returns FP values in XMMs. - CCIfType<[f32, f64, f128], - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // Otherwise, everything is the same as Windows X86-64 C CC. - CCDelegateTo -]>; - -// X86-64 HiPE return-value convention. -def RetCC_X86_64_HiPE : CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: HP, P, VAL1, VAL2 - CCIfType<[i64], CCAssignToReg<[R15, RBP, RAX, RDX]>> -]>; - -// X86-64 WebKit_JS return-value convention. -def RetCC_X86_64_WebKit_JS : CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: RAX - CCIfType<[i64], CCAssignToReg<[RAX]>> -]>; - -def RetCC_X86_64_Swift : CallingConv<[ - - CCIfSwiftError>>, - - // For integers, ECX, R8D can be used as extra return registers. - CCIfType<[v1i1], CCPromoteToType>, - CCIfType<[i1], CCPromoteToType>, - CCIfType<[i8] , CCAssignToReg<[AL, DL, CL, R8B]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX, R8W]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX, R8D]>>, - CCIfType<[i64], CCAssignToReg<[RAX, RDX, RCX, R8]>>, - - // XMM0, XMM1, XMM2 and XMM3 can be used to return FP values. - CCIfType<[f32], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[f64], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[f128], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // MMX vector types are returned in XMM0, XMM1, XMM2 and XMM3. - CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCDelegateTo -]>; - -// X86-64 AnyReg return-value convention. No explicit register is specified for -// the return-value. The register allocator is allowed and expected to choose -// any free register. -// -// This calling convention is currently only supported by the stackmap and -// patchpoint intrinsics. All other uses will result in an assert on Debug -// builds. On Release builds we fallback to the X86 C calling convention. -def RetCC_X86_64_AnyReg : CallingConv<[ - CCCustom<"CC_X86_AnyReg_Error"> -]>; - -// X86-64 HHVM return-value convention. -def RetCC_X86_64_HHVM: CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: could return in any GP register save RSP and R12. - CCIfType<[i64], CCAssignToReg<[RBX, RBP, RDI, RSI, RDX, RCX, R8, R9, - RAX, R10, R11, R13, R14, R15]>> -]>; - - -defm X86_32_RegCall : - X86_RegCall_base; -defm X86_Win64_RegCall : - X86_RegCall_base; -defm X86_SysV64_RegCall : - X86_RegCall_base; - -// This is the root return-value convention for the X86-32 backend. -def RetCC_X86_32 : CallingConv<[ - // If FastCC, use RetCC_X86_32_Fast. - CCIfCC<"CallingConv::Fast", CCDelegateTo>, - // If HiPE, use RetCC_X86_32_HiPE. - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Otherwise, use RetCC_X86_32_C. - CCDelegateTo -]>; - -// This is the root return-value convention for the X86-64 backend. -def RetCC_X86_64 : CallingConv<[ - // HiPE uses RetCC_X86_64_HiPE - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - - // Handle JavaScript calls. - CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, - CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, - - // Handle Swift calls. - CCIfCC<"CallingConv::Swift", CCDelegateTo>, - - // Handle explicit CC selection - CCIfCC<"CallingConv::Win64", CCDelegateTo>, - CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, - - // Handle Vectorcall CC - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - - // Handle HHVM calls. - CCIfCC<"CallingConv::HHVM", CCDelegateTo>, - - CCIfCC<"CallingConv::X86_RegCall", - CCIfSubtarget<"isTargetWin64()", - CCDelegateTo>>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Mingw64 and native Win64 use Win64 CC - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - - // Otherwise, drop to normal X86-64 CC - CCDelegateTo -]>; - -// This is the return-value convention used for the entire X86 backend. -def RetCC_X86 : CallingConv<[ - - // Check if this is the Intel OpenCL built-ins calling convention - CCIfCC<"CallingConv::Intel_OCL_BI", CCDelegateTo>, - - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -//===----------------------------------------------------------------------===// -// X86-64 Argument Calling Conventions -//===----------------------------------------------------------------------===// - -def CC_X86_64_C : CallingConv<[ - // Handles byval parameters. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in R10. - CCIfNest>>, - CCIfNest>, - - // Pass SwiftSelf in a callee saved register. - CCIfSwiftSelf>>, - - // A SwiftError is passed in R12. - CCIfSwiftError>>, - - // For Swift Calling Convention, pass sret in %rax. - CCIfCC<"CallingConv::Swift", - CCIfSRet>>>, - - // The first 6 integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, - CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, - - // The first 8 MMX vector arguments are passed in XMM registers on Darwin. - CCIfType<[x86mmx], - CCIfSubtarget<"isTargetDarwin()", - CCIfSubtarget<"hasSSE2()", - CCPromoteToType>>>, - - // Boolean vectors of AVX-512 are passed in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // The first 8 FP/Vector arguments are passed in XMM registers. - CCIfType<[f32, f64, f128, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>>>, - - // The first 8 256-bit vector arguments are passed in YMM registers, unless - // this is a vararg function. - // FIXME: This isn't precisely correct; the x86-64 ABI document says that - // fixed arguments to vararg functions are supposed to be passed in - // registers. Actually modeling that would be a lot of work, though. - CCIfNotVarArg>>>, - - // The first 8 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, - - // Long doubles get stack slots whose size and alignment depends on the - // subtarget. - CCIfType<[f80, f128], CCAssignToStack<0, 0>>, - - // Vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, - - // 256-bit vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v16i32, v8i64, v16f32, v8f64], - CCAssignToStack<64, 64>> -]>; - -// Calling convention for X86-64 HHVM. -def CC_X86_64_HHVM : CallingConv<[ - // Use all/any GP registers for args, except RSP. - CCIfType<[i64], CCAssignToReg<[RBX, R12, RBP, R15, - RDI, RSI, RDX, RCX, R8, R9, - RAX, R10, R11, R13, R14]>> -]>; - -// Calling convention for helper functions in HHVM. -def CC_X86_64_HHVM_C : CallingConv<[ - // Pass the first argument in RBP. - CCIfType<[i64], CCAssignToReg<[RBP]>>, - - // Otherwise it's the same as the regular C calling convention. - CCDelegateTo -]>; - -// Calling convention used on Win64 -def CC_X86_Win64_C : CallingConv<[ - // FIXME: Handle byval stuff. - // FIXME: Handle varargs. - - // Promote i1/v1i1 arguments to i8. - CCIfType<[i1, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in R10. - CCIfNest>, - - // A SwiftError is passed in R12. - CCIfSwiftError>>, - - // 128 bit vectors are passed by pointer - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCPassIndirect>, - - - // 256 bit vectors are passed by pointer - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], CCPassIndirect>, - - // 512 bit vectors are passed by pointer - CCIfType<[v16i32, v16f32, v8f64, v8i64], CCPassIndirect>, - - // Long doubles are passed by pointer - CCIfType<[f80], CCPassIndirect>, - - // The first 4 MMX vector arguments are passed in GPRs. - CCIfType<[x86mmx], CCBitConvertToType>, - - // The first 4 integer arguments are passed in integer registers. - CCIfType<[i8 ], CCAssignToRegWithShadow<[CL , DL , R8B , R9B ], - [XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[i16], CCAssignToRegWithShadow<[CX , DX , R8W , R9W ], - [XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], - [XMM0, XMM1, XMM2, XMM3]>>, - - // Do not pass the sret argument in RCX, the Win64 thiscall calling - // convention requires "this" to be passed in RCX. - CCIfCC<"CallingConv::X86_ThisCall", - CCIfSRet>>>, - - CCIfType<[i64], CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], - [XMM0, XMM1, XMM2, XMM3]>>, - - // The first 4 FP/Vector arguments are passed in XMM registers. - CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToRegWithShadow<[XMM0, XMM1, XMM2, XMM3], - [RCX , RDX , R8 , R9 ]>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i8, i16, i32, i64, f32, f64], CCAssignToStack<8, 8>> -]>; - -def CC_X86_Win64_VectorCall : CallingConv<[ - CCCustom<"CC_X86_64_VectorCall">, - - // Delegate to fastcall to handle integer types. - CCDelegateTo -]>; - - -def CC_X86_64_GHC : CallingConv<[ - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, SpLim - CCIfType<[i64], - CCAssignToReg<[R13, RBP, R12, RBX, R14, RSI, RDI, R8, R9, R15]>>, - - // Pass in STG registers: F1, F2, F3, F4, D1, D2 - CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", - CCAssignToReg<[XMM1, XMM2, XMM3, XMM4, XMM5, XMM6]>>>, - // AVX - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", - CCAssignToReg<[YMM1, YMM2, YMM3, YMM4, YMM5, YMM6]>>>, - // AVX-512 - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()", - CCAssignToReg<[ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6]>>> -]>; - -def CC_X86_64_HiPE : CallingConv<[ - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Pass in VM's registers: HP, P, ARG0, ARG1, ARG2, ARG3 - CCIfType<[i64], CCAssignToReg<[R15, RBP, RSI, RDX, RCX, R8]>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>> -]>; - -def CC_X86_64_WebKit_JS : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Only the first integer argument is passed in register. - CCIfType<[i32], CCAssignToReg<[EAX]>>, - CCIfType<[i64], CCAssignToReg<[RAX]>>, - - // The remaining integer arguments are passed on the stack. 32bit integer and - // floating-point arguments are aligned to 4 byte and stored in 4 byte slots. - // 64bit integer and floating-point arguments are aligned to 8 byte and stored - // in 8 byte stack slots. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - CCIfType<[i64, f64], CCAssignToStack<8, 8>> -]>; - -// No explicit register is specified for the AnyReg calling convention. The -// register allocator may assign the arguments to any free register. -// -// This calling convention is currently only supported by the stackmap and -// patchpoint intrinsics. All other uses will result in an assert on Debug -// builds. On Release builds we fallback to the X86 C calling convention. -def CC_X86_64_AnyReg : CallingConv<[ - CCCustom<"CC_X86_AnyReg_Error"> -]>; - -//===----------------------------------------------------------------------===// -// X86 C Calling Convention -//===----------------------------------------------------------------------===// - -/// CC_X86_32_Vector_Common - In all X86-32 calling conventions, extra vector -/// values are spilled on the stack. -def CC_X86_32_Vector_Common : CallingConv<[ - // Other SSE vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, - - // 256-bit AVX vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit AVX 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCAssignToStack<64, 64>> -]>; - -// CC_X86_32_Vector_Standard - The first 3 vector arguments are passed in -// vector registers -def CC_X86_32_Vector_Standard : CallingConv<[ - // SSE vector arguments are passed in XMM registers. - CCIfNotVarArg>>, - - // AVX 256-bit vector arguments are passed in YMM registers. - CCIfNotVarArg>>>, - - // AVX 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>, - - CCDelegateTo -]>; - -// CC_X86_32_Vector_Darwin - The first 4 vector arguments are passed in -// vector registers. -def CC_X86_32_Vector_Darwin : CallingConv<[ - // SSE vector arguments are passed in XMM registers. - CCIfNotVarArg>>, - - // AVX 256-bit vector arguments are passed in YMM registers. - CCIfNotVarArg>>>, - - // AVX 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>, - - CCDelegateTo -]>; - -/// CC_X86_32_Common - In all X86-32 calling conventions, extra integers and FP -/// values are spilled on the stack. -def CC_X86_32_Common : CallingConv<[ - // Handles byval parameters. - CCIfByVal>, - - // The first 3 float or double arguments, if marked 'inreg' and if the call - // is not a vararg call and if SSE2 is available, are passed in SSE registers. - CCIfNotVarArg>>>>, - - // The first 3 __m64 vector arguments are passed in mmx registers if the - // call is not a vararg call. - CCIfNotVarArg>>, - - // Integer/Float values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - - // Doubles get 8-byte slots that are 4-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 4>>, - - // Long doubles get slots whose size depends on the subtarget. - CCIfType<[f80], CCAssignToStack<0, 4>>, - - // Boolean vectors of AVX-512 are passed in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // __m64 vectors get 8-byte stack slots that are 4-byte aligned. They are - // passed in the parameter area. - CCIfType<[x86mmx], CCAssignToStack<8, 4>>, - - // Darwin passes vectors in a form that differs from the i386 psABI - CCIfSubtarget<"isTargetDarwin()", CCDelegateTo>, - - // Otherwise, drop to 'normal' X86-32 CC - CCDelegateTo -]>; - -def CC_X86_32_C : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in ECX. - CCIfNest>, - - // The first 3 integer arguments, if marked 'inreg' and if the call is not - // a vararg call, are passed in integer registers. - CCIfNotVarArg>>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_MCU : CallingConv<[ - // Handles byval parameters. Note that, like FastCC, we can't rely on - // the delegation to CC_X86_32_Common because that happens after code that - // puts arguments in registers. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // If the call is not a vararg call, some arguments may be passed - // in integer registers. - CCIfNotVarArg>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_FastCall : CallingConv<[ - // Promote i1 to i8. - CCIfType<[i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in EAX. - CCIfNest>, - - // The first 2 integer arguments are passed in ECX/EDX - CCIfInReg>>, - CCIfInReg>>, - CCIfInReg>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_Win32_VectorCall : CallingConv<[ - // Pass floating point in XMMs - CCCustom<"CC_X86_32_VectorCall">, - - // Delegate to fastcall to handle integer types. - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Common : CallingConv<[ - // The first integer argument is passed in ECX - CCIfType<[i32], CCAssignToReg<[ECX]>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Mingw : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Win : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // Pass sret arguments indirectly through stack. - CCIfSRet>, - - CCDelegateTo -]>; - -def CC_X86_32_ThisCall : CallingConv<[ - CCIfSubtarget<"isTargetCygMing()", CCDelegateTo>, - CCDelegateTo -]>; - -def CC_X86_32_FastCC : CallingConv<[ - // Handles byval parameters. Note that we can't rely on the delegation - // to CC_X86_32_Common for this because that happens after code that - // puts arguments in registers. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in EAX. - CCIfNest>, - - // The first 2 integer arguments are passed in ECX/EDX - CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>, - - // The first 3 float or double arguments, if the call is not a vararg - // call and if SSE2 is available, are passed in SSE registers. - CCIfNotVarArg>>>, - - // Doubles get 8-byte slots that are 8-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 8>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_GHC : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1 - CCIfType<[i32], CCAssignToReg<[EBX, EBP, EDI, ESI]>> -]>; - -def CC_X86_32_HiPE : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Pass in VM's registers: HP, P, ARG0, ARG1, ARG2 - CCIfType<[i32], CCAssignToReg<[ESI, EBP, EAX, EDX, ECX]>>, - - // Integer/Float values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>> -]>; - -// X86-64 Intel OpenCL built-ins calling convention. -def CC_Intel_OCL_BI : CallingConv<[ - - CCIfType<[i32], CCIfSubtarget<"isTargetWin64()", CCAssignToReg<[ECX, EDX, R8D, R9D]>>>, - CCIfType<[i64], CCIfSubtarget<"isTargetWin64()", CCAssignToReg<[RCX, RDX, R8, R9 ]>>>, - - CCIfType<[i32], CCIfSubtarget<"is64Bit()", CCAssignToReg<[EDI, ESI, EDX, ECX]>>>, - CCIfType<[i64], CCIfSubtarget<"is64Bit()", CCAssignToReg<[RDI, RSI, RDX, RCX]>>>, - - CCIfType<[i32], CCAssignToStack<4, 4>>, - - // The SSE vector arguments are passed in XMM registers. - CCIfType<[f32, f64, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // The 256-bit vector arguments are passed in YMM registers. - CCIfType<[v8f32, v4f64, v8i32, v4i64], - CCAssignToReg<[YMM0, YMM1, YMM2, YMM3]>>, - - // The 512-bit vector arguments are passed in ZMM registers. - CCIfType<[v16f32, v8f64, v16i32, v8i64], - CCAssignToReg<[ZMM0, ZMM1, ZMM2, ZMM3]>>, - - // Pass masks in mask registers - CCIfType<[v16i1, v8i1], CCAssignToReg<[K1]>>, - - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -def CC_X86_32_Intr : CallingConv<[ - CCAssignToStack<4, 4> -]>; - -def CC_X86_64_Intr : CallingConv<[ - CCAssignToStack<8, 8> -]>; - -//===----------------------------------------------------------------------===// -// X86 Root Argument Calling Conventions -//===----------------------------------------------------------------------===// - -// This is the root argument convention for the X86-32 backend. -def CC_X86_32 : CallingConv<[ - // X86_INTR calling convention is valid in MCU target and should override the - // MCU calling convention. Thus, this should be checked before isTargetMCU(). - CCIfCC<"CallingConv::X86_INTR", CCDelegateTo>, - CCIfSubtarget<"isTargetMCU()", CCDelegateTo>, - CCIfCC<"CallingConv::X86_FastCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_ThisCall", CCDelegateTo>, - CCIfCC<"CallingConv::Fast", CCDelegateTo>, - CCIfCC<"CallingConv::GHC", CCDelegateTo>, - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Otherwise, drop to normal X86-32 CC - CCDelegateTo -]>; - -// This is the root argument convention for the X86-64 backend. -def CC_X86_64 : CallingConv<[ - CCIfCC<"CallingConv::GHC", CCDelegateTo>, - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, - CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, - CCIfCC<"CallingConv::Win64", CCDelegateTo>, - CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::HHVM", CCDelegateTo>, - CCIfCC<"CallingConv::HHVM_C", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_INTR", CCDelegateTo>, - - // Mingw64 and native Win64 use Win64 CC - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - - // Otherwise, drop to normal X86-64 CC - CCDelegateTo -]>; - -// This is the argument convention used for the entire X86 backend. -def CC_X86 : CallingConv<[ - CCIfCC<"CallingConv::Intel_OCL_BI", CCDelegateTo>, - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -//===----------------------------------------------------------------------===// -// Callee-saved Registers. -//===----------------------------------------------------------------------===// - -def CSR_NoRegs : CalleeSavedRegs<(add)>; - -def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>; -def CSR_64 : CalleeSavedRegs<(add RBX, R12, R13, R14, R15, RBP)>; - -def CSR_64_SwiftError : CalleeSavedRegs<(sub CSR_64, R12)>; - -def CSR_32EHRet : CalleeSavedRegs<(add EAX, EDX, CSR_32)>; -def CSR_64EHRet : CalleeSavedRegs<(add RAX, RDX, CSR_64)>; - -def CSR_Win64_NoSSE : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, R13, R14, R15)>; - -def CSR_Win64 : CalleeSavedRegs<(add CSR_Win64_NoSSE, - (sequence "XMM%u", 6, 15))>; - -def CSR_Win64_SwiftError : CalleeSavedRegs<(sub CSR_Win64, R12)>; - -// The function used by Darwin to obtain the address of a thread-local variable -// uses rdi to pass a single parameter and rax for the return value. All other -// GPRs are preserved. -def CSR_64_TLS_Darwin : CalleeSavedRegs<(add CSR_64, RCX, RDX, RSI, - R8, R9, R10, R11)>; - -// CSRs that are handled by prologue, epilogue. -def CSR_64_CXX_TLS_Darwin_PE : CalleeSavedRegs<(add RBP)>; - -// CSRs that are handled explicitly via copies. -def CSR_64_CXX_TLS_Darwin_ViaCopy : CalleeSavedRegs<(sub CSR_64_TLS_Darwin, RBP)>; - -// All GPRs - except r11 -def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI, - R8, R9, R10, RSP)>; - -// All registers - except r11 -def CSR_64_RT_AllRegs : CalleeSavedRegs<(add CSR_64_RT_MostRegs, - (sequence "XMM%u", 0, 15))>; -def CSR_64_RT_AllRegs_AVX : CalleeSavedRegs<(add CSR_64_RT_MostRegs, - (sequence "YMM%u", 0, 15))>; - -def CSR_64_MostRegs : CalleeSavedRegs<(add RBX, RCX, RDX, RSI, RDI, R8, R9, R10, - R11, R12, R13, R14, R15, RBP, - (sequence "XMM%u", 0, 15))>; - -def CSR_32_AllRegs : CalleeSavedRegs<(add EAX, EBX, ECX, EDX, EBP, ESI, - EDI)>; -def CSR_32_AllRegs_SSE : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "XMM%u", 0, 7))>; -def CSR_32_AllRegs_AVX : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "YMM%u", 0, 7))>; -def CSR_32_AllRegs_AVX512 : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "ZMM%u", 0, 7), - (sequence "K%u", 0, 7))>; - -def CSR_64_AllRegs : CalleeSavedRegs<(add CSR_64_MostRegs, RAX)>; -def CSR_64_AllRegs_NoSSE : CalleeSavedRegs<(add RAX, RBX, RCX, RDX, RSI, RDI, R8, R9, - R10, R11, R12, R13, R14, R15, RBP)>; -def CSR_64_AllRegs_AVX : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX, - (sequence "YMM%u", 0, 15)), - (sequence "XMM%u", 0, 15))>; -def CSR_64_AllRegs_AVX512 : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX, - (sequence "ZMM%u", 0, 31), - (sequence "K%u", 0, 7)), - (sequence "XMM%u", 0, 15))>; - -// Standard C + YMM6-15 -def CSR_Win64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, - R13, R14, R15, - (sequence "YMM%u", 6, 15))>; - -def CSR_Win64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, - R12, R13, R14, R15, - (sequence "ZMM%u", 6, 21), - K4, K5, K6, K7)>; -//Standard C + XMM 8-15 -def CSR_64_Intel_OCL_BI : CalleeSavedRegs<(add CSR_64, - (sequence "XMM%u", 8, 15))>; - -//Standard C + YMM 8-15 -def CSR_64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add CSR_64, - (sequence "YMM%u", 8, 15))>; - -def CSR_64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RDI, RSI, R14, R15, - (sequence "ZMM%u", 16, 31), - K4, K5, K6, K7)>; - -// Only R12 is preserved for PHP calls in HHVM. -def CSR_64_HHVM : CalleeSavedRegs<(add R12)>; - -// Register calling convention preserves few GPR and XMM8-15 -def CSR_32_RegCall_NoSSE : CalleeSavedRegs<(add ESI, EDI, EBX, EBP, ESP)>; -def CSR_32_RegCall : CalleeSavedRegs<(add CSR_32_RegCall_NoSSE, - (sequence "XMM%u", 4, 7))>; -def CSR_Win64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, RSP, - (sequence "R%u", 10, 15))>; -def CSR_Win64_RegCall : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE, - (sequence "XMM%u", 8, 15))>; -def CSR_SysV64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, RSP, - (sequence "R%u", 12, 15))>; -def CSR_SysV64_RegCall : CalleeSavedRegs<(add CSR_SysV64_RegCall_NoSSE, - (sequence "XMM%u", 8, 15))>; - diff --git a/suite/synctools/tablegen/X86/X86Capstone.td b/suite/synctools/tablegen/X86/X86Capstone.td deleted file mode 100644 index ca21b63a01..0000000000 --- a/suite/synctools/tablegen/X86/X86Capstone.td +++ /dev/null @@ -1,7 +0,0 @@ -// Capstone definitions fix for X86 LLVM instructions. - -let Defs = [EFLAGS] in - def INT1 : I<0xf1, RawFrm, (outs), (ins), "int1", []>; - -// def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", [], IIC_FNCLEX>; -def FSETPM : I<0xDB, MRM_E4, (outs), (ins), "fsetpm", []>; diff --git a/suite/synctools/tablegen/X86/X86Instr3DNow.td b/suite/synctools/tablegen/X86/X86Instr3DNow.td deleted file mode 100644 index 46dc6bf766..0000000000 --- a/suite/synctools/tablegen/X86/X86Instr3DNow.td +++ /dev/null @@ -1,111 +0,0 @@ -//===-- X86Instr3DNow.td - The 3DNow! Instruction Set ------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the 3DNow! instruction set, which extends MMX to support -// floating point and also adds a few more random instructions for good measure. -// -//===----------------------------------------------------------------------===// - -class I3DNow o, Format F, dag outs, dag ins, string asm, list pat> - : I, Requires<[Has3DNow]> { -} - -class I3DNow_binop o, Format F, dag ins, string Mnemonic, list pat> - : I3DNow, ThreeDNow { - let Constraints = "$src1 = $dst"; -} - -class I3DNow_conv o, Format F, dag ins, string Mnemonic, list pat> - : I3DNow, ThreeDNow; - -multiclass I3DNow_binop_rm_int opc, string Mn, - X86FoldableSchedWrite sched, bit Commutable = 0, - string Ver = ""> { - let isCommutable = Commutable in - def rr : I3DNow_binop( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, VR64:$src2))]>, - Sched<[sched]>; - def rm : I3DNow_binop( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, - (bitconvert (load_mmx addr:$src2))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass I3DNow_conv_rm_int opc, string Mn, - X86FoldableSchedWrite sched, string Ver = ""> { - def rr : I3DNow_conv( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src))]>, - Sched<[sched]>; - def rm : I3DNow_conv( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) - (bitconvert (load_mmx addr:$src))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -defm PAVGUSB : I3DNow_binop_rm_int<0xBF, "pavgusb", SchedWriteVecALU.MMX, 1>; -defm PF2ID : I3DNow_conv_rm_int<0x1D, "pf2id", WriteCvtPS2I>; -defm PFACC : I3DNow_binop_rm_int<0xAE, "pfacc", WriteFAdd>; -defm PFADD : I3DNow_binop_rm_int<0x9E, "pfadd", WriteFAdd, 1>; -defm PFCMPEQ : I3DNow_binop_rm_int<0xB0, "pfcmpeq", WriteFAdd, 1>; -defm PFCMPGE : I3DNow_binop_rm_int<0x90, "pfcmpge", WriteFAdd>; -defm PFCMPGT : I3DNow_binop_rm_int<0xA0, "pfcmpgt", WriteFAdd>; -defm PFMAX : I3DNow_binop_rm_int<0xA4, "pfmax", WriteFAdd>; -defm PFMIN : I3DNow_binop_rm_int<0x94, "pfmin", WriteFAdd>; -defm PFMUL : I3DNow_binop_rm_int<0xB4, "pfmul", WriteFAdd, 1>; -defm PFRCP : I3DNow_conv_rm_int<0x96, "pfrcp", WriteFAdd>; -defm PFRCPIT1 : I3DNow_binop_rm_int<0xA6, "pfrcpit1", WriteFAdd>; -defm PFRCPIT2 : I3DNow_binop_rm_int<0xB6, "pfrcpit2", WriteFAdd>; -defm PFRSQIT1 : I3DNow_binop_rm_int<0xA7, "pfrsqit1", WriteFAdd>; -defm PFRSQRT : I3DNow_conv_rm_int<0x97, "pfrsqrt", WriteFAdd>; -defm PFSUB : I3DNow_binop_rm_int<0x9A, "pfsub", WriteFAdd, 1>; -defm PFSUBR : I3DNow_binop_rm_int<0xAA, "pfsubr", WriteFAdd, 1>; -defm PI2FD : I3DNow_conv_rm_int<0x0D, "pi2fd", WriteCvtI2PS>; -defm PMULHRW : I3DNow_binop_rm_int<0xB7, "pmulhrw", SchedWriteVecIMul.MMX, 1>; - -let SchedRW = [WriteEMMS] in -def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms", - [(int_x86_mmx_femms)]>, TB; - -// PREFETCHWT1 is supported we want to use it for everything but T0. -def PrefetchWLevel : PatFrag<(ops), (i32 imm), [{ - return N->getSExtValue() == 3 || !Subtarget->hasPREFETCHWT1(); -}]>; - -// Use PREFETCHWT1 for NTA, T2, T1. -def PrefetchWT1Level : ImmLeaf; - -let SchedRW = [WriteLoad] in { -let Predicates = [Has3DNow, NoSSEPrefetch] in -def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr), - "prefetch\t$addr", - [(prefetch addr:$addr, imm, imm, (i32 1))]>, TB; - -def PREFETCHW : I<0x0D, MRM1m, (outs), (ins i8mem:$addr), "prefetchw\t$addr", - [(prefetch addr:$addr, (i32 1), (i32 PrefetchWLevel), (i32 1))]>, - TB, Requires<[HasPrefetchW]>; - -def PREFETCHWT1 : I<0x0D, MRM2m, (outs), (ins i8mem:$addr), "prefetchwt1\t$addr", - [(prefetch addr:$addr, (i32 1), (i32 PrefetchWT1Level), (i32 1))]>, - TB, Requires<[HasPREFETCHWT1]>; -} - -// "3DNowA" instructions -defm PF2IW : I3DNow_conv_rm_int<0x1C, "pf2iw", WriteCvtPS2I, "a">; -defm PI2FW : I3DNow_conv_rm_int<0x0C, "pi2fw", WriteCvtI2PS, "a">; -defm PFNACC : I3DNow_binop_rm_int<0x8A, "pfnacc", WriteFAdd, 0, "a">; -defm PFPNACC : I3DNow_binop_rm_int<0x8E, "pfpnacc", WriteFAdd, 0, "a">; -defm PSWAPD : I3DNow_conv_rm_int<0xBB, "pswapd", SchedWriteShuffle.MMX, "a">; diff --git a/suite/synctools/tablegen/X86/X86InstrAVX512.td b/suite/synctools/tablegen/X86/X86InstrAVX512.td deleted file mode 100644 index 3872b128ba..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrAVX512.td +++ /dev/null @@ -1,11968 +0,0 @@ -//===-- X86InstrAVX512.td - AVX512 Instruction Set ---------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 AVX512 instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -// Group template arguments that can be derived from the vector type (EltNum x -// EltVT). These are things like the register class for the writemask, etc. -// The idea is to pass one of these as the template argument rather than the -// individual arguments. -// The template is also used for scalar types, in this case numelts is 1. -class X86VectorVTInfo { - RegisterClass RC = rc; - ValueType EltVT = eltvt; - int NumElts = numelts; - - // Corresponding mask register class. - RegisterClass KRC = !cast("VK" # NumElts); - - // Corresponding write-mask register class. - RegisterClass KRCWM = !cast("VK" # NumElts # "WM"); - - // The mask VT. - ValueType KVT = !cast("v" # NumElts # "i1"); - - // Suffix used in the instruction mnemonic. - string Suffix = suffix; - - // VTName is a string name for vector VT. For vector types it will be - // v # NumElts # EltVT, so for vector of 8 elements of i32 it will be v8i32 - // It is a little bit complex for scalar types, where NumElts = 1. - // In this case we build v4f32 or v2f64 - string VTName = "v" # !if (!eq (NumElts, 1), - !if (!eq (EltVT.Size, 32), 4, - !if (!eq (EltVT.Size, 64), 2, NumElts)), NumElts) # EltVT; - - // The vector VT. - ValueType VT = !cast(VTName); - - string EltTypeName = !cast(EltVT); - // Size of the element type in bits, e.g. 32 for v16i32. - string EltSizeName = !subst("i", "", !subst("f", "", EltTypeName)); - int EltSize = EltVT.Size; - - // "i" for integer types and "f" for floating-point types - string TypeVariantName = !subst(EltSizeName, "", EltTypeName); - - // Size of RC in bits, e.g. 512 for VR512. - int Size = VT.Size; - - // The corresponding memory operand, e.g. i512mem for VR512. - X86MemOperand MemOp = !cast(TypeVariantName # Size # "mem"); - X86MemOperand ScalarMemOp = !cast(EltVT # "mem"); - // FP scalar memory operand for intrinsics - ssmem/sdmem. - Operand IntScalarMemOp = !if (!eq (EltTypeName, "f32"), !cast("ssmem"), - !if (!eq (EltTypeName, "f64"), !cast("sdmem"), ?)); - - // Load patterns - // Note: For 128/256-bit integer VT we choose loadv2i64/loadv4i64 - // due to load promotion during legalization - PatFrag LdFrag = !cast("load" # - !if (!eq (TypeVariantName, "i"), - !if (!eq (Size, 128), "v2i64", - !if (!eq (Size, 256), "v4i64", - !if (!eq (Size, 512), "v8i64", - VTName))), VTName)); - - PatFrag AlignedLdFrag = !cast("alignedload" # - !if (!eq (TypeVariantName, "i"), - !if (!eq (Size, 128), "v2i64", - !if (!eq (Size, 256), "v4i64", - !if (!eq (Size, 512), "v8i64", - VTName))), VTName)); - - PatFrag ScalarLdFrag = !cast("load" # EltVT); - - ComplexPattern ScalarIntMemCPat = !if (!eq (EltTypeName, "f32"), - !cast("sse_load_f32"), - !if (!eq (EltTypeName, "f64"), - !cast("sse_load_f64"), - ?)); - - // The string to specify embedded broadcast in assembly. - string BroadcastStr = "{1to" # NumElts # "}"; - - // 8-bit compressed displacement tuple/subvector format. This is only - // defined for NumElts <= 8. - CD8VForm CD8TupleForm = !if (!eq (!srl(NumElts, 4), 0), - !cast("CD8VT" # NumElts), ?); - - SubRegIndex SubRegIdx = !if (!eq (Size, 128), sub_xmm, - !if (!eq (Size, 256), sub_ymm, ?)); - - Domain ExeDomain = !if (!eq (EltTypeName, "f32"), SSEPackedSingle, - !if (!eq (EltTypeName, "f64"), SSEPackedDouble, - SSEPackedInt)); - - RegisterClass FRC = !if (!eq (EltTypeName, "f32"), FR32X, FR64X); - - // A vector type of the same width with element type i64. This is used to - // create patterns for logic ops. - ValueType i64VT = !cast("v" # !srl(Size, 6) # "i64"); - - // A vector type of the same width with element type i32. This is used to - // create the canonical constant zero node ImmAllZerosV. - ValueType i32VT = !cast("v" # !srl(Size, 5) # "i32"); - dag ImmAllZerosV = (VT (bitconvert (i32VT immAllZerosV))); - - string ZSuffix = !if (!eq (Size, 128), "Z128", - !if (!eq (Size, 256), "Z256", "Z")); -} - -def v64i8_info : X86VectorVTInfo<64, i8, VR512, "b">; -def v32i16_info : X86VectorVTInfo<32, i16, VR512, "w">; -def v16i32_info : X86VectorVTInfo<16, i32, VR512, "d">; -def v8i64_info : X86VectorVTInfo<8, i64, VR512, "q">; -def v16f32_info : X86VectorVTInfo<16, f32, VR512, "ps">; -def v8f64_info : X86VectorVTInfo<8, f64, VR512, "pd">; - -// "x" in v32i8x_info means RC = VR256X -def v32i8x_info : X86VectorVTInfo<32, i8, VR256X, "b">; -def v16i16x_info : X86VectorVTInfo<16, i16, VR256X, "w">; -def v8i32x_info : X86VectorVTInfo<8, i32, VR256X, "d">; -def v4i64x_info : X86VectorVTInfo<4, i64, VR256X, "q">; -def v8f32x_info : X86VectorVTInfo<8, f32, VR256X, "ps">; -def v4f64x_info : X86VectorVTInfo<4, f64, VR256X, "pd">; - -def v16i8x_info : X86VectorVTInfo<16, i8, VR128X, "b">; -def v8i16x_info : X86VectorVTInfo<8, i16, VR128X, "w">; -def v4i32x_info : X86VectorVTInfo<4, i32, VR128X, "d">; -def v2i64x_info : X86VectorVTInfo<2, i64, VR128X, "q">; -def v4f32x_info : X86VectorVTInfo<4, f32, VR128X, "ps">; -def v2f64x_info : X86VectorVTInfo<2, f64, VR128X, "pd">; - -// We map scalar types to the smallest (128-bit) vector type -// with the appropriate element type. This allows to use the same masking logic. -def i32x_info : X86VectorVTInfo<1, i32, GR32, "si">; -def i64x_info : X86VectorVTInfo<1, i64, GR64, "sq">; -def f32x_info : X86VectorVTInfo<1, f32, VR128X, "ss">; -def f64x_info : X86VectorVTInfo<1, f64, VR128X, "sd">; - -class AVX512VLVectorVTInfo { - X86VectorVTInfo info512 = i512; - X86VectorVTInfo info256 = i256; - X86VectorVTInfo info128 = i128; -} - -def avx512vl_i8_info : AVX512VLVectorVTInfo; -def avx512vl_i16_info : AVX512VLVectorVTInfo; -def avx512vl_i32_info : AVX512VLVectorVTInfo; -def avx512vl_i64_info : AVX512VLVectorVTInfo; -def avx512vl_f32_info : AVX512VLVectorVTInfo; -def avx512vl_f64_info : AVX512VLVectorVTInfo; - -class X86KVectorVTInfo { - RegisterClass KRC = _krc; - RegisterClass KRCWM = _krcwm; - ValueType KVT = _vt; -} - -def v1i1_info : X86KVectorVTInfo; -def v2i1_info : X86KVectorVTInfo; -def v4i1_info : X86KVectorVTInfo; -def v8i1_info : X86KVectorVTInfo; -def v16i1_info : X86KVectorVTInfo; -def v32i1_info : X86KVectorVTInfo; -def v64i1_info : X86KVectorVTInfo; - -// This multiclass generates the masking variants from the non-masking -// variant. It only provides the assembly pieces for the masking variants. -// It assumes custom ISel patterns for masking which can be provided as -// template arguments. -multiclass AVX512_maskable_custom O, Format F, - dag Outs, - dag Ins, dag MaskingIns, dag ZeroMaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern, - list MaskingPattern, - list ZeroMaskingPattern, - string MaskingConstraint = "", - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable> { - let isCommutable = IsCommutable in - def NAME: AVX512; - - // Prefer over VMOV*rrk Pat<> - let isCommutable = IsKCommutable in - def NAME#k: AVX512, - EVEX_K { - // In case of the 3src subclass this is overridden with a let. - string Constraints = MaskingConstraint; - } - - // Zero mask does not add any restrictions to commute operands transformation. - // So, it is Ok to use IsCommutable instead of IsKCommutable. - let isCommutable = IsKZCommutable in // Prefer over VMOV*rrkz Pat<> - def NAME#kz: AVX512, - EVEX_KZ; -} - - -// Common base class of AVX512_maskable and AVX512_maskable_3src. -multiclass AVX512_maskable_common O, Format F, X86VectorVTInfo _, - dag Outs, - dag Ins, dag MaskingIns, dag ZeroMaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskingRHS, - SDNode Select = vselect, - string MaskingConstraint = "", - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable> : - AVX512_maskable_custom; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -// This version uses a separate dag for non-masking and masking. -multiclass AVX512_maskable_split O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskRHS, - bit IsCommutable = 0, bit IsKCommutable = 0, - SDNode Select = vselect> : - AVX512_maskable_custom; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -multiclass AVX512_maskable O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable, - SDNode Select = vselect> : - AVX512_maskable_common; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the scalar instruction. -multiclass AVX512_maskable_scalar O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0> : - AVX512_maskable; - -// Similar to AVX512_maskable but in this case one of the source operands -// ($src1) is already tied to $dst so we just use that for the preserved -// vector elements. NOTE that the NonTiedIns (the ins dag) should exclude -// $src1. -multiclass AVX512_maskable_3src O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, - bit IsKCommutable = 0, - SDNode Select = vselect, - bit MaskOnly = 0> : - AVX512_maskable_common; - -// Similar to AVX512_maskable_3src but in this case the input VT for the tied -// operand differs from the output VT. This requires a bitconvert on -// the preserved vector going into the vselect. -// NOTE: The unmasked pattern is disabled. -multiclass AVX512_maskable_3src_cast O, Format F, X86VectorVTInfo OutVT, - X86VectorVTInfo InVT, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, bit IsCommutable = 0> : - AVX512_maskable_common; - -multiclass AVX512_maskable_3src_scalar O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit MaskOnly = 0> : - AVX512_maskable_3src; - -multiclass AVX512_maskable_in_asm O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern> : - AVX512_maskable_custom; - -multiclass AVX512_maskable_3src_in_asm O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern> : - AVX512_maskable_custom; - -// Instruction with mask that puts result in mask register, -// like "compare" and "vptest" -multiclass AVX512_maskable_custom_cmp O, Format F, - dag Outs, - dag Ins, dag MaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern, - list MaskingPattern, - bit IsCommutable = 0> { - let isCommutable = IsCommutable in - def NAME: AVX512; - - def NAME#k: AVX512, EVEX_K; -} - -multiclass AVX512_maskable_common_cmp O, Format F, X86VectorVTInfo _, - dag Outs, - dag Ins, dag MaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskingRHS, - bit IsCommutable = 0> : - AVX512_maskable_custom_cmp; - -multiclass AVX512_maskable_cmp O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, bit IsCommutable = 0> : - AVX512_maskable_common_cmp; - -multiclass AVX512_maskable_cmp_alt O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm> : - AVX512_maskable_custom_cmp; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -multiclass AVX512_maskable_logic O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskedRHS, - bit IsCommutable = 0, SDNode Select = vselect> : - AVX512_maskable_custom; - - -// Alias instruction that maps zero vector to pxor / xorp* for AVX-512. -// This is expanded by ExpandPostRAPseudos to an xorps / vxorps, and then -// swizzled by ExecutionDomainFix to pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteZero] in { -def AVX512_512_SET0 : I<0, Pseudo, (outs VR512:$dst), (ins), "", - [(set VR512:$dst, (v16i32 immAllZerosV))]>; -def AVX512_512_SETALLONES : I<0, Pseudo, (outs VR512:$dst), (ins), "", - [(set VR512:$dst, (v16i32 immAllOnesV))]>; -} - -// Alias instructions that allow VPTERNLOG to be used with a mask to create -// a mix of all ones and all zeros elements. This is done this way to force -// the same register to be used as input for all three sources. -let isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteVecALU] in { -def AVX512_512_SEXT_MASK_32 : I<0, Pseudo, (outs VR512:$dst), - (ins VK16WM:$mask), "", - [(set VR512:$dst, (vselect (v16i1 VK16WM:$mask), - (v16i32 immAllOnesV), - (v16i32 immAllZerosV)))]>; -def AVX512_512_SEXT_MASK_64 : I<0, Pseudo, (outs VR512:$dst), - (ins VK8WM:$mask), "", - [(set VR512:$dst, (vselect (v8i1 VK8WM:$mask), - (bc_v8i64 (v16i32 immAllOnesV)), - (bc_v8i64 (v16i32 immAllZerosV))))]>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteZero] in { -def AVX512_128_SET0 : I<0, Pseudo, (outs VR128X:$dst), (ins), "", - [(set VR128X:$dst, (v4i32 immAllZerosV))]>; -def AVX512_256_SET0 : I<0, Pseudo, (outs VR256X:$dst), (ins), "", - [(set VR256X:$dst, (v8i32 immAllZerosV))]>; -} - -// Alias instructions that map fld0 to xorps for sse or vxorps for avx. -// This is expanded by ExpandPostRAPseudos. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero], Predicates = [HasAVX512] in { - def AVX512_FsFLD0SS : I<0, Pseudo, (outs FR32X:$dst), (ins), "", - [(set FR32X:$dst, fp32imm0)]>; - def AVX512_FsFLD0SD : I<0, Pseudo, (outs FR64X:$dst), (ins), "", - [(set FR64X:$dst, fpimm0)]>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - VECTOR INSERT -// - -// Supports two different pattern operators for mask and unmasked ops. Allows -// null_frag to be passed for one. -multiclass vinsert_for_size_split { - let hasSideEffects = 0, ExeDomain = To.ExeDomain in { - defm rr : AVX512_maskable_split, - AVX512AIi8Base, EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - defm rm : AVX512_maskable_split, AVX512AIi8Base, EVEX_4V, - EVEX_CD8, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -// Passes the same pattern operator for masked and unmasked ops. -multiclass vinsert_for_size : - vinsert_for_size_split; - -multiclass vinsert_for_size_lowering p> { - let Predicates = p in { - def : Pat<(vinsert_insert:$ins - (To.VT To.RC:$src1), (From.VT From.RC:$src2), (iPTR imm)), - (To.VT (!cast(InstrStr#"rr") - To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins)))>; - - def : Pat<(vinsert_insert:$ins - (To.VT To.RC:$src1), - (From.VT (bitconvert (From.LdFrag addr:$src2))), - (iPTR imm)), - (To.VT (!cast(InstrStr#"rm") - To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins)))>; - } -} - -multiclass vinsert_for_type { - - let Predicates = [HasVLX] in - defm NAME # "32x4Z256" : vinsert_for_size, - X86VectorVTInfo< 8, EltVT32, VR256X>, - vinsert128_insert, sched>, EVEX_V256; - - defm NAME # "32x4Z" : vinsert_for_size, - X86VectorVTInfo<16, EltVT32, VR512>, - vinsert128_insert, sched>, EVEX_V512; - - defm NAME # "64x4Z" : vinsert_for_size, - X86VectorVTInfo< 8, EltVT64, VR512>, - vinsert256_insert, sched>, VEX_W, EVEX_V512; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasVLX, HasDQI] in - defm NAME # "64x2Z256" : vinsert_for_size_split, - X86VectorVTInfo< 4, EltVT64, VR256X>, - null_frag, vinsert128_insert, sched>, - VEX_W1X, EVEX_V256; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasDQI] in { - defm NAME # "64x2Z" : vinsert_for_size_split, - X86VectorVTInfo< 8, EltVT64, VR512>, - null_frag, vinsert128_insert, sched>, - VEX_W, EVEX_V512; - - defm NAME # "32x8Z" : vinsert_for_size_split, - X86VectorVTInfo<16, EltVT32, VR512>, - null_frag, vinsert256_insert, sched>, - EVEX_V512; - } -} - -// FIXME: Is there a better scheduler class for VINSERTF/VINSERTI? -defm VINSERTF : vinsert_for_type; -defm VINSERTI : vinsert_for_type; - -// Codegen pattern with the alternative types, -// Even with AVX512DQ we'll still use these for unmasked operations. -defm : vinsert_for_size_lowering<"VINSERTF32x4Z256", v2f64x_info, v4f64x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v2i64x_info, v4i64x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; - -defm : vinsert_for_size_lowering<"VINSERTF32x4Z", v2f64x_info, v8f64_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v2i64x_info, v8i64_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; - -defm : vinsert_for_size_lowering<"VINSERTF64x4Z", v8f32x_info, v16f32_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v8i32x_info, v16i32_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; - -// Codegen pattern with the alternative types insert VEC128 into VEC256 -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v8i16x_info, v16i16x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v16i8x_info, v32i8x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -// Codegen pattern with the alternative types insert VEC128 into VEC512 -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v8i16x_info, v32i16_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v16i8x_info, v64i8_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -// Codegen pattern with the alternative types insert VEC256 into VEC512 -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v16i16x_info, v32i16_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v32i8x_info, v64i8_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; - - -multiclass vinsert_for_mask_cast p> { -let Predicates = p in { - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT From.RC:$src2), - (iPTR imm))), - Cast.RC:$src0)), - (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT - (bitconvert - (From.LdFrag addr:$src2))), - (iPTR imm))), - Cast.RC:$src0)), - (!cast(InstrStr#"rmk") - Cast.RC:$src0, Cast.KRCWM:$mask, To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT From.RC:$src2), - (iPTR imm))), - Cast.ImmAllZerosV)), - (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT - (bitconvert - (From.LdFrag addr:$src2))), - (iPTR imm))), - Cast.ImmAllZerosV)), - (!cast(InstrStr#"rmkz") - Cast.KRCWM:$mask, To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; -} -} - -defm : vinsert_for_mask_cast<"VINSERTF32x4Z256", v2f64x_info, v4f64x_info, - v8f32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v4f32x_info, v8f32x_info, - v4f64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v2i64x_info, v4i64x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v8i16x_info, v16i16x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v16i8x_info, v32i8x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v4i32x_info, v8i32x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v8i16x_info, v16i16x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v16i8x_info, v32i8x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; - -defm : vinsert_for_mask_cast<"VINSERTF32x4Z", v2f64x_info, v8f64_info, - v16f32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z", v4f32x_info, v16f32_info, - v8f64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v2i64x_info, v8i64_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v8i16x_info, v32i16_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v16i8x_info, v64i8_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v4i32x_info, v16i32_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v8i16x_info, v32i16_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v16i8x_info, v64i8_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; - -defm : vinsert_for_mask_cast<"VINSERTF32x8Z", v4f64x_info, v8f64_info, - v16f32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTF64x4Z", v8f32x_info, v16f32_info, - v8f64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v4i64x_info, v8i64_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v16i16x_info, v32i16_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v32i8x_info, v64i8_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v8i32x_info, v16i32_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v16i16x_info, v32i16_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v32i8x_info, v64i8_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; - -// vinsertps - insert f32 to XMM -let ExeDomain = SSEPackedSingle in { -def VINSERTPSZrr : AVX512AIi8<0x21, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2, u8imm:$src3), - "vinsertps\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR128X:$dst, (X86insertps VR128X:$src1, VR128X:$src2, imm:$src3))]>, - EVEX_4V, Sched<[SchedWriteFShuffle.XMM]>; -def VINSERTPSZrm: AVX512AIi8<0x21, MRMSrcMem, (outs VR128X:$dst), - (ins VR128X:$src1, f32mem:$src2, u8imm:$src3), - "vinsertps\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR128X:$dst, (X86insertps VR128X:$src1, - (v4f32 (scalar_to_vector (loadf32 addr:$src2))), - imm:$src3))]>, - EVEX_4V, EVEX_CD8<32, CD8VT1>, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 VECTOR EXTRACT -//--- - -// Supports two different pattern operators for mask and unmasked ops. Allows -// null_frag to be passed for one. -multiclass vextract_for_size_split { - - let hasSideEffects = 0, ExeDomain = To.ExeDomain in { - defm rr : AVX512_maskable_split, - AVX512AIi8Base, EVEX, Sched<[SchedRR]>; - - def mr : AVX512AIi8, EVEX, - Sched<[SchedMR]>; - - let mayStore = 1, hasSideEffects = 0 in - def mrk : AVX512AIi8, - EVEX_K, EVEX, Sched<[SchedMR]>, NotMemoryFoldable; - } -} - -// Passes the same pattern operator for masked and unmasked ops. -multiclass vextract_for_size : - vextract_for_size_split; - -// Codegen pattern for the alternative types -multiclass vextract_for_size_lowering p> { - let Predicates = p in { - def : Pat<(vextract_extract:$ext (From.VT From.RC:$src1), (iPTR imm)), - (To.VT (!cast(InstrStr#"rr") - From.RC:$src1, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; - def : Pat<(store (To.VT (vextract_extract:$ext (From.VT From.RC:$src1), - (iPTR imm))), addr:$dst), - (!cast(InstrStr#"mr") addr:$dst, From.RC:$src1, - (EXTRACT_get_vextract_imm To.RC:$ext))>; - } -} - -multiclass vextract_for_type { - let Predicates = [HasAVX512] in { - defm NAME # "32x4Z" : vextract_for_size, - X86VectorVTInfo< 4, EltVT32, VR128X>, - vextract128_extract, SchedRR, SchedMR>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; - defm NAME # "64x4Z" : vextract_for_size, - X86VectorVTInfo< 4, EltVT64, VR256X>, - vextract256_extract, SchedRR, SchedMR>, - VEX_W, EVEX_V512, EVEX_CD8<64, CD8VT4>; - } - let Predicates = [HasVLX] in - defm NAME # "32x4Z256" : vextract_for_size, - X86VectorVTInfo< 4, EltVT32, VR128X>, - vextract128_extract, SchedRR, SchedMR>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasVLX, HasDQI] in - defm NAME # "64x2Z256" : vextract_for_size_split, - X86VectorVTInfo< 2, EltVT64, VR128X>, - null_frag, vextract128_extract, SchedRR, SchedMR>, - VEX_W1X, EVEX_V256, EVEX_CD8<64, CD8VT2>; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasDQI] in { - defm NAME # "64x2Z" : vextract_for_size_split, - X86VectorVTInfo< 2, EltVT64, VR128X>, - null_frag, vextract128_extract, SchedRR, SchedMR>, - VEX_W, EVEX_V512, EVEX_CD8<64, CD8VT2>; - defm NAME # "32x8Z" : vextract_for_size_split, - X86VectorVTInfo< 8, EltVT32, VR256X>, - null_frag, vextract256_extract, SchedRR, SchedMR>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; - } -} - -// TODO - replace WriteFStore/WriteVecStore with X86SchedWriteMoveLSWidths types. -defm VEXTRACTF : vextract_for_type; -defm VEXTRACTI : vextract_for_type; - -// extract_subvector codegen patterns with the alternative types. -// Even with AVX512DQ we'll still use these for unmasked operations. -defm : vextract_for_size_lowering<"VEXTRACTF32x4Z", v8f64_info, v2f64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v8i64_info, v2i64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; - -defm : vextract_for_size_lowering<"VEXTRACTF64x4Z", v16f32_info, v8f32x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v16i32_info, v8i32x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; - -defm : vextract_for_size_lowering<"VEXTRACTF32x4Z256", v4f64x_info, v2f64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v4i64x_info, v2i64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; - -// Codegen pattern with the alternative types extract VEC128 from VEC256 -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v16i16x_info, v8i16x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v32i8x_info, v16i8x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; - -// Codegen pattern with the alternative types extract VEC128 from VEC512 -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v32i16_info, v8i16x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v64i8_info, v16i8x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -// Codegen pattern with the alternative types extract VEC256 from VEC512 -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v32i16_info, v16i16x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v64i8_info, v32i8x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; - - -// A 128-bit extract from bits [255:128] of a 512-bit vector should use a -// smaller extract to enable EVEX->VEX. -let Predicates = [NoVLX] in { -def : Pat<(v2i64 (extract_subvector (v8i64 VR512:$src), (iPTR 2))), - (v2i64 (VEXTRACTI128rr - (v4i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v2f64 (extract_subvector (v8f64 VR512:$src), (iPTR 2))), - (v2f64 (VEXTRACTF128rr - (v4f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4i32 (extract_subvector (v16i32 VR512:$src), (iPTR 4))), - (v4i32 (VEXTRACTI128rr - (v8i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4f32 (extract_subvector (v16f32 VR512:$src), (iPTR 4))), - (v4f32 (VEXTRACTF128rr - (v8f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v8i16 (extract_subvector (v32i16 VR512:$src), (iPTR 8))), - (v8i16 (VEXTRACTI128rr - (v16i16 (EXTRACT_SUBREG (v32i16 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v16i8 (extract_subvector (v64i8 VR512:$src), (iPTR 16))), - (v16i8 (VEXTRACTI128rr - (v32i8 (EXTRACT_SUBREG (v64i8 VR512:$src), sub_ymm)), - (iPTR 1)))>; -} - -// A 128-bit extract from bits [255:128] of a 512-bit vector should use a -// smaller extract to enable EVEX->VEX. -let Predicates = [HasVLX] in { -def : Pat<(v2i64 (extract_subvector (v8i64 VR512:$src), (iPTR 2))), - (v2i64 (VEXTRACTI32x4Z256rr - (v4i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v2f64 (extract_subvector (v8f64 VR512:$src), (iPTR 2))), - (v2f64 (VEXTRACTF32x4Z256rr - (v4f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4i32 (extract_subvector (v16i32 VR512:$src), (iPTR 4))), - (v4i32 (VEXTRACTI32x4Z256rr - (v8i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4f32 (extract_subvector (v16f32 VR512:$src), (iPTR 4))), - (v4f32 (VEXTRACTF32x4Z256rr - (v8f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v8i16 (extract_subvector (v32i16 VR512:$src), (iPTR 8))), - (v8i16 (VEXTRACTI32x4Z256rr - (v16i16 (EXTRACT_SUBREG (v32i16 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v16i8 (extract_subvector (v64i8 VR512:$src), (iPTR 16))), - (v16i8 (VEXTRACTI32x4Z256rr - (v32i8 (EXTRACT_SUBREG (v64i8 VR512:$src), sub_ymm)), - (iPTR 1)))>; -} - - -// Additional patterns for handling a bitcast between the vselect and the -// extract_subvector. -multiclass vextract_for_mask_cast p> { -let Predicates = p in { - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (vextract_extract:$ext - (From.VT From.RC:$src), (iPTR imm)))), - To.RC:$src0)), - (Cast.VT (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, From.RC:$src, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; - - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (vextract_extract:$ext - (From.VT From.RC:$src), (iPTR imm)))), - Cast.ImmAllZerosV)), - (Cast.VT (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, From.RC:$src, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; -} -} - -defm : vextract_for_mask_cast<"VEXTRACTF32x4Z256", v4f64x_info, v2f64x_info, - v4f32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x2Z256", v8f32x_info, v4f32x_info, - v2f64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v4i64x_info, v2i64x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v16i16x_info, v8i16x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v32i8x_info, v16i8x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v8i32x_info, v4i32x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v16i16x_info, v8i16x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v32i8x_info, v16i8x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; - -defm : vextract_for_mask_cast<"VEXTRACTF32x4Z", v8f64_info, v2f64x_info, - v4f32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x2Z", v16f32_info, v4f32x_info, - v2f64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v8i64_info, v2i64x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v32i16_info, v8i16x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v64i8_info, v16i8x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v16i32_info, v4i32x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v32i16_info, v8i16x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v64i8_info, v16i8x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; - -defm : vextract_for_mask_cast<"VEXTRACTF32x8Z", v8f64_info, v4f64x_info, - v8f32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x4Z", v16f32_info, v8f32x_info, - v4f64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v8i64_info, v4i64x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v32i16_info, v16i16x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v64i8_info, v32i8x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v16i32_info, v8i32x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v32i16_info, v16i16x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v64i8_info, v32i8x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; - -// vextractps - extract 32 bits from XMM -def VEXTRACTPSZrr : AVX512AIi8<0x17, MRMDestReg, (outs GR32:$dst), - (ins VR128X:$src1, u8imm:$src2), - "vextractps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, (extractelt (bc_v4i32 (v4f32 VR128X:$src1)), imm:$src2))]>, - EVEX, VEX_WIG, Sched<[WriteVecExtract]>; - -def VEXTRACTPSZmr : AVX512AIi8<0x17, MRMDestMem, (outs), - (ins f32mem:$dst, VR128X:$src1, u8imm:$src2), - "vextractps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(store (extractelt (bc_v4i32 (v4f32 VR128X:$src1)), imm:$src2), - addr:$dst)]>, - EVEX, VEX_WIG, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecExtractSt]>; - -//===---------------------------------------------------------------------===// -// AVX-512 BROADCAST -//--- -// broadcast with a scalar argument. -multiclass avx512_broadcast_scalar opc, string OpcodeStr, - string Name, - X86VectorVTInfo DestInfo, X86VectorVTInfo SrcInfo> { - def : Pat<(DestInfo.VT (X86VBroadcast SrcInfo.FRC:$src)), - (!cast(Name#DestInfo.ZSuffix#r) - (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; - def : Pat<(DestInfo.VT (vselect DestInfo.KRCWM:$mask, - (X86VBroadcast SrcInfo.FRC:$src), - DestInfo.RC:$src0)), - (!cast(Name#DestInfo.ZSuffix#rk) - DestInfo.RC:$src0, DestInfo.KRCWM:$mask, - (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; - def : Pat<(DestInfo.VT (vselect DestInfo.KRCWM:$mask, - (X86VBroadcast SrcInfo.FRC:$src), - DestInfo.ImmAllZerosV)), - (!cast(Name#DestInfo.ZSuffix#rkz) - DestInfo.KRCWM:$mask, (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; -} - -// Split version to allow mask and broadcast node to be different types. This -// helps support the 32x2 broadcasts. -multiclass avx512_broadcast_rm_split opc, string OpcodeStr, - string Name, - SchedWrite SchedRR, SchedWrite SchedRM, - X86VectorVTInfo MaskInfo, - X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo, - SDPatternOperator UnmaskedOp = X86VBroadcast> { - let ExeDomain = DestInfo.ExeDomain, hasSideEffects = 0 in { - defm r : AVX512_maskable_split, - T8PD, EVEX, Sched<[SchedRR]>; - let mayLoad = 1 in - defm m : AVX512_maskable_split, - T8PD, EVEX, EVEX_CD8, - Sched<[SchedRM]>; - } - - def : Pat<(MaskInfo.VT - (bitconvert - (DestInfo.VT (UnmaskedOp - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src))))))), - (!cast(Name#MaskInfo.ZSuffix#m) addr:$src)>; - def : Pat<(MaskInfo.VT (vselect MaskInfo.KRCWM:$mask, - (bitconvert - (DestInfo.VT - (X86VBroadcast - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src)))))), - MaskInfo.RC:$src0)), - (!cast(Name#DestInfo.ZSuffix#mk) - MaskInfo.RC:$src0, MaskInfo.KRCWM:$mask, addr:$src)>; - def : Pat<(MaskInfo.VT (vselect MaskInfo.KRCWM:$mask, - (bitconvert - (DestInfo.VT - (X86VBroadcast - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src)))))), - MaskInfo.ImmAllZerosV)), - (!cast(Name#MaskInfo.ZSuffix#mkz) - MaskInfo.KRCWM:$mask, addr:$src)>; -} - -// Helper class to force mask and broadcast result to same type. -multiclass avx512_broadcast_rm opc, string OpcodeStr, string Name, - SchedWrite SchedRR, SchedWrite SchedRM, - X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo> : - avx512_broadcast_rm_split; - -multiclass avx512_fp_broadcast_sd opc, string OpcodeStr, - AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in { - defm Z : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V512; - } - - let Predicates = [HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V256; - } -} - -multiclass avx512_fp_broadcast_ss opc, string OpcodeStr, - AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in { - defm Z : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V512; - } - - let Predicates = [HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V256; - defm Z128 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V128; - } -} -defm VBROADCASTSS : avx512_fp_broadcast_ss<0x18, "vbroadcastss", - avx512vl_f32_info>; -defm VBROADCASTSD : avx512_fp_broadcast_sd<0x19, "vbroadcastsd", - avx512vl_f64_info>, VEX_W1X; - -multiclass avx512_int_broadcast_reg opc, SchedWrite SchedRR, - X86VectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC> { - let ExeDomain = _.ExeDomain in - defm r : AVX512_maskable, T8PD, EVEX, - Sched<[SchedRR]>; -} - -multiclass avx512_int_broadcastbw_reg opc, string Name, SchedWrite SchedRR, - X86VectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC, SubRegIndex Subreg> { - let hasSideEffects = 0, ExeDomain = _.ExeDomain in - defm r : AVX512_maskable_custom, T8PD, EVEX, Sched<[SchedRR]>; - - def : Pat <(_.VT (OpNode SrcRC:$src)), - (!cast(Name#r) - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; - - def : Pat <(vselect _.KRCWM:$mask, (_.VT (OpNode SrcRC:$src)), _.RC:$src0), - (!cast(Name#rk) _.RC:$src0, _.KRCWM:$mask, - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; - - def : Pat <(vselect _.KRCWM:$mask, (_.VT (OpNode SrcRC:$src)), _.ImmAllZerosV), - (!cast(Name#rkz) _.KRCWM:$mask, - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; -} - -multiclass avx512_int_broadcastbw_reg_vl opc, string Name, - AVX512VLVectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC, SubRegIndex Subreg, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_int_broadcastbw_reg, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_int_broadcastbw_reg, EVEX_V256; - defm Z128 : avx512_int_broadcastbw_reg, EVEX_V128; - } -} - -multiclass avx512_int_broadcast_reg_vl opc, AVX512VLVectorVTInfo _, - SDPatternOperator OpNode, - RegisterClass SrcRC, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_int_broadcast_reg, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_int_broadcast_reg, EVEX_V256; - defm Z128 : avx512_int_broadcast_reg, EVEX_V128; - } -} - -defm VPBROADCASTBr : avx512_int_broadcastbw_reg_vl<0x7A, "VPBROADCASTBr", - avx512vl_i8_info, X86VBroadcast, GR8, sub_8bit, HasBWI>; -defm VPBROADCASTWr : avx512_int_broadcastbw_reg_vl<0x7B, "VPBROADCASTWr", - avx512vl_i16_info, X86VBroadcast, GR16, sub_16bit, - HasBWI>; -defm VPBROADCASTDr : avx512_int_broadcast_reg_vl<0x7C, avx512vl_i32_info, - X86VBroadcast, GR32, HasAVX512>; -defm VPBROADCASTQr : avx512_int_broadcast_reg_vl<0x7C, avx512vl_i64_info, - X86VBroadcast, GR64, HasAVX512>, VEX_W; - -// Provide aliases for broadcast from the same register class that -// automatically does the extract. -multiclass avx512_int_broadcast_rm_lowering { - def : Pat<(DestInfo.VT (X86VBroadcast (SrcInfo.VT SrcInfo.RC:$src))), - (!cast(Name#DestInfo.ZSuffix#"r") - (ExtInfo.VT (EXTRACT_SUBREG (SrcInfo.VT SrcInfo.RC:$src), sub_xmm)))>; -} - -multiclass avx512_int_broadcast_rm_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd> { - let Predicates = [prd] in { - defm Z : avx512_broadcast_rm, - avx512_int_broadcast_rm_lowering, - EVEX_V512; - // Defined separately to avoid redefinition. - defm Z_Alt : avx512_int_broadcast_rm_lowering; - } - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_int_broadcast_rm_lowering, - EVEX_V256; - defm Z128 : avx512_broadcast_rm, - EVEX_V128; - } -} - -defm VPBROADCASTB : avx512_int_broadcast_rm_vl<0x78, "vpbroadcastb", - avx512vl_i8_info, HasBWI>; -defm VPBROADCASTW : avx512_int_broadcast_rm_vl<0x79, "vpbroadcastw", - avx512vl_i16_info, HasBWI>; -defm VPBROADCASTD : avx512_int_broadcast_rm_vl<0x58, "vpbroadcastd", - avx512vl_i32_info, HasAVX512>; -defm VPBROADCASTQ : avx512_int_broadcast_rm_vl<0x59, "vpbroadcastq", - avx512vl_i64_info, HasAVX512>, VEX_W1X; - -multiclass avx512_subvec_broadcast_rm opc, string OpcodeStr, - X86VectorVTInfo _Dst, X86VectorVTInfo _Src> { - defm rm : AVX512_maskable, - Sched<[SchedWriteShuffle.YMM.Folded]>, - AVX5128IBase, EVEX; -} - -// This should be used for the AVX512DQ broadcast instructions. It disables -// the unmasked patterns so that we only use the DQ instructions when masking -// is requested. -multiclass avx512_subvec_broadcast_rm_dq opc, string OpcodeStr, - X86VectorVTInfo _Dst, X86VectorVTInfo _Src> { - let hasSideEffects = 0, mayLoad = 1 in - defm rm : AVX512_maskable_split, - Sched<[SchedWriteShuffle.YMM.Folded]>, - AVX5128IBase, EVEX; -} - -let Predicates = [HasAVX512] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v8i64 (X86VBroadcast (v8i64 (X86vzload addr:$src)))), - (VPBROADCASTQZm addr:$src)>; -} - -let Predicates = [HasVLX] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v2i64 (X86VBroadcast (v2i64 (X86vzload addr:$src)))), - (VPBROADCASTQZ128m addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v4i64 (X86vzload addr:$src)))), - (VPBROADCASTQZ256m addr:$src)>; -} -let Predicates = [HasVLX, HasBWI] in { - // loadi16 is tricky to fold, because !isTypeDesirableForOp, justifiably. - // This means we'll encounter truncated i32 loads; match that here. - def : Pat<(v8i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWZ128m addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWZ256m addr:$src)>; - def : Pat<(v8i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWZ128m addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWZ256m addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 BROADCAST SUBVECTORS -// - -defm VBROADCASTI32X4 : avx512_subvec_broadcast_rm<0x5a, "vbroadcasti32x4", - v16i32_info, v4i32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTF32X4 : avx512_subvec_broadcast_rm<0x1a, "vbroadcastf32x4", - v16f32_info, v4f32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTI64X4 : avx512_subvec_broadcast_rm<0x5b, "vbroadcasti64x4", - v8i64_info, v4i64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT4>; -defm VBROADCASTF64X4 : avx512_subvec_broadcast_rm<0x1b, "vbroadcastf64x4", - v8f64_info, v4f64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT4>; - -let Predicates = [HasAVX512] in { -def : Pat<(v16f32 (X86SubVBroadcast (loadv8f32 addr:$src))), - (VBROADCASTF64X4rm addr:$src)>; -def : Pat<(v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; -def : Pat<(v32i16 (X86SubVBroadcast (bc_v16i16 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; -def : Pat<(v64i8 (X86SubVBroadcast (bc_v32i8 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; - -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. -def : Pat<(v8f64 (X86SubVBroadcast (v4f64 VR256X:$src))), - (VINSERTF64x4Zrr (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v4f64 VR256X:$src), 1)>; -def : Pat<(v16f32 (X86SubVBroadcast (v8f32 VR256X:$src))), - (VINSERTF64x4Zrr (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v8f32 VR256X:$src), 1)>; -def : Pat<(v8i64 (X86SubVBroadcast (v4i64 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v4i64 VR256X:$src), 1)>; -def : Pat<(v16i32 (X86SubVBroadcast (v8i32 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v8i32 VR256X:$src), 1)>; -def : Pat<(v32i16 (X86SubVBroadcast (v16i16 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v16i16 VR256X:$src), 1)>; -def : Pat<(v64i8 (X86SubVBroadcast (v32i8 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v32i8 VR256X:$src), 1)>; - -def : Pat<(v8f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF32X4rm addr:$src)>; -def : Pat<(v8i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI32X4rm addr:$src)>; -def : Pat<(v32i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4rm addr:$src)>; -def : Pat<(v64i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4rm addr:$src)>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - (bc_v16f32 (v16i32 immAllZerosV))), - (VBROADCASTF32X4rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - VR512:$src0), - (VBROADCASTF32X4rmk VR512:$src0, VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - (v16i32 immAllZerosV)), - (VBROADCASTI32X4rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - VR512:$src0), - (VBROADCASTI32X4rmk VR512:$src0, VK16WM:$mask, addr:$src)>; - -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv8f32 addr:$src)))), - (bc_v8f64 (v16i32 immAllZerosV))), - (VBROADCASTF64X4rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv8f32 addr:$src)))), - VR512:$src0), - (VBROADCASTF64X4rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src))))), - (bc_v8i64 (v16i32 immAllZerosV))), - (VBROADCASTI64X4rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src))))), - VR512:$src0), - (VBROADCASTI64X4rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -} - -let Predicates = [HasVLX] in { -defm VBROADCASTI32X4Z256 : avx512_subvec_broadcast_rm<0x5a, "vbroadcasti32x4", - v8i32x_info, v4i32x_info>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTF32X4Z256 : avx512_subvec_broadcast_rm<0x1a, "vbroadcastf32x4", - v8f32x_info, v4f32x_info>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; - -def : Pat<(v4f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF32X4Z256rm addr:$src)>; -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI32X4Z256rm addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4Z256rm addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4Z256rm addr:$src)>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK8WM:$mask, - (bc_v8f32 (v4f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - (bc_v8f32 (v8i32 immAllZerosV))), - (VBROADCASTF32X4Z256rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f32 (v4f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - VR256X:$src0), - (VBROADCASTF32X4Z256rmk VR256X:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i32 (v4i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - (v8i32 immAllZerosV)), - (VBROADCASTI32X4Z256rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i32 (v4i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - VR256X:$src0), - (VBROADCASTI32X4Z256rmk VR256X:$src0, VK8WM:$mask, addr:$src)>; - - -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. -def : Pat<(v4f64 (X86SubVBroadcast (v2f64 VR128X:$src))), - (VINSERTF32x4Z256rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v2f64 VR128X:$src), 1)>; -def : Pat<(v8f32 (X86SubVBroadcast (v4f32 VR128X:$src))), - (VINSERTF32x4Z256rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v4f32 VR128X:$src), 1)>; -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v2i64 VR128X:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v4i32 VR128X:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v8i16 VR128X:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v16i8 VR128X:$src), 1)>; -} - -let Predicates = [HasVLX, HasDQI] in { -defm VBROADCASTI64X2Z128 : avx512_subvec_broadcast_rm_dq<0x5a, "vbroadcasti64x2", - v4i64x_info, v2i64x_info>, VEX_W1X, - EVEX_V256, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTF64X2Z128 : avx512_subvec_broadcast_rm_dq<0x1a, "vbroadcastf64x2", - v4f64x_info, v2f64x_info>, VEX_W1X, - EVEX_V256, EVEX_CD8<64, CD8VT2>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK4WM:$mask, - (bc_v4f64 (v8f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - (bc_v4f64 (v8i32 immAllZerosV))), - (VBROADCASTF64X2Z128rmkz VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4f64 (v8f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - VR256X:$src0), - (VBROADCASTF64X2Z128rmk VR256X:$src0, VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4i64 (v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - (bc_v4i64 (v8i32 immAllZerosV))), - (VBROADCASTI64X2Z128rmkz VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4i64 (v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - VR256X:$src0), - (VBROADCASTI64X2Z128rmk VR256X:$src0, VK4WM:$mask, addr:$src)>; -} - -let Predicates = [HasDQI] in { -defm VBROADCASTI64X2 : avx512_subvec_broadcast_rm_dq<0x5a, "vbroadcasti64x2", - v8i64_info, v2i64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTI32X8 : avx512_subvec_broadcast_rm_dq<0x5b, "vbroadcasti32x8", - v16i32_info, v8i32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; -defm VBROADCASTF64X2 : avx512_subvec_broadcast_rm_dq<0x1a, "vbroadcastf64x2", - v8f64_info, v2f64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTF32X8 : avx512_subvec_broadcast_rm_dq<0x1b, "vbroadcastf32x8", - v16f32_info, v8f32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv4f64 addr:$src)))), - (bc_v16f32 (v16i32 immAllZerosV))), - (VBROADCASTF32X8rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv4f64 addr:$src)))), - VR512:$src0), - (VBROADCASTF32X8rmk VR512:$src0, VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv4i64 addr:$src)))), - (v16i32 immAllZerosV)), - (VBROADCASTI32X8rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv4i64 addr:$src)))), - VR512:$src0), - (VBROADCASTI32X8rmk VR512:$src0, VK16WM:$mask, addr:$src)>; - -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - (bc_v8f64 (v16i32 immAllZerosV))), - (VBROADCASTF64X2rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - VR512:$src0), - (VBROADCASTF64X2rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - (bc_v8i64 (v16i32 immAllZerosV))), - (VBROADCASTI64X2rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - VR512:$src0), - (VBROADCASTI64X2rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -} - -multiclass avx512_common_broadcast_32x2 opc, string OpcodeStr, - AVX512VLVectorVTInfo _Dst, AVX512VLVectorVTInfo _Src> { - let Predicates = [HasDQI] in - defm Z : avx512_broadcast_rm_split, - EVEX_V512; - let Predicates = [HasDQI, HasVLX] in - defm Z256 : avx512_broadcast_rm_split, - EVEX_V256; -} - -multiclass avx512_common_broadcast_i32x2 opc, string OpcodeStr, - AVX512VLVectorVTInfo _Dst, AVX512VLVectorVTInfo _Src> : - avx512_common_broadcast_32x2 { - - let Predicates = [HasDQI, HasVLX] in - defm Z128 : avx512_broadcast_rm_split, - EVEX_V128; -} - -defm VBROADCASTI32X2 : avx512_common_broadcast_i32x2<0x59, "vbroadcasti32x2", - avx512vl_i32_info, avx512vl_i64_info>; -defm VBROADCASTF32X2 : avx512_common_broadcast_32x2<0x19, "vbroadcastf32x2", - avx512vl_f32_info, avx512vl_f64_info>; - -let Predicates = [HasVLX] in { -def : Pat<(v8f32 (X86VBroadcast (v8f32 VR256X:$src))), - (VBROADCASTSSZ256r (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))>; -def : Pat<(v4f64 (X86VBroadcast (v4f64 VR256X:$src))), - (VBROADCASTSDZ256r (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))>; -} - -def : Pat<(v16f32 (X86VBroadcast (v16f32 VR512:$src))), - (VBROADCASTSSZr (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)))>; -def : Pat<(v16f32 (X86VBroadcast (v8f32 VR256X:$src))), - (VBROADCASTSSZr (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))>; - -def : Pat<(v8f64 (X86VBroadcast (v8f64 VR512:$src))), - (VBROADCASTSDZr (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)))>; -def : Pat<(v8f64 (X86VBroadcast (v4f64 VR256X:$src))), - (VBROADCASTSDZr (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))>; - -//===----------------------------------------------------------------------===// -// AVX-512 BROADCAST MASK TO VECTOR REGISTER -//--- -multiclass avx512_mask_broadcastm opc, string OpcodeStr, - X86VectorVTInfo _, RegisterClass KRC> { - def rr : AVX512XS8I, - EVEX, Sched<[WriteShuffle]>; -} - -multiclass avx512_mask_broadcast opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, RegisterClass KRC> { - let Predicates = [HasCDI] in - defm Z : avx512_mask_broadcastm, EVEX_V512; - let Predicates = [HasCDI, HasVLX] in { - defm Z256 : avx512_mask_broadcastm, EVEX_V256; - defm Z128 : avx512_mask_broadcastm, EVEX_V128; - } -} - -defm VPBROADCASTMW2D : avx512_mask_broadcast<0x3A, "vpbroadcastmw2d", - avx512vl_i32_info, VK16>; -defm VPBROADCASTMB2Q : avx512_mask_broadcast<0x2A, "vpbroadcastmb2q", - avx512vl_i64_info, VK8>, VEX_W; - -//===----------------------------------------------------------------------===// -// -- VPERMI2 - 3 source operands form -- -multiclass avx512_perm_i opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, - hasSideEffects = 0 in { - defm rr: AVX512_maskable_3src_cast, - EVEX_4V, AVX5128IBase, Sched<[sched]>; - - let mayLoad = 1 in - defm rm: AVX512_maskable_3src_cast, - EVEX_4V, AVX5128IBase, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_perm_i_mb opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, - hasSideEffects = 0, mayLoad = 1 in - defm rmb: AVX512_maskable_3src_cast, - AVX5128IBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_perm_i_sizes opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo ShuffleMask> { - defm NAME: avx512_perm_i, - avx512_perm_i_mb, EVEX_V512; - let Predicates = [HasVLX] in { - defm NAME#128: avx512_perm_i, - avx512_perm_i_mb, EVEX_V128; - defm NAME#256: avx512_perm_i, - avx512_perm_i_mb, EVEX_V256; - } -} - -multiclass avx512_perm_i_sizes_bw opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo Idx, - Predicate Prd> { - let Predicates = [Prd] in - defm NAME: avx512_perm_i, EVEX_V512; - let Predicates = [Prd, HasVLX] in { - defm NAME#128: avx512_perm_i, EVEX_V128; - defm NAME#256: avx512_perm_i, EVEX_V256; - } -} - -defm VPERMI2D : avx512_perm_i_sizes<0x76, "vpermi2d", WriteVarShuffle256, - avx512vl_i32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMI2Q : avx512_perm_i_sizes<0x76, "vpermi2q", WriteVarShuffle256, - avx512vl_i64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPERMI2W : avx512_perm_i_sizes_bw<0x75, "vpermi2w", WriteVarShuffle256, - avx512vl_i16_info, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPERMI2B : avx512_perm_i_sizes_bw<0x75, "vpermi2b", WriteVarShuffle256, - avx512vl_i8_info, avx512vl_i8_info, HasVBMI>, - EVEX_CD8<8, CD8VF>; -defm VPERMI2PS : avx512_perm_i_sizes<0x77, "vpermi2ps", WriteFVarShuffle256, - avx512vl_f32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMI2PD : avx512_perm_i_sizes<0x77, "vpermi2pd", WriteFVarShuffle256, - avx512vl_f64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; - -// Extra patterns to deal with extra bitcasts due to passthru and index being -// different types on the fp versions. -multiclass avx512_perm_i_lowering { - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 (_.VT _.RC:$src2), - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), _.RC:$src3), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rrk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 _.RC:$src2, - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), - (_.LdFrag addr:$src3)), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rmk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 _.RC:$src2, - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), - (X86VBroadcast (_.ScalarLdFrag addr:$src3))), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rmbk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3)>; -} - -// TODO: Should we add more casts? The vXi64 case is common due to ABI. -defm : avx512_perm_i_lowering<"VPERMI2PS", v16f32_info, v16i32_info, v8i64_info>; -defm : avx512_perm_i_lowering<"VPERMI2PS256", v8f32x_info, v8i32x_info, v4i64x_info>; -defm : avx512_perm_i_lowering<"VPERMI2PS128", v4f32x_info, v4i32x_info, v2i64x_info>; - -// VPERMT2 -multiclass avx512_perm_t opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable_3src, - EVEX_4V, AVX5128IBase, Sched<[sched]>; - - defm rm: AVX512_maskable_3src, - EVEX_4V, AVX5128IBase, Sched<[sched.Folded, ReadAfterLd]>; - } -} -multiclass avx512_perm_t_mb opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in - defm rmb: AVX512_maskable_3src, - AVX5128IBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_perm_t_sizes opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo ShuffleMask> { - defm NAME: avx512_perm_t, - avx512_perm_t_mb, EVEX_V512; - let Predicates = [HasVLX] in { - defm NAME#128: avx512_perm_t, - avx512_perm_t_mb, EVEX_V128; - defm NAME#256: avx512_perm_t, - avx512_perm_t_mb, EVEX_V256; - } -} - -multiclass avx512_perm_t_sizes_bw opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo Idx, Predicate Prd> { - let Predicates = [Prd] in - defm NAME: avx512_perm_t, EVEX_V512; - let Predicates = [Prd, HasVLX] in { - defm NAME#128: avx512_perm_t, EVEX_V128; - defm NAME#256: avx512_perm_t, EVEX_V256; - } -} - -defm VPERMT2D : avx512_perm_t_sizes<0x7E, "vpermt2d", WriteVarShuffle256, - avx512vl_i32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMT2Q : avx512_perm_t_sizes<0x7E, "vpermt2q", WriteVarShuffle256, - avx512vl_i64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPERMT2W : avx512_perm_t_sizes_bw<0x7D, "vpermt2w", WriteVarShuffle256, - avx512vl_i16_info, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPERMT2B : avx512_perm_t_sizes_bw<0x7D, "vpermt2b", WriteVarShuffle256, - avx512vl_i8_info, avx512vl_i8_info, HasVBMI>, - EVEX_CD8<8, CD8VF>; -defm VPERMT2PS : avx512_perm_t_sizes<0x7F, "vpermt2ps", WriteFVarShuffle256, - avx512vl_f32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMT2PD : avx512_perm_t_sizes<0x7F, "vpermt2pd", WriteFVarShuffle256, - avx512vl_f64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; - -//===----------------------------------------------------------------------===// -// AVX-512 - BLEND using mask -// - -multiclass WriteFVarBlendask opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - def rr : AVX5128I, - EVEX_4V, Sched<[sched]>; - def rrk : AVX5128I, EVEX_4V, EVEX_K, Sched<[sched]>; - def rrkz : AVX5128I, EVEX_4V, EVEX_KZ, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in { - def rm : AVX5128I, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX5128I, EVEX_4V, EVEX_K, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - def rmkz : AVX5128I, EVEX_4V, EVEX_KZ, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - } - } -} -multiclass WriteFVarBlendask_rmb opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let mayLoad = 1, hasSideEffects = 0 in { - def rmbk : AVX5128I, - EVEX_4V, EVEX_K, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - - def rmbkz : AVX5128I, - EVEX_4V, EVEX_KZ, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - - def rmb : AVX5128I, - EVEX_4V, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass blendmask_dq opc, string OpcodeStr, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - defm Z : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z256 : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V256; - defm Z128 : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V128; - } -} - -multiclass blendmask_bw opc, string OpcodeStr, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasBWI] in - defm Z : WriteFVarBlendask, - EVEX_V512; - - let Predicates = [HasBWI, HasVLX] in { - defm Z256 : WriteFVarBlendask, - EVEX_V256; - defm Z128 : WriteFVarBlendask, - EVEX_V128; - } -} - -defm VBLENDMPS : blendmask_dq<0x65, "vblendmps", SchedWriteFVarBlend, - avx512vl_f32_info>; -defm VBLENDMPD : blendmask_dq<0x65, "vblendmpd", SchedWriteFVarBlend, - avx512vl_f64_info>, VEX_W; -defm VPBLENDMD : blendmask_dq<0x64, "vpblendmd", SchedWriteVarBlend, - avx512vl_i32_info>; -defm VPBLENDMQ : blendmask_dq<0x64, "vpblendmq", SchedWriteVarBlend, - avx512vl_i64_info>, VEX_W; -defm VPBLENDMB : blendmask_bw<0x66, "vpblendmb", SchedWriteVarBlend, - avx512vl_i8_info>; -defm VPBLENDMW : blendmask_bw<0x66, "vpblendmw", SchedWriteVarBlend, - avx512vl_i16_info>, VEX_W; - -//===----------------------------------------------------------------------===// -// Compare Instructions -//===----------------------------------------------------------------------===// - -// avx512_cmp_scalar - AVX512 CMPSS and CMPSD - -multiclass avx512_cmp_scalar { - defm rr_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (OpNode (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc)>, EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - defm rm_Int : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.IntScalarMemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (OpNode (_.VT _.RC:$src1), _.ScalarIntMemCPat:$src2, - imm:$cc)>, EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rrb_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "{sae}, $src2, $src1", "$src1, $src2, {sae}", - (OpNodeRnd (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc, - (i32 FROUND_NO_EXC))>, - EVEX_4V, EVEX_B, Sched<[sched]>; - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rri_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs VK1:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, EVEX_4V, - Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - defm rmi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - - defm rrb_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, {sae}, $src2, $src1","$src1, $src2, {sae}, $cc">, - EVEX_4V, EVEX_B, Sched<[sched]>, NotMemoryFoldable; - }// let isAsmParserOnly = 1, hasSideEffects = 0 - - let isCodeGenOnly = 1 in { - let isCommutable = 1 in - def rr : AVX512Ii8<0xC2, MRMSrcReg, - (outs _.KRC:$dst), (ins _.FRC:$src1, _.FRC:$src2, AVXCC:$cc), - !strconcat("vcmp${cc}", _.Suffix, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - _.FRC:$src2, - imm:$cc))]>, - EVEX_4V, Sched<[sched]>; - def rm : AVX512Ii8<0xC2, MRMSrcMem, - (outs _.KRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2, AVXCC:$cc), - !strconcat("vcmp${cc}", _.Suffix, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2), - imm:$cc))]>, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let Predicates = [HasAVX512] in { - let ExeDomain = SSEPackedSingle in - defm VCMPSSZ : avx512_cmp_scalar, AVX512XSIi8Base; - let ExeDomain = SSEPackedDouble in - defm VCMPSDZ : avx512_cmp_scalar, AVX512XDIi8Base, VEX_W; -} - -multiclass avx512_icmp_packed opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable> { - let isCommutable = IsCommutable in - def rr : AVX512BI, - EVEX_4V, Sched<[sched]>; - def rm : AVX512BI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isCommutable = IsCommutable in - def rrk : AVX512BI, - EVEX_4V, EVEX_K, Sched<[sched]>; - def rmk : AVX512BI, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_icmp_packed_rmb opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable> : - avx512_icmp_packed { - def rmb : AVX512BI, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmbk : AVX512BI, - EVEX_4V, EVEX_K, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_icmp_packed_vl opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_icmp_packed, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_packed, EVEX_V256; - defm Z128 : avx512_icmp_packed, EVEX_V128; - } -} - -multiclass avx512_icmp_packed_rmb_vl opc, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, - Predicate prd, bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_icmp_packed_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_packed_rmb, EVEX_V256; - defm Z128 : avx512_icmp_packed_rmb, EVEX_V128; - } -} - -// This fragment treats X86cmpm as commutable to help match loads in both -// operands for PCMPEQ. -def X86setcc_commute : SDNode<"ISD::SETCC", SDTSetCC, [SDNPCommutative]>; -def X86pcmpeqm_c : PatFrag<(ops node:$src1, node:$src2), - (X86setcc_commute node:$src1, node:$src2, SETEQ)>; -def X86pcmpgtm : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETGT)>; - -// AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't -// increase the pattern complexity the way an immediate would. -let AddedComplexity = 2 in { -// FIXME: Is there a better scheduler class for VPCMP? -defm VPCMPEQB : avx512_icmp_packed_vl<0x74, "vpcmpeqb", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i8_info, HasBWI, 1>, - EVEX_CD8<8, CD8VF>, VEX_WIG; - -defm VPCMPEQW : avx512_icmp_packed_vl<0x75, "vpcmpeqw", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i16_info, HasBWI, 1>, - EVEX_CD8<16, CD8VF>, VEX_WIG; - -defm VPCMPEQD : avx512_icmp_packed_rmb_vl<0x76, "vpcmpeqd", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i32_info, HasAVX512, 1>, - EVEX_CD8<32, CD8VF>; - -defm VPCMPEQQ : avx512_icmp_packed_rmb_vl<0x29, "vpcmpeqq", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i64_info, HasAVX512, 1>, - T8PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VPCMPGTB : avx512_icmp_packed_vl<0x64, "vpcmpgtb", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>, VEX_WIG; - -defm VPCMPGTW : avx512_icmp_packed_vl<0x65, "vpcmpgtw", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - EVEX_CD8<16, CD8VF>, VEX_WIG; - -defm VPCMPGTD : avx512_icmp_packed_rmb_vl<0x66, "vpcmpgtd", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i32_info, HasAVX512>, - EVEX_CD8<32, CD8VF>; - -defm VPCMPGTQ : avx512_icmp_packed_rmb_vl<0x37, "vpcmpgtq", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i64_info, HasAVX512>, - T8PD, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_icmp_cc opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> { - let isCommutable = 1 in - def rri : AVX512AIi8, - EVEX_4V, Sched<[sched]>; - def rmi : AVX512AIi8, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isCommutable = 1 in - def rrik : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched]>; - def rmik : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rri_alt : AVX512AIi8, - EVEX_4V, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmi_alt : AVX512AIi8, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - def rrik_alt : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmik_alt : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - - def : Pat<(_.KVT (CommFrag:$cc (bitconvert (_.LdFrag addr:$src2)), - (_.VT _.RC:$src1), cond)), - (!cast(Name#_.ZSuffix#"rmi") - _.RC:$src1, addr:$src2, (CommFrag.OperandTransform $cc))>; - - def : Pat<(and _.KRCWM:$mask, - (_.KVT (CommFrag:$cc (bitconvert (_.LdFrag addr:$src2)), - (_.VT _.RC:$src1), cond))), - (!cast(Name#_.ZSuffix#"rmik") - _.KRCWM:$mask, _.RC:$src1, addr:$src2, - (CommFrag.OperandTransform $cc))>; -} - -multiclass avx512_icmp_cc_rmb opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> : - avx512_icmp_cc { - def rmib : AVX512AIi8, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmibk : AVX512AIi8, - EVEX_4V, EVEX_K, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0, mayLoad = 1 in { - def rmib_alt : AVX512AIi8, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - def rmibk_alt : AVX512AIi8, - EVEX_4V, EVEX_K, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - - def : Pat<(_.KVT (CommFrag:$cc (X86VBroadcast (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), cond)), - (!cast(Name#_.ZSuffix#"rmib") - _.RC:$src1, addr:$src2, (CommFrag.OperandTransform $cc))>; - - def : Pat<(and _.KRCWM:$mask, - (_.KVT (CommFrag:$cc (X86VBroadcast - (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), cond))), - (!cast(Name#_.ZSuffix#"rmibk") - _.KRCWM:$mask, _.RC:$src1, addr:$src2, - (CommFrag.OperandTransform $cc))>; -} - -multiclass avx512_icmp_cc_vl opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_icmp_cc, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_cc, EVEX_V256; - defm Z128 : avx512_icmp_cc, EVEX_V128; - } -} - -multiclass avx512_icmp_cc_rmb_vl opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_icmp_cc_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_cc_rmb, EVEX_V256; - defm Z128 : avx512_icmp_cc_rmb, EVEX_V128; - } -} - -def X86pcmpm_imm : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - -// Swapped operand version of the above. -def X86pcmpm_imm_commute : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - SSECC = X86::getSwappedVPCMPImm(SSECC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - -def X86pcmpm : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -// Same as above, but commutes immediate. Use for load folding. -def X86pcmpm_commute : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm_commute>; - -def X86pcmpum : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -// Same as above, but commutes immediate. Use for load folding. -def X86pcmpum_commute : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm_commute>; - -// FIXME: Is there a better scheduler class for VPCMP/VPCMPU? -defm VPCMPB : avx512_icmp_cc_vl<0x3F, "b", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>; -defm VPCMPUB : avx512_icmp_cc_vl<0x3E, "ub", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>; - -defm VPCMPW : avx512_icmp_cc_vl<0x3F, "w", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPCMPUW : avx512_icmp_cc_vl<0x3E, "uw", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; - -defm VPCMPD : avx512_icmp_cc_rmb_vl<0x1F, "d", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i32_info, - HasAVX512>, EVEX_CD8<32, CD8VF>; -defm VPCMPUD : avx512_icmp_cc_rmb_vl<0x1E, "ud", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i32_info, - HasAVX512>, EVEX_CD8<32, CD8VF>; - -defm VPCMPQ : avx512_icmp_cc_rmb_vl<0x1F, "q", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i64_info, - HasAVX512>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPCMPUQ : avx512_icmp_cc_rmb_vl<0x1E, "uq", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i64_info, - HasAVX512>, VEX_W, EVEX_CD8<64, CD8VF>; - -multiclass avx512_vcmp_common { - defm rri : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), (ins _.RC:$src1, _.RC:$src2,AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (X86cmpm (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc), 1>, - Sched<[sched]>; - - defm rmi : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst),(ins _.RC:$src1, _.MemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (X86cmpm (_.VT _.RC:$src1), - (_.VT (bitconvert (_.LdFrag addr:$src2))), - imm:$cc)>, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rmbi : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "${src2}"##_.BroadcastStr##", $src1", - "$src1, ${src2}"##_.BroadcastStr, - (X86cmpm (_.VT _.RC:$src1), - (_.VT (X86VBroadcast(_.ScalarLdFrag addr:$src2))), - imm:$cc)>, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rri_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - Sched<[sched]>, NotMemoryFoldable; - - let mayLoad = 1 in { - defm rmi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.MemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - - defm rmbi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, ${src2}"##_.BroadcastStr##", $src1", - "$src1, ${src2}"##_.BroadcastStr##", $cc">, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - } - - // Patterns for selecting with loads in other operand. - def : Pat<(X86cmpm (_.LdFrag addr:$src2), (_.VT _.RC:$src1), - CommutableCMPCC:$cc), - (!cast(Name#_.ZSuffix#"rmi") _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(and _.KRCWM:$mask, (X86cmpm (_.LdFrag addr:$src2), - (_.VT _.RC:$src1), - CommutableCMPCC:$cc)), - (!cast(Name#_.ZSuffix#"rmik") _.KRCWM:$mask, - _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(X86cmpm (X86VBroadcast (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), CommutableCMPCC:$cc), - (!cast(Name#_.ZSuffix#"rmbi") _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(and _.KRCWM:$mask, (X86cmpm (X86VBroadcast - (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), - CommutableCMPCC:$cc)), - (!cast(Name#_.ZSuffix#"rmbik") _.KRCWM:$mask, - _.RC:$src1, addr:$src2, - imm:$cc)>; -} - -multiclass avx512_vcmp_sae { - // comparison code form (VCMP[EQ/LT/LE/...] - defm rrib : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst),(ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "{sae}, $src2, $src1", "$src1, $src2, {sae}", - (X86cmpmRnd (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc, - (i32 FROUND_NO_EXC))>, - EVEX_B, Sched<[sched]>; - - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rrib_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, {sae}, $src2, $src1", - "$src1, $src2, {sae}, $cc">, - EVEX_B, Sched<[sched]>, NotMemoryFoldable; - } -} - -multiclass avx512_vcmp { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcmp_common, - avx512_vcmp_sae, EVEX_V512; - - } - let Predicates = [HasAVX512,HasVLX] in { - defm Z128 : avx512_vcmp_common, EVEX_V128; - defm Z256 : avx512_vcmp_common, EVEX_V256; - } -} - -defm VCMPPD : avx512_vcmp, - AVX512PDIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VCMPPS : avx512_vcmp, - AVX512PSIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - -// Patterns to select fp compares with load as first operand. -let Predicates = [HasAVX512] in { - def : Pat<(v1i1 (X86cmpms (loadf64 addr:$src2), FR64X:$src1, - CommutableCMPCC:$cc)), - (VCMPSDZrm FR64X:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v1i1 (X86cmpms (loadf32 addr:$src2), FR32X:$src1, - CommutableCMPCC:$cc)), - (VCMPSSZrm FR32X:$src1, addr:$src2, imm:$cc)>; -} - -// ---------------------------------------------------------------- -// FPClass -//handle fpclass instruction mask = op(reg_scalar,imm) -// op(mem_scalar,imm) -multiclass avx512_scalar_fpclass opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - Predicate prd> { - let Predicates = [prd], ExeDomain = _.ExeDomain in { - def rr : AVX512, - Sched<[sched]>; - def rrk : AVX512, - EVEX_K, Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX512, - EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle fpclass instruction mask = fpclass(reg_vec, reg_vec, imm) -// fpclass(reg_vec, mem_vec, imm) -// fpclass(reg_vec, broadcast(eltVt), imm) -multiclass avx512_vector_fpclass opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string mem, string broadcast>{ - let ExeDomain = _.ExeDomain in { - def rr : AVX512, - Sched<[sched]>; - def rrk : AVX512, - EVEX_K, Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX512, - EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - def rmb : AVX512, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmbk : AVX512, - EVEX_B, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_vector_fpclass_all opc, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - string broadcast>{ - let Predicates = [prd] in { - defm Z : avx512_vector_fpclass, EVEX_V512; - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_vector_fpclass, EVEX_V128; - defm Z256 : avx512_vector_fpclass, EVEX_V256; - } -} - -multiclass avx512_fp_fpclass_all opcVec, - bits<8> opcScalar, SDNode VecOpNode, - SDNode ScalarOpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm PS : avx512_vector_fpclass_all, - EVEX_CD8<32, CD8VF>; - defm PD : avx512_vector_fpclass_all, - EVEX_CD8<64, CD8VF> , VEX_W; - defm SSZ : avx512_scalar_fpclass, - EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_scalar_fpclass, - EVEX_CD8<64, CD8VT1>, VEX_W; -} - -defm VFPCLASS : avx512_fp_fpclass_all<"vfpclass", 0x66, 0x67, X86Vfpclass, - X86Vfpclasss, SchedWriteFCmp, HasDQI>, - AVX512AIi8Base, EVEX; - -//----------------------------------------------------------------- -// Mask register copy, including -// - copy between mask registers -// - load/store mask registers -// - copy from GPR to mask register and vice versa -// -multiclass avx512_mask_mov opc_kk, bits<8> opc_km, bits<8> opc_mk, - string OpcodeStr, RegisterClass KRC, - ValueType vvt, X86MemOperand x86memop> { - let isMoveReg = 1, hasSideEffects = 0, SchedRW = [WriteMove] in - def kk : I, - Sched<[WriteMove]>; - def km : I, - Sched<[WriteLoad]>; - def mk : I, - Sched<[WriteStore]>; -} - -multiclass avx512_mask_mov_gpr opc_kr, bits<8> opc_rk, - string OpcodeStr, - RegisterClass KRC, RegisterClass GRC> { - let hasSideEffects = 0 in { - def kr : I, - Sched<[WriteMove]>; - def rk : I, - Sched<[WriteMove]>; - } -} - -let Predicates = [HasDQI] in - defm KMOVB : avx512_mask_mov<0x90, 0x90, 0x91, "kmovb", VK8, v8i1, i8mem>, - avx512_mask_mov_gpr<0x92, 0x93, "kmovb", VK8, GR32>, - VEX, PD; - -let Predicates = [HasAVX512] in - defm KMOVW : avx512_mask_mov<0x90, 0x90, 0x91, "kmovw", VK16, v16i1, i16mem>, - avx512_mask_mov_gpr<0x92, 0x93, "kmovw", VK16, GR32>, - VEX, PS; - -let Predicates = [HasBWI] in { - defm KMOVD : avx512_mask_mov<0x90, 0x90, 0x91, "kmovd", VK32, v32i1,i32mem>, - VEX, PD, VEX_W; - defm KMOVD : avx512_mask_mov_gpr<0x92, 0x93, "kmovd", VK32, GR32>, - VEX, XD; - defm KMOVQ : avx512_mask_mov<0x90, 0x90, 0x91, "kmovq", VK64, v64i1, i64mem>, - VEX, PS, VEX_W; - defm KMOVQ : avx512_mask_mov_gpr<0x92, 0x93, "kmovq", VK64, GR64>, - VEX, XD, VEX_W; -} - -// GR from/to mask register -def : Pat<(v16i1 (bitconvert (i16 GR16:$src))), - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), GR16:$src, sub_16bit)), VK16)>; -def : Pat<(i16 (bitconvert (v16i1 VK16:$src))), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS VK16:$src, GR32)), sub_16bit)>; - -def : Pat<(v8i1 (bitconvert (i8 GR8:$src))), - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), GR8:$src, sub_8bit)), VK8)>; -def : Pat<(i8 (bitconvert (v8i1 VK8:$src))), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS VK8:$src, GR32)), sub_8bit)>; - -def : Pat<(i32 (zext (i16 (bitconvert (v16i1 VK16:$src))))), - (KMOVWrk VK16:$src)>; -def : Pat<(i32 (anyext (i16 (bitconvert (v16i1 VK16:$src))))), - (COPY_TO_REGCLASS VK16:$src, GR32)>; - -def : Pat<(i32 (zext (i8 (bitconvert (v8i1 VK8:$src))))), - (KMOVBrk VK8:$src)>, Requires<[HasDQI]>; -def : Pat<(i32 (anyext (i8 (bitconvert (v8i1 VK8:$src))))), - (COPY_TO_REGCLASS VK8:$src, GR32)>; - -def : Pat<(v32i1 (bitconvert (i32 GR32:$src))), - (COPY_TO_REGCLASS GR32:$src, VK32)>; -def : Pat<(i32 (bitconvert (v32i1 VK32:$src))), - (COPY_TO_REGCLASS VK32:$src, GR32)>; -def : Pat<(v64i1 (bitconvert (i64 GR64:$src))), - (COPY_TO_REGCLASS GR64:$src, VK64)>; -def : Pat<(i64 (bitconvert (v64i1 VK64:$src))), - (COPY_TO_REGCLASS VK64:$src, GR64)>; - -// Load/store kreg -let Predicates = [HasDQI] in { - def : Pat<(store VK1:$src, addr:$dst), - (KMOVBmk addr:$dst, (COPY_TO_REGCLASS VK1:$src, VK8))>; - - def : Pat<(v1i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK1)>; - def : Pat<(v2i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK2)>; - def : Pat<(v4i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK4)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v8i1 (bitconvert (i8 (load addr:$src)))), - (COPY_TO_REGCLASS (MOVZX32rm8 addr:$src), VK8)>; -} - -let Predicates = [HasAVX512] in { - multiclass operation_gpr_mask_copy_lowering { - def : Pat<(maskVT (scalar_to_vector GR32:$src)), - (COPY_TO_REGCLASS GR32:$src, maskRC)>; - - def : Pat<(maskVT (scalar_to_vector GR8:$src)), - (COPY_TO_REGCLASS (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src, sub_8bit), maskRC)>; - } - - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - - def : Pat<(insert_subvector (v16i1 immAllZerosV), - (v1i1 (scalar_to_vector GR8:$src)), (iPTR 0)), - (COPY_TO_REGCLASS - (KMOVWkr (AND32ri8 - (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src, sub_8bit), - (i32 1))), VK16)>; -} - -// Mask unary operation -// - KNOT -multiclass avx512_mask_unop opc, string OpcodeStr, - RegisterClass KRC, SDPatternOperator OpNode, - X86FoldableSchedWrite sched, Predicate prd> { - let Predicates = [prd] in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_unop_all opc, string OpcodeStr, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched> { - defm B : avx512_mask_unop, VEX, PD; - defm W : avx512_mask_unop, VEX, PS; - defm D : avx512_mask_unop, VEX, PD, VEX_W; - defm Q : avx512_mask_unop, VEX, PS, VEX_W; -} - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KNOT : avx512_mask_unop_all<0x44, "knot", vnot, SchedWriteVecLogic.XMM>; - -// KNL does not support KMOVB, 8-bit mask is promoted to 16-bit -let Predicates = [HasAVX512, NoDQI] in -def : Pat<(vnot VK8:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK8:$src, VK16)), VK8)>; - -def : Pat<(vnot VK4:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK4:$src, VK16)), VK4)>; -def : Pat<(vnot VK2:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK2:$src, VK16)), VK2)>; - -// Mask binary operation -// - KAND, KANDN, KOR, KXNOR, KXOR -multiclass avx512_mask_binop opc, string OpcodeStr, - RegisterClass KRC, SDPatternOperator OpNode, - X86FoldableSchedWrite sched, Predicate prd, - bit IsCommutable> { - let Predicates = [prd], isCommutable = IsCommutable in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_binop_all opc, string OpcodeStr, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched, bit IsCommutable, - Predicate prdW = HasAVX512> { - defm B : avx512_mask_binop, VEX_4V, VEX_L, PD; - defm W : avx512_mask_binop, VEX_4V, VEX_L, PS; - defm D : avx512_mask_binop, VEX_4V, VEX_L, VEX_W, PD; - defm Q : avx512_mask_binop, VEX_4V, VEX_L, VEX_W, PS; -} - -def andn : PatFrag<(ops node:$i0, node:$i1), (and (not node:$i0), node:$i1)>; -def xnor : PatFrag<(ops node:$i0, node:$i1), (not (xor node:$i0, node:$i1))>; -// These nodes use 'vnot' instead of 'not' to support vectors. -def vandn : PatFrag<(ops node:$i0, node:$i1), (and (vnot node:$i0), node:$i1)>; -def vxnor : PatFrag<(ops node:$i0, node:$i1), (vnot (xor node:$i0, node:$i1))>; - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KAND : avx512_mask_binop_all<0x41, "kand", and, SchedWriteVecLogic.XMM, 1>; -defm KOR : avx512_mask_binop_all<0x45, "kor", or, SchedWriteVecLogic.XMM, 1>; -defm KXNOR : avx512_mask_binop_all<0x46, "kxnor", vxnor, SchedWriteVecLogic.XMM, 1>; -defm KXOR : avx512_mask_binop_all<0x47, "kxor", xor, SchedWriteVecLogic.XMM, 1>; -defm KANDN : avx512_mask_binop_all<0x42, "kandn", vandn, SchedWriteVecLogic.XMM, 0>; -defm KADD : avx512_mask_binop_all<0x4A, "kadd", X86kadd, SchedWriteVecLogic.XMM, 1, HasDQI>; - -multiclass avx512_binop_pat { - // With AVX512F, 8-bit mask is promoted to 16-bit mask, - // for the DQI set, this type is legal and KxxxB instruction is used - let Predicates = [NoDQI] in - def : Pat<(VOpNode VK8:$src1, VK8:$src2), - (COPY_TO_REGCLASS - (Inst (COPY_TO_REGCLASS VK8:$src1, VK16), - (COPY_TO_REGCLASS VK8:$src2, VK16)), VK8)>; - - // All types smaller than 8 bits require conversion anyway - def : Pat<(OpNode VK1:$src1, VK1:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK1:$src1, VK16), - (COPY_TO_REGCLASS VK1:$src2, VK16)), VK1)>; - def : Pat<(VOpNode VK2:$src1, VK2:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK2:$src1, VK16), - (COPY_TO_REGCLASS VK2:$src2, VK16)), VK1)>; - def : Pat<(VOpNode VK4:$src1, VK4:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK4:$src1, VK16), - (COPY_TO_REGCLASS VK4:$src2, VK16)), VK1)>; -} - -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; - -// Mask unpacking -multiclass avx512_mask_unpck { - let Predicates = [prd] in { - let hasSideEffects = 0 in - def rr : I<0x4b, MRMSrcReg, (outs KRC:$dst), - (ins KRC:$src1, KRC:$src2), - "kunpck"#Suffix#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - VEX_4V, VEX_L, Sched<[sched]>; - - def : Pat<(VT (concat_vectors KRCSrc:$src1, KRCSrc:$src2)), - (!cast(NAME##rr) - (COPY_TO_REGCLASS KRCSrc:$src2, KRC), - (COPY_TO_REGCLASS KRCSrc:$src1, KRC))>; - } -} - -defm KUNPCKBW : avx512_mask_unpck<"bw", VK16, v16i1, VK8, WriteShuffle, HasAVX512>, PD; -defm KUNPCKWD : avx512_mask_unpck<"wd", VK32, v32i1, VK16, WriteShuffle, HasBWI>, PS; -defm KUNPCKDQ : avx512_mask_unpck<"dq", VK64, v64i1, VK32, WriteShuffle, HasBWI>, PS, VEX_W; - -// Mask bit testing -multiclass avx512_mask_testop opc, string OpcodeStr, RegisterClass KRC, - SDNode OpNode, X86FoldableSchedWrite sched, - Predicate prd> { - let Predicates = [prd], Defs = [EFLAGS] in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_testop_w opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - Predicate prdW = HasAVX512> { - defm B : avx512_mask_testop, - VEX, PD; - defm W : avx512_mask_testop, - VEX, PS; - defm Q : avx512_mask_testop, - VEX, PS, VEX_W; - defm D : avx512_mask_testop, - VEX, PD, VEX_W; -} - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KORTEST : avx512_mask_testop_w<0x98, "kortest", X86kortest, SchedWriteVecLogic.XMM>; -defm KTEST : avx512_mask_testop_w<0x99, "ktest", X86ktest, SchedWriteVecLogic.XMM, HasDQI>; - -// Mask shift -multiclass avx512_mask_shiftop opc, string OpcodeStr, RegisterClass KRC, - SDNode OpNode, X86FoldableSchedWrite sched> { - let Predicates = [HasAVX512] in - def ri : Ii8, - Sched<[sched]>; -} - -multiclass avx512_mask_shiftop_w opc1, bits<8> opc2, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched> { - defm W : avx512_mask_shiftop, VEX, TAPD, VEX_W; - let Predicates = [HasDQI] in - defm B : avx512_mask_shiftop, VEX, TAPD; - let Predicates = [HasBWI] in { - defm Q : avx512_mask_shiftop, VEX, TAPD, VEX_W; - defm D : avx512_mask_shiftop, VEX, TAPD; - } -} - -defm KSHIFTL : avx512_mask_shiftop_w<0x32, 0x33, "kshiftl", X86kshiftl, WriteShuffle>; -defm KSHIFTR : avx512_mask_shiftop_w<0x30, 0x31, "kshiftr", X86kshiftr, WriteShuffle>; - -// Patterns for comparing 128/256-bit integer vectors using 512-bit instruction. -multiclass axv512_icmp_packed_no_vlx_lowering { - def : Pat<(Narrow.KVT (Frag (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2))), - (COPY_TO_REGCLASS - (!cast(InstStr#"Zrr") - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx))), - Narrow.KRC)>; - - def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (Frag (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2)))), - (COPY_TO_REGCLASS - (!cast(InstStr#"Zrrk") - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx))), - Narrow.KRC)>; -} - -// Patterns for comparing 128/256-bit integer vectors using 512-bit instruction. -multiclass axv512_icmp_packed_cc_no_vlx_lowering { -def : Pat<(Narrow.KVT (Frag:$cc (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), cond)), - (COPY_TO_REGCLASS - (!cast(InstStr##Zrri) - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - (Frag.OperandTransform $cc)), Narrow.KRC)>; - -def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (Narrow.KVT (Frag:$cc (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), - cond)))), - (COPY_TO_REGCLASS (!cast(InstStr##Zrrik) - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - (Frag.OperandTransform $cc)), Narrow.KRC)>; -} - -// Same as above, but for fp types which don't use PatFrags. -multiclass axv512_cmp_packed_cc_no_vlx_lowering { -def : Pat<(Narrow.KVT (OpNode (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), imm:$cc)), - (COPY_TO_REGCLASS - (!cast(InstStr##Zrri) - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - imm:$cc), Narrow.KRC)>; - -def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (OpNode (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), imm:$cc))), - (COPY_TO_REGCLASS (!cast(InstStr##Zrrik) - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - imm:$cc), Narrow.KRC)>; -} - -let Predicates = [HasAVX512, NoVLX] in { - // AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't - // increase the pattern complexity the way an immediate would. - let AddedComplexity = 2 in { - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - } - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; -} - -let Predicates = [HasBWI, NoVLX] in { - // AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't - // increase the pattern complexity the way an immediate would. - let AddedComplexity = 2 in { - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - } - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; -} - -// Mask setting all 0s or 1s -multiclass avx512_mask_setop { - let Predicates = [HasAVX512] in - let isReMaterializable = 1, isAsCheapAsAMove = 1, isPseudo = 1, - SchedRW = [WriteZero] in - def #NAME# : I<0, Pseudo, (outs KRC:$dst), (ins), "", - [(set KRC:$dst, (VT Val))]>; -} - -multiclass avx512_mask_setop_w { - defm W : avx512_mask_setop; - defm D : avx512_mask_setop; - defm Q : avx512_mask_setop; -} - -defm KSET0 : avx512_mask_setop_w; -defm KSET1 : avx512_mask_setop_w; - -// With AVX-512 only, 8-bit mask is promoted to 16-bit mask. -let Predicates = [HasAVX512] in { - def : Pat<(v8i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK8)>; - def : Pat<(v4i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK4)>; - def : Pat<(v2i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK2)>; - def : Pat<(v1i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK1)>; - def : Pat<(v8i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK8)>; - def : Pat<(v4i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK4)>; - def : Pat<(v2i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK2)>; - def : Pat<(v1i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK1)>; -} - -// Patterns for kmask insert_subvector/extract_subvector to/from index=0 -multiclass operation_subvector_mask_lowering { - def : Pat<(subVT (extract_subvector (VT RC:$src), (iPTR 0))), - (subVT (COPY_TO_REGCLASS RC:$src, subRC))>; - - def : Pat<(VT (insert_subvector undef, subRC:$src, (iPTR 0))), - (VT (COPY_TO_REGCLASS subRC:$src, RC))>; -} -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; - -//===----------------------------------------------------------------------===// -// AVX-512 - Aligned and unaligned load and store -// - -multiclass avx512_load opc, string OpcodeStr, string Name, - X86VectorVTInfo _, PatFrag ld_frag, PatFrag mload, - X86SchedWriteMoveLS Sched, string EVEX2VEXOvrd, - bit NoRMPattern = 0, - SDPatternOperator SelectOprr = vselect> { - let hasSideEffects = 0 in { - let isMoveReg = 1 in - def rr : AVX512PI, EVEX, Sched<[Sched.RR]>, - EVEX2VEXOverride; - def rrkz : AVX512PI, - EVEX, EVEX_KZ, Sched<[Sched.RR]>; - - let mayLoad = 1, canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : AVX512PI, EVEX, Sched<[Sched.RM]>, - EVEX2VEXOverride; - - let Constraints = "$src0 = $dst", isConvertibleToThreeAddress = 1 in { - def rrk : AVX512PI, - EVEX, EVEX_K, Sched<[Sched.RR]>; - def rmk : AVX512PI, - EVEX, EVEX_K, Sched<[Sched.RM]>; - } - def rmkz : AVX512PI, EVEX, EVEX_KZ, Sched<[Sched.RM]>; - } - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, undef)), - (!cast(Name#_.ZSuffix##rmkz) _.KRCWM:$mask, addr:$ptr)>; - - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix##rmkz) _.KRCWM:$mask, addr:$ptr)>; - - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, (_.VT _.RC:$src0))), - (!cast(Name#_.ZSuffix##rmk) _.RC:$src0, - _.KRCWM:$mask, addr:$ptr)>; -} - -multiclass avx512_alignedload_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoRMPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_load, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_load, EVEX_V256; - defm Z128 : avx512_load, EVEX_V128; - } -} - -multiclass avx512_load_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoRMPattern = 0, - SDPatternOperator SelectOprr = vselect> { - let Predicates = [prd] in - defm Z : avx512_load, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_load, EVEX_V256; - defm Z128 : avx512_load, EVEX_V128; - } -} - -multiclass avx512_store opc, string OpcodeStr, string BaseName, - X86VectorVTInfo _, PatFrag st_frag, PatFrag mstore, - X86SchedWriteMoveLS Sched, string EVEX2VEXOvrd, - bit NoMRPattern = 0> { - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - let isMoveReg = 1 in - def rr_REV : AVX512PI, EVEX, - FoldGenData, Sched<[Sched.RR]>, - EVEX2VEXOverride; - def rrk_REV : AVX512PI, EVEX, EVEX_K, - FoldGenData, - Sched<[Sched.RR]>; - def rrkz_REV : AVX512PI, EVEX, EVEX_KZ, - FoldGenData, - Sched<[Sched.RR]>; - } - - let hasSideEffects = 0, mayStore = 1 in - def mr : AVX512PI, EVEX, Sched<[Sched.MR]>, - EVEX2VEXOverride; - def mrk : AVX512PI, EVEX, EVEX_K, Sched<[Sched.MR]>, - NotMemoryFoldable; - - def: Pat<(mstore addr:$ptr, _.KRCWM:$mask, (_.VT _.RC:$src)), - (!cast(BaseName#_.ZSuffix#mrk) addr:$ptr, - _.KRCWM:$mask, _.RC:$src)>; - - // def : InstAlias(BaseName#_.ZSuffix#"rr_REV") - // _.RC:$dst, _.RC:$src), 0>; - // def : InstAlias(BaseName#_.ZSuffix#"rrk_REV") - // _.RC:$dst, _.KRCWM:$mask, _.RC:$src), 0>; - // def : InstAlias(BaseName#_.ZSuffix#"rrkz_REV") - // _.RC:$dst, _.KRCWM:$mask, _.RC:$src), 0>; -} - -multiclass avx512_store_vl< bits<8> opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoMRPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_store, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_store, EVEX_V256; - defm Z128 : avx512_store, EVEX_V128; - } -} - -multiclass avx512_alignedstore_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoMRPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_store, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_store, EVEX_V256; - defm Z128 : avx512_store, EVEX_V128; - } -} - -defm VMOVAPS : avx512_alignedload_vl<0x28, "vmovaps", avx512vl_f32_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPS">, - avx512_alignedstore_vl<0x29, "vmovaps", avx512vl_f32_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPS">, - PS, EVEX_CD8<32, CD8VF>; - -defm VMOVAPD : avx512_alignedload_vl<0x28, "vmovapd", avx512vl_f64_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPD">, - avx512_alignedstore_vl<0x29, "vmovapd", avx512vl_f64_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPD">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVUPS : avx512_load_vl<0x10, "vmovups", avx512vl_f32_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPS", 0, null_frag>, - avx512_store_vl<0x11, "vmovups", avx512vl_f32_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPS">, - PS, EVEX_CD8<32, CD8VF>; - -defm VMOVUPD : avx512_load_vl<0x10, "vmovupd", avx512vl_f64_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPD", 0, null_frag>, - avx512_store_vl<0x11, "vmovupd", avx512vl_f64_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPD">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVDQA32 : avx512_alignedload_vl<0x6F, "vmovdqa32", avx512vl_i32_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA", 1>, - avx512_alignedstore_vl<0x7F, "vmovdqa32", avx512vl_i32_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA", 1>, - PD, EVEX_CD8<32, CD8VF>; - -defm VMOVDQA64 : avx512_alignedload_vl<0x6F, "vmovdqa64", avx512vl_i64_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA">, - avx512_alignedstore_vl<0x7F, "vmovdqa64", avx512vl_i64_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVDQU8 : avx512_load_vl<0x6F, "vmovdqu8", avx512vl_i8_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - avx512_store_vl<0x7F, "vmovdqu8", avx512vl_i8_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XD, EVEX_CD8<8, CD8VF>; - -defm VMOVDQU16 : avx512_load_vl<0x6F, "vmovdqu16", avx512vl_i16_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - avx512_store_vl<0x7F, "vmovdqu16", avx512vl_i16_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XD, VEX_W, EVEX_CD8<16, CD8VF>; - -defm VMOVDQU32 : avx512_load_vl<0x6F, "vmovdqu32", avx512vl_i32_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 1, null_frag>, - avx512_store_vl<0x7F, "vmovdqu32", avx512vl_i32_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XS, EVEX_CD8<32, CD8VF>; - -defm VMOVDQU64 : avx512_load_vl<0x6F, "vmovdqu64", avx512vl_i64_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 0, null_frag>, - avx512_store_vl<0x7F, "vmovdqu64", avx512vl_i64_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU">, - XS, VEX_W, EVEX_CD8<64, CD8VF>; - -/* -// Special instructions to help with spilling when we don't have VLX. We need -// to load or store from a ZMM register instead. These are converted in -// expandPostRAPseudos. -let isReMaterializable = 1, canFoldAsLoad = 1, - isPseudo = 1, mayLoad = 1, hasSideEffects = 0 in { -def VMOVAPSZ128rm_NOVLX : I<0, Pseudo, (outs VR128X:$dst), (ins f128mem:$src), - "", []>, Sched<[WriteFLoadX]>; -def VMOVAPSZ256rm_NOVLX : I<0, Pseudo, (outs VR256X:$dst), (ins f256mem:$src), - "", []>, Sched<[WriteFLoadY]>; -def VMOVUPSZ128rm_NOVLX : I<0, Pseudo, (outs VR128X:$dst), (ins f128mem:$src), - "", []>, Sched<[WriteFLoadX]>; -def VMOVUPSZ256rm_NOVLX : I<0, Pseudo, (outs VR256X:$dst), (ins f256mem:$src), - "", []>, Sched<[WriteFLoadY]>; -} - -let isPseudo = 1, mayStore = 1, hasSideEffects = 0 in { -def VMOVAPSZ128mr_NOVLX : I<0, Pseudo, (outs), (ins f128mem:$dst, VR128X:$src), - "", []>, Sched<[WriteFStoreX]>; -def VMOVAPSZ256mr_NOVLX : I<0, Pseudo, (outs), (ins f256mem:$dst, VR256X:$src), - "", []>, Sched<[WriteFStoreY]>; -def VMOVUPSZ128mr_NOVLX : I<0, Pseudo, (outs), (ins f128mem:$dst, VR128X:$src), - "", []>, Sched<[WriteFStoreX]>; -def VMOVUPSZ256mr_NOVLX : I<0, Pseudo, (outs), (ins f256mem:$dst, VR256X:$src), - "", []>, Sched<[WriteFStoreY]>; -} -*/ - -def : Pat<(v8i64 (vselect VK8WM:$mask, (bc_v8i64 (v16i32 immAllZerosV)), - (v8i64 VR512:$src))), - (VMOVDQA64Zrrkz (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK8:$mask, VK16)), - VK8), VR512:$src)>; - -def : Pat<(v16i32 (vselect VK16WM:$mask, (v16i32 immAllZerosV), - (v16i32 VR512:$src))), - (VMOVDQA32Zrrkz (KNOTWrr VK16WM:$mask), VR512:$src)>; - -// These patterns exist to prevent the above patterns from introducing a second -// mask inversion when one already exists. -def : Pat<(v8i64 (vselect (xor VK8:$mask, (v8i1 immAllOnesV)), - (bc_v8i64 (v16i32 immAllZerosV)), - (v8i64 VR512:$src))), - (VMOVDQA64Zrrkz VK8:$mask, VR512:$src)>; -def : Pat<(v16i32 (vselect (xor VK16:$mask, (v16i1 immAllOnesV)), - (v16i32 immAllZerosV), - (v16i32 VR512:$src))), - (VMOVDQA32Zrrkz VK16WM:$mask, VR512:$src)>; - -multiclass mask_move_lowering { - def : Pat<(Narrow.VT (vselect (Narrow.KVT Narrow.KRCWM:$mask), - Narrow.RC:$src1, Narrow.RC:$src0)), - (EXTRACT_SUBREG - (Wide.VT - (!cast(InstrStr#"rrk") - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src0, Narrow.SubRegIdx)), - (COPY_TO_REGCLASS Narrow.KRCWM:$mask, Wide.KRCWM), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)))), - Narrow.SubRegIdx)>; - - def : Pat<(Narrow.VT (vselect (Narrow.KVT Narrow.KRCWM:$mask), - Narrow.RC:$src1, Narrow.ImmAllZerosV)), - (EXTRACT_SUBREG - (Wide.VT - (!cast(InstrStr#"rrkz") - (COPY_TO_REGCLASS Narrow.KRCWM:$mask, Wide.KRCWM), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)))), - Narrow.SubRegIdx)>; -} - -// Patterns for handling v8i1 selects of 256-bit vectors when VLX isn't -// available. Use a 512-bit operation and extract. -let Predicates = [HasAVX512, NoVLX] in { - defm : mask_move_lowering<"VMOVAPSZ", v4f32x_info, v16f32_info>; - defm : mask_move_lowering<"VMOVDQA32Z", v4i32x_info, v16i32_info>; - defm : mask_move_lowering<"VMOVAPSZ", v8f32x_info, v16f32_info>; - defm : mask_move_lowering<"VMOVDQA32Z", v8i32x_info, v16i32_info>; - - defm : mask_move_lowering<"VMOVAPDZ", v2f64x_info, v8f64_info>; - defm : mask_move_lowering<"VMOVDQA64Z", v2i64x_info, v8i64_info>; - defm : mask_move_lowering<"VMOVAPDZ", v4f64x_info, v8f64_info>; - defm : mask_move_lowering<"VMOVDQA64Z", v4i64x_info, v8i64_info>; -} - -let Predicates = [HasBWI, NoVLX] in { - defm : mask_move_lowering<"VMOVDQU8Z", v16i8x_info, v64i8_info>; - defm : mask_move_lowering<"VMOVDQU8Z", v32i8x_info, v64i8_info>; - - defm : mask_move_lowering<"VMOVDQU16Z", v8i16x_info, v32i16_info>; - defm : mask_move_lowering<"VMOVDQU16Z", v16i16x_info, v32i16_info>; -} - -let Predicates = [HasAVX512] in { - // 512-bit store. - def : Pat<(alignedstore (v16i32 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(alignedstore (v32i16 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(alignedstore (v64i8 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v16i32 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v32i16 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v64i8 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; -} - -let Predicates = [HasVLX] in { - // 128-bit store. - def : Pat<(alignedstore (v4i32 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignedstore (v8i16 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignedstore (v16i8 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v4i32 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v8i16 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v16i8 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - - // 256-bit store. - def : Pat<(alignedstore (v8i32 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignedstore (v16i16 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignedstore (v32i8 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v8i32 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v16i16 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v32i8 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; -} - -multiclass masked_move_for_extract { - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (extract_subvector - (From.VT From.RC:$src), (iPTR 0)))), - To.RC:$src0)), - (Cast.VT (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, - (To.VT (EXTRACT_SUBREG From.RC:$src, To.SubRegIdx))))>; - - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (extract_subvector - (From.VT From.RC:$src), (iPTR 0)))), - Cast.ImmAllZerosV)), - (Cast.VT (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, - (To.VT (EXTRACT_SUBREG From.RC:$src, To.SubRegIdx))))>; -} - - -let Predicates = [HasVLX] in { -// A masked extract from the first 128-bits of a 256-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z128", v4i64x_info, v2i64x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v8i32x_info, v4i32x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v16i16x_info, v8i16x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v32i8x_info, v16i8x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v4i64x_info, v2i64x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v8i32x_info, v4i32x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v16i16x_info, v8i16x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v32i8x_info, v16i8x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v4f64x_info, v2f64x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v8f32x_info, v4f32x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v4f64x_info, v2f64x_info, v4f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v8f32x_info, v4f32x_info, v4f32x_info>; - -// A masked extract from the first 128-bits of a 512-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z128", v8i64_info, v2i64x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v16i32_info, v4i32x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v32i16_info, v8i16x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v64i8_info, v16i8x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v8i64_info, v2i64x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v16i32_info, v4i32x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v32i16_info, v8i16x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v64i8_info, v16i8x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v8f64_info, v2f64x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v16f32_info, v4f32x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v8f64_info, v2f64x_info, v4f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v16f32_info, v4f32x_info, v4f32x_info>; - -// A masked extract from the first 256-bits of a 512-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z256", v8i64_info, v4i64x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v16i32_info, v8i32x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v32i16_info, v16i16x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v64i8_info, v32i8x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v8i64_info, v4i64x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v16i32_info, v8i32x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v32i16_info, v16i16x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v64i8_info, v32i8x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ256", v8f64_info, v4f64x_info, v4f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ256", v16f32_info, v8f32x_info, v4f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ256", v8f64_info, v4f64x_info, v8f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ256", v16f32_info, v8f32x_info, v8f32x_info>; -} - -// Move Int Doubleword to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVDI2PDIZrr : AVX512BI<0x6E, MRMSrcReg, (outs VR128X:$dst), (ins GR32:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - EVEX, Sched<[WriteVecMoveFromGpr]>; -def VMOVDI2PDIZrm : AVX512BI<0x6E, MRMSrcMem, (outs VR128X:$dst), (ins i32mem:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecLoad]>; -def VMOV64toPQIZrr : AVX512BI<0x6E, MRMSrcReg, (outs VR128X:$dst), (ins GR64:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def VMOV64toPQIZrm : AVX512BI<0x6E, MRMSrcMem, (outs VR128X:$dst), - (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, - EVEX, VEX_W, EVEX_CD8<64, CD8VT1>, Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in { -def VMOV64toSDZrr : AVX512BI<0x6E, MRMSrcReg, (outs FR64X:$dst), (ins GR64:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set FR64X:$dst, (bitconvert GR64:$src))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -def VMOV64toSDZrm : AVX512XSI<0x7E, MRMSrcMem, (outs FR64X:$dst), (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set FR64X:$dst, (bitconvert (loadi64 addr:$src)))]>, - EVEX, VEX_W, EVEX_CD8<8, CD8VT8>, Sched<[WriteVecLoad]>; -def VMOVSDto64Zrr : AVX512BI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64X:$src))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -def VMOVSDto64Zmr : AVX512BI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64X:$src)), addr:$dst)]>, - EVEX, VEX_W, Sched<[WriteVecStore]>, - EVEX_CD8<64, CD8VT1>; -} -} // ExeDomain = SSEPackedInt - -// Move Int Doubleword to Single Scalar -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { -def VMOVDI2SSZrr : AVX512BI<0x6E, MRMSrcReg, (outs FR32X:$dst), (ins GR32:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set FR32X:$dst, (bitconvert GR32:$src))]>, - EVEX, Sched<[WriteVecMoveFromGpr]>; - -def VMOVDI2SSZrm : AVX512BI<0x6E, MRMSrcMem, (outs FR32X:$dst), (ins i32mem:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set FR32X:$dst, (bitconvert (loadi32 addr:$src)))]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -// Move doubleword from xmm register to r/m32 -// -let ExeDomain = SSEPackedInt in { -def VMOVPDI2DIZrr : AVX512BI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128X:$src), - (iPTR 0)))]>, - EVEX, Sched<[WriteVecMoveToGpr]>; -def VMOVPDI2DIZmr : AVX512BI<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, VR128X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128X:$src), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -// Move quadword from xmm1 register to r/m64 -// -let ExeDomain = SSEPackedInt in { -def VMOVPQIto64Zrr : I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128X:$src), - (iPTR 0)))]>, - PD, EVEX, VEX_W, Sched<[WriteVecMoveToGpr]>, - Requires<[HasAVX512]>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def VMOVPQIto64Zmr : I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, PD, - EVEX, VEX_W, Sched<[WriteVecStore]>, - Requires<[HasAVX512, In64BitMode]>; - -def VMOVPQI2QIZmr : I<0xD6, MRMDestMem, (outs), - (ins i64mem:$dst, VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(store (extractelt (v2i64 VR128X:$src), (iPTR 0)), - addr:$dst)]>, - EVEX, PD, VEX_W, EVEX_CD8<64, CD8VT1>, - Sched<[WriteVecStore]>, Requires<[HasAVX512]>; - -let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in -def VMOVPQI2QIZrr : AVX512BI<0xD6, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, - EVEX, VEX_W, Sched<[SchedWriteVecLogic.XMM]>; -} // ExeDomain = SSEPackedInt - -// def : InstAlias<"vmovq.s\t{$src, $dst|$dst, $src}", -// (VMOVPQI2QIZrr VR128X:$dst, VR128X:$src), 0>; - -// Move Scalar Single to Double Int -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { -def VMOVSS2DIZrr : AVX512BI<0x7E, MRMDestReg, (outs GR32:$dst), - (ins FR32X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32X:$src))]>, - EVEX, Sched<[WriteVecMoveToGpr]>; -def VMOVSS2DIZmr : AVX512BI<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, FR32X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32X:$src)), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -// Move Quadword Int to Packed Quadword Int -// -let ExeDomain = SSEPackedInt in { -def VMOVQI2PQIZrm : AVX512XSI<0x7E, MRMSrcMem, (outs VR128X:$dst), - (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, - EVEX, VEX_W, EVEX_CD8<8, CD8VT8>, Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt - -// Allow "vmovd" but print "vmovq". -// def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", -// (VMOV64toPQIZrr VR128X:$dst, GR64:$src), 0>; -// def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", -// (VMOVPQIto64Zrr GR64:$dst, VR128X:$src), 0>; - -//===----------------------------------------------------------------------===// -// AVX-512 MOVSS, MOVSD -//===----------------------------------------------------------------------===// - -multiclass avx512_move_scalar { - let Predicates = [HasAVX512, OptForSize] in - def rr : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (OpNode _.RC:$src1, _.RC:$src2)))], - _.ExeDomain>, EVEX_4V, Sched<[SchedWriteFShuffle.XMM]>; - def rrkz : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.KRCWM:$mask, _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst {${mask}} {z}|", - "$dst {${mask}} {z}, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (X86selects _.KRCWM:$mask, - (_.VT (OpNode _.RC:$src1, _.RC:$src2)), - _.ImmAllZerosV)))], - _.ExeDomain>, EVEX_4V, EVEX_KZ, Sched<[SchedWriteFShuffle.XMM]>; - let Constraints = "$src0 = $dst" in - def rrk : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.RC:$src0, _.KRCWM:$mask, _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst {${mask}}|", - "$dst {${mask}}, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (X86selects _.KRCWM:$mask, - (_.VT (OpNode _.RC:$src1, _.RC:$src2)), - (_.VT _.RC:$src0))))], - _.ExeDomain>, EVEX_4V, EVEX_K, Sched<[SchedWriteFShuffle.XMM]>; - let canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : AVX512PI<0x10, MRMSrcMem, (outs _.FRC:$dst), (ins _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(set _.FRC:$dst, (_.ScalarLdFrag addr:$src))], - _.ExeDomain>, EVEX, Sched<[WriteFLoad]>; - let mayLoad = 1, hasSideEffects = 0 in { - let Constraints = "$src0 = $dst" in - def rmk : AVX512PI<0x10, MRMSrcMem, (outs _.RC:$dst), - (ins _.RC:$src0, _.KRCWM:$mask, _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst {${mask}}|", - "$dst {${mask}}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_K, Sched<[WriteFLoad]>; - def rmkz : AVX512PI<0x10, MRMSrcMem, (outs _.RC:$dst), - (ins _.KRCWM:$mask, _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst {${mask}} {z}|", - "$dst {${mask}} {z}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_KZ, Sched<[WriteFLoad]>; - } - def mr: AVX512PI<0x11, MRMDestMem, (outs), (ins _.ScalarMemOp:$dst, _.FRC:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(store _.FRC:$src, addr:$dst)], _.ExeDomain>, - EVEX, Sched<[WriteFStore]>; - let mayStore = 1, hasSideEffects = 0 in - def mrk: AVX512PI<0x11, MRMDestMem, (outs), - (ins _.ScalarMemOp:$dst, VK1WM:$mask, _.FRC:$src), - !strconcat(asm, "\t{$src, $dst {${mask}}|$dst {${mask}}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_K, Sched<[WriteFStore]>, - NotMemoryFoldable; -} - -defm VMOVSSZ : avx512_move_scalar<"vmovss", X86Movss, f32x_info>, - VEX_LIG, XS, EVEX_CD8<32, CD8VT1>; - -defm VMOVSDZ : avx512_move_scalar<"vmovsd", X86Movsd, f64x_info>, - VEX_LIG, XD, VEX_W, EVEX_CD8<64, CD8VT1>; - - -multiclass avx512_move_scalar_lowering { - -def : Pat<(_.VT (OpNode _.RC:$src0, - (_.VT (scalar_to_vector - (_.EltVT (X86selects VK1WM:$mask, - (_.EltVT _.FRC:$src1), - (_.EltVT _.FRC:$src2))))))), - (!cast(InstrStr#rrk) - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, _.RC)), - VK1WM:$mask, - (_.VT _.RC:$src0), - (_.VT (COPY_TO_REGCLASS _.FRC:$src1, _.RC)))>; - -def : Pat<(_.VT (OpNode _.RC:$src0, - (_.VT (scalar_to_vector - (_.EltVT (X86selects VK1WM:$mask, - (_.EltVT _.FRC:$src1), - (_.EltVT ZeroFP))))))), - (!cast(InstrStr#rrkz) - VK1WM:$mask, - (_.VT _.RC:$src0), - (_.VT (COPY_TO_REGCLASS _.FRC:$src1, _.RC)))>; -} - -multiclass avx512_store_scalar_lowering { - -def : Pat<(masked_store addr:$dst, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -} - -multiclass avx512_store_scalar_lowering_subreg { - -def : Pat<(masked_store addr:$dst, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -} - -// This matches the more recent codegen from clang that avoids emitting a 512 -// bit masked store directly. Codegen will widen 128-bit masked store to 512 -// bits on AVX512F only targets. -multiclass avx512_store_scalar_lowering_subreg2 { - -// AVX512F pattern. -def : Pat<(masked_store addr:$dst, Mask512, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -// AVX512VL pattern. -def : Pat<(masked_store addr:$dst, Mask128, (_.info128.VT _.info128.RC:$src)), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; -} - -multiclass avx512_load_scalar_lowering { - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - addr:$srcAddr)>; - -} - -multiclass avx512_load_scalar_lowering_subreg { - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -} - -// This matches the more recent codegen from clang that avoids emitting a 512 -// bit masked load directly. Codegen will widen 128-bit masked load to 512 -// bits on AVX512F only targets. -multiclass avx512_load_scalar_lowering_subreg2 { -// AVX512F patterns. -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask512, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask512, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -// AVX512Vl patterns. -def : Pat<(_.info128.VT (masked_load addr:$srcAddr, Mask128, - (_.info128.VT (bitconvert (v4i32 immAllZerosV))))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (masked_load addr:$srcAddr, Mask128, - (_.info128.VT (X86vzmovl _.info128.RC:$src)))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; -} - -defm : avx512_move_scalar_lowering<"VMOVSSZ", X86Movss, fp32imm0, v4f32x_info>; -defm : avx512_move_scalar_lowering<"VMOVSDZ", X86Movsd, fp64imm0, v2f64x_info>; - -defm : avx512_store_scalar_lowering<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (trunc (and GR32:$mask, (i32 1)))))), GR32>; -defm : avx512_store_scalar_lowering_subreg<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (and GR16:$mask, (i16 1))))), GR16, sub_16bit>; -defm : avx512_store_scalar_lowering_subreg<"VMOVSDZ", avx512vl_f64_info, - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), GR8, sub_8bit>; - -defm : avx512_store_scalar_lowering_subreg2<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (insert_subvector - (v16i1 immAllZerosV), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), - (iPTR 0))), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), GR8, sub_8bit>; -defm : avx512_store_scalar_lowering_subreg2<"VMOVSDZ", avx512vl_f64_info, - (v8i1 - (extract_subvector - (v16i1 - (insert_subvector - (v16i1 immAllZerosV), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), - (iPTR 0))), - (iPTR 0))), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), GR8, sub_8bit>; - -defm : avx512_load_scalar_lowering<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (trunc (and GR32:$mask, (i32 1)))))), GR32>; -defm : avx512_load_scalar_lowering_subreg<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (and GR16:$mask, (i16 1))))), GR16, sub_16bit>; -defm : avx512_load_scalar_lowering_subreg<"VMOVSDZ", avx512vl_f64_info, - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), GR8, sub_8bit>; - -defm : avx512_load_scalar_lowering_subreg2<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (insert_subvector - (v16i1 immAllZerosV), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), - (iPTR 0))), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), GR8, sub_8bit>; -defm : avx512_load_scalar_lowering_subreg2<"VMOVSDZ", avx512vl_f64_info, - (v8i1 - (extract_subvector - (v16i1 - (insert_subvector - (v16i1 immAllZerosV), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), - (iPTR 0))), - (iPTR 0))), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), GR8, sub_8bit>; - -def : Pat<(f32 (X86selects VK1WM:$mask, (f32 FR32X:$src1), (f32 FR32X:$src2))), - (COPY_TO_REGCLASS (v4f32 (VMOVSSZrrk - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)), - VK1WM:$mask, (v4f32 (IMPLICIT_DEF)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)))), FR32X)>; - -def : Pat<(f32 (X86selects VK1WM:$mask, (f32 FR32X:$src1), fp32imm0)), - (COPY_TO_REGCLASS (v4f32 (VMOVSSZrrkz VK1WM:$mask, (v4f32 (IMPLICIT_DEF)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)))), FR32X)>; - -def : Pat<(f64 (X86selects VK1WM:$mask, (f64 FR64X:$src1), (f64 FR64X:$src2))), - (COPY_TO_REGCLASS (v2f64 (VMOVSDZrrk - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)), - VK1WM:$mask, (v2f64 (IMPLICIT_DEF)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)))), FR64X)>; - -def : Pat<(f64 (X86selects VK1WM:$mask, (f64 FR64X:$src1), fpimm0)), - (COPY_TO_REGCLASS (v2f64 (VMOVSDZrrkz VK1WM:$mask, (v2f64 (IMPLICIT_DEF)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)))), FR64X)>; - -let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def VMOVSSZrr_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrr">, - Sched<[SchedWriteFShuffle.XMM]>; - - let Constraints = "$src0 = $dst" in - def VMOVSSZrrk_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f32x_info.RC:$src0, f32x_info.KRCWM:$mask, - VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - []>, EVEX_K, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrrk">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSSZrrkz_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f32x_info.KRCWM:$mask, VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - []>, EVEX_KZ, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrrkz">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSDZrr_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XD, EVEX_4V, VEX_LIG, VEX_W, - FoldGenData<"VMOVSDZrr">, - Sched<[SchedWriteFShuffle.XMM]>; - - let Constraints = "$src0 = $dst" in - def VMOVSDZrrk_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f64x_info.RC:$src0, f64x_info.KRCWM:$mask, - VR128X:$src1, VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - []>, EVEX_K, XD, EVEX_4V, VEX_LIG, - VEX_W, FoldGenData<"VMOVSDZrrk">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSDZrrkz_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f64x_info.KRCWM:$mask, VR128X:$src1, - VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - []>, EVEX_KZ, XD, EVEX_4V, VEX_LIG, - VEX_W, FoldGenData<"VMOVSDZrrkz">, - Sched<[SchedWriteFShuffle.XMM]>; -} - -// def : InstAlias<"vmovss.s\t{$src2, $src1, $dst|$dst, $src1, $src2}", -// (VMOVSSZrr_REV VR128X:$dst, VR128X:$src1, VR128X:$src2), 0>; -// def : InstAlias<"vmovss.s\t{$src2, $src1, $dst {${mask}}|"# -// "$dst {${mask}}, $src1, $src2}", -// (VMOVSSZrrk_REV VR128X:$dst, VK1WM:$mask, -// VR128X:$src1, VR128X:$src2), 0>; -// def : InstAlias<"vmovss.s\t{$src2, $src1, $dst {${mask}} {z}|"# -// "$dst {${mask}} {z}, $src1, $src2}", -// (VMOVSSZrrkz_REV VR128X:$dst, VK1WM:$mask, -// VR128X:$src1, VR128X:$src2), 0>; -// def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst|$dst, $src1, $src2}", -// (VMOVSDZrr_REV VR128X:$dst, VR128X:$src1, VR128X:$src2), 0>; -// def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst {${mask}}|"# -// "$dst {${mask}}, $src1, $src2}", -// (VMOVSDZrrk_REV VR128X:$dst, VK1WM:$mask, -// VR128X:$src1, VR128X:$src2), 0>; -// def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst {${mask}} {z}|"# -// "$dst {${mask}} {z}, $src1, $src2}", -// (VMOVSDZrrkz_REV VR128X:$dst, VK1WM:$mask, -// VR128X:$src1, VR128X:$src2), 0>; - -let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128X:$src))), - (VMOVSSZrr (v4f32 (AVX512_128_SET0)), VR128X:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128X:$src))), - (VMOVSSZrr (v4i32 (AVX512_128_SET0)), VR128X:$src)>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSZrr (v4f32 (AVX512_128_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSZrr (v4i32 (AVX512_128_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256X:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDZrr (v2f64 (AVX512_128_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDZrr (v2i64 (AVX512_128_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256X:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v16f32 (X86vzmovl (v16f32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSZrr (v4f32 (AVX512_128_SET0)), - (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (v16i32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSZrr (v4i32 (AVX512_128_SET0)), - (v4i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v8f64 (X86vzmovl (v8f64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDZrr (v2f64 (AVX512_128_SET0)), - (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v8i64 (X86vzmovl (v8i64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDZrr (v2i64 (AVX512_128_SET0)), - (v2i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_xmm)))), sub_xmm)>; - -} - -// Use 128-bit blends for OptForSpeed since BLENDs have better throughput than -// VMOVSS/SD. Unfortunately, loses the ability to use XMM16-31. -let Predicates = [HasAVX512, OptForSpeed] in { - def : Pat<(v16f32 (X86vzmovl (v16f32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VBLENDPSrri (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (v16i32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VPBLENDWrri (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_xmm)), - (i8 3))), sub_xmm)>; - - def : Pat<(v8f64 (X86vzmovl (v8f64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VBLENDPDrri (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v8i64 (X86vzmovl (v8i64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VPBLENDWrri (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_xmm)), - (i8 0xf))), sub_xmm)>; -} - -let Predicates = [HasAVX512] in { - - // MOVSSrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - - // MOVSDrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - - // Represent the same patterns above but in the form they appear for - // 256-bit types - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v8f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v8f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - - // Represent the same patterns above but in the form they appear for - // 512-bit types - def : Pat<(v16i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v16f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v16f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v8f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - def : Pat<(v8f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector (loadi64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128X:$src), (iPTR 0))), - addr:$dst), - (VMOVSSZmr addr:$dst, (COPY_TO_REGCLASS (v4f32 VR128X:$src), FR32X))>; -} - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVZPQILo2PQIZrr : AVX512XSI<0x7E, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, (v2i64 (X86vzmovl - (v2i64 VR128X:$src))))]>, - EVEX, VEX_W; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (VMOVDI2PDIZrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (VMOV64toPQIZrr GR64:$src)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIZrr GR64:$src)), sub_xmm)>; - - def : Pat<(v8i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIZrr GR64:$src)), sub_xmm)>; - - // AVX 128-bit movd/movq instruction write zeros in the high 128-bit part. - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v8i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (VMOVQI2PQIZrm addr:$src)>; - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128X:$src))), - (VMOVZPQILo2PQIZrr VR128X:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), - (VMOVQI2PQIZrm addr:$src)>; - def : Pat<(v4i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; - - // Use regular 128-bit instructions to match 256-bit scalar_to_vec+zext. - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrr GR32:$src)), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrr GR32:$src)), sub_xmm)>; - - // Use regular 128-bit instructions to match 512-bit scalar_to_vec+zext. - def : Pat<(v16i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v8i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Non-temporals -//===----------------------------------------------------------------------===// - -def VMOVNTDQAZrm : AVX512PI<0x2A, MRMSrcMem, (outs VR512:$dst), - (ins i512mem:$src), "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.ZMM.RM]>, - EVEX, T8PD, EVEX_V512, EVEX_CD8<64, CD8VF>; - -let Predicates = [HasVLX] in { - def VMOVNTDQAZ256rm : AVX512PI<0x2A, MRMSrcMem, (outs VR256X:$dst), - (ins i256mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.YMM.RM]>, - EVEX, T8PD, EVEX_V256, EVEX_CD8<64, CD8VF>; - - def VMOVNTDQAZ128rm : AVX512PI<0x2A, MRMSrcMem, (outs VR128X:$dst), - (ins i128mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.XMM.RM]>, - EVEX, T8PD, EVEX_V128, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_movnt opc, string OpcodeStr, X86VectorVTInfo _, - X86SchedWriteMoveLS Sched, - PatFrag st_frag = alignednontemporalstore> { - let SchedRW = [Sched.MR], AddedComplexity = 400 in - def mr : AVX512PI, EVEX, EVEX_CD8<_.EltSize, CD8VF>; -} - -multiclass avx512_movnt_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteMoveLSWidths Sched> { - let Predicates = [HasAVX512] in - defm Z : avx512_movnt, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_movnt, EVEX_V256; - defm Z128 : avx512_movnt, EVEX_V128; - } -} - -defm VMOVNTDQ : avx512_movnt_vl<0xE7, "vmovntdq", avx512vl_i64_info, - SchedWriteVecMoveLSNT>, PD; -defm VMOVNTPD : avx512_movnt_vl<0x2B, "vmovntpd", avx512vl_f64_info, - SchedWriteFMoveLSNT>, PD, VEX_W; -defm VMOVNTPS : avx512_movnt_vl<0x2B, "vmovntps", avx512vl_f32_info, - SchedWriteFMoveLSNT>, PS; - -let Predicates = [HasAVX512], AddedComplexity = 400 in { - def : Pat<(alignednontemporalstore (v16i32 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - def : Pat<(alignednontemporalstore (v32i16 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - def : Pat<(alignednontemporalstore (v64i8 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - - def : Pat<(v8f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; - def : Pat<(v16f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; - def : Pat<(v8i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; -} - -let Predicates = [HasVLX], AddedComplexity = 400 in { - def : Pat<(alignednontemporalstore (v8i32 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignednontemporalstore (v16i16 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignednontemporalstore (v32i8 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - - def : Pat<(v4f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - def : Pat<(v8f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - def : Pat<(v4i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - - def : Pat<(alignednontemporalstore (v4i32 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Integer arithmetic -// -multiclass avx512_binop_rm opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, AVX512BIBase, EVEX_4V, - Sched<[sched]>; - - defm rm : AVX512_maskable, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_binop_rmb opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable = 0> : - avx512_binop_rm { - defm rmb : AVX512_maskable, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_binop_rm_vl opc, string OpcodeStr, SDNode OpNode, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_binop_rm, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_binop_rm, EVEX_V256; - defm Z128 : avx512_binop_rm, EVEX_V128; - } -} - -multiclass avx512_binop_rmb_vl opc, string OpcodeStr, SDNode OpNode, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_binop_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_binop_rmb, EVEX_V256; - defm Z128 : avx512_binop_rmb, EVEX_V128; - } -} - -multiclass avx512_binop_rm_vl_q opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rmb_vl, - VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_binop_rm_vl_d opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rmb_vl, EVEX_CD8<32, CD8VF>; -} - -multiclass avx512_binop_rm_vl_w opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl, EVEX_CD8<16, CD8VF>, - VEX_WIG; -} - -multiclass avx512_binop_rm_vl_b opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl, EVEX_CD8<8, CD8VF>, - VEX_WIG; -} - -multiclass avx512_binop_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd, bit IsCommutable = 0> { - defm Q : avx512_binop_rm_vl_q; - - defm D : avx512_binop_rm_vl_d; -} - -multiclass avx512_binop_rm_vl_bw opc_b, bits<8> opc_w, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd, bit IsCommutable = 0> { - defm W : avx512_binop_rm_vl_w; - - defm B : avx512_binop_rm_vl_b; -} - -multiclass avx512_binop_rm_vl_all opc_b, bits<8> opc_w, - bits<8> opc_d, bits<8> opc_q, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl_dq, - avx512_binop_rm_vl_bw; -} - -multiclass avx512_binop_rm2 opc, string OpcodeStr, - X86FoldableSchedWrite sched, - SDNode OpNode,X86VectorVTInfo _Src, - X86VectorVTInfo _Dst, X86VectorVTInfo _Brdct, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, - AVX512BIBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rmb : AVX512_maskable, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -defm VPADD : avx512_binop_rm_vl_all<0xFC, 0xFD, 0xFE, 0xD4, "vpadd", add, - SchedWriteVecALU, 1>; -defm VPSUB : avx512_binop_rm_vl_all<0xF8, 0xF9, 0xFA, 0xFB, "vpsub", sub, - SchedWriteVecALU, 0>; -defm VPADDS : avx512_binop_rm_vl_bw<0xEC, 0xED, "vpadds", X86adds, - SchedWriteVecALU, HasBWI, 1>; -defm VPSUBS : avx512_binop_rm_vl_bw<0xE8, 0xE9, "vpsubs", X86subs, - SchedWriteVecALU, HasBWI, 0>; -defm VPADDUS : avx512_binop_rm_vl_bw<0xDC, 0xDD, "vpaddus", X86addus, - SchedWriteVecALU, HasBWI, 1>; -defm VPSUBUS : avx512_binop_rm_vl_bw<0xD8, 0xD9, "vpsubus", X86subus, - SchedWriteVecALU, HasBWI, 0>; -defm VPMULLD : avx512_binop_rm_vl_d<0x40, "vpmulld", mul, - SchedWritePMULLD, HasAVX512, 1>, T8PD; -defm VPMULLW : avx512_binop_rm_vl_w<0xD5, "vpmullw", mul, - SchedWriteVecIMul, HasBWI, 1>; -defm VPMULLQ : avx512_binop_rm_vl_q<0x40, "vpmullq", mul, - SchedWriteVecIMul, HasDQI, 1>, T8PD, - NotEVEX2VEXConvertible; -defm VPMULHW : avx512_binop_rm_vl_w<0xE5, "vpmulhw", mulhs, SchedWriteVecIMul, - HasBWI, 1>; -defm VPMULHUW : avx512_binop_rm_vl_w<0xE4, "vpmulhuw", mulhu, SchedWriteVecIMul, - HasBWI, 1>; -defm VPMULHRSW : avx512_binop_rm_vl_w<0x0B, "vpmulhrsw", X86mulhrs, - SchedWriteVecIMul, HasBWI, 1>, T8PD; -defm VPAVG : avx512_binop_rm_vl_bw<0xE0, 0xE3, "vpavg", X86avg, - SchedWriteVecALU, HasBWI, 1>; -defm VPMULDQ : avx512_binop_rm_vl_q<0x28, "vpmuldq", X86pmuldq, - SchedWriteVecIMul, HasAVX512, 1>, T8PD; -defm VPMULUDQ : avx512_binop_rm_vl_q<0xF4, "vpmuludq", X86pmuludq, - SchedWriteVecIMul, HasAVX512, 1>; - -multiclass avx512_binop_all opc, string OpcodeStr, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _SrcVTInfo, - AVX512VLVectorVTInfo _DstVTInfo, - SDNode OpNode, Predicate prd, bit IsCommutable = 0> { - let Predicates = [prd] in - defm NAME#Z : avx512_binop_rm2, - EVEX_V512, EVEX_CD8<64, CD8VF>, VEX_W; - let Predicates = [HasVLX, prd] in { - defm NAME#Z256 : avx512_binop_rm2, - EVEX_V256, EVEX_CD8<64, CD8VF>, VEX_W; - defm NAME#Z128 : avx512_binop_rm2, - EVEX_V128, EVEX_CD8<64, CD8VF>, VEX_W; - } -} - -defm VPMULTISHIFTQB : avx512_binop_all<0x83, "vpmultishiftqb", SchedWriteVecALU, - avx512vl_i8_info, avx512vl_i8_info, - X86multishift, HasVBMI, 0>, T8PD; - -multiclass avx512_packs_rmb opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _Src, X86VectorVTInfo _Dst, - X86FoldableSchedWrite sched> { - defm rmb : AVX512_maskable, - EVEX_4V, EVEX_B, EVEX_CD8<_Src.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_packs_rm opc, string OpcodeStr, - SDNode OpNode,X86VectorVTInfo _Src, - X86VectorVTInfo _Dst, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, - EVEX_CD8<_Src.EltSize, CD8VF>, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - EVEX_4V, EVEX_CD8<_Src.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_packs_all_i32_i16 opc, string OpcodeStr, - SDNode OpNode> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, - avx512_packs_rmb, EVEX_V512; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, - avx512_packs_rmb, - EVEX_V256; - defm NAME#Z128 : avx512_packs_rm, - avx512_packs_rmb, - EVEX_V128; - } -} -multiclass avx512_packs_all_i16_i8 opc, string OpcodeStr, - SDNode OpNode> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, EVEX_V512, VEX_WIG; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, - EVEX_V256, VEX_WIG; - defm NAME#Z128 : avx512_packs_rm, - EVEX_V128, VEX_WIG; - } -} - -multiclass avx512_vpmadd opc, string OpcodeStr, - SDNode OpNode, AVX512VLVectorVTInfo _Src, - AVX512VLVectorVTInfo _Dst, bit IsCommutable = 0> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, EVEX_V512; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, EVEX_V256; - defm NAME#Z128 : avx512_packs_rm, EVEX_V128; - } -} - -defm VPACKSSDW : avx512_packs_all_i32_i16<0x6B, "vpackssdw", X86Packss>, AVX512BIBase; -defm VPACKUSDW : avx512_packs_all_i32_i16<0x2b, "vpackusdw", X86Packus>, AVX5128IBase; -defm VPACKSSWB : avx512_packs_all_i16_i8 <0x63, "vpacksswb", X86Packss>, AVX512BIBase; -defm VPACKUSWB : avx512_packs_all_i16_i8 <0x67, "vpackuswb", X86Packus>, AVX512BIBase; - -defm VPMADDUBSW : avx512_vpmadd<0x04, "vpmaddubsw", X86vpmaddubsw, - avx512vl_i8_info, avx512vl_i16_info>, AVX512BIBase, T8PD, VEX_WIG; -defm VPMADDWD : avx512_vpmadd<0xF5, "vpmaddwd", X86vpmaddwd, - avx512vl_i16_info, avx512vl_i32_info, 1>, AVX512BIBase, VEX_WIG; - -defm VPMAXSB : avx512_binop_rm_vl_b<0x3C, "vpmaxsb", smax, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMAXSW : avx512_binop_rm_vl_w<0xEE, "vpmaxsw", smax, - SchedWriteVecALU, HasBWI, 1>; -defm VPMAXSD : avx512_binop_rm_vl_d<0x3D, "vpmaxsd", smax, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMAXSQ : avx512_binop_rm_vl_q<0x3D, "vpmaxsq", smax, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMAXUB : avx512_binop_rm_vl_b<0xDE, "vpmaxub", umax, - SchedWriteVecALU, HasBWI, 1>; -defm VPMAXUW : avx512_binop_rm_vl_w<0x3E, "vpmaxuw", umax, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMAXUD : avx512_binop_rm_vl_d<0x3F, "vpmaxud", umax, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMAXUQ : avx512_binop_rm_vl_q<0x3F, "vpmaxuq", umax, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMINSB : avx512_binop_rm_vl_b<0x38, "vpminsb", smin, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMINSW : avx512_binop_rm_vl_w<0xEA, "vpminsw", smin, - SchedWriteVecALU, HasBWI, 1>; -defm VPMINSD : avx512_binop_rm_vl_d<0x39, "vpminsd", smin, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMINSQ : avx512_binop_rm_vl_q<0x39, "vpminsq", smin, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMINUB : avx512_binop_rm_vl_b<0xDA, "vpminub", umin, - SchedWriteVecALU, HasBWI, 1>; -defm VPMINUW : avx512_binop_rm_vl_w<0x3A, "vpminuw", umin, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMINUD : avx512_binop_rm_vl_d<0x3B, "vpminud", umin, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMINUQ : avx512_binop_rm_vl_q<0x3B, "vpminuq", umin, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -// PMULLQ: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasDQI, NoVLX] in { - def : Pat<(v4i64 (mul (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (mul (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -// PMULLQ: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasDQI, NoVLX] in { - def : Pat<(v4i64 (mul (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (mul (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -multiclass avx512_min_max_lowering { - def : Pat<(v4i64 (OpNode VR256X:$src1, VR256X:$src2)), - (EXTRACT_SUBREG - (Instr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (OpNode VR128X:$src1, VR128X:$src2)), - (EXTRACT_SUBREG - (Instr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -let Predicates = [HasAVX512, NoVLX] in { - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; -} - -//===----------------------------------------------------------------------===// -// AVX-512 Logical Instructions -//===----------------------------------------------------------------------===// - -// OpNodeMsk is the OpNode to use when element size is important. OpNode will -// be set to null_frag for 32-bit elements. -multiclass avx512_logic_rm opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86FoldableSchedWrite sched, - X86VectorVTInfo _, bit IsCommutable = 0> { - let hasSideEffects = 0 in - defm rr : AVX512_maskable_logic, AVX512BIBase, EVEX_4V, - Sched<[sched]>; - - let hasSideEffects = 0, mayLoad = 1 in - defm rm : AVX512_maskable_logic, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} - -// OpNodeMsk is the OpNode to use where element size is important. So use -// for all of the broadcast patterns. -multiclass avx512_logic_rmb opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable = 0> : - avx512_logic_rm { - defm rmb : AVX512_maskable_logic, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_logic_rmb_vl opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, - bit IsCommutable = 0> { - let Predicates = [HasAVX512] in - defm Z : avx512_logic_rmb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_logic_rmb, EVEX_V256; - defm Z128 : avx512_logic_rmb, EVEX_V128; - } -} - -multiclass avx512_logic_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - bit IsCommutable = 0> { - defm Q : avx512_logic_rmb_vl, - VEX_W, EVEX_CD8<64, CD8VF>; - defm D : avx512_logic_rmb_vl, - EVEX_CD8<32, CD8VF>; -} - -defm VPAND : avx512_logic_rm_vl_dq<0xDB, 0xDB, "vpand", and, - SchedWriteVecLogic, 1>; -defm VPOR : avx512_logic_rm_vl_dq<0xEB, 0xEB, "vpor", or, - SchedWriteVecLogic, 1>; -defm VPXOR : avx512_logic_rm_vl_dq<0xEF, 0xEF, "vpxor", xor, - SchedWriteVecLogic, 1>; -defm VPANDN : avx512_logic_rm_vl_dq<0xDF, 0xDF, "vpandn", X86andnp, - SchedWriteVecLogic>; - -//===----------------------------------------------------------------------===// -// AVX-512 FP arithmetic -//===----------------------------------------------------------------------===// - -multiclass avx512_fp_scalar opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, SDNode VecNode, - X86FoldableSchedWrite sched, bit IsCommutable> { - let ExeDomain = _.ExeDomain in { - defm rr_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rm_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - let isCodeGenOnly = 1, Predicates = [HasAVX512] in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = IsCommutable; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } - } -} - -multiclass avx512_fp_scalar_round opc, string OpcodeStr,X86VectorVTInfo _, - SDNode VecNode, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - let ExeDomain = _.ExeDomain in - defm rrb_Int : AVX512_maskable_scalar, - EVEX_B, EVEX_RC, Sched<[sched]>; -} -multiclass avx512_fp_scalar_sae opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, SDNode VecNode, SDNode SaeNode, - X86FoldableSchedWrite sched, bit IsCommutable> { - let ExeDomain = _.ExeDomain in { - defm rr_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rm_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, Predicates = [HasAVX512] in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = IsCommutable; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } - - defm rrb_Int : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - } -} - -multiclass avx512_binop_s_round opc, string OpcodeStr, SDNode OpNode, - SDNode VecNode, X86SchedWriteSizes sched, - bit IsCommutable> { - defm SSZ : avx512_fp_scalar, - avx512_fp_scalar_round, - XS, EVEX_4V, VEX_LIG, EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalar, - avx512_fp_scalar_round, - XD, VEX_W, EVEX_4V, VEX_LIG, EVEX_CD8<64, CD8VT1>; -} - -multiclass avx512_binop_s_sae opc, string OpcodeStr, SDNode OpNode, - SDNode VecNode, SDNode SaeNode, - X86SchedWriteSizes sched, bit IsCommutable> { - defm SSZ : avx512_fp_scalar_sae, - XS, EVEX_4V, VEX_LIG, EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalar_sae, - XD, VEX_W, EVEX_4V, VEX_LIG, EVEX_CD8<64, CD8VT1>; -} -defm VADD : avx512_binop_s_round<0x58, "vadd", fadd, X86faddRnds, - SchedWriteFAddSizes, 1>; -defm VMUL : avx512_binop_s_round<0x59, "vmul", fmul, X86fmulRnds, - SchedWriteFMulSizes, 1>; -defm VSUB : avx512_binop_s_round<0x5C, "vsub", fsub, X86fsubRnds, - SchedWriteFAddSizes, 0>; -defm VDIV : avx512_binop_s_round<0x5E, "vdiv", fdiv, X86fdivRnds, - SchedWriteFDivSizes, 0>; -defm VMIN : avx512_binop_s_sae<0x5D, "vmin", X86fmin, X86fmins, X86fminRnds, - SchedWriteFCmpSizes, 0>; -defm VMAX : avx512_binop_s_sae<0x5F, "vmax", X86fmax, X86fmaxs, X86fmaxRnds, - SchedWriteFCmpSizes, 0>; - -// MIN/MAX nodes are commutable under "unsafe-fp-math". In this case we use -// X86fminc and X86fmaxc instead of X86fmin and X86fmax -multiclass avx512_comutable_binop_s opc, string OpcodeStr, - X86VectorVTInfo _, SDNode OpNode, - X86FoldableSchedWrite sched> { - let isCodeGenOnly = 1, Predicates = [HasAVX512], ExeDomain = _.ExeDomain in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = 1; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} -defm VMINCSSZ : avx512_comutable_binop_s<0x5D, "vminss", f32x_info, X86fminc, - SchedWriteFCmp.Scl>, XS, EVEX_4V, - VEX_LIG, EVEX_CD8<32, CD8VT1>; - -defm VMINCSDZ : avx512_comutable_binop_s<0x5D, "vminsd", f64x_info, X86fminc, - SchedWriteFCmp.Scl>, XD, VEX_W, EVEX_4V, - VEX_LIG, EVEX_CD8<64, CD8VT1>; - -defm VMAXCSSZ : avx512_comutable_binop_s<0x5F, "vmaxss", f32x_info, X86fmaxc, - SchedWriteFCmp.Scl>, XS, EVEX_4V, - VEX_LIG, EVEX_CD8<32, CD8VT1>; - -defm VMAXCSDZ : avx512_comutable_binop_s<0x5F, "vmaxsd", f64x_info, X86fmaxc, - SchedWriteFCmp.Scl>, XD, VEX_W, EVEX_4V, - VEX_LIG, EVEX_CD8<64, CD8VT1>; - -multiclass avx512_fp_packed opc, string OpcodeStr, SDPatternOperator OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable, - bit IsKZCommutable = IsCommutable> { - let ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm rr: AVX512_maskable, - EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in { - defm rm: AVX512_maskable, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } - } -} - -multiclass avx512_fp_round_packed opc, string OpcodeStr, - SDPatternOperator OpNodeRnd, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrb: AVX512_maskable, - EVEX_4V, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fp_sae_packed opc, string OpcodeStr, - SDPatternOperator OpNodeRnd, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrb: AVX512_maskable, - EVEX_4V, EVEX_B, Sched<[sched]>; -} - -multiclass avx512_fp_binop_p opc, string OpcodeStr, SDPatternOperator OpNode, - Predicate prd, X86SchedWriteSizes sched, - bit IsCommutable = 0, - bit IsPD128Commutable = IsCommutable> { - let Predicates = [prd] in { - defm PSZ : avx512_fp_packed, EVEX_V512, PS, - EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_packed, EVEX_V512, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - } - - // Define only if AVX512VL feature is present. - let Predicates = [prd, HasVLX] in { - defm PSZ128 : avx512_fp_packed, EVEX_V128, PS, - EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp_packed, EVEX_V256, PS, - EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp_packed, EVEX_V128, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp_packed, EVEX_V256, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - } -} - -multiclass avx512_fp_binop_p_round opc, string OpcodeStr, SDNode OpNodeRnd, - X86SchedWriteSizes sched> { - defm PSZ : avx512_fp_round_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_round_packed, - EVEX_V512, PD, VEX_W,EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_fp_binop_p_sae opc, string OpcodeStr, SDNode OpNodeRnd, - X86SchedWriteSizes sched> { - defm PSZ : avx512_fp_sae_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_sae_packed, - EVEX_V512, PD, VEX_W,EVEX_CD8<64, CD8VF>; -} - -defm VADD : avx512_fp_binop_p<0x58, "vadd", fadd, HasAVX512, - SchedWriteFAddSizes, 1>, - avx512_fp_binop_p_round<0x58, "vadd", X86faddRnd, SchedWriteFAddSizes>; -defm VMUL : avx512_fp_binop_p<0x59, "vmul", fmul, HasAVX512, - SchedWriteFMulSizes, 1>, - avx512_fp_binop_p_round<0x59, "vmul", X86fmulRnd, SchedWriteFMulSizes>; -defm VSUB : avx512_fp_binop_p<0x5C, "vsub", fsub, HasAVX512, - SchedWriteFAddSizes>, - avx512_fp_binop_p_round<0x5C, "vsub", X86fsubRnd, SchedWriteFAddSizes>; -defm VDIV : avx512_fp_binop_p<0x5E, "vdiv", fdiv, HasAVX512, - SchedWriteFDivSizes>, - avx512_fp_binop_p_round<0x5E, "vdiv", X86fdivRnd, SchedWriteFDivSizes>; -defm VMIN : avx512_fp_binop_p<0x5D, "vmin", X86fmin, HasAVX512, - SchedWriteFCmpSizes, 0>, - avx512_fp_binop_p_sae<0x5D, "vmin", X86fminRnd, SchedWriteFCmpSizes>; -defm VMAX : avx512_fp_binop_p<0x5F, "vmax", X86fmax, HasAVX512, - SchedWriteFCmpSizes, 0>, - avx512_fp_binop_p_sae<0x5F, "vmax", X86fmaxRnd, SchedWriteFCmpSizes>; -let isCodeGenOnly = 1 in { - defm VMINC : avx512_fp_binop_p<0x5D, "vmin", X86fminc, HasAVX512, - SchedWriteFCmpSizes, 1>; - defm VMAXC : avx512_fp_binop_p<0x5F, "vmax", X86fmaxc, HasAVX512, - SchedWriteFCmpSizes, 1>; -} -defm VAND : avx512_fp_binop_p<0x54, "vand", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; -defm VANDN : avx512_fp_binop_p<0x55, "vandn", null_frag, HasDQI, - SchedWriteFLogicSizes, 0>; -defm VOR : avx512_fp_binop_p<0x56, "vor", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; -defm VXOR : avx512_fp_binop_p<0x57, "vxor", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; - -// Patterns catch floating point selects with bitcasted integer logic ops. -multiclass avx512_fp_logical_lowering { -let Predicates = [prd] in { - // Masked register-register logical operations. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, _.RC:$src2))), - _.RC:$src0)), - (!cast(InstrStr#rrk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#rrkz) _.KRCWM:$mask, _.RC:$src1, - _.RC:$src2)>; - // Masked register-memory logical operations. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, - (load addr:$src2)))), - _.RC:$src0)), - (!cast(InstrStr#rmk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, (load addr:$src2)))), - _.ImmAllZerosV)), - (!cast(InstrStr#rmkz) _.KRCWM:$mask, _.RC:$src1, - addr:$src2)>; - // Register-broadcast logical operations. - def : Pat<(_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT (X86VBroadcast - (_.ScalarLdFrag addr:$src2)))))), - (!cast(InstrStr#rmb) _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert - (_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT - (X86VBroadcast - (_.ScalarLdFrag addr:$src2))))))), - _.RC:$src0)), - (!cast(InstrStr#rmbk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert - (_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT - (X86VBroadcast - (_.ScalarLdFrag addr:$src2))))))), - _.ImmAllZerosV)), - (!cast(InstrStr#rmbkz) _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; -} -} - -multiclass avx512_fp_logical_lowering_sizes { - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; -} - -defm : avx512_fp_logical_lowering_sizes<"VPAND", and>; -defm : avx512_fp_logical_lowering_sizes<"VPOR", or>; -defm : avx512_fp_logical_lowering_sizes<"VPXOR", xor>; -defm : avx512_fp_logical_lowering_sizes<"VPANDN", X86andnp>; - -let Predicates = [HasVLX,HasDQI] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86for FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VORPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86fxor FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VXORPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86fandn FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDNPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - - def : Pat<(f32 (X86fand FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86for FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VORPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86fxor FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VXORPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86fandn FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDNPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; -} - -multiclass avx512_fp_scalef_p opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable, - EVEX_4V, Sched<[sched]>; - defm rm: AVX512_maskable, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp_scalef_scalar opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable_scalar, - Sched<[sched]>; - defm rm: AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp_scalef_all opc, bits<8> opcScaler, string OpcodeStr, - SDNode OpNode, SDNode OpNodeScal, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp_scalef_p, - avx512_fp_round_packed, - EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_scalef_p, - avx512_fp_round_packed, - EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; - defm SSZ : avx512_fp_scalef_scalar, - avx512_fp_scalar_round, - EVEX_4V,EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalef_scalar, - avx512_fp_scalar_round, - EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; - - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp_scalef_p, - EVEX_V128, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp_scalef_p, - EVEX_V256, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp_scalef_p, - EVEX_V128, VEX_W, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp_scalef_p, - EVEX_V256, VEX_W, EVEX_CD8<64, CD8VF>; - } -} -defm VSCALEF : avx512_fp_scalef_all<0x2C, 0x2D, "vscalef", X86scalef, X86scalefs, - SchedWriteFAdd>, T8PD, NotEVEX2VEXConvertible; - -//===----------------------------------------------------------------------===// -// AVX-512 VPTESTM instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_vptest opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string Name> { - let ExeDomain = _.ExeDomain in { - let isCommutable = 1 in - defm rr : AVX512_maskable_cmp, - EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable_cmp, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } - - // Patterns for compare with 0 that just use the same source twice. - def : Pat<(_.KVT (OpNode _.RC:$src, _.ImmAllZerosV)), - (_.KVT (!cast(Name # _.ZSuffix # "rr") - _.RC:$src, _.RC:$src))>; - - def : Pat<(_.KVT (and _.KRC:$mask, (OpNode _.RC:$src, _.ImmAllZerosV))), - (_.KVT (!cast(Name # _.ZSuffix # "rrk") - _.KRC:$mask, _.RC:$src, _.RC:$src))>; -} - -multiclass avx512_vptest_mb opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rmb : AVX512_maskable_cmp, - EVEX_B, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass avx512_vptest_lowering { - def : Pat<(_.KVT (OpNode (bitconvert (_.i64VT (and _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV)), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name # "Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src1, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src2, _.SubRegIdx)), - _.KRC))>; - - def : Pat<(_.KVT (and _.KRC:$mask, - (OpNode (bitconvert (_.i64VT (and _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV))), - (COPY_TO_REGCLASS - (!cast(Name # "Zrrk") - (COPY_TO_REGCLASS _.KRC:$mask, ExtendInfo.KRC), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src1, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src2, _.SubRegIdx)), - _.KRC)>; - - def : Pat<(_.KVT (OpNode _.RC:$src, _.ImmAllZerosV)), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name # "Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC))>; - - def : Pat<(_.KVT (and _.KRC:$mask, (OpNode _.RC:$src, _.ImmAllZerosV))), - (COPY_TO_REGCLASS - (!cast(Name # "Zrrk") - (COPY_TO_REGCLASS _.KRC:$mask, ExtendInfo.KRC), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC)>; -} - -multiclass avx512_vptest_dq_sizes opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_vptest, - avx512_vptest_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_vptest, - avx512_vptest_mb, EVEX_V256; - defm Z128 : avx512_vptest, - avx512_vptest_mb, EVEX_V128; - } - let Predicates = [HasAVX512, NoVLX] in { - defm Z256_Alt : avx512_vptest_lowering< OpNode, _.info512, _.info256, NAME>; - defm Z128_Alt : avx512_vptest_lowering< OpNode, _.info512, _.info128, NAME>; - } -} - -multiclass avx512_vptest_dq opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched> { - defm D : avx512_vptest_dq_sizes; - defm Q : avx512_vptest_dq_sizes, VEX_W; -} - -multiclass avx512_vptest_wb opc, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in { - defm WZ: avx512_vptest, EVEX_V512, VEX_W; - defm BZ: avx512_vptest, EVEX_V512; - } - let Predicates = [HasVLX, HasBWI] in { - - defm WZ256: avx512_vptest, EVEX_V256, VEX_W; - defm WZ128: avx512_vptest, EVEX_V128, VEX_W; - defm BZ256: avx512_vptest, EVEX_V256; - defm BZ128: avx512_vptest, EVEX_V128; - } - - let Predicates = [HasAVX512, NoVLX] in { - defm BZ256_Alt : avx512_vptest_lowering; - defm BZ128_Alt : avx512_vptest_lowering; - defm WZ256_Alt : avx512_vptest_lowering; - defm WZ128_Alt : avx512_vptest_lowering; - } -} - -// These patterns are used to match vptestm/vptestnm. We don't treat pcmpeqm -// as commutable here because we already canonicalized all zeros vectors to the -// RHS during lowering. -def X86pcmpeqm : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETEQ)>; -def X86pcmpnem : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETNE)>; - -multiclass avx512_vptest_all_forms opc_wb, bits<8> opc_dq, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched> : - avx512_vptest_wb, - avx512_vptest_dq; - -defm VPTESTM : avx512_vptest_all_forms<0x26, 0x27, "vptestm", X86pcmpnem, - SchedWriteVecLogic>, T8PD; -defm VPTESTNM : avx512_vptest_all_forms<0x26, 0x27, "vptestnm", X86pcmpeqm, - SchedWriteVecLogic>, T8XS; - -//===----------------------------------------------------------------------===// -// AVX-512 Shift instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_shift_rmi opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm ri : AVX512_maskable, - Sched<[sched]>; - defm mi : AVX512_maskable, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_shift_rmbi opc, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm mbi : AVX512_maskable, - EVEX_B, Sched<[sched.Folded]>; -} - -multiclass avx512_shift_rrm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, ValueType SrcVT, - PatFrag bc_frag, X86VectorVTInfo _> { - // src2 is always 128-bit - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, - AVX512BIBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX512BIBase, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_shift_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, ValueType SrcVT, - PatFrag bc_frag, AVX512VLVectorVTInfo VTInfo, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_shift_rrm, EVEX_V512, - EVEX_CD8 ; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_shift_rrm, EVEX_V256, - EVEX_CD8; - defm Z128 : avx512_shift_rrm, EVEX_V128, - EVEX_CD8; - } -} - -multiclass avx512_shift_types opcd, bits<8> opcq, bits<8> opcw, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit NotEVEX2VEXConvertibleQ = 0> { - defm D : avx512_shift_sizes; - let notEVEX2VEXConvertible = NotEVEX2VEXConvertibleQ in - defm Q : avx512_shift_sizes, VEX_W; - defm W : avx512_shift_sizes; -} - -multiclass avx512_shift_rmi_sizes opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasAVX512] in - defm Z: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z256: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V256; - defm Z128: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V128; - } -} - -multiclass avx512_shift_rmi_w opcw, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm WZ: avx512_shift_rmi, EVEX_V512, VEX_WIG; - let Predicates = [HasVLX, HasBWI] in { - defm WZ256: avx512_shift_rmi, EVEX_V256, VEX_WIG; - defm WZ128: avx512_shift_rmi, EVEX_V128, VEX_WIG; - } -} - -multiclass avx512_shift_rmi_dq opcd, bits<8> opcq, - Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit NotEVEX2VEXConvertibleQ = 0> { - defm D: avx512_shift_rmi_sizes, EVEX_CD8<32, CD8VF>; - let notEVEX2VEXConvertible = NotEVEX2VEXConvertibleQ in - defm Q: avx512_shift_rmi_sizes, EVEX_CD8<64, CD8VF>, VEX_W; -} - -defm VPSRL : avx512_shift_rmi_dq<0x72, 0x73, MRM2r, MRM2m, "vpsrl", X86vsrli, - SchedWriteVecShiftImm>, - avx512_shift_rmi_w<0x71, MRM2r, MRM2m, "vpsrlw", X86vsrli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSLL : avx512_shift_rmi_dq<0x72, 0x73, MRM6r, MRM6m, "vpsll", X86vshli, - SchedWriteVecShiftImm>, - avx512_shift_rmi_w<0x71, MRM6r, MRM6m, "vpsllw", X86vshli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSRA : avx512_shift_rmi_dq<0x72, 0x72, MRM4r, MRM4m, "vpsra", X86vsrai, - SchedWriteVecShiftImm, 1>, - avx512_shift_rmi_w<0x71, MRM4r, MRM4m, "vpsraw", X86vsrai, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPROR : avx512_shift_rmi_dq<0x72, 0x72, MRM0r, MRM0m, "vpror", X86vrotri, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; -defm VPROL : avx512_shift_rmi_dq<0x72, 0x72, MRM1r, MRM1m, "vprol", X86vrotli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSLL : avx512_shift_types<0xF2, 0xF3, 0xF1, "vpsll", X86vshl, - SchedWriteVecShift>; -defm VPSRA : avx512_shift_types<0xE2, 0xE2, 0xE1, "vpsra", X86vsra, - SchedWriteVecShift, 1>; -defm VPSRL : avx512_shift_types<0xD2, 0xD3, 0xD1, "vpsrl", X86vsrl, - SchedWriteVecShift>; - -// Use 512bit VPSRA/VPSRAI version to implement v2i64/v4i64 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v4i64 (X86vsra (v4i64 VR256X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - VR128X:$src2)), sub_ymm)>; - - def : Pat<(v2i64 (X86vsra (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - VR128X:$src2)), sub_xmm)>; - - def : Pat<(v4i64 (X86vsrai (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v2i64 (X86vsrai (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; -} - -//===-------------------------------------------------------------------===// -// Variable Bit Shifts -//===-------------------------------------------------------------------===// - -multiclass avx512_var_shift opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, - AVX5128IBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX5128IBase, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_var_shift_mb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rmb : AVX512_maskable, - AVX5128IBase, EVEX_B, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_var_shift_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_var_shift, - avx512_var_shift_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V256; - defm Z128 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V128; - } -} - -multiclass avx512_var_shift_types opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - defm D : avx512_var_shift_sizes; - defm Q : avx512_var_shift_sizes, VEX_W; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass avx512_var_shift_lowering p> { - let Predicates = p in { - def : Pat<(_.info256.VT (OpNode (_.info256.VT _.info256.RC:$src1), - (_.info256.VT _.info256.RC:$src2))), - (EXTRACT_SUBREG - (!cast(OpcodeStr#"Zrr") - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(_.info128.VT (OpNode (_.info128.VT _.info128.RC:$src1), - (_.info128.VT _.info128.RC:$src2))), - (EXTRACT_SUBREG - (!cast(OpcodeStr#"Zrr") - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; - } -} -multiclass avx512_var_shift_w opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm WZ: avx512_var_shift, - EVEX_V512, VEX_W; - let Predicates = [HasVLX, HasBWI] in { - - defm WZ256: avx512_var_shift, - EVEX_V256, VEX_W; - defm WZ128: avx512_var_shift, - EVEX_V128, VEX_W; - } -} - -defm VPSLLV : avx512_var_shift_types<0x47, "vpsllv", shl, SchedWriteVarVecShift>, - avx512_var_shift_w<0x12, "vpsllvw", shl, SchedWriteVarVecShift>; - -defm VPSRAV : avx512_var_shift_types<0x46, "vpsrav", sra, SchedWriteVarVecShift>, - avx512_var_shift_w<0x11, "vpsravw", sra, SchedWriteVarVecShift>; - -defm VPSRLV : avx512_var_shift_types<0x45, "vpsrlv", srl, SchedWriteVarVecShift>, - avx512_var_shift_w<0x10, "vpsrlvw", srl, SchedWriteVarVecShift>; - -defm VPRORV : avx512_var_shift_types<0x14, "vprorv", rotr, SchedWriteVarVecShift>; -defm VPROLV : avx512_var_shift_types<0x15, "vprolv", rotl, SchedWriteVarVecShift>; - -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; - -// Special handing for handling VPSRAV intrinsics. -multiclass avx512_var_shift_int_lowering p> { - let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, _.RC:$src2)), - (!cast(InstrStr#_.ZSuffix#rr) _.RC:$src1, - _.RC:$src2)>; - def : Pat<(_.VT (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2)))), - (!cast(InstrStr#_.ZSuffix##rm) - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix#rrk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2))), - _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix##rmk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix#rrkz) _.KRC:$mask, - _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix##rmkz) _.KRC:$mask, - _.RC:$src1, addr:$src2)>; - } -} - -multiclass avx512_var_shift_int_lowering_mb p> : - avx512_var_shift_int_lowering { - let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2)))), - (!cast(InstrStr#_.ZSuffix##rmb) - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2))), - _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix##rmbk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix##rmbkz) _.KRC:$mask, - _.RC:$src1, addr:$src2)>; - } -} - -defm : avx512_var_shift_int_lowering<"VPSRAVW", v8i16x_info, [HasVLX, HasBWI]>; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v16i16x_info, [HasVLX, HasBWI]>; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v32i16_info, [HasBWI]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v4i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v8i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v16i32_info, [HasAVX512]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v2i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v4i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v8i64_info, [HasAVX512]>; - -// Use 512bit VPROL/VPROLI version to implement v2i64/v4i64 + v4i32/v8i32 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (rotl (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (rotl (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v4i32 (rotl (v4i32 VR128X:$src1), (v4i32 VR128X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v8i32 (rotl (v8i32 VR256X:$src1), (v8i32 VR256X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v2i64 (X86vrotli (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v4i64 (X86vrotli (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v4i32 (X86vrotli (v4i32 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v8i32 (X86vrotli (v8i32 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; -} - -// Use 512bit VPROR/VPRORI version to implement v2i64/v4i64 + v4i32/v8i32 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (rotr (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (rotr (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v4i32 (rotr (v4i32 VR128X:$src1), (v4i32 VR128X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v8i32 (rotr (v8i32 VR256X:$src1), (v8i32 VR256X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v2i64 (X86vrotri (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v4i64 (X86vrotri (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v4i32 (X86vrotri (v4i32 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v8i32 (X86vrotri (v8i32 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; -} - -//===-------------------------------------------------------------------===// -// 1-src variable permutation VPERMW/D/Q -//===-------------------------------------------------------------------===// - -multiclass avx512_vperm_dq_sizes opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_var_shift, - avx512_var_shift_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in - defm Z256 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V256; -} - -multiclass avx512_vpermi_dq_sizes opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasAVX512] in - defm Z: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in - defm Z256: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V256; -} - -multiclass avx512_vperm_bw opc, string OpcodeStr, - Predicate prd, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo _> { - let Predicates = [prd] in - defm Z: avx512_var_shift, - EVEX_V512 ; - let Predicates = [HasVLX, prd] in { - defm Z256: avx512_var_shift, - EVEX_V256 ; - defm Z128: avx512_var_shift, - EVEX_V128 ; - } -} - -defm VPERMW : avx512_vperm_bw<0x8D, "vpermw", HasBWI, X86VPermv, - WriteVarShuffle256, avx512vl_i16_info>, VEX_W; -defm VPERMB : avx512_vperm_bw<0x8D, "vpermb", HasVBMI, X86VPermv, - WriteVarShuffle256, avx512vl_i8_info>; - -defm VPERMD : avx512_vperm_dq_sizes<0x36, "vpermd", X86VPermv, - WriteVarShuffle256, avx512vl_i32_info>; -defm VPERMQ : avx512_vperm_dq_sizes<0x36, "vpermq", X86VPermv, - WriteVarShuffle256, avx512vl_i64_info>, VEX_W; -defm VPERMPS : avx512_vperm_dq_sizes<0x16, "vpermps", X86VPermv, - WriteFVarShuffle256, avx512vl_f32_info>; -defm VPERMPD : avx512_vperm_dq_sizes<0x16, "vpermpd", X86VPermv, - WriteFVarShuffle256, avx512vl_f64_info>, VEX_W; - -defm VPERMQ : avx512_vpermi_dq_sizes<0x00, MRMSrcReg, MRMSrcMem, "vpermq", - X86VPermi, WriteShuffle256, avx512vl_i64_info>, - EVEX, AVX512AIi8Base, EVEX_CD8<64, CD8VF>, VEX_W; -defm VPERMPD : avx512_vpermi_dq_sizes<0x01, MRMSrcReg, MRMSrcMem, "vpermpd", - X86VPermi, WriteFShuffle256, avx512vl_f64_info>, - EVEX, AVX512AIi8Base, EVEX_CD8<64, CD8VF>, VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPERMIL -//===----------------------------------------------------------------------===// - -multiclass avx512_permil_vec OpcVar, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo Ctrl> { - defm rr: AVX512_maskable, - T8PD, EVEX_4V, Sched<[sched]>; - defm rm: AVX512_maskable, - T8PD, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - T8PD, EVEX_4V, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_permil_vec_common OpcVar, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, - AVX512VLVectorVTInfo Ctrl> { - let Predicates = [HasAVX512] in { - defm Z : avx512_permil_vec, EVEX_V512; - } - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_permil_vec, EVEX_V128; - defm Z256 : avx512_permil_vec, EVEX_V256; - } -} - -multiclass avx512_permil OpcImm, bits<8> OpcVar, - AVX512VLVectorVTInfo _, AVX512VLVectorVTInfo Ctrl>{ - defm NAME: avx512_permil_vec_common; - defm NAME: avx512_shift_rmi_sizes, - EVEX, AVX512AIi8Base, EVEX_CD8<_.info128.EltSize, CD8VF>; -} - -let ExeDomain = SSEPackedSingle in -defm VPERMILPS : avx512_permil<"vpermilps", 0x04, 0x0C, avx512vl_f32_info, - avx512vl_i32_info>; -let ExeDomain = SSEPackedDouble in -defm VPERMILPD : avx512_permil<"vpermilpd", 0x05, 0x0D, avx512vl_f64_info, - avx512vl_i64_info>, VEX_W1X; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPSHUFD, VPSHUFLW, VPSHUFHW -//===----------------------------------------------------------------------===// - -defm VPSHUFD : avx512_shift_rmi_sizes<0x70, MRMSrcReg, MRMSrcMem, "vpshufd", - X86PShufd, SchedWriteShuffle, avx512vl_i32_info>, - EVEX, AVX512BIi8Base, EVEX_CD8<32, CD8VF>; -defm VPSHUFH : avx512_shift_rmi_w<0x70, MRMSrcReg, MRMSrcMem, "vpshufhw", - X86PShufhw, SchedWriteShuffle>, - EVEX, AVX512XSIi8Base; -defm VPSHUFL : avx512_shift_rmi_w<0x70, MRMSrcReg, MRMSrcMem, "vpshuflw", - X86PShuflw, SchedWriteShuffle>, - EVEX, AVX512XDIi8Base; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPSHUFB -//===----------------------------------------------------------------------===// - -multiclass avx512_pshufb_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm Z: avx512_var_shift, - EVEX_V512; - - let Predicates = [HasVLX, HasBWI] in { - defm Z256: avx512_var_shift, - EVEX_V256; - defm Z128: avx512_var_shift, - EVEX_V128; - } -} - -defm VPSHUFB: avx512_pshufb_sizes<0x00, "vpshufb", X86pshufb, - SchedWriteVarShuffle>, VEX_WIG; - -//===----------------------------------------------------------------------===// -// Move Low to High and High to Low packed FP Instructions -//===----------------------------------------------------------------------===// - -def VMOVLHPSZrr : AVX512PSI<0x16, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovlhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128X:$dst, (v4f32 (X86Movlhps VR128X:$src1, VR128X:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, EVEX_4V; -let isCommutable = 1 in -def VMOVHLPSZrr : AVX512PSI<0x12, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovhlps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128X:$dst, (v4f32 (X86Movhlps VR128X:$src1, VR128X:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, EVEX_4V, NotMemoryFoldable; - -//===----------------------------------------------------------------------===// -// VMOVHPS/PD VMOVLPS Instructions -// All patterns was taken from SSS implementation. -//===----------------------------------------------------------------------===// - -multiclass avx512_mov_hilo_packed opc, string OpcodeStr, - SDPatternOperator OpNode, - X86VectorVTInfo _> { - let hasSideEffects = 0, mayLoad = 1, ExeDomain = _.ExeDomain in - def rm : AVX512, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>, EVEX_4V; -} - -// No patterns for MOVLPS/MOVHPS as the Movlhps node should only be created in -// SSE1. And MOVLPS pattern is even more complex. -defm VMOVHPSZ128 : avx512_mov_hilo_packed<0x16, "vmovhps", null_frag, - v4f32x_info>, EVEX_CD8<32, CD8VT2>, PS; -defm VMOVHPDZ128 : avx512_mov_hilo_packed<0x16, "vmovhpd", X86Unpckl, - v2f64x_info>, EVEX_CD8<64, CD8VT1>, PD, VEX_W; -defm VMOVLPSZ128 : avx512_mov_hilo_packed<0x12, "vmovlps", null_frag, - v4f32x_info>, EVEX_CD8<32, CD8VT2>, PS; -defm VMOVLPDZ128 : avx512_mov_hilo_packed<0x12, "vmovlpd", X86Movsd, - v2f64x_info>, EVEX_CD8<64, CD8VT1>, PD, VEX_W; - -let Predicates = [HasAVX512] in { - // VMOVHPD patterns - def : Pat<(v2f64 (X86Unpckl VR128X:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (VMOVHPDZ128rm VR128X:$src1, addr:$src2)>; -} - -let SchedRW = [WriteFStore] in { -def VMOVHPSZ128mr : AVX512PSI<0x17, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128X:$src)), - (bc_v2f64 (v4f32 VR128X:$src))), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT2>; -def VMOVHPDZ128mr : AVX512PDI<0x17, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128X:$src, VR128X:$src)), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<64, CD8VT1>, VEX_W; -def VMOVLPSZ128mr : AVX512PSI<0x13, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128X:$src)), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT2>; -def VMOVLPDZ128mr : AVX512PDI<0x13, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128X:$src), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<64, CD8VT1>, VEX_W; -} // SchedRW - -let Predicates = [HasAVX512] in { - // VMOVHPD patterns - def : Pat<(store (f64 (extractelt - (v2f64 (X86VPermilpi VR128X:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (VMOVHPDZ128mr addr:$dst, VR128X:$src)>; -} -//===----------------------------------------------------------------------===// -// FMA - Fused Multiply Operations -// - -multiclass avx512_fma3p_213_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_213_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_213_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_213_rm, - avx512_fma3_213_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_213_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_213_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_213_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd> { - defm PS : avx512_fma3p_213_common; - defm PD : avx512_fma3p_213_common, - VEX_W; -} - -defm VFMADD213 : avx512_fma3p_213_f<0xA8, "vfmadd213", X86Fmadd, X86FmaddRnd>; -defm VFMSUB213 : avx512_fma3p_213_f<0xAA, "vfmsub213", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB213 : avx512_fma3p_213_f<0xA6, "vfmaddsub213", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD213 : avx512_fma3p_213_f<0xA7, "vfmsubadd213", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD213 : avx512_fma3p_213_f<0xAC, "vfnmadd213", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB213 : avx512_fma3p_213_f<0xAE, "vfnmsub213", X86Fnmsub, X86FnmsubRnd>; - - -multiclass avx512_fma3p_231_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, AVX512FMA3Base, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_231_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_231_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_231_rm, - avx512_fma3_231_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_231_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_231_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_231_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd > { - defm PS : avx512_fma3p_231_common; - defm PD : avx512_fma3p_231_common, - VEX_W; -} - -defm VFMADD231 : avx512_fma3p_231_f<0xB8, "vfmadd231", X86Fmadd, X86FmaddRnd>; -defm VFMSUB231 : avx512_fma3p_231_f<0xBA, "vfmsub231", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB231 : avx512_fma3p_231_f<0xB6, "vfmaddsub231", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD231 : avx512_fma3p_231_f<0xB7, "vfmsubadd231", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD231 : avx512_fma3p_231_f<0xBC, "vfnmadd231", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB231 : avx512_fma3p_231_f<0xBE, "vfnmsub231", X86Fnmsub, X86FnmsubRnd>; - -multiclass avx512_fma3p_132_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_132_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_132_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_132_rm, - avx512_fma3_132_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_132_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_132_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_132_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd > { - defm PS : avx512_fma3p_132_common; - defm PD : avx512_fma3p_132_common, - VEX_W; -} - -defm VFMADD132 : avx512_fma3p_132_f<0x98, "vfmadd132", X86Fmadd, X86FmaddRnd>; -defm VFMSUB132 : avx512_fma3p_132_f<0x9A, "vfmsub132", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB132 : avx512_fma3p_132_f<0x96, "vfmaddsub132", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD132 : avx512_fma3p_132_f<0x97, "vfmsubadd132", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD132 : avx512_fma3p_132_f<0x9C, "vfnmadd132", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB132 : avx512_fma3p_132_f<0x9E, "vfnmsub132", X86Fnmsub, X86FnmsubRnd>; - -// Scalar FMA -multiclass avx512_fma3s_common opc, string OpcodeStr, X86VectorVTInfo _, - dag RHS_r, dag RHS_m, dag RHS_b, bit MaskOnlyReg> { -let Constraints = "$src1 = $dst", hasSideEffects = 0 in { - defm r_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, Sched<[SchedWriteFMA.Scl]>; - - let mayLoad = 1 in - defm m_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, Sched<[SchedWriteFMA.Scl.Folded, ReadAfterLd]>; - - defm rb_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[SchedWriteFMA.Scl]>; - - let isCodeGenOnly = 1, isCommutable = 1 in { - def r : AVX512FMA3S, Sched<[SchedWriteFMA.Scl]>; - def m : AVX512FMA3S, Sched<[SchedWriteFMA.Scl.Folded, ReadAfterLd]>; - - def rb : AVX512FMA3S, EVEX_B, EVEX_RC, - Sched<[SchedWriteFMA.Scl]>; - }// isCodeGenOnly = 1 -}// Constraints = "$src1 = $dst" -} - -multiclass avx512_fma3s_all opc213, bits<8> opc231, bits<8> opc132, - string OpcodeStr, SDNode OpNode, SDNode OpNodeRnd, - X86VectorVTInfo _, string SUFF> { - let ExeDomain = _.ExeDomain in { - defm NAME#213#SUFF#Z: avx512_fma3s_common; - - defm NAME#231#SUFF#Z: avx512_fma3s_common; - - // One pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm NAME#132#SUFF#Z: avx512_fma3s_common; - } -} - -multiclass avx512_fma3s opc213, bits<8> opc231, bits<8> opc132, - string OpcodeStr, SDNode OpNode, SDNode OpNodeRnd> { - let Predicates = [HasAVX512] in { - defm NAME : avx512_fma3s_all, - EVEX_CD8<32, CD8VT1>, VEX_LIG; - defm NAME : avx512_fma3s_all, - EVEX_CD8<64, CD8VT1>, VEX_LIG, VEX_W; - } -} - -defm VFMADD : avx512_fma3s<0xA9, 0xB9, 0x99, "vfmadd", X86Fmadd, X86FmaddRnd>; -defm VFMSUB : avx512_fma3s<0xAB, 0xBB, 0x9B, "vfmsub", X86Fmsub, X86FmsubRnd>; -defm VFNMADD : avx512_fma3s<0xAD, 0xBD, 0x9D, "vfnmadd", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB : avx512_fma3s<0xAF, 0xBF, 0x9F, "vfnmsub", X86Fnmsub, X86FnmsubRnd>; - -multiclass avx512_scalar_fma_patterns { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3))))), - (!cast(Prefix#"213"#Suffix#"Zr_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zr_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)))))), - (!cast(Prefix#"213"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3), _.FRC:$src2))))), - (!cast(Prefix#"132"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zr_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3), _.FRC:$src2), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"132"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zr_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zr_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zr_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2, (_.ScalarLdFrag addr:$src3)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"132"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - // Patterns with rounding mode. - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - } -} - -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; - -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; - -//===----------------------------------------------------------------------===// -// AVX-512 Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit IFMA -//===----------------------------------------------------------------------===// -let Constraints = "$src1 = $dst" in { -multiclass avx512_pmadd52_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - // NOTE: The SDNode have the multiply operands first with the add last. - // This enables commuted load patterns to be autogenerated by tablegen. - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} -} // Constraints = "$src1 = $dst" - -multiclass avx512_pmadd52_common opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasIFMA] in { - defm Z : avx512_pmadd52_rm, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasIFMA] in { - defm Z256 : avx512_pmadd52_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_pmadd52_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -defm VPMADD52LUQ : avx512_pmadd52_common<0xb4, "vpmadd52luq", x86vpmadd52l, - SchedWriteVecIMul, avx512vl_i64_info>, - VEX_W; -defm VPMADD52HUQ : avx512_pmadd52_common<0xb5, "vpmadd52huq", x86vpmadd52h, - SchedWriteVecIMul, avx512vl_i64_info>, - VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 Scalar convert from sign integer to float/double -//===----------------------------------------------------------------------===// - -multiclass avx512_vcvtsi opc, SDNode OpNode, X86FoldableSchedWrite sched, - RegisterClass SrcRC, X86VectorVTInfo DstVT, - X86MemOperand x86memop, PatFrag ld_frag, string asm> { - let hasSideEffects = 0 in { - def rr : SI, - EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - def rm : SI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - } // hasSideEffects = 0 - let isCodeGenOnly = 1 in { - def rr_Int : SI, - EVEX_4V, Sched<[sched]>; - - def rm_Int : SI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - }//isCodeGenOnly = 1 -} - -multiclass avx512_vcvtsi_round opc, SDNode OpNode, - X86FoldableSchedWrite sched, RegisterClass SrcRC, - X86VectorVTInfo DstVT, string asm> { - def rrb_Int : SI, - EVEX_4V, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_vcvtsi_common opc, SDNode OpNode, - X86FoldableSchedWrite sched, - RegisterClass SrcRC, X86VectorVTInfo DstVT, - X86MemOperand x86memop, PatFrag ld_frag, string asm> { - defm NAME : avx512_vcvtsi_round, - avx512_vcvtsi, VEX_LIG; -} - -let Predicates = [HasAVX512] in { -defm VCVTSI2SSZ : avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SS, GR32, - v4f32x_info, i32mem, loadi32, "cvtsi2ss{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSI642SSZ: avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SS, GR64, - v4f32x_info, i64mem, loadi64, "cvtsi2ss{q}">, - XS, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTSI2SDZ : avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SD, GR32, - v2f64x_info, i32mem, loadi32, "cvtsi2sd{l}">, - XD, EVEX_CD8<32, CD8VT1>; -defm VCVTSI642SDZ: avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SD, GR64, - v2f64x_info, i64mem, loadi64, "cvtsi2sd{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -// def : InstAlias<"vcvtsi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", -// (VCVTSI2SSZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; -// def : InstAlias<"vcvtsi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", -// (VCVTSI2SDZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; - -def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f32 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; - -def : Pat<(f32 (sint_to_fp GR32:$src)), - (VCVTSI2SSZrr (f32 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f32 (sint_to_fp GR64:$src)), - (VCVTSI642SSZrr (f32 (IMPLICIT_DEF)), GR64:$src)>; -def : Pat<(f64 (sint_to_fp GR32:$src)), - (VCVTSI2SDZrr (f64 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f64 (sint_to_fp GR64:$src)), - (VCVTSI642SDZrr (f64 (IMPLICIT_DEF)), GR64:$src)>; - -defm VCVTUSI2SSZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SS, GR32, - v4f32x_info, i32mem, loadi32, - "cvtusi2ss{l}">, XS, EVEX_CD8<32, CD8VT1>; -defm VCVTUSI642SSZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SS, GR64, - v4f32x_info, i64mem, loadi64, "cvtusi2ss{q}">, - XS, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTUSI2SDZ : avx512_vcvtsi<0x7B, X86UintToFpRnd, WriteCvtI2SD, GR32, v2f64x_info, - i32mem, loadi32, "cvtusi2sd{l}">, - XD, VEX_LIG, EVEX_CD8<32, CD8VT1>; -defm VCVTUSI642SDZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SD, GR64, - v2f64x_info, i64mem, loadi64, "cvtusi2sd{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -// def : InstAlias<"vcvtusi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", -// (VCVTUSI2SSZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; -// def : InstAlias<"vcvtusi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", -// (VCVTUSI2SDZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; - -def : Pat<(f32 (uint_to_fp (loadi32 addr:$src))), - (VCVTUSI2SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f32 (uint_to_fp (loadi64 addr:$src))), - (VCVTUSI642SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (uint_to_fp (loadi32 addr:$src))), - (VCVTUSI2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (uint_to_fp (loadi64 addr:$src))), - (VCVTUSI642SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; - -def : Pat<(f32 (uint_to_fp GR32:$src)), - (VCVTUSI2SSZrr (f32 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f32 (uint_to_fp GR64:$src)), - (VCVTUSI642SSZrr (f32 (IMPLICIT_DEF)), GR64:$src)>; -def : Pat<(f64 (uint_to_fp GR32:$src)), - (VCVTUSI2SDZrr (f64 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f64 (uint_to_fp GR64:$src)), - (VCVTUSI642SDZrr (f64 (IMPLICIT_DEF)), GR64:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 Scalar convert from float/double to integer -//===----------------------------------------------------------------------===// - -multiclass avx512_cvt_s_int_round opc, X86VectorVTInfo SrcVT, - X86VectorVTInfo DstVT, SDNode OpNode, - X86FoldableSchedWrite sched, string asm, - string aliasStr, - bit CodeGenOnly = 1> { - let Predicates = [HasAVX512] in { - def rr_Int : SI, - EVEX, VEX_LIG, Sched<[sched]>; - def rrb_Int : SI, - EVEX, VEX_LIG, EVEX_B, EVEX_RC, - Sched<[sched]>; - let isCodeGenOnly = CodeGenOnly, ForceDisassemble = CodeGenOnly in - def rm_Int : SI, - EVEX, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - - // def : InstAlias<"v" # asm # aliasStr # "\t{$src, $dst|$dst, $src}", - // (!cast(NAME # "rr_Int") DstVT.RC:$dst, SrcVT.RC:$src), 0, "att">; - // def : InstAlias<"v" # asm # aliasStr # "\t{$rc, $src, $dst|$dst, $src, $rc}", - // (!cast(NAME # "rrb_Int") DstVT.RC:$dst, SrcVT.RC:$src, AVX512RC:$rc), 0, "att">; - } // Predicates = [HasAVX512] -} - -multiclass avx512_cvt_s_int_round_aliases opc, X86VectorVTInfo SrcVT, - X86VectorVTInfo DstVT, SDNode OpNode, - X86FoldableSchedWrite sched, string asm, - string aliasStr> : - avx512_cvt_s_int_round { - let Predicates = [HasAVX512] in { - // def : InstAlias<"v" # asm # aliasStr # "\t{$src, $dst|$dst, $src}", - // (!cast(NAME # "rm_Int") DstVT.RC:$dst, - // SrcVT.IntScalarMemOp:$src), 0, "att">; - } // Predicates = [HasAVX512] -} - -// Convert float/double to signed/unsigned int 32/64 -defm VCVTSS2SIZ: avx512_cvt_s_int_round<0x2D, f32x_info, i32x_info, - X86cvts2si, WriteCvtSS2I, "cvtss2si", "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2SI64Z: avx512_cvt_s_int_round<0x2D, f32x_info, i64x_info, - X86cvts2si, WriteCvtSS2I, "cvtss2si", "{q}">, - XS, VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2USIZ: avx512_cvt_s_int_round_aliases<0x79, f32x_info, i32x_info, - X86cvts2usi, WriteCvtSS2I, "cvtss2usi", "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2USI64Z: avx512_cvt_s_int_round_aliases<0x79, f32x_info, i64x_info, - X86cvts2usi, WriteCvtSS2I, "cvtss2usi", "{q}">, - XS, VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTSD2SIZ: avx512_cvt_s_int_round<0x2D, f64x_info, i32x_info, - X86cvts2si, WriteCvtSD2I, "cvtsd2si", "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2SI64Z: avx512_cvt_s_int_round<0x2D, f64x_info, i64x_info, - X86cvts2si, WriteCvtSD2I, "cvtsd2si", "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2USIZ: avx512_cvt_s_int_round_aliases<0x79, f64x_info, i32x_info, - X86cvts2usi, WriteCvtSD2I, "cvtsd2usi", "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2USI64Z: avx512_cvt_s_int_round_aliases<0x79, f64x_info, i64x_info, - X86cvts2usi, WriteCvtSD2I, "cvtsd2usi", "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -// The SSE version of these instructions are disabled for AVX512. -// Therefore, the SSE intrinsics are mapped to the AVX512 instructions. -let Predicates = [HasAVX512] in { - def : Pat<(i32 (int_x86_sse_cvtss2si (v4f32 VR128X:$src))), - (VCVTSS2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse_cvtss2si sse_load_f32:$src)), - (VCVTSS2SIZrm_Int sse_load_f32:$src)>; - def : Pat<(i64 (int_x86_sse_cvtss2si64 (v4f32 VR128X:$src))), - (VCVTSS2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse_cvtss2si64 sse_load_f32:$src)), - (VCVTSS2SI64Zrm_Int sse_load_f32:$src)>; - def : Pat<(i32 (int_x86_sse2_cvtsd2si (v2f64 VR128X:$src))), - (VCVTSD2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse2_cvtsd2si sse_load_f64:$src)), - (VCVTSD2SIZrm_Int sse_load_f64:$src)>; - def : Pat<(i64 (int_x86_sse2_cvtsd2si64 (v2f64 VR128X:$src))), - (VCVTSD2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse2_cvtsd2si64 sse_load_f64:$src)), - (VCVTSD2SI64Zrm_Int sse_load_f64:$src)>; -} // HasAVX512 - -// Patterns used for matching vcvtsi2s{s,d} intrinsic sequences from clang -// which produce unnecessary vmovs{s,d} instructions -let Predicates = [HasAVX512] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (VCVTSI642SSZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (VCVTSI2SSZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (VCVTSI642SDZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (VCVTSI2SDZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp GR64:$src)))))), - (VCVTUSI642SSZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp (loadi64 addr:$src))))))), - (VCVTUSI642SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp GR32:$src)))))), - (VCVTUSI2SSZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp (loadi32 addr:$src))))))), - (VCVTUSI2SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp GR64:$src)))))), - (VCVTUSI642SDZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp (loadi64 addr:$src))))))), - (VCVTUSI642SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp GR32:$src)))))), - (VCVTUSI2SDZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp (loadi32 addr:$src))))))), - (VCVTUSI2SDZrm_Int VR128X:$dst, addr:$src)>; -} // Predicates = [HasAVX512] - -// Convert float/double to signed/unsigned int 32/64 with truncation -multiclass avx512_cvt_s_all opc, string asm, X86VectorVTInfo _SrcRC, - X86VectorVTInfo _DstRC, SDNode OpNode, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - string aliasStr, bit CodeGenOnly = 1>{ -let Predicates = [HasAVX512] in { - let isCodeGenOnly = 1 in { - def rr : AVX512, - EVEX, Sched<[sched]>; - def rm : AVX512, - EVEX, Sched<[sched.Folded, ReadAfterLd]>; - } - - def rr_Int : AVX512, - EVEX, VEX_LIG, Sched<[sched]>; - def rrb_Int : AVX512, - EVEX,VEX_LIG , EVEX_B, Sched<[sched]>; - let isCodeGenOnly = CodeGenOnly, ForceDisassemble = CodeGenOnly in - def rm_Int : AVX512, - EVEX, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - - // def : InstAlias(NAME # "rr_Int") _DstRC.RC:$dst, _SrcRC.RC:$src), 0, "att">; - // def : InstAlias(NAME # "rrb_Int") _DstRC.RC:$dst, _SrcRC.RC:$src), 0, "att">; -} //HasAVX512 -} - -multiclass avx512_cvt_s_all_unsigned opc, string asm, - X86VectorVTInfo _SrcRC, - X86VectorVTInfo _DstRC, SDNode OpNode, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - string aliasStr> : - avx512_cvt_s_all { -let Predicates = [HasAVX512] in { - // def : InstAlias(NAME # "rm_Int") _DstRC.RC:$dst, - // _SrcRC.IntScalarMemOp:$src), 0, "att">; -} -} - -defm VCVTTSS2SIZ: avx512_cvt_s_all<0x2C, "vcvttss2si", f32x_info, i32x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSS2I, "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSS2SI64Z: avx512_cvt_s_all<0x2C, "vcvttss2si", f32x_info, i64x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSS2I, "{q}">, - VEX_W, XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSD2SIZ: avx512_cvt_s_all<0x2C, "vcvttsd2si", f64x_info, i32x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSD2I, "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTTSD2SI64Z: avx512_cvt_s_all<0x2C, "vcvttsd2si", f64x_info, i64x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSD2I, "{q}">, - VEX_W, XD, EVEX_CD8<64, CD8VT1>; - -defm VCVTTSS2USIZ: avx512_cvt_s_all_unsigned<0x78, "vcvttss2usi", f32x_info, i32x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSS2I, "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSS2USI64Z: avx512_cvt_s_all_unsigned<0x78, "vcvttss2usi", f32x_info, i64x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSS2I, "{q}">, - XS,VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTTSD2USIZ: avx512_cvt_s_all_unsigned<0x78, "vcvttsd2usi", f64x_info, i32x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSD2I, "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTTSD2USI64Z: avx512_cvt_s_all_unsigned<0x78, "vcvttsd2usi", f64x_info, i64x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSD2I, "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -let Predicates = [HasAVX512] in { - def : Pat<(i32 (int_x86_sse_cvttss2si (v4f32 VR128X:$src))), - (VCVTTSS2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse_cvttss2si sse_load_f32:$src)), - (VCVTTSS2SIZrm_Int ssmem:$src)>; - def : Pat<(i64 (int_x86_sse_cvttss2si64 (v4f32 VR128X:$src))), - (VCVTTSS2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse_cvttss2si64 sse_load_f32:$src)), - (VCVTTSS2SI64Zrm_Int ssmem:$src)>; - def : Pat<(i32 (int_x86_sse2_cvttsd2si (v2f64 VR128X:$src))), - (VCVTTSD2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse2_cvttsd2si sse_load_f64:$src)), - (VCVTTSD2SIZrm_Int sdmem:$src)>; - def : Pat<(i64 (int_x86_sse2_cvttsd2si64 (v2f64 VR128X:$src))), - (VCVTTSD2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse2_cvttsd2si64 sse_load_f64:$src)), - (VCVTTSD2SI64Zrm_Int sdmem:$src)>; -} // HasAVX512 - -//===----------------------------------------------------------------------===// -// AVX-512 Convert form float to double and back -//===----------------------------------------------------------------------===// - -multiclass avx512_cvt_fp_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNode, - X86FoldableSchedWrite sched> { - defm rr_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, Sched<[sched]>; - defm rm_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr : I, - EVEX_4V, VEX_LIG, Sched<[sched]>; - let mayLoad = 1 in - def rm : I, - EVEX_4V, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -// Scalar Conversion with SAE - suppress all exceptions -multiclass avx512_cvt_fp_sae_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, EVEX_B, Sched<[sched]>; -} - -// Scalar Conversion with rounding control (RC) -multiclass avx512_cvt_fp_rc_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, Sched<[sched]>, - EVEX_B, EVEX_RC; -} -multiclass avx512_cvt_fp_scalar_sd2ss opc, string OpcodeStr, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - X86VectorVTInfo _src, X86VectorVTInfo _dst> { - let Predicates = [HasAVX512] in { - defm Z : avx512_cvt_fp_scalar, - avx512_cvt_fp_rc_scalar, VEX_W, EVEX_CD8<64, CD8VT1>, XD; - } -} - -multiclass avx512_cvt_fp_scalar_ss2sd opc, string OpcodeStr, SDNode OpNodeRnd, - X86FoldableSchedWrite sched, - X86VectorVTInfo _src, X86VectorVTInfo _dst> { - let Predicates = [HasAVX512] in { - defm Z : avx512_cvt_fp_scalar, - avx512_cvt_fp_sae_scalar, - EVEX_CD8<32, CD8VT1>, XS; - } -} -defm VCVTSD2SS : avx512_cvt_fp_scalar_sd2ss<0x5A, "vcvtsd2ss", - X86froundRnd, WriteCvtSD2SS, f64x_info, - f32x_info>; -defm VCVTSS2SD : avx512_cvt_fp_scalar_ss2sd<0x5A, "vcvtss2sd", - X86fpextRnd, WriteCvtSS2SD, f32x_info, - f64x_info>; - -def : Pat<(f64 (fpextend FR32X:$src)), - (VCVTSS2SDZrr (f64 (IMPLICIT_DEF)), FR32X:$src)>, - Requires<[HasAVX512]>; -def : Pat<(f64 (fpextend (loadf32 addr:$src))), - (VCVTSS2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[HasAVX512, OptForSize]>; - -def : Pat<(f64 (extloadf32 addr:$src)), - (VCVTSS2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[HasAVX512, OptForSize]>; - -def : Pat<(f64 (extloadf32 addr:$src)), - (VCVTSS2SDZrr (f64 (IMPLICIT_DEF)), (VMOVSSZrm addr:$src))>, - Requires<[HasAVX512, OptForSpeed]>; - -def : Pat<(f32 (fpround FR64X:$src)), - (VCVTSD2SSZrr (f32 (IMPLICIT_DEF)), FR64X:$src)>, - Requires<[HasAVX512]>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128X:$src, (iPTR 0))))))))), - (VCVTSD2SSZrr_Int VR128X:$dst, VR128X:$src)>, - Requires<[HasAVX512]>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128X:$src, (iPTR 0))))))))), - (VCVTSS2SDZrr_Int VR128X:$dst, VR128X:$src)>, - Requires<[HasAVX512]>; - -//===----------------------------------------------------------------------===// -// AVX-512 Vector convert from signed/unsigned integer to float/double -// and from float/double to signed/unsigned integer -//===----------------------------------------------------------------------===// - -multiclass avx512_vcvt_fp opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNode, - X86FoldableSchedWrite sched, - string Broadcast = _.BroadcastStr, - string Alias = "", X86MemOperand MemOp = _Src.MemOp> { - - defm rr : AVX512_maskable, - EVEX, Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, Sched<[sched.Folded]>; - - defm rmb : AVX512_maskable, EVEX, EVEX_B, - Sched<[sched.Folded]>; -} -// Conversion with SAE - suppress all exceptions -multiclass avx512_vcvt_fp_sae opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb : AVX512_maskable, - EVEX, EVEX_B, Sched<[sched]>; -} - -// Conversion with rounding control (RC) -multiclass avx512_vcvt_fp_rc opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb : AVX512_maskable, - EVEX, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -// Extend Float to Double -multiclass avx512_cvtps2pd opc, string OpcodeStr, - X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Truncate Double to Float -multiclass avx512_cvtpd2ps opc, string OpcodeStr, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - // def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - // def : InstAlias(NAME # "Z128rm") VR128X:$dst, f128mem:$src), 0, "intel">; - // def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - // def : InstAlias(NAME # "Z256rm") VR128X:$dst, f256mem:$src), 0, "intel">; - } -} - -defm VCVTPD2PS : avx512_cvtpd2ps<0x5A, "vcvtpd2ps", SchedWriteCvtPD2PS>, - VEX_W, PD, EVEX_CD8<64, CD8VF>; -defm VCVTPS2PD : avx512_cvtps2pd<0x5A, "vcvtps2pd", SchedWriteCvtPS2PD>, - PS, EVEX_CD8<32, CD8VH>; - -def : Pat<(v8f64 (extloadv8f32 addr:$src)), - (VCVTPS2PDZrm addr:$src)>; - -let Predicates = [HasVLX] in { - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128X:$src)))))), - (VCVTPD2PSZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (loadv2f64 addr:$src)))))), - (VCVTPD2PSZ128rm addr:$src)>; - def : Pat<(v2f64 (extloadv2f32 addr:$src)), - (VCVTPS2PDZ128rm addr:$src)>; - def : Pat<(v4f64 (extloadv4f32 addr:$src)), - (VCVTPS2PDZ256rm addr:$src)>; -} - -// Convert Signed/Unsigned Doubleword to Double -multiclass avx512_cvtdq2pd opc, string OpcodeStr, SDNode OpNode, - SDNode OpNode128, X86SchedWriteWidths sched> { - // No rounding in this op - let Predicates = [HasAVX512] in - defm Z : avx512_vcvt_fp, EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Doubleword to Float -multiclass avx512_cvtdq2ps opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Doubleword with truncation -multiclass avx512_cvttps2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Doubleword -multiclass avx512_cvtps2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Double to Signed/Unsigned Doubleword with truncation -multiclass avx512_cvttpd2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parser. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - // def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - // def : InstAlias(NAME # "Z128rm") VR128X:$dst, i128mem:$src), 0, "intel">; - // def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - // def : InstAlias(NAME # "Z256rm") VR128X:$dst, i256mem:$src), 0, "intel">; - } -} - -// Convert Double to Signed/Unsigned Doubleword -multiclass avx512_cvtpd2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parcer. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - // def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - // def : InstAlias(NAME # "Z128rm") VR128X:$dst, f128mem:$src), 0, "intel">; - // def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - // def : InstAlias(NAME # "Z256rm") VR128X:$dst, f256mem:$src), 0, "intel">; - } -} - -// Convert Double to Signed/Unsigned Quardword -multiclass avx512_cvtpd2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Double to Signed/Unsigned Quardword with truncation -multiclass avx512_cvttpd2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Quardword to Double -multiclass avx512_cvtqq2pd opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128, NotEVEX2VEXConvertible; - defm Z256 : avx512_vcvt_fp, EVEX_V256, NotEVEX2VEXConvertible; - } -} - -// Convert Float to Signed/Unsigned Quardword -multiclass avx512_cvtps2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // Explicitly specified broadcast string, since we take only 2 elements - // from v4f32x_info source - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Quardword with truncation -multiclass avx512_cvttps2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // Explicitly specified broadcast string, since we take only 2 elements - // from v4f32x_info source - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Quardword to Float -multiclass avx512_cvtqq2ps opc, string OpcodeStr, SDNode OpNode, - SDNode OpNode128, SDNode OpNodeRnd, - X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parcer. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128, - NotEVEX2VEXConvertible; - defm Z256 : avx512_vcvt_fp, EVEX_V256, - NotEVEX2VEXConvertible; - - // def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - // def : InstAlias(NAME # "Z128rm") VR128X:$dst, i128mem:$src), 0, "intel">; - // def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - // def : InstAlias(NAME # "Z256rm") VR128X:$dst, i256mem:$src), 0, "intel">; - } -} - -defm VCVTDQ2PD : avx512_cvtdq2pd<0xE6, "vcvtdq2pd", sint_to_fp, X86VSintToFP, - SchedWriteCvtDQ2PD>, XS, EVEX_CD8<32, CD8VH>; - -defm VCVTDQ2PS : avx512_cvtdq2ps<0x5B, "vcvtdq2ps", sint_to_fp, - X86VSintToFpRnd, SchedWriteCvtDQ2PS>, - PS, EVEX_CD8<32, CD8VF>; - -defm VCVTTPS2DQ : avx512_cvttps2dq<0x5B, "vcvttps2dq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPS2DQ>, - XS, EVEX_CD8<32, CD8VF>; - -defm VCVTTPD2DQ : avx512_cvttpd2dq<0xE6, "vcvttpd2dq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPD2DQ>, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2UDQ : avx512_cvttps2dq<0x78, "vcvttps2udq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPS2DQ>, PS, - EVEX_CD8<32, CD8VF>; - -defm VCVTTPD2UDQ : avx512_cvttpd2dq<0x78, "vcvttpd2udq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPD2DQ>, - PS, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTUDQ2PD : avx512_cvtdq2pd<0x7A, "vcvtudq2pd", uint_to_fp, - X86VUintToFP, SchedWriteCvtDQ2PD>, XS, - EVEX_CD8<32, CD8VH>; - -defm VCVTUDQ2PS : avx512_cvtdq2ps<0x7A, "vcvtudq2ps", uint_to_fp, - X86VUintToFpRnd, SchedWriteCvtDQ2PS>, XD, - EVEX_CD8<32, CD8VF>; - -defm VCVTPS2DQ : avx512_cvtps2dq<0x5B, "vcvtps2dq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VF>; - -defm VCVTPD2DQ : avx512_cvtpd2dq<0xE6, "vcvtpd2dq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPD2DQ>, XD, - VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2UDQ : avx512_cvtps2dq<0x79, "vcvtps2udq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPS2DQ>, - PS, EVEX_CD8<32, CD8VF>; - -defm VCVTPD2UDQ : avx512_cvtpd2dq<0x79, "vcvtpd2udq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PS, EVEX_CD8<64, CD8VF>; - -defm VCVTPD2QQ : avx512_cvtpd2qq<0x7B, "vcvtpd2qq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2QQ : avx512_cvtps2qq<0x7B, "vcvtps2qq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTPD2UQQ : avx512_cvtpd2qq<0x79, "vcvtpd2uqq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2UQQ : avx512_cvtps2qq<0x79, "vcvtps2uqq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTTPD2QQ : avx512_cvttpd2qq<0x7A, "vcvttpd2qq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2QQ : avx512_cvttps2qq<0x7A, "vcvttps2qq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTTPD2UQQ : avx512_cvttpd2qq<0x78, "vcvttpd2uqq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2UQQ : avx512_cvttps2qq<0x78, "vcvttps2uqq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTQQ2PD : avx512_cvtqq2pd<0xE6, "vcvtqq2pd", sint_to_fp, - X86VSintToFpRnd, SchedWriteCvtDQ2PD>, VEX_W, XS, - EVEX_CD8<64, CD8VF>; - -defm VCVTUQQ2PD : avx512_cvtqq2pd<0x7A, "vcvtuqq2pd", uint_to_fp, - X86VUintToFpRnd, SchedWriteCvtDQ2PD>, VEX_W, XS, - EVEX_CD8<64, CD8VF>; - -defm VCVTQQ2PS : avx512_cvtqq2ps<0x5B, "vcvtqq2ps", sint_to_fp, X86VSintToFP, - X86VSintToFpRnd, SchedWriteCvtDQ2PS>, VEX_W, PS, - EVEX_CD8<64, CD8VF>; - -defm VCVTUQQ2PS : avx512_cvtqq2ps<0x7A, "vcvtuqq2ps", uint_to_fp, X86VUintToFP, - X86VUintToFpRnd, SchedWriteCvtDQ2PS>, VEX_W, XD, - EVEX_CD8<64, CD8VF>; - -let Predicates = [HasAVX512] in { - def : Pat<(v16i32 (fp_to_sint (v16f32 VR512:$src))), - (VCVTTPS2DQZrr VR512:$src)>; - def : Pat<(v16i32 (fp_to_sint (loadv16f32 addr:$src))), - (VCVTTPS2DQZrm addr:$src)>; - - def : Pat<(v16i32 (fp_to_uint (v16f32 VR512:$src))), - (VCVTTPS2UDQZrr VR512:$src)>; - def : Pat<(v16i32 (fp_to_uint (loadv16f32 addr:$src))), - (VCVTTPS2UDQZrm addr:$src)>; - - def : Pat<(v8i32 (fp_to_sint (v8f64 VR512:$src))), - (VCVTTPD2DQZrr VR512:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f64 addr:$src))), - (VCVTTPD2DQZrm addr:$src)>; - - def : Pat<(v8i32 (fp_to_uint (v8f64 VR512:$src))), - (VCVTTPD2UDQZrr VR512:$src)>; - def : Pat<(v8i32 (fp_to_uint (loadv8f64 addr:$src))), - (VCVTTPD2UDQZrm addr:$src)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128X:$src))), - (VCVTTPS2DQZ128rr VR128X:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2DQZ128rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_uint (v4f32 VR128X:$src))), - (VCVTTPS2UDQZ128rr VR128X:$src)>; - def : Pat<(v4i32 (fp_to_uint (loadv4f32 addr:$src))), - (VCVTTPS2UDQZ128rm addr:$src)>; - - def : Pat<(v8i32 (fp_to_sint (v8f32 VR256X:$src))), - (VCVTTPS2DQZ256rr VR256X:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2DQZ256rm addr:$src)>; - - def : Pat<(v8i32 (fp_to_uint (v8f32 VR256X:$src))), - (VCVTTPS2UDQZ256rr VR256X:$src)>; - def : Pat<(v8i32 (fp_to_uint (loadv8f32 addr:$src))), - (VCVTTPS2UDQZ256rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_sint (v4f64 VR256X:$src))), - (VCVTTPD2DQZ256rr VR256X:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2DQZ256rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_uint (v4f64 VR256X:$src))), - (VCVTTPD2UDQZ256rr VR256X:$src)>; - def : Pat<(v4i32 (fp_to_uint (loadv4f64 addr:$src))), - (VCVTTPD2UDQZ256rm addr:$src)>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v8i64 (fp_to_sint (v8f32 VR256X:$src))), - (VCVTTPS2QQZrr VR256X:$src)>; - def : Pat<(v8i64 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2QQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_uint (v8f32 VR256X:$src))), - (VCVTTPS2UQQZrr VR256X:$src)>; - def : Pat<(v8i64 (fp_to_uint (loadv8f32 addr:$src))), - (VCVTTPS2UQQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_sint (v8f64 VR512:$src))), - (VCVTTPD2QQZrr VR512:$src)>; - def : Pat<(v8i64 (fp_to_sint (loadv8f64 addr:$src))), - (VCVTTPD2QQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_uint (v8f64 VR512:$src))), - (VCVTTPD2UQQZrr VR512:$src)>; - def : Pat<(v8i64 (fp_to_uint (loadv8f64 addr:$src))), - (VCVTTPD2UQQZrm addr:$src)>; -} - -let Predicates = [HasDQI, HasVLX] in { - def : Pat<(v4i64 (fp_to_sint (v4f32 VR128X:$src))), - (VCVTTPS2QQZ256rr VR128X:$src)>; - def : Pat<(v4i64 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2QQZ256rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_uint (v4f32 VR128X:$src))), - (VCVTTPS2UQQZ256rr VR128X:$src)>; - def : Pat<(v4i64 (fp_to_uint (loadv4f32 addr:$src))), - (VCVTTPS2UQQZ256rm addr:$src)>; - - def : Pat<(v2i64 (fp_to_sint (v2f64 VR128X:$src))), - (VCVTTPD2QQZ128rr VR128X:$src)>; - def : Pat<(v2i64 (fp_to_sint (loadv2f64 addr:$src))), - (VCVTTPD2QQZ128rm addr:$src)>; - - def : Pat<(v2i64 (fp_to_uint (v2f64 VR128X:$src))), - (VCVTTPD2UQQZ128rr VR128X:$src)>; - def : Pat<(v2i64 (fp_to_uint (loadv2f64 addr:$src))), - (VCVTTPD2UQQZ128rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_sint (v4f64 VR256X:$src))), - (VCVTTPD2QQZ256rr VR256X:$src)>; - def : Pat<(v4i64 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2QQZ256rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_uint (v4f64 VR256X:$src))), - (VCVTTPD2UQQZ256rr VR256X:$src)>; - def : Pat<(v4i64 (fp_to_uint (loadv4f64 addr:$src))), - (VCVTTPD2UQQZ256rm addr:$src)>; -} - -let Predicates = [HasAVX512, NoVLX] in { -def : Pat<(v8i32 (fp_to_uint (v8f32 VR256X:$src1))), - (EXTRACT_SUBREG (v16i32 (VCVTTPS2UDQZrr - (v16f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4i32 (fp_to_uint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v16i32 (VCVTTPS2UDQZrr - (v16f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i32 (fp_to_uint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i32 (VCVTTPD2UDQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v8f32 (uint_to_fp (v8i32 VR256X:$src1))), - (EXTRACT_SUBREG (v16f32 (VCVTUDQ2PSZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (uint_to_fp (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v16f32 (VCVTUDQ2PSZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (uint_to_fp (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUDQ2PDZrr - (v8i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v2f64 (X86VUintToFP (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUDQ2PDZrr - (v8i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; -} - -let Predicates = [HasAVX512, HasVLX] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128X:$src)))))), - (VCVTPD2DQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src)))))), - (VCVTPD2DQZ128rm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2UInt (v2f64 VR128X:$src)))))), - (VCVTPD2UDQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128X:$src)))))), - (VCVTTPD2DQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (loadv2f64 addr:$src)))))), - (VCVTTPD2DQZ128rm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2ui (v2f64 VR128X:$src)))))), - (VCVTTPD2UDQZ128rr VR128X:$src)>; - - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTDQ2PDZ128rm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTDQ2PDZ128rm addr:$src)>; - - def : Pat<(v2f64 (X86VUintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTUDQ2PDZ128rm addr:$src)>; - def : Pat<(v2f64 (X86VUintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTUDQ2PDZ128rm addr:$src)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v8f32 (fpround (loadv8f64 addr:$src))), - (VCVTPD2PSZrm addr:$src)>; - def : Pat<(v8f64 (extloadv8f32 addr:$src)), - (VCVTPS2PDZrm addr:$src)>; -} - -let Predicates = [HasDQI, HasVLX] in { - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86VSintToFP (v2i64 VR128X:$src)))))), - (VCVTQQ2PSZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86VUintToFP (v2i64 VR128X:$src)))))), - (VCVTUQQ2PSZ128rr VR128X:$src)>; -} - -let Predicates = [HasDQI, NoVLX] in { -def : Pat<(v2i64 (fp_to_sint (v2f64 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2QQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i64 (fp_to_sint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPS2QQZrr - (v8f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v4i64 (fp_to_sint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2QQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v2i64 (fp_to_uint (v2f64 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2UQQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i64 (fp_to_uint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPS2UQQZrr - (v8f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v4i64 (fp_to_uint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2UQQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (sint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f32 (VCVTQQ2PSZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v2f64 (sint_to_fp (v2i64 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (sint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (uint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f32 (VCVTUQQ2PSZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v2f64 (uint_to_fp (v2i64 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (uint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; -} - -//===----------------------------------------------------------------------===// -// Half precision conversion instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_cvtph2ps { - defm rr : AVX512_maskable<0x13, MRMSrcReg, _dest ,(outs _dest.RC:$dst), - (ins _src.RC:$src), "vcvtph2ps", "$src", "$src", - (X86cvtph2ps (_src.VT _src.RC:$src))>, - T8PD, Sched<[sched]>; - defm rm : AVX512_maskable<0x13, MRMSrcMem, _dest, (outs _dest.RC:$dst), - (ins x86memop:$src), "vcvtph2ps", "$src", "$src", - (X86cvtph2ps (_src.VT - (bitconvert - (ld_frag addr:$src))))>, - T8PD, Sched<[sched.Folded]>; -} - -multiclass avx512_cvtph2ps_sae { - defm rrb : AVX512_maskable<0x13, MRMSrcReg, _dest, (outs _dest.RC:$dst), - (ins _src.RC:$src), "vcvtph2ps", - "{sae}, $src", "$src, {sae}", - (X86cvtph2psRnd (_src.VT _src.RC:$src), - (i32 FROUND_NO_EXC))>, - T8PD, EVEX_B, Sched<[sched]>; -} - -let Predicates = [HasAVX512] in - defm VCVTPH2PSZ : avx512_cvtph2ps, - avx512_cvtph2ps_sae, - EVEX, EVEX_V512, EVEX_CD8<32, CD8VH>; - -let Predicates = [HasVLX] in { - defm VCVTPH2PSZ256 : avx512_cvtph2ps, EVEX, EVEX_V256, - EVEX_CD8<32, CD8VH>; - defm VCVTPH2PSZ128 : avx512_cvtph2ps, EVEX, EVEX_V128, - EVEX_CD8<32, CD8VH>; - - // Pattern match vcvtph2ps of a scalar i64 load. - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzmovl_v2i64 addr:$src)))), - (VCVTPH2PSZ128rm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzload_v2i64 addr:$src)))), - (VCVTPH2PSZ128rm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (bitconvert - (v2i64 (scalar_to_vector (loadi64 addr:$src))))))), - (VCVTPH2PSZ128rm addr:$src)>; -} - -multiclass avx512_cvtps2ph { - defm rr : AVX512_maskable<0x1D, MRMDestReg, _dest ,(outs _dest.RC:$dst), - (ins _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph", "$src2, $src1", "$src1, $src2", - (X86cvtps2ph (_src.VT _src.RC:$src1), - (i32 imm:$src2)), 0, 0>, - AVX512AIi8Base, Sched<[RR]>; - let hasSideEffects = 0, mayStore = 1 in { - def mr : AVX512AIi8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[MR]>; - def mrk : AVX512AIi8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, _dest.KRCWM:$mask, _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst {${mask}}|$dst {${mask}}, $src1, $src2}", []>, - EVEX_K, Sched<[MR]>, NotMemoryFoldable; - } -} - -multiclass avx512_cvtps2ph_sae { - let hasSideEffects = 0 in - defm rrb : AVX512_maskable_in_asm<0x1D, MRMDestReg, _dest, - (outs _dest.RC:$dst), - (ins _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph", "$src2, {sae}, $src1", "$src1, {sae}, $src2", []>, - EVEX_B, AVX512AIi8Base, Sched<[Sched]>; -} - -let Predicates = [HasAVX512] in { - defm VCVTPS2PHZ : avx512_cvtps2ph, - avx512_cvtps2ph_sae, - EVEX, EVEX_V512, EVEX_CD8<32, CD8VH>; - let Predicates = [HasVLX] in { - defm VCVTPS2PHZ256 : avx512_cvtps2ph, - EVEX, EVEX_V256, EVEX_CD8<32, CD8VH>; - defm VCVTPS2PHZ128 : avx512_cvtps2ph, - EVEX, EVEX_V128, EVEX_CD8<32, CD8VH>; - } - - def : Pat<(store (f64 (extractelt - (bc_v2f64 (v8i16 (X86cvtps2ph VR128X:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHZ128mr addr:$dst, VR128X:$src1, imm:$src2)>; - def : Pat<(store (i64 (extractelt - (bc_v2i64 (v8i16 (X86cvtps2ph VR128X:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHZ128mr addr:$dst, VR128X:$src1, imm:$src2)>; - def : Pat<(store (v8i16 (X86cvtps2ph VR256X:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHZ256mr addr:$dst, VR256X:$src1, imm:$src2)>; - def : Pat<(store (v16i16 (X86cvtps2ph VR512:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHZmr addr:$dst, VR512:$src1, imm:$src2)>; -} - -// Patterns for matching conversions from float to half-float and vice versa. -let Predicates = [HasVLX] in { - // Use MXCSR.RC for rounding instead of explicitly specifying the default - // rounding mode (Nearest-Even, encoded as 0). Both are equivalent in the - // configurations we support (the default). However, falling back to MXCSR is - // more consistent with other instructions, which are always controlled by it. - // It's encoded as 0b100. - def : Pat<(fp_to_f16 FR32X:$src), - (i16 (EXTRACT_SUBREG (VMOVPDI2DIZrr (v8i16 (VCVTPS2PHZ128rr - (v4f32 (COPY_TO_REGCLASS FR32X:$src, VR128X)), 4))), sub_16bit))>; - - def : Pat<(f16_to_fp GR16:$src), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSZ128rr - (v8i16 (COPY_TO_REGCLASS (MOVSX32rr16 GR16:$src), VR128X)))), FR32X)) >; - - def : Pat<(f16_to_fp (i16 (fp_to_f16 FR32X:$src))), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSZ128rr - (v8i16 (VCVTPS2PHZ128rr - (v4f32 (COPY_TO_REGCLASS FR32X:$src, VR128X)), 4)))), FR32X)) >; -} - -// Unordered/Ordered scalar fp compare with Sea and set EFLAGS -multiclass avx512_ord_cmp_sae opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def rrb: AVX512, - EVEX, EVEX_B, VEX_LIG, EVEX_V128, Sched<[sched]>; -} - -let Defs = [EFLAGS], Predicates = [HasAVX512] in { - defm VUCOMISSZ : avx512_ord_cmp_sae<0x2E, v4f32x_info, "vucomiss", WriteFCom>, - AVX512PSIi8Base, EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : avx512_ord_cmp_sae<0x2E, v2f64x_info, "vucomisd", WriteFCom>, - AVX512PDIi8Base, VEX_W, EVEX_CD8<64, CD8VT1>; - defm VCOMISSZ : avx512_ord_cmp_sae<0x2F, v4f32x_info, "vcomiss", WriteFCom>, - AVX512PSIi8Base, EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : avx512_ord_cmp_sae<0x2F, v2f64x_info, "vcomisd", WriteFCom>, - AVX512PDIi8Base, VEX_W, EVEX_CD8<64, CD8VT1>; -} - -let Defs = [EFLAGS], Predicates = [HasAVX512] in { - defm VUCOMISSZ : sse12_ord_cmp<0x2E, FR32X, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : sse12_ord_cmp<0x2E, FR64X, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - let Pattern = [] in { - defm VCOMISSZ : sse12_ord_cmp<0x2F, FR32X, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : sse12_ord_cmp<0x2F, FR64X, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - } - let isCodeGenOnly = 1 in { - defm VUCOMISSZ : sse12_ord_cmp_int<0x2E, VR128X, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : sse12_ord_cmp_int<0x2E, VR128X, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - - defm VCOMISSZ : sse12_ord_cmp_int<0x2F, VR128X, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : sse12_ord_cmp_int<0x2F, VR128X, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - } -} - -/// avx512_fp14_s rcp14ss, rcp14sd, rsqrt14ss, rsqrt14sd -multiclass avx512_fp14_s opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let Predicates = [HasAVX512], ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable_scalar, - EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable_scalar, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -defm VRCP14SSZ : avx512_fp14_s<0x4D, "vrcp14ss", X86rcp14s, SchedWriteFRcp.Scl, - f32x_info>, EVEX_CD8<32, CD8VT1>, - T8PD; -defm VRCP14SDZ : avx512_fp14_s<0x4D, "vrcp14sd", X86rcp14s, SchedWriteFRcp.Scl, - f64x_info>, VEX_W, EVEX_CD8<64, CD8VT1>, - T8PD; -defm VRSQRT14SSZ : avx512_fp14_s<0x4F, "vrsqrt14ss", X86rsqrt14s, - SchedWriteFRsqrt.Scl, f32x_info>, - EVEX_CD8<32, CD8VT1>, T8PD; -defm VRSQRT14SDZ : avx512_fp14_s<0x4F, "vrsqrt14sd", X86rsqrt14s, - SchedWriteFRsqrt.Scl, f64x_info>, VEX_W, - EVEX_CD8<64, CD8VT1>, T8PD; - -/// avx512_fp14_p rcp14ps, rcp14pd, rsqrt14ps, rsqrt14pd -multiclass avx512_fp14_p opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable, EVEX, T8PD, - Sched<[sched]>; - defm m: AVX512_maskable, EVEX, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb: AVX512_maskable, - EVEX, T8PD, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp14_p_vl_all opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp14_p, EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp14_p, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; - - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp14_p, - EVEX_V128, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp14_p, - EVEX_V256, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp14_p, - EVEX_V128, VEX_W, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp14_p, - EVEX_V256, VEX_W, EVEX_CD8<64, CD8VF>; - } -} - -defm VRSQRT14 : avx512_fp14_p_vl_all<0x4E, "vrsqrt14", X86rsqrt14, SchedWriteFRsqrt>; -defm VRCP14 : avx512_fp14_p_vl_all<0x4C, "vrcp14", X86rcp14, SchedWriteFRcp>; - -/// avx512_fp28_s rcp28ss, rcp28sd, rsqrt28ss, rsqrt28sd -multiclass avx512_fp28_s opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in { - defm r : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rb : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - - defm m : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_eri_s opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched> { - defm SSZ : avx512_fp28_s, - EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp28_s, - EVEX_CD8<64, CD8VT1>, VEX_W; -} - -let Predicates = [HasERI] in { - defm VRCP28 : avx512_eri_s<0xCB, "vrcp28", X86rcp28s, SchedWriteFRcp.Scl>, - T8PD, EVEX_4V; - defm VRSQRT28 : avx512_eri_s<0xCD, "vrsqrt28", X86rsqrt28s, - SchedWriteFRsqrt.Scl>, T8PD, EVEX_4V; -} - -defm VGETEXP : avx512_eri_s<0x43, "vgetexp", X86fgetexpRnds, - SchedWriteFRnd.Scl>, T8PD, EVEX_4V; -/// avx512_fp28_p rcp28ps, rcp28pd, rsqrt28ps, rsqrt28pd - -multiclass avx512_fp28_p opc, string OpcodeStr, X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in { - defm r : AVX512_maskable, - Sched<[sched]>; - - defm m : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - - defm mb : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} -multiclass avx512_fp28_p_round opc, string OpcodeStr, X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in - defm rb : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_eri opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp28_p, - avx512_fp28_p_round, - T8PD, EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp28_p, - avx512_fp28_p_round, - T8PD, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_fp_unaryop_packed opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp28_p, - EVEX_V128, T8PD, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp28_p, - EVEX_V256, T8PD, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp28_p, - EVEX_V128, VEX_W, T8PD, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp28_p, - EVEX_V256, VEX_W, T8PD, EVEX_CD8<64, CD8VF>; - } -} - -let Predicates = [HasERI] in { - defm VRSQRT28 : avx512_eri<0xCC, "vrsqrt28", X86rsqrt28, SchedWriteFRsqrt>, EVEX; - defm VRCP28 : avx512_eri<0xCA, "vrcp28", X86rcp28, SchedWriteFRcp>, EVEX; - defm VEXP2 : avx512_eri<0xC8, "vexp2", X86exp2, SchedWriteFAdd>, EVEX; -} -defm VGETEXP : avx512_eri<0x42, "vgetexp", X86fgetexpRnd, SchedWriteFRnd>, - avx512_fp_unaryop_packed<0x42, "vgetexp", X86fgetexpRnd, - SchedWriteFRnd>, EVEX; - -multiclass avx512_sqrt_packed_round opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in - defm rb: AVX512_maskable, - EVEX, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_sqrt_packed opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable, EVEX, - Sched<[sched]>; - defm m: AVX512_maskable, EVEX, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb: AVX512_maskable, - EVEX, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_sqrt_packed_all opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm PSZ : avx512_sqrt_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_sqrt_packed, - EVEX_V512, VEX_W, PD, EVEX_CD8<64, CD8VF>; - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_sqrt_packed, - EVEX_V128, PS, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_sqrt_packed, - EVEX_V256, PS, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_sqrt_packed, - EVEX_V128, VEX_W, PD, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_sqrt_packed, - EVEX_V256, VEX_W, PD, EVEX_CD8<64, CD8VF>; - } -} - -multiclass avx512_sqrt_packed_all_round opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm PSZ : avx512_sqrt_packed_round, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_sqrt_packed_round, - EVEX_V512, VEX_W, PD, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_sqrt_scalar opc, string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> { - let ExeDomain = _.ExeDomain in { - defm r_Int : AVX512_maskable_scalar, - Sched<[sched]>; - defm m_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - defm rb_Int : AVX512_maskable_scalar, - EVEX_B, EVEX_RC, Sched<[sched]>; - - let isCodeGenOnly = 1, hasSideEffects = 0, Predicates=[HasAVX512] in { - def r : I, - Sched<[sched]>; - let mayLoad = 1 in - def m : I, - Sched<[sched.Folded, ReadAfterLd]>; - } - } - - let Predicates = [HasAVX512] in { - def : Pat<(_.EltVT (fsqrt _.FRC:$src)), - (!cast(Name#Zr) - (_.EltVT (IMPLICIT_DEF)), _.FRC:$src)>; - } - - let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(_.EltVT (fsqrt (load addr:$src))), - (!cast(Name#Zm) - (_.EltVT (IMPLICIT_DEF)), addr:$src)>; - } -} - -multiclass avx512_sqrt_scalar_all opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm SSZ : avx512_sqrt_scalar, - EVEX_CD8<32, CD8VT1>, EVEX_4V, XS; - defm SDZ : avx512_sqrt_scalar, - EVEX_CD8<64, CD8VT1>, EVEX_4V, XD, VEX_W; -} - -defm VSQRT : avx512_sqrt_packed_all<0x51, "vsqrt", SchedWriteFSqrtSizes>, - avx512_sqrt_packed_all_round<0x51, "vsqrt", SchedWriteFSqrtSizes>; - -defm VSQRT : avx512_sqrt_scalar_all<0x51, "vsqrt", SchedWriteFSqrtSizes>, VEX_LIG; - -multiclass avx512_rndscale_scalar opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm r_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rb_Int : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - - defm m_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, hasSideEffects = 0, Predicates = [HasAVX512] in { - def r : I, Sched<[sched]>; - - let mayLoad = 1 in - def m : I, Sched<[sched.Folded, ReadAfterLd]>; - } - } - - let Predicates = [HasAVX512] in { - def : Pat<(ffloor _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0x9)))>; - def : Pat<(fceil _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xa)))>; - def : Pat<(ftrunc _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xb)))>; - def : Pat<(frint _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0x4)))>; - def : Pat<(fnearbyint _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xc)))>; - } - - let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(ffloor (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0x9)))>; - def : Pat<(fceil (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xa)))>; - def : Pat<(ftrunc (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xb)))>; - def : Pat<(frint (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0x4)))>; - def : Pat<(fnearbyint (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xc)))>; - } -} - -defm VRNDSCALESSZ : avx512_rndscale_scalar<0x0A, "vrndscaless", - SchedWriteFRnd.Scl, f32x_info>, - AVX512AIi8Base, EVEX_4V, - EVEX_CD8<32, CD8VT1>; - -defm VRNDSCALESDZ : avx512_rndscale_scalar<0x0B, "vrndscalesd", - SchedWriteFRnd.Scl, f64x_info>, - VEX_W, AVX512AIi8Base, EVEX_4V, - EVEX_CD8<64, CD8VT1>; - -multiclass avx512_masked_scalar { - let Predicates = [BasePredicate] in { - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects Mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - (extractelt _.VT:$dst, (iPTR 0))))), - (!cast("V"#OpcPrefix#r_Intk) - _.VT:$dst, OutMask, _.VT:$src2, _.VT:$src1)>; - - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects Mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - ZeroFP))), - (!cast("V"#OpcPrefix#r_Intkz) - OutMask, _.VT:$src2, _.VT:$src1)>; - } -} - -defm : avx512_masked_scalar; -defm : avx512_masked_scalar; - -multiclass avx512_masked_scalar_imm ImmV, Predicate BasePredicate> { - let Predicates = [BasePredicate] in { - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects VK1WM:$mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - (extractelt _.VT:$dst, (iPTR 0))))), - (!cast("V"#OpcPrefix#Zr_Intk) - _.VT:$dst, VK1WM:$mask, _.VT:$src1, _.VT:$src2, (i32 ImmV))>; - - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects VK1WM:$mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), ZeroFP))), - (!cast("V"#OpcPrefix#Zr_Intkz) - VK1WM:$mask, _.VT:$src1, _.VT:$src2, (i32 ImmV))>; - } -} - -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; - - -//------------------------------------------------- -// Integer truncate and extend operations -//------------------------------------------------- - -multiclass avx512_trunc_common opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo SrcInfo, - X86VectorVTInfo DestInfo, X86MemOperand x86memop> { - let ExeDomain = DestInfo.ExeDomain in - defm rr : AVX512_maskable, - EVEX, T8XS, Sched<[sched]>; - - let mayStore = 1, hasSideEffects = 0, ExeDomain = DestInfo.ExeDomain in { - def mr : AVX512XS8I, - EVEX, Sched<[sched.Folded]>; - - def mrk : AVX512XS8I, - EVEX, EVEX_K, Sched<[sched.Folded]>, NotMemoryFoldable; - }//mayStore = 1, hasSideEffects = 0 -} - -multiclass avx512_trunc_mr_lowering { - - def : Pat<(truncFrag (SrcInfo.VT SrcInfo.RC:$src), addr:$dst), - (!cast(Name#SrcInfo.ZSuffix##mr) - addr:$dst, SrcInfo.RC:$src)>; - - def : Pat<(mtruncFrag addr:$dst, SrcInfo.KRCWM:$mask, - (SrcInfo.VT SrcInfo.RC:$src)), - (!cast(Name#SrcInfo.ZSuffix##mrk) - addr:$dst, SrcInfo.KRCWM:$mask, SrcInfo.RC:$src)>; -} - -multiclass avx512_trunc opc, string OpcodeStr, SDNode OpNode128, - SDNode OpNode256, SDNode OpNode512, X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTSrcInfo, - X86VectorVTInfo DestInfoZ128, - X86VectorVTInfo DestInfoZ256, X86VectorVTInfo DestInfoZ, - X86MemOperand x86memopZ128, X86MemOperand x86memopZ256, - X86MemOperand x86memopZ, PatFrag truncFrag, - PatFrag mtruncFrag, Predicate prd = HasAVX512>{ - - let Predicates = [HasVLX, prd] in { - defm Z128: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V128; - - defm Z256: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V256; - } - let Predicates = [prd] in - defm Z: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V512; -} - -multiclass avx512_trunc_qb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<8, CD8VO>; -} - -multiclass avx512_trunc_qw opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VQ>; -} - -multiclass avx512_trunc_qd opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<32, CD8VH>; -} - -multiclass avx512_trunc_db opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<8, CD8VQ>; -} - -multiclass avx512_trunc_dw opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VH>; -} - -multiclass avx512_trunc_wb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VH>; -} - -defm VPMOVQB : avx512_trunc_qb<0x32, "vpmovqb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSQB : avx512_trunc_qb<0x22, "vpmovsqb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSQB : avx512_trunc_qb<0x12, "vpmovusqb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -defm VPMOVQW : avx512_trunc_qw<0x34, "vpmovqw", trunc, WriteShuffle256, - truncstorevi16, masked_truncstorevi16, X86vtrunc>; -defm VPMOVSQW : avx512_trunc_qw<0x24, "vpmovsqw", X86vtruncs, WriteShuffle256, - truncstore_s_vi16, masked_truncstore_s_vi16>; -defm VPMOVUSQW : avx512_trunc_qw<0x14, "vpmovusqw", X86vtruncus, WriteShuffle256, - truncstore_us_vi16, masked_truncstore_us_vi16>; - -defm VPMOVQD : avx512_trunc_qd<0x35, "vpmovqd", trunc, WriteShuffle256, - truncstorevi32, masked_truncstorevi32, X86vtrunc>; -defm VPMOVSQD : avx512_trunc_qd<0x25, "vpmovsqd", X86vtruncs, WriteShuffle256, - truncstore_s_vi32, masked_truncstore_s_vi32>; -defm VPMOVUSQD : avx512_trunc_qd<0x15, "vpmovusqd", X86vtruncus, WriteShuffle256, - truncstore_us_vi32, masked_truncstore_us_vi32>; - -defm VPMOVDB : avx512_trunc_db<0x31, "vpmovdb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSDB : avx512_trunc_db<0x21, "vpmovsdb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSDB : avx512_trunc_db<0x11, "vpmovusdb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -defm VPMOVDW : avx512_trunc_dw<0x33, "vpmovdw", trunc, WriteShuffle256, - truncstorevi16, masked_truncstorevi16, X86vtrunc>; -defm VPMOVSDW : avx512_trunc_dw<0x23, "vpmovsdw", X86vtruncs, WriteShuffle256, - truncstore_s_vi16, masked_truncstore_s_vi16>; -defm VPMOVUSDW : avx512_trunc_dw<0x13, "vpmovusdw", X86vtruncus, WriteShuffle256, - truncstore_us_vi16, masked_truncstore_us_vi16>; - -defm VPMOVWB : avx512_trunc_wb<0x30, "vpmovwb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSWB : avx512_trunc_wb<0x20, "vpmovswb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSWB : avx512_trunc_wb<0x10, "vpmovuswb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -let Predicates = [HasAVX512, NoVLX] in { -def: Pat<(v8i16 (trunc (v8i32 VR256X:$src))), - (v8i16 (EXTRACT_SUBREG - (v16i16 (VPMOVDWZrr (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm)))), sub_xmm))>; -def: Pat<(v4i32 (trunc (v4i64 VR256X:$src))), - (v4i32 (EXTRACT_SUBREG - (v8i32 (VPMOVQDZrr (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm)))), sub_xmm))>; -} - -let Predicates = [HasBWI, NoVLX] in { -def: Pat<(v16i8 (trunc (v16i16 VR256X:$src))), - (v16i8 (EXTRACT_SUBREG (VPMOVWBZrr (v32i16 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm))), sub_xmm))>; -} - -multiclass WriteShuffle256_common opc, string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo DestInfo, X86VectorVTInfo SrcInfo, - X86MemOperand x86memop, PatFrag LdFrag, SDNode OpNode>{ - let ExeDomain = DestInfo.ExeDomain in { - defm rr : AVX512_maskable, - EVEX, Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, Sched<[sched.Folded]>; - } -} - -multiclass WriteShuffle256_BW opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasBWI] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasBWI] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_BD opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_BQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_WD opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi16")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_WQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi16")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_DQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi32")> { - - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V128; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V256; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V512; - } -} - -defm VPMOVZXBW : WriteShuffle256_BW<0x30, "vpmovzxbw", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXBD : WriteShuffle256_BD<0x31, "vpmovzxbd", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXBQ : WriteShuffle256_BQ<0x32, "vpmovzxbq", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXWD : WriteShuffle256_WD<0x33, "vpmovzxwd", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXWQ : WriteShuffle256_WQ<0x34, "vpmovzxwq", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXDQ : WriteShuffle256_DQ<0x35, "vpmovzxdq", X86vzext, zext_invec, "z", WriteShuffle256>; - -defm VPMOVSXBW: WriteShuffle256_BW<0x20, "vpmovsxbw", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXBD: WriteShuffle256_BD<0x21, "vpmovsxbd", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXBQ: WriteShuffle256_BQ<0x22, "vpmovsxbq", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXWD: WriteShuffle256_WD<0x23, "vpmovsxwd", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXWQ: WriteShuffle256_WQ<0x24, "vpmovsxwq", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXDQ: WriteShuffle256_DQ<0x25, "vpmovsxdq", X86vsext, sext_invec, "s", WriteShuffle256>; - - -multiclass AVX512_pmovx_patterns { - // 128-bit patterns - let Predicates = [HasVLX, HasBWI] in { - def : Pat<(v8i16 (InVecOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (bc_v16i8 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - } - let Predicates = [HasVLX] in { - def : Pat<(v4i32 (InVecOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v16i8 (v4i32 (scalar_to_vector (extloadi32i16 addr:$src)))))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - - def : Pat<(v4i32 (InVecOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v8i16 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v8i16 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v8i16 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v4i32 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - } - // 256-bit patterns - let Predicates = [HasVLX, HasBWI] in { - def : Pat<(v16i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - } - let Predicates = [HasVLX] in { - def : Pat<(v8i32 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - - def : Pat<(v8i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - } - // 512-bit patterns - let Predicates = [HasBWI] in { - def : Pat<(v32i16 (ExtOp (bc_v32i8 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#BWZrm) addr:$src)>; - } - let Predicates = [HasAVX512] in { - def : Pat<(v16i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BQZrm) addr:$src)>; - def : Pat<(v8i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZrm) addr:$src)>; - - def : Pat<(v16i32 (ExtOp (bc_v16i16 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#WDZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v8i32 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#DQZrm) addr:$src)>; - } -} - -defm : AVX512_pmovx_patterns<"VPMOVSX", X86vsext, sext_invec>; -defm : AVX512_pmovx_patterns<"VPMOVZX", X86vzext, zext_invec>; - -//===----------------------------------------------------------------------===// -// GATHER - SCATTER Operations - -// FIXME: Improve scheduling of gather/scatter instructions. -multiclass avx512_gather opc, string OpcodeStr, X86VectorVTInfo _, - X86MemOperand memop, PatFrag GatherNode, - RegisterClass MaskRC = _.KRCWM> { - let Constraints = "@earlyclobber $dst, $src1 = $dst, $mask = $mask_wb", - ExeDomain = _.ExeDomain in - def rm : AVX5128I, EVEX, EVEX_K, - EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteLoad]>; -} - -multiclass avx512_gather_q_pd dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_gather, EVEX_V512, VEX_W; - defm NAME##Q##SUFF##Z: avx512_gather, EVEX_V512, VEX_W; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_gather, EVEX_V256, VEX_W; - defm NAME##Q##SUFF##Z256: avx512_gather, EVEX_V256, VEX_W; - defm NAME##D##SUFF##Z128: avx512_gather, EVEX_V128, VEX_W; - defm NAME##Q##SUFF##Z128: avx512_gather, EVEX_V128, VEX_W; -} -} - -multiclass avx512_gather_d_ps dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_gather, EVEX_V512; - defm NAME##Q##SUFF##Z: avx512_gather, EVEX_V512; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_gather, EVEX_V256; - defm NAME##Q##SUFF##Z256: avx512_gather, EVEX_V256; - defm NAME##D##SUFF##Z128: avx512_gather, EVEX_V128; - defm NAME##Q##SUFF##Z128: avx512_gather, - EVEX_V128; -} -} - - -defm VGATHER : avx512_gather_q_pd<0x92, 0x93, avx512vl_f64_info, "vgather", "PD">, - avx512_gather_d_ps<0x92, 0x93, avx512vl_f32_info, "vgather", "PS">; - -defm VPGATHER : avx512_gather_q_pd<0x90, 0x91, avx512vl_i64_info, "vpgather", "Q">, - avx512_gather_d_ps<0x90, 0x91, avx512vl_i32_info, "vpgather", "D">; - -multiclass avx512_scatter opc, string OpcodeStr, X86VectorVTInfo _, - X86MemOperand memop, PatFrag ScatterNode, - RegisterClass MaskRC = _.KRCWM> { - -let mayStore = 1, Constraints = "$mask = $mask_wb", ExeDomain = _.ExeDomain in - - def mr : AVX5128I, - EVEX, EVEX_K, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[WriteStore]>; -} - -multiclass avx512_scatter_q_pd dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_scatter, EVEX_V512, VEX_W; - defm NAME##Q##SUFF##Z: avx512_scatter, EVEX_V512, VEX_W; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_scatter, EVEX_V256, VEX_W; - defm NAME##Q##SUFF##Z256: avx512_scatter, EVEX_V256, VEX_W; - defm NAME##D##SUFF##Z128: avx512_scatter, EVEX_V128, VEX_W; - defm NAME##Q##SUFF##Z128: avx512_scatter, EVEX_V128, VEX_W; -} -} - -multiclass avx512_scatter_d_ps dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_scatter, EVEX_V512; - defm NAME##Q##SUFF##Z: avx512_scatter, EVEX_V512; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_scatter, EVEX_V256; - defm NAME##Q##SUFF##Z256: avx512_scatter, EVEX_V256; - defm NAME##D##SUFF##Z128: avx512_scatter, EVEX_V128; - defm NAME##Q##SUFF##Z128: avx512_scatter, - EVEX_V128; -} -} - -defm VSCATTER : avx512_scatter_q_pd<0xA2, 0xA3, avx512vl_f64_info, "vscatter", "PD">, - avx512_scatter_d_ps<0xA2, 0xA3, avx512vl_f32_info, "vscatter", "PS">; - -defm VPSCATTER : avx512_scatter_q_pd<0xA0, 0xA1, avx512vl_i64_info, "vpscatter", "Q">, - avx512_scatter_d_ps<0xA0, 0xA1, avx512vl_i32_info, "vpscatter", "D">; - -// prefetch -multiclass avx512_gather_scatter_prefetch opc, Format F, string OpcodeStr, - RegisterClass KRC, X86MemOperand memop> { - let Predicates = [HasPFI], mayLoad = 1, mayStore = 1 in - def m : AVX5128I, - EVEX, EVEX_K, Sched<[WriteLoad]>; -} - -defm VGATHERPF0DPS: avx512_gather_scatter_prefetch<0xC6, MRM1m, "vgatherpf0dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF0QPS: avx512_gather_scatter_prefetch<0xC7, MRM1m, "vgatherpf0qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF0DPD: avx512_gather_scatter_prefetch<0xC6, MRM1m, "vgatherpf0dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF0QPD: avx512_gather_scatter_prefetch<0xC7, MRM1m, "vgatherpf0qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF1DPS: avx512_gather_scatter_prefetch<0xC6, MRM2m, "vgatherpf1dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF1QPS: avx512_gather_scatter_prefetch<0xC7, MRM2m, "vgatherpf1qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF1DPD: avx512_gather_scatter_prefetch<0xC6, MRM2m, "vgatherpf1dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF1QPD: avx512_gather_scatter_prefetch<0xC7, MRM2m, "vgatherpf1qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF0DPS: avx512_gather_scatter_prefetch<0xC6, MRM5m, "vscatterpf0dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF0QPS: avx512_gather_scatter_prefetch<0xC7, MRM5m, "vscatterpf0qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF0DPD: avx512_gather_scatter_prefetch<0xC6, MRM5m, "vscatterpf0dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF0QPD: avx512_gather_scatter_prefetch<0xC7, MRM5m, "vscatterpf0qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF1DPS: avx512_gather_scatter_prefetch<0xC6, MRM6m, "vscatterpf1dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF1QPS: avx512_gather_scatter_prefetch<0xC7, MRM6m, "vscatterpf1qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF1DPD: avx512_gather_scatter_prefetch<0xC6, MRM6m, "vscatterpf1dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF1QPD: avx512_gather_scatter_prefetch<0xC7, MRM6m, "vscatterpf1qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -multiclass cvt_by_vec_width opc, X86VectorVTInfo Vec, string OpcodeStr > { -def rr : AVX512XS8I, - EVEX, Sched<[WriteMove]>; // TODO - WriteVecTrunc? -} - -multiclass cvt_mask_by_elt_width opc, AVX512VLVectorVTInfo VTInfo, - string OpcodeStr, Predicate prd> { -let Predicates = [prd] in - defm Z : cvt_by_vec_width, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : cvt_by_vec_width, EVEX_V256; - defm Z128 : cvt_by_vec_width, EVEX_V128; - } -} - -defm VPMOVM2B : cvt_mask_by_elt_width<0x28, avx512vl_i8_info, "vpmovm2" , HasBWI>; -defm VPMOVM2W : cvt_mask_by_elt_width<0x28, avx512vl_i16_info, "vpmovm2", HasBWI> , VEX_W; -defm VPMOVM2D : cvt_mask_by_elt_width<0x38, avx512vl_i32_info, "vpmovm2", HasDQI>; -defm VPMOVM2Q : cvt_mask_by_elt_width<0x38, avx512vl_i64_info, "vpmovm2", HasDQI> , VEX_W; - -multiclass convert_vector_to_mask_common opc, X86VectorVTInfo _, string OpcodeStr > { - def rr : AVX512XS8I, - EVEX, Sched<[WriteMove]>; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass convert_vector_to_mask_lowering { - - def : Pat<(_.KVT (X86pcmpgtm _.ImmAllZerosV, (_.VT _.RC:$src))), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name#"Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC))>; -} - -multiclass avx512_convert_vector_to_mask opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : convert_vector_to_mask_common , - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : convert_vector_to_mask_common, - EVEX_V256; - defm Z128 : convert_vector_to_mask_common, - EVEX_V128; - } - let Predicates = [prd, NoVLX] in { - defm Z256_Alt : convert_vector_to_mask_lowering; - defm Z128_Alt : convert_vector_to_mask_lowering; - } -} - -defm VPMOVB2M : avx512_convert_vector_to_mask<0x29, "vpmovb2m", - avx512vl_i8_info, HasBWI>; -defm VPMOVW2M : avx512_convert_vector_to_mask<0x29, "vpmovw2m", - avx512vl_i16_info, HasBWI>, VEX_W; -defm VPMOVD2M : avx512_convert_vector_to_mask<0x39, "vpmovd2m", - avx512vl_i32_info, HasDQI>; -defm VPMOVQ2M : avx512_convert_vector_to_mask<0x39, "vpmovq2m", - avx512vl_i64_info, HasDQI>, VEX_W; - -// Patterns for handling sext from a mask register to v16i8/v16i16 when DQI -// is available, but BWI is not. We can't handle this in lowering because -// a target independent DAG combine likes to combine sext and trunc. -let Predicates = [HasDQI, NoBWI] in { - def : Pat<(v16i8 (sext (v16i1 VK16:$src))), - (VPMOVDBZrr (v16i32 (VPMOVM2DZrr VK16:$src)))>; - def : Pat<(v16i16 (sext (v16i1 VK16:$src))), - (VPMOVDWZrr (v16i32 (VPMOVM2DZrr VK16:$src)))>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - COMPRESS and EXPAND -// - -multiclass compress_by_vec_width_common opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - defm rr : AVX512_maskable, AVX5128IBase, - Sched<[sched]>; - - let mayStore = 1, hasSideEffects = 0 in - def mr : AVX5128I, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded]>; - - def mrk : AVX5128I, - EVEX_K, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded]>; -} - -multiclass compress_by_vec_width_lowering { - def : Pat<(X86mCompressingStore addr:$dst, _.KRCWM:$mask, - (_.VT _.RC:$src)), - (!cast(Name#_.ZSuffix##mrk) - addr:$dst, _.KRCWM:$mask, _.RC:$src)>; -} - -multiclass compress_by_elt_width opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in - defm Z : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V512; - - let Predicates = [Pred, HasVLX] in { - defm Z256 : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V256; - defm Z128 : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPCOMPRESS? -defm VPCOMPRESSD : compress_by_elt_width <0x8B, "vpcompressd", WriteVarShuffle256, - avx512vl_i32_info>, EVEX, NotMemoryFoldable; -defm VPCOMPRESSQ : compress_by_elt_width <0x8B, "vpcompressq", WriteVarShuffle256, - avx512vl_i64_info>, EVEX, VEX_W, NotMemoryFoldable; -defm VCOMPRESSPS : compress_by_elt_width <0x8A, "vcompressps", WriteVarShuffle256, - avx512vl_f32_info>, EVEX, NotMemoryFoldable; -defm VCOMPRESSPD : compress_by_elt_width <0x8A, "vcompresspd", WriteVarShuffle256, - avx512vl_f64_info>, EVEX, VEX_W, NotMemoryFoldable; - -// expand -multiclass expand_by_vec_width opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - defm rr : AVX512_maskable, AVX5128IBase, - Sched<[sched]>; - - defm rm : AVX512_maskable, - AVX5128IBase, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass expand_by_vec_width_lowering { - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, undef)), - (!cast(Name#_.ZSuffix##rmkz) - _.KRCWM:$mask, addr:$src)>; - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix##rmkz) - _.KRCWM:$mask, addr:$src)>; - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, - (_.VT _.RC:$src0))), - (!cast(Name#_.ZSuffix##rmk) - _.RC:$src0, _.KRCWM:$mask, addr:$src)>; -} - -multiclass expand_by_elt_width opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in - defm Z : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V512; - - let Predicates = [Pred, HasVLX] in { - defm Z256 : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V256; - defm Z128 : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPEXPAND? -defm VPEXPANDD : expand_by_elt_width <0x89, "vpexpandd", WriteVarShuffle256, - avx512vl_i32_info>, EVEX; -defm VPEXPANDQ : expand_by_elt_width <0x89, "vpexpandq", WriteVarShuffle256, - avx512vl_i64_info>, EVEX, VEX_W; -defm VEXPANDPS : expand_by_elt_width <0x88, "vexpandps", WriteVarShuffle256, - avx512vl_f32_info>, EVEX; -defm VEXPANDPD : expand_by_elt_width <0x88, "vexpandpd", WriteVarShuffle256, - avx512vl_f64_info>, EVEX, VEX_W; - -//handle instruction reg_vec1 = op(reg_vec,imm) -// op(mem_vec,imm) -// op(broadcast(eltVt),imm) -//all instruction created with FROUND_CURRENT -multiclass avx512_unary_fp_packed_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_unary_fp_sae_packed_imm opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrib : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_common_unary_fp_sae_packed_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in { - defm Z : avx512_unary_fp_packed_imm, - avx512_unary_fp_sae_packed_imm, EVEX_V512; - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_unary_fp_packed_imm, EVEX_V128; - defm Z256 : avx512_unary_fp_packed_imm, EVEX_V256; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -// op(reg_vec2,broadcast(eltVt),imm) -//all instruction created with FROUND_CURRENT -multiclass avx512_fp_packed_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -multiclass avx512_3Op_rm_imm8 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo>{ - let ExeDomain = DestInfo.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -// op(reg_vec2,broadcast(eltVt),imm) -multiclass avx512_3Op_imm8 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _>: - avx512_3Op_rm_imm8{ - - let ExeDomain = _.ExeDomain in - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -//handle scalar instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_scalar,imm) -multiclass avx512_fp_scalar_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_scalar, - Sched<[sched]>; - defm rmi : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_fp_sae_packed_imm opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrib : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -//handle scalar instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_fp_sae_scalar_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm NAME#rrib : AVX512_maskable_scalar, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_common_fp_sae_packed_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in { - defm Z : avx512_fp_packed_imm, - avx512_fp_sae_packed_imm, - EVEX_V512; - - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_fp_packed_imm, - EVEX_V128; - defm Z256 : avx512_fp_packed_imm, - EVEX_V256; - } -} - -multiclass avx512_common_3Op_rm_imm8 opc, SDNode OpNode, string OpStr, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo DestInfo, - AVX512VLVectorVTInfo SrcInfo, Predicate Pred = HasBWI> { - let Predicates = [Pred] in { - defm Z : avx512_3Op_rm_imm8, EVEX_V512, AVX512AIi8Base, EVEX_4V; - } - let Predicates = [Pred, HasVLX] in { - defm Z128 : avx512_3Op_rm_imm8, EVEX_V128, AVX512AIi8Base, EVEX_4V; - defm Z256 : avx512_3Op_rm_imm8, EVEX_V256, AVX512AIi8Base, EVEX_4V; - } -} - -multiclass avx512_common_3Op_imm8 opc, SDNode OpNode, X86SchedWriteWidths sched, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in { - defm Z : avx512_3Op_imm8, - EVEX_V512; - } - let Predicates = [Pred, HasVLX] in { - defm Z128 : avx512_3Op_imm8, - EVEX_V128; - defm Z256 : avx512_3Op_imm8, - EVEX_V256; - } -} - -multiclass avx512_common_fp_sae_scalar_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd> { - let Predicates = [prd] in { - defm Z : avx512_fp_scalar_imm, - avx512_fp_sae_scalar_imm; - } -} - -multiclass avx512_common_unary_fp_sae_packed_imm_all opcPs, bits<8> opcPd, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - defm PS : avx512_common_unary_fp_sae_packed_imm, - EVEX_CD8<32, CD8VF>; - defm PD : avx512_common_unary_fp_sae_packed_imm, - EVEX_CD8<64, CD8VF>, VEX_W; -} - -defm VREDUCE : avx512_common_unary_fp_sae_packed_imm_all<"vreduce", 0x56, 0x56, - X86VReduce, X86VReduceRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, EVEX; -defm VRNDSCALE : avx512_common_unary_fp_sae_packed_imm_all<"vrndscale", 0x08, 0x09, - X86VRndScale, X86VRndScaleRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, EVEX; -defm VGETMANT : avx512_common_unary_fp_sae_packed_imm_all<"vgetmant", 0x26, 0x26, - X86VGetMant, X86VGetMantRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, EVEX; - -defm VRANGEPD : avx512_common_fp_sae_packed_imm<"vrangepd", avx512vl_f64_info, - 0x50, X86VRange, X86VRangeRnd, - SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VRANGEPS : avx512_common_fp_sae_packed_imm<"vrangeps", avx512vl_f32_info, - 0x50, X86VRange, X86VRangeRnd, - SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - -defm VRANGESD: avx512_common_fp_sae_scalar_imm<"vrangesd", - f64x_info, 0x51, X86Ranges, X86RangesRnd, SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VRANGESS: avx512_common_fp_sae_scalar_imm<"vrangess", f32x_info, - 0x51, X86Ranges, X86RangesRnd, SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - -defm VREDUCESD: avx512_common_fp_sae_scalar_imm<"vreducesd", f64x_info, - 0x57, X86Reduces, X86ReducesRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VREDUCESS: avx512_common_fp_sae_scalar_imm<"vreducess", f32x_info, - 0x57, X86Reduces, X86ReducesRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - -defm VGETMANTSD: avx512_common_fp_sae_scalar_imm<"vgetmantsd", f64x_info, - 0x27, X86GetMants, X86GetMantsRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VGETMANTSS: avx512_common_fp_sae_scalar_imm<"vgetmantss", f32x_info, - 0x27, X86GetMants, X86GetMantsRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - - -multiclass AVX512_rndscale_lowering { - // Register - def : Pat<(_.VT (ffloor _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (frint _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xB))>; - - // Merge-masking - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xB))>; - - // Zero-masking - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xB))>; - - // Load - def : Pat<(_.VT (ffloor (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xA))>; - def : Pat<(_.VT (frint (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xB))>; - - // Merge-masking + load - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Zero-masking + load - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Broadcast load - def : Pat<(_.VT (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xA))>; - def : Pat<(_.VT (frint (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xB))>; - - // Merge-masking + broadcast load - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (frint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Zero-masking + broadcast load - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (frint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xB))>; -} - -let Predicates = [HasAVX512] in { - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; -} - -let Predicates = [HasVLX] in { - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; -} - -multiclass avx512_shuff_packed_128_common opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, - X86VectorVTInfo CastInfo, - string EVEX2VEXOvrd> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>, EVEX2VEXOverride; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>, - EVEX2VEXOverride; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_shuff_packed_128 opc, - string EVEX2VEXOvrd>{ - let Predicates = [HasAVX512] in - defm Z : avx512_shuff_packed_128_common, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in - defm Z256 : avx512_shuff_packed_128_common, EVEX_V256; -} - -defm VSHUFF32X4 : avx512_shuff_packed_128<"vshuff32x4", WriteFShuffle256, - avx512vl_f32_info, avx512vl_f64_info, 0x23, "VPERM2F128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; -defm VSHUFF64X2 : avx512_shuff_packed_128<"vshuff64x2", WriteFShuffle256, - avx512vl_f64_info, avx512vl_f64_info, 0x23, "VPERM2F128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VSHUFI32X4 : avx512_shuff_packed_128<"vshufi32x4", WriteFShuffle256, - avx512vl_i32_info, avx512vl_i64_info, 0x43, "VPERM2I128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; -defm VSHUFI64X2 : avx512_shuff_packed_128<"vshufi64x2", WriteFShuffle256, - avx512vl_i64_info, avx512vl_i64_info, 0x43, "VPERM2I128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; - -let Predicates = [HasAVX512] in { -// Provide fallback in case the load node that is used in the broadcast -// patterns above is used by additional users, which prevents the pattern -// selection. -def : Pat<(v8f64 (X86SubVBroadcast (v2f64 VR128X:$src))), - (VSHUFF64X2Zrri (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -def : Pat<(v8i64 (X86SubVBroadcast (v2i64 VR128X:$src))), - (VSHUFI64X2Zrri (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v16f32 (X86SubVBroadcast (v4f32 VR128X:$src))), - (VSHUFF32X4Zrri (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -def : Pat<(v16i32 (X86SubVBroadcast (v4i32 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v32i16 (X86SubVBroadcast (v8i16 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v64i8 (X86SubVBroadcast (v16i8 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -} - -multiclass avx512_valign opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - // NOTE: EVEX2VEXOverride changed back to Unset for 256-bit at the - // instantiation of this class. - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>, EVEX2VEXOverride<"VPALIGNRrri">; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>, - EVEX2VEXOverride<"VPALIGNRrmi">; - - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_valign_common { - let Predicates = [HasAVX512] in { - defm Z : avx512_valign<0x03, OpcodeStr, sched.ZMM, _.info512>, - AVX512AIi8Base, EVEX_4V, EVEX_V512; - } - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_valign<0x03, OpcodeStr, sched.XMM, _.info128>, - AVX512AIi8Base, EVEX_4V, EVEX_V128; - // We can't really override the 256-bit version so change it back to unset. - let EVEX2VEXOverride = ? in - defm Z256 : avx512_valign<0x03, OpcodeStr, sched.YMM, _.info256>, - AVX512AIi8Base, EVEX_4V, EVEX_V256; - } -} - -defm VALIGND: avx512_valign_common<"valignd", SchedWriteShuffle, - avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VALIGNQ: avx512_valign_common<"valignq", SchedWriteShuffle, - avx512vl_i64_info>, EVEX_CD8<64, CD8VF>, - VEX_W; - -defm VPALIGNR: avx512_common_3Op_rm_imm8<0x0F, X86PAlignr, "vpalignr", - SchedWriteShuffle, avx512vl_i8_info, - avx512vl_i8_info>, EVEX_CD8<8, CD8VF>; - -// Fragments to help convert valignq into masked valignd. Or valignq/valignd -// into vpalignr. -def ValignqImm32XForm : SDNodeXFormgetZExtValue() * 2, SDLoc(N)); -}]>; -def ValignqImm8XForm : SDNodeXFormgetZExtValue() * 8, SDLoc(N)); -}]>; -def ValigndImm8XForm : SDNodeXFormgetZExtValue() * 4, SDLoc(N)); -}]>; - -multiclass avx512_vpalign_mask_lowering { - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, From.RC:$src2, - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rrik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, To.RC:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, From.RC:$src2, - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rrikz") To.KRCWM:$mask, - To.RC:$src1, To.RC:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert (To.LdFrag addr:$src2)), - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rmik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert (To.LdFrag addr:$src2)), - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rmikz") To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; -} - -multiclass avx512_vpalign_mask_lowering_mb : - avx512_vpalign_mask_lowering { - def : Pat<(From.VT (OpNode From.RC:$src1, - (bitconvert (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3)), - (!cast(OpcodeStr#"rmbi") To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert - (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rmbik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert - (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rmbikz") To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; -} - -let Predicates = [HasAVX512] in { - // For 512-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ", X86VAlign, v8i64_info, - v16i32_info, ValignqImm32XForm>; -} - -let Predicates = [HasVLX] in { - // For 128-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ128", X86VAlign, v2i64x_info, - v4i32x_info, ValignqImm32XForm>; - // For 256-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ256", X86VAlign, v4i64x_info, - v8i32x_info, ValignqImm32XForm>; -} - -let Predicates = [HasVLX, HasBWI] in { - // We can turn 128 and 256 bit VALIGND/VALIGNQ into VPALIGNR. - defm : avx512_vpalign_mask_lowering<"VPALIGNRZ128", X86VAlign, v2i64x_info, - v16i8x_info, ValignqImm8XForm>; - defm : avx512_vpalign_mask_lowering<"VPALIGNRZ128", X86VAlign, v4i32x_info, - v16i8x_info, ValigndImm8XForm>; -} - -defm VDBPSADBW: avx512_common_3Op_rm_imm8<0x42, X86dbpsadbw, "vdbpsadbw", - SchedWritePSADBW, avx512vl_i16_info, avx512vl_i8_info>, - EVEX_CD8<8, CD8VF>, NotEVEX2VEXConvertible; - -multiclass avx512_unary_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, EVEX, AVX5128IBase, - Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, AVX5128IBase, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_unary_rmb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> : - avx512_unary_rm { - defm rmb : AVX512_maskable, - EVEX, AVX5128IBase, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded]>; -} - -multiclass avx512_unary_rm_vl opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_unary_rm, - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_unary_rm, - EVEX_V256; - defm Z128 : avx512_unary_rm, - EVEX_V128; - } -} - -multiclass avx512_unary_rmb_vl opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTInfo, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_unary_rmb, - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_unary_rmb, - EVEX_V256; - defm Z128 : avx512_unary_rmb, - EVEX_V128; - } -} - -multiclass avx512_unary_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm Q : avx512_unary_rmb_vl, VEX_W; - defm D : avx512_unary_rmb_vl; -} - -multiclass avx512_unary_rm_vl_bw opc_b, bits<8> opc_w, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm W : avx512_unary_rm_vl, VEX_WIG; - defm B : avx512_unary_rm_vl, VEX_WIG; -} - -multiclass avx512_unary_rm_vl_all opc_b, bits<8> opc_w, - bits<8> opc_d, bits<8> opc_q, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME : avx512_unary_rm_vl_dq, - avx512_unary_rm_vl_bw; -} - -defm VPABS : avx512_unary_rm_vl_all<0x1C, 0x1D, 0x1E, 0x1F, "vpabs", abs, - SchedWriteVecALU>; - -// VPABS: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v4i64 (abs VR256X:$src)), - (EXTRACT_SUBREG - (VPABSQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm)), - sub_ymm)>; - def : Pat<(v2i64 (abs VR128X:$src)), - (EXTRACT_SUBREG - (VPABSQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm)), - sub_xmm)>; -} - -// Use 512bit version to implement 128/256 bit. -multiclass avx512_unary_lowering { - let Predicates = [prd, NoVLX] in { - def : Pat<(_.info256.VT(OpNode _.info256.RC:$src1)), - (EXTRACT_SUBREG - (!cast(InstrStr # "Zrr") - (INSERT_SUBREG(_.info512.VT(IMPLICIT_DEF)), - _.info256.RC:$src1, - _.info256.SubRegIdx)), - _.info256.SubRegIdx)>; - - def : Pat<(_.info128.VT(OpNode _.info128.RC:$src1)), - (EXTRACT_SUBREG - (!cast(InstrStr # "Zrr") - (INSERT_SUBREG(_.info512.VT(IMPLICIT_DEF)), - _.info128.RC:$src1, - _.info128.SubRegIdx)), - _.info128.SubRegIdx)>; - } -} - -defm VPLZCNT : avx512_unary_rm_vl_dq<0x44, 0x44, "vplzcnt", ctlz, - SchedWriteVecIMul, HasCDI>; - -// FIXME: Is there a better scheduler class for VPCONFLICT? -defm VPCONFLICT : avx512_unary_rm_vl_dq<0xC4, 0xC4, "vpconflict", X86Conflict, - SchedWriteVecALU, HasCDI>; - -// VPLZCNT: Use 512bit version to implement 128/256 bit in case NoVLX. -defm : avx512_unary_lowering<"VPLZCNTQ", ctlz, avx512vl_i64_info, HasCDI>; -defm : avx512_unary_lowering<"VPLZCNTD", ctlz, avx512vl_i32_info, HasCDI>; - -//===---------------------------------------------------------------------===// -// Counts number of ones - VPOPCNTD and VPOPCNTQ -//===---------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for VPOPCNTD/VPOPCNTQ? -defm VPOPCNT : avx512_unary_rm_vl_dq<0x55, 0x55, "vpopcnt", ctpop, - SchedWriteVecALU, HasVPOPCNTDQ>; - -defm : avx512_unary_lowering<"VPOPCNTQ", ctpop, avx512vl_i64_info, HasVPOPCNTDQ>; -defm : avx512_unary_lowering<"VPOPCNTD", ctpop, avx512vl_i32_info, HasVPOPCNTDQ>; - -//===---------------------------------------------------------------------===// -// Replicate Single FP - MOVSHDUP and MOVSLDUP -//===---------------------------------------------------------------------===// - -multiclass avx512_replicate opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME: avx512_unary_rm_vl, XS; -} - -defm VMOVSHDUP : avx512_replicate<0x16, "vmovshdup", X86Movshdup, - SchedWriteFShuffle>; -defm VMOVSLDUP : avx512_replicate<0x12, "vmovsldup", X86Movsldup, - SchedWriteFShuffle>; - -//===----------------------------------------------------------------------===// -// AVX-512 - MOVDDUP -//===----------------------------------------------------------------------===// - -multiclass avx512_movddup_128 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, EVEX, - Sched<[sched]>; - defm rm : AVX512_maskable, - EVEX, EVEX_CD8<_.EltSize, CD8VH>, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_movddup_common opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTInfo> { - defm Z : avx512_unary_rm, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_unary_rm, EVEX_V256; - defm Z128 : avx512_movddup_128, EVEX_V128; - } -} - -multiclass avx512_movddup opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME: avx512_movddup_common, XD, VEX_W; -} - -defm VMOVDDUP : avx512_movddup<0x12, "vmovddup", X86Movddup, SchedWriteFShuffle>; - -let Predicates = [HasVLX] in { -def : Pat<(v2f64 (X86VBroadcast (loadf64 addr:$src))), - (VMOVDDUPZ128rm addr:$src)>; -def : Pat<(v2f64 (X86VBroadcast f64:$src)), - (VMOVDDUPZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; -def : Pat<(v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (VMOVDDUPZ128rm addr:$src)>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast f64:$src)), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rrk VR128X:$src0, VK2WM:$mask, - (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast f64:$src)), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rrkz VK2WM:$mask, (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadf64 addr:$src))), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rmk VR128X:$src0, VK2WM:$mask, addr:$src)>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadf64 addr:$src))), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rmkz VK2WM:$mask, addr:$src)>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rmk VR128X:$src0, VK2WM:$mask, addr:$src)>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rmkz VK2WM:$mask, addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Unpack Instructions -//===----------------------------------------------------------------------===// - -defm VUNPCKH : avx512_fp_binop_p<0x15, "vunpckh", X86Unpckh, HasAVX512, - SchedWriteFShuffleSizes, 0, 1>; -defm VUNPCKL : avx512_fp_binop_p<0x14, "vunpckl", X86Unpckl, HasAVX512, - SchedWriteFShuffleSizes>; - -defm VPUNPCKLBW : avx512_binop_rm_vl_b<0x60, "vpunpcklbw", X86Unpckl, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKHBW : avx512_binop_rm_vl_b<0x68, "vpunpckhbw", X86Unpckh, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKLWD : avx512_binop_rm_vl_w<0x61, "vpunpcklwd", X86Unpckl, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKHWD : avx512_binop_rm_vl_w<0x69, "vpunpckhwd", X86Unpckh, - SchedWriteShuffle, HasBWI>; - -defm VPUNPCKLDQ : avx512_binop_rm_vl_d<0x62, "vpunpckldq", X86Unpckl, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKHDQ : avx512_binop_rm_vl_d<0x6A, "vpunpckhdq", X86Unpckh, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKLQDQ : avx512_binop_rm_vl_q<0x6C, "vpunpcklqdq", X86Unpckl, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKHQDQ : avx512_binop_rm_vl_q<0x6D, "vpunpckhqdq", X86Unpckh, - SchedWriteShuffle, HasAVX512>; - -//===----------------------------------------------------------------------===// -// AVX-512 - Extract & Insert Integer Instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_extract_elt_bw_m opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _> { - def mr : AVX512Ii8, - EVEX, EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteVecExtractSt]>; -} - -multiclass avx512_extract_elt_b { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8<0x14, MRMDestReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, - (X86pextrb (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, TAPD, Sched<[WriteVecExtract]>; - - defm NAME : avx512_extract_elt_bw_m<0x14, OpcodeStr, X86pextrb, _>, TAPD; - } -} - -multiclass avx512_extract_elt_w { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8<0xC5, MRMSrcReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, - (X86pextrw (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, PD, Sched<[WriteVecExtract]>; - - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in - def rr_REV : AVX512Ii8<0x15, MRMDestReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - EVEX, TAPD, FoldGenData, - Sched<[WriteVecExtract]>; - - defm NAME : avx512_extract_elt_bw_m<0x15, OpcodeStr, X86pextrw, _>, TAPD; - } -} - -multiclass avx512_extract_elt_dq { - let Predicates = [HasDQI] in { - def rr : AVX512Ii8<0x16, MRMDestReg, (outs GRC:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GRC:$dst, - (extractelt (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, TAPD, Sched<[WriteVecExtract]>; - - def mr : AVX512Ii8<0x16, MRMDestMem, (outs), - (ins _.ScalarMemOp:$dst, _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(store (extractelt (_.VT _.RC:$src1), - imm:$src2),addr:$dst)]>, - EVEX, EVEX_CD8<_.EltSize, CD8VT1>, TAPD, - Sched<[WriteVecExtractSt]>; - } -} - -defm VPEXTRBZ : avx512_extract_elt_b<"vpextrb", v16i8x_info>, VEX_WIG; -defm VPEXTRWZ : avx512_extract_elt_w<"vpextrw", v8i16x_info>, VEX_WIG; -defm VPEXTRDZ : avx512_extract_elt_dq<"vpextrd", v4i32x_info, GR32>; -defm VPEXTRQZ : avx512_extract_elt_dq<"vpextrq", v2i64x_info, GR64>, VEX_W; - -multiclass avx512_insert_elt_m opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, PatFrag LdFrag> { - def rm : AVX512Ii8, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -multiclass avx512_insert_elt_bw opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, PatFrag LdFrag> { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8, EVEX_4V, - Sched<[WriteVecInsert]>; - - defm NAME : avx512_insert_elt_m; - } -} - -multiclass avx512_insert_elt_dq opc, string OpcodeStr, - X86VectorVTInfo _, RegisterClass GRC> { - let Predicates = [HasDQI] in { - def rr : AVX512Ii8, - EVEX_4V, TAPD, Sched<[WriteVecInsert]>; - - defm NAME : avx512_insert_elt_m, TAPD; - } -} - -defm VPINSRBZ : avx512_insert_elt_bw<0x20, "vpinsrb", X86pinsrb, v16i8x_info, - extloadi8>, TAPD, VEX_WIG; -defm VPINSRWZ : avx512_insert_elt_bw<0xC4, "vpinsrw", X86pinsrw, v8i16x_info, - extloadi16>, PD, VEX_WIG; -defm VPINSRDZ : avx512_insert_elt_dq<0x22, "vpinsrd", v4i32x_info, GR32>; -defm VPINSRQZ : avx512_insert_elt_dq<0x22, "vpinsrq", v2i64x_info, GR64>, VEX_W; - -//===----------------------------------------------------------------------===// -// VSHUFPS - VSHUFPD Operations -//===----------------------------------------------------------------------===// - -multiclass avx512_shufp{ - defm NAME: avx512_common_3Op_imm8, - EVEX_CD8, - AVX512AIi8Base, EVEX_4V; -} - -defm VSHUFPS: avx512_shufp<"vshufps", avx512vl_i32_info, avx512vl_f32_info>, PS; -defm VSHUFPD: avx512_shufp<"vshufpd", avx512vl_i64_info, avx512vl_f64_info>, PD, VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 - Byte shift Left/Right -//===----------------------------------------------------------------------===// - -// FIXME: The SSE/AVX names are PSLLDQri etc. - should we add the i here as well? -multiclass avx512_shift_packed opc, SDNode OpNode, Format MRMr, - Format MRMm, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - def rr : AVX512, - Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_shift_packed_all opc, SDNode OpNode, Format MRMr, - Format MRMm, string OpcodeStr, - X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in - defm Z : avx512_shift_packed, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_shift_packed, EVEX_V256; - defm Z128 : avx512_shift_packed, EVEX_V128; - } -} -defm VPSLLDQ : avx512_shift_packed_all<0x73, X86vshldq, MRM7r, MRM7m, "vpslldq", - SchedWriteShuffle, HasBWI>, - AVX512PDIi8Base, EVEX_4V, VEX_WIG; -defm VPSRLDQ : avx512_shift_packed_all<0x73, X86vshrdq, MRM3r, MRM3m, "vpsrldq", - SchedWriteShuffle, HasBWI>, - AVX512PDIi8Base, EVEX_4V, VEX_WIG; - -multiclass avx512_psadbw_packed opc, SDNode OpNode, - string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo _dst, X86VectorVTInfo _src> { - def rr : AVX512BI, - Sched<[sched]>; - def rm : AVX512BI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_psadbw_packed_all opc, SDNode OpNode, - string OpcodeStr, X86SchedWriteWidths sched, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_psadbw_packed, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_psadbw_packed, EVEX_V256; - defm Z128 : avx512_psadbw_packed, EVEX_V128; - } -} - -defm VPSADBW : avx512_psadbw_packed_all<0xf6, X86psadbw, "vpsadbw", - SchedWritePSADBW, HasBWI>, EVEX_4V, VEX_WIG; - -// Transforms to swizzle an immediate to enable better matching when -// memory operand isn't in the right place. -def VPTERNLOG321_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 1/4 and 3/6. - uint8_t NewImm = Imm & 0xa5; - if (Imm & 0x02) NewImm |= 0x10; - if (Imm & 0x10) NewImm |= 0x02; - if (Imm & 0x08) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG213_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 2/4 and 3/5. - uint8_t NewImm = Imm & 0xc3; - if (Imm & 0x04) NewImm |= 0x10; - if (Imm & 0x10) NewImm |= 0x04; - if (Imm & 0x08) NewImm |= 0x20; - if (Imm & 0x20) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG132_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 1/2 and 5/6. - uint8_t NewImm = Imm & 0x99; - if (Imm & 0x02) NewImm |= 0x04; - if (Imm & 0x04) NewImm |= 0x02; - if (Imm & 0x20) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x20; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG231_imm8 : SDNodeXFormgetZExtValue(); - // Move bits 1->2, 2->4, 3->6, 4->1, 5->3, 6->5 - uint8_t NewImm = Imm & 0x81; - if (Imm & 0x02) NewImm |= 0x04; - if (Imm & 0x04) NewImm |= 0x10; - if (Imm & 0x08) NewImm |= 0x40; - if (Imm & 0x10) NewImm |= 0x02; - if (Imm & 0x20) NewImm |= 0x08; - if (Imm & 0x40) NewImm |= 0x20; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG312_imm8 : SDNodeXFormgetZExtValue(); - // Move bits 1->4, 2->1, 3->5, 4->2, 5->6, 6->3 - uint8_t NewImm = Imm & 0x81; - if (Imm & 0x02) NewImm |= 0x10; - if (Imm & 0x04) NewImm |= 0x02; - if (Imm & 0x08) NewImm |= 0x20; - if (Imm & 0x10) NewImm |= 0x04; - if (Imm & 0x20) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; - -multiclass avx512_ternlog opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string Name>{ - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src, - AVX512AIi8Base, EVEX_4V, Sched<[sched]>; - defm rmi : AVX512_maskable_3src, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable_3src, EVEX_B, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - }// Constraints = "$src1 = $dst" - - // Additional patterns for matching passthru operand in other positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src3, _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rrik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, _.RC:$src3, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rrik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - - // Additional patterns for matching loads in other positions. - def : Pat<(_.VT (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (OpNode _.RC:$src1, - (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching zero masking with loads in other - // positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmikz) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmikz) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching masked loads with different - // operand orders. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, - (bitconvert (_.LdFrag addr:$src3)), (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG231_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src1, _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG312_imm8 imm:$src4))>; - - // Additional patterns for matching broadcasts in other positions. - def : Pat<(_.VT (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmbi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmbi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching zero masking with broadcasts in other - // positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmbikz) _.RC:$src1, - _.KRCWM:$mask, _.RC:$src2, addr:$src3, - (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmbikz) _.RC:$src1, - _.KRCWM:$mask, _.RC:$src2, addr:$src3, - (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching masked broadcasts with different - // operand orders. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - (i8 imm:$src4)), _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG231_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src1, _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG312_imm8 imm:$src4))>; -} - -multiclass avx512_common_ternlog { - let Predicates = [HasAVX512] in - defm Z : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.ZMM, - _.info512, NAME>, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.XMM, - _.info128, NAME>, EVEX_V128; - defm Z256 : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.YMM, - _.info256, NAME>, EVEX_V256; - } -} - -defm VPTERNLOGD : avx512_common_ternlog<"vpternlogd", SchedWriteVecALU, - avx512vl_i32_info>; -defm VPTERNLOGQ : avx512_common_ternlog<"vpternlogq", SchedWriteVecALU, - avx512vl_i64_info>, VEX_W; - -// Patterns to implement vnot using vpternlog instead of creating all ones -// using pcmpeq or vpternlog and then xoring with that. The value 15 is chosen -// so that the result is only dependent on src0. But we use the same source -// for all operands to prevent a false dependency. -// TODO: We should maybe have a more generalized algorithm for folding to -// vpternlog. -let Predicates = [HasAVX512] in { - def : Pat<(v8i64 (xor VR512:$src, (bc_v8i64 (v16i32 immAllOnesV)))), - (VPTERNLOGQZrri VR512:$src, VR512:$src, VR512:$src, (i8 15))>; -} - -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (xor VR128X:$src, (bc_v2i64 (v4i32 immAllOnesV)))), - (EXTRACT_SUBREG - (VPTERNLOGQZrri - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (i8 15)), sub_xmm)>; - def : Pat<(v4i64 (xor VR256X:$src, (bc_v4i64 (v8i32 immAllOnesV)))), - (EXTRACT_SUBREG - (VPTERNLOGQZrri - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (i8 15)), sub_ymm)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v2i64 (xor VR128X:$src, (bc_v2i64 (v4i32 immAllOnesV)))), - (VPTERNLOGQZ128rri VR128X:$src, VR128X:$src, VR128X:$src, (i8 15))>; - def : Pat<(v4i64 (xor VR256X:$src, (bc_v4i64 (v8i32 immAllOnesV)))), - (VPTERNLOGQZ256rri VR256X:$src, VR256X:$src, VR256X:$src, (i8 15))>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - FixupImm -//===----------------------------------------------------------------------===// - -multiclass avx512_fixupimm_packed opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo TblVT>{ - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src, Sched<[sched]>; - defm rmi : AVX512_maskable_3src, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable_3src, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } // Constraints = "$src1 = $dst" -} - -multiclass avx512_fixupimm_packed_sae opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo TblVT>{ -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rrib : AVX512_maskable_3src, - EVEX_B, Sched<[sched]>; - } -} - -multiclass avx512_fixupimm_scalar opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo _src3VT> { - let Constraints = "$src1 = $dst" , Predicates = [HasAVX512], - ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src_scalar, Sched<[sched]>; - defm rrib : AVX512_maskable_3src_scalar, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - defm rmi : AVX512_maskable_3src_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fixupimm_packed_all { - let Predicates = [HasAVX512] in - defm Z : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.ZMM, - _Vec.info512, _Tbl.info512>, - avx512_fixupimm_packed_sae<0x54, "vfixupimm", X86VFixupimm, sched.ZMM, - _Vec.info512, _Tbl.info512>, AVX512AIi8Base, - EVEX_4V, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.XMM, - _Vec.info128, _Tbl.info128>, AVX512AIi8Base, - EVEX_4V, EVEX_V128; - defm Z256 : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.YMM, - _Vec.info256, _Tbl.info256>, AVX512AIi8Base, - EVEX_4V, EVEX_V256; - } -} - -defm VFIXUPIMMSSZ : avx512_fixupimm_scalar<0x55, "vfixupimm", X86VFixupimmScalar, - SchedWriteFAdd.Scl, f32x_info, v4i32x_info>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; -defm VFIXUPIMMSDZ : avx512_fixupimm_scalar<0x55, "vfixupimm", X86VFixupimmScalar, - SchedWriteFAdd.Scl, f64x_info, v2i64x_info>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VFIXUPIMMPS : avx512_fixupimm_packed_all, EVEX_CD8<32, CD8VF>; -defm VFIXUPIMMPD : avx512_fixupimm_packed_all, EVEX_CD8<64, CD8VF>, VEX_W; - -// Patterns used to select SSE scalar fp arithmetic instructions from -// either: -// -// (1) a scalar fp operation followed by a blend -// -// The effect is that the backend no longer emits unnecessary vector -// insert instructions immediately after SSE scalar fp instructions -// like addss or mulss. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// A[0] += B[0]; -// return A; -// } -// -// Previously we generated: -// addss %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 -// -// (2) a vector packed single/double fp operation followed by a vector insert -// -// The effect is that the backend converts the packed fp instruction -// followed by a vector insert into a single SSE scalar fp instruction. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// __m128 C = A + B; -// return (__m128) {c[0], a[1], a[2], a[3]}; -// } -// -// Previously we generated: -// addps %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 - -// TODO: Some canonicalization in lowering would simplify the number of -// patterns we have to try to match. -multiclass AVX512_scalar_math_fp_patterns { - let Predicates = [HasAVX512] in { - // extracted scalar math op with insert via movss - def : Pat<(MoveNode - (_.VT VR128X:$dst), - (_.VT (scalar_to_vector - (Op (_.EltVT (extractelt (_.VT VR128X:$dst), (iPTR 0))), - _.FRC:$src)))), - (!cast("V"#OpcPrefix#Zrr_Int) _.VT:$dst, - (_.VT (COPY_TO_REGCLASS _.FRC:$src, VR128X)))>; - - // extracted masked scalar math op with insert via movss - def : Pat<(MoveNode (_.VT VR128X:$src1), - (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT - (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2), - _.FRC:$src0))), - (!cast("V"#OpcPrefix#Zrr_Intk) - (_.VT (COPY_TO_REGCLASS _.FRC:$src0, VR128X)), - VK1WM:$mask, _.VT:$src1, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)))>; - - // extracted masked scalar math op with insert via movss - def : Pat<(MoveNode (_.VT VR128X:$src1), - (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT - (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2), (_.EltVT ZeroFP)))), - (!cast("V"#OpcPrefix#Zrr_Intkz) - VK1WM:$mask, _.VT:$src1, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)))>; - } -} - -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; - -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; - -multiclass AVX512_scalar_unary_math_patterns { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move _.VT:$dst, - (scalar_to_vector (OpNode (extractelt _.VT:$src, 0))))), - (!cast("V"#OpcPrefix#Zr_Int) _.VT:$dst, _.VT:$src)>; - } -} - -defm : AVX512_scalar_unary_math_patterns; -defm : AVX512_scalar_unary_math_patterns; - -multiclass AVX512_scalar_unary_math_imm_patterns ImmV> { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move _.VT:$dst, - (scalar_to_vector (OpNode (extractelt _.VT:$src, 0))))), - (!cast("V"#OpcPrefix#Zr_Int) _.VT:$dst, _.VT:$src, - (i32 ImmV))>; - } -} - -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; - -//===----------------------------------------------------------------------===// -// AES instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_vaes Op, string OpStr, string IntPrefix> { - let Predicates = [HasVLX, HasVAES] in { - defm Z128 : AESI_binop_rm_int(IntPrefix), - loadv2i64, 0, VR128X, i128mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V128, VEX_WIG; - defm Z256 : AESI_binop_rm_int(IntPrefix##"_256"), - loadv4i64, 0, VR256X, i256mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512, HasVAES] in - defm Z : AESI_binop_rm_int(IntPrefix##"_512"), - loadv8i64, 0, VR512, i512mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V512, VEX_WIG; -} - -defm VAESENC : avx512_vaes<0xDC, "vaesenc", "int_x86_aesni_aesenc">; -defm VAESENCLAST : avx512_vaes<0xDD, "vaesenclast", "int_x86_aesni_aesenclast">; -defm VAESDEC : avx512_vaes<0xDE, "vaesdec", "int_x86_aesni_aesdec">; -defm VAESDECLAST : avx512_vaes<0xDF, "vaesdeclast", "int_x86_aesni_aesdeclast">; - -//===----------------------------------------------------------------------===// -// PCLMUL instructions - Carry less multiplication -//===----------------------------------------------------------------------===// - -let Predicates = [HasAVX512, HasVPCLMULQDQ] in -defm VPCLMULQDQZ : vpclmulqdq, - EVEX_4V, EVEX_V512, EVEX_CD8<64, CD8VF>, VEX_WIG; - -let Predicates = [HasVLX, HasVPCLMULQDQ] in { -defm VPCLMULQDQZ128 : vpclmulqdq, - EVEX_4V, EVEX_V128, EVEX_CD8<64, CD8VF>, VEX_WIG; - -defm VPCLMULQDQZ256: vpclmulqdq, EVEX_4V, EVEX_V256, - EVEX_CD8<64, CD8VF>, VEX_WIG; -} - -// Aliases -//defm : vpclmulqdq_aliases<"VPCLMULQDQZ", VR512, i512mem>; -//defm : vpclmulqdq_aliases<"VPCLMULQDQZ128", VR128X, i128mem>; -//defm : vpclmulqdq_aliases<"VPCLMULQDQZ256", VR256X, i256mem>; - -//===----------------------------------------------------------------------===// -// VBMI2 -//===----------------------------------------------------------------------===// - -multiclass VBMI2_shift_var_rm Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> { - let Constraints = "$src1 = $dst", - ExeDomain = VTI.ExeDomain in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - defm m: AVX512_maskable_3src, - AVX512FMA3Base, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass VBMI2_shift_var_rmb Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> - : VBMI2_shift_var_rm { - let Constraints = "$src1 = $dst", - ExeDomain = VTI.ExeDomain in - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VBMI2_shift_var_rm_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTI> { - let Predicates = [HasVBMI2] in - defm Z : VBMI2_shift_var_rm, - EVEX_V512; - let Predicates = [HasVBMI2, HasVLX] in { - defm Z256 : VBMI2_shift_var_rm, - EVEX_V256; - defm Z128 : VBMI2_shift_var_rm, - EVEX_V128; - } -} - -multiclass VBMI2_shift_var_rmb_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTI> { - let Predicates = [HasVBMI2] in - defm Z : VBMI2_shift_var_rmb, - EVEX_V512; - let Predicates = [HasVBMI2, HasVLX] in { - defm Z256 : VBMI2_shift_var_rmb, - EVEX_V256; - defm Z128 : VBMI2_shift_var_rmb, - EVEX_V128; - } -} -multiclass VBMI2_shift_var wOp, bits<8> dqOp, string Prefix, - SDNode OpNode, X86SchedWriteWidths sched> { - defm W : VBMI2_shift_var_rm_common, VEX_W, EVEX_CD8<16, CD8VF>; - defm D : VBMI2_shift_var_rmb_common, EVEX_CD8<32, CD8VF>; - defm Q : VBMI2_shift_var_rmb_common, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass VBMI2_shift_imm wOp, bits<8> dqOp, string Prefix, - SDNode OpNode, X86SchedWriteWidths sched> { - defm W : avx512_common_3Op_rm_imm8, - VEX_W, EVEX_CD8<16, CD8VF>; - defm D : avx512_common_3Op_imm8, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - defm Q : avx512_common_3Op_imm8, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -} - -// Concat & Shift -defm VPSHLDV : VBMI2_shift_var<0x70, 0x71, "vpshldv", X86VShldv, SchedWriteVecIMul>; -defm VPSHRDV : VBMI2_shift_var<0x72, 0x73, "vpshrdv", X86VShrdv, SchedWriteVecIMul>; -defm VPSHLD : VBMI2_shift_imm<0x70, 0x71, "vpshld", X86VShld, SchedWriteVecIMul>; -defm VPSHRD : VBMI2_shift_imm<0x72, 0x73, "vpshrd", X86VShrd, SchedWriteVecIMul>; - -// Compress -defm VPCOMPRESSB : compress_by_elt_width<0x63, "vpcompressb", WriteVarShuffle256, - avx512vl_i8_info, HasVBMI2>, EVEX, - NotMemoryFoldable; -defm VPCOMPRESSW : compress_by_elt_width <0x63, "vpcompressw", WriteVarShuffle256, - avx512vl_i16_info, HasVBMI2>, EVEX, VEX_W, - NotMemoryFoldable; -// Expand -defm VPEXPANDB : expand_by_elt_width <0x62, "vpexpandb", WriteVarShuffle256, - avx512vl_i8_info, HasVBMI2>, EVEX; -defm VPEXPANDW : expand_by_elt_width <0x62, "vpexpandw", WriteVarShuffle256, - avx512vl_i16_info, HasVBMI2>, EVEX, VEX_W; - -//===----------------------------------------------------------------------===// -// VNNI -//===----------------------------------------------------------------------===// - -let Constraints = "$src1 = $dst" in -multiclass VNNI_rmb Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> { - defm r : AVX512_maskable_3src, - EVEX_4V, T8PD, Sched<[sched]>; - defm m : AVX512_maskable_3src, - EVEX_4V, EVEX_CD8<32, CD8VF>, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb : AVX512_maskable_3src, - EVEX_4V, EVEX_CD8<32, CD8VF>, EVEX_B, - T8PD, Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VNNI_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasVNNI] in - defm Z : VNNI_rmb, EVEX_V512; - let Predicates = [HasVNNI, HasVLX] in { - defm Z256 : VNNI_rmb, EVEX_V256; - defm Z128 : VNNI_rmb, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPDP? -defm VPDPBUSD : VNNI_common<0x50, "vpdpbusd", X86Vpdpbusd, SchedWriteVecIMul>; -defm VPDPBUSDS : VNNI_common<0x51, "vpdpbusds", X86Vpdpbusds, SchedWriteVecIMul>; -defm VPDPWSSD : VNNI_common<0x52, "vpdpwssd", X86Vpdpwssd, SchedWriteVecIMul>; -defm VPDPWSSDS : VNNI_common<0x53, "vpdpwssds", X86Vpdpwssds, SchedWriteVecIMul>; - -//===----------------------------------------------------------------------===// -// Bit Algorithms -//===----------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for VPOPCNTB/VPOPCNTW? -defm VPOPCNTB : avx512_unary_rm_vl<0x54, "vpopcntb", ctpop, SchedWriteVecALU, - avx512vl_i8_info, HasBITALG>; -defm VPOPCNTW : avx512_unary_rm_vl<0x54, "vpopcntw", ctpop, SchedWriteVecALU, - avx512vl_i16_info, HasBITALG>, VEX_W; - -defm : avx512_unary_lowering<"VPOPCNTB", ctpop, avx512vl_i8_info, HasBITALG>; -defm : avx512_unary_lowering<"VPOPCNTW", ctpop, avx512vl_i16_info, HasBITALG>; - -multiclass VPSHUFBITQMB_rm { - defm rr : AVX512_maskable_cmp<0x8F, MRMSrcReg, VTI, (outs VTI.KRC:$dst), - (ins VTI.RC:$src1, VTI.RC:$src2), - "vpshufbitqmb", - "$src2, $src1", "$src1, $src2", - (X86Vpshufbitqmb (VTI.VT VTI.RC:$src1), - (VTI.VT VTI.RC:$src2))>, EVEX_4V, T8PD, - Sched<[sched]>; - defm rm : AVX512_maskable_cmp<0x8F, MRMSrcMem, VTI, (outs VTI.KRC:$dst), - (ins VTI.RC:$src1, VTI.MemOp:$src2), - "vpshufbitqmb", - "$src2, $src1", "$src1, $src2", - (X86Vpshufbitqmb (VTI.VT VTI.RC:$src1), - (VTI.VT (bitconvert (VTI.LdFrag addr:$src2))))>, - EVEX_4V, EVEX_CD8<8, CD8VF>, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VPSHUFBITQMB_common { - let Predicates = [HasBITALG] in - defm Z : VPSHUFBITQMB_rm, EVEX_V512; - let Predicates = [HasBITALG, HasVLX] in { - defm Z256 : VPSHUFBITQMB_rm, EVEX_V256; - defm Z128 : VPSHUFBITQMB_rm, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPSHUFBITQMB? -defm VPSHUFBITQMB : VPSHUFBITQMB_common; - -//===----------------------------------------------------------------------===// -// GFNI -//===----------------------------------------------------------------------===// - -multiclass GF2P8MULB_avx512_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasGFNI, HasAVX512, HasBWI] in - defm Z : avx512_binop_rm, - EVEX_V512; - let Predicates = [HasGFNI, HasVLX, HasBWI] in { - defm Z256 : avx512_binop_rm, - EVEX_V256; - defm Z128 : avx512_binop_rm, - EVEX_V128; - } -} - -defm VGF2P8MULB : GF2P8MULB_avx512_common<0xCF, "vgf2p8mulb", X86GF2P8mulb, - SchedWriteVecALU>, - EVEX_CD8<8, CD8VF>, T8PD; - -multiclass GF2P8AFFINE_avx512_rmb_imm Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI, - X86VectorVTInfo BcstVTI> - : avx512_3Op_rm_imm8 { - let ExeDomain = VTI.ExeDomain in - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass GF2P8AFFINE_avx512_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasGFNI, HasAVX512, HasBWI] in - defm Z : GF2P8AFFINE_avx512_rmb_imm, EVEX_V512; - let Predicates = [HasGFNI, HasVLX, HasBWI] in { - defm Z256 : GF2P8AFFINE_avx512_rmb_imm, EVEX_V256; - defm Z128 : GF2P8AFFINE_avx512_rmb_imm, EVEX_V128; - } -} - -defm VGF2P8AFFINEINVQB : GF2P8AFFINE_avx512_common<0xCF, "vgf2p8affineinvqb", - X86GF2P8affineinvqb, SchedWriteVecIMul>, - EVEX_4V, EVEX_CD8<8, CD8VF>, VEX_W, AVX512AIi8Base; -defm VGF2P8AFFINEQB : GF2P8AFFINE_avx512_common<0xCE, "vgf2p8affineqb", - X86GF2P8affineqb, SchedWriteVecIMul>, - EVEX_4V, EVEX_CD8<8, CD8VF>, VEX_W, AVX512AIi8Base; - - -//===----------------------------------------------------------------------===// -// AVX5124FMAPS -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0, mayLoad = 1, ExeDomain = SSEPackedSingle, - Constraints = "$src1 = $dst" in { -defm V4FMADDPSrm : AVX512_maskable_3src_in_asm<0x9A, MRMSrcMem, v16f32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "v4fmaddps", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm V4FNMADDPSrm : AVX512_maskable_3src_in_asm<0xAA, MRMSrcMem, v16f32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "v4fnmaddps", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm V4FMADDSSrm : AVX512_maskable_3src_in_asm<0x9B, MRMSrcMem, f32x_info, - (outs VR128X:$dst), (ins VR128X:$src2, f128mem:$src3), - "v4fmaddss", "$src3, $src2", "$src2, $src3", - []>, EVEX_V128, EVEX_4V, T8XD, EVEX_CD8<32, CD8VF>, - Sched<[SchedWriteFMA.Scl.Folded]>; - -defm V4FNMADDSSrm : AVX512_maskable_3src_in_asm<0xAB, MRMSrcMem, f32x_info, - (outs VR128X:$dst), (ins VR128X:$src2, f128mem:$src3), - "v4fnmaddss", "$src3, $src2", "$src2, $src3", - []>, EVEX_V128, EVEX_4V, T8XD, EVEX_CD8<32, CD8VF>, - Sched<[SchedWriteFMA.Scl.Folded]>; -} - -//===----------------------------------------------------------------------===// -// AVX5124VNNIW -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0, mayLoad = 1, ExeDomain = SSEPackedInt, - Constraints = "$src1 = $dst" in { -defm VP4DPWSSDrm : AVX512_maskable_3src_in_asm<0x52, MRMSrcMem, v16i32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "vp4dpwssd", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm VP4DPWSSDSrm : AVX512_maskable_3src_in_asm<0x53, MRMSrcMem, v16i32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "vp4dpwssds", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; -} - diff --git a/suite/synctools/tablegen/X86/X86InstrArithmetic.td b/suite/synctools/tablegen/X86/X86InstrArithmetic.td deleted file mode 100644 index d150114c04..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrArithmetic.td +++ /dev/null @@ -1,1350 +0,0 @@ -//===-- X86InstrArithmetic.td - Integer Arithmetic Instrs --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the integer arithmetic instructions in the X86 -// architecture. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// LEA - Load Effective Address -let SchedRW = [WriteLEA] in { -let hasSideEffects = 0 in -def LEA16r : I<0x8D, MRMSrcMem, - (outs GR16:$dst), (ins anymem:$src), - "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize16; -let isReMaterializable = 1 in -def LEA32r : I<0x8D, MRMSrcMem, - (outs GR32:$dst), (ins anymem:$src), - "lea{l}\t{$src|$dst}, {$dst|$src}", - [(set GR32:$dst, lea32addr:$src)]>, - OpSize32, Requires<[Not64BitMode]>; - -def LEA64_32r : I<0x8D, MRMSrcMem, - (outs GR32:$dst), (ins lea64_32mem:$src), - "lea{l}\t{$src|$dst}, {$dst|$src}", - [(set GR32:$dst, lea64_32addr:$src)]>, - OpSize32, Requires<[In64BitMode]>; - -let isReMaterializable = 1 in -def LEA64r : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src), - "lea{q}\t{$src|$dst}, {$dst|$src}", - [(set GR64:$dst, lea64addr:$src)]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Fixed-Register Multiplication and Division Instructions. -// - -// SchedModel info for instruction that loads one value and gets the second -// (and possibly third) value from a register. -// This is used for instructions that put the memory operands before other -// uses. -class SchedLoadReg : Sched<[SW, - // Memory operand. - ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, - // Register reads (implicit or explicit). - ReadAfterLd, ReadAfterLd]>; - -// Extra precision multiplication - -// AL is really implied by AX, but the registers in Defs must match the -// SDNode results (i8, i32). -// AL,AH = AL*GR8 -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def MUL8r : I<0xF6, MRM4r, (outs), (ins GR8:$src), "mul{b}\t$src", - // FIXME: Used for 8-bit mul, ignore result upper 8 bits. - // This probably ought to be moved to a def : Pat<> if the - // syntax can be accepted. - [(set AL, (mul AL, GR8:$src)), - (implicit EFLAGS)]>, Sched<[WriteIMul]>; -// AX,DX = AX*GR16 -let Defs = [AX,DX,EFLAGS], Uses = [AX], hasSideEffects = 0 in -def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src), - "mul{w}\t$src", - []>, OpSize16, Sched<[WriteIMul]>; -// EAX,EDX = EAX*GR32 -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in -def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src), - "mul{l}\t$src", - [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>, - OpSize32, Sched<[WriteIMul]>; -// RAX,RDX = RAX*GR64 -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 in -def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src), - "mul{q}\t$src", - [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>, - Sched<[WriteIMul64]>; -// AL,AH = AL*[mem8] -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src), - "mul{b}\t$src", - // FIXME: Used for 8-bit mul, ignore result upper 8 bits. - // This probably ought to be moved to a def : Pat<> if the - // syntax can be accepted. - [(set AL, (mul AL, (loadi8 addr:$src))), - (implicit EFLAGS)]>, SchedLoadReg; -// AX,DX = AX*[mem16] -let mayLoad = 1, hasSideEffects = 0 in { -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src), - "mul{w}\t$src", []>, OpSize16, SchedLoadReg; -// EAX,EDX = EAX*[mem32] -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src), - "mul{l}\t$src", []>, OpSize32, SchedLoadReg; -// RAX,RDX = RAX*[mem64] -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src), - "mul{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} - -let hasSideEffects = 0 in { -// AL,AH = AL*GR8 -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>, - Sched<[WriteIMul]>; -// AX,DX = AX*GR16 -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>, - OpSize16, Sched<[WriteIMul]>; -// EAX,EDX = EAX*GR32 -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>, - OpSize32, Sched<[WriteIMul]>; -// RAX,RDX = RAX*GR64 -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", []>, - Sched<[WriteIMul64]>; - -let mayLoad = 1 in { -// AL,AH = AL*[mem8] -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src), - "imul{b}\t$src", []>, SchedLoadReg; -// AX,DX = AX*[mem16] -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src), - "imul{w}\t$src", []>, OpSize16, SchedLoadReg; -// EAX,EDX = EAX*[mem32] -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src), - "imul{l}\t$src", []>, OpSize32, SchedLoadReg; -// RAX,RDX = RAX*[mem64] -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src), - "imul{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} -} // hasSideEffects - - -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst" in { - -let isCommutable = 1 in { -// X = IMUL Y, Z --> X = IMUL Z, Y -// Register-Register Signed Integer Multiply -def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2), - "imul{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, GR16:$src2))]>, - Sched<[WriteIMul]>, TB, OpSize16; -def IMUL32rr : I<0xAF, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2), - "imul{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, GR32:$src2))]>, - Sched<[WriteIMul]>, TB, OpSize32; -def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "imul{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, GR64:$src2))]>, - Sched<[WriteIMul64]>, TB; -} // isCommutable - -// Register-Memory Signed Integer Multiply -def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$src1, i16mem:$src2), - "imul{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, (loadi16 addr:$src2)))]>, - Sched<[WriteIMul.Folded, ReadAfterLd]>, TB, OpSize16; -def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "imul{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, (loadi32 addr:$src2)))]>, - Sched<[WriteIMul.Folded, ReadAfterLd]>, TB, OpSize32; -def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "imul{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, (loadi64 addr:$src2)))]>, - Sched<[WriteIMul64.Folded, ReadAfterLd]>, TB; -} // Constraints = "$src1 = $dst" - -} // Defs = [EFLAGS] - -// Surprisingly enough, these are not two address instructions! -let Defs = [EFLAGS] in { -// Register-Integer Signed Integer Multiply -def IMUL16rri : Ii16<0x69, MRMSrcReg, // GR16 = GR16*I16 - (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, imm:$src2))]>, - Sched<[WriteIMul]>, OpSize16; -def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, // GR16 = GR16*I8 - (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, i16immSExt8:$src2))]>, - Sched<[WriteIMul]>, OpSize16; -def IMUL32rri : Ii32<0x69, MRMSrcReg, // GR32 = GR32*I32 - (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, imm:$src2))]>, - Sched<[WriteIMul]>, OpSize32; -def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // GR32 = GR32*I8 - (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, i32immSExt8:$src2))]>, - Sched<[WriteIMul]>, OpSize32; -def IMUL64rri32 : RIi32S<0x69, MRMSrcReg, // GR64 = GR64*I32 - (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, i64immSExt32:$src2))]>, - Sched<[WriteIMul64]>; -def IMUL64rri8 : RIi8<0x6B, MRMSrcReg, // GR64 = GR64*I8 - (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, i64immSExt8:$src2))]>, - Sched<[WriteIMul64]>; - -// Memory-Integer Signed Integer Multiply -def IMUL16rmi : Ii16<0x69, MRMSrcMem, // GR16 = [mem16]*I16 - (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag (loadi16 addr:$src1), imm:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize16; -def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem, // GR16 = [mem16]*I8 - (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize16; -def IMUL32rmi : Ii32<0x69, MRMSrcMem, // GR32 = [mem32]*I32 - (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag (loadi32 addr:$src1), imm:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize32; -def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8 - (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize32; -def IMUL64rmi32 : RIi32S<0x69, MRMSrcMem, // GR64 = [mem64]*I32 - (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag (loadi64 addr:$src1), - i64immSExt32:$src2))]>, - Sched<[WriteIMul64.Folded]>; -def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8 - (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag (loadi64 addr:$src1), - i64immSExt8:$src2))]>, - Sched<[WriteIMul64.Folded]>; -} // Defs = [EFLAGS] - -// unsigned division/remainder -let hasSideEffects = 1 in { // so that we don't speculatively execute -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH - "div{b}\t$src", []>, Sched<[WriteDiv8]>; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX - "div{w}\t$src", []>, Sched<[WriteDiv16]>, OpSize16; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in -def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX - "div{l}\t$src", []>, Sched<[WriteDiv32]>, OpSize32; -// RDX:RAX/r64 = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src), - "div{q}\t$src", []>, Sched<[WriteDiv64]>; - -let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH - "div{b}\t$src", []>, SchedLoadReg; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX - "div{w}\t$src", []>, OpSize16, SchedLoadReg; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX -def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), - "div{l}\t$src", []>, SchedLoadReg, OpSize32; -// RDX:RAX/[mem64] = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), - "div{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} - -// Signed division/remainder. -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH - "idiv{b}\t$src", []>, Sched<[WriteIDiv8]>; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX - "idiv{w}\t$src", []>, Sched<[WriteIDiv16]>, OpSize16; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in -def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX - "idiv{l}\t$src", []>, Sched<[WriteIDiv32]>, OpSize32; -// RDX:RAX/r64 = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src), - "idiv{q}\t$src", []>, Sched<[WriteIDiv64]>; - -let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH - "idiv{b}\t$src", []>, SchedLoadReg; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX - "idiv{w}\t$src", []>, OpSize16, SchedLoadReg; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX -def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), - "idiv{l}\t$src", []>, OpSize32, SchedLoadReg; -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX -def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src), - "idiv{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 - -//===----------------------------------------------------------------------===// -// Two address Instructions. -// - -// unary instructions -let CodeSize = 2 in { -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1), - "neg{b}\t$dst", - [(set GR8:$dst, (ineg GR8:$src1)), - (implicit EFLAGS)]>; -def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "neg{w}\t$dst", - [(set GR16:$dst, (ineg GR16:$src1)), - (implicit EFLAGS)]>, OpSize16; -def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "neg{l}\t$dst", - [(set GR32:$dst, (ineg GR32:$src1)), - (implicit EFLAGS)]>, OpSize32; -def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst", - [(set GR64:$dst, (ineg GR64:$src1)), - (implicit EFLAGS)]>; -} // Constraints = "$src1 = $dst", SchedRW - -// Read-modify-write negate. -let SchedRW = [WriteALURMW] in { -def NEG8m : I<0xF6, MRM3m, (outs), (ins i8mem :$dst), - "neg{b}\t$dst", - [(store (ineg (loadi8 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>; -def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst), - "neg{w}\t$dst", - [(store (ineg (loadi16 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, OpSize16; -def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst), - "neg{l}\t$dst", - [(store (ineg (loadi32 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst", - [(store (ineg (loadi64 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, - Requires<[In64BitMode]>; -} // SchedRW -} // Defs = [EFLAGS] - - -// Note: NOT does not set EFLAGS! - -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1), - "not{b}\t$dst", - [(set GR8:$dst, (not GR8:$src1))]>; -def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "not{w}\t$dst", - [(set GR16:$dst, (not GR16:$src1))]>, OpSize16; -def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "not{l}\t$dst", - [(set GR32:$dst, (not GR32:$src1))]>, OpSize32; -def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src1), "not{q}\t$dst", - [(set GR64:$dst, (not GR64:$src1))]>; -} // Constraints = "$src1 = $dst", SchedRW - -let SchedRW = [WriteALURMW] in { -def NOT8m : I<0xF6, MRM2m, (outs), (ins i8mem :$dst), - "not{b}\t$dst", - [(store (not (loadi8 addr:$dst)), addr:$dst)]>; -def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst), - "not{w}\t$dst", - [(store (not (loadi16 addr:$dst)), addr:$dst)]>, - OpSize16; -def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst), - "not{l}\t$dst", - [(store (not (loadi32 addr:$dst)), addr:$dst)]>, - OpSize32; -def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst", - [(store (not (loadi64 addr:$dst)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW -} // CodeSize - -// TODO: inc/dec is slow for P4, but fast for Pentium-M. -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -let CodeSize = 2 in -def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "inc{b}\t$dst", - [(set GR8:$dst, EFLAGS, (X86inc_flag GR8:$src1))]>; -let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA. -def INC16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "inc{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86inc_flag GR16:$src1))]>, OpSize16; -def INC32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "inc{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86inc_flag GR32:$src1))]>, OpSize32; -def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86inc_flag GR64:$src1))]>; -} // isConvertibleToThreeAddress = 1, CodeSize = 2 - -// Short forms only valid in 32-bit mode. Selected during MCInst lowering. -let CodeSize = 1, hasSideEffects = 0 in { -def INC16r_alt : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1), - "inc{w}\t$dst", []>, - OpSize16, Requires<[Not64BitMode]>; -def INC32r_alt : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1), - "inc{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // CodeSize = 1, hasSideEffects = 0 -} // Constraints = "$src1 = $dst", SchedRW - -let CodeSize = 2, SchedRW = [WriteALURMW] in { -let Predicates = [UseIncDec] in { - def INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst", - [(store (add (loadi8 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>; - def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst", - [(store (add (loadi16 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>, OpSize16; - def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst", - [(store (add (loadi32 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -} // Predicates -let Predicates = [UseIncDec, In64BitMode] in { - def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst", - [(store (add (loadi64 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>; -} // Predicates -} // CodeSize = 2, SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -let CodeSize = 2 in -def DEC8r : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "dec{b}\t$dst", - [(set GR8:$dst, EFLAGS, (X86dec_flag GR8:$src1))]>; -let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA. -def DEC16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "dec{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86dec_flag GR16:$src1))]>, OpSize16; -def DEC32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "dec{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86dec_flag GR32:$src1))]>, OpSize32; -def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src1), "dec{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86dec_flag GR64:$src1))]>; -} // isConvertibleToThreeAddress = 1, CodeSize = 2 - -// Short forms only valid in 32-bit mode. Selected during MCInst lowering. -let CodeSize = 1, hasSideEffects = 0 in { -def DEC16r_alt : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1), - "dec{w}\t$dst", []>, - OpSize16, Requires<[Not64BitMode]>; -def DEC32r_alt : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1), - "dec{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // CodeSize = 1, hasSideEffects = 0 -} // Constraints = "$src1 = $dst", SchedRW - - -let CodeSize = 2, SchedRW = [WriteALURMW] in { -let Predicates = [UseIncDec] in { - def DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst", - [(store (add (loadi8 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>; - def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst", - [(store (add (loadi16 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>, OpSize16; - def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst", - [(store (add (loadi32 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -} // Predicates -let Predicates = [UseIncDec, In64BitMode] in { - def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst", - [(store (add (loadi64 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>; -} // Predicates -} // CodeSize = 2, SchedRW -} // Defs = [EFLAGS] - -/// X86TypeInfo - This is a bunch of information that describes relevant X86 -/// information about value types. For example, it can tell you what the -/// register class and preferred load to use. -class X86TypeInfo { - /// VT - This is the value type itself. - ValueType VT = vt; - - /// InstrSuffix - This is the suffix used on instructions with this type. For - /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q". - string InstrSuffix = instrsuffix; - - /// RegClass - This is the register class associated with this type. For - /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64. - RegisterClass RegClass = regclass; - - /// LoadNode - This is the load node associated with this type. For - /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64. - PatFrag LoadNode = loadnode; - - /// MemOperand - This is the memory operand associated with this type. For - /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem. - X86MemOperand MemOperand = memoperand; - - /// ImmEncoding - This is the encoding of an immediate of this type. For - /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32 - /// since the immediate fields of i64 instructions is a 32-bit sign extended - /// value. - ImmType ImmEncoding = immkind; - - /// ImmOperand - This is the operand kind of an immediate of this type. For - /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 -> - /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign - /// extended value. - Operand ImmOperand = immoperand; - - /// ImmOperator - This is the operator that should be used to match an - /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32). - SDPatternOperator ImmOperator = immoperator; - - /// Imm8Operand - This is the operand kind to use for an imm8 of this type. - /// For example, i8 -> , i16 -> i16i8imm, i32 -> i32i8imm. This is - /// only used for instructions that have a sign-extended imm8 field form. - Operand Imm8Operand = imm8operand; - - /// Imm8Operator - This is the operator that should be used to match an 8-bit - /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8). - SDPatternOperator Imm8Operator = imm8operator; - - /// HasOddOpcode - This bit is true if the instruction should have an odd (as - /// opposed to even) opcode. Operations on i8 are usually even, operations on - /// other datatypes are odd. - bit HasOddOpcode = hasOddOpcode; - - /// OpSize - Selects whether the instruction needs a 0x66 prefix based on - /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this - /// to Opsize16. i32 sets this to OpSize32. - OperandSize OpSize = opSize; - - /// HasREX_WPrefix - This bit is set to true if the instruction should have - /// the 0x40 REX prefix. This is set for i64 types. - bit HasREX_WPrefix = hasREX_WPrefix; -} - -def invalid_node : SDNode<"<>", SDTIntLeaf,[],"<>">; - - -def Xi8 : X86TypeInfo; -def Xi16 : X86TypeInfo; -def Xi32 : X86TypeInfo; -def Xi64 : X86TypeInfo; - -/// ITy - This instruction base class takes the type info for the instruction. -/// Using this, it: -/// 1. Concatenates together the instruction mnemonic with the appropriate -/// suffix letter, a tab, and the arguments. -/// 2. Infers whether the instruction should have a 0x66 prefix byte. -/// 3. Infers whether the instruction should have a 0x40 REX_W prefix. -/// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations) -/// or 1 (for i16,i32,i64 operations). -class ITy opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins, - string mnemonic, string args, list pattern> - : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4}, - opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode }, - f, outs, ins, - !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> { - - // Infer instruction prefixes from type info. - let OpSize = typeinfo.OpSize; - let hasREX_WPrefix = typeinfo.HasREX_WPrefix; -} - -// BinOpRR - Instructions like "add reg, reg, reg". -class BinOpRR opcode, string mnemonic, X86TypeInfo typeinfo, - dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]>; - -// BinOpRR_F - Instructions like "cmp reg, Reg", where the pattern has -// just a EFLAGS as a result. -class BinOpRR_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode> - : BinOpRR; - -// BinOpRR_RF - Instructions like "add reg, reg, reg", where the pattern has -// both a regclass and EFLAGS as a result. -class BinOpRR_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRR; - -// BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has -// both a regclass and EFLAGS as a result, and has EFLAGS as input. -class BinOpRR_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRR; - -// BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding). -class BinOpRR_Rev opcode, string mnemonic, X86TypeInfo typeinfo, - X86FoldableSchedWrite sched = WriteALU> - : ITy, - Sched<[sched]> { - // The disassembler should know about this, but not the asmparser. - let isCodeGenOnly = 1; - let ForceDisassemble = 1; - let hasSideEffects = 0; -} - -// BinOpRR_RDD_Rev - Instructions like "adc reg, reg, reg" (reversed encoding). -class BinOpRR_RFF_Rev opcode, string mnemonic, X86TypeInfo typeinfo> - : BinOpRR_Rev; - -// BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding). -class BinOpRR_F_Rev opcode, string mnemonic, X86TypeInfo typeinfo> - : ITy, - Sched<[WriteALU]> { - // The disassembler should know about this, but not the asmparser. - let isCodeGenOnly = 1; - let ForceDisassemble = 1; - let hasSideEffects = 0; -} - -// BinOpRM - Instructions like "add reg, reg, [mem]". -class BinOpRM opcode, string mnemonic, X86TypeInfo typeinfo, - dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched.Folded, ReadAfterLd]>; - -// BinOpRM_F - Instructions like "cmp reg, [mem]". -class BinOpRM_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRM_RF - Instructions like "add reg, reg, [mem]". -class BinOpRM_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRM_RFF - Instructions like "adc reg, reg, [mem]". -class BinOpRM_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRI - Instructions like "add reg, reg, imm". -class BinOpRI opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]> { - let ImmT = typeinfo.ImmEncoding; -} - -// BinOpRI_F - Instructions like "cmp reg, imm". -class BinOpRI_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI; - -// BinOpRI_RF - Instructions like "add reg, reg, imm". -class BinOpRI_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpRI; -// BinOpRI_RFF - Instructions like "adc reg, reg, imm". -class BinOpRI_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpRI; - -// BinOpRI8 - Instructions like "add reg, reg, imm8". -class BinOpRI8 opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]> { - let ImmT = Imm8; // Always 8-bit immediate. -} - -// BinOpRI8_F - Instructions like "cmp reg, imm8". -class BinOpRI8_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpRI8_RF - Instructions like "add reg, reg, imm8". -class BinOpRI8_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpRI8_RFF - Instructions like "adc reg, reg, imm8". -class BinOpRI8_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpMR - Instructions like "add [mem], reg". -class BinOpMR opcode, string mnemonic, X86TypeInfo typeinfo, - list pattern> - : ITy; - -// BinOpMR_RMW - Instructions like "add [mem], reg". -class BinOpMR_RMW opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpMR, Sched<[WriteALURMW]>; - -// BinOpMR_RMW_FF - Instructions like "adc [mem], reg". -class BinOpMR_RMW_FF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpMR, Sched<[WriteADCRMW]>; - -// BinOpMR_F - Instructions like "cmp [mem], reg". -class BinOpMR_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode> - : BinOpMR, - Sched<[WriteALULd, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, ReadDefault, ReadAfterLd]>; - -// BinOpMI - Instructions like "add [mem], imm". -class BinOpMI opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, list pattern> - : ITy { - let ImmT = typeinfo.ImmEncoding; -} - -// BinOpMI_RMW - Instructions like "add [mem], imm". -class BinOpMI_RMW opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpMI, Sched<[WriteALURMW]>; -// BinOpMI_RMW_FF - Instructions like "adc [mem], imm". -class BinOpMI_RMW_FF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpMI, Sched<[WriteADCRMW]>; - -// BinOpMI_F - Instructions like "cmp [mem], imm". -class BinOpMI_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpMI, - Sched<[WriteALULd]>; - -// BinOpMI8 - Instructions like "add [mem], imm8". -class BinOpMI8 pattern> - : ITy<0x82, f, typeinfo, - (outs), (ins typeinfo.MemOperand:$dst, typeinfo.Imm8Operand:$src), - mnemonic, "{$src, $dst|$dst, $src}", pattern> { - let ImmT = Imm8; // Always 8-bit immediate. -} - -// BinOpMI8_RMW - Instructions like "add [mem], imm8". -class BinOpMI8_RMW - : BinOpMI8, Sched<[WriteALURMW]>; - -// BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8". -class BinOpMI8_RMW_FF - : BinOpMI8, Sched<[WriteADCRMW]>; - -// BinOpMI8_F - Instructions like "cmp [mem], imm8". -class BinOpMI8_F - : BinOpMI8, - Sched<[WriteALULd]>; - -// BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS. -class BinOpAI opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands, X86FoldableSchedWrite sched = WriteALU> - : ITy, Sched<[sched]> { - let ImmT = typeinfo.ImmEncoding; - let Uses = [areg]; - let Defs = [areg, EFLAGS]; - let hasSideEffects = 0; -} - -// BinOpAI_RFF - Instructions like "adc %eax, %eax, imm", that implicitly define -// and use EFLAGS. -class BinOpAI_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands> - : BinOpAI { - let Uses = [areg, EFLAGS]; -} - -// BinOpAI_F - Instructions like "cmp %eax, %eax, imm", that imp-def EFLAGS. -class BinOpAI_F opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands> - : BinOpAI { - let Defs = [EFLAGS]; -} - -/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is -/// defined with "(set GPR:$dst, EFLAGS, (...". -/// -/// It would be nice to get rid of the second and third argument here, but -/// tblgen can't handle dependent type references aggressively enough: PR8330 -multiclass ArithBinOp_RF BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnodeflag, SDNode opnode, - bit CommutableRR, bit ConvertibleToThreeAddress> { - let Defs = [EFLAGS] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_RF; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_RF; - def NAME#32rr : BinOpRR_RF; - def NAME#64rr : BinOpRR_RF; - } // isConvertibleToThreeAddress - } // isCommutable - - def NAME#8rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_RF; - def NAME#16rm : BinOpRM_RF; - def NAME#32rm : BinOpRM_RF; - def NAME#64rm : BinOpRM_RF; - - def NAME#8ri : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>; - def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>; - def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>; - - def NAME#16ri : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>; - def NAME#32ri : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>; - def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>; - } - } // Constraints = "$src1 = $dst" - - let mayLoad = 1, mayStore = 1 in { - def NAME#8mr : BinOpMR_RMW; - def NAME#16mr : BinOpMR_RMW; - def NAME#32mr : BinOpMR_RMW; - def NAME#64mr : BinOpMR_RMW; - } - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_RMW; - def NAME#32mi8 : BinOpMI8_RMW; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_RMW; - - def NAME#8mi : BinOpMI_RMW<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_RMW<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_RMW<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_RMW<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - let Constraints = "$src1 = $dst" in - def NAME#8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1, mayStore = 1 in - def NAME#8mi8 : BinOpMI8_RMW; - } - } // Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI; - def NAME#16i16 : BinOpAI; - def NAME#32i32 : BinOpAI; - def NAME#64i32 : BinOpAI; -} - -/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is -/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and -/// SBB. -/// -/// It would be nice to get rid of the second and third argument here, but -/// tblgen can't handle dependent type references aggressively enough: PR8330 -multiclass ArithBinOp_RFF BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnode, bit CommutableRR, - bit ConvertibleToThreeAddress> { - let Uses = [EFLAGS], Defs = [EFLAGS] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_RFF; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_RFF; - def NAME#32rr : BinOpRR_RFF; - def NAME#64rr : BinOpRR_RFF; - } // isConvertibleToThreeAddress - } // isCommutable - - def NAME#8rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_RFF_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_RFF; - def NAME#16rm : BinOpRM_RFF; - def NAME#32rm : BinOpRM_RFF; - def NAME#64rm : BinOpRM_RFF; - - def NAME#8ri : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>; - - def NAME#16ri : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>; - } - } // Constraints = "$src1 = $dst" - - def NAME#8mr : BinOpMR_RMW_FF; - def NAME#16mr : BinOpMR_RMW_FF; - def NAME#32mr : BinOpMR_RMW_FF; - def NAME#64mr : BinOpMR_RMW_FF; - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_RMW_FF; - def NAME#32mi8 : BinOpMI8_RMW_FF; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_RMW_FF; - - def NAME#8mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_RMW_FF<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - let Constraints = "$src1 = $dst" in - def NAME#8ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1, mayStore = 1 in - def NAME#8mi8 : BinOpMI8_RMW_FF; - } - } // Uses = [EFLAGS], Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI_RFF; - def NAME#16i16 : BinOpAI_RFF; - def NAME#32i32 : BinOpAI_RFF; - def NAME#64i32 : BinOpAI_RFF; -} - -/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is -/// defined with "(set EFLAGS, (...". It would be really nice to find a way -/// to factor this with the other ArithBinOp_*. -/// -multiclass ArithBinOp_F BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnode, - bit CommutableRR, bit ConvertibleToThreeAddress> { - let Defs = [EFLAGS] in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_F; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_F; - def NAME#32rr : BinOpRR_F; - def NAME#64rr : BinOpRR_F; - } - } // isCommutable - - def NAME#8rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_F_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_F; - def NAME#16rm : BinOpRM_F; - def NAME#32rm : BinOpRM_F; - def NAME#64rm : BinOpRM_F; - - def NAME#8ri : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>; - - def NAME#16ri : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>; - } - - def NAME#8mr : BinOpMR_F; - def NAME#16mr : BinOpMR_F; - def NAME#32mr : BinOpMR_F; - def NAME#64mr : BinOpMR_F; - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_F; - def NAME#32mi8 : BinOpMI8_F; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_F; - - def NAME#8mi : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_F<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_F<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_F<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - def NAME#8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1 in - def NAME#8mi8 : BinOpMI8_F; - } - } // Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI_F; - def NAME#16i16 : BinOpAI_F; - def NAME#32i32 : BinOpAI_F; - def NAME#64i32 : BinOpAI_F; -} - - -defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m, - X86and_flag, and, 1, 0>; -defm OR : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m, - X86or_flag, or, 1, 0>; -defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m, - X86xor_flag, xor, 1, 0>; -defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m, - X86add_flag, add, 1, 1>; -let isCompare = 1 in { -defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m, - X86sub_flag, sub, 0, 0>; -} - -// Arithmetic. -defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag, - 1, 0>; -defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag, - 0, 0>; - -let isCompare = 1 in { -defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>; -} - - -//===----------------------------------------------------------------------===// -// Semantically, test instructions are similar like AND, except they don't -// generate a result. From an encoding perspective, they are very different: -// they don't have all the usual imm8 and REV forms, and are encoded into a -// different space. -def X86testpat : PatFrag<(ops node:$lhs, node:$rhs), - (X86cmp (and_su node:$lhs, node:$rhs), 0)>; - -let isCompare = 1 in { - let Defs = [EFLAGS] in { - let isCommutable = 1 in { - def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat>; - def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat>; - def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat>; - def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat>; - } // isCommutable - - def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , X86testpat>; - def TEST16mr : BinOpMR_F<0x84, "test", Xi16, X86testpat>; - def TEST32mr : BinOpMR_F<0x84, "test", Xi32, X86testpat>; - def TEST64mr : BinOpMR_F<0x84, "test", Xi64, X86testpat>; - - def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>; - def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>; - def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>; - let Predicates = [In64BitMode] in - def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>; - - def TEST8mi : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>; - def TEST16mi : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM0m>; - def TEST32mi : BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM0m>; - let Predicates = [In64BitMode] in - def TEST64mi32 : BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM0m>; - - def TEST8mi_alt: BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM1m>; - def TEST16mi_alt : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM1m>; - def TEST32mi_alt: BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM1m>; - let Predicates = [In64BitMode] in - def TEST64mi32_alt: BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM1m>; - - def TEST8ri_alt : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM1r>; - def TEST16ri_alt : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM1r>; - def TEST32ri_alt : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM1r>; - let Predicates = [In64BitMode] in - def TEST64ri32_alt : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM1r>; - } // Defs = [EFLAGS] - - def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL, - "{$src, %al|al, $src}">; - def TEST16i16 : BinOpAI_F<0xA8, "test", Xi16, AX, - "{$src, %ax|ax, $src}">; - def TEST32i32 : BinOpAI_F<0xA8, "test", Xi32, EAX, - "{$src, %eax|eax, $src}">; - def TEST64i32 : BinOpAI_F<0xA8, "test", Xi64, RAX, - "{$src, %rax|rax, $src}">; -} // isCompare - -//===----------------------------------------------------------------------===// -// ANDN Instruction -// -multiclass bmi_andn { - def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))]>, - Sched<[WriteALU]>; - def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, EFLAGS, - (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))]>, - Sched<[WriteALULd, ReadAfterLd]>; -} - -// Complexity is reduced to give and with immediate a chance to match first. -let Predicates = [HasBMI], Defs = [EFLAGS], AddedComplexity = -6 in { - defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8PS, VEX_4V; - defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8PS, VEX_4V, VEX_W; -} - -let Predicates = [HasBMI], AddedComplexity = -6 in { - def : Pat<(and (not GR32:$src1), GR32:$src2), - (ANDN32rr GR32:$src1, GR32:$src2)>; - def : Pat<(and (not GR64:$src1), GR64:$src2), - (ANDN64rr GR64:$src1, GR64:$src2)>; - def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)), - (ANDN32rm GR32:$src1, addr:$src2)>; - def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)), - (ANDN64rm GR64:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// MULX Instruction -// -multiclass bmi_mulx { -let hasSideEffects = 0 in { - let isCommutable = 1 in - def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), - []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>; - - let mayLoad = 1 in - def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), - []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>; -} -} - -let Predicates = [HasBMI2] in { - let Uses = [EDX] in - defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem, WriteIMul>; - let Uses = [RDX] in - defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem, WriteIMul64>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// ADCX and ADOX Instructions -// -let Predicates = [HasADX], Defs = [EFLAGS], Uses = [EFLAGS], - Constraints = "$src1 = $dst", AddedComplexity = 10 in { - let SchedRW = [WriteADC] in { - def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "adcx{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86adc_flag GR32:$src1, GR32:$src2, EFLAGS))]>, T8PD; - def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "adcx{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86adc_flag GR64:$src1, GR64:$src2, EFLAGS))]>, T8PD; - - // We don't have patterns for ADOX yet. - let hasSideEffects = 0 in { - def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - - def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - } // hasSideEffects = 0 - } // SchedRW - - let mayLoad = 1, SchedRW = [WriteADCLd, ReadAfterLd] in { - def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "adcx{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86adc_flag GR32:$src1, (loadi32 addr:$src2), EFLAGS))]>, - T8PD; - - def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "adcx{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86adc_flag GR64:$src1, (loadi64 addr:$src2), EFLAGS))]>, - T8PD; - - // We don't have patterns for ADOX yet. - let hasSideEffects = 0 in { - def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - - def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - } // hasSideEffects = 0 - } // mayLoad = 1, SchedRW = [WriteADCLd] -} diff --git a/suite/synctools/tablegen/X86/X86InstrCMovSetCC.td b/suite/synctools/tablegen/X86/X86InstrCMovSetCC.td deleted file mode 100644 index eda4ba5ae6..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrCMovSetCC.td +++ /dev/null @@ -1,116 +0,0 @@ -//===-- X86InstrCMovSetCC.td - Conditional Move and SetCC --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 conditional move and set on condition -// instructions. -// -//===----------------------------------------------------------------------===// - - -// CMOV instructions. -multiclass CMOV opc, string Mnemonic, X86FoldableSchedWrite Sched, - PatLeaf CondNode> { - let Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst", - isCommutable = 1, SchedRW = [Sched] in { - def NAME#16rr - : I, - TB, OpSize16; - def NAME#32rr - : I, - TB, OpSize32; - def NAME#64rr - :RI, TB; - } - - let Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst", - SchedRW = [Sched.Folded, ReadAfterLd] in { - def NAME#16rm - : I, TB, OpSize16; - def NAME#32rm - : I, TB, OpSize32; - def NAME#64rm - :RI, TB; - } // Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst" -} // end multiclass - - -// Conditional Moves. -defm CMOVO : CMOV<0x40, "cmovo" , WriteCMOV, X86_COND_O>; -defm CMOVNO : CMOV<0x41, "cmovno", WriteCMOV, X86_COND_NO>; -defm CMOVB : CMOV<0x42, "cmovb" , WriteCMOV, X86_COND_B>; -defm CMOVAE : CMOV<0x43, "cmovae", WriteCMOV, X86_COND_AE>; -defm CMOVE : CMOV<0x44, "cmove" , WriteCMOV, X86_COND_E>; -defm CMOVNE : CMOV<0x45, "cmovne", WriteCMOV, X86_COND_NE>; -defm CMOVBE : CMOV<0x46, "cmovbe", WriteCMOV2, X86_COND_BE>; -defm CMOVA : CMOV<0x47, "cmova" , WriteCMOV2, X86_COND_A>; -defm CMOVS : CMOV<0x48, "cmovs" , WriteCMOV, X86_COND_S>; -defm CMOVNS : CMOV<0x49, "cmovns", WriteCMOV, X86_COND_NS>; -defm CMOVP : CMOV<0x4A, "cmovp" , WriteCMOV, X86_COND_P>; -defm CMOVNP : CMOV<0x4B, "cmovnp", WriteCMOV, X86_COND_NP>; -defm CMOVL : CMOV<0x4C, "cmovl" , WriteCMOV, X86_COND_L>; -defm CMOVGE : CMOV<0x4D, "cmovge", WriteCMOV, X86_COND_GE>; -defm CMOVLE : CMOV<0x4E, "cmovle", WriteCMOV, X86_COND_LE>; -defm CMOVG : CMOV<0x4F, "cmovg" , WriteCMOV, X86_COND_G>; - - -// SetCC instructions. -multiclass SETCC opc, string Mnemonic, PatLeaf OpNode> { - let Uses = [EFLAGS] in { - def r : I, - TB, Sched<[WriteSETCC]>; - def m : I, - TB, Sched<[WriteSETCCStore]>; - } // Uses = [EFLAGS] -} - -defm SETO : SETCC<0x90, "seto", X86_COND_O>; // is overflow bit set -defm SETNO : SETCC<0x91, "setno", X86_COND_NO>; // is overflow bit not set -defm SETB : SETCC<0x92, "setb", X86_COND_B>; // unsigned less than -defm SETAE : SETCC<0x93, "setae", X86_COND_AE>; // unsigned greater or equal -defm SETE : SETCC<0x94, "sete", X86_COND_E>; // equal to -defm SETNE : SETCC<0x95, "setne", X86_COND_NE>; // not equal to -defm SETBE : SETCC<0x96, "setbe", X86_COND_BE>; // unsigned less than or equal -defm SETA : SETCC<0x97, "seta", X86_COND_A>; // unsigned greater than -defm SETS : SETCC<0x98, "sets", X86_COND_S>; // is signed bit set -defm SETNS : SETCC<0x99, "setns", X86_COND_NS>; // is not signed -defm SETP : SETCC<0x9A, "setp", X86_COND_P>; // is parity bit set -defm SETNP : SETCC<0x9B, "setnp", X86_COND_NP>; // is parity bit not set -defm SETL : SETCC<0x9C, "setl", X86_COND_L>; // signed less than -defm SETGE : SETCC<0x9D, "setge", X86_COND_GE>; // signed greater or equal -defm SETLE : SETCC<0x9E, "setle", X86_COND_LE>; // signed less than or equal -defm SETG : SETCC<0x9F, "setg", X86_COND_G>; // signed greater than - -// SALC is an undocumented instruction. Information for this instruction can be found -// here http://www.rcollins.org/secrets/opcodes/SALC.html -// Set AL if carry. -let Uses = [EFLAGS], Defs = [AL], SchedRW = [WriteALU] in { - def SALC : I<0xD6, RawFrm, (outs), (ins), "salc", []>, Requires<[Not64BitMode]>; -} diff --git a/suite/synctools/tablegen/X86/X86InstrCompiler.td b/suite/synctools/tablegen/X86/X86InstrCompiler.td deleted file mode 100644 index 76b93bdada..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrCompiler.td +++ /dev/null @@ -1,2103 +0,0 @@ -//===- X86InstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the various pseudo instructions used by the compiler, -// as well as Pat patterns used during instruction selection. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Pattern Matching Support - -def GetLo32XForm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def GetLo8XForm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - - -//===----------------------------------------------------------------------===// -// Random Pseudo Instructions. - -// PIC base construction. This expands to code that looks like this: -// call $next_inst -// popl %destreg" -let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP], - SchedRW = [WriteJump] in - def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label), - "", []>; - -// 64-bit large code model PIC base construction. -let hasSideEffects = 0, mayLoad = 1, isNotDuplicable = 1, SchedRW = [WriteJump] in - def MOVGOT64r : PseudoI<(outs GR64:$reg), - (ins GR64:$scratch, i64i32imm_pcrel:$got), []>; - -// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into -// a stack adjustment and the codegen must know that they may modify the stack -// pointer before prolog-epilog rewriting occurs. -// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become -// sub / add which can clobber EFLAGS. -let Defs = [ESP, EFLAGS, SSP], Uses = [ESP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), - "#ADJCALLSTACKDOWN", []>, Requires<[NotLP64]>; -def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), - "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)]>, - Requires<[NotLP64]>; -} -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN32 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[NotLP64]>; - - -// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into -// a stack adjustment and the codegen must know that they may modify the stack -// pointer before prolog-epilog rewriting occurs. -// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become -// sub / add which can clobber EFLAGS. -let Defs = [RSP, EFLAGS, SSP], Uses = [RSP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), - "#ADJCALLSTACKDOWN", []>, Requires<[IsLP64]>; -def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), - "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)]>, - Requires<[IsLP64]>; -} -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN64 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[IsLP64]>; - -let SchedRW = [WriteSystem] in { - -// x86-64 va_start lowering magic. -let usesCustomInserter = 1, Defs = [EFLAGS] in { -def VASTART_SAVE_XMM_REGS : I<0, Pseudo, - (outs), - (ins GR8:$al, - i64imm:$regsavefi, i64imm:$offset, - variable_ops), - "#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset", - [(X86vastart_save_xmm_regs GR8:$al, - imm:$regsavefi, - imm:$offset), - (implicit EFLAGS)]>; - -// The VAARG_64 pseudo-instruction takes the address of the va_list, -// and places the address of the next argument into a register. -let Defs = [EFLAGS] in -def VAARG_64 : I<0, Pseudo, - (outs GR64:$dst), - (ins i8mem:$ap, i32imm:$size, i8imm:$mode, i32imm:$align), - "#VAARG_64 $dst, $ap, $size, $mode, $align", - [(set GR64:$dst, - (X86vaarg64 addr:$ap, imm:$size, imm:$mode, imm:$align)), - (implicit EFLAGS)]>; - - -// When using segmented stacks these are lowered into instructions which first -// check if the current stacklet has enough free memory. If it does, memory is -// allocated by bumping the stack pointer. Otherwise memory is allocated from -// the heap. - -let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in -def SEG_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size), - "# variable sized alloca for segmented stacks", - [(set GR32:$dst, - (X86SegAlloca GR32:$size))]>, - Requires<[NotLP64]>; - -let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in -def SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size), - "# variable sized alloca for segmented stacks", - [(set GR64:$dst, - (X86SegAlloca GR64:$size))]>, - Requires<[In64BitMode]>; -} - -// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows -// targets. These calls are needed to probe the stack when allocating more than -// 4k bytes in one go. Touching the stack at 4K increments is necessary to -// ensure that the guard pages used by the OS virtual memory manager are -// allocated in correct sequence. -// The main point of having separate instruction are extra unmodelled effects -// (compared to ordinary calls) like stack pointer change. - -let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in -def WIN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR32:$size)]>, - Requires<[NotLP64]>; - -let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in -def WIN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR64:$size)]>, - Requires<[In64BitMode]>; -} // SchedRW - -// These instructions XOR the frame pointer into a GPR. They are used in some -// stack protection schemes. These are post-RA pseudos because we only know the -// frame register after register allocation. -let Constraints = "$src = $dst", isPseudo = 1, Defs = [EFLAGS] in { - def XOR32_FP : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src), - "xorl\t$$FP, $src", []>, - Requires<[NotLP64]>, Sched<[WriteALU]>; - def XOR64_FP : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src), - "xorq\t$$FP $src", []>, - Requires<[In64BitMode]>, Sched<[WriteALU]>; -} - -//===----------------------------------------------------------------------===// -// EH Pseudo Instructions -// -let SchedRW = [WriteSystem] in { -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, isCodeGenOnly = 1 in { -def EH_RETURN : I<0xC3, RawFrm, (outs), (ins GR32:$addr), - "ret\t#eh_return, addr: $addr", - [(X86ehret GR32:$addr)]>, Sched<[WriteJumpLd]>; - -} - -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, isCodeGenOnly = 1 in { -def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), - "ret\t#eh_return, addr: $addr", - [(X86ehret GR64:$addr)]>, Sched<[WriteJumpLd]>; - -} - -let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, - isCodeGenOnly = 1, isReturn = 1 in { - def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>; - - // CATCHRET needs a custom inserter for SEH. - let usesCustomInserter = 1 in - def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst, brtarget32:$from), - "# CATCHRET", - [(catchret bb:$dst, bb:$from)]>; -} - -let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1, - usesCustomInserter = 1 in -def CATCHPAD : I<0, Pseudo, (outs), (ins), "# CATCHPAD", [(catchpad)]>; - -// This instruction is responsible for re-establishing stack pointers after an -// exception has been caught and we are rejoining normal control flow in the -// parent function or funclet. It generally sets ESP and EBP, and optionally -// ESI. It is only needed for 32-bit WinEH, as the runtime restores CSRs for us -// elsewhere. -let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1 in -def EH_RESTORE : I<0, Pseudo, (outs), (ins), "# EH_RESTORE", []>; - -let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, - usesCustomInserter = 1 in { - def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf), - "#EH_SJLJ_SETJMP32", - [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>, - Requires<[Not64BitMode]>; - def EH_SjLj_SetJmp64 : I<0, Pseudo, (outs GR32:$dst), (ins i64mem:$buf), - "#EH_SJLJ_SETJMP64", - [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>, - Requires<[In64BitMode]>; - let isTerminator = 1 in { - def EH_SjLj_LongJmp32 : I<0, Pseudo, (outs), (ins i32mem:$buf), - "#EH_SJLJ_LONGJMP32", - [(X86eh_sjlj_longjmp addr:$buf)]>, - Requires<[Not64BitMode]>; - def EH_SjLj_LongJmp64 : I<0, Pseudo, (outs), (ins i64mem:$buf), - "#EH_SJLJ_LONGJMP64", - [(X86eh_sjlj_longjmp addr:$buf)]>, - Requires<[In64BitMode]>; - } -} - -let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in { - def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst), - "#EH_SjLj_Setup\t$dst", []>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Pseudo instructions used by unwind info. -// -let isPseudo = 1, SchedRW = [WriteSystem] in { - def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg), - "#SEH_PushReg $reg", []>; - def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst), - "#SEH_SaveReg $reg, $dst", []>; - def SEH_SaveXMM : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst), - "#SEH_SaveXMM $reg, $dst", []>; - def SEH_StackAlloc : I<0, Pseudo, (outs), (ins i32imm:$size), - "#SEH_StackAlloc $size", []>; - def SEH_SetFrame : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$offset), - "#SEH_SetFrame $reg, $offset", []>; - def SEH_PushFrame : I<0, Pseudo, (outs), (ins i1imm:$mode), - "#SEH_PushFrame $mode", []>; - def SEH_EndPrologue : I<0, Pseudo, (outs), (ins), - "#SEH_EndPrologue", []>; - def SEH_Epilogue : I<0, Pseudo, (outs), (ins), - "#SEH_Epilogue", []>; -} - -//===----------------------------------------------------------------------===// -// Pseudo instructions used by segmented stacks. -// - -// This is lowered into a RET instruction by MCInstLower. We need -// this so that we don't have to have a MachineBasicBlock which ends -// with a RET and also has successors. -let isPseudo = 1, SchedRW = [WriteJumpLd] in { -def MORESTACK_RET: I<0, Pseudo, (outs), (ins), "", []>; - -// This instruction is lowered to a RET followed by a MOV. The two -// instructions are not generated on a higher level since then the -// verifier sees a MachineBasicBlock ending with a non-terminator. -def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), "", []>; -} - -//===----------------------------------------------------------------------===// -// Alias Instructions -//===----------------------------------------------------------------------===// - -// Alias instruction mapping movr0 to xor. -// FIXME: remove when we can teach regalloc that xor reg, reg is ok. -let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, AddedComplexity = 10 in -def MOV32r0 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, 0)]>, Sched<[WriteZero]>; - -// Other widths can also make use of the 32-bit xor, which may have a smaller -// encoding and avoid partial register updates. -let AddedComplexity = 10 in { -def : Pat<(i8 0), (EXTRACT_SUBREG (MOV32r0), sub_8bit)>; -def : Pat<(i16 0), (EXTRACT_SUBREG (MOV32r0), sub_16bit)>; -def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)>; -} - -let Predicates = [OptForSize, Not64BitMode], - AddedComplexity = 10 in { - let SchedRW = [WriteALU] in { - // Pseudo instructions for materializing 1 and -1 using XOR+INC/DEC, - // which only require 3 bytes compared to MOV32ri which requires 5. - let Defs = [EFLAGS], isReMaterializable = 1, isPseudo = 1 in { - def MOV32r1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, 1)]>; - def MOV32r_1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, -1)]>; - } - } // SchedRW - - // MOV16ri is 4 bytes, so the instructions above are smaller. - def : Pat<(i16 1), (EXTRACT_SUBREG (MOV32r1), sub_16bit)>; - def : Pat<(i16 -1), (EXTRACT_SUBREG (MOV32r_1), sub_16bit)>; -} - -let isReMaterializable = 1, isPseudo = 1, AddedComplexity = 5, - SchedRW = [WriteALU] in { -// AddedComplexity higher than MOV64ri but lower than MOV32r0 and MOV32r1. -def MOV32ImmSExti8 : I<0, Pseudo, (outs GR32:$dst), (ins i32i8imm:$src), "", - [(set GR32:$dst, i32immSExt8:$src)]>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -def MOV64ImmSExti8 : I<0, Pseudo, (outs GR64:$dst), (ins i64i8imm:$src), "", - [(set GR64:$dst, i64immSExt8:$src)]>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -} - -// Materialize i64 constant where top 32-bits are zero. This could theoretically -// use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however -// that would make it more difficult to rematerialize. -let isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, hasSideEffects = 0, SchedRW = [WriteMove] in -def MOV32ri64 : I<0, Pseudo, (outs GR32:$dst), (ins i64i32imm:$src), "", []>; - -// This 64-bit pseudo-move can be used for both a 64-bit constant that is -// actually the zero-extension of a 32-bit constant and for labels in the -// x86-64 small code model. -def mov64imm32 : ComplexPattern; - -let AddedComplexity = 1 in -def : Pat<(i64 mov64imm32:$src), - (SUBREG_TO_REG (i64 0), (MOV32ri64 mov64imm32:$src), sub_32bit)>; - -// Use sbb to materialize carry bit. -let Uses = [EFLAGS], Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteALU] in { -// FIXME: These are pseudo ops that should be replaced with Pat<> patterns. -// However, Pat<> can't replicate the destination reg into the inputs of the -// result. -def SETB_C8r : I<0, Pseudo, (outs GR8:$dst), (ins), "", - [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C16r : I<0, Pseudo, (outs GR16:$dst), (ins), "", - [(set GR16:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C32r : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C64r : I<0, Pseudo, (outs GR64:$dst), (ins), "", - [(set GR64:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -} // isCodeGenOnly - - -def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i64 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C64r)>; - -def : Pat<(i16 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i64 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C64r)>; - -// We canonicalize 'setb' to "(and (sbb reg,reg), 1)" on the hope that the and -// will be eliminated and that the sbb can be extended up to a wider type. When -// this happens, it is great. However, if we are left with an 8-bit sbb and an -// and, we might as well just match it as a setb. -def : Pat<(and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1), - (SETBr)>; - -// (add OP, SETB) -> (adc OP, 0) -def : Pat<(add (and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR8:$op), - (ADC8ri GR8:$op, 0)>; -def : Pat<(add (and (i32 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR32:$op), - (ADC32ri8 GR32:$op, 0)>; -def : Pat<(add (and (i64 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR64:$op), - (ADC64ri8 GR64:$op, 0)>; - -// (sub OP, SETB) -> (sbb OP, 0) -def : Pat<(sub GR8:$op, (and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB8ri GR8:$op, 0)>; -def : Pat<(sub GR32:$op, (and (i32 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB32ri8 GR32:$op, 0)>; -def : Pat<(sub GR64:$op, (and (i64 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB64ri8 GR64:$op, 0)>; - -// (sub OP, SETCC_CARRY) -> (adc OP, 0) -def : Pat<(sub GR8:$op, (i8 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC8ri GR8:$op, 0)>; -def : Pat<(sub GR32:$op, (i32 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC32ri8 GR32:$op, 0)>; -def : Pat<(sub GR64:$op, (i64 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC64ri8 GR64:$op, 0)>; - -//===----------------------------------------------------------------------===// -// String Pseudo Instructions -// -let SchedRW = [WriteMicrocoded] in { -let Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI], isCodeGenOnly = 1 in { -def REP_MOVSB_32 : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", - [(X86rep_movs i8)]>, REP, - Requires<[Not64BitMode]>; -def REP_MOVSW_32 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", - [(X86rep_movs i16)]>, REP, OpSize16, - Requires<[Not64BitMode]>; -def REP_MOVSD_32 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", - [(X86rep_movs i32)]>, REP, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI], isCodeGenOnly = 1 in { -def REP_MOVSB_64 : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", - [(X86rep_movs i8)]>, REP, - Requires<[In64BitMode]>; -def REP_MOVSW_64 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", - [(X86rep_movs i16)]>, REP, OpSize16, - Requires<[In64BitMode]>; -def REP_MOVSD_64 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", - [(X86rep_movs i32)]>, REP, OpSize32, - Requires<[In64BitMode]>; -def REP_MOVSQ_64 : RI<0xA5, RawFrm, (outs), (ins), "{rep;movsq|rep movsq}", - [(X86rep_movs i64)]>, REP, - Requires<[In64BitMode]>; -} - -// FIXME: Should use "(X86rep_stos AL)" as the pattern. -let Defs = [ECX,EDI], isCodeGenOnly = 1 in { - let Uses = [AL,ECX,EDI] in - def REP_STOSB_32 : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", - [(X86rep_stos i8)]>, REP, - Requires<[Not64BitMode]>; - let Uses = [AX,ECX,EDI] in - def REP_STOSW_32 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", - [(X86rep_stos i16)]>, REP, OpSize16, - Requires<[Not64BitMode]>; - let Uses = [EAX,ECX,EDI] in - def REP_STOSD_32 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", - [(X86rep_stos i32)]>, REP, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RCX,RDI], isCodeGenOnly = 1 in { - let Uses = [AL,RCX,RDI] in - def REP_STOSB_64 : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", - [(X86rep_stos i8)]>, REP, - Requires<[In64BitMode]>; - let Uses = [AX,RCX,RDI] in - def REP_STOSW_64 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", - [(X86rep_stos i16)]>, REP, OpSize16, - Requires<[In64BitMode]>; - let Uses = [RAX,RCX,RDI] in - def REP_STOSD_64 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", - [(X86rep_stos i32)]>, REP, OpSize32, - Requires<[In64BitMode]>; - - let Uses = [RAX,RCX,RDI] in - def REP_STOSQ_64 : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", - [(X86rep_stos i64)]>, REP, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Thread Local Storage Instructions -// -let SchedRW = [WriteSystem] in { - -// ELF TLS Support -// All calls clobber the non-callee saved registers. ESP is marked as -// a use to prevent stack-pointer assignments that appear immediately -// before calls from potentially appearing dead. -let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, - ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, - MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, - XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF], - usesCustomInserter = 1, Uses = [ESP, SSP] in { -def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLS_addr32", - [(X86tlsaddr tls32addr:$sym)]>, - Requires<[Not64BitMode]>; -def TLS_base_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLS_base_addr32", - [(X86tlsbaseaddr tls32baseaddr:$sym)]>, - Requires<[Not64BitMode]>; -} - -// All calls clobber the non-callee saved registers. RSP is marked as -// a use to prevent stack-pointer assignments that appear immediately -// before calls from potentially appearing dead. -let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, - ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, - MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, - XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF], - usesCustomInserter = 1, Uses = [RSP, SSP] in { -def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLS_addr64", - [(X86tlsaddr tls64addr:$sym)]>, - Requires<[In64BitMode]>; -def TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLS_base_addr64", - [(X86tlsbaseaddr tls64baseaddr:$sym)]>, - Requires<[In64BitMode]>; -} - -// Darwin TLS Support -// For i386, the address of the thunk is passed on the stack, on return the -// address of the variable is in %eax. %ecx is trashed during the function -// call. All other registers are preserved. -let Defs = [EAX, ECX, EFLAGS, DF], - Uses = [ESP, SSP], - usesCustomInserter = 1 in -def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLSCall_32", - [(X86TLSCall addr:$sym)]>, - Requires<[Not64BitMode]>; - -// For x86_64, the address of the thunk is passed in %rdi, but the -// pseudo directly use the symbol, so do not add an implicit use of -// %rdi. The lowering will do the right thing with RDI. -// On return the address of the variable is in %rax. All other -// registers are preserved. -let Defs = [RAX, EFLAGS, DF], - Uses = [RSP, SSP], - usesCustomInserter = 1 in -def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLSCall_64", - [(X86TLSCall addr:$sym)]>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Conditional Move Pseudo Instructions - -// CMOV* - Used to implement the SELECT DAG operation. Expanded after -// instruction selection into a branch sequence. -multiclass CMOVrr_PSEUDO { - def CMOV#NAME : I<0, Pseudo, - (outs RC:$dst), (ins RC:$t, RC:$f, i8imm:$cond), - "#CMOV_"#NAME#" PSEUDO!", - [(set RC:$dst, (VT (X86cmov RC:$t, RC:$f, imm:$cond, - EFLAGS)))]>; -} - -let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in { - // X86 doesn't have 8-bit conditional moves. Use a customInserter to - // emit control flow. An alternative to this is to mark i8 SELECT as Promote, - // however that requires promoting the operands, and can induce additional - // i8 register pressure. - defm _GR8 : CMOVrr_PSEUDO; - - let Predicates = [NoCMov] in { - defm _GR32 : CMOVrr_PSEUDO; - defm _GR16 : CMOVrr_PSEUDO; - } // Predicates = [NoCMov] - - // fcmov doesn't handle all possible EFLAGS, provide a fallback if there is no - // SSE1/SSE2. - let Predicates = [FPStackf32] in - defm _RFP32 : CMOVrr_PSEUDO; - - let Predicates = [FPStackf64] in - defm _RFP64 : CMOVrr_PSEUDO; - - defm _RFP80 : CMOVrr_PSEUDO; - - defm _FR32 : CMOVrr_PSEUDO; - defm _FR64 : CMOVrr_PSEUDO; - defm _F128 : CMOVrr_PSEUDO; - defm _V4F32 : CMOVrr_PSEUDO; - defm _V2F64 : CMOVrr_PSEUDO; - defm _V2I64 : CMOVrr_PSEUDO; - defm _V8F32 : CMOVrr_PSEUDO; - defm _V4F64 : CMOVrr_PSEUDO; - defm _V4I64 : CMOVrr_PSEUDO; - defm _V8I64 : CMOVrr_PSEUDO; - defm _V8F64 : CMOVrr_PSEUDO; - defm _V16F32 : CMOVrr_PSEUDO; - defm _V8I1 : CMOVrr_PSEUDO; - defm _V16I1 : CMOVrr_PSEUDO; - defm _V32I1 : CMOVrr_PSEUDO; - defm _V64I1 : CMOVrr_PSEUDO; -} // usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] - -//===----------------------------------------------------------------------===// -// Normal-Instructions-With-Lock-Prefix Pseudo Instructions -//===----------------------------------------------------------------------===// - -// FIXME: Use normal instructions and add lock prefix dynamically. - -// Memory barriers - -// TODO: Get this to fold the constant into the instruction. -let isCodeGenOnly = 1, Defs = [EFLAGS] in -def OR32mrLocked : I<0x09, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$zero), - "or{l}\t{$zero, $dst|$dst, $zero}", []>, - Requires<[Not64BitMode]>, OpSize32, LOCK, - Sched<[WriteALULd, WriteRMW]>; - -let hasSideEffects = 1 in -def Int_MemBarrier : I<0, Pseudo, (outs), (ins), - "#MEMBARRIER", - [(X86MemBarrier)]>, Sched<[WriteLoad]>; - -// RegOpc corresponds to the mr version of the instruction -// ImmOpc corresponds to the mi version of the instruction -// ImmOpc8 corresponds to the mi8 version of the instruction -// ImmMod corresponds to the instruction format of the mi and mi8 versions -multiclass LOCK_ArithBinOp RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8, - Format ImmMod, SDNode Op, string mnemonic> { -let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { - -def NAME#8mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 0 }, - MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), - !strconcat(mnemonic, "{b}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR8:$src2))]>, LOCK; - -def NAME#16mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR16:$src2))]>, - OpSize16, LOCK; - -def NAME#32mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR32:$src2))]>, - OpSize32, LOCK; - -def NAME#64mr : RI<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR64:$src2))]>, LOCK; - -def NAME#8mi : Ii8<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 0 }, - ImmMod, (outs), (ins i8mem :$dst, i8imm :$src2), - !strconcat(mnemonic, "{b}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i8 imm:$src2)))]>, LOCK; - -def NAME#16mi : Ii16<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i16mem :$dst, i16imm :$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i16 imm:$src2)))]>, - OpSize16, LOCK; - -def NAME#32mi : Ii32<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i32mem :$dst, i32imm :$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i32 imm:$src2)))]>, - OpSize32, LOCK; - -def NAME#64mi32 : RIi32S<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i64mem :$dst, i64i32imm :$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt32:$src2))]>, - LOCK; - -def NAME#16mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i16mem :$dst, i16i8imm :$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i16immSExt8:$src2))]>, - OpSize16, LOCK; - -def NAME#32mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i32mem :$dst, i32i8imm :$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i32immSExt8:$src2))]>, - OpSize32, LOCK; - -def NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i64mem :$dst, i64i8imm :$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt8:$src2))]>, - LOCK; -} - -} - -defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, X86lock_add, "add">; -defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, X86lock_sub, "sub">; -defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">; -defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">; -defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">; - -multiclass LOCK_ArithUnOp Opc8, bits<8> Opc, Format Form, - string frag, string mnemonic> { -let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { -def NAME#8m : I(frag # "_8") addr:$dst))]>, - LOCK; -def NAME#16m : I(frag # "_16") addr:$dst))]>, - OpSize16, LOCK; -def NAME#32m : I(frag # "_32") addr:$dst))]>, - OpSize32, LOCK; -def NAME#64m : RI(frag # "_64") addr:$dst))]>, - LOCK; -} -} - -multiclass unary_atomic_intrin { - def _8 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; - }]>; - def _16 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; - }]>; - def _32 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; - }]>; - def _64 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i64; - }]>; -} - -defm X86lock_inc : unary_atomic_intrin; -defm X86lock_dec : unary_atomic_intrin; - -defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, "X86lock_inc", "inc">; -defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, "X86lock_dec", "dec">; - -// Atomic compare and swap. -multiclass LCMPXCHG_UnOp Opc, Format Form, string mnemonic, - SDPatternOperator frag, X86MemOperand x86memop> { -let isCodeGenOnly = 1, usesCustomInserter = 1 in { - def NAME : I, TB, LOCK; -} -} - -multiclass LCMPXCHG_BinOp Opc8, bits<8> Opc, Format Form, - string mnemonic, SDPatternOperator frag> { -let isCodeGenOnly = 1, SchedRW = [WriteALULd, WriteRMW] in { - let Defs = [AL, EFLAGS], Uses = [AL] in - def NAME#8 : I, TB, LOCK; - let Defs = [AX, EFLAGS], Uses = [AX] in - def NAME#16 : I, TB, OpSize16, LOCK; - let Defs = [EAX, EFLAGS], Uses = [EAX] in - def NAME#32 : I, TB, OpSize32, LOCK; - let Defs = [RAX, EFLAGS], Uses = [RAX] in - def NAME#64 : RI, TB, LOCK; -} -} - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX], - SchedRW = [WriteALULd, WriteRMW] in { -defm LCMPXCHG8B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg8b", X86cas8, i64mem>; -} - -// This pseudo must be used when the frame uses RBX as -// the base pointer. Indeed, in such situation RBX is a reserved -// register and the register allocator will ignore any use/def of -// it. In other words, the register will not fix the clobbering of -// RBX that will happen when setting the arguments for the instruction. -// -// Unlike the actual related instruction, we mark that this one -// defines EBX (instead of using EBX). -// The rationale is that we will define RBX during the expansion of -// the pseudo. The argument feeding EBX is ebx_input. -// -// The additional argument, $ebx_save, is a temporary register used to -// save the value of RBX across the actual instruction. -// -// To make sure the register assigned to $ebx_save does not interfere with -// the definition of the actual instruction, we use a definition $dst which -// is tied to $rbx_save. That way, the live-range of $rbx_save spans across -// the instruction and we are sure we will have a valid register to restore -// the value of RBX. -let Defs = [EAX, EDX, EBX, EFLAGS], Uses = [EAX, ECX, EDX], - SchedRW = [WriteALULd, WriteRMW], isCodeGenOnly = 1, isPseudo = 1, - Constraints = "$ebx_save = $dst", usesCustomInserter = 1 in { -def LCMPXCHG8B_SAVE_EBX : - I<0, Pseudo, (outs GR32:$dst), - (ins i64mem:$ptr, GR32:$ebx_input, GR32:$ebx_save), - !strconcat("cmpxchg8b", "\t$ptr"), - [(set GR32:$dst, (X86cas8save_ebx addr:$ptr, GR32:$ebx_input, - GR32:$ebx_save))]>; -} - - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX], - Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW] in { -defm LCMPXCHG16B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg16b", - X86cas16, i128mem>, REX_W; -} - -// Same as LCMPXCHG8B_SAVE_RBX but for the 16 Bytes variant. -let Defs = [RAX, RDX, RBX, EFLAGS], Uses = [RAX, RCX, RDX], - Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW], - isCodeGenOnly = 1, isPseudo = 1, Constraints = "$rbx_save = $dst", - usesCustomInserter = 1 in { -def LCMPXCHG16B_SAVE_RBX : - I<0, Pseudo, (outs GR64:$dst), - (ins i128mem:$ptr, GR64:$rbx_input, GR64:$rbx_save), - !strconcat("cmpxchg16b", "\t$ptr"), - [(set GR64:$dst, (X86cas16save_rbx addr:$ptr, GR64:$rbx_input, - GR64:$rbx_save))]>; -} - -defm LCMPXCHG : LCMPXCHG_BinOp<0xB0, 0xB1, MRMDestMem, "cmpxchg", X86cas>; - -// Atomic exchange and add -multiclass ATOMIC_LOAD_BINOP opc8, bits<8> opc, string mnemonic, - string frag> { - let Constraints = "$val = $dst", Defs = [EFLAGS], isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8 : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16 : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32 : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64 : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm LXADD : ATOMIC_LOAD_BINOP<0xc0, 0xc1, "xadd", "atomic_load_add">, TB, LOCK; - -/* The following multiclass tries to make sure that in code like - * x.store (immediate op x.load(acquire), release) - * and - * x.store (register op x.load(acquire), release) - * an operation directly on memory is generated instead of wasting a register. - * It is not automatic as atomic_store/load are only lowered to MOV instructions - * extremely late to prevent them from being accidentally reordered in the backend - * (see below the RELEASE_MOV* / ACQUIRE_MOV* pseudo-instructions) - */ -multiclass RELEASE_BINOP_MI { - def NAME#8mi : I<0, Pseudo, (outs), (ins i8mem:$dst, i8imm:$src), - "#BINOP "#NAME#"8mi PSEUDO!", - [(atomic_store_8 addr:$dst, (op - (atomic_load_8 addr:$dst), (i8 imm:$src)))]>; - def NAME#8mr : I<0, Pseudo, (outs), (ins i8mem:$dst, GR8:$src), - "#BINOP "#NAME#"8mr PSEUDO!", - [(atomic_store_8 addr:$dst, (op - (atomic_load_8 addr:$dst), GR8:$src))]>; - // NAME#16 is not generated as 16-bit arithmetic instructions are considered - // costly and avoided as far as possible by this backend anyway - def NAME#32mi : I<0, Pseudo, (outs), (ins i32mem:$dst, i32imm:$src), - "#BINOP "#NAME#"32mi PSEUDO!", - [(atomic_store_32 addr:$dst, (op - (atomic_load_32 addr:$dst), (i32 imm:$src)))]>; - def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, GR32:$src), - "#BINOP "#NAME#"32mr PSEUDO!", - [(atomic_store_32 addr:$dst, (op - (atomic_load_32 addr:$dst), GR32:$src))]>; - def NAME#64mi32 : I<0, Pseudo, (outs), (ins i64mem:$dst, i64i32imm:$src), - "#BINOP "#NAME#"64mi32 PSEUDO!", - [(atomic_store_64 addr:$dst, (op - (atomic_load_64 addr:$dst), (i64immSExt32:$src)))]>; - def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, GR64:$src), - "#BINOP "#NAME#"64mr PSEUDO!", - [(atomic_store_64 addr:$dst, (op - (atomic_load_64 addr:$dst), GR64:$src))]>; -} -let Defs = [EFLAGS], SchedRW = [WriteMicrocoded] in { - defm RELEASE_ADD : RELEASE_BINOP_MI; - defm RELEASE_AND : RELEASE_BINOP_MI; - defm RELEASE_OR : RELEASE_BINOP_MI; - defm RELEASE_XOR : RELEASE_BINOP_MI; - // Note: we don't deal with sub, because substractions of constants are - // optimized into additions before this code can run. -} - -// Same as above, but for floating-point. -// FIXME: imm version. -// FIXME: Version that doesn't clobber $src, using AVX's VADDSS. -// FIXME: This could also handle SIMD operations with *ps and *pd instructions. -let usesCustomInserter = 1, SchedRW = [WriteMicrocoded] in { -multiclass RELEASE_FP_BINOP_MI { - def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, FR32:$src), - "#BINOP "#NAME#"32mr PSEUDO!", - [(atomic_store_32 addr:$dst, - (i32 (bitconvert (op - (f32 (bitconvert (i32 (atomic_load_32 addr:$dst)))), - FR32:$src))))]>, Requires<[HasSSE1]>; - def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, FR64:$src), - "#BINOP "#NAME#"64mr PSEUDO!", - [(atomic_store_64 addr:$dst, - (i64 (bitconvert (op - (f64 (bitconvert (i64 (atomic_load_64 addr:$dst)))), - FR64:$src))))]>, Requires<[HasSSE2]>; -} -defm RELEASE_FADD : RELEASE_FP_BINOP_MI; -// FIXME: Add fsub, fmul, fdiv, ... -} - -multiclass RELEASE_UNOP { - def NAME#8m : I<0, Pseudo, (outs), (ins i8mem:$dst), - "#UNOP "#NAME#"8m PSEUDO!", - [(atomic_store_8 addr:$dst, dag8)]>; - def NAME#16m : I<0, Pseudo, (outs), (ins i16mem:$dst), - "#UNOP "#NAME#"16m PSEUDO!", - [(atomic_store_16 addr:$dst, dag16)]>; - def NAME#32m : I<0, Pseudo, (outs), (ins i32mem:$dst), - "#UNOP "#NAME#"32m PSEUDO!", - [(atomic_store_32 addr:$dst, dag32)]>; - def NAME#64m : I<0, Pseudo, (outs), (ins i64mem:$dst), - "#UNOP "#NAME#"64m PSEUDO!", - [(atomic_store_64 addr:$dst, dag64)]>; -} - -let Defs = [EFLAGS], Predicates = [UseIncDec], SchedRW = [WriteMicrocoded] in { - defm RELEASE_INC : RELEASE_UNOP< - (add (atomic_load_8 addr:$dst), (i8 1)), - (add (atomic_load_16 addr:$dst), (i16 1)), - (add (atomic_load_32 addr:$dst), (i32 1)), - (add (atomic_load_64 addr:$dst), (i64 1))>; - defm RELEASE_DEC : RELEASE_UNOP< - (add (atomic_load_8 addr:$dst), (i8 -1)), - (add (atomic_load_16 addr:$dst), (i16 -1)), - (add (atomic_load_32 addr:$dst), (i32 -1)), - (add (atomic_load_64 addr:$dst), (i64 -1))>; -} -/* -TODO: These don't work because the type inference of TableGen fails. -TODO: find a way to fix it. -let Defs = [EFLAGS] in { - defm RELEASE_NEG : RELEASE_UNOP< - (ineg (atomic_load_8 addr:$dst)), - (ineg (atomic_load_16 addr:$dst)), - (ineg (atomic_load_32 addr:$dst)), - (ineg (atomic_load_64 addr:$dst))>; -} -// NOT doesn't set flags. -defm RELEASE_NOT : RELEASE_UNOP< - (not (atomic_load_8 addr:$dst)), - (not (atomic_load_16 addr:$dst)), - (not (atomic_load_32 addr:$dst)), - (not (atomic_load_64 addr:$dst))>; -*/ - -let SchedRW = [WriteMicrocoded] in { -def RELEASE_MOV8mi : I<0, Pseudo, (outs), (ins i8mem:$dst, i8imm:$src), - "#RELEASE_MOV8mi PSEUDO!", - [(atomic_store_8 addr:$dst, (i8 imm:$src))]>; -def RELEASE_MOV16mi : I<0, Pseudo, (outs), (ins i16mem:$dst, i16imm:$src), - "#RELEASE_MOV16mi PSEUDO!", - [(atomic_store_16 addr:$dst, (i16 imm:$src))]>; -def RELEASE_MOV32mi : I<0, Pseudo, (outs), (ins i32mem:$dst, i32imm:$src), - "#RELEASE_MOV32mi PSEUDO!", - [(atomic_store_32 addr:$dst, (i32 imm:$src))]>; -def RELEASE_MOV64mi32 : I<0, Pseudo, (outs), (ins i64mem:$dst, i64i32imm:$src), - "#RELEASE_MOV64mi32 PSEUDO!", - [(atomic_store_64 addr:$dst, i64immSExt32:$src)]>; - -def RELEASE_MOV8mr : I<0, Pseudo, (outs), (ins i8mem :$dst, GR8 :$src), - "#RELEASE_MOV8mr PSEUDO!", - [(atomic_store_8 addr:$dst, GR8 :$src)]>; -def RELEASE_MOV16mr : I<0, Pseudo, (outs), (ins i16mem:$dst, GR16:$src), - "#RELEASE_MOV16mr PSEUDO!", - [(atomic_store_16 addr:$dst, GR16:$src)]>; -def RELEASE_MOV32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, GR32:$src), - "#RELEASE_MOV32mr PSEUDO!", - [(atomic_store_32 addr:$dst, GR32:$src)]>; -def RELEASE_MOV64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, GR64:$src), - "#RELEASE_MOV64mr PSEUDO!", - [(atomic_store_64 addr:$dst, GR64:$src)]>; - -def ACQUIRE_MOV8rm : I<0, Pseudo, (outs GR8 :$dst), (ins i8mem :$src), - "#ACQUIRE_MOV8rm PSEUDO!", - [(set GR8:$dst, (atomic_load_8 addr:$src))]>; -def ACQUIRE_MOV16rm : I<0, Pseudo, (outs GR16:$dst), (ins i16mem:$src), - "#ACQUIRE_MOV16rm PSEUDO!", - [(set GR16:$dst, (atomic_load_16 addr:$src))]>; -def ACQUIRE_MOV32rm : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$src), - "#ACQUIRE_MOV32rm PSEUDO!", - [(set GR32:$dst, (atomic_load_32 addr:$src))]>; -def ACQUIRE_MOV64rm : I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$src), - "#ACQUIRE_MOV64rm PSEUDO!", - [(set GR64:$dst, (atomic_load_64 addr:$src))]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// DAG Pattern Matching Rules -//===----------------------------------------------------------------------===// - -// Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves -// binary size compared to a regular MOV, but it introduces an unnecessary -// load, so is not suitable for regular or optsize functions. -let Predicates = [OptForMinSize] in { -def : Pat<(store (i16 0), addr:$dst), (AND16mi8 addr:$dst, 0)>; -def : Pat<(store (i32 0), addr:$dst), (AND32mi8 addr:$dst, 0)>; -def : Pat<(store (i64 0), addr:$dst), (AND64mi8 addr:$dst, 0)>; -def : Pat<(store (i16 -1), addr:$dst), (OR16mi8 addr:$dst, -1)>; -def : Pat<(store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>; -def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>; -} - -// In kernel code model, we can get the address of a label -// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of -// the MOV64ri32 should accept these. -def : Pat<(i64 (X86Wrapper tconstpool :$dst)), - (MOV64ri32 tconstpool :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tjumptable :$dst)), - (MOV64ri32 tjumptable :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), - (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper texternalsym:$dst)), - (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper mcsym:$dst)), - (MOV64ri32 mcsym:$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), - (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>; - -// If we have small model and -static mode, it is safe to store global addresses -// directly as immediates. FIXME: This is really a hack, the 'imm' predicate -// for MOV64mi32 should handle this sort of thing. -def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tconstpool:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tjumptable:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tglobaladdr:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst), - (MOV64mi32 addr:$dst, texternalsym:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper mcsym:$src)), addr:$dst), - (MOV64mi32 addr:$dst, mcsym:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tblockaddress:$src)>, - Requires<[NearData, IsNotPIC]>; - -def : Pat<(i32 (X86RecoverFrameAlloc mcsym:$dst)), (MOV32ri mcsym:$dst)>; -def : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>; - -// Calls - -// tls has some funny stuff here... -// This corresponds to movabs $foo@tpoff, %rax -def : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)), - (MOV64ri32 tglobaltlsaddr :$dst)>; -// This corresponds to add $foo@tpoff, %rax -def : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)), - (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>; - - -// Direct PC relative function call for small code model. 32-bit displacement -// sign extended to 64-bit. -def : Pat<(X86call (i64 tglobaladdr:$dst)), - (CALL64pcrel32 tglobaladdr:$dst)>; -def : Pat<(X86call (i64 texternalsym:$dst)), - (CALL64pcrel32 texternalsym:$dst)>; - -// Tailcall stuff. The TCRETURN instructions execute after the epilog, so they -// can never use callee-saved registers. That is the purpose of the GR64_TC -// register classes. -// -// The only volatile register that is never used by the calling convention is -// %r11. This happens when calling a vararg function with 6 arguments. -// -// Match an X86tcret that uses less than 7 volatile registers. -def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off), - (X86tcret node:$ptr, node:$off), [{ - // X86tcret args: (*chain, ptr, imm, regs..., glue) - unsigned NumRegs = 0; - for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) - if (isa(N->getOperand(i)) && ++NumRegs > 6) - return false; - return true; -}]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (TCRETURNri ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, NotUseRetpoline]>; - -// FIXME: This is disabled for 32-bit PIC mode because the global base -// register which is part of the address mode may be assigned a -// callee-saved register. -def : Pat<(X86tcret (load addr:$dst), imm:$off), - (TCRETURNmi addr:$dst, imm:$off)>, - Requires<[Not64BitMode, IsNotPIC, NotUseRetpoline]>; - -def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off), - (TCRETURNdi tglobaladdr:$dst, imm:$off)>, - Requires<[NotLP64]>; - -def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off), - (TCRETURNdi texternalsym:$dst, imm:$off)>, - Requires<[NotLP64]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (TCRETURNri64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; - -// Don't fold loads into X86tcret requiring more than 6 regs. -// There wouldn't be enough scratch registers for base+index. -def : Pat<(X86tcret_6regs (load addr:$dst), imm:$off), - (TCRETURNmi64 addr:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, UseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN32 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, UseRetpoline]>; - -def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off), - (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>, - Requires<[IsLP64]>; - -def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off), - (TCRETURNdi64 texternalsym:$dst, imm:$off)>, - Requires<[IsLP64]>; - -// Normal calls, with various flavors of addresses. -def : Pat<(X86call (i32 tglobaladdr:$dst)), - (CALLpcrel32 tglobaladdr:$dst)>; -def : Pat<(X86call (i32 texternalsym:$dst)), - (CALLpcrel32 texternalsym:$dst)>; -def : Pat<(X86call (i32 imm:$dst)), - (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>; - -// Comparisons. - -// TEST R,R is smaller than CMP R,0 -def : Pat<(X86cmp GR8:$src1, 0), - (TEST8rr GR8:$src1, GR8:$src1)>; -def : Pat<(X86cmp GR16:$src1, 0), - (TEST16rr GR16:$src1, GR16:$src1)>; -def : Pat<(X86cmp GR32:$src1, 0), - (TEST32rr GR32:$src1, GR32:$src1)>; -def : Pat<(X86cmp GR64:$src1, 0), - (TEST64rr GR64:$src1, GR64:$src1)>; - -// Conditional moves with folded loads with operands swapped and conditions -// inverted. -multiclass CMOVmr { - let Predicates = [HasCMov] in { - def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS), - (Inst16 GR16:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS), - (Inst32 GR32:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS), - (Inst64 GR64:$src2, addr:$src1)>; - } -} - -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; - -// zextload bool -> zextload byte -// i1 stored in one byte in zero-extended form. -// Upper bits cleanup should be executed before Store. -def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(zextloadi64i1 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; - -// extload bool -> extload byte -// When extloading from 16-bit and smaller memory locations into 64-bit -// registers, use zero-extending loads so that the entire 64-bit register is -// defined, avoiding partial-register updates. - -def : Pat<(extloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(extloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(extloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(extloadi32i8 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>; - -// For other extloads, use subregs, since the high contents of the register are -// defined after an extload. -def : Pat<(extloadi64i1 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i8 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i16 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i32 addr:$src), - (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>; - -// anyext. Define these to do an explicit zero-extend to -// avoid partial-register updates. -def : Pat<(i16 (anyext GR8 :$src)), (EXTRACT_SUBREG - (MOVZX32rr8 GR8 :$src), sub_16bit)>; -def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>; - -// Except for i16 -> i32 since isel expect i16 ops to be promoted to i32. -def : Pat<(i32 (anyext GR16:$src)), - (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, sub_16bit)>; - -def : Pat<(i64 (anyext GR8 :$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8 :$src), sub_32bit)>; -def : Pat<(i64 (anyext GR16:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16 :$src), sub_32bit)>; -def : Pat<(i64 (anyext GR32:$src)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>; - - -// Any instruction that defines a 32-bit result leaves the high half of the -// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may -// be copying from a truncate. Any other 32-bit operation will zero-extend -// up to 64 bits. AssertSext/AssertZext aren't saying anything about the upper -// 32 bits, they're probably just qualifying a CopyFromReg. -def def32 : PatLeaf<(i32 GR32:$src), [{ - return N->getOpcode() != ISD::TRUNCATE && - N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && - N->getOpcode() != ISD::CopyFromReg && - N->getOpcode() != ISD::AssertSext && - N->getOpcode() != ISD::AssertZext; -}]>; - -// In the case of a 32-bit def that is known to implicitly zero-extend, -// we can use a SUBREG_TO_REG. -def : Pat<(i64 (zext def32:$src)), - (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>; - -//===----------------------------------------------------------------------===// -// Pattern match OR as ADD -//===----------------------------------------------------------------------===// - -// If safe, we prefer to pattern match OR as ADD at isel time. ADD can be -// 3-addressified into an LEA instruction to avoid copies. However, we also -// want to finally emit these instructions as an or at the end of the code -// generator to make the generated code easier to read. To do this, we select -// into "disjoint bits" pseudo ops. - -// Treat an 'or' node is as an 'add' if the or'ed bits are known to be zero. -def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ - if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) - return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); - - KnownBits Known0; - CurDAG->computeKnownBits(N->getOperand(0), Known0, 0); - KnownBits Known1; - CurDAG->computeKnownBits(N->getOperand(1), Known1, 0); - return (~Known0.Zero & ~Known1.Zero) == 0; -}]>; - - -// (or x1, x2) -> (add x1, x2) if two operands are known not to share bits. -// Try this before the selecting to OR. -let AddedComplexity = 5, SchedRW = [WriteALU] in { - -let isConvertibleToThreeAddress = 1, - Constraints = "$src1 = $dst", Defs = [EFLAGS] in { -let isCommutable = 1 in { -def ADD16rr_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "", // orw/addw REG, REG - [(set GR16:$dst, (or_is_add GR16:$src1, GR16:$src2))]>; -def ADD32rr_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "", // orl/addl REG, REG - [(set GR32:$dst, (or_is_add GR32:$src1, GR32:$src2))]>; -def ADD64rr_DB : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "", // orq/addq REG, REG - [(set GR64:$dst, (or_is_add GR64:$src1, GR64:$src2))]>; -} // isCommutable - -// NOTE: These are order specific, we want the ri8 forms to be listed -// first so that they are slightly preferred to the ri forms. - -def ADD16ri8_DB : I<0, Pseudo, - (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "", // orw/addw REG, imm8 - [(set GR16:$dst,(or_is_add GR16:$src1,i16immSExt8:$src2))]>; -def ADD16ri_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "", // orw/addw REG, imm - [(set GR16:$dst, (or_is_add GR16:$src1, imm:$src2))]>; - -def ADD32ri8_DB : I<0, Pseudo, - (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "", // orl/addl REG, imm8 - [(set GR32:$dst,(or_is_add GR32:$src1,i32immSExt8:$src2))]>; -def ADD32ri_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), - "", // orl/addl REG, imm - [(set GR32:$dst, (or_is_add GR32:$src1, imm:$src2))]>; - - -def ADD64ri8_DB : I<0, Pseudo, - (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "", // orq/addq REG, imm8 - [(set GR64:$dst, (or_is_add GR64:$src1, - i64immSExt8:$src2))]>; -def ADD64ri32_DB : I<0, Pseudo, - (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), - "", // orq/addq REG, imm - [(set GR64:$dst, (or_is_add GR64:$src1, - i64immSExt32:$src2))]>; -} -} // AddedComplexity, SchedRW - -//===----------------------------------------------------------------------===// -// Pattern match SUB as XOR -//===----------------------------------------------------------------------===// - -// An immediate in the LHS of a subtract can't be encoded in the instruction. -// If there is no possibility of a borrow we can use an XOR instead of a SUB -// to enable the immediate to be folded. -// TODO: Move this to a DAG combine? - -def sub_is_xor : PatFrag<(ops node:$lhs, node:$rhs), (sub node:$lhs, node:$rhs),[{ - if (ConstantSDNode *CN = dyn_cast(N->getOperand(0))) { - KnownBits Known; - CurDAG->computeKnownBits(N->getOperand(1), Known); - - // If all possible ones in the RHS are set in the LHS then there can't be - // a borrow and we can use xor. - return (~Known.Zero).isSubsetOf(CN->getAPIntValue()); - } - - return false; -}]>; - -let AddedComplexity = 5 in { -def : Pat<(sub_is_xor imm:$src2, GR8:$src1), - (XOR8ri GR8:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i16immSExt8:$src2, GR16:$src1), - (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(sub_is_xor imm:$src2, GR16:$src1), - (XOR16ri GR16:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i32immSExt8:$src2, GR32:$src1), - (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(sub_is_xor imm:$src2, GR32:$src1), - (XOR32ri GR32:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i64immSExt8:$src2, GR64:$src1), - (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(sub_is_xor i64immSExt32:$src2, GR64:$src1), - (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; -} - -//===----------------------------------------------------------------------===// -// Some peepholes -//===----------------------------------------------------------------------===// - -// Odd encoding trick: -128 fits into an 8-bit immediate field while -// +128 doesn't, so in this special case use a sub instead of an add. -def : Pat<(add GR16:$src1, 128), - (SUB16ri8 GR16:$src1, -128)>; -def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst), - (SUB16mi8 addr:$dst, -128)>; - -def : Pat<(add GR32:$src1, 128), - (SUB32ri8 GR32:$src1, -128)>; -def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst), - (SUB32mi8 addr:$dst, -128)>; - -def : Pat<(add GR64:$src1, 128), - (SUB64ri8 GR64:$src1, -128)>; -def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst), - (SUB64mi8 addr:$dst, -128)>; - -// The same trick applies for 32-bit immediate fields in 64-bit -// instructions. -def : Pat<(add GR64:$src1, 0x0000000080000000), - (SUB64ri32 GR64:$src1, 0xffffffff80000000)>; -def : Pat<(store (add (loadi64 addr:$dst), 0x0000000080000000), addr:$dst), - (SUB64mi32 addr:$dst, 0xffffffff80000000)>; - -// To avoid needing to materialize an immediate in a register, use a 32-bit and -// with implicit zero-extension instead of a 64-bit and if the immediate has at -// least 32 bits of leading zeros. If in addition the last 32 bits can be -// represented with a sign extension of a 8 bit constant, use that. -// This can also reduce instruction size by eliminating the need for the REX -// prefix. - -// AddedComplexity is needed to give priority over i64immSExt8 and i64immSExt32. -let AddedComplexity = 1 in { -def : Pat<(and GR64:$src, i64immZExt32SExt8:$imm), - (SUBREG_TO_REG - (i64 0), - (AND32ri8 - (EXTRACT_SUBREG GR64:$src, sub_32bit), - (i32 (GetLo8XForm imm:$imm))), - sub_32bit)>; - -def : Pat<(and GR64:$src, i64immZExt32:$imm), - (SUBREG_TO_REG - (i64 0), - (AND32ri - (EXTRACT_SUBREG GR64:$src, sub_32bit), - (i32 (GetLo32XForm imm:$imm))), - sub_32bit)>; -} // AddedComplexity = 1 - - -// AddedComplexity is needed due to the increased complexity on the -// i64immZExt32SExt8 and i64immZExt32 patterns above. Applying this to all -// the MOVZX patterns keeps thems together in DAGIsel tables. -let AddedComplexity = 1 in { -// r & (2^16-1) ==> movz -def : Pat<(and GR32:$src1, 0xffff), - (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>; -// r & (2^8-1) ==> movz -def : Pat<(and GR32:$src1, 0xff), - (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>; -// r & (2^8-1) ==> movz -def : Pat<(and GR16:$src1, 0xff), - (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)), - sub_16bit)>; - -// r & (2^32-1) ==> movz -def : Pat<(and GR64:$src, 0x00000000FFFFFFFF), - (SUBREG_TO_REG (i64 0), - (MOV32rr (EXTRACT_SUBREG GR64:$src, sub_32bit)), - sub_32bit)>; -// r & (2^16-1) ==> movz -def : Pat<(and GR64:$src, 0xffff), - (SUBREG_TO_REG (i64 0), - (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR64:$src, sub_16bit))), - sub_32bit)>; -// r & (2^8-1) ==> movz -def : Pat<(and GR64:$src, 0xff), - (SUBREG_TO_REG (i64 0), - (MOVZX32rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit))), - sub_32bit)>; -} // AddedComplexity = 1 - - -// Try to use BTS/BTR/BTC for single bit operations on the upper 32-bits. - -def BTRXForm : SDNodeXFormgetAPIntValue().countTrailingOnes(), SDLoc(N)); -}]>; - -def BTCBTSXForm : SDNodeXFormgetAPIntValue().countTrailingZeros(), SDLoc(N)); -}]>; - -def BTRMask64 : ImmLeaf(Imm) && !isInt<32>(Imm) && isPowerOf2_64(~Imm); -}]>; - -def BTCBTSMask64 : ImmLeaf(Imm) && isPowerOf2_64(Imm); -}]>; - -// For now only do this for optsize. -let AddedComplexity = 1, Predicates=[OptForSize] in { - def : Pat<(and GR64:$src1, BTRMask64:$mask), - (BTR64ri8 GR64:$src1, (BTRXForm imm:$mask))>; - def : Pat<(or GR64:$src1, BTCBTSMask64:$mask), - (BTS64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; - def : Pat<(xor GR64:$src1, BTCBTSMask64:$mask), - (BTC64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; -} - - -// sext_inreg patterns -def : Pat<(sext_inreg GR32:$src, i16), - (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>; -def : Pat<(sext_inreg GR32:$src, i8), - (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>; - -def : Pat<(sext_inreg GR16:$src, i8), - (EXTRACT_SUBREG (MOVSX32rr8 (EXTRACT_SUBREG GR16:$src, sub_8bit)), - sub_16bit)>; - -def : Pat<(sext_inreg GR64:$src, i32), - (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>; -def : Pat<(sext_inreg GR64:$src, i16), - (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>; -def : Pat<(sext_inreg GR64:$src, i8), - (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>; - -// sext, sext_load, zext, zext_load -def: Pat<(i16 (sext GR8:$src)), - (EXTRACT_SUBREG (MOVSX32rr8 GR8:$src), sub_16bit)>; -def: Pat<(sextloadi16i8 addr:$src), - (EXTRACT_SUBREG (MOVSX32rm8 addr:$src), sub_16bit)>; -def: Pat<(i16 (zext GR8:$src)), - (EXTRACT_SUBREG (MOVZX32rr8 GR8:$src), sub_16bit)>; -def: Pat<(zextloadi16i8 addr:$src), - (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>; - -// trunc patterns -def : Pat<(i16 (trunc GR32:$src)), - (EXTRACT_SUBREG GR32:$src, sub_16bit)>; -def : Pat<(i8 (trunc GR32:$src)), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), - sub_8bit)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc GR16:$src)), - (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), - sub_8bit)>, - Requires<[Not64BitMode]>; -def : Pat<(i32 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_32bit)>; -def : Pat<(i16 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_16bit)>; -def : Pat<(i8 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_8bit)>; -def : Pat<(i8 (trunc GR32:$src)), - (EXTRACT_SUBREG GR32:$src, sub_8bit)>, - Requires<[In64BitMode]>; -def : Pat<(i8 (trunc GR16:$src)), - (EXTRACT_SUBREG GR16:$src, sub_8bit)>, - Requires<[In64BitMode]>; - -def immff00_ffff : ImmLeaf= 0xff00 && Imm <= 0xffff; -}]>; - -// h-register tricks -def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc (srl_su (i32 (anyext GR16:$src)), (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))), - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(srl GR16:$src, (i8 8)), - (EXTRACT_SUBREG - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_16bit)>; -def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; -def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; -def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; -def : Pat<(srl (and_su GR32:$src, immff00_ffff), (i8 8)), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; - -// h-register tricks. -// For now, be conservative on x86-64 and use an h-register extract only if the -// value is immediately zero-extended or stored, which are somewhat common -// cases. This uses a bunch of code to prevent a register requiring a REX prefix -// from being allocated in the same instruction as the h register, as there's -// currently no way to describe this requirement to the register allocator. - -// h-register extract and zero-extend. -def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi)), - sub_32bit)>; -def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_32bit)>; -def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_32bit)>; - -// h-register extract and store. -def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi))>; -def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>, - Requires<[In64BitMode]>; -def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>, - Requires<[In64BitMode]>; - - -// (shl x, 1) ==> (add x, x) -// Note that if x is undef (immediate or otherwise), we could theoretically -// end up with the two uses of x getting different values, producing a result -// where the least significant bit is not 0. However, the probability of this -// happening is considered low enough that this is officially not a -// "real problem". -def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr GR8 :$src1, GR8 :$src1)>; -def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; -def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; -def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; - -// Helper imms to check if a mask doesn't change significant shift/rotate bits. -def immShift8 : ImmLeaf(Imm) >= 3; -}]>; -def immShift16 : ImmLeaf(Imm) >= 4; -}]>; -def immShift32 : ImmLeaf(Imm) >= 5; -}]>; -def immShift64 : ImmLeaf(Imm) >= 6; -}]>; - -// Shift amount is implicitly masked. -multiclass MaskedShiftAmountPats { - // (shift x (and y, 31)) ==> (shift x, y) - def : Pat<(frag GR8:$src1, (and CL, immShift32)), - (!cast(name # "8rCL") GR8:$src1)>; - def : Pat<(frag GR16:$src1, (and CL, immShift32)), - (!cast(name # "16rCL") GR16:$src1)>; - def : Pat<(frag GR32:$src1, (and CL, immShift32)), - (!cast(name # "32rCL") GR32:$src1)>; - def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "8mCL") addr:$dst)>; - def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "16mCL") addr:$dst)>; - def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "32mCL") addr:$dst)>; - - // (shift x (and y, 63)) ==> (shift x, y) - def : Pat<(frag GR64:$src1, (and CL, immShift64)), - (!cast(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), - (!cast(name # "64mCL") addr:$dst)>; -} - -defm : MaskedShiftAmountPats; -defm : MaskedShiftAmountPats; -defm : MaskedShiftAmountPats; - -// ROL/ROR instructions allow a stronger mask optimization than shift for 8- and -// 16-bit. We can remove a mask of any (bitwidth - 1) on the rotation amount -// because over-rotating produces the same result. This is noted in the Intel -// docs with: "tempCOUNT <- (COUNT & COUNTMASK) MOD SIZE". Masking the rotation -// amount could affect EFLAGS results, but that does not matter because we are -// not tracking flags for these nodes. -multiclass MaskedRotateAmountPats { - // (rot x (and y, BitWidth - 1)) ==> (rot x, y) - def : Pat<(frag GR8:$src1, (and CL, immShift8)), - (!cast(name # "8rCL") GR8:$src1)>; - def : Pat<(frag GR16:$src1, (and CL, immShift16)), - (!cast(name # "16rCL") GR16:$src1)>; - def : Pat<(frag GR32:$src1, (and CL, immShift32)), - (!cast(name # "32rCL") GR32:$src1)>; - def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift8)), addr:$dst), - (!cast(name # "8mCL") addr:$dst)>; - def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift16)), addr:$dst), - (!cast(name # "16mCL") addr:$dst)>; - def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "32mCL") addr:$dst)>; - - // (rot x (and y, 63)) ==> (rot x, y) - def : Pat<(frag GR64:$src1, (and CL, immShift64)), - (!cast(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), - (!cast(name # "64mCL") addr:$dst)>; -} - - -defm : MaskedRotateAmountPats; -defm : MaskedRotateAmountPats; - -// Double shift amount is implicitly masked. -multiclass MaskedDoubleShiftAmountPats { - // (shift x (and y, 31)) ==> (shift x, y) - def : Pat<(frag GR16:$src1, GR16:$src2, (and CL, immShift32)), - (!cast(name # "16rrCL") GR16:$src1, GR16:$src2)>; - def : Pat<(frag GR32:$src1, GR32:$src2, (and CL, immShift32)), - (!cast(name # "32rrCL") GR32:$src1, GR32:$src2)>; - - // (shift x (and y, 63)) ==> (shift x, y) - def : Pat<(frag GR64:$src1, GR64:$src2, (and CL, immShift64)), - (!cast(name # "64rrCL") GR64:$src1, GR64:$src2)>; -} - -defm : MaskedDoubleShiftAmountPats; -defm : MaskedDoubleShiftAmountPats; - -let Predicates = [HasBMI2] in { - let AddedComplexity = 1 in { - def : Pat<(sra GR32:$src1, (and GR8:$src2, immShift32)), - (SARX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra GR64:$src1, (and GR8:$src2, immShift64)), - (SARX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl GR32:$src1, (and GR8:$src2, immShift32)), - (SHRX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl GR64:$src1, (and GR8:$src2, immShift64)), - (SHRX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl GR32:$src1, (and GR8:$src2, immShift32)), - (SHLX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl GR64:$src1, (and GR8:$src2, immShift64)), - (SHLX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } - - def : Pat<(sra (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SARX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SARX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHRX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHRX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHLX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHLX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} - -// Use BTR/BTS/BTC for clearing/setting/toggling a bit in a variable location. -multiclass one_bit_patterns { - def : Pat<(and RC:$src1, (rotl -2, GR8:$src2)), - (BTR RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(or RC:$src1, (shl 1, GR8:$src2)), - (BTS RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(xor RC:$src1, (shl 1, GR8:$src2)), - (BTC RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - // Similar to above, but removing unneeded masking of the shift amount. - def : Pat<(and RC:$src1, (rotl -2, (and GR8:$src2, ImmShift))), - (BTR RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(or RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), - (BTS RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(xor RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), - (BTC RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} - -defm : one_bit_patterns; -defm : one_bit_patterns; -defm : one_bit_patterns; - - -// (anyext (setcc_carry)) -> (setcc_carry) -def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i32 (anyext (i16 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; - -//===----------------------------------------------------------------------===// -// EFLAGS-defining Patterns -//===----------------------------------------------------------------------===// - -// add reg, reg -def : Pat<(add GR8 :$src1, GR8 :$src2), (ADD8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(add GR16:$src1, GR16:$src2), (ADD16rr GR16:$src1, GR16:$src2)>; -def : Pat<(add GR32:$src1, GR32:$src2), (ADD32rr GR32:$src1, GR32:$src2)>; -def : Pat<(add GR64:$src1, GR64:$src2), (ADD64rr GR64:$src1, GR64:$src2)>; - -// add reg, mem -def : Pat<(add GR8:$src1, (loadi8 addr:$src2)), - (ADD8rm GR8:$src1, addr:$src2)>; -def : Pat<(add GR16:$src1, (loadi16 addr:$src2)), - (ADD16rm GR16:$src1, addr:$src2)>; -def : Pat<(add GR32:$src1, (loadi32 addr:$src2)), - (ADD32rm GR32:$src1, addr:$src2)>; -def : Pat<(add GR64:$src1, (loadi64 addr:$src2)), - (ADD64rm GR64:$src1, addr:$src2)>; - -// add reg, imm -def : Pat<(add GR8 :$src1, imm:$src2), (ADD8ri GR8:$src1 , imm:$src2)>; -def : Pat<(add GR16:$src1, imm:$src2), (ADD16ri GR16:$src1, imm:$src2)>; -def : Pat<(add GR32:$src1, imm:$src2), (ADD32ri GR32:$src1, imm:$src2)>; -def : Pat<(add GR16:$src1, i16immSExt8:$src2), - (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(add GR32:$src1, i32immSExt8:$src2), - (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(add GR64:$src1, i64immSExt8:$src2), - (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(add GR64:$src1, i64immSExt32:$src2), - (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// sub reg, reg -def : Pat<(sub GR8 :$src1, GR8 :$src2), (SUB8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(sub GR16:$src1, GR16:$src2), (SUB16rr GR16:$src1, GR16:$src2)>; -def : Pat<(sub GR32:$src1, GR32:$src2), (SUB32rr GR32:$src1, GR32:$src2)>; -def : Pat<(sub GR64:$src1, GR64:$src2), (SUB64rr GR64:$src1, GR64:$src2)>; - -// sub reg, mem -def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)), - (SUB8rm GR8:$src1, addr:$src2)>; -def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)), - (SUB16rm GR16:$src1, addr:$src2)>; -def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)), - (SUB32rm GR32:$src1, addr:$src2)>; -def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)), - (SUB64rm GR64:$src1, addr:$src2)>; - -// sub reg, imm -def : Pat<(sub GR8:$src1, imm:$src2), - (SUB8ri GR8:$src1, imm:$src2)>; -def : Pat<(sub GR16:$src1, imm:$src2), - (SUB16ri GR16:$src1, imm:$src2)>; -def : Pat<(sub GR32:$src1, imm:$src2), - (SUB32ri GR32:$src1, imm:$src2)>; -def : Pat<(sub GR16:$src1, i16immSExt8:$src2), - (SUB16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(sub GR32:$src1, i32immSExt8:$src2), - (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(sub GR64:$src1, i64immSExt8:$src2), - (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(sub GR64:$src1, i64immSExt32:$src2), - (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// sub 0, reg -def : Pat<(X86sub_flag 0, GR8 :$src), (NEG8r GR8 :$src)>; -def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>; -def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>; -def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>; - -// sub reg, relocImm -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt8_su:$src2), - (SUB64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>; -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt32_su:$src2), - (SUB64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>; - -// mul reg, reg -def : Pat<(mul GR16:$src1, GR16:$src2), - (IMUL16rr GR16:$src1, GR16:$src2)>; -def : Pat<(mul GR32:$src1, GR32:$src2), - (IMUL32rr GR32:$src1, GR32:$src2)>; -def : Pat<(mul GR64:$src1, GR64:$src2), - (IMUL64rr GR64:$src1, GR64:$src2)>; - -// mul reg, mem -def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)), - (IMUL16rm GR16:$src1, addr:$src2)>; -def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)), - (IMUL32rm GR32:$src1, addr:$src2)>; -def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)), - (IMUL64rm GR64:$src1, addr:$src2)>; - -// mul reg, imm -def : Pat<(mul GR16:$src1, imm:$src2), - (IMUL16rri GR16:$src1, imm:$src2)>; -def : Pat<(mul GR32:$src1, imm:$src2), - (IMUL32rri GR32:$src1, imm:$src2)>; -def : Pat<(mul GR16:$src1, i16immSExt8:$src2), - (IMUL16rri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(mul GR32:$src1, i32immSExt8:$src2), - (IMUL32rri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(mul GR64:$src1, i64immSExt8:$src2), - (IMUL64rri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(mul GR64:$src1, i64immSExt32:$src2), - (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>; - -// reg = mul mem, imm -def : Pat<(mul (loadi16 addr:$src1), imm:$src2), - (IMUL16rmi addr:$src1, imm:$src2)>; -def : Pat<(mul (loadi32 addr:$src1), imm:$src2), - (IMUL32rmi addr:$src1, imm:$src2)>; -def : Pat<(mul (loadi16 addr:$src1), i16immSExt8:$src2), - (IMUL16rmi8 addr:$src1, i16immSExt8:$src2)>; -def : Pat<(mul (loadi32 addr:$src1), i32immSExt8:$src2), - (IMUL32rmi8 addr:$src1, i32immSExt8:$src2)>; -def : Pat<(mul (loadi64 addr:$src1), i64immSExt8:$src2), - (IMUL64rmi8 addr:$src1, i64immSExt8:$src2)>; -def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2), - (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>; - -// Increment/Decrement reg. -// Do not make INC/DEC if it is slow -let Predicates = [UseIncDec] in { - def : Pat<(add GR8:$src, 1), (INC8r GR8:$src)>; - def : Pat<(add GR16:$src, 1), (INC16r GR16:$src)>; - def : Pat<(add GR32:$src, 1), (INC32r GR32:$src)>; - def : Pat<(add GR64:$src, 1), (INC64r GR64:$src)>; - def : Pat<(add GR8:$src, -1), (DEC8r GR8:$src)>; - def : Pat<(add GR16:$src, -1), (DEC16r GR16:$src)>; - def : Pat<(add GR32:$src, -1), (DEC32r GR32:$src)>; - def : Pat<(add GR64:$src, -1), (DEC64r GR64:$src)>; -} - -// or reg/reg. -def : Pat<(or GR8 :$src1, GR8 :$src2), (OR8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(or GR16:$src1, GR16:$src2), (OR16rr GR16:$src1, GR16:$src2)>; -def : Pat<(or GR32:$src1, GR32:$src2), (OR32rr GR32:$src1, GR32:$src2)>; -def : Pat<(or GR64:$src1, GR64:$src2), (OR64rr GR64:$src1, GR64:$src2)>; - -// or reg/mem -def : Pat<(or GR8:$src1, (loadi8 addr:$src2)), - (OR8rm GR8:$src1, addr:$src2)>; -def : Pat<(or GR16:$src1, (loadi16 addr:$src2)), - (OR16rm GR16:$src1, addr:$src2)>; -def : Pat<(or GR32:$src1, (loadi32 addr:$src2)), - (OR32rm GR32:$src1, addr:$src2)>; -def : Pat<(or GR64:$src1, (loadi64 addr:$src2)), - (OR64rm GR64:$src1, addr:$src2)>; - -// or reg/imm -def : Pat<(or GR8:$src1 , imm:$src2), (OR8ri GR8 :$src1, imm:$src2)>; -def : Pat<(or GR16:$src1, imm:$src2), (OR16ri GR16:$src1, imm:$src2)>; -def : Pat<(or GR32:$src1, imm:$src2), (OR32ri GR32:$src1, imm:$src2)>; -def : Pat<(or GR16:$src1, i16immSExt8:$src2), - (OR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(or GR32:$src1, i32immSExt8:$src2), - (OR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(or GR64:$src1, i64immSExt8:$src2), - (OR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(or GR64:$src1, i64immSExt32:$src2), - (OR64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// xor reg/reg -def : Pat<(xor GR8 :$src1, GR8 :$src2), (XOR8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(xor GR16:$src1, GR16:$src2), (XOR16rr GR16:$src1, GR16:$src2)>; -def : Pat<(xor GR32:$src1, GR32:$src2), (XOR32rr GR32:$src1, GR32:$src2)>; -def : Pat<(xor GR64:$src1, GR64:$src2), (XOR64rr GR64:$src1, GR64:$src2)>; - -// xor reg/mem -def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)), - (XOR8rm GR8:$src1, addr:$src2)>; -def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)), - (XOR16rm GR16:$src1, addr:$src2)>; -def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)), - (XOR32rm GR32:$src1, addr:$src2)>; -def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)), - (XOR64rm GR64:$src1, addr:$src2)>; - -// xor reg/imm -def : Pat<(xor GR8:$src1, imm:$src2), - (XOR8ri GR8:$src1, imm:$src2)>; -def : Pat<(xor GR16:$src1, imm:$src2), - (XOR16ri GR16:$src1, imm:$src2)>; -def : Pat<(xor GR32:$src1, imm:$src2), - (XOR32ri GR32:$src1, imm:$src2)>; -def : Pat<(xor GR16:$src1, i16immSExt8:$src2), - (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(xor GR32:$src1, i32immSExt8:$src2), - (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(xor GR64:$src1, i64immSExt8:$src2), - (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(xor GR64:$src1, i64immSExt32:$src2), - (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// and reg/reg -def : Pat<(and GR8 :$src1, GR8 :$src2), (AND8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(and GR16:$src1, GR16:$src2), (AND16rr GR16:$src1, GR16:$src2)>; -def : Pat<(and GR32:$src1, GR32:$src2), (AND32rr GR32:$src1, GR32:$src2)>; -def : Pat<(and GR64:$src1, GR64:$src2), (AND64rr GR64:$src1, GR64:$src2)>; - -// and reg/mem -def : Pat<(and GR8:$src1, (loadi8 addr:$src2)), - (AND8rm GR8:$src1, addr:$src2)>; -def : Pat<(and GR16:$src1, (loadi16 addr:$src2)), - (AND16rm GR16:$src1, addr:$src2)>; -def : Pat<(and GR32:$src1, (loadi32 addr:$src2)), - (AND32rm GR32:$src1, addr:$src2)>; -def : Pat<(and GR64:$src1, (loadi64 addr:$src2)), - (AND64rm GR64:$src1, addr:$src2)>; - -// and reg/imm -def : Pat<(and GR8:$src1, imm:$src2), - (AND8ri GR8:$src1, imm:$src2)>; -def : Pat<(and GR16:$src1, imm:$src2), - (AND16ri GR16:$src1, imm:$src2)>; -def : Pat<(and GR32:$src1, imm:$src2), - (AND32ri GR32:$src1, imm:$src2)>; -def : Pat<(and GR16:$src1, i16immSExt8:$src2), - (AND16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(and GR32:$src1, i32immSExt8:$src2), - (AND32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(and GR64:$src1, i64immSExt8:$src2), - (AND64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(and GR64:$src1, i64immSExt32:$src2), - (AND64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// Bit scan instruction patterns to match explicit zero-undef behavior. -def : Pat<(cttz_zero_undef GR16:$src), (BSF16rr GR16:$src)>; -def : Pat<(cttz_zero_undef GR32:$src), (BSF32rr GR32:$src)>; -def : Pat<(cttz_zero_undef GR64:$src), (BSF64rr GR64:$src)>; -def : Pat<(cttz_zero_undef (loadi16 addr:$src)), (BSF16rm addr:$src)>; -def : Pat<(cttz_zero_undef (loadi32 addr:$src)), (BSF32rm addr:$src)>; -def : Pat<(cttz_zero_undef (loadi64 addr:$src)), (BSF64rm addr:$src)>; - -// When HasMOVBE is enabled it is possible to get a non-legalized -// register-register 16 bit bswap. This maps it to a ROL instruction. -let Predicates = [HasMOVBE] in { - def : Pat<(bswap GR16:$src), (ROL16ri GR16:$src, (i8 8))>; -} - -// These patterns are selected by some custom code in X86ISelDAGToDAG.cpp that -// custom combines and+srl into BEXTR. We use these patterns to avoid a bunch -// of manual code for folding loads. -let Predicates = [HasBMI, NoTBM] in { - def : Pat<(X86bextr GR32:$src1, (i32 imm:$src2)), - (BEXTR32rr GR32:$src1, (MOV32ri imm:$src2))>; - def : Pat<(X86bextr (loadi32 addr:$src1), (i32 imm:$src2)), - (BEXTR32rm addr:$src1, (MOV32ri imm:$src2))>; - def : Pat<(X86bextr GR64:$src1, mov64imm32:$src2), - (BEXTR64rr GR64:$src1, - (SUBREG_TO_REG (i64 0), - (MOV32ri64 mov64imm32:$src2), - sub_32bit))>; - def : Pat<(X86bextr (loadi64 addr:$src1), mov64imm32:$src2), - (BEXTR64rm addr:$src1, - (SUBREG_TO_REG (i64 0), - (MOV32ri64 mov64imm32:$src2), - sub_32bit))>; -} // HasBMI, NoTBM diff --git a/suite/synctools/tablegen/X86/X86InstrControl.td b/suite/synctools/tablegen/X86/X86InstrControl.td deleted file mode 100644 index 3271b43e3f..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrControl.td +++ /dev/null @@ -1,413 +0,0 @@ -//===-- X86InstrControl.td - Control Flow Instructions -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 jump, return, call, and related instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Control Flow Instructions. -// - -// Return instructions. -// -// The X86retflag return instructions are variadic because we may add ST0 and -// ST1 arguments when returning values on the x87 stack. -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, FPForm = SpecialFP, SchedRW = [WriteJumpLd] in { - def RETL : I <0xC3, RawFrm, (outs), (ins variable_ops), - "ret{l}", []>, OpSize32, Requires<[Not64BitMode]>; - def RETQ : I <0xC3, RawFrm, (outs), (ins variable_ops), - "ret{q}", []>, OpSize32, Requires<[In64BitMode]>; - def RETW : I <0xC3, RawFrm, (outs), (ins), - "ret{w}", []>, OpSize16; - def RETIL : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), - "ret{l}\t$amt", []>, OpSize32, Requires<[Not64BitMode]>; - def RETIQ : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), - "ret{q}\t$amt", []>, OpSize32, Requires<[In64BitMode]>; - def RETIW : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt), - "ret{w}\t$amt", []>, OpSize16; - def LRETL : I <0xCB, RawFrm, (outs), (ins), - "{l}ret{l|f}", []>, OpSize32; - def LRETQ : RI <0xCB, RawFrm, (outs), (ins), - "{l}ret{|f}q", []>, Requires<[In64BitMode]>; - def LRETW : I <0xCB, RawFrm, (outs), (ins), - "{l}ret{w|f}", []>, OpSize16; - def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{l|f}\t$amt", []>, OpSize32; - def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{|f}q\t$amt", []>, Requires<[In64BitMode]>; - def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{w|f}\t$amt", []>, OpSize16; - - // The machine return from interrupt instruction, but sometimes we need to - // perform a post-epilogue stack adjustment. Codegen emits the pseudo form - // which expands to include an SP adjustment if necessary. - def IRET16 : I <0xcf, RawFrm, (outs), (ins), "iret{w}", []>, - OpSize16; - def IRET32 : I <0xcf, RawFrm, (outs), (ins), "iret{l|d}", []>, OpSize32; - def IRET64 : RI <0xcf, RawFrm, (outs), (ins), "iretq", []>, Requires<[In64BitMode]>; - // let isCodeGenOnly = 1 in - // def IRET : PseudoI<(outs), (ins i32imm:$adj), [(X86iret timm:$adj)]>; - // def RET : PseudoI<(outs), (ins i32imm:$adj, variable_ops), [(X86retflag timm:$adj)]>; -} - -// Unconditional branches. -let isBarrier = 1, isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in { - def JMP_1 : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst), - "jmp\t$dst", [(br bb:$dst)]>; - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def JMP_2 : Ii16PCRel<0xE9, RawFrm, (outs), (ins brtarget16:$dst), - "jmp\t$dst", []>, OpSize16; - def JMP_4 : Ii32PCRel<0xE9, RawFrm, (outs), (ins brtarget32:$dst), - "jmp\t$dst", []>, OpSize32; - } -} - -// Conditional Branches. -let isBranch = 1, isTerminator = 1, Uses = [EFLAGS], SchedRW = [WriteJump] in { - multiclass ICBr opc1, bits<8> opc4, string asm, PatFrag Cond> { - def _1 : Ii8PCRel ; - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def _2 : Ii16PCRel, OpSize16, TB; - def _4 : Ii32PCRel, TB, OpSize32; - } - } -} - -defm JO : ICBr<0x70, 0x80, "jo\t$dst" , X86_COND_O>; -defm JNO : ICBr<0x71, 0x81, "jno\t$dst", X86_COND_NO>; -defm JB : ICBr<0x72, 0x82, "jb\t$dst" , X86_COND_B>; -defm JAE : ICBr<0x73, 0x83, "jae\t$dst", X86_COND_AE>; -defm JE : ICBr<0x74, 0x84, "je\t$dst" , X86_COND_E>; -defm JNE : ICBr<0x75, 0x85, "jne\t$dst", X86_COND_NE>; -defm JBE : ICBr<0x76, 0x86, "jbe\t$dst", X86_COND_BE>; -defm JA : ICBr<0x77, 0x87, "ja\t$dst" , X86_COND_A>; -defm JS : ICBr<0x78, 0x88, "js\t$dst" , X86_COND_S>; -defm JNS : ICBr<0x79, 0x89, "jns\t$dst", X86_COND_NS>; -defm JP : ICBr<0x7A, 0x8A, "jp\t$dst" , X86_COND_P>; -defm JNP : ICBr<0x7B, 0x8B, "jnp\t$dst", X86_COND_NP>; -defm JL : ICBr<0x7C, 0x8C, "jl\t$dst" , X86_COND_L>; -defm JGE : ICBr<0x7D, 0x8D, "jge\t$dst", X86_COND_GE>; -defm JLE : ICBr<0x7E, 0x8E, "jle\t$dst", X86_COND_LE>; -defm JG : ICBr<0x7F, 0x8F, "jg\t$dst" , X86_COND_G>; - -// jcx/jecx/jrcx instructions. -let isBranch = 1, isTerminator = 1, hasSideEffects = 0, SchedRW = [WriteJump] in { - // These are the 32-bit versions of this instruction for the asmparser. In - // 32-bit mode, the address size prefix is jcxz and the unprefixed version is - // jecxz. - let Uses = [CX] in - def JCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jcxz\t$dst", []>, AdSize16, Requires<[Not64BitMode]>; - let Uses = [ECX] in - def JECXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jecxz\t$dst", []>, AdSize32; - - let Uses = [RCX] in - def JRCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jrcxz\t$dst", []>, AdSize64, Requires<[In64BitMode]>; -} - -// Indirect branches -let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { - def JMP16r : I<0xFF, MRM4r, (outs), (ins GR16:$dst), "jmp{w}\t{*}$dst", - [(brind GR16:$dst)]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJump]>; - def JMP16m : I<0xFF, MRM4m, (outs), (ins i16mem:$dst), "jmp{w}\t{*}$dst", - [(brind (loadi16 addr:$dst))]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJumpLd]>; - - def JMP32r : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst", - [(brind GR32:$dst)]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJump]>; - def JMP32m : I<0xFF, MRM4m, (outs), (ins i32mem:$dst), "jmp{l}\t{*}$dst", - [(brind (loadi32 addr:$dst))]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJumpLd]>; - - def JMP64r : I<0xFF, MRM4r, (outs), (ins GR64:$dst), "jmp{q}\t{*}$dst", - [(brind GR64:$dst)]>, Requires<[In64BitMode]>, - Sched<[WriteJump]>; - def JMP64m : I<0xFF, MRM4m, (outs), (ins i64mem:$dst), "jmp{q}\t{*}$dst", - [(brind (loadi64 addr:$dst))]>, Requires<[In64BitMode]>, - Sched<[WriteJumpLd]>; - - // Non-tracking jumps for IBT, use with caution. - let isCodeGenOnly = 1 in { - def JMP16r_NT : I<0xFF, MRM4r, (outs), (ins GR16 : $dst), "jmp{w}\t{*}$dst", - [(X86NoTrackBrind GR16 : $dst)]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJump]>, NOTRACK; - - def JMP16m_NT : I<0xFF, MRM4m, (outs), (ins i16mem : $dst), "jmp{w}\t{*}$dst", - [(X86NoTrackBrind (loadi16 addr : $dst))]>, - Requires<[Not64BitMode]>, OpSize16, Sched<[WriteJumpLd]>, - NOTRACK; - - def JMP32r_NT : I<0xFF, MRM4r, (outs), (ins GR32 : $dst), "jmp{l}\t{*}$dst", - [(X86NoTrackBrind GR32 : $dst)]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJump]>, NOTRACK; - def JMP32m_NT : I<0xFF, MRM4m, (outs), (ins i32mem : $dst), "jmp{l}\t{*}$dst", - [(X86NoTrackBrind (loadi32 addr : $dst))]>, - Requires<[Not64BitMode]>, OpSize32, Sched<[WriteJumpLd]>, - NOTRACK; - - def JMP64r_NT : I<0xFF, MRM4r, (outs), (ins GR64 : $dst), "jmp{q}\t{*}$dst", - [(X86NoTrackBrind GR64 : $dst)]>, Requires<[In64BitMode]>, - Sched<[WriteJump]>, NOTRACK; - def JMP64m_NT : I<0xFF, MRM4m, (outs), (ins i64mem : $dst), "jmp{q}\t{*}$dst", - [(X86NoTrackBrind(loadi64 addr : $dst))]>, - Requires<[In64BitMode]>, Sched<[WriteJumpLd]>, NOTRACK; - } - - let Predicates = [Not64BitMode], AsmVariantName = "att" in { - def FARJMP16i : Iseg16<0xEA, RawFrmImm16, (outs), - (ins i16imm:$off, i16imm:$seg), - "ljmp{w}\t$seg : $off", []>, - OpSize16, Sched<[WriteJump]>; - def FARJMP32i : Iseg32<0xEA, RawFrmImm16, (outs), - (ins i32imm:$off, i16imm:$seg), - "ljmp{l}\t$seg : $off", []>, - OpSize32, Sched<[WriteJump]>; - } - def FARJMP64 : RI<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "ljmp{q}\t{*}$dst", []>, Sched<[WriteJump]>, Requires<[In64BitMode]>; - - let AsmVariantName = "att" in - def FARJMP16m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "ljmp{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; - def FARJMP32m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "{l}jmp{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; -} - -// Loop instructions -let SchedRW = [WriteJump] in { -def LOOP : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", []>; -def LOOPE : Ii8PCRel<0xE1, RawFrm, (outs), (ins brtarget8:$dst), "loope\t$dst", []>; -def LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins brtarget8:$dst), "loopne\t$dst", []>; -} - -//===----------------------------------------------------------------------===// -// Call Instructions... -// -let isCall = 1 in - // All calls clobber the non-callee saved registers. ESP is marked as - // a use to prevent stack-pointer assignments that appear immediately - // before calls from potentially appearing dead. Uses for argument - // registers are added manually. - let Uses = [ESP, SSP] in { - def CALLpcrel32 : Ii32PCRel<0xE8, RawFrm, - (outs), (ins i32imm_pcrel:$dst), - "call{l}\t$dst", []>, OpSize32, - Requires<[Not64BitMode]>, Sched<[WriteJump]>; - let hasSideEffects = 0 in - def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm, - (outs), (ins i16imm_pcrel:$dst), - "call{w}\t$dst", []>, OpSize16, - Sched<[WriteJump]>; - def CALL16r : I<0xFF, MRM2r, (outs), (ins GR16:$dst), - "call{w}\t{*}$dst", [(X86call GR16:$dst)]>, - OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>; - def CALL16m : I<0xFF, MRM2m, (outs), (ins i16mem:$dst), - "call{w}\t{*}$dst", [(X86call (loadi16 addr:$dst))]>, - OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>; - def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst), - "call{l}\t{*}$dst", [(X86call GR32:$dst)]>, OpSize32, - Requires<[Not64BitMode,NotUseRetpoline]>, Sched<[WriteJump]>; - def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst), - "call{l}\t{*}$dst", [(X86call (loadi32 addr:$dst))]>, - OpSize32, - Requires<[Not64BitMode,FavorMemIndirectCall,NotUseRetpoline]>, - Sched<[WriteJumpLd]>; - - // Non-tracking calls for IBT, use with caution. - let isCodeGenOnly = 1 in { - def CALL16r_NT : I<0xFF, MRM2r, (outs), (ins GR16 : $dst), - "call{w}\t{*}$dst",[(X86NoTrackCall GR16 : $dst)]>, - OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; - def CALL16m_NT : I<0xFF, MRM2m, (outs), (ins i16mem : $dst), - "call{w}\t{*}$dst",[(X86NoTrackCall(loadi16 addr : $dst))]>, - OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>, NOTRACK; - def CALL32r_NT : I<0xFF, MRM2r, (outs), (ins GR32 : $dst), - "call{l}\t{*}$dst",[(X86NoTrackCall GR32 : $dst)]>, - OpSize32, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; - def CALL32m_NT : I<0xFF, MRM2m, (outs), (ins i32mem : $dst), - "call{l}\t{*}$dst",[(X86NoTrackCall(loadi32 addr : $dst))]>, - OpSize32, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>, NOTRACK; - } - - let Predicates = [Not64BitMode], AsmVariantName = "att" in { - def FARCALL16i : Iseg16<0x9A, RawFrmImm16, (outs), - (ins i16imm:$off, i16imm:$seg), - "lcall{w}\t$seg : $off", []>, - OpSize16, Sched<[WriteJump]>; - def FARCALL32i : Iseg32<0x9A, RawFrmImm16, (outs), - (ins i32imm:$off, i16imm:$seg), - "lcall{l}\t$seg : $off", []>, - OpSize32, Sched<[WriteJump]>; - } - - def FARCALL16m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "lcall{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; - def FARCALL32m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "{l}call{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; - } - - -/* -// Tail call stuff. -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [ESP, SSP] in { - def TCRETURNdi : PseudoI<(outs), - (ins i32imm_pcrel:$dst, i32imm:$offset), []>, NotMemoryFoldable; - def TCRETURNri : PseudoI<(outs), - (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>, NotMemoryFoldable; - let mayLoad = 1 in - def TCRETURNmi : PseudoI<(outs), - (ins i32mem_TC:$dst, i32imm:$offset), []>; - - // FIXME: The should be pseudo instructions that are lowered when going to - // mcinst. - def TAILJMPd : Ii32PCRel<0xE9, RawFrm, (outs), - (ins i32imm_pcrel:$dst), "jmp\t$dst", []>; - - def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "", []>; // FIXME: Remove encoding when JIT is dead. - let mayLoad = 1 in - def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem_TC:$dst), - "jmp{l}\t{*}$dst", []>; -} - -// Conditional tail calls are similar to the above, but they are branches -// rather than barriers, and they use EFLAGS. -let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [ESP, EFLAGS, SSP] in { - def TCRETURNdicc : PseudoI<(outs), - (ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>; - - // This gets substituted to a conditional jump instruction in MC lowering. - def TAILJMPd_CC : Ii32PCRel<0x80, RawFrm, (outs), - (ins i32imm_pcrel:$dst, i32imm:$cond), "", []>; -} -*/ - - -//===----------------------------------------------------------------------===// -// Call Instructions... -// - -// RSP is marked as a use to prevent stack-pointer assignments that appear -// immediately before calls from potentially appearing dead. Uses for argument -// registers are added manually. -let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in { - // NOTE: this pattern doesn't match "X86call imm", because we do not know - // that the offset between an arbitrary immediate and the call will fit in - // the 32-bit pcrel field that we have. - def CALL64pcrel32 : Ii32PCRel<0xE8, RawFrm, - (outs), (ins i64i32imm_pcrel:$dst), - "call{q}\t$dst", []>, OpSize32, - Requires<[In64BitMode]>; - def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst), - "call{q}\t{*}$dst", [(X86call GR64:$dst)]>, - Requires<[In64BitMode,NotUseRetpoline]>; - def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst), - "call{q}\t{*}$dst", [(X86call (loadi64 addr:$dst))]>, - Requires<[In64BitMode,FavorMemIndirectCall, - NotUseRetpoline]>; - - // Non-tracking calls for IBT, use with caution. - let isCodeGenOnly = 1 in { - def CALL64r_NT : I<0xFF, MRM2r, (outs), (ins GR64 : $dst), - "call{q}\t{*}$dst",[(X86NoTrackCall GR64 : $dst)]>, - Requires<[In64BitMode]>, NOTRACK; - def CALL64m_NT : I<0xFF, MRM2m, (outs), (ins i64mem : $dst), - "call{q}\t{*}$dst", - [(X86NoTrackCall(loadi64 addr : $dst))]>, - Requires<[In64BitMode,FavorMemIndirectCall]>, NOTRACK; - } - - def FARCALL64 : RI<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "lcall{q}\t{*}$dst", []>; -} - -/* -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, - isCodeGenOnly = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in { - def TCRETURNdi64 : PseudoI<(outs), - (ins i64i32imm_pcrel:$dst, i32imm:$offset), - []>; - def TCRETURNri64 : PseudoI<(outs), - (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>, NotMemoryFoldable; - let mayLoad = 1 in - def TCRETURNmi64 : PseudoI<(outs), - (ins i64mem_TC:$dst, i32imm:$offset), []>, NotMemoryFoldable; - - def TAILJMPd64 : Ii32PCRel<0xE9, RawFrm, (outs), (ins i64i32imm_pcrel:$dst), - "jmp\t$dst", []>; - - def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "jmp{q}\t{*}$dst", []>; - - let mayLoad = 1 in - def TAILJMPm64 : I<0xFF, MRM4m, (outs), (ins i64mem_TC:$dst), - "jmp{q}\t{*}$dst", []>; - - // Win64 wants indirect jumps leaving the function to have a REX_W prefix. - let hasREX_WPrefix = 1 in { - def TAILJMPr64_REX : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "rex64 jmp{q}\t{*}$dst", []>; - - let mayLoad = 1 in - def TAILJMPm64_REX : I<0xFF, MRM4m, (outs), (ins i64mem_TC:$dst), - "rex64 jmp{q}\t{*}$dst", []>; - } -} - -let isPseudo = 1, isCall = 1, isCodeGenOnly = 1, - Uses = [RSP, SSP], - usesCustomInserter = 1, - SchedRW = [WriteJump] in { - def RETPOLINE_CALL32 : - PseudoI<(outs), (ins GR32:$dst), [(X86call GR32:$dst)]>, - Requires<[Not64BitMode,UseRetpoline]>; - - def RETPOLINE_CALL64 : - PseudoI<(outs), (ins GR64:$dst), [(X86call GR64:$dst)]>, - Requires<[In64BitMode,UseRetpoline]>; - - // Retpoline variant of indirect tail calls. - let isTerminator = 1, isReturn = 1, isBarrier = 1 in { - def RETPOLINE_TCRETURN64 : - PseudoI<(outs), (ins GR64:$dst, i32imm:$offset), []>; - def RETPOLINE_TCRETURN32 : - PseudoI<(outs), (ins GR32:$dst, i32imm:$offset), []>; - } -} - -// Conditional tail calls are similar to the above, but they are branches -// rather than barriers, and they use EFLAGS. -let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [RSP, EFLAGS, SSP] in { - def TCRETURNdi64cc : PseudoI<(outs), - (ins i64i32imm_pcrel:$dst, i32imm:$offset, - i32imm:$cond), []>; - - // This gets substituted to a conditional jump instruction in MC lowering. - def TAILJMPd64_CC : Ii32PCRel<0x80, RawFrm, (outs), - (ins i64i32imm_pcrel:$dst, i32imm:$cond), "", []>; -} -*/ diff --git a/suite/synctools/tablegen/X86/X86InstrExtension.td b/suite/synctools/tablegen/X86/X86InstrExtension.td deleted file mode 100644 index 421792c559..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrExtension.td +++ /dev/null @@ -1,204 +0,0 @@ -//===-- X86InstrExtension.td - Sign and Zero Extensions ----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the sign and zero extension operations. -// -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0 in { - let Defs = [AX], Uses = [AL] in // AX = signext(AL) - def CBW : I<0x98, RawFrm, (outs), (ins), - "{cbtw|cbw}", []>, OpSize16, Sched<[WriteALU]>; - let Defs = [EAX], Uses = [AX] in // EAX = signext(AX) - def CWDE : I<0x98, RawFrm, (outs), (ins), - "{cwtl|cwde}", []>, OpSize32, Sched<[WriteALU]>; - - let Defs = [AX,DX], Uses = [AX] in // DX:AX = signext(AX) - def CWD : I<0x99, RawFrm, (outs), (ins), - "{cwtd|cwd}", []>, OpSize16, Sched<[WriteALU]>; - let Defs = [EAX,EDX], Uses = [EAX] in // EDX:EAX = signext(EAX) - def CDQ : I<0x99, RawFrm, (outs), (ins), - "{cltd|cdq}", []>, OpSize32, Sched<[WriteALU]>; - - - let Defs = [RAX], Uses = [EAX] in // RAX = signext(EAX) - def CDQE : RI<0x98, RawFrm, (outs), (ins), - "{cltq|cdqe}", []>, Sched<[WriteALU]>; - - let Defs = [RAX,RDX], Uses = [RAX] in // RDX:RAX = signext(RAX) - def CQO : RI<0x99, RawFrm, (outs), (ins), - "{cqto|cqo}", []>, Sched<[WriteALU]>; -} - -// Sign/Zero extenders -let hasSideEffects = 0 in { -def MOVSX16rr8 : I<0xBE, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src), - "movs{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVSX16rm8 : I<0xBE, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src), - "movs{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALULd]>; -} // hasSideEffects = 0 -def MOVSX32rr8 : I<0xBE, MRMSrcReg, (outs GR32:$dst), (ins GR8:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sext GR8:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVSX32rm8 : I<0xBE, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sextloadi32i8 addr:$src))]>, TB, - OpSize32, Sched<[WriteALULd]>; -def MOVSX32rr16: I<0xBF, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), - "movs{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sext GR16:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVSX32rm16: I<0xBF, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "movs{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sextloadi32i16 addr:$src))]>, - OpSize32, TB, Sched<[WriteALULd]>; - -let hasSideEffects = 0 in { -def MOVZX16rr8 : I<0xB6, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src), - "movz{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX16rm8 : I<0xB6, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src), - "movz{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALULd]>; -} // hasSideEffects = 0 -def MOVZX32rr8 : I<0xB6, MRMSrcReg, (outs GR32:$dst), (ins GR8 :$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zext GR8:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVZX32rm8 : I<0xB6, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zextloadi32i8 addr:$src))]>, TB, - OpSize32, Sched<[WriteALULd]>; -def MOVZX32rr16: I<0xB7, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), - "movz{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zext GR16:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "movz{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, - TB, OpSize32, Sched<[WriteALULd]>; - -// These instructions exist as a consequence of operand size prefix having -// control of the destination size, but not the input size. Only support them -// for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOVSX16rr16: I<0xBF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "movs{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALU]>, NotMemoryFoldable; -def MOVZX16rr16: I<0xB7, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "movz{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALU]>, NotMemoryFoldable; -let mayLoad = 1 in { -def MOVSX16rm16: I<0xBF, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movs{ww|x}\t{$src, $dst|$dst, $src}", - []>, OpSize16, TB, Sched<[WriteALULd]>, NotMemoryFoldable; -def MOVZX16rm16: I<0xB7, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movz{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALULd]>, NotMemoryFoldable; -} // mayLoad = 1 -} // isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 - -// These are the same as the regular MOVZX32rr8 and MOVZX32rm8 -// except that they use GR32_NOREX for the output operand register class -// instead of GR32. This allows them to operate on h registers on x86-64. -let hasSideEffects = 0, isCodeGenOnly = 1 in { -def MOVZX32rr8_NOREX : I<0xB6, MRMSrcReg, - (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX32rm8_NOREX : I<0xB6, MRMSrcMem, - (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALULd]>; - -def MOVSX32rr8_NOREX : I<0xBE, MRMSrcReg, - (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVSX32rm8_NOREX : I<0xBE, MRMSrcMem, - (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALULd]>; -} - -// MOVSX64rr8 always has a REX prefix and it has an 8-bit register -// operand, which makes it a rare instruction with an 8-bit register -// operand that can never access an h register. If support for h registers -// were generalized, this would require a special register class. -def MOVSX64rr8 : RI<0xBE, MRMSrcReg, (outs GR64:$dst), (ins GR8 :$src), - "movs{bq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR8:$src))]>, TB, - Sched<[WriteALU]>; -def MOVSX64rm8 : RI<0xBE, MRMSrcMem, (outs GR64:$dst), (ins i8mem :$src), - "movs{bq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i8 addr:$src))]>, - TB, Sched<[WriteALULd]>; -def MOVSX64rr16: RI<0xBF, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), - "movs{wq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR16:$src))]>, TB, - Sched<[WriteALU]>; -def MOVSX64rm16: RI<0xBF, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "movs{wq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i16 addr:$src))]>, - TB, Sched<[WriteALULd]>; -def MOVSX64rr32: RI<0x63, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "movs{lq|xd}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR32:$src))]>, - Sched<[WriteALU]>, Requires<[In64BitMode]>; -def MOVSX64rm32: RI<0x63, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), - "movs{lq|xd}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i32 addr:$src))]>, - Sched<[WriteALULd]>, Requires<[In64BitMode]>; - -// movzbq and movzwq encodings for the disassembler -let hasSideEffects = 0 in { -def MOVZX64rr8 : RI<0xB6, MRMSrcReg, (outs GR64:$dst), (ins GR8:$src), - "movz{bq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX64rm8 : RI<0xB6, MRMSrcMem, (outs GR64:$dst), (ins i8mem:$src), - "movz{bq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALULd]>; -def MOVZX64rr16 : RI<0xB7, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), - "movz{wq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX64rm16 : RI<0xB7, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "movz{wq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALULd]>; -} - -// 64-bit zero-extension patterns use SUBREG_TO_REG and an operation writing a -// 32-bit register. -def : Pat<(i64 (zext GR8:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8:$src), sub_32bit)>; -def : Pat<(zextloadi64i8 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; - -def : Pat<(i64 (zext GR16:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16:$src), sub_32bit)>; -def : Pat<(zextloadi64i16 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>; - -// The preferred way to do 32-bit-to-64-bit zero extension on x86-64 is to use a -// SUBREG_TO_REG to utilize implicit zero-extension, however this isn't possible -// when the 32-bit value is defined by a truncate or is copied from something -// where the high bits aren't necessarily all zero. In such cases, we fall back -// to these explicit zext instructions. -def : Pat<(i64 (zext GR32:$src)), - (SUBREG_TO_REG (i64 0), (MOV32rr GR32:$src), sub_32bit)>; -def : Pat<(i64 (zextloadi64i32 addr:$src)), - (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>; diff --git a/suite/synctools/tablegen/X86/X86InstrFMA.td b/suite/synctools/tablegen/X86/X86InstrFMA.td deleted file mode 100644 index 18277417a3..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrFMA.td +++ /dev/null @@ -1,636 +0,0 @@ -//===-- X86InstrFMA.td - FMA Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes FMA (Fused Multiply-Add) instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// FMA3 - Intel 3 operand Fused Multiply-Add instructions -//===----------------------------------------------------------------------===// - -// For all FMA opcodes declared in fma3p_rm_* and fma3s_rm_* multiclasses -// defined below, both the register and memory variants are commutable. -// For the register form the commutable operands are 1, 2 and 3. -// For the memory variant the folded operand must be in 3. Thus, -// in that case, only the operands 1 and 2 can be swapped. -// Commuting some of operands may require the opcode change. -// FMA*213*: -// operands 1 and 2 (memory & register forms): *213* --> *213*(no changes); -// operands 1 and 3 (register forms only): *213* --> *231*; -// operands 2 and 3 (register forms only): *213* --> *132*. -// FMA*132*: -// operands 1 and 2 (memory & register forms): *132* --> *231*; -// operands 1 and 3 (register forms only): *132* --> *132*(no changes); -// operands 2 and 3 (register forms only): *132* --> *213*. -// FMA*231*: -// operands 1 and 2 (memory & register forms): *231* --> *132*; -// operands 1 and 3 (register forms only): *231* --> *213*; -// operands 2 and 3 (register forms only): *231* --> *231*(no changes). - -multiclass fma3p_rm_213 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - def r : FMA3, - Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3p_rm_231 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3, Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3p_rm_132 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", hasSideEffects = 0, isCommutable = 1 in -multiclass fma3p_forms opc132, bits<8> opc213, bits<8> opc231, - string OpcodeStr, string PackTy, string Suff, - PatFrag MemFrag128, PatFrag MemFrag256, - SDNode Op, ValueType OpTy128, ValueType OpTy256, - X86SchedWriteWidths sched> { - defm NAME#213#Suff : fma3p_rm_213; - defm NAME#231#Suff : fma3p_rm_231; - defm NAME#132#Suff : fma3p_rm_132; - - defm NAME#213#Suff#Y : fma3p_rm_213, - VEX_L; - defm NAME#231#Suff#Y : fma3p_rm_231, - VEX_L; - defm NAME#132#Suff#Y : fma3p_rm_132, - VEX_L; -} - -// Fused Multiply-Add -let ExeDomain = SSEPackedSingle in { - defm VFMADD : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "ps", "PS", - loadv4f32, loadv8f32, X86Fmadd, v4f32, v8f32, - SchedWriteFMA>; - defm VFMSUB : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "ps", "PS", - loadv4f32, loadv8f32, X86Fmsub, v4f32, v8f32, - SchedWriteFMA>; - defm VFMADDSUB : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "ps", "PS", - loadv4f32, loadv8f32, X86Fmaddsub, v4f32, v8f32, - SchedWriteFMA>; - defm VFMSUBADD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "ps", "PS", - loadv4f32, loadv8f32, X86Fmsubadd, v4f32, v8f32, - SchedWriteFMA>; -} - -let ExeDomain = SSEPackedDouble in { - defm VFMADD : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "pd", "PD", - loadv2f64, loadv4f64, X86Fmadd, v2f64, - v4f64, SchedWriteFMA>, VEX_W; - defm VFMSUB : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "pd", "PD", - loadv2f64, loadv4f64, X86Fmsub, v2f64, - v4f64, SchedWriteFMA>, VEX_W; - defm VFMADDSUB : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "pd", "PD", - loadv2f64, loadv4f64, X86Fmaddsub, - v2f64, v4f64, SchedWriteFMA>, VEX_W; - defm VFMSUBADD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "pd", "PD", - loadv2f64, loadv4f64, X86Fmsubadd, - v2f64, v4f64, SchedWriteFMA>, VEX_W; -} - -// Fused Negative Multiply-Add -let ExeDomain = SSEPackedSingle in { - defm VFNMADD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "ps", "PS", loadv4f32, - loadv8f32, X86Fnmadd, v4f32, v8f32, SchedWriteFMA>; - defm VFNMSUB : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "ps", "PS", loadv4f32, - loadv8f32, X86Fnmsub, v4f32, v8f32, SchedWriteFMA>; -} -let ExeDomain = SSEPackedDouble in { - defm VFNMADD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "pd", "PD", loadv2f64, - loadv4f64, X86Fnmadd, v2f64, v4f64, SchedWriteFMA>, VEX_W; - defm VFNMSUB : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "pd", "PD", loadv2f64, - loadv4f64, X86Fnmsub, v2f64, v4f64, SchedWriteFMA>, VEX_W; -} - -// All source register operands of FMA opcodes defined in fma3s_rm multiclass -// can be commuted. In many cases such commute transformation requires an opcode -// adjustment, for example, commuting the operands 1 and 2 in FMA*132 form -// would require an opcode change to FMA*231: -// FMA*132* reg1, reg2, reg3; // reg1 * reg3 + reg2; -// --> -// FMA*231* reg2, reg1, reg3; // reg1 * reg3 + reg2; -// Please see more detailed comment at the very beginning of the section -// defining FMA3 opcodes above. -multiclass fma3s_rm_213 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched> { - def r : FMA3S, - Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3s_rm_231 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3S, Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3s_rm_132 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3S, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", isCommutable = 1, hasSideEffects = 0 in -multiclass fma3s_forms opc132, bits<8> opc213, bits<8> opc231, - string OpStr, string PackTy, string Suff, - SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched> { - defm NAME#213#Suff : fma3s_rm_213; - defm NAME#231#Suff : fma3s_rm_231; - defm NAME#132#Suff : fma3s_rm_132; -} - -// These FMA*_Int instructions are defined specially for being used when -// the scalar FMA intrinsics are lowered to machine instructions, and in that -// sense, they are similar to existing ADD*_Int, SUB*_Int, MUL*_Int, etc. -// instructions. -// -// All of the FMA*_Int opcodes are defined as commutable here. -// Commuting the 2nd and 3rd source register operands of FMAs is quite trivial -// and the corresponding optimizations have been developed. -// Commuting the 1st operand of FMA*_Int requires some additional analysis, -// the commute optimization is legal only if all users of FMA*_Int use only -// the lowest element of the FMA*_Int instruction. Even though such analysis -// may be not implemented yet we allow the routines doing the actual commute -// transformation to decide if one or another instruction is commutable or not. -let Constraints = "$src1 = $dst", isCommutable = 1, isCodeGenOnly = 1, - hasSideEffects = 0 in -multiclass fma3s_rm_int opc, string OpcodeStr, - Operand memopr, RegisterClass RC, - X86FoldableSchedWrite sched> { - def r_Int : FMA3S_Int, Sched<[sched]>; - - let mayLoad = 1 in - def m_Int : FMA3S_Int, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -// The FMA 213 form is created for lowering of scalar FMA intrinscis -// to machine instructions. -// The FMA 132 form can trivially be get by commuting the 2nd and 3rd operands -// of FMA 213 form. -// The FMA 231 form can be get only by commuting the 1st operand of 213 or 132 -// forms and is possible only after special analysis of all uses of the initial -// instruction. Such analysis do not exist yet and thus introducing the 231 -// form of FMA*_Int instructions is done using an optimistic assumption that -// such analysis will be implemented eventually. -multiclass fma3s_int_forms opc132, bits<8> opc213, bits<8> opc231, - string OpStr, string PackTy, string Suff, - RegisterClass RC, Operand memop, - X86FoldableSchedWrite sched> { - defm NAME#132#Suff : fma3s_rm_int; - defm NAME#213#Suff : fma3s_rm_int; - defm NAME#231#Suff : fma3s_rm_int; -} - -multiclass fma3s opc132, bits<8> opc213, bits<8> opc231, - string OpStr, SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = SSEPackedSingle in - defm NAME : fma3s_forms, - fma3s_int_forms; - - let ExeDomain = SSEPackedDouble in - defm NAME : fma3s_forms, - fma3s_int_forms, VEX_W; -} - -defm VFMADD : fma3s<0x99, 0xA9, 0xB9, "vfmadd", X86Fmadd, - SchedWriteFMA.Scl>, VEX_LIG; -defm VFMSUB : fma3s<0x9B, 0xAB, 0xBB, "vfmsub", X86Fmsub, - SchedWriteFMA.Scl>, VEX_LIG; - -defm VFNMADD : fma3s<0x9D, 0xAD, 0xBD, "vfnmadd", X86Fnmadd, - SchedWriteFMA.Scl>, VEX_LIG; -defm VFNMSUB : fma3s<0x9F, 0xAF, 0xBF, "vfnmsub", X86Fnmsub, - SchedWriteFMA.Scl>, VEX_LIG; - -multiclass scalar_fma_patterns { - let Predicates = [HasFMA, NoAVX512] in { - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - RC:$src3))))), - (!cast(Prefix#"213"#Suffix#"r_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, RC:$src3, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"r_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - (mem_frag addr:$src3)))))), - (!cast(Prefix#"213"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - (mem_frag addr:$src3), RC:$src2))))), - (!cast(Prefix#"132"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, (mem_frag addr:$src3), - (EltVT (extractelt (VT VR128:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - } -} - -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; - -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; - -//===----------------------------------------------------------------------===// -// FMA4 - AMD 4 operand Fused Multiply-Add instructions -//===----------------------------------------------------------------------===// - -multiclass fma4s opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType OpVT, SDNode OpNode, - PatFrag mem_frag, X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rr : FMA4S, VEX_W, VEX_LIG, - Sched<[sched]>; - def rm : FMA4S, VEX_W, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : FMA4S, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src3 - ReadAfterLd]>; -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : FMA4S, - VEX_LIG, FoldGenData, Sched<[sched]>; -} - -multiclass fma4s_int opc, string OpcodeStr, Operand memop, - ValueType VT, X86FoldableSchedWrite sched> { -let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr_Int : FMA4S_Int, VEX_W, VEX_LIG, Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : FMA4S_Int, VEX_W, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - let mayLoad = 1 in - def mr_Int : FMA4S_Int, - VEX_LIG, Sched<[sched.Folded, ReadAfterLd, - // memop:$src2 - ReadDefault, ReadDefault, ReadDefault, - ReadDefault, ReadDefault, - // VR128::$src3 - ReadAfterLd]>; - def rr_Int_REV : FMA4S_Int, VEX_LIG, FoldGenData, Sched<[sched]>; -} // isCodeGenOnly = 1 -} - -multiclass fma4p opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT128, ValueType OpVT256, - PatFrag ld_frag128, PatFrag ld_frag256, - X86SchedWriteWidths sched> { - let isCommutable = 1 in - def rr : FMA4, - VEX_W, Sched<[sched.XMM]>; - def rm : FMA4, VEX_W, - Sched<[sched.XMM.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : FMA4, - Sched<[sched.XMM.Folded, ReadAfterLd, - // f128mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR128::$src3 - ReadAfterLd]>; - let isCommutable = 1 in - def Yrr : FMA4, - VEX_W, VEX_L, Sched<[sched.YMM]>; - def Yrm : FMA4, VEX_W, VEX_L, - Sched<[sched.YMM.Folded, ReadAfterLd, ReadAfterLd]>; - def Ymr : FMA4, VEX_L, - Sched<[sched.YMM.Folded, ReadAfterLd, - // f256mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR256::$src3 - ReadAfterLd]>; -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { - def rr_REV : FMA4, - Sched<[sched.XMM]>, FoldGenData; - def Yrr_REV : FMA4, - VEX_L, Sched<[sched.YMM]>, FoldGenData; -} // isCodeGenOnly = 1 -} - -let ExeDomain = SSEPackedSingle in { - // Scalar Instructions - defm VFMADDSS4 : fma4s<0x6A, "vfmaddss", FR32, f32mem, f32, X86Fmadd, loadf32, - SchedWriteFMA.Scl>, - fma4s_int<0x6A, "vfmaddss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFMSUBSS4 : fma4s<0x6E, "vfmsubss", FR32, f32mem, f32, X86Fmsub, loadf32, - SchedWriteFMA.Scl>, - fma4s_int<0x6E, "vfmsubss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFNMADDSS4 : fma4s<0x7A, "vfnmaddss", FR32, f32mem, f32, - X86Fnmadd, loadf32, SchedWriteFMA.Scl>, - fma4s_int<0x7A, "vfnmaddss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFNMSUBSS4 : fma4s<0x7E, "vfnmsubss", FR32, f32mem, f32, - X86Fnmsub, loadf32, SchedWriteFMA.Scl>, - fma4s_int<0x7E, "vfnmsubss", ssmem, v4f32, - SchedWriteFMA.Scl>; - // Packed Instructions - defm VFMADDPS4 : fma4p<0x68, "vfmaddps", X86Fmadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMSUBPS4 : fma4p<0x6C, "vfmsubps", X86Fmsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFNMADDPS4 : fma4p<0x78, "vfnmaddps", X86Fnmadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFNMSUBPS4 : fma4p<0x7C, "vfnmsubps", X86Fnmsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMADDSUBPS4 : fma4p<0x5C, "vfmaddsubps", X86Fmaddsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMSUBADDPS4 : fma4p<0x5E, "vfmsubaddps", X86Fmsubadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; -} - -let ExeDomain = SSEPackedDouble in { - // Scalar Instructions - defm VFMADDSD4 : fma4s<0x6B, "vfmaddsd", FR64, f64mem, f64, X86Fmadd, loadf64, - SchedWriteFMA.Scl>, - fma4s_int<0x6B, "vfmaddsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFMSUBSD4 : fma4s<0x6F, "vfmsubsd", FR64, f64mem, f64, X86Fmsub, loadf64, - SchedWriteFMA.Scl>, - fma4s_int<0x6F, "vfmsubsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFNMADDSD4 : fma4s<0x7B, "vfnmaddsd", FR64, f64mem, f64, - X86Fnmadd, loadf64, SchedWriteFMA.Scl>, - fma4s_int<0x7B, "vfnmaddsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFNMSUBSD4 : fma4s<0x7F, "vfnmsubsd", FR64, f64mem, f64, - X86Fnmsub, loadf64, SchedWriteFMA.Scl>, - fma4s_int<0x7F, "vfnmsubsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - // Packed Instructions - defm VFMADDPD4 : fma4p<0x69, "vfmaddpd", X86Fmadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMSUBPD4 : fma4p<0x6D, "vfmsubpd", X86Fmsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFNMADDPD4 : fma4p<0x79, "vfnmaddpd", X86Fnmadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFNMSUBPD4 : fma4p<0x7D, "vfnmsubpd", X86Fnmsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMADDSUBPD4 : fma4p<0x5D, "vfmaddsubpd", X86Fmaddsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMSUBADDPD4 : fma4p<0x5F, "vfmsubaddpd", X86Fmsubadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; -} - -multiclass scalar_fma4_patterns { - let Predicates = [HasFMA4] in { - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, RC:$src2, RC:$src3))))), - (!cast(Name#"rr_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), - (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, RC:$src2, - (mem_frag addr:$src3)))))), - (!cast(Name#"rm_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), - (VT (COPY_TO_REGCLASS RC:$src2, VR128)), addr:$src3)>; - - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, (mem_frag addr:$src2), - RC:$src3))))), - (!cast(Name#"mr_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), addr:$src2, - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - } -} - -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; - -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; diff --git a/suite/synctools/tablegen/X86/X86InstrFPStack.td b/suite/synctools/tablegen/X86/X86InstrFPStack.td deleted file mode 100644 index a21f077927..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrFPStack.td +++ /dev/null @@ -1,748 +0,0 @@ -//===- X86InstrFPStack.td - FPU Instruction Set ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 x87 FPU instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// FPStack specific DAG Nodes. -//===----------------------------------------------------------------------===// - -def SDTX86FpGet2 : SDTypeProfile<2, 0, [SDTCisVT<0, f80>, - SDTCisVT<1, f80>]>; -def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fnstsw : SDTypeProfile<1, 1, [SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; -def SDTX86FpToIMem : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; - -def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; - -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, - [SDNPHasChain, SDNPInGlue, SDNPMayStore, - SDNPMemOperand]>; -def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fildflag : SDNode<"X86ISD::FILD_FLAG", SDTX86Fild, - [SDNPHasChain, SDNPOutGlue, SDNPMayLoad, - SDNPMemOperand]>; -def X86fp_stsw : SDNode<"X86ISD::FNSTSW16r", SDTX86Fnstsw>; -def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, - [SDNPHasChain, SDNPMayStore, SDNPSideEffect, - SDNPMemOperand]>; - -//===----------------------------------------------------------------------===// -// FPStack pattern fragments -//===----------------------------------------------------------------------===// - -def fpimm0 : FPImmLeaf; - -def fpimmneg0 : FPImmLeaf; - -def fpimm1 : FPImmLeaf; - -def fpimmneg1 : FPImmLeaf; - -/* -// Some 'special' instructions - expanded after instruction selection. -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - def FP32_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP32:$src), - [(X86fp_to_i16mem RFP32:$src, addr:$dst)]>; - def FP32_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP32:$src), - [(X86fp_to_i32mem RFP32:$src, addr:$dst)]>; - def FP32_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP32:$src), - [(X86fp_to_i64mem RFP32:$src, addr:$dst)]>; - def FP64_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP64:$src), - [(X86fp_to_i16mem RFP64:$src, addr:$dst)]>; - def FP64_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP64:$src), - [(X86fp_to_i32mem RFP64:$src, addr:$dst)]>; - def FP64_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP64:$src), - [(X86fp_to_i64mem RFP64:$src, addr:$dst)]>; - def FP80_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP80:$src), - [(X86fp_to_i16mem RFP80:$src, addr:$dst)]>; - def FP80_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP80:$src), - [(X86fp_to_i32mem RFP80:$src, addr:$dst)]>; - def FP80_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP80:$src), - [(X86fp_to_i64mem RFP80:$src, addr:$dst)]>; -} -*/ - -// All FP Stack operations are represented with four instructions here. The -// first three instructions, generated by the instruction selector, use "RFP32" -// "RFP64" or "RFP80" registers: traditional register files to reference 32-bit, -// 64-bit or 80-bit floating point values. These sizes apply to the values, -// not the registers, which are always 80 bits; RFP32, RFP64 and RFP80 can be -// copied to each other without losing information. These instructions are all -// pseudo instructions and use the "_Fp" suffix. -// In some cases there are additional variants with a mixture of different -// register sizes. -// The second instruction is defined with FPI, which is the actual instruction -// emitted by the assembler. These use "RST" registers, although frequently -// the actual register(s) used are implicit. These are always 80 bits. -// The FP stackifier pass converts one to the other after register allocation -// occurs. -// -// Note that the FpI instruction should have instruction selection info (e.g. -// a pattern) and the FPI instruction should have emission info (e.g. opcode -// encoding and asm printing info). - -// FpIf32, FpIf64 - Floating Point Pseudo Instruction template. -// f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. -// f64 instructions can use SSE2 and are predicated on FPStackf64 == !SSE2. -// f80 instructions cannot use SSE and use neither of these. -class FpIf32 pattern> : - FpI_, Requires<[FPStackf32]>; -class FpIf64 pattern> : - FpI_, Requires<[FPStackf64]>; - -// Factoring for arithmetic. -multiclass FPBinary_rr { -// Register op register -> register -// These are separated out because they have no reversed form. -def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), TwoArgFP, - [(set RFP32:$dst, (OpNode RFP32:$src1, RFP32:$src2))]>; -def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), TwoArgFP, - [(set RFP64:$dst, (OpNode RFP64:$src1, RFP64:$src2))]>; -def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), TwoArgFP, - [(set RFP80:$dst, (OpNode RFP80:$src1, RFP80:$src2))]>; -} -// The FopST0 series are not included here because of the irregularities -// in where the 'r' goes in assembly output. -// These instructions cannot address 80-bit memory. -multiclass FPBinary { -let mayLoad = 1, hasSideEffects = 1 in { -// ST(0) = ST(0) + [mem] -def _Fp32m : FpIf32<(outs RFP32:$dst), - (ins RFP32:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (loadf32 addr:$src2))), - (set RFP32:$dst, - (OpNode (loadf32 addr:$src2), RFP32:$src1)))]>; -def _Fp64m : FpIf64<(outs RFP64:$dst), - (ins RFP64:$src1, f64mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (loadf64 addr:$src2))), - (set RFP64:$dst, - (OpNode (loadf64 addr:$src2), RFP64:$src1)))]>; -def _Fp64m32: FpIf64<(outs RFP64:$dst), - (ins RFP64:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (f64 (extloadf32 addr:$src2)))), - (set RFP64:$dst, - (OpNode (f64 (extloadf32 addr:$src2)), RFP64:$src1)))]>; -def _Fp80m32: FpI_<(outs RFP80:$dst), - (ins RFP80:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (f80 (extloadf32 addr:$src2)))), - (set RFP80:$dst, - (OpNode (f80 (extloadf32 addr:$src2)), RFP80:$src1)))]>; -def _Fp80m64: FpI_<(outs RFP80:$dst), - (ins RFP80:$src1, f64mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2)))), - (set RFP80:$dst, - (OpNode (f80 (extloadf64 addr:$src2)), RFP80:$src1)))]>; -def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), - !strconcat("f", asmstring, "{s}\t$src")>; -def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), - !strconcat("f", asmstring, "{l}\t$src")>; -// ST(0) = ST(0) + [memint] -def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (X86fild addr:$src2, i16))), - (set RFP32:$dst, - (OpNode (X86fild addr:$src2, i16), RFP32:$src1)))]>; -def _FpI32m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (X86fild addr:$src2, i32))), - (set RFP32:$dst, - (OpNode (X86fild addr:$src2, i32), RFP32:$src1)))]>; -def _FpI16m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (X86fild addr:$src2, i16))), - (set RFP64:$dst, - (OpNode (X86fild addr:$src2, i16), RFP64:$src1)))]>; -def _FpI32m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (X86fild addr:$src2, i32))), - (set RFP64:$dst, - (OpNode (X86fild addr:$src2, i32), RFP64:$src1)))]>; -def _FpI16m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (X86fild addr:$src2, i16))), - (set RFP80:$dst, - (OpNode (X86fild addr:$src2, i16), RFP80:$src1)))]>; -def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (X86fild addr:$src2, i32))), - (set RFP80:$dst, - (OpNode (X86fild addr:$src2, i32), RFP80:$src1)))]>; -def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), - !strconcat("fi", asmstring, "{s}\t$src")>; -def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), - !strconcat("fi", asmstring, "{l}\t$src")>; -} // mayLoad = 1, hasSideEffects = 1 -} - -let Defs = [FPSW] in { -// FPBinary_rr just defines pseudo-instructions, no need to set a scheduling -// resources. -let hasNoSchedulingInfo = 1 in { -defm ADD : FPBinary_rr; -defm SUB : FPBinary_rr; -defm MUL : FPBinary_rr; -defm DIV : FPBinary_rr; -} - -// Sets the scheduling resources for the actual NAME#_Fm definitions. -let SchedRW = [WriteFAddLd] in { -defm ADD : FPBinary; -defm SUB : FPBinary; -defm SUBR: FPBinary; -} - -let SchedRW = [WriteFMulLd] in { -defm MUL : FPBinary; -} - -let SchedRW = [WriteFDivLd] in { -defm DIV : FPBinary; -defm DIVR: FPBinary; -} -} // Defs = [FPSW] - -class FPST0rInst - : FPI<0xD8, fp, (outs), (ins RST:$op), asm>; -class FPrST0Inst - : FPI<0xDC, fp, (outs), (ins RST:$op), asm>; -class FPrST0PInst - : FPI<0xDE, fp, (outs), (ins RST:$op), asm>; - -// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion -// of some of the 'reverse' forms of the fsub and fdiv instructions. As such, -// we have to put some 'r's in and take them out of weird places. -let SchedRW = [WriteFAdd] in { -def ADD_FST0r : FPST0rInst ; -def ADD_FrST0 : FPrST0Inst ; -def ADD_FPrST0 : FPrST0PInst; -def SUBR_FST0r : FPST0rInst ; -def SUB_FrST0 : FPrST0Inst ; -def SUB_FPrST0 : FPrST0PInst; -def SUB_FST0r : FPST0rInst ; -def SUBR_FrST0 : FPrST0Inst ; -def SUBR_FPrST0 : FPrST0PInst; -} // SchedRW -let SchedRW = [WriteFCom] in { -def COM_FST0r : FPST0rInst ; -def COMP_FST0r : FPST0rInst ; -} // SchedRW -let SchedRW = [WriteFMul] in { -def MUL_FST0r : FPST0rInst ; -def MUL_FrST0 : FPrST0Inst ; -def MUL_FPrST0 : FPrST0PInst; -} // SchedRW -let SchedRW = [WriteFDiv] in { -def DIVR_FST0r : FPST0rInst ; -def DIV_FrST0 : FPrST0Inst ; -def DIV_FPrST0 : FPrST0PInst; -def DIV_FST0r : FPST0rInst ; -def DIVR_FrST0 : FPrST0Inst ; -def DIVR_FPrST0 : FPrST0PInst; -} // SchedRW - -// Unary operations. -multiclass FPUnary { -def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), OneArgFPRW, - [(set RFP32:$dst, (OpNode RFP32:$src))]>; -def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), OneArgFPRW, - [(set RFP64:$dst, (OpNode RFP64:$src))]>; -def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, - [(set RFP80:$dst, (OpNode RFP80:$src))]>; -def _F : FPI<0xD9, fp, (outs), (ins), asmstring>; -} - -let Defs = [FPSW] in { - -let SchedRW = [WriteFSign] in { -defm CHS : FPUnary; -defm ABS : FPUnary; -} - -let SchedRW = [WriteFSqrt80] in -defm SQRT: FPUnary; - -let SchedRW = [WriteMicrocoded] in { -defm SIN : FPUnary; -defm COS : FPUnary; -} - -let SchedRW = [WriteFCom] in { -let hasSideEffects = 0 in { -def TST_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; -def TST_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; -def TST_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; -} // hasSideEffects - -def TST_F : FPI<0xD9, MRM_E4, (outs), (ins), "ftst">; -} // SchedRW -} // Defs = [FPSW] - -// Versions of FP instructions that take a single memory operand. Added for the -// disassembler; remove as they are included with patterns elsewhere. -let SchedRW = [WriteFComLd] in { -def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; -def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; - -def FCOM64m : FPI<0xDC, MRM2m, (outs), (ins f64mem:$src), "fcom{l}\t$src">; -def FCOMP64m : FPI<0xDC, MRM3m, (outs), (ins f64mem:$src), "fcomp{l}\t$src">; - -def FICOM16m : FPI<0xDE, MRM2m, (outs), (ins i16mem:$src), "ficom{s}\t$src">; -def FICOMP16m: FPI<0xDE, MRM3m, (outs), (ins i16mem:$src), "ficomp{s}\t$src">; - -def FICOM32m : FPI<0xDA, MRM2m, (outs), (ins i32mem:$src), "ficom{l}\t$src">; -def FICOMP32m: FPI<0xDA, MRM3m, (outs), (ins i32mem:$src), "ficomp{l}\t$src">; -} // SchedRW - -let SchedRW = [WriteMicrocoded] in { -def FLDENVm : FPI<0xD9, MRM4m, (outs), (ins f32mem:$src), "fldenv\t$src">; -def FSTENVm : FPI<0xD9, MRM6m, (outs), (ins f32mem:$dst), "fnstenv\t$dst">; - -def FRSTORm : FPI<0xDD, MRM4m, (outs), (ins f32mem:$dst), "frstor\t$dst">; -def FSAVEm : FPI<0xDD, MRM6m, (outs), (ins f32mem:$dst), "fnsave\t$dst">; -def FNSTSWm : FPI<0xDD, MRM7m, (outs), (ins i16mem:$dst), "fnstsw\t$dst">; - -def FBLDm : FPI<0xDF, MRM4m, (outs), (ins f80mem:$src), "fbld\ttbyte ptr $src">; -def FBSTPm : FPI<0xDF, MRM6m, (outs), (ins f80mem:$dst), "fbstp\ttbyte ptr $dst">; -} // SchedRW - -// Floating point cmovs. -class FpIf32CMov pattern> : - FpI_, Requires<[FPStackf32, HasCMov]>; -class FpIf64CMov pattern> : - FpI_, Requires<[FPStackf64, HasCMov]>; - -multiclass FPCMov { - def _Fp32 : FpIf32CMov<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), - CondMovFP, - [(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2, - cc, EFLAGS))]>; - def _Fp64 : FpIf64CMov<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), - CondMovFP, - [(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2, - cc, EFLAGS))]>; - def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), - CondMovFP, - [(set RFP80:$dst, (X86cmov RFP80:$src1, RFP80:$src2, - cc, EFLAGS))]>, - Requires<[HasCMov]>; -} - -let Defs = [FPSW] in { -let SchedRW = [WriteFCMOV] in { -let Uses = [EFLAGS], Constraints = "$src1 = $dst" in { -defm CMOVB : FPCMov; -defm CMOVBE : FPCMov; -defm CMOVE : FPCMov; -defm CMOVP : FPCMov; -defm CMOVNB : FPCMov; -defm CMOVNBE: FPCMov; -defm CMOVNE : FPCMov; -defm CMOVNP : FPCMov; -} // Uses = [EFLAGS], Constraints = "$src1 = $dst" - -let Predicates = [HasCMov] in { -// These are not factored because there's no clean way to pass DA/DB. -def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RST:$op), - "fcmovb\t{$op, %st(0)|st(0), $op}">; -def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RST:$op), - "fcmovbe\t{$op, %st(0)|st(0), $op}">; -def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RST:$op), - "fcmove\t{$op, %st(0)|st(0), $op}">; -def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RST:$op), - "fcmovu\t{$op, %st(0)|st(0), $op}">; -def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RST:$op), - "fcmovnb\t{$op, %st(0)|st(0), $op}">; -def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RST:$op), - "fcmovnbe\t{$op, %st(0)|st(0), $op}">; -def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RST:$op), - "fcmovne\t{$op, %st(0)|st(0), $op}">; -def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RST:$op), - "fcmovnu\t{$op, %st(0)|st(0), $op}">; -} // Predicates = [HasCMov] -} // SchedRW - -// Floating point loads & stores. -let SchedRW = [WriteLoad] in { -let canFoldAsLoad = 1 in { -def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP32:$dst, (loadf32 addr:$src))]>; -let isReMaterializable = 1 in - def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, - [(set RFP64:$dst, (loadf64 addr:$src))]>; -def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, - [(set RFP80:$dst, (loadf80 addr:$src))]>; -} // canFoldAsLoad -def LD_Fp32m64 : FpIf64<(outs RFP64:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP64:$dst, (f64 (extloadf32 addr:$src)))]>; -def LD_Fp64m80 : FpI_<(outs RFP80:$dst), (ins f64mem:$src), ZeroArgFP, - [(set RFP80:$dst, (f80 (extloadf64 addr:$src)))]>; -def LD_Fp32m80 : FpI_<(outs RFP80:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP80:$dst, (f80 (extloadf32 addr:$src)))]>; -def ILD_Fp16m32: FpIf32<(outs RFP32:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m32: FpIf32<(outs RFP32:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m32: FpIf32<(outs RFP32:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i64))]>; -def ILD_Fp16m64: FpIf64<(outs RFP64:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m64: FpIf64<(outs RFP64:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m64: FpIf64<(outs RFP64:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i64))]>; -def ILD_Fp16m80: FpI_<(outs RFP80:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m80: FpI_<(outs RFP80:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i64))]>; -} // SchedRW - -let SchedRW = [WriteStore] in { -def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, - [(store RFP32:$src, addr:$op)]>; -def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, - [(truncstoref32 RFP64:$src, addr:$op)]>; -def ST_Fp64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, - [(store RFP64:$src, addr:$op)]>; -def ST_Fp80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, - [(truncstoref32 RFP80:$src, addr:$op)]>; -def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, - [(truncstoref64 RFP80:$src, addr:$op)]>; -// FST does not support 80-bit memory target; FSTP must be used. - -let mayStore = 1, hasSideEffects = 0 in { -def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; -def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; -def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; -def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; -def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; -} // mayStore - -def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, - [(store RFP80:$src, addr:$op)]>; - -let mayStore = 1, hasSideEffects = 0 in { -def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp16m64 : FpIf64<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp32m64 : FpIf64<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; -def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; -def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; -} // mayStore -} // SchedRW - -let mayLoad = 1, SchedRW = [WriteLoad] in { -def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; -def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; -def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; -def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; -def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; -def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; -} -let mayStore = 1, SchedRW = [WriteStore] in { -def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; -def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; -def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; -def ST_FP64m : FPI<0xDD, MRM3m, (outs), (ins f64mem:$dst), "fstp{l}\t$dst">; -def ST_FP80m : FPI<0xDB, MRM7m, (outs), (ins f80mem:$dst), "fstp{t}\t$dst">; -def IST_F16m : FPI<0xDF, MRM2m, (outs), (ins i16mem:$dst), "fist{s}\t$dst">; -def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; -def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; -def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; -def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; -} - -// FISTTP requires SSE3 even though it's a FPStack op. -let Predicates = [HasSSE3], SchedRW = [WriteStore] in { -def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; -def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i32mem RFP32:$src, addr:$op)]>; -def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i64mem RFP32:$src, addr:$op)]>; -def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i16mem RFP64:$src, addr:$op)]>; -def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i32mem RFP64:$src, addr:$op)]>; -def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i64mem RFP64:$src, addr:$op)]>; -def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i16mem RFP80:$src, addr:$op)]>; -def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i32mem RFP80:$src, addr:$op)]>; -def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; -} // Predicates = [HasSSE3] - -let mayStore = 1, SchedRW = [WriteStore] in { -def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; -def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; -def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; -} - -// FP Stack manipulation instructions. -let SchedRW = [WriteMove] in { -def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RST:$op), "fld\t$op">; -def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RST:$op), "fst\t$op">; -def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RST:$op), "fstp\t$op">; -def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RST:$op), "fxch\t$op">; -} - -// Floating point constant loads. -let isReMaterializable = 1, SchedRW = [WriteZero] in { -def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, - [(set RFP32:$dst, fpimm0)]>; -def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, - [(set RFP32:$dst, fpimm1)]>; -def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, - [(set RFP64:$dst, fpimm0)]>; -def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, - [(set RFP64:$dst, fpimm1)]>; -def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, - [(set RFP80:$dst, fpimm0)]>; -def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, - [(set RFP80:$dst, fpimm1)]>; -} - -let SchedRW = [WriteFLD0] in -def LD_F0 : FPI<0xD9, MRM_EE, (outs), (ins), "fldz">; - -let SchedRW = [WriteFLD1] in -def LD_F1 : FPI<0xD9, MRM_E8, (outs), (ins), "fld1">; - -let SchedRW = [WriteFLDC], Defs = [FPSW] in { -def FLDL2T : I<0xD9, MRM_E9, (outs), (ins), "fldl2t", []>; -def FLDL2E : I<0xD9, MRM_EA, (outs), (ins), "fldl2e", []>; -def FLDPI : I<0xD9, MRM_EB, (outs), (ins), "fldpi", []>; -def FLDLG2 : I<0xD9, MRM_EC, (outs), (ins), "fldlg2", []>; -def FLDLN2 : I<0xD9, MRM_ED, (outs), (ins), "fldln2", []>; -} // SchedRW - -// Floating point compares. -let SchedRW = [WriteFCom] in { -def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP32:$lhs, RFP32:$rhs)))]>; -def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP64:$lhs, RFP64:$rhs)))]>; -def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP80:$lhs, RFP80:$rhs)))]>; -} // SchedRW -} // Defs = [FPSW] - -let SchedRW = [WriteFCom] in { -// CC = ST(0) cmp ST(i) -let Defs = [EFLAGS, FPSW] in { -def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; -def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; -def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; -} - -let Defs = [FPSW], Uses = [ST0] in { -def UCOM_Fr : FPI<0xDD, MRM4r, // FPSW = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucom\t$reg">; -def UCOM_FPr : FPI<0xDD, MRM5r, // FPSW = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucomp\t$reg">; -def UCOM_FPPr : FPI<0xDA, MRM_E9, // cmp ST(0) with ST(1), pop, pop - (outs), (ins), "fucompp">; -} - -let Defs = [EFLAGS, FPSW], Uses = [ST0] in { -def UCOM_FIr : FPI<0xDB, MRM5r, // CC = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucomi\t$reg">; -def UCOM_FIPr : FPI<0xDF, MRM5r, // CC = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucompi\t$reg">; -} - -let Defs = [EFLAGS, FPSW] in { -def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RST:$reg), "fcomi\t$reg">; -def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RST:$reg), "fcompi\t$reg">; -} -} // SchedRW - -// Floating point flag ops. -let SchedRW = [WriteALU] in { -let Defs = [AX], Uses = [FPSW] in -def FNSTSW16r : I<0xDF, MRM_E0, // AX = fp flags - (outs), (ins), "fnstsw\t{%ax|ax}", - [(set AX, (X86fp_stsw FPSW))]>; -let Defs = [FPSW] in -def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world - (outs), (ins i16mem:$dst), "fnstcw\t$dst", - [(X86fp_cwd_get16 addr:$dst)]>; -} // SchedRW -let Defs = [FPSW], mayLoad = 1 in -def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] - (outs), (ins i16mem:$dst), "fldcw\t$dst", []>, - Sched<[WriteLoad]>; - -// FPU control instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [FPSW] in { -def FNINIT : I<0xDB, MRM_E3, (outs), (ins), "fninit", []>; -def FFREE : FPI<0xDD, MRM0r, (outs), (ins RST:$reg), "ffree\t$reg">; -def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RST:$reg), "ffreep\t$reg">; - -def FPNCEST0r : FPI<0xD9, MRM3r, (outs RST:$op), (ins), - "fstpnce\t{%st(0), $op|$op, st(0)}">; - -def FENI8087_NOP : I<0xDB, MRM_E0, (outs), (ins), "feni8087_nop", []>; - -def FDISI8087_NOP : I<0xDB, MRM_E1, (outs), (ins), "fdisi8087_nop", []>; - -// Clear exceptions -def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", []>; -} // Defs = [FPSW] -} // SchedRW - -// Operand-less floating-point instructions for the disassembler. -def FNOP : I<0xD9, MRM_D0, (outs), (ins), "fnop", []>, Sched<[WriteNop]>; - -let SchedRW = [WriteMicrocoded] in { -let Defs = [FPSW] in { -def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; -def FXAM : I<0xD9, MRM_E5, (outs), (ins), "fxam", []>; -def F2XM1 : I<0xD9, MRM_F0, (outs), (ins), "f2xm1", []>; -def FYL2X : I<0xD9, MRM_F1, (outs), (ins), "fyl2x", []>; -def FPTAN : I<0xD9, MRM_F2, (outs), (ins), "fptan", []>; -def FPATAN : I<0xD9, MRM_F3, (outs), (ins), "fpatan", []>; -def FXTRACT : I<0xD9, MRM_F4, (outs), (ins), "fxtract", []>; -def FPREM1 : I<0xD9, MRM_F5, (outs), (ins), "fprem1", []>; -def FDECSTP : I<0xD9, MRM_F6, (outs), (ins), "fdecstp", []>; -def FINCSTP : I<0xD9, MRM_F7, (outs), (ins), "fincstp", []>; -def FPREM : I<0xD9, MRM_F8, (outs), (ins), "fprem", []>; -def FYL2XP1 : I<0xD9, MRM_F9, (outs), (ins), "fyl2xp1", []>; -def FSINCOS : I<0xD9, MRM_FB, (outs), (ins), "fsincos", []>; -def FRNDINT : I<0xD9, MRM_FC, (outs), (ins), "frndint", []>; -def FSCALE : I<0xD9, MRM_FD, (outs), (ins), "fscale", []>; -def FCOMPP : I<0xDE, MRM_D9, (outs), (ins), "fcompp", []>; -} // Defs = [FPSW] - -def FXSAVE : I<0xAE, MRM0m, (outs), (ins opaquemem:$dst), - "fxsave\t$dst", [(int_x86_fxsave addr:$dst)]>, TB, - Requires<[HasFXSR]>; -def FXSAVE64 : RI<0xAE, MRM0m, (outs), (ins opaquemem:$dst), - "fxsave64\t$dst", [(int_x86_fxsave64 addr:$dst)]>, - TB, Requires<[HasFXSR, In64BitMode]>; -def FXRSTOR : I<0xAE, MRM1m, (outs), (ins opaquemem:$src), - "fxrstor\t$src", [(int_x86_fxrstor addr:$src)]>, - TB, Requires<[HasFXSR]>; -def FXRSTOR64 : RI<0xAE, MRM1m, (outs), (ins opaquemem:$src), - "fxrstor64\t$src", [(int_x86_fxrstor64 addr:$src)]>, - TB, Requires<[HasFXSR, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Non-Instruction Patterns -//===----------------------------------------------------------------------===// - -// Required for RET of f32 / f64 / f80 values. -def : Pat<(X86fld addr:$src, f32), (LD_Fp32m addr:$src)>; -def : Pat<(X86fld addr:$src, f64), (LD_Fp64m addr:$src)>; -def : Pat<(X86fld addr:$src, f80), (LD_Fp80m addr:$src)>; - -// Required for CALL which return f32 / f64 / f80 values. -def : Pat<(X86fst RFP32:$src, addr:$op, f32), (ST_Fp32m addr:$op, RFP32:$src)>; -def : Pat<(X86fst RFP64:$src, addr:$op, f32), (ST_Fp64m32 addr:$op, - RFP64:$src)>; -def : Pat<(X86fst RFP64:$src, addr:$op, f64), (ST_Fp64m addr:$op, RFP64:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f32), (ST_Fp80m32 addr:$op, - RFP80:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f64), (ST_Fp80m64 addr:$op, - RFP80:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f80), (ST_FpP80m addr:$op, - RFP80:$src)>; - -// Floating point constant -0.0 and -1.0 -def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; -def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; -def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; -def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; -def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; -def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; - -// Used to conv. i64 to f64 since there isn't a SSE version. -def : Pat<(X86fildflag addr:$src, i64), (ILD_Fp64m64 addr:$src)>; - -// FP extensions map onto simple pseudo-value conversions if they are to/from -// the FP stack. -def : Pat<(f64 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, - Requires<[FPStackf32]>; -def : Pat<(f80 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, - Requires<[FPStackf32]>; -def : Pat<(f80 (fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, - Requires<[FPStackf64]>; - -// FP truncations map onto simple pseudo-value conversions if they are to/from -// the FP stack. We have validated that only value-preserving truncations make -// it through isel. -def : Pat<(f32 (fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, - Requires<[FPStackf32]>; -def : Pat<(f32 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, - Requires<[FPStackf32]>; -def : Pat<(f64 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, - Requires<[FPStackf64]>; diff --git a/suite/synctools/tablegen/X86/X86InstrFormats.td b/suite/synctools/tablegen/X86/X86InstrFormats.td deleted file mode 100644 index 47d4719d30..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrFormats.td +++ /dev/null @@ -1,993 +0,0 @@ -//===-- X86InstrFormats.td - X86 Instruction Formats -------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -// Format specifies the encoding used by the instruction. This is part of the -// ad-hoc solution used to emit machine instruction encodings by our machine -// code emitter. -class Format val> { - bits<7> Value = val; -} - -def Pseudo : Format<0>; -def RawFrm : Format<1>; -def AddRegFrm : Format<2>; -def RawFrmMemOffs : Format<3>; -def RawFrmSrc : Format<4>; -def RawFrmDst : Format<5>; -def RawFrmDstSrc : Format<6>; -def RawFrmImm8 : Format<7>; -def RawFrmImm16 : Format<8>; -def MRMDestMem : Format<32>; -def MRMSrcMem : Format<33>; -def MRMSrcMem4VOp3 : Format<34>; -def MRMSrcMemOp4 : Format<35>; -def MRMXm : Format<39>; -def MRM0m : Format<40>; def MRM1m : Format<41>; def MRM2m : Format<42>; -def MRM3m : Format<43>; def MRM4m : Format<44>; def MRM5m : Format<45>; -def MRM6m : Format<46>; def MRM7m : Format<47>; -def MRMDestReg : Format<48>; -def MRMSrcReg : Format<49>; -def MRMSrcReg4VOp3 : Format<50>; -def MRMSrcRegOp4 : Format<51>; -def MRMXr : Format<55>; -def MRM0r : Format<56>; def MRM1r : Format<57>; def MRM2r : Format<58>; -def MRM3r : Format<59>; def MRM4r : Format<60>; def MRM5r : Format<61>; -def MRM6r : Format<62>; def MRM7r : Format<63>; -def MRM_C0 : Format<64>; def MRM_C1 : Format<65>; def MRM_C2 : Format<66>; -def MRM_C3 : Format<67>; def MRM_C4 : Format<68>; def MRM_C5 : Format<69>; -def MRM_C6 : Format<70>; def MRM_C7 : Format<71>; def MRM_C8 : Format<72>; -def MRM_C9 : Format<73>; def MRM_CA : Format<74>; def MRM_CB : Format<75>; -def MRM_CC : Format<76>; def MRM_CD : Format<77>; def MRM_CE : Format<78>; -def MRM_CF : Format<79>; def MRM_D0 : Format<80>; def MRM_D1 : Format<81>; -def MRM_D2 : Format<82>; def MRM_D3 : Format<83>; def MRM_D4 : Format<84>; -def MRM_D5 : Format<85>; def MRM_D6 : Format<86>; def MRM_D7 : Format<87>; -def MRM_D8 : Format<88>; def MRM_D9 : Format<89>; def MRM_DA : Format<90>; -def MRM_DB : Format<91>; def MRM_DC : Format<92>; def MRM_DD : Format<93>; -def MRM_DE : Format<94>; def MRM_DF : Format<95>; def MRM_E0 : Format<96>; -def MRM_E1 : Format<97>; def MRM_E2 : Format<98>; def MRM_E3 : Format<99>; -def MRM_E4 : Format<100>; def MRM_E5 : Format<101>; def MRM_E6 : Format<102>; -def MRM_E7 : Format<103>; def MRM_E8 : Format<104>; def MRM_E9 : Format<105>; -def MRM_EA : Format<106>; def MRM_EB : Format<107>; def MRM_EC : Format<108>; -def MRM_ED : Format<109>; def MRM_EE : Format<110>; def MRM_EF : Format<111>; -def MRM_F0 : Format<112>; def MRM_F1 : Format<113>; def MRM_F2 : Format<114>; -def MRM_F3 : Format<115>; def MRM_F4 : Format<116>; def MRM_F5 : Format<117>; -def MRM_F6 : Format<118>; def MRM_F7 : Format<119>; def MRM_F8 : Format<120>; -def MRM_F9 : Format<121>; def MRM_FA : Format<122>; def MRM_FB : Format<123>; -def MRM_FC : Format<124>; def MRM_FD : Format<125>; def MRM_FE : Format<126>; -def MRM_FF : Format<127>; - -// ImmType - This specifies the immediate type used by an instruction. This is -// part of the ad-hoc solution used to emit machine instruction encodings by our -// machine code emitter. -class ImmType val> { - bits<4> Value = val; -} -def NoImm : ImmType<0>; -def Imm8 : ImmType<1>; -def Imm8PCRel : ImmType<2>; -def Imm8Reg : ImmType<3>; // Register encoded in [7:4]. -def Imm16 : ImmType<4>; -def Imm16PCRel : ImmType<5>; -def Imm32 : ImmType<6>; -def Imm32PCRel : ImmType<7>; -def Imm32S : ImmType<8>; -def Imm64 : ImmType<9>; - -// FPFormat - This specifies what form this FP instruction has. This is used by -// the Floating-Point stackifier pass. -class FPFormat val> { - bits<3> Value = val; -} -def NotFP : FPFormat<0>; -def ZeroArgFP : FPFormat<1>; -def OneArgFP : FPFormat<2>; -def OneArgFPRW : FPFormat<3>; -def TwoArgFP : FPFormat<4>; -def CompareFP : FPFormat<5>; -def CondMovFP : FPFormat<6>; -def SpecialFP : FPFormat<7>; - -// Class specifying the SSE execution domain, used by the SSEDomainFix pass. -// Keep in sync with tables in X86InstrInfo.cpp. -class Domain val> { - bits<2> Value = val; -} -def GenericDomain : Domain<0>; -def SSEPackedSingle : Domain<1>; -def SSEPackedDouble : Domain<2>; -def SSEPackedInt : Domain<3>; - -// Class specifying the vector form of the decompressed -// displacement of 8-bit. -class CD8VForm val> { - bits<3> Value = val; -} -def CD8VF : CD8VForm<0>; // v := VL -def CD8VH : CD8VForm<1>; // v := VL/2 -def CD8VQ : CD8VForm<2>; // v := VL/4 -def CD8VO : CD8VForm<3>; // v := VL/8 -// The tuple (subvector) forms. -def CD8VT1 : CD8VForm<4>; // v := 1 -def CD8VT2 : CD8VForm<5>; // v := 2 -def CD8VT4 : CD8VForm<6>; // v := 4 -def CD8VT8 : CD8VForm<7>; // v := 8 - -// Class specifying the prefix used an opcode extension. -class Prefix val> { - bits<3> Value = val; -} -def NoPrfx : Prefix<0>; -def PD : Prefix<1>; -def XS : Prefix<2>; -def XD : Prefix<3>; -def PS : Prefix<4>; // Similar to NoPrfx, but disassembler uses this to know - // that other instructions with this opcode use PD/XS/XD - // and if any of those is not supported they shouldn't - // decode to this instruction. e.g. ANDSS/ANDSD don't - // exist, but the 0xf2/0xf3 encoding shouldn't - // disable to ANDPS. - -// Class specifying the opcode map. -class Map val> { - bits<3> Value = val; -} -def OB : Map<0>; -def TB : Map<1>; -def T8 : Map<2>; -def TA : Map<3>; -def XOP8 : Map<4>; -def XOP9 : Map<5>; -def XOPA : Map<6>; -def ThreeDNow : Map<7>; - -// Class specifying the encoding -class Encoding val> { - bits<2> Value = val; -} -def EncNormal : Encoding<0>; -def EncVEX : Encoding<1>; -def EncXOP : Encoding<2>; -def EncEVEX : Encoding<3>; - -// Operand size for encodings that change based on mode. -class OperandSize val> { - bits<2> Value = val; -} -def OpSizeFixed : OperandSize<0>; // Never needs a 0x66 prefix. -def OpSize16 : OperandSize<1>; // Needs 0x66 prefix in 32-bit mode. -def OpSize32 : OperandSize<2>; // Needs 0x66 prefix in 16-bit mode. - -// Address size for encodings that change based on mode. -class AddressSize val> { - bits<2> Value = val; -} -def AdSizeX : AddressSize<0>; // Address size determined using addr operand. -def AdSize16 : AddressSize<1>; // Encodes a 16-bit address. -def AdSize32 : AddressSize<2>; // Encodes a 32-bit address. -def AdSize64 : AddressSize<3>; // Encodes a 64-bit address. - -// Prefix byte classes which are used to indicate to the ad-hoc machine code -// emitter that various prefix bytes are required. -class OpSize16 { OperandSize OpSize = OpSize16; } -class OpSize32 { OperandSize OpSize = OpSize32; } -class AdSize16 { AddressSize AdSize = AdSize16; } -class AdSize32 { AddressSize AdSize = AdSize32; } -class AdSize64 { AddressSize AdSize = AdSize64; } -class REX_W { bit hasREX_WPrefix = 1; } -class LOCK { bit hasLockPrefix = 1; } -class REP { bit hasREPPrefix = 1; } -class TB { Map OpMap = TB; } -class T8 { Map OpMap = T8; } -class TA { Map OpMap = TA; } -class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; } -class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; } -class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; } -class ThreeDNow { Map OpMap = ThreeDNow; } -class OBXS { Prefix OpPrefix = XS; } -class PS : TB { Prefix OpPrefix = PS; } -class PD : TB { Prefix OpPrefix = PD; } -class XD : TB { Prefix OpPrefix = XD; } -class XS : TB { Prefix OpPrefix = XS; } -class T8PS : T8 { Prefix OpPrefix = PS; } -class T8PD : T8 { Prefix OpPrefix = PD; } -class T8XD : T8 { Prefix OpPrefix = XD; } -class T8XS : T8 { Prefix OpPrefix = XS; } -class TAPS : TA { Prefix OpPrefix = PS; } -class TAPD : TA { Prefix OpPrefix = PD; } -class TAXD : TA { Prefix OpPrefix = XD; } -class VEX { Encoding OpEnc = EncVEX; } -class VEX_W { bits<2> VEX_WPrefix = 1; } -class VEX_WIG { bits<2> VEX_WPrefix = 2; } -// Special version of VEX_W that can be changed to VEX.W==0 for EVEX2VEX. -// FIXME: We should consider adding separate bits for VEX_WIG and the extra -// part of W1X. This would probably simplify the tablegen emitters and -// the TSFlags creation below. -class VEX_W1X { bits<2> VEX_WPrefix = 3; } -class VEX_4V : VEX { bit hasVEX_4V = 1; } -class VEX_L { bit hasVEX_L = 1; } -class VEX_LIG { bit ignoresVEX_L = 1; } -class EVEX { Encoding OpEnc = EncEVEX; } -class EVEX_4V : EVEX { bit hasVEX_4V = 1; } -class EVEX_K { bit hasEVEX_K = 1; } -class EVEX_KZ : EVEX_K { bit hasEVEX_Z = 1; } -class EVEX_B { bit hasEVEX_B = 1; } -class EVEX_RC { bit hasEVEX_RC = 1; } -class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; } -class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; } -class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; } -class NOTRACK { bit hasNoTrackPrefix = 1; } - -// Specify AVX512 8-bit compressed displacement encoding based on the vector -// element size in bits (8, 16, 32, 64) and the CDisp8 form. -class EVEX_CD8 { - int CD8_EltSize = !srl(esize, 3); - bits<3> CD8_Form = form.Value; -} - -class XOP { Encoding OpEnc = EncXOP; } -class XOP_4V : XOP { bit hasVEX_4V = 1; } - -// Specify the alternative register form instruction to replace the current -// instruction in case it was picked during generation of memory folding tables -class FoldGenData { - string FoldGenRegForm = _RegisterForm; -} - -// Provide a specific instruction to be used by the EVEX2VEX conversion. -class EVEX2VEXOverride { - string EVEX2VEXOverride = VEXInstrName; -} - -// Mark the instruction as "illegal to memory fold/unfold" -class NotMemoryFoldable { bit isMemoryFoldable = 0; } - -// Prevent EVEX->VEX conversion from considering this instruction. -class NotEVEX2VEXConvertible { bit notEVEX2VEXConvertible = 1; } - -class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, - string AsmStr, Domain d = GenericDomain> - : Instruction { - let Namespace = "X86"; - - bits<8> Opcode = opcod; - Format Form = f; - bits<7> FormBits = Form.Value; - ImmType ImmT = i; - - dag OutOperandList = outs; - dag InOperandList = ins; - string AsmString = AsmStr; - - // If this is a pseudo instruction, mark it isCodeGenOnly. - let isCodeGenOnly = !eq(!cast(f), "Pseudo"); - - // - // Attributes specific to X86 instructions... - // - bit ForceDisassemble = 0; // Force instruction to disassemble even though it's - // isCodeGenonly. Needed to hide an ambiguous - // AsmString from the parser, but still disassemble. - - OperandSize OpSize = OpSizeFixed; // Does this instruction's encoding change - // based on operand size of the mode? - bits<2> OpSizeBits = OpSize.Value; - AddressSize AdSize = AdSizeX; // Does this instruction's encoding change - // based on address size of the mode? - bits<2> AdSizeBits = AdSize.Value; - - Prefix OpPrefix = NoPrfx; // Which prefix byte does this inst have? - bits<3> OpPrefixBits = OpPrefix.Value; - Map OpMap = OB; // Which opcode map does this inst have? - bits<3> OpMapBits = OpMap.Value; - bit hasREX_WPrefix = 0; // Does this inst require the REX.W prefix? - FPFormat FPForm = NotFP; // What flavor of FP instruction is this? - bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix? - Domain ExeDomain = d; - bit hasREPPrefix = 0; // Does this inst have a REP prefix? - Encoding OpEnc = EncNormal; // Encoding used by this instruction - bits<2> OpEncBits = OpEnc.Value; - bits<2> VEX_WPrefix = 0; // Does this inst set the VEX_W field? - bit hasVEX_4V = 0; // Does this inst require the VEX.VVVV field? - bit hasVEX_L = 0; // Does this inst use large (256-bit) registers? - bit ignoresVEX_L = 0; // Does this instruction ignore the L-bit - bit hasEVEX_K = 0; // Does this inst require masking? - bit hasEVEX_Z = 0; // Does this inst set the EVEX_Z field? - bit hasEVEX_L2 = 0; // Does this inst set the EVEX_L2 field? - bit hasEVEX_B = 0; // Does this inst set the EVEX_B field? - bits<3> CD8_Form = 0; // Compressed disp8 form - vector-width. - // Declare it int rather than bits<4> so that all bits are defined when - // assigning to bits<7>. - int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes. - bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction. - bit hasNoTrackPrefix = 0; // Does this inst has 0x3E (NoTrack) prefix? - - bits<2> EVEX_LL; - let EVEX_LL{0} = hasVEX_L; - let EVEX_LL{1} = hasEVEX_L2; - // Vector size in bytes. - bits<7> VectSize = !shl(16, EVEX_LL); - - // The scaling factor for AVX512's compressed displacement is either - // - the size of a power-of-two number of elements or - // - the size of a single element for broadcasts or - // - the total vector size divided by a power-of-two number. - // Possible values are: 0 (non-AVX512 inst), 1, 2, 4, 8, 16, 32 and 64. - bits<7> CD8_Scale = !if (!eq (OpEnc.Value, EncEVEX.Value), - !if (CD8_Form{2}, - !shl(CD8_EltSize, CD8_Form{1-0}), - !if (hasEVEX_B, - CD8_EltSize, - !srl(VectSize, CD8_Form{1-0}))), 0); - - // Used in the memory folding generation (TableGen backend) to point to an alternative - // instruction to replace the current one in case it got picked during generation. - string FoldGenRegForm = ?; - - // Used to prevent an explicit EVEX2VEX override for this instruction. - string EVEX2VEXOverride = ?; - - bit isMemoryFoldable = 1; // Is it allowed to memory fold/unfold this instruction? - bit notEVEX2VEXConvertible = 0; // Prevent EVEX->VEX conversion. - - // TSFlags layout should be kept in sync with X86BaseInfo.h. - let TSFlags{6-0} = FormBits; - let TSFlags{8-7} = OpSizeBits; - let TSFlags{10-9} = AdSizeBits; - // No need for 3rd bit, we don't need to distinguish NoPrfx from PS. - let TSFlags{12-11} = OpPrefixBits{1-0}; - let TSFlags{15-13} = OpMapBits; - let TSFlags{16} = hasREX_WPrefix; - let TSFlags{20-17} = ImmT.Value; - let TSFlags{23-21} = FPForm.Value; - let TSFlags{24} = hasLockPrefix; - let TSFlags{25} = hasREPPrefix; - let TSFlags{27-26} = ExeDomain.Value; - let TSFlags{29-28} = OpEncBits; - let TSFlags{37-30} = Opcode; - // Currently no need for second bit in TSFlags - W Ignore is equivalent to 0. - let TSFlags{38} = VEX_WPrefix{0}; - let TSFlags{39} = hasVEX_4V; - let TSFlags{40} = hasVEX_L; - let TSFlags{41} = hasEVEX_K; - let TSFlags{42} = hasEVEX_Z; - let TSFlags{43} = hasEVEX_L2; - let TSFlags{44} = hasEVEX_B; - // If we run out of TSFlags bits, it's possible to encode this in 3 bits. - let TSFlags{51-45} = CD8_Scale; - let TSFlags{52} = hasEVEX_RC; - let TSFlags{53} = hasNoTrackPrefix; -} - -class PseudoI pattern> - : X86Inst<0, Pseudo, NoImm, oops, iops, ""> { - let Pattern = pattern; -} - -class I o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8 o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8Reg o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii32S o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii64 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii16PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii32PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -// FPStack Instruction Templates: -// FPI - Floating Point Instruction template. -class FPI o, Format F, dag outs, dag ins, string asm> - : I {} - -// FpI_ - Floating Point Pseudo Instruction template. Not Predicated. -class FpI_ pattern> - : PseudoI { - let FPForm = fp; -} - -// Templates for instructions that use a 16- or 32-bit segmented address as -// their only operand: lcall (FAR CALL) and ljmp (FAR JMP) -// -// Iseg16 - 16-bit segment selector, 16-bit offset -// Iseg32 - 16-bit segment selector, 32-bit offset - -class Iseg16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Iseg32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -// SI - SSE 1 & 2 scalar instructions -class SI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SI - SSE 1 & 2 scalar intrinsics - vex form available on AVX512 -class SI_Int o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} -// SIi8 - SSE 1 & 2 scalar instructions - vex form available on AVX512 -class SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - [UseSSE2]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// PI - SSE 1 & 2 packed instructions -class PI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// MMXPI - SSE 1 & 2 packed instructions with MMX operands -class MMXPI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpPrefix.Value, PD.Value), [HasMMX, HasSSE2], - [HasMMX, HasSSE1]); -} - -// PIi8 - SSE 1 & 2 packed instructions with immediate -class PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SSE1 Instruction Templates: -// -// SSI - SSE1 instructions with XS prefix. -// PSI - SSE1 instructions with PS prefix. -// PSIi8 - SSE1 instructions with ImmT == Imm8 and PS prefix. -// VSSI - SSE1 instructions with XS prefix in AVX form. -// VPSI - SSE1 instructions with PS prefix in AVX form, packed single. - -class SSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE1]>; -class SSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE1]>; -class PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[UseSSE1]>; -class PSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, - Requires<[UseSSE1]>; -class VSSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX]>; - -// SSE2 Instruction Templates: -// -// SDI - SSE2 instructions with XD prefix. -// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix. -// S2SI - SSE2 instructions with XS prefix. -// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix. -// PDI - SSE2 instructions with PD prefix, packed double domain. -// PDIi8 - SSE2 instructions with ImmT == Imm8 and PD prefix. -// VSDI - SSE2 scalar instructions with XD prefix in AVX form. -// VPDI - SSE2 vector instructions with PD prefix in AVX form, -// packed double domain. -// VS2I - SSE2 scalar instructions with PD prefix in AVX form. -// S2I - SSE2 scalar instructions with PD prefix. -// MMXSDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix as well as -// MMX operands. -// MMXSSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix as well as -// MMX operands. - -class SDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, Requires<[UseSSE2]>; -class SDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[UseSSE2]>; -class S2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE2]>; -class S2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE2]>; -class PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE2]>; -class PDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[UseSSE2]>; -class VSDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseAVX]>; -class VS2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - PD, Requires<[HasAVX]>; -class VS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseAVX]>; -class S2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[UseSSE2]>; -class MMXSDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX, HasSSE2]>; -class MMXS2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX, HasSSE2]>; - -// SSE3 Instruction Templates: -// -// S3I - SSE3 instructions with PD prefixes. -// S3SI - SSE3 instructions with XS prefix. -// S3DI - SSE3 instructions with XD prefix. - -class S3SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[UseSSE3]>; -class S3DI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseSSE3]>; -class S3I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE3]>; - - -// SSSE3 Instruction Templates: -// -// SS38I - SSSE3 instructions with T8 prefix. -// SS3AI - SSSE3 instructions with TA prefix. -// MMXSS38I - SSSE3 instructions with T8 prefix and MMX operands. -// MMXSS3AI - SSSE3 instructions with TA prefix and MMX operands. -// -// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version -// uses the MMX registers. The 64-bit versions are grouped with the MMX -// classes. They need to be enabled even if AVX is enabled. - -class SS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSSE3]>; -class SS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSSE3]>; -class MMXSS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PS, - Requires<[HasMMX, HasSSSE3]>; -class MMXSS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPS, - Requires<[HasMMX, HasSSSE3]>; - -// SSE4.1 Instruction Templates: -// -// SS48I - SSE 4.1 instructions with T8 prefix. -// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8. -// -class SS48I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE41]>; -class SS4AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE41]>; - -// SSE4.2 Instruction Templates: -// -// SS428I - SSE 4.2 instructions with T8 prefix. -class SS428I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE42]>; - -// SS42FI - SSE 4.2 instructions with T8XD prefix. -// NOTE: 'HasSSE42' is used as SS42FI is only used for CRC32 insns. -class SS42FI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XD, Requires<[HasSSE42]>; - -// SS42AI = SSE 4.2 instructions with TA prefix -class SS42AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE42]>; - -// AVX Instruction Templates: -// Instructions introduced in AVX (no SSE equivalent forms) -// -// AVX8I - AVX instructions with T8PD prefix. -// AVXAIi8 - AVX instructions with TAPD prefix and ImmT = Imm8. -class AVX8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX]>; -class AVXAIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX]>; - -// AVX2 Instruction Templates: -// Instructions introduced in AVX2 (no SSE equivalent forms) -// -// AVX28I - AVX2 instructions with T8PD prefix. -// AVX2AIi8 - AVX2 instructions with TAPD prefix and ImmT = Imm8. -class AVX28I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX2]>; -class AVX2AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX2]>; - - -// AVX-512 Instruction Templates: -// Instructions introduced in AVX-512 (no SSE equivalent forms) -// -// AVX5128I - AVX-512 instructions with T8PD prefix. -// AVX512AIi8 - AVX-512 instructions with TAPD prefix and ImmT = Imm8. -// AVX512PDI - AVX-512 instructions with PD, double packed. -// AVX512PSI - AVX-512 instructions with PS, single packed. -// AVX512XS8I - AVX-512 instructions with T8 and XS prefixes. -// AVX512XSI - AVX-512 instructions with XS prefix, generic domain. -// AVX512BI - AVX-512 instructions with PD, int packed domain. -// AVX512SI - AVX-512 scalar instructions with PD prefix. - -class AVX5128I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX512]>; -class AVX5128IBase : T8PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512XS8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XS, - Requires<[HasAVX512]>; -class AVX512XSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX512]>; -class AVX512XDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[HasAVX512]>; -class AVX512BI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512BIBase : PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512BIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[HasAVX512]>; -class AVX512BIi8Base : PD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XSIi8Base : XS { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XDIi8Base : XD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512PSIi8Base : PS { - Domain ExeDomain = SSEPackedSingle; - ImmType ImmT = Imm8; -} -class AVX512PDIi8Base : PD { - Domain ExeDomain = SSEPackedDouble; - ImmType ImmT = Imm8; -} -class AVX512AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX512]>; -class AVX512AIi8Base : TAPD { - ImmType ImmT = Imm8; -} -class AVX512Ii8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - Requires<[HasAVX512]>; -class AVX512PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX512]>; -class AVX512PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8, Requires<[HasAVX512]>; -class AVX512PI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : I, Requires<[HasAVX512]>; -class AVX512FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - EVEX_4V, Requires<[HasAVX512]>; -class AVX512FMA3Base : T8PD, EVEX_4V; - -class AVX512 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, Requires<[HasAVX512]>; - -// AES Instruction Templates: -// -// AES8I -// These use the same encoding as the SSE4.2 T8 and TA encodings. -class AES8I o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - Requires<[NoAVX, HasAES]>; - -class AESAI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[NoAVX, HasAES]>; - -// PCLMUL Instruction Templates -class PCLMULIi8 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8, TAPD; - -// FMA3 Instruction Templates -class FMA3 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoVLX]>; -class FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoAVX512]>; -class FMA3S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoAVX512]>; - -// FMA4 Instruction Templates -class FMA4 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoVLX]>; -class FMA4S o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoAVX512]>; -class FMA4S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4]>; - -// XOP 2, 3 and 4 Operand Instruction Template -class IXOP o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - XOP9, Requires<[HasXOP]>; - -// XOP 2 and 3 Operand Instruction Templates with imm byte -class IXOPi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - XOP8, Requires<[HasXOP]>; -// XOP 4 Operand Instruction Templates with imm byte -class IXOPi8Reg o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8Reg, - XOP8, Requires<[HasXOP]>; - -// XOP 5 operand instruction (VEX encoding!) -class IXOP5 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, Requires<[HasXOP]>; - -// X86-64 Instruction templates... -// - -class RI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, REX_W; -class RIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, REX_W; -class RIi16 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii16, REX_W; -class RIi32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32, REX_W; -class RIi32S o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32S, REX_W; -class RIi64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii64, REX_W; - -class RS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : S2I, REX_W; -class VRS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : VS2I, VEX_W; - -// MMX Instruction templates -// - -// MMXI - MMX instructions with TB prefix. -// MMXI32 - MMX instructions with TB prefix valid only in 32 bit mode. -// MMXI64 - MMX instructions with TB prefix valid only in 64 bit mode. -// MMX2I - MMX / SSE2 instructions with PD prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXID - MMX instructions with XD prefix. -// MMXIS - MMX instructions with XS prefix. -class MMXI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX]>; -class MMXI32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,Not64BitMode]>; -class MMXI64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,In64BitMode]>; -class MMXRI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, REX_W, Requires<[HasMMX]>; -class MMX2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[HasMMX]>; -class MMXIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, Requires<[HasMMX]>; -class MMXID o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX]>; -class MMXIS o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX]>; diff --git a/suite/synctools/tablegen/X86/X86InstrFragmentsSIMD.td b/suite/synctools/tablegen/X86/X86InstrFragmentsSIMD.td deleted file mode 100644 index 7392759079..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrFragmentsSIMD.td +++ /dev/null @@ -1,1075 +0,0 @@ -//===-- X86InstrFragmentsSIMD.td - x86 SIMD ISA ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides pattern fragments useful for SIMD instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MMX specific DAG Nodes. -//===----------------------------------------------------------------------===// - -// Low word of MMX to GPR. -def MMX_X86movd2w : SDNode<"X86ISD::MMX_MOVD2W", SDTypeProfile<1, 1, - [SDTCisVT<0, i32>, SDTCisVT<1, x86mmx>]>>; -// GPR to low word of MMX. -def MMX_X86movw2d : SDNode<"X86ISD::MMX_MOVW2D", SDTypeProfile<1, 1, - [SDTCisVT<0, x86mmx>, SDTCisVT<1, i32>]>>; - -//===----------------------------------------------------------------------===// -// MMX Pattern Fragments -//===----------------------------------------------------------------------===// - -def load_mmx : PatFrag<(ops node:$ptr), (x86mmx (load node:$ptr))>; - -//===----------------------------------------------------------------------===// -// SSE specific DAG Nodes. -//===----------------------------------------------------------------------===// - -def SDTX86VFCMP : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>]>; - -def X86fmin : SDNode<"X86ISD::FMIN", SDTFPBinOp>; -def X86fmax : SDNode<"X86ISD::FMAX", SDTFPBinOp>; -def X86fmins : SDNode<"X86ISD::FMINS", SDTFPBinOp>; -def X86fmaxs : SDNode<"X86ISD::FMAXS", SDTFPBinOp>; - -// Commutative and Associative FMIN and FMAX. -def X86fminc : SDNode<"X86ISD::FMINC", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fmaxc : SDNode<"X86ISD::FMAXC", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; - -def X86fand : SDNode<"X86ISD::FAND", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86for : SDNode<"X86ISD::FOR", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fxor : SDNode<"X86ISD::FXOR", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fandn : SDNode<"X86ISD::FANDN", SDTFPBinOp>; -def X86frsqrt : SDNode<"X86ISD::FRSQRT", SDTFPUnaryOp>; -def X86frcp : SDNode<"X86ISD::FRCP", SDTFPUnaryOp>; -def X86fhadd : SDNode<"X86ISD::FHADD", SDTFPBinOp>; -def X86fhsub : SDNode<"X86ISD::FHSUB", SDTFPBinOp>; -def X86hadd : SDNode<"X86ISD::HADD", SDTIntBinOp>; -def X86hsub : SDNode<"X86ISD::HSUB", SDTIntBinOp>; -def X86comi : SDNode<"X86ISD::COMI", SDTX86CmpTest>; -def X86ucomi : SDNode<"X86ISD::UCOMI", SDTX86CmpTest>; -def X86cmps : SDNode<"X86ISD::FSETCC", SDTX86Cmps>; -def X86pshufb : SDNode<"X86ISD::PSHUFB", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i8>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86psadbw : SDNode<"X86ISD::PSADBW", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>, [SDNPCommutative]>; -def X86dbpsadbw : SDNode<"X86ISD::DBPSADBW", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>, SDTCisInt<3>]>>; -def X86andnp : SDNode<"X86ISD::ANDNP", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86multishift : SDNode<"X86ISD::MULTISHIFT", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<1,2>]>>; -def X86pextrb : SDNode<"X86ISD::PEXTRB", - SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, v16i8>, - SDTCisPtrTy<2>]>>; -def X86pextrw : SDNode<"X86ISD::PEXTRW", - SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, v8i16>, - SDTCisPtrTy<2>]>>; -def X86pinsrb : SDNode<"X86ISD::PINSRB", - SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; -def X86pinsrw : SDNode<"X86ISD::PINSRW", - SDTypeProfile<1, 3, [SDTCisVT<0, v8i16>, SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; -def X86insertps : SDNode<"X86ISD::INSERTPS", - SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisSameAs<0,1>, - SDTCisVT<2, v4f32>, SDTCisVT<3, i8>]>>; -def X86vzmovl : SDNode<"X86ISD::VZEXT_MOVL", - SDTypeProfile<1, 1, [SDTCisSameAs<0,1>]>>; - -def X86vzload : SDNode<"X86ISD::VZEXT_LOAD", SDTLoad, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; - -def X86vzext : SDNode<"X86ISD::VZEXT", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<1, 0>]>>; - -def X86vsext : SDNode<"X86ISD::VSEXT", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<1, 0>]>>; - -def SDTVtrunc : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<0, 1>]>; - -def X86vtrunc : SDNode<"X86ISD::VTRUNC", SDTVtrunc>; -def X86vtruncs : SDNode<"X86ISD::VTRUNCS", SDTVtrunc>; -def X86vtruncus : SDNode<"X86ISD::VTRUNCUS", SDTVtrunc>; - -def X86vfpext : SDNode<"X86ISD::VFPEXT", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f64>, - SDTCVecEltisVT<1, f32>, - SDTCisSameSizeAs<0, 1>]>>; -def X86vfpround: SDNode<"X86ISD::VFPROUND", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, f64>, - SDTCisSameSizeAs<0, 1>]>>; - -def X86froundRnd: SDNode<"X86ISD::VFPROUNDS_RND", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, f32>, - SDTCisSameAs<0, 1>, - SDTCVecEltisVT<2, f64>, - SDTCisSameSizeAs<0, 2>, - SDTCisVT<3, i32>]>>; - -def X86fpextRnd : SDNode<"X86ISD::VFPEXTS_RND", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, f64>, - SDTCisSameAs<0, 1>, - SDTCVecEltisVT<2, f32>, - SDTCisSameSizeAs<0, 2>, - SDTCisVT<3, i32>]>>; - -def X86vshiftimm : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisVT<2, i8>, SDTCisInt<0>]>; - -def X86vshldq : SDNode<"X86ISD::VSHLDQ", X86vshiftimm>; -def X86vshrdq : SDNode<"X86ISD::VSRLDQ", X86vshiftimm>; -def X86cmpp : SDNode<"X86ISD::CMPP", SDTX86VFCMP>; -def X86pcmpeq : SDNode<"X86ISD::PCMPEQ", SDTIntBinOp, [SDNPCommutative]>; -def X86pcmpgt : SDNode<"X86ISD::PCMPGT", SDTIntBinOp>; - -def X86CmpMaskCC : - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCVecEltisVT<0, i1>, - SDTCisVec<1>, SDTCisSameAs<2, 1>, - SDTCisSameNumEltsAs<0, 1>, SDTCisVT<3, i8>]>; -def X86CmpMaskCCRound : - SDTypeProfile<1, 4, [SDTCisVec<0>,SDTCVecEltisVT<0, i1>, - SDTCisVec<1>, SDTCisFP<1>, SDTCisSameAs<2, 1>, - SDTCisSameNumEltsAs<0, 1>, SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; -def X86CmpMaskCCScalar : - SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisFP<1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>]>; - -def X86CmpMaskCCScalarRound : - SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisFP<1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -def X86cmpm : SDNode<"X86ISD::CMPM", X86CmpMaskCC>; -// Hack to make CMPM commutable in tablegen patterns for load folding. -def X86cmpm_c : SDNode<"X86ISD::CMPM", X86CmpMaskCC, [SDNPCommutative]>; -def X86cmpmRnd : SDNode<"X86ISD::CMPM_RND", X86CmpMaskCCRound>; -def X86cmpms : SDNode<"X86ISD::FSETCCM", X86CmpMaskCCScalar>; -def X86cmpmsRnd : SDNode<"X86ISD::FSETCCM_RND", X86CmpMaskCCScalarRound>; - -def X86phminpos: SDNode<"X86ISD::PHMINPOS", - SDTypeProfile<1, 1, [SDTCisVT<0, v8i16>, SDTCisVT<1, v8i16>]>>; - -def X86vshiftuniform : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisVec<2>, SDTCisInt<0>, - SDTCisInt<1>]>; - -def X86vshl : SDNode<"X86ISD::VSHL", X86vshiftuniform>; -def X86vsrl : SDNode<"X86ISD::VSRL", X86vshiftuniform>; -def X86vsra : SDNode<"X86ISD::VSRA", X86vshiftuniform>; - -def X86vshiftvariable : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisInt<0>]>; - -def X86vsrav : SDNode<"X86ISD::VSRAV", X86vshiftvariable>; - -def X86vshli : SDNode<"X86ISD::VSHLI", X86vshiftimm>; -def X86vsrli : SDNode<"X86ISD::VSRLI", X86vshiftimm>; -def X86vsrai : SDNode<"X86ISD::VSRAI", X86vshiftimm>; - -def X86kshiftl : SDNode<"X86ISD::KSHIFTL", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisSameAs<0, 1>, - SDTCisVT<2, i8>]>>; -def X86kshiftr : SDNode<"X86ISD::KSHIFTR", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisSameAs<0, 1>, - SDTCisVT<2, i8>]>>; - -def X86kadd : SDNode<"X86ISD::KADD", SDTIntBinOp, [SDNPCommutative]>; - -def X86vrotli : SDNode<"X86ISD::VROTLI", X86vshiftimm>; -def X86vrotri : SDNode<"X86ISD::VROTRI", X86vshiftimm>; - -def X86vpshl : SDNode<"X86ISD::VPSHL", X86vshiftvariable>; -def X86vpsha : SDNode<"X86ISD::VPSHA", X86vshiftvariable>; - -def X86vpcom : SDNode<"X86ISD::VPCOM", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>, SDTCisInt<0>]>>; -def X86vpcomu : SDNode<"X86ISD::VPCOMU", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>, SDTCisInt<0>]>>; -def X86vpermil2 : SDNode<"X86ISD::VPERMIL2", - SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisFP<0>, SDTCisInt<3>, - SDTCisSameNumEltsAs<0, 3>, - SDTCisSameSizeAs<0,3>, - SDTCisVT<4, i8>]>>; -def X86vpperm : SDNode<"X86ISD::VPPERM", - SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisSameAs<0, 3>]>>; - -def SDTX86CmpPTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisVec<1>, - SDTCisSameAs<2, 1>]>; - -def X86addus : SDNode<"X86ISD::ADDUS", SDTIntBinOp, [SDNPCommutative]>; -def X86subus : SDNode<"X86ISD::SUBUS", SDTIntBinOp>; -def X86adds : SDNode<"X86ISD::ADDS", SDTIntBinOp, [SDNPCommutative]>; -def X86subs : SDNode<"X86ISD::SUBS", SDTIntBinOp>; -def X86mulhrs : SDNode<"X86ISD::MULHRS", SDTIntBinOp, [SDNPCommutative]>; -def X86avg : SDNode<"X86ISD::AVG" , SDTIntBinOp, [SDNPCommutative]>; -def X86ptest : SDNode<"X86ISD::PTEST", SDTX86CmpPTest>; -def X86testp : SDNode<"X86ISD::TESTP", SDTX86CmpPTest>; -def X86kortest : SDNode<"X86ISD::KORTEST", SDTX86CmpPTest>; -def X86ktest : SDNode<"X86ISD::KTEST", SDTX86CmpPTest>; - -def X86movmsk : SDNode<"X86ISD::MOVMSK", - SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVec<1>]>>; - -def X86selects : SDNode<"X86ISD::SELECTS", - SDTypeProfile<1, 3, [SDTCisVT<1, v1i1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<2, 3>]>>; - -def X86pmuludq : SDNode<"X86ISD::PMULUDQ", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; -def X86pmuldq : SDNode<"X86ISD::PMULDQ", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; - -def X86extrqi : SDNode<"X86ISD::EXTRQI", - SDTypeProfile<1, 3, [SDTCisVT<0, v2i64>, SDTCisSameAs<0,1>, - SDTCisVT<2, i8>, SDTCisVT<3, i8>]>>; -def X86insertqi : SDNode<"X86ISD::INSERTQI", - SDTypeProfile<1, 4, [SDTCisVT<0, v2i64>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisVT<3, i8>, - SDTCisVT<4, i8>]>>; - -// Specific shuffle nodes - At some point ISD::VECTOR_SHUFFLE will always get -// translated into one of the target nodes below during lowering. -// Note: this is a work in progress... -def SDTShuff1Op : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>; -def SDTShuff2Op : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>; -def SDTShuff2OpFP : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisFP<0>, - SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>; - -def SDTShuff2OpM : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisFP<0>, SDTCisInt<2>, - SDTCisSameNumEltsAs<0,2>, - SDTCisSameSizeAs<0,2>]>; -def SDTShuff2OpI : SDTypeProfile<1, 2, [SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisVT<2, i8>]>; -def SDTShuff3OpI : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisVT<3, i8>]>; -def SDTFPBinOpImm: SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i32>]>; -def SDTFPBinOpImmRound: SDTypeProfile<1, 4, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i32>, - SDTCisVT<4, i32>]>; -def SDTFPTernaryOpImmRound: SDTypeProfile<1, 5, [SDTCisFP<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisInt<3>, - SDTCisSameSizeAs<0, 3>, - SDTCisSameNumEltsAs<0, 3>, - SDTCisVT<4, i32>, - SDTCisVT<5, i32>]>; -def SDTFPUnaryOpImm: SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisVT<2, i32>]>; -def SDTFPUnaryOpImmRound: SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i32>]>; - -def SDTVBroadcast : SDTypeProfile<1, 1, [SDTCisVec<0>]>; -def SDTVBroadcastm : SDTypeProfile<1, 1, [SDTCisVec<0>, - SDTCisInt<0>, SDTCisInt<1>]>; - -def SDTBlend : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisVT<3, i8>]>; - -def SDTTernlog : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>, SDTCisVT<4, i8>]>; - -def SDTFPBinOpRound : SDTypeProfile<1, 3, [ // fadd_round, fmul_round, etc. - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0>, SDTCisVT<3, i32>]>; - -def SDTFPUnaryOpRound : SDTypeProfile<1, 2, [ // fsqrt_round, fgetexp_round, etc. - SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisVT<2, i32>]>; - -def SDTFmaRound : SDTypeProfile<1, 4, [SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>, - SDTCisFP<0>, SDTCisVT<4, i32>]>; - -def X86PAlignr : SDNode<"X86ISD::PALIGNR", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, i8>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>]>>; -def X86VAlign : SDNode<"X86ISD::VALIGN", SDTShuff3OpI>; - -def X86VShld : SDNode<"X86ISD::VSHLD", SDTShuff3OpI>; -def X86VShrd : SDNode<"X86ISD::VSHRD", SDTShuff3OpI>; -def X86VShldv : SDNode<"X86ISD::VSHLDV", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>]>>; -def X86VShrdv : SDNode<"X86ISD::VSHRDV", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>]>>; - -def X86Conflict : SDNode<"X86ISD::CONFLICT", SDTIntUnaryOp>; - -def X86PShufd : SDNode<"X86ISD::PSHUFD", SDTShuff2OpI>; -def X86PShufhw : SDNode<"X86ISD::PSHUFHW", SDTShuff2OpI>; -def X86PShuflw : SDNode<"X86ISD::PSHUFLW", SDTShuff2OpI>; - -def X86Shufp : SDNode<"X86ISD::SHUFP", SDTShuff3OpI>; -def X86Shuf128 : SDNode<"X86ISD::SHUF128", SDTShuff3OpI>; - -def X86Movddup : SDNode<"X86ISD::MOVDDUP", SDTShuff1Op>; -def X86Movshdup : SDNode<"X86ISD::MOVSHDUP", SDTShuff1Op>; -def X86Movsldup : SDNode<"X86ISD::MOVSLDUP", SDTShuff1Op>; - -def X86Movsd : SDNode<"X86ISD::MOVSD", SDTShuff2OpFP>; -def X86Movss : SDNode<"X86ISD::MOVSS", SDTShuff2OpFP>; - -def X86Movlhps : SDNode<"X86ISD::MOVLHPS", SDTShuff2OpFP>; -def X86Movhlps : SDNode<"X86ISD::MOVHLPS", SDTShuff2OpFP>; - -def SDTPack : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, - SDTCisVec<1>, SDTCisInt<1>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>, - SDTCisOpSmallerThanOp<0, 1>]>; -def X86Packss : SDNode<"X86ISD::PACKSS", SDTPack>; -def X86Packus : SDNode<"X86ISD::PACKUS", SDTPack>; - -def X86Unpckl : SDNode<"X86ISD::UNPCKL", SDTShuff2Op>; -def X86Unpckh : SDNode<"X86ISD::UNPCKH", SDTShuff2Op>; - -def X86vpmaddubsw : SDNode<"X86ISD::VPMADDUBSW", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>>; -def X86vpmaddwd : SDNode<"X86ISD::VPMADDWD", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i32>, - SDTCVecEltisVT<1, i16>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; - -def X86VPermilpv : SDNode<"X86ISD::VPERMILPV", SDTShuff2OpM>; -def X86VPermilpi : SDNode<"X86ISD::VPERMILPI", SDTShuff2OpI>; -def X86VPermv : SDNode<"X86ISD::VPERMV", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<1>, - SDTCisSameNumEltsAs<0,1>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86VPermi : SDNode<"X86ISD::VPERMI", SDTShuff2OpI>; -def X86VPermt2 : SDNode<"X86ISD::VPERMV3", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisInt<2>, - SDTCisVec<2>, SDTCisSameNumEltsAs<0, 2>, - SDTCisSameSizeAs<0,2>, - SDTCisSameAs<0,3>]>, []>; - -def X86vpternlog : SDNode<"X86ISD::VPTERNLOG", SDTTernlog>; - -def X86VPerm2x128 : SDNode<"X86ISD::VPERM2X128", SDTShuff3OpI>; - -def X86VFixupimm : SDNode<"X86ISD::VFIXUPIMM", SDTFPTernaryOpImmRound>; -def X86VFixupimmScalar : SDNode<"X86ISD::VFIXUPIMMS", SDTFPTernaryOpImmRound>; -def X86VRange : SDNode<"X86ISD::VRANGE", SDTFPBinOpImm>; -def X86VRangeRnd : SDNode<"X86ISD::VRANGE_RND", SDTFPBinOpImmRound>; -def X86VReduce : SDNode<"X86ISD::VREDUCE", SDTFPUnaryOpImm>; -def X86VReduceRnd : SDNode<"X86ISD::VREDUCE_RND", SDTFPUnaryOpImmRound>; -def X86VRndScale : SDNode<"X86ISD::VRNDSCALE", SDTFPUnaryOpImm>; -def X86VRndScaleRnd: SDNode<"X86ISD::VRNDSCALE_RND", SDTFPUnaryOpImmRound>; -def X86VGetMant : SDNode<"X86ISD::VGETMANT", SDTFPUnaryOpImm>; -def X86VGetMantRnd : SDNode<"X86ISD::VGETMANT_RND", SDTFPUnaryOpImmRound>; -def X86Vfpclass : SDNode<"X86ISD::VFPCLASS", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisFP<1>, - SDTCisSameNumEltsAs<0,1>, - SDTCisVT<2, i32>]>, []>; -def X86Vfpclasss : SDNode<"X86ISD::VFPCLASSS", - SDTypeProfile<1, 2, [SDTCisVT<0, v1i1>, - SDTCisFP<1>, SDTCisVT<2, i32>]>,[]>; - -def X86SubVBroadcast : SDNode<"X86ISD::SUBV_BROADCAST", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSubVecOfVec<1, 0>]>, []>; - -def X86VBroadcast : SDNode<"X86ISD::VBROADCAST", SDTVBroadcast>; -def X86VBroadcastm : SDNode<"X86ISD::VBROADCASTM", SDTVBroadcastm>; - -def X86Blendi : SDNode<"X86ISD::BLENDI", SDTBlend>; - -def X86Addsub : SDNode<"X86ISD::ADDSUB", SDTFPBinOp>; - -def X86faddRnd : SDNode<"X86ISD::FADD_RND", SDTFPBinOpRound>; -def X86faddRnds : SDNode<"X86ISD::FADDS_RND", SDTFPBinOpRound>; -def X86fsubRnd : SDNode<"X86ISD::FSUB_RND", SDTFPBinOpRound>; -def X86fsubRnds : SDNode<"X86ISD::FSUBS_RND", SDTFPBinOpRound>; -def X86fmulRnd : SDNode<"X86ISD::FMUL_RND", SDTFPBinOpRound>; -def X86fmulRnds : SDNode<"X86ISD::FMULS_RND", SDTFPBinOpRound>; -def X86fdivRnd : SDNode<"X86ISD::FDIV_RND", SDTFPBinOpRound>; -def X86fdivRnds : SDNode<"X86ISD::FDIVS_RND", SDTFPBinOpRound>; -def X86fmaxRnd : SDNode<"X86ISD::FMAX_RND", SDTFPBinOpRound>; -def X86fmaxRnds : SDNode<"X86ISD::FMAXS_RND", SDTFPBinOpRound>; -def X86fminRnd : SDNode<"X86ISD::FMIN_RND", SDTFPBinOpRound>; -def X86fminRnds : SDNode<"X86ISD::FMINS_RND", SDTFPBinOpRound>; -def X86scalef : SDNode<"X86ISD::SCALEF", SDTFPBinOpRound>; -def X86scalefs : SDNode<"X86ISD::SCALEFS", SDTFPBinOpRound>; -def X86fsqrtRnd : SDNode<"X86ISD::FSQRT_RND", SDTFPUnaryOpRound>; -def X86fsqrtRnds : SDNode<"X86ISD::FSQRTS_RND", SDTFPBinOpRound>; -def X86fgetexpRnd : SDNode<"X86ISD::FGETEXP_RND", SDTFPUnaryOpRound>; -def X86fgetexpRnds : SDNode<"X86ISD::FGETEXPS_RND", SDTFPBinOpRound>; - -def X86Fmadd : SDNode<"ISD::FMA", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fnmadd : SDNode<"X86ISD::FNMADD", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmsub : SDNode<"X86ISD::FMSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fnmsub : SDNode<"X86ISD::FNMSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmaddsub : SDNode<"X86ISD::FMADDSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmsubadd : SDNode<"X86ISD::FMSUBADD", SDTFPTernaryOp, [SDNPCommutative]>; - -def X86FmaddRnd : SDNode<"X86ISD::FMADD_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FnmaddRnd : SDNode<"X86ISD::FNMADD_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmsubRnd : SDNode<"X86ISD::FMSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FnmsubRnd : SDNode<"X86ISD::FNMSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmaddsubRnd : SDNode<"X86ISD::FMADDSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmsubaddRnd : SDNode<"X86ISD::FMSUBADD_RND", SDTFmaRound, [SDNPCommutative]>; - -def SDTIFma : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>]>; -def x86vpmadd52l : SDNode<"X86ISD::VPMADD52L", SDTIFma, [SDNPCommutative]>; -def x86vpmadd52h : SDNode<"X86ISD::VPMADD52H", SDTIFma, [SDNPCommutative]>; - -def X86rsqrt14 : SDNode<"X86ISD::RSQRT14", SDTFPUnaryOp>; -def X86rcp14 : SDNode<"X86ISD::RCP14", SDTFPUnaryOp>; - -// VNNI -def SDTVnni : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>]>; -def X86Vpdpbusd : SDNode<"X86ISD::VPDPBUSD", SDTVnni>; -def X86Vpdpbusds : SDNode<"X86ISD::VPDPBUSDS", SDTVnni>; -def X86Vpdpwssd : SDNode<"X86ISD::VPDPWSSD", SDTVnni>; -def X86Vpdpwssds : SDNode<"X86ISD::VPDPWSSDS", SDTVnni>; - -def X86rsqrt28 : SDNode<"X86ISD::RSQRT28", SDTFPUnaryOpRound>; -def X86rcp28 : SDNode<"X86ISD::RCP28", SDTFPUnaryOpRound>; -def X86exp2 : SDNode<"X86ISD::EXP2", SDTFPUnaryOpRound>; - -def X86rsqrt14s : SDNode<"X86ISD::RSQRT14S", SDTFPBinOp>; -def X86rcp14s : SDNode<"X86ISD::RCP14S", SDTFPBinOp>; -def X86rsqrt28s : SDNode<"X86ISD::RSQRT28S", SDTFPBinOpRound>; -def X86rcp28s : SDNode<"X86ISD::RCP28S", SDTFPBinOpRound>; -def X86Ranges : SDNode<"X86ISD::VRANGES", SDTFPBinOpImm>; -def X86RndScales : SDNode<"X86ISD::VRNDSCALES", SDTFPBinOpImm>; -def X86Reduces : SDNode<"X86ISD::VREDUCES", SDTFPBinOpImm>; -def X86GetMants : SDNode<"X86ISD::VGETMANTS", SDTFPBinOpImm>; -def X86RangesRnd : SDNode<"X86ISD::VRANGES_RND", SDTFPBinOpImmRound>; -def X86RndScalesRnd : SDNode<"X86ISD::VRNDSCALES_RND", SDTFPBinOpImmRound>; -def X86ReducesRnd : SDNode<"X86ISD::VREDUCES_RND", SDTFPBinOpImmRound>; -def X86GetMantsRnd : SDNode<"X86ISD::VGETMANTS_RND", SDTFPBinOpImmRound>; - -def X86compress: SDNode<"X86ISD::COMPRESS", SDTypeProfile<1, 1, - [SDTCisSameAs<0, 1>, SDTCisVec<1>]>, []>; -def X86expand : SDNode<"X86ISD::EXPAND", SDTypeProfile<1, 1, - [SDTCisSameAs<0, 1>, SDTCisVec<1>]>, []>; - -// vpshufbitqmb -def X86Vpshufbitqmb : SDNode<"X86ISD::VPSHUFBITQMB", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<1,2>, - SDTCVecEltisVT<0,i1>, - SDTCisSameNumEltsAs<0,1>]>>; - -def SDTintToFPRound: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisFP<0>, - SDTCisSameAs<0,1>, SDTCisInt<2>, - SDTCisVT<3, i32>]>; - -def SDTFloatToInt: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisFP<1>]>; -def SDTFloatToIntRnd: SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisFP<1>, - SDTCisVT<2, i32>]>; -def SDTSFloatToIntRnd: SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisFP<1>, - SDTCisVec<1>, SDTCisVT<2, i32>]>; - -def SDTVintToFP: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisFP<0>, SDTCisInt<1>]>; -def SDTVintToFPRound: SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisFP<0>, SDTCisInt<1>, - SDTCisVT<2, i32>]>; - -// Scalar -def X86SintToFpRnd : SDNode<"X86ISD::SCALAR_SINT_TO_FP_RND", SDTintToFPRound>; -def X86UintToFpRnd : SDNode<"X86ISD::SCALAR_UINT_TO_FP_RND", SDTintToFPRound>; - -def X86cvtts2IntRnd : SDNode<"X86ISD::CVTTS2SI_RND", SDTSFloatToIntRnd>; -def X86cvtts2UIntRnd : SDNode<"X86ISD::CVTTS2UI_RND", SDTSFloatToIntRnd>; - -def X86cvts2si : SDNode<"X86ISD::CVTS2SI_RND", SDTSFloatToIntRnd>; -def X86cvts2usi : SDNode<"X86ISD::CVTS2UI_RND", SDTSFloatToIntRnd>; - -// Vector with rounding mode - -// cvtt fp-to-int staff -def X86cvttp2siRnd : SDNode<"X86ISD::CVTTP2SI_RND", SDTFloatToIntRnd>; -def X86cvttp2uiRnd : SDNode<"X86ISD::CVTTP2UI_RND", SDTFloatToIntRnd>; - -def X86VSintToFpRnd : SDNode<"X86ISD::SINT_TO_FP_RND", SDTVintToFPRound>; -def X86VUintToFpRnd : SDNode<"X86ISD::UINT_TO_FP_RND", SDTVintToFPRound>; - -// cvt fp-to-int staff -def X86cvtp2IntRnd : SDNode<"X86ISD::CVTP2SI_RND", SDTFloatToIntRnd>; -def X86cvtp2UIntRnd : SDNode<"X86ISD::CVTP2UI_RND", SDTFloatToIntRnd>; - -// Vector without rounding mode - -// cvtt fp-to-int staff -def X86cvttp2si : SDNode<"X86ISD::CVTTP2SI", SDTFloatToInt>; -def X86cvttp2ui : SDNode<"X86ISD::CVTTP2UI", SDTFloatToInt>; - -def X86VSintToFP : SDNode<"X86ISD::CVTSI2P", SDTVintToFP>; -def X86VUintToFP : SDNode<"X86ISD::CVTUI2P", SDTVintToFP>; - -// cvt int-to-fp staff -def X86cvtp2Int : SDNode<"X86ISD::CVTP2SI", SDTFloatToInt>; -def X86cvtp2UInt : SDNode<"X86ISD::CVTP2UI", SDTFloatToInt>; - - -def X86cvtph2ps : SDNode<"X86ISD::CVTPH2PS", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, i16>]> >; - -def X86cvtph2psRnd : SDNode<"X86ISD::CVTPH2PS_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, i16>, - SDTCisVT<2, i32>]> >; - -def X86cvtps2ph : SDNode<"X86ISD::CVTPS2PH", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, f32>, - SDTCisVT<2, i32>]> >; -def X86vfpextRnd : SDNode<"X86ISD::VFPEXT_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f64>, - SDTCVecEltisVT<1, f32>, - SDTCisOpSmallerThanOp<1, 0>, - SDTCisVT<2, i32>]>>; -def X86vfproundRnd: SDNode<"X86ISD::VFPROUND_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, f64>, - SDTCisOpSmallerThanOp<0, 1>, - SDTCisVT<2, i32>]>>; - -// galois field arithmetic -def X86GF2P8affineinvqb : SDNode<"X86ISD::GF2P8AFFINEINVQB", SDTBlend>; -def X86GF2P8affineqb : SDNode<"X86ISD::GF2P8AFFINEQB", SDTBlend>; -def X86GF2P8mulb : SDNode<"X86ISD::GF2P8MULB", SDTIntBinOp>; - -//===----------------------------------------------------------------------===// -// SSE Complex Patterns -//===----------------------------------------------------------------------===// - -// These are 'extloads' from a scalar to the low element of a vector, zeroing -// the top elements. These are used for the SSE 'ss' and 'sd' instruction -// forms. -def sse_load_f32 : ComplexPattern; -def sse_load_f64 : ComplexPattern; - -def ssmem : Operand { - let PrintMethod = "printf32mem"; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} -def sdmem : Operand { - let PrintMethod = "printf64mem"; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -//===----------------------------------------------------------------------===// -// SSE pattern fragments -//===----------------------------------------------------------------------===// - -// Vector load wrappers to prevent folding of non-temporal aligned loads on -// supporting targets. -def vecload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - return !useNonTemporalLoad(cast(N)); -}]>; - -// 128-bit load pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def loadv4f32 : PatFrag<(ops node:$ptr), (v4f32 (vecload node:$ptr))>; -def loadv2f64 : PatFrag<(ops node:$ptr), (v2f64 (vecload node:$ptr))>; -def loadv2i64 : PatFrag<(ops node:$ptr), (v2i64 (vecload node:$ptr))>; - -// 256-bit load pattern fragments -// NOTE: all 256-bit integer vector loads are promoted to v4i64 -def loadv8f32 : PatFrag<(ops node:$ptr), (v8f32 (vecload node:$ptr))>; -def loadv4f64 : PatFrag<(ops node:$ptr), (v4f64 (vecload node:$ptr))>; -def loadv4i64 : PatFrag<(ops node:$ptr), (v4i64 (vecload node:$ptr))>; - -// 512-bit load pattern fragments -def loadv16f32 : PatFrag<(ops node:$ptr), (v16f32 (vecload node:$ptr))>; -def loadv8f64 : PatFrag<(ops node:$ptr), (v8f64 (vecload node:$ptr))>; -def loadv8i64 : PatFrag<(ops node:$ptr), (v8i64 (vecload node:$ptr))>; - -// 128-/256-/512-bit extload pattern fragments -def extloadv2f32 : PatFrag<(ops node:$ptr), (v2f64 (extloadvf32 node:$ptr))>; -def extloadv4f32 : PatFrag<(ops node:$ptr), (v4f64 (extloadvf32 node:$ptr))>; -def extloadv8f32 : PatFrag<(ops node:$ptr), (v8f64 (extloadvf32 node:$ptr))>; - -// Like 'store', but always requires vector size alignment. -def alignedstore : PatFrag<(ops node:$val, node:$ptr), - (store node:$val, node:$ptr), [{ - auto *St = cast(N); - return St->getAlignment() >= St->getMemoryVT().getStoreSize(); -}]>; - -// Like 'load', but always requires 128-bit vector alignment. -def alignedvecload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - auto *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize() && - !useNonTemporalLoad(cast(N)); -}]>; - -// 128-bit aligned load pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def alignedloadv4f32 : PatFrag<(ops node:$ptr), - (v4f32 (alignedvecload node:$ptr))>; -def alignedloadv2f64 : PatFrag<(ops node:$ptr), - (v2f64 (alignedvecload node:$ptr))>; -def alignedloadv2i64 : PatFrag<(ops node:$ptr), - (v2i64 (alignedvecload node:$ptr))>; - -// 256-bit aligned load pattern fragments -// NOTE: all 256-bit integer vector loads are promoted to v4i64 -def alignedloadv8f32 : PatFrag<(ops node:$ptr), - (v8f32 (alignedvecload node:$ptr))>; -def alignedloadv4f64 : PatFrag<(ops node:$ptr), - (v4f64 (alignedvecload node:$ptr))>; -def alignedloadv4i64 : PatFrag<(ops node:$ptr), - (v4i64 (alignedvecload node:$ptr))>; - -// 512-bit aligned load pattern fragments -def alignedloadv16f32 : PatFrag<(ops node:$ptr), - (v16f32 (alignedvecload node:$ptr))>; -def alignedloadv8f64 : PatFrag<(ops node:$ptr), - (v8f64 (alignedvecload node:$ptr))>; -def alignedloadv8i64 : PatFrag<(ops node:$ptr), - (v8i64 (alignedvecload node:$ptr))>; - -// Like 'vecload', but uses special alignment checks suitable for use in -// memory operands in most SSE instructions, which are required to -// be naturally aligned on some targets but not on others. If the subtarget -// allows unaligned accesses, match any load, though this may require -// setting a feature bit in the processor (on startup, for example). -// Opteron 10h and later implement such a feature. -def memop : PatFrag<(ops node:$ptr), (vecload node:$ptr), [{ - auto *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -// 128-bit memop pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def memopv4f32 : PatFrag<(ops node:$ptr), (v4f32 (memop node:$ptr))>; -def memopv2f64 : PatFrag<(ops node:$ptr), (v2f64 (memop node:$ptr))>; -def memopv2i64 : PatFrag<(ops node:$ptr), (v2i64 (memop node:$ptr))>; - -def X86masked_gather : SDNode<"X86ISD::MGATHER", - SDTypeProfile<2, 3, [SDTCisVec<0>, - SDTCisVec<1>, SDTCisInt<1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<1, 3>, - SDTCisPtrTy<4>]>, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; - -def X86masked_scatter : SDNode<"X86ISD::MSCATTER", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<0, 2>, - SDTCVecEltisVT<0, i1>, - SDTCisPtrTy<3>]>, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def mgatherv4i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v4i32; -}]>; - -def mgatherv8i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v8i32; -}]>; - -def mgatherv2i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v2i64; -}]>; -def mgatherv4i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v4i64; -}]>; -def mgatherv8i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v8i64; -}]>; -def mgatherv16i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v16i32; -}]>; - -def mscatterv2i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v2i64; -}]>; - -def mscatterv4i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v4i32; -}]>; - -def mscatterv4i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v4i64; -}]>; - -def mscatterv8i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v8i32; -}]>; - -def mscatterv8i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v8i64; -}]>; -def mscatterv16i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v16i32; -}]>; - -// 128-bit bitconvert pattern fragments -def bc_v4f32 : PatFrag<(ops node:$in), (v4f32 (bitconvert node:$in))>; -def bc_v2f64 : PatFrag<(ops node:$in), (v2f64 (bitconvert node:$in))>; -def bc_v16i8 : PatFrag<(ops node:$in), (v16i8 (bitconvert node:$in))>; -def bc_v8i16 : PatFrag<(ops node:$in), (v8i16 (bitconvert node:$in))>; -def bc_v4i32 : PatFrag<(ops node:$in), (v4i32 (bitconvert node:$in))>; -def bc_v2i64 : PatFrag<(ops node:$in), (v2i64 (bitconvert node:$in))>; - -// 256-bit bitconvert pattern fragments -def bc_v32i8 : PatFrag<(ops node:$in), (v32i8 (bitconvert node:$in))>; -def bc_v16i16 : PatFrag<(ops node:$in), (v16i16 (bitconvert node:$in))>; -def bc_v8i32 : PatFrag<(ops node:$in), (v8i32 (bitconvert node:$in))>; -def bc_v4i64 : PatFrag<(ops node:$in), (v4i64 (bitconvert node:$in))>; -def bc_v8f32 : PatFrag<(ops node:$in), (v8f32 (bitconvert node:$in))>; -def bc_v4f64 : PatFrag<(ops node:$in), (v4f64 (bitconvert node:$in))>; - -// 512-bit bitconvert pattern fragments -def bc_v64i8 : PatFrag<(ops node:$in), (v64i8 (bitconvert node:$in))>; -def bc_v16i32 : PatFrag<(ops node:$in), (v16i32 (bitconvert node:$in))>; -def bc_v8i64 : PatFrag<(ops node:$in), (v8i64 (bitconvert node:$in))>; -def bc_v8f64 : PatFrag<(ops node:$in), (v8f64 (bitconvert node:$in))>; -def bc_v16f32 : PatFrag<(ops node:$in), (v16f32 (bitconvert node:$in))>; - -def vzmovl_v2i64 : PatFrag<(ops node:$src), - (bitconvert (v2i64 (X86vzmovl - (v2i64 (scalar_to_vector (loadi64 node:$src))))))>; -def vzmovl_v4i32 : PatFrag<(ops node:$src), - (bitconvert (v4i32 (X86vzmovl - (v4i32 (scalar_to_vector (loadi32 node:$src))))))>; - -def vzload_v2i64 : PatFrag<(ops node:$src), - (bitconvert (v2i64 (X86vzload node:$src)))>; - - -def fp32imm0 : PatLeaf<(f32 fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def fp64imm0 : PatLeaf<(f64 fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def I8Imm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def FROUND_NO_EXC : PatLeaf<(i32 8)>; -def FROUND_CURRENT : PatLeaf<(i32 4)>; - -// BYTE_imm - Transform bit immediates into byte immediates. -def BYTE_imm : SDNodeXForm> 3 - return getI32Imm(N->getZExtValue() >> 3, SDLoc(N)); -}]>; - -// EXTRACT_get_vextract128_imm xform function: convert extract_subvector index -// to VEXTRACTF128/VEXTRACTI128 imm. -def EXTRACT_get_vextract128_imm : SDNodeXForm; - -// INSERT_get_vinsert128_imm xform function: convert insert_subvector index to -// VINSERTF128/VINSERTI128 imm. -def INSERT_get_vinsert128_imm : SDNodeXForm; - -// EXTRACT_get_vextract256_imm xform function: convert extract_subvector index -// to VEXTRACTF64x4 imm. -def EXTRACT_get_vextract256_imm : SDNodeXForm; - -// INSERT_get_vinsert256_imm xform function: convert insert_subvector index to -// VINSERTF64x4 imm. -def INSERT_get_vinsert256_imm : SDNodeXForm; - -def vextract128_extract : PatFrag<(ops node:$bigvec, node:$index), - (extract_subvector node:$bigvec, - node:$index), [{}], - EXTRACT_get_vextract128_imm>; - -def vinsert128_insert : PatFrag<(ops node:$bigvec, node:$smallvec, - node:$index), - (insert_subvector node:$bigvec, node:$smallvec, - node:$index), [{}], - INSERT_get_vinsert128_imm>; - -def vextract256_extract : PatFrag<(ops node:$bigvec, node:$index), - (extract_subvector node:$bigvec, - node:$index), [{}], - EXTRACT_get_vextract256_imm>; - -def vinsert256_insert : PatFrag<(ops node:$bigvec, node:$smallvec, - node:$index), - (insert_subvector node:$bigvec, node:$smallvec, - node:$index), [{}], - INSERT_get_vinsert256_imm>; - -def X86mload : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return !cast(N)->isExpandingLoad() && - cast(N)->getExtensionType() == ISD::NON_EXTLOAD; -}]>; - -def masked_load_aligned128 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 16; -}]>; - -def masked_load_aligned256 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 32; -}]>; - -def masked_load_aligned512 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 64; -}]>; - -def masked_load_unaligned : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return !cast(N)->isExpandingLoad() && - cast(N)->getExtensionType() == ISD::NON_EXTLOAD; -}]>; - -def X86mExpandingLoad : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isExpandingLoad(); -}]>; - -// Masked store fragments. -// X86mstore can't be implemented in core DAG files because some targets -// do not support vector types (llvm-tblgen will fail). -def X86mstore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return (!cast(N)->isTruncatingStore()) && - (!cast(N)->isCompressingStore()); -}]>; - -def masked_store_aligned128 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 16; -}]>; - -def masked_store_aligned256 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 32; -}]>; - -def masked_store_aligned512 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 64; -}]>; - -def masked_store_unaligned : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return (!cast(N)->isTruncatingStore()) && - (!cast(N)->isCompressingStore()); -}]>; - -def X86mCompressingStore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isCompressingStore(); -}]>; - -// masked truncstore fragments -// X86mtruncstore can't be implemented in core DAG files because some targets -// doesn't support vector type ( llvm-tblgen will fail) -def X86mtruncstore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isTruncatingStore(); -}]>; -def masked_truncstorevi8 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; -def masked_truncstorevi16 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; -def masked_truncstorevi32 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def X86TruncSStore : SDNode<"X86ISD::VTRUNCSTORES", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86TruncUSStore : SDNode<"X86ISD::VTRUNCSTOREUS", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86MTruncSStore : SDNode<"X86ISD::VMTRUNCSTORES", SDTMaskedStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86MTruncUSStore : SDNode<"X86ISD::VMTRUNCSTOREUS", SDTMaskedStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def truncstore_s_vi8 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def truncstore_us_vi8 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def truncstore_s_vi16 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def truncstore_us_vi16 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def truncstore_s_vi32 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def truncstore_us_vi32 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def masked_truncstore_s_vi8 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def masked_truncstore_us_vi8 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def masked_truncstore_s_vi16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def masked_truncstore_us_vi16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def masked_truncstore_s_vi32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def masked_truncstore_us_vi32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; diff --git a/suite/synctools/tablegen/X86/X86InstrInfo.td b/suite/synctools/tablegen/X86/X86InstrInfo.td deleted file mode 100644 index 56927c8945..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrInfo.td +++ /dev/null @@ -1,3582 +0,0 @@ -//===-- X86InstrInfo.td - Main X86 Instruction Definition --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instruction set, defining the instructions, and -// properties of the instructions which are needed for code generation, machine -// code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 specific DAG Nodes. -// - -def SDTIntShiftDOp: SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisInt<3>]>; - -def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<1, 2>]>; - -def SDTX86Cmps : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; -//def SDTX86Cmpss : SDTypeProfile<1, 3, [SDTCisVT<0, f32>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; - -def SDTX86Cmov : SDTypeProfile<1, 4, - [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -// Unary and binary operator instructions that set EFLAGS as a side-effect. -def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, - [SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS -def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<4, i32>]>; -// RES1, RES2, FLAGS = op LHS, RHS -def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; -def SDTX86BrCond : SDTypeProfile<0, 3, - [SDTCisVT<0, OtherVT>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86SetCC : SDTypeProfile<1, 2, - [SDTCisVT<0, i8>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; -def SDTX86SetCC_C : SDTypeProfile<1, 2, - [SDTCisInt<0>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; - -def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, - SDTCisVT<2, i8>]>; -def SDTX86caspair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86caspairSaveEbx8 : SDTypeProfile<1, 3, - [SDTCisVT<0, i32>, SDTCisPtrTy<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; -def SDTX86caspairSaveRbx16 : SDTypeProfile<1, 3, - [SDTCisVT<0, i64>, SDTCisPtrTy<1>, - SDTCisVT<2, i64>, SDTCisVT<3, i64>]>; - -def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, - SDTCisInt<2>]>; - -def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>]>; - -def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; - -def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; -def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; - -def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, - SDTCisVT<1, iPTR>, - SDTCisVT<2, iPTR>]>; - -def SDT_X86VAARG_64 : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; - -def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; - -def SDTX86Void : SDTypeProfile<0, 0, []>; - -def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - -def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86WIN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; - -def SDT_X86MEMBARRIER : SDTypeProfile<0, 0, []>; - -def X86MemBarrier : SDNode<"X86ISD::MEMBARRIER", SDT_X86MEMBARRIER, - [SDNPHasChain,SDNPSideEffect]>; -def X86MFence : SDNode<"X86ISD::MFENCE", SDT_X86MEMBARRIER, - [SDNPHasChain]>; - - -def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; -def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; -def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; -def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; - -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; -def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; - -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, - [SDNPHasChain]>; -def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; - -def X86sahf : SDNode<"X86ISD::SAHF", SDTX86sahf>; - -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8save_ebx : SDNode<"X86ISD::LCMPXCHG8_SAVE_EBX_DAG", - SDTX86caspairSaveEbx8, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def X86cas16save_rbx : SDNode<"X86ISD::LCMPXCHG16_SAVE_RBX_DAG", - SDTX86caspairSaveRbx16, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; - -def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue]>; - -def X86vastart_save_xmm_regs : - SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", - SDT_X86VASTART_SAVE_XMM_REGS, - [SDNPHasChain, SDNPVariadic]>; -def X86vaarg64 : - SDNode<"X86ISD::VAARG_64", SDT_X86VAARG_64, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86callseq_start : - SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def X86callseq_end : - SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; -def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, - [SDNPHasChain]>; - -def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; -def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad]>; - -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdtscp : SDNode<"X86ISD::RDTSCP_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdpmc : SDNode<"X86ISD::RDPMC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; - -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; -def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; - -def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", - SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, - SDTCisInt<1>]>>; - -def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, - [SDNPHasChain]>; - -def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", - SDTypeProfile<1, 1, [SDTCisInt<0>, - SDTCisPtrTy<1>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", - SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", - SDTypeProfile<0, 0, []>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; -def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, - [SDNPCommutative]>; -def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; -def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; - -def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>; -def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>; -def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, - [SDNPCommutative]>; - -def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86lock_inc : SDNode<"X86ISD::LINC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_dec : SDNode<"X86ISD::LDEC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; - -def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; - -def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA, - [SDNPHasChain, SDNPOutGlue]>; - -def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, - [SDNPHasChain]>; - -def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86lwpins : SDNode<"X86ISD::LWPINS", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; - -def X86umwait : SDNode<"X86ISD::UMWAIT", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tpause : SDNode<"X86ISD::TPAUSE", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -//===----------------------------------------------------------------------===// -// X86 Operand Definitions. -// - -// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for -// the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; - -// *mem - Operand definitions for the funky X86 addressing mode operands. -// -def X86MemAsmOperand : AsmOperandClass { - let Name = "Mem"; -} -let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { - def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } - def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } - def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } - def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } - def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } - def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } - def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } - def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } - // Gather mem operands - def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } - def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } - def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } - def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } - def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } - - def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } - def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } - def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } - def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } - def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } - def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } - def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } - def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } -} - -def X86AbsMemAsmOperand : AsmOperandClass { - let Name = "AbsMem"; - let SuperClasses = [X86MemAsmOperand]; -} - -class X86MemOperand : Operand { - let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = parserMatchClass; - let OperandType = "OPERAND_MEMORY"; -} - -// Gather mem operands -class X86VMemOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); -} - -def anymem : X86MemOperand<"printanymem">; - -// FIXME: Right now we allow any size during parsing, but we might want to -// restrict to only unsized memory. -def opaquemem : X86MemOperand<"printopaquemem">; - -def i8mem : X86MemOperand<"printi8mem", X86Mem8AsmOperand>; -def i16mem : X86MemOperand<"printi16mem", X86Mem16AsmOperand>; -def i32mem : X86MemOperand<"printi32mem", X86Mem32AsmOperand>; -def i64mem : X86MemOperand<"printi64mem", X86Mem64AsmOperand>; -def i128mem : X86MemOperand<"printi128mem", X86Mem128AsmOperand>; -def i256mem : X86MemOperand<"printi256mem", X86Mem256AsmOperand>; -def i512mem : X86MemOperand<"printi512mem", X86Mem512AsmOperand>; -def f32mem : X86MemOperand<"printf32mem", X86Mem32AsmOperand>; -def f64mem : X86MemOperand<"printf64mem", X86Mem64AsmOperand>; -def f80mem : X86MemOperand<"printf80mem", X86Mem80AsmOperand>; -def f128mem : X86MemOperand<"printf128mem", X86Mem128AsmOperand>; -def f256mem : X86MemOperand<"printf256mem", X86Mem256AsmOperand>; -def f512mem : X86MemOperand<"printf512mem", X86Mem512AsmOperand>; - -def v512mem : X86VMemOperand; - -// Gather mem operands -def vx64mem : X86VMemOperand; -def vx128mem : X86VMemOperand; -def vx256mem : X86VMemOperand; -def vy128mem : X86VMemOperand; -def vy256mem : X86VMemOperand; - -def vx64xmem : X86VMemOperand; -def vx128xmem : X86VMemOperand; -def vx256xmem : X86VMemOperand; -def vy128xmem : X86VMemOperand; -def vy256xmem : X86VMemOperand; -def vy512xmem : X86VMemOperand; -def vz256mem : X86VMemOperand; -def vz512mem : X86VMemOperand; - -// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead -// of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; - -def i8mem_NOREX : Operand { - let PrintMethod = "printi8mem"; - let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, - SEGMENT_REG); - let ParserMatchClass = X86Mem8AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// GPRs available for tailcall. -// It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; - -// Special i32mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i32mem_TC : Operand { - let PrintMethod = "printi32mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, - i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// Special i64mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i64mem_TC : Operand { - let PrintMethod = "printi64mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, - ptr_rc_tailcall, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -let OperandType = "OPERAND_PCREL", - ParserMatchClass = X86AbsMemAsmOperand, - PrintMethod = "printPCRelImm" in { -def i32imm_pcrel : Operand; -def i16imm_pcrel : Operand; - -// Branch targets have OtherVT type and print as pc-relative values. -def brtarget : Operand; -def brtarget8 : Operand; - -} - -// Special parser to detect 16-bit mode to select 16-bit displacement. -def X86AbsMem16AsmOperand : AsmOperandClass { - let Name = "AbsMem16"; - let RenderMethod = "addAbsMemOperands"; - let SuperClasses = [X86AbsMemAsmOperand]; -} - -// Branch targets have OtherVT type and print as pc-relative values. -let OperandType = "OPERAND_PCREL", - PrintMethod = "printPCRelImm" in { -let ParserMatchClass = X86AbsMem16AsmOperand in - def brtarget16 : Operand; -let ParserMatchClass = X86AbsMemAsmOperand in - def brtarget32 : Operand; -} - -let RenderMethod = "addSrcIdxOperands" in { - def X86SrcIdx8Operand : AsmOperandClass { - let Name = "SrcIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86SrcIdx16Operand : AsmOperandClass { - let Name = "SrcIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86SrcIdx32Operand : AsmOperandClass { - let Name = "SrcIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86SrcIdx64Operand : AsmOperandClass { - let Name = "SrcIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addSrcIdxOperands" - -let RenderMethod = "addDstIdxOperands" in { - def X86DstIdx8Operand : AsmOperandClass { - let Name = "DstIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86DstIdx16Operand : AsmOperandClass { - let Name = "DstIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86DstIdx32Operand : AsmOperandClass { - let Name = "DstIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86DstIdx64Operand : AsmOperandClass { - let Name = "DstIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addDstIdxOperands" - -let RenderMethod = "addMemOffsOperands" in { - def X86MemOffs16_8AsmOperand : AsmOperandClass { - let Name = "MemOffs16_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs16_16AsmOperand : AsmOperandClass { - let Name = "MemOffs16_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs16_32AsmOperand : AsmOperandClass { - let Name = "MemOffs16_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_8AsmOperand : AsmOperandClass { - let Name = "MemOffs32_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs32_16AsmOperand : AsmOperandClass { - let Name = "MemOffs32_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs32_32AsmOperand : AsmOperandClass { - let Name = "MemOffs32_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_64AsmOperand : AsmOperandClass { - let Name = "MemOffs32_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } - def X86MemOffs64_8AsmOperand : AsmOperandClass { - let Name = "MemOffs64_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs64_16AsmOperand : AsmOperandClass { - let Name = "MemOffs64_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs64_32AsmOperand : AsmOperandClass { - let Name = "MemOffs64_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs64_64AsmOperand : AsmOperandClass { - let Name = "MemOffs64_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addMemOffsOperands" - -class X86SrcIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); -} - -class X86DstIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc); -} - -def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; -def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; -def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; -def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; -def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; -def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; -def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; -def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; - -class X86MemOffsOperand - : X86MemOperand { - let MIOperandInfo = (ops immOperand, SEGMENT_REG); -} - -def offset16_8 : X86MemOffsOperand; -def offset16_16 : X86MemOffsOperand; -def offset16_32 : X86MemOffsOperand; -def offset32_8 : X86MemOffsOperand; -def offset32_16 : X86MemOffsOperand; -def offset32_32 : X86MemOffsOperand; -def offset32_64 : X86MemOffsOperand; -def offset64_8 : X86MemOffsOperand; -def offset64_16 : X86MemOffsOperand; -def offset64_32 : X86MemOffsOperand; -def offset64_64 : X86MemOffsOperand; - -def SSECC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVXCC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVX512ICC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def XOPCC : Operand { - let PrintMethod = "printXOPCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -class ImmSExtAsmOperandClass : AsmOperandClass { - let SuperClasses = [ImmAsmOperand]; - let RenderMethod = "addImmOperands"; -} - -def X86GR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR32orGR64"; -} - -def GR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR32orGR64AsmOperand; -} -def AVX512RCOperand : AsmOperandClass { - let Name = "AVX512RC"; -} -def AVX512RC : Operand { - let PrintMethod = "printRoundingControl"; - let OperandType = "OPERAND_IMMEDIATE"; - let ParserMatchClass = AVX512RCOperand; -} - -// Sign-extended immediate classes. We don't need to define the full lattice -// here because there is no instruction with an ambiguity between ImmSExti64i32 -// and ImmSExti32i8. -// -// The strange ranges come from the fact that the assembler always works with -// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" -// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). - -// [0, 0x7FFFFFFF] | -// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i32"; -} - -// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti16i8"; - let SuperClasses = [ImmSExti64i32AsmOperand]; -} - -// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti32i8"; -} - -// [0, 0x0000007F] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i8"; - let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, - ImmSExti64i32AsmOperand]; -} - -// Unsigned immediate used by SSE/AVX instructions -// [0, 0xFF] -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmUnsignedi8AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi8"; - let RenderMethod = "addImmOperands"; -} - -// A couple of more descriptive operand definitions. -// 16-bits but only 8 bits are significant. -def i16i8imm : Operand { - let ParserMatchClass = ImmSExti16i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} -// 32-bits but only 8 bits are significant. -def i32i8imm : Operand { - let ParserMatchClass = ImmSExti32i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant. -def i64i32imm : Operand { - let ParserMatchClass = ImmSExti64i32AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 8 bits are significant. -def i64i8imm : Operand { - let ParserMatchClass = ImmSExti64i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 8-bit immediate used by SSE/AVX instructions. -def u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 32-bit immediate but only 8-bits are significant and they are unsigned. -// Used by some SSE/AVX instructions that use intrinsics. -def i32u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant, and those bits are treated as being -// pc relative. -def i64i32imm_pcrel : Operand { - let PrintMethod = "printPCRelImm"; - let ParserMatchClass = X86AbsMemAsmOperand; - let OperandType = "OPERAND_PCREL"; -} - -def lea64_32mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -// Memory operands that use 64-bit pointers in both ILP32 and LP64. -def lea64mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - - -//===----------------------------------------------------------------------===// -// X86 Complex Pattern Definitions. -// - -// Define X86-specific addressing mode. -def addr : ComplexPattern; -def lea32addr : ComplexPattern; -// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. -def lea64_32addr : ComplexPattern; - -def tls32addr : ComplexPattern; - -def tls32baseaddr : ComplexPattern; - -def lea64addr : ComplexPattern; - -def tls64addr : ComplexPattern; - -def tls64baseaddr : ComplexPattern; - -def vectoraddr : ComplexPattern; - -// A relocatable immediate is either an immediate operand or an operand that can -// be relocated by the linker to an immediate, such as a regular symbol in -// non-PIC code. -def relocImm : ComplexPattern; - -//===----------------------------------------------------------------------===// -// X86 Instruction Predicate Definitions. -def TruePredicate : Predicate<"true">; - -def HasCMov : Predicate<"Subtarget->hasCMov()">; -def NoCMov : Predicate<"!Subtarget->hasCMov()">; - -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def Has3DNow : Predicate<"Subtarget->has3DNow()">; -def Has3DNowA : Predicate<"Subtarget->has3DNowA()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; -def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; -def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; -def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; -def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; -def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; -def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; -def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; -def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; -def NoAVX : Predicate<"!Subtarget->hasAVX()">; -def HasAVX : Predicate<"Subtarget->hasAVX()">; -def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; -def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; -def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; -def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; -def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; -def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; -def HasCDI : Predicate<"Subtarget->hasCDI()">; -def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; -def HasPFI : Predicate<"Subtarget->hasPFI()">; -def HasERI : Predicate<"Subtarget->hasERI()">; -def HasDQI : Predicate<"Subtarget->hasDQI()">; -def NoDQI : Predicate<"!Subtarget->hasDQI()">; -def HasBWI : Predicate<"Subtarget->hasBWI()">; -def NoBWI : Predicate<"!Subtarget->hasBWI()">; -def HasVLX : Predicate<"Subtarget->hasVLX()">; -def NoVLX : Predicate<"!Subtarget->hasVLX()">; -def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; -def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; -def PKU : Predicate<"Subtarget->hasPKU()">; -def HasVNNI : Predicate<"Subtarget->hasVNNI()">; - -def HasBITALG : Predicate<"Subtarget->hasBITALG()">; -def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; -def HasAES : Predicate<"Subtarget->hasAES()">; -def HasVAES : Predicate<"Subtarget->hasVAES()">; -def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; -def HasFXSR : Predicate<"Subtarget->hasFXSR()">; -def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; -def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; -def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; -def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; -def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; -def NoVLX_Or_NoVPCLMULQDQ : - Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; -def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; -def HasGFNI : Predicate<"Subtarget->hasGFNI()">; -def HasFMA : Predicate<"Subtarget->hasFMA()">; -def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; -def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; -def HasXOP : Predicate<"Subtarget->hasXOP()">; -def HasTBM : Predicate<"Subtarget->hasTBM()">; -def NoTBM : Predicate<"!Subtarget->hasTBM()">; -def HasLWP : Predicate<"Subtarget->hasLWP()">; -def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; -def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; -def HasF16C : Predicate<"Subtarget->hasF16C()">; -def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; -def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; -def HasBMI : Predicate<"Subtarget->hasBMI()">; -def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; -def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; -def HasVBMI : Predicate<"Subtarget->hasVBMI()">; -def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; -def HasIFMA : Predicate<"Subtarget->hasIFMA()">; -def HasRTM : Predicate<"Subtarget->hasRTM()">; -def HasADX : Predicate<"Subtarget->hasADX()">; -def HasSHA : Predicate<"Subtarget->hasSHA()">; -def HasSGX : Predicate<"Subtarget->hasSGX()">; -def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; -def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; -def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; -def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; -def HasPrefetchW : Predicate<"Subtarget->hasPRFCHW()">; -def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; -def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; -def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; -def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; -def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; -def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; -def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; -def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; -def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; -def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; -def HasMPX : Predicate<"Subtarget->hasMPX()">; -def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; -def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; -def HasCLWB : Predicate<"Subtarget->hasCLWB()">; -def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; -def HasRDPID : Predicate<"Subtarget->hasRDPID()">; -def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; -def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; -def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; -def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; -def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, - AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, - AssemblerPredicate<"Mode64Bit", "64-bit mode">; -def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; -def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; -def In16BitMode : Predicate<"Subtarget->is16Bit()">, - AssemblerPredicate<"Mode16Bit", "16-bit mode">; -def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, - AssemblerPredicate<"!Mode16Bit", "Not 16-bit mode">; -def In32BitMode : Predicate<"Subtarget->is32Bit()">, - AssemblerPredicate<"Mode32Bit", "32-bit mode">; -def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; -def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; -def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" - "Subtarget->getFrameLowering()->hasFP(*MF)"> { - let RecomputePerFunction = 1; -} -def IsPS4 : Predicate<"Subtarget->isTargetPS4()">; -def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">; -def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; -def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; -def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; -def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" - "TM.getCodeModel() == CodeModel::Kernel">; -def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; - -// We could compute these on a per-module basis but doing so requires accessing -// the Function object through the Subtarget and objections were raised -// to that (see post-commit review comments for r301750). -let RecomputePerFunction = 1 in { - def OptForSize : Predicate<"MF->getFunction().optForSize()">; - def OptForMinSize : Predicate<"MF->getFunction().optForMinSize()">; - def OptForSpeed : Predicate<"!MF->getFunction().optForSize()">; - def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " - "MF->getFunction().optForSize()">; - def NoSSE41_Or_OptForSize : Predicate<"MF->getFunction().optForSize() || " - "!Subtarget->hasSSE41()">; -} - -def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; -def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; -def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; -def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; -def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; -def HasERMSB : Predicate<"Subtarget->hasERMSB()">; -def HasMFence : Predicate<"Subtarget->hasMFence()">; -def UseRetpoline : Predicate<"Subtarget->useRetpoline()">; -def NotUseRetpoline : Predicate<"!Subtarget->useRetpoline()">; - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -include "X86InstrFormats.td" - -//===----------------------------------------------------------------------===// -// Pattern fragments. -// - -// X86 specific condition code. These correspond to CondCode in -// X86InstrInfo.h. They must be kept in synch. -def X86_COND_A : PatLeaf<(i8 0)>; // alt. COND_NBE -def X86_COND_AE : PatLeaf<(i8 1)>; // alt. COND_NC -def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C -def X86_COND_BE : PatLeaf<(i8 3)>; // alt. COND_NA -def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z -def X86_COND_G : PatLeaf<(i8 5)>; // alt. COND_NLE -def X86_COND_GE : PatLeaf<(i8 6)>; // alt. COND_NL -def X86_COND_L : PatLeaf<(i8 7)>; // alt. COND_NGE -def X86_COND_LE : PatLeaf<(i8 8)>; // alt. COND_NG -def X86_COND_NE : PatLeaf<(i8 9)>; // alt. COND_NZ -def X86_COND_NO : PatLeaf<(i8 10)>; -def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO -def X86_COND_NS : PatLeaf<(i8 12)>; -def X86_COND_O : PatLeaf<(i8 13)>; -def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE -def X86_COND_S : PatLeaf<(i8 15)>; - -def i16immSExt8 : ImmLeaf(Imm); }]>; -def i32immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt32 : ImmLeaf(Imm); }]>; - -// FIXME: Ideally we would just replace the above i*immSExt* matchers with -// relocImm-based matchers, but then FastISel would be unable to use them. -def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<8>(N); -}]>; -def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<32>(N); -}]>; - -// If we have multiple users of an immediate, it's much smaller to reuse -// the register, rather than encode the immediate in every instruction. -// This has the risk of increasing register pressure from stretched live -// ranges, however, the immediates should be trivial to rematerialize by -// the RA in the event of high register pressure. -// TODO : This is currently enabled for stores and binary ops. There are more -// cases for which this can be enabled, though this catches the bulk of the -// issues. -// TODO2 : This should really also be enabled under O2, but there's currently -// an issue with RA where we don't pull the constants into their users -// when we rematerialize them. I'll follow-up on enabling O2 after we fix that -// issue. -// TODO3 : This is currently limited to single basic blocks (DAG creation -// pulls block immediates to the top and merges them if necessary). -// Eventually, it would be nice to allow ConstantHoisting to merge constants -// globally for potentially added savings. -// -def imm8_su : PatLeaf<(i8 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm16_su : PatLeaf<(i16 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm32_su : PatLeaf<(i32 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit -// unsigned field. -def i64immZExt32 : ImmLeaf(Imm); }]>; - -def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); -}]>; - -// Helper fragments for loads. - -// It's safe to fold a zextload/extload from i1 as a regular i8 load. The -// upper bits are guaranteed to be zero and we were going to emit a MOV8rm -// which might get folded during peephole anyway. -def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || - ExtType == ISD::ZEXTLOAD; -}]>; - -// It's always safe to treat a anyext i16 load as a i32 load if the i16 is -// known to be 32-bit aligned or better. Ditto for i8 to i16. -def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 2 && !LD->isVolatile(); - return false; -}]>; - -def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 4 && !LD->isVolatile(); - return false; -}]>; - -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; -def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; -def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; -def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; -def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; -def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; -def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; -def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; -def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; - -def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; -def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; -def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; -def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; -def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; -def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; -def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; -def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; -def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; -def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; - -def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; -def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; -def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; -def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; -def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>; - - -// An 'and' node with a single use. -def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'srl' node with a single use. -def srl_su : PatFrag<(ops node:$lhs, node:$rhs), (srl node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'trunc' node with a single use. -def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ - return N->hasOneUse(); -}]>; - -//===----------------------------------------------------------------------===// -// Instruction list. -// - -// Nop -let hasSideEffects = 0, SchedRW = [WriteNop] in { - def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; - def NOOPW : I<0x1f, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPL : I<0x1f, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQ : RI<0x1f, MRMXm, (outs), (ins i64mem:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - // Also allow register so we can assemble/disassemble - def NOOPWr : I<0x1f, MRMXr, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPLr : I<0x1f, MRMXr, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQr : RI<0x1f, MRMXr, (outs), (ins GR64:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - def NOOPW_19 : I<0x19, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_19 : I<0x19, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1a : I<0x1a, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1a : I<0x1a, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1b : I<0x1b, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1b : I<0x1b, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1c : I<0x1c, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1c : I<0x1c, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1d : I<0x1d, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1d : I<0x1d, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1e : I<0x1e, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1e : I<0x1e, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m4 : I<0x18, MRM4m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m4 : I<0x18, MRM4m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r4 : I<0x18, MRM4r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r4 : I<0x18, MRM4r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m5 : I<0x18, MRM5m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m5 : I<0x18, MRM5m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r5 : I<0x18, MRM5r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r5 : I<0x18, MRM5r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m6 : I<0x18, MRM6m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m6 : I<0x18, MRM6m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r6 : I<0x18, MRM6r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r6 : I<0x18, MRM6r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m7 : I<0x18, MRM7m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m7 : I<0x18, MRM7m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r7 : I<0x18, MRM7r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r7 : I<0x18, MRM7r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; -} - - -// Constructing a stack frame. -def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl), - "enter\t$len, $lvl", []>, Sched<[WriteMicrocoded]>; - -let SchedRW = [WriteALU] in { -let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, hasSideEffects=0 in -def LEAVE : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[Not64BitMode]>; - -let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, hasSideEffects = 0 in -def LEAVE64 : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Miscellaneous Instructions. -// - -/* -let isBarrier = 1, hasSideEffects = 1, usesCustomInserter = 1, - SchedRW = [WriteSystem] in - def Int_eh_sjlj_setup_dispatch - : PseudoI<(outs), (ins), [(X86eh_sjlj_setup_dispatch)]>; -*/ - -let Defs = [ESP], Uses = [ESP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP16r : I<0x58, AddRegFrm, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16; -def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP16rmr: I<0x8F, MRM0r, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16, NotMemoryFoldable; -def POP32rmr: I<0x8F, MRM0r, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayStore = 1, mayLoad = 1, SchedRW = [WriteRMW] in { -def POP16rmm: I<0x8F, MRM0m, (outs), (ins i16mem:$dst), "pop{w}\t$dst", []>, - OpSize16; -def POP32rmm: I<0x8F, MRM0m, (outs), (ins i32mem:$dst), "pop{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayStore, mayLoad, WriteRMW - -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH16r : I<0x50, AddRegFrm, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16; -def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH16rmr: I<0xFF, MRM6r, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16, NotMemoryFoldable; -def PUSH32rmr: I<0xFF, MRM6r, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 - -def PUSH16i8 : Ii8<0x6a, RawFrm, (outs), (ins i16i8imm:$imm), - "push{w}\t$imm", []>, OpSize16; -def PUSHi16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), - "push{w}\t$imm", []>, OpSize16; - -def PUSH32i8 : Ii8<0x6a, RawFrm, (outs), (ins i32i8imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -def PUSHi32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -} // mayStore, SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH16rmm: I<0xFF, MRM6m, (outs), (ins i16mem:$src), "push{w}\t$src", []>, - OpSize16; -def PUSH32rmm: I<0xFF, MRM6m, (outs), (ins i32mem:$src), "push{l}\t$src", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayLoad, mayStore, SchedRW - -} - -/* -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW], Defs = [ESP] in { - let Uses = [ESP] in - def RDFLAGS32 : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_flags_read_u32))]>, - Requires<[Not64BitMode]>; - - let Uses = [RSP] in - def RDFLAGS64 : PseudoI<(outs GR64:$dst), (ins), - [(set GR64:$dst, (int_x86_flags_read_u64))]>, - Requires<[In64BitMode]>; -} - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW] in { - let Defs = [ESP, EFLAGS, DF], Uses = [ESP] in - def WRFLAGS32 : PseudoI<(outs), (ins GR32:$src), - [(int_x86_flags_write_u32 GR32:$src)]>, - Requires<[Not64BitMode]>; - - let Defs = [RSP, EFLAGS, DF], Uses = [RSP] in - def WRFLAGS64 : PseudoI<(outs), (ins GR64:$src), - [(int_x86_flags_write_u64 GR64:$src)]>, - Requires<[In64BitMode]>; -} -*/ - -let Defs = [ESP, EFLAGS, DF], Uses = [ESP], mayLoad = 1, hasSideEffects=0, - SchedRW = [WriteLoad] in { -def POPF16 : I<0x9D, RawFrm, (outs), (ins), "popf{w}", []>, OpSize16; -def POPF32 : I<0x9D, RawFrm, (outs), (ins), "popf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [ESP], Uses = [ESP, EFLAGS, DF], mayStore = 1, hasSideEffects=0, - SchedRW = [WriteStore] in { -def PUSHF16 : I<0x9C, RawFrm, (outs), (ins), "pushf{w}", []>, OpSize16; -def PUSHF32 : I<0x9C, RawFrm, (outs), (ins), "pushf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in -def POP64rmm: I<0x8F, MRM0m, (outs), (ins i64mem:$dst), "pop{q}\t$dst", []>, - OpSize32, Requires<[In64BitMode]>; -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayStore, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>, - OpSize32, Requires<[In64BitMode]>; -} // mayLoad, mayStore, SchedRW -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects = 0, mayStore = 1, - SchedRW = [WriteStore] in { -def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -def PUSH64i32 : Ii32S<0x68, RawFrm, (outs), (ins i64i32imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -} - -let Defs = [RSP, EFLAGS, DF], Uses = [RSP], mayLoad = 1, hasSideEffects=0 in -def POPF64 : I<0x9D, RawFrm, (outs), (ins), "popfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteLoad]>; -let Defs = [RSP], Uses = [RSP, EFLAGS, DF], mayStore = 1, hasSideEffects=0 in -def PUSHF64 : I<0x9C, RawFrm, (outs), (ins), "pushfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteStore]>; - -let Defs = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], Uses = [ESP], - mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteLoad] in { -def POPA32 : I<0x61, RawFrm, (outs), (ins), "popal", []>, - OpSize32, Requires<[Not64BitMode]>; -def POPA16 : I<0x61, RawFrm, (outs), (ins), "popaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} -let Defs = [ESP], Uses = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], - mayStore = 1, hasSideEffects = 0, SchedRW = [WriteStore] in { -def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pushal", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHA16 : I<0x60, RawFrm, (outs), (ins), "pushaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} - -let Constraints = "$src = $dst", SchedRW = [WriteBSWAP32] in { -// This instruction is a consequence of BSWAP32r observing operand size. The -// encoding is valid, but the behavior is undefined. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in -def BSWAP16r_BAD : I<0xC8, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "bswap{w}\t$dst", []>, OpSize16, TB; -// GR32 = bswap GR32 -def BSWAP32r : I<0xC8, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "bswap{l}\t$dst", - [(set GR32:$dst, (bswap GR32:$src))]>, OpSize32, TB; - -let SchedRW = [WriteBSWAP64] in -def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "bswap{q}\t$dst", - [(set GR64:$dst, (bswap GR64:$src))]>, TB; -} // Constraints = "$src = $dst", SchedRW - -// Bit scan instructions. -let Defs = [EFLAGS] in { -def BSF16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSF]>; -def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSFLd]>; -def BSF32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSF]>; -def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSFLd]>; -def BSF64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf GR64:$src))]>, - PS, Sched<[WriteBSF]>; -def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSFLd]>; - -def BSR16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSR]>; -def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSRLd]>; -def BSR32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSR]>; -def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSRLd]>; -def BSR64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr GR64:$src))]>, - PS, Sched<[WriteBSR]>; -def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSRLd]>; -} // Defs = [EFLAGS] - -let SchedRW = [WriteMicrocoded] in { -let Defs = [EDI,ESI], Uses = [EDI,ESI,DF] in { -def MOVSB : I<0xA4, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "movsb\t{$src, $dst|$dst, $src}", []>; -def MOVSW : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "movsw\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOVSL : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "movs{l|d}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOVSQ : RI<0xA5, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "movsq\t{$src, $dst|$dst, $src}", []>, - Requires<[In64BitMode]>; -} - -let Defs = [EDI], Uses = [AL,EDI,DF] in -def STOSB : I<0xAA, RawFrmDst, (outs), (ins dstidx8:$dst), - "stosb\t{%al, $dst|$dst, al}", []>; -let Defs = [EDI], Uses = [AX,EDI,DF] in -def STOSW : I<0xAB, RawFrmDst, (outs), (ins dstidx16:$dst), - "stosw\t{%ax, $dst|$dst, ax}", []>, OpSize16; -let Defs = [EDI], Uses = [EAX,EDI,DF] in -def STOSL : I<0xAB, RawFrmDst, (outs), (ins dstidx32:$dst), - "stos{l|d}\t{%eax, $dst|$dst, eax}", []>, OpSize32; -let Defs = [RDI], Uses = [RAX,RDI,DF] in -def STOSQ : RI<0xAB, RawFrmDst, (outs), (ins dstidx64:$dst), - "stosq\t{%rax, $dst|$dst, rax}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,EFLAGS], Uses = [AL,EDI,DF] in -def SCASB : I<0xAE, RawFrmDst, (outs), (ins dstidx8:$dst), - "scasb\t{$dst, %al|al, $dst}", []>; -let Defs = [EDI,EFLAGS], Uses = [AX,EDI,DF] in -def SCASW : I<0xAF, RawFrmDst, (outs), (ins dstidx16:$dst), - "scasw\t{$dst, %ax|ax, $dst}", []>, OpSize16; -let Defs = [EDI,EFLAGS], Uses = [EAX,EDI,DF] in -def SCASL : I<0xAF, RawFrmDst, (outs), (ins dstidx32:$dst), - "scas{l|d}\t{$dst, %eax|eax, $dst}", []>, OpSize32; -let Defs = [EDI,EFLAGS], Uses = [RAX,EDI,DF] in -def SCASQ : RI<0xAF, RawFrmDst, (outs), (ins dstidx64:$dst), - "scasq\t{$dst, %rax|rax, $dst}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,ESI,EFLAGS], Uses = [EDI,ESI,DF] in { -def CMPSB : I<0xA6, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "cmpsb\t{$dst, $src|$src, $dst}", []>; -def CMPSW : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "cmpsw\t{$dst, $src|$src, $dst}", []>, OpSize16; -def CMPSL : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "cmps{l|d}\t{$dst, $src|$src, $dst}", []>, OpSize32; -def CMPSQ : RI<0xA7, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "cmpsq\t{$dst, $src|$src, $dst}", []>, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Move Instructions. -// -let SchedRW = [WriteMove] in { -let hasSideEffects = 0, isMoveReg = 1 in { -def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>; -def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, imm:$src)]>, OpSize16; -def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, relocImm:$src)]>, OpSize32; -def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, i64immSExt32:$src)]>; -} -let isReMaterializable = 1 in { -def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), - "movabs{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, relocImm:$src)]>; -} - -// Longer forms that use a ModR/M byte. Needed for disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOV8ri_alt : Ii8 <0xC6, MRM0r, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8ri">; -def MOV16ri_alt : Ii16<0xC7, MRM0r, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16ri">; -def MOV32ri_alt : Ii32<0xC7, MRM0r, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32ri">; -} -} // SchedRW - -let SchedRW = [WriteStore] in { -def MOV8mi : Ii8 <0xC6, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store (i8 imm8_su:$src), addr:$dst)]>; -def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store (i16 imm16_su:$src), addr:$dst)]>, OpSize16; -def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store (i32 imm32_su:$src), addr:$dst)]>, OpSize32; -def MOV64mi32 : RIi32S<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store i64immSExt32_su:$src, addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { - -/// Memory offset versions of moves. The immediate is an address mode sized -/// offset from the segment base. -let SchedRW = [WriteALU] in { -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao32 : Ii32<0xA0, RawFrmMemOffs, (outs), (ins offset32_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, - AdSize32; -let Defs = [AX] in -def MOV16ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize32; -let Defs = [EAX] in -def MOV32ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize32; -let Defs = [RAX] in -def MOV64ao32 : RIi32<0xA1, RawFrmMemOffs, (outs), (ins offset32_64:$src), - "mov{q}\t{$src, %rax|rax, $src}", []>, - AdSize32; - -let Defs = [AL] in -def MOV8ao16 : Ii16<0xA0, RawFrmMemOffs, (outs), (ins offset16_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, AdSize16; -let Defs = [AX] in -def MOV16ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize16; -let Defs = [EAX] in -def MOV32ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - AdSize16, OpSize32; -} // mayLoad -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o32a : Ii32<0xA2, RawFrmMemOffs, (outs), (ins offset32_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize32; -let Uses = [AX] in -def MOV16o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize32; -let Uses = [EAX] in -def MOV32o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize32; -let Uses = [RAX] in -def MOV64o32a : RIi32<0xA3, RawFrmMemOffs, (outs), (ins offset32_64:$dst), - "mov{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize32; - -let Uses = [AL] in -def MOV8o16a : Ii16<0xA2, RawFrmMemOffs, (outs), (ins offset16_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize16; -let Uses = [AX] in -def MOV16o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize16; -let Uses = [EAX] in -def MOV32o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize16; -} // mayStore - -// These forms all have full 64-bit absolute addresses in their instructions -// and use the movabs mnemonic to indicate this specific form. -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao64 : Ii64<0xA0, RawFrmMemOffs, (outs), (ins offset64_8:$src), - "movabs{b}\t{$src, %al|al, $src}", []>, - AdSize64; -let Defs = [AX] in -def MOV16ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_16:$src), - "movabs{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize64; -let Defs = [EAX] in -def MOV32ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_32:$src), - "movabs{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize64; -let Defs = [RAX] in -def MOV64ao64 : RIi64<0xA1, RawFrmMemOffs, (outs), (ins offset64_64:$src), - "movabs{q}\t{$src, %rax|rax, $src}", []>, - AdSize64; -} // mayLoad - -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o64a : Ii64<0xA2, RawFrmMemOffs, (outs), (ins offset64_8:$dst), - "movabs{b}\t{%al, $dst|$dst, al}", []>, - AdSize64; -let Uses = [AX] in -def MOV16o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_16:$dst), - "movabs{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize64; -let Uses = [EAX] in -def MOV32o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_32:$dst), - "movabs{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize64; -let Uses = [RAX] in -def MOV64o64a : RIi64<0xA3, RawFrmMemOffs, (outs), (ins offset64_64:$dst), - "movabs{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize64; -} // mayStore -} // SchedRW -} // hasSideEffects = 0 - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [WriteMove], isMoveReg = 1 in { -def MOV8rr_REV : I<0x8A, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8rr">; -def MOV16rr_REV : I<0x8B, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16rr">; -def MOV32rr_REV : I<0x8B, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32rr">; -def MOV64rr_REV : RI<0x8B, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV64rr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -//// def : InstAlias<"mov{b}.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0>; -//// def : InstAlias<"mov{w}.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0>; -//// def : InstAlias<"mov{l}.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0>; -//// def : InstAlias<"mov{q}.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0>; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0, "att">; - -let canFoldAsLoad = 1, isReMaterializable = 1, SchedRW = [WriteLoad] in { -def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, (loadi8 addr:$src))]>; -def MOV16rm : I<0x8B, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (loadi16 addr:$src))]>, OpSize16; -def MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (loadi32 addr:$src))]>, OpSize32; -def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (load addr:$src))]>; -} - -let SchedRW = [WriteStore] in { -def MOV8mr : I<0x88, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store GR16:$src, addr:$dst)]>, OpSize16; -def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store GR32:$src, addr:$dst)]>, OpSize32; -def MOV64mr : RI<0x89, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store GR64:$src, addr:$dst)]>; -} // SchedRW - -// Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so -// that they can be used for copying and storing h registers, which can't be -// encoded when a REX prefix is present. -let isCodeGenOnly = 1 in { -let hasSideEffects = 0, isMoveReg = 1 in -def MOV8rr_NOREX : I<0x88, MRMDestReg, - (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteMove]>; -let mayStore = 1, hasSideEffects = 0 in -def MOV8mr_NOREX : I<0x88, MRMDestMem, - (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteStore]>; -let mayLoad = 1, hasSideEffects = 0, - canFoldAsLoad = 1, isReMaterializable = 1 in -def MOV8rm_NOREX : I<0x8A, MRMSrcMem, - (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteLoad]>; -} - - -// Condition code ops, incl. set if equal/not equal/... -let SchedRW = [WriteLAHFSAHF] in { -let Defs = [EFLAGS], Uses = [AH] in -def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", - [(set EFLAGS, (X86sahf AH))]>, - Requires<[HasLAHFSAHF]>; -let Defs = [AH], Uses = [EFLAGS], hasSideEffects = 0 in -def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>, // AH = flags - Requires<[HasLAHFSAHF]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Bit tests instructions: BT, BTS, BTR, BTC. - -let Defs = [EFLAGS] in { -let SchedRW = [WriteBitTest] in { -def BT16rr : I<0xA3, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, GR16:$src2))]>, - OpSize16, TB, NotMemoryFoldable; -def BT32rr : I<0xA3, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, GR32:$src2))]>, - OpSize32, TB, NotMemoryFoldable; -def BT64rr : RI<0xA3, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, GR64:$src2))]>, TB, - NotMemoryFoldable; -} // SchedRW - -// Unlike with the register+register form, the memory+register form of the -// bt instruction does not ignore the high bits of the index. From ISel's -// perspective, this is pretty bizarre. Make these instructions disassembly -// only for now. These instructions are also slow on modern CPUs so that's -// another reason to avoid generating them. - -let mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteALULd] in { - def BT16mr : I<0xA3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - []>, OpSize16, TB, NotMemoryFoldable; - def BT32mr : I<0xA3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - []>, OpSize32, TB, NotMemoryFoldable; - def BT64mr : RI<0xA3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - []>, TB, NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest] in { -def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, i64immSExt8:$src2))]>, TB; -} // SchedRW - -// Note that these instructions aren't slow because that only applies when the -// other operand is in a register. When it's an immediate, bt is still fast. -let SchedRW = [WriteALU] in { -def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi64 addr:$src1), - i64immSExt8:$src2))]>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16rr : I<0xBB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32rr : I<0xBB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64rr : RI<0xBB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mr : I<0xBB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32mr : I<0xBB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64mr : RI<0xBB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16rr : I<0xB3, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32rr : I<0xB3, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64rr : RI<0xB3, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mr : I<0xB3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32mr : I<0xB3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64mr : RI<0xB3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16rr : I<0xAB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32rr : I<0xAB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64rr : RI<0xAB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mr : I<0xAB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32mr : I<0xAB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64mr : RI<0xAB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 -} // Defs = [EFLAGS] - - -//===----------------------------------------------------------------------===// -// Atomic support -// - -// Atomic swap. These are just normal xchg instructions. But since a memory -// operand is referenced, the atomicity is ensured. -multiclass ATOMIC_SWAP opc8, bits<8> opc, string mnemonic, string frag> { - let Constraints = "$val = $dst", SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8rm : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16rm : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32rm : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64rm : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm XCHG : ATOMIC_SWAP<0x86, 0x87, "xchg", "atomic_swap">, NotMemoryFoldable; - -// Swap between registers. -let SchedRW = [WriteALU] in { -let Constraints = "$src1 = $dst1, $src2 = $dst2", hasSideEffects = 0 in { -def XCHG8rr : I<0x86, MRMSrcReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xchg{b}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -def XCHG16rr : I<0x87, MRMSrcReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xchg{w}\t{$src1, $src2|$src2, $src1}", []>, - OpSize16, NotMemoryFoldable; -def XCHG32rr : I<0x87, MRMSrcReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xchg{l}\t{$src1, $src2|$src2, $src1}", []>, - OpSize32, NotMemoryFoldable; -def XCHG64rr : RI<0x87, MRMSrcReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1 ,GR64:$src2), - "xchg{q}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -} - -def NOOP19rr: I<0x19, MRMSrcReg, (outs), (ins GR32:$val, GR32:$src), - "nop\t{$val, $src|$src, $val}", []>, TB, - OpSize32; - -// Swap between EAX and other registers. -let Constraints = "$src = $dst", hasSideEffects = 0 in { -let Uses = [AX], Defs = [AX] in -def XCHG16ar : I<0x90, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "xchg{w}\t{%ax, $src|$src, ax}", []>, OpSize16; -let Uses = [EAX], Defs = [EAX] in -def XCHG32ar : I<0x90, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "xchg{l}\t{%eax, $src|$src, eax}", []>, OpSize32; -let Uses = [RAX], Defs = [RAX] in -def XCHG64ar : RI<0x90, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "xchg{q}\t{%rax, $src|$src, rax}", []>; -} -} // SchedRW - -let hasSideEffects = 0, Constraints = "$src1 = $dst1, $src2 = $dst2", - Defs = [EFLAGS], SchedRW = [WriteALU] in { -def XADD8rr : I<0xC0, MRMDestReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xadd{b}\t{$src2, $src1|$src1, $src2}", []>, TB; -def XADD16rr : I<0xC1, MRMDestReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xadd{w}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize16; -def XADD32rr : I<0xC1, MRMDestReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xadd{l}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize32; -def XADD64rr : RI<0xC1, MRMDestReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1, GR64:$src2), - "xadd{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, hasSideEffects = 0, Constraints = "$val = $dst", - Defs = [EFLAGS], SchedRW = [WriteALULd, WriteRMW] in { -def XADD8rm : I<0xC0, MRMSrcMem, (outs GR8:$dst), - (ins GR8:$val, i8mem:$ptr), - "xadd{b}\t{$val, $ptr|$ptr, $val}", []>, TB; -def XADD16rm : I<0xC1, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$val, i16mem:$ptr), - "xadd{w}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize16; -def XADD32rm : I<0xC1, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$val, i32mem:$ptr), - "xadd{l}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize32; -def XADD64rm : RI<0xC1, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$val, i64mem:$ptr), - "xadd{q}\t{$val, $ptr|$ptr, $val}", []>, TB; - -} - -let SchedRW = [WriteALU], hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rr : I<0xB0, MRMDestReg, (outs GR8:$dst), (ins GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rr : I<0xB1, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rr : I<0xB1, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rr : RI<0xB1, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -} // SchedRW, hasSideEffects - -let SchedRW = [WriteALULd, WriteRMW], mayLoad = 1, mayStore = 1, - hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rm : I<0xB0, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rm : I<0xB1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rm : I<0xB1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rm : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in -def CMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$dst), - "cmpxchg8b\t$dst", []>, TB; - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX] in -def CMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$dst), - "cmpxchg16b\t$dst", []>, - TB, Requires<[HasCmpxchg16b, In64BitMode]>; -} // SchedRW, mayLoad, mayStore, hasSideEffects - - -// Lock instruction prefix -let SchedRW = [WriteMicrocoded] in -def LOCK_PREFIX : I<0xF0, RawFrm, (outs), (ins), "lock", []>; - -let SchedRW = [WriteNop] in { - -// Rex64 instruction prefix -def REX64_PREFIX : I<0x48, RawFrm, (outs), (ins), "rex64", []>, - Requires<[In64BitMode]>; - -// Data16 instruction prefix -def DATA16_PREFIX : I<0x66, RawFrm, (outs), (ins), "data16", []>; -} // SchedRW - -// Repeat string operation instruction prefixes -let Defs = [ECX], Uses = [ECX,DF], SchedRW = [WriteMicrocoded] in { -// Repeat (used with INS, OUTS, MOVS, LODS and STOS) -def REP_PREFIX : I<0xF3, RawFrm, (outs), (ins), "rep", []>; -// Repeat while not equal (used with CMPS and SCAS) -def REPNE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "repne", []>; -} - -// String manipulation instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [AL,ESI], Uses = [ESI,DF] in -def LODSB : I<0xAC, RawFrmSrc, (outs), (ins srcidx8:$src), - "lodsb\t{$src, %al|al, $src}", []>; -let Defs = [AX,ESI], Uses = [ESI,DF] in -def LODSW : I<0xAD, RawFrmSrc, (outs), (ins srcidx16:$src), - "lodsw\t{$src, %ax|ax, $src}", []>, OpSize16; -let Defs = [EAX,ESI], Uses = [ESI,DF] in -def LODSL : I<0xAD, RawFrmSrc, (outs), (ins srcidx32:$src), - "lods{l|d}\t{$src, %eax|eax, $src}", []>, OpSize32; -let Defs = [RAX,ESI], Uses = [ESI,DF] in -def LODSQ : RI<0xAD, RawFrmSrc, (outs), (ins srcidx64:$src), - "lodsq\t{$src, %rax|rax, $src}", []>, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteSystem] in { -let Defs = [ESI], Uses = [DX,ESI,DF] in { -def OUTSB : I<0x6E, RawFrmSrc, (outs), (ins srcidx8:$src), - "outsb\t{$src, %dx|dx, $src}", []>; -def OUTSW : I<0x6F, RawFrmSrc, (outs), (ins srcidx16:$src), - "outsw\t{$src, %dx|dx, $src}", []>, OpSize16; -def OUTSL : I<0x6F, RawFrmSrc, (outs), (ins srcidx32:$src), - "outs{l|d}\t{$src, %dx|dx, $src}", []>, OpSize32; -} - -let Defs = [EDI], Uses = [DX,EDI,DF] in { -def INSB : I<0x6C, RawFrmDst, (outs), (ins dstidx8:$dst), - "insb\t{%dx, $dst|$dst, dx}", []>; -def INSW : I<0x6D, RawFrmDst, (outs), (ins dstidx16:$dst), - "insw\t{%dx, $dst|$dst, dx}", []>, OpSize16; -def INSL : I<0x6D, RawFrmDst, (outs), (ins dstidx32:$dst), - "ins{l|d}\t{%dx, $dst|$dst, dx}", []>, OpSize32; -} -} - -// EFLAGS management instructions. -let SchedRW = [WriteALU], Defs = [EFLAGS], Uses = [EFLAGS] in { -def CLC : I<0xF8, RawFrm, (outs), (ins), "clc", []>; -def STC : I<0xF9, RawFrm, (outs), (ins), "stc", []>; -def CMC : I<0xF5, RawFrm, (outs), (ins), "cmc", []>; -} - -// DF management instructions. -let SchedRW = [WriteALU], Defs = [DF] in { -def CLD : I<0xFC, RawFrm, (outs), (ins), "cld", []>; -def STD : I<0xFD, RawFrm, (outs), (ins), "std", []>; -} - -// Table lookup instructions -let Uses = [AL,EBX], Defs = [AL], hasSideEffects = 0, mayLoad = 1 in -def XLAT : I<0xD7, RawFrm, (outs), (ins), "xlatb", []>, Sched<[WriteLoad]>; - -let SchedRW = [WriteMicrocoded] in { -// ASCII Adjust After Addition -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAA : I<0x37, RawFrm, (outs), (ins), "aaa", []>, - Requires<[Not64BitMode]>; - -// ASCII Adjust AX Before Division -let Uses = [AX], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAD8i8 : Ii8<0xD5, RawFrm, (outs), (ins i8imm:$src), - "aad\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AX After Multiply -let Uses = [AL], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAM8i8 : Ii8<0xD4, RawFrm, (outs), (ins i8imm:$src), - "aam\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AL After Subtraction - sets -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAS : I<0x3F, RawFrm, (outs), (ins), "aas", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Addition -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAA : I<0x27, RawFrm, (outs), (ins), "daa", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Subtraction -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAS : I<0x2F, RawFrm, (outs), (ins), "das", []>, - Requires<[Not64BitMode]>; -} // SchedRW - -let SchedRW = [WriteSystem] in { -// Check Array Index Against Bounds -// Note: "bound" does not have reversed operands in at&t syntax. -def BOUNDS16rm : I<0x62, MRMSrcMem, (outs GR16:$dst), (ins i32mem:$src), - "bound\t$dst, $src", []>, OpSize16, - Requires<[Not64BitMode]>; -def BOUNDS32rm : I<0x62, MRMSrcMem, (outs GR32:$dst), (ins i64mem:$src), - "bound\t$dst, $src", []>, OpSize32, - Requires<[Not64BitMode]>; - -// Adjust RPL Field of Segment Selector -def ARPL16rr : I<0x63, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -let mayStore = 1 in -def ARPL16mr : I<0x63, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVBE Instructions -// -let Predicates = [HasMOVBE] in { - let SchedRW = [WriteALULd] in { - def MOVBE16rm : I<0xF0, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (bswap (loadi16 addr:$src)))]>, - OpSize16, T8PS; - def MOVBE32rm : I<0xF0, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bswap (loadi32 addr:$src)))]>, - OpSize32, T8PS; - def MOVBE64rm : RI<0xF0, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bswap (loadi64 addr:$src)))]>, - T8PS; - } - let SchedRW = [WriteStore] in { - def MOVBE16mr : I<0xF1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(store (bswap GR16:$src), addr:$dst)]>, - OpSize16, T8PS; - def MOVBE32mr : I<0xF1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(store (bswap GR32:$src), addr:$dst)]>, - OpSize32, T8PS; - def MOVBE64mr : RI<0xF1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(store (bswap GR64:$src), addr:$dst)]>, - T8PS; - } -} - -//===----------------------------------------------------------------------===// -// RDRAND Instruction -// -let Predicates = [HasRDRAND], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDRAND16r : I<0xC7, MRM6r, (outs GR16:$dst), (ins), - "rdrand{w}\t$dst", [(set GR16:$dst, EFLAGS, (X86rdrand))]>, - OpSize16, PS; - def RDRAND32r : I<0xC7, MRM6r, (outs GR32:$dst), (ins), - "rdrand{l}\t$dst", [(set GR32:$dst, EFLAGS, (X86rdrand))]>, - OpSize32, PS; - def RDRAND64r : RI<0xC7, MRM6r, (outs GR64:$dst), (ins), - "rdrand{q}\t$dst", [(set GR64:$dst, EFLAGS, (X86rdrand))]>, - PS; -} - -//===----------------------------------------------------------------------===// -// RDSEED Instruction -// -let Predicates = [HasRDSEED], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDSEED16r : I<0xC7, MRM7r, (outs GR16:$dst), (ins), "rdseed{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86rdseed))]>, OpSize16, PS; - def RDSEED32r : I<0xC7, MRM7r, (outs GR32:$dst), (ins), "rdseed{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86rdseed))]>, OpSize32, PS; - def RDSEED64r : RI<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdseed{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86rdseed))]>, PS; -} - -//===----------------------------------------------------------------------===// -// LZCNT Instruction -// -let Predicates = [HasLZCNT], Defs = [EFLAGS] in { - def LZCNT16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteLZCNT]>; - def LZCNT16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteLZCNTLd]>; - - def LZCNT32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteLZCNT]>; - def LZCNT32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteLZCNTLd]>; - - def LZCNT64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteLZCNT]>; - def LZCNT64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteLZCNTLd]>; -} - -//===----------------------------------------------------------------------===// -// BMI Instructions -// -let Predicates = [HasBMI], Defs = [EFLAGS] in { - def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteTZCNT]>; - def TZCNT16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteTZCNTLd]>; - - def TZCNT32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteTZCNT]>; - def TZCNT32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteTZCNTLd]>; - - def TZCNT64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteTZCNT]>; - def TZCNT64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteTZCNTLd]>; -} - -multiclass bmi_bls { -let hasSideEffects = 0 in { - def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALU]>; - let mayLoad = 1 in - def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALULd]>; -} -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>; - defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W; - defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>; - defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W; - defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>; - defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate BMI instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasBMI] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, -1)), - (BLSR32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, -1)), - (BLSR64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, -1)), - (BLSMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, -1)), - (BLSMSK64rr GR64:$src)>; - - def : Pat<(and GR32:$src, (ineg GR32:$src)), - (BLSI32rr GR32:$src)>; - def : Pat<(and GR64:$src, (ineg GR64:$src)), - (BLSI64rr GR64:$src)>; -} - -multiclass bmi_bextr opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BEXTR32 : bmi_bextr<0xF7, "bextr{l}", GR32, i32mem, - X86bextr, loadi32, WriteBEXTR>; - defm BEXTR64 : bmi_bextr<0xF7, "bextr{q}", GR64, i64mem, - X86bextr, loadi64, WriteBEXTR>, VEX_W; -} - -multiclass bmi_bzhi opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, Intrinsic Int, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI2], Defs = [EFLAGS] in { - defm BZHI32 : bmi_bzhi<0xF5, "bzhi{l}", GR32, i32mem, - int_x86_bmi_bzhi_32, loadi32, WriteBZHI>; - defm BZHI64 : bmi_bzhi<0xF5, "bzhi{q}", GR64, i64mem, - int_x86_bmi_bzhi_64, loadi64, WriteBZHI>, VEX_W; -} - -def CountTrailingOnes : SDNodeXFormgetZExtValue()), SDLoc(N)); -}]>; - -def BEXTRMaskXForm : SDNodeXFormgetZExtValue()); - return getI32Imm(Length << 8, SDLoc(N)); -}]>; - -def AndMask64 : ImmLeaf(Imm); -}]>; - -// Use BEXTR for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI, NoBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTR64rr GR64:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTR64rm addr:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; -} - -// Use BZHI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; -} - -let Predicates = [HasBMI2] in { - multiclass _bmi_bzhi_pattern { - def : Pat; - def : Pat; - } - - multiclass bmi_bzhi_patterns { - // x & ((1 << y) - 1) - defm : _bmi_bzhi_pattern<(and RC:$src, (add (shl 1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (add (shl 1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & ~(-1 << y) - defm : _bmi_bzhi_pattern<(and RC:$src, (xor (shl -1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (xor (shl -1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & (-1 >> (bitwidth - y)) - defm : _bmi_bzhi_pattern<(and RC:$src, (srl -1, (sub bitwidth, GR8:$lz))), - (and (x86memop addr:$src), - (srl -1, (sub bitwidth, GR8:$lz))), - RC, VT, DstInst, DstMemInst>; - - // x << (bitwidth - y) >> (bitwidth - y) - defm : _bmi_bzhi_pattern<(srl (shl RC:$src, (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - (srl (shl (x86memop addr:$src), - (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - RC, VT, DstInst, DstMemInst>; - } - - defm : bmi_bzhi_patterns; - defm : bmi_bzhi_patterns; - - // x & (-1 >> (32 - y)) - def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(and (loadi32 addr:$src), (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x & (-1 >> (64 - y)) - def : Pat<(and GR64:$src, (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - - // x << (32 - y) >> (32 - y) - def : Pat<(srl (shl GR32:$src, (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(srl (shl (loadi32 addr:$src), (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x << (64 - y) >> (64 - y) - def : Pat<(srl (shl GR64:$src, (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(srl (shl (loadi64 addr:$src), (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; -} // HasBMI2 - -multiclass bmi_pdep_pext { - def rr : I<0xF5, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, RC:$src2))]>, - VEX_4V, Sched<[WriteALU]>; - def rm : I<0xF5, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, (ld_frag addr:$src2)))]>, - VEX_4V, Sched<[WriteALULd, ReadAfterLd]>; -} - -let Predicates = [HasBMI2] in { - defm PDEP32 : bmi_pdep_pext<"pdep{l}", GR32, i32mem, - int_x86_bmi_pdep_32, loadi32>, T8XD; - defm PDEP64 : bmi_pdep_pext<"pdep{q}", GR64, i64mem, - int_x86_bmi_pdep_64, loadi64>, T8XD, VEX_W; - defm PEXT32 : bmi_pdep_pext<"pext{l}", GR32, i32mem, - int_x86_bmi_pext_32, loadi32>, T8XS; - defm PEXT64 : bmi_pdep_pext<"pext{q}", GR64, i64mem, - int_x86_bmi_pext_64, loadi64>, T8XS, VEX_W; -} - -//===----------------------------------------------------------------------===// -// TBM Instructions -// -let Predicates = [HasTBM], Defs = [EFLAGS] in { - -multiclass tbm_ternary_imm opc, RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - SDNode OpNode, Operand immtype, - SDPatternOperator immoperator, - X86FoldableSchedWrite Sched> { - def ri : Ii32, - XOP, XOPA, Sched<[Sched]>; - def mi : Ii32, - XOP, XOPA, Sched<[Sched.Folded]>; -} - -defm BEXTRI32 : tbm_ternary_imm<0x10, GR32, "bextr{l}", i32mem, loadi32, - X86bextr, i32imm, imm, WriteBEXTR>; -let ImmT = Imm32S in -defm BEXTRI64 : tbm_ternary_imm<0x10, GR64, "bextr{q}", i64mem, loadi64, - X86bextr, i64i32imm, - i64immSExt32, WriteBEXTR>, VEX_W; - -multiclass tbm_binary_rm opc, Format FormReg, Format FormMem, - RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, X86FoldableSchedWrite Sched> { -let hasSideEffects = 0 in { - def rr : I, - XOP_4V, XOP9, Sched<[Sched]>; - let mayLoad = 1 in - def rm : I, - XOP_4V, XOP9, Sched<[Sched.Folded]>; -} -} - -multiclass tbm_binary_intr opc, string OpcodeStr, - X86FoldableSchedWrite Sched, - Format FormReg, Format FormMem> { - defm NAME#32 : tbm_binary_rm; - defm NAME#64 : tbm_binary_rm, VEX_W; -} - -defm BLCFILL : tbm_binary_intr<0x01, "blcfill", WriteALU, MRM1r, MRM1m>; -defm BLCI : tbm_binary_intr<0x02, "blci", WriteALU, MRM6r, MRM6m>; -defm BLCIC : tbm_binary_intr<0x01, "blcic", WriteALU, MRM5r, MRM5m>; -defm BLCMSK : tbm_binary_intr<0x02, "blcmsk", WriteALU, MRM1r, MRM1m>; -defm BLCS : tbm_binary_intr<0x01, "blcs", WriteALU, MRM3r, MRM3m>; -defm BLSFILL : tbm_binary_intr<0x01, "blsfill", WriteALU, MRM2r, MRM2m>; -defm BLSIC : tbm_binary_intr<0x01, "blsic", WriteALU, MRM6r, MRM6m>; -defm T1MSKC : tbm_binary_intr<0x01, "t1mskc", WriteALU, MRM7r, MRM7m>; -defm TZMSK : tbm_binary_intr<0x01, "tzmsk", WriteALU, MRM4r, MRM4m>; -} // HasTBM, EFLAGS - -// Use BEXTRI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>; - - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>; -} - -//===----------------------------------------------------------------------===// -// Lightweight Profiling Instructions - -let Predicates = [HasLWP], SchedRW = [WriteSystem] in { - -def LLWPCB : I<0x12, MRM0r, (outs), (ins GR32:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR32:$src)]>, XOP, XOP9; -def SLWPCB : I<0x12, MRM1r, (outs GR32:$dst), (ins), "slwpcb\t$dst", - [(set GR32:$dst, (int_x86_slwpcb))]>, XOP, XOP9; - -def LLWPCB64 : I<0x12, MRM0r, (outs), (ins GR64:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR64:$src)]>, XOP, XOP9, VEX_W; -def SLWPCB64 : I<0x12, MRM1r, (outs GR64:$dst), (ins), "slwpcb\t$dst", - [(set GR64:$dst, (int_x86_slwpcb))]>, XOP, XOP9, VEX_W; - -multiclass lwpins_intr { - def rri : Ii32<0x12, MRM0r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, GR32:$src1, imm:$cntl))]>, - XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM0m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, (loadi32 addr:$src1), imm:$cntl))]>, - XOP_4V, XOPA; -} - -let Defs = [EFLAGS] in { - defm LWPINS32 : lwpins_intr; - defm LWPINS64 : lwpins_intr, VEX_W; -} // EFLAGS - -multiclass lwpval_intr { - def rri : Ii32<0x12, MRM1r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, GR32:$src1, imm:$cntl)]>, XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM1m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, (loadi32 addr:$src1), imm:$cntl)]>, - XOP_4V, XOPA; -} - -defm LWPVAL32 : lwpval_intr; -defm LWPVAL64 : lwpval_intr, VEX_W; - -} // HasLWP, SchedRW - -//===----------------------------------------------------------------------===// -// MONITORX/MWAITX Instructions -// -let SchedRW = [ WriteSystem ] in { -/* - let usesCustomInserter = 1 in { - def MONITORX : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_monitorx addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[ HasMWAITX ]>; - } -*/ - - let Uses = [ EAX, ECX, EDX ] in { - def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", []>, - TB, Requires<[ HasMWAITX ]>; - } - - let Uses = [ ECX, EAX, EBX ] in { - def MWAITXrrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx", - [(int_x86_mwaitx ECX, EAX, EBX)]>, - TB, Requires<[ HasMWAITX ]>; - } -} // SchedRW - -// def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrrr)>, -// Requires<[ Not64BitMode ]>; -// def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrrr)>, -// Requires<[ In64BitMode ]>; - -// def : InstAlias<"monitorx\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORXrrr)>, -// Requires<[ Not64BitMode ]>; -// def : InstAlias<"monitorx\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORXrrr)>, -// Requires<[ In64BitMode ]>; - -//===----------------------------------------------------------------------===// -// WAITPKG Instructions -// -let SchedRW = [WriteSystem] in { - def UMONITOR16 : I<0xAE, MRM6r, (outs), (ins GR16:$src), - "umonitor\t$src", [(int_x86_umonitor GR16:$src)]>, - XS, AdSize16, Requires<[HasWAITPKG, Not64BitMode]>; - def UMONITOR32 : I<0xAE, MRM6r, (outs), (ins GR32:$src), - "umonitor\t$src", [(int_x86_umonitor GR32:$src)]>, - XS, AdSize32, Requires<[HasWAITPKG]>; - def UMONITOR64 : I<0xAE, MRM6r, (outs), (ins GR64:$src), - "umonitor\t$src", [(int_x86_umonitor GR64:$src)]>, - XS, AdSize64, Requires<[HasWAITPKG, In64BitMode]>; - let Uses = [EAX, EDX], Defs = [EFLAGS] in { - def UMWAIT : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "umwait\t$src", - [(set EFLAGS, (X86umwait GR32orGR64:$src, EDX, EAX))]>, - XD, Requires<[HasWAITPKG]>; - def TPAUSE : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "tpause\t$src", - [(set EFLAGS, (X86tpause GR32orGR64:$src, EDX, EAX))]>, - PD, Requires<[HasWAITPKG]>, NotMemoryFoldable; - } -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIRI - Move doubleword/quadword as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIRI32 : I<0xF9, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore32 addr:$dst, GR32:$src)]>, - T8, Requires<[HasMOVDIRI]>; -def MOVDIRI64 : RI<0xF9, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore64 addr:$dst, GR64:$src)]>, - T8, Requires<[In64BitMode, HasMOVDIRI]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIR64B - Move 64 bytes as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIR64B16 : I<0xF8, MRMSrcMem, (outs), (ins GR16:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", []>, - T8PD, AdSize16, Requires<[HasMOVDIR64B, Not64BitMode]>; -def MOVDIR64B32 : I<0xF8, MRMSrcMem, (outs), (ins GR32:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR32:$dst, addr:$src)]>, - T8PD, AdSize32, Requires<[HasMOVDIR64B]>; -def MOVDIR64B64 : I<0xF8, MRMSrcMem, (outs), (ins GR64:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR64:$dst, addr:$src)]>, - T8PD, AdSize64, Requires<[HasMOVDIR64B, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CLZERO Instruction -// -let SchedRW = [WriteSystem] in { - let Uses = [EAX] in - def CLZEROr : I<0x01, MRM_FC, (outs), (ins), "clzero", []>, - TB, Requires<[HasCLZERO]>; - -/* - let usesCustomInserter = 1 in { - def CLZERO : PseudoI<(outs), (ins i32mem:$src1), - [(int_x86_clzero addr:$src1)]>, Requires<[HasCLZERO]>; - } -*/ -} // SchedRW - -// def : InstAlias<"clzero\t{%eax|eax}", (CLZEROr)>, Requires<[Not64BitMode]>; -// def : InstAlias<"clzero\t{%rax|rax}", (CLZEROr)>, Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate TBM instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasTBM] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, 1)), - (BLCFILL32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, 1)), - (BLCFILL64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (not (add GR32:$src, 1))), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (not (add GR64:$src, 1))), - (BLCI64rr GR64:$src)>; - - // Extra patterns because opt can optimize the above patterns to this. - def : Pat<(or GR32:$src, (sub -2, GR32:$src)), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (sub -2, GR64:$src)), - (BLCI64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, 1)), - (BLCIC32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, 1)), - (BLCIC64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, 1)), - (BLCMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, 1)), - (BLCMSK64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, 1)), - (BLCS32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, 1)), - (BLCS64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, -1)), - (BLSFILL32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, -1)), - (BLSFILL64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, -1)), - (BLSIC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, -1)), - (BLSIC64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, 1)), - (T1MSKC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, 1)), - (T1MSKC64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, -1)), - (TZMSK32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, -1)), - (TZMSK64rr GR64:$src)>; -} // HasTBM - -//===----------------------------------------------------------------------===// -// Memory Instructions -// - -let Predicates = [HasCLFLUSHOPT], SchedRW = [WriteLoad] in -def CLFLUSHOPT : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflushopt\t$src", [(int_x86_clflushopt addr:$src)]>, PD; - -let Predicates = [HasCLWB], SchedRW = [WriteLoad] in -def CLWB : I<0xAE, MRM6m, (outs), (ins i8mem:$src), "clwb\t$src", - [(int_x86_clwb addr:$src)]>, PD, NotMemoryFoldable; - -let Predicates = [HasCLDEMOTE], SchedRW = [WriteLoad] in -def CLDEMOTE : I<0x1C, MRM0m, (outs), (ins i8mem:$src), "cldemote\t$src", - [(int_x86_cldemote addr:$src)]>, TB; - -//===----------------------------------------------------------------------===// -// Subsystems. -//===----------------------------------------------------------------------===// - -include "X86Capstone.td" - -include "X86InstrArithmetic.td" -include "X86InstrCMovSetCC.td" -include "X86InstrExtension.td" -include "X86InstrControl.td" -include "X86InstrShiftRotate.td" - -// X87 Floating Point Stack. -include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -include "X86InstrFMA.td" - -// XOP -include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -include "X86InstrSSE.td" -include "X86InstrAVX512.td" -include "X86InstrMMX.td" -include "X86Instr3DNow.td" - -// MPX instructions -include "X86InstrMPX.td" - -include "X86InstrVMX.td" -include "X86InstrSVM.td" - -include "X86InstrTSX.td" -include "X86InstrSGX.td" - -// System instructions. -include "X86InstrSystem.td" - -// Compiler Pseudo Instructions and Pat Patterns -//include "X86InstrCompiler.td" -//include "X86InstrVecCompiler.td" - -//===----------------------------------------------------------------------===// -// Assembler Mnemonic Aliases -//===----------------------------------------------------------------------===// - -def : MnemonicAlias<"call", "callw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"call", "calll", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"call", "callq", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"cbw", "cbtw", "att">; -def : MnemonicAlias<"cwde", "cwtl", "att">; -def : MnemonicAlias<"cwd", "cwtd", "att">; -def : MnemonicAlias<"cdq", "cltd", "att">; -def : MnemonicAlias<"cdqe", "cltq", "att">; -def : MnemonicAlias<"cqo", "cqto", "att">; - -// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq. -def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>; - -def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"loopz", "loope">; -def : MnemonicAlias<"loopnz", "loopne">; - -def : MnemonicAlias<"pop", "popw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pop", "popl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pop", "popq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popf", "popfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"popf", "popfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popfd", "popfl", "att">; - -// FIXME: This is wrong for "push reg". "push %bx" should turn into pushw in -// all modes. However: "push (addr)" and "push $42" should default to -// pushl/pushq depending on the current mode. Similar for "pop %bx" -def : MnemonicAlias<"push", "pushw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"push", "pushl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"push", "pushq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pushf", "pushfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushfd", "pushfl", "att">; - -def : MnemonicAlias<"popad", "popal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"pushad", "pushal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"popa", "popaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "intel">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "intel">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"popa", "popaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "att">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"repe", "rep">; -def : MnemonicAlias<"repz", "rep">; -def : MnemonicAlias<"repnz", "repne">; - -def : MnemonicAlias<"ret", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"ret", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"ret", "retq", "att">, Requires<[In64BitMode]>; - -// Apply 'ret' behavior to 'retn' -def : MnemonicAlias<"retn", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"retn", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"retn", "retq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"retn", "ret", "intel">; - -def : MnemonicAlias<"sal", "shl", "intel">; -def : MnemonicAlias<"salb", "shlb", "att">; -def : MnemonicAlias<"salw", "shlw", "att">; -def : MnemonicAlias<"sall", "shll", "att">; -def : MnemonicAlias<"salq", "shlq", "att">; - -def : MnemonicAlias<"smovb", "movsb", "att">; -def : MnemonicAlias<"smovw", "movsw", "att">; -def : MnemonicAlias<"smovl", "movsl", "att">; -def : MnemonicAlias<"smovq", "movsq", "att">; - -def : MnemonicAlias<"ud2a", "ud2", "att">; -def : MnemonicAlias<"verrw", "verr", "att">; - -// MS recognizes 'xacquire'/'xrelease' as 'acquire'/'release' -def : MnemonicAlias<"acquire", "xacquire", "intel">; -def : MnemonicAlias<"release", "xrelease", "intel">; - -// System instruction aliases. -def : MnemonicAlias<"iret", "iretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"iret", "iretl", "att">, Requires<[Not16BitMode]>; -def : MnemonicAlias<"sysret", "sysretl", "att">; -def : MnemonicAlias<"sysexit", "sysexitl", "att">; - -def : MnemonicAlias<"lgdt", "lgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"lidt", "lidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lidt", "lidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lidt", "lidtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sidt", "sidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sidt", "sidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sidt", "sidtq", "att">, Requires<[In64BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"lidt", "lidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lidt", "lidtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sidt", "sidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sidt", "sidtd", "intel">, Requires<[In32BitMode]>; - - -// Floating point stack aliases. -def : MnemonicAlias<"fcmovz", "fcmove", "att">; -def : MnemonicAlias<"fcmova", "fcmovnbe", "att">; -def : MnemonicAlias<"fcmovnae", "fcmovb", "att">; -def : MnemonicAlias<"fcmovna", "fcmovbe", "att">; -def : MnemonicAlias<"fcmovae", "fcmovnb", "att">; -def : MnemonicAlias<"fcomip", "fcompi">; -def : MnemonicAlias<"fildq", "fildll", "att">; -def : MnemonicAlias<"fistpq", "fistpll", "att">; -def : MnemonicAlias<"fisttpq", "fisttpll", "att">; -def : MnemonicAlias<"fldcww", "fldcw", "att">; -def : MnemonicAlias<"fnstcww", "fnstcw", "att">; -def : MnemonicAlias<"fnstsww", "fnstsw", "att">; -def : MnemonicAlias<"fucomip", "fucompi">; -def : MnemonicAlias<"fwait", "wait">; - -def : MnemonicAlias<"fxsaveq", "fxsave64", "att">; -def : MnemonicAlias<"fxrstorq", "fxrstor64", "att">; -def : MnemonicAlias<"xsaveq", "xsave64", "att">; -def : MnemonicAlias<"xrstorq", "xrstor64", "att">; -def : MnemonicAlias<"xsaveoptq", "xsaveopt64", "att">; -def : MnemonicAlias<"xrstorsq", "xrstors64", "att">; -def : MnemonicAlias<"xsavecq", "xsavec64", "att">; -def : MnemonicAlias<"xsavesq", "xsaves64", "att">; - -class CondCodeAlias - : MnemonicAlias; - -/// IntegerCondCodeMnemonicAlias - This multiclass defines a bunch of -/// MnemonicAlias's that canonicalize the condition code in a mnemonic, for -/// example "setz" -> "sete". -multiclass IntegerCondCodeMnemonicAlias { - def C : CondCodeAlias; // setc -> setb - def Z : CondCodeAlias; // setz -> sete - def NA : CondCodeAlias; // setna -> setbe - def NB : CondCodeAlias; // setnb -> setae - def NC : CondCodeAlias; // setnc -> setae - def NG : CondCodeAlias; // setng -> setle - def NL : CondCodeAlias; // setnl -> setge - def NZ : CondCodeAlias; // setnz -> setne - def PE : CondCodeAlias; // setpe -> setp - def PO : CondCodeAlias; // setpo -> setnp - - def NAE : CondCodeAlias; // setnae -> setb - def NBE : CondCodeAlias; // setnbe -> seta - def NGE : CondCodeAlias; // setnge -> setl - def NLE : CondCodeAlias; // setnle -> setg -} - -// Aliases for set -defm : IntegerCondCodeMnemonicAlias<"set", "">; -// Aliases for j -defm : IntegerCondCodeMnemonicAlias<"j", "">; -// Aliases for cmov{w,l,q} -defm : IntegerCondCodeMnemonicAlias<"cmov", "w", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "l", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "q", "att">; -// No size suffix for intel-style asm. -defm : IntegerCondCodeMnemonicAlias<"cmov", "", "intel">; - - -//===----------------------------------------------------------------------===// -// Assembler Instruction Aliases -//===----------------------------------------------------------------------===// - -// aad/aam default to base 10 if no operand is specified. -// def : InstAlias<"aad", (AAD8i8 10)>, Requires<[Not64BitMode]>; -// def : InstAlias<"aam", (AAM8i8 10)>, Requires<[Not64BitMode]>; - -// Disambiguate the mem/imm form of bt-without-a-suffix as btl. -// Likewise for btc/btr/bts. -// def : InstAlias<"bt\t{$imm, $mem|$mem, $imm}", -// (BT32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"btc\t{$imm, $mem|$mem, $imm}", -// (BTC32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"btr\t{$imm, $mem|$mem, $imm}", -// (BTR32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"bts\t{$imm, $mem|$mem, $imm}", -// (BTS32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; - -// clr aliases. -// def : InstAlias<"clr{b}\t$reg", (XOR8rr GR8 :$reg, GR8 :$reg), 0>; -// def : InstAlias<"clr{w}\t$reg", (XOR16rr GR16:$reg, GR16:$reg), 0>; -// def : InstAlias<"clr{l}\t$reg", (XOR32rr GR32:$reg, GR32:$reg), 0>; -// def : InstAlias<"clr{q}\t$reg", (XOR64rr GR64:$reg, GR64:$reg), 0>; - -// lods aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"lodsb\t$src", (LODSB srcidx8:$src), 0>; -// def : InstAlias<"lodsw\t$src", (LODSW srcidx16:$src), 0>; -// def : InstAlias<"lods{l|d}\t$src", (LODSL srcidx32:$src), 0>; -// def : InstAlias<"lodsq\t$src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"lods\t{$src, %al|al, $src}", (LODSB srcidx8:$src), 0>; -// def : InstAlias<"lods\t{$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>; -// def : InstAlias<"lods\t{$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>; -// def : InstAlias<"lods\t{$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"lods\t$src", (LODSB srcidx8:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSW srcidx16:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSL srcidx32:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSQ srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - - -// stos aliases. Accept the source being omitted because it's implicit in -// the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the source. -// def : InstAlias<"stosb\t$dst", (STOSB dstidx8:$dst), 0>; -// def : InstAlias<"stosw\t$dst", (STOSW dstidx16:$dst), 0>; -// def : InstAlias<"stos{l|d}\t$dst", (STOSL dstidx32:$dst), 0>; -// def : InstAlias<"stosq\t$dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"stos\t{%al, $dst|$dst, al}", (STOSB dstidx8:$dst), 0>; -// def : InstAlias<"stos\t{%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>; -// def : InstAlias<"stos\t{%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>; -// def : InstAlias<"stos\t{%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"stos\t$dst", (STOSB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSL dstidx32:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - - -// scas aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"scasb\t$dst", (SCASB dstidx8:$dst), 0>; -// def : InstAlias<"scasw\t$dst", (SCASW dstidx16:$dst), 0>; -// def : InstAlias<"scas{l|d}\t$dst", (SCASL dstidx32:$dst), 0>; -// def : InstAlias<"scasq\t$dst", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"scas\t{$dst, %al|al, $dst}", (SCASB dstidx8:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %ax|ax, $dst}", (SCASW dstidx16:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %eax|eax, $dst}", (SCASL dstidx32:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %rax|rax, $dst}", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"scas\t$dst", (SCASB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASL dstidx32:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - -// cmps aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// movs aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// div and idiv aliases for explicit A register. -// def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>; -// def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>; -// def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32r GR32:$src)>; -// def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64r GR64:$src)>; -// def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8m i8mem :$src)>; -// def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16m i16mem:$src)>; -// def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32m i32mem:$src)>; -// def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64m i64mem:$src)>; -// def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8r GR8 :$src)>; -// def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16r GR16:$src)>; -// def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32r GR32:$src)>; -// def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64r GR64:$src)>; -// def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8m i8mem :$src)>; -// def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16m i16mem:$src)>; -// def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32m i32mem:$src)>; -// def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64m i64mem:$src)>; - - - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -// def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -//def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -// def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -// def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -// def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -// def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -// def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -// def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -// def : InstAlias<"fxch", (XCH_F ST1), 0>; -// def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -// def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -// def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -// def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -// def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -// def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -// def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -// def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -/* -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -//multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; -*/ - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -// def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -// def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -// def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -// def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -// def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -// def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; - -// def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// lcall and ljmp aliases. This seems to be an odd mapping in 64-bit mode, but -// this is compatible with what GAS does. -// def : InstAlias<"lcall\t$seg : $off", (FARCALL32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -// def : InstAlias<"ljmp\t$seg : $off", (FARJMP32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -// def : InstAlias<"lcall\t{*}$dst", (FARCALL32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -// def : InstAlias<"ljmp\t{*}$dst", (FARJMP32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -// def : InstAlias<"lcall\t$seg : $off", (FARCALL16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"ljmp\t$seg : $off", (FARJMP16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"lcall\t{*}$dst", (FARCALL16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"ljmp\t{*}$dst", (FARJMP16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; - -// def : InstAlias<"jmp\t{*}$dst", (JMP64m i64mem:$dst), 0, "att">, Requires<[In64BitMode]>; -// def : InstAlias<"jmp\t{*}$dst", (JMP32m i32mem:$dst), 0, "att">, Requires<[In32BitMode]>; -// def : InstAlias<"jmp\t{*}$dst", (JMP16m i16mem:$dst), 0, "att">, Requires<[In16BitMode]>; - - -// "imul , B" is an alias for "imul , B, B". -// def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri GR16:$r, GR16:$r, i16imm:$imm), 0>; -// def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri8 GR16:$r, GR16:$r, i16i8imm:$imm), 0>; -// def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri GR32:$r, GR32:$r, i32imm:$imm), 0>; -// def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri8 GR32:$r, GR32:$r, i32i8imm:$imm), 0>; -// def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri32 GR64:$r, GR64:$r, i64i32imm:$imm), 0>; -// def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri8 GR64:$r, GR64:$r, i64i8imm:$imm), 0>; - -// ins aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSL dstidx32:$dst), 0, "intel">; - -// outs aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the source. -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSB srcidx8:$src), 0, "intel">; -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSW srcidx16:$src), 0, "intel">; -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSL srcidx32:$src), 0, "intel">; - -// inb %dx -> inb %al, %dx -// def : InstAlias<"inb\t{%dx|dx}", (IN8rr), 0>; -// def : InstAlias<"inw\t{%dx|dx}", (IN16rr), 0>; -// def : InstAlias<"inl\t{%dx|dx}", (IN32rr), 0>; -// def : InstAlias<"inb\t$port", (IN8ri u8imm:$port), 0>; -// def : InstAlias<"inw\t$port", (IN16ri u8imm:$port), 0>; -// def : InstAlias<"inl\t$port", (IN32ri u8imm:$port), 0>; - - -// jmp and call aliases for lcall and ljmp. jmp $42,$5 -> ljmp -// def : InstAlias<"call\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -// def : InstAlias<"jmp\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -// def : InstAlias<"call\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -// def : InstAlias<"jmp\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -// def : InstAlias<"callw\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"jmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"calll\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"jmpl\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; - -// Match 'movq , ' as an alias for movabsq. -// def : InstAlias<"mov{q}\t{$imm, $reg|$reg, $imm}", (MOV64ri GR64:$reg, i64imm:$imm), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; - -// movsx aliases -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rr8 GR16:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr8 GR32:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr16 GR32:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr8 GR64:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr32 GR64:$dst, GR32:$src), 0, "att">; - -// movzx aliases -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rr8 GR16:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr8 GR32:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr16 GR32:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr8 GR64:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// Note: No GR32->GR64 movzx form. - -// outb %dx -> outb %al, %dx -// def : InstAlias<"outb\t{%dx|dx}", (OUT8rr), 0>; -// def : InstAlias<"outw\t{%dx|dx}", (OUT16rr), 0>; -// def : InstAlias<"outl\t{%dx|dx}", (OUT32rr), 0>; -// def : InstAlias<"outb\t$port", (OUT8ir u8imm:$port), 0>; -// def : InstAlias<"outw\t$port", (OUT16ir u8imm:$port), 0>; -// def : InstAlias<"outl\t$port", (OUT32ir u8imm:$port), 0>; - -// 'sldt ' can be encoded with either sldtw or sldtq with the same -// effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity -// errors, since its encoding is the most compact. -// def : InstAlias<"sldt $mem", (SLDT16m i16mem:$mem), 0>; - -// shld/shrd op,op -> shld op, op, CL -// def : InstAlias<"shld{w}\t{$r2, $r1|$r1, $r2}", (SHLD16rrCL GR16:$r1, GR16:$r2), 0>; -// def : InstAlias<"shld{l}\t{$r2, $r1|$r1, $r2}", (SHLD32rrCL GR32:$r1, GR32:$r2), 0>; -// def : InstAlias<"shld{q}\t{$r2, $r1|$r1, $r2}", (SHLD64rrCL GR64:$r1, GR64:$r2), 0>; -// def : InstAlias<"shrd{w}\t{$r2, $r1|$r1, $r2}", (SHRD16rrCL GR16:$r1, GR16:$r2), 0>; -// def : InstAlias<"shrd{l}\t{$r2, $r1|$r1, $r2}", (SHRD32rrCL GR32:$r1, GR32:$r2), 0>; -// def : InstAlias<"shrd{q}\t{$r2, $r1|$r1, $r2}", (SHRD64rrCL GR64:$r1, GR64:$r2), 0>; - -// def : InstAlias<"shld{w}\t{$reg, $mem|$mem, $reg}", (SHLD16mrCL i16mem:$mem, GR16:$reg), 0>; -// def : InstAlias<"shld{l}\t{$reg, $mem|$mem, $reg}", (SHLD32mrCL i32mem:$mem, GR32:$reg), 0>; -// def : InstAlias<"shld{q}\t{$reg, $mem|$mem, $reg}", (SHLD64mrCL i64mem:$mem, GR64:$reg), 0>; -// def : InstAlias<"shrd{w}\t{$reg, $mem|$mem, $reg}", (SHRD16mrCL i16mem:$mem, GR16:$reg), 0>; -// def : InstAlias<"shrd{l}\t{$reg, $mem|$mem, $reg}", (SHRD32mrCL i32mem:$mem, GR32:$reg), 0>; -// def : InstAlias<"shrd{q}\t{$reg, $mem|$mem, $reg}", (SHRD64mrCL i64mem:$mem, GR64:$reg), 0>; - -/* FIXME: This is disabled because the asm matcher is currently incapable of - * matching a fixed immediate like $1. -// "shl X, $1" is an alias for "shl X". -multiclass ShiftRotateByOneAlias { - // def : InstAlias(!strconcat(Opc, "8r1")) GR8:$op)>; - // def : InstAlias(!strconcat(Opc, "16r1")) GR16:$op)>; - // def : InstAlias(!strconcat(Opc, "32r1")) GR32:$op)>; - // def : InstAlias(!strconcat(Opc, "64r1")) GR64:$op)>; - // def : InstAlias(!strconcat(Opc, "8m1")) i8mem:$op)>; - // def : InstAlias(!strconcat(Opc, "16m1")) i16mem:$op)>; - // def : InstAlias(!strconcat(Opc, "32m1")) i32mem:$op)>; - // def : InstAlias(!strconcat(Opc, "64m1")) i64mem:$op)>; -} - -defm : ShiftRotateByOneAlias<"rcl", "RCL">; -defm : ShiftRotateByOneAlias<"rcr", "RCR">; -defm : ShiftRotateByOneAlias<"rol", "ROL">; -defm : ShiftRotateByOneAlias<"ror", "ROR">; -FIXME */ - -// test: We accept "testX , " and "testX , " as synonyms. -// def : InstAlias<"test{b}\t{$mem, $val|$val, $mem}", -// (TEST8mr i8mem :$mem, GR8 :$val), 0>; -// def : InstAlias<"test{w}\t{$mem, $val|$val, $mem}", -// (TEST16mr i16mem:$mem, GR16:$val), 0>; -// def : InstAlias<"test{l}\t{$mem, $val|$val, $mem}", -// (TEST32mr i32mem:$mem, GR32:$val), 0>; -// def : InstAlias<"test{q}\t{$mem, $val|$val, $mem}", -// (TEST64mr i64mem:$mem, GR64:$val), 0>; - -// xchg: We accept "xchgX , " and "xchgX , " as synonyms. -// def : InstAlias<"xchg{b}\t{$mem, $val|$val, $mem}", -// (XCHG8rm GR8 :$val, i8mem :$mem), 0>; -// def : InstAlias<"xchg{w}\t{$mem, $val|$val, $mem}", -// (XCHG16rm GR16:$val, i16mem:$mem), 0>; -// def : InstAlias<"xchg{l}\t{$mem, $val|$val, $mem}", -// (XCHG32rm GR32:$val, i32mem:$mem), 0>; -// def : InstAlias<"xchg{q}\t{$mem, $val|$val, $mem}", -// (XCHG64rm GR64:$val, i64mem:$mem), 0>; - -// xchg: We accept "xchgX , %eax" and "xchgX %eax, " as synonyms. -// def : InstAlias<"xchg{w}\t{%ax, $src|$src, ax}", (XCHG16ar GR16:$src), 0>; -// def : InstAlias<"xchg{l}\t{%eax, $src|$src, eax}", (XCHG32ar GR32:$src), 0>; -// def : InstAlias<"xchg{q}\t{%rax, $src|$src, rax}", (XCHG64ar GR64:$src), 0>; - -// In 64-bit mode, xchg %eax, %eax can't be encoded with the 0x90 opcode we -// would get by default because it's defined as NOP. But xchg %eax, %eax implies -// implicit zeroing of the upper 32 bits. So alias to the longer encoding. -// def : InstAlias<"xchg{l}\t{%eax, %eax|eax, eax}", -// (XCHG32rr EAX, EAX), 0>, Requires<[In64BitMode]>; - -// xchg %rax, %rax is a nop in x86-64 and can be encoded as such. Without this -// we emit an unneeded REX.w prefix. -// def : InstAlias<"xchg{q}\t{%rax, %rax|rax, rax}", (NOOP), 0>; - -// These aliases exist to get the parser to prioritize matching 8-bit -// immediate encodings over matching the implicit ax/eax/rax encodings. By -// explicitly mentioning the A register here, these entries will be ordered -// first due to the more explicit immediate type. -// def : InstAlias<"adc{w}\t{$imm, %ax|ax, $imm}", (ADC16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"add{w}\t{$imm, %ax|ax, $imm}", (ADD16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"and{w}\t{$imm, %ax|ax, $imm}", (AND16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"cmp{w}\t{$imm, %ax|ax, $imm}", (CMP16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"or{w}\t{$imm, %ax|ax, $imm}", (OR16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"sbb{w}\t{$imm, %ax|ax, $imm}", (SBB16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"sub{w}\t{$imm, %ax|ax, $imm}", (SUB16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"xor{w}\t{$imm, %ax|ax, $imm}", (XOR16ri8 AX, i16i8imm:$imm), 0>; - -// def : InstAlias<"adc{l}\t{$imm, %eax|eax, $imm}", (ADC32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"add{l}\t{$imm, %eax|eax, $imm}", (ADD32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"and{l}\t{$imm, %eax|eax, $imm}", (AND32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"cmp{l}\t{$imm, %eax|eax, $imm}", (CMP32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"or{l}\t{$imm, %eax|eax, $imm}", (OR32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"sbb{l}\t{$imm, %eax|eax, $imm}", (SBB32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"sub{l}\t{$imm, %eax|eax, $imm}", (SUB32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"xor{l}\t{$imm, %eax|eax, $imm}", (XOR32ri8 EAX, i32i8imm:$imm), 0>; - -// def : InstAlias<"adc{q}\t{$imm, %rax|rax, $imm}", (ADC64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"add{q}\t{$imm, %rax|rax, $imm}", (ADD64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"and{q}\t{$imm, %rax|rax, $imm}", (AND64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"cmp{q}\t{$imm, %rax|rax, $imm}", (CMP64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"or{q}\t{$imm, %rax|rax, $imm}", (OR64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"sbb{q}\t{$imm, %rax|rax, $imm}", (SBB64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"sub{q}\t{$imm, %rax|rax, $imm}", (SUB64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"xor{q}\t{$imm, %rax|rax, $imm}", (XOR64ri8 RAX, i64i8imm:$imm), 0>; diff --git a/suite/synctools/tablegen/X86/X86InstrInfo_reduce.td b/suite/synctools/tablegen/X86/X86InstrInfo_reduce.td deleted file mode 100644 index 2237c9c28b..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrInfo_reduce.td +++ /dev/null @@ -1,3582 +0,0 @@ -//===-- X86InstrInfo.td - Main X86 Instruction Definition --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instruction set, defining the instructions, and -// properties of the instructions which are needed for code generation, machine -// code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 specific DAG Nodes. -// - -def SDTIntShiftDOp: SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisInt<3>]>; - -def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<1, 2>]>; - -def SDTX86Cmps : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; -//def SDTX86Cmpss : SDTypeProfile<1, 3, [SDTCisVT<0, f32>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; - -def SDTX86Cmov : SDTypeProfile<1, 4, - [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -// Unary and binary operator instructions that set EFLAGS as a side-effect. -def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, - [SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS -def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<4, i32>]>; -// RES1, RES2, FLAGS = op LHS, RHS -def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; -def SDTX86BrCond : SDTypeProfile<0, 3, - [SDTCisVT<0, OtherVT>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86SetCC : SDTypeProfile<1, 2, - [SDTCisVT<0, i8>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; -def SDTX86SetCC_C : SDTypeProfile<1, 2, - [SDTCisInt<0>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; - -def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, - SDTCisVT<2, i8>]>; -def SDTX86caspair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86caspairSaveEbx8 : SDTypeProfile<1, 3, - [SDTCisVT<0, i32>, SDTCisPtrTy<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; -def SDTX86caspairSaveRbx16 : SDTypeProfile<1, 3, - [SDTCisVT<0, i64>, SDTCisPtrTy<1>, - SDTCisVT<2, i64>, SDTCisVT<3, i64>]>; - -def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, - SDTCisInt<2>]>; - -def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>]>; - -def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; - -def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; -def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; - -def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, - SDTCisVT<1, iPTR>, - SDTCisVT<2, iPTR>]>; - -def SDT_X86VAARG_64 : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; - -def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; - -def SDTX86Void : SDTypeProfile<0, 0, []>; - -def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - -def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86WIN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; - -def SDT_X86MEMBARRIER : SDTypeProfile<0, 0, []>; - -def X86MemBarrier : SDNode<"X86ISD::MEMBARRIER", SDT_X86MEMBARRIER, - [SDNPHasChain,SDNPSideEffect]>; -def X86MFence : SDNode<"X86ISD::MFENCE", SDT_X86MEMBARRIER, - [SDNPHasChain]>; - - -def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; -def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; -def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; -def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; - -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; -def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; - -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, - [SDNPHasChain]>; -def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; - -def X86sahf : SDNode<"X86ISD::SAHF", SDTX86sahf>; - -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8save_ebx : SDNode<"X86ISD::LCMPXCHG8_SAVE_EBX_DAG", - SDTX86caspairSaveEbx8, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def X86cas16save_rbx : SDNode<"X86ISD::LCMPXCHG16_SAVE_RBX_DAG", - SDTX86caspairSaveRbx16, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; - -def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue]>; - -def X86vastart_save_xmm_regs : - SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", - SDT_X86VASTART_SAVE_XMM_REGS, - [SDNPHasChain, SDNPVariadic]>; -def X86vaarg64 : - SDNode<"X86ISD::VAARG_64", SDT_X86VAARG_64, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86callseq_start : - SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def X86callseq_end : - SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; -def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, - [SDNPHasChain]>; - -def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; -def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad]>; - -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdtscp : SDNode<"X86ISD::RDTSCP_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdpmc : SDNode<"X86ISD::RDPMC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; - -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; -def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; - -def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", - SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, - SDTCisInt<1>]>>; - -def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, - [SDNPHasChain]>; - -def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", - SDTypeProfile<1, 1, [SDTCisInt<0>, - SDTCisPtrTy<1>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", - SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", - SDTypeProfile<0, 0, []>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; -def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, - [SDNPCommutative]>; -def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; -def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; - -def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>; -def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>; -def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, - [SDNPCommutative]>; - -def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86lock_inc : SDNode<"X86ISD::LINC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_dec : SDNode<"X86ISD::LDEC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; - -def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; - -def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA, - [SDNPHasChain, SDNPOutGlue]>; - -def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, - [SDNPHasChain]>; - -def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86lwpins : SDNode<"X86ISD::LWPINS", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; - -def X86umwait : SDNode<"X86ISD::UMWAIT", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tpause : SDNode<"X86ISD::TPAUSE", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -//===----------------------------------------------------------------------===// -// X86 Operand Definitions. -// - -// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for -// the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; - -// *mem - Operand definitions for the funky X86 addressing mode operands. -// -def X86MemAsmOperand : AsmOperandClass { - let Name = "Mem"; -} -let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { - def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } - def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } - def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } - def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } - def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } - def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } - def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } - def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } - // Gather mem operands - def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } - def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } - def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } - def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } - def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } - - def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } - def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } - def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } - def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } - def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } - def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } - def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } - def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } -} - -def X86AbsMemAsmOperand : AsmOperandClass { - let Name = "AbsMem"; - let SuperClasses = [X86MemAsmOperand]; -} - -class X86MemOperand : Operand { - let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = parserMatchClass; - let OperandType = "OPERAND_MEMORY"; -} - -// Gather mem operands -class X86VMemOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); -} - -def anymem : X86MemOperand<"printanymem">; - -// FIXME: Right now we allow any size during parsing, but we might want to -// restrict to only unsized memory. -def opaquemem : X86MemOperand<"printopaquemem">; - -def i8mem : X86MemOperand<"printi8mem", X86Mem8AsmOperand>; -def i16mem : X86MemOperand<"printi16mem", X86Mem16AsmOperand>; -def i32mem : X86MemOperand<"printi32mem", X86Mem32AsmOperand>; -def i64mem : X86MemOperand<"printi64mem", X86Mem64AsmOperand>; -def i128mem : X86MemOperand<"printi128mem", X86Mem128AsmOperand>; -def i256mem : X86MemOperand<"printi256mem", X86Mem256AsmOperand>; -def i512mem : X86MemOperand<"printi512mem", X86Mem512AsmOperand>; -def f32mem : X86MemOperand<"printf32mem", X86Mem32AsmOperand>; -def f64mem : X86MemOperand<"printf64mem", X86Mem64AsmOperand>; -def f80mem : X86MemOperand<"printf80mem", X86Mem80AsmOperand>; -def f128mem : X86MemOperand<"printf128mem", X86Mem128AsmOperand>; -def f256mem : X86MemOperand<"printf256mem", X86Mem256AsmOperand>; -def f512mem : X86MemOperand<"printf512mem", X86Mem512AsmOperand>; - -def v512mem : X86VMemOperand; - -// Gather mem operands -def vx64mem : X86VMemOperand; -def vx128mem : X86VMemOperand; -def vx256mem : X86VMemOperand; -def vy128mem : X86VMemOperand; -def vy256mem : X86VMemOperand; - -def vx64xmem : X86VMemOperand; -def vx128xmem : X86VMemOperand; -def vx256xmem : X86VMemOperand; -def vy128xmem : X86VMemOperand; -def vy256xmem : X86VMemOperand; -def vy512xmem : X86VMemOperand; -def vz256mem : X86VMemOperand; -def vz512mem : X86VMemOperand; - -// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead -// of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; - -def i8mem_NOREX : Operand { - let PrintMethod = "printi8mem"; - let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, - SEGMENT_REG); - let ParserMatchClass = X86Mem8AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// GPRs available for tailcall. -// It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; - -// Special i32mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i32mem_TC : Operand { - let PrintMethod = "printi32mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, - i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// Special i64mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i64mem_TC : Operand { - let PrintMethod = "printi64mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, - ptr_rc_tailcall, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -let OperandType = "OPERAND_PCREL", - ParserMatchClass = X86AbsMemAsmOperand, - PrintMethod = "printPCRelImm" in { -def i32imm_pcrel : Operand; -def i16imm_pcrel : Operand; - -// Branch targets have OtherVT type and print as pc-relative values. -def brtarget : Operand; -def brtarget8 : Operand; - -} - -// Special parser to detect 16-bit mode to select 16-bit displacement. -def X86AbsMem16AsmOperand : AsmOperandClass { - let Name = "AbsMem16"; - let RenderMethod = "addAbsMemOperands"; - let SuperClasses = [X86AbsMemAsmOperand]; -} - -// Branch targets have OtherVT type and print as pc-relative values. -let OperandType = "OPERAND_PCREL", - PrintMethod = "printPCRelImm" in { -let ParserMatchClass = X86AbsMem16AsmOperand in - def brtarget16 : Operand; -let ParserMatchClass = X86AbsMemAsmOperand in - def brtarget32 : Operand; -} - -let RenderMethod = "addSrcIdxOperands" in { - def X86SrcIdx8Operand : AsmOperandClass { - let Name = "SrcIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86SrcIdx16Operand : AsmOperandClass { - let Name = "SrcIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86SrcIdx32Operand : AsmOperandClass { - let Name = "SrcIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86SrcIdx64Operand : AsmOperandClass { - let Name = "SrcIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addSrcIdxOperands" - -let RenderMethod = "addDstIdxOperands" in { - def X86DstIdx8Operand : AsmOperandClass { - let Name = "DstIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86DstIdx16Operand : AsmOperandClass { - let Name = "DstIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86DstIdx32Operand : AsmOperandClass { - let Name = "DstIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86DstIdx64Operand : AsmOperandClass { - let Name = "DstIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addDstIdxOperands" - -let RenderMethod = "addMemOffsOperands" in { - def X86MemOffs16_8AsmOperand : AsmOperandClass { - let Name = "MemOffs16_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs16_16AsmOperand : AsmOperandClass { - let Name = "MemOffs16_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs16_32AsmOperand : AsmOperandClass { - let Name = "MemOffs16_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_8AsmOperand : AsmOperandClass { - let Name = "MemOffs32_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs32_16AsmOperand : AsmOperandClass { - let Name = "MemOffs32_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs32_32AsmOperand : AsmOperandClass { - let Name = "MemOffs32_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_64AsmOperand : AsmOperandClass { - let Name = "MemOffs32_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } - def X86MemOffs64_8AsmOperand : AsmOperandClass { - let Name = "MemOffs64_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs64_16AsmOperand : AsmOperandClass { - let Name = "MemOffs64_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs64_32AsmOperand : AsmOperandClass { - let Name = "MemOffs64_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs64_64AsmOperand : AsmOperandClass { - let Name = "MemOffs64_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addMemOffsOperands" - -class X86SrcIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); -} - -class X86DstIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc); -} - -def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; -def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; -def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; -def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; -def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; -def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; -def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; -def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; - -class X86MemOffsOperand - : X86MemOperand { - let MIOperandInfo = (ops immOperand, SEGMENT_REG); -} - -def offset16_8 : X86MemOffsOperand; -def offset16_16 : X86MemOffsOperand; -def offset16_32 : X86MemOffsOperand; -def offset32_8 : X86MemOffsOperand; -def offset32_16 : X86MemOffsOperand; -def offset32_32 : X86MemOffsOperand; -def offset32_64 : X86MemOffsOperand; -def offset64_8 : X86MemOffsOperand; -def offset64_16 : X86MemOffsOperand; -def offset64_32 : X86MemOffsOperand; -def offset64_64 : X86MemOffsOperand; - -def SSECC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVXCC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVX512ICC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def XOPCC : Operand { - let PrintMethod = "printXOPCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -class ImmSExtAsmOperandClass : AsmOperandClass { - let SuperClasses = [ImmAsmOperand]; - let RenderMethod = "addImmOperands"; -} - -def X86GR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR32orGR64"; -} - -def GR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR32orGR64AsmOperand; -} -def AVX512RCOperand : AsmOperandClass { - let Name = "AVX512RC"; -} -def AVX512RC : Operand { - let PrintMethod = "printRoundingControl"; - let OperandType = "OPERAND_IMMEDIATE"; - let ParserMatchClass = AVX512RCOperand; -} - -// Sign-extended immediate classes. We don't need to define the full lattice -// here because there is no instruction with an ambiguity between ImmSExti64i32 -// and ImmSExti32i8. -// -// The strange ranges come from the fact that the assembler always works with -// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" -// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). - -// [0, 0x7FFFFFFF] | -// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i32"; -} - -// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti16i8"; - let SuperClasses = [ImmSExti64i32AsmOperand]; -} - -// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti32i8"; -} - -// [0, 0x0000007F] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i8"; - let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, - ImmSExti64i32AsmOperand]; -} - -// Unsigned immediate used by SSE/AVX instructions -// [0, 0xFF] -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmUnsignedi8AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi8"; - let RenderMethod = "addImmOperands"; -} - -// A couple of more descriptive operand definitions. -// 16-bits but only 8 bits are significant. -def i16i8imm : Operand { - let ParserMatchClass = ImmSExti16i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} -// 32-bits but only 8 bits are significant. -def i32i8imm : Operand { - let ParserMatchClass = ImmSExti32i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant. -def i64i32imm : Operand { - let ParserMatchClass = ImmSExti64i32AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 8 bits are significant. -def i64i8imm : Operand { - let ParserMatchClass = ImmSExti64i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 8-bit immediate used by SSE/AVX instructions. -def u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 32-bit immediate but only 8-bits are significant and they are unsigned. -// Used by some SSE/AVX instructions that use intrinsics. -def i32u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant, and those bits are treated as being -// pc relative. -def i64i32imm_pcrel : Operand { - let PrintMethod = "printPCRelImm"; - let ParserMatchClass = X86AbsMemAsmOperand; - let OperandType = "OPERAND_PCREL"; -} - -def lea64_32mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -// Memory operands that use 64-bit pointers in both ILP32 and LP64. -def lea64mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - - -//===----------------------------------------------------------------------===// -// X86 Complex Pattern Definitions. -// - -// Define X86-specific addressing mode. -def addr : ComplexPattern; -def lea32addr : ComplexPattern; -// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. -def lea64_32addr : ComplexPattern; - -def tls32addr : ComplexPattern; - -def tls32baseaddr : ComplexPattern; - -def lea64addr : ComplexPattern; - -def tls64addr : ComplexPattern; - -def tls64baseaddr : ComplexPattern; - -def vectoraddr : ComplexPattern; - -// A relocatable immediate is either an immediate operand or an operand that can -// be relocated by the linker to an immediate, such as a regular symbol in -// non-PIC code. -def relocImm : ComplexPattern; - -//===----------------------------------------------------------------------===// -// X86 Instruction Predicate Definitions. -def TruePredicate : Predicate<"true">; - -def HasCMov : Predicate<"Subtarget->hasCMov()">; -def NoCMov : Predicate<"!Subtarget->hasCMov()">; - -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def Has3DNow : Predicate<"Subtarget->has3DNow()">; -def Has3DNowA : Predicate<"Subtarget->has3DNowA()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; -def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; -def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; -def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; -def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; -def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; -def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; -def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; -def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; -def NoAVX : Predicate<"!Subtarget->hasAVX()">; -def HasAVX : Predicate<"Subtarget->hasAVX()">; -def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; -def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; -def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; -def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; -def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; -def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; -def HasCDI : Predicate<"Subtarget->hasCDI()">; -def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; -def HasPFI : Predicate<"Subtarget->hasPFI()">; -def HasERI : Predicate<"Subtarget->hasERI()">; -def HasDQI : Predicate<"Subtarget->hasDQI()">; -def NoDQI : Predicate<"!Subtarget->hasDQI()">; -def HasBWI : Predicate<"Subtarget->hasBWI()">; -def NoBWI : Predicate<"!Subtarget->hasBWI()">; -def HasVLX : Predicate<"Subtarget->hasVLX()">; -def NoVLX : Predicate<"!Subtarget->hasVLX()">; -def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; -def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; -def PKU : Predicate<"Subtarget->hasPKU()">; -def HasVNNI : Predicate<"Subtarget->hasVNNI()">; - -def HasBITALG : Predicate<"Subtarget->hasBITALG()">; -def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; -def HasAES : Predicate<"Subtarget->hasAES()">; -def HasVAES : Predicate<"Subtarget->hasVAES()">; -def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; -def HasFXSR : Predicate<"Subtarget->hasFXSR()">; -def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; -def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; -def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; -def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; -def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; -def NoVLX_Or_NoVPCLMULQDQ : - Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; -def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; -def HasGFNI : Predicate<"Subtarget->hasGFNI()">; -def HasFMA : Predicate<"Subtarget->hasFMA()">; -def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; -def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; -def HasXOP : Predicate<"Subtarget->hasXOP()">; -def HasTBM : Predicate<"Subtarget->hasTBM()">; -def NoTBM : Predicate<"!Subtarget->hasTBM()">; -def HasLWP : Predicate<"Subtarget->hasLWP()">; -def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; -def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; -def HasF16C : Predicate<"Subtarget->hasF16C()">; -def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; -def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; -def HasBMI : Predicate<"Subtarget->hasBMI()">; -def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; -def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; -def HasVBMI : Predicate<"Subtarget->hasVBMI()">; -def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; -def HasIFMA : Predicate<"Subtarget->hasIFMA()">; -def HasRTM : Predicate<"Subtarget->hasRTM()">; -def HasADX : Predicate<"Subtarget->hasADX()">; -def HasSHA : Predicate<"Subtarget->hasSHA()">; -def HasSGX : Predicate<"Subtarget->hasSGX()">; -def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; -def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; -def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; -def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; -def HasPrefetchW : Predicate<"Subtarget->hasPRFCHW()">; -def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; -def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; -def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; -def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; -def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; -def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; -def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; -def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; -def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; -def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; -def HasMPX : Predicate<"Subtarget->hasMPX()">; -def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; -def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; -def HasCLWB : Predicate<"Subtarget->hasCLWB()">; -def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; -def HasRDPID : Predicate<"Subtarget->hasRDPID()">; -def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; -def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; -def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; -def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; -def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, - AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, - AssemblerPredicate<"Mode64Bit", "64-bit mode">; -def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; -def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; -def In16BitMode : Predicate<"Subtarget->is16Bit()">, - AssemblerPredicate<"Mode16Bit", "16-bit mode">; -def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, - AssemblerPredicate<"!Mode16Bit", "Not 16-bit mode">; -def In32BitMode : Predicate<"Subtarget->is32Bit()">, - AssemblerPredicate<"Mode32Bit", "32-bit mode">; -def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; -def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; -def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" - "Subtarget->getFrameLowering()->hasFP(*MF)"> { - let RecomputePerFunction = 1; -} -def IsPS4 : Predicate<"Subtarget->isTargetPS4()">; -def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">; -def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; -def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; -def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; -def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" - "TM.getCodeModel() == CodeModel::Kernel">; -def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; - -// We could compute these on a per-module basis but doing so requires accessing -// the Function object through the Subtarget and objections were raised -// to that (see post-commit review comments for r301750). -let RecomputePerFunction = 1 in { - def OptForSize : Predicate<"MF->getFunction().optForSize()">; - def OptForMinSize : Predicate<"MF->getFunction().optForMinSize()">; - def OptForSpeed : Predicate<"!MF->getFunction().optForSize()">; - def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " - "MF->getFunction().optForSize()">; - def NoSSE41_Or_OptForSize : Predicate<"MF->getFunction().optForSize() || " - "!Subtarget->hasSSE41()">; -} - -def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; -def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; -def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; -def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; -def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; -def HasERMSB : Predicate<"Subtarget->hasERMSB()">; -def HasMFence : Predicate<"Subtarget->hasMFence()">; -def UseRetpoline : Predicate<"Subtarget->useRetpoline()">; -def NotUseRetpoline : Predicate<"!Subtarget->useRetpoline()">; - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -include "X86InstrFormats.td" - -//===----------------------------------------------------------------------===// -// Pattern fragments. -// - -// X86 specific condition code. These correspond to CondCode in -// X86InstrInfo.h. They must be kept in synch. -def X86_COND_A : PatLeaf<(i8 0)>; // alt. COND_NBE -def X86_COND_AE : PatLeaf<(i8 1)>; // alt. COND_NC -def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C -def X86_COND_BE : PatLeaf<(i8 3)>; // alt. COND_NA -def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z -def X86_COND_G : PatLeaf<(i8 5)>; // alt. COND_NLE -def X86_COND_GE : PatLeaf<(i8 6)>; // alt. COND_NL -def X86_COND_L : PatLeaf<(i8 7)>; // alt. COND_NGE -def X86_COND_LE : PatLeaf<(i8 8)>; // alt. COND_NG -def X86_COND_NE : PatLeaf<(i8 9)>; // alt. COND_NZ -def X86_COND_NO : PatLeaf<(i8 10)>; -def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO -def X86_COND_NS : PatLeaf<(i8 12)>; -def X86_COND_O : PatLeaf<(i8 13)>; -def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE -def X86_COND_S : PatLeaf<(i8 15)>; - -def i16immSExt8 : ImmLeaf(Imm); }]>; -def i32immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt32 : ImmLeaf(Imm); }]>; - -// FIXME: Ideally we would just replace the above i*immSExt* matchers with -// relocImm-based matchers, but then FastISel would be unable to use them. -def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<8>(N); -}]>; -def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<32>(N); -}]>; - -// If we have multiple users of an immediate, it's much smaller to reuse -// the register, rather than encode the immediate in every instruction. -// This has the risk of increasing register pressure from stretched live -// ranges, however, the immediates should be trivial to rematerialize by -// the RA in the event of high register pressure. -// TODO : This is currently enabled for stores and binary ops. There are more -// cases for which this can be enabled, though this catches the bulk of the -// issues. -// TODO2 : This should really also be enabled under O2, but there's currently -// an issue with RA where we don't pull the constants into their users -// when we rematerialize them. I'll follow-up on enabling O2 after we fix that -// issue. -// TODO3 : This is currently limited to single basic blocks (DAG creation -// pulls block immediates to the top and merges them if necessary). -// Eventually, it would be nice to allow ConstantHoisting to merge constants -// globally for potentially added savings. -// -def imm8_su : PatLeaf<(i8 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm16_su : PatLeaf<(i16 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm32_su : PatLeaf<(i32 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit -// unsigned field. -def i64immZExt32 : ImmLeaf(Imm); }]>; - -def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); -}]>; - -// Helper fragments for loads. - -// It's safe to fold a zextload/extload from i1 as a regular i8 load. The -// upper bits are guaranteed to be zero and we were going to emit a MOV8rm -// which might get folded during peephole anyway. -def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || - ExtType == ISD::ZEXTLOAD; -}]>; - -// It's always safe to treat a anyext i16 load as a i32 load if the i16 is -// known to be 32-bit aligned or better. Ditto for i8 to i16. -def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 2 && !LD->isVolatile(); - return false; -}]>; - -def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 4 && !LD->isVolatile(); - return false; -}]>; - -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; -def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; -def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; -def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; -def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; -def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; -def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; -def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; -def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; - -def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; -def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; -def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; -def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; -def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; -def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; -def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; -def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; -def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; -def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; - -def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; -def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; -def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; -def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; -def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>; - - -// An 'and' node with a single use. -def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'srl' node with a single use. -def srl_su : PatFrag<(ops node:$lhs, node:$rhs), (srl node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'trunc' node with a single use. -def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ - return N->hasOneUse(); -}]>; - -//===----------------------------------------------------------------------===// -// Instruction list. -// - -// Nop -let hasSideEffects = 0, SchedRW = [WriteNop] in { - def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; - def NOOPW : I<0x1f, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPL : I<0x1f, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQ : RI<0x1f, MRMXm, (outs), (ins i64mem:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - // Also allow register so we can assemble/disassemble - def NOOPWr : I<0x1f, MRMXr, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPLr : I<0x1f, MRMXr, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQr : RI<0x1f, MRMXr, (outs), (ins GR64:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - def NOOPW_19 : I<0x19, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_19 : I<0x19, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1a : I<0x1a, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1a : I<0x1a, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1b : I<0x1b, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1b : I<0x1b, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1c : I<0x1c, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1c : I<0x1c, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1d : I<0x1d, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1d : I<0x1d, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1e : I<0x1e, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1e : I<0x1e, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m4 : I<0x18, MRM4m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m4 : I<0x18, MRM4m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r4 : I<0x18, MRM4r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r4 : I<0x18, MRM4r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m5 : I<0x18, MRM5m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m5 : I<0x18, MRM5m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r5 : I<0x18, MRM5r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r5 : I<0x18, MRM5r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m6 : I<0x18, MRM6m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m6 : I<0x18, MRM6m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r6 : I<0x18, MRM6r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r6 : I<0x18, MRM6r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m7 : I<0x18, MRM7m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m7 : I<0x18, MRM7m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r7 : I<0x18, MRM7r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r7 : I<0x18, MRM7r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; -} - - -// Constructing a stack frame. -def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl), - "enter\t$len, $lvl", []>, Sched<[WriteMicrocoded]>; - -let SchedRW = [WriteALU] in { -let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, hasSideEffects=0 in -def LEAVE : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[Not64BitMode]>; - -let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, hasSideEffects = 0 in -def LEAVE64 : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Miscellaneous Instructions. -// - -/* -let isBarrier = 1, hasSideEffects = 1, usesCustomInserter = 1, - SchedRW = [WriteSystem] in - def Int_eh_sjlj_setup_dispatch - : PseudoI<(outs), (ins), [(X86eh_sjlj_setup_dispatch)]>; -*/ - -let Defs = [ESP], Uses = [ESP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP16r : I<0x58, AddRegFrm, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16; -def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP16rmr: I<0x8F, MRM0r, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16, NotMemoryFoldable; -def POP32rmr: I<0x8F, MRM0r, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayStore = 1, mayLoad = 1, SchedRW = [WriteRMW] in { -def POP16rmm: I<0x8F, MRM0m, (outs), (ins i16mem:$dst), "pop{w}\t$dst", []>, - OpSize16; -def POP32rmm: I<0x8F, MRM0m, (outs), (ins i32mem:$dst), "pop{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayStore, mayLoad, WriteRMW - -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH16r : I<0x50, AddRegFrm, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16; -def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH16rmr: I<0xFF, MRM6r, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16, NotMemoryFoldable; -def PUSH32rmr: I<0xFF, MRM6r, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 - -def PUSH16i8 : Ii8<0x6a, RawFrm, (outs), (ins i16i8imm:$imm), - "push{w}\t$imm", []>, OpSize16; -def PUSHi16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), - "push{w}\t$imm", []>, OpSize16; - -def PUSH32i8 : Ii8<0x6a, RawFrm, (outs), (ins i32i8imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -def PUSHi32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -} // mayStore, SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH16rmm: I<0xFF, MRM6m, (outs), (ins i16mem:$src), "push{w}\t$src", []>, - OpSize16; -def PUSH32rmm: I<0xFF, MRM6m, (outs), (ins i32mem:$src), "push{l}\t$src", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayLoad, mayStore, SchedRW - -} - -/* -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW], Defs = [ESP] in { - let Uses = [ESP] in - def RDFLAGS32 : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_flags_read_u32))]>, - Requires<[Not64BitMode]>; - - let Uses = [RSP] in - def RDFLAGS64 : PseudoI<(outs GR64:$dst), (ins), - [(set GR64:$dst, (int_x86_flags_read_u64))]>, - Requires<[In64BitMode]>; -} - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW] in { - let Defs = [ESP, EFLAGS, DF], Uses = [ESP] in - def WRFLAGS32 : PseudoI<(outs), (ins GR32:$src), - [(int_x86_flags_write_u32 GR32:$src)]>, - Requires<[Not64BitMode]>; - - let Defs = [RSP, EFLAGS, DF], Uses = [RSP] in - def WRFLAGS64 : PseudoI<(outs), (ins GR64:$src), - [(int_x86_flags_write_u64 GR64:$src)]>, - Requires<[In64BitMode]>; -} -*/ - -let Defs = [ESP, EFLAGS, DF], Uses = [ESP], mayLoad = 1, hasSideEffects=0, - SchedRW = [WriteLoad] in { -def POPF16 : I<0x9D, RawFrm, (outs), (ins), "popf{w}", []>, OpSize16; -def POPF32 : I<0x9D, RawFrm, (outs), (ins), "popf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [ESP], Uses = [ESP, EFLAGS, DF], mayStore = 1, hasSideEffects=0, - SchedRW = [WriteStore] in { -def PUSHF16 : I<0x9C, RawFrm, (outs), (ins), "pushf{w}", []>, OpSize16; -def PUSHF32 : I<0x9C, RawFrm, (outs), (ins), "pushf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in -def POP64rmm: I<0x8F, MRM0m, (outs), (ins i64mem:$dst), "pop{q}\t$dst", []>, - OpSize32, Requires<[In64BitMode]>; -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayStore, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>, - OpSize32, Requires<[In64BitMode]>; -} // mayLoad, mayStore, SchedRW -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects = 0, mayStore = 1, - SchedRW = [WriteStore] in { -def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -def PUSH64i32 : Ii32S<0x68, RawFrm, (outs), (ins i64i32imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -} - -let Defs = [RSP, EFLAGS, DF], Uses = [RSP], mayLoad = 1, hasSideEffects=0 in -def POPF64 : I<0x9D, RawFrm, (outs), (ins), "popfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteLoad]>; -let Defs = [RSP], Uses = [RSP, EFLAGS, DF], mayStore = 1, hasSideEffects=0 in -def PUSHF64 : I<0x9C, RawFrm, (outs), (ins), "pushfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteStore]>; - -let Defs = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], Uses = [ESP], - mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteLoad] in { -def POPA32 : I<0x61, RawFrm, (outs), (ins), "popal", []>, - OpSize32, Requires<[Not64BitMode]>; -def POPA16 : I<0x61, RawFrm, (outs), (ins), "popaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} -let Defs = [ESP], Uses = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], - mayStore = 1, hasSideEffects = 0, SchedRW = [WriteStore] in { -def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pushal", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHA16 : I<0x60, RawFrm, (outs), (ins), "pushaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} - -let Constraints = "$src = $dst", SchedRW = [WriteBSWAP32] in { -// This instruction is a consequence of BSWAP32r observing operand size. The -// encoding is valid, but the behavior is undefined. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in -def BSWAP16r_BAD : I<0xC8, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "bswap{w}\t$dst", []>, OpSize16, TB; -// GR32 = bswap GR32 -def BSWAP32r : I<0xC8, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "bswap{l}\t$dst", - [(set GR32:$dst, (bswap GR32:$src))]>, OpSize32, TB; - -let SchedRW = [WriteBSWAP64] in -def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "bswap{q}\t$dst", - [(set GR64:$dst, (bswap GR64:$src))]>, TB; -} // Constraints = "$src = $dst", SchedRW - -// Bit scan instructions. -let Defs = [EFLAGS] in { -def BSF16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSF]>; -def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSFLd]>; -def BSF32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSF]>; -def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSFLd]>; -def BSF64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf GR64:$src))]>, - PS, Sched<[WriteBSF]>; -def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSFLd]>; - -def BSR16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSR]>; -def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSRLd]>; -def BSR32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSR]>; -def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSRLd]>; -def BSR64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr GR64:$src))]>, - PS, Sched<[WriteBSR]>; -def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSRLd]>; -} // Defs = [EFLAGS] - -let SchedRW = [WriteMicrocoded] in { -let Defs = [EDI,ESI], Uses = [EDI,ESI,DF] in { -def MOVSB : I<0xA4, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "movsb\t{$src, $dst|$dst, $src}", []>; -def MOVSW : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "movsw\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOVSL : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "movs{l|d}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOVSQ : RI<0xA5, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "movsq\t{$src, $dst|$dst, $src}", []>, - Requires<[In64BitMode]>; -} - -let Defs = [EDI], Uses = [AL,EDI,DF] in -def STOSB : I<0xAA, RawFrmDst, (outs), (ins dstidx8:$dst), - "stosb\t{%al, $dst|$dst, al}", []>; -let Defs = [EDI], Uses = [AX,EDI,DF] in -def STOSW : I<0xAB, RawFrmDst, (outs), (ins dstidx16:$dst), - "stosw\t{%ax, $dst|$dst, ax}", []>, OpSize16; -let Defs = [EDI], Uses = [EAX,EDI,DF] in -def STOSL : I<0xAB, RawFrmDst, (outs), (ins dstidx32:$dst), - "stos{l|d}\t{%eax, $dst|$dst, eax}", []>, OpSize32; -let Defs = [RDI], Uses = [RAX,RDI,DF] in -def STOSQ : RI<0xAB, RawFrmDst, (outs), (ins dstidx64:$dst), - "stosq\t{%rax, $dst|$dst, rax}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,EFLAGS], Uses = [AL,EDI,DF] in -def SCASB : I<0xAE, RawFrmDst, (outs), (ins dstidx8:$dst), - "scasb\t{$dst, %al|al, $dst}", []>; -let Defs = [EDI,EFLAGS], Uses = [AX,EDI,DF] in -def SCASW : I<0xAF, RawFrmDst, (outs), (ins dstidx16:$dst), - "scasw\t{$dst, %ax|ax, $dst}", []>, OpSize16; -let Defs = [EDI,EFLAGS], Uses = [EAX,EDI,DF] in -def SCASL : I<0xAF, RawFrmDst, (outs), (ins dstidx32:$dst), - "scas{l|d}\t{$dst, %eax|eax, $dst}", []>, OpSize32; -let Defs = [EDI,EFLAGS], Uses = [RAX,EDI,DF] in -def SCASQ : RI<0xAF, RawFrmDst, (outs), (ins dstidx64:$dst), - "scasq\t{$dst, %rax|rax, $dst}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,ESI,EFLAGS], Uses = [EDI,ESI,DF] in { -def CMPSB : I<0xA6, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "cmpsb\t{$dst, $src|$src, $dst}", []>; -def CMPSW : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "cmpsw\t{$dst, $src|$src, $dst}", []>, OpSize16; -def CMPSL : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "cmps{l|d}\t{$dst, $src|$src, $dst}", []>, OpSize32; -def CMPSQ : RI<0xA7, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "cmpsq\t{$dst, $src|$src, $dst}", []>, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Move Instructions. -// -let SchedRW = [WriteMove] in { -let hasSideEffects = 0, isMoveReg = 1 in { -def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>; -def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, imm:$src)]>, OpSize16; -def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, relocImm:$src)]>, OpSize32; -def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, i64immSExt32:$src)]>; -} -let isReMaterializable = 1 in { -def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), - "movabs{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, relocImm:$src)]>; -} - -// Longer forms that use a ModR/M byte. Needed for disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOV8ri_alt : Ii8 <0xC6, MRM0r, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8ri">; -def MOV16ri_alt : Ii16<0xC7, MRM0r, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16ri">; -def MOV32ri_alt : Ii32<0xC7, MRM0r, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32ri">; -} -} // SchedRW - -let SchedRW = [WriteStore] in { -def MOV8mi : Ii8 <0xC6, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store (i8 imm8_su:$src), addr:$dst)]>; -def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store (i16 imm16_su:$src), addr:$dst)]>, OpSize16; -def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store (i32 imm32_su:$src), addr:$dst)]>, OpSize32; -def MOV64mi32 : RIi32S<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store i64immSExt32_su:$src, addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { - -/// Memory offset versions of moves. The immediate is an address mode sized -/// offset from the segment base. -let SchedRW = [WriteALU] in { -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao32 : Ii32<0xA0, RawFrmMemOffs, (outs), (ins offset32_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, - AdSize32; -let Defs = [AX] in -def MOV16ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize32; -let Defs = [EAX] in -def MOV32ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize32; -let Defs = [RAX] in -def MOV64ao32 : RIi32<0xA1, RawFrmMemOffs, (outs), (ins offset32_64:$src), - "mov{q}\t{$src, %rax|rax, $src}", []>, - AdSize32; - -let Defs = [AL] in -def MOV8ao16 : Ii16<0xA0, RawFrmMemOffs, (outs), (ins offset16_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, AdSize16; -let Defs = [AX] in -def MOV16ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize16; -let Defs = [EAX] in -def MOV32ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - AdSize16, OpSize32; -} // mayLoad -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o32a : Ii32<0xA2, RawFrmMemOffs, (outs), (ins offset32_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize32; -let Uses = [AX] in -def MOV16o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize32; -let Uses = [EAX] in -def MOV32o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize32; -let Uses = [RAX] in -def MOV64o32a : RIi32<0xA3, RawFrmMemOffs, (outs), (ins offset32_64:$dst), - "mov{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize32; - -let Uses = [AL] in -def MOV8o16a : Ii16<0xA2, RawFrmMemOffs, (outs), (ins offset16_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize16; -let Uses = [AX] in -def MOV16o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize16; -let Uses = [EAX] in -def MOV32o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize16; -} // mayStore - -// These forms all have full 64-bit absolute addresses in their instructions -// and use the movabs mnemonic to indicate this specific form. -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao64 : Ii64<0xA0, RawFrmMemOffs, (outs), (ins offset64_8:$src), - "movabs{b}\t{$src, %al|al, $src}", []>, - AdSize64; -let Defs = [AX] in -def MOV16ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_16:$src), - "movabs{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize64; -let Defs = [EAX] in -def MOV32ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_32:$src), - "movabs{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize64; -let Defs = [RAX] in -def MOV64ao64 : RIi64<0xA1, RawFrmMemOffs, (outs), (ins offset64_64:$src), - "movabs{q}\t{$src, %rax|rax, $src}", []>, - AdSize64; -} // mayLoad - -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o64a : Ii64<0xA2, RawFrmMemOffs, (outs), (ins offset64_8:$dst), - "movabs{b}\t{%al, $dst|$dst, al}", []>, - AdSize64; -let Uses = [AX] in -def MOV16o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_16:$dst), - "movabs{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize64; -let Uses = [EAX] in -def MOV32o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_32:$dst), - "movabs{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize64; -let Uses = [RAX] in -def MOV64o64a : RIi64<0xA3, RawFrmMemOffs, (outs), (ins offset64_64:$dst), - "movabs{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize64; -} // mayStore -} // SchedRW -} // hasSideEffects = 0 - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [WriteMove], isMoveReg = 1 in { -def MOV8rr_REV : I<0x8A, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8rr">; -def MOV16rr_REV : I<0x8B, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16rr">; -def MOV32rr_REV : I<0x8B, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32rr">; -def MOV64rr_REV : RI<0x8B, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV64rr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -//// def : InstAlias<"mov{b}.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0>; -//// def : InstAlias<"mov{w}.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0>; -//// def : InstAlias<"mov{l}.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0>; -//// def : InstAlias<"mov{q}.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0>; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0, "att">; -//// def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0, "att">; - -let canFoldAsLoad = 1, isReMaterializable = 1, SchedRW = [WriteLoad] in { -def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, (loadi8 addr:$src))]>; -def MOV16rm : I<0x8B, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (loadi16 addr:$src))]>, OpSize16; -def MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (loadi32 addr:$src))]>, OpSize32; -def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (load addr:$src))]>; -} - -let SchedRW = [WriteStore] in { -def MOV8mr : I<0x88, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store GR16:$src, addr:$dst)]>, OpSize16; -def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store GR32:$src, addr:$dst)]>, OpSize32; -def MOV64mr : RI<0x89, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store GR64:$src, addr:$dst)]>; -} // SchedRW - -// Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so -// that they can be used for copying and storing h registers, which can't be -// encoded when a REX prefix is present. -let isCodeGenOnly = 1 in { -let hasSideEffects = 0, isMoveReg = 1 in -def MOV8rr_NOREX : I<0x88, MRMDestReg, - (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteMove]>; -let mayStore = 1, hasSideEffects = 0 in -def MOV8mr_NOREX : I<0x88, MRMDestMem, - (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteStore]>; -let mayLoad = 1, hasSideEffects = 0, - canFoldAsLoad = 1, isReMaterializable = 1 in -def MOV8rm_NOREX : I<0x8A, MRMSrcMem, - (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteLoad]>; -} - - -// Condition code ops, incl. set if equal/not equal/... -let SchedRW = [WriteLAHFSAHF] in { -let Defs = [EFLAGS], Uses = [AH] in -def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", - [(set EFLAGS, (X86sahf AH))]>, - Requires<[HasLAHFSAHF]>; -let Defs = [AH], Uses = [EFLAGS], hasSideEffects = 0 in -def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>, // AH = flags - Requires<[HasLAHFSAHF]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Bit tests instructions: BT, BTS, BTR, BTC. - -let Defs = [EFLAGS] in { -let SchedRW = [WriteBitTest] in { -def BT16rr : I<0xA3, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, GR16:$src2))]>, - OpSize16, TB, NotMemoryFoldable; -def BT32rr : I<0xA3, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, GR32:$src2))]>, - OpSize32, TB, NotMemoryFoldable; -def BT64rr : RI<0xA3, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, GR64:$src2))]>, TB, - NotMemoryFoldable; -} // SchedRW - -// Unlike with the register+register form, the memory+register form of the -// bt instruction does not ignore the high bits of the index. From ISel's -// perspective, this is pretty bizarre. Make these instructions disassembly -// only for now. These instructions are also slow on modern CPUs so that's -// another reason to avoid generating them. - -let mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteALULd] in { - def BT16mr : I<0xA3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - []>, OpSize16, TB, NotMemoryFoldable; - def BT32mr : I<0xA3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - []>, OpSize32, TB, NotMemoryFoldable; - def BT64mr : RI<0xA3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - []>, TB, NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest] in { -def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, i64immSExt8:$src2))]>, TB; -} // SchedRW - -// Note that these instructions aren't slow because that only applies when the -// other operand is in a register. When it's an immediate, bt is still fast. -let SchedRW = [WriteALU] in { -def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi64 addr:$src1), - i64immSExt8:$src2))]>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16rr : I<0xBB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32rr : I<0xBB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64rr : RI<0xBB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mr : I<0xBB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32mr : I<0xBB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64mr : RI<0xBB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16rr : I<0xB3, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32rr : I<0xB3, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64rr : RI<0xB3, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mr : I<0xB3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32mr : I<0xB3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64mr : RI<0xB3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16rr : I<0xAB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32rr : I<0xAB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64rr : RI<0xAB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mr : I<0xAB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32mr : I<0xAB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64mr : RI<0xAB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 -} // Defs = [EFLAGS] - - -//===----------------------------------------------------------------------===// -// Atomic support -// - -// Atomic swap. These are just normal xchg instructions. But since a memory -// operand is referenced, the atomicity is ensured. -multiclass ATOMIC_SWAP opc8, bits<8> opc, string mnemonic, string frag> { - let Constraints = "$val = $dst", SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8rm : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16rm : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32rm : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64rm : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm XCHG : ATOMIC_SWAP<0x86, 0x87, "xchg", "atomic_swap">, NotMemoryFoldable; - -// Swap between registers. -let SchedRW = [WriteALU] in { -let Constraints = "$src1 = $dst1, $src2 = $dst2", hasSideEffects = 0 in { -def XCHG8rr : I<0x86, MRMSrcReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xchg{b}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -def XCHG16rr : I<0x87, MRMSrcReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xchg{w}\t{$src1, $src2|$src2, $src1}", []>, - OpSize16, NotMemoryFoldable; -def XCHG32rr : I<0x87, MRMSrcReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xchg{l}\t{$src1, $src2|$src2, $src1}", []>, - OpSize32, NotMemoryFoldable; -def XCHG64rr : RI<0x87, MRMSrcReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1 ,GR64:$src2), - "xchg{q}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -} - -def NOOP19rr: I<0x19, MRMSrcReg, (outs), (ins GR32:$val, GR32:$src), - "nop\t{$val, $src|$src, $val}", []>, TB, - OpSize32; - -// Swap between EAX and other registers. -let Constraints = "$src = $dst", hasSideEffects = 0 in { -let Uses = [AX], Defs = [AX] in -def XCHG16ar : I<0x90, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "xchg{w}\t{%ax, $src|$src, ax}", []>, OpSize16; -let Uses = [EAX], Defs = [EAX] in -def XCHG32ar : I<0x90, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "xchg{l}\t{%eax, $src|$src, eax}", []>, OpSize32; -let Uses = [RAX], Defs = [RAX] in -def XCHG64ar : RI<0x90, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "xchg{q}\t{%rax, $src|$src, rax}", []>; -} -} // SchedRW - -let hasSideEffects = 0, Constraints = "$src1 = $dst1, $src2 = $dst2", - Defs = [EFLAGS], SchedRW = [WriteALU] in { -def XADD8rr : I<0xC0, MRMDestReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xadd{b}\t{$src2, $src1|$src1, $src2}", []>, TB; -def XADD16rr : I<0xC1, MRMDestReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xadd{w}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize16; -def XADD32rr : I<0xC1, MRMDestReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xadd{l}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize32; -def XADD64rr : RI<0xC1, MRMDestReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1, GR64:$src2), - "xadd{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, hasSideEffects = 0, Constraints = "$val = $dst", - Defs = [EFLAGS], SchedRW = [WriteALULd, WriteRMW] in { -def XADD8rm : I<0xC0, MRMSrcMem, (outs GR8:$dst), - (ins GR8:$val, i8mem:$ptr), - "xadd{b}\t{$val, $ptr|$ptr, $val}", []>, TB; -def XADD16rm : I<0xC1, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$val, i16mem:$ptr), - "xadd{w}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize16; -def XADD32rm : I<0xC1, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$val, i32mem:$ptr), - "xadd{l}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize32; -def XADD64rm : RI<0xC1, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$val, i64mem:$ptr), - "xadd{q}\t{$val, $ptr|$ptr, $val}", []>, TB; - -} - -let SchedRW = [WriteALU], hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rr : I<0xB0, MRMDestReg, (outs GR8:$dst), (ins GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rr : I<0xB1, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rr : I<0xB1, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rr : RI<0xB1, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -} // SchedRW, hasSideEffects - -let SchedRW = [WriteALULd, WriteRMW], mayLoad = 1, mayStore = 1, - hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rm : I<0xB0, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rm : I<0xB1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rm : I<0xB1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rm : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in -def CMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$dst), - "cmpxchg8b\t$dst", []>, TB; - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX] in -def CMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$dst), - "cmpxchg16b\t$dst", []>, - TB, Requires<[HasCmpxchg16b, In64BitMode]>; -} // SchedRW, mayLoad, mayStore, hasSideEffects - - -// Lock instruction prefix -let SchedRW = [WriteMicrocoded] in -def LOCK_PREFIX : I<0xF0, RawFrm, (outs), (ins), "lock", []>; - -let SchedRW = [WriteNop] in { - -// Rex64 instruction prefix -def REX64_PREFIX : I<0x48, RawFrm, (outs), (ins), "rex64", []>, - Requires<[In64BitMode]>; - -// Data16 instruction prefix -def DATA16_PREFIX : I<0x66, RawFrm, (outs), (ins), "data16", []>; -} // SchedRW - -// Repeat string operation instruction prefixes -let Defs = [ECX], Uses = [ECX,DF], SchedRW = [WriteMicrocoded] in { -// Repeat (used with INS, OUTS, MOVS, LODS and STOS) -def REP_PREFIX : I<0xF3, RawFrm, (outs), (ins), "rep", []>; -// Repeat while not equal (used with CMPS and SCAS) -def REPNE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "repne", []>; -} - -// String manipulation instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [AL,ESI], Uses = [ESI,DF] in -def LODSB : I<0xAC, RawFrmSrc, (outs), (ins srcidx8:$src), - "lodsb\t{$src, %al|al, $src}", []>; -let Defs = [AX,ESI], Uses = [ESI,DF] in -def LODSW : I<0xAD, RawFrmSrc, (outs), (ins srcidx16:$src), - "lodsw\t{$src, %ax|ax, $src}", []>, OpSize16; -let Defs = [EAX,ESI], Uses = [ESI,DF] in -def LODSL : I<0xAD, RawFrmSrc, (outs), (ins srcidx32:$src), - "lods{l|d}\t{$src, %eax|eax, $src}", []>, OpSize32; -let Defs = [RAX,ESI], Uses = [ESI,DF] in -def LODSQ : RI<0xAD, RawFrmSrc, (outs), (ins srcidx64:$src), - "lodsq\t{$src, %rax|rax, $src}", []>, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteSystem] in { -let Defs = [ESI], Uses = [DX,ESI,DF] in { -def OUTSB : I<0x6E, RawFrmSrc, (outs), (ins srcidx8:$src), - "outsb\t{$src, %dx|dx, $src}", []>; -def OUTSW : I<0x6F, RawFrmSrc, (outs), (ins srcidx16:$src), - "outsw\t{$src, %dx|dx, $src}", []>, OpSize16; -def OUTSL : I<0x6F, RawFrmSrc, (outs), (ins srcidx32:$src), - "outs{l|d}\t{$src, %dx|dx, $src}", []>, OpSize32; -} - -let Defs = [EDI], Uses = [DX,EDI,DF] in { -def INSB : I<0x6C, RawFrmDst, (outs), (ins dstidx8:$dst), - "insb\t{%dx, $dst|$dst, dx}", []>; -def INSW : I<0x6D, RawFrmDst, (outs), (ins dstidx16:$dst), - "insw\t{%dx, $dst|$dst, dx}", []>, OpSize16; -def INSL : I<0x6D, RawFrmDst, (outs), (ins dstidx32:$dst), - "ins{l|d}\t{%dx, $dst|$dst, dx}", []>, OpSize32; -} -} - -// EFLAGS management instructions. -let SchedRW = [WriteALU], Defs = [EFLAGS], Uses = [EFLAGS] in { -def CLC : I<0xF8, RawFrm, (outs), (ins), "clc", []>; -def STC : I<0xF9, RawFrm, (outs), (ins), "stc", []>; -def CMC : I<0xF5, RawFrm, (outs), (ins), "cmc", []>; -} - -// DF management instructions. -let SchedRW = [WriteALU], Defs = [DF] in { -def CLD : I<0xFC, RawFrm, (outs), (ins), "cld", []>; -def STD : I<0xFD, RawFrm, (outs), (ins), "std", []>; -} - -// Table lookup instructions -let Uses = [AL,EBX], Defs = [AL], hasSideEffects = 0, mayLoad = 1 in -def XLAT : I<0xD7, RawFrm, (outs), (ins), "xlatb", []>, Sched<[WriteLoad]>; - -let SchedRW = [WriteMicrocoded] in { -// ASCII Adjust After Addition -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAA : I<0x37, RawFrm, (outs), (ins), "aaa", []>, - Requires<[Not64BitMode]>; - -// ASCII Adjust AX Before Division -let Uses = [AX], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAD8i8 : Ii8<0xD5, RawFrm, (outs), (ins i8imm:$src), - "aad\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AX After Multiply -let Uses = [AL], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAM8i8 : Ii8<0xD4, RawFrm, (outs), (ins i8imm:$src), - "aam\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AL After Subtraction - sets -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAS : I<0x3F, RawFrm, (outs), (ins), "aas", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Addition -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAA : I<0x27, RawFrm, (outs), (ins), "daa", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Subtraction -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAS : I<0x2F, RawFrm, (outs), (ins), "das", []>, - Requires<[Not64BitMode]>; -} // SchedRW - -let SchedRW = [WriteSystem] in { -// Check Array Index Against Bounds -// Note: "bound" does not have reversed operands in at&t syntax. -def BOUNDS16rm : I<0x62, MRMSrcMem, (outs GR16:$dst), (ins i32mem:$src), - "bound\t$dst, $src", []>, OpSize16, - Requires<[Not64BitMode]>; -def BOUNDS32rm : I<0x62, MRMSrcMem, (outs GR32:$dst), (ins i64mem:$src), - "bound\t$dst, $src", []>, OpSize32, - Requires<[Not64BitMode]>; - -// Adjust RPL Field of Segment Selector -def ARPL16rr : I<0x63, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -let mayStore = 1 in -def ARPL16mr : I<0x63, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVBE Instructions -// -let Predicates = [HasMOVBE] in { - let SchedRW = [WriteALULd] in { - def MOVBE16rm : I<0xF0, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (bswap (loadi16 addr:$src)))]>, - OpSize16, T8PS; - def MOVBE32rm : I<0xF0, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bswap (loadi32 addr:$src)))]>, - OpSize32, T8PS; - def MOVBE64rm : RI<0xF0, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bswap (loadi64 addr:$src)))]>, - T8PS; - } - let SchedRW = [WriteStore] in { - def MOVBE16mr : I<0xF1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(store (bswap GR16:$src), addr:$dst)]>, - OpSize16, T8PS; - def MOVBE32mr : I<0xF1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(store (bswap GR32:$src), addr:$dst)]>, - OpSize32, T8PS; - def MOVBE64mr : RI<0xF1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(store (bswap GR64:$src), addr:$dst)]>, - T8PS; - } -} - -//===----------------------------------------------------------------------===// -// RDRAND Instruction -// -let Predicates = [HasRDRAND], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDRAND16r : I<0xC7, MRM6r, (outs GR16:$dst), (ins), - "rdrand{w}\t$dst", [(set GR16:$dst, EFLAGS, (X86rdrand))]>, - OpSize16, PS; - def RDRAND32r : I<0xC7, MRM6r, (outs GR32:$dst), (ins), - "rdrand{l}\t$dst", [(set GR32:$dst, EFLAGS, (X86rdrand))]>, - OpSize32, PS; - def RDRAND64r : RI<0xC7, MRM6r, (outs GR64:$dst), (ins), - "rdrand{q}\t$dst", [(set GR64:$dst, EFLAGS, (X86rdrand))]>, - PS; -} - -//===----------------------------------------------------------------------===// -// RDSEED Instruction -// -let Predicates = [HasRDSEED], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDSEED16r : I<0xC7, MRM7r, (outs GR16:$dst), (ins), "rdseed{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86rdseed))]>, OpSize16, PS; - def RDSEED32r : I<0xC7, MRM7r, (outs GR32:$dst), (ins), "rdseed{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86rdseed))]>, OpSize32, PS; - def RDSEED64r : RI<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdseed{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86rdseed))]>, PS; -} - -//===----------------------------------------------------------------------===// -// LZCNT Instruction -// -let Predicates = [HasLZCNT], Defs = [EFLAGS] in { - def LZCNT16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteLZCNT]>; - def LZCNT16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteLZCNTLd]>; - - def LZCNT32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteLZCNT]>; - def LZCNT32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteLZCNTLd]>; - - def LZCNT64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteLZCNT]>; - def LZCNT64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteLZCNTLd]>; -} - -//===----------------------------------------------------------------------===// -// BMI Instructions -// -let Predicates = [HasBMI], Defs = [EFLAGS] in { - def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteTZCNT]>; - def TZCNT16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteTZCNTLd]>; - - def TZCNT32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteTZCNT]>; - def TZCNT32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteTZCNTLd]>; - - def TZCNT64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteTZCNT]>; - def TZCNT64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteTZCNTLd]>; -} - -multiclass bmi_bls { -let hasSideEffects = 0 in { - def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALU]>; - let mayLoad = 1 in - def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALULd]>; -} -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>; - defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W; - defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>; - defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W; - defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>; - defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate BMI instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasBMI] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, -1)), - (BLSR32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, -1)), - (BLSR64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, -1)), - (BLSMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, -1)), - (BLSMSK64rr GR64:$src)>; - - def : Pat<(and GR32:$src, (ineg GR32:$src)), - (BLSI32rr GR32:$src)>; - def : Pat<(and GR64:$src, (ineg GR64:$src)), - (BLSI64rr GR64:$src)>; -} - -multiclass bmi_bextr opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BEXTR32 : bmi_bextr<0xF7, "bextr{l}", GR32, i32mem, - X86bextr, loadi32, WriteBEXTR>; - defm BEXTR64 : bmi_bextr<0xF7, "bextr{q}", GR64, i64mem, - X86bextr, loadi64, WriteBEXTR>, VEX_W; -} - -multiclass bmi_bzhi opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, Intrinsic Int, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI2], Defs = [EFLAGS] in { - defm BZHI32 : bmi_bzhi<0xF5, "bzhi{l}", GR32, i32mem, - int_x86_bmi_bzhi_32, loadi32, WriteBZHI>; - defm BZHI64 : bmi_bzhi<0xF5, "bzhi{q}", GR64, i64mem, - int_x86_bmi_bzhi_64, loadi64, WriteBZHI>, VEX_W; -} - -def CountTrailingOnes : SDNodeXFormgetZExtValue()), SDLoc(N)); -}]>; - -def BEXTRMaskXForm : SDNodeXFormgetZExtValue()); - return getI32Imm(Length << 8, SDLoc(N)); -}]>; - -def AndMask64 : ImmLeaf(Imm); -}]>; - -// Use BEXTR for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI, NoBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTR64rr GR64:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTR64rm addr:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; -} - -// Use BZHI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; -} - -let Predicates = [HasBMI2] in { - multiclass _bmi_bzhi_pattern { - def : Pat; - def : Pat; - } - - multiclass bmi_bzhi_patterns { - // x & ((1 << y) - 1) - defm : _bmi_bzhi_pattern<(and RC:$src, (add (shl 1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (add (shl 1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & ~(-1 << y) - defm : _bmi_bzhi_pattern<(and RC:$src, (xor (shl -1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (xor (shl -1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & (-1 >> (bitwidth - y)) - defm : _bmi_bzhi_pattern<(and RC:$src, (srl -1, (sub bitwidth, GR8:$lz))), - (and (x86memop addr:$src), - (srl -1, (sub bitwidth, GR8:$lz))), - RC, VT, DstInst, DstMemInst>; - - // x << (bitwidth - y) >> (bitwidth - y) - defm : _bmi_bzhi_pattern<(srl (shl RC:$src, (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - (srl (shl (x86memop addr:$src), - (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - RC, VT, DstInst, DstMemInst>; - } - - defm : bmi_bzhi_patterns; - defm : bmi_bzhi_patterns; - - // x & (-1 >> (32 - y)) - def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(and (loadi32 addr:$src), (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x & (-1 >> (64 - y)) - def : Pat<(and GR64:$src, (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - - // x << (32 - y) >> (32 - y) - def : Pat<(srl (shl GR32:$src, (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(srl (shl (loadi32 addr:$src), (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x << (64 - y) >> (64 - y) - def : Pat<(srl (shl GR64:$src, (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(srl (shl (loadi64 addr:$src), (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; -} // HasBMI2 - -multiclass bmi_pdep_pext { - def rr : I<0xF5, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, RC:$src2))]>, - VEX_4V, Sched<[WriteALU]>; - def rm : I<0xF5, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, (ld_frag addr:$src2)))]>, - VEX_4V, Sched<[WriteALULd, ReadAfterLd]>; -} - -let Predicates = [HasBMI2] in { - defm PDEP32 : bmi_pdep_pext<"pdep{l}", GR32, i32mem, - int_x86_bmi_pdep_32, loadi32>, T8XD; - defm PDEP64 : bmi_pdep_pext<"pdep{q}", GR64, i64mem, - int_x86_bmi_pdep_64, loadi64>, T8XD, VEX_W; - defm PEXT32 : bmi_pdep_pext<"pext{l}", GR32, i32mem, - int_x86_bmi_pext_32, loadi32>, T8XS; - defm PEXT64 : bmi_pdep_pext<"pext{q}", GR64, i64mem, - int_x86_bmi_pext_64, loadi64>, T8XS, VEX_W; -} - -//===----------------------------------------------------------------------===// -// TBM Instructions -// -let Predicates = [HasTBM], Defs = [EFLAGS] in { - -multiclass tbm_ternary_imm opc, RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - SDNode OpNode, Operand immtype, - SDPatternOperator immoperator, - X86FoldableSchedWrite Sched> { - def ri : Ii32, - XOP, XOPA, Sched<[Sched]>; - def mi : Ii32, - XOP, XOPA, Sched<[Sched.Folded]>; -} - -defm BEXTRI32 : tbm_ternary_imm<0x10, GR32, "bextr{l}", i32mem, loadi32, - X86bextr, i32imm, imm, WriteBEXTR>; -let ImmT = Imm32S in -defm BEXTRI64 : tbm_ternary_imm<0x10, GR64, "bextr{q}", i64mem, loadi64, - X86bextr, i64i32imm, - i64immSExt32, WriteBEXTR>, VEX_W; - -multiclass tbm_binary_rm opc, Format FormReg, Format FormMem, - RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, X86FoldableSchedWrite Sched> { -let hasSideEffects = 0 in { - def rr : I, - XOP_4V, XOP9, Sched<[Sched]>; - let mayLoad = 1 in - def rm : I, - XOP_4V, XOP9, Sched<[Sched.Folded]>; -} -} - -multiclass tbm_binary_intr opc, string OpcodeStr, - X86FoldableSchedWrite Sched, - Format FormReg, Format FormMem> { - defm NAME#32 : tbm_binary_rm; - defm NAME#64 : tbm_binary_rm, VEX_W; -} - -defm BLCFILL : tbm_binary_intr<0x01, "blcfill", WriteALU, MRM1r, MRM1m>; -defm BLCI : tbm_binary_intr<0x02, "blci", WriteALU, MRM6r, MRM6m>; -defm BLCIC : tbm_binary_intr<0x01, "blcic", WriteALU, MRM5r, MRM5m>; -defm BLCMSK : tbm_binary_intr<0x02, "blcmsk", WriteALU, MRM1r, MRM1m>; -defm BLCS : tbm_binary_intr<0x01, "blcs", WriteALU, MRM3r, MRM3m>; -defm BLSFILL : tbm_binary_intr<0x01, "blsfill", WriteALU, MRM2r, MRM2m>; -defm BLSIC : tbm_binary_intr<0x01, "blsic", WriteALU, MRM6r, MRM6m>; -defm T1MSKC : tbm_binary_intr<0x01, "t1mskc", WriteALU, MRM7r, MRM7m>; -defm TZMSK : tbm_binary_intr<0x01, "tzmsk", WriteALU, MRM4r, MRM4m>; -} // HasTBM, EFLAGS - -// Use BEXTRI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>; - - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>; -} - -//===----------------------------------------------------------------------===// -// Lightweight Profiling Instructions - -let Predicates = [HasLWP], SchedRW = [WriteSystem] in { - -def LLWPCB : I<0x12, MRM0r, (outs), (ins GR32:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR32:$src)]>, XOP, XOP9; -def SLWPCB : I<0x12, MRM1r, (outs GR32:$dst), (ins), "slwpcb\t$dst", - [(set GR32:$dst, (int_x86_slwpcb))]>, XOP, XOP9; - -def LLWPCB64 : I<0x12, MRM0r, (outs), (ins GR64:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR64:$src)]>, XOP, XOP9, VEX_W; -def SLWPCB64 : I<0x12, MRM1r, (outs GR64:$dst), (ins), "slwpcb\t$dst", - [(set GR64:$dst, (int_x86_slwpcb))]>, XOP, XOP9, VEX_W; - -multiclass lwpins_intr { - def rri : Ii32<0x12, MRM0r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, GR32:$src1, imm:$cntl))]>, - XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM0m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, (loadi32 addr:$src1), imm:$cntl))]>, - XOP_4V, XOPA; -} - -let Defs = [EFLAGS] in { - defm LWPINS32 : lwpins_intr; - defm LWPINS64 : lwpins_intr, VEX_W; -} // EFLAGS - -multiclass lwpval_intr { - def rri : Ii32<0x12, MRM1r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, GR32:$src1, imm:$cntl)]>, XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM1m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, (loadi32 addr:$src1), imm:$cntl)]>, - XOP_4V, XOPA; -} - -defm LWPVAL32 : lwpval_intr; -defm LWPVAL64 : lwpval_intr, VEX_W; - -} // HasLWP, SchedRW - -//===----------------------------------------------------------------------===// -// MONITORX/MWAITX Instructions -// -let SchedRW = [ WriteSystem ] in { -/* - let usesCustomInserter = 1 in { - def MONITORX : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_monitorx addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[ HasMWAITX ]>; - } -*/ - - let Uses = [ EAX, ECX, EDX ] in { - def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", []>, - TB, Requires<[ HasMWAITX ]>; - } - - let Uses = [ ECX, EAX, EBX ] in { - def MWAITXrrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx", - [(int_x86_mwaitx ECX, EAX, EBX)]>, - TB, Requires<[ HasMWAITX ]>; - } -} // SchedRW - -// def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrrr)>, -// Requires<[ Not64BitMode ]>; -// def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrrr)>, -// Requires<[ In64BitMode ]>; - -// def : InstAlias<"monitorx\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORXrrr)>, -// Requires<[ Not64BitMode ]>; -// def : InstAlias<"monitorx\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORXrrr)>, -// Requires<[ In64BitMode ]>; - -//===----------------------------------------------------------------------===// -// WAITPKG Instructions -// -let SchedRW = [WriteSystem] in { - def UMONITOR16 : I<0xAE, MRM6r, (outs), (ins GR16:$src), - "umonitor\t$src", [(int_x86_umonitor GR16:$src)]>, - XS, AdSize16, Requires<[HasWAITPKG, Not64BitMode]>; - def UMONITOR32 : I<0xAE, MRM6r, (outs), (ins GR32:$src), - "umonitor\t$src", [(int_x86_umonitor GR32:$src)]>, - XS, AdSize32, Requires<[HasWAITPKG]>; - def UMONITOR64 : I<0xAE, MRM6r, (outs), (ins GR64:$src), - "umonitor\t$src", [(int_x86_umonitor GR64:$src)]>, - XS, AdSize64, Requires<[HasWAITPKG, In64BitMode]>; - let Uses = [EAX, EDX], Defs = [EFLAGS] in { - def UMWAIT : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "umwait\t$src", - [(set EFLAGS, (X86umwait GR32orGR64:$src, EDX, EAX))]>, - XD, Requires<[HasWAITPKG]>; - def TPAUSE : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "tpause\t$src", - [(set EFLAGS, (X86tpause GR32orGR64:$src, EDX, EAX))]>, - PD, Requires<[HasWAITPKG]>, NotMemoryFoldable; - } -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIRI - Move doubleword/quadword as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIRI32 : I<0xF9, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore32 addr:$dst, GR32:$src)]>, - T8, Requires<[HasMOVDIRI]>; -def MOVDIRI64 : RI<0xF9, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore64 addr:$dst, GR64:$src)]>, - T8, Requires<[In64BitMode, HasMOVDIRI]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIR64B - Move 64 bytes as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIR64B16 : I<0xF8, MRMSrcMem, (outs), (ins GR16:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", []>, - T8PD, AdSize16, Requires<[HasMOVDIR64B, Not64BitMode]>; -def MOVDIR64B32 : I<0xF8, MRMSrcMem, (outs), (ins GR32:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR32:$dst, addr:$src)]>, - T8PD, AdSize32, Requires<[HasMOVDIR64B]>; -def MOVDIR64B64 : I<0xF8, MRMSrcMem, (outs), (ins GR64:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR64:$dst, addr:$src)]>, - T8PD, AdSize64, Requires<[HasMOVDIR64B, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CLZERO Instruction -// -let SchedRW = [WriteSystem] in { - let Uses = [EAX] in - def CLZEROr : I<0x01, MRM_FC, (outs), (ins), "clzero", []>, - TB, Requires<[HasCLZERO]>; - -/* - let usesCustomInserter = 1 in { - def CLZERO : PseudoI<(outs), (ins i32mem:$src1), - [(int_x86_clzero addr:$src1)]>, Requires<[HasCLZERO]>; - } -*/ -} // SchedRW - -// def : InstAlias<"clzero\t{%eax|eax}", (CLZEROr)>, Requires<[Not64BitMode]>; -// def : InstAlias<"clzero\t{%rax|rax}", (CLZEROr)>, Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate TBM instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasTBM] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, 1)), - (BLCFILL32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, 1)), - (BLCFILL64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (not (add GR32:$src, 1))), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (not (add GR64:$src, 1))), - (BLCI64rr GR64:$src)>; - - // Extra patterns because opt can optimize the above patterns to this. - def : Pat<(or GR32:$src, (sub -2, GR32:$src)), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (sub -2, GR64:$src)), - (BLCI64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, 1)), - (BLCIC32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, 1)), - (BLCIC64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, 1)), - (BLCMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, 1)), - (BLCMSK64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, 1)), - (BLCS32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, 1)), - (BLCS64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, -1)), - (BLSFILL32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, -1)), - (BLSFILL64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, -1)), - (BLSIC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, -1)), - (BLSIC64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, 1)), - (T1MSKC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, 1)), - (T1MSKC64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, -1)), - (TZMSK32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, -1)), - (TZMSK64rr GR64:$src)>; -} // HasTBM - -//===----------------------------------------------------------------------===// -// Memory Instructions -// - -let Predicates = [HasCLFLUSHOPT], SchedRW = [WriteLoad] in -def CLFLUSHOPT : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflushopt\t$src", [(int_x86_clflushopt addr:$src)]>, PD; - -let Predicates = [HasCLWB], SchedRW = [WriteLoad] in -def CLWB : I<0xAE, MRM6m, (outs), (ins i8mem:$src), "clwb\t$src", - [(int_x86_clwb addr:$src)]>, PD, NotMemoryFoldable; - -let Predicates = [HasCLDEMOTE], SchedRW = [WriteLoad] in -def CLDEMOTE : I<0x1C, MRM0m, (outs), (ins i8mem:$src), "cldemote\t$src", - [(int_x86_cldemote addr:$src)]>, TB; - -//===----------------------------------------------------------------------===// -// Subsystems. -//===----------------------------------------------------------------------===// - -include "X86Capstone.td" - -include "X86InstrArithmetic.td" -include "X86InstrCMovSetCC.td" -include "X86InstrExtension.td" -include "X86InstrControl.td" -include "X86InstrShiftRotate.td" - -// X87 Floating Point Stack. -//include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -//include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -//include "X86InstrFMA.td" - -// XOP -//include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -//include "X86InstrSSE.td" -//include "X86InstrAVX512.td" -//include "X86InstrMMX.td" -//include "X86Instr3DNow.td" - -// MPX instructions -//include "X86InstrMPX.td" - -include "X86InstrVMX.td" -include "X86InstrSVM.td" - -//include "X86InstrTSX.td" -//include "X86InstrSGX.td" - -// System instructions. -include "X86InstrSystem.td" - -// Compiler Pseudo Instructions and Pat Patterns -//include "X86InstrCompiler.td" -//include "X86InstrVecCompiler.td" - -//===----------------------------------------------------------------------===// -// Assembler Mnemonic Aliases -//===----------------------------------------------------------------------===// - -def : MnemonicAlias<"call", "callw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"call", "calll", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"call", "callq", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"cbw", "cbtw", "att">; -def : MnemonicAlias<"cwde", "cwtl", "att">; -def : MnemonicAlias<"cwd", "cwtd", "att">; -def : MnemonicAlias<"cdq", "cltd", "att">; -def : MnemonicAlias<"cdqe", "cltq", "att">; -def : MnemonicAlias<"cqo", "cqto", "att">; - -// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq. -def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>; - -def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"loopz", "loope">; -def : MnemonicAlias<"loopnz", "loopne">; - -def : MnemonicAlias<"pop", "popw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pop", "popl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pop", "popq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popf", "popfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"popf", "popfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popfd", "popfl", "att">; - -// FIXME: This is wrong for "push reg". "push %bx" should turn into pushw in -// all modes. However: "push (addr)" and "push $42" should default to -// pushl/pushq depending on the current mode. Similar for "pop %bx" -def : MnemonicAlias<"push", "pushw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"push", "pushl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"push", "pushq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pushf", "pushfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushfd", "pushfl", "att">; - -def : MnemonicAlias<"popad", "popal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"pushad", "pushal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"popa", "popaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "intel">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "intel">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"popa", "popaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "att">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"repe", "rep">; -def : MnemonicAlias<"repz", "rep">; -def : MnemonicAlias<"repnz", "repne">; - -def : MnemonicAlias<"ret", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"ret", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"ret", "retq", "att">, Requires<[In64BitMode]>; - -// Apply 'ret' behavior to 'retn' -def : MnemonicAlias<"retn", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"retn", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"retn", "retq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"retn", "ret", "intel">; - -def : MnemonicAlias<"sal", "shl", "intel">; -def : MnemonicAlias<"salb", "shlb", "att">; -def : MnemonicAlias<"salw", "shlw", "att">; -def : MnemonicAlias<"sall", "shll", "att">; -def : MnemonicAlias<"salq", "shlq", "att">; - -def : MnemonicAlias<"smovb", "movsb", "att">; -def : MnemonicAlias<"smovw", "movsw", "att">; -def : MnemonicAlias<"smovl", "movsl", "att">; -def : MnemonicAlias<"smovq", "movsq", "att">; - -def : MnemonicAlias<"ud2a", "ud2", "att">; -def : MnemonicAlias<"verrw", "verr", "att">; - -// MS recognizes 'xacquire'/'xrelease' as 'acquire'/'release' -def : MnemonicAlias<"acquire", "xacquire", "intel">; -def : MnemonicAlias<"release", "xrelease", "intel">; - -// System instruction aliases. -def : MnemonicAlias<"iret", "iretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"iret", "iretl", "att">, Requires<[Not16BitMode]>; -def : MnemonicAlias<"sysret", "sysretl", "att">; -def : MnemonicAlias<"sysexit", "sysexitl", "att">; - -def : MnemonicAlias<"lgdt", "lgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"lidt", "lidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lidt", "lidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lidt", "lidtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sidt", "sidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sidt", "sidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sidt", "sidtq", "att">, Requires<[In64BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"lidt", "lidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lidt", "lidtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sidt", "sidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sidt", "sidtd", "intel">, Requires<[In32BitMode]>; - - -// Floating point stack aliases. -def : MnemonicAlias<"fcmovz", "fcmove", "att">; -def : MnemonicAlias<"fcmova", "fcmovnbe", "att">; -def : MnemonicAlias<"fcmovnae", "fcmovb", "att">; -def : MnemonicAlias<"fcmovna", "fcmovbe", "att">; -def : MnemonicAlias<"fcmovae", "fcmovnb", "att">; -def : MnemonicAlias<"fcomip", "fcompi">; -def : MnemonicAlias<"fildq", "fildll", "att">; -def : MnemonicAlias<"fistpq", "fistpll", "att">; -def : MnemonicAlias<"fisttpq", "fisttpll", "att">; -def : MnemonicAlias<"fldcww", "fldcw", "att">; -def : MnemonicAlias<"fnstcww", "fnstcw", "att">; -def : MnemonicAlias<"fnstsww", "fnstsw", "att">; -def : MnemonicAlias<"fucomip", "fucompi">; -def : MnemonicAlias<"fwait", "wait">; - -def : MnemonicAlias<"fxsaveq", "fxsave64", "att">; -def : MnemonicAlias<"fxrstorq", "fxrstor64", "att">; -def : MnemonicAlias<"xsaveq", "xsave64", "att">; -def : MnemonicAlias<"xrstorq", "xrstor64", "att">; -def : MnemonicAlias<"xsaveoptq", "xsaveopt64", "att">; -def : MnemonicAlias<"xrstorsq", "xrstors64", "att">; -def : MnemonicAlias<"xsavecq", "xsavec64", "att">; -def : MnemonicAlias<"xsavesq", "xsaves64", "att">; - -class CondCodeAlias - : MnemonicAlias; - -/// IntegerCondCodeMnemonicAlias - This multiclass defines a bunch of -/// MnemonicAlias's that canonicalize the condition code in a mnemonic, for -/// example "setz" -> "sete". -multiclass IntegerCondCodeMnemonicAlias { - def C : CondCodeAlias; // setc -> setb - def Z : CondCodeAlias; // setz -> sete - def NA : CondCodeAlias; // setna -> setbe - def NB : CondCodeAlias; // setnb -> setae - def NC : CondCodeAlias; // setnc -> setae - def NG : CondCodeAlias; // setng -> setle - def NL : CondCodeAlias; // setnl -> setge - def NZ : CondCodeAlias; // setnz -> setne - def PE : CondCodeAlias; // setpe -> setp - def PO : CondCodeAlias; // setpo -> setnp - - def NAE : CondCodeAlias; // setnae -> setb - def NBE : CondCodeAlias; // setnbe -> seta - def NGE : CondCodeAlias; // setnge -> setl - def NLE : CondCodeAlias; // setnle -> setg -} - -// Aliases for set -defm : IntegerCondCodeMnemonicAlias<"set", "">; -// Aliases for j -defm : IntegerCondCodeMnemonicAlias<"j", "">; -// Aliases for cmov{w,l,q} -defm : IntegerCondCodeMnemonicAlias<"cmov", "w", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "l", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "q", "att">; -// No size suffix for intel-style asm. -defm : IntegerCondCodeMnemonicAlias<"cmov", "", "intel">; - - -//===----------------------------------------------------------------------===// -// Assembler Instruction Aliases -//===----------------------------------------------------------------------===// - -// aad/aam default to base 10 if no operand is specified. -// def : InstAlias<"aad", (AAD8i8 10)>, Requires<[Not64BitMode]>; -// def : InstAlias<"aam", (AAM8i8 10)>, Requires<[Not64BitMode]>; - -// Disambiguate the mem/imm form of bt-without-a-suffix as btl. -// Likewise for btc/btr/bts. -// def : InstAlias<"bt\t{$imm, $mem|$mem, $imm}", -// (BT32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"btc\t{$imm, $mem|$mem, $imm}", -// (BTC32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"btr\t{$imm, $mem|$mem, $imm}", -// (BTR32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -// def : InstAlias<"bts\t{$imm, $mem|$mem, $imm}", -// (BTS32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; - -// clr aliases. -// def : InstAlias<"clr{b}\t$reg", (XOR8rr GR8 :$reg, GR8 :$reg), 0>; -// def : InstAlias<"clr{w}\t$reg", (XOR16rr GR16:$reg, GR16:$reg), 0>; -// def : InstAlias<"clr{l}\t$reg", (XOR32rr GR32:$reg, GR32:$reg), 0>; -// def : InstAlias<"clr{q}\t$reg", (XOR64rr GR64:$reg, GR64:$reg), 0>; - -// lods aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"lodsb\t$src", (LODSB srcidx8:$src), 0>; -// def : InstAlias<"lodsw\t$src", (LODSW srcidx16:$src), 0>; -// def : InstAlias<"lods{l|d}\t$src", (LODSL srcidx32:$src), 0>; -// def : InstAlias<"lodsq\t$src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"lods\t{$src, %al|al, $src}", (LODSB srcidx8:$src), 0>; -// def : InstAlias<"lods\t{$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>; -// def : InstAlias<"lods\t{$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>; -// def : InstAlias<"lods\t{$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"lods\t$src", (LODSB srcidx8:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSW srcidx16:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSL srcidx32:$src), 0, "intel">; -// def : InstAlias<"lods\t$src", (LODSQ srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - - -// stos aliases. Accept the source being omitted because it's implicit in -// the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the source. -// def : InstAlias<"stosb\t$dst", (STOSB dstidx8:$dst), 0>; -// def : InstAlias<"stosw\t$dst", (STOSW dstidx16:$dst), 0>; -// def : InstAlias<"stos{l|d}\t$dst", (STOSL dstidx32:$dst), 0>; -// def : InstAlias<"stosq\t$dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"stos\t{%al, $dst|$dst, al}", (STOSB dstidx8:$dst), 0>; -// def : InstAlias<"stos\t{%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>; -// def : InstAlias<"stos\t{%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>; -// def : InstAlias<"stos\t{%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"stos\t$dst", (STOSB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSL dstidx32:$dst), 0, "intel">; -// def : InstAlias<"stos\t$dst", (STOSQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - - -// scas aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"scasb\t$dst", (SCASB dstidx8:$dst), 0>; -// def : InstAlias<"scasw\t$dst", (SCASW dstidx16:$dst), 0>; -// def : InstAlias<"scas{l|d}\t$dst", (SCASL dstidx32:$dst), 0>; -// def : InstAlias<"scasq\t$dst", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"scas\t{$dst, %al|al, $dst}", (SCASB dstidx8:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %ax|ax, $dst}", (SCASW dstidx16:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %eax|eax, $dst}", (SCASL dstidx32:$dst), 0>; -// def : InstAlias<"scas\t{$dst, %rax|rax, $dst}", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -// def : InstAlias<"scas\t$dst", (SCASB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASL dstidx32:$dst), 0, "intel">; -// def : InstAlias<"scas\t$dst", (SCASQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - -// cmps aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -// def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// movs aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -// def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// div and idiv aliases for explicit A register. -// def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>; -// def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>; -// def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32r GR32:$src)>; -// def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64r GR64:$src)>; -// def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8m i8mem :$src)>; -// def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16m i16mem:$src)>; -// def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32m i32mem:$src)>; -// def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64m i64mem:$src)>; -// def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8r GR8 :$src)>; -// def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16r GR16:$src)>; -// def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32r GR32:$src)>; -// def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64r GR64:$src)>; -// def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8m i8mem :$src)>; -// def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16m i16mem:$src)>; -// def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32m i32mem:$src)>; -// def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64m i64mem:$src)>; - - - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -// def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -//def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -// def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -// def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -// def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -// def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -// def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -// def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -// def : InstAlias<"fxch", (XCH_F ST1), 0>; -// def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -// def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -// def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -// def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -// def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -// def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -// def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -// def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -/* -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -//multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; -*/ - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -// def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -// def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -// def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -// def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -// def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -// def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; - -// def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// lcall and ljmp aliases. This seems to be an odd mapping in 64-bit mode, but -// this is compatible with what GAS does. -// def : InstAlias<"lcall\t$seg : $off", (FARCALL32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -// def : InstAlias<"ljmp\t$seg : $off", (FARJMP32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -// def : InstAlias<"lcall\t{*}$dst", (FARCALL32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -// def : InstAlias<"ljmp\t{*}$dst", (FARJMP32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -// def : InstAlias<"lcall\t$seg : $off", (FARCALL16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"ljmp\t$seg : $off", (FARJMP16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"lcall\t{*}$dst", (FARCALL16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; -// def : InstAlias<"ljmp\t{*}$dst", (FARJMP16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; - -// def : InstAlias<"jmp\t{*}$dst", (JMP64m i64mem:$dst), 0, "att">, Requires<[In64BitMode]>; -// def : InstAlias<"jmp\t{*}$dst", (JMP32m i32mem:$dst), 0, "att">, Requires<[In32BitMode]>; -// def : InstAlias<"jmp\t{*}$dst", (JMP16m i16mem:$dst), 0, "att">, Requires<[In16BitMode]>; - - -// "imul , B" is an alias for "imul , B, B". -// def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri GR16:$r, GR16:$r, i16imm:$imm), 0>; -// def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri8 GR16:$r, GR16:$r, i16i8imm:$imm), 0>; -// def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri GR32:$r, GR32:$r, i32imm:$imm), 0>; -// def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri8 GR32:$r, GR32:$r, i32i8imm:$imm), 0>; -// def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri32 GR64:$r, GR64:$r, i64i32imm:$imm), 0>; -// def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri8 GR64:$r, GR64:$r, i64i8imm:$imm), 0>; - -// ins aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the destination. -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSB dstidx8:$dst), 0, "intel">; -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSW dstidx16:$dst), 0, "intel">; -// def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSL dstidx32:$dst), 0, "intel">; - -// outs aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the source. -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSB srcidx8:$src), 0, "intel">; -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSW srcidx16:$src), 0, "intel">; -// def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSL srcidx32:$src), 0, "intel">; - -// inb %dx -> inb %al, %dx -// def : InstAlias<"inb\t{%dx|dx}", (IN8rr), 0>; -// def : InstAlias<"inw\t{%dx|dx}", (IN16rr), 0>; -// def : InstAlias<"inl\t{%dx|dx}", (IN32rr), 0>; -// def : InstAlias<"inb\t$port", (IN8ri u8imm:$port), 0>; -// def : InstAlias<"inw\t$port", (IN16ri u8imm:$port), 0>; -// def : InstAlias<"inl\t$port", (IN32ri u8imm:$port), 0>; - - -// jmp and call aliases for lcall and ljmp. jmp $42,$5 -> ljmp -// def : InstAlias<"call\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -// def : InstAlias<"jmp\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -// def : InstAlias<"call\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -// def : InstAlias<"jmp\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -// def : InstAlias<"callw\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"jmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"calll\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -// def : InstAlias<"jmpl\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; - -// Match 'movq , ' as an alias for movabsq. -// def : InstAlias<"mov{q}\t{$imm, $reg|$reg, $imm}", (MOV64ri GR64:$reg, i64imm:$imm), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; - -// movsx aliases -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rr8 GR16:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr8 GR32:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr16 GR32:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr8 GR64:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr32 GR64:$dst, GR32:$src), 0, "att">; - -// movzx aliases -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rr8 GR16:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr8 GR32:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr16 GR32:$dst, GR16:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr8 GR64:$dst, GR8:$src), 0, "att">; -// def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// Note: No GR32->GR64 movzx form. - -// outb %dx -> outb %al, %dx -// def : InstAlias<"outb\t{%dx|dx}", (OUT8rr), 0>; -// def : InstAlias<"outw\t{%dx|dx}", (OUT16rr), 0>; -// def : InstAlias<"outl\t{%dx|dx}", (OUT32rr), 0>; -// def : InstAlias<"outb\t$port", (OUT8ir u8imm:$port), 0>; -// def : InstAlias<"outw\t$port", (OUT16ir u8imm:$port), 0>; -// def : InstAlias<"outl\t$port", (OUT32ir u8imm:$port), 0>; - -// 'sldt ' can be encoded with either sldtw or sldtq with the same -// effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity -// errors, since its encoding is the most compact. -// def : InstAlias<"sldt $mem", (SLDT16m i16mem:$mem), 0>; - -// shld/shrd op,op -> shld op, op, CL -// def : InstAlias<"shld{w}\t{$r2, $r1|$r1, $r2}", (SHLD16rrCL GR16:$r1, GR16:$r2), 0>; -// def : InstAlias<"shld{l}\t{$r2, $r1|$r1, $r2}", (SHLD32rrCL GR32:$r1, GR32:$r2), 0>; -// def : InstAlias<"shld{q}\t{$r2, $r1|$r1, $r2}", (SHLD64rrCL GR64:$r1, GR64:$r2), 0>; -// def : InstAlias<"shrd{w}\t{$r2, $r1|$r1, $r2}", (SHRD16rrCL GR16:$r1, GR16:$r2), 0>; -// def : InstAlias<"shrd{l}\t{$r2, $r1|$r1, $r2}", (SHRD32rrCL GR32:$r1, GR32:$r2), 0>; -// def : InstAlias<"shrd{q}\t{$r2, $r1|$r1, $r2}", (SHRD64rrCL GR64:$r1, GR64:$r2), 0>; - -// def : InstAlias<"shld{w}\t{$reg, $mem|$mem, $reg}", (SHLD16mrCL i16mem:$mem, GR16:$reg), 0>; -// def : InstAlias<"shld{l}\t{$reg, $mem|$mem, $reg}", (SHLD32mrCL i32mem:$mem, GR32:$reg), 0>; -// def : InstAlias<"shld{q}\t{$reg, $mem|$mem, $reg}", (SHLD64mrCL i64mem:$mem, GR64:$reg), 0>; -// def : InstAlias<"shrd{w}\t{$reg, $mem|$mem, $reg}", (SHRD16mrCL i16mem:$mem, GR16:$reg), 0>; -// def : InstAlias<"shrd{l}\t{$reg, $mem|$mem, $reg}", (SHRD32mrCL i32mem:$mem, GR32:$reg), 0>; -// def : InstAlias<"shrd{q}\t{$reg, $mem|$mem, $reg}", (SHRD64mrCL i64mem:$mem, GR64:$reg), 0>; - -/* FIXME: This is disabled because the asm matcher is currently incapable of - * matching a fixed immediate like $1. -// "shl X, $1" is an alias for "shl X". -multiclass ShiftRotateByOneAlias { - // def : InstAlias(!strconcat(Opc, "8r1")) GR8:$op)>; - // def : InstAlias(!strconcat(Opc, "16r1")) GR16:$op)>; - // def : InstAlias(!strconcat(Opc, "32r1")) GR32:$op)>; - // def : InstAlias(!strconcat(Opc, "64r1")) GR64:$op)>; - // def : InstAlias(!strconcat(Opc, "8m1")) i8mem:$op)>; - // def : InstAlias(!strconcat(Opc, "16m1")) i16mem:$op)>; - // def : InstAlias(!strconcat(Opc, "32m1")) i32mem:$op)>; - // def : InstAlias(!strconcat(Opc, "64m1")) i64mem:$op)>; -} - -defm : ShiftRotateByOneAlias<"rcl", "RCL">; -defm : ShiftRotateByOneAlias<"rcr", "RCR">; -defm : ShiftRotateByOneAlias<"rol", "ROL">; -defm : ShiftRotateByOneAlias<"ror", "ROR">; -FIXME */ - -// test: We accept "testX , " and "testX , " as synonyms. -// def : InstAlias<"test{b}\t{$mem, $val|$val, $mem}", -// (TEST8mr i8mem :$mem, GR8 :$val), 0>; -// def : InstAlias<"test{w}\t{$mem, $val|$val, $mem}", -// (TEST16mr i16mem:$mem, GR16:$val), 0>; -// def : InstAlias<"test{l}\t{$mem, $val|$val, $mem}", -// (TEST32mr i32mem:$mem, GR32:$val), 0>; -// def : InstAlias<"test{q}\t{$mem, $val|$val, $mem}", -// (TEST64mr i64mem:$mem, GR64:$val), 0>; - -// xchg: We accept "xchgX , " and "xchgX , " as synonyms. -// def : InstAlias<"xchg{b}\t{$mem, $val|$val, $mem}", -// (XCHG8rm GR8 :$val, i8mem :$mem), 0>; -// def : InstAlias<"xchg{w}\t{$mem, $val|$val, $mem}", -// (XCHG16rm GR16:$val, i16mem:$mem), 0>; -// def : InstAlias<"xchg{l}\t{$mem, $val|$val, $mem}", -// (XCHG32rm GR32:$val, i32mem:$mem), 0>; -// def : InstAlias<"xchg{q}\t{$mem, $val|$val, $mem}", -// (XCHG64rm GR64:$val, i64mem:$mem), 0>; - -// xchg: We accept "xchgX , %eax" and "xchgX %eax, " as synonyms. -// def : InstAlias<"xchg{w}\t{%ax, $src|$src, ax}", (XCHG16ar GR16:$src), 0>; -// def : InstAlias<"xchg{l}\t{%eax, $src|$src, eax}", (XCHG32ar GR32:$src), 0>; -// def : InstAlias<"xchg{q}\t{%rax, $src|$src, rax}", (XCHG64ar GR64:$src), 0>; - -// In 64-bit mode, xchg %eax, %eax can't be encoded with the 0x90 opcode we -// would get by default because it's defined as NOP. But xchg %eax, %eax implies -// implicit zeroing of the upper 32 bits. So alias to the longer encoding. -// def : InstAlias<"xchg{l}\t{%eax, %eax|eax, eax}", -// (XCHG32rr EAX, EAX), 0>, Requires<[In64BitMode]>; - -// xchg %rax, %rax is a nop in x86-64 and can be encoded as such. Without this -// we emit an unneeded REX.w prefix. -// def : InstAlias<"xchg{q}\t{%rax, %rax|rax, rax}", (NOOP), 0>; - -// These aliases exist to get the parser to prioritize matching 8-bit -// immediate encodings over matching the implicit ax/eax/rax encodings. By -// explicitly mentioning the A register here, these entries will be ordered -// first due to the more explicit immediate type. -// def : InstAlias<"adc{w}\t{$imm, %ax|ax, $imm}", (ADC16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"add{w}\t{$imm, %ax|ax, $imm}", (ADD16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"and{w}\t{$imm, %ax|ax, $imm}", (AND16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"cmp{w}\t{$imm, %ax|ax, $imm}", (CMP16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"or{w}\t{$imm, %ax|ax, $imm}", (OR16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"sbb{w}\t{$imm, %ax|ax, $imm}", (SBB16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"sub{w}\t{$imm, %ax|ax, $imm}", (SUB16ri8 AX, i16i8imm:$imm), 0>; -// def : InstAlias<"xor{w}\t{$imm, %ax|ax, $imm}", (XOR16ri8 AX, i16i8imm:$imm), 0>; - -// def : InstAlias<"adc{l}\t{$imm, %eax|eax, $imm}", (ADC32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"add{l}\t{$imm, %eax|eax, $imm}", (ADD32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"and{l}\t{$imm, %eax|eax, $imm}", (AND32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"cmp{l}\t{$imm, %eax|eax, $imm}", (CMP32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"or{l}\t{$imm, %eax|eax, $imm}", (OR32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"sbb{l}\t{$imm, %eax|eax, $imm}", (SBB32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"sub{l}\t{$imm, %eax|eax, $imm}", (SUB32ri8 EAX, i32i8imm:$imm), 0>; -// def : InstAlias<"xor{l}\t{$imm, %eax|eax, $imm}", (XOR32ri8 EAX, i32i8imm:$imm), 0>; - -// def : InstAlias<"adc{q}\t{$imm, %rax|rax, $imm}", (ADC64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"add{q}\t{$imm, %rax|rax, $imm}", (ADD64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"and{q}\t{$imm, %rax|rax, $imm}", (AND64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"cmp{q}\t{$imm, %rax|rax, $imm}", (CMP64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"or{q}\t{$imm, %rax|rax, $imm}", (OR64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"sbb{q}\t{$imm, %rax|rax, $imm}", (SBB64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"sub{q}\t{$imm, %rax|rax, $imm}", (SUB64ri8 RAX, i64i8imm:$imm), 0>; -// def : InstAlias<"xor{q}\t{$imm, %rax|rax, $imm}", (XOR64ri8 RAX, i64i8imm:$imm), 0>; diff --git a/suite/synctools/tablegen/X86/X86InstrMMX.td b/suite/synctools/tablegen/X86/X86InstrMMX.td deleted file mode 100644 index c2be946001..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrMMX.td +++ /dev/null @@ -1,612 +0,0 @@ -//===-- X86InstrMMX.td - Describe the MMX Instruction Set --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 MMX instruction set, defining the instructions, -// and properties of the instructions which are needed for code generation, -// machine code emission, and analysis. -// -// All instructions that use MMX should be in this file, even if they also use -// SSE. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MMX Multiclasses -//===----------------------------------------------------------------------===// - -// Alias instruction that maps zero vector to pxor mmx. -// This is expanded by ExpandPostRAPseudos to an pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { -def MMX_SET0 : I<0, Pseudo, (outs VR64:$dst), (ins), "", []>; -} - -let Constraints = "$src1 = $dst" in { - // MMXI_binop_rm_int - Simple MMX binary operator based on intrinsic. - // When this is cleaned up, remove the FIXME from X86RecognizableInstr.cpp. - multiclass MMXI_binop_rm_int opc, string OpcodeStr, Intrinsic IntId, - X86FoldableSchedWrite sched, bit Commutable = 0, - X86MemOperand OType = i64mem> { - def irr : MMXI, - Sched<[sched]> { - let isCommutable = Commutable; - } - def irm : MMXI, - Sched<[sched.Folded, ReadAfterLd]>; - } - - multiclass MMXI_binop_rmi_int opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, Intrinsic IntId, - Intrinsic IntId2, X86FoldableSchedWrite sched, - X86FoldableSchedWrite schedImm> { - def rr : MMXI, - Sched<[sched]>; - def rm : MMXI, - Sched<[sched.Folded, ReadAfterLd]>; - def ri : MMXIi8, - Sched<[schedImm]>; - } -} - -/// Unary MMX instructions requiring SSSE3. -multiclass SS3I_unop_rm_int_mm opc, string OpcodeStr, - Intrinsic IntId64, X86FoldableSchedWrite sched> { - def rr : MMXSS38I, - Sched<[sched]>; - - def rm : MMXSS38I, - Sched<[sched.Folded]>; -} - -/// Binary MMX instructions requiring SSSE3. -let ImmT = NoImm, Constraints = "$src1 = $dst" in { -multiclass SS3I_binop_rm_int_mm opc, string OpcodeStr, - Intrinsic IntId64, X86FoldableSchedWrite sched, - bit Commutable = 0> { - let isCommutable = Commutable in - def rr : MMXSS38I, - Sched<[sched]>; - def rm : MMXSS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -/// PALIGN MMX instructions (require SSSE3). -multiclass ssse3_palign_mm { - def rri : MMXSS3AI<0x0F, MRMSrcReg, (outs VR64:$dst), - (ins VR64:$src1, VR64:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - [(set VR64:$dst, (IntId VR64:$src1, VR64:$src2, (i8 imm:$src3)))]>, - Sched<[sched]>; - def rmi : MMXSS3AI<0x0F, MRMSrcMem, (outs VR64:$dst), - (ins VR64:$src1, i64mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - [(set VR64:$dst, (IntId VR64:$src1, - (bitconvert (load_mmx addr:$src2)), (i8 imm:$src3)))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass sse12_cvt_pint opc, RegisterClass SrcRC, RegisterClass DstRC, - Intrinsic Int, X86MemOperand x86memop, PatFrag ld_frag, - string asm, X86FoldableSchedWrite sched, Domain d> { - def irr : MMXPI, - Sched<[sched]>; - def irm : MMXPI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_pint_3addr opc, RegisterClass SrcRC, - RegisterClass DstRC, Intrinsic Int, X86MemOperand x86memop, - PatFrag ld_frag, string asm, Domain d> { - def irr : MMXPI, - Sched<[WriteCvtI2PS]>; - def irm : MMXPI, - Sched<[WriteCvtI2PS.Folded]>; -} - -//===----------------------------------------------------------------------===// -// MMX EMMS Instruction -//===----------------------------------------------------------------------===// - -let SchedRW = [WriteEMMS] in -def MMX_EMMS : MMXI<0x77, RawFrm, (outs), (ins), "emms", [(int_x86_mmx_emms)]>; - -//===----------------------------------------------------------------------===// -// MMX Scalar Instructions -//===----------------------------------------------------------------------===// - -// Data Transfer Instructions -def MMX_MOVD64rr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (scalar_to_vector GR32:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -def MMX_MOVD64rm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (scalar_to_vector (loadi32 addr:$src))))]>, - Sched<[WriteVecLoad]>; - -let Predicates = [HasMMX] in { - def : Pat<(x86mmx (MMX_X86movw2d GR32:$src)), - (MMX_MOVD64rr GR32:$src)>; - def : Pat<(x86mmx (MMX_X86movw2d (i32 0))), - (MMX_SET0)>; - def : Pat<(x86mmx (MMX_X86movw2d (loadi32 addr:$src))), - (MMX_MOVD64rm addr:$src)>; -} - -let mayStore = 1 in -def MMX_MOVD64mr : MMXI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR64:$src), - "movd\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecStore]>; - -def MMX_MOVD64grr : MMXI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR64:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, - (MMX_X86movd2w (x86mmx VR64:$src)))]>, - Sched<[WriteVecMoveToGpr]>, FoldGenData<"MMX_MOVD64rr">; - -let isBitcast = 1 in -def MMX_MOVD64to64rr : MMXRI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, (bitconvert GR64:$src))]>, - Sched<[WriteVecMoveFromGpr]>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def MMX_MOVD64to64rm : MMXRI<0x6E, MRMSrcMem, (outs VR64:$dst), - (ins i64mem:$src), "movq\t{$src, $dst|$dst, $src}", - []>, Sched<[SchedWriteVecMoveLS.MMX.RM]>; - -let isBitcast = 1 in { -def MMX_MOVD64from64rr : MMXRI<0x7E, MRMDestReg, - (outs GR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert VR64:$src))]>, - Sched<[WriteVecMoveToGpr]>; -let SchedRW = [WriteVecMove], hasSideEffects = 0, isMoveReg = 1 in { -def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>; -let isCodeGenOnly = 1, ForceDisassemble = 1 in -def MMX_MOVQ64rr_REV : MMXI<0x7F, MRMDestReg, (outs VR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MMX_MOVQ64rr">; -} // SchedRW, hasSideEffects, isMoveReg -} // isBitcast - -// def : InstAlias<"movq.s\t{$src, $dst|$dst, $src}", -// (MMX_MOVQ64rr_REV VR64:$dst, VR64:$src), 0>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def MMX_MOVD64from64rm : MMXRI<0x7E, MRMDestMem, - (outs), (ins i64mem:$dst, VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.MMX.MR]>; - -let SchedRW = [SchedWriteVecMoveLS.MMX.RM] in { -let canFoldAsLoad = 1 in -def MMX_MOVQ64rm : MMXI<0x6F, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, (load_mmx addr:$src))]>; -} // SchedRW - -let SchedRW = [SchedWriteVecMoveLS.MMX.MR] in -def MMX_MOVQ64mr : MMXI<0x7F, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (x86mmx VR64:$src), addr:$dst)]>; - -let SchedRW = [SchedWriteVecMoveLS.XMM.RR] in { -def MMX_MOVDQ2Qrr : MMXSDIi8<0xD6, MRMSrcReg, (outs VR64:$dst), - (ins VR128:$src), "movdq2q\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (bitconvert - (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))))))]>; - -def MMX_MOVQ2DQrr : MMXS2SIi8<0xD6, MRMSrcReg, (outs VR128:$dst), - (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 - (scalar_to_vector - (i64 (bitconvert (x86mmx VR64:$src))))))]>; - -let isCodeGenOnly = 1, hasSideEffects = 1 in { -def MMX_MOVQ2FR64rr: MMXS2SIi8<0xD6, MRMSrcReg, (outs FR64:$dst), - (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", - []>; - -def MMX_MOVFR642Qrr: MMXSDIi8<0xD6, MRMSrcReg, (outs VR64:$dst), - (ins FR64:$src), "movdq2q\t{$src, $dst|$dst, $src}", - []>; -} -} // SchedRW - -let Predicates = [HasMMX, HasSSE1] in -def MMX_MOVNTQmr : MMXI<0xE7, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), - "movntq\t{$src, $dst|$dst, $src}", - [(int_x86_mmx_movnt_dq addr:$dst, VR64:$src)]>, - Sched<[SchedWriteVecMoveLSNT.MMX.MR]>; - -let Predicates = [HasMMX] in { - // movd to MMX register zero-extends - def : Pat<(x86mmx (X86vzmovl (x86mmx (scalar_to_vector GR32:$src)))), - (MMX_MOVD64rr GR32:$src)>; - def : Pat<(x86mmx (X86vzmovl (x86mmx (scalar_to_vector (loadi32 addr:$src))))), - (MMX_MOVD64rm addr:$src)>; -} - -// Arithmetic Instructions -defm MMX_PABSB : SS3I_unop_rm_int_mm<0x1C, "pabsb", int_x86_ssse3_pabs_b, - SchedWriteVecALU.MMX>; -defm MMX_PABSW : SS3I_unop_rm_int_mm<0x1D, "pabsw", int_x86_ssse3_pabs_w, - SchedWriteVecALU.MMX>; -defm MMX_PABSD : SS3I_unop_rm_int_mm<0x1E, "pabsd", int_x86_ssse3_pabs_d, - SchedWriteVecALU.MMX>; -// -- Addition -defm MMX_PADDB : MMXI_binop_rm_int<0xFC, "paddb", int_x86_mmx_padd_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDW : MMXI_binop_rm_int<0xFD, "paddw", int_x86_mmx_padd_w, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDD : MMXI_binop_rm_int<0xFE, "paddd", int_x86_mmx_padd_d, - SchedWriteVecALU.MMX, 1>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PADDQ : MMXI_binop_rm_int<0xD4, "paddq", int_x86_mmx_padd_q, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDSB : MMXI_binop_rm_int<0xEC, "paddsb" , int_x86_mmx_padds_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDSW : MMXI_binop_rm_int<0xED, "paddsw" , int_x86_mmx_padds_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PADDUSB : MMXI_binop_rm_int<0xDC, "paddusb", int_x86_mmx_paddus_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDUSW : MMXI_binop_rm_int<0xDD, "paddusw", int_x86_mmx_paddus_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PHADDW : SS3I_binop_rm_int_mm<0x01, "phaddw", int_x86_ssse3_phadd_w, - SchedWritePHAdd.MMX>; -defm MMX_PHADDD : SS3I_binop_rm_int_mm<0x02, "phaddd", int_x86_ssse3_phadd_d, - SchedWritePHAdd.MMX>; -defm MMX_PHADDSW : SS3I_binop_rm_int_mm<0x03, "phaddsw",int_x86_ssse3_phadd_sw, - SchedWritePHAdd.MMX>; - -// -- Subtraction -defm MMX_PSUBB : MMXI_binop_rm_int<0xF8, "psubb", int_x86_mmx_psub_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBW : MMXI_binop_rm_int<0xF9, "psubw", int_x86_mmx_psub_w, - SchedWriteVecALU.MMX>; -defm MMX_PSUBD : MMXI_binop_rm_int<0xFA, "psubd", int_x86_mmx_psub_d, - SchedWriteVecALU.MMX>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PSUBQ : MMXI_binop_rm_int<0xFB, "psubq", int_x86_mmx_psub_q, - SchedWriteVecALU.MMX>; - -defm MMX_PSUBSB : MMXI_binop_rm_int<0xE8, "psubsb" , int_x86_mmx_psubs_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBSW : MMXI_binop_rm_int<0xE9, "psubsw" , int_x86_mmx_psubs_w, - SchedWriteVecALU.MMX>; - -defm MMX_PSUBUSB : MMXI_binop_rm_int<0xD8, "psubusb", int_x86_mmx_psubus_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBUSW : MMXI_binop_rm_int<0xD9, "psubusw", int_x86_mmx_psubus_w, - SchedWriteVecALU.MMX>; - -defm MMX_PHSUBW : SS3I_binop_rm_int_mm<0x05, "phsubw", int_x86_ssse3_phsub_w, - SchedWritePHAdd.MMX>; -defm MMX_PHSUBD : SS3I_binop_rm_int_mm<0x06, "phsubd", int_x86_ssse3_phsub_d, - SchedWritePHAdd.MMX>; -defm MMX_PHSUBSW : SS3I_binop_rm_int_mm<0x07, "phsubsw",int_x86_ssse3_phsub_sw, - SchedWritePHAdd.MMX>; - -// -- Multiplication -defm MMX_PMULLW : MMXI_binop_rm_int<0xD5, "pmullw", int_x86_mmx_pmull_w, - SchedWriteVecIMul.MMX, 1>; - -defm MMX_PMULHW : MMXI_binop_rm_int<0xE5, "pmulhw", int_x86_mmx_pmulh_w, - SchedWriteVecIMul.MMX, 1>; -let Predicates = [HasMMX, HasSSE1] in -defm MMX_PMULHUW : MMXI_binop_rm_int<0xE4, "pmulhuw", int_x86_mmx_pmulhu_w, - SchedWriteVecIMul.MMX, 1>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PMULUDQ : MMXI_binop_rm_int<0xF4, "pmuludq", int_x86_mmx_pmulu_dq, - SchedWriteVecIMul.MMX, 1>; -defm MMX_PMULHRSW : SS3I_binop_rm_int_mm<0x0B, "pmulhrsw", - int_x86_ssse3_pmul_hr_sw, - SchedWriteVecIMul.MMX, 1>; - -// -- Miscellanea -defm MMX_PMADDWD : MMXI_binop_rm_int<0xF5, "pmaddwd", int_x86_mmx_pmadd_wd, - SchedWriteVecIMul.MMX, 1>; - -defm MMX_PMADDUBSW : SS3I_binop_rm_int_mm<0x04, "pmaddubsw", - int_x86_ssse3_pmadd_ub_sw, - SchedWriteVecIMul.MMX>; -let Predicates = [HasMMX, HasSSE1] in { -defm MMX_PAVGB : MMXI_binop_rm_int<0xE0, "pavgb", int_x86_mmx_pavg_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PAVGW : MMXI_binop_rm_int<0xE3, "pavgw", int_x86_mmx_pavg_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PMINUB : MMXI_binop_rm_int<0xDA, "pminub", int_x86_mmx_pminu_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PMINSW : MMXI_binop_rm_int<0xEA, "pminsw", int_x86_mmx_pmins_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PMAXUB : MMXI_binop_rm_int<0xDE, "pmaxub", int_x86_mmx_pmaxu_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PMAXSW : MMXI_binop_rm_int<0xEE, "pmaxsw", int_x86_mmx_pmaxs_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PSADBW : MMXI_binop_rm_int<0xF6, "psadbw", int_x86_mmx_psad_bw, - SchedWritePSADBW.MMX, 1>; -} - -defm MMX_PSIGNB : SS3I_binop_rm_int_mm<0x08, "psignb", int_x86_ssse3_psign_b, - SchedWriteVecALU.MMX>; -defm MMX_PSIGNW : SS3I_binop_rm_int_mm<0x09, "psignw", int_x86_ssse3_psign_w, - SchedWriteVecALU.MMX>; -defm MMX_PSIGND : SS3I_binop_rm_int_mm<0x0A, "psignd", int_x86_ssse3_psign_d, - SchedWriteVecALU.MMX>; -let Constraints = "$src1 = $dst" in - defm MMX_PALIGNR : ssse3_palign_mm<"palignr", int_x86_mmx_palignr_b, - SchedWriteShuffle.MMX>; - -// Logical Instructions -defm MMX_PAND : MMXI_binop_rm_int<0xDB, "pand", int_x86_mmx_pand, - SchedWriteVecLogic.MMX, 1>; -defm MMX_POR : MMXI_binop_rm_int<0xEB, "por" , int_x86_mmx_por, - SchedWriteVecLogic.MMX, 1>; -defm MMX_PXOR : MMXI_binop_rm_int<0xEF, "pxor", int_x86_mmx_pxor, - SchedWriteVecLogic.MMX, 1>; -defm MMX_PANDN : MMXI_binop_rm_int<0xDF, "pandn", int_x86_mmx_pandn, - SchedWriteVecLogic.MMX>; - -// Shift Instructions -defm MMX_PSRLW : MMXI_binop_rmi_int<0xD1, 0x71, MRM2r, "psrlw", - int_x86_mmx_psrl_w, int_x86_mmx_psrli_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRLD : MMXI_binop_rmi_int<0xD2, 0x72, MRM2r, "psrld", - int_x86_mmx_psrl_d, int_x86_mmx_psrli_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRLQ : MMXI_binop_rmi_int<0xD3, 0x73, MRM2r, "psrlq", - int_x86_mmx_psrl_q, int_x86_mmx_psrli_q, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -defm MMX_PSLLW : MMXI_binop_rmi_int<0xF1, 0x71, MRM6r, "psllw", - int_x86_mmx_psll_w, int_x86_mmx_pslli_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSLLD : MMXI_binop_rmi_int<0xF2, 0x72, MRM6r, "pslld", - int_x86_mmx_psll_d, int_x86_mmx_pslli_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSLLQ : MMXI_binop_rmi_int<0xF3, 0x73, MRM6r, "psllq", - int_x86_mmx_psll_q, int_x86_mmx_pslli_q, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -defm MMX_PSRAW : MMXI_binop_rmi_int<0xE1, 0x71, MRM4r, "psraw", - int_x86_mmx_psra_w, int_x86_mmx_psrai_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRAD : MMXI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad", - int_x86_mmx_psra_d, int_x86_mmx_psrai_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -// Comparison Instructions -defm MMX_PCMPEQB : MMXI_binop_rm_int<0x74, "pcmpeqb", int_x86_mmx_pcmpeq_b, - SchedWriteVecALU.MMX>; -defm MMX_PCMPEQW : MMXI_binop_rm_int<0x75, "pcmpeqw", int_x86_mmx_pcmpeq_w, - SchedWriteVecALU.MMX>; -defm MMX_PCMPEQD : MMXI_binop_rm_int<0x76, "pcmpeqd", int_x86_mmx_pcmpeq_d, - SchedWriteVecALU.MMX>; - -defm MMX_PCMPGTB : MMXI_binop_rm_int<0x64, "pcmpgtb", int_x86_mmx_pcmpgt_b, - SchedWriteVecALU.MMX>; -defm MMX_PCMPGTW : MMXI_binop_rm_int<0x65, "pcmpgtw", int_x86_mmx_pcmpgt_w, - SchedWriteVecALU.MMX>; -defm MMX_PCMPGTD : MMXI_binop_rm_int<0x66, "pcmpgtd", int_x86_mmx_pcmpgt_d, - SchedWriteVecALU.MMX>; - -// -- Unpack Instructions -defm MMX_PUNPCKHBW : MMXI_binop_rm_int<0x68, "punpckhbw", - int_x86_mmx_punpckhbw, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKHWD : MMXI_binop_rm_int<0x69, "punpckhwd", - int_x86_mmx_punpckhwd, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKHDQ : MMXI_binop_rm_int<0x6A, "punpckhdq", - int_x86_mmx_punpckhdq, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKLBW : MMXI_binop_rm_int<0x60, "punpcklbw", - int_x86_mmx_punpcklbw, - SchedWriteShuffle.MMX, - 0, i32mem>; -defm MMX_PUNPCKLWD : MMXI_binop_rm_int<0x61, "punpcklwd", - int_x86_mmx_punpcklwd, - SchedWriteShuffle.MMX, - 0, i32mem>; -defm MMX_PUNPCKLDQ : MMXI_binop_rm_int<0x62, "punpckldq", - int_x86_mmx_punpckldq, - SchedWriteShuffle.MMX, - 0, i32mem>; - -// -- Pack Instructions -defm MMX_PACKSSWB : MMXI_binop_rm_int<0x63, "packsswb", int_x86_mmx_packsswb, - SchedWriteShuffle.MMX>; -defm MMX_PACKSSDW : MMXI_binop_rm_int<0x6B, "packssdw", int_x86_mmx_packssdw, - SchedWriteShuffle.MMX>; -defm MMX_PACKUSWB : MMXI_binop_rm_int<0x67, "packuswb", int_x86_mmx_packuswb, - SchedWriteShuffle.MMX>; - -// -- Shuffle Instructions -defm MMX_PSHUFB : SS3I_binop_rm_int_mm<0x00, "pshufb", int_x86_ssse3_pshuf_b, - SchedWriteVarShuffle.MMX>; - -def MMX_PSHUFWri : MMXIi8<0x70, MRMSrcReg, - (outs VR64:$dst), (ins VR64:$src1, u8imm:$src2), - "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR64:$dst, - (int_x86_sse_pshuf_w VR64:$src1, imm:$src2))]>, - Sched<[SchedWriteShuffle.MMX]>; -def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, - (outs VR64:$dst), (ins i64mem:$src1, u8imm:$src2), - "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR64:$dst, - (int_x86_sse_pshuf_w (load_mmx addr:$src1), - imm:$src2))]>, - Sched<[SchedWriteShuffle.MMX.Folded]>; - -// -- Conversion Instructions -defm MMX_CVTPS2PI : sse12_cvt_pint<0x2D, VR128, VR64, int_x86_sse_cvtps2pi, - f64mem, load, "cvtps2pi\t{$src, $dst|$dst, $src}", - WriteCvtPS2I, SSEPackedSingle>, PS; -defm MMX_CVTPD2PI : sse12_cvt_pint<0x2D, VR128, VR64, int_x86_sse_cvtpd2pi, - f128mem, memop, "cvtpd2pi\t{$src, $dst|$dst, $src}", - WriteCvtPD2I, SSEPackedDouble>, PD; -defm MMX_CVTTPS2PI : sse12_cvt_pint<0x2C, VR128, VR64, int_x86_sse_cvttps2pi, - f64mem, load, "cvttps2pi\t{$src, $dst|$dst, $src}", - WriteCvtPS2I, SSEPackedSingle>, PS; -defm MMX_CVTTPD2PI : sse12_cvt_pint<0x2C, VR128, VR64, int_x86_sse_cvttpd2pi, - f128mem, memop, "cvttpd2pi\t{$src, $dst|$dst, $src}", - WriteCvtPD2I, SSEPackedDouble>, PD; -defm MMX_CVTPI2PD : sse12_cvt_pint<0x2A, VR64, VR128, int_x86_sse_cvtpi2pd, - i64mem, load, "cvtpi2pd\t{$src, $dst|$dst, $src}", - WriteCvtI2PD, SSEPackedDouble>, PD; -let Constraints = "$src1 = $dst" in { - defm MMX_CVTPI2PS : sse12_cvt_pint_3addr<0x2A, VR64, VR128, - int_x86_sse_cvtpi2ps, - i64mem, load, "cvtpi2ps\t{$src2, $dst|$dst, $src2}", - SSEPackedSingle>, PS; -} - -// Extract / Insert -let Predicates = [HasMMX, HasSSE1] in -def MMX_PEXTRWrr: MMXIi8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR64:$src1, i32u8imm:$src2), - "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (int_x86_mmx_pextr_w VR64:$src1, - imm:$src2))]>, - Sched<[WriteVecExtract]>; -let Constraints = "$src1 = $dst" in { -let Predicates = [HasMMX, HasSSE1] in { - def MMX_PINSRWrr : MMXIi8<0xC4, MRMSrcReg, - (outs VR64:$dst), - (ins VR64:$src1, GR32orGR64:$src2, i32u8imm:$src3), - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR64:$dst, (int_x86_mmx_pinsr_w VR64:$src1, - GR32orGR64:$src2, imm:$src3))]>, - Sched<[WriteVecInsert]>; - - def MMX_PINSRWrm : MMXIi8<0xC4, MRMSrcMem, - (outs VR64:$dst), - (ins VR64:$src1, i16mem:$src2, i32u8imm:$src3), - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR64:$dst, (int_x86_mmx_pinsr_w VR64:$src1, - (i32 (anyext (loadi16 addr:$src2))), - imm:$src3))]>, - Sched<[WriteVecInsertLd, ReadAfterLd]>; -} -} - -// Mask creation -let Predicates = [HasMMX, HasSSE1] in -def MMX_PMOVMSKBrr : MMXI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR64:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, - (int_x86_mmx_pmovmskb VR64:$src))]>, - Sched<[WriteMMXMOVMSK]>; - -// Low word of XMM to MMX. -def MMX_X86movdq2q : SDNode<"X86ISD::MOVDQ2Q", SDTypeProfile<1, 1, - [SDTCisVT<0, x86mmx>, SDTCisVT<1, v2i64>]>>; - -def : Pat<(x86mmx (MMX_X86movdq2q VR128:$src)), - (x86mmx (MMX_MOVDQ2Qrr VR128:$src))>; - -def : Pat<(x86mmx (MMX_X86movdq2q (loadv2i64 addr:$src))), - (x86mmx (MMX_MOVQ64rm addr:$src))>; - -// Misc. -let SchedRW = [SchedWriteShuffle.MMX] in { -let Uses = [EDI], Predicates = [HasMMX, HasSSE1,Not64BitMode] in -def MMX_MASKMOVQ : MMXI32<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), - "maskmovq\t{$mask, $src|$src, $mask}", - [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, EDI)]>; -let Uses = [RDI], Predicates = [HasMMX, HasSSE1,In64BitMode] in -def MMX_MASKMOVQ64: MMXI64<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), - "maskmovq\t{$mask, $src|$src, $mask}", - [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, RDI)]>; -} - -// 64-bit bit convert. -let Predicates = [HasMMX, HasSSE2] in { -def : Pat<(f64 (bitconvert (x86mmx VR64:$src))), - (MMX_MOVQ2FR64rr VR64:$src)>; -def : Pat<(x86mmx (bitconvert (f64 FR64:$src))), - (MMX_MOVFR642Qrr FR64:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvtp2Int (v4f32 VR128:$src)))))), - (MMX_CVTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvttp2si (v4f32 VR128:$src)))))), - (MMX_CVTTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (fp_to_sint (v4f32 VR128:$src)))))), - (MMX_CVTTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (MMX_CVTPD2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (MMX_CVTTPD2PIirr VR128:$src)>; -} diff --git a/suite/synctools/tablegen/X86/X86InstrMPX.td b/suite/synctools/tablegen/X86/X86InstrMPX.td deleted file mode 100644 index c1a8cc7c5f..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrMPX.td +++ /dev/null @@ -1,80 +0,0 @@ -//===-- X86InstrMPX.td - MPX Instruction Set ---------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 MPX instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -// FIXME: Investigate a better scheduler class once MPX is used inside LLVM. -let SchedRW = [WriteSystem] in { - -multiclass mpx_bound_make opc, string OpcodeStr> { - def 32rm: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rm: I, - Requires<[HasMPX, In64BitMode]>; -} - -defm BNDMK : mpx_bound_make<0x1B, "bndmk">, XS; - -multiclass mpx_bound_check opc, string OpcodeStr> { - def 32rm: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rm: I, - Requires<[HasMPX, In64BitMode]>; - - def 32rr: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rr: I, - Requires<[HasMPX, In64BitMode]>; -} -defm BNDCL : mpx_bound_check<0x1A, "bndcl">, XS, NotMemoryFoldable; -defm BNDCU : mpx_bound_check<0x1A, "bndcu">, XD, NotMemoryFoldable; -defm BNDCN : mpx_bound_check<0x1B, "bndcn">, XD, NotMemoryFoldable; - -def BNDMOVrr : I<0x1A, MRMSrcReg, (outs BNDR:$dst), (ins BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX]>, NotMemoryFoldable; -let mayLoad = 1 in { -def BNDMOV32rm : I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins i64mem:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, Not64BitMode]>, NotMemoryFoldable; -def BNDMOV64rm : I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins i128mem:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, In64BitMode]>, NotMemoryFoldable; -} -let isCodeGenOnly = 1, ForceDisassemble = 1 in -def BNDMOVrr_REV : I<0x1B, MRMDestReg, (outs BNDR:$dst), (ins BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX]>, NotMemoryFoldable; -let mayStore = 1 in { -def BNDMOV32mr : I<0x1B, MRMDestMem, (outs), (ins i64mem:$dst, BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, Not64BitMode]>, NotMemoryFoldable; -def BNDMOV64mr : I<0x1B, MRMDestMem, (outs), (ins i128mem:$dst, BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, In64BitMode]>, NotMemoryFoldable; - -def BNDSTXmr: I<0x1B, MRMDestMem, (outs), (ins anymem:$dst, BNDR:$src), - "bndstx\t{$src, $dst|$dst, $src}", []>, PS, - Requires<[HasMPX]>; -} -let mayLoad = 1 in -def BNDLDXrm: I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins anymem:$src), - "bndldx\t{$src, $dst|$dst, $src}", []>, PS, - Requires<[HasMPX]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrSGX.td b/suite/synctools/tablegen/X86/X86InstrSGX.td deleted file mode 100644 index 488cc44380..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrSGX.td +++ /dev/null @@ -1,30 +0,0 @@ -//===-- X86InstrSGX.td - SGX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel SGX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SGX instructions - -let SchedRW = [WriteSystem], Predicates = [HasSGX] in { -// ENCLS - Execute an Enclave System Function of Specified Leaf Number -def ENCLS : I<0x01, MRM_CF, (outs), (ins), - "encls", []>, TB; - -// ENCLU - Execute an Enclave User Function of Specified Leaf Number -def ENCLU : I<0x01, MRM_D7, (outs), (ins), - "enclu", []>, TB; - -// ENCLV - Execute an Enclave VMM Function of Specified Leaf Number -def ENCLV : I<0x01, MRM_C0, (outs), (ins), - "enclv", []>, TB; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrSSE.td b/suite/synctools/tablegen/X86/X86InstrSSE.td deleted file mode 100644 index 5c6b4155b1..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrSSE.td +++ /dev/null @@ -1,8258 +0,0 @@ -//===-- X86InstrSSE.td - SSE Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 SSE instruction set, defining the instructions, -// and properties of the instructions which are needed for code generation, -// machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 Instructions Classes -//===----------------------------------------------------------------------===// - -/// sse12_fp_scalar - SSE 1 & 2 scalar instructions class -multiclass sse12_fp_scalar opc, string OpcodeStr, SDNode OpNode, - RegisterClass RC, X86MemOperand x86memop, - Domain d, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in { - def rr : SI, - Sched<[sched]>; - } - def rm : SI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// sse12_fp_scalar_int - SSE 1 & 2 scalar instructions intrinsics class -multiclass sse12_fp_scalar_int opc, string OpcodeStr, - SDPatternOperator OpNode, RegisterClass RC, - ValueType VT, string asm, Operand memopr, - ComplexPattern mem_cpat, Domain d, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { -let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr_Int : SI_Int, - Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : SI_Int, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -/// sse12_fp_packed - SSE 1 & 2 packed instructions class -multiclass sse12_fp_packed opc, string OpcodeStr, SDNode OpNode, - RegisterClass RC, ValueType vt, - X86MemOperand x86memop, PatFrag mem_frag, - Domain d, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : PI, - Sched<[sched]>; - let mayLoad = 1 in - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// sse12_fp_packed_logical_rm - SSE 1 & 2 packed instructions class -multiclass sse12_fp_packed_logical_rm opc, RegisterClass RC, Domain d, - string OpcodeStr, X86MemOperand x86memop, - X86FoldableSchedWrite sched, - list pat_rr, list pat_rm, - bit Is2Addr = 1> { - let isCommutable = 1, hasSideEffects = 0 in - def rr : PI, - Sched<[sched]>; - let hasSideEffects = 0, mayLoad = 1 in - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - - -/* -// Alias instructions that map fld0 to xorps for sse or vxorps for avx. -// This is expanded by ExpandPostRAPseudos. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { - def FsFLD0SS : I<0, Pseudo, (outs FR32:$dst), (ins), "", - [(set FR32:$dst, fp32imm0)]>, Requires<[HasSSE1, NoAVX512]>; - def FsFLD0SD : I<0, Pseudo, (outs FR64:$dst), (ins), "", - [(set FR64:$dst, fpimm0)]>, Requires<[HasSSE2, NoAVX512]>; -} -*/ - -//===----------------------------------------------------------------------===// -// AVX & SSE - Zero/One Vectors -//===----------------------------------------------------------------------===// - -// Alias instruction that maps zero vector to pxor / xorp* for sse. -// This is expanded by ExpandPostRAPseudos to an xorps / vxorps, and then -// swizzled by ExecutionDomainFix to pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { -def V_SET0 : I<0, Pseudo, (outs VR128:$dst), (ins), "", - [(set VR128:$dst, (v4f32 immAllZerosV))]>; -} - -let Predicates = [NoAVX512] in -def : Pat<(v4i32 immAllZerosV), (V_SET0)>; - - -// The same as done above but for AVX. The 256-bit AVX1 ISA doesn't support PI, -// and doesn't need it because on sandy bridge the register is set to zero -// at the rename stage without using any execution unit, so SET0PSY -// and SET0PDY can be used for vector int instructions without penalty -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [NoAVX512], SchedRW = [WriteZero] in { -def AVX_SET0 : I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllZerosV))]>; -} - -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-ones value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { - def V_SETALLONES : I<0, Pseudo, (outs VR128:$dst), (ins), "", - [(set VR128:$dst, (v4i32 immAllOnesV))]>; - let Predicates = [HasAVX1Only, OptForMinSize] in { - def AVX1_SETALLONES: I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllOnesV))]>; - } - let Predicates = [HasAVX2] in - def AVX2_SETALLONES : I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllOnesV))]>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move FP Scalar Instructions -// -// Move Instructions. Register-to-register movss/movsd is not used for FR32/64 -// register copies because it's a partial register update; Register-to-register -// movss/movsd is not modeled as an INSERT_SUBREG because INSERT_SUBREG requires -// that the insert be implementable in terms of a copy, and just mentioned, we -// don't use movss/movsd for copies. -//===----------------------------------------------------------------------===// - -multiclass sse12_move_rr { - let isCommutable = 1 in - def rr : SI<0x10, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - !strconcat(base_opc, asm_opr), - [(set VR128:$dst, (vt (OpNode VR128:$src1, VR128:$src2)))], d>, - Sched<[SchedWriteFShuffle.XMM]>; - - // For the disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - !strconcat(base_opc, asm_opr), []>, - Sched<[SchedWriteFShuffle.XMM]>, FoldGenData; -} - -multiclass sse12_move { - // AVX - let Predicates = [UseAVX, OptForSize] in - defm V#NAME : sse12_move_rr, - VEX_4V, VEX_LIG, VEX_WIG; - - def V#NAME#mr : SI<0x11, MRMDestMem, (outs), (ins x86memop:$dst, RC:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(store RC:$src, addr:$dst)], d>, - VEX, VEX_LIG, Sched<[WriteFStore]>, VEX_WIG; - // SSE1 & 2 - let Constraints = "$src1 = $dst" in { - let Predicates = [pred, NoSSE41_Or_OptForSize] in - defm NAME : sse12_move_rr; - } - - def NAME#mr : SI<0x11, MRMDestMem, (outs), (ins x86memop:$dst, RC:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(store RC:$src, addr:$dst)], d>, - Sched<[WriteFStore]>; - - // def : InstAlias<"v"#OpcodeStr#".s\t{$src2, $src1, $dst|$dst, $src1, $src2}", - // (!cast("V"#NAME#"rr_REV") - // VR128:$dst, VR128:$src1, VR128:$src2), 0>; - // def : InstAlias(NAME#"rr_REV") - // VR128:$dst, VR128:$src2), 0>; -} - -// Loading from memory automatically zeroing upper bits. -multiclass sse12_move_rm { - def V#NAME#rm : SI<0x10, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set RC:$dst, (mem_pat addr:$src))], d>, - VEX, VEX_LIG, Sched<[WriteFLoad]>, VEX_WIG; - def NAME#rm : SI<0x10, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set RC:$dst, (mem_pat addr:$src))], d>, - Sched<[WriteFLoad]>; -} - -defm MOVSS : sse12_move, XS; -defm MOVSD : sse12_move, XD; - -let canFoldAsLoad = 1, isReMaterializable = 1 in { - defm MOVSS : sse12_move_rm, XS; - defm MOVSD : sse12_move_rm, XD; -} - -// Patterns -let Predicates = [UseAVX] in { - // MOVSSrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - - // MOVSDrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - - // Represent the same patterns above but in the form they appear for - // 256-bit types - def : Pat<(v8f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_xmm)>; - def : Pat<(v8f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_xmm)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - addr:$dst), - (VMOVSSmr addr:$dst, (COPY_TO_REGCLASS (v4f32 VR128:$src), FR32))>; -} - -let Predicates = [UseAVX, OptForSize] in { - // Move scalar to XMM zero-extended, zeroing a VR128 then do a - // MOVSS to the lower bits. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (VMOVSSrr (v4f32 (V_SET0)), VR128:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (VMOVSSrr (v4i32 (V_SET0)), VR128:$src)>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSrr (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSrr (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDrr (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDrr (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256:$src), sub_xmm)))), - sub_xmm)>; -} - -let Predicates = [UseSSE1] in { - let Predicates = [UseSSE1, NoSSE41_Or_OptForSize] in { - // Move scalar to XMM zero-extended, zeroing a VR128 then do a - // MOVSS to the lower bits. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (MOVSSrr (v4f32 (V_SET0)), VR128:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (MOVSSrr (v4i32 (V_SET0)), VR128:$src)>; - } - - // MOVSSrm already zeros the high parts of the register. - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - addr:$dst), - (MOVSSmr addr:$dst, (COPY_TO_REGCLASS VR128:$src, FR32))>; -} - -let Predicates = [UseSSE2] in { - // MOVSDrm already zeros the high parts of the register. - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; -} - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -// def : InstAlias<"vmovss\t{$src2, $src1, $dst|$dst, $src1, $src2}", -// (VMOVSSrr_REV VR128L:$dst, VR128:$src1, VR128H:$src2), 0>; -// def : InstAlias<"vmovsd\t{$src2, $src1, $dst|$dst, $src1, $src2}", -// (VMOVSDrr_REV VR128L:$dst, VR128:$src1, VR128H:$src2), 0>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Aligned/Unaligned FP Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_mov_packed opc, RegisterClass RC, - X86MemOperand x86memop, PatFrag ld_frag, - string asm, Domain d, - X86SchedWriteMoveLS sched> { -let hasSideEffects = 0, isMoveReg = 1 in - def rr : PI, - Sched<[sched.RR]>; -let canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : PI, - Sched<[sched.RM]>; -} - -let Predicates = [HasAVX, NoVLX] in { -defm VMOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS, VEX, VEX_WIG; -defm VMOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD, VEX, VEX_WIG; -defm VMOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS, VEX, VEX_WIG; -defm VMOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD, VEX, VEX_WIG; - -defm VMOVAPSY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv8f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.YMM>, - PS, VEX, VEX_L, VEX_WIG; -defm VMOVAPDY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv4f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.YMM>, - PD, VEX, VEX_L, VEX_WIG; -defm VMOVUPSY : sse12_mov_packed<0x10, VR256, f256mem, loadv8f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.YMM>, - PS, VEX, VEX_L, VEX_WIG; -defm VMOVUPDY : sse12_mov_packed<0x10, VR256, f256mem, loadv4f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.YMM>, - PD, VEX, VEX_L, VEX_WIG; -} - -let Predicates = [UseSSE1] in { -defm MOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS; -defm MOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS; -} -let Predicates = [UseSSE2] in { -defm MOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD; -defm MOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD; -} - -let Predicates = [HasAVX, NoVLX] in { -let SchedRW = [SchedWriteFMoveLS.XMM.MR] in { -def VMOVAPSmr : VPSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f32 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVAPDmr : VPDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v2f64 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVUPSmr : VPSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v4f32 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVUPDmr : VPDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v2f64 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLS.YMM.MR] in { -def VMOVAPSYmr : VPSI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v8f32 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVAPDYmr : VPDI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f64 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVUPSYmr : VPSI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v8f32 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVUPDYmr : VPDI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v4f64 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -} // SchedRW -} // Predicate - -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - isMoveReg = 1 in { -let SchedRW = [SchedWriteFMoveLS.XMM.RR] in { - def VMOVAPSrr_REV : VPSI<0x29, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVAPSrr">; - def VMOVAPDrr_REV : VPDI<0x29, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVAPDrr">; - def VMOVUPSrr_REV : VPSI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVUPSrr">; - def VMOVUPDrr_REV : VPDI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVUPDrr">; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLS.YMM.RR] in { - def VMOVAPSYrr_REV : VPSI<0x29, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVAPSYrr">; - def VMOVAPDYrr_REV : VPDI<0x29, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVAPDYrr">; - def VMOVUPSYrr_REV : VPSI<0x11, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVUPSYrr">; - def VMOVUPDYrr_REV : VPDI<0x11, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVUPDYrr">; -} // SchedRW -} // Predicate - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -// def : InstAlias<"vmovaps\t{$src, $dst|$dst, $src}", -// (VMOVAPSrr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovapd\t{$src, $dst|$dst, $src}", -// (VMOVAPDrr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovups\t{$src, $dst|$dst, $src}", -// (VMOVUPSrr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovupd\t{$src, $dst|$dst, $src}", -// (VMOVUPDrr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovaps\t{$src, $dst|$dst, $src}", -// (VMOVAPSYrr_REV VR256L:$dst, VR256H:$src), 0>; -// def : InstAlias<"vmovapd\t{$src, $dst|$dst, $src}", -// (VMOVAPDYrr_REV VR256L:$dst, VR256H:$src), 0>; -// def : InstAlias<"vmovups\t{$src, $dst|$dst, $src}", -// (VMOVUPSYrr_REV VR256L:$dst, VR256H:$src), 0>; -// def : InstAlias<"vmovupd\t{$src, $dst|$dst, $src}", -// (VMOVUPDYrr_REV VR256L:$dst, VR256H:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -// def : InstAlias<"vmovaps.s\t{$src, $dst|$dst, $src}", -// (VMOVAPSrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovapd.s\t{$src, $dst|$dst, $src}", -// (VMOVAPDrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovups.s\t{$src, $dst|$dst, $src}", -// (VMOVUPSrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovupd.s\t{$src, $dst|$dst, $src}", -// (VMOVUPDrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovaps.s\t{$src, $dst|$dst, $src}", -// (VMOVAPSYrr_REV VR256:$dst, VR256:$src), 0>; -// def : InstAlias<"vmovapd.s\t{$src, $dst|$dst, $src}", -// (VMOVAPDYrr_REV VR256:$dst, VR256:$src), 0>; -// def : InstAlias<"vmovups.s\t{$src, $dst|$dst, $src}", -// (VMOVUPSYrr_REV VR256:$dst, VR256:$src), 0>; -// def : InstAlias<"vmovupd.s\t{$src, $dst|$dst, $src}", -// (VMOVUPDYrr_REV VR256:$dst, VR256:$src), 0>; - -let SchedRW = [SchedWriteFMoveLS.XMM.MR] in { -def MOVAPSmr : PSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f32 VR128:$src), addr:$dst)]>; -def MOVAPDmr : PDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v2f64 VR128:$src), addr:$dst)]>; -def MOVUPSmr : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v4f32 VR128:$src), addr:$dst)]>; -def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v2f64 VR128:$src), addr:$dst)]>; -} // SchedRW - -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - isMoveReg = 1, SchedRW = [SchedWriteFMoveLS.XMM.RR] in { - def MOVAPSrr_REV : PSI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVAPSrr">; - def MOVAPDrr_REV : PDI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVAPDrr">; - def MOVUPSrr_REV : PSI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVUPSrr">; - def MOVUPDrr_REV : PDI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVUPDrr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -// def : InstAlias<"movaps.s\t{$src, $dst|$dst, $src}", -// (MOVAPSrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"movapd.s\t{$src, $dst|$dst, $src}", -// (MOVAPDrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"movups.s\t{$src, $dst|$dst, $src}", -// (MOVUPSrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"movupd.s\t{$src, $dst|$dst, $src}", -// (MOVUPDrr_REV VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in { - // 256-bit load/store need to use floating point load/store in case we don't - // have AVX2. Execution domain fixing will convert to integer if AVX2 is - // available and changing the domain is beneficial. - def : Pat<(alignedloadv4i64 addr:$src), - (VMOVAPSYrm addr:$src)>; - def : Pat<(loadv4i64 addr:$src), - (VMOVUPSYrm addr:$src)>; - def : Pat<(alignedstore (v4i64 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v8i32 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v16i16 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v32i8 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v4i64 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v8i32 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v16i16 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v32i8 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; -} - -// Use movaps / movups for SSE integer load / store (one byte shorter). -// The instructions selected below are then converted to MOVDQA/MOVDQU -// during the SSE domain pass. -let Predicates = [UseSSE1] in { - def : Pat<(alignedloadv2i64 addr:$src), - (MOVAPSrm addr:$src)>; - def : Pat<(loadv2i64 addr:$src), - (MOVUPSrm addr:$src)>; - - def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v2i64 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v4i32 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v8i16 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v16i8 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Low packed FP Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_mov_hilo_packed_baseopc, SDNode pdnode, - string base_opc, string asm_opr> { - // No pattern as they need be special cased between high and low. - let hasSideEffects = 0, mayLoad = 1 in - def PSrm : PI, PS, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; - - def PDrm : PI, PD, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -multiclass sse12_mov_hilo_packedopc, SDPatternOperator pdnode, - string base_opc> { - let Predicates = [UseAVX] in - defm V#NAME : sse12_mov_hilo_packed_base, - VEX_4V, VEX_WIG; - - let Constraints = "$src1 = $dst" in - defm NAME : sse12_mov_hilo_packed_base; -} - -defm MOVL : sse12_mov_hilo_packed<0x12, X86Movsd, "movlp">; - -let SchedRW = [WriteFStore] in { -let Predicates = [UseAVX] in { -def VMOVLPSmr : VPSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128:$src)), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVLPDmr : VPDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -}// UseAVX -def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128:$src)), - (iPTR 0))), addr:$dst)]>; -def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128:$src), - (iPTR 0))), addr:$dst)]>; -} // SchedRW - -let Predicates = [UseSSE1] in { - // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS - def : Pat<(store (i64 (extractelt (bc_v2i64 (v4f32 VR128:$src2)), - (iPTR 0))), addr:$src1), - (MOVLPSmr addr:$src1, VR128:$src2)>; - - // This pattern helps select MOVLPS on SSE1 only targets. With SSE2 we'll - // end up with a movsd or blend instead of shufp. - // No need for aligned load, we're only loading 64-bits. - def : Pat<(X86Shufp (loadv4f32 addr:$src2), VR128:$src1, (i8 -28)), - (MOVLPSrm VR128:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Hi packed FP Instructions -//===----------------------------------------------------------------------===// - -defm MOVH : sse12_mov_hilo_packed<0x16, X86Unpckl, "movhp">; - -let SchedRW = [WriteFStore] in { -// v2f64 extract element 1 is always custom lowered to unpack high to low -// and extract element 0 so the non-store version isn't too horrible. -let Predicates = [UseAVX] in { -def VMOVHPSmr : VPSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128:$src)), - (bc_v2f64 (v4f32 VR128:$src))), - (iPTR 0))), addr:$dst)]>, VEX, VEX_WIG; -def VMOVHPDmr : VPDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128:$src, VR128:$src)), - (iPTR 0))), addr:$dst)]>, VEX, VEX_WIG; -} // UseAVX -def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128:$src)), - (bc_v2f64 (v4f32 VR128:$src))), - (iPTR 0))), addr:$dst)]>; -def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128:$src, VR128:$src)), - (iPTR 0))), addr:$dst)]>; -} // SchedRW - -let Predicates = [UseAVX] in { - // Also handle an i64 load because that may get selected as a faster way to - // load the data. - def : Pat<(v2f64 (X86Unpckl VR128:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (VMOVHPDrm VR128:$src1, addr:$src2)>; - - def : Pat<(store (f64 (extractelt - (v2f64 (X86VPermilpi VR128:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (VMOVHPDmr addr:$dst, VR128:$src)>; -} - -let Predicates = [UseSSE1] in { - // This pattern helps select MOVHPS on SSE1 only targets. With SSE2 we'll - // end up with a movsd or blend instead of shufp. - // No need for aligned load, we're only loading 64-bits. - def : Pat<(X86Movlhps VR128:$src1, (loadv4f32 addr:$src2)), - (MOVHPSrm VR128:$src1, addr:$src2)>; -} - -let Predicates = [UseSSE2] in { - // MOVHPD patterns - - // Also handle an i64 load because that may get selected as a faster way to - // load the data. - def : Pat<(v2f64 (X86Unpckl VR128:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (MOVHPDrm VR128:$src1, addr:$src2)>; - - def : Pat<(store (f64 (extractelt - (v2f64 (X86Shufp VR128:$src, VR128:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (MOVHPDmr addr:$dst, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Low to High and High to Low packed FP Instructions -//===----------------------------------------------------------------------===// - -let Predicates = [UseAVX] in { - def VMOVLHPSrr : VPSI<0x16, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movlhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movlhps VR128:$src1, VR128:$src2)))]>, - VEX_4V, Sched<[SchedWriteFShuffle.XMM]>, VEX_WIG; - let isCommutable = 1 in - def VMOVHLPSrr : VPSI<0x12, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movhlps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movhlps VR128:$src1, VR128:$src2)))]>, - VEX_4V, Sched<[SchedWriteFShuffle.XMM]>, VEX_WIG, - NotMemoryFoldable; -} -let Constraints = "$src1 = $dst" in { - def MOVLHPSrr : PSI<0x16, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movlhps\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movlhps VR128:$src1, VR128:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>; - let isCommutable = 1 in - def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movhlps\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movhlps VR128:$src1, VR128:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, NotMemoryFoldable; -} - -// TODO: This is largely to trick fastisel into ignoring the pattern. -def UnpckhUnary : PatFrag<(ops node:$src1, node:$src2), - (X86Unpckh node:$src1, node:$src2), [{ - return N->getOperand(0) == N->getOperand(1); -}]>; - -let Predicates = [UseSSE2] in { - // TODO: This is a hack pattern to allow lowering to emit unpckh instead of - // movhlps for sse2 without changing a bunch of tests. - def : Pat<(v2f64 (UnpckhUnary VR128:$src, VR128:$src)), - (MOVHLPSrr VR128:$src, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Conversion Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_cvt_s opc, RegisterClass SrcRC, RegisterClass DstRC, - SDNode OpNode, X86MemOperand x86memop, PatFrag ld_frag, - string asm, X86FoldableSchedWrite sched> { - def rr : SI, - Sched<[sched]>; - def rm : SI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_p opc, RegisterClass RC, X86MemOperand x86memop, - ValueType DstTy, ValueType SrcTy, PatFrag ld_frag, - string asm, Domain d, X86FoldableSchedWrite sched> { -let hasSideEffects = 0 in { - def rr : I, - Sched<[sched]>; - let mayLoad = 1 in - def rm : I, - Sched<[sched.Folded]>; -} -} - -multiclass sse12_vcvt_avx opc, RegisterClass SrcRC, RegisterClass DstRC, - X86MemOperand x86memop, string asm, - X86FoldableSchedWrite sched> { -let hasSideEffects = 0, Predicates = [UseAVX] in { - def rr : SI, - Sched<[sched]>; - let mayLoad = 1 in - def rm : SI, - Sched<[sched.Folded, ReadAfterLd]>; -} // hasSideEffects = 0 -} - -let Predicates = [UseAVX] in { -defm VCVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, - XS, VEX, VEX_LIG; -defm VCVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, - XS, VEX, VEX_W, VEX_LIG; -defm VCVTTSD2SI : sse12_cvt_s<0x2C, FR64, GR32, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, - XD, VEX, VEX_LIG; -defm VCVTTSD2SI64 : sse12_cvt_s<0x2C, FR64, GR64, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, - XD, VEX, VEX_W, VEX_LIG; - -// def : InstAlias<"vcvttss2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTTSS2SIrr GR32:$dst, FR32:$src), 0, "att">; -// def : InstAlias<"vcvttss2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTTSS2SIrm GR32:$dst, f32mem:$src), 0, "att">; -// def : InstAlias<"vcvttsd2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTTSD2SIrr GR32:$dst, FR64:$src), 0, "att">; -// def : InstAlias<"vcvttsd2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTTSD2SIrm GR32:$dst, f64mem:$src), 0, "att">; -// def : InstAlias<"vcvttss2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTTSS2SI64rr GR64:$dst, FR32:$src), 0, "att">; -// def : InstAlias<"vcvttss2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTTSS2SI64rm GR64:$dst, f32mem:$src), 0, "att">; -// def : InstAlias<"vcvttsd2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTTSD2SI64rr GR64:$dst, FR64:$src), 0, "att">; -// def : InstAlias<"vcvttsd2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTTSD2SI64rm GR64:$dst, f64mem:$src), 0, "att">; -} -// The assembler can recognize rr 64-bit instructions by seeing a rxx -// register, but the same isn't true when only using memory operands, -// provide other assembly "l" and "q" forms to address this explicitly -// where appropriate to do so. -defm VCVTSI2SS : sse12_vcvt_avx<0x2A, GR32, FR32, i32mem, "cvtsi2ss{l}", - WriteCvtI2SS>, XS, VEX_4V, VEX_LIG; -defm VCVTSI642SS : sse12_vcvt_avx<0x2A, GR64, FR32, i64mem, "cvtsi2ss{q}", - WriteCvtI2SS>, XS, VEX_4V, VEX_W, VEX_LIG; -defm VCVTSI2SD : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd{l}", - WriteCvtI2SD>, XD, VEX_4V, VEX_LIG; -defm VCVTSI642SD : sse12_vcvt_avx<0x2A, GR64, FR64, i64mem, "cvtsi2sd{q}", - WriteCvtI2SD>, XD, VEX_4V, VEX_W, VEX_LIG; - -let Predicates = [UseAVX] in { - // def : InstAlias<"vcvtsi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", - // (VCVTSI2SSrm FR64:$dst, FR64:$src1, i32mem:$src), 0, "att">; - // def : InstAlias<"vcvtsi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", - // (VCVTSI2SDrm FR64:$dst, FR64:$src1, i32mem:$src), 0, "att">; - - def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SSrm (f32 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f32 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SSrm (f32 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f64 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f64 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SDrm (f64 (IMPLICIT_DEF)), addr:$src)>; - - def : Pat<(f32 (sint_to_fp GR32:$src)), - (VCVTSI2SSrr (f32 (IMPLICIT_DEF)), GR32:$src)>; - def : Pat<(f32 (sint_to_fp GR64:$src)), - (VCVTSI642SSrr (f32 (IMPLICIT_DEF)), GR64:$src)>; - def : Pat<(f64 (sint_to_fp GR32:$src)), - (VCVTSI2SDrr (f64 (IMPLICIT_DEF)), GR32:$src)>; - def : Pat<(f64 (sint_to_fp GR64:$src)), - (VCVTSI642SDrr (f64 (IMPLICIT_DEF)), GR64:$src)>; -} - -defm CVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, XS; -defm CVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, XS, REX_W; -defm CVTTSD2SI : sse12_cvt_s<0x2C, FR64, GR32, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, XD; -defm CVTTSD2SI64 : sse12_cvt_s<0x2C, FR64, GR64, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, XD, REX_W; -defm CVTSI2SS : sse12_cvt_s<0x2A, GR32, FR32, sint_to_fp, i32mem, loadi32, - "cvtsi2ss{l}\t{$src, $dst|$dst, $src}", - WriteCvtI2SS>, XS; -defm CVTSI642SS : sse12_cvt_s<0x2A, GR64, FR32, sint_to_fp, i64mem, loadi64, - "cvtsi2ss{q}\t{$src, $dst|$dst, $src}", - WriteCvtI2SS>, XS, REX_W; -defm CVTSI2SD : sse12_cvt_s<0x2A, GR32, FR64, sint_to_fp, i32mem, loadi32, - "cvtsi2sd{l}\t{$src, $dst|$dst, $src}", - WriteCvtI2SD>, XD; -defm CVTSI642SD : sse12_cvt_s<0x2A, GR64, FR64, sint_to_fp, i64mem, loadi64, - "cvtsi2sd{q}\t{$src, $dst|$dst, $src}", - WriteCvtI2SD>, XD, REX_W; - -// def : InstAlias<"cvttss2si{l}\t{$src, $dst|$dst, $src}", -// (CVTTSS2SIrr GR32:$dst, FR32:$src), 0, "att">; -// def : InstAlias<"cvttss2si{l}\t{$src, $dst|$dst, $src}", -// (CVTTSS2SIrm GR32:$dst, f32mem:$src), 0, "att">; -// def : InstAlias<"cvttsd2si{l}\t{$src, $dst|$dst, $src}", -// (CVTTSD2SIrr GR32:$dst, FR64:$src), 0, "att">; -// def : InstAlias<"cvttsd2si{l}\t{$src, $dst|$dst, $src}", -// (CVTTSD2SIrm GR32:$dst, f64mem:$src), 0, "att">; -// def : InstAlias<"cvttss2si{q}\t{$src, $dst|$dst, $src}", -// (CVTTSS2SI64rr GR64:$dst, FR32:$src), 0, "att">; -// def : InstAlias<"cvttss2si{q}\t{$src, $dst|$dst, $src}", -// (CVTTSS2SI64rm GR64:$dst, f32mem:$src), 0, "att">; -// def : InstAlias<"cvttsd2si{q}\t{$src, $dst|$dst, $src}", -// (CVTTSD2SI64rr GR64:$dst, FR64:$src), 0, "att">; -// def : InstAlias<"cvttsd2si{q}\t{$src, $dst|$dst, $src}", -// (CVTTSD2SI64rm GR64:$dst, f64mem:$src), 0, "att">; - -// def : InstAlias<"cvtsi2ss\t{$src, $dst|$dst, $src}", -// (CVTSI2SSrm FR64:$dst, i32mem:$src), 0, "att">; -// def : InstAlias<"cvtsi2sd\t{$src, $dst|$dst, $src}", -// (CVTSI2SDrm FR64:$dst, i32mem:$src), 0, "att">; - -// Conversion Instructions Intrinsics - Match intrinsics which expect MM -// and/or XMM operand(s). - -// FIXME: We probably want to match the rm form only when optimizing for -// size, to avoid false dependencies (see sse_fp_unop_s for details) -multiclass sse12_cvt_sint opc, RegisterClass SrcRC, RegisterClass DstRC, - Intrinsic Int, Operand memop, ComplexPattern mem_cpat, - string asm, X86FoldableSchedWrite sched> { - def rr_Int : SI, - Sched<[sched]>; - def rm_Int : SI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_sint_3addr opc, RegisterClass SrcRC, - RegisterClass DstRC, X86MemOperand x86memop, - string asm, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { -let hasSideEffects = 0 in { - def rr_Int : SI, Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : SI, Sched<[sched.Folded, ReadAfterLd]>; -} -} - -let Predicates = [UseAVX] in { -defm VCVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, - int_x86_sse2_cvtsd2si, sdmem, sse_load_f64, "cvtsd2si", - WriteCvtSD2I>, XD, VEX, VEX_LIG; -defm VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, - int_x86_sse2_cvtsd2si64, sdmem, sse_load_f64, "cvtsd2si", - WriteCvtSD2I>, XD, VEX, VEX_W, VEX_LIG; -} -defm CVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si, - sdmem, sse_load_f64, "cvtsd2si", WriteCvtSD2I>, XD; -defm CVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse2_cvtsd2si64, - sdmem, sse_load_f64, "cvtsd2si", WriteCvtSD2I>, XD, REX_W; - - -let isCodeGenOnly = 1 in { - let Predicates = [UseAVX] in { - defm VCVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2ss{l}", WriteCvtI2SS, 0>, XS, VEX_4V; - defm VCVTSI642SS : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2ss{q}", WriteCvtI2SS, 0>, XS, VEX_4V, VEX_W; - defm VCVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2sd{l}", WriteCvtI2SD, 0>, XD, VEX_4V; - defm VCVTSI642SD : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2sd{q}", WriteCvtI2SD, 0>, XD, VEX_4V, VEX_W; - } - let Constraints = "$src1 = $dst" in { - defm CVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2ss{l}", WriteCvtI2SS>, XS; - defm CVTSI642SS : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2ss{q}", WriteCvtI2SS>, XS, REX_W; - defm CVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2sd{l}", WriteCvtI2SD>, XD; - defm CVTSI642SD : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2sd{q}", WriteCvtI2SD>, XD, REX_W; - } -} // isCodeGenOnly = 1 - -/// SSE 1 Only - -// Aliases for intrinsics -let isCodeGenOnly = 1 in { -let Predicates = [UseAVX] in { -defm VCVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, - ssmem, sse_load_f32, "cvttss2si", - WriteCvtSS2I>, XS, VEX; -defm VCVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse_cvttss2si64, ssmem, sse_load_f32, - "cvttss2si", WriteCvtSS2I>, - XS, VEX, VEX_W; -defm VCVTTSD2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse2_cvttsd2si, - sdmem, sse_load_f64, "cvttsd2si", - WriteCvtSS2I>, XD, VEX; -defm VCVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse2_cvttsd2si64, sdmem, sse_load_f64, - "cvttsd2si", WriteCvtSS2I>, - XD, VEX, VEX_W; -} -defm CVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, - ssmem, sse_load_f32, "cvttss2si", - WriteCvtSS2I>, XS; -defm CVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse_cvttss2si64, ssmem, sse_load_f32, - "cvttss2si", WriteCvtSS2I>, XS, REX_W; -defm CVTTSD2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse2_cvttsd2si, - sdmem, sse_load_f64, "cvttsd2si", - WriteCvtSD2I>, XD; -defm CVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse2_cvttsd2si64, sdmem, sse_load_f64, - "cvttsd2si", WriteCvtSD2I>, XD, REX_W; -} // isCodeGenOnly = 1 - -let Predicates = [UseAVX] in { -defm VCVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, VEX, VEX_LIG; -defm VCVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, VEX, VEX_W, VEX_LIG; -} -defm CVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS; -defm CVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, REX_W; - -defm VCVTDQ2PS : sse12_cvt_p<0x5B, VR128, i128mem, v4f32, v4i32, loadv2i64, - "vcvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PS>, - PS, VEX, Requires<[HasAVX, NoVLX]>, VEX_WIG; -defm VCVTDQ2PSY : sse12_cvt_p<0x5B, VR256, i256mem, v8f32, v8i32, loadv4i64, - "vcvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PSY>, - PS, VEX, VEX_L, Requires<[HasAVX, NoVLX]>, VEX_WIG; - -defm CVTDQ2PS : sse12_cvt_p<0x5B, VR128, i128mem, v4f32, v4i32, memopv2i64, - "cvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PS>, - PS, Requires<[UseSSE2]>; - -let Predicates = [UseAVX] in { -// def : InstAlias<"vcvtss2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTSS2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"vcvtss2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTSS2SIrm_Int GR32:$dst, ssmem:$src), 0, "att">; -// def : InstAlias<"vcvtsd2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTSD2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"vcvtsd2si{l}\t{$src, $dst|$dst, $src}", -// (VCVTSD2SIrm_Int GR32:$dst, sdmem:$src), 0, "att">; -// def : InstAlias<"vcvtss2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTSS2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"vcvtss2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTSS2SI64rm_Int GR64:$dst, ssmem:$src), 0, "att">; -// def : InstAlias<"vcvtsd2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTSD2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"vcvtsd2si{q}\t{$src, $dst|$dst, $src}", -// (VCVTSD2SI64rm_Int GR64:$dst, sdmem:$src), 0, "att">; -} - -// def : InstAlias<"cvtss2si{l}\t{$src, $dst|$dst, $src}", -// (CVTSS2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"cvtss2si{l}\t{$src, $dst|$dst, $src}", -// (CVTSS2SIrm_Int GR32:$dst, ssmem:$src), 0, "att">; -// def : InstAlias<"cvtsd2si{l}\t{$src, $dst|$dst, $src}", -// (CVTSD2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"cvtsd2si{l}\t{$src, $dst|$dst, $src}", -// (CVTSD2SIrm_Int GR32:$dst, sdmem:$src), 0, "att">; -// def : InstAlias<"cvtss2si{q}\t{$src, $dst|$dst, $src}", -// (CVTSS2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"cvtss2si{q}\t{$src, $dst|$dst, $src}", -// (CVTSS2SI64rm_Int GR64:$dst, ssmem:$src), 0, "att">; -// def : InstAlias<"cvtsd2si{q}\t{$src, $dst|$dst, $src}", -// (CVTSD2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -// def : InstAlias<"cvtsd2si{q}\t{$src, $dst|$dst, $src}", -// (CVTSD2SI64rm_Int GR64:$dst, sdmem:$src), 0, "att">; - -/// SSE 2 Only - -// Convert scalar double to scalar single -let hasSideEffects = 0, Predicates = [UseAVX] in { -def VCVTSD2SSrr : VSDI<0x5A, MRMSrcReg, (outs FR32:$dst), - (ins FR32:$src1, FR64:$src2), - "cvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSD2SS]>; -let mayLoad = 1 in -def VCVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), - (ins FR32:$src1, f64mem:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XD, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -} - -def : Pat<(f32 (fpround FR64:$src)), - (VCVTSD2SSrr (f32 (IMPLICIT_DEF)), FR64:$src)>, - Requires<[UseAVX]>; - -def CVTSD2SSrr : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src), - "cvtsd2ss\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (fpround FR64:$src))]>, - Sched<[WriteCvtSD2SS]>; -def CVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), - "cvtsd2ss\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (fpround (loadf64 addr:$src)))]>, - XD, Requires<[UseSSE2, OptForSize]>, - Sched<[WriteCvtSD2SS.Folded]>; - -let isCodeGenOnly = 1 in { -def VCVTSD2SSrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_sse2_cvtsd2ss VR128:$src1, VR128:$src2))]>, - XD, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSD2SS]>; -def VCVTSD2SSrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, sdmem:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (int_x86_sse2_cvtsd2ss - VR128:$src1, sse_load_f64:$src2))]>, - XD, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -let Constraints = "$src1 = $dst" in { -def CVTSD2SSrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "cvtsd2ss\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (int_x86_sse2_cvtsd2ss VR128:$src1, VR128:$src2))]>, - XD, Requires<[UseSSE2]>, Sched<[WriteCvtSD2SS]>; -def CVTSD2SSrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, sdmem:$src2), - "cvtsd2ss\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, (int_x86_sse2_cvtsd2ss - VR128:$src1, sse_load_f64:$src2))]>, - XD, Requires<[UseSSE2]>, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -} -} // isCodeGenOnly = 1 - -// Convert scalar single to scalar double -// SSE2 instructions with XS prefix -let hasSideEffects = 0 in { -def VCVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), - (ins FR64:$src1, FR32:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XS, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSS2SD]>, Requires<[UseAVX]>; -let mayLoad = 1 in -def VCVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), - (ins FR64:$src1, f32mem:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XS, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>, - Requires<[UseAVX, OptForSize]>; -} - -def : Pat<(f64 (fpextend FR32:$src)), - (VCVTSS2SDrr (f64 (IMPLICIT_DEF)), FR32:$src)>, Requires<[UseAVX]>; -def : Pat<(fpextend (loadf32 addr:$src)), - (VCVTSS2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>, Requires<[UseAVX, OptForSize]>; - -def : Pat<(extloadf32 addr:$src), - (VCVTSS2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[UseAVX, OptForSize]>; -def : Pat<(extloadf32 addr:$src), - (VCVTSS2SDrr (f64 (IMPLICIT_DEF)), (VMOVSSrm addr:$src))>, - Requires<[UseAVX, OptForSpeed]>; - -def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src), - "cvtss2sd\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (fpextend FR32:$src))]>, - XS, Requires<[UseSSE2]>, Sched<[WriteCvtSS2SD]>; -def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), - "cvtss2sd\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (extloadf32 addr:$src))]>, - XS, Requires<[UseSSE2, OptForSize]>, - Sched<[WriteCvtSS2SD.Folded]>; - -// extload f32 -> f64. This matches load+fpextend because we have a hack in -// the isel (PreprocessForFPConvert) that can introduce loads after dag -// combine. -// Since these loads aren't folded into the fpextend, we have to match it -// explicitly here. -def : Pat<(fpextend (loadf32 addr:$src)), - (CVTSS2SDrm addr:$src)>, Requires<[UseSSE2, OptForSize]>; -def : Pat<(extloadf32 addr:$src), - (CVTSS2SDrr (MOVSSrm addr:$src))>, Requires<[UseSSE2, OptForSpeed]>; - -let isCodeGenOnly = 1, hasSideEffects = 0 in { -def VCVTSS2SDrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, VEX_4V, VEX_WIG, - Requires<[HasAVX]>, Sched<[WriteCvtSS2SD]>; -let mayLoad = 1 in -def VCVTSS2SDrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, ssmem:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>; -let Constraints = "$src1 = $dst" in { // SSE2 instructions with XS prefix -def CVTSS2SDrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "cvtss2sd\t{$src2, $dst|$dst, $src2}", - []>, XS, Requires<[UseSSE2]>, - Sched<[WriteCvtSS2SD]>; -let mayLoad = 1 in -def CVTSS2SDrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, ssmem:$src2), - "cvtss2sd\t{$src2, $dst|$dst, $src2}", - []>, XS, Requires<[UseSSE2]>, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>; -} -} // isCodeGenOnly = 1 - -// Patterns used for matching (v)cvtsi2ss, (v)cvtsi2sd, (v)cvtsd2ss and -// (v)cvtss2sd intrinsic sequences from clang which produce unnecessary -// vmovs{s,d} instructions -let Predicates = [UseAVX] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128:$src, (iPTR 0))))))))), - (VCVTSD2SSrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128:$src, (iPTR 0))))))))), - (VCVTSS2SDrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (VCVTSI642SSrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (VCVTSI2SSrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (VCVTSI642SDrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SDrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (VCVTSI2SDrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SDrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseAVX] - -let Predicates = [UseSSE2] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128:$src, (iPTR 0))))))))), - (CVTSD2SSrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128:$src, (iPTR 0))))))))), - (CVTSS2SDrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (CVTSI642SDrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (CVTSI642SDrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (CVTSI2SDrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (CVTSI2SDrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseSSE2] - -let Predicates = [UseSSE1] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (CVTSI642SSrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (CVTSI642SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (CVTSI2SSrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (CVTSI2SSrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseSSE1] - -let Predicates = [HasAVX, NoVLX] in { -// Convert packed single/double fp to doubleword -def VCVTPS2DQrr : VPDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4i32 (X86cvtp2Int (v4f32 VR128:$src))))]>, - VEX, Sched<[WriteCvtPS2I]>, VEX_WIG; -def VCVTPS2DQrm : VPDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv4f32 addr:$src))))]>, - VEX, Sched<[WriteCvtPS2ILd]>, VEX_WIG; -def VCVTPS2DQYrr : VPDI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvtp2Int (v8f32 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IY]>, VEX_WIG; -def VCVTPS2DQYrm : VPDI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvtp2Int (loadv8f32 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IYLd]>, VEX_WIG; -} -def CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4i32 (X86cvtp2Int (v4f32 VR128:$src))))]>, - Sched<[WriteCvtPS2I]>; -def CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (memopv4f32 addr:$src))))]>, - Sched<[WriteCvtPS2ILd]>; - - -// Convert Packed Double FP to Packed DW Integers -let Predicates = [HasAVX, NoVLX] in { -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. -def VCVTPD2DQrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v2f64 VR128:$src))))]>, - VEX, Sched<[WriteCvtPD2I]>, VEX_WIG; - -// XMM only -// def : InstAlias<"vcvtpd2dqx\t{$src, $dst|$dst, $src}", -// (VCVTPD2DQrr VR128:$dst, VR128:$src), 0>; -def VCVTPD2DQrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "vcvtpd2dq{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src))))]>, VEX, - Sched<[WriteCvtPD2ILd]>, VEX_WIG; -// def : InstAlias<"vcvtpd2dqx\t{$src, $dst|$dst, $src}", -// (VCVTPD2DQrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -def VCVTPD2DQYrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "vcvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v4f64 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IY]>, VEX_WIG; -def VCVTPD2DQYrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "vcvtpd2dq{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv4f64 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IYLd]>, VEX_WIG; -// def : InstAlias<"vcvtpd2dqy\t{$src, $dst|$dst, $src}", -// (VCVTPD2DQYrr VR128:$dst, VR256:$src), 0>; -// def : InstAlias<"vcvtpd2dqy\t{$src, $dst|$dst, $src}", -// (VCVTPD2DQYrm VR128:$dst, f256mem:$src), 0, "intel">; -} - -def CVTPD2DQrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (memopv2f64 addr:$src))))]>, - Sched<[WriteCvtPD2ILd]>; -def CVTPD2DQrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v2f64 VR128:$src))))]>, - Sched<[WriteCvtPD2I]>; - -// Convert with truncation packed single/double fp to doubleword -// SSE2 packed instructions with XS prefix -let Predicates = [HasAVX, NoVLX] in { -def VCVTTPS2DQrr : VS2SI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f32 VR128:$src))))]>, - VEX, Sched<[WriteCvtPS2I]>, VEX_WIG; -def VCVTTPS2DQrm : VS2SI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv4f32 addr:$src))))]>, - VEX, Sched<[WriteCvtPS2ILd]>, VEX_WIG; -def VCVTTPS2DQYrr : VS2SI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvttp2si (v8f32 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IY]>, VEX_WIG; -def VCVTTPS2DQYrm : VS2SI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvttp2si (loadv8f32 addr:$src))))]>, - VEX, VEX_L, - Sched<[WriteCvtPS2IYLd]>, VEX_WIG; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), - (VCVTTPS2DQrr VR128:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2DQrm addr:$src)>; - def : Pat<(v8i32 (fp_to_sint (v8f32 VR256:$src))), - (VCVTTPS2DQYrr VR256:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2DQYrm addr:$src)>; -} - -def CVTTPS2DQrr : S2SI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f32 VR128:$src))))]>, - Sched<[WriteCvtPS2I]>; -def CVTTPS2DQrm : S2SI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (memopv4f32 addr:$src))))]>, - Sched<[WriteCvtPS2ILd]>; - -let Predicates = [UseSSE2] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), - (CVTTPS2DQrr VR128:$src)>; - def : Pat<(v4i32 (fp_to_sint (memopv4f32 addr:$src))), - (CVTTPS2DQrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in -def VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v2f64 VR128:$src))))]>, - VEX, Sched<[WriteCvtPD2I]>, VEX_WIG; - -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. - -// XMM only -// def : InstAlias<"vcvttpd2dqx\t{$src, $dst|$dst, $src}", -// (VCVTTPD2DQrr VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in -def VCVTTPD2DQrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttpd2dq{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv2f64 addr:$src))))]>, - VEX, Sched<[WriteCvtPD2ILd]>, VEX_WIG; -// def : InstAlias<"vcvttpd2dqx\t{$src, $dst|$dst, $src}", -// (VCVTTPD2DQrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -let Predicates = [HasAVX, NoVLX] in { -def VCVTTPD2DQYrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f64 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IY]>, VEX_WIG; -def VCVTTPD2DQYrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "cvttpd2dq{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv4f64 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IYLd]>, VEX_WIG; -} -// def : InstAlias<"vcvttpd2dqy\t{$src, $dst|$dst, $src}", -// (VCVTTPD2DQYrr VR128:$dst, VR256:$src), 0>; -// def : InstAlias<"vcvttpd2dqy\t{$src, $dst|$dst, $src}", -// (VCVTTPD2DQYrm VR128:$dst, f256mem:$src), 0, "intel">; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f64 VR256:$src))), - (VCVTTPD2DQYrr VR256:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2DQYrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (VCVTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src)))))), - (VCVTPD2DQrm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (VCVTTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (loadv2f64 addr:$src)))))), - (VCVTTPD2DQrm addr:$src)>; -} // Predicates = [HasAVX, NoVLX] - -def CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v2f64 VR128:$src))))]>, - Sched<[WriteCvtPD2I]>; -def CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (memopv2f64 addr:$src))))]>, - Sched<[WriteCvtPD2ILd]>; - -let Predicates = [UseSSE2] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (CVTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (memopv2f64 addr:$src)))))), - (CVTPD2DQrm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (CVTTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (memopv2f64 addr:$src)))))), - (CVTTPD2DQrm addr:$src)>; -} // Predicates = [UseSSE2] - -// Convert packed single to packed double -let Predicates = [HasAVX, NoVLX] in { - // SSE2 instructions without OpSize prefix -def VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (X86vfpext (v4f32 VR128:$src))))]>, - PS, VEX, Sched<[WriteCvtPS2PD]>, VEX_WIG; -def VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (extloadv2f32 addr:$src)))]>, - PS, VEX, Sched<[WriteCvtPS2PD.Folded]>, VEX_WIG; -def VCVTPS2PDYrr : I<0x5A, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (v4f64 (fpextend (v4f32 VR128:$src))))]>, - PS, VEX, VEX_L, Sched<[WriteCvtPS2PDY]>, VEX_WIG; -def VCVTPS2PDYrm : I<0x5A, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (v4f64 (extloadv4f32 addr:$src)))]>, - PS, VEX, VEX_L, Sched<[WriteCvtPS2PDY.Folded]>, VEX_WIG; -} - -let Predicates = [UseSSE2] in { -def CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (X86vfpext (v4f32 VR128:$src))))]>, - PS, Sched<[WriteCvtPS2PD]>; -def CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "cvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (extloadv2f32 addr:$src)))]>, - PS, Sched<[WriteCvtPS2PD.Folded]>; -} - -// Convert Packed DW Integers to Packed Double FP -let Predicates = [HasAVX, NoVLX] in { -let hasSideEffects = 0, mayLoad = 1 in -def VCVTDQ2PDrm : S2SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (bc_v4i32 (loadv2i64 addr:$src)))))]>, - VEX, Sched<[WriteCvtI2PDLd]>, VEX_WIG; -def VCVTDQ2PDrr : S2SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (v4i32 VR128:$src))))]>, - VEX, Sched<[WriteCvtI2PD]>, VEX_WIG; -def VCVTDQ2PDYrm : S2SI<0xE6, MRMSrcMem, (outs VR256:$dst), (ins i128mem:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v4f64 (sint_to_fp (bc_v4i32 (loadv2i64 addr:$src)))))]>, - VEX, VEX_L, Sched<[WriteCvtI2PDYLd]>, - VEX_WIG; -def VCVTDQ2PDYrr : S2SI<0xE6, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v4f64 (sint_to_fp (v4i32 VR128:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtI2PDY]>, VEX_WIG; -} - -let hasSideEffects = 0, mayLoad = 1 in -def CVTDQ2PDrm : S2SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "cvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (bc_v4i32 (loadv2i64 addr:$src)))))]>, - Sched<[WriteCvtI2PDLd]>; -def CVTDQ2PDrr : S2SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (v4i32 VR128:$src))))]>, - Sched<[WriteCvtI2PD]>; - -// AVX register conversion intrinsics -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTDQ2PDrm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTDQ2PDrm addr:$src)>; -} // Predicates = [HasAVX, NoVLX] - -// SSE2 register conversion intrinsics -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (CVTDQ2PDrm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (CVTDQ2PDrm addr:$src)>; -} // Predicates = [UseSSE2] - -// Convert packed double to packed single -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. -let Predicates = [HasAVX, NoVLX] in -def VCVTPD2PSrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (v2f64 VR128:$src)))]>, - VEX, Sched<[WriteCvtPD2PS]>, VEX_WIG; - -// XMM only -// def : InstAlias<"vcvtpd2psx\t{$src, $dst|$dst, $src}", -// (VCVTPD2PSrr VR128:$dst, VR128:$src), 0>; -let Predicates = [HasAVX, NoVLX] in -def VCVTPD2PSrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2ps{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (loadv2f64 addr:$src)))]>, - VEX, Sched<[WriteCvtPD2PS.Folded]>, VEX_WIG; -// def : InstAlias<"vcvtpd2psx\t{$src, $dst|$dst, $src}", -// (VCVTPD2PSrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -let Predicates = [HasAVX, NoVLX] in { -def VCVTPD2PSYrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (fpround VR256:$src))]>, - VEX, VEX_L, Sched<[WriteCvtPD2PSY]>, VEX_WIG; -def VCVTPD2PSYrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "cvtpd2ps{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (fpround (loadv4f64 addr:$src)))]>, - VEX, VEX_L, Sched<[WriteCvtPD2PSY.Folded]>, VEX_WIG; -} -// def : InstAlias<"vcvtpd2psy\t{$src, $dst|$dst, $src}", -// (VCVTPD2PSYrr VR128:$dst, VR256:$src), 0>; -// def : InstAlias<"vcvtpd2psy\t{$src, $dst|$dst, $src}", -// (VCVTPD2PSYrm VR128:$dst, f256mem:$src), 0, "intel">; - -def CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (v2f64 VR128:$src)))]>, - Sched<[WriteCvtPD2PS]>; -def CVTPD2PSrm : PDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (memopv2f64 addr:$src)))]>, - Sched<[WriteCvtPD2PS.Folded]>; - -// AVX 256-bit register conversion intrinsics -// FIXME: Migrate SSE conversion intrinsics matching to use patterns as below -// whenever possible to avoid declaring two versions of each one. - -let Predicates = [HasAVX, NoVLX] in { - // Match fpround and fpextend for 128/256-bit conversions - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128:$src)))))), - (VCVTPD2PSrr VR128:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (loadv2f64 addr:$src)))))), - (VCVTPD2PSrm addr:$src)>; -} - -let Predicates = [UseSSE2] in { - // Match fpround and fpextend for 128 conversions - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128:$src)))))), - (CVTPD2PSrr VR128:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (memopv2f64 addr:$src)))))), - (CVTPD2PSrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Compare Instructions -//===----------------------------------------------------------------------===// - -// sse12_cmp_scalar - sse 1 & 2 compare scalar instructions -multiclass sse12_cmp_scalar { - let isCommutable = 1 in - def rr : SIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, CC:$cc), asm, - [(set RC:$dst, (OpNode (VT RC:$src1), RC:$src2, imm:$cc))]>, - Sched<[sched]>; - def rm : SIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, CC:$cc), asm, - [(set RC:$dst, (OpNode (VT RC:$src1), - (ld_frag addr:$src2), imm:$cc))]>, - Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rr_alt : SIi8<0xC2, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$cc), asm_alt, []>, - Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rm_alt : SIi8<0xC2, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$cc), asm_alt, []>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - } -} - -let ExeDomain = SSEPackedSingle in -defm VCMPSS : sse12_cmp_scalar, XS, VEX_4V, VEX_LIG, VEX_WIG; -let ExeDomain = SSEPackedDouble in -defm VCMPSD : sse12_cmp_scalar, - XD, VEX_4V, VEX_LIG, VEX_WIG; - -let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in - defm CMPSS : sse12_cmp_scalar, XS; - let ExeDomain = SSEPackedDouble in - defm CMPSD : sse12_cmp_scalar, XD; -} - -multiclass sse12_cmp_scalar_int { - def rr_Int : SIi8<0xC2, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src, CC:$cc), asm, - [(set VR128:$dst, (Int VR128:$src1, - VR128:$src, imm:$cc))]>, - Sched<[sched]>; -let mayLoad = 1 in - def rm_Int : SIi8<0xC2, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, memop:$src, CC:$cc), asm, - [(set VR128:$dst, (Int VR128:$src1, - mem_cpat:$src, imm:$cc))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let isCodeGenOnly = 1 in { - // Aliases to match intrinsics which expect XMM operand(s). - let ExeDomain = SSEPackedSingle in - defm VCMPSS : sse12_cmp_scalar_int, XS, VEX_4V; - let ExeDomain = SSEPackedDouble in - defm VCMPSD : sse12_cmp_scalar_int, - XD, VEX_4V; - let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in - defm CMPSS : sse12_cmp_scalar_int, XS; - let ExeDomain = SSEPackedDouble in - defm CMPSD : sse12_cmp_scalar_int, XD; -} -} - - -// sse12_ord_cmp - Unordered/Ordered scalar fp compare and set EFLAGS -multiclass sse12_ord_cmp opc, RegisterClass RC, SDNode OpNode, - ValueType vt, X86MemOperand x86memop, - PatFrag ld_frag, string OpcodeStr, - X86FoldableSchedWrite sched> { -let hasSideEffects = 0 in { - def rr: SI, - Sched<[sched]>; -let mayLoad = 1 in - def rm: SI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -// sse12_ord_cmp_int - Intrinsic version of sse12_ord_cmp -multiclass sse12_ord_cmp_int opc, RegisterClass RC, SDNode OpNode, - ValueType vt, Operand memop, - ComplexPattern mem_cpat, string OpcodeStr, - X86FoldableSchedWrite sched> { - def rr_Int: SI, - Sched<[sched]>; -let mayLoad = 1 in - def rm_Int: SI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Defs = [EFLAGS] in { - defm VUCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS, VEX, VEX_LIG, VEX_WIG; - defm VUCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD, VEX, VEX_LIG, VEX_WIG; - let Pattern = [] in { - defm VCOMISS : sse12_ord_cmp<0x2F, FR32, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS, VEX, VEX_LIG, VEX_WIG; - defm VCOMISD : sse12_ord_cmp<0x2F, FR64, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD, VEX, VEX_LIG, VEX_WIG; - } - - let isCodeGenOnly = 1 in { - defm VUCOMISS : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS, VEX, VEX_WIG; - defm VUCOMISD : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD, VEX, VEX_WIG; - - defm VCOMISS : sse12_ord_cmp_int<0x2F, VR128, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS, VEX, VEX_WIG; - defm VCOMISD : sse12_ord_cmp_int<0x2F, VR128, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD, VEX, VEX_WIG; - } - defm UCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS; - defm UCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD; - - let Pattern = [] in { - defm COMISS : sse12_ord_cmp<0x2F, FR32, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS; - defm COMISD : sse12_ord_cmp<0x2F, FR64, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD; - } - - let isCodeGenOnly = 1 in { - defm UCOMISS : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS; - defm UCOMISD : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD; - - defm COMISS : sse12_ord_cmp_int<0x2F, VR128, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS; - defm COMISD : sse12_ord_cmp_int<0x2F, VR128, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD; - } -} // Defs = [EFLAGS] - -// sse12_cmp_packed - sse 1 & 2 compare packed instructions -multiclass sse12_cmp_packed { - let isCommutable = 1 in - def rri : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, CC:$cc), asm, - [(set RC:$dst, (VT (X86cmpp RC:$src1, RC:$src2, imm:$cc)))], d>, - Sched<[sched]>; - def rmi : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, CC:$cc), asm, - [(set RC:$dst, - (VT (X86cmpp RC:$src1, (ld_frag addr:$src2), imm:$cc)))], d>, - Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rri_alt : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc), - asm_alt, [], d>, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmi_alt : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc), - asm_alt, [], d>, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } -} - -defm VCMPPS : sse12_cmp_packed, PS, VEX_4V, VEX_WIG; -defm VCMPPD : sse12_cmp_packed, PD, VEX_4V, VEX_WIG; -defm VCMPPSY : sse12_cmp_packed, PS, VEX_4V, VEX_L, VEX_WIG; -defm VCMPPDY : sse12_cmp_packed, PD, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in { - defm CMPPS : sse12_cmp_packed, PS; - defm CMPPD : sse12_cmp_packed, PD; -} - -def CommutableCMPCC : PatLeaf<(imm), [{ - uint64_t Imm = N->getZExtValue() & 0x7; - return (Imm == 0x00 || Imm == 0x03 || Imm == 0x04 || Imm == 0x07); -}]>; - -// Patterns to select compares with loads in first operand. -let Predicates = [HasAVX] in { - def : Pat<(v4f64 (X86cmpp (loadv4f64 addr:$src2), VR256:$src1, - CommutableCMPCC:$cc)), - (VCMPPDYrmi VR256:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v8f32 (X86cmpp (loadv8f32 addr:$src2), VR256:$src1, - CommutableCMPCC:$cc)), - (VCMPPSYrmi VR256:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v2f64 (X86cmpp (loadv2f64 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (VCMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v4f32 (X86cmpp (loadv4f32 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (VCMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, - CommutableCMPCC:$cc)), - (VCMPSDrm FR64:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, - CommutableCMPCC:$cc)), - (VCMPSSrm FR32:$src1, addr:$src2, imm:$cc)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86cmpp (memopv2f64 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, - CommutableCMPCC:$cc)), - (CMPSDrm FR64:$src1, addr:$src2, imm:$cc)>; -} - -let Predicates = [UseSSE1] in { - def : Pat<(v4f32 (X86cmpp (memopv4f32 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (CMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, - CommutableCMPCC:$cc)), - (CMPSSrm FR32:$src1, addr:$src2, imm:$cc)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Shuffle Instructions -//===----------------------------------------------------------------------===// - -/// sse12_shuffle - sse 1 & 2 fp shuffle instructions -multiclass sse12_shuffle { - def rmi : PIi8<0xC6, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$src3), asm, - [(set RC:$dst, (vt (X86Shufp RC:$src1, (mem_frag addr:$src2), - (i8 imm:$src3))))], d>, - Sched<[sched.Folded, ReadAfterLd]>; - def rri : PIi8<0xC6, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), asm, - [(set RC:$dst, (vt (X86Shufp RC:$src1, RC:$src2, - (i8 imm:$src3))))], d>, - Sched<[sched]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VSHUFPS : sse12_shuffle, - PS, VEX_4V, VEX_WIG; - defm VSHUFPSY : sse12_shuffle, - PS, VEX_4V, VEX_L, VEX_WIG; - defm VSHUFPD : sse12_shuffle, - PD, VEX_4V, VEX_WIG; - defm VSHUFPDY : sse12_shuffle, - PD, VEX_4V, VEX_L, VEX_WIG; -} -let Constraints = "$src1 = $dst" in { - defm SHUFPS : sse12_shuffle, PS; - defm SHUFPD : sse12_shuffle, PD; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Unpack FP Instructions -//===----------------------------------------------------------------------===// - -/// sse12_unpack_interleave - sse 1 & 2 fp unpack and interleave -multiclass sse12_unpack_interleave opc, SDNode OpNode, ValueType vt, - PatFrag mem_frag, RegisterClass RC, - X86MemOperand x86memop, string asm, - X86FoldableSchedWrite sched, Domain d, - bit IsCommutable = 0> { - let isCommutable = IsCommutable in - def rr : PI, - Sched<[sched]>; - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX] in { -defm VUNPCKHPS: sse12_unpack_interleave<0x15, X86Unpckh, v4f32, loadv4f32, - VR128, f128mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS, VEX_4V, VEX_WIG; -defm VUNPCKHPD: sse12_unpack_interleave<0x15, X86Unpckh, v2f64, loadv2f64, - VR128, f128mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble, 1>, PD, VEX_4V, VEX_WIG; -defm VUNPCKLPS: sse12_unpack_interleave<0x14, X86Unpckl, v4f32, loadv4f32, - VR128, f128mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS, VEX_4V, VEX_WIG; -defm VUNPCKLPD: sse12_unpack_interleave<0x14, X86Unpckl, v2f64, loadv2f64, - VR128, f128mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble>, PD, VEX_4V, VEX_WIG; - -defm VUNPCKHPSY: sse12_unpack_interleave<0x15, X86Unpckh, v8f32, loadv8f32, - VR256, f256mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedSingle>, PS, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKHPDY: sse12_unpack_interleave<0x15, X86Unpckh, v4f64, loadv4f64, - VR256, f256mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedDouble>, PD, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKLPSY: sse12_unpack_interleave<0x14, X86Unpckl, v8f32, loadv8f32, - VR256, f256mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedSingle>, PS, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKLPDY: sse12_unpack_interleave<0x14, X86Unpckl, v4f64, loadv4f64, - VR256, f256mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedDouble>, PD, VEX_4V, VEX_L, VEX_WIG; -}// Predicates = [HasAVX, NoVLX] - -let Constraints = "$src1 = $dst" in { - defm UNPCKHPS: sse12_unpack_interleave<0x15, X86Unpckh, v4f32, memopv4f32, - VR128, f128mem, "unpckhps\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS; - defm UNPCKHPD: sse12_unpack_interleave<0x15, X86Unpckh, v2f64, memopv2f64, - VR128, f128mem, "unpckhpd\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble, 1>, PD; - defm UNPCKLPS: sse12_unpack_interleave<0x14, X86Unpckl, v4f32, memopv4f32, - VR128, f128mem, "unpcklps\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS; - defm UNPCKLPD: sse12_unpack_interleave<0x14, X86Unpckl, v2f64, memopv2f64, - VR128, f128mem, "unpcklpd\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble>, PD; -} // Constraints = "$src1 = $dst" - -let Predicates = [HasAVX1Only] in { - def : Pat<(v8i32 (X86Unpckl VR256:$src1, (bc_v8i32 (loadv4i64 addr:$src2)))), - (VUNPCKLPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86Unpckl VR256:$src1, VR256:$src2)), - (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v8i32 (X86Unpckh VR256:$src1, (bc_v8i32 (loadv4i64 addr:$src2)))), - (VUNPCKHPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86Unpckh VR256:$src1, VR256:$src2)), - (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>; - - def : Pat<(v4i64 (X86Unpckl VR256:$src1, (loadv4i64 addr:$src2))), - (VUNPCKLPDYrm VR256:$src1, addr:$src2)>; - def : Pat<(v4i64 (X86Unpckl VR256:$src1, VR256:$src2)), - (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (X86Unpckh VR256:$src1, (loadv4i64 addr:$src2))), - (VUNPCKHPDYrm VR256:$src1, addr:$src2)>; - def : Pat<(v4i64 (X86Unpckh VR256:$src1, VR256:$src2)), - (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Extract Floating-Point Sign mask -//===----------------------------------------------------------------------===// - -/// sse12_extr_sign_mask - sse 1 & 2 unpack and interleave -multiclass sse12_extr_sign_mask { - def rr : PI<0x50, MRMSrcReg, (outs GR32orGR64:$dst), (ins RC:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(set GR32orGR64:$dst, (X86movmsk (vt RC:$src)))], d>, - Sched<[WriteFMOVMSK]>; -} - -let Predicates = [HasAVX] in { - defm VMOVMSKPS : sse12_extr_sign_mask, PS, VEX, VEX_WIG; - defm VMOVMSKPD : sse12_extr_sign_mask, PD, VEX, VEX_WIG; - defm VMOVMSKPSY : sse12_extr_sign_mask, PS, VEX, VEX_L, VEX_WIG; - defm VMOVMSKPDY : sse12_extr_sign_mask, PD, VEX, VEX_L, VEX_WIG; -} - -defm MOVMSKPS : sse12_extr_sign_mask, PS; -defm MOVMSKPD : sse12_extr_sign_mask, PD; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Logical Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -/// PDI_binop_rm - Simple SSE2 binary operator. -multiclass PDI_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit IsCommutable, bit Is2Addr> { - let isCommutable = IsCommutable in - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} // ExeDomain = SSEPackedInt - -multiclass PDI_binop_all opc, string OpcodeStr, SDNode Opcode, - ValueType OpVT128, ValueType OpVT256, - X86SchedWriteWidths sched, bit IsCommutable, - Predicate prd> { -let Predicates = [HasAVX, prd] in - defm V#NAME : PDI_binop_rm, VEX_4V, VEX_WIG; - -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_rm; - -let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : PDI_binop_rm, VEX_4V, VEX_L, VEX_WIG; -} - -// These are ordered here for pattern ordering requirements with the fp versions - -defm PAND : PDI_binop_all<0xDB, "pand", and, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm POR : PDI_binop_all<0xEB, "por", or, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm PXOR : PDI_binop_all<0xEF, "pxor", xor, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm PANDN : PDI_binop_all<0xDF, "pandn", X86andnp, v2i64, v4i64, - SchedWriteVecLogic, 0, NoVLX>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Logical Instructions -//===----------------------------------------------------------------------===// - -/// sse12_fp_packed_logical - SSE 1 & 2 packed FP logical ops -/// -/// There are no patterns here because isel prefers integer versions for SSE2 -/// and later. There are SSE1 v4f32 patterns later. -multiclass sse12_fp_packed_logical opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasAVX, NoVLX] in { - defm V#NAME#PSY : sse12_fp_packed_logical_rm, PS, VEX_4V, VEX_L, VEX_WIG; - - defm V#NAME#PDY : sse12_fp_packed_logical_rm, PD, VEX_4V, VEX_L, VEX_WIG; - - defm V#NAME#PS : sse12_fp_packed_logical_rm, PS, VEX_4V, VEX_WIG; - - defm V#NAME#PD : sse12_fp_packed_logical_rm, PD, VEX_4V, VEX_WIG; - } - - let Constraints = "$src1 = $dst" in { - defm PS : sse12_fp_packed_logical_rm, PS; - - defm PD : sse12_fp_packed_logical_rm, PD; - } -} - -defm AND : sse12_fp_packed_logical<0x54, "and", and, SchedWriteFLogic>; -defm OR : sse12_fp_packed_logical<0x56, "or", or, SchedWriteFLogic>; -defm XOR : sse12_fp_packed_logical<0x57, "xor", xor, SchedWriteFLogic>; -let isCommutable = 0 in - defm ANDN : sse12_fp_packed_logical<0x55, "andn", X86andnp, SchedWriteFLogic>; - -// If only AVX1 is supported, we need to handle integer operations with -// floating point instructions since the integer versions aren't available. -let Predicates = [HasAVX1Only] in { - def : Pat<(v4i64 (and VR256:$src1, VR256:$src2)), - (VANDPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (or VR256:$src1, VR256:$src2)), - (VORPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (xor VR256:$src1, VR256:$src2)), - (VXORPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (X86andnp VR256:$src1, VR256:$src2)), - (VANDNPSYrr VR256:$src1, VR256:$src2)>; - - def : Pat<(and VR256:$src1, (loadv4i64 addr:$src2)), - (VANDPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(or VR256:$src1, (loadv4i64 addr:$src2)), - (VORPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(xor VR256:$src1, (loadv4i64 addr:$src2)), - (VXORPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(X86andnp VR256:$src1, (loadv4i64 addr:$src2)), - (VANDNPSYrm VR256:$src1, addr:$src2)>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoDQI] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86for FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fxor FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VXORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fandn FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDNPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - - def : Pat<(f32 (X86fand FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86for FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fxor FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VXORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fandn FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDNPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; -} - -let Predicates = [UseSSE1] in { - // Use packed logical operations for scalar ops. - def : Pat<(f32 (X86fand FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ANDPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86for FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fxor FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (XORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fandn FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ANDNPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; -} - -let Predicates = [UseSSE2] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ANDPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86for FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fxor FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (XORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fandn FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ANDNPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; -} - -// Patterns for packed operations when we don't have integer type available. -def : Pat<(v4f32 (X86fand VR128:$src1, VR128:$src2)), - (ANDPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86for VR128:$src1, VR128:$src2)), - (ORPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86fxor VR128:$src1, VR128:$src2)), - (XORPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86fandn VR128:$src1, VR128:$src2)), - (ANDNPSrr VR128:$src1, VR128:$src2)>; - -def : Pat<(X86fand VR128:$src1, (memopv4f32 addr:$src2)), - (ANDPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86for VR128:$src1, (memopv4f32 addr:$src2)), - (ORPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86fxor VR128:$src1, (memopv4f32 addr:$src2)), - (XORPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86fandn VR128:$src1, (memopv4f32 addr:$src2)), - (ANDNPSrm VR128:$src1, addr:$src2)>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Arithmetic Instructions -//===----------------------------------------------------------------------===// - -/// basic_sse12_fp_binop_xxx - SSE 1 & 2 binops come in both scalar and -/// vector forms. -/// -/// In addition, we also have a special variant of the scalar form here to -/// represent the associated intrinsic operation. This form is unlike the -/// plain scalar form, in that it takes an entire vector (instead of a scalar) -/// and leaves the top elements unmodified (therefore these cannot be commuted). -/// -/// These three forms can each be reg+reg or reg+mem. -/// - -/// FIXME: once all 256-bit intrinsics are matched, cleanup and refactor those -/// classes below -multiclass basic_sse12_fp_binop_p opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteSizes sched> { - let Predicates = [HasAVX, NoVLX] in { - defm V#NAME#PS : sse12_fp_packed, PS, VEX_4V, VEX_WIG; - defm V#NAME#PD : sse12_fp_packed, PD, VEX_4V, VEX_WIG; - - defm V#NAME#PSY : sse12_fp_packed, PS, VEX_4V, VEX_L, VEX_WIG; - defm V#NAME#PDY : sse12_fp_packed, PD, VEX_4V, VEX_L, VEX_WIG; - } - - let Constraints = "$src1 = $dst" in { - defm PS : sse12_fp_packed, PS; - defm PD : sse12_fp_packed, PD; - } -} - -multiclass basic_sse12_fp_binop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteSizes sched> { - defm V#NAME#SS : sse12_fp_scalar, - XS, VEX_4V, VEX_LIG, VEX_WIG; - defm V#NAME#SD : sse12_fp_scalar, - XD, VEX_4V, VEX_LIG, VEX_WIG; - - let Constraints = "$src1 = $dst" in { - defm SS : sse12_fp_scalar, XS; - defm SD : sse12_fp_scalar, XD; - } -} - -multiclass basic_sse12_fp_binop_s_int opc, string OpcodeStr, - SDPatternOperator OpNode, - X86SchedWriteSizes sched> { - defm V#NAME#SS : sse12_fp_scalar_int, XS, VEX_4V, VEX_LIG, VEX_WIG; - defm V#NAME#SD : sse12_fp_scalar_int, XD, VEX_4V, VEX_LIG, VEX_WIG; - - let Constraints = "$src1 = $dst" in { - defm SS : sse12_fp_scalar_int, XS; - defm SD : sse12_fp_scalar_int, XD; - } -} - -// Binary Arithmetic instructions -defm ADD : basic_sse12_fp_binop_p<0x58, "add", fadd, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s<0x58, "add", fadd, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s_int<0x58, "add", null_frag, SchedWriteFAddSizes>; -defm MUL : basic_sse12_fp_binop_p<0x59, "mul", fmul, SchedWriteFMulSizes>, - basic_sse12_fp_binop_s<0x59, "mul", fmul, SchedWriteFMulSizes>, - basic_sse12_fp_binop_s_int<0x59, "mul", null_frag, SchedWriteFMulSizes>; -let isCommutable = 0 in { - defm SUB : basic_sse12_fp_binop_p<0x5C, "sub", fsub, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s<0x5C, "sub", fsub, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s_int<0x5C, "sub", null_frag, SchedWriteFAddSizes>; - defm DIV : basic_sse12_fp_binop_p<0x5E, "div", fdiv, SchedWriteFDivSizes>, - basic_sse12_fp_binop_s<0x5E, "div", fdiv, SchedWriteFDivSizes>, - basic_sse12_fp_binop_s_int<0x5E, "div", null_frag, SchedWriteFDivSizes>; - defm MAX : basic_sse12_fp_binop_p<0x5F, "max", X86fmax, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5F, "max", X86fmax, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s_int<0x5F, "max", X86fmaxs, SchedWriteFCmpSizes>; - defm MIN : basic_sse12_fp_binop_p<0x5D, "min", X86fmin, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5D, "min", X86fmin, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s_int<0x5D, "min", X86fmins, SchedWriteFCmpSizes>; -} - -let isCodeGenOnly = 1 in { - defm MAXC: basic_sse12_fp_binop_p<0x5F, "max", X86fmaxc, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5F, "max", X86fmaxc, SchedWriteFCmpSizes>; - defm MINC: basic_sse12_fp_binop_p<0x5D, "min", X86fminc, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5D, "min", X86fminc, SchedWriteFCmpSizes>; -} - -// Patterns used to select SSE scalar fp arithmetic instructions from -// either: -// -// (1) a scalar fp operation followed by a blend -// -// The effect is that the backend no longer emits unnecessary vector -// insert instructions immediately after SSE scalar fp instructions -// like addss or mulss. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// A[0] += B[0]; -// return A; -// } -// -// Previously we generated: -// addss %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 -// -// (2) a vector packed single/double fp operation followed by a vector insert -// -// The effect is that the backend converts the packed fp instruction -// followed by a vector insert into a single SSE scalar fp instruction. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// __m128 C = A + B; -// return (__m128) {c[0], a[1], a[2], a[3]}; -// } -// -// Previously we generated: -// addps %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 - -// TODO: Some canonicalization in lowering would simplify the number of -// patterns we have to try to match. -multiclass scalar_math_patterns { - let Predicates = [BasePredicate] in { - // extracted scalar math op with insert via movss/movsd - def : Pat<(VT (Move (VT VR128:$dst), - (VT (scalar_to_vector - (Op (EltTy (extractelt (VT VR128:$dst), (iPTR 0))), - RC:$src))))), - (!cast(OpcPrefix#rr_Int) VT:$dst, - (VT (COPY_TO_REGCLASS RC:$src, VR128)))>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - // extracted scalar math op with insert via movss/movsd - def : Pat<(VT (Move (VT VR128:$dst), - (VT (scalar_to_vector - (Op (EltTy (extractelt (VT VR128:$dst), (iPTR 0))), - RC:$src))))), - (!cast("V"#OpcPrefix#rr_Int) VT:$dst, - (VT (COPY_TO_REGCLASS RC:$src, VR128)))>; - } -} - -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; - -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; - -/// Unop Arithmetic -/// In addition, we also have a special variant of the scalar form here to -/// represent the associated intrinsic operation. This form is unlike the -/// plain scalar form, in that it takes an entire vector (instead of a -/// scalar) and leaves the top elements undefined. -/// -/// And, we have a special variant form for a full-vector intrinsic form. - -/// sse_fp_unop_s - SSE1 unops in scalar form -/// For the non-AVX defs, we need $src1 to be tied to $dst because -/// the HW instructions are 2 operand / destructive. -multiclass sse_fp_unop_s opc, string OpcodeStr, RegisterClass RC, - ValueType ScalarVT, X86MemOperand x86memop, - Operand intmemop, SDNode OpNode, Domain d, - X86FoldableSchedWrite sched, Predicate target> { - let hasSideEffects = 0 in { - def r : I, Sched<[sched]>, - Requires<[target]>; - let mayLoad = 1 in - def m : I, - Sched<[sched.Folded, ReadAfterLd]>, - Requires<[target, OptForSize]>; - - let isCodeGenOnly = 1, Constraints = "$src1 = $dst", ExeDomain = d in { - def r_Int : I, - Sched<[sched]>; - let mayLoad = 1 in - def m_Int : I, - Sched<[sched.Folded, ReadAfterLd]>; - } - } - -} - -multiclass sse_fp_unop_s_intr { - let Predicates = [target] in { - // These are unary operations, but they are modeled as having 2 source operands - // because the high elements of the destination are unchanged in SSE. - def : Pat<(Intr VR128:$src), - (!cast(NAME#r_Int) VR128:$src, VR128:$src)>; - } - // We don't want to fold scalar loads into these instructions unless - // optimizing for size. This is because the folded instruction will have a - // partial register update, while the unfolded sequence will not, e.g. - // movss mem, %xmm0 - // rcpss %xmm0, %xmm0 - // which has a clobber before the rcp, vs. - // rcpss mem, %xmm0 - let Predicates = [target, OptForSize] in { - def : Pat<(Intr int_cpat:$src2), - (!cast(NAME#m_Int) - (vt (IMPLICIT_DEF)), addr:$src2)>; - } -} - -multiclass avx_fp_unop_s_intr { - let Predicates = [target] in { - def : Pat<(Intr VR128:$src), - (!cast(NAME#r_Int) VR128:$src, - VR128:$src)>; - } - let Predicates = [target, OptForSize] in { - def : Pat<(Intr int_cpat:$src2), - (!cast(NAME#m_Int) - (vt (IMPLICIT_DEF)), addr:$src2)>; - } -} - -multiclass avx_fp_unop_s opc, string OpcodeStr, RegisterClass RC, - ValueType ScalarVT, X86MemOperand x86memop, - Operand intmemop, SDNode OpNode, Domain d, - X86FoldableSchedWrite sched, Predicate target> { - let hasSideEffects = 0 in { - def r : I, Sched<[sched]>; - let mayLoad = 1 in - def m : I, Sched<[sched.Folded, ReadAfterLd]>; - let isCodeGenOnly = 1, ExeDomain = d in { - def r_Int : I, Sched<[sched]>; - let mayLoad = 1 in - def m_Int : I, Sched<[sched.Folded, ReadAfterLd]>; - } - } - - // We don't want to fold scalar loads into these instructions unless - // optimizing for size. This is because the folded instruction will have a - // partial register update, while the unfolded sequence will not, e.g. - // vmovss mem, %xmm0 - // vrcpss %xmm0, %xmm0, %xmm0 - // which has a clobber before the rcp, vs. - // vrcpss mem, %xmm0, %xmm0 - // TODO: In theory, we could fold the load, and avoid the stall caused by - // the partial register store, either in BreakFalseDeps or with smarter RA. - let Predicates = [target] in { - def : Pat<(OpNode RC:$src), (!cast(NAME#r) - (ScalarVT (IMPLICIT_DEF)), RC:$src)>; - } - let Predicates = [target, OptForSize] in { - def : Pat<(ScalarVT (OpNode (load addr:$src))), - (!cast(NAME#m) (ScalarVT (IMPLICIT_DEF)), - addr:$src)>; - } -} - -/// sse1_fp_unop_p - SSE1 unops in packed form. -multiclass sse1_fp_unop_p opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, list prds> { -let Predicates = prds in { - def V#NAME#PSr : PSI, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#PSm : PSI, - VEX, Sched<[sched.XMM.Folded]>, VEX_WIG; - def V#NAME#PSYr : PSI, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#PSYm : PSI, - VEX, VEX_L, Sched<[sched.YMM.Folded]>, VEX_WIG; -} - - def PSr : PSI, - Sched<[sched.XMM]>; - def PSm : PSI, - Sched<[sched.XMM.Folded]>; -} - -/// sse2_fp_unop_p - SSE2 unops in vector forms. -multiclass sse2_fp_unop_p opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { -let Predicates = [HasAVX, NoVLX] in { - def V#NAME#PDr : PDI, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#PDm : PDI, - VEX, Sched<[sched.XMM.Folded]>, VEX_WIG; - def V#NAME#PDYr : PDI, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#PDYm : PDI, - VEX, VEX_L, Sched<[sched.YMM.Folded]>, VEX_WIG; -} - - def PDr : PDI, - Sched<[sched.XMM]>; - def PDm : PDI, - Sched<[sched.XMM.Folded]>; -} - -multiclass sse1_fp_unop_s_intr opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SS : sse_fp_unop_s_intr("int_x86_sse_"##OpcodeStr##_ss), - UseSSE1, "SS">, XS; - defm V#NAME#SS : avx_fp_unop_s_intr("int_x86_sse_"##OpcodeStr##_ss), - AVXTarget>, - XS, VEX_4V, VEX_LIG, VEX_WIG, NotMemoryFoldable; -} - -multiclass sse1_fp_unop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SS : sse_fp_unop_s, XS; - defm V#NAME#SS : avx_fp_unop_s, - XS, VEX_4V, VEX_LIG, VEX_WIG; -} - -multiclass sse2_fp_unop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SD : sse_fp_unop_s, XD; - defm V#NAME#SD : avx_fp_unop_s, - XD, VEX_4V, VEX_LIG, VEX_WIG; -} - -// Square root. -defm SQRT : sse1_fp_unop_s<0x51, "sqrt", fsqrt, SchedWriteFSqrt, UseAVX>, - sse1_fp_unop_p<0x51, "sqrt", fsqrt, SchedWriteFSqrt, [HasAVX, NoVLX]>, - sse2_fp_unop_s<0x51, "sqrt", fsqrt, SchedWriteFSqrt64, UseAVX>, - sse2_fp_unop_p<0x51, "sqrt", fsqrt, SchedWriteFSqrt64>; - -// Reciprocal approximations. Note that these typically require refinement -// in order to obtain suitable precision. -defm RSQRT : sse1_fp_unop_s<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, HasAVX>, - sse1_fp_unop_s_intr<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, HasAVX>, - sse1_fp_unop_p<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, [HasAVX]>; -defm RCP : sse1_fp_unop_s<0x53, "rcp", X86frcp, SchedWriteFRcp, HasAVX>, - sse1_fp_unop_s_intr<0x53, "rcp", X86frcp, SchedWriteFRcp, HasAVX>, - sse1_fp_unop_p<0x53, "rcp", X86frcp, SchedWriteFRcp, [HasAVX]>; - -// There is no f64 version of the reciprocal approximation instructions. - -multiclass scalar_unary_math_patterns { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } -} - -multiclass scalar_unary_math_imm_patterns ImmV, - Predicate BasePredicate> { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src, (i32 ImmV))>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src, (i32 ImmV))>; - } -} - -defm : scalar_unary_math_patterns; -defm : scalar_unary_math_patterns; - -multiclass scalar_unary_math_intr_patterns { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (Intr VT:$src))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [HasAVX] in { - def : Pat<(VT (Move VT:$dst, (Intr VT:$src))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } -} - -defm : scalar_unary_math_intr_patterns; -defm : scalar_unary_math_intr_patterns; - - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Non-temporal stores -//===----------------------------------------------------------------------===// - -let AddedComplexity = 400 in { // Prefer non-temporal versions -let Predicates = [HasAVX, NoVLX] in { -let SchedRW = [SchedWriteFMoveLSNT.XMM.MR] in { -def VMOVNTPSmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG; -def VMOVNTPDmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2f64 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLSNT.YMM.MR] in { -def VMOVNTPSYmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v8f32 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG; -def VMOVNTPDYmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f64 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG; -} // SchedRW - -let ExeDomain = SSEPackedInt in { -def VMOVNTDQmr : VPDI<0xE7, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2i64 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG, - Sched<[SchedWriteVecMoveLSNT.XMM.MR]>; -def VMOVNTDQYmr : VPDI<0xE7, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4i64 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG, - Sched<[SchedWriteVecMoveLSNT.YMM.MR]>; -} // ExeDomain -} // Predicates - -let SchedRW = [SchedWriteFMoveLSNT.XMM.MR] in { -def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>; -def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore(v2f64 VR128:$src), addr:$dst)]>; -} // SchedRW - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecMoveLSNT.XMM.MR] in -def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2i64 VR128:$src), addr:$dst)]>; - -let SchedRW = [WriteStoreNT] in { -// There is no AVX form for instructions below this point -def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movnti{l}\t{$src, $dst|$dst, $src}", - [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, - PS, Requires<[HasSSE2]>; -def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movnti{q}\t{$src, $dst|$dst, $src}", - [(nontemporalstore (i64 GR64:$src), addr:$dst)]>, - PS, Requires<[HasSSE2]>; -} // SchedRW = [WriteStoreNT] - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(alignednontemporalstore (v8i32 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - def : Pat<(alignednontemporalstore (v16i16 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - def : Pat<(alignednontemporalstore (v32i8 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - - def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; -} - -} // AddedComplexity - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Prefetch and memory fence -//===----------------------------------------------------------------------===// - -// Prefetch intrinsic. -let Predicates = [HasSSEPrefetch], SchedRW = [WriteLoad] in { -def PREFETCHT0 : I<0x18, MRM1m, (outs), (ins i8mem:$src), - "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3), (i32 1))]>, TB; -def PREFETCHT1 : I<0x18, MRM2m, (outs), (ins i8mem:$src), - "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2), (i32 1))]>, TB; -def PREFETCHT2 : I<0x18, MRM3m, (outs), (ins i8mem:$src), - "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1), (i32 1))]>, TB; -def PREFETCHNTA : I<0x18, MRM0m, (outs), (ins i8mem:$src), - "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), (i32 1))]>, TB; -} - -// FIXME: How should flush instruction be modeled? -let SchedRW = [WriteLoad] in { -// Flush cache -def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>, - PS, Requires<[HasSSE2]>; -} - -let SchedRW = [WriteNop] in { -// Pause. This "instruction" is encoded as "rep; nop", so even though it -// was introduced with SSE2, it's backward compatible. -def PAUSE : I<0x90, RawFrm, (outs), (ins), - "pause", [(int_x86_sse2_pause)]>, OBXS; -} - -let SchedRW = [WriteFence] in { -// Load, store, and memory fence -// TODO: As with mfence, we may want to ease the availability of sfence/lfence -// to include any 64-bit target. -def SFENCE : I<0xAE, MRM_F8, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>, - PS, Requires<[HasSSE1]>; -def LFENCE : I<0xAE, MRM_E8, (outs), (ins), "lfence", [(int_x86_sse2_lfence)]>, - PS, Requires<[HasSSE2]>; -def MFENCE : I<0xAE, MRM_F0, (outs), (ins), "mfence", [(int_x86_sse2_mfence)]>, - PS, Requires<[HasMFence]>; -} // SchedRW - -def : Pat<(X86MFence), (MFENCE)>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Load/Store XCSR register -//===----------------------------------------------------------------------===// - -def VLDMXCSR : VPSI<0xAE, MRM2m, (outs), (ins i32mem:$src), - "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, - VEX, Sched<[WriteLDMXCSR]>, VEX_WIG; -def VSTMXCSR : VPSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), - "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, - VEX, Sched<[WriteSTMXCSR]>, VEX_WIG; - -def LDMXCSR : I<0xAE, MRM2m, (outs), (ins i32mem:$src), - "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, - TB, Sched<[WriteLDMXCSR]>; -def STMXCSR : I<0xAE, MRM3m, (outs), (ins i32mem:$dst), - "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, - TB, Sched<[WriteSTMXCSR]>; - -//===---------------------------------------------------------------------===// -// SSE2 - Move Aligned/Unaligned Packed Integer Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -let hasSideEffects = 0 in { -def VMOVDQArr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, VEX, VEX_WIG; -def VMOVDQUrr : VSSI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, VEX, VEX_WIG; -def VMOVDQAYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, VEX, VEX_L, VEX_WIG; -def VMOVDQUYrr : VSSI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, VEX, VEX_L, VEX_WIG; -} - -// For Disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def VMOVDQArr_REV : VPDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, - VEX, VEX_WIG, FoldGenData<"VMOVDQArr">; -def VMOVDQAYrr_REV : VPDI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVDQAYrr">; -def VMOVDQUrr_REV : VSSI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, - VEX, VEX_WIG, FoldGenData<"VMOVDQUrr">; -def VMOVDQUYrr_REV : VSSI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVDQUYrr">; -} - -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - hasSideEffects = 0, Predicates = [HasAVX,NoVLX] in { -def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (alignedloadv2i64 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, VEX, VEX_WIG; -def VMOVDQAYrm : VPDI<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, - VEX, VEX_L, VEX_WIG; -def VMOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (loadv2i64 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, - XS, VEX, VEX_WIG; -def VMOVDQUYrm : I<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, - XS, VEX, VEX_L, VEX_WIG; -} - -let mayStore = 1, hasSideEffects = 0, Predicates = [HasAVX,NoVLX] in { -def VMOVDQAmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [(alignedstore (v2i64 VR128:$src), addr:$dst)]>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, VEX, VEX_WIG; -def VMOVDQAYmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.MR]>, VEX, VEX_L, VEX_WIG; -def VMOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(store (v2i64 VR128:$src), addr:$dst)]>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, XS, VEX, VEX_WIG; -def VMOVDQUYmr : I<0x7F, MRMDestMem, (outs), (ins i256mem:$dst, VR256:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, - Sched<[SchedWriteVecMoveLS.YMM.MR]>, XS, VEX, VEX_L, VEX_WIG; -} - -let SchedRW = [SchedWriteVecMoveLS.XMM.RR] in { -let hasSideEffects = 0 in { -def MOVDQArr : PDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>; - -def MOVDQUrr : I<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - XS, Requires<[UseSSE2]>; -} - -// For Disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOVDQArr_REV : PDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVDQArr">; - -def MOVDQUrr_REV : I<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - XS, Requires<[UseSSE2]>, FoldGenData<"MOVDQUrr">; -} -} // SchedRW - -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - hasSideEffects = 0, SchedRW = [SchedWriteVecMoveLS.XMM.RM] in { -def MOVDQArm : PDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [/*(set VR128:$dst, (alignedloadv2i64 addr:$src))*/]>; -def MOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [/*(set VR128:$dst, (loadv2i64 addr:$src))*/]>, - XS, Requires<[UseSSE2]>; -} - -let mayStore = 1, hasSideEffects = 0, - SchedRW = [SchedWriteVecMoveLS.XMM.MR] in { -def MOVDQAmr : PDI<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [/*(alignedstore (v2i64 VR128:$src), addr:$dst)*/]>; -def MOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [/*(store (v2i64 VR128:$src), addr:$dst)*/]>, - XS, Requires<[UseSSE2]>; -} - -} // ExeDomain = SSEPackedInt - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -// def : InstAlias<"vmovdqa\t{$src, $dst|$dst, $src}", -// (VMOVDQArr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovdqa\t{$src, $dst|$dst, $src}", -// (VMOVDQAYrr_REV VR256L:$dst, VR256H:$src), 0>; -// def : InstAlias<"vmovdqu\t{$src, $dst|$dst, $src}", -// (VMOVDQUrr_REV VR128L:$dst, VR128H:$src), 0>; -// def : InstAlias<"vmovdqu\t{$src, $dst|$dst, $src}", -// (VMOVDQUYrr_REV VR256L:$dst, VR256H:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -// def : InstAlias<"vmovdqa.s\t{$src, $dst|$dst, $src}", -// (VMOVDQArr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovdqa.s\t{$src, $dst|$dst, $src}", -// (VMOVDQAYrr_REV VR256:$dst, VR256:$src), 0>; -// def : InstAlias<"vmovdqu.s\t{$src, $dst|$dst, $src}", -// (VMOVDQUrr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"vmovdqu.s\t{$src, $dst|$dst, $src}", -// (VMOVDQUYrr_REV VR256:$dst, VR256:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -// def : InstAlias<"movdqa.s\t{$src, $dst|$dst, $src}", -// (MOVDQArr_REV VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"movdqu.s\t{$src, $dst|$dst, $src}", -// (MOVDQUrr_REV VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in { - // Additional patterns for other integer sizes. - def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(store (v4i32 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; - def : Pat<(store (v8i16 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; - def : Pat<(store (v16i8 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Arithmetic Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -/// PDI_binop_rm2 - Simple SSE2 binary operator with different src and dst types -multiclass PDI_binop_rm2 opc, string OpcodeStr, SDNode OpNode, - ValueType DstVT, ValueType SrcVT, RegisterClass RC, - PatFrag memop_frag, X86MemOperand x86memop, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} // ExeDomain = SSEPackedInt - -defm PADDB : PDI_binop_all<0xFC, "paddb", add, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDW : PDI_binop_all<0xFD, "paddw", add, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDD : PDI_binop_all<0xFE, "paddd", add, v4i32, v8i32, - SchedWriteVecALU, 1, NoVLX>; -defm PADDQ : PDI_binop_all<0xD4, "paddq", add, v2i64, v4i64, - SchedWriteVecALU, 1, NoVLX>; -defm PADDSB : PDI_binop_all<0xEC, "paddsb", X86adds, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDSW : PDI_binop_all<0xED, "paddsw", X86adds, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDUSB : PDI_binop_all<0xDC, "paddusb", X86addus, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDUSW : PDI_binop_all<0xDD, "paddusw", X86addus, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMULLW : PDI_binop_all<0xD5, "pmullw", mul, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PMULHUW : PDI_binop_all<0xE4, "pmulhuw", mulhu, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PMULHW : PDI_binop_all<0xE5, "pmulhw", mulhs, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PSUBB : PDI_binop_all<0xF8, "psubb", sub, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBW : PDI_binop_all<0xF9, "psubw", sub, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBD : PDI_binop_all<0xFA, "psubd", sub, v4i32, v8i32, - SchedWriteVecALU, 0, NoVLX>; -defm PSUBQ : PDI_binop_all<0xFB, "psubq", sub, v2i64, v4i64, - SchedWriteVecALU, 0, NoVLX>; -defm PSUBSB : PDI_binop_all<0xE8, "psubsb", X86subs, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBSW : PDI_binop_all<0xE9, "psubsw", X86subs, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBUSB : PDI_binop_all<0xD8, "psubusb", X86subus, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBUSW : PDI_binop_all<0xD9, "psubusw", X86subus, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PMINUB : PDI_binop_all<0xDA, "pminub", umin, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMINSW : PDI_binop_all<0xEA, "pminsw", smin, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMAXUB : PDI_binop_all<0xDE, "pmaxub", umax, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMAXSW : PDI_binop_all<0xEE, "pmaxsw", smax, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PAVGB : PDI_binop_all<0xE0, "pavgb", X86avg, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PAVGW : PDI_binop_all<0xE3, "pavgw", X86avg, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMULUDQ : PDI_binop_all<0xF4, "pmuludq", X86pmuludq, v2i64, v4i64, - SchedWriteVecIMul, 1, NoVLX>; - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in -defm VPMADDWD : PDI_binop_rm2<0xF5, "vpmaddwd", X86vpmaddwd, v4i32, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecIMul.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in -defm VPMADDWDY : PDI_binop_rm2<0xF5, "vpmaddwd", X86vpmaddwd, v8i32, v16i16, - VR256, loadv4i64, i256mem, SchedWriteVecIMul.YMM, - 0>, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in -defm PMADDWD : PDI_binop_rm2<0xF5, "pmaddwd", X86vpmaddwd, v4i32, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecIMul.XMM>; - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in -defm VPSADBW : PDI_binop_rm2<0xF6, "vpsadbw", X86psadbw, v2i64, v16i8, VR128, - loadv2i64, i128mem, SchedWritePSADBW.XMM, 0>, - VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in -defm VPSADBWY : PDI_binop_rm2<0xF6, "vpsadbw", X86psadbw, v4i64, v32i8, VR256, - loadv4i64, i256mem, SchedWritePSADBW.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in -defm PSADBW : PDI_binop_rm2<0xF6, "psadbw", X86psadbw, v2i64, v16i8, VR128, - memopv2i64, i128mem, SchedWritePSADBW.XMM>; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Logical Instructions -//===---------------------------------------------------------------------===// - -multiclass PDI_binop_rmi opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, SDNode OpNode, - SDNode OpNode2, RegisterClass RC, - X86FoldableSchedWrite sched, - X86FoldableSchedWrite schedImm, - ValueType DstVT, ValueType SrcVT, - PatFrag ld_frag, bit Is2Addr = 1> { - // src2 is always 128-bit - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; - def ri : PDIi8, - Sched<[schedImm]>; -} - -multiclass PDI_binop_rmi_all opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, SDNode OpNode, - SDNode OpNode2, ValueType DstVT128, - ValueType DstVT256, ValueType SrcVT, - X86SchedWriteWidths sched, - X86SchedWriteWidths schedImm, Predicate prd> { -let Predicates = [HasAVX, prd] in - defm V#NAME : PDI_binop_rmi, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : PDI_binop_rmi, VEX_4V, VEX_L, - VEX_WIG; -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_rmi; -} - -multiclass PDI_binop_ri opc, Format ImmForm, string OpcodeStr, - SDNode OpNode, RegisterClass RC, ValueType VT, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - def ri : PDIi8, - Sched<[sched]>; -} - -multiclass PDI_binop_ri_all opc, Format ImmForm, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in - defm V#NAME : PDI_binop_ri, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in - defm V#NAME#Y : PDI_binop_ri, - VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_ri; -} - -let ExeDomain = SSEPackedInt in { - defm PSLLW : PDI_binop_rmi_all<0xF1, 0x71, MRM6r, "psllw", X86vshl, X86vshli, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSLLD : PDI_binop_rmi_all<0xF2, 0x72, MRM6r, "pslld", X86vshl, X86vshli, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - defm PSLLQ : PDI_binop_rmi_all<0xF3, 0x73, MRM6r, "psllq", X86vshl, X86vshli, - v2i64, v4i64, v2i64, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSRLW : PDI_binop_rmi_all<0xD1, 0x71, MRM2r, "psrlw", X86vsrl, X86vsrli, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSRLD : PDI_binop_rmi_all<0xD2, 0x72, MRM2r, "psrld", X86vsrl, X86vsrli, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - defm PSRLQ : PDI_binop_rmi_all<0xD3, 0x73, MRM2r, "psrlq", X86vsrl, X86vsrli, - v2i64, v4i64, v2i64, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSRAW : PDI_binop_rmi_all<0xE1, 0x71, MRM4r, "psraw", X86vsra, X86vsrai, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSRAD : PDI_binop_rmi_all<0xE2, 0x72, MRM4r, "psrad", X86vsra, X86vsrai, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSLLDQ : PDI_binop_ri_all<0x73, MRM7r, "pslldq", X86vshldq, - SchedWriteShuffle>; - defm PSRLDQ : PDI_binop_ri_all<0x73, MRM3r, "psrldq", X86vshrdq, - SchedWriteShuffle>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Comparison Instructions -//===---------------------------------------------------------------------===// - -defm PCMPEQB : PDI_binop_all<0x74, "pcmpeqb", X86pcmpeq, v16i8, v32i8, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPEQW : PDI_binop_all<0x75, "pcmpeqw", X86pcmpeq, v8i16, v16i16, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPEQD : PDI_binop_all<0x76, "pcmpeqd", X86pcmpeq, v4i32, v8i32, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPGTB : PDI_binop_all<0x64, "pcmpgtb", X86pcmpgt, v16i8, v32i8, - SchedWriteVecALU, 0, TruePredicate>; -defm PCMPGTW : PDI_binop_all<0x65, "pcmpgtw", X86pcmpgt, v8i16, v16i16, - SchedWriteVecALU, 0, TruePredicate>; -defm PCMPGTD : PDI_binop_all<0x66, "pcmpgtd", X86pcmpgt, v4i32, v8i32, - SchedWriteVecALU, 0, TruePredicate>; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Shuffle Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pshuffle { -let Predicates = [HasAVX, prd] in { - def V#NAME#ri : Ii8<0x70, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode VR128:$src1, (i8 imm:$src2))))]>, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#mi : Ii8<0x70, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode (bitconvert (loadv2i64 addr:$src1)), - (i8 imm:$src2))))]>, VEX, - Sched<[sched.XMM.Folded]>, VEX_WIG; -} - -let Predicates = [HasAVX2, prd] in { - def V#NAME#Yri : Ii8<0x70, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, - (vt256 (OpNode VR256:$src1, (i8 imm:$src2))))]>, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#Ymi : Ii8<0x70, MRMSrcMem, (outs VR256:$dst), - (ins i256mem:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, - (vt256 (OpNode (bitconvert (loadv4i64 addr:$src1)), - (i8 imm:$src2))))]>, VEX, VEX_L, - Sched<[sched.YMM.Folded]>, VEX_WIG; -} - -let Predicates = [UseSSE2] in { - def ri : Ii8<0x70, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, u8imm:$src2), - !strconcat(OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode VR128:$src1, (i8 imm:$src2))))]>, - Sched<[sched.XMM]>; - def mi : Ii8<0x70, MRMSrcMem, - (outs VR128:$dst), (ins i128mem:$src1, u8imm:$src2), - !strconcat(OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode (bitconvert (memopv2i64 addr:$src1)), - (i8 imm:$src2))))]>, - Sched<[sched.XMM.Folded]>; -} -} -} // ExeDomain = SSEPackedInt - -defm PSHUFD : sse2_pshuffle<"pshufd", v4i32, v8i32, X86PShufd, - SchedWriteShuffle, NoVLX>, PD; -defm PSHUFHW : sse2_pshuffle<"pshufhw", v8i16, v16i16, X86PShufhw, - SchedWriteShuffle, NoVLX_Or_NoBWI>, XS; -defm PSHUFLW : sse2_pshuffle<"pshuflw", v8i16, v16i16, X86PShuflw, - SchedWriteShuffle, NoVLX_Or_NoBWI>, XD; - -//===---------------------------------------------------------------------===// -// Packed Integer Pack Instructions (SSE & AVX) -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pack opc, string OpcodeStr, ValueType OutVT, - ValueType ArgVT, SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass sse4_pack opc, string OpcodeStr, ValueType OutVT, - ValueType ArgVT, SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - def rr : SS48I, - Sched<[sched]>; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPACKSSWB : sse2_pack<0x63, "vpacksswb", v16i8, v8i16, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPACKSSDW : sse2_pack<0x6B, "vpackssdw", v8i16, v4i32, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - - defm VPACKUSWB : sse2_pack<0x67, "vpackuswb", v16i8, v8i16, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPACKUSDW : sse4_pack<0x2B, "vpackusdw", v8i16, v4i32, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPACKSSWBY : sse2_pack<0x63, "vpacksswb", v32i8, v16i16, X86Packss, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPACKSSDWY : sse2_pack<0x6B, "vpackssdw", v16i16, v8i32, X86Packss, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - - defm VPACKUSWBY : sse2_pack<0x67, "vpackuswb", v32i8, v16i16, X86Packus, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPACKUSDWY : sse4_pack<0x2B, "vpackusdw", v16i16, v8i32, X86Packus, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L; -} - -let Constraints = "$src1 = $dst" in { - defm PACKSSWB : sse2_pack<0x63, "packsswb", v16i8, v8i16, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PACKSSDW : sse2_pack<0x6B, "packssdw", v8i16, v4i32, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PACKUSWB : sse2_pack<0x67, "packuswb", v16i8, v8i16, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PACKUSDW : sse4_pack<0x2B, "packusdw", v8i16, v4i32, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; -} -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Unpack Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_unpack opc, string OpcodeStr, ValueType vt, - SDNode OpNode, RegisterClass RC, X86MemOperand x86memop, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKLQDQ : sse2_unpack<0x6C, "vpunpcklqdq", v2i64, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHQDQ : sse2_unpack<0x6D, "vpunpckhqdq", v2i64, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPUNPCKLBWY : sse2_unpack<0x60, "vpunpcklbw", v32i8, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKLWDY : sse2_unpack<0x61, "vpunpcklwd", v16i16, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHBWY : sse2_unpack<0x68, "vpunpckhbw", v32i8, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHWDY : sse2_unpack<0x69, "vpunpckhwd", v16i16, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPUNPCKLDQY : sse2_unpack<0x62, "vpunpckldq", v8i32, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKLQDQY : sse2_unpack<0x6C, "vpunpcklqdq", v4i64, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHDQY : sse2_unpack<0x6A, "vpunpckhdq", v8i32, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHQDQY : sse2_unpack<0x6D, "vpunpckhqdq", v4i64, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLQDQ : sse2_unpack<0x6C, "punpcklqdq", v2i64, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHQDQ : sse2_unpack<0x6D, "punpckhqdq", v2i64, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; -} -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Extract and Insert -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pinsrw { - def rr : Ii8<0xC4, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, - GR32orGR64:$src2, u8imm:$src3), - !if(Is2Addr, - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - "vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), - [(set VR128:$dst, - (X86pinsrw VR128:$src1, GR32orGR64:$src2, imm:$src3))]>, - Sched<[WriteVecInsert]>; - def rm : Ii8<0xC4, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, - i16mem:$src2, u8imm:$src3), - !if(Is2Addr, - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - "vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), - [(set VR128:$dst, - (X86pinsrw VR128:$src1, (extloadi16 addr:$src2), - imm:$src3))]>, - Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -// Extract -let Predicates = [HasAVX, NoBWI] in -def VPEXTRWrr : Ii8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR128:$src1, u8imm:$src2), - "vpextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (X86pextrw (v8i16 VR128:$src1), - imm:$src2))]>, - PD, VEX, Sched<[WriteVecExtract]>; -def PEXTRWrr : PDIi8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR128:$src1, u8imm:$src2), - "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (X86pextrw (v8i16 VR128:$src1), - imm:$src2))]>, - Sched<[WriteVecExtract]>; - -// Insert -let Predicates = [HasAVX, NoBWI] in -defm VPINSRW : sse2_pinsrw<0>, PD, VEX_4V; - -let Predicates = [UseSSE2], Constraints = "$src1 = $dst" in -defm PINSRW : sse2_pinsrw, PD; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Mask Creation -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { - -def VPMOVMSKBrr : VPDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR128:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v16i8 VR128:$src)))]>, - Sched<[WriteVecMOVMSK]>, VEX, VEX_WIG; - -let Predicates = [HasAVX2] in { -def VPMOVMSKBYrr : VPDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR256:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v32i8 VR256:$src)))]>, - Sched<[WriteVecMOVMSKY]>, VEX, VEX_L, VEX_WIG; -} - -def PMOVMSKBrr : PDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), (ins VR128:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v16i8 VR128:$src)))]>, - Sched<[WriteVecMOVMSK]>; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Conditional Store -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecMoveLS.XMM.MR] in { -let Uses = [EDI], Predicates = [HasAVX,Not64BitMode] in -def VMASKMOVDQU : VPDI<0xF7, MRMSrcReg, (outs), - (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, EDI)]>, - VEX, VEX_WIG; -let Uses = [RDI], Predicates = [HasAVX,In64BitMode] in -def VMASKMOVDQU64 : VPDI<0xF7, MRMSrcReg, (outs), - (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>, - VEX, VEX_WIG; - -let Uses = [EDI], Predicates = [UseSSE2,Not64BitMode] in -def MASKMOVDQU : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, EDI)]>; -let Uses = [RDI], Predicates = [UseSSE2,In64BitMode] in -def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Move Doubleword/Quadword -//===---------------------------------------------------------------------===// - -//===---------------------------------------------------------------------===// -// Move Int Doubleword to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVDI2PDIrr : VS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; -def VMOVDI2PDIrm : VS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - VEX, Sched<[WriteVecLoad]>; -def VMOV64toPQIrr : VRS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def VMOV64toPQIrm : VRS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - VEX, Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in -def VMOV64toSDrr : VRS2I<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert GR64:$src))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; - -def MOVDI2PDIrr : S2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -def MOVDI2PDIrm : S2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - Sched<[WriteVecLoad]>; -def MOV64toPQIrr : RS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def MOV64toPQIrm : RS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in -def MOV64toSDrr : RS2I<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert GR64:$src))]>, - Sched<[WriteVecMoveFromGpr]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Move Int Doubleword to Single Scalar -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - def VMOVDI2SSrr : VS2I<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert GR32:$src))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; - - def VMOVDI2SSrm : VS2I<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>, - VEX, Sched<[WriteVecLoad]>; - def MOVDI2SSrr : S2I<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert GR32:$src))]>, - Sched<[WriteVecMoveFromGpr]>; - - def MOVDI2SSrm : S2I<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>, - Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -//===---------------------------------------------------------------------===// -// Move Packed Doubleword Int to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVPDI2DIrr : VS2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128:$src), - (iPTR 0)))]>, VEX, - Sched<[WriteVecMoveToGpr]>; -def VMOVPDI2DImr : VS2I<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; -def MOVPDI2DIrr : S2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128:$src), - (iPTR 0)))]>, - Sched<[WriteVecMoveToGpr]>; -def MOVPDI2DImr : S2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128:$src), - (iPTR 0))), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Move Packed Doubleword Int first element to Doubleword Int -// -let ExeDomain = SSEPackedInt in { -let SchedRW = [WriteVecMoveToGpr] in { -def VMOVPQIto64rr : VRS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128:$src), - (iPTR 0)))]>, - VEX; - -def MOVPQIto64rr : RS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128:$src), - (iPTR 0)))]>; -} //SchedRW - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def VMOVPQIto64mr : VRS2I<0x7E, MRMDestMem, (outs), - (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - VEX, Sched<[WriteVecStore]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def MOVPQIto64mr : RS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Bitcast FR64 <-> GR64 -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - let Predicates = [UseAVX] in - def VMOV64toSDrm : VS2SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>, - VEX, Sched<[WriteVecLoad]>; - def VMOVSDto64rr : VRS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64:$src))]>, - VEX, Sched<[WriteVecMoveToGpr]>; - def VMOVSDto64mr : VRS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; - - def MOV64toSDrm : S2SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>, - Sched<[WriteVecLoad]>; - def MOVSDto64rr : RS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64:$src))]>, - Sched<[WriteVecMoveToGpr]>; - def MOVSDto64mr : RS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -//===---------------------------------------------------------------------===// -// Move Scalar Single to Double Int -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - def VMOVSS2DIrr : VS2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32:$src))]>, - VEX, Sched<[WriteVecMoveToGpr]>; - def VMOVSS2DImr : VS2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; - def MOVSS2DIrr : S2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32:$src))]>, - Sched<[WriteVecMoveToGpr]>; - def MOVSS2DImr : S2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -let Predicates = [UseAVX] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (VMOVDI2PDIrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (VMOV64toPQIrr GR64:$src)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIrr GR64:$src)), sub_xmm)>; - // AVX 128-bit movd/movq instructions write zeros in the high 128-bit part. - // These instructions also write zeros in the high part of a 256-bit register. - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIrm addr:$src)), sub_xmm)>; - def : Pat<(v8i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v4i32 (VMOVDI2PDIrm addr:$src)), sub_xmm)>; - // Use regular 128-bit instructions to match 256-bit scalar_to_vec+zext. - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIrr GR32:$src)), sub_xmm)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (MOVDI2PDIrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (MOV64toPQIrr GR64:$src)>; - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (MOVDI2PDIrm addr:$src)>; -} - -// Before the MC layer of LLVM existed, clang emitted "movd" assembly instead of -// "movq" due to MacOS parsing limitation. In order to parse old assembly, we add -// these aliases. -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MOV64toPQIrr VR128:$dst, GR64:$src), 0>; -// def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MOVPQIto64rr GR64:$dst, VR128:$src), 0>; -// Allow "vmovd" but print "vmovq" since we don't need compatibility for AVX. -// def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", -// (VMOV64toPQIrr VR128:$dst, GR64:$src), 0>; -// def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", -// (VMOVPQIto64rr GR64:$dst, VR128:$src), 0>; - -//===---------------------------------------------------------------------===// -// SSE2 - Move Quadword -//===---------------------------------------------------------------------===// - -//===---------------------------------------------------------------------===// -// Move Quadword Int to Packed Quadword Int -// - -let ExeDomain = SSEPackedInt, SchedRW = [WriteVecLoad] in { -def VMOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, XS, - VEX, Requires<[UseAVX]>, VEX_WIG; -def MOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, - XS, Requires<[UseSSE2]>; // SSE2 instruction with XS Prefix -} // ExeDomain, SchedRW - -//===---------------------------------------------------------------------===// -// Move Packed Quadword Int to Quadword Int -// -let ExeDomain = SSEPackedInt, SchedRW = [WriteVecStore] in { -def VMOVPQI2QImr : VS2I<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -def MOVPQI2QImr : S2I<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))), addr:$dst)]>; -} // ExeDomain, SchedRW - -// For disassembler only -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVPQI2QIrr : VS2I<0xD6, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, VEX, VEX_WIG; -def MOVPQI2QIrr : S2I<0xD6, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>; -} - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -// def : InstAlias<"vmovq\t{$src, $dst|$dst, $src}", -// (VMOVPQI2QIrr VR128L:$dst, VR128H:$src), 0>; - -// def : InstAlias<"vmovq.s\t{$src, $dst|$dst, $src}", -// (VMOVPQI2QIrr VR128:$dst, VR128:$src), 0>; -// def : InstAlias<"movq.s\t{$src, $dst|$dst, $src}", -// (MOVPQI2QIrr VR128:$dst, VR128:$src), 0>; - -let Predicates = [UseAVX] in { - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (VMOVQI2PQIrm addr:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), - (VMOVQI2PQIrm addr:$src)>; - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector (loadi64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIrm addr:$src)), sub_xmm)>; - def : Pat<(v4i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIrm addr:$src)), sub_xmm)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (MOVQI2PQIrm addr:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), (MOVQI2PQIrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// Moving from XMM to XMM and clear upper 64 bits. Note, there is a bug in -// IA32 document. movq xmm1, xmm2 does clear the high bits. -// -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, - XS, VEX, Requires<[UseAVX]>, VEX_WIG; -def MOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, - XS, Requires<[UseSSE2]>; -} // ExeDomain, SchedRW - -let Predicates = [UseAVX] in { - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), - (VMOVZPQILo2PQIrr VR128:$src)>; -} -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), - (MOVZPQILo2PQIrr VR128:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Replicate Single FP - MOVSHDUP and MOVSLDUP -//===---------------------------------------------------------------------===// - -multiclass sse3_replicate_sfp op, SDNode OpNode, string OpcodeStr, - ValueType vt, RegisterClass RC, PatFrag mem_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched> { -def rr : S3SI, - Sched<[sched]>; -def rm : S3SI, - Sched<[sched.Folded]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VMOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup", - v4f32, VR128, loadv4f32, f128mem, - SchedWriteFShuffle.XMM>, VEX, VEX_WIG; - defm VMOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup", - v4f32, VR128, loadv4f32, f128mem, - SchedWriteFShuffle.XMM>, VEX, VEX_WIG; - defm VMOVSHDUPY : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup", - v8f32, VR256, loadv8f32, f256mem, - SchedWriteFShuffle.YMM>, VEX, VEX_L, VEX_WIG; - defm VMOVSLDUPY : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup", - v8f32, VR256, loadv8f32, f256mem, - SchedWriteFShuffle.YMM>, VEX, VEX_L, VEX_WIG; -} -defm MOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "movshdup", v4f32, VR128, - memopv4f32, f128mem, SchedWriteFShuffle.XMM>; -defm MOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "movsldup", v4f32, VR128, - memopv4f32, f128mem, SchedWriteFShuffle.XMM>; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (X86Movshdup VR128:$src)), - (VMOVSHDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVSHDUPrm addr:$src)>; - def : Pat<(v4i32 (X86Movsldup VR128:$src)), - (VMOVSLDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVSLDUPrm addr:$src)>; - def : Pat<(v8i32 (X86Movshdup VR256:$src)), - (VMOVSHDUPYrr VR256:$src)>; - def : Pat<(v8i32 (X86Movshdup (bc_v8i32 (loadv4i64 addr:$src)))), - (VMOVSHDUPYrm addr:$src)>; - def : Pat<(v8i32 (X86Movsldup VR256:$src)), - (VMOVSLDUPYrr VR256:$src)>; - def : Pat<(v8i32 (X86Movsldup (bc_v8i32 (loadv4i64 addr:$src)))), - (VMOVSLDUPYrm addr:$src)>; -} - -let Predicates = [UseSSE3] in { - def : Pat<(v4i32 (X86Movshdup VR128:$src)), - (MOVSHDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))), - (MOVSHDUPrm addr:$src)>; - def : Pat<(v4i32 (X86Movsldup VR128:$src)), - (MOVSLDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))), - (MOVSLDUPrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Replicate Double FP - MOVDDUP -//===---------------------------------------------------------------------===// - -multiclass sse3_replicate_dfp { -def rr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR128:$dst, (v2f64 (X86Movddup VR128:$src)))]>, - Sched<[sched.XMM]>; -def rm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR128:$dst, - (v2f64 (X86Movddup - (scalar_to_vector (loadf64 addr:$src)))))]>, - Sched<[sched.XMM.Folded]>; -} - -// FIXME: Merge with above classes when there are patterns for the ymm version -multiclass sse3_replicate_dfp_y { -def rr : S3DI<0x12, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR256:$dst, (v4f64 (X86Movddup VR256:$src)))]>, - Sched<[sched.YMM]>; -def rm : S3DI<0x12, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR256:$dst, - (v4f64 (X86Movddup (loadv4f64 addr:$src))))]>, - Sched<[sched.YMM.Folded]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VMOVDDUP : sse3_replicate_dfp<"vmovddup", SchedWriteFShuffle>, - VEX, VEX_WIG; - defm VMOVDDUPY : sse3_replicate_dfp_y<"vmovddup", SchedWriteFShuffle>, - VEX, VEX_L, VEX_WIG; -} - -defm MOVDDUP : sse3_replicate_dfp<"movddup", SchedWriteFShuffle>; - - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(X86Movddup (loadv2f64 addr:$src)), - (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>; -} - -let Predicates = [UseSSE3] in { - // No need for aligned memory as this only loads 64-bits. - def : Pat<(X86Movddup (loadv2f64 addr:$src)), - (MOVDDUPrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Move Unaligned Integer -//===---------------------------------------------------------------------===// - -let Predicates = [HasAVX] in { - def VLDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vlddqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, VEX, VEX_WIG; - def VLDDQUYrm : S3DI<0xF0, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vlddqu\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (int_x86_avx_ldu_dq_256 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, VEX, VEX_L, VEX_WIG; -} // Predicates - -def LDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "lddqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>; - -//===---------------------------------------------------------------------===// -// SSE3 - Arithmetic -//===---------------------------------------------------------------------===// - -multiclass sse3_addsub { - def rr : I<0xD0, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2), - !if(Is2Addr, - !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")), - [(set RC:$dst, (vt (X86Addsub RC:$src1, RC:$src2)))]>, - Sched<[sched]>; - def rm : I<0xD0, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !if(Is2Addr, - !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")), - [(set RC:$dst, (vt (X86Addsub RC:$src1, (ld_frag addr:$src2))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { - let ExeDomain = SSEPackedSingle in { - defm VADDSUBPS : sse3_addsub<"vaddsubps", v4f32, VR128, f128mem, - SchedWriteFAddSizes.PS.XMM, loadv4f32, 0>, - XD, VEX_4V, VEX_WIG; - defm VADDSUBPSY : sse3_addsub<"vaddsubps", v8f32, VR256, f256mem, - SchedWriteFAddSizes.PS.YMM, loadv8f32, 0>, - XD, VEX_4V, VEX_L, VEX_WIG; - } - let ExeDomain = SSEPackedDouble in { - defm VADDSUBPD : sse3_addsub<"vaddsubpd", v2f64, VR128, f128mem, - SchedWriteFAddSizes.PD.XMM, loadv2f64, 0>, - PD, VEX_4V, VEX_WIG; - defm VADDSUBPDY : sse3_addsub<"vaddsubpd", v4f64, VR256, f256mem, - SchedWriteFAddSizes.PD.YMM, loadv4f64, 0>, - PD, VEX_4V, VEX_L, VEX_WIG; - } -} -let Constraints = "$src1 = $dst", Predicates = [UseSSE3] in { - let ExeDomain = SSEPackedSingle in - defm ADDSUBPS : sse3_addsub<"addsubps", v4f32, VR128, f128mem, - SchedWriteFAddSizes.PS.XMM, memopv4f32>, XD; - let ExeDomain = SSEPackedDouble in - defm ADDSUBPD : sse3_addsub<"addsubpd", v2f64, VR128, f128mem, - SchedWriteFAddSizes.PD.XMM, memopv2f64>, PD; -} - -//===---------------------------------------------------------------------===// -// SSE3 Instructions -//===---------------------------------------------------------------------===// - -// Horizontal ops -multiclass S3D_Int o, string OpcodeStr, ValueType vt, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : S3DI, - Sched<[sched]>; - - def rm : S3DI, - Sched<[sched.Folded, ReadAfterLd]>; -} -multiclass S3_Int o, string OpcodeStr, ValueType vt, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : S3I, - Sched<[sched]>; - - def rm : S3I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { - let ExeDomain = SSEPackedSingle in { - defm VHADDPS : S3D_Int<0x7C, "vhaddps", v4f32, VR128, f128mem, - X86fhadd, WriteFHAdd, loadv4f32, 0>, VEX_4V, VEX_WIG; - defm VHSUBPS : S3D_Int<0x7D, "vhsubps", v4f32, VR128, f128mem, - X86fhsub, WriteFHAdd, loadv4f32, 0>, VEX_4V, VEX_WIG; - defm VHADDPSY : S3D_Int<0x7C, "vhaddps", v8f32, VR256, f256mem, - X86fhadd, WriteFHAddY, loadv8f32, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VHSUBPSY : S3D_Int<0x7D, "vhsubps", v8f32, VR256, f256mem, - X86fhsub, WriteFHAddY, loadv8f32, 0>, VEX_4V, VEX_L, VEX_WIG; - } - let ExeDomain = SSEPackedDouble in { - defm VHADDPD : S3_Int<0x7C, "vhaddpd", v2f64, VR128, f128mem, - X86fhadd, WriteFHAdd, loadv2f64, 0>, VEX_4V, VEX_WIG; - defm VHSUBPD : S3_Int<0x7D, "vhsubpd", v2f64, VR128, f128mem, - X86fhsub, WriteFHAdd, loadv2f64, 0>, VEX_4V, VEX_WIG; - defm VHADDPDY : S3_Int<0x7C, "vhaddpd", v4f64, VR256, f256mem, - X86fhadd, WriteFHAddY, loadv4f64, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VHSUBPDY : S3_Int<0x7D, "vhsubpd", v4f64, VR256, f256mem, - X86fhsub, WriteFHAddY, loadv4f64, 0>, VEX_4V, VEX_L, VEX_WIG; - } -} - -let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in { - defm HADDPS : S3D_Int<0x7C, "haddps", v4f32, VR128, f128mem, X86fhadd, - WriteFHAdd, memopv4f32>; - defm HSUBPS : S3D_Int<0x7D, "hsubps", v4f32, VR128, f128mem, X86fhsub, - WriteFHAdd, memopv4f32>; - } - let ExeDomain = SSEPackedDouble in { - defm HADDPD : S3_Int<0x7C, "haddpd", v2f64, VR128, f128mem, X86fhadd, - WriteFHAdd, memopv2f64>; - defm HSUBPD : S3_Int<0x7D, "hsubpd", v2f64, VR128, f128mem, X86fhsub, - WriteFHAdd, memopv2f64>; - } -} - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Absolute Instructions -//===---------------------------------------------------------------------===// - -/// SS3I_unop_rm_int - Simple SSSE3 unary op whose type can be v*{i8,i16,i32}. -multiclass SS3I_unop_rm opc, string OpcodeStr, ValueType vt, - SDNode OpNode, X86SchedWriteWidths sched, PatFrag ld_frag> { - def rr : SS38I, - Sched<[sched.XMM]>; - - def rm : SS38I, - Sched<[sched.XMM.Folded]>; -} - -/// SS3I_unop_rm_int_y - Simple SSSE3 unary op whose type can be v*{i8,i16,i32}. -multiclass SS3I_unop_rm_y opc, string OpcodeStr, ValueType vt, - SDNode OpNode, X86SchedWriteWidths sched> { - def Yrr : SS38I, - Sched<[sched.YMM]>; - - def Yrm : SS38I, - Sched<[sched.YMM.Folded]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPABSB : SS3I_unop_rm<0x1C, "vpabsb", v16i8, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; - defm VPABSW : SS3I_unop_rm<0x1D, "vpabsw", v8i16, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; -} -let Predicates = [HasAVX, NoVLX] in { - defm VPABSD : SS3I_unop_rm<0x1E, "vpabsd", v4i32, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPABSB : SS3I_unop_rm_y<0x1C, "vpabsb", v32i8, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; - defm VPABSW : SS3I_unop_rm_y<0x1D, "vpabsw", v16i16, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX] in { - defm VPABSD : SS3I_unop_rm_y<0x1E, "vpabsd", v8i32, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; -} - -defm PABSB : SS3I_unop_rm<0x1C, "pabsb", v16i8, abs, SchedWriteVecALU, - memopv2i64>; -defm PABSW : SS3I_unop_rm<0x1D, "pabsw", v8i16, abs, SchedWriteVecALU, - memopv2i64>; -defm PABSD : SS3I_unop_rm<0x1E, "pabsd", v4i32, abs, SchedWriteVecALU, - memopv2i64>; - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Binary Operator Instructions -//===---------------------------------------------------------------------===// - -/// SS3I_binop_rm - Simple SSSE3 bin op -multiclass SS3I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType DstVT, ValueType OpVT, RegisterClass RC, - PatFrag memop_frag, X86MemOperand x86memop, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS38I, - Sched<[sched]>; - def rm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// SS3I_binop_rm_int - Simple SSSE3 bin op whose type can be v*{i8,i16,i32}. -multiclass SS3I_binop_rm_int opc, string OpcodeStr, - Intrinsic IntId128, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS38I, - Sched<[sched]>; - def rm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass SS3I_binop_rm_int_y opc, string OpcodeStr, - Intrinsic IntId256, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def Yrr : SS38I, - Sched<[sched]>; - def Yrm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let ImmT = NoImm, Predicates = [HasAVX, NoVLX_Or_NoBWI] in { -let isCommutable = 0 in { - defm VPSHUFB : SS3I_binop_rm<0x00, "vpshufb", X86pshufb, v16i8, v16i8, - VR128, loadv2i64, i128mem, - SchedWriteVarShuffle.XMM, 0>, VEX_4V, VEX_WIG; - defm VPMADDUBSW : SS3I_binop_rm<0x04, "vpmaddubsw", X86vpmaddubsw, v8i16, - v16i8, VR128, loadv2i64, i128mem, - SchedWriteVecIMul.XMM, 0>, VEX_4V, VEX_WIG; -} -defm VPMULHRSW : SS3I_binop_rm<0x0B, "vpmulhrsw", X86mulhrs, v8i16, v8i16, - VR128, loadv2i64, i128mem, - SchedWriteVecIMul.XMM, 0>, VEX_4V, VEX_WIG; -} - -let ImmT = NoImm, Predicates = [HasAVX] in { -let isCommutable = 0 in { - defm VPHADDW : SS3I_binop_rm<0x01, "vphaddw", X86hadd, v8i16, v8i16, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHADDD : SS3I_binop_rm<0x02, "vphaddd", X86hadd, v4i32, v4i32, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHSUBW : SS3I_binop_rm<0x05, "vphsubw", X86hsub, v8i16, v8i16, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHSUBD : SS3I_binop_rm<0x06, "vphsubd", X86hsub, v4i32, v4i32, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V; - defm VPSIGNB : SS3I_binop_rm_int<0x08, "vpsignb", - int_x86_ssse3_psign_b_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPSIGNW : SS3I_binop_rm_int<0x09, "vpsignw", - int_x86_ssse3_psign_w_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPSIGND : SS3I_binop_rm_int<0x0A, "vpsignd", - int_x86_ssse3_psign_d_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPHADDSW : SS3I_binop_rm_int<0x03, "vphaddsw", - int_x86_ssse3_phadd_sw_128, - SchedWritePHAdd.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPHSUBSW : SS3I_binop_rm_int<0x07, "vphsubsw", - int_x86_ssse3_phsub_sw_128, - SchedWritePHAdd.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; -} -} - -let ImmT = NoImm, Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { -let isCommutable = 0 in { - defm VPSHUFBY : SS3I_binop_rm<0x00, "vpshufb", X86pshufb, v32i8, v32i8, - VR256, loadv4i64, i256mem, - SchedWriteVarShuffle.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPMADDUBSWY : SS3I_binop_rm<0x04, "vpmaddubsw", X86vpmaddubsw, v16i16, - v32i8, VR256, loadv4i64, i256mem, - SchedWriteVecIMul.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -} -defm VPMULHRSWY : SS3I_binop_rm<0x0B, "vpmulhrsw", X86mulhrs, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWriteVecIMul.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -} - -let ImmT = NoImm, Predicates = [HasAVX2] in { -let isCommutable = 0 in { - defm VPHADDWY : SS3I_binop_rm<0x01, "vphaddw", X86hadd, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHADDDY : SS3I_binop_rm<0x02, "vphaddd", X86hadd, v8i32, v8i32, VR256, - loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBWY : SS3I_binop_rm<0x05, "vphsubw", X86hsub, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBDY : SS3I_binop_rm<0x06, "vphsubd", X86hsub, v8i32, v8i32, VR256, - loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L; - defm VPSIGNB : SS3I_binop_rm_int_y<0x08, "vpsignb", int_x86_avx2_psign_b, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPSIGNW : SS3I_binop_rm_int_y<0x09, "vpsignw", int_x86_avx2_psign_w, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPSIGND : SS3I_binop_rm_int_y<0x0A, "vpsignd", int_x86_avx2_psign_d, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPHADDSW : SS3I_binop_rm_int_y<0x03, "vphaddsw", - int_x86_avx2_phadd_sw, - SchedWritePHAdd.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBSW : SS3I_binop_rm_int_y<0x07, "vphsubsw", - int_x86_avx2_phsub_sw, - SchedWritePHAdd.YMM>, VEX_4V, VEX_L, VEX_WIG; -} -} - -// None of these have i8 immediate fields. -let ImmT = NoImm, Constraints = "$src1 = $dst" in { -let isCommutable = 0 in { - defm PHADDW : SS3I_binop_rm<0x01, "phaddw", X86hadd, v8i16, v8i16, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHADDD : SS3I_binop_rm<0x02, "phaddd", X86hadd, v4i32, v4i32, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHSUBW : SS3I_binop_rm<0x05, "phsubw", X86hsub, v8i16, v8i16, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHSUBD : SS3I_binop_rm<0x06, "phsubd", X86hsub, v4i32, v4i32, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PSIGNB : SS3I_binop_rm_int<0x08, "psignb", int_x86_ssse3_psign_b_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSIGNW : SS3I_binop_rm_int<0x09, "psignw", int_x86_ssse3_psign_w_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSIGND : SS3I_binop_rm_int<0x0A, "psignd", int_x86_ssse3_psign_d_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSHUFB : SS3I_binop_rm<0x00, "pshufb", X86pshufb, v16i8, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVarShuffle.XMM>; - defm PHADDSW : SS3I_binop_rm_int<0x03, "phaddsw", - int_x86_ssse3_phadd_sw_128, - SchedWritePHAdd.XMM, memopv2i64>; - defm PHSUBSW : SS3I_binop_rm_int<0x07, "phsubsw", - int_x86_ssse3_phsub_sw_128, - SchedWritePHAdd.XMM, memopv2i64>; - defm PMADDUBSW : SS3I_binop_rm<0x04, "pmaddubsw", X86vpmaddubsw, v8i16, - v16i8, VR128, memopv2i64, i128mem, - SchedWriteVecIMul.XMM>; -} -defm PMULHRSW : SS3I_binop_rm<0x0B, "pmulhrsw", X86mulhrs, v8i16, v8i16, - VR128, memopv2i64, i128mem, SchedWriteVecIMul.XMM>; -} - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Align Instruction Patterns -//===---------------------------------------------------------------------===// - -multiclass ssse3_palignr { - let hasSideEffects = 0 in { - def rri : SS3AI<0x0F, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), - !if(Is2Addr, - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - !strconcat(asm, - "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")), - [(set RC:$dst, (VT (X86PAlignr RC:$src1, RC:$src2, (i8 imm:$src3))))]>, - Sched<[sched]>; - let mayLoad = 1 in - def rmi : SS3AI<0x0F, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$src3), - !if(Is2Addr, - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - !strconcat(asm, - "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")), - [(set RC:$dst, (VT (X86PAlignr RC:$src1, - (bitconvert (memop_frag addr:$src2)), - (i8 imm:$src3))))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in - defm VPALIGNR : ssse3_palignr<"vpalignr", v16i8, VR128, loadv2i64, i128mem, - SchedWriteShuffle.XMM, 0>, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in - defm VPALIGNRY : ssse3_palignr<"vpalignr", v32i8, VR256, loadv4i64, i256mem, - SchedWriteShuffle.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst", Predicates = [UseSSSE3] in - defm PALIGNR : ssse3_palignr<"palignr", v16i8, VR128, memopv2i64, i128mem, - SchedWriteShuffle.XMM>; - -//===---------------------------------------------------------------------===// -// SSSE3 - Thread synchronization -//===---------------------------------------------------------------------===// - -let SchedRW = [WriteSystem] in { -/* -let usesCustomInserter = 1 in { -def MONITOR : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_sse3_monitor addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[HasSSE3]>; -} -*/ - -let Uses = [EAX, ECX, EDX] in -def MONITORrrr : I<0x01, MRM_C8, (outs), (ins), "monitor", []>, - TB, Requires<[HasSSE3]>; - -let Uses = [ECX, EAX] in -def MWAITrr : I<0x01, MRM_C9, (outs), (ins), "mwait", - [(int_x86_sse3_mwait ECX, EAX)]>, TB, Requires<[HasSSE3]>; -} // SchedRW - -// def : InstAlias<"mwait\t{%eax, %ecx|ecx, eax}", (MWAITrr)>, Requires<[Not64BitMode]>; -// def : InstAlias<"mwait\t{%rax, %rcx|rcx, rax}", (MWAITrr)>, Requires<[In64BitMode]>; - -// def : InstAlias<"monitor\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORrrr)>, -// Requires<[Not64BitMode]>; -// def : InstAlias<"monitor\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORrrr)>, -// Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Packed Move with Sign/Zero Extend -//===----------------------------------------------------------------------===// - -multiclass SS41I_pmovx_rrrm opc, string OpcodeStr, X86MemOperand MemOp, - RegisterClass OutRC, RegisterClass InRC, - X86FoldableSchedWrite sched> { - def rr : SS48I, - Sched<[sched]>; - - def rm : SS48I, - Sched<[sched.Folded]>; -} - -multiclass SS41I_pmovx_rm_all opc, string OpcodeStr, - X86MemOperand MemOp, X86MemOperand MemYOp, - Predicate prd> { - defm NAME : SS41I_pmovx_rrrm; - let Predicates = [HasAVX, prd] in - defm V#NAME : SS41I_pmovx_rrrm, - VEX, VEX_WIG; - let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : SS41I_pmovx_rrrm, - VEX, VEX_L, VEX_WIG; -} - -multiclass SS41I_pmovx_rm opc, string OpcodeStr, X86MemOperand MemOp, - X86MemOperand MemYOp, Predicate prd> { - defm PMOVSX#NAME : SS41I_pmovx_rm_all; - defm PMOVZX#NAME : SS41I_pmovx_rm_all; -} - -defm BW : SS41I_pmovx_rm<0x20, "bw", i64mem, i128mem, NoVLX_Or_NoBWI>; -defm WD : SS41I_pmovx_rm<0x23, "wd", i64mem, i128mem, NoVLX>; -defm DQ : SS41I_pmovx_rm<0x25, "dq", i64mem, i128mem, NoVLX>; - -defm BD : SS41I_pmovx_rm<0x21, "bd", i32mem, i64mem, NoVLX>; -defm WQ : SS41I_pmovx_rm<0x24, "wq", i32mem, i64mem, NoVLX>; - -defm BQ : SS41I_pmovx_rm<0x22, "bq", i16mem, i32mem, NoVLX>; - -// AVX2 Patterns -multiclass SS41I_pmovx_avx2_patterns { - // Register-Register patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BWYrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BDYrr) VR128:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BQYrr) VR128:$src)>; - - def : Pat<(v8i32 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WDYrr) VR128:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WQYrr) VR128:$src)>; - - def : Pat<(v4i64 (ExtOp (v4i32 VR128:$src))), - (!cast(OpcPrefix#DQYrr) VR128:$src)>; - } - - // Simple Register-Memory patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - - def : Pat<(v8i32 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi32") addr:$src)), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - } - - // AVX2 Register-Memory patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - - def : Pat<(v8i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - } -} - -defm : SS41I_pmovx_avx2_patterns<"VPMOVSX", "s", X86vsext>; -defm : SS41I_pmovx_avx2_patterns<"VPMOVZX", "z", X86vzext>; - -// SSE4.1/AVX patterns. -multiclass SS41I_pmovx_patterns { - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BWrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BDrr) VR128:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BQrr) VR128:$src)>; - - def : Pat<(v4i32 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WDrr) VR128:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WQrr) VR128:$src)>; - - def : Pat<(v2i64 (ExtOp (v4i32 VR128:$src))), - (!cast(OpcPrefix#DQrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BWrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BQrm) addr:$src)>; - - def : Pat<(v4i32 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WQrm) addr:$src)>; - - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi32") addr:$src)), - (!cast(OpcPrefix#DQrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (bc_v16i8 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (extloadi32i16 addr:$src)))))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - - def : Pat<(v4i32 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v8i16 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v8i16 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v4i32 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - } -} - -defm : SS41I_pmovx_patterns<"VPMOVSX", "s", sext_invec>; -defm : SS41I_pmovx_patterns<"VPMOVZX", "z", zext_invec>; - -let Predicates = [UseSSE41] in { - defm : SS41I_pmovx_patterns<"PMOVSX", "s", sext_invec>; - defm : SS41I_pmovx_patterns<"PMOVZX", "z", zext_invec>; -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Extract Instructions -//===----------------------------------------------------------------------===// - -/// SS41I_binop_ext8 - SSE 4.1 extract 8 bits to 32 bit reg or 8 bit mem -multiclass SS41I_extract8 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - let hasSideEffects = 0, mayStore = 1 in - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPEXTRB : SS41I_extract8<0x14, "vpextrb">, VEX; - -defm PEXTRB : SS41I_extract8<0x14, "pextrb">; - - -/// SS41I_extract16 - SSE 4.1 extract 16 bits to memory destination -multiclass SS41I_extract16 opc, string OpcodeStr> { - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : SS4AIi8, - Sched<[WriteVecExtract]>, FoldGenData; - - let hasSideEffects = 0, mayStore = 1 in - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPEXTRW : SS41I_extract16<0x15, "vpextrw">, VEX; - -defm PEXTRW : SS41I_extract16<0x15, "pextrw">; - - -/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination -multiclass SS41I_extract32 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPEXTRD : SS41I_extract32<0x16, "vpextrd">, VEX; - -defm PEXTRD : SS41I_extract32<0x16, "pextrd">; - -/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination -multiclass SS41I_extract64 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPEXTRQ : SS41I_extract64<0x16, "vpextrq">, VEX, VEX_W; - -defm PEXTRQ : SS41I_extract64<0x16, "pextrq">, REX_W; - -/// SS41I_extractf32 - SSE 4.1 extract 32 bits fp value to int reg or memory -/// destination -multiclass SS41I_extractf32 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let ExeDomain = SSEPackedSingle in { - let Predicates = [UseAVX] in - defm VEXTRACTPS : SS41I_extractf32<0x17, "vextractps">, VEX, VEX_WIG; - defm EXTRACTPS : SS41I_extractf32<0x17, "extractps">; -} - -// Also match an EXTRACTPS store when the store is done as f32 instead of i32. -def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)), - imm:$src2))), - addr:$dst), - (VEXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>, - Requires<[HasAVX]>; -def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)), - imm:$src2))), - addr:$dst), - (EXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>, - Requires<[UseSSE41]>; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Insert Instructions -//===----------------------------------------------------------------------===// - -multiclass SS41I_insert8 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPINSRB : SS41I_insert8<0x20, "vpinsrb", 0>, VEX_4V; -let Constraints = "$src1 = $dst" in - defm PINSRB : SS41I_insert8<0x20, "pinsrb">; - -multiclass SS41I_insert32 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPINSRD : SS41I_insert32<0x22, "vpinsrd", 0>, VEX_4V; -let Constraints = "$src1 = $dst" in - defm PINSRD : SS41I_insert32<0x22, "pinsrd">; - -multiclass SS41I_insert64 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPINSRQ : SS41I_insert64<0x22, "vpinsrq", 0>, VEX_4V, VEX_W; -let Constraints = "$src1 = $dst" in - defm PINSRQ : SS41I_insert64<0x22, "pinsrq">, REX_W; - -// insertps has a few different modes, there's the first two here below which -// are optimized inserts that won't zero arbitrary elements in the destination -// vector. The next one matches the intrinsic and could zero arbitrary elements -// in the target vector. -multiclass SS41I_insertf32 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[SchedWriteFShuffle.XMM]>; - def rm : SS4AIi8, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedSingle in { - let Predicates = [UseAVX] in - defm VINSERTPS : SS41I_insertf32<0x21, "vinsertps", 0>, - VEX_4V, VEX_WIG; - let Constraints = "$src1 = $dst" in - defm INSERTPS : SS41I_insertf32<0x21, "insertps", 1>; -} - -let Predicates = [UseAVX] in { - // If we're inserting an element from a vbroadcast of a load, fold the - // load into the X86insertps instruction. - def : Pat<(v4f32 (X86insertps (v4f32 VR128:$src1), - (X86VBroadcast (loadf32 addr:$src2)), imm:$src3)), - (VINSERTPSrm VR128:$src1, addr:$src2, imm:$src3)>; - def : Pat<(v4f32 (X86insertps (v4f32 VR128:$src1), - (X86VBroadcast (loadv4f32 addr:$src2)), imm:$src3)), - (VINSERTPSrm VR128:$src1, addr:$src2, imm:$src3)>; -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Round Instructions -//===----------------------------------------------------------------------===// - -multiclass sse41_fp_unop_p opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - ValueType VT, PatFrag mem_frag, SDNode OpNode, - X86FoldableSchedWrite sched> { - // Intrinsic operation, reg. - // Vector intrinsic operation, reg - def r : SS4AIi8, - Sched<[sched]>; - - // Vector intrinsic operation, mem - def m : SS4AIi8, - Sched<[sched.Folded]>; -} - -multiclass avx_fp_unop_rm opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched> { -let ExeDomain = SSEPackedSingle, hasSideEffects = 0 in { - def SSr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SSm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, hasSideEffects = 0 - -let ExeDomain = SSEPackedDouble, hasSideEffects = 0 in { - def SDr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SDm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, hasSideEffects = 0 -} - -multiclass sse41_fp_unop_s opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched> { -let ExeDomain = SSEPackedSingle, hasSideEffects = 0 in { - def SSr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SSm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, hasSideEffects = 0 - -let ExeDomain = SSEPackedDouble, hasSideEffects = 0 in { - def SDr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SDm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, hasSideEffects = 0 -} - -multiclass sse41_fp_binop_s opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched, - ValueType VT32, ValueType VT64, - SDNode OpNode, bit Is2Addr = 1> { -let ExeDomain = SSEPackedSingle, isCodeGenOnly = 1 in { - def SSr_Int : SS4AIi8, - Sched<[sched]>; - - def SSm_Int : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, isCodeGenOnly = 1 - -let ExeDomain = SSEPackedDouble, isCodeGenOnly = 1 in { - def SDr_Int : SS4AIi8, - Sched<[sched]>; - - def SDm_Int : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, isCodeGenOnly = 1 -} - -// FP round - roundss, roundps, roundsd, roundpd -let Predicates = [HasAVX, NoVLX] in { - let ExeDomain = SSEPackedSingle in { - // Intrinsic form - defm VROUNDPS : sse41_fp_unop_p<0x08, "vroundps", f128mem, VR128, v4f32, - loadv4f32, X86VRndScale, SchedWriteFRnd.XMM>, - VEX, VEX_WIG; - defm VROUNDPSY : sse41_fp_unop_p<0x08, "vroundps", f256mem, VR256, v8f32, - loadv8f32, X86VRndScale, SchedWriteFRnd.YMM>, - VEX, VEX_L, VEX_WIG; - } - - let ExeDomain = SSEPackedDouble in { - defm VROUNDPD : sse41_fp_unop_p<0x09, "vroundpd", f128mem, VR128, v2f64, - loadv2f64, X86VRndScale, SchedWriteFRnd.XMM>, - VEX, VEX_WIG; - defm VROUNDPDY : sse41_fp_unop_p<0x09, "vroundpd", f256mem, VR256, v4f64, - loadv4f64, X86VRndScale, SchedWriteFRnd.YMM>, - VEX, VEX_L, VEX_WIG; - } -} -let Predicates = [HasAVX, NoAVX512] in { - defm VROUND : sse41_fp_binop_s<0x0A, 0x0B, "vround", SchedWriteFRnd.Scl, - v4f32, v2f64, X86RndScales, 0>, - VEX_4V, VEX_LIG, VEX_WIG; - defm VROUND : avx_fp_unop_rm<0x0A, 0x0B, "vround", SchedWriteFRnd.Scl>, - VEX_4V, VEX_LIG, VEX_WIG; -} - -let Predicates = [UseAVX] in { - def : Pat<(ffloor FR32:$src), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xC))>; - def : Pat<(f32 (fceil FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xA))>; - def : Pat<(f32 (frint FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xC))>; - def : Pat<(f64 (fceil FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xA))>; - def : Pat<(f64 (frint FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xB))>; -} - -let Predicates = [UseAVX, OptForSize] in { - def : Pat<(ffloor (loadf32 addr:$src)), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xC))>; - def : Pat<(f32 (fceil (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xA))>; - def : Pat<(f32 (frint (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xC))>; - def : Pat<(f64 (fceil (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xA))>; - def : Pat<(f64 (frint (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xB))>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (ffloor VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xB))>; - - def : Pat<(v4f32 (ffloor (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xB))>; - - def : Pat<(v8f32 (ffloor VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0x9))>; - def : Pat<(v8f32 (fnearbyint VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xC))>; - def : Pat<(v8f32 (fceil VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xA))>; - def : Pat<(v8f32 (frint VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0x4))>; - def : Pat<(v8f32 (ftrunc VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xB))>; - - def : Pat<(v8f32 (ffloor (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0x9))>; - def : Pat<(v8f32 (fnearbyint (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xC))>; - def : Pat<(v8f32 (fceil (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xA))>; - def : Pat<(v8f32 (frint (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0x4))>; - def : Pat<(v8f32 (ftrunc (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xB))>; - - def : Pat<(v4f64 (ffloor VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0x9))>; - def : Pat<(v4f64 (fnearbyint VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xC))>; - def : Pat<(v4f64 (fceil VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xA))>; - def : Pat<(v4f64 (frint VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0x4))>; - def : Pat<(v4f64 (ftrunc VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xB))>; - - def : Pat<(v4f64 (ffloor (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0x9))>; - def : Pat<(v4f64 (fnearbyint (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xC))>; - def : Pat<(v4f64 (fceil (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xA))>; - def : Pat<(v4f64 (frint (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0x4))>; - def : Pat<(v4f64 (ftrunc (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xB))>; -} - -let ExeDomain = SSEPackedSingle in -defm ROUNDPS : sse41_fp_unop_p<0x08, "roundps", f128mem, VR128, v4f32, - memopv4f32, X86VRndScale, SchedWriteFRnd.XMM>; -let ExeDomain = SSEPackedDouble in -defm ROUNDPD : sse41_fp_unop_p<0x09, "roundpd", f128mem, VR128, v2f64, - memopv2f64, X86VRndScale, SchedWriteFRnd.XMM>; - -defm ROUND : sse41_fp_unop_s<0x0A, 0x0B, "round", SchedWriteFRnd.Scl>; - -let Constraints = "$src1 = $dst" in -defm ROUND : sse41_fp_binop_s<0x0A, 0x0B, "round", SchedWriteFRnd.Scl, - v4f32, v2f64, X86RndScales>; - -let Predicates = [UseSSE41] in { - def : Pat<(ffloor FR32:$src), - (ROUNDSSr FR32:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xC))>; - def : Pat<(f32 (fceil FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xA))>; - def : Pat<(f32 (frint FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xC))>; - def : Pat<(f64 (fceil FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xA))>; - def : Pat<(f64 (frint FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xB))>; -} - -let Predicates = [UseSSE41, OptForSize] in { - def : Pat<(ffloor (loadf32 addr:$src)), - (ROUNDSSm addr:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xC))>; - def : Pat<(f32 (fceil (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xA))>; - def : Pat<(f32 (frint (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xC))>; - def : Pat<(f64 (fceil (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xA))>; - def : Pat<(f64 (frint (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xB))>; -} - -let Predicates = [UseSSE41] in { - def : Pat<(v4f32 (ffloor VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xB))>; - - def : Pat<(v4f32 (ffloor (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xB))>; -} - -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Packed Bit Test -//===----------------------------------------------------------------------===// - -// ptest instruction we'll lower to this in X86ISelLowering primarily from -// the intel intrinsic that corresponds to this. -let Defs = [EFLAGS], Predicates = [HasAVX] in { -def VPTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (v2i64 VR128:$src2)))]>, - Sched<[SchedWriteVecTest.XMM]>, VEX, VEX_WIG; -def VPTESTrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS,(X86ptest VR128:$src1, (loadv2i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.XMM.Folded, ReadAfterLd]>, - VEX, VEX_WIG; - -def VPTESTYrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR256:$src1, VR256:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR256:$src1, (v4i64 VR256:$src2)))]>, - Sched<[SchedWriteVecTest.YMM]>, VEX, VEX_L, VEX_WIG; -def VPTESTYrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR256:$src1, i256mem:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS,(X86ptest VR256:$src1, (loadv4i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.YMM.Folded, ReadAfterLd]>, - VEX, VEX_L, VEX_WIG; -} - -let Defs = [EFLAGS] in { -def PTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), - "ptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (v2i64 VR128:$src2)))]>, - Sched<[SchedWriteVecTest.XMM]>; -def PTESTrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), - "ptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (memopv2i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.XMM.Folded, ReadAfterLd]>; -} - -// The bit test instructions below are AVX only -multiclass avx_bittest opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, PatFrag mem_frag, ValueType vt, - X86FoldableSchedWrite sched> { - def rr : SS48I, - Sched<[sched]>, VEX; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>, VEX; -} - -let Defs = [EFLAGS], Predicates = [HasAVX] in { -let ExeDomain = SSEPackedSingle in { -defm VTESTPS : avx_bittest<0x0E, "vtestps", VR128, f128mem, loadv4f32, v4f32, - SchedWriteFTest.XMM>; -defm VTESTPSY : avx_bittest<0x0E, "vtestps", VR256, f256mem, loadv8f32, v8f32, - SchedWriteFTest.YMM>, VEX_L; -} -let ExeDomain = SSEPackedDouble in { -defm VTESTPD : avx_bittest<0x0F, "vtestpd", VR128, f128mem, loadv2f64, v2f64, - SchedWriteFTest.XMM>; -defm VTESTPDY : avx_bittest<0x0F, "vtestpd", VR256, f256mem, loadv4f64, v4f64, - SchedWriteFTest.YMM>, VEX_L; -} -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Misc Instructions -//===----------------------------------------------------------------------===// - -let Defs = [EFLAGS], Predicates = [HasPOPCNT] in { - def POPCNT16rr : I<0xB8, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "popcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctpop GR16:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, OpSize16, XS; - def POPCNT16rm : I<0xB8, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "popcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctpop (loadi16 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, OpSize16, XS; - - def POPCNT32rr : I<0xB8, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "popcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctpop GR32:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, OpSize32, XS; - - def POPCNT32rm : I<0xB8, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "popcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctpop (loadi32 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, OpSize32, XS; - - def POPCNT64rr : RI<0xB8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "popcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctpop GR64:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, XS; - def POPCNT64rm : RI<0xB8, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "popcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctpop (loadi64 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, XS; -} - -// SS41I_unop_rm_int_v16 - SSE 4.1 unary operator whose type is v8i16. -multiclass SS41I_unop_rm_int_v16 opc, string OpcodeStr, - SDNode OpNode, PatFrag ld_frag, - X86FoldableSchedWrite Sched> { - def rr : SS48I, - Sched<[Sched]>; - def rm : SS48I, - Sched<[Sched.Folded]>; -} - -// PHMIN has the same profile as PSAD, thus we use the same scheduling -// model, although the naming is misleading. -let Predicates = [HasAVX] in -defm VPHMINPOSUW : SS41I_unop_rm_int_v16<0x41, "vphminposuw", - X86phminpos, loadv2i64, - WritePHMINPOS>, VEX, VEX_WIG; -defm PHMINPOSUW : SS41I_unop_rm_int_v16<0x41, "phminposuw", - X86phminpos, memopv2i64, - WritePHMINPOS>; - -/// SS48I_binop_rm - Simple SSE41 binary operator. -multiclass SS48I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS48I, - Sched<[sched]>; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VPMINSD : SS48I_binop_rm<0x39, "vpminsd", smin, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMINUD : SS48I_binop_rm<0x3B, "vpminud", umin, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXSD : SS48I_binop_rm<0x3D, "vpmaxsd", smax, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXUD : SS48I_binop_rm<0x3F, "vpmaxud", umax, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMULDQ : SS48I_binop_rm<0x28, "vpmuldq", X86pmuldq, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecIMul.XMM, 0>, - VEX_4V, VEX_WIG; -} -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPMINSB : SS48I_binop_rm<0x38, "vpminsb", smin, v16i8, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMINUW : SS48I_binop_rm<0x3A, "vpminuw", umin, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXSB : SS48I_binop_rm<0x3C, "vpmaxsb", smax, v16i8, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXUW : SS48I_binop_rm<0x3E, "vpmaxuw", umax, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPMINSDY : SS48I_binop_rm<0x39, "vpminsd", smin, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMINUDY : SS48I_binop_rm<0x3B, "vpminud", umin, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXSDY : SS48I_binop_rm<0x3D, "vpmaxsd", smax, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXUDY : SS48I_binop_rm<0x3F, "vpmaxud", umax, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMULDQY : SS48I_binop_rm<0x28, "vpmuldq", X86pmuldq, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecIMul.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPMINSBY : SS48I_binop_rm<0x38, "vpminsb", smin, v32i8, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMINUWY : SS48I_binop_rm<0x3A, "vpminuw", umin, v16i16, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXSBY : SS48I_binop_rm<0x3C, "vpmaxsb", smax, v32i8, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXUWY : SS48I_binop_rm<0x3E, "vpmaxuw", umax, v16i16, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm PMINSB : SS48I_binop_rm<0x38, "pminsb", smin, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINSD : SS48I_binop_rm<0x39, "pminsd", smin, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINUD : SS48I_binop_rm<0x3B, "pminud", umin, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINUW : SS48I_binop_rm<0x3A, "pminuw", umin, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXSB : SS48I_binop_rm<0x3C, "pmaxsb", smax, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXSD : SS48I_binop_rm<0x3D, "pmaxsd", smax, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXUD : SS48I_binop_rm<0x3F, "pmaxud", umax, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXUW : SS48I_binop_rm<0x3E, "pmaxuw", umax, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMULDQ : SS48I_binop_rm<0x28, "pmuldq", X86pmuldq, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecIMul.XMM, 1>; -} - -let Predicates = [HasAVX, NoVLX] in - defm VPMULLD : SS48I_binop_rm<0x40, "vpmulld", mul, v4i32, VR128, - loadv2i64, i128mem, SchedWritePMULLD.XMM, 0>, - VEX_4V, VEX_WIG; -let Predicates = [HasAVX] in - defm VPCMPEQQ : SS48I_binop_rm<0x29, "vpcmpeqq", X86pcmpeq, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2, NoVLX] in - defm VPMULLDY : SS48I_binop_rm<0x40, "vpmulld", mul, v8i32, VR256, - loadv4i64, i256mem, SchedWritePMULLD.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -let Predicates = [HasAVX2] in - defm VPCMPEQQY : SS48I_binop_rm<0x29, "vpcmpeqq", X86pcmpeq, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - -let Constraints = "$src1 = $dst" in { - defm PMULLD : SS48I_binop_rm<0x40, "pmulld", mul, v4i32, VR128, - memopv2i64, i128mem, SchedWritePMULLD.XMM, 1>; - defm PCMPEQQ : SS48I_binop_rm<0x29, "pcmpeqq", X86pcmpeq, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; -} - -/// SS41I_binop_rmi_int - SSE 4.1 binary operator with 8-bit immediate -multiclass SS41I_binop_rmi_int opc, string OpcodeStr, - Intrinsic IntId, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// SS41I_binop_rmi - SSE 4.1 binary operator with 8-bit immediate -multiclass SS41I_binop_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -def BlendCommuteImm2 : SDNodeXFormgetZExtValue() & 0x03; - return getI8Imm(Imm ^ 0x03, SDLoc(N)); -}]>; - -def BlendCommuteImm4 : SDNodeXFormgetZExtValue() & 0x0f; - return getI8Imm(Imm ^ 0x0f, SDLoc(N)); -}]>; - -def BlendCommuteImm8 : SDNodeXFormgetZExtValue() & 0xff; - return getI8Imm(Imm ^ 0xff, SDLoc(N)); -}]>; - -let Predicates = [HasAVX] in { - let isCommutable = 0 in { - defm VMPSADBW : SS41I_binop_rmi_int<0x42, "vmpsadbw", int_x86_sse41_mpsadbw, - VR128, loadv2i64, i128mem, 0, - SchedWriteMPSAD.XMM>, VEX_4V, VEX_WIG; - } - - let ExeDomain = SSEPackedSingle in - defm VDPPS : SS41I_binop_rmi_int<0x40, "vdpps", int_x86_sse41_dpps, - VR128, loadv4f32, f128mem, 0, - SchedWriteDPPS.XMM>, VEX_4V, VEX_WIG; - let ExeDomain = SSEPackedDouble in - defm VDPPD : SS41I_binop_rmi_int<0x41, "vdppd", int_x86_sse41_dppd, - VR128, loadv2f64, f128mem, 0, - SchedWriteDPPD.XMM>, VEX_4V, VEX_WIG; - let ExeDomain = SSEPackedSingle in - defm VDPPSY : SS41I_binop_rmi_int<0x40, "vdpps", int_x86_avx_dp_ps_256, - VR256, loadv8f32, i256mem, 0, - SchedWriteDPPS.YMM>, VEX_4V, VEX_L, VEX_WIG; -} - -let Predicates = [HasAVX2] in { - let isCommutable = 0 in { - defm VMPSADBWY : SS41I_binop_rmi_int<0x42, "vmpsadbw", int_x86_avx2_mpsadbw, - VR256, loadv4i64, i256mem, 0, - SchedWriteMPSAD.YMM>, VEX_4V, VEX_L, VEX_WIG; - } -} - -let Constraints = "$src1 = $dst" in { - let isCommutable = 0 in { - defm MPSADBW : SS41I_binop_rmi_int<0x42, "mpsadbw", int_x86_sse41_mpsadbw, - VR128, memopv2i64, i128mem, 1, - SchedWriteMPSAD.XMM>; - } - - let ExeDomain = SSEPackedSingle in - defm DPPS : SS41I_binop_rmi_int<0x40, "dpps", int_x86_sse41_dpps, - VR128, memopv4f32, f128mem, 1, - SchedWriteDPPS.XMM>; - let ExeDomain = SSEPackedDouble in - defm DPPD : SS41I_binop_rmi_int<0x41, "dppd", int_x86_sse41_dppd, - VR128, memopv2f64, f128mem, 1, - SchedWriteDPPD.XMM>; -} - -/// SS41I_blend_rmi - SSE 4.1 blend with 8-bit immediate -multiclass SS41I_blend_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, Domain d, - X86FoldableSchedWrite sched, SDNodeXForm commuteXForm> { -let ExeDomain = d, Constraints = !if(Is2Addr, "$src1 = $dst", "") in { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - - // Pattern to commute if load is in first source. - def : Pat<(OpVT (OpNode (bitconvert (memop_frag addr:$src2)), - RC:$src1, imm:$src3)), - (!cast(NAME#"rmi") RC:$src1, addr:$src2, - (commuteXForm imm:$src3))>; -} - -let Predicates = [HasAVX] in { - defm VBLENDPS : SS41I_blend_rmi<0x0C, "vblendps", X86Blendi, v4f32, - VR128, loadv4f32, f128mem, 0, SSEPackedSingle, - SchedWriteFBlend.XMM, BlendCommuteImm4>, - VEX_4V, VEX_WIG; - defm VBLENDPSY : SS41I_blend_rmi<0x0C, "vblendps", X86Blendi, v8f32, - VR256, loadv8f32, f256mem, 0, SSEPackedSingle, - SchedWriteFBlend.YMM, BlendCommuteImm8>, - VEX_4V, VEX_L, VEX_WIG; - defm VBLENDPD : SS41I_blend_rmi<0x0D, "vblendpd", X86Blendi, v2f64, - VR128, loadv2f64, f128mem, 0, SSEPackedDouble, - SchedWriteFBlend.XMM, BlendCommuteImm2>, - VEX_4V, VEX_WIG; - defm VBLENDPDY : SS41I_blend_rmi<0x0D, "vblendpd", X86Blendi, v4f64, - VR256, loadv4f64, f256mem, 0, SSEPackedDouble, - SchedWriteFBlend.YMM, BlendCommuteImm4>, - VEX_4V, VEX_L, VEX_WIG; - defm VPBLENDW : SS41I_blend_rmi<0x0E, "vpblendw", X86Blendi, v8i16, - VR128, loadv2i64, i128mem, 0, SSEPackedInt, - SchedWriteBlend.XMM, BlendCommuteImm8>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2] in { - defm VPBLENDWY : SS41I_blend_rmi<0x0E, "vpblendw", X86Blendi, v16i16, - VR256, loadv4i64, i256mem, 0, SSEPackedInt, - SchedWriteBlend.YMM, BlendCommuteImm8>, - VEX_4V, VEX_L, VEX_WIG; -} - -defm BLENDPS : SS41I_blend_rmi<0x0C, "blendps", X86Blendi, v4f32, - VR128, memopv4f32, f128mem, 1, SSEPackedSingle, - SchedWriteFBlend.XMM, BlendCommuteImm4>; -defm BLENDPD : SS41I_blend_rmi<0x0D, "blendpd", X86Blendi, v2f64, - VR128, memopv2f64, f128mem, 1, SSEPackedDouble, - SchedWriteFBlend.XMM, BlendCommuteImm2>; -defm PBLENDW : SS41I_blend_rmi<0x0E, "pblendw", X86Blendi, v8i16, - VR128, memopv2i64, i128mem, 1, SSEPackedInt, - SchedWriteBlend.XMM, BlendCommuteImm8>; - -// For insertion into the zero index (low half) of a 256-bit vector, it is -// more efficient to generate a blend with immediate instead of an insert*128. -let Predicates = [HasAVX] in { -def : Pat<(insert_subvector (v4f64 VR256:$src1), (v2f64 VR128:$src2), (iPTR 0)), - (VBLENDPDYrri VR256:$src1, - (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0x3)>; -def : Pat<(insert_subvector (v8f32 VR256:$src1), (v4f32 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -/// SS41I_quaternary_int_avx - AVX SSE 4.1 with 4 operators -multiclass SS41I_quaternary_int_avx opc, string OpcodeStr, - RegisterClass RC, X86MemOperand x86memop, - PatFrag mem_frag, Intrinsic IntId, - X86FoldableSchedWrite sched> { - def rr : Ii8Reg, TAPD, VEX_4V, - Sched<[sched]>; - - def rm : Ii8Reg, TAPD, VEX_4V, - Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC::$src3 - ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { -let ExeDomain = SSEPackedDouble in { -defm VBLENDVPD : SS41I_quaternary_int_avx<0x4B, "vblendvpd", VR128, f128mem, - loadv2f64, int_x86_sse41_blendvpd, - SchedWriteFVarBlend.XMM>; -defm VBLENDVPDY : SS41I_quaternary_int_avx<0x4B, "vblendvpd", VR256, f256mem, - loadv4f64, int_x86_avx_blendv_pd_256, - SchedWriteFVarBlend.YMM>, VEX_L; -} // ExeDomain = SSEPackedDouble -let ExeDomain = SSEPackedSingle in { -defm VBLENDVPS : SS41I_quaternary_int_avx<0x4A, "vblendvps", VR128, f128mem, - loadv4f32, int_x86_sse41_blendvps, - SchedWriteFVarBlend.XMM>; -defm VBLENDVPSY : SS41I_quaternary_int_avx<0x4A, "vblendvps", VR256, f256mem, - loadv8f32, int_x86_avx_blendv_ps_256, - SchedWriteFVarBlend.YMM>, VEX_L; -} // ExeDomain = SSEPackedSingle -defm VPBLENDVB : SS41I_quaternary_int_avx<0x4C, "vpblendvb", VR128, i128mem, - loadv2i64, int_x86_sse41_pblendvb, - SchedWriteVarBlend.XMM>; -} - -let Predicates = [HasAVX2] in { -defm VPBLENDVBY : SS41I_quaternary_int_avx<0x4C, "vpblendvb", VR256, i256mem, - loadv4i64, int_x86_avx2_pblendvb, - SchedWriteVarBlend.YMM>, VEX_L; -} - -let Predicates = [HasAVX] in { - def : Pat<(v16i8 (vselect (v16i8 VR128:$mask), (v16i8 VR128:$src1), - (v16i8 VR128:$src2))), - (VPBLENDVBrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v4i32 (vselect (v4i32 VR128:$mask), (v4i32 VR128:$src1), - (v4i32 VR128:$src2))), - (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v4f32 (vselect (v4i32 VR128:$mask), (v4f32 VR128:$src1), - (v4f32 VR128:$src2))), - (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v2i64 (vselect (v2i64 VR128:$mask), (v2i64 VR128:$src1), - (v2i64 VR128:$src2))), - (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v2f64 (vselect (v2i64 VR128:$mask), (v2f64 VR128:$src1), - (v2f64 VR128:$src2))), - (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v8i32 (vselect (v8i32 VR256:$mask), (v8i32 VR256:$src1), - (v8i32 VR256:$src2))), - (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v8f32 (vselect (v8i32 VR256:$mask), (v8f32 VR256:$src1), - (v8f32 VR256:$src2))), - (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v4i64 (vselect (v4i64 VR256:$mask), (v4i64 VR256:$src1), - (v4i64 VR256:$src2))), - (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v4f64 (vselect (v4i64 VR256:$mask), (v4f64 VR256:$src1), - (v4f64 VR256:$src2))), - (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>; -} - -let Predicates = [HasAVX2] in { - def : Pat<(v32i8 (vselect (v32i8 VR256:$mask), (v32i8 VR256:$src1), - (v32i8 VR256:$src2))), - (VPBLENDVBYrr VR256:$src2, VR256:$src1, VR256:$mask)>; -} - -// Prefer a movss or movsd over a blendps when optimizing for size. these were -// changed to use blends because blends have better throughput on sandybridge -// and haswell, but movs[s/d] are 1-2 byte shorter instructions. -let Predicates = [HasAVX, OptForSpeed] in { - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (VBLENDPSrri (v4f32 (V_SET0)), VR128:$src, (i8 1))>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (VPBLENDWrri (v4i32 (V_SET0)), VR128:$src, (i8 3))>; - - def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)), - (VBLENDPSrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss VR128:$src1, (loadv4f32 addr:$src2))), - (VBLENDPSrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss (loadv4f32 addr:$src2), VR128:$src1)), - (VBLENDPSrmi VR128:$src1, addr:$src2, (i8 0xe))>; - - def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)), - (VBLENDPDrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd VR128:$src1, (loadv2f64 addr:$src2))), - (VBLENDPDrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd (loadv2f64 addr:$src2), VR128:$src1)), - (VBLENDPDrmi VR128:$src1, addr:$src2, (i8 2))>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VBLENDPSrri (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VPBLENDWrri (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256:$src), sub_xmm)), - (i8 3))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VBLENDPDrri (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VPBLENDWrri (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256:$src), sub_xmm)), - (i8 0xf))), sub_xmm)>; -} - -// Prefer a movss or movsd over a blendps when optimizing for size. these were -// changed to use blends because blends have better throughput on sandybridge -// and haswell, but movs[s/d] are 1-2 byte shorter instructions. -let Predicates = [UseSSE41, OptForSpeed] in { - // With SSE41 we can use blends for these patterns. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (BLENDPSrri (v4f32 (V_SET0)), VR128:$src, (i8 1))>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (PBLENDWrri (v4i32 (V_SET0)), VR128:$src, (i8 3))>; - - def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)), - (BLENDPSrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss VR128:$src1, (memopv4f32 addr:$src2))), - (BLENDPSrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss (memopv4f32 addr:$src2), VR128:$src1)), - (BLENDPSrmi VR128:$src1, addr:$src2, (i8 0xe))>; - - def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)), - (BLENDPDrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd VR128:$src1, (memopv2f64 addr:$src2))), - (BLENDPDrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd (memopv2f64 addr:$src2), VR128:$src1)), - (BLENDPDrmi VR128:$src1, addr:$src2, (i8 2))>; -} - - -/// SS41I_ternary_int - SSE 4.1 ternary operator -let Uses = [XMM0], Constraints = "$src1 = $dst" in { - multiclass SS41I_ternary_int opc, string OpcodeStr, PatFrag mem_frag, - X86MemOperand x86memop, Intrinsic IntId, - X86FoldableSchedWrite sched> { - def rr0 : SS48I, - Sched<[sched]>; - - def rm0 : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let ExeDomain = SSEPackedDouble in -defm BLENDVPD : SS41I_ternary_int<0x15, "blendvpd", memopv2f64, f128mem, - int_x86_sse41_blendvpd, SchedWriteFVarBlend.XMM>; -let ExeDomain = SSEPackedSingle in -defm BLENDVPS : SS41I_ternary_int<0x14, "blendvps", memopv4f32, f128mem, - int_x86_sse41_blendvps, SchedWriteFVarBlend.XMM>; -defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", memopv2i64, i128mem, - int_x86_sse41_pblendvb, SchedWriteVarBlend.XMM>; - -// Aliases with the implicit xmm0 argument -// def : InstAlias<"blendvpd\t{$src2, $dst|$dst, $src2}", -// (BLENDVPDrr0 VR128:$dst, VR128:$src2), 0>; -// def : InstAlias<"blendvpd\t{$src2, $dst|$dst, $src2}", -// (BLENDVPDrm0 VR128:$dst, f128mem:$src2), 0>; -// def : InstAlias<"blendvps\t{$src2, $dst|$dst, $src2}", -// (BLENDVPSrr0 VR128:$dst, VR128:$src2), 0>; -// def : InstAlias<"blendvps\t{$src2, $dst|$dst, $src2}", -// (BLENDVPSrm0 VR128:$dst, f128mem:$src2), 0>; -// def : InstAlias<"pblendvb\t{$src2, $dst|$dst, $src2}", -// (PBLENDVBrr0 VR128:$dst, VR128:$src2), 0>; -// def : InstAlias<"pblendvb\t{$src2, $dst|$dst, $src2}", -// (PBLENDVBrm0 VR128:$dst, i128mem:$src2), 0>; - -let Predicates = [UseSSE41] in { - def : Pat<(v16i8 (vselect (v16i8 XMM0), (v16i8 VR128:$src1), - (v16i8 VR128:$src2))), - (PBLENDVBrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v4i32 (vselect (v4i32 XMM0), (v4i32 VR128:$src1), - (v4i32 VR128:$src2))), - (BLENDVPSrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v4f32 (vselect (v4i32 XMM0), (v4f32 VR128:$src1), - (v4f32 VR128:$src2))), - (BLENDVPSrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v2i64 (vselect (v2i64 XMM0), (v2i64 VR128:$src1), - (v2i64 VR128:$src2))), - (BLENDVPDrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v2f64 (vselect (v2i64 XMM0), (v2f64 VR128:$src1), - (v2f64 VR128:$src2))), - (BLENDVPDrr0 VR128:$src2, VR128:$src1)>; -} - -let AddedComplexity = 400 in { // Prefer non-temporal versions - -let Predicates = [HasAVX, NoVLX] in -def VMOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.XMM.RM]>, VEX, VEX_WIG; -let Predicates = [HasAVX2, NoVLX] in -def VMOVNTDQAYrm : SS48I<0x2A, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.YMM.RM]>, VEX, VEX_L, VEX_WIG; -def MOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.XMM.RM]>; - -let Predicates = [HasAVX2, NoVLX] in { - def : Pat<(v8f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; - def : Pat<(v4f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; - def : Pat<(v4i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; -} - -let Predicates = [UseSSE41] in { - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; -} - -} // AddedComplexity - -//===----------------------------------------------------------------------===// -// SSE4.2 - Compare Instructions -//===----------------------------------------------------------------------===// - -/// SS42I_binop_rm - Simple SSE 4.2 binary operator -multiclass SS42I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - def rr : SS428I, - Sched<[sched]>; - def rm : SS428I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in - defm VPCMPGTQ : SS42I_binop_rm<0x37, "vpcmpgtq", X86pcmpgt, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2] in - defm VPCMPGTQY : SS42I_binop_rm<0x37, "vpcmpgtq", X86pcmpgt, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - -let Constraints = "$src1 = $dst" in - defm PCMPGTQ : SS42I_binop_rm<0x37, "pcmpgtq", X86pcmpgt, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM>; - -//===----------------------------------------------------------------------===// -// SSE4.2 - String/text Processing Instructions -//===----------------------------------------------------------------------===// - -multiclass pcmpistrm_SS42AI { - def rr : SS42AI<0x62, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrM]>; - let mayLoad = 1 in - def rm :SS42AI<0x62, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrM.Folded, ReadAfterLd]>; -} - -let Defs = [XMM0, EFLAGS], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPISTRM : pcmpistrm_SS42AI<"vpcmpistrm">, VEX; - defm PCMPISTRM : pcmpistrm_SS42AI<"pcmpistrm"> ; -} - -multiclass SS42AI_pcmpestrm { - def rr : SS42AI<0x60, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrM]>; - let mayLoad = 1 in - def rm : SS42AI<0x60, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrM.Folded, ReadAfterLd]>; -} - -let Defs = [XMM0, EFLAGS], Uses = [EAX, EDX], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPESTRM : SS42AI_pcmpestrm<"vpcmpestrm">, VEX; - defm PCMPESTRM : SS42AI_pcmpestrm<"pcmpestrm">; -} - -multiclass SS42AI_pcmpistri { - def rr : SS42AI<0x63, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrI]>; - let mayLoad = 1 in - def rm : SS42AI<0x63, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrI.Folded, ReadAfterLd]>; -} - -let Defs = [ECX, EFLAGS], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPISTRI : SS42AI_pcmpistri<"vpcmpistri">, VEX; - defm PCMPISTRI : SS42AI_pcmpistri<"pcmpistri">; -} - -multiclass SS42AI_pcmpestri { - def rr : SS42AI<0x61, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrI]>; - let mayLoad = 1 in - def rm : SS42AI<0x61, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrI.Folded, ReadAfterLd]>; -} - -let Defs = [ECX, EFLAGS], Uses = [EAX, EDX], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPESTRI : SS42AI_pcmpestri<"vpcmpestri">, VEX; - defm PCMPESTRI : SS42AI_pcmpestri<"pcmpestri">; -} - -//===----------------------------------------------------------------------===// -// SSE4.2 - CRC Instructions -//===----------------------------------------------------------------------===// - -// No CRC instructions have AVX equivalents - -// crc intrinsic instruction -// This set of instructions are only rm, the only difference is the size -// of r and m. -class SS42I_crc32r opc, string asm, RegisterClass RCOut, - RegisterClass RCIn, SDPatternOperator Int> : - SS42FI, - Sched<[WriteCRC32]>; - -class SS42I_crc32m opc, string asm, RegisterClass RCOut, - X86MemOperand x86memop, SDPatternOperator Int> : - SS42FI, - Sched<[WriteCRC32.Folded, ReadAfterLd]>; - -let Constraints = "$src1 = $dst" in { - def CRC32r32m8 : SS42I_crc32m<0xF0, "crc32{b}", GR32, i8mem, - int_x86_sse42_crc32_32_8>; - def CRC32r32r8 : SS42I_crc32r<0xF0, "crc32{b}", GR32, GR8, - int_x86_sse42_crc32_32_8>; - def CRC32r32m16 : SS42I_crc32m<0xF1, "crc32{w}", GR32, i16mem, - int_x86_sse42_crc32_32_16>, OpSize16; - def CRC32r32r16 : SS42I_crc32r<0xF1, "crc32{w}", GR32, GR16, - int_x86_sse42_crc32_32_16>, OpSize16; - def CRC32r32m32 : SS42I_crc32m<0xF1, "crc32{l}", GR32, i32mem, - int_x86_sse42_crc32_32_32>, OpSize32; - def CRC32r32r32 : SS42I_crc32r<0xF1, "crc32{l}", GR32, GR32, - int_x86_sse42_crc32_32_32>, OpSize32; - def CRC32r64m64 : SS42I_crc32m<0xF1, "crc32{q}", GR64, i64mem, - int_x86_sse42_crc32_64_64>, REX_W; - def CRC32r64r64 : SS42I_crc32r<0xF1, "crc32{q}", GR64, GR64, - int_x86_sse42_crc32_64_64>, REX_W; - let hasSideEffects = 0 in { - let mayLoad = 1 in - def CRC32r64m8 : SS42I_crc32m<0xF0, "crc32{b}", GR64, i8mem, - null_frag>, REX_W; - def CRC32r64r8 : SS42I_crc32r<0xF0, "crc32{b}", GR64, GR8, - null_frag>, REX_W; - } -} - -//===----------------------------------------------------------------------===// -// SHA-NI Instructions -//===----------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for SHA than WriteVecIMul? -multiclass SHAI_binop Opc, string OpcodeStr, Intrinsic IntId, - X86FoldableSchedWrite sched, bit UsesXMM0 = 0> { - def rr : I, - T8, Sched<[sched]>; - - def rm : I, T8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", Predicates = [HasSHA] in { - def SHA1RNDS4rri : Ii8<0xCC, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - "sha1rnds4\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_sha1rnds4 VR128:$src1, VR128:$src2, - (i8 imm:$src3)))]>, TA, - Sched<[SchedWriteVecIMul.XMM]>; - def SHA1RNDS4rmi : Ii8<0xCC, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - "sha1rnds4\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_sha1rnds4 VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2)), - (i8 imm:$src3)))]>, TA, - Sched<[SchedWriteVecIMul.XMM.Folded, ReadAfterLd]>; - - defm SHA1NEXTE : SHAI_binop<0xC8, "sha1nexte", int_x86_sha1nexte, - SchedWriteVecIMul.XMM>; - defm SHA1MSG1 : SHAI_binop<0xC9, "sha1msg1", int_x86_sha1msg1, - SchedWriteVecIMul.XMM>; - defm SHA1MSG2 : SHAI_binop<0xCA, "sha1msg2", int_x86_sha1msg2, - SchedWriteVecIMul.XMM>; - - let Uses=[XMM0] in - defm SHA256RNDS2 : SHAI_binop<0xCB, "sha256rnds2", int_x86_sha256rnds2, - SchedWriteVecIMul.XMM, 1>; - - defm SHA256MSG1 : SHAI_binop<0xCC, "sha256msg1", int_x86_sha256msg1, - SchedWriteVecIMul.XMM>; - defm SHA256MSG2 : SHAI_binop<0xCD, "sha256msg2", int_x86_sha256msg2, - SchedWriteVecIMul.XMM>; -} - -// Aliases with explicit %xmm0 -// def : InstAlias<"sha256rnds2\t{$src2, $dst|$dst, $src2}", -// (SHA256RNDS2rr VR128:$dst, VR128:$src2), 0>; -// def : InstAlias<"sha256rnds2\t{$src2, $dst|$dst, $src2}", -// (SHA256RNDS2rm VR128:$dst, i128mem:$src2), 0>; - -//===----------------------------------------------------------------------===// -// AES-NI Instructions -//===----------------------------------------------------------------------===// - -multiclass AESI_binop_rm_int opc, string OpcodeStr, - Intrinsic IntId, PatFrag ld_frag, - bit Is2Addr = 0, RegisterClass RC = VR128, - X86MemOperand MemOp = i128mem> { - let AsmString = OpcodeStr## - !if(Is2Addr, "\t{$src2, $dst|$dst, $src2}", - "\t{$src2, $src1, $dst|$dst, $src1, $src2}") in { - def rr : AES8I, - Sched<[WriteAESDecEnc]>; - def rm : AES8I, - Sched<[WriteAESDecEnc.Folded, ReadAfterLd]>; - } -} - -// Perform One Round of an AES Encryption/Decryption Flow -let Predicates = [HasAVX, NoVLX_Or_NoVAES, HasAES] in { - defm VAESENC : AESI_binop_rm_int<0xDC, "vaesenc", - int_x86_aesni_aesenc, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESENCLAST : AESI_binop_rm_int<0xDD, "vaesenclast", - int_x86_aesni_aesenclast, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESDEC : AESI_binop_rm_int<0xDE, "vaesdec", - int_x86_aesni_aesdec, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESDECLAST : AESI_binop_rm_int<0xDF, "vaesdeclast", - int_x86_aesni_aesdeclast, loadv2i64>, VEX_4V, VEX_WIG; -} - -let Predicates = [NoVLX, HasVAES] in { - defm VAESENCY : AESI_binop_rm_int<0xDC, "vaesenc", - int_x86_aesni_aesenc_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESENCLASTY : AESI_binop_rm_int<0xDD, "vaesenclast", - int_x86_aesni_aesenclast_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESDECY : AESI_binop_rm_int<0xDE, "vaesdec", - int_x86_aesni_aesdec_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESDECLASTY : AESI_binop_rm_int<0xDF, "vaesdeclast", - int_x86_aesni_aesdeclast_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm AESENC : AESI_binop_rm_int<0xDC, "aesenc", - int_x86_aesni_aesenc, memopv2i64, 1>; - defm AESENCLAST : AESI_binop_rm_int<0xDD, "aesenclast", - int_x86_aesni_aesenclast, memopv2i64, 1>; - defm AESDEC : AESI_binop_rm_int<0xDE, "aesdec", - int_x86_aesni_aesdec, memopv2i64, 1>; - defm AESDECLAST : AESI_binop_rm_int<0xDF, "aesdeclast", - int_x86_aesni_aesdeclast, memopv2i64, 1>; -} - -// Perform the AES InvMixColumn Transformation -let Predicates = [HasAVX, HasAES] in { - def VAESIMCrr : AES8I<0xDB, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1), - "vaesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, - (int_x86_aesni_aesimc VR128:$src1))]>, Sched<[WriteAESIMC]>, - VEX, VEX_WIG; - def VAESIMCrm : AES8I<0xDB, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1), - "vaesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, (int_x86_aesni_aesimc (loadv2i64 addr:$src1)))]>, - Sched<[WriteAESIMC.Folded]>, VEX, VEX_WIG; -} -def AESIMCrr : AES8I<0xDB, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1), - "aesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, - (int_x86_aesni_aesimc VR128:$src1))]>, Sched<[WriteAESIMC]>; -def AESIMCrm : AES8I<0xDB, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1), - "aesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, (int_x86_aesni_aesimc (memopv2i64 addr:$src1)))]>, - Sched<[WriteAESIMC.Folded]>; - -// AES Round Key Generation Assist -let Predicates = [HasAVX, HasAES] in { - def VAESKEYGENASSIST128rr : AESAI<0xDF, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - "vaeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist VR128:$src1, imm:$src2))]>, - Sched<[WriteAESKeyGen]>, VEX, VEX_WIG; - def VAESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - "vaeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist (loadv2i64 addr:$src1), imm:$src2))]>, - Sched<[WriteAESKeyGen.Folded]>, VEX, VEX_WIG; -} -def AESKEYGENASSIST128rr : AESAI<0xDF, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - "aeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist VR128:$src1, imm:$src2))]>, - Sched<[WriteAESKeyGen]>; -def AESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - "aeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist (memopv2i64 addr:$src1), imm:$src2))]>, - Sched<[WriteAESKeyGen.Folded]>; - -//===----------------------------------------------------------------------===// -// PCLMUL Instructions -//===----------------------------------------------------------------------===// - -// Immediate transform to help with commuting. -def PCLMULCommuteImm : SDNodeXFormgetZExtValue(); - return getI8Imm((uint8_t)((Imm >> 4) | (Imm << 4)), SDLoc(N)); -}]>; - -// SSE carry-less Multiplication instructions -let Predicates = [NoAVX, HasPCLMUL] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = 1 in - def PCLMULQDQrr : PCLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_pclmulqdq VR128:$src1, VR128:$src2, imm:$src3))]>, - Sched<[WriteCLMul]>; - - def PCLMULQDQrm : PCLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_pclmulqdq VR128:$src1, (memopv2i64 addr:$src2), - imm:$src3))]>, - Sched<[WriteCLMul.Folded, ReadAfterLd]>; - } // Constraints = "$src1 = $dst" - - def : Pat<(int_x86_pclmulqdq (memopv2i64 addr:$src2), VR128:$src1, - (i8 imm:$src3)), - (PCLMULQDQrm VR128:$src1, addr:$src2, - (PCLMULCommuteImm imm:$src3))>; -} // Predicates = [NoAVX, HasPCLMUL] - -// SSE aliases -foreach HI = ["hq","lq"] in -foreach LO = ["hq","lq"] in { - // def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - // (PCLMULQDQrr VR128:$dst, VR128:$src, - // !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; - // def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - // (PCLMULQDQrm VR128:$dst, i128mem:$src, - // !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; -} - -// AVX carry-less Multiplication instructions -multiclass vpclmulqdq { - let isCommutable = 1 in - def rr : PCLMULIi8<0x44, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, RC:$src2, imm:$src3))]>, - Sched<[WriteCLMul]>; - - def rm : PCLMULIi8<0x44, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, MemOp:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, (LdFrag addr:$src2), imm:$src3))]>, - Sched<[WriteCLMul.Folded, ReadAfterLd]>; - - // We can commute a load in the first operand by swapping the sources and - // rotating the immediate. - def : Pat<(IntId (LdFrag addr:$src2), RC:$src1, (i8 imm:$src3)), - (!cast(NAME#"rm") RC:$src1, addr:$src2, - (PCLMULCommuteImm imm:$src3))>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoVPCLMULQDQ, HasPCLMUL] in -defm VPCLMULQDQ : vpclmulqdq, VEX_4V, VEX_WIG; - -let Predicates = [NoVLX, HasVPCLMULQDQ] in -defm VPCLMULQDQY : vpclmulqdq, VEX_4V, VEX_L, VEX_WIG; - -/* -multiclass vpclmulqdq_aliases_impl { - // def : InstAlias<"vpclmul"##Hi##Lo##"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - // (!cast(InstStr # "rr") RC:$dst, RC:$src1, RC:$src2, - // !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; - // def : InstAlias<"vpclmul"##Hi##Lo##"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - // (!cast(InstStr # "rm") RC:$dst, RC:$src1, MemOp:$src2, - // !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; -} - -multiclass vpclmulqdq_aliases { - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; -} - -// AVX aliases -defm : vpclmulqdq_aliases<"VPCLMULQDQ", VR128, i128mem>; -defm : vpclmulqdq_aliases<"VPCLMULQDQY", VR256, i256mem>; -*/ - -//===----------------------------------------------------------------------===// -// SSE4A Instructions -//===----------------------------------------------------------------------===// - -let Predicates = [HasSSE4A] in { - -let ExeDomain = SSEPackedInt in { -let Constraints = "$src = $dst" in { -def EXTRQI : Ii8<0x78, MRMXr, (outs VR128:$dst), - (ins VR128:$src, u8imm:$len, u8imm:$idx), - "extrq\t{$idx, $len, $src|$src, $len, $idx}", - [(set VR128:$dst, (X86extrqi VR128:$src, imm:$len, - imm:$idx))]>, - PD, Sched<[SchedWriteVecALU.XMM]>; -def EXTRQ : I<0x79, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$mask), - "extrq\t{$mask, $src|$src, $mask}", - [(set VR128:$dst, (int_x86_sse4a_extrq VR128:$src, - VR128:$mask))]>, - PD, Sched<[SchedWriteVecALU.XMM]>; - -def INSERTQI : Ii8<0x78, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$src2, u8imm:$len, u8imm:$idx), - "insertq\t{$idx, $len, $src2, $src|$src, $src2, $len, $idx}", - [(set VR128:$dst, (X86insertqi VR128:$src, VR128:$src2, - imm:$len, imm:$idx))]>, - XD, Sched<[SchedWriteVecALU.XMM]>; -def INSERTQ : I<0x79, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$mask), - "insertq\t{$mask, $src|$src, $mask}", - [(set VR128:$dst, (int_x86_sse4a_insertq VR128:$src, - VR128:$mask))]>, - XD, Sched<[SchedWriteVecALU.XMM]>; -} -} // ExeDomain = SSEPackedInt - -// Non-temporal (unaligned) scalar stores. -let AddedComplexity = 400 in { // Prefer non-temporal versions -let hasSideEffects = 0, mayStore = 1, SchedRW = [SchedWriteFMoveLSNT.Scl.MR] in { -def MOVNTSS : I<0x2B, MRMDestMem, (outs), (ins f32mem:$dst, VR128:$src), - "movntss\t{$src, $dst|$dst, $src}", []>, XS; - -def MOVNTSD : I<0x2B, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movntsd\t{$src, $dst|$dst, $src}", []>, XD; -} // SchedRW - -def : Pat<(nontemporalstore FR32:$src, addr:$dst), - (MOVNTSS addr:$dst, (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - -def : Pat<(nontemporalstore FR64:$src, addr:$dst), - (MOVNTSD addr:$dst, (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; - -} // AddedComplexity -} // HasSSE4A - -//===----------------------------------------------------------------------===// -// AVX Instructions -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// VBROADCAST - Load from memory and broadcast to all elements of the -// destination operand -// -class avx_broadcast_rm opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType VT, - PatFrag ld_frag, SchedWrite Sched> : - AVX8I, - Sched<[Sched]>, VEX; - -// AVX2 adds register forms -class avx2_broadcast_rr opc, string OpcodeStr, RegisterClass RC, - ValueType ResVT, ValueType OpVT, SchedWrite Sched> : - AVX28I, - Sched<[Sched]>, VEX; - -let ExeDomain = SSEPackedSingle, Predicates = [HasAVX, NoVLX] in { - def VBROADCASTSSrm : avx_broadcast_rm<0x18, "vbroadcastss", VR128, - f32mem, v4f32, loadf32, - SchedWriteFShuffle.XMM.Folded>; - def VBROADCASTSSYrm : avx_broadcast_rm<0x18, "vbroadcastss", VR256, - f32mem, v8f32, loadf32, - SchedWriteFShuffle.XMM.Folded>, VEX_L; -} -let ExeDomain = SSEPackedDouble, Predicates = [HasAVX, NoVLX] in -def VBROADCASTSDYrm : avx_broadcast_rm<0x19, "vbroadcastsd", VR256, f64mem, - v4f64, loadf64, - SchedWriteFShuffle.XMM.Folded>, VEX_L; - -let ExeDomain = SSEPackedSingle, Predicates = [HasAVX2, NoVLX] in { - def VBROADCASTSSrr : avx2_broadcast_rr<0x18, "vbroadcastss", VR128, - v4f32, v4f32, SchedWriteFShuffle.XMM>; - def VBROADCASTSSYrr : avx2_broadcast_rr<0x18, "vbroadcastss", VR256, - v8f32, v4f32, WriteFShuffle256>, VEX_L; -} -let ExeDomain = SSEPackedDouble, Predicates = [HasAVX2, NoVLX] in -def VBROADCASTSDYrr : avx2_broadcast_rr<0x19, "vbroadcastsd", VR256, - v4f64, v2f64, WriteFShuffle256>, VEX_L; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (X86VBroadcast (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (VBROADCASTSSrm addr:$src)>; - def : Pat<(v8f32 (X86VBroadcast (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (VBROADCASTSSYrm addr:$src)>; - def : Pat<(v4f64 (X86VBroadcast (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (VBROADCASTSDYrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VBROADCAST*128 - Load from memory and broadcast 128-bit vector to both -// halves of a 256-bit vector. -// -let mayLoad = 1, hasSideEffects = 0, Predicates = [HasAVX2] in -def VBROADCASTI128 : AVX8I<0x5A, MRMSrcMem, (outs VR256:$dst), - (ins i128mem:$src), - "vbroadcasti128\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteShuffleLd]>, VEX, VEX_L; - -let mayLoad = 1, hasSideEffects = 0, Predicates = [HasAVX], - ExeDomain = SSEPackedSingle in -def VBROADCASTF128 : AVX8I<0x1A, MRMSrcMem, (outs VR256:$dst), - (ins f128mem:$src), - "vbroadcastf128\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteFShuffle.XMM.Folded]>, VEX, VEX_L; - -let Predicates = [HasAVX2, NoVLX] in { -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { -def : Pat<(v4f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v8f32 (X86SubVBroadcast (loadv4f32 addr:$src))), - (VBROADCASTF128 addr:$src)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VINSERTF128 - Insert packed floating-point values -// -let hasSideEffects = 0, ExeDomain = SSEPackedSingle in { -def VINSERTF128rr : AVXAIi8<0x18, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR128:$src2, u8imm:$src3), - "vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteFShuffle256]>, VEX_4V, VEX_L; -let mayLoad = 1 in -def VINSERTF128rm : AVXAIi8<0x18, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f128mem:$src2, u8imm:$src3), - "vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteFShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; -} - -// To create a 256-bit all ones value, we should produce VCMPTRUEPS -// with YMM register containing zero. -// FIXME: Avoid producing vxorps to clear the fake inputs. -let Predicates = [HasAVX1Only] in { -def : Pat<(v8i32 immAllOnesV), (VCMPPSYrri (AVX_SET0), (AVX_SET0), 0xf)>; -} - -multiclass vinsert_lowering { - def : Pat<(vinsert128_insert:$ins (To VR256:$src1), (From VR128:$src2), - (iPTR imm)), - (!cast(InstrStr#rr) VR256:$src1, VR128:$src2, - (INSERT_get_vinsert128_imm VR256:$ins))>; - def : Pat<(vinsert128_insert:$ins (To VR256:$src1), - (From (bitconvert (memop_frag addr:$src2))), - (iPTR imm)), - (!cast(InstrStr#rm) VR256:$src1, addr:$src2, - (INSERT_get_vinsert128_imm VR256:$ins))>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : vinsert_lowering<"VINSERTF128", v4f32, v8f32, loadv4f32>; - defm : vinsert_lowering<"VINSERTF128", v2f64, v4f64, loadv2f64>; -} - -let Predicates = [HasAVX1Only] in { - defm : vinsert_lowering<"VINSERTF128", v2i64, v4i64, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v4i32, v8i32, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v8i16, v16i16, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v16i8, v32i8, loadv2i64>; -} - -//===----------------------------------------------------------------------===// -// VEXTRACTF128 - Extract packed floating-point values -// -let hasSideEffects = 0, ExeDomain = SSEPackedSingle in { -def VEXTRACTF128rr : AVXAIi8<0x19, MRMDestReg, (outs VR128:$dst), - (ins VR256:$src1, u8imm:$src2), - "vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, Sched<[WriteFShuffle256]>, VEX, VEX_L; -let mayStore = 1 in -def VEXTRACTF128mr : AVXAIi8<0x19, MRMDestMem, (outs), - (ins f128mem:$dst, VR256:$src1, u8imm:$src2), - "vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, Sched<[WriteFStoreX]>, VEX, VEX_L; -} - -multiclass vextract_lowering { - def : Pat<(vextract128_extract:$ext VR256:$src1, (iPTR imm)), - (To (!cast(InstrStr#rr) - (From VR256:$src1), - (EXTRACT_get_vextract128_imm VR128:$ext)))>; - def : Pat<(store (To (vextract128_extract:$ext (From VR256:$src1), - (iPTR imm))), addr:$dst), - (!cast(InstrStr#mr) addr:$dst, VR256:$src1, - (EXTRACT_get_vextract128_imm VR128:$ext))>; -} - -// AVX1 patterns -let Predicates = [HasAVX, NoVLX] in { - defm : vextract_lowering<"VEXTRACTF128", v8f32, v4f32>; - defm : vextract_lowering<"VEXTRACTF128", v4f64, v2f64>; -} - -let Predicates = [HasAVX1Only] in { - defm : vextract_lowering<"VEXTRACTF128", v4i64, v2i64>; - defm : vextract_lowering<"VEXTRACTF128", v8i32, v4i32>; - defm : vextract_lowering<"VEXTRACTF128", v16i16, v8i16>; - defm : vextract_lowering<"VEXTRACTF128", v32i8, v16i8>; -} - -//===----------------------------------------------------------------------===// -// VMASKMOV - Conditional SIMD Packed Loads and Stores -// -multiclass avx_movmask_rm opc_rm, bits<8> opc_mr, string OpcodeStr, - Intrinsic IntLd, Intrinsic IntLd256, - Intrinsic IntSt, Intrinsic IntSt256> { - def rm : AVX8I, - VEX_4V, Sched<[WriteFMaskedLoad]>; - def Yrm : AVX8I, - VEX_4V, VEX_L, Sched<[WriteFMaskedLoadY]>; - def mr : AVX8I, - VEX_4V, Sched<[WriteFMaskedStore]>; - def Ymr : AVX8I, - VEX_4V, VEX_L, Sched<[WriteFMaskedStoreY]>; -} - -let ExeDomain = SSEPackedSingle in -defm VMASKMOVPS : avx_movmask_rm<0x2C, 0x2E, "vmaskmovps", - int_x86_avx_maskload_ps, - int_x86_avx_maskload_ps_256, - int_x86_avx_maskstore_ps, - int_x86_avx_maskstore_ps_256>; -let ExeDomain = SSEPackedDouble in -defm VMASKMOVPD : avx_movmask_rm<0x2D, 0x2F, "vmaskmovpd", - int_x86_avx_maskload_pd, - int_x86_avx_maskload_pd_256, - int_x86_avx_maskstore_pd, - int_x86_avx_maskstore_pd_256>; - -//===----------------------------------------------------------------------===// -// VPERMIL - Permute Single and Double Floating-Point Values -// - -multiclass avx_permil opc_rm, bits<8> opc_rmi, string OpcodeStr, - RegisterClass RC, X86MemOperand x86memop_f, - X86MemOperand x86memop_i, PatFrag i_frag, - ValueType f_vt, ValueType i_vt, - X86FoldableSchedWrite sched, - X86FoldableSchedWrite varsched> { - let Predicates = [HasAVX, NoVLX] in { - def rr : AVX8I, VEX_4V, - Sched<[varsched]>; - def rm : AVX8I, VEX_4V, - Sched<[varsched.Folded, ReadAfterLd]>; - - def ri : AVXAIi8, VEX, - Sched<[sched]>; - def mi : AVXAIi8, VEX, - Sched<[sched.Folded]>; - }// Predicates = [HasAVX, NoVLX] -} - -let ExeDomain = SSEPackedSingle in { - defm VPERMILPS : avx_permil<0x0C, 0x04, "vpermilps", VR128, f128mem, i128mem, - loadv2i64, v4f32, v4i32, SchedWriteFShuffle.XMM, - SchedWriteFVarShuffle.XMM>; - defm VPERMILPSY : avx_permil<0x0C, 0x04, "vpermilps", VR256, f256mem, i256mem, - loadv4i64, v8f32, v8i32, SchedWriteFShuffle.YMM, - SchedWriteFVarShuffle.YMM>, VEX_L; -} -let ExeDomain = SSEPackedDouble in { - defm VPERMILPD : avx_permil<0x0D, 0x05, "vpermilpd", VR128, f128mem, i128mem, - loadv2i64, v2f64, v2i64, SchedWriteFShuffle.XMM, - SchedWriteFVarShuffle.XMM>; - defm VPERMILPDY : avx_permil<0x0D, 0x05, "vpermilpd", VR256, f256mem, i256mem, - loadv4i64, v4f64, v4i64, SchedWriteFShuffle.YMM, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - -//===----------------------------------------------------------------------===// -// VPERM2F128 - Permute Floating-Point Values in 128-bit chunks -// - -let ExeDomain = SSEPackedSingle in { -let isCommutable = 1 in -def VPERM2F128rr : AVXAIi8<0x06, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR256:$src2, u8imm:$src3), - "vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (v4f64 (X86VPerm2x128 VR256:$src1, VR256:$src2, - (i8 imm:$src3))))]>, VEX_4V, VEX_L, - Sched<[WriteFShuffle256]>; -def VPERM2F128rm : AVXAIi8<0x06, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f256mem:$src2, u8imm:$src3), - "vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (X86VPerm2x128 VR256:$src1, (loadv4f64 addr:$src2), - (i8 imm:$src3)))]>, VEX_4V, VEX_L, - Sched<[WriteFShuffle256Ld, ReadAfterLd]>; -} - -// Immediate transform to help with commuting. -def Perm2XCommuteImm : SDNodeXFormgetZExtValue() ^ 0x22, SDLoc(N)); -}]>; - -let Predicates = [HasAVX] in { -// Pattern with load in other operand. -def : Pat<(v4f64 (X86VPerm2x128 (loadv4f64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86VPerm2x128 VR256:$src1, VR256:$src2, (i8 imm:$imm))), - (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>; -def : Pat<(v4i64 (X86VPerm2x128 VR256:$src1, - (loadv4i64 addr:$src2), (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, imm:$imm)>; -// Pattern with load in other operand. -def : Pat<(v4i64 (X86VPerm2x128 (loadv4i64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; -} - -//===----------------------------------------------------------------------===// -// VZERO - Zero YMM registers -// Note: These instruction do not affect the YMM16-YMM31. -// - -let SchedRW = [WriteSystem] in { -let Defs = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, - YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15] in { - // Zero All YMM registers - def VZEROALL : I<0x77, RawFrm, (outs), (ins), "vzeroall", - [(int_x86_avx_vzeroall)]>, PS, VEX, VEX_L, - Requires<[HasAVX]>, VEX_WIG; - - // Zero Upper bits of YMM registers - def VZEROUPPER : I<0x77, RawFrm, (outs), (ins), "vzeroupper", - [(int_x86_avx_vzeroupper)]>, PS, VEX, - Requires<[HasAVX]>, VEX_WIG; -} // Defs -} // SchedRW - -//===----------------------------------------------------------------------===// -// Half precision conversion instructions -// - -multiclass f16c_ph2ps { - def rr : I<0x13, MRMSrcReg, (outs RC:$dst), (ins VR128:$src), - "vcvtph2ps\t{$src, $dst|$dst, $src}", - [(set RC:$dst, (X86cvtph2ps VR128:$src))]>, - T8PD, VEX, Sched<[sched]>; - let hasSideEffects = 0, mayLoad = 1 in - def rm : I<0x13, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - "vcvtph2ps\t{$src, $dst|$dst, $src}", - [(set RC:$dst, (X86cvtph2ps (bc_v8i16 - (loadv2i64 addr:$src))))]>, - T8PD, VEX, Sched<[sched.Folded]>; -} - -multiclass f16c_ps2ph { - def rr : Ii8<0x1D, MRMDestReg, (outs VR128:$dst), - (ins RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (X86cvtps2ph RC:$src1, imm:$src2))]>, - TAPD, VEX, Sched<[RR]>; - let hasSideEffects = 0, mayStore = 1 in - def mr : Ii8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - TAPD, VEX, Sched<[MR]>; -} - -let Predicates = [HasF16C, NoVLX] in { - defm VCVTPH2PS : f16c_ph2ps; - defm VCVTPH2PSY : f16c_ph2ps, VEX_L; - defm VCVTPS2PH : f16c_ps2ph; - defm VCVTPS2PHY : f16c_ps2ph, VEX_L; - - // Pattern match vcvtph2ps of a scalar i64 load. - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzmovl_v2i64 addr:$src)))), - (VCVTPH2PSrm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzload_v2i64 addr:$src)))), - (VCVTPH2PSrm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (bitconvert - (v2i64 (scalar_to_vector (loadi64 addr:$src))))))), - (VCVTPH2PSrm addr:$src)>; - - def : Pat<(store (f64 (extractelt - (bc_v2f64 (v8i16 (X86cvtps2ph VR128:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHmr addr:$dst, VR128:$src1, imm:$src2)>; - def : Pat<(store (i64 (extractelt - (bc_v2i64 (v8i16 (X86cvtps2ph VR128:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHmr addr:$dst, VR128:$src1, imm:$src2)>; - def : Pat<(store (v8i16 (X86cvtps2ph VR256:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHYmr addr:$dst, VR256:$src1, imm:$src2)>; -} - -// Patterns for matching conversions from float to half-float and vice versa. -let Predicates = [HasF16C, NoVLX] in { - // Use MXCSR.RC for rounding instead of explicitly specifying the default - // rounding mode (Nearest-Even, encoded as 0). Both are equivalent in the - // configurations we support (the default). However, falling back to MXCSR is - // more consistent with other instructions, which are always controlled by it. - // It's encoded as 0b100. - def : Pat<(fp_to_f16 FR32:$src), - (i16 (EXTRACT_SUBREG (VMOVPDI2DIrr (v8i16 (VCVTPS2PHrr - (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 4))), sub_16bit))>; - - def : Pat<(f16_to_fp GR16:$src), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSrr - (v4i32 (COPY_TO_REGCLASS (MOVSX32rr16 GR16:$src), VR128)))), FR32)) >; - - def : Pat<(f16_to_fp (i16 (fp_to_f16 FR32:$src))), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSrr - (v8i16 (VCVTPS2PHrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 4)))), FR32)) >; -} - -//===----------------------------------------------------------------------===// -// AVX2 Instructions -//===----------------------------------------------------------------------===// - -/// AVX2_blend_rmi - AVX2 blend with 8-bit immediate -multiclass AVX2_blend_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, X86FoldableSchedWrite sched, - RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, SDNodeXForm commuteXForm> { - let isCommutable = 1 in - def rri : AVX2AIi8, - Sched<[sched]>, VEX_4V; - def rmi : AVX2AIi8, - Sched<[sched.Folded, ReadAfterLd]>, VEX_4V; - - // Pattern to commute if load is in first source. - def : Pat<(OpVT (OpNode (bitconvert (memop_frag addr:$src2)), - RC:$src1, imm:$src3)), - (!cast(NAME#"rmi") RC:$src1, addr:$src2, - (commuteXForm imm:$src3))>; -} - -defm VPBLENDD : AVX2_blend_rmi<0x02, "vpblendd", X86Blendi, v4i32, - SchedWriteBlend.XMM, VR128, loadv2i64, i128mem, - BlendCommuteImm4>; -defm VPBLENDDY : AVX2_blend_rmi<0x02, "vpblendd", X86Blendi, v8i32, - SchedWriteBlend.YMM, VR256, loadv4i64, i256mem, - BlendCommuteImm8>, VEX_L; - -// For insertion into the zero index (low half) of a 256-bit vector, it is -// more efficient to generate a blend with immediate instead of an insert*128. -let Predicates = [HasAVX2] in { -def : Pat<(insert_subvector (v8i32 VR256:$src1), (v4i32 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v4i64 VR256:$src1), (v2i64 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v16i16 VR256:$src1), (v8i16 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v32i8 VR256:$src1), (v16i8 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(insert_subvector (v8i32 VR256:$src1), (v4i32 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v4i64 VR256:$src1), (v2i64 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v16i16 VR256:$src1), (v8i16 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v32i8 VR256:$src1), (v16i8 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -//===----------------------------------------------------------------------===// -// VPBROADCAST - Load from memory and broadcast to all elements of the -// destination operand -// -multiclass avx2_broadcast opc, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - ValueType OpVT128, ValueType OpVT256, Predicate prd> { - let Predicates = [HasAVX2, prd] in { - def rr : AVX28I, - Sched<[SchedWriteShuffle.XMM]>, VEX; - def rm : AVX28I, - Sched<[SchedWriteShuffle.XMM.Folded]>, VEX; - def Yrr : AVX28I, - Sched<[WriteShuffle256]>, VEX, VEX_L; - def Yrm : AVX28I, - Sched<[SchedWriteShuffle.XMM.Folded]>, VEX, VEX_L; - - // Provide aliases for broadcast from the same register class that - // automatically does the extract. - def : Pat<(OpVT256 (X86VBroadcast (OpVT256 VR256:$src))), - (!cast(NAME#"Yrr") - (OpVT128 (EXTRACT_SUBREG (OpVT256 VR256:$src),sub_xmm)))>; - } -} - -defm VPBROADCASTB : avx2_broadcast<0x78, "vpbroadcastb", i8mem, loadi8, - v16i8, v32i8, NoVLX_Or_NoBWI>; -defm VPBROADCASTW : avx2_broadcast<0x79, "vpbroadcastw", i16mem, loadi16, - v8i16, v16i16, NoVLX_Or_NoBWI>; -defm VPBROADCASTD : avx2_broadcast<0x58, "vpbroadcastd", i32mem, loadi32, - v4i32, v8i32, NoVLX>; -defm VPBROADCASTQ : avx2_broadcast<0x59, "vpbroadcastq", i64mem, loadi64, - v2i64, v4i64, NoVLX>; - -let Predicates = [HasAVX2, NoVLX] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v2i64 (X86VBroadcast (v2i64 (X86vzload addr:$src)))), - (VPBROADCASTQrm addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v4i64 (X86vzload addr:$src)))), - (VPBROADCASTQYrm addr:$src)>; - - def : Pat<(v4i32 (X86VBroadcast (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VPBROADCASTDrm addr:$src)>; - def : Pat<(v8i32 (X86VBroadcast (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VPBROADCASTDYrm addr:$src)>; - def : Pat<(v2i64 (X86VBroadcast (v2i64 (scalar_to_vector (loadi64 addr:$src))))), - (VPBROADCASTQrm addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v2i64 (scalar_to_vector (loadi64 addr:$src))))), - (VPBROADCASTQYrm addr:$src)>; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - // loadi16 is tricky to fold, because !isTypeDesirableForOp, justifiably. - // This means we'll encounter truncated i32 loads; match that here. - def : Pat<(v8i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWrm addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWYrm addr:$src)>; - def : Pat<(v8i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWrm addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWYrm addr:$src)>; -} - -let Predicates = [HasAVX2, NoVLX] in { - // Provide aliases for broadcast from the same register class that - // automatically does the extract. - def : Pat<(v8f32 (X86VBroadcast (v8f32 VR256:$src))), - (VBROADCASTSSYrr (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), - sub_xmm)))>; - def : Pat<(v4f64 (X86VBroadcast (v4f64 VR256:$src))), - (VBROADCASTSDYrr (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), - sub_xmm)))>; -} - -let Predicates = [HasAVX2, NoVLX] in { - // Provide fallback in case the load node that is used in the patterns above - // is used by additional users, which prevents the pattern selection. - def : Pat<(v4f32 (X86VBroadcast FR32:$src)), - (VBROADCASTSSrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - def : Pat<(v8f32 (X86VBroadcast FR32:$src)), - (VBROADCASTSSYrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - def : Pat<(v4f64 (X86VBroadcast FR64:$src)), - (VBROADCASTSDYrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - def : Pat<(v16i8 (X86VBroadcast GR8:$src)), - (VPBROADCASTBrr (v16i8 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR8:$src, sub_8bit)), - VR128)))>; - def : Pat<(v32i8 (X86VBroadcast GR8:$src)), - (VPBROADCASTBYrr (v16i8 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR8:$src, sub_8bit)), - VR128)))>; - - def : Pat<(v8i16 (X86VBroadcast GR16:$src)), - (VPBROADCASTWrr (v8i16 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR16:$src, sub_16bit)), - VR128)))>; - def : Pat<(v16i16 (X86VBroadcast GR16:$src)), - (VPBROADCASTWYrr (v8i16 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR16:$src, sub_16bit)), - VR128)))>; -} -let Predicates = [HasAVX2, NoVLX] in { - def : Pat<(v4i32 (X86VBroadcast GR32:$src)), - (VPBROADCASTDrr (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)))>; - def : Pat<(v8i32 (X86VBroadcast GR32:$src)), - (VPBROADCASTDYrr (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)))>; - def : Pat<(v2i64 (X86VBroadcast GR64:$src)), - (VPBROADCASTQrr (v2i64 (COPY_TO_REGCLASS GR64:$src, VR128)))>; - def : Pat<(v4i64 (X86VBroadcast GR64:$src)), - (VPBROADCASTQYrr (v2i64 (COPY_TO_REGCLASS GR64:$src, VR128)))>; -} - -// AVX1 broadcast patterns -let Predicates = [HasAVX1Only] in { -def : Pat<(v8i32 (X86VBroadcast (loadi32 addr:$src))), - (VBROADCASTSSYrm addr:$src)>; -def : Pat<(v4i64 (X86VBroadcast (loadi64 addr:$src))), - (VBROADCASTSDYrm addr:$src)>; -def : Pat<(v4i32 (X86VBroadcast (loadi32 addr:$src))), - (VBROADCASTSSrm addr:$src)>; -} - - // Provide fallback in case the load node that is used in the patterns above - // is used by additional users, which prevents the pattern selection. -let Predicates = [HasAVX, NoVLX] in { - // 128bit broadcasts: - def : Pat<(v2f64 (X86VBroadcast f64:$src)), - (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; - def : Pat<(v2f64 (X86VBroadcast (loadf64 addr:$src))), - (VMOVDDUPrm addr:$src)>; - - def : Pat<(v2f64 (X86VBroadcast v2f64:$src)), - (VMOVDDUPrr VR128:$src)>; - def : Pat<(v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (VMOVDDUPrm addr:$src)>; -} - -let Predicates = [HasAVX1Only] in { - def : Pat<(v4f32 (X86VBroadcast FR32:$src)), - (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)>; - def : Pat<(v8f32 (X86VBroadcast FR32:$src)), - (VINSERTF128rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), - (v4f32 (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)), sub_xmm), - (v4f32 (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)), 1)>; - def : Pat<(v4f64 (X86VBroadcast FR64:$src)), - (VINSERTF128rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), - (v2f64 (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))), sub_xmm), - (v2f64 (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))), 1)>; - - def : Pat<(v4i32 (X86VBroadcast GR32:$src)), - (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)>; - def : Pat<(v8i32 (X86VBroadcast GR32:$src)), - (VINSERTF128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)), sub_xmm), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)), 1)>; - def : Pat<(v4i64 (X86VBroadcast GR64:$src)), - (VINSERTF128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)), sub_xmm), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)), 1)>; - - def : Pat<(v2i64 (X86VBroadcast i64:$src)), - (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)>; - def : Pat<(v2i64 (X86VBroadcast (loadi64 addr:$src))), - (VMOVDDUPrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VPERM - Permute instructions -// - -multiclass avx2_perm opc, string OpcodeStr, PatFrag mem_frag, - ValueType OpVT, X86FoldableSchedWrite Sched, - X86MemOperand memOp> { - let Predicates = [HasAVX2, NoVLX] in { - def Yrr : AVX28I, - Sched<[Sched]>, VEX_4V, VEX_L; - def Yrm : AVX28I, - Sched<[Sched.Folded, ReadAfterLd]>, VEX_4V, VEX_L; - } -} - -defm VPERMD : avx2_perm<0x36, "vpermd", loadv4i64, v8i32, WriteVarShuffle256, - i256mem>; -let ExeDomain = SSEPackedSingle in -defm VPERMPS : avx2_perm<0x16, "vpermps", loadv8f32, v8f32, WriteFVarShuffle256, - f256mem>; - -multiclass avx2_perm_imm opc, string OpcodeStr, PatFrag mem_frag, - ValueType OpVT, X86FoldableSchedWrite Sched, - X86MemOperand memOp> { - let Predicates = [HasAVX2, NoVLX] in { - def Yri : AVX2AIi8, - Sched<[Sched]>, VEX, VEX_L; - def Ymi : AVX2AIi8, - Sched<[Sched.Folded, ReadAfterLd]>, VEX, VEX_L; - } -} - -defm VPERMQ : avx2_perm_imm<0x00, "vpermq", loadv4i64, v4i64, - WriteShuffle256, i256mem>, VEX_W; -let ExeDomain = SSEPackedDouble in -defm VPERMPD : avx2_perm_imm<0x01, "vpermpd", loadv4f64, v4f64, - WriteFShuffle256, f256mem>, VEX_W; - -//===----------------------------------------------------------------------===// -// VPERM2I128 - Permute Floating-Point Values in 128-bit chunks -// -let isCommutable = 1 in -def VPERM2I128rr : AVX2AIi8<0x46, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR256:$src2, u8imm:$src3), - "vperm2i128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (v4i64 (X86VPerm2x128 VR256:$src1, VR256:$src2, - (i8 imm:$src3))))]>, Sched<[WriteShuffle256]>, - VEX_4V, VEX_L; -def VPERM2I128rm : AVX2AIi8<0x46, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f256mem:$src2, u8imm:$src3), - "vperm2i128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (X86VPerm2x128 VR256:$src1, (loadv4i64 addr:$src2), - (i8 imm:$src3)))]>, - Sched<[WriteShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; - -let Predicates = [HasAVX2] in -def : Pat<(v4i64 (X86VPerm2x128 (loadv4i64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2I128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; - - -//===----------------------------------------------------------------------===// -// VINSERTI128 - Insert packed integer values -// -let hasSideEffects = 0 in { -def VINSERTI128rr : AVX2AIi8<0x38, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR128:$src2, u8imm:$src3), - "vinserti128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteShuffle256]>, VEX_4V, VEX_L; -let mayLoad = 1 in -def VINSERTI128rm : AVX2AIi8<0x38, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, i128mem:$src2, u8imm:$src3), - "vinserti128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm : vinsert_lowering<"VINSERTI128", v2i64, v4i64, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v4i32, v8i32, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v8i16, v16i16, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v16i8, v32i8, loadv2i64>; -} - -//===----------------------------------------------------------------------===// -// VEXTRACTI128 - Extract packed integer values -// -def VEXTRACTI128rr : AVX2AIi8<0x39, MRMDestReg, (outs VR128:$dst), - (ins VR256:$src1, u8imm:$src2), - "vextracti128\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[WriteShuffle256]>, VEX, VEX_L; -let hasSideEffects = 0, mayStore = 1 in -def VEXTRACTI128mr : AVX2AIi8<0x39, MRMDestMem, (outs), - (ins i128mem:$dst, VR256:$src1, u8imm:$src2), - "vextracti128\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, VEX, VEX_L; - -let Predicates = [HasAVX2, NoVLX] in { - defm : vextract_lowering<"VEXTRACTI128", v4i64, v2i64>; - defm : vextract_lowering<"VEXTRACTI128", v8i32, v4i32>; - defm : vextract_lowering<"VEXTRACTI128", v16i16, v8i16>; - defm : vextract_lowering<"VEXTRACTI128", v32i8, v16i8>; -} - -//===----------------------------------------------------------------------===// -// VPMASKMOV - Conditional SIMD Integer Packed Loads and Stores -// -multiclass avx2_pmovmask { - def rm : AVX28I<0x8c, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, (IntLd128 addr:$src2, VR128:$src1))]>, - VEX_4V, Sched<[WriteVecMaskedLoad]>; - def Yrm : AVX28I<0x8c, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, i256mem:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, (IntLd256 addr:$src2, VR256:$src1))]>, - VEX_4V, VEX_L, Sched<[WriteVecMaskedLoadY]>; - def mr : AVX28I<0x8e, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src1, VR128:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(IntSt128 addr:$dst, VR128:$src1, VR128:$src2)]>, - VEX_4V, Sched<[WriteVecMaskedStore]>; - def Ymr : AVX28I<0x8e, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src1, VR256:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(IntSt256 addr:$dst, VR256:$src1, VR256:$src2)]>, - VEX_4V, VEX_L, Sched<[WriteVecMaskedStoreY]>; -} - -defm VPMASKMOVD : avx2_pmovmask<"vpmaskmovd", - int_x86_avx2_maskload_d, - int_x86_avx2_maskload_d_256, - int_x86_avx2_maskstore_d, - int_x86_avx2_maskstore_d_256>; -defm VPMASKMOVQ : avx2_pmovmask<"vpmaskmovq", - int_x86_avx2_maskload_q, - int_x86_avx2_maskload_q_256, - int_x86_avx2_maskstore_q, - int_x86_avx2_maskstore_q_256>, VEX_W; - -multiclass maskmov_lowering { - // masked store - def: Pat<(X86mstore addr:$ptr, (MaskVT RC:$mask), (VT RC:$src)), - (!cast(InstrStr#"mr") addr:$ptr, RC:$mask, RC:$src)>; - // masked load - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), undef)), - (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)>; - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), - (VT (bitconvert (ZeroVT immAllZerosV))))), - (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)>; - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), (VT RC:$src0))), - (!cast(BlendStr#"rr") - RC:$src0, - (VT (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)), - RC:$mask)>; -} -let Predicates = [HasAVX] in { - defm : maskmov_lowering<"VMASKMOVPS", VR128, v4f32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VMASKMOVPD", VR128, v2f64, v2i64, "VBLENDVPD", v4i32>; - defm : maskmov_lowering<"VMASKMOVPSY", VR256, v8f32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPDY", VR256, v4f64, v4i64, "VBLENDVPDY", v8i32>; -} -let Predicates = [HasAVX1Only] in { - // load/store i32/i64 not supported use ps/pd version - defm : maskmov_lowering<"VMASKMOVPSY", VR256, v8i32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPDY", VR256, v4i64, v4i64, "VBLENDVPDY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPS", VR128, v4i32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VMASKMOVPD", VR128, v2i64, v2i64, "VBLENDVPD", v4i32>; -} -let Predicates = [HasAVX2] in { - defm : maskmov_lowering<"VPMASKMOVDY", VR256, v8i32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VPMASKMOVQY", VR256, v4i64, v4i64, "VBLENDVPDY", v8i32>; - defm : maskmov_lowering<"VPMASKMOVD", VR128, v4i32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VPMASKMOVQ", VR128, v2i64, v2i64, "VBLENDVPD", v4i32>; -} - -//===----------------------------------------------------------------------===// -// SubVector Broadcasts -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. - -let Predicates = [HasAVX2, NoVLX] in { -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2i64 VR128:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4i32 VR128:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v8i16 VR128:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v16i8 VR128:$src), 1)>; -} - -let Predicates = [HasAVX, NoVLX] in { -def : Pat<(v4f64 (X86SubVBroadcast (v2f64 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2f64 VR128:$src), 1)>; -def : Pat<(v8f32 (X86SubVBroadcast (v4f32 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4f32 VR128:$src), 1)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2i64 VR128:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4i32 VR128:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v8i16 VR128:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v16i8 VR128:$src), 1)>; -} - -//===----------------------------------------------------------------------===// -// Variable Bit Shifts -// -multiclass avx2_var_shift opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, ValueType vt256> { - def rr : AVX28I, - VEX_4V, Sched<[SchedWriteVarVecShift.XMM]>; - def rm : AVX28I, - VEX_4V, Sched<[SchedWriteVarVecShift.XMM.Folded, ReadAfterLd]>; - def Yrr : AVX28I, - VEX_4V, VEX_L, Sched<[SchedWriteVarVecShift.YMM]>; - def Yrm : AVX28I, - VEX_4V, VEX_L, Sched<[SchedWriteVarVecShift.YMM.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPSLLVD : avx2_var_shift<0x47, "vpsllvd", shl, v4i32, v8i32>; - defm VPSLLVQ : avx2_var_shift<0x47, "vpsllvq", shl, v2i64, v4i64>, VEX_W; - defm VPSRLVD : avx2_var_shift<0x45, "vpsrlvd", srl, v4i32, v8i32>; - defm VPSRLVQ : avx2_var_shift<0x45, "vpsrlvq", srl, v2i64, v4i64>, VEX_W; - defm VPSRAVD : avx2_var_shift<0x46, "vpsravd", sra, v4i32, v8i32>; - - def : Pat<(v4i32 (X86vsrav VR128:$src1, VR128:$src2)), - (VPSRAVDrr VR128:$src1, VR128:$src2)>; - def : Pat<(v4i32 (X86vsrav VR128:$src1, - (bitconvert (loadv2i64 addr:$src2)))), - (VPSRAVDrm VR128:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, VR256:$src2)), - (VPSRAVDYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, - (bitconvert (loadv4i64 addr:$src2)))), - (VPSRAVDYrm VR256:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// VGATHER - GATHER Operations - -// FIXME: Improve scheduling of gather instructions. -multiclass avx2_gather opc, string OpcodeStr, ValueType VTx, - ValueType VTy, PatFrag GatherNode128, - PatFrag GatherNode256, RegisterClass RC256, - X86MemOperand memop128, X86MemOperand memop256, - ValueType MTx = VTx, ValueType MTy = VTy> { - def rm : AVX28I, - VEX, Sched<[WriteLoad]>; - def Yrm : AVX28I, - VEX, VEX_L, Sched<[WriteLoad]>; -} - -let Predicates = [UseAVX2] in { - let mayLoad = 1, hasSideEffects = 0, Constraints - = "@earlyclobber $dst,@earlyclobber $mask_wb, $src1 = $dst, $mask = $mask_wb" - in { - defm VPGATHERDQ : avx2_gather<0x90, "vpgatherdq", v2i64, v4i64, mgatherv4i32, - mgatherv4i32, VR256, vx128mem, vx256mem>, VEX_W; - defm VPGATHERQQ : avx2_gather<0x91, "vpgatherqq", v2i64, v4i64, mgatherv2i64, - mgatherv4i64, VR256, vx128mem, vy256mem>, VEX_W; - defm VPGATHERDD : avx2_gather<0x90, "vpgatherdd", v4i32, v8i32, mgatherv4i32, - mgatherv8i32, VR256, vx128mem, vy256mem>; - defm VPGATHERQD : avx2_gather<0x91, "vpgatherqd", v4i32, v4i32, mgatherv2i64, - mgatherv4i64, VR128, vx64mem, vy128mem>; - - let ExeDomain = SSEPackedDouble in { - defm VGATHERDPD : avx2_gather<0x92, "vgatherdpd", v2f64, v4f64, mgatherv4i32, - mgatherv4i32, VR256, vx128mem, vx256mem, - v2i64, v4i64>, VEX_W; - defm VGATHERQPD : avx2_gather<0x93, "vgatherqpd", v2f64, v4f64, mgatherv2i64, - mgatherv4i64, VR256, vx128mem, vy256mem, - v2i64, v4i64>, VEX_W; - } - - let ExeDomain = SSEPackedSingle in { - defm VGATHERDPS : avx2_gather<0x92, "vgatherdps", v4f32, v8f32, mgatherv4i32, - mgatherv8i32, VR256, vx128mem, vy256mem, - v4i32, v8i32>; - defm VGATHERQPS : avx2_gather<0x93, "vgatherqps", v4f32, v4f32, mgatherv2i64, - mgatherv4i64, VR128, vx64mem, vy128mem, - v4i32, v4i32>; - } - } -} - -//===----------------------------------------------------------------------===// -// Extra selection patterns for f128, f128mem - -// movaps is shorter than movdqa. movaps is in SSE and movdqa is in SSE2. -def : Pat<(alignedstore (f128 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, (COPY_TO_REGCLASS (f128 VR128:$src), VR128))>; -def : Pat<(store (f128 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, (COPY_TO_REGCLASS (f128 VR128:$src), VR128))>; - -def : Pat<(alignedloadf128 addr:$src), - (COPY_TO_REGCLASS (MOVAPSrm addr:$src), VR128)>; -def : Pat<(loadf128 addr:$src), - (COPY_TO_REGCLASS (MOVUPSrm addr:$src), VR128)>; - -// andps is shorter than andpd or pand. andps is SSE and andpd/pand are in SSE2 -def : Pat<(f128 (X86fand VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (ANDPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86fand VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (ANDPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -def : Pat<(f128 (X86for VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (ORPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86for VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (ORPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -def : Pat<(f128 (X86fxor VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (XORPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86fxor VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (XORPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -//===----------------------------------------------------------------------===// -// GFNI instructions -//===----------------------------------------------------------------------===// - -multiclass GF2P8MULB_rm { - let ExeDomain = SSEPackedInt, - AsmString = !if(Is2Addr, - OpcodeStr##"\t{$src2, $dst|$dst, $src2}", - OpcodeStr##"\t{$src2, $src1, $dst|$dst, $src1, $src2}") in { - let isCommutable = 1 in - def rr : PDI<0xCF, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), "", - [(set RC:$dst, (OpVT (X86GF2P8mulb RC:$src1, RC:$src2)))]>, - Sched<[SchedWriteVecALU.XMM]>, T8PD; - - def rm : PDI<0xCF, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, X86MemOp:$src2), "", - [(set RC:$dst, (OpVT (X86GF2P8mulb RC:$src1, - (bitconvert (MemOpFrag addr:$src2)))))]>, - Sched<[SchedWriteVecALU.XMM.Folded, ReadAfterLd]>, T8PD; - } -} - -multiclass GF2P8AFFINE_rmi Op, string OpStr, ValueType OpVT, - SDNode OpNode, RegisterClass RC, PatFrag MemOpFrag, - X86MemOperand X86MemOp, bit Is2Addr = 0> { - let AsmString = !if(Is2Addr, - OpStr##"\t{$src3, $src2, $dst|$dst, $src2, $src3}", - OpStr##"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}") in { - def rri : Ii8, Sched<[SchedWriteVecALU.XMM]>; - def rmi : Ii8, - Sched<[SchedWriteVecALU.XMM.Folded, ReadAfterLd]>; - } -} - -multiclass GF2P8AFFINE_common Op, string OpStr, SDNode OpNode> { - let Constraints = "$src1 = $dst", - Predicates = [HasGFNI, UseSSE2] in - defm NAME : GF2P8AFFINE_rmi; - let Predicates = [HasGFNI, HasAVX, NoVLX_Or_NoBWI] in { - defm V##NAME : GF2P8AFFINE_rmi, VEX_4V, VEX_W; - defm V##NAME##Y : GF2P8AFFINE_rmi, VEX_4V, VEX_L, VEX_W; - } -} - -// GF2P8MULB -let Constraints = "$src1 = $dst", - Predicates = [HasGFNI, UseSSE2] in -defm GF2P8MULB : GF2P8MULB_rm<"gf2p8mulb", v16i8, VR128, memopv2i64, - i128mem, 1>; -let Predicates = [HasGFNI, HasAVX, NoVLX_Or_NoBWI] in { - defm VGF2P8MULB : GF2P8MULB_rm<"vgf2p8mulb", v16i8, VR128, loadv2i64, - i128mem>, VEX_4V; - defm VGF2P8MULBY : GF2P8MULB_rm<"vgf2p8mulb", v32i8, VR256, loadv4i64, - i256mem>, VEX_4V, VEX_L; -} -// GF2P8AFFINEINVQB, GF2P8AFFINEQB -let isCommutable = 0 in { - defm GF2P8AFFINEINVQB : GF2P8AFFINE_common<0xCF, "gf2p8affineinvqb", - X86GF2P8affineinvqb>, TAPD; - defm GF2P8AFFINEQB : GF2P8AFFINE_common<0xCE, "gf2p8affineqb", - X86GF2P8affineqb>, TAPD; -} - diff --git a/suite/synctools/tablegen/X86/X86InstrSVM.td b/suite/synctools/tablegen/X86/X86InstrSVM.td deleted file mode 100644 index 2dc6e8b436..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrSVM.td +++ /dev/null @@ -1,63 +0,0 @@ -//===-- X86InstrSVM.td - SVM Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the AMD SVM instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SVM instructions - -let SchedRW = [WriteSystem] in { -// 0F 01 D9 -def VMMCALL : I<0x01, MRM_D9, (outs), (ins), "vmmcall", []>, TB; - -// 0F 01 DC -def STGI : I<0x01, MRM_DC, (outs), (ins), "stgi", []>, TB; - -// 0F 01 DD -def CLGI : I<0x01, MRM_DD, (outs), (ins), "clgi", []>, TB; - -// 0F 01 DE -let Uses = [EAX] in -def SKINIT : I<0x01, MRM_DE, (outs), (ins), "skinit\t{%eax|eax}", []>, TB; - -// 0F 01 D8 -let Uses = [EAX] in -def VMRUN32 : I<0x01, MRM_D8, (outs), (ins), "vmrun\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMRUN64 : I<0x01, MRM_D8, (outs), (ins), "vmrun\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DA -let Uses = [EAX] in -def VMLOAD32 : I<0x01, MRM_DA, (outs), (ins), "vmload\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMLOAD64 : I<0x01, MRM_DA, (outs), (ins), "vmload\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DB -let Uses = [EAX] in -def VMSAVE32 : I<0x01, MRM_DB, (outs), (ins), "vmsave\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMSAVE64 : I<0x01, MRM_DB, (outs), (ins), "vmsave\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DF -let Uses = [EAX, ECX] in -def INVLPGA32 : I<0x01, MRM_DF, (outs), (ins), - "invlpga\t{%eax, %ecx|eax, ecx}", []>, TB, Requires<[Not64BitMode]>; -let Uses = [RAX, ECX] in -def INVLPGA64 : I<0x01, MRM_DF, (outs), (ins), - "invlpga\t{%rax, %ecx|rax, ecx}", []>, TB, Requires<[In64BitMode]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrShiftRotate.td b/suite/synctools/tablegen/X86/X86InstrShiftRotate.td deleted file mode 100644 index cbcb1daf88..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrShiftRotate.td +++ /dev/null @@ -1,1031 +0,0 @@ -//===-- X86InstrShiftRotate.td - Shift and Rotate Instrs ---*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the shift and rotate instructions. -// -//===----------------------------------------------------------------------===// - -// FIXME: Someone needs to smear multipattern goodness all over this file. - -let Defs = [EFLAGS] in { - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SHL8rCL : I<0xD2, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1), - "shl{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (shl GR8:$src1, CL))]>; -def SHL16rCL : I<0xD3, MRM4r, (outs GR16:$dst), (ins GR16:$src1), - "shl{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (shl GR16:$src1, CL))]>, OpSize16; -def SHL32rCL : I<0xD3, MRM4r, (outs GR32:$dst), (ins GR32:$src1), - "shl{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (shl GR32:$src1, CL))]>, OpSize32; -def SHL64rCL : RI<0xD3, MRM4r, (outs GR64:$dst), (ins GR64:$src1), - "shl{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (shl GR64:$src1, CL))]>; -} // Uses = [CL] - -def SAL8rCL : I<0xD2, MRM6r, (outs GR8 :$dst), (ins GR8 :$src1), "sal{b}\t{%cl, $dst|$dst, cl}", []>; -def SAL16rCL : I<0xD3, MRM6r, (outs GR16:$dst), (ins GR16:$src1), - "sal{w}\t{%cl, $dst|$dst, cl}", - []>, OpSize16; -def SAL32rCL : I<0xD3, MRM6r, (outs GR32:$dst), (ins GR32:$src1), - "sal{l}\t{%cl, $dst|$dst, cl}", - []>, OpSize32; -def SAL64rCL : RI<0xD3, MRM6r, (outs GR64:$dst), (ins GR64:$src1), - "sal{q}\t{%cl, $dst|$dst, cl}", - []>; - -def SHL8ri : Ii8<0xC0, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "shl{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (shl GR8:$src1, (i8 imm:$src2)))]>; - -def SAL8ri : Ii8<0xC0, MRM6r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), - "sal{b}\t{$src2, $dst|$dst, $src2}", - []>; - -let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. -def SHL16ri : Ii8<0xC1, MRM4r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "shl{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (shl GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SHL32ri : Ii8<0xC1, MRM4r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "shl{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SHL64ri : RIi8<0xC1, MRM4r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "shl{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (shl GR64:$src1, (i8 imm:$src2)))]>; - -def SAL16ri : Ii8<0xC1, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), - "sal{w}\t{$src2, $dst|$dst, $src2}", - []>, - OpSize16; -def SAL32ri : Ii8<0xC1, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), - "sal{l}\t{$src2, $dst|$dst, $src2}", - []>, - OpSize32; -def SAL64ri : RIi8<0xC1, MRM6r, (outs GR64:$dst), - (ins GR64:$src1, i8imm:$src2), - "sal{q}\t{$src2, $dst|$dst, $src2}", - []>; -} // isConvertibleToThreeAddress = 1 - -// NOTE: We don't include patterns for shifts of a register by one, because -// 'add reg,reg' is cheaper (and we have a Pat pattern for shift-by-one). -let hasSideEffects = 0 in { -def SHL8r1 : I<0xD0, MRM4r, (outs GR8:$dst), (ins GR8:$src1), - "shl{b}\t{$$1, $dst|$dst, 1}", []>; -def SHL16r1 : I<0xD1, MRM4r, (outs GR16:$dst), (ins GR16:$src1), - "shl{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def SHL32r1 : I<0xD1, MRM4r, (outs GR32:$dst), (ins GR32:$src1), - "shl{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def SHL64r1 : RI<0xD1, MRM4r, (outs GR64:$dst), (ins GR64:$src1), - "shl{q}\t{$$1, $dst|$dst, 1}", []>; -def SAL8r1 : I<0xD0, MRM6r, (outs GR8:$dst), (ins GR8:$src1), - "sal{b}\t{$$1, $dst|$dst, 1}", []>; -def SAL16r1 : I<0xD1, MRM6r, (outs GR16:$dst), (ins GR16:$src1), - "sal{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def SAL32r1 : I<0xD1, MRM6r, (outs GR32:$dst), (ins GR32:$src1), - "sal{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def SAL64r1 : RI<0xD1, MRM6r, (outs GR64:$dst), (ins GR64:$src1), - "sal{q}\t{$$1, $dst|$dst, 1}", []>; -} // hasSideEffects = 0 -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -// FIXME: Why do we need an explicit "Uses = [CL]" when the instr has a pattern -// using CL? -let Uses = [CL] in { -def SHL8mCL : I<0xD2, MRM4m, (outs), (ins i8mem :$dst), - "shl{b}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi8 addr:$dst), CL), addr:$dst)]>; -def SHL16mCL : I<0xD3, MRM4m, (outs), (ins i16mem:$dst), - "shl{w}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SHL32mCL : I<0xD3, MRM4m, (outs), (ins i32mem:$dst), - "shl{l}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SHL64mCL : RI<0xD3, MRM4m, (outs), (ins i64mem:$dst), - "shl{q}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8mCL : I<0xD2, MRM6m, (outs), (ins i8mem :$dst), - "sal{b}\t{%cl, $dst|$dst, cl}", - []>; -def SAL16mCL : I<0xD3, MRM6m, (outs), (ins i16mem:$dst), - "sal{w}\t{%cl, $dst|$dst, cl}", - []>, - OpSize16; -def SAL32mCL : I<0xD3, MRM6m, (outs), (ins i32mem:$dst), - "sal{l}\t{%cl, $dst|$dst, cl}", - []>, - OpSize32; -def SAL64mCL : RI<0xD3, MRM6m, (outs), (ins i64mem:$dst), - "sal{q}\t{%cl, $dst|$dst, cl}", - []>; -} -def SHL8mi : Ii8<0xC0, MRM4m, (outs), (ins i8mem :$dst, u8imm:$src), - "shl{b}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SHL16mi : Ii8<0xC1, MRM4m, (outs), (ins i16mem:$dst, u8imm:$src), - "shl{w}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SHL32mi : Ii8<0xC1, MRM4m, (outs), (ins i32mem:$dst, u8imm:$src), - "shl{l}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SHL64mi : RIi8<0xC1, MRM4m, (outs), (ins i64mem:$dst, u8imm:$src), - "shl{q}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8mi : Ii8<0xC0, MRM6m, (outs), (ins i8mem :$dst, i8imm:$src), - "sal{b}\t{$src, $dst|$dst, $src}", - []>; -def SAL16mi : Ii8<0xC1, MRM6m, (outs), (ins i16mem:$dst, i8imm:$src), - "sal{w}\t{$src, $dst|$dst, $src}", - []>, OpSize16; -def SAL32mi : Ii8<0xC1, MRM6m, (outs), (ins i32mem:$dst, i8imm:$src), - "sal{l}\t{$src, $dst|$dst, $src}", - []>, OpSize32; -def SAL64mi : RIi8<0xC1, MRM6m, (outs), (ins i64mem:$dst, i8imm:$src), - "sal{q}\t{$src, $dst|$dst, $src}", - []>; - -// Shift by 1 -def SHL8m1 : I<0xD0, MRM4m, (outs), (ins i8mem :$dst), - "shl{b}\t{$dst|$dst, 1}", - [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SHL16m1 : I<0xD1, MRM4m, (outs), (ins i16mem:$dst), - "shl{w}\t{$dst|$dst, 1}", - [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SHL32m1 : I<0xD1, MRM4m, (outs), (ins i32mem:$dst), - "shl{l}\t{$dst|$dst, 1}", - [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SHL64m1 : RI<0xD1, MRM4m, (outs), (ins i64mem:$dst), - "shl{q}\t{$dst|$dst, 1}", - [(store (shl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8m1 : I<0xD0, MRM6m, (outs), (ins i8mem :$dst), - "sal{b}\t{$dst|$dst, 1}", - []>; -def SAL16m1 : I<0xD1, MRM6m, (outs), (ins i16mem:$dst), - "sal{w}\t{$dst|$dst, 1}", - []>, OpSize16; -def SAL32m1 : I<0xD1, MRM6m, (outs), (ins i32mem:$dst), - "sal{l}\t{$dst|$dst, 1}", - []>, OpSize32; -def SAL64m1 : RI<0xD1, MRM6m, (outs), (ins i64mem:$dst), - "sal{q}\t{$dst|$dst, 1}", - []>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SHR8rCL : I<0xD2, MRM5r, (outs GR8 :$dst), (ins GR8 :$src1), - "shr{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (srl GR8:$src1, CL))]>; -def SHR16rCL : I<0xD3, MRM5r, (outs GR16:$dst), (ins GR16:$src1), - "shr{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (srl GR16:$src1, CL))]>, OpSize16; -def SHR32rCL : I<0xD3, MRM5r, (outs GR32:$dst), (ins GR32:$src1), - "shr{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (srl GR32:$src1, CL))]>, OpSize32; -def SHR64rCL : RI<0xD3, MRM5r, (outs GR64:$dst), (ins GR64:$src1), - "shr{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (srl GR64:$src1, CL))]>; -} - -def SHR8ri : Ii8<0xC0, MRM5r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$src2), - "shr{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (srl GR8:$src1, (i8 imm:$src2)))]>; -def SHR16ri : Ii8<0xC1, MRM5r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "shr{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (srl GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SHR32ri : Ii8<0xC1, MRM5r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "shr{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SHR64ri : RIi8<0xC1, MRM5r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$src2), - "shr{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (srl GR64:$src1, (i8 imm:$src2)))]>; - -// Shift right by 1 -def SHR8r1 : I<0xD0, MRM5r, (outs GR8:$dst), (ins GR8:$src1), - "shr{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>; -def SHR16r1 : I<0xD1, MRM5r, (outs GR16:$dst), (ins GR16:$src1), - "shr{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize16; -def SHR32r1 : I<0xD1, MRM5r, (outs GR32:$dst), (ins GR32:$src1), - "shr{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>, OpSize32; -def SHR64r1 : RI<0xD1, MRM5r, (outs GR64:$dst), (ins GR64:$src1), - "shr{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (srl GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def SHR8mCL : I<0xD2, MRM5m, (outs), (ins i8mem :$dst), - "shr{b}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi8 addr:$dst), CL), addr:$dst)]>; -def SHR16mCL : I<0xD3, MRM5m, (outs), (ins i16mem:$dst), - "shr{w}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SHR32mCL : I<0xD3, MRM5m, (outs), (ins i32mem:$dst), - "shr{l}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SHR64mCL : RI<0xD3, MRM5m, (outs), (ins i64mem:$dst), - "shr{q}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def SHR8mi : Ii8<0xC0, MRM5m, (outs), (ins i8mem :$dst, u8imm:$src), - "shr{b}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SHR16mi : Ii8<0xC1, MRM5m, (outs), (ins i16mem:$dst, u8imm:$src), - "shr{w}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SHR32mi : Ii8<0xC1, MRM5m, (outs), (ins i32mem:$dst, u8imm:$src), - "shr{l}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SHR64mi : RIi8<0xC1, MRM5m, (outs), (ins i64mem:$dst, u8imm:$src), - "shr{q}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Shift by 1 -def SHR8m1 : I<0xD0, MRM5m, (outs), (ins i8mem :$dst), - "shr{b}\t{$dst|$dst, 1}", - [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SHR16m1 : I<0xD1, MRM5m, (outs), (ins i16mem:$dst), - "shr{w}\t{$dst|$dst, 1}", - [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SHR32m1 : I<0xD1, MRM5m, (outs), (ins i32mem:$dst), - "shr{l}\t{$dst|$dst, 1}", - [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SHR64m1 : RI<0xD1, MRM5m, (outs), (ins i64mem:$dst), - "shr{q}\t{$dst|$dst, 1}", - [(store (srl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SAR8rCL : I<0xD2, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1), - "sar{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (sra GR8:$src1, CL))]>; -def SAR16rCL : I<0xD3, MRM7r, (outs GR16:$dst), (ins GR16:$src1), - "sar{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (sra GR16:$src1, CL))]>, - OpSize16; -def SAR32rCL : I<0xD3, MRM7r, (outs GR32:$dst), (ins GR32:$src1), - "sar{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (sra GR32:$src1, CL))]>, - OpSize32; -def SAR64rCL : RI<0xD3, MRM7r, (outs GR64:$dst), (ins GR64:$src1), - "sar{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (sra GR64:$src1, CL))]>; -} - -def SAR8ri : Ii8<0xC0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "sar{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (sra GR8:$src1, (i8 imm:$src2)))]>; -def SAR16ri : Ii8<0xC1, MRM7r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "sar{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (sra GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SAR32ri : Ii8<0xC1, MRM7r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "sar{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SAR64ri : RIi8<0xC1, MRM7r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "sar{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (sra GR64:$src1, (i8 imm:$src2)))]>; - -// Shift by 1 -def SAR8r1 : I<0xD0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1), - "sar{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>; -def SAR16r1 : I<0xD1, MRM7r, (outs GR16:$dst), (ins GR16:$src1), - "sar{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize16; -def SAR32r1 : I<0xD1, MRM7r, (outs GR32:$dst), (ins GR32:$src1), - "sar{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>, OpSize32; -def SAR64r1 : RI<0xD1, MRM7r, (outs GR64:$dst), (ins GR64:$src1), - "sar{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (sra GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def SAR8mCL : I<0xD2, MRM7m, (outs), (ins i8mem :$dst), - "sar{b}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi8 addr:$dst), CL), addr:$dst)]>; -def SAR16mCL : I<0xD3, MRM7m, (outs), (ins i16mem:$dst), - "sar{w}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SAR32mCL : I<0xD3, MRM7m, (outs), (ins i32mem:$dst), - "sar{l}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SAR64mCL : RI<0xD3, MRM7m, (outs), (ins i64mem:$dst), - "sar{q}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def SAR8mi : Ii8<0xC0, MRM7m, (outs), (ins i8mem :$dst, u8imm:$src), - "sar{b}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SAR16mi : Ii8<0xC1, MRM7m, (outs), (ins i16mem:$dst, u8imm:$src), - "sar{w}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SAR32mi : Ii8<0xC1, MRM7m, (outs), (ins i32mem:$dst, u8imm:$src), - "sar{l}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SAR64mi : RIi8<0xC1, MRM7m, (outs), (ins i64mem:$dst, u8imm:$src), - "sar{q}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Shift by 1 -def SAR8m1 : I<0xD0, MRM7m, (outs), (ins i8mem :$dst), - "sar{b}\t{$dst|$dst, 1}", - [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SAR16m1 : I<0xD1, MRM7m, (outs), (ins i16mem:$dst), - "sar{w}\t{$dst|$dst, 1}", - [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SAR32m1 : I<0xD1, MRM7m, (outs), (ins i32mem:$dst), - "sar{l}\t{$dst|$dst, 1}", - [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SAR64m1 : RI<0xD1, MRM7m, (outs), (ins i64mem:$dst), - "sar{q}\t{$dst|$dst, 1}", - [(store (sra (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Rotate instructions -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0 in { -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { - -let Uses = [CL, EFLAGS] in { -def RCL8rCL : I<0xD2, MRM2r, (outs GR8:$dst), (ins GR8:$src1), - "rcl{b}\t{%cl, $dst|$dst, cl}", []>; -def RCL16rCL : I<0xD3, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCL32rCL : I<0xD3, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src1), - "rcl{q}\t{%cl, $dst|$dst, cl}", []>; -} // Uses = [CL, EFLAGS] - -let Uses = [EFLAGS] in { -def RCL8r1 : I<0xD0, MRM2r, (outs GR8:$dst), (ins GR8:$src1), - "rcl{b}\t{$$1, $dst|$dst, 1}", []>; -def RCL8ri : Ii8<0xC0, MRM2r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt), - "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL16r1 : I<0xD1, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "rcl{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def RCL16ri : Ii8<0xC1, MRM2r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt), - "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCL32r1 : I<0xD1, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "rcl{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def RCL32ri : Ii8<0xC1, MRM2r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt), - "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCL64r1 : RI<0xD1, MRM2r, (outs GR64:$dst), (ins GR64:$src1), - "rcl{q}\t{$$1, $dst|$dst, 1}", []>; -def RCL64ri : RIi8<0xC1, MRM2r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt), - "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; -} // Uses = [EFLAGS] - -let Uses = [CL, EFLAGS] in { -def RCR8rCL : I<0xD2, MRM3r, (outs GR8:$dst), (ins GR8:$src1), - "rcr{b}\t{%cl, $dst|$dst, cl}", []>; -def RCR16rCL : I<0xD3, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCR32rCL : I<0xD3, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCR64rCL : RI<0xD3, MRM3r, (outs GR64:$dst), (ins GR64:$src1), - "rcr{q}\t{%cl, $dst|$dst, cl}", []>; -} // Uses = [CL, EFLAGS] - -let Uses = [EFLAGS] in { -def RCR8r1 : I<0xD0, MRM3r, (outs GR8:$dst), (ins GR8:$src1), - "rcr{b}\t{$$1, $dst|$dst, 1}", []>; -def RCR8ri : Ii8<0xC0, MRM3r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt), - "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR16r1 : I<0xD1, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "rcr{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def RCR16ri : Ii8<0xC1, MRM3r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt), - "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCR32r1 : I<0xD1, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "rcr{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def RCR32ri : Ii8<0xC1, MRM3r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt), - "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCR64r1 : RI<0xD1, MRM3r, (outs GR64:$dst), (ins GR64:$src1), - "rcr{q}\t{$$1, $dst|$dst, 1}", []>; -def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt), - "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; -} // Uses = [EFLAGS] - -} // Constraints = "$src = $dst" - -let SchedRW = [WriteShiftLd, WriteRMW], mayStore = 1 in { -let Uses = [EFLAGS] in { -def RCL8m1 : I<0xD0, MRM2m, (outs), (ins i8mem:$dst), - "rcl{b}\t$dst", []>; -def RCL8mi : Ii8<0xC0, MRM2m, (outs), (ins i8mem:$dst, u8imm:$cnt), - "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL16m1 : I<0xD1, MRM2m, (outs), (ins i16mem:$dst), - "rcl{w}\t$dst", []>, OpSize16; -def RCL16mi : Ii8<0xC1, MRM2m, (outs), (ins i16mem:$dst, u8imm:$cnt), - "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCL32m1 : I<0xD1, MRM2m, (outs), (ins i32mem:$dst), - "rcl{l}\t$dst", []>, OpSize32; -def RCL32mi : Ii8<0xC1, MRM2m, (outs), (ins i32mem:$dst, u8imm:$cnt), - "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCL64m1 : RI<0xD1, MRM2m, (outs), (ins i64mem:$dst), - "rcl{q}\t$dst", []>, Requires<[In64BitMode]>; -def RCL64mi : RIi8<0xC1, MRM2m, (outs), (ins i64mem:$dst, u8imm:$cnt), - "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>, - Requires<[In64BitMode]>; - -def RCR8m1 : I<0xD0, MRM3m, (outs), (ins i8mem:$dst), - "rcr{b}\t{$$1, $dst|$dst, 1}", []>; -def RCR8mi : Ii8<0xC0, MRM3m, (outs), (ins i8mem:$dst, u8imm:$cnt), - "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR16m1 : I<0xD1, MRM3m, (outs), (ins i16mem:$dst), - "rcr{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def RCR16mi : Ii8<0xC1, MRM3m, (outs), (ins i16mem:$dst, u8imm:$cnt), - "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCR32m1 : I<0xD1, MRM3m, (outs), (ins i32mem:$dst), - "rcr{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def RCR32mi : Ii8<0xC1, MRM3m, (outs), (ins i32mem:$dst, u8imm:$cnt), - "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCR64m1 : RI<0xD1, MRM3m, (outs), (ins i64mem:$dst), - "rcr{q}\t{$$1, $dst|$dst, 1}", []>, Requires<[In64BitMode]>; -def RCR64mi : RIi8<0xC1, MRM3m, (outs), (ins i64mem:$dst, u8imm:$cnt), - "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>, - Requires<[In64BitMode]>; -} // Uses = [EFLAGS] - -let Uses = [CL, EFLAGS] in { -def RCL8mCL : I<0xD2, MRM2m, (outs), (ins i8mem:$dst), - "rcl{b}\t{%cl, $dst|$dst, cl}", []>; -def RCL16mCL : I<0xD3, MRM2m, (outs), (ins i16mem:$dst), - "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCL32mCL : I<0xD3, MRM2m, (outs), (ins i32mem:$dst), - "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCL64mCL : RI<0xD3, MRM2m, (outs), (ins i64mem:$dst), - "rcl{q}\t{%cl, $dst|$dst, cl}", []>, - Requires<[In64BitMode]>; - -def RCR8mCL : I<0xD2, MRM3m, (outs), (ins i8mem:$dst), - "rcr{b}\t{%cl, $dst|$dst, cl}", []>; -def RCR16mCL : I<0xD3, MRM3m, (outs), (ins i16mem:$dst), - "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCR32mCL : I<0xD3, MRM3m, (outs), (ins i32mem:$dst), - "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCR64mCL : RI<0xD3, MRM3m, (outs), (ins i64mem:$dst), - "rcr{q}\t{%cl, $dst|$dst, cl}", []>, - Requires<[In64BitMode]>; -} // Uses = [CL, EFLAGS] -} // SchedRW -} // hasSideEffects = 0 - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -// FIXME: provide shorter instructions when imm8 == 1 -let Uses = [CL] in { -def ROL8rCL : I<0xD2, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "rol{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (rotl GR8:$src1, CL))]>; -def ROL16rCL : I<0xD3, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "rol{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (rotl GR16:$src1, CL))]>, OpSize16; -def ROL32rCL : I<0xD3, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "rol{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (rotl GR32:$src1, CL))]>, OpSize32; -def ROL64rCL : RI<0xD3, MRM0r, (outs GR64:$dst), (ins GR64:$src1), - "rol{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (rotl GR64:$src1, CL))]>; -} - -def ROL8ri : Ii8<0xC0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "rol{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 imm:$src2)))]>; -def ROL16ri : Ii8<0xC1, MRM0r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "rol{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 imm:$src2)))]>, OpSize16; -def ROL32ri : Ii8<0xC1, MRM0r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "rol{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>, OpSize32; -def ROL64ri : RIi8<0xC1, MRM0r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "rol{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$src2)))]>; - -// Rotate by 1 -def ROL8r1 : I<0xD0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "rol{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>; -def ROL16r1 : I<0xD1, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "rol{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize16; -def ROL32r1 : I<0xD1, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "rol{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>, OpSize32; -def ROL64r1 : RI<0xD1, MRM0r, (outs GR64:$dst), (ins GR64:$src1), - "rol{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def ROL8mCL : I<0xD2, MRM0m, (outs), (ins i8mem :$dst), - "rol{b}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi8 addr:$dst), CL), addr:$dst)]>; -def ROL16mCL : I<0xD3, MRM0m, (outs), (ins i16mem:$dst), - "rol{w}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16; -def ROL32mCL : I<0xD3, MRM0m, (outs), (ins i32mem:$dst), - "rol{l}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32; -def ROL64mCL : RI<0xD3, MRM0m, (outs), (ins i64mem:$dst), - "rol{q}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def ROL8mi : Ii8<0xC0, MRM0m, (outs), (ins i8mem :$dst, u8imm:$src1), - "rol{b}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi8 addr:$dst), (i8 imm:$src1)), addr:$dst)]>; -def ROL16mi : Ii8<0xC1, MRM0m, (outs), (ins i16mem:$dst, u8imm:$src1), - "rol{w}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi16 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - OpSize16; -def ROL32mi : Ii8<0xC1, MRM0m, (outs), (ins i32mem:$dst, u8imm:$src1), - "rol{l}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi32 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - OpSize32; -def ROL64mi : RIi8<0xC1, MRM0m, (outs), (ins i64mem:$dst, u8imm:$src1), - "rol{q}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi64 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Rotate by 1 -def ROL8m1 : I<0xD0, MRM0m, (outs), (ins i8mem :$dst), - "rol{b}\t{$dst|$dst, 1}", - [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def ROL16m1 : I<0xD1, MRM0m, (outs), (ins i16mem:$dst), - "rol{w}\t{$dst|$dst, 1}", - [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def ROL32m1 : I<0xD1, MRM0m, (outs), (ins i32mem:$dst), - "rol{l}\t{$dst|$dst, 1}", - [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def ROL64m1 : RI<0xD1, MRM0m, (outs), (ins i64mem:$dst), - "rol{q}\t{$dst|$dst, 1}", - [(store (rotl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def ROR8rCL : I<0xD2, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "ror{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (rotr GR8:$src1, CL))]>; -def ROR16rCL : I<0xD3, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "ror{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (rotr GR16:$src1, CL))]>, OpSize16; -def ROR32rCL : I<0xD3, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "ror{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (rotr GR32:$src1, CL))]>, OpSize32; -def ROR64rCL : RI<0xD3, MRM1r, (outs GR64:$dst), (ins GR64:$src1), - "ror{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (rotr GR64:$src1, CL))]>; -} - -def ROR8ri : Ii8<0xC0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "ror{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (rotr GR8:$src1, (i8 relocImm:$src2)))]>; -def ROR16ri : Ii8<0xC1, MRM1r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "ror{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (rotr GR16:$src1, (i8 relocImm:$src2)))]>, - OpSize16; -def ROR32ri : Ii8<0xC1, MRM1r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "ror{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (rotr GR32:$src1, (i8 relocImm:$src2)))]>, - OpSize32; -def ROR64ri : RIi8<0xC1, MRM1r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "ror{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (rotr GR64:$src1, (i8 relocImm:$src2)))]>; - -// Rotate by 1 -def ROR8r1 : I<0xD0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "ror{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 7)))]>; -def ROR16r1 : I<0xD1, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "ror{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 15)))]>, OpSize16; -def ROR32r1 : I<0xD1, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "ror{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 31)))]>, OpSize32; -def ROR64r1 : RI<0xD1, MRM1r, (outs GR64:$dst), (ins GR64:$src1), - "ror{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 63)))]>; -} // Constraints = "$src = $dst", SchedRW - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def ROR8mCL : I<0xD2, MRM1m, (outs), (ins i8mem :$dst), - "ror{b}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi8 addr:$dst), CL), addr:$dst)]>; -def ROR16mCL : I<0xD3, MRM1m, (outs), (ins i16mem:$dst), - "ror{w}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16; -def ROR32mCL : I<0xD3, MRM1m, (outs), (ins i32mem:$dst), - "ror{l}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32; -def ROR64mCL : RI<0xD3, MRM1m, (outs), (ins i64mem:$dst), - "ror{q}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def ROR8mi : Ii8<0xC0, MRM1m, (outs), (ins i8mem :$dst, u8imm:$src), - "ror{b}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def ROR16mi : Ii8<0xC1, MRM1m, (outs), (ins i16mem:$dst, u8imm:$src), - "ror{w}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def ROR32mi : Ii8<0xC1, MRM1m, (outs), (ins i32mem:$dst, u8imm:$src), - "ror{l}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def ROR64mi : RIi8<0xC1, MRM1m, (outs), (ins i64mem:$dst, u8imm:$src), - "ror{q}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Rotate by 1 -def ROR8m1 : I<0xD0, MRM1m, (outs), (ins i8mem :$dst), - "ror{b}\t{$dst|$dst, 1}", - [(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst)]>; -def ROR16m1 : I<0xD1, MRM1m, (outs), (ins i16mem:$dst), - "ror{w}\t{$dst|$dst, 1}", - [(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst)]>, - OpSize16; -def ROR32m1 : I<0xD1, MRM1m, (outs), (ins i32mem:$dst), - "ror{l}\t{$dst|$dst, 1}", - [(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst)]>, - OpSize32; -def ROR64m1 : RI<0xD1, MRM1m, (outs), (ins i64mem:$dst), - "ror{q}\t{$dst|$dst, 1}", - [(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - - -//===----------------------------------------------------------------------===// -// Double shift instructions (generalizations of rotate) -//===----------------------------------------------------------------------===// - -let Constraints = "$src1 = $dst" in { - -let Uses = [CL], SchedRW = [WriteSHDrrcl] in { -def SHLD16rrCL : I<0xA5, MRMDestReg, (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2), - "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, CL))]>, - TB, OpSize16; -def SHRD16rrCL : I<0xAD, MRMDestReg, (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2), - "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, CL))]>, - TB, OpSize16; -def SHLD32rrCL : I<0xA5, MRMDestReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, CL))]>, - TB, OpSize32; -def SHRD32rrCL : I<0xAD, MRMDestReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, CL))]>, - TB, OpSize32; -def SHLD64rrCL : RI<0xA5, MRMDestReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, CL))]>, - TB; -def SHRD64rrCL : RI<0xAD, MRMDestReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, CL))]>, - TB; -} // SchedRW - -let isCommutable = 1, SchedRW = [WriteSHDrri] in { // These instructions commute to each other. -def SHLD16rri8 : Ii8<0xA4, MRMDestReg, - (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2, u8imm:$src3), - "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, - (i8 imm:$src3)))]>, - TB, OpSize16; -def SHRD16rri8 : Ii8<0xAC, MRMDestReg, - (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2, u8imm:$src3), - "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, - (i8 imm:$src3)))]>, - TB, OpSize16; -def SHLD32rri8 : Ii8<0xA4, MRMDestReg, - (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2, u8imm:$src3), - "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, - (i8 imm:$src3)))]>, - TB, OpSize32; -def SHRD32rri8 : Ii8<0xAC, MRMDestReg, - (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2, u8imm:$src3), - "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, - (i8 imm:$src3)))]>, - TB, OpSize32; -def SHLD64rri8 : RIi8<0xA4, MRMDestReg, - (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2, u8imm:$src3), - "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, - (i8 imm:$src3)))]>, - TB; -def SHRD64rri8 : RIi8<0xAC, MRMDestReg, - (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2, u8imm:$src3), - "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, - (i8 imm:$src3)))]>, - TB; -} // SchedRW -} // Constraints = "$src = $dst" - -let Uses = [CL], SchedRW = [WriteSHDmrcl] in { -def SHLD16mrCL : I<0xA5, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi16 addr:$dst), GR16:$src2, CL), - addr:$dst)]>, TB, OpSize16; -def SHRD16mrCL : I<0xAD, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, CL), - addr:$dst)]>, TB, OpSize16; - -def SHLD32mrCL : I<0xA5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi32 addr:$dst), GR32:$src2, CL), - addr:$dst)]>, TB, OpSize32; -def SHRD32mrCL : I<0xAD, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, CL), - addr:$dst)]>, TB, OpSize32; - -def SHLD64mrCL : RI<0xA5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi64 addr:$dst), GR64:$src2, CL), - addr:$dst)]>, TB; -def SHRD64mrCL : RI<0xAD, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, CL), - addr:$dst)]>, TB; -} // SchedRW - -let SchedRW = [WriteSHDmri] in { -def SHLD16mri8 : Ii8<0xA4, MRMDestMem, - (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3), - "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi16 addr:$dst), GR16:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize16; -def SHRD16mri8 : Ii8<0xAC, MRMDestMem, - (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3), - "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize16; - -def SHLD32mri8 : Ii8<0xA4, MRMDestMem, - (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3), - "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi32 addr:$dst), GR32:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize32; -def SHRD32mri8 : Ii8<0xAC, MRMDestMem, - (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3), - "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize32; - -def SHLD64mri8 : RIi8<0xA4, MRMDestMem, - (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3), - "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi64 addr:$dst), GR64:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB; -def SHRD64mri8 : RIi8<0xAC, MRMDestMem, - (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3), - "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB; -} // SchedRW - -} // Defs = [EFLAGS] - -// Sandy Bridge and newer Intel processors support faster rotates using -// SHLD to avoid a partial flag update on the normal rotate instructions. -let Predicates = [HasFastSHLDRotate], AddedComplexity = 5 in { - def : Pat<(rotl GR32:$src, (i8 imm:$shamt)), - (SHLD32rri8 GR32:$src, GR32:$src, imm:$shamt)>; - def : Pat<(rotl GR64:$src, (i8 imm:$shamt)), - (SHLD64rri8 GR64:$src, GR64:$src, imm:$shamt)>; -} - -def ROT32L2R_imm8 : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def ROT64L2R_imm8 : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -multiclass bmi_rotate { -let hasSideEffects = 0 in { - def ri : Ii8<0xF0, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, u8imm:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>, TAXD, VEX, Sched<[WriteShift]>; - let mayLoad = 1 in - def mi : Ii8<0xF0, MRMSrcMem, (outs RC:$dst), - (ins x86memop:$src1, u8imm:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>, TAXD, VEX, Sched<[WriteShiftLd]>; -} -} - -multiclass bmi_shift { -let hasSideEffects = 0 in { - def rr : I<0xF7, MRMSrcReg4VOp3, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>, - VEX, Sched<[WriteShift]>; - let mayLoad = 1 in - def rm : I<0xF7, MRMSrcMem4VOp3, - (outs RC:$dst), (ins x86memop:$src1, RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>, - VEX, Sched<[WriteShiftLd, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} -} - -let Predicates = [HasBMI2] in { - defm RORX32 : bmi_rotate<"rorx{l}", GR32, i32mem>; - defm RORX64 : bmi_rotate<"rorx{q}", GR64, i64mem>, VEX_W; - defm SARX32 : bmi_shift<"sarx{l}", GR32, i32mem>, T8XS; - defm SARX64 : bmi_shift<"sarx{q}", GR64, i64mem>, T8XS, VEX_W; - defm SHRX32 : bmi_shift<"shrx{l}", GR32, i32mem>, T8XD; - defm SHRX64 : bmi_shift<"shrx{q}", GR64, i64mem>, T8XD, VEX_W; - defm SHLX32 : bmi_shift<"shlx{l}", GR32, i32mem>, T8PD; - defm SHLX64 : bmi_shift<"shlx{q}", GR64, i64mem>, T8PD, VEX_W; - - // Prefer RORX which is non-destructive and doesn't update EFLAGS. - let AddedComplexity = 10 in { - def : Pat<(rotl GR32:$src, (i8 imm:$shamt)), - (RORX32ri GR32:$src, (ROT32L2R_imm8 imm:$shamt))>; - def : Pat<(rotl GR64:$src, (i8 imm:$shamt)), - (RORX64ri GR64:$src, (ROT64L2R_imm8 imm:$shamt))>; - } - - def : Pat<(rotl (loadi32 addr:$src), (i8 imm:$shamt)), - (RORX32mi addr:$src, (ROT32L2R_imm8 imm:$shamt))>; - def : Pat<(rotl (loadi64 addr:$src), (i8 imm:$shamt)), - (RORX64mi addr:$src, (ROT64L2R_imm8 imm:$shamt))>; - - // Prefer SARX/SHRX/SHLX over SAR/SHR/SHL with variable shift BUT not - // immedidate shift, i.e. the following code is considered better - // - // mov %edi, %esi - // shl $imm, %esi - // ... %edi, ... - // - // than - // - // movb $imm, %sil - // shlx %sil, %edi, %esi - // ... %edi, ... - // - let AddedComplexity = 1 in { - def : Pat<(sra GR32:$src1, GR8:$src2), - (SARX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra GR64:$src1, GR8:$src2), - (SARX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl GR32:$src1, GR8:$src2), - (SHRX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl GR64:$src1, GR8:$src2), - (SHRX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl GR32:$src1, GR8:$src2), - (SHLX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl GR64:$src1, GR8:$src2), - (SHLX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } - - // We prefer to use - // mov (%ecx), %esi - // shl $imm, $esi - // - // over - // - // movb $imm, %al - // shlx %al, (%ecx), %esi - // - // This priority is enforced by IsProfitableToFoldLoad. - def : Pat<(sra (loadi32 addr:$src1), GR8:$src2), - (SARX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra (loadi64 addr:$src1), GR8:$src2), - (SARX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl (loadi32 addr:$src1), GR8:$src2), - (SHRX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl (loadi64 addr:$src1), GR8:$src2), - (SHRX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl (loadi32 addr:$src1), GR8:$src2), - (SHLX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl (loadi64 addr:$src1), GR8:$src2), - (SHLX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} diff --git a/suite/synctools/tablegen/X86/X86InstrSystem.td b/suite/synctools/tablegen/X86/X86InstrSystem.td deleted file mode 100644 index 5bc58e298c..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrSystem.td +++ /dev/null @@ -1,755 +0,0 @@ -//===-- X86InstrSystem.td - System Instructions ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instructions that are generally used in -// privileged modes. These are not typically used by the compiler, but are -// supported for the assembler and disassembler. -// -//===----------------------------------------------------------------------===// - -let SchedRW = [WriteSystem] in { -let Defs = [RAX, RDX] in - def RDTSC : I<0x31, RawFrm, (outs), (ins), "rdtsc", [(X86rdtsc)]>, TB; - -let Defs = [RAX, RCX, RDX] in - def RDTSCP : I<0x01, MRM_F9, (outs), (ins), "rdtscp", [(X86rdtscp)]>, TB; - -// CPU flow control instructions - -let mayLoad = 1, mayStore = 0, hasSideEffects = 1, isTrap = 1 in { - def TRAP : I<0x0B, RawFrm, (outs), (ins), "ud2", [(trap)]>, TB; - - def UD1Wm : I<0xB9, MRMSrcMem, (outs), (ins GR16:$src1, i16mem:$src2), - "ud1{w} {$src2, $src1|$src1, $src2}", []>, TB, OpSize16; - def UD1Lm : I<0xB9, MRMSrcMem, (outs), (ins GR32:$src1, i32mem:$src2), - "ud1{l} {$src2, $src1|$src1, $src2}", []>, TB, OpSize32; - def UD1Qm : RI<0xB9, MRMSrcMem, (outs), (ins GR64:$src1, i64mem:$src2), - "ud1{q} {$src2, $src1|$src1, $src2}", []>, TB; - - def UD1Wr : I<0xB9, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2), - "ud1{w} {$src2, $src1|$src1, $src2}", []>, TB, OpSize16; - def UD1Lr : I<0xB9, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2), - "ud1{l} {$src2, $src1|$src1, $src2}", []>, TB, OpSize32; - def UD1Qr : RI<0xB9, MRMSrcReg, (outs), (ins GR64:$src1, GR64:$src2), - "ud1{q} {$src2, $src1|$src1, $src2}", []>, TB; -} - -def HLT : I<0xF4, RawFrm, (outs), (ins), "hlt", []>; -def RSM : I<0xAA, RawFrm, (outs), (ins), "rsm", []>, TB; - -// Interrupt and SysCall Instructions. -let Uses = [EFLAGS] in - def INTO : I<0xce, RawFrm, (outs), (ins), "into", []>, Requires<[Not64BitMode]>; - -def INT3 : I<0xcc, RawFrm, (outs), (ins), "int3", [(int_x86_int (i8 3))]>; -} // SchedRW - -// The long form of "int $3" turns into int3 as a size optimization. -// FIXME: This doesn't work because InstAlias can't match immediate constants. -//// def : InstAlias<"int\t$3", (INT3)>; - -let SchedRW = [WriteSystem] in { - -def INT : Ii8<0xcd, RawFrm, (outs), (ins u8imm:$trap), "int\t$trap", - [(int_x86_int imm:$trap)]>; - - -def SYSCALL : I<0x05, RawFrm, (outs), (ins), "syscall", []>, TB; -def SYSRET : I<0x07, RawFrm, (outs), (ins), "sysret{l}", []>, TB; -def SYSRET64 :RI<0x07, RawFrm, (outs), (ins), "sysretq", []>, TB, - Requires<[In64BitMode]>; - -def SYSENTER : I<0x34, RawFrm, (outs), (ins), "sysenter", []>, TB; - -def SYSEXIT : I<0x35, RawFrm, (outs), (ins), "sysexit{l}", []>, TB; -def SYSEXIT64 :RI<0x35, RawFrm, (outs), (ins), "sysexitq", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -def : Pat<(debugtrap), - (INT3)>, Requires<[NotPS4]>; -def : Pat<(debugtrap), - (INT (i8 0x41))>, Requires<[IsPS4]>; - -//===----------------------------------------------------------------------===// -// Input/Output Instructions. -// -let SchedRW = [WriteSystem] in { -let Defs = [AL], Uses = [DX] in -def IN8rr : I<0xEC, RawFrm, (outs), (ins), "in{b}\t{%dx, %al|al, dx}", []>; -let Defs = [AX], Uses = [DX] in -def IN16rr : I<0xED, RawFrm, (outs), (ins), "in{w}\t{%dx, %ax|ax, dx}", []>, - OpSize16; -let Defs = [EAX], Uses = [DX] in -def IN32rr : I<0xED, RawFrm, (outs), (ins), "in{l}\t{%dx, %eax|eax, dx}", []>, - OpSize32; - -let Defs = [AL] in -def IN8ri : Ii8<0xE4, RawFrm, (outs), (ins u8imm:$port), - "in{b}\t{$port, %al|al, $port}", []>; -let Defs = [AX] in -def IN16ri : Ii8<0xE5, RawFrm, (outs), (ins u8imm:$port), - "in{w}\t{$port, %ax|ax, $port}", []>, OpSize16; -let Defs = [EAX] in -def IN32ri : Ii8<0xE5, RawFrm, (outs), (ins u8imm:$port), - "in{l}\t{$port, %eax|eax, $port}", []>, OpSize32; - -let Uses = [DX, AL] in -def OUT8rr : I<0xEE, RawFrm, (outs), (ins), "out{b}\t{%al, %dx|dx, al}", []>; -let Uses = [DX, AX] in -def OUT16rr : I<0xEF, RawFrm, (outs), (ins), "out{w}\t{%ax, %dx|dx, ax}", []>, - OpSize16; -let Uses = [DX, EAX] in -def OUT32rr : I<0xEF, RawFrm, (outs), (ins), "out{l}\t{%eax, %dx|dx, eax}", []>, - OpSize32; - -let Uses = [AL] in -def OUT8ir : Ii8<0xE6, RawFrm, (outs), (ins u8imm:$port), - "out{b}\t{%al, $port|$port, al}", []>; -let Uses = [AX] in -def OUT16ir : Ii8<0xE7, RawFrm, (outs), (ins u8imm:$port), - "out{w}\t{%ax, $port|$port, ax}", []>, OpSize16; -let Uses = [EAX] in -def OUT32ir : Ii8<0xE7, RawFrm, (outs), (ins u8imm:$port), - "out{l}\t{%eax, $port|$port, eax}", []>, OpSize32; - -} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from debug registers - -let SchedRW = [WriteSystem] in { -def MOV32rd : I<0x21, MRMDestReg, (outs GR32:$dst), (ins DEBUG_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64rd : I<0x21, MRMDestReg, (outs GR64:$dst), (ins DEBUG_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; - -def MOV32dr : I<0x23, MRMSrcReg, (outs DEBUG_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64dr : I<0x23, MRMSrcReg, (outs DEBUG_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from control registers - -let SchedRW = [WriteSystem] in { -def MOV32rc : I<0x20, MRMDestReg, (outs GR32:$dst), (ins CONTROL_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64rc : I<0x20, MRMDestReg, (outs GR64:$dst), (ins CONTROL_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; - -def MOV32cr : I<0x22, MRMSrcReg, (outs CONTROL_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64cr : I<0x22, MRMSrcReg, (outs CONTROL_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Segment override instruction prefixes - -//let SchedRW = [WriteNop] in { -//def CS_PREFIX : I<0x2E, RawFrm, (outs), (ins), "cs", []>; -//def SS_PREFIX : I<0x36, RawFrm, (outs), (ins), "ss", []>; -//def DS_PREFIX : I<0x3E, RawFrm, (outs), (ins), "ds", []>; -//def ES_PREFIX : I<0x26, RawFrm, (outs), (ins), "es", []>; -//def FS_PREFIX : I<0x64, RawFrm, (outs), (ins), "fs", []>; -//def GS_PREFIX : I<0x65, RawFrm, (outs), (ins), "gs", []>; -//} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from segment registers. -// - -let SchedRW = [WriteMove] in { -def MOV16rs : I<0x8C, MRMDestReg, (outs GR16:$dst), (ins SEGMENT_REG:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rs : I<0x8C, MRMDestReg, (outs GR32:$dst), (ins SEGMENT_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rs : RI<0x8C, MRMDestReg, (outs GR64:$dst), (ins SEGMENT_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -let mayStore = 1 in { -def MOV16ms : I<0x8C, MRMDestMem, (outs), (ins i16mem:$dst, SEGMENT_REG:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>; -} -def MOV16sr : I<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32sr : I<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64sr : RI<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -let mayLoad = 1 in { -def MOV16sm : I<0x8E, MRMSrcMem, (outs SEGMENT_REG:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Segmentation support instructions. - -let SchedRW = [WriteSystem] in { -def SWAPGS : I<0x01, MRM_F8, (outs), (ins), "swapgs", []>, TB; - -let mayLoad = 1 in -def LAR16rm : I<0x02, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -def LAR16rr : I<0x02, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; - -// i16mem operand in LAR32rm and GR32 operand in LAR32rr is not a typo. -let mayLoad = 1 in -def LAR32rm : I<0x02, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "lar{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -def LAR32rr : I<0x02, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lar{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -// i16mem operand in LAR64rm and GR32 operand in LAR64rr is not a typo. -let mayLoad = 1 in -def LAR64rm : RI<0x02, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "lar{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; -def LAR64rr : RI<0x02, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "lar{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; - -// i16mem operand in LSL32rm and GR32 operand in LSL32rr is not a typo. -let mayLoad = 1 in -def LSL16rm : I<0x03, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lsl{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -def LSL16rr : I<0x03, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lsl{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -// i16mem operand in LSL64rm and GR32 operand in LSL64rr is not a typo. -let mayLoad = 1 in -def LSL32rm : I<0x03, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "lsl{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -def LSL32rr : I<0x03, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lsl{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -let mayLoad = 1 in -def LSL64rm : RI<0x03, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "lsl{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; -def LSL64rr : RI<0x03, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "lsl{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; - -def INVLPG : I<0x01, MRM7m, (outs), (ins i8mem:$addr), "invlpg\t$addr", []>, TB; - -def STR16r : I<0x00, MRM1r, (outs GR16:$dst), (ins), - "str{w}\t$dst", []>, TB, OpSize16; -def STR32r : I<0x00, MRM1r, (outs GR32:$dst), (ins), - "str{l}\t$dst", []>, TB, OpSize32; -def STR64r : RI<0x00, MRM1r, (outs GR64:$dst), (ins), - "str{q}\t$dst", []>, TB; -let mayStore = 1 in -def STRm : I<0x00, MRM1m, (outs), (ins i16mem:$dst), "str{w}\t$dst", []>, TB; - -def LTRr : I<0x00, MRM3r, (outs), (ins GR16:$src), "ltr{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LTRm : I<0x00, MRM3m, (outs), (ins i16mem:$src), "ltr{w}\t$src", []>, TB, NotMemoryFoldable; - -def PUSHCS16 : I<0x0E, RawFrm, (outs), (ins), "push{w}\t{%cs|cs}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHCS32 : I<0x0E, RawFrm, (outs), (ins), "push{l}\t{%cs|cs}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHSS16 : I<0x16, RawFrm, (outs), (ins), "push{w}\t{%ss|ss}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHSS32 : I<0x16, RawFrm, (outs), (ins), "push{l}\t{%ss|ss}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHDS16 : I<0x1E, RawFrm, (outs), (ins), "push{w}\t{%ds|ds}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHDS32 : I<0x1E, RawFrm, (outs), (ins), "push{l}\t{%ds|ds}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHES16 : I<0x06, RawFrm, (outs), (ins), "push{w}\t{%es|es}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHES32 : I<0x06, RawFrm, (outs), (ins), "push{l}\t{%es|es}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHFS16 : I<0xa0, RawFrm, (outs), (ins), "push{w}\t{%fs|fs}", []>, - OpSize16, TB; -def PUSHFS32 : I<0xa0, RawFrm, (outs), (ins), "push{l}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def PUSHGS16 : I<0xa8, RawFrm, (outs), (ins), "push{w}\t{%gs|gs}", []>, - OpSize16, TB; -def PUSHGS32 : I<0xa8, RawFrm, (outs), (ins), "push{l}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def PUSHFS64 : I<0xa0, RawFrm, (outs), (ins), "push{q}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; -def PUSHGS64 : I<0xa8, RawFrm, (outs), (ins), "push{q}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -// No "pop cs" instruction. -def POPSS16 : I<0x17, RawFrm, (outs), (ins), "pop{w}\t{%ss|ss}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPSS32 : I<0x17, RawFrm, (outs), (ins), "pop{l}\t{%ss|ss}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPDS16 : I<0x1F, RawFrm, (outs), (ins), "pop{w}\t{%ds|ds}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPDS32 : I<0x1F, RawFrm, (outs), (ins), "pop{l}\t{%ds|ds}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPES16 : I<0x07, RawFrm, (outs), (ins), "pop{w}\t{%es|es}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPES32 : I<0x07, RawFrm, (outs), (ins), "pop{l}\t{%es|es}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPFS16 : I<0xa1, RawFrm, (outs), (ins), "pop{w}\t{%fs|fs}", []>, - OpSize16, TB; -def POPFS32 : I<0xa1, RawFrm, (outs), (ins), "pop{l}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def POPFS64 : I<0xa1, RawFrm, (outs), (ins), "pop{q}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -def POPGS16 : I<0xa9, RawFrm, (outs), (ins), "pop{w}\t{%gs|gs}", []>, - OpSize16, TB; -def POPGS32 : I<0xa9, RawFrm, (outs), (ins), "pop{l}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def POPGS64 : I<0xa9, RawFrm, (outs), (ins), "pop{q}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -def LDS16rm : I<0xc5, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lds{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - Requires<[Not64BitMode]>; -def LDS32rm : I<0xc5, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lds{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - Requires<[Not64BitMode]>; - -def LSS16rm : I<0xb2, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lss{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LSS32rm : I<0xb2, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lss{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; -def LSS64rm : RI<0xb2, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lss{q}\t{$src, $dst|$dst, $src}", []>, TB; - -def LES16rm : I<0xc4, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "les{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - Requires<[Not64BitMode]>; -def LES32rm : I<0xc4, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "les{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - Requires<[Not64BitMode]>; - -def LFS16rm : I<0xb4, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lfs{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LFS32rm : I<0xb4, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lfs{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; -def LFS64rm : RI<0xb4, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lfs{q}\t{$src, $dst|$dst, $src}", []>, TB; - -def LGS16rm : I<0xb5, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lgs{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LGS32rm : I<0xb5, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lgs{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; - -def LGS64rm : RI<0xb5, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lgs\t{$src, $dst|$dst, $src}", []>, TB; - -def VERRr : I<0x00, MRM4r, (outs), (ins GR16:$seg), "verr\t$seg", []>, TB, NotMemoryFoldable; -def VERWr : I<0x00, MRM5r, (outs), (ins GR16:$seg), "verw\t$seg", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in { -def VERRm : I<0x00, MRM4m, (outs), (ins i16mem:$seg), "verr\t$seg", []>, TB, NotMemoryFoldable; -def VERWm : I<0x00, MRM5m, (outs), (ins i16mem:$seg), "verw\t$seg", []>, TB, NotMemoryFoldable; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Descriptor-table support instructions - -let SchedRW = [WriteSystem] in { -def SGDT16m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{w}\t$dst", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def SGDT32m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{l}\t$dst", []>, OpSize32, TB, Requires <[Not64BitMode]>; -def SGDT64m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{q}\t$dst", []>, TB, Requires <[In64BitMode]>; -def SIDT16m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{w}\t$dst", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def SIDT32m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{l}\t$dst", []>, OpSize32, TB, Requires <[Not64BitMode]>; -def SIDT64m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{q}\t$dst", []>, TB, Requires <[In64BitMode]>; -def SLDT16r : I<0x00, MRM0r, (outs GR16:$dst), (ins), - "sldt{w}\t$dst", []>, TB, OpSize16; -let mayStore = 1 in -def SLDT16m : I<0x00, MRM0m, (outs), (ins i16mem:$dst), - "sldt{w}\t$dst", []>, TB; -def SLDT32r : I<0x00, MRM0r, (outs GR32:$dst), (ins), - "sldt{l}\t$dst", []>, OpSize32, TB; - -// LLDT is not interpreted specially in 64-bit mode because there is no sign -// extension. -def SLDT64r : RI<0x00, MRM0r, (outs GR64:$dst), (ins), - "sldt{q}\t$dst", []>, TB, Requires<[In64BitMode]>; - -def LGDT16m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{w}\t$src", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def LGDT32m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{l}\t$src", []>, OpSize32, TB, Requires<[Not64BitMode]>; -def LGDT64m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{q}\t$src", []>, TB, Requires<[In64BitMode]>; -def LIDT16m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{w}\t$src", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def LIDT32m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{l}\t$src", []>, OpSize32, TB, Requires<[Not64BitMode]>; -def LIDT64m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{q}\t$src", []>, TB, Requires<[In64BitMode]>; -def LLDT16r : I<0x00, MRM2r, (outs), (ins GR16:$src), - "lldt{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LLDT16m : I<0x00, MRM2m, (outs), (ins i16mem:$src), - "lldt{w}\t$src", []>, TB, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Specialized register support -let SchedRW = [WriteSystem] in { -let Uses = [EAX, ECX, EDX] in -def WRMSR : I<0x30, RawFrm, (outs), (ins), "wrmsr", []>, TB; -let Defs = [EAX, EDX], Uses = [ECX] in -def RDMSR : I<0x32, RawFrm, (outs), (ins), "rdmsr", []>, TB; - -let Defs = [RAX, RDX], Uses = [ECX] in - def RDPMC : I<0x33, RawFrm, (outs), (ins), "rdpmc", [(X86rdpmc)]>, TB; - -def SMSW16r : I<0x01, MRM4r, (outs GR16:$dst), (ins), - "smsw{w}\t$dst", []>, OpSize16, TB; -def SMSW32r : I<0x01, MRM4r, (outs GR32:$dst), (ins), - "smsw{l}\t$dst", []>, OpSize32, TB; -// no m form encodable; use SMSW16m -def SMSW64r : RI<0x01, MRM4r, (outs GR64:$dst), (ins), - "smsw{q}\t$dst", []>, TB; - -// For memory operands, there is only a 16-bit form -def SMSW16m : I<0x01, MRM4m, (outs), (ins i16mem:$dst), - "smsw{w}\t$dst", []>, TB; - -def LMSW16r : I<0x01, MRM6r, (outs), (ins GR16:$src), - "lmsw{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LMSW16m : I<0x01, MRM6m, (outs), (ins i16mem:$src), - "lmsw{w}\t$src", []>, TB, NotMemoryFoldable; - -let Defs = [EAX, EBX, ECX, EDX], Uses = [EAX, ECX] in - def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Cache instructions -let SchedRW = [WriteSystem] in { -def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB; -def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", [(int_x86_wbinvd)]>, TB; - -// wbnoinvd is like wbinvd, except without invalidation -// encoding: like wbinvd + an 0xF3 prefix -def WBNOINVD : I<0x09, RawFrm, (outs), (ins), "wbnoinvd", - [(int_x86_wbnoinvd)]>, XS, - Requires<[HasWBNOINVD]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CET instructions -// Use with caution, availability is not predicated on features. -let SchedRW = [WriteSystem] in { - let Uses = [SSP] in { - let Defs = [SSP] in { - def INCSSPD : I<0xAE, MRM5r, (outs), (ins GR32:$src), "incsspd\t$src", - [(int_x86_incsspd GR32:$src)]>, XS; - def INCSSPQ : RI<0xAE, MRM5r, (outs), (ins GR64:$src), "incsspq\t$src", - [(int_x86_incsspq GR64:$src)]>, XS; - } // Defs SSP - - let Constraints = "$src = $dst" in { - def RDSSPD : I<0x1E, MRM1r, (outs GR32:$dst), (ins GR32:$src), - "rdsspd\t$dst", - [(set GR32:$dst, (int_x86_rdsspd GR32:$src))]>, XS; - def RDSSPQ : RI<0x1E, MRM1r, (outs GR64:$dst), (ins GR64:$src), - "rdsspq\t$dst", - [(set GR64:$dst, (int_x86_rdsspq GR64:$src))]>, XS; - } - - let Defs = [SSP] in { - def SAVEPREVSSP : I<0x01, MRM_EA, (outs), (ins), "saveprevssp", - [(int_x86_saveprevssp)]>, XS; - def RSTORSSP : I<0x01, MRM5m, (outs), (ins i32mem:$src), - "rstorssp\t$src", - [(int_x86_rstorssp addr:$src)]>, XS; - } // Defs SSP - } // Uses SSP - - def WRSSD : I<0xF6, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "wrssd\t{$src, $dst|$dst, $src}", - [(int_x86_wrssd GR32:$src, addr:$dst)]>, T8PS; - def WRSSQ : RI<0xF6, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "wrssq\t{$src, $dst|$dst, $src}", - [(int_x86_wrssq GR64:$src, addr:$dst)]>, T8PS; - def WRUSSD : I<0xF5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "wrussd\t{$src, $dst|$dst, $src}", - [(int_x86_wrussd GR32:$src, addr:$dst)]>, T8PD; - def WRUSSQ : RI<0xF5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "wrussq\t{$src, $dst|$dst, $src}", - [(int_x86_wrussq GR64:$src, addr:$dst)]>, T8PD; - - let Defs = [SSP] in { - let Uses = [SSP] in { - def SETSSBSY : I<0x01, MRM_E8, (outs), (ins), "setssbsy", - [(int_x86_setssbsy)]>, XS; - } // Uses SSP - - def CLRSSBSY : I<0xAE, MRM6m, (outs), (ins i32mem:$src), - "clrssbsy\t$src", - [(int_x86_clrssbsy addr:$src)]>, XS; - } // Defs SSP -} // SchedRW - -let SchedRW = [WriteSystem] in { - def ENDBR64 : I<0x1E, MRM_FA, (outs), (ins), "endbr64", []>, XS; - def ENDBR32 : I<0x1E, MRM_FB, (outs), (ins), "endbr32", []>, XS; -} // SchedRW - -//===----------------------------------------------------------------------===// -// XSAVE instructions -let SchedRW = [WriteSystem] in { -let Predicates = [HasXSAVE] in { -let Defs = [EDX, EAX], Uses = [ECX] in - def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB; - -let Uses = [EDX, EAX, ECX] in - def XSETBV : I<0x01, MRM_D1, (outs), (ins), - "xsetbv", - [(int_x86_xsetbv ECX, EDX, EAX)]>, TB; - -} // HasXSAVE - -let Uses = [EDX, EAX] in { -def XSAVE : I<0xAE, MRM4m, (outs), (ins opaquemem:$dst), - "xsave\t$dst", - [(int_x86_xsave addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE]>; -def XSAVE64 : RI<0xAE, MRM4m, (outs), (ins opaquemem:$dst), - "xsave64\t$dst", - [(int_x86_xsave64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE, In64BitMode]>; -def XRSTOR : I<0xAE, MRM5m, (outs), (ins opaquemem:$dst), - "xrstor\t$dst", - [(int_x86_xrstor addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE]>; -def XRSTOR64 : RI<0xAE, MRM5m, (outs), (ins opaquemem:$dst), - "xrstor64\t$dst", - [(int_x86_xrstor64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE, In64BitMode]>; -def XSAVEOPT : I<0xAE, MRM6m, (outs), (ins opaquemem:$dst), - "xsaveopt\t$dst", - [(int_x86_xsaveopt addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVEOPT]>; -def XSAVEOPT64 : RI<0xAE, MRM6m, (outs), (ins opaquemem:$dst), - "xsaveopt64\t$dst", - [(int_x86_xsaveopt64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVEOPT, In64BitMode]>; -def XSAVEC : I<0xC7, MRM4m, (outs), (ins opaquemem:$dst), - "xsavec\t$dst", - [(int_x86_xsavec addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVEC]>; -def XSAVEC64 : RI<0xC7, MRM4m, (outs), (ins opaquemem:$dst), - "xsavec64\t$dst", - [(int_x86_xsavec64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVEC, In64BitMode]>; -def XSAVES : I<0xC7, MRM5m, (outs), (ins opaquemem:$dst), - "xsaves\t$dst", - [(int_x86_xsaves addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES]>; -def XSAVES64 : RI<0xC7, MRM5m, (outs), (ins opaquemem:$dst), - "xsaves64\t$dst", - [(int_x86_xsaves64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVE, In64BitMode]>; -def XRSTORS : I<0xC7, MRM3m, (outs), (ins opaquemem:$dst), - "xrstors\t$dst", - [(int_x86_xrstors addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES]>; -def XRSTORS64 : RI<0xC7, MRM3m, (outs), (ins opaquemem:$dst), - "xrstors64\t$dst", - [(int_x86_xrstors64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES, In64BitMode]>; -} // Uses -} // SchedRW - -//===----------------------------------------------------------------------===// -// VIA PadLock crypto instructions -let Defs = [RAX, RDI], Uses = [RDX, RDI], SchedRW = [WriteSystem] in - def XSTORE : I<0xa7, MRM_C0, (outs), (ins), "xstore", []>, TB; - -// def : InstAlias<"xstorerng", (XSTORE)>; - -let SchedRW = [WriteSystem] in { -let Defs = [RSI, RDI], Uses = [RBX, RDX, RSI, RDI] in { - def XCRYPTECB : I<0xa7, MRM_C8, (outs), (ins), "xcryptecb", []>, TB; - def XCRYPTCBC : I<0xa7, MRM_D0, (outs), (ins), "xcryptcbc", []>, TB; - def XCRYPTCTR : I<0xa7, MRM_D8, (outs), (ins), "xcryptctr", []>, TB; - def XCRYPTCFB : I<0xa7, MRM_E0, (outs), (ins), "xcryptcfb", []>, TB; - def XCRYPTOFB : I<0xa7, MRM_E8, (outs), (ins), "xcryptofb", []>, TB; -} - -let Defs = [RAX, RSI, RDI], Uses = [RAX, RSI, RDI] in { - def XSHA1 : I<0xa6, MRM_C8, (outs), (ins), "xsha1", []>, TB; - def XSHA256 : I<0xa6, MRM_D0, (outs), (ins), "xsha256", []>, TB; -} -let Defs = [RAX, RDX, RSI], Uses = [RAX, RSI] in - def MONTMUL : I<0xa6, MRM_C0, (outs), (ins), "montmul", []>, TB; -} // SchedRW - -/* -//==-----------------------------------------------------------------------===// -// PKU - enable protection key -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - def WRPKRU : PseudoI<(outs), (ins GR32:$src), - [(int_x86_wrpkru GR32:$src)]>; - def RDPKRU : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_rdpkru))]>; -} -*/ - -let SchedRW = [WriteSystem] in { -let Defs = [EAX, EDX], Uses = [ECX] in - def RDPKRUr : I<0x01, MRM_EE, (outs), (ins), "rdpkru", []>, TB; -let Uses = [EAX, ECX, EDX] in - def WRPKRUr : I<0x01, MRM_EF, (outs), (ins), "wrpkru", []>, TB; -} // SchedRW - -//===----------------------------------------------------------------------===// -// FS/GS Base Instructions -let Predicates = [HasFSGSBase, In64BitMode], SchedRW = [WriteSystem] in { - def RDFSBASE : I<0xAE, MRM0r, (outs GR32:$dst), (ins), - "rdfsbase{l}\t$dst", - [(set GR32:$dst, (int_x86_rdfsbase_32))]>, XS; - def RDFSBASE64 : RI<0xAE, MRM0r, (outs GR64:$dst), (ins), - "rdfsbase{q}\t$dst", - [(set GR64:$dst, (int_x86_rdfsbase_64))]>, XS; - def RDGSBASE : I<0xAE, MRM1r, (outs GR32:$dst), (ins), - "rdgsbase{l}\t$dst", - [(set GR32:$dst, (int_x86_rdgsbase_32))]>, XS; - def RDGSBASE64 : RI<0xAE, MRM1r, (outs GR64:$dst), (ins), - "rdgsbase{q}\t$dst", - [(set GR64:$dst, (int_x86_rdgsbase_64))]>, XS; - def WRFSBASE : I<0xAE, MRM2r, (outs), (ins GR32:$src), - "wrfsbase{l}\t$src", - [(int_x86_wrfsbase_32 GR32:$src)]>, XS; - def WRFSBASE64 : RI<0xAE, MRM2r, (outs), (ins GR64:$src), - "wrfsbase{q}\t$src", - [(int_x86_wrfsbase_64 GR64:$src)]>, XS; - def WRGSBASE : I<0xAE, MRM3r, (outs), (ins GR32:$src), - "wrgsbase{l}\t$src", - [(int_x86_wrgsbase_32 GR32:$src)]>, XS; - def WRGSBASE64 : RI<0xAE, MRM3r, (outs), (ins GR64:$src), - "wrgsbase{q}\t$src", - [(int_x86_wrgsbase_64 GR64:$src)]>, XS; -} - -//===----------------------------------------------------------------------===// -// INVPCID Instruction -let SchedRW = [WriteSystem] in { -def INVPCID32 : I<0x82, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invpcid\t{$src2, $src1|$src1, $src2}", - [(int_x86_invpcid GR32:$src1, addr:$src2)]>, T8PD, - Requires<[Not64BitMode, HasINVPCID]>; -def INVPCID64 : I<0x82, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invpcid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode, HasINVPCID]>; -} // SchedRW - -let Predicates = [In64BitMode, HasINVPCID] in { - // The instruction can only use a 64 bit register as the register argument - // in 64 bit mode, while the intrinsic only accepts a 32 bit argument - // corresponding to it. - // The accepted values for now are 0,1,2,3 anyways (see Intel SDM -- INVCPID - // type),/ so it doesn't hurt us that one can't supply a 64 bit value here. - def : Pat<(int_x86_invpcid GR32:$src1, addr:$src2), - (INVPCID64 - (SUBREG_TO_REG (i64 0), (MOV32rr GR32:$src1), sub_32bit), - addr:$src2)>; -} - - -//===----------------------------------------------------------------------===// -// SMAP Instruction -let Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def CLAC : I<0x01, MRM_CA, (outs), (ins), "clac", []>, TB; - def STAC : I<0x01, MRM_CB, (outs), (ins), "stac", []>, TB; -} - -//===----------------------------------------------------------------------===// -// SMX Instruction -let SchedRW = [WriteSystem] in { -let Uses = [RAX, RBX, RCX, RDX], Defs = [RAX, RBX, RCX] in { - def GETSEC : I<0x37, RawFrm, (outs), (ins), "getsec", []>, TB; -} // Uses, Defs -} // SchedRW - -//===----------------------------------------------------------------------===// -// TS flag control instruction. -let SchedRW = [WriteSystem] in { -def CLTS : I<0x06, RawFrm, (outs), (ins), "clts", []>, TB; -} - -//===----------------------------------------------------------------------===// -// IF (inside EFLAGS) management instructions. -let SchedRW = [WriteSystem], Uses = [EFLAGS], Defs = [EFLAGS] in { -def CLI : I<0xFA, RawFrm, (outs), (ins), "cli", []>; -def STI : I<0xFB, RawFrm, (outs), (ins), "sti", []>; -} - -//===----------------------------------------------------------------------===// -// RDPID Instruction -let SchedRW = [WriteSystem] in { -def RDPID32 : I<0xC7, MRM7r, (outs GR32:$dst), (ins), - "rdpid\t$dst", [(set GR32:$dst, (int_x86_rdpid))]>, XS, - Requires<[Not64BitMode, HasRDPID]>; -def RDPID64 : I<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdpid\t$dst", []>, XS, - Requires<[In64BitMode, HasRDPID]>; -} // SchedRW - -let Predicates = [In64BitMode, HasRDPID] in { - // Due to silly instruction definition, we have to compensate for the - // instruction outputting a 64-bit register. - def : Pat<(int_x86_rdpid), - (EXTRACT_SUBREG (RDPID64), sub_32bit)>; -} - - -//===----------------------------------------------------------------------===// -// PTWRITE Instruction - Write Data to a Processor Trace Packet -let SchedRW = [WriteSystem] in { -def PTWRITEm: I<0xAE, MRM4m, (outs), (ins i32mem:$dst), - "ptwrite{l}\t$dst", [(int_x86_ptwrite32 (loadi32 addr:$dst))]>, XS, - Requires<[HasPTWRITE]>; -def PTWRITE64m : RI<0xAE, MRM4m, (outs), (ins i64mem:$dst), - "ptwrite{q}\t$dst", [(int_x86_ptwrite64 (loadi64 addr:$dst))]>, XS, - Requires<[In64BitMode, HasPTWRITE]>; - -def PTWRITEr : I<0xAE, MRM4r, (outs), (ins GR32:$dst), - "ptwrite{l}\t$dst", [(int_x86_ptwrite32 GR32:$dst)]>, XS, - Requires<[HasPTWRITE]>; -def PTWRITE64r : RI<0xAE, MRM4r, (outs), (ins GR64:$dst), - "ptwrite{q}\t$dst", [(int_x86_ptwrite64 GR64:$dst)]>, XS, - Requires<[In64BitMode, HasPTWRITE]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Platform Configuration instruction - -// From ISA docs: -// "This instruction is used to execute functions for configuring platform -// features. -// EAX: Leaf function to be invoked. -// RBX/RCX/RDX: Leaf-specific purpose." -// "Successful execution of the leaf clears RAX (set to zero) and ZF, CF, PF, -// AF, OF, and SF are cleared. In case of failure, the failure reason is -// indicated in RAX with ZF set to 1 and CF, PF, AF, OF, and SF are cleared." -// Thus all these mentioned registers are considered clobbered. - -let SchedRW = [WriteSystem] in { -let Uses = [RAX, RBX, RCX, RDX], Defs = [RAX, RBX, RCX, RDX, EFLAGS] in - def PCONFIG : I<0x01, MRM_C5, (outs), (ins), "pconfig", []>, TB, - Requires<[HasPCONFIG]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrTSX.td b/suite/synctools/tablegen/X86/X86InstrTSX.td deleted file mode 100644 index 8b9f723a41..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrTSX.td +++ /dev/null @@ -1,60 +0,0 @@ -//===-- X86InstrVMX.td - TSX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel TSX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// TSX instructions - -def X86xtest: SDNode<"X86ISD::XTEST", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -let SchedRW = [WriteSystem] in { - -//let usesCustomInserter = 1 in -//def XBEGIN : I<0, Pseudo, (outs GR32:$dst), (ins), -// "# XBEGIN", [(set GR32:$dst, (int_x86_xbegin))]>, -// Requires<[HasRTM]>; - -let isBranch = 1, isTerminator = 1, Defs = [EAX] in { -def XBEGIN_2 : Ii16PCRel<0xc7, MRM_F8, (outs), (ins brtarget16:$dst), - "xbegin\t$dst", []>, OpSize16; -def XBEGIN_4 : Ii32PCRel<0xc7, MRM_F8, (outs), (ins brtarget32:$dst), - "xbegin\t$dst", []>, OpSize32; -} - -// Pseudo instruction to fake the definition of EAX on the fallback code path. -//let isPseudo = 1, Defs = [EAX] in { -//def XABORT_DEF : I<0, Pseudo, (outs), (ins), "# XABORT DEF", []>; -//} - -def XEND : I<0x01, MRM_D5, (outs), (ins), - "xend", [(int_x86_xend)]>, TB, Requires<[HasRTM]>; - -let Defs = [EFLAGS] in -def XTEST : I<0x01, MRM_D6, (outs), (ins), - "xtest", [(set EFLAGS, (X86xtest))]>, TB, Requires<[HasRTM]>; - -def XABORT : Ii8<0xc6, MRM_F8, (outs), (ins i8imm:$imm), - "xabort\t$imm", - [(int_x86_xabort imm:$imm)]>, Requires<[HasRTM]>; -} // SchedRW - -// HLE prefixes -let SchedRW = [WriteSystem] in { - -let isAsmParserOnly = 1 in { -def XACQUIRE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "xacquire", []>; -def XRELEASE_PREFIX : I<0xF3, RawFrm, (outs), (ins), "xrelease", []>; -} - -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrVMX.td b/suite/synctools/tablegen/X86/X86InstrVMX.td deleted file mode 100644 index 06a438ebfc..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrVMX.td +++ /dev/null @@ -1,88 +0,0 @@ -//===-- X86InstrVMX.td - VMX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel VMX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// VMX instructions - -let SchedRW = [WriteSystem] in { -// 66 0F 38 80 -def INVEPT32 : I<0x80, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invept\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[Not64BitMode]>; -def INVEPT64 : I<0x80, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invept\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode]>; - -// 66 0F 38 81 -def INVVPID32 : I<0x81, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invvpid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[Not64BitMode]>; -def INVVPID64 : I<0x81, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invvpid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode]>; - -// 0F 01 C1 -def VMCALL : I<0x01, MRM_C1, (outs), (ins), "vmcall", []>, TB; -def VMCLEARm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), - "vmclear\t$vmcs", []>, PD; - -// OF 01 D4 -def VMFUNC : I<0x01, MRM_D4, (outs), (ins), "vmfunc", []>, TB; - -// 0F 01 C2 -def VMLAUNCH : I<0x01, MRM_C2, (outs), (ins), "vmlaunch", []>, TB; - -// 0F 01 C3 -def VMRESUME : I<0x01, MRM_C3, (outs), (ins), "vmresume", []>, TB; -def VMPTRLDm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), - "vmptrld\t$vmcs", []>, PS; -def VMPTRSTm : I<0xC7, MRM7m, (outs), (ins i64mem:$vmcs), - "vmptrst\t$vmcs", []>, PS; -def VMREAD64rr : I<0x78, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "vmread{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMREAD32rr : I<0x78, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "vmread{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; - -let mayStore = 1 in { -def VMREAD64mr : I<0x78, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "vmread{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMREAD32mr : I<0x78, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "vmread{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; -} // mayStore - -def VMWRITE64rr : I<0x79, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "vmwrite{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMWRITE32rr : I<0x79, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "vmwrite{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; - -let mayLoad = 1 in { -def VMWRITE64rm : I<0x79, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "vmwrite{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMWRITE32rm : I<0x79, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "vmwrite{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; -} // mayLoad - -// 0F 01 C4 -def VMXOFF : I<0x01, MRM_C4, (outs), (ins), "vmxoff", []>, TB; -def VMXON : I<0xC7, MRM6m, (outs), (ins i64mem:$vmxon), - "vmxon\t$vmxon", []>, XS; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/X86InstrVecCompiler.td b/suite/synctools/tablegen/X86/X86InstrVecCompiler.td deleted file mode 100644 index 322bdb74e2..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrVecCompiler.td +++ /dev/null @@ -1,511 +0,0 @@ -//===- X86InstrVecCompiler.td - Vector Compiler Patterns ---*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the various vector pseudo instructions used by the -// compiler, as well as Pat patterns used during instruction selection. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// No op bitconverts -//===----------------------------------------------------------------------===// - -// Bitcasts between 128-bit vector types. Return the original type since -// no instruction is needed for the conversion -def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v8i16 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v16i8 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v2f64 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v4f32 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v2i64 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v8i16 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v16i8 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v2f64 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v4f32 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v2i64 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v4i32 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v16i8 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v2f64 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v4f32 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v2i64 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v4i32 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v8i16 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v2f64 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v4f32 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v2i64 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v8i16 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v16i8 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v2i64 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v4i32 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v8i16 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v16i8 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v4f32 VR128:$src))), (v2f64 VR128:$src)>; - -// Bitcasts between 256-bit vector types. Return the original type since -// no instruction is needed for the conversion -def : Pat<(v4i64 (bitconvert (v8i32 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v16i16 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v32i8 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v8f32 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v4f64 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v4i64 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v16i16 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v32i8 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v4f64 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v8f32 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v4i64 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v8i32 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v32i8 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v4f64 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v8f32 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v4i64 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v8i32 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v16i16 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v4f64 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v8f32 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v4i64 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v8i32 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v16i16 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v32i8 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v4f64 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v4i64 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v8i32 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v16i16 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v32i8 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v8f32 VR256:$src))), (v4f64 VR256:$src)>; - -// Bitcasts between 512-bit vector types. Return the original type since -// no instruction is needed for the conversion. -def : Pat<(v8f64 (bitconvert (v8i64 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v16i32 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v32i16 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v64i8 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v16f32 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v8i64 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v16i32 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v32i16 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v64i8 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v8f64 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v16i32 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v32i16 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v64i8 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v8f64 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v16f32 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v8i64 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v16f32 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v32i16 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v64i8 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v8f64 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v8i64 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v16i32 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v64i8 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v8f64 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v16f32 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v8i64 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v16i32 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v32i16 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v8f64 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v16f32 VR512:$src))), (v64i8 VR512:$src)>; - - -//===----------------------------------------------------------------------===// -// Non-instruction patterns -//===----------------------------------------------------------------------===// - -// A vector extract of the first f32/f64 position is a subregister copy -def : Pat<(f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - (COPY_TO_REGCLASS (v4f32 VR128:$src), FR32)>; -def : Pat<(f64 (extractelt (v2f64 VR128:$src), (iPTR 0))), - (COPY_TO_REGCLASS (v2f64 VR128:$src), FR64)>; - -// Implicitly promote a 32-bit scalar to a vector. -def : Pat<(v4f32 (scalar_to_vector FR32:$src)), - (COPY_TO_REGCLASS FR32:$src, VR128)>; -// Implicitly promote a 64-bit scalar to a vector. -def : Pat<(v2f64 (scalar_to_vector FR64:$src)), - (COPY_TO_REGCLASS FR64:$src, VR128)>; - - -//===----------------------------------------------------------------------===// -// Subvector tricks -//===----------------------------------------------------------------------===// - -// Patterns for insert_subvector/extract_subvector to/from index=0 -multiclass subvector_subreg_lowering { - def : Pat<(subVT (extract_subvector (VT RC:$src), (iPTR 0))), - (subVT (EXTRACT_SUBREG RC:$src, subIdx))>; - - def : Pat<(VT (insert_subvector undef, subRC:$src, (iPTR 0))), - (VT (INSERT_SUBREG (IMPLICIT_DEF), subRC:$src, subIdx))>; -} - -// A 128-bit subvector extract from the first 256-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 256-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - -// A 128-bit subvector extract from the first 512-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 512-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - -// A 128-bit subvector extract from the first 512-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 512-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - - -multiclass subvector_store_lowering { - def : Pat<(alignedstore (DstTy (extract_subvector - (SrcTy RC:$src), (iPTR 0))), addr:$dst), - (!cast("VMOV"#AlignedStr#"mr") addr:$dst, - (DstTy (EXTRACT_SUBREG RC:$src, SubIdx)))>; - - def : Pat<(store (DstTy (extract_subvector - (SrcTy RC:$src), (iPTR 0))), addr:$dst), - (!cast("VMOV"#UnalignedStr#"mr") addr:$dst, - (DstTy (EXTRACT_SUBREG RC:$src, SubIdx)))>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : subvector_store_lowering<"APD", "UPD", VR256X, v2f64, v4f64, sub_xmm>; - defm : subvector_store_lowering<"APS", "UPS", VR256X, v4f32, v8f32, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v2i64, v4i64, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v4i32, v8i32, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v8i16, v16i16, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v16i8, v32i8, sub_xmm>; -} - -let Predicates = [HasVLX] in { - // Special patterns for storing subvector extracts of lower 128-bits - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ128", "UPDZ128", VR256X, v2f64, v4f64, - sub_xmm>; - defm : subvector_store_lowering<"APSZ128", "UPSZ128", VR256X, v4f32, v8f32, - sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v2i64, - v4i64, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v4i32, - v8i32, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v8i16, - v16i16, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v16i8, - v32i8, sub_xmm>; - - // Special patterns for storing subvector extracts of lower 128-bits of 512. - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ128", "UPDZ128", VR512, v2f64, v8f64, - sub_xmm>; - defm : subvector_store_lowering<"APSZ128", "UPSZ128", VR512, v4f32, v16f32, - sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v2i64, - v8i64, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v4i32, - v16i32, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v8i16, - v32i16, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v16i8, - v64i8, sub_xmm>; - - // Special patterns for storing subvector extracts of lower 256-bits of 512. - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ256", "UPDZ256", VR512, v4f64, v8f64, - sub_ymm>; - defm : subvector_store_lowering<"APSZ256", "UPSZ256", VR512, v8f32, v16f32, - sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v4i64, - v8i64, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v8i32, - v16i32, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v16i16, - v32i16, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v32i8, - v64i8, sub_ymm>; -} - -// If we're inserting into an all zeros vector, just use a plain move which -// will zero the upper bits. A post-isel hook will take care of removing -// any moves that we can prove are unnecessary. -multiclass subvec_zero_lowering { - def : Pat<(DstTy (insert_subvector (bitconvert (ZeroTy immAllZerosV)), - (SrcTy RC:$src), (iPTR 0))), - (SUBREG_TO_REG (i64 0), - (SrcTy (!cast("VMOV"#MoveStr#"rr") RC:$src)), SubIdx)>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : subvec_zero_lowering<"APD", VR128, v4f64, v2f64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"APS", VR128, v8f32, v4f32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v4i64, v2i64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v8i32, v4i32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v16i16, v8i16, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v32i8, v16i8, v8i32, sub_xmm>; -} - -let Predicates = [HasVLX] in { - defm : subvec_zero_lowering<"APDZ128", VR128X, v4f64, v2f64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"APSZ128", VR128X, v8f32, v4f32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v4i64, v2i64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v8i32, v4i32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v16i16, v8i16, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v32i8, v16i8, v8i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDZ128", VR128X, v8f64, v2f64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"APSZ128", VR128X, v16f32, v4f32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v8i64, v2i64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v16i32, v4i32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v32i16, v8i16, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v64i8, v16i8, v16i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDZ256", VR256X, v8f64, v4f64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"APSZ256", VR256X, v16f32, v8f32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v8i64, v4i64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v16i32, v8i32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v32i16, v16i16, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v64i8, v32i8, v16i32, sub_ymm>; -} - -let Predicates = [HasAVX512, NoVLX] in { - defm : subvec_zero_lowering<"APD", VR128, v8f64, v2f64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"APS", VR128, v16f32, v4f32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v8i64, v2i64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v16i32, v4i32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v32i16, v8i16, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v64i8, v16i8, v16i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDY", VR256, v8f64, v4f64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"APSY", VR256, v16f32, v8f32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v8i64, v4i64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v16i32, v8i32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v32i16, v16i16, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v64i8, v32i8, v16i32, sub_ymm>; -} - -class maskzeroupper : - PatLeaf<(vt RC:$src), [{ - return isMaskZeroExtended(N); - }]>; - -def maskzeroupperv1i1 : maskzeroupper; -def maskzeroupperv2i1 : maskzeroupper; -def maskzeroupperv4i1 : maskzeroupper; -def maskzeroupperv8i1 : maskzeroupper; -def maskzeroupperv16i1 : maskzeroupper; -def maskzeroupperv32i1 : maskzeroupper; - -// The patterns determine if we can depend on the upper bits of a mask register -// being zeroed by the previous operation so that we can skip explicit -// zeroing. -let Predicates = [HasBWI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv16i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK16:$src, VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv16i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK16:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv32i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK32:$src, VK64)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK16)>; - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK16)>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK8)>; -} - -let Predicates = [HasVLX, HasDQI] in { - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK8)>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK8)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK16)>; - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK16)>; -} - -let Predicates = [HasBWI, HasVLX] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK32)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK64)>; -} - -// If the bits are not zero we have to fall back to explicitly zeroing by -// using shifts. -let Predicates = [HasAVX512] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK1:$mask, VK16), - (i8 15)), (i8 15))>; - - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK2:$mask, VK16), - (i8 14)), (i8 14))>; - - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK4:$mask, VK16), - (i8 12)), (i8 12))>; -} - -let Predicates = [HasAVX512, NoDQI] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK8:$mask, VK16), - (i8 8)), (i8 8))>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK16)>; - - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK1:$mask, VK8), - (i8 7)), (i8 7))>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK2:$mask, VK8), - (i8 6)), (i8 6))>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK4:$mask, VK8), - (i8 4)), (i8 4))>; -} - -let Predicates = [HasBWI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v16i1 VK16:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVWkk VK16:$mask), VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v16i1 VK16:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVWkk VK16:$mask), VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v32i1 VK32:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVDkk VK32:$mask), VK64)>; -} - -let Predicates = [HasBWI, NoDQI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK8:$mask, VK32), - (i8 24)), (i8 24))>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK8:$mask, VK64), - (i8 56)), (i8 56))>; -} - -let Predicates = [HasBWI, HasDQI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK64)>; -} - -let Predicates = [HasBWI, HasVLX] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK1:$mask, VK32), - (i8 31)), (i8 31))>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK2:$mask, VK32), - (i8 30)), (i8 30))>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK4:$mask, VK32), - (i8 28)), (i8 28))>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK1:$mask, VK64), - (i8 63)), (i8 63))>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK2:$mask, VK64), - (i8 62)), (i8 62))>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK4:$mask, VK64), - (i8 60)), (i8 60))>; -} diff --git a/suite/synctools/tablegen/X86/X86InstrXOP.td b/suite/synctools/tablegen/X86/X86InstrXOP.td deleted file mode 100644 index ff3e3be48a..0000000000 --- a/suite/synctools/tablegen/X86/X86InstrXOP.td +++ /dev/null @@ -1,446 +0,0 @@ -//===-- X86InstrXOP.td - XOP Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes XOP (eXtended OPerations) -// -//===----------------------------------------------------------------------===// - -multiclass xop2op opc, string OpcodeStr, Intrinsic Int, PatFrag memop> { - def rr : IXOP, XOP, Sched<[SchedWritePHAdd.XMM]>; - def rm : IXOP, XOP, - Sched<[SchedWritePHAdd.XMM.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPHSUBWD : xop2op<0xE2, "vphsubwd", int_x86_xop_vphsubwd, loadv2i64>; - defm VPHSUBDQ : xop2op<0xE3, "vphsubdq", int_x86_xop_vphsubdq, loadv2i64>; - defm VPHSUBBW : xop2op<0xE1, "vphsubbw", int_x86_xop_vphsubbw, loadv2i64>; - defm VPHADDWQ : xop2op<0xC7, "vphaddwq", int_x86_xop_vphaddwq, loadv2i64>; - defm VPHADDWD : xop2op<0xC6, "vphaddwd", int_x86_xop_vphaddwd, loadv2i64>; - defm VPHADDUWQ : xop2op<0xD7, "vphadduwq", int_x86_xop_vphadduwq, loadv2i64>; - defm VPHADDUWD : xop2op<0xD6, "vphadduwd", int_x86_xop_vphadduwd, loadv2i64>; - defm VPHADDUDQ : xop2op<0xDB, "vphaddudq", int_x86_xop_vphaddudq, loadv2i64>; - defm VPHADDUBW : xop2op<0xD1, "vphaddubw", int_x86_xop_vphaddubw, loadv2i64>; - defm VPHADDUBQ : xop2op<0xD3, "vphaddubq", int_x86_xop_vphaddubq, loadv2i64>; - defm VPHADDUBD : xop2op<0xD2, "vphaddubd", int_x86_xop_vphaddubd, loadv2i64>; - defm VPHADDDQ : xop2op<0xCB, "vphadddq", int_x86_xop_vphadddq, loadv2i64>; - defm VPHADDBW : xop2op<0xC1, "vphaddbw", int_x86_xop_vphaddbw, loadv2i64>; - defm VPHADDBQ : xop2op<0xC3, "vphaddbq", int_x86_xop_vphaddbq, loadv2i64>; - defm VPHADDBD : xop2op<0xC2, "vphaddbd", int_x86_xop_vphaddbd, loadv2i64>; -} - -// Scalar load 2 addr operand instructions -multiclass xop2opsld opc, string OpcodeStr, Intrinsic Int, - Operand memop, ComplexPattern mem_cpat, - X86FoldableSchedWrite sched> { - def rr : IXOP, XOP, Sched<[sched]>; - def rm : IXOP, XOP, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass xop2op128 opc, string OpcodeStr, Intrinsic Int, - PatFrag memop, X86FoldableSchedWrite sched> { - def rr : IXOP, XOP, Sched<[sched]>; - def rm : IXOP, XOP, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass xop2op256 opc, string OpcodeStr, Intrinsic Int, - PatFrag memop, X86FoldableSchedWrite sched> { - def Yrr : IXOP, XOP, VEX_L, Sched<[sched]>; - def Yrm : IXOP, XOP, VEX_L, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedSingle in { - defm VFRCZSS : xop2opsld<0x82, "vfrczss", int_x86_xop_vfrcz_ss, - ssmem, sse_load_f32, SchedWriteFRnd.Scl>; - defm VFRCZPS : xop2op128<0x80, "vfrczps", int_x86_xop_vfrcz_ps, loadv4f32, - SchedWriteFRnd.XMM>; - defm VFRCZPS : xop2op256<0x80, "vfrczps", int_x86_xop_vfrcz_ps_256, loadv8f32, - SchedWriteFRnd.YMM>; -} - -let ExeDomain = SSEPackedDouble in { - defm VFRCZSD : xop2opsld<0x83, "vfrczsd", int_x86_xop_vfrcz_sd, - sdmem, sse_load_f64, SchedWriteFRnd.Scl>; - defm VFRCZPD : xop2op128<0x81, "vfrczpd", int_x86_xop_vfrcz_pd, loadv2f64, - SchedWriteFRnd.XMM>; - defm VFRCZPD : xop2op256<0x81, "vfrczpd", int_x86_xop_vfrcz_pd_256, loadv4f64, - SchedWriteFRnd.YMM>; -} - -multiclass xop3op opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def rr : IXOP, - XOP, Sched<[sched]>; - def rm : IXOP, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd]>; - def mr : IXOP, - XOP, Sched<[sched.Folded, ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : IXOP, - XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPROTB : xop3op<0x90, "vprotb", rotl, v16i8, SchedWriteVarVecShift.XMM>; - defm VPROTD : xop3op<0x92, "vprotd", rotl, v4i32, SchedWriteVarVecShift.XMM>; - defm VPROTQ : xop3op<0x93, "vprotq", rotl, v2i64, SchedWriteVarVecShift.XMM>; - defm VPROTW : xop3op<0x91, "vprotw", rotl, v8i16, SchedWriteVarVecShift.XMM>; - defm VPSHAB : xop3op<0x98, "vpshab", X86vpsha, v16i8, SchedWriteVarVecShift.XMM>; - defm VPSHAD : xop3op<0x9A, "vpshad", X86vpsha, v4i32, SchedWriteVarVecShift.XMM>; - defm VPSHAQ : xop3op<0x9B, "vpshaq", X86vpsha, v2i64, SchedWriteVarVecShift.XMM>; - defm VPSHAW : xop3op<0x99, "vpshaw", X86vpsha, v8i16, SchedWriteVarVecShift.XMM>; - defm VPSHLB : xop3op<0x94, "vpshlb", X86vpshl, v16i8, SchedWriteVarVecShift.XMM>; - defm VPSHLD : xop3op<0x96, "vpshld", X86vpshl, v4i32, SchedWriteVarVecShift.XMM>; - defm VPSHLQ : xop3op<0x97, "vpshlq", X86vpshl, v2i64, SchedWriteVarVecShift.XMM>; - defm VPSHLW : xop3op<0x95, "vpshlw", X86vpshl, v8i16, SchedWriteVarVecShift.XMM>; -} - -multiclass xop3opimm opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def ri : IXOPi8, - XOP, Sched<[sched]>; - def mi : IXOPi8, - XOP, Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPROTB : xop3opimm<0xC0, "vprotb", X86vrotli, v16i8, - SchedWriteVecShiftImm.XMM>; - defm VPROTD : xop3opimm<0xC2, "vprotd", X86vrotli, v4i32, - SchedWriteVecShiftImm.XMM>; - defm VPROTQ : xop3opimm<0xC3, "vprotq", X86vrotli, v2i64, - SchedWriteVecShiftImm.XMM>; - defm VPROTW : xop3opimm<0xC1, "vprotw", X86vrotli, v8i16, - SchedWriteVecShiftImm.XMM>; -} - -// Instruction where second source can be memory, but third must be register -multiclass xop4opm2 opc, string OpcodeStr, Intrinsic Int, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rr : IXOPi8Reg, XOP_4V, - Sched<[sched]>; - def rm : IXOPi8Reg, XOP_4V, Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPMADCSWD : xop4opm2<0xB6, "vpmadcswd", - int_x86_xop_vpmadcswd, SchedWriteVecIMul.XMM>; - defm VPMADCSSWD : xop4opm2<0xA6, "vpmadcsswd", - int_x86_xop_vpmadcsswd, SchedWriteVecIMul.XMM>; - defm VPMACSWW : xop4opm2<0x95, "vpmacsww", - int_x86_xop_vpmacsww, SchedWriteVecIMul.XMM>; - defm VPMACSWD : xop4opm2<0x96, "vpmacswd", - int_x86_xop_vpmacswd, SchedWriteVecIMul.XMM>; - defm VPMACSSWW : xop4opm2<0x85, "vpmacssww", - int_x86_xop_vpmacssww, SchedWriteVecIMul.XMM>; - defm VPMACSSWD : xop4opm2<0x86, "vpmacsswd", - int_x86_xop_vpmacsswd, SchedWriteVecIMul.XMM>; - defm VPMACSSDQL : xop4opm2<0x87, "vpmacssdql", - int_x86_xop_vpmacssdql, SchedWritePMULLD.XMM>; - defm VPMACSSDQH : xop4opm2<0x8F, "vpmacssdqh", - int_x86_xop_vpmacssdqh, SchedWritePMULLD.XMM>; - defm VPMACSSDD : xop4opm2<0x8E, "vpmacssdd", - int_x86_xop_vpmacssdd, SchedWritePMULLD.XMM>; - defm VPMACSDQL : xop4opm2<0x97, "vpmacsdql", - int_x86_xop_vpmacsdql, SchedWritePMULLD.XMM>; - defm VPMACSDQH : xop4opm2<0x9F, "vpmacsdqh", - int_x86_xop_vpmacsdqh, SchedWritePMULLD.XMM>; - defm VPMACSDD : xop4opm2<0x9E, "vpmacsdd", - int_x86_xop_vpmacsdd, SchedWritePMULLD.XMM>; -} - -// IFMA patterns - for cases where we can safely ignore the overflow bits from -// the multiply or easily match with existing intrinsics. -let Predicates = [HasXOP] in { - def : Pat<(v8i16 (add (mul (v8i16 VR128:$src1), (v8i16 VR128:$src2)), - (v8i16 VR128:$src3))), - (VPMACSWWrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v4i32 (add (mul (v4i32 VR128:$src1), (v4i32 VR128:$src2)), - (v4i32 VR128:$src3))), - (VPMACSDDrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v2i64 (add (X86pmuldq (bc_v2i64 (X86PShufd (v4i32 VR128:$src1), (i8 -11))), - (bc_v2i64 (X86PShufd (v4i32 VR128:$src2), (i8 -11)))), - (v2i64 VR128:$src3))), - (VPMACSDQHrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v2i64 (add (X86pmuldq (v2i64 VR128:$src1), (v2i64 VR128:$src2)), - (v2i64 VR128:$src3))), - (VPMACSDQLrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v4i32 (add (X86vpmaddwd (v8i16 VR128:$src1), (v8i16 VR128:$src2)), - (v4i32 VR128:$src3))), - (VPMADCSWDrr VR128:$src1, VR128:$src2, VR128:$src3)>; -} - -// Transforms to swizzle an immediate to help matching memory operand in first -// operand. -def CommuteVPCOMCC : SDNodeXFormgetZExtValue() & 0x7; - Imm = X86::getSwappedVPCOMImm(Imm); - return getI8Imm(Imm, SDLoc(N)); -}]>; - -// Instruction where second source can be memory, third must be imm8 -multiclass xopvpcom opc, string Suffix, SDNode OpNode, ValueType vt128, - X86FoldableSchedWrite sched> { - let ExeDomain = SSEPackedInt in { // SSE integer instructions - let isCommutable = 1 in - def ri : IXOPi8, - XOP_4V, Sched<[sched]>; - def mi : IXOPi8, - XOP_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def ri_alt : IXOPi8, XOP_4V, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def mi_alt : IXOPi8, XOP_4V, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - } - - def : Pat<(OpNode (bitconvert (loadv2i64 addr:$src2)), - (vt128 VR128:$src1), imm:$cc), - (!cast(NAME#"mi") VR128:$src1, addr:$src2, - (CommuteVPCOMCC imm:$cc))>; -} - -defm VPCOMB : xopvpcom<0xCC, "b", X86vpcom, v16i8, SchedWriteVecALU.XMM>; -defm VPCOMW : xopvpcom<0xCD, "w", X86vpcom, v8i16, SchedWriteVecALU.XMM>; -defm VPCOMD : xopvpcom<0xCE, "d", X86vpcom, v4i32, SchedWriteVecALU.XMM>; -defm VPCOMQ : xopvpcom<0xCF, "q", X86vpcom, v2i64, SchedWriteVecALU.XMM>; -defm VPCOMUB : xopvpcom<0xEC, "ub", X86vpcomu, v16i8, SchedWriteVecALU.XMM>; -defm VPCOMUW : xopvpcom<0xED, "uw", X86vpcomu, v8i16, SchedWriteVecALU.XMM>; -defm VPCOMUD : xopvpcom<0xEE, "ud", X86vpcomu, v4i32, SchedWriteVecALU.XMM>; -defm VPCOMUQ : xopvpcom<0xEF, "uq", X86vpcomu, v2i64, SchedWriteVecALU.XMM>; - -multiclass xop4op opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def rrr : IXOPi8Reg, - XOP_4V, Sched<[sched]>; - def rrm : IXOPi8Reg, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def rmr : IXOPi8Reg, - XOP_4V, Sched<[sched.Folded, ReadAfterLd, - // 128mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR128:$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8Reg, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPPERM : xop4op<0xA3, "vpperm", X86vpperm, v16i8, - SchedWriteVarShuffle.XMM>; -} - -// Instruction where either second or third source can be memory -multiclass xop4op_int opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType VT, - X86FoldableSchedWrite sched> { - def rrr : IXOPi8Reg, XOP_4V, - Sched<[sched]>; - def rrm : IXOPi8Reg, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def rmr : IXOPi8Reg, - XOP_4V, Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC::$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8Reg, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPCMOV : xop4op_int<0xA2, "vpcmov", VR128, i128mem, v2i64, - SchedWriteShuffle.XMM>; - defm VPCMOVY : xop4op_int<0xA2, "vpcmov", VR256, i256mem, v4i64, - SchedWriteShuffle.YMM>, VEX_L; -} - -multiclass xop_vpermil2 Opc, string OpcodeStr, RegisterClass RC, - X86MemOperand intmemop, X86MemOperand fpmemop, - ValueType VT, PatFrag FPLdFrag, PatFrag IntLdFrag, - X86FoldableSchedWrite sched> { - def rr : IXOP5, - Sched<[sched]>; - def rm : IXOP5, VEX_W, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : IXOP5, - Sched<[sched.Folded, ReadAfterLd, - // fpmemop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, - // RC:$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : IXOP5, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedDouble in { - defm VPERMIL2PD : xop_vpermil2<0x49, "vpermil2pd", VR128, i128mem, f128mem, - v2f64, loadv2f64, loadv2i64, - SchedWriteFVarShuffle.XMM>; - defm VPERMIL2PDY : xop_vpermil2<0x49, "vpermil2pd", VR256, i256mem, f256mem, - v4f64, loadv4f64, loadv4i64, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - -let ExeDomain = SSEPackedSingle in { - defm VPERMIL2PS : xop_vpermil2<0x48, "vpermil2ps", VR128, i128mem, f128mem, - v4f32, loadv4f32, loadv2i64, - SchedWriteFVarShuffle.XMM>; - defm VPERMIL2PSY : xop_vpermil2<0x48, "vpermil2ps", VR256, i256mem, f256mem, - v8f32, loadv8f32, loadv4i64, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - diff --git a/suite/synctools/tablegen/X86/X86PfmCounters.td b/suite/synctools/tablegen/X86/X86PfmCounters.td deleted file mode 100644 index 093fbafa3f..0000000000 --- a/suite/synctools/tablegen/X86/X86PfmCounters.td +++ /dev/null @@ -1,77 +0,0 @@ -//===-- X86PfmCounters.td - X86 Hardware Counters ----------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This describes the available hardware counters for various subtargets. -// -//===----------------------------------------------------------------------===// - -let SchedModel = SandyBridgeModel in { -def SBCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SBPort0Counter : PfmIssueCounter; -def SBPort1Counter : PfmIssueCounter; -def SBPort23Counter : PfmIssueCounter; -def SBPort4Counter : PfmIssueCounter; -def SBPort5Counter : PfmIssueCounter; -} - -let SchedModel = HaswellModel in { -def HWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def HWPort0Counter : PfmIssueCounter; -def HWPort1Counter : PfmIssueCounter; -def HWPort2Counter : PfmIssueCounter; -def HWPort3Counter : PfmIssueCounter; -def HWPort4Counter : PfmIssueCounter; -def HWPort5Counter : PfmIssueCounter; -def HWPort6Counter : PfmIssueCounter; -def HWPort7Counter : PfmIssueCounter; -} - -let SchedModel = BroadwellModel in { -def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def BWPort0Counter : PfmIssueCounter; -def BWPort1Counter : PfmIssueCounter; -def BWPort2Counter : PfmIssueCounter; -def BWPort3Counter : PfmIssueCounter; -def BWPort4Counter : PfmIssueCounter; -def BWPort5Counter : PfmIssueCounter; -def BWPort6Counter : PfmIssueCounter; -def BWPort7Counter : PfmIssueCounter; -} - -let SchedModel = SkylakeClientModel in { -def SKLCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SKLPort0Counter : PfmIssueCounter; -def SKLPort1Counter : PfmIssueCounter; -def SKLPort2Counter : PfmIssueCounter; -def SKLPort3Counter : PfmIssueCounter; -def SKLPort4Counter : PfmIssueCounter; -def SKLPort5Counter : PfmIssueCounter; -def SKLPort6Counter : PfmIssueCounter; -def SKLPort7Counter : PfmIssueCounter; -} - -let SchedModel = SkylakeServerModel in { -def SKXCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SKXPort0Counter : PfmIssueCounter; -def SKXPort1Counter : PfmIssueCounter; -def SKXPort2Counter : PfmIssueCounter; -def SKXPort3Counter : PfmIssueCounter; -def SKXPort4Counter : PfmIssueCounter; -def SKXPort5Counter : PfmIssueCounter; -def SKXPort6Counter : PfmIssueCounter; -def SKXPort7Counter : PfmIssueCounter; -} - -let SchedModel = BtVer2Model in { -def JCycleCounter : PfmCycleCounter<"cpu_clk_unhalted">; -def JFPU0Counter : PfmIssueCounter; -def JFPU1Counter : PfmIssueCounter; -} diff --git a/suite/synctools/tablegen/X86/X86RegisterBanks.td b/suite/synctools/tablegen/X86/X86RegisterBanks.td deleted file mode 100644 index 6d17cd53a0..0000000000 --- a/suite/synctools/tablegen/X86/X86RegisterBanks.td +++ /dev/null @@ -1,17 +0,0 @@ -//=- X86RegisterBank.td - Describe the AArch64 Banks -----*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -/// General Purpose Registers: RAX, RCX,... -def GPRRegBank : RegisterBank<"GPR", [GR64]>; - -/// Floating Point/Vector Registers -def VECRRegBank : RegisterBank<"VECR", [VR512]>; diff --git a/suite/synctools/tablegen/X86/X86RegisterInfo.td b/suite/synctools/tablegen/X86/X86RegisterInfo.td deleted file mode 100644 index 907d402223..0000000000 --- a/suite/synctools/tablegen/X86/X86RegisterInfo.td +++ /dev/null @@ -1,591 +0,0 @@ -//===- X86RegisterInfo.td - Describe the X86 Register File --*- tablegen -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 Register file, defining the registers themselves, -// aliases between the registers, and the register classes built out of the -// registers. -// -//===----------------------------------------------------------------------===// - -class X86Reg Enc, list subregs = []> : Register { - let Namespace = "X86"; - let HWEncoding = Enc; - let SubRegs = subregs; -} - -// Subregister indices. -let Namespace = "X86" in { - def sub_8bit : SubRegIndex<8>; - def sub_8bit_hi : SubRegIndex<8, 8>; - def sub_8bit_hi_phony : SubRegIndex<8, 8>; - def sub_16bit : SubRegIndex<16>; - def sub_16bit_hi : SubRegIndex<16, 16>; - def sub_32bit : SubRegIndex<32>; - def sub_xmm : SubRegIndex<128>; - def sub_ymm : SubRegIndex<256>; -} - -//===----------------------------------------------------------------------===// -// Register definitions... -// - -// In the register alias definitions below, we define which registers alias -// which others. We only specify which registers the small registers alias, -// because the register file generator is smart enough to figure out that -// AL aliases AX if we tell it that AX aliased AL (for example). - -// Dwarf numbering is different for 32-bit and 64-bit, and there are -// variations by target as well. Currently the first entry is for X86-64, -// second - for EH on X86-32/Darwin and third is 'generic' one (X86-32/Linux -// and debug information on X86-32/Darwin) - -// 8-bit registers -// Low registers -def AL : X86Reg<"al", 0>; -def DL : X86Reg<"dl", 2>; -def CL : X86Reg<"cl", 1>; -def BL : X86Reg<"bl", 3>; - -// High registers. On x86-64, these cannot be used in any instruction -// with a REX prefix. -def AH : X86Reg<"ah", 4>; -def DH : X86Reg<"dh", 6>; -def CH : X86Reg<"ch", 5>; -def BH : X86Reg<"bh", 7>; - -// X86-64 only, requires REX. -let CostPerUse = 1 in { -def SIL : X86Reg<"sil", 6>; -def DIL : X86Reg<"dil", 7>; -def BPL : X86Reg<"bpl", 5>; -def SPL : X86Reg<"spl", 4>; -def R8B : X86Reg<"r8b", 8>; -def R9B : X86Reg<"r9b", 9>; -def R10B : X86Reg<"r10b", 10>; -def R11B : X86Reg<"r11b", 11>; -def R12B : X86Reg<"r12b", 12>; -def R13B : X86Reg<"r13b", 13>; -def R14B : X86Reg<"r14b", 14>; -def R15B : X86Reg<"r15b", 15>; -} - -let isArtificial = 1 in { -// High byte of the low 16 bits of the super-register: -def SIH : X86Reg<"", -1>; -def DIH : X86Reg<"", -1>; -def BPH : X86Reg<"", -1>; -def SPH : X86Reg<"", -1>; -def R8BH : X86Reg<"", -1>; -def R9BH : X86Reg<"", -1>; -def R10BH : X86Reg<"", -1>; -def R11BH : X86Reg<"", -1>; -def R12BH : X86Reg<"", -1>; -def R13BH : X86Reg<"", -1>; -def R14BH : X86Reg<"", -1>; -def R15BH : X86Reg<"", -1>; -// High word of the low 32 bits of the super-register: -def HAX : X86Reg<"", -1>; -def HDX : X86Reg<"", -1>; -def HCX : X86Reg<"", -1>; -def HBX : X86Reg<"", -1>; -def HSI : X86Reg<"", -1>; -def HDI : X86Reg<"", -1>; -def HBP : X86Reg<"", -1>; -def HSP : X86Reg<"", -1>; -def HIP : X86Reg<"", -1>; -def R8WH : X86Reg<"", -1>; -def R9WH : X86Reg<"", -1>; -def R10WH : X86Reg<"", -1>; -def R11WH : X86Reg<"", -1>; -def R12WH : X86Reg<"", -1>; -def R13WH : X86Reg<"", -1>; -def R14WH : X86Reg<"", -1>; -def R15WH : X86Reg<"", -1>; -} - -// 16-bit registers -let SubRegIndices = [sub_8bit, sub_8bit_hi], CoveredBySubRegs = 1 in { -def AX : X86Reg<"ax", 0, [AL,AH]>; -def DX : X86Reg<"dx", 2, [DL,DH]>; -def CX : X86Reg<"cx", 1, [CL,CH]>; -def BX : X86Reg<"bx", 3, [BL,BH]>; -} -let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CoveredBySubRegs = 1 in { -def SI : X86Reg<"si", 6, [SIL,SIH]>; -def DI : X86Reg<"di", 7, [DIL,DIH]>; -def BP : X86Reg<"bp", 5, [BPL,BPH]>; -def SP : X86Reg<"sp", 4, [SPL,SPH]>; -} -def IP : X86Reg<"ip", 0>; - -// X86-64 only, requires REX. -let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CostPerUse = 1, - CoveredBySubRegs = 1 in { -def R8W : X86Reg<"r8w", 8, [R8B,R8BH]>; -def R9W : X86Reg<"r9w", 9, [R9B,R9BH]>; -def R10W : X86Reg<"r10w", 10, [R10B,R10BH]>; -def R11W : X86Reg<"r11w", 11, [R11B,R11BH]>; -def R12W : X86Reg<"r12w", 12, [R12B,R12BH]>; -def R13W : X86Reg<"r13w", 13, [R13B,R13BH]>; -def R14W : X86Reg<"r14w", 14, [R14B,R14BH]>; -def R15W : X86Reg<"r15w", 15, [R15B,R15BH]>; -} - -// 32-bit registers -let SubRegIndices = [sub_16bit, sub_16bit_hi], CoveredBySubRegs = 1 in { -def EAX : X86Reg<"eax", 0, [AX, HAX]>, DwarfRegNum<[-2, 0, 0]>; -def EDX : X86Reg<"edx", 2, [DX, HDX]>, DwarfRegNum<[-2, 2, 2]>; -def ECX : X86Reg<"ecx", 1, [CX, HCX]>, DwarfRegNum<[-2, 1, 1]>; -def EBX : X86Reg<"ebx", 3, [BX, HBX]>, DwarfRegNum<[-2, 3, 3]>; -def ESI : X86Reg<"esi", 6, [SI, HSI]>, DwarfRegNum<[-2, 6, 6]>; -def EDI : X86Reg<"edi", 7, [DI, HDI]>, DwarfRegNum<[-2, 7, 7]>; -def EBP : X86Reg<"ebp", 5, [BP, HBP]>, DwarfRegNum<[-2, 4, 5]>; -def ESP : X86Reg<"esp", 4, [SP, HSP]>, DwarfRegNum<[-2, 5, 4]>; -def EIP : X86Reg<"eip", 0, [IP, HIP]>, DwarfRegNum<[-2, 8, 8]>; -} - -// X86-64 only, requires REX -let SubRegIndices = [sub_16bit, sub_16bit_hi], CostPerUse = 1, - CoveredBySubRegs = 1 in { -def R8D : X86Reg<"r8d", 8, [R8W,R8WH]>; -def R9D : X86Reg<"r9d", 9, [R9W,R9WH]>; -def R10D : X86Reg<"r10d", 10, [R10W,R10WH]>; -def R11D : X86Reg<"r11d", 11, [R11W,R11WH]>; -def R12D : X86Reg<"r12d", 12, [R12W,R12WH]>; -def R13D : X86Reg<"r13d", 13, [R13W,R13WH]>; -def R14D : X86Reg<"r14d", 14, [R14W,R14WH]>; -def R15D : X86Reg<"r15d", 15, [R15W,R15WH]>; -} - -// 64-bit registers, X86-64 only -let SubRegIndices = [sub_32bit] in { -def RAX : X86Reg<"rax", 0, [EAX]>, DwarfRegNum<[0, -2, -2]>; -def RDX : X86Reg<"rdx", 2, [EDX]>, DwarfRegNum<[1, -2, -2]>; -def RCX : X86Reg<"rcx", 1, [ECX]>, DwarfRegNum<[2, -2, -2]>; -def RBX : X86Reg<"rbx", 3, [EBX]>, DwarfRegNum<[3, -2, -2]>; -def RSI : X86Reg<"rsi", 6, [ESI]>, DwarfRegNum<[4, -2, -2]>; -def RDI : X86Reg<"rdi", 7, [EDI]>, DwarfRegNum<[5, -2, -2]>; -def RBP : X86Reg<"rbp", 5, [EBP]>, DwarfRegNum<[6, -2, -2]>; -def RSP : X86Reg<"rsp", 4, [ESP]>, DwarfRegNum<[7, -2, -2]>; - -// These also require REX. -let CostPerUse = 1 in { -def R8 : X86Reg<"r8", 8, [R8D]>, DwarfRegNum<[ 8, -2, -2]>; -def R9 : X86Reg<"r9", 9, [R9D]>, DwarfRegNum<[ 9, -2, -2]>; -def R10 : X86Reg<"r10", 10, [R10D]>, DwarfRegNum<[10, -2, -2]>; -def R11 : X86Reg<"r11", 11, [R11D]>, DwarfRegNum<[11, -2, -2]>; -def R12 : X86Reg<"r12", 12, [R12D]>, DwarfRegNum<[12, -2, -2]>; -def R13 : X86Reg<"r13", 13, [R13D]>, DwarfRegNum<[13, -2, -2]>; -def R14 : X86Reg<"r14", 14, [R14D]>, DwarfRegNum<[14, -2, -2]>; -def R15 : X86Reg<"r15", 15, [R15D]>, DwarfRegNum<[15, -2, -2]>; -def RIP : X86Reg<"rip", 0, [EIP]>, DwarfRegNum<[16, -2, -2]>; -}} - -// MMX Registers. These are actually aliased to ST0 .. ST7 -def MM0 : X86Reg<"mm0", 0>, DwarfRegNum<[41, 29, 29]>; -def MM1 : X86Reg<"mm1", 1>, DwarfRegNum<[42, 30, 30]>; -def MM2 : X86Reg<"mm2", 2>, DwarfRegNum<[43, 31, 31]>; -def MM3 : X86Reg<"mm3", 3>, DwarfRegNum<[44, 32, 32]>; -def MM4 : X86Reg<"mm4", 4>, DwarfRegNum<[45, 33, 33]>; -def MM5 : X86Reg<"mm5", 5>, DwarfRegNum<[46, 34, 34]>; -def MM6 : X86Reg<"mm6", 6>, DwarfRegNum<[47, 35, 35]>; -def MM7 : X86Reg<"mm7", 7>, DwarfRegNum<[48, 36, 36]>; - -// Pseudo Floating Point registers -def FP0 : X86Reg<"fp0", 0>; -def FP1 : X86Reg<"fp1", 0>; -def FP2 : X86Reg<"fp2", 0>; -def FP3 : X86Reg<"fp3", 0>; -def FP4 : X86Reg<"fp4", 0>; -def FP5 : X86Reg<"fp5", 0>; -def FP6 : X86Reg<"fp6", 0>; -def FP7 : X86Reg<"fp7", 0>; - -// XMM Registers, used by the various SSE instruction set extensions. -def XMM0: X86Reg<"xmm0", 0>, DwarfRegNum<[17, 21, 21]>; -def XMM1: X86Reg<"xmm1", 1>, DwarfRegNum<[18, 22, 22]>; -def XMM2: X86Reg<"xmm2", 2>, DwarfRegNum<[19, 23, 23]>; -def XMM3: X86Reg<"xmm3", 3>, DwarfRegNum<[20, 24, 24]>; -def XMM4: X86Reg<"xmm4", 4>, DwarfRegNum<[21, 25, 25]>; -def XMM5: X86Reg<"xmm5", 5>, DwarfRegNum<[22, 26, 26]>; -def XMM6: X86Reg<"xmm6", 6>, DwarfRegNum<[23, 27, 27]>; -def XMM7: X86Reg<"xmm7", 7>, DwarfRegNum<[24, 28, 28]>; - -// X86-64 only -let CostPerUse = 1 in { -def XMM8: X86Reg<"xmm8", 8>, DwarfRegNum<[25, -2, -2]>; -def XMM9: X86Reg<"xmm9", 9>, DwarfRegNum<[26, -2, -2]>; -def XMM10: X86Reg<"xmm10", 10>, DwarfRegNum<[27, -2, -2]>; -def XMM11: X86Reg<"xmm11", 11>, DwarfRegNum<[28, -2, -2]>; -def XMM12: X86Reg<"xmm12", 12>, DwarfRegNum<[29, -2, -2]>; -def XMM13: X86Reg<"xmm13", 13>, DwarfRegNum<[30, -2, -2]>; -def XMM14: X86Reg<"xmm14", 14>, DwarfRegNum<[31, -2, -2]>; -def XMM15: X86Reg<"xmm15", 15>, DwarfRegNum<[32, -2, -2]>; - -def XMM16: X86Reg<"xmm16", 16>, DwarfRegNum<[67, -2, -2]>; -def XMM17: X86Reg<"xmm17", 17>, DwarfRegNum<[68, -2, -2]>; -def XMM18: X86Reg<"xmm18", 18>, DwarfRegNum<[69, -2, -2]>; -def XMM19: X86Reg<"xmm19", 19>, DwarfRegNum<[70, -2, -2]>; -def XMM20: X86Reg<"xmm20", 20>, DwarfRegNum<[71, -2, -2]>; -def XMM21: X86Reg<"xmm21", 21>, DwarfRegNum<[72, -2, -2]>; -def XMM22: X86Reg<"xmm22", 22>, DwarfRegNum<[73, -2, -2]>; -def XMM23: X86Reg<"xmm23", 23>, DwarfRegNum<[74, -2, -2]>; -def XMM24: X86Reg<"xmm24", 24>, DwarfRegNum<[75, -2, -2]>; -def XMM25: X86Reg<"xmm25", 25>, DwarfRegNum<[76, -2, -2]>; -def XMM26: X86Reg<"xmm26", 26>, DwarfRegNum<[77, -2, -2]>; -def XMM27: X86Reg<"xmm27", 27>, DwarfRegNum<[78, -2, -2]>; -def XMM28: X86Reg<"xmm28", 28>, DwarfRegNum<[79, -2, -2]>; -def XMM29: X86Reg<"xmm29", 29>, DwarfRegNum<[80, -2, -2]>; -def XMM30: X86Reg<"xmm30", 30>, DwarfRegNum<[81, -2, -2]>; -def XMM31: X86Reg<"xmm31", 31>, DwarfRegNum<[82, -2, -2]>; - -} // CostPerUse - -// YMM0-15 registers, used by AVX instructions and -// YMM16-31 registers, used by AVX-512 instructions. -let SubRegIndices = [sub_xmm] in { - foreach Index = 0-31 in { - def YMM#Index : X86Reg<"ymm"#Index, Index, [!cast("XMM"#Index)]>, - DwarfRegAlias("XMM"#Index)>; - } -} - -// ZMM Registers, used by AVX-512 instructions. -let SubRegIndices = [sub_ymm] in { - foreach Index = 0-31 in { - def ZMM#Index : X86Reg<"zmm"#Index, Index, [!cast("YMM"#Index)]>, - DwarfRegAlias("XMM"#Index)>; - } -} - -// Mask Registers, used by AVX-512 instructions. -def K0 : X86Reg<"k0", 0>, DwarfRegNum<[118, 93, 93]>; -def K1 : X86Reg<"k1", 1>, DwarfRegNum<[119, 94, 94]>; -def K2 : X86Reg<"k2", 2>, DwarfRegNum<[120, 95, 95]>; -def K3 : X86Reg<"k3", 3>, DwarfRegNum<[121, 96, 96]>; -def K4 : X86Reg<"k4", 4>, DwarfRegNum<[122, 97, 97]>; -def K5 : X86Reg<"k5", 5>, DwarfRegNum<[123, 98, 98]>; -def K6 : X86Reg<"k6", 6>, DwarfRegNum<[124, 99, 99]>; -def K7 : X86Reg<"k7", 7>, DwarfRegNum<[125, 100, 100]>; - -// Floating point stack registers. These don't map one-to-one to the FP -// pseudo registers, but we still mark them as aliasing FP registers. That -// way both kinds can be live without exceeding the stack depth. ST registers -// are only live around inline assembly. -def ST0 : X86Reg<"st(0)", 0>, DwarfRegNum<[33, 12, 11]>; -def ST1 : X86Reg<"st(1)", 1>, DwarfRegNum<[34, 13, 12]>; -def ST2 : X86Reg<"st(2)", 2>, DwarfRegNum<[35, 14, 13]>; -def ST3 : X86Reg<"st(3)", 3>, DwarfRegNum<[36, 15, 14]>; -def ST4 : X86Reg<"st(4)", 4>, DwarfRegNum<[37, 16, 15]>; -def ST5 : X86Reg<"st(5)", 5>, DwarfRegNum<[38, 17, 16]>; -def ST6 : X86Reg<"st(6)", 6>, DwarfRegNum<[39, 18, 17]>; -def ST7 : X86Reg<"st(7)", 7>, DwarfRegNum<[40, 19, 18]>; - -// Floating-point status word -def FPSW : X86Reg<"fpsw", 0>; - -// Status flags register. -// -// Note that some flags that are commonly thought of as part of the status -// flags register are modeled separately. Typically this is due to instructions -// reading and updating those flags independently of all the others. We don't -// want to create false dependencies between these instructions and so we use -// a separate register to model them. -def EFLAGS : X86Reg<"flags", 0>; - -// The direction flag. -def DF : X86Reg<"dirflag", 0>; - - -// Segment registers -def CS : X86Reg<"cs", 1>; -def DS : X86Reg<"ds", 3>; -def SS : X86Reg<"ss", 2>; -def ES : X86Reg<"es", 0>; -def FS : X86Reg<"fs", 4>; -def GS : X86Reg<"gs", 5>; - -// Debug registers -def DR0 : X86Reg<"dr0", 0>; -def DR1 : X86Reg<"dr1", 1>; -def DR2 : X86Reg<"dr2", 2>; -def DR3 : X86Reg<"dr3", 3>; -def DR4 : X86Reg<"dr4", 4>; -def DR5 : X86Reg<"dr5", 5>; -def DR6 : X86Reg<"dr6", 6>; -def DR7 : X86Reg<"dr7", 7>; -def DR8 : X86Reg<"dr8", 8>; -def DR9 : X86Reg<"dr9", 9>; -def DR10 : X86Reg<"dr10", 10>; -def DR11 : X86Reg<"dr11", 11>; -def DR12 : X86Reg<"dr12", 12>; -def DR13 : X86Reg<"dr13", 13>; -def DR14 : X86Reg<"dr14", 14>; -def DR15 : X86Reg<"dr15", 15>; - -// Control registers -def CR0 : X86Reg<"cr0", 0>; -def CR1 : X86Reg<"cr1", 1>; -def CR2 : X86Reg<"cr2", 2>; -def CR3 : X86Reg<"cr3", 3>; -def CR4 : X86Reg<"cr4", 4>; -def CR5 : X86Reg<"cr5", 5>; -def CR6 : X86Reg<"cr6", 6>; -def CR7 : X86Reg<"cr7", 7>; -def CR8 : X86Reg<"cr8", 8>; -def CR9 : X86Reg<"cr9", 9>; -def CR10 : X86Reg<"cr10", 10>; -def CR11 : X86Reg<"cr11", 11>; -def CR12 : X86Reg<"cr12", 12>; -def CR13 : X86Reg<"cr13", 13>; -def CR14 : X86Reg<"cr14", 14>; -def CR15 : X86Reg<"cr15", 15>; - -// Pseudo index registers -def EIZ : X86Reg<"eiz", 4>; -def RIZ : X86Reg<"riz", 4>; - -// Bound registers, used in MPX instructions -def BND0 : X86Reg<"bnd0", 0>; -def BND1 : X86Reg<"bnd1", 1>; -def BND2 : X86Reg<"bnd2", 2>; -def BND3 : X86Reg<"bnd3", 3>; - -// CET registers - Shadow Stack Pointer -def SSP : X86Reg<"ssp", 0>; - -//===----------------------------------------------------------------------===// -// Register Class Definitions... now that we have all of the pieces, define the -// top-level register classes. The order specified in the register list is -// implicitly defined to be the register allocation order. -// - -// List call-clobbered registers before callee-save registers. RBX, RBP, (and -// R12, R13, R14, and R15 for X86-64) are callee-save registers. -// In 64-mode, there are 12 additional i8 registers, SIL, DIL, BPL, SPL, and -// R8B, ... R15B. -// Allocate R12 and R13 last, as these require an extra byte when -// encoded in x86_64 instructions. -// FIXME: Allow AH, CH, DH, BH to be used as general-purpose registers in -// 64-bit mode. The main complication is that they cannot be encoded in an -// instruction requiring a REX prefix, while SIL, DIL, BPL, R8D, etc. -// require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d" -// cannot be encoded. -def GR8 : RegisterClass<"X86", [i8], 8, - (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL, - R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B)> { - let AltOrders = [(sub GR8, AH, BH, CH, DH)]; - let AltOrderSelect = [{ - return MF.getSubtarget().is64Bit(); - }]; -} - -let isAllocatable = 0 in -def GRH8 : RegisterClass<"X86", [i8], 8, - (add SIH, DIH, BPH, SPH, R8BH, R9BH, R10BH, R11BH, - R12BH, R13BH, R14BH, R15BH)>; - -def GR16 : RegisterClass<"X86", [i16], 16, - (add AX, CX, DX, SI, DI, BX, BP, SP, - R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W)>; - -let isAllocatable = 0 in -def GRH16 : RegisterClass<"X86", [i16], 16, - (add HAX, HCX, HDX, HSI, HDI, HBX, HBP, HSP, HIP, - R8WH, R9WH, R10WH, R11WH, R12WH, R13WH, R14WH, - R15WH)>; - -def GR32 : RegisterClass<"X86", [i32], 32, - (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, - R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D)>; - -// GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since -// RIP isn't really a register and it can't be used anywhere except in an -// address, but it doesn't cause trouble. -// FIXME: it *does* cause trouble - CheckBaseRegAndIndexReg() has extra -// tests because of the inclusion of RIP in this register class. -def GR64 : RegisterClass<"X86", [i64], 64, - (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - RBX, R14, R15, R12, R13, RBP, RSP, RIP)>; - -// Segment registers for use by MOV instructions (and others) that have a -// segment register as one operand. Always contain a 16-bit segment -// descriptor. -def SEGMENT_REG : RegisterClass<"X86", [i16], 16, (add CS, DS, SS, ES, FS, GS)>; - -// Debug registers. -def DEBUG_REG : RegisterClass<"X86", [i32], 32, (sequence "DR%u", 0, 15)>; - -// Control registers. -def CONTROL_REG : RegisterClass<"X86", [i64], 64, (sequence "CR%u", 0, 15)>; - -// GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD, GR64_ABCD - Subclasses of -// GR8, GR16, GR32, and GR64 which contain just the "a" "b", "c", and "d" -// registers. On x86-32, GR16_ABCD and GR32_ABCD are classes for registers -// that support 8-bit subreg operations. On x86-64, GR16_ABCD, GR32_ABCD, -// and GR64_ABCD are classes for registers that support 8-bit h-register -// operations. -def GR8_ABCD_L : RegisterClass<"X86", [i8], 8, (add AL, CL, DL, BL)>; -def GR8_ABCD_H : RegisterClass<"X86", [i8], 8, (add AH, CH, DH, BH)>; -def GR16_ABCD : RegisterClass<"X86", [i16], 16, (add AX, CX, DX, BX)>; -def GR32_ABCD : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX, EBX)>; -def GR64_ABCD : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RBX)>; -def GR32_TC : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX)>; -def GR64_TC : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RSI, RDI, - R8, R9, R11, RIP)>; -def GR64_TCW64 : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, - R8, R9, R10, R11, RIP)>; - -// GR8_NOREX - GR8 registers which do not require a REX prefix. -def GR8_NOREX : RegisterClass<"X86", [i8], 8, - (add AL, CL, DL, AH, CH, DH, BL, BH)> { - let AltOrders = [(sub GR8_NOREX, AH, BH, CH, DH)]; - let AltOrderSelect = [{ - return MF.getSubtarget().is64Bit(); - }]; -} -// GR16_NOREX - GR16 registers which do not require a REX prefix. -def GR16_NOREX : RegisterClass<"X86", [i16], 16, - (add AX, CX, DX, SI, DI, BX, BP, SP)>; -// GR32_NOREX - GR32 registers which do not require a REX prefix. -def GR32_NOREX : RegisterClass<"X86", [i32], 32, - (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP)>; -// GR64_NOREX - GR64 registers which do not require a REX prefix. -def GR64_NOREX : RegisterClass<"X86", [i64], 64, - (add RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP, RIP)>; - -// GR32_NOSP - GR32 registers except ESP. -def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)>; - -// GR64_NOSP - GR64 registers except RSP (and RIP). -def GR64_NOSP : RegisterClass<"X86", [i64], 64, (sub GR64, RSP, RIP)>; - -// GR32_NOREX_NOSP - GR32 registers which do not require a REX prefix except -// ESP. -def GR32_NOREX_NOSP : RegisterClass<"X86", [i32], 32, - (and GR32_NOREX, GR32_NOSP)>; - -// GR64_NOREX_NOSP - GR64_NOREX registers except RSP. -def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64, - (and GR64_NOREX, GR64_NOSP)>; - -// Register classes used for ABIs that use 32-bit address accesses, -// while using the whole x84_64 ISA. - -// In such cases, it is fine to use RIP as we are sure the 32 high -// bits are not set. We do not need variants for NOSP as RIP is not -// allowed there. -// RIP is not spilled anywhere for now, so stick to 32-bit alignment -// to save on memory space. -// FIXME: We could allow all 64bit registers, but we would need -// something to check that the 32 high bits are not set, -// which we do not have right now. -def LOW32_ADDR_ACCESS : RegisterClass<"X86", [i32], 32, (add GR32, RIP)>; - -// When RBP is used as a base pointer in a 32-bit addresses environment, -// this is also safe to use the full register to access addresses. -// Since RBP will never be spilled, stick to a 32 alignment to save -// on memory consumption. -def LOW32_ADDR_ACCESS_RBP : RegisterClass<"X86", [i32], 32, - (add LOW32_ADDR_ACCESS, RBP)>; - -// A class to support the 'A' assembler constraint: [ER]AX then [ER]DX. -def GR32_AD : RegisterClass<"X86", [i32], 32, (add EAX, EDX)>; -def GR64_AD : RegisterClass<"X86", [i64], 64, (add RAX, RDX)>; - -// Scalar SSE2 floating point registers. -def FR32 : RegisterClass<"X86", [f32], 32, (sequence "XMM%u", 0, 15)>; - -def FR64 : RegisterClass<"X86", [f64], 64, (add FR32)>; - - -// FIXME: This sets up the floating point register files as though they are f64 -// values, though they really are f80 values. This will cause us to spill -// values as 64-bit quantities instead of 80-bit quantities, which is much much -// faster on common hardware. In reality, this should be controlled by a -// command line option or something. - -def RFP32 : RegisterClass<"X86",[f32], 32, (sequence "FP%u", 0, 6)>; -def RFP64 : RegisterClass<"X86",[f64], 32, (add RFP32)>; -def RFP80 : RegisterClass<"X86",[f80], 32, (add RFP32)>; - -// Floating point stack registers (these are not allocatable by the -// register allocator - the floating point stackifier is responsible -// for transforming FPn allocations to STn registers) -def RST : RegisterClass<"X86", [f80, f64, f32], 32, (sequence "ST%u", 0, 7)> { - let isAllocatable = 0; -} - -// Generic vector registers: VR64 and VR128. -// Ensure that float types are declared first - only float is legal on SSE1. -def VR64: RegisterClass<"X86", [x86mmx], 64, (sequence "MM%u", 0, 7)>; -def VR128 : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (add FR32)>; -def VR256 : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 15)>; - -// Special classes that help the assembly parser choose some alternate -// instructions to favor 2-byte VEX encodings. -def VR128L : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (sequence "XMM%u", 0, 7)>; -def VR128H : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (sequence "XMM%u", 8, 15)>; -def VR256L : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 7)>; -def VR256H : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 8, 15)>; - -// Status flags registers. -def CCR : RegisterClass<"X86", [i32], 32, (add EFLAGS)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} -def FPCCR : RegisterClass<"X86", [i16], 16, (add FPSW)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} -def DFCCR : RegisterClass<"X86", [i32], 32, (add DF)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} - -// AVX-512 vector/mask registers. -def VR512 : RegisterClass<"X86", [v16f32, v8f64, v64i8, v32i16, v16i32, v8i64], - 512, (sequence "ZMM%u", 0, 31)>; - -// Scalar AVX-512 floating point registers. -def FR32X : RegisterClass<"X86", [f32], 32, (sequence "XMM%u", 0, 31)>; - -def FR64X : RegisterClass<"X86", [f64], 64, (add FR32X)>; - -// Extended VR128 and VR256 for AVX-512 instructions -def VR128X : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (add FR32X)>; -def VR256X : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 31)>; - -// Mask registers -def VK1 : RegisterClass<"X86", [v1i1], 16, (sequence "K%u", 0, 7)> {let Size = 16;} -def VK2 : RegisterClass<"X86", [v2i1], 16, (add VK1)> {let Size = 16;} -def VK4 : RegisterClass<"X86", [v4i1], 16, (add VK2)> {let Size = 16;} -def VK8 : RegisterClass<"X86", [v8i1], 16, (add VK4)> {let Size = 16;} -def VK16 : RegisterClass<"X86", [v16i1], 16, (add VK8)> {let Size = 16;} -def VK32 : RegisterClass<"X86", [v32i1], 32, (add VK16)> {let Size = 32;} -def VK64 : RegisterClass<"X86", [v64i1], 64, (add VK32)> {let Size = 64;} - -def VK1WM : RegisterClass<"X86", [v1i1], 16, (sub VK1, K0)> {let Size = 16;} -def VK2WM : RegisterClass<"X86", [v2i1], 16, (sub VK2, K0)> {let Size = 16;} -def VK4WM : RegisterClass<"X86", [v4i1], 16, (sub VK4, K0)> {let Size = 16;} -def VK8WM : RegisterClass<"X86", [v8i1], 16, (sub VK8, K0)> {let Size = 16;} -def VK16WM : RegisterClass<"X86", [v16i1], 16, (add VK8WM)> {let Size = 16;} -def VK32WM : RegisterClass<"X86", [v32i1], 32, (add VK16WM)> {let Size = 32;} -def VK64WM : RegisterClass<"X86", [v64i1], 64, (add VK32WM)> {let Size = 64;} - -// Bound registers -def BNDR : RegisterClass<"X86", [v2i64], 128, (sequence "BND%u", 0, 3)>; diff --git a/suite/synctools/tablegen/X86/X86SchedBroadwell.td b/suite/synctools/tablegen/X86/X86SchedBroadwell.td deleted file mode 100644 index 6334d9e89a..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedBroadwell.td +++ /dev/null @@ -1,1692 +0,0 @@ -//=- X86SchedBroadwell.td - X86 Broadwell Scheduling ---------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Broadwell to support instruction -// scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def BroadwellModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and BW can decode 4 - // instructions per cycle. - let IssueWidth = 4; - let MicroOpBufferSize = 192; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = BroadwellModel in { - -// Broadwell can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def BWPort0 : ProcResource<1>; -def BWPort1 : ProcResource<1>; -def BWPort2 : ProcResource<1>; -def BWPort3 : ProcResource<1>; -def BWPort4 : ProcResource<1>; -def BWPort5 : ProcResource<1>; -def BWPort6 : ProcResource<1>; -def BWPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def BWPort01 : ProcResGroup<[BWPort0, BWPort1]>; -def BWPort23 : ProcResGroup<[BWPort2, BWPort3]>; -def BWPort237 : ProcResGroup<[BWPort2, BWPort3, BWPort7]>; -def BWPort04 : ProcResGroup<[BWPort0, BWPort4]>; -def BWPort05 : ProcResGroup<[BWPort0, BWPort5]>; -def BWPort06 : ProcResGroup<[BWPort0, BWPort6]>; -def BWPort15 : ProcResGroup<[BWPort1, BWPort5]>; -def BWPort16 : ProcResGroup<[BWPort1, BWPort6]>; -def BWPort56 : ProcResGroup<[BWPort5, BWPort6]>; -def BWPort015 : ProcResGroup<[BWPort0, BWPort1, BWPort5]>; -def BWPort056 : ProcResGroup<[BWPort0, BWPort5, BWPort6]>; -def BWPort0156: ProcResGroup<[BWPort0, BWPort1, BWPort5, BWPort6]>; - -// 60 Entry Unified Scheduler -def BWPortAny : ProcResGroup<[BWPort0, BWPort1, BWPort2, BWPort3, BWPort4, - BWPort5, BWPort6, BWPort7]> { - let BufferSize=60; -} - -// Integer division issued on port 0. -def BWDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def BWFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass BWWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : BWWriteResPair; // Simple integer ALU op. -defm : BWWriteResPair; // Integer ALU + flags op. -defm : BWWriteResPair; // Integer multiplication. -defm : BWWriteResPair; // Integer 64-bit multiplication. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : BWWriteResPair; -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. - -def : WriteRes; // LEA instructions can't fold loads. - -defm : BWWriteResPair; // Conditional move. -defm : BWWriteResPair; // // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. - -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // Bit Test instrs - -// Bit counts. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Integer shifts and rotates. -defm : BWWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// BMI1 BEXTR, BMI2 BZHI -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : BWWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : BWWriteResPair; // Floating point add/sub. -defm : BWWriteResPair; // Floating point add/sub (XMM). -defm : BWWriteResPair; // Floating point add/sub (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double add/sub. -defm : BWWriteResPair; // Floating point double add/sub (XMM). -defm : BWWriteResPair; // Floating point double add/sub (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point compare. -defm : BWWriteResPair; // Floating point compare (XMM). -defm : BWWriteResPair; // Floating point compare (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double compare. -defm : BWWriteResPair; // Floating point double compare (XMM). -defm : BWWriteResPair; // Floating point double compare (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point compare to flags. - -defm : BWWriteResPair; // Floating point multiplication. -defm : BWWriteResPair; // Floating point multiplication (XMM). -defm : BWWriteResPair; // Floating point multiplication (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double multiplication. -defm : BWWriteResPair; // Floating point double multiplication (XMM). -defm : BWWriteResPair; // Floating point double multiplication (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -//defm : BWWriteResPair; // Floating point division. -defm : BWWriteResPair; // Floating point division (XMM). -defm : BWWriteResPair; // Floating point division (YMM). -defm : X86WriteResPairUnsupported; -//defm : BWWriteResPair; // Floating point division. -defm : BWWriteResPair; // Floating point division (XMM). -defm : BWWriteResPair; // Floating point division (YMM). -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; // Floating point square root. -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point square root (XMM). -defm : BWWriteResPair; // Floating point square root (YMM). -defm : X86WriteResPairUnsupported; -defm : X86WriteRes; // Floating point double square root. -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point double square root (XMM). -defm : BWWriteResPair; // Floating point double square root (YMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point long double square root. - -defm : BWWriteResPair; // Floating point reciprocal estimate. -defm : BWWriteResPair; // Floating point reciprocal estimate (XMM). -defm : BWWriteResPair; // Floating point reciprocal estimate (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point reciprocal square root estimate. -defm : BWWriteResPair; // Floating point reciprocal square root estimate (XMM). -defm : BWWriteResPair; // Floating point reciprocal square root estimate (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Fused Multiply Add. -defm : BWWriteResPair; // Fused Multiply Add (XMM). -defm : BWWriteResPair; // Fused Multiply Add (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double dot product. -defm : BWWriteResPair; // Floating point single dot product. -defm : BWWriteResPair; // Floating point single dot product (YMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point fabs/fchs. -defm : X86WriteRes; // Floating point rounding. -defm : X86WriteRes; // Floating point rounding (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point and/or/xor logicals. -defm : BWWriteResPair; // Floating point and/or/xor logicals (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point TEST instructions. -defm : BWWriteResPair; // Floating point TEST instructions (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector shuffles. -defm : BWWriteResPair; // Floating point vector shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector variable shuffles. -defm : BWWriteResPair; // Floating point vector variable shuffles. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector blends. -defm : BWWriteResPair; // Floating point vector blends. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Fp vector variable blends. -defm : BWWriteResPair; // Fp vector variable blends. -defm : X86WriteResPairUnsupported; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; - -defm : BWWriteResPair; // Vector integer ALU op, no logicals. -defm : BWWriteResPair; // Vector integer ALU op, no logicals. -defm : BWWriteResPair; // Vector integer ALU op, no logicals (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer and/or/xor. -defm : BWWriteResPair; // Vector integer and/or/xor. -defm : BWWriteResPair; // Vector integer and/or/xor (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer TEST instructions. -defm : BWWriteResPair; // Vector integer TEST instructions (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer multiply. -defm : BWWriteResPair; // Vector integer multiply. -defm : BWWriteResPair; // Vector integer multiply. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PMULLD. -defm : BWWriteResPair; // Vector PMULLD (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector shuffles. -defm : BWWriteResPair; // Vector shuffles. -defm : BWWriteResPair; // Vector shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector variable shuffles. -defm : BWWriteResPair; // Vector variable shuffles. -defm : BWWriteResPair; // Vector variable shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector blends. -defm : BWWriteResPair; // Vector blends (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector variable blends. -defm : BWWriteResPair; // Vector variable blends (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector MPSAD. -defm : BWWriteResPair; // Vector MPSAD. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PSADBW. -defm : BWWriteResPair; // Vector PSADBW. -defm : BWWriteResPair; // Vector PSADBW (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; // Vector integer immediate shifts (XMM). -defm : BWWriteResPair; // Vector integer immediate shifts (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Variable vector shifts. -defm : BWWriteResPair; // Variable vector shifts (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} - -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 23; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 1; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 14; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 19; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 29; - let NumMicroOps = 11; - let ResourceCycles = [2,7,2]; -} -def : WriteRes { - let Latency = 33; - let NumMicroOps = 11; - let ResourceCycles = [2,7,1,1]; -} - -// Carry-less multiplication instructions. -defm : BWWriteResPair; - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : BWWriteResPair; // Fp 256-bit width vector shuffles. -defm : BWWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : BWWriteResPair; // 256-bit width vector shuffles. -defm : BWWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Remaining instrs. - -def BWWriteResGroup1 : SchedWriteRes<[BWPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup1], (instregex "VPSLLVQ(Y?)rr", - "VPSRLVQ(Y?)rr")>; - -def BWWriteResGroup2 : SchedWriteRes<[BWPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup2], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def BWWriteResGroup3 : SchedWriteRes<[BWPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup3], (instregex "MMX_MOVQ2DQrr")>; - -def BWWriteResGroup4 : SchedWriteRes<[BWPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def BWWriteResGroup5 : SchedWriteRes<[BWPort01]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup5], (instrs FINCSTP, FNOP)>; - -def BWWriteResGroup6 : SchedWriteRes<[BWPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup6], (instrs CDQ, CQO)>; - -def BWWriteResGroup7 : SchedWriteRes<[BWPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup7], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def BWWriteResGroup8 : SchedWriteRes<[BWPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup8], (instregex "VPBLENDD(Y?)rri")>; - -def BWWriteResGroup9 : SchedWriteRes<[BWPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup9], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def BWWriteResGroup10 : SchedWriteRes<[BWPort4,BWPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup10], (instregex "FBSTPm", - "ST_FP(32|64|80)m")>; - -def BWWriteResGroup12 : SchedWriteRes<[BWPort01]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup12], (instrs FDECSTP)>; - -def BWWriteResGroup13 : SchedWriteRes<[BWPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup13], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri")>; - -def BWWriteResGroup14 : SchedWriteRes<[BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup14], (instrs LFENCE, - MFENCE, - WAIT, - XGETBV)>; - -def BWWriteResGroup15 : SchedWriteRes<[BWPort0,BWPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup15], (instregex "(V?)CVTPS2PDrr", - "(V?)CVTSS2SDrr")>; - -def BWWriteResGroup16 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup16], (instregex "CLFLUSH")>; - -def BWWriteResGroup17 : SchedWriteRes<[BWPort01,BWPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup17], (instregex "MMX_MOVDQ2Qrr")>; - -def BWWriteResGroup18 : SchedWriteRes<[BWPort237,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup18], (instrs SFENCE)>; - -def BWWriteResGroup20 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup20], (instrs CWD)>; -def: InstRW<[BWWriteResGroup20], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[BWWriteResGroup20], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri", - "SET(A|BE)r")>; - -def BWWriteResGroup22 : SchedWriteRes<[BWPort4,BWPort6,BWPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup22], (instrs FNSTCW16m)>; - -def BWWriteResGroup24 : SchedWriteRes<[BWPort4,BWPort237,BWPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup24], (instregex "MOVBE(16|32|64)mr")>; - -def BWWriteResGroup25 : SchedWriteRes<[BWPort4,BWPort237,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup25], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[BWWriteResGroup25], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def BWWriteResGroup27 : SchedWriteRes<[BWPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup27], (instregex "MMX_CVTPI2PSirr", - "PDEP(32|64)rr", - "PEXT(32|64)rr", - "(V?)CVTDQ2PS(Y?)rr")>; - -def BWWriteResGroup27_16 : SchedWriteRes<[BWPort1, BWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup27_16], (instrs IMUL16rri, IMUL16rri8)>; - -def BWWriteResGroup28 : SchedWriteRes<[BWPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup28], (instregex "VPBROADCASTBrr", - "VPBROADCASTWrr")>; - -def BWWriteResGroup30 : SchedWriteRes<[BWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[BWWriteResGroup30], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def BWWriteResGroup33 : SchedWriteRes<[BWPort5,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup33], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def BWWriteResGroup34 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup34], (instregex "CLD")>; - -def BWWriteResGroup35 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup35], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def BWWriteResGroup36 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup36], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def BWWriteResGroup37 : SchedWriteRes<[BWPort4,BWPort6,BWPort237,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup37], (instregex "CALL(16|32|64)r")>; - -def BWWriteResGroup38 : SchedWriteRes<[BWPort4,BWPort237,BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup38], (instrs CALL64pcrel32)>; -def: InstRW<[BWWriteResGroup38], (instregex "SET(A|BE)m")>; - -def BWWriteResGroup39 : SchedWriteRes<[BWPort0,BWPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup39], (instregex "(V?)CVT(T?)SD2SI64rr", - "(V?)CVT(T?)SD2SIrr", - "(V?)CVT(T?)SS2SI64rr", - "(V?)CVT(T?)SS2SIrr")>; - -def BWWriteResGroup40 : SchedWriteRes<[BWPort0,BWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup40], (instregex "VCVTPS2PDYrr")>; - -def BWWriteResGroup41 : SchedWriteRes<[BWPort0,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup41], (instrs FNSTSW16r)>; - -def BWWriteResGroup42 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup42], (instrs IMUL64r, MUL64r, MULX64rr)>; -def: InstRW<[BWWriteResGroup42], (instregex "MMX_CVTPI2PDirr", - "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVTDQ2PDrr", - "(V?)CVTPD2PSrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI642SDrr", - "(V?)CVTSI2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVT(T?)PD2DQrr")>; - -def BWWriteResGroup42_16 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[BWWriteResGroup42_16], (instrs IMUL16r, MUL16r)>; - -def BWWriteResGroup43 : SchedWriteRes<[BWPort0,BWPort4,BWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup43], (instrs FNSTSWm)>; - -def BWWriteResGroup44 : SchedWriteRes<[BWPort1,BWPort4,BWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup44], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def BWWriteResGroup45 : SchedWriteRes<[BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[BWWriteResGroup45], (instrs FNCLEX)>; - -def BWWriteResGroup46 : SchedWriteRes<[BWPort015,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[BWWriteResGroup46], (instrs VZEROUPPER)>; - -def BWWriteResGroup47 : SchedWriteRes<[BWPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup47], (instregex "(V?)PCMPGTQ(Y?)rr", - "MUL_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup49 : SchedWriteRes<[BWPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup49], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "VBROADCASTSSrm", - "(V?)MOVDDUPrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def BWWriteResGroup50 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup50], (instregex "(V?)CVTSI642SSrr")>; - -def BWWriteResGroup51 : SchedWriteRes<[BWPort1,BWPort6,BWPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup51], (instregex "STR(16|32|64)r")>; - -def BWWriteResGroup52 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup52], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def BWWriteResGroup54 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[BWWriteResGroup54], (instrs PAUSE)>; - -def BWWriteResGroup55 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[BWWriteResGroup55], (instrs XSETBV)>; - -def BWWriteResGroup56 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[BWWriteResGroup56], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def BWWriteResGroup57 : SchedWriteRes<[BWPort4,BWPort237,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[BWWriteResGroup57], (instregex "PUSHF(16|64)")>; - -def BWWriteResGroup58 : SchedWriteRes<[BWPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup58], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def BWWriteResGroup59 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup59], (instregex "(V?)CVTPS2PDrm", - "(V?)CVTSS2SDrm", - "VPSLLVQrm", - "VPSRLVQrm")>; - -def BWWriteResGroup60 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup60], (instregex "VCVTDQ2PDYrr", - "VCVTPD2PSYrr", - "VCVT(T?)PD2DQYrr")>; - -def BWWriteResGroup62 : SchedWriteRes<[BWPort6,BWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup62], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def BWWriteResGroup63 : SchedWriteRes<[BWPort23,BWPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup63], (instregex "BT(16|32|64)mi8")>; - -def BWWriteResGroup64 : SchedWriteRes<[BWPort23,BWPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup64], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def BWWriteResGroup65 : SchedWriteRes<[BWPort23,BWPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup65], (instregex "VINSERTF128rm", - "VINSERTI128rm", - "VPBLENDDrmi")>; - -def BWWriteResGroup66 : SchedWriteRes<[BWPort23,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup66], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[BWWriteResGroup66], (instregex "POP(16|32|64)rmr")>; - -def BWWriteResGroup68 : SchedWriteRes<[BWPort1,BWPort6,BWPort06,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup68], (instregex "SLDT(16|32|64)r")>; - -def BWWriteResGroup69 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup69], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def BWWriteResGroup70 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup70], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def BWWriteResGroup71 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[BWWriteResGroup71], (instrs STD)>; - -def BWWriteResGroup73 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup73], (instregex "VPSLLVQYrm", - "VPSRLVQYrm")>; - -def BWWriteResGroup74 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup74], (instregex "FCOM(P?)(32|64)m")>; - -def BWWriteResGroup77 : SchedWriteRes<[BWPort23,BWPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup77], (instregex "VPBLENDDYrmi")>; - -def BWWriteResGroup79 : SchedWriteRes<[BWPort5,BWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup79], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def BWWriteResGroup80 : SchedWriteRes<[BWPort23,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup80], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def BWWriteResGroup82 : SchedWriteRes<[BWPort0,BWPort01,BWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup82], (instrs FLDCW16m)>; - -def BWWriteResGroup84 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup84], (instrs LRETQ, RETQ)>; - -def BWWriteResGroup87 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup87], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def BWWriteResGroup88 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup88], (instregex "XADD(8|16|32|64)rm")>; - -def BWWriteResGroup89 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[BWWriteResGroup89], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def BWWriteResGroup90 : SchedWriteRes<[BWPort6,BWPort06,BWPort15,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [2,2,1,2]; -} -def: InstRW<[BWWriteResGroup90], (instrs LOOP)>; - -def BWWriteResGroup91 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup91], (instregex "MMX_CVTPI2PSirm", - "PDEP(32|64)rm", - "PEXT(32|64)rm", - "(V?)CVTDQ2PSrm")>; - -def BWWriteResGroup91_16 : SchedWriteRes<[BWPort1, BWPort0156, BWPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup91_16], (instrs IMUL16rmi, IMUL16rmi8)>; - -def BWWriteResGroup91_16_2 : SchedWriteRes<[BWPort1, BWPort06, BWPort0156, BWPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[BWWriteResGroup91_16_2], (instrs IMUL16m, MUL16m)>; - -def BWWriteResGroup92 : SchedWriteRes<[BWPort5,BWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup92], (instregex "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVSXWQYrm", - "VPMOVZXWDYrm")>; - -def BWWriteResGroup97 : SchedWriteRes<[BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup97], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def BWWriteResGroup98 : SchedWriteRes<[BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[BWWriteResGroup98], (instregex "ROR(8|16|32|64)mCL")>; - -def BWWriteResGroup99 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[BWWriteResGroup99], (instregex "XCHG(8|16|32|64)rm")>; - -def BWWriteResGroup100 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def : SchedAlias; -def: InstRW<[BWWriteResGroup100], (instregex "CMPXCHG(8|16|32|64)rm", - "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def BWWriteResGroup101 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup101], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VCVTPS2DQYrm", - "VCVTTPS2DQYrm")>; - -def BWWriteResGroup105 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup105], (instregex "(V?)CVTSS2SI(64)?rm", - "(V?)CVT(T?)SD2SI64rm", - "(V?)CVT(T?)SD2SIrm", - "VCVTTSS2SI64rm", - "(V?)CVTTSS2SIrm")>; - -def BWWriteResGroup106 : SchedWriteRes<[BWPort0,BWPort5,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup106], (instregex "VCVTPS2PDYrm")>; - -def BWWriteResGroup107 : SchedWriteRes<[BWPort1,BWPort5,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup107], (instrs IMUL64m, MUL64m, MULX64rm)>; -def: InstRW<[BWWriteResGroup107], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVTPI2PDirm", - "MMX_CVT(T?)PD2PIirm", - "(V?)CVTDQ2PDrm", - "(V?)CVTSD2SSrm")>; - -def BWWriteResGroup108 : SchedWriteRes<[BWPort5,BWPort23,BWPort015]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup108], (instregex "VPBROADCASTB(Y?)rm", - "VPBROADCASTW(Y?)rm")>; - -def BWWriteResGroup112 : SchedWriteRes<[BWPort23,BWPort06,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[BWWriteResGroup112], (instregex "RDRAND(16|32|64)r")>; - -def BWWriteResGroup113 : SchedWriteRes<[BWPort1,BWPort6,BWPort23,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[BWWriteResGroup113], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def BWWriteResGroup115 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup115], (instregex "(V?)PCMPGTQrm")>; - -def BWWriteResGroup117 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup117], (instregex "FICOM(P?)(16|32)m")>; - -def BWWriteResGroup120 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup120], (instregex "CVTTSS2SI64rm")>; - -def BWWriteResGroup121 : SchedWriteRes<[BWPort1,BWPort23,BWPort06,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup121], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def BWWriteResGroup122_1 : SchedWriteRes<[BWPort0,BWFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; // Really 2.5 cycle throughput -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup123 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup123], (instregex "MUL_F(32|64)m", - "VPCMPGTQYrm")>; - -def BWWriteResGroup128 : SchedWriteRes<[BWPort1,BWPort5,BWPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup128], (instregex "VCVTDQ2PDYrm")>; - -def BWWriteResGroup131 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,2,3]; -} -def: InstRW<[BWWriteResGroup131], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def BWWriteResGroup132 : SchedWriteRes<[BWPort1,BWPort06,BWPort15,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,4,1,3]; -} -def: InstRW<[BWWriteResGroup132], (instregex "RCL8rCL")>; - -def BWWriteResGroup133 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[BWWriteResGroup133], (instrs LOOPE)>; -def: InstRW<[BWWriteResGroup133], (instrs LOOPNE)>; - -def BWWriteResGroup135 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup135], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def BWWriteResGroup139_1 : SchedWriteRes<[BWPort0,BWFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup141 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup141], (instregex "MUL_FI(16|32)m")>; - -def BWWriteResGroup144 : SchedWriteRes<[BWPort1,BWPort6,BWPort23,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 8; - let ResourceCycles = [2,2,1,3]; -} -def: InstRW<[BWWriteResGroup144], (instregex "LAR(16|32|64)rr")>; - -def BWWriteResGroup145 : SchedWriteRes<[BWPort1,BWPort06,BWPort15,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,3,1,4]; -} -def: InstRW<[BWWriteResGroup145], (instregex "RCR8rCL")>; - -def BWWriteResGroup146 : SchedWriteRes<[BWPort0,BWPort1,BWPort6,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 12; - let ResourceCycles = [2,1,4,5]; -} -def: InstRW<[BWWriteResGroup146], (instrs XCH_F)>; - -def BWWriteResGroup147 : SchedWriteRes<[BWPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup147], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup149 : SchedWriteRes<[BWPort1,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,4,1,2]; -} -def: InstRW<[BWWriteResGroup149], (instregex "RCL(8|16|32|64)mCL")>; - -def BWWriteResGroup150 : SchedWriteRes<[BWPort0,BWPort23,BWFPDivider]> { - let Latency = 16; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup153 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[BWWriteResGroup153], (instrs CMPXCHG8B)>; - -def BWWriteResGroup154 : SchedWriteRes<[BWPort5]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[BWWriteResGroup154], (instrs VZEROALL)>; - -def BWWriteResGroup159 : SchedWriteRes<[BWPort5,BWPort6,BWPort06,BWPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[BWWriteResGroup159], (instrs CPUID)>; -def: InstRW<[BWWriteResGroup159], (instrs RDTSC)>; - -def BWWriteResGroup160 : SchedWriteRes<[BWPort1,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,3,1,3]; -} -def: InstRW<[BWWriteResGroup160], (instregex "RCR(8|16|32|64)mCL")>; - -def BWWriteResGroup161 : SchedWriteRes<[BWPort0,BWPort23,BWFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup165 : SchedWriteRes<[BWPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup165], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup167 : SchedWriteRes<[BWPort4,BWPort5,BWPort6,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[BWWriteResGroup167], (instrs INSB, INSL, INSW)>; - -def BWWriteResGroup169 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup169], (instregex "DIV_F(32|64)m")>; - -def BWWriteResGroup171 : SchedWriteRes<[BWPort0,BWPort4,BWPort5,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 21; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[BWWriteResGroup171], (instrs CMPXCHG16B)>; - -def BWWriteResGroup172 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 22; - let NumMicroOps = 18; - let ResourceCycles = [1,1,16]; -} -def: InstRW<[BWWriteResGroup172], (instregex "POPF64")>; - -def BWWriteResGroup176 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [3,1,15]; -} -def: InstRW<[BWWriteResGroup176], (instregex "XRSTOR(64)?")>; - -def BWWriteResGroup177 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 24; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup177], (instregex "DIV_FI(16|32)m")>; - -def BWWriteResGroup180 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 26; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup180], (instregex "DIVR_F(32|64)m")>; - -def BWWriteResGroup182 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 29; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup182], (instregex "DIVR_FI(16|32)m")>; - -def BWWriteResGroup183_1 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 22; - let NumMicroOps = 7; - let ResourceCycles = [1,3,2,1]; -} -def: InstRW<[BWWriteResGroup183_1], (instrs VGATHERQPDrm)>; - -def BWWriteResGroup183_2 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 23; - let NumMicroOps = 9; - let ResourceCycles = [1,3,4,1]; -} -def: InstRW<[BWWriteResGroup183_2], (instrs VGATHERQPDYrm)>; - -def BWWriteResGroup183_3 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_3], (instrs VGATHERQPSYrm)>; - -def BWWriteResGroup183_4 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 25; - let NumMicroOps = 7; - let ResourceCycles = [1,3,2,1]; -} -def: InstRW<[BWWriteResGroup183_4], (instrs VGATHERDPDrm, - VGATHERDPSrm)>; - -def BWWriteResGroup183_5 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 26; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_5], (instrs VGATHERDPDYrm)>; - -def BWWriteResGroup183_6 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 26; - let NumMicroOps = 14; - let ResourceCycles = [1,4,8,1]; -} -def: InstRW<[BWWriteResGroup183_6], (instrs VGATHERDPSYrm)>; - -def BWWriteResGroup183_7 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 27; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_7], (instrs VGATHERQPSrm)>; - -def BWWriteResGroup185 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 29; - let NumMicroOps = 27; - let ResourceCycles = [1,5,1,1,19]; -} -def: InstRW<[BWWriteResGroup185], (instrs XSAVE64)>; - -def BWWriteResGroup186 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 30; - let NumMicroOps = 28; - let ResourceCycles = [1,6,1,1,19]; -} -def: InstRW<[BWWriteResGroup186], (instrs XSAVE)>; -def: InstRW<[BWWriteResGroup186], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def BWWriteResGroup190 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23,BWPort0156]> { - let Latency = 34; - let NumMicroOps = 8; - let ResourceCycles = [2,2,2,1,1]; -} -def: InstRW<[BWWriteResGroup190], (instregex "DIV(8|16|32|64)m")>; - -def BWWriteResGroup191 : SchedWriteRes<[BWPort5,BWPort6,BWPort23,BWPort06,BWPort0156]> { - let Latency = 34; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[BWWriteResGroup191], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def BWWriteResGroup193 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23,BWPort0156]> { - let Latency = 35; - let NumMicroOps = 8; - let ResourceCycles = [2,2,2,1,1]; -} -def: InstRW<[BWWriteResGroup193], (instregex "IDIV(8|16|32|64)m")>; - -def BWWriteResGroup194 : SchedWriteRes<[BWPort5,BWPort6,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[BWWriteResGroup194], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def BWWriteResGroup196 : SchedWriteRes<[BWPort5,BWPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[BWWriteResGroup196], (instrs RDTSCP)>; - -def BWWriteResGroup197 : SchedWriteRes<[BWPort0,BWPort01,BWPort23,BWPort05,BWPort06,BWPort015,BWPort0156]> { - let Latency = 60; - let NumMicroOps = 64; - let ResourceCycles = [2,2,8,1,10,2,39]; -} -def: InstRW<[BWWriteResGroup197], (instrs FLDENVm)>; - -def BWWriteResGroup198 : SchedWriteRes<[BWPort0,BWPort6,BWPort23,BWPort05,BWPort06,BWPort15,BWPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[BWWriteResGroup198], (instrs FXRSTOR64)>; - -def BWWriteResGroup199 : SchedWriteRes<[BWPort0,BWPort6,BWPort23,BWPort05,BWPort06,BWPort15,BWPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[BWWriteResGroup199], (instrs FXRSTOR)>; - -def BWWriteResGroup200 : SchedWriteRes<[BWPort5,BWPort01,BWPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[BWWriteResGroup200], (instrs FNINIT)>; - -def BWWriteResGroup201 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort6,BWPort01,BWPort0156]> { - let Latency = 80; - let NumMicroOps = 32; - let ResourceCycles = [7,7,3,3,1,11]; -} -def: InstRW<[BWWriteResGroup201], (instregex "DIV(16|32|64)r")>; - -def BWWriteResGroup202 : SchedWriteRes<[BWPort0,BWPort1,BWPort4,BWPort5,BWPort6,BWPort237,BWPort06,BWPort0156]> { - let Latency = 115; - let NumMicroOps = 100; - let ResourceCycles = [9,9,11,8,1,11,21,30]; -} -def: InstRW<[BWWriteResGroup202], (instrs FSTENVm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86SchedHaswell.td b/suite/synctools/tablegen/X86/X86SchedHaswell.td deleted file mode 100644 index 876c3e4162..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedHaswell.td +++ /dev/null @@ -1,1975 +0,0 @@ -//=- X86SchedHaswell.td - X86 Haswell Scheduling -------------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Haswell to support instruction -// scheduling and other instruction cost heuristics. -// -// Note that we define some instructions here that are not supported by haswell, -// but we still have to define them because KNL uses the HSW model. -// They are currently tagged with a comment `Unsupported = 1`. -// FIXME: Use Unsupported = 1 once KNL has its own model. -// -//===----------------------------------------------------------------------===// - -def HaswellModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and HW can decode 4 - // instructions per cycle. - let IssueWidth = 4; - let MicroOpBufferSize = 192; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = HaswellModel in { - -// Haswell can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def HWPort0 : ProcResource<1>; -def HWPort1 : ProcResource<1>; -def HWPort2 : ProcResource<1>; -def HWPort3 : ProcResource<1>; -def HWPort4 : ProcResource<1>; -def HWPort5 : ProcResource<1>; -def HWPort6 : ProcResource<1>; -def HWPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def HWPort01 : ProcResGroup<[HWPort0, HWPort1]>; -def HWPort23 : ProcResGroup<[HWPort2, HWPort3]>; -def HWPort237 : ProcResGroup<[HWPort2, HWPort3, HWPort7]>; -def HWPort04 : ProcResGroup<[HWPort0, HWPort4]>; -def HWPort05 : ProcResGroup<[HWPort0, HWPort5]>; -def HWPort06 : ProcResGroup<[HWPort0, HWPort6]>; -def HWPort15 : ProcResGroup<[HWPort1, HWPort5]>; -def HWPort16 : ProcResGroup<[HWPort1, HWPort6]>; -def HWPort56 : ProcResGroup<[HWPort5, HWPort6]>; -def HWPort015 : ProcResGroup<[HWPort0, HWPort1, HWPort5]>; -def HWPort056 : ProcResGroup<[HWPort0, HWPort5, HWPort6]>; -def HWPort0156: ProcResGroup<[HWPort0, HWPort1, HWPort5, HWPort6]>; - -// 60 Entry Unified Scheduler -def HWPortAny : ProcResGroup<[HWPort0, HWPort1, HWPort2, HWPort3, HWPort4, - HWPort5, HWPort6, HWPort7]> { - let BufferSize=60; -} - -// Integer division issued on port 0. -def HWDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def HWFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass HWWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Store_addr on 237. -// Store_data on 4. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes; - -// Arithmetic. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -def : WriteRes { let Latency = 3; } - -// Integer shifts and rotates. -defm : HWWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : HWWriteResPair; // Conditional move. -defm : HWWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -// Conversion between integer and float. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; - -// Vector integer shifts. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// String instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 1; } - -// AES Instructions. -def : WriteRes { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 13; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { - let Latency = 14; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 20; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { - let Latency = 29; - let NumMicroOps = 11; - let ResourceCycles = [2,7,2]; -} -def : WriteRes { - let Latency = 34; - let NumMicroOps = 11; - let ResourceCycles = [2,7,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -//================ Exceptions ================// - -//-- Specific Scheduling Models --// - -// Starting with P0. -def HWWriteP0 : SchedWriteRes<[HWPort0]>; - -def HWWriteP01 : SchedWriteRes<[HWPort01]>; - -def HWWrite2P01 : SchedWriteRes<[HWPort01]> { - let NumMicroOps = 2; -} -def HWWrite3P01 : SchedWriteRes<[HWPort01]> { - let NumMicroOps = 3; -} - -def HWWriteP0156_P23 : SchedWriteRes<[HWPort0156, HWPort23]> { - let NumMicroOps = 2; -} - -def HWWrite2P0156_P23 : SchedWriteRes<[HWPort0156, HWPort23]> { - let NumMicroOps = 3; - let ResourceCycles = [2, 1]; -} - -// Starting with P1. -def HWWriteP1 : SchedWriteRes<[HWPort1]>; - - -def HWWrite2P1 : SchedWriteRes<[HWPort1]> { - let NumMicroOps = 2; - let ResourceCycles = [2]; -} - -// Notation: -// - r: register. -// - mm: 64 bit mmx register. -// - x = 128 bit xmm register. -// - (x)mm = mmx or xmm register. -// - y = 256 bit ymm register. -// - v = any vector register. -// - m = memory. - -//=== Integer Instructions ===// -//-- Move instructions --// - -// XLAT. -def HWWriteXLAT : SchedWriteRes<[]> { - let Latency = 7; - let NumMicroOps = 3; -} -def : InstRW<[HWWriteXLAT], (instrs XLAT)>; - -// PUSHA. -def HWWritePushA : SchedWriteRes<[]> { - let NumMicroOps = 19; -} -def : InstRW<[HWWritePushA], (instregex "PUSHA(16|32)")>; - -// POPA. -def HWWritePopA : SchedWriteRes<[]> { - let NumMicroOps = 18; -} -def : InstRW<[HWWritePopA], (instregex "POPA(16|32)")>; - -//-- Arithmetic instructions --// - -// DIV. -// r8. -def HWWriteDiv8 : SchedWriteRes<[HWPort0, HWPort1, HWPort5, HWPort6]> { - let Latency = 22; - let NumMicroOps = 9; -} -def : InstRW<[HWWriteDiv8], (instregex "DIV8r")>; - -// IDIV. -// r8. -def HWWriteIDiv8 : SchedWriteRes<[HWPort0, HWPort1, HWPort5, HWPort6]> { - let Latency = 23; - let NumMicroOps = 9; -} -def : InstRW<[HWWriteIDiv8], (instregex "IDIV8r")>; - -// BT. -// m,r. -def HWWriteBTmr : SchedWriteRes<[]> { - let NumMicroOps = 10; -} -def : InstRW<[HWWriteBTmr], (instregex "BT(16|32|64)mr")>; - -// BTR BTS BTC. -// m,r. -def HWWriteBTRSCmr : SchedWriteRes<[]> { - let NumMicroOps = 11; -} -def : InstRW<[HWWriteBTRSCmr], (instregex "BT(R|S|C)(16|32|64)mr")>; - -//-- Control transfer instructions --// - -// CALL. -// i. -def HWWriteRETI : SchedWriteRes<[HWPort23, HWPort6, HWPort015]> { - let NumMicroOps = 4; - let ResourceCycles = [1, 2, 1]; -} -def : InstRW<[HWWriteRETI], (instregex "RETI(L|Q|W)", "LRETI(L|Q|W)")>; - -// BOUND. -// r,m. -def HWWriteBOUND : SchedWriteRes<[]> { - let NumMicroOps = 15; -} -def : InstRW<[HWWriteBOUND], (instregex "BOUNDS(16|32)rm")>; - -// INTO. -def HWWriteINTO : SchedWriteRes<[]> { - let NumMicroOps = 4; -} -def : InstRW<[HWWriteINTO], (instrs INTO)>; - -//-- String instructions --// - -// LODSB/W. -def : InstRW<[HWWrite2P0156_P23], (instregex "LODS(B|W)")>; - -// LODSD/Q. -def : InstRW<[HWWriteP0156_P23], (instregex "LODS(L|Q)")>; - -// MOVS. -def HWWriteMOVS : SchedWriteRes<[HWPort23, HWPort4, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 5; - let ResourceCycles = [2, 1, 2]; -} -def : InstRW<[HWWriteMOVS], (instrs MOVSB, MOVSL, MOVSQ, MOVSW)>; - -// CMPS. -def HWWriteCMPS : SchedWriteRes<[HWPort23, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 5; - let ResourceCycles = [2, 3]; -} -def : InstRW<[HWWriteCMPS], (instregex "CMPS(B|L|Q|W)")>; - -//-- Other --// - -// RDPMC.f -def HWWriteRDPMC : SchedWriteRes<[]> { - let NumMicroOps = 34; -} -def : InstRW<[HWWriteRDPMC], (instrs RDPMC)>; - -// RDRAND. -def HWWriteRDRAND : SchedWriteRes<[HWPort23, HWPort015]> { - let NumMicroOps = 17; - let ResourceCycles = [1, 16]; -} -def : InstRW<[HWWriteRDRAND], (instregex "RDRAND(16|32|64)r")>; - -//=== Floating Point x87 Instructions ===// -//-- Move instructions --// - -// FLD. -// m80. -def : InstRW<[HWWriteP01], (instregex "LD_Frr")>; - -// FBLD. -// m80. -def HWWriteFBLD : SchedWriteRes<[]> { - let Latency = 47; - let NumMicroOps = 43; -} -def : InstRW<[HWWriteFBLD], (instregex "FBLDm")>; - -// FST(P). -// r. -def : InstRW<[HWWriteP01], (instregex "ST_(F|FP)rr")>; - -// FFREE. -def : InstRW<[HWWriteP01], (instregex "FFREE")>; - -// FNSAVE. -def HWWriteFNSAVE : SchedWriteRes<[]> { - let NumMicroOps = 147; -} -def : InstRW<[HWWriteFNSAVE], (instregex "FSAVEm")>; - -// FRSTOR. -def HWWriteFRSTOR : SchedWriteRes<[]> { - let NumMicroOps = 90; -} -def : InstRW<[HWWriteFRSTOR], (instregex "FRSTORm")>; - -//-- Arithmetic instructions --// - -// FCOMPP FUCOMPP. -// r. -def : InstRW<[HWWrite2P01], (instrs FCOMPP, UCOM_FPPr)>; - -// FCOMI(P) FUCOMI(P). -// m. -def : InstRW<[HWWrite3P01], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -// FTST. -def : InstRW<[HWWriteP1], (instregex "TST_F")>; - -// FXAM. -def : InstRW<[HWWrite2P1], (instrs FXAM)>; - -// FPREM. -def HWWriteFPREM : SchedWriteRes<[]> { - let Latency = 19; - let NumMicroOps = 28; -} -def : InstRW<[HWWriteFPREM], (instrs FPREM)>; - -// FPREM1. -def HWWriteFPREM1 : SchedWriteRes<[]> { - let Latency = 27; - let NumMicroOps = 41; -} -def : InstRW<[HWWriteFPREM1], (instrs FPREM1)>; - -// FRNDINT. -def HWWriteFRNDINT : SchedWriteRes<[]> { - let Latency = 11; - let NumMicroOps = 17; -} -def : InstRW<[HWWriteFRNDINT], (instrs FRNDINT)>; - -//-- Math instructions --// - -// FSCALE. -def HWWriteFSCALE : SchedWriteRes<[]> { - let Latency = 75; // 49-125 - let NumMicroOps = 50; // 25-75 -} -def : InstRW<[HWWriteFSCALE], (instrs FSCALE)>; - -// FXTRACT. -def HWWriteFXTRACT : SchedWriteRes<[]> { - let Latency = 15; - let NumMicroOps = 17; -} -def : InstRW<[HWWriteFXTRACT], (instrs FXTRACT)>; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -//=== Floating Point XMM and YMM Instructions ===// - -// Remaining instrs. - -def HWWriteResGroup0 : SchedWriteRes<[HWPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCAST(D|Q)rm")>; - -def HWWriteResGroup0_1 : SchedWriteRes<[HWPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0_1], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCAST(D|Q)Yrm")>; - -def HWWriteResGroup0_2 : SchedWriteRes<[HWPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0_2], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; - -def HWWriteResGroup1 : SchedWriteRes<[HWPort4,HWPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup1], (instregex "FBSTPm", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def HWWriteResGroup2 : SchedWriteRes<[HWPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup2], (instregex "VPSLLVQ(Y?)rr", - "VPSRLVQ(Y?)rr")>; - -def HWWriteResGroup3 : SchedWriteRes<[HWPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup3], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def HWWriteResGroup4 : SchedWriteRes<[HWPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup4], (instregex "MMX_MOVQ2DQrr")>; - -def HWWriteResGroup5 : SchedWriteRes<[HWPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup5], (instregex "JMP(16|32|64)r")>; - -def HWWriteResGroup6 : SchedWriteRes<[HWPort01]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def HWWriteResGroup7 : SchedWriteRes<[HWPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup7], (instrs CDQ, CQO)>; - -def HWWriteResGroup8 : SchedWriteRes<[HWPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def HWWriteResGroup9 : SchedWriteRes<[HWPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup9], (instregex "VPBLENDD(Y?)rri")>; - -def HWWriteResGroup10 : SchedWriteRes<[HWPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[HWWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def HWWriteResGroup11 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11], (instregex "(V?)CVTPS2PDrm")>; - -def HWWriteResGroup11_1 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11_1], (instregex "(V?)CVTSS2SDrm", - "VPSLLVQrm", - "VPSRLVQrm")>; - -def HWWriteResGroup11_2 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11_2], (instregex "VPSLLVQYrm", - "VPSRLVQYrm")>; - -def HWWriteResGroup12 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup12], (instregex "MMX_CVTPI2PSirm", - "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def HWWriteResGroup12_1 : SchedWriteRes<[HWPort1,HWPort0156,HWPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup12_1], (instrs IMUL16rmi, IMUL16rmi8)>; - -def HWWriteResGroup12_2 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156,HWPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[HWWriteResGroup12_2], (instrs IMUL16m, MUL16m)>; - -def HWWriteResGroup13 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup13], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def HWWriteResGroup13_1 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup13_1], (instregex "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def HWWriteResGroup14 : SchedWriteRes<[HWPort6,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup14], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def HWWriteResGroup15 : SchedWriteRes<[HWPort23,HWPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup15], (instregex "BT(16|32|64)mi8")>; - -def HWWriteResGroup16 : SchedWriteRes<[HWPort23,HWPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup16], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def HWWriteResGroup17 : SchedWriteRes<[HWPort23,HWPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup17], (instregex "VINSERTF128rm", - "VINSERTI128rm", - "VPBLENDDrmi")>; - -def HWWriteResGroup17_2 : SchedWriteRes<[HWPort23,HWPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup17_2], (instregex "VPBLENDDYrmi")>; - -def HWWriteResGroup18 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup18], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[HWWriteResGroup18], (instregex "POP(16|32|64)rmr")>; - -def HWWriteResGroup19 : SchedWriteRes<[HWPort237,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup19], (instrs SFENCE)>; - -def HWWriteResGroup21 : SchedWriteRes<[HWPort4,HWPort6,HWPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup21], (instrs FNSTCW16m)>; - -def HWWriteResGroup23 : SchedWriteRes<[HWPort4,HWPort237,HWPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup23], (instregex "MOVBE(32|64)mr")>; - -def HWWriteResGroup23_16 : SchedWriteRes<[HWPort06, HWPort237, HWPort4]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup23_16], (instrs MOVBE16mr)>; - -def HWWriteResGroup24 : SchedWriteRes<[HWPort4,HWPort237,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup24], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[HWWriteResGroup24], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def HWWriteResGroup25 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup25], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def HWWriteResGroup26 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup26], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def HWWriteResGroup28 : SchedWriteRes<[HWPort01]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup28], (instrs FDECSTP)>; - -def HWWriteResGroup29 : SchedWriteRes<[HWPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup29], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri")>; - -def HWWriteResGroup30 : SchedWriteRes<[HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup30], (instrs LFENCE, - MFENCE, - WAIT, - XGETBV)>; - -def HWWriteResGroup31 : SchedWriteRes<[HWPort0,HWPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup31], (instregex "(V?)CVTPS2PDrr", - "(V?)CVTSS2SDrr")>; - -def HWWriteResGroup32 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup32], (instregex "CLFLUSH")>; - -def HWWriteResGroup33 : SchedWriteRes<[HWPort01,HWPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup33], (instregex "MMX_MOVDQ2Qrr")>; - -def HWWriteResGroup35 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup35], (instrs CWD, JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[HWWriteResGroup35], (instregex "SET(A|BE)r")>; - -def HWWriteResGroup36_2 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup36_2], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def HWWriteResGroup37 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup37], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def HWWriteResGroup39 : SchedWriteRes<[HWPort0,HWPort01,HWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup39], (instrs FLDCW16m)>; - -def HWWriteResGroup41 : SchedWriteRes<[HWPort6,HWPort23,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup41], (instrs LRETQ, RETL, RETQ)>; - -def HWWriteResGroup44 : SchedWriteRes<[HWPort4,HWPort6,HWPort237,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup44], (instregex "CALL(16|32|64)r")>; - -def HWWriteResGroup45 : SchedWriteRes<[HWPort4,HWPort237,HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup45], (instrs CALL64pcrel32)>; -def: InstRW<[HWWriteResGroup45], (instregex "SET(A|BE)m")>; - -def HWWriteResGroup46 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup46], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def HWWriteResGroup47 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup47], (instregex "XADD(8|16|32|64)rm")>; - -def HWWriteResGroup48 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[HWWriteResGroup48], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def HWWriteResGroup50 : SchedWriteRes<[HWPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup50], (instregex "MMX_CVTPI2PSirr", - "PDEP(32|64)rr", - "PEXT(32|64)rr", - "(V?)CVTDQ2PS(Y?)rr")>; - -def HWWriteResGroup50_16i : SchedWriteRes<[HWPort1, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup50_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def HWWriteResGroup51 : SchedWriteRes<[HWPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup51], (instregex "VPBROADCAST(B|W)rr")>; - -def HWWriteResGroup52 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup52], (instregex "(V?)CVTPS2DQrm", - "(V?)CVTTPS2DQrm")>; - -def HWWriteResGroup52_1 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup52_1], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VCVTDQ2PSYrm", - "VCVTPS2DQYrm", - "VCVTTPS2DQYrm")>; - -def HWWriteResGroup53_1 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup53_1], (instregex "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVZXWDYrm")>; - -def HWWriteResGroup54 : SchedWriteRes<[HWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[HWWriteResGroup54], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def HWWriteResGroup57 : SchedWriteRes<[HWPort5,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup57], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def HWWriteResGroup58 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup58], (instregex "CLD")>; - -def HWWriteResGroup59 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup59], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def HWWriteResGroup60 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup60], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def HWWriteResGroup61 : SchedWriteRes<[HWPort0,HWPort4,HWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup61], (instrs FNSTSWm)>; - -def HWWriteResGroup62 : SchedWriteRes<[HWPort1,HWPort4,HWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup62], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def HWWriteResGroup66 : SchedWriteRes<[HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup66], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def HWWriteResGroup67 : SchedWriteRes<[HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[HWWriteResGroup67], (instregex "ROR(8|16|32|64)mCL")>; - -def HWWriteResGroup68 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[HWWriteResGroup68], (instregex "XCHG(8|16|32|64)rm")>; - -def HWWriteResGroup69 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: InstRW<[HWWriteResGroup69], (instregex "CMPXCHG(8|16|32|64)rm", - "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; -def: SchedAlias; - -def HWWriteResGroup70 : SchedWriteRes<[HWPort0,HWPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup70], (instregex "(V?)CVT(T?)SD2SI(64)?rr", - "(V?)CVT(T?)SS2SI(64)?rr")>; - -def HWWriteResGroup71 : SchedWriteRes<[HWPort0,HWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup71], (instregex "VCVTPS2PDYrr")>; - -def HWWriteResGroup72 : SchedWriteRes<[HWPort0,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup72], (instrs FNSTSW16r)>; - -def HWWriteResGroup73 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup73], (instregex "MMX_CVTPI2PDirr", - "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVTDQ2PDrr", - "(V?)CVTPD2PSrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI(64)?2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVT(T?)PD2DQrr")>; - -def HWWriteResGroup74 : SchedWriteRes<[HWPort1,HWPort6]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup74], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def HWWriteResGroup74_16 : SchedWriteRes<[HWPort1, HWPort06, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[HWWriteResGroup74_16], (instrs IMUL16r, MUL16r)>; - -def HWWriteResGroup75 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup75], (instregex "FICOM(P?)(16|32)m")>; - -def HWWriteResGroup76 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup76], (instregex "(V?)CVTSD2SI(64)?rm", - "(V?)CVTSS2SI(64)?rm", - "(V?)CVTTSD2SI(64)?rm", - "VCVTTSS2SI64rm", - "(V?)CVTTSS2SIrm")>; - -def HWWriteResGroup77 : SchedWriteRes<[HWPort0,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup77], (instregex "VCVTPS2PDYrm")>; - -def HWWriteResGroup78 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup78], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm", - "(V?)CVTDQ2PDrm")>; - -def HWWriteResGroup78_1 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup78_1], (instregex "MMX_CVTPI2PDirm", - "(V?)CVTSD2SSrm")>; - -def HWWriteResGroup79 : SchedWriteRes<[HWPort1,HWPort6,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup79], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def HWWriteResGroup80 : SchedWriteRes<[HWPort5,HWPort23,HWPort015]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup80], (instregex "VPBROADCAST(B|W)(Y?)rm")>; - -def HWWriteResGroup81 : SchedWriteRes<[HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[HWWriteResGroup81], (instrs FNCLEX)>; - -def HWWriteResGroup82 : SchedWriteRes<[HWPort015,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[HWWriteResGroup82], (instrs VZEROUPPER)>; - -def HWWriteResGroup83 : SchedWriteRes<[HWPort1,HWPort6,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[HWWriteResGroup83], (instregex "LAR(16|32|64)rr")>; - -def HWWriteResGroup87 : SchedWriteRes<[HWPort1,HWPort6,HWPort23,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[HWWriteResGroup87], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def HWWriteResGroup88 : SchedWriteRes<[HWPort4,HWPort237,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[HWWriteResGroup88], (instregex "PUSHF(16|64)")>; - -def HWWriteResGroup89 : SchedWriteRes<[HWPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup89], (instregex "(V?)PCMPGTQ(Y?)rr", - "MUL_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup91_2 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup91_2], (instregex "(V?)PCMPGTQrm")>; - -def HWWriteResGroup91_3 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup91_3], (instregex "MUL_F(32|64)m", - "VPCMPGTQYrm")>; - -def HWWriteResGroup93 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup93], (instregex "(V?)CVTSI642SSrr")>; - -def HWWriteResGroup94 : SchedWriteRes<[HWPort1,HWPort6,HWPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup94], (instregex "STR(16|32|64)r")>; - -def HWWriteResGroup95 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup95], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def HWWriteResGroup97 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup97], (instregex "CVTTSS2SI64rm")>; - -def HWWriteResGroup98 : SchedWriteRes<[HWPort1,HWPort23,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup98], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def HWWriteResGroup99 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[HWWriteResGroup99], (instrs PAUSE)>; - -def HWWriteResGroup100 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[HWWriteResGroup100], (instrs XSETBV)>; - -def HWWriteResGroup101 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[HWWriteResGroup101], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def HWWriteResGroup102 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup102], (instregex "VCVTDQ2PDYrr", - "VCVTPD2PSYrr", - "VCVT(T?)PD2DQYrr")>; - -def HWWriteResGroup103 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup103], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def HWWriteResGroup104 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup104], (instregex "VCVTDQ2PDYrm")>; - -def HWWriteResGroup107 : SchedWriteRes<[HWPort1,HWPort6,HWPort06,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup107], (instregex "SLDT(16|32|64)r")>; - -def HWWriteResGroup108 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[HWWriteResGroup108], (instrs STD)>; - -def HWWriteResGroup114 : SchedWriteRes<[HWPort6,HWPort06,HWPort15,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [2,2,1,2]; -} -def: InstRW<[HWWriteResGroup114], (instrs LOOP)>; - -def HWWriteResGroup115 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 15; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup115], (instregex "MUL_FI(16|32)m")>; - -def HWWriteResGroup120 : SchedWriteRes<[HWPort1,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 16; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,4,1,2]; -} -def: InstRW<[HWWriteResGroup120], (instregex "RCL(8|16|32|64)mCL")>; - -def HWWriteResGroup129 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,2,3]; -} -def: InstRW<[HWWriteResGroup129], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def HWWriteResGroup130 : SchedWriteRes<[HWPort1,HWPort06,HWPort15,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,4,1,3]; -} -def: InstRW<[HWWriteResGroup130], (instregex "RCL8rCL")>; - -def HWWriteResGroup131 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[HWWriteResGroup131], (instrs LOOPE, LOOPNE)>; - -def HWWriteResGroup132 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 17; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[HWWriteResGroup132], (instrs CMPXCHG8B)>; - -def HWWriteResGroup135 : SchedWriteRes<[HWPort1,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 19; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,3,1,3]; -} -def: InstRW<[HWWriteResGroup135], (instregex "RCR(8|16|32|64)mCL")>; - -def HWWriteResGroup142 : SchedWriteRes<[HWPort1,HWPort06,HWPort15,HWPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,3,1,4]; -} -def: InstRW<[HWWriteResGroup142], (instregex "RCR8rCL")>; - -def HWWriteResGroup143 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 19; - let NumMicroOps = 15; - let ResourceCycles = [1,14]; -} -def: InstRW<[HWWriteResGroup143], (instregex "POPF16")>; - -def HWWriteResGroup144 : SchedWriteRes<[HWPort4,HWPort5,HWPort6,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 21; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[HWWriteResGroup144], (instrs INSB, INSL, INSW)>; - -def HWWriteResGroup145 : SchedWriteRes<[HWPort5]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[HWWriteResGroup145], (instrs VZEROALL)>; - -def HWWriteResGroup146 : SchedWriteRes<[HWPort0,HWPort4,HWPort5,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 22; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[HWWriteResGroup146], (instrs CMPXCHG16B)>; - -def HWWriteResGroup147 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort01,HWPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[HWWriteResGroup147], (instrs XCH_F)>; - -def HWWriteResGroup149 : SchedWriteRes<[HWPort5,HWPort6,HWPort06,HWPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[HWWriteResGroup149], (instrs CPUID, RDTSC)>; - -def HWWriteResGroup151 : SchedWriteRes<[HWPort6,HWPort23,HWPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [3,1,15]; -} -def: InstRW<[HWWriteResGroup151], (instregex "XRSTOR(64)?")>; - -def HWWriteResGroup154 : SchedWriteRes<[HWPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup154], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup155 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup155], (instregex "DIVR_F(32|64)m")>; - -def HWWriteResGroup156 : SchedWriteRes<[HWPort5,HWPort6,HWPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[HWWriteResGroup156], (instrs MWAITrr)>; - -def HWWriteResGroup161 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup161], (instregex "DIVR_FI(16|32)m")>; - -def HWWriteResGroup162 : SchedWriteRes<[HWPort0]> { - let Latency = 24; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup162], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup163 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 31; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup163], (instregex "DIV_F(32|64)m")>; - -def HWWriteResGroup164 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 30; - let NumMicroOps = 27; - let ResourceCycles = [1,5,1,1,19]; -} -def: InstRW<[HWWriteResGroup164], (instrs XSAVE64)>; - -def HWWriteResGroup165 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 31; - let NumMicroOps = 28; - let ResourceCycles = [1,6,1,1,19]; -} -def: InstRW<[HWWriteResGroup165], (instrs XSAVE)>; -def: InstRW<[HWWriteResGroup165], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def HWWriteResGroup166 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 34; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup166], (instregex "DIV_FI(16|32)m")>; - -def HWWriteResGroup170 : SchedWriteRes<[HWPort5,HWPort6,HWPort23,HWPort06,HWPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[HWWriteResGroup170], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def HWWriteResGroup171 : SchedWriteRes<[HWPort5,HWPort6,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 36; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[HWWriteResGroup171], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def HWWriteResGroup175 : SchedWriteRes<[HWPort1,HWPort4,HWPort5,HWPort6,HWPort23,HWPort237,HWPort15,HWPort0156]> { - let Latency = 41; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[HWWriteResGroup175], (instrs VMCLEARm)>; - -def HWWriteResGroup176 : SchedWriteRes<[HWPort5,HWPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[HWWriteResGroup176], (instrs RDTSCP)>; - -def HWWriteResGroup177 : SchedWriteRes<[HWPort0,HWPort01,HWPort23,HWPort05,HWPort06,HWPort015,HWPort0156]> { - let Latency = 61; - let NumMicroOps = 64; - let ResourceCycles = [2,2,8,1,10,2,39]; -} -def: InstRW<[HWWriteResGroup177], (instrs FLDENVm)>; - -def HWWriteResGroup178 : SchedWriteRes<[HWPort0,HWPort6,HWPort23,HWPort05,HWPort06,HWPort15,HWPort0156]> { - let Latency = 64; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[HWWriteResGroup178], (instrs FXRSTOR64)>; - -def HWWriteResGroup179 : SchedWriteRes<[HWPort0,HWPort6,HWPort23,HWPort05,HWPort06,HWPort15,HWPort0156]> { - let Latency = 64; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[HWWriteResGroup179], (instrs FXRSTOR)>; - -def HWWriteResGroup180 : SchedWriteRes<[HWPort5,HWPort01,HWPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[HWWriteResGroup180], (instrs FNINIT)>; - -def HWWriteResGroup181 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort01,HWPort0156]> { - let Latency = 98; - let NumMicroOps = 32; - let ResourceCycles = [7,7,3,3,1,11]; -} -def: InstRW<[HWWriteResGroup181], (instregex "DIV(16|32|64)r")>; - -def HWWriteResGroup182 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort06,HWPort0156]> { - let Latency = 112; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[HWWriteResGroup182], (instregex "IDIV(16|32|64)r")>; - -def HWWriteResGroup183 : SchedWriteRes<[HWPort0,HWPort1,HWPort4,HWPort5,HWPort6,HWPort237,HWPort06,HWPort0156]> { - let Latency = 115; - let NumMicroOps = 100; - let ResourceCycles = [9,9,11,8,1,11,21,30]; -} -def: InstRW<[HWWriteResGroup183], (instrs FSTENVm)>; - -def HWWriteResGroup184 : SchedWriteRes<[HWPort0, HWPort5, HWPort15, HWPort015, HWPort06, HWPort23]> { - let Latency = 26; - let NumMicroOps = 12; - let ResourceCycles = [2,2,1,3,2,2]; -} -def: InstRW<[HWWriteResGroup184], (instrs VGATHERDPDrm, - VPGATHERDQrm, - VPGATHERDDrm)>; - -def HWWriteResGroup185 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 24; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup185], (instrs VGATHERQPDYrm, - VPGATHERQQYrm)>; - -def HWWriteResGroup186 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 28; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup186], (instrs VPGATHERQDYrm)>; - -def HWWriteResGroup187 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 25; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup187], (instrs VPGATHERQDrm)>; - -def HWWriteResGroup188 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 27; - let NumMicroOps = 20; - let ResourceCycles = [3,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup188], (instrs VGATHERDPDYrm, - VPGATHERDQYrm)>; - -def HWWriteResGroup189 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 27; - let NumMicroOps = 34; - let ResourceCycles = [5,3,8,1,9,8]; -} -def: InstRW<[HWWriteResGroup189], (instrs VGATHERDPSYrm, - VPGATHERDDYrm)>; - -def HWWriteResGroup190 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 23; - let NumMicroOps = 14; - let ResourceCycles = [3,3,2,1,3,2]; -} -def: InstRW<[HWWriteResGroup190], (instrs VGATHERQPDrm, - VPGATHERQQrm)>; - -def HWWriteResGroup191 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 28; - let NumMicroOps = 15; - let ResourceCycles = [3,3,2,1,4,2]; -} -def: InstRW<[HWWriteResGroup191], (instrs VGATHERQPSYrm)>; - -def HWWriteResGroup192 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 25; - let NumMicroOps = 15; - let ResourceCycles = [3,3,2,1,4,2]; -} -def: InstRW<[HWWriteResGroup192], (instrs VGATHERQPSrm, - VGATHERDPSrm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86SchedPredicates.td b/suite/synctools/tablegen/X86/X86SchedPredicates.td deleted file mode 100644 index 27aaeb1935..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedPredicates.td +++ /dev/null @@ -1,49 +0,0 @@ -//===-- X86SchedPredicates.td - X86 Scheduling Predicates --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines scheduling predicate definitions that are common to -// all X86 subtargets. -// -//===----------------------------------------------------------------------===// - -// A predicate used to identify dependency-breaking instructions that clear the -// content of the destination register. Note that this predicate only checks if -// input registers are the same. This predicate doesn't make any assumptions on -// the expected instruction opcodes, because different processors may implement -// different zero-idioms. -def ZeroIdiomPredicate : CheckSameRegOperand<1, 2>; - -// A predicate used to check if an instruction is a LEA, and if it uses all -// three source operands: base, index, and offset. -def IsThreeOperandsLEAPredicate: CheckAll<[ - CheckOpcode<[LEA32r, LEA64r, LEA64_32r, LEA16r]>, - - // isRegOperand(Base) - CheckIsRegOperand<1>, - CheckNot>, - - // isRegOperand(Index) - CheckIsRegOperand<3>, - CheckNot>, - - // hasLEAOffset(Offset) - CheckAny<[ - CheckAll<[ - CheckIsImmOperand<4>, - CheckNot> - ]>, - CheckNonPortable<"MI.getOperand(4).isGlobal()"> - ]> -]>; - -// This predicate evaluates to true only if the input machine instruction is a -// 3-operands LEA. Tablegen automatically generates a new method for it in -// X86GenInstrInfo. -def IsThreeOperandsLEAFn : - TIIPredicate<"X86", "isThreeOperandsLEA", IsThreeOperandsLEAPredicate>; diff --git a/suite/synctools/tablegen/X86/X86SchedSandyBridge.td b/suite/synctools/tablegen/X86/X86SchedSandyBridge.td deleted file mode 100644 index 6b7bbdea86..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedSandyBridge.td +++ /dev/null @@ -1,1159 +0,0 @@ -//=- X86SchedSandyBridge.td - X86 Sandy Bridge Scheduling ----*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Sandy Bridge to support instruction -// scheduling and other instruction cost heuristics. -// -// Note that we define some instructions here that are not supported by SNB, -// but we still have to define them because SNB is the default subtarget for -// X86. These instructions are tagged with a comment `Unsupported = 1`. -// -//===----------------------------------------------------------------------===// - -def SandyBridgeModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SB can decode 4 - // instructions per cycle. - // FIXME: Identify instructions that aren't a single fused micro-op. - let IssueWidth = 4; - let MicroOpBufferSize = 168; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size. - let LoopMicroOpBufferSize = 28; - - // This flag is set to allow the scheduler to assign - // a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SandyBridgeModel in { - -// Sandy Bridge can issue micro-ops to 6 different ports in one cycle. - -// Ports 0, 1, and 5 handle all computation. -def SBPort0 : ProcResource<1>; -def SBPort1 : ProcResource<1>; -def SBPort5 : ProcResource<1>; - -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. -def SBPort23 : ProcResource<2>; - -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -def SBPort4 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SBPort01 : ProcResGroup<[SBPort0, SBPort1]>; -def SBPort05 : ProcResGroup<[SBPort0, SBPort5]>; -def SBPort15 : ProcResGroup<[SBPort1, SBPort5]>; -def SBPort015 : ProcResGroup<[SBPort0, SBPort1, SBPort5]>; - -// 54 Entry Unified Scheduler -def SBPortAny : ProcResGroup<[SBPort0, SBPort1, SBPort23, SBPort4, SBPort5]> { - let BufferSize=54; -} - -// Integer division issued on port 0. -def SBDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def SBFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SBWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3 cycle to recompute the address. -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 5; } -def : WriteRes; -def : WriteRes; - -// Arithmetic. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -def : WriteRes { let Latency = 3; } - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -defm : SBWriteResPair; // Conditional move. -defm : SBWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -// NOTE: These don't exist on Sandy Bridge. Ports are guesses. -defm : SBWriteResPair; -defm : SBWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Conversion between integer and float. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : SBWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; // TODO this is probably wrong for 256/512-bit for the "generic" model -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; - -// Vector integer shifts. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 7; - let NumMicroOps = 2; -} - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 5; - let NumMicroOps = 3; -} - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -//////////////////////////////////////////////////////////////////////////////// -// String instructions. -//////////////////////////////////////////////////////////////////////////////// - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let ResourceCycles = [8]; -} -def : WriteRes { - let Latency = 11; - let ResourceCycles = [7, 1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 4; - let ResourceCycles = [8]; -} -def : WriteRes { - let Latency = 4; - let ResourceCycles = [7, 1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 1; } - -// AES Instructions. -def : WriteRes { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def : WriteRes { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} - -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 18; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [11]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [10, 1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 14; - let ResourceCycles = [18]; -} -def : WriteRes { - let Latency = 14; - let ResourceCycles = [17, 1]; -} - -// Load/store MXCSR. -// FIXME: This is probably wrong. Only STMXCSR should require Port4. -def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } -def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -// AVX2/FMA is not supported on that architecture, but we should define the basic -// scheduling resources anyway. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Remaining SNB instrs. - -def SBWriteResGroup1 : SchedWriteRes<[SBPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup1], (instrs COMP_FST0r, - COM_FST0r, - UCOM_FPr, - UCOM_Fr)>; - -def SBWriteResGroup2 : SchedWriteRes<[SBPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup2], (instrs FDECSTP, FINCSTP, FFREE, FFREEP, FNOP, - LD_Frr, ST_Frr, ST_FPrr)>; -def: InstRW<[SBWriteResGroup2], (instrs LOOP, LOOPE, LOOPNE)>; // FIXME: This seems wrong compared to other Intel CPUs. -def: InstRW<[SBWriteResGroup2], (instrs RETQ)>; - -def SBWriteResGroup4 : SchedWriteRes<[SBPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup4], (instrs CDQ, CQO)>; - -def SBWriteResGroup5 : SchedWriteRes<[SBPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup5], (instregex "MMX_PABS(B|D|W)rr", - "MMX_PADDQirr", - "MMX_PALIGNRrri", - "MMX_PSIGN(B|D|W)rr")>; - -def SBWriteResGroup9 : SchedWriteRes<[SBPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SBWriteResGroup9], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SBWriteResGroup11 : SchedWriteRes<[SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SBWriteResGroup11], (instrs SCASB, - SCASL, - SCASQ, - SCASW)>; - -def SBWriteResGroup12 : SchedWriteRes<[SBPort0,SBPort1]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup12], (instregex "(V?)COMISDrr", - "(V?)COMISSrr", - "(V?)UCOMISDrr", - "(V?)UCOMISSrr")>; - -def SBWriteResGroup15 : SchedWriteRes<[SBPort0,SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup15], (instrs CWD, - FNSTSW16r)>; - -def SBWriteResGroup18 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup18], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SBWriteResGroup18], (instregex "MMX_MOVDQ2Qrr")>; - -def SBWriteResGroup21 : SchedWriteRes<[SBPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup21], (instregex "PUSHFS64")>; - -def SBWriteResGroup21_16i : SchedWriteRes<[SBPort1, SBPort015]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup21_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def SBWriteResGroup22 : SchedWriteRes<[SBPort0,SBPort5]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup22], (instregex "(V?)EXTRACTPSrr")>; - -def SBWriteResGroup23_2 : SchedWriteRes<[SBPort05]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SBWriteResGroup23_2], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SBWriteResGroup25 : SchedWriteRes<[SBPort015]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SBWriteResGroup25], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SBWriteResGroup25_1 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup25_1], (instrs LEAVE, LEAVE64)>; - -def SBWriteResGroup26_2 : SchedWriteRes<[SBPort0,SBPort1,SBPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup26_2], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -def SBWriteResGroup27 : SchedWriteRes<[SBPort0,SBPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup27], (instrs IMUL64r, MUL64r)>; - -def SBWriteResGroup27_1 : SchedWriteRes<[SBPort1,SBPort05,SBPort015]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup27_1], (instrs IMUL32r, MUL32r)>; - -def SBWriteResGroup27_2 : SchedWriteRes<[SBPort1,SBPort05,SBPort015]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup27_2], (instrs IMUL16r, MUL16r)>; - -def SBWriteResGroup29 : SchedWriteRes<[SBPort1,SBPort015]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup29], (instregex "MOV64sr")>; - -def SBWriteResGroup29_2 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup29_2], (instrs PAUSE)>; - -def SBWriteResGroup30 : SchedWriteRes<[SBPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup30], (instregex "(V?)PCMPGTQrr")>; - -def SBWriteResGroup31 : SchedWriteRes<[SBPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup31], (instregex "MOVSX(16|32|64)rm(8|16|32)", - "MOVZX(16|32|64)rm(8|16)")>; - -def SBWriteResGroup33 : SchedWriteRes<[SBPort4,SBPort23]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup33], (instregex "PUSH(16r|32r|64r|64i8)")>; - -def SBWriteResGroup35 : SchedWriteRes<[SBPort1,SBPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup35], (instrs CLI)>; - -def SBWriteResGroup35_2 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup35_2], (instregex "ISTT_FP(16|32|64)m", - "PUSHGS64")>; - -def SBWriteResGroup36 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup36], (instrs CALL64pcrel32)>; -def: InstRW<[SBWriteResGroup36], (instregex "CALL(16|32|64)r", - "(V?)EXTRACTPSmr")>; - -def SBWriteResGroup40 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup40], (instrs STOSB, STOSL, STOSQ, STOSW)>; - -def SBWriteResGroup41 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup41], (instrs FNINIT)>; - -def SBWriteResGroup42 : SchedWriteRes<[SBPort05,SBPort015]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup42], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SBWriteResGroup43 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup43], (instregex "SET(A|BE)m")>; - -def SBWriteResGroup45 : SchedWriteRes<[SBPort0,SBPort4,SBPort23,SBPort15]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup45], (instregex "(V?)PEXTR(D|Q)mr", - "PUSHF(16|64)")>; - -def SBWriteResGroup46 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup46], (instregex "CLFLUSH")>; - -def SBWriteResGroup47 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SBWriteResGroup47], (instregex "FXRSTOR")>; - -def SBWriteResGroup48 : SchedWriteRes<[SBPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup48], (instregex "MMX_MOVD64from64rm", - "POP(16|32|64)r", - "VBROADCASTSSrm", - "(V?)MOV64toPQIrm", - "(V?)MOVDDUPrm", - "(V?)MOVDI2PDIrm", - "(V?)MOVQI2PQIrm", - "(V?)MOVSDrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "(V?)MOVSSrm")>; - -def SBWriteResGroup49 : SchedWriteRes<[SBPort5,SBPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup49], (instregex "MOV16sm")>; - -def SBWriteResGroup50 : SchedWriteRes<[SBPort23,SBPort05]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup50], (instregex "BT(16|32|64)mi8")>; - -def SBWriteResGroup51 : SchedWriteRes<[SBPort23,SBPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup51], (instregex "MMX_PABS(B|D|W)rm", - "MMX_PALIGNRrmi", - "MMX_PSIGN(B|D|W)rm")>; - -def SBWriteResGroup52 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup52], (instrs LODSL, LODSQ)>; - -def SBWriteResGroup53 : SchedWriteRes<[SBPort4,SBPort23]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup53], (instregex "ST_F(32|64)m", - "ST_FP(32|64|80)m")>; - -def SBWriteResGroup54 : SchedWriteRes<[SBPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup54], (instregex "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm")>; - -def SBWriteResGroup58 : SchedWriteRes<[SBPort23,SBPort05]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup58], (instrs VINSERTF128rm)>; - -def SBWriteResGroup59 : SchedWriteRes<[SBPort23,SBPort15]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup59], (instregex "MMX_PADDQirm")>; - -def SBWriteResGroup62 : SchedWriteRes<[SBPort5,SBPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup62], (instregex "VER(R|W)m")>; - -def SBWriteResGroup63 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup63], (instrs LODSB, LODSW)>; - -def SBWriteResGroup64 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup64], (instrs FARJMP64)>; - -def SBWriteResGroup66 : SchedWriteRes<[SBPort0,SBPort4,SBPort23]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup66], (instrs FNSTSWm)>; - -def SBWriteResGroup67 : SchedWriteRes<[SBPort1,SBPort5,SBPort015]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SBWriteResGroup67], (instregex "SLDT(16|32|64)r", - "STR(16|32|64)r")>; - -def SBWriteResGroup68 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup68], (instrs FNSTCW16m)>; -def: InstRW<[SBWriteResGroup68], (instregex "CALL(16|32|64)m")>; - -def SBWriteResGroup69 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SBWriteResGroup69], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SBWriteResGroup77 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup77], (instregex "(V?)(U?)COMI(SD|SS)rm")>; - -def SBWriteResGroup81 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup81], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SBWriteResGroup83 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SBWriteResGroup83], (instrs CMPSB, - CMPSL, - CMPSQ, - CMPSW)>; - -def SBWriteResGroup84 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup84], (instrs FLDCW16m)>; - -def SBWriteResGroup85 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup85], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SBWriteResGroup86 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup86], (instrs MOVSB, MOVSL, MOVSQ, MOVSW)>; -def: InstRW<[SBWriteResGroup86], (instregex "XADD(8|16|32|64)rm")>; - -def SBWriteResGroup87 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SBWriteResGroup87], (instrs FARCALL64)>; - -def SBWriteResGroup93 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93], (instregex "CVT(T?)SD2SI(64)?rm", - "CVT(T?)SS2SI(64)?rm")>; - -def SBWriteResGroup93_1 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93_1], (instrs IMUL64m, MUL64m)>; - -def SBWriteResGroup93_2 : SchedWriteRes<[SBPort1,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup93_2], (instrs IMUL32m, MUL32m)>; - -def SBWriteResGroup93_3 : SchedWriteRes<[SBPort1,SBPort05,SBPort015,SBPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SBWriteResGroup93_3], (instrs IMUL16m, MUL16m)>; - -def SBWriteResGroup93_4 : SchedWriteRes<[SBPort1,SBPort015,SBPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93_4], (instrs IMUL16rmi, IMUL16rmi8)>; - -def SBWriteResGroup95 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup95], (instregex "LD_F(32|64|80)m")>; - -def SBWriteResGroup97 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup97], (instregex "IST_F(16|32)m", - "IST_FP(16|32|64)m")>; - -def SBWriteResGroup97_2 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,3]; -} -def: InstRW<[SBWriteResGroup97_2], (instregex "ROL(8|16|32|64)mCL", - "ROR(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SBWriteResGroup98 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,3]; -} -def: SchedAlias; - -def SBWriteResGroup99 : SchedWriteRes<[SBPort4,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,2,1]; -} -def: InstRW<[SBWriteResGroup99, ReadAfterLd], (instrs ADC8mr, ADC16mr, ADC32mr, ADC64mr, - SBB8mr, SBB16mr, SBB32mr, SBB64mr)>; - -def SBWriteResGroup100 : SchedWriteRes<[SBPort4,SBPort5,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,2,1,1]; -} -def: InstRW<[SBWriteResGroup100], (instregex "BT(16|32|64)mr", - "BTC(16|32|64)mr", - "BTR(16|32|64)mr", - "BTS(16|32|64)mr")>; - -def SBWriteResGroup101 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup101], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m")>; - -def SBWriteResGroup104 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup104], (instregex "(V?)PCMPGTQrm")>; - -def SBWriteResGroup106 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup106], (instregex "FICOM(P?)(16|32)m")>; - -def SBWriteResGroup111 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup111], (instregex "MUL_F(32|64)m")>; - -def SBWriteResGroup114 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup114], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def SBWriteResGroup119 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 15; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup119], (instregex "MUL_FI(16|32)m")>; - -def SBWriteResGroup130 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 31; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup130], (instregex "DIV(R?)_F(32|64)m")>; - -def SBWriteResGroup131 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 34; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup131], (instregex "DIV(R?)_FI(16|32)m")>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86SchedSkylakeClient.td b/suite/synctools/tablegen/X86/X86SchedSkylakeClient.td deleted file mode 100644 index bda088e151..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedSkylakeClient.td +++ /dev/null @@ -1,1850 +0,0 @@ -//=- X86SchedSkylake.td - X86 Skylake Client Scheduling ------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Skylake Client to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SkylakeClientModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SKylake can - // decode 6 instructions per cycle. - let IssueWidth = 6; - let MicroOpBufferSize = 224; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 14; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SkylakeClientModel in { - -// Skylake Client can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def SKLPort0 : ProcResource<1>; -def SKLPort1 : ProcResource<1>; -def SKLPort2 : ProcResource<1>; -def SKLPort3 : ProcResource<1>; -def SKLPort4 : ProcResource<1>; -def SKLPort5 : ProcResource<1>; -def SKLPort6 : ProcResource<1>; -def SKLPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SKLPort01 : ProcResGroup<[SKLPort0, SKLPort1]>; -def SKLPort23 : ProcResGroup<[SKLPort2, SKLPort3]>; -def SKLPort237 : ProcResGroup<[SKLPort2, SKLPort3, SKLPort7]>; -def SKLPort04 : ProcResGroup<[SKLPort0, SKLPort4]>; -def SKLPort05 : ProcResGroup<[SKLPort0, SKLPort5]>; -def SKLPort06 : ProcResGroup<[SKLPort0, SKLPort6]>; -def SKLPort15 : ProcResGroup<[SKLPort1, SKLPort5]>; -def SKLPort16 : ProcResGroup<[SKLPort1, SKLPort6]>; -def SKLPort56 : ProcResGroup<[SKLPort5, SKLPort6]>; -def SKLPort015 : ProcResGroup<[SKLPort0, SKLPort1, SKLPort5]>; -def SKLPort056 : ProcResGroup<[SKLPort0, SKLPort5, SKLPort6]>; -def SKLPort0156: ProcResGroup<[SKLPort0, SKLPort1, SKLPort5, SKLPort6]>; - -def SKLDivider : ProcResource<1>; // Integer division issued on port 0. -// FP division and sqrt on port 0. -def SKLFPDivider : ProcResource<1>; - -// 60 Entry Unified Scheduler -def SKLPortAny : ProcResGroup<[SKLPort0, SKLPort1, SKLPort2, SKLPort3, SKLPort4, - SKLPort5, SKLPort6, SKLPort7]> { - let BufferSize=60; -} - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SKLWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : SKLWriteResPair; // Simple integer ALU op. -defm : SKLWriteResPair; // Integer ALU + flags op. -defm : SKLWriteResPair; // Integer multiplication. -defm : SKLWriteResPair; // Integer 64-bit multiplication. - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -defm : SKLWriteResPair; - -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. -def : WriteRes; // LEA instructions can't fold loads. - -defm : SKLWriteResPair; // Conditional move. -defm : SKLWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // - -// Bit counts. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Integer shifts and rotates. -defm : SKLWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// BMI1 BEXTR, BMI2 BZHI -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : SKLWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; // Floating point add/sub. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double add/sub. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point compare. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double compare. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point compare to flags. - -defm : SKLWriteResPair; // Floating point multiplication. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double multiplication. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point division. -//defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -//defm : SKLWriteResPair; // Floating point double division. -//defm : SKLWriteResPair; -//defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point square root. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double square root. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point long double square root. - -defm : SKLWriteResPair; // Floating point reciprocal estimate. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point reciprocal square root estimate. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Fused Multiply Add. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double dot product. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point fabs/fchs. -defm : SKLWriteResPair; // Floating point rounding. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point and/or/xor logicals. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point TEST instructions. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector shuffles. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector shuffles. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Fp vector variable blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; // Vector integer ALU op, no logicals. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer and/or/xor. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer TEST instructions. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer multiply. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PMULLD. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector shuffles. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector shuffles. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector variable blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector MPSAD. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PSADBW. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : SKLWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Vector integer immediate shifts. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Variable vector shifts. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 20; - let NumMicroOps = 11; - let ResourceCycles = [3,6,2]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 11; - let ResourceCycles = [3,6,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : SKLWriteResPair; // Fp 256-bit width vector shuffles. -defm : SKLWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : SKLWriteResPair; // 256-bit width vector shuffles. -defm : SKLWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Remaining instrs. - -def SKLWriteResGroup1 : SchedWriteRes<[SKLPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup1], (instregex "MMX_PADDS(B|W)irr", - "MMX_PADDUS(B|W)irr", - "MMX_PAVG(B|W)irr", - "MMX_PCMPEQ(B|D|W)irr", - "MMX_PCMPGT(B|D|W)irr", - "MMX_P(MAX|MIN)SWirr", - "MMX_P(MAX|MIN)UBirr", - "MMX_PSUBS(B|W)irr", - "MMX_PSUBUS(B|W)irr")>; - -def SKLWriteResGroup3 : SchedWriteRes<[SKLPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup3], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def SKLWriteResGroup4 : SchedWriteRes<[SKLPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def SKLWriteResGroup6 : SchedWriteRes<[SKLPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def SKLWriteResGroup7 : SchedWriteRes<[SKLPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup7], (instrs CDQ, CQO, CLAC, STAC)>; - -def SKLWriteResGroup8 : SchedWriteRes<[SKLPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def SKLWriteResGroup9 : SchedWriteRes<[SKLPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup9], (instregex "(V?)PADD(B|D|Q|W)(Y?)rr", - "VPBLENDD(Y?)rri", - "(V?)PSUB(B|D|Q|W)(Y?)rr")>; - -def SKLWriteResGroup10 : SchedWriteRes<[SKLPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[SKLWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def SKLWriteResGroup11 : SchedWriteRes<[SKLPort4,SKLPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup11], (instregex "FBSTPm", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def SKLWriteResGroup13 : SchedWriteRes<[SKLPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup13], (instregex "MMX_MOVQ2DQrr")>; - -def SKLWriteResGroup14 : SchedWriteRes<[SKLPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup14], (instrs FDECSTP)>; -def: InstRW<[SKLWriteResGroup14], (instregex "MMX_MOVDQ2Qrr")>; - -def SKLWriteResGroup15 : SchedWriteRes<[SKLPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup15], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SKLWriteResGroup17 : SchedWriteRes<[SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup17], (instrs LFENCE, - WAIT, - XGETBV)>; - -def SKLWriteResGroup20 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup20], (instregex "CLFLUSH")>; - -def SKLWriteResGroup21 : SchedWriteRes<[SKLPort237,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup21], (instrs SFENCE)>; - -def SKLWriteResGroup23 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup23], (instrs CWD)>; -def: InstRW<[SKLWriteResGroup23], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SKLWriteResGroup23], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri")>; - -def SKLWriteResGroup25 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup25], (instrs FNSTCW16m)>; - -def SKLWriteResGroup27 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup27], (instregex "MOVBE(16|32|64)mr")>; - -def SKLWriteResGroup28 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup28], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[SKLWriteResGroup28], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def SKLWriteResGroup29 : SchedWriteRes<[SKLPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup29], (instregex "PDEP(32|64)rr", - "PEXT(32|64)rr")>; - -def SKLWriteResGroup29_16i : SchedWriteRes<[SKLPort1, SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup29_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def SKLWriteResGroup30 : SchedWriteRes<[SKLPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup30], (instregex "(ADD|SUB|SUBR)_(FPrST0|FST0r|FrST0)", - "VPBROADCASTBrr", - "VPBROADCASTWrr", - "(V?)PCMPGTQ(Y?)rr")>; - -def SKLWriteResGroup32 : SchedWriteRes<[SKLPort0,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup32], (instrs FNSTSW16r)>; - -def SKLWriteResGroup33 : SchedWriteRes<[SKLPort06]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKLWriteResGroup33], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SKLWriteResGroup34 : SchedWriteRes<[SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKLWriteResGroup34], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SKLWriteResGroup35 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup35], (instregex "MMX_PH(ADD|SUB)SWrr")>; - -def SKLWriteResGroup36 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup36], (instregex "(V?)PHADDSW(Y?)rr", - "(V?)PHSUBSW(Y?)rr")>; - -def SKLWriteResGroup39 : SchedWriteRes<[SKLPort5,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup39], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def SKLWriteResGroup40 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup40], (instregex "CLD")>; - -def SKLWriteResGroup41 : SchedWriteRes<[SKLPort237,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup41], (instrs MFENCE)>; - -def SKLWriteResGroup42 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup42], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def SKLWriteResGroup43 : SchedWriteRes<[SKLPort0,SKLPort4,SKLPort237]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup43], (instrs FNSTSWm)>; - -def SKLWriteResGroup44 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort06]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup44], (instregex "SET(A|BE)m")>; - -def SKLWriteResGroup45 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort237,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup45], (instregex "CALL(16|32|64)r")>; - -def SKLWriteResGroup46 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup46], (instrs CALL64pcrel32)>; - -def SKLWriteResGroup47 : SchedWriteRes<[SKLPort0]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup47], (instregex "MUL_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup48 : SchedWriteRes<[SKLPort01]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup48], (instregex "(V?)CVTDQ2PS(Y?)rr", - "(V?)CVT(T?)PS2DQ(Y?)rr")>; - -def SKLWriteResGroup51 : SchedWriteRes<[SKLPort1,SKLPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup51], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def SKLWriteResGroup51_16 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup51_16], (instrs IMUL16r, MUL16r)>; - -def SKLWriteResGroup53 : SchedWriteRes<[SKLPort4,SKLPort5,SKLPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup53], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def SKLWriteResGroup54 : SchedWriteRes<[SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[SKLWriteResGroup54], (instrs FNCLEX)>; - -def SKLWriteResGroup55 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKLWriteResGroup55], (instrs PAUSE)>; - -def SKLWriteResGroup56 : SchedWriteRes<[SKLPort015,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKLWriteResGroup56], (instrs VZEROUPPER)>; - -def SKLWriteResGroup57 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup57], (instregex "LAR(16|32|64)rr")>; - -def SKLWriteResGroup58 : SchedWriteRes<[SKLPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup58], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; // TODO: Should this be SKLWriteResGroup67? - -def SKLWriteResGroup59 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup59], (instregex "MMX_CVTPI2PDirr", - "(V?)CVTDQ2PDrr")>; - -def SKLWriteResGroup60 : SchedWriteRes<[SKLPort5,SKLPort015]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup60], (instregex "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVT(T?)PD2DQrr", - "(V?)CVTPD2PSrr", - "(V?)CVTPS2PDrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI642SDrr", - "(V?)CVTSI2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVTSS2SDrr")>; - -def SKLWriteResGroup61 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup61], (instregex "STR(16|32|64)r")>; - -def SKLWriteResGroup62 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup62], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def SKLWriteResGroup63 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[SKLWriteResGroup63], (instrs XSETBV)>; - -def SKLWriteResGroup64 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SKLWriteResGroup64], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SKLWriteResGroup65 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[SKLWriteResGroup65], (instregex "PUSHF(16|64)")>; - -def SKLWriteResGroup67 : SchedWriteRes<[SKLPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup67], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def SKLWriteResGroup68 : SchedWriteRes<[SKLPort0]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup68], (instregex "MMX_CVTPI2PSirr")>; - -def SKLWriteResGroup69 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup69], (instregex "MMX_PADDSBirm", - "MMX_PADDSWirm", - "MMX_PADDUSBirm", - "MMX_PADDUSWirm", - "MMX_PAVGBirm", - "MMX_PAVGWirm", - "MMX_PCMPEQBirm", - "MMX_PCMPEQDirm", - "MMX_PCMPEQWirm", - "MMX_PCMPGTBirm", - "MMX_PCMPGTDirm", - "MMX_PCMPGTWirm", - "MMX_PMAXSWirm", - "MMX_PMAXUBirm", - "MMX_PMINSWirm", - "MMX_PMINUBirm", - "MMX_PSUBSBirm", - "MMX_PSUBSWirm", - "MMX_PSUBUSBirm", - "MMX_PSUBUSWirm")>; - -def SKLWriteResGroup70 : SchedWriteRes<[SKLPort0,SKLPort01]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup70], (instregex "(V?)CVTSS2SI(64)?rr", - "(V?)CVT(T?)SD2SI(64)?rr")>; - -def SKLWriteResGroup72 : SchedWriteRes<[SKLPort6,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup72], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def SKLWriteResGroup74 : SchedWriteRes<[SKLPort23,SKLPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup74], (instregex "BT(16|32|64)mi8")>; - -def SKLWriteResGroup75 : SchedWriteRes<[SKLPort23,SKLPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup75], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def SKLWriteResGroup76 : SchedWriteRes<[SKLPort23,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup76], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[SKLWriteResGroup76], (instregex "POP(16|32|64)rmr")>; - -def SKLWriteResGroup78 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup78], (instregex "(V?)CVTSI642SSrr")>; - -def SKLWriteResGroup80 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup80], (instregex "SLDT(16|32|64)r")>; - -def SKLWriteResGroup82 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup82], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SKLWriteResGroup83 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup83], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def SKLWriteResGroup84 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[SKLWriteResGroup84], (instrs STD)>; - -def SKLWriteResGroup85 : SchedWriteRes<[SKLPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup85], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def SKLWriteResGroup86 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup86], (instregex "VCVTDQ2PDYrr")>; - -def SKLWriteResGroup88 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup88], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def SKLWriteResGroup89 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup89], (instregex "VCVTPD2PSYrr", - "VCVTPS2PDYrr", - "VCVT(T?)PD2DQYrr")>; - -def SKLWriteResGroup91 : SchedWriteRes<[SKLPort23,SKLPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup91], (instregex "(V?)INSERTF128rm", - "(V?)INSERTI128rm", - "(V?)PADD(B|D|Q|W)rm", - "(V?)PBLENDDrmi", - "(V?)PSUB(B|D|Q|W)rm")>; - -def SKLWriteResGroup92 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup92], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def SKLWriteResGroup94 : SchedWriteRes<[SKLPort23,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup94], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def SKLWriteResGroup95 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort01]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup95], (instregex "(V?)CVTTSS2SI(64)?rr")>; - -def SKLWriteResGroup96 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort05]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup96], (instrs FLDCW16m)>; - -def SKLWriteResGroup98 : SchedWriteRes<[SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup98], (instrs LRETQ, RETQ)>; - -def SKLWriteResGroup100 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup100], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SKLWriteResGroup101 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup101], (instregex "XADD(8|16|32|64)rm")>; - -def SKLWriteResGroup102 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup102], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def SKLWriteResGroup103 : SchedWriteRes<[SKLPort6,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,3,1,2]; -} -def: InstRW<[SKLWriteResGroup103], (instrs LOOP)>; - -def SKLWriteResGroup107 : SchedWriteRes<[SKLPort1,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup107], (instregex "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def SKLWriteResGroup107_16 : SchedWriteRes<[SKLPort1, SKLPort0156, SKLPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup107_16], (instrs IMUL16rmi, IMUL16rmi8)>; - -def SKLWriteResGroup107_16_2 : SchedWriteRes<[SKLPort1, SKLPort06, SKLPort0156, SKLPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SKLWriteResGroup107_16_2], (instrs IMUL16m, MUL16m)>; - -def SKLWriteResGroup108 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup108], (instregex "FCOM(P?)(32|64)m", - "VPBROADCASTBYrm", - "VPBROADCASTWYrm", - "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def SKLWriteResGroup110 : SchedWriteRes<[SKLPort23,SKLPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup110], (instregex "VPADD(B|D|Q|W)Yrm", - "VPBLENDDYrmi", - "VPSUB(B|D|Q|W)Yrm")>; - -def SKLWriteResGroup112 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKLWriteResGroup112], (instregex "MMX_PH(ADD|SUB)SWrm")>; - -def SKLWriteResGroup115 : SchedWriteRes<[SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[SKLWriteResGroup115], (instregex "ROR(8|16|32|64)mCL")>; - -def SKLWriteResGroup116 : SchedWriteRes<[SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup116], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def SKLWriteResGroup117 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[SKLWriteResGroup117], (instregex "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SKLWriteResGroup119 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: SchedAlias; -def: InstRW<[SKLWriteResGroup119], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SKLWriteResGroup120 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup120], (instregex "MMX_CVTPI2PSirm")>; - -def SKLWriteResGroup121 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup121], (instregex "(V?)PCMPGTQrm", - "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVZXWDYrm")>; - -def SKLWriteResGroup123 : SchedWriteRes<[SKLPort23,SKLPort01]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup123], (instregex "MMX_CVT(T?)PS2PIirm", - "(V?)CVTPS2PDrm")>; - -def SKLWriteResGroup127 : SchedWriteRes<[SKLPort1,SKLPort5,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup127], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def SKLWriteResGroup128 : SchedWriteRes<[SKLPort5,SKLPort01,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKLWriteResGroup128], (instregex "(V?)PHADDSWrm", - "(V?)PHSUBSWrm")>; - -def SKLWriteResGroup131 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup131], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def SKLWriteResGroup133 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup133], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VPCMPGTQYrm")>; - -def SKLWriteResGroup134 : SchedWriteRes<[SKLPort01,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup134], (instregex "(V?)CVTDQ2PSrm", - "(V?)CVTPS2DQrm", - "(V?)CVTSS2SDrm", - "(V?)CVTTPS2DQrm")>; - -def SKLWriteResGroup138 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup138], (instregex "MMX_CVTPI2PDirm")>; - -def SKLWriteResGroup139 : SchedWriteRes<[SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup139], (instregex "(V?)CVTSD2SSrm")>; - -def SKLWriteResGroup140 : SchedWriteRes<[SKLPort5,SKLPort01,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKLWriteResGroup140], (instregex "VPHADDSWYrm", - "VPHSUBSWYrm")>; - -def SKLWriteResGroup142 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort06,SKLPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup142], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def SKLWriteResGroup143 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 10; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,3]; -} -def: InstRW<[SKLWriteResGroup143], (instregex "XCHG(8|16|32|64)rm")>; - -def SKLWriteResGroup145 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup146 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup146], (instregex "MUL_F(32|64)m")>; - -def SKLWriteResGroup147 : SchedWriteRes<[SKLPort01,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup147], (instregex "VCVTDQ2PSYrm", - "VCVTPS2PDYrm", - "VCVT(T?)PS2DQYrm")>; - -def SKLWriteResGroup149 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup149], (instregex "FICOM(P?)(16|32)m")>; - -def SKLWriteResGroup150 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup150], (instregex "(V?)CVTDQ2PDrm")>; - -def SKLWriteResGroup151 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort01]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup151], (instregex "(V?)CVTSS2SI64rm", - "(V?)CVT(T?)SD2SI(64)?rm", - "VCVTTSS2SI64rm", - "(V?)CVT(T?)SS2SIrm")>; - -def SKLWriteResGroup152 : SchedWriteRes<[SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup152], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm")>; - -def SKLWriteResGroup154 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,3,2]; -} -def: InstRW<[SKLWriteResGroup154], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def SKLWriteResGroup155 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,5,1,2]; -} -def: InstRW<[SKLWriteResGroup155], (instregex "RCL8rCL")>; - -def SKLWriteResGroup156 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[SKLWriteResGroup156], (instrs LOOPE, LOOPNE)>; - -def SKLWriteResGroup160 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 12; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup160], (instregex "CVTTSS2SI64rm")>; - -def SKLWriteResGroup162 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup162], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def SKLWriteResGroup163 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup163], (instregex "VCVTDQ2PDYrm")>; - -def SKLWriteResGroup166 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup166_1 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup169 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup169], (instregex "MUL_FI(16|32)m")>; - -def SKLWriteResGroup170 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,4,1,3]; -} -def: InstRW<[SKLWriteResGroup170], (instregex "RCR8rCL")>; - -def SKLWriteResGroup171 : SchedWriteRes<[SKLPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup171], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup174 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,5,1,1]; -} -def: InstRW<[SKLWriteResGroup174], (instregex "RCL(8|16|32|64)mCL")>; - -def SKLWriteResGroup177 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[SKLWriteResGroup177], (instrs CMPXCHG8B)>; - -def SKLWriteResGroup178 : SchedWriteRes<[SKLPort0156]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[SKLWriteResGroup178], (instrs VZEROALL)>; - -def SKLWriteResGroup179 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 17; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup180 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort05,SKLPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[SKLWriteResGroup180], (instrs XCH_F)>; - -def SKLWriteResGroup184 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[SKLWriteResGroup184], (instrs CPUID, RDTSC)>; - -def SKLWriteResGroup185 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,4,1,2]; -} -def: InstRW<[SKLWriteResGroup185], (instregex "RCR(8|16|32|64)mCL")>; - -def SKLWriteResGroup186 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup189 : SchedWriteRes<[SKLPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup189], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup190 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 20; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup192 : SchedWriteRes<[SKLPort4,SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup192], (instrs INSB, INSL, INSW)>; - -def SKLWriteResGroup193 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[SKLWriteResGroup193], (instrs MWAITrr)>; - -def SKLWriteResGroup195 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup196 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup196], (instregex "DIV_F(32|64)m")>; - -def SKLWriteResGroup196_1 : SchedWriteRes<[SKLPort0, SKLPort23, SKLPort5, SKLPort015]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup196_1], (instrs VGATHERDPSrm, - VGATHERDPDrm, - VGATHERQPDrm, - VGATHERQPSrm, - VPGATHERDDrm, - VPGATHERDQrm, - VPGATHERQDrm, - VPGATHERQQrm)>; - -def SKLWriteResGroup196_2 : SchedWriteRes<[SKLPort0, SKLPort23, SKLPort5, SKLPort015]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup196_2], (instrs VGATHERDPSYrm, - VGATHERQPDYrm, - VGATHERQPSYrm, - VPGATHERDDYrm, - VPGATHERDQYrm, - VPGATHERQDYrm, - VPGATHERQQYrm, - VGATHERDPDYrm)>; - -def SKLWriteResGroup198 : SchedWriteRes<[SKLPort0,SKLPort4,SKLPort5,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[SKLWriteResGroup198], (instrs CMPXCHG16B)>; - -def SKLWriteResGroup202 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 25; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup202], (instregex "DIV_FI(16|32)m")>; - -def SKLWriteResGroup206 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup206], (instregex "DIVR_F(32|64)m")>; - -def SKLWriteResGroup207 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23,SKLPort0156]> { - let Latency = 28; - let NumMicroOps = 8; - let ResourceCycles = [2,4,1,1]; -} -def: InstRW<[SKLWriteResGroup207], (instregex "IDIV(8|16|32|64)m")>; - -def SKLWriteResGroup208 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup208], (instregex "DIVR_FI(16|32)m")>; - -def SKLWriteResGroup209 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort23,SKLPort06,SKLPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[SKLWriteResGroup209], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def SKLWriteResGroup210 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[SKLWriteResGroup210], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def SKLWriteResGroup211 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 37; - let NumMicroOps = 31; - let ResourceCycles = [1,8,1,21]; -} -def: InstRW<[SKLWriteResGroup211], (instregex "XRSTOR(64)?")>; - -def SKLWriteResGroup212 : SchedWriteRes<[SKLPort1,SKLPort4,SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort15,SKLPort0156]> { - let Latency = 40; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[SKLWriteResGroup212], (instrs VMCLEARm)>; - -def SKLWriteResGroup213 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 41; - let NumMicroOps = 39; - let ResourceCycles = [1,10,1,1,26]; -} -def: InstRW<[SKLWriteResGroup213], (instrs XSAVE64)>; - -def SKLWriteResGroup214 : SchedWriteRes<[SKLPort5,SKLPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[SKLWriteResGroup214], (instrs RDTSCP)>; - -def SKLWriteResGroup215 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 42; - let NumMicroOps = 40; - let ResourceCycles = [1,11,1,1,26]; -} -def: InstRW<[SKLWriteResGroup215], (instrs XSAVE)>; -def: InstRW<[SKLWriteResGroup215], (instregex "XSAVEC", "XSAVES")>; - -def SKLWriteResGroup216 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 46; - let NumMicroOps = 44; - let ResourceCycles = [1,11,1,1,30]; -} -def: InstRW<[SKLWriteResGroup216], (instregex "XSAVEOPT")>; - -def SKLWriteResGroup217 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort05,SKLPort06,SKLPort0156]> { - let Latency = 62; - let NumMicroOps = 64; - let ResourceCycles = [2,8,5,10,39]; -} -def: InstRW<[SKLWriteResGroup217], (instrs FLDENVm)>; - -def SKLWriteResGroup218 : SchedWriteRes<[SKLPort0,SKLPort6,SKLPort23,SKLPort05,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[SKLWriteResGroup218], (instrs FXRSTOR64)>; - -def SKLWriteResGroup219 : SchedWriteRes<[SKLPort0,SKLPort6,SKLPort23,SKLPort05,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[SKLWriteResGroup219], (instrs FXRSTOR)>; - -def SKLWriteResGroup220 : SchedWriteRes<[SKLPort5,SKLPort05,SKLPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[SKLWriteResGroup220], (instrs FNINIT)>; - -def SKLWriteResGroup221 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort05,SKLPort0156]> { - let Latency = 76; - let NumMicroOps = 32; - let ResourceCycles = [7,2,8,3,1,11]; -} -def: InstRW<[SKLWriteResGroup221], (instregex "DIV(16|32|64)r")>; - -def SKLWriteResGroup222 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 102; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[SKLWriteResGroup222], (instregex "IDIV(16|32|64)r")>; - -def SKLWriteResGroup223 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort4,SKLPort5,SKLPort6,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 106; - let NumMicroOps = 100; - let ResourceCycles = [9,1,11,16,1,11,21,30]; -} -def: InstRW<[SKLWriteResGroup223], (instrs FSTENVm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86SchedSkylakeServer.td b/suite/synctools/tablegen/X86/X86SchedSkylakeServer.td deleted file mode 100644 index 9d5f8555c5..0000000000 --- a/suite/synctools/tablegen/X86/X86SchedSkylakeServer.td +++ /dev/null @@ -1,2580 +0,0 @@ -//=- X86SchedSkylake.td - X86 Skylake Server Scheduling ------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Skylake Server to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SkylakeServerModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SKylake can - // decode 6 instructions per cycle. - let IssueWidth = 6; - let MicroOpBufferSize = 224; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 14; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SkylakeServerModel in { - -// Skylake Server can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def SKXPort0 : ProcResource<1>; -def SKXPort1 : ProcResource<1>; -def SKXPort2 : ProcResource<1>; -def SKXPort3 : ProcResource<1>; -def SKXPort4 : ProcResource<1>; -def SKXPort5 : ProcResource<1>; -def SKXPort6 : ProcResource<1>; -def SKXPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SKXPort01 : ProcResGroup<[SKXPort0, SKXPort1]>; -def SKXPort23 : ProcResGroup<[SKXPort2, SKXPort3]>; -def SKXPort237 : ProcResGroup<[SKXPort2, SKXPort3, SKXPort7]>; -def SKXPort04 : ProcResGroup<[SKXPort0, SKXPort4]>; -def SKXPort05 : ProcResGroup<[SKXPort0, SKXPort5]>; -def SKXPort06 : ProcResGroup<[SKXPort0, SKXPort6]>; -def SKXPort15 : ProcResGroup<[SKXPort1, SKXPort5]>; -def SKXPort16 : ProcResGroup<[SKXPort1, SKXPort6]>; -def SKXPort56 : ProcResGroup<[SKXPort5, SKXPort6]>; -def SKXPort015 : ProcResGroup<[SKXPort0, SKXPort1, SKXPort5]>; -def SKXPort056 : ProcResGroup<[SKXPort0, SKXPort5, SKXPort6]>; -def SKXPort0156: ProcResGroup<[SKXPort0, SKXPort1, SKXPort5, SKXPort6]>; - -def SKXDivider : ProcResource<1>; // Integer division issued on port 0. -// FP division and sqrt on port 0. -def SKXFPDivider : ProcResource<1>; - -// 60 Entry Unified Scheduler -def SKXPortAny : ProcResGroup<[SKXPort0, SKXPort1, SKXPort2, SKXPort3, SKXPort4, - SKXPort5, SKXPort6, SKXPort7]> { - let BufferSize=60; -} - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SKXWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : SKXWriteResPair; // Simple integer ALU op. -defm : SKXWriteResPair; // Integer ALU + flags op. -defm : SKXWriteResPair; // Integer multiplication. -defm : SKXWriteResPair; // Integer 64-bit multiplication. - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; - -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. -def : WriteRes; // LEA instructions can't fold loads. - -defm : SKXWriteResPair; // Conditional move. -defm : SKXWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // - -// Integer shifts and rotates. -defm : SKXWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Bit counts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : SKXWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; // Floating point add/sub. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double add/sub. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point compare. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double compare. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point compare to flags. - -defm : SKXWriteResPair; // Floating point multiplication. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double multiplication. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // 10-14 cycles. // Floating point division. -//defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. -//defm : SKXWriteResPair; // 10-14 cycles. // Floating point division. -//defm : SKXWriteResPair; // 10-14 cycles. -//defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. - -defm : SKXWriteResPair; // Floating point square root. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double square root. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point long double square root. - -defm : SKXWriteResPair; // Floating point reciprocal estimate. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point reciprocal square root estimate. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Fused Multiply Add. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double dot product. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point fabs/fchs. -defm : SKXWriteResPair; // Floating point rounding. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point and/or/xor logicals. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point TEST instructions. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector variable shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Fp vector variable blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; // Vector integer ALU op, no logicals. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer and/or/xor. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer TEST instructions. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer multiply. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PMULLD. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector variable shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector variable blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector MPSAD. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PSADBW. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : SKXWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer immediate shifts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Variable vector shifts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : SKXWriteResPair; // Needs more work: DD vs DQ. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Needs more work: DD vs DQ. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 20; - let NumMicroOps = 11; - let ResourceCycles = [3,6,2]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 11; - let ResourceCycles = [3,6,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : SKXWriteResPair; // Fp 256-bit width vector shuffles. -defm : SKXWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : SKXWriteResPair; // 256-bit width vector shuffles. -defm : SKXWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Remaining instrs. - -def SKXWriteResGroup1 : SchedWriteRes<[SKXPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup1], (instregex "KAND(B|D|Q|W)rr", - "KANDN(B|D|Q|W)rr", - "KMOV(B|D|Q|W)kk", - "KNOT(B|D|Q|W)rr", - "KOR(B|D|Q|W)rr", - "KXNOR(B|D|Q|W)rr", - "KXOR(B|D|Q|W)rr", - "MMX_PADDS(B|W)irr", - "MMX_PADDUS(B|W)irr", - "MMX_PAVG(B|W)irr", - "MMX_PCMPEQ(B|D|W)irr", - "MMX_PCMPGT(B|D|W)irr", - "MMX_P(MAX|MIN)SWirr", - "MMX_P(MAX|MIN)UBirr", - "MMX_PSUBS(B|W)irr", - "MMX_PSUBUS(B|W)irr", - "VPMOVB2M(Z|Z128|Z256)rr", - "VPMOVD2M(Z|Z128|Z256)rr", - "VPMOVQ2M(Z|Z128|Z256)rr", - "VPMOVW2M(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup3 : SchedWriteRes<[SKXPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup3], (instregex "COM(P?)_FST0r", - "KMOV(B|D|Q|W)kr", - "UCOM_F(P?)r")>; - -def SKXWriteResGroup4 : SchedWriteRes<[SKXPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def SKXWriteResGroup6 : SchedWriteRes<[SKXPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def SKXWriteResGroup7 : SchedWriteRes<[SKXPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup7], (instrs CDQ, CQO, CLAC, STAC)>; - -def SKXWriteResGroup8 : SchedWriteRes<[SKXPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def SKXWriteResGroup9 : SchedWriteRes<[SKXPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup9], (instregex "VBLENDMPD(Z128|Z256)rr", - "VBLENDMPS(Z128|Z256)rr", - "VPADD(B|D|Q|W)(Y|Z|Z128|Z256)rr", - "(V?)PADD(B|D|Q|W)rr", - "VPBLENDD(Y?)rri", - "VPBLENDMB(Z128|Z256)rr", - "VPBLENDMD(Z128|Z256)rr", - "VPBLENDMQ(Z128|Z256)rr", - "VPBLENDMW(Z128|Z256)rr", - "VPSUB(B|D|Q|W)(Y|Z|Z128|Z256)rr", - "(V?)PSUB(B|D|Q|W)rr", - "VPTERNLOGD(Z|Z128|Z256)rri", - "VPTERNLOGQ(Z|Z128|Z256)rri")>; - -def SKXWriteResGroup10 : SchedWriteRes<[SKXPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[SKXWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def SKXWriteResGroup11 : SchedWriteRes<[SKXPort4,SKXPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup11], (instregex "FBSTPm", - "KMOV(B|D|Q|W)mk", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def SKXWriteResGroup13 : SchedWriteRes<[SKXPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup13], (instregex "MMX_MOVQ2DQrr")>; - -def SKXWriteResGroup14 : SchedWriteRes<[SKXPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup14], (instrs FDECSTP)>; -def: InstRW<[SKXWriteResGroup14], (instregex "MMX_MOVDQ2Qrr")>; - -def SKXWriteResGroup15 : SchedWriteRes<[SKXPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup15], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SKXWriteResGroup17 : SchedWriteRes<[SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup17], (instrs LFENCE, - WAIT, - XGETBV)>; - -def SKXWriteResGroup20 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup20], (instregex "CLFLUSH")>; - -def SKXWriteResGroup21 : SchedWriteRes<[SKXPort237,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup21], (instrs SFENCE)>; - -def SKXWriteResGroup23 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup23], (instrs CWD)>; -def: InstRW<[SKXWriteResGroup23], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SKXWriteResGroup23], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri")>; - -def SKXWriteResGroup25 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup25], (instrs FNSTCW16m)>; - -def SKXWriteResGroup27 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup27], (instregex "MOVBE(16|32|64)mr")>; - -def SKXWriteResGroup28 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup28], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[SKXWriteResGroup28], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def SKXWriteResGroup29 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort15]> { - let Latency = 2; - let NumMicroOps = 5; - let ResourceCycles = [2,2,1]; -} -def: InstRW<[SKXWriteResGroup29], (instregex "VMOVDQU8Zmr(b?)")>; - -def SKXWriteResGroup30 : SchedWriteRes<[SKXPort0]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup30], (instregex "KMOV(B|D|Q|W)rk", - "KORTEST(B|D|Q|W)rr", - "KTEST(B|D|Q|W)rr")>; - -def SKXWriteResGroup31 : SchedWriteRes<[SKXPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup31], (instregex "PDEP(32|64)rr", - "PEXT(32|64)rr")>; - -def SKXWriteResGroup31_16i : SchedWriteRes<[SKXPort1, SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup31_16i], (instrs IMUL16rri, IMUL16rri8)>; - - -def SKXWriteResGroup32 : SchedWriteRes<[SKXPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup32], (instregex "(ADD|SUB|SUBR)_(FPrST0|FST0r|FrST0)", - "KADD(B|D|Q|W)rr", - "KSHIFTL(B|D|Q|W)ri", - "KSHIFTR(B|D|Q|W)ri", - "KUNPCKBWrr", - "KUNPCKDQrr", - "KUNPCKWDrr", - "VALIGND(Z|Z128|Z256)rri", - "VALIGNQ(Z|Z128|Z256)rri", - "VCMPPD(Z|Z128|Z256)rri", - "VCMPPS(Z|Z128|Z256)rri", - "VCMPSDZrr", - "VCMPSSZrr", - "VDBPSADBWZrri", // TODO: 512-bit ops require ports 0/1 to be joined. - "VFPCLASSPD(Z|Z128|Z256)rr", - "VFPCLASSPS(Z|Z128|Z256)rr", - "VFPCLASSSDZrr", - "VFPCLASSSSZrr", - "VPBROADCASTBrr", - "VPBROADCASTWrr", - "VPCMPB(Z|Z128|Z256)rri", - "VPCMPD(Z|Z128|Z256)rri", - "VPCMPEQ(B|D|Q|W)(Z|Z128|Z256)rr", - "VPCMPGT(B|D|Q|W)(Z|Z128|Z256)rr", - "(V?)PCMPGTQ(Y?)rr", - "VPCMPQ(Z|Z128|Z256)rri", - "VPCMPU(B|D|Q|W)(Z|Z128|Z256)rri", - "VPCMPW(Z|Z128|Z256)rri", - "VP(MAX|MIN)(S|U)Q(Z|Z128|Z256)rr", - "VPSADBWZrr", // TODO: 512-bit ops require ports 0/1 to be joined. - "VPTEST(N?)M(B|D|Q|W)(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup34 : SchedWriteRes<[SKXPort0,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup34], (instrs FNSTSW16r)>; - -def SKXWriteResGroup35 : SchedWriteRes<[SKXPort06]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup35], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SKXWriteResGroup36 : SchedWriteRes<[SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup36], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SKXWriteResGroup37 : SchedWriteRes<[SKXPort0,SKXPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup37], (instregex "MMX_PH(ADD|SUB)SWrr")>; - -def SKXWriteResGroup38 : SchedWriteRes<[SKXPort5,SKXPort01]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup38], (instregex "(V?)PH(ADD|SUB)SW(Y?)rr")>; - -def SKXWriteResGroup41 : SchedWriteRes<[SKXPort5,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup41], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def SKXWriteResGroup42 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup42], (instregex "CLD")>; - -def SKXWriteResGroup43 : SchedWriteRes<[SKXPort237,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup43], (instrs MFENCE)>; - -def SKXWriteResGroup44 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup44], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def SKXWriteResGroup45 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup45], (instrs FNSTSWm)>; - -def SKXWriteResGroup46 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort06]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup46], (instregex "SET(A|BE)m")>; - -def SKXWriteResGroup47 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort237,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup47], (instregex "CALL(16|32|64)r")>; - -def SKXWriteResGroup48 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup48], (instrs CALL64pcrel32)>; - -def SKXWriteResGroup49 : SchedWriteRes<[SKXPort0]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup49], (instregex "MUL_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup50 : SchedWriteRes<[SKXPort01]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup50], (instregex "VCVTDQ2PS(Y|Z128|Z256)rr", - "(V?)CVTDQ2PSrr", - "VCVTPD2QQ(Z128|Z256)rr", - "VCVTPD2UQQ(Z128|Z256)rr", - "VCVTPS2DQ(Y|Z128|Z256)rr", - "(V?)CVTPS2DQrr", - "VCVTPS2UDQ(Z128|Z256)rr", - "VCVTQQ2PD(Z128|Z256)rr", - "VCVTTPD2QQ(Z128|Z256)rr", - "VCVTTPD2UQQ(Z128|Z256)rr", - "VCVTTPS2DQ(Z128|Z256)rr", - "(V?)CVTTPS2DQrr", - "VCVTTPS2UDQ(Z128|Z256)rr", - "VCVTUDQ2PS(Z128|Z256)rr", - "VCVTUQQ2PD(Z128|Z256)rr")>; - -def SKXWriteResGroup50z : SchedWriteRes<[SKXPort05]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup50z], (instrs VCVTDQ2PSZrr, - VCVTPD2QQZrr, - VCVTPD2UQQZrr, - VCVTPS2DQZrr, - VCVTPS2UDQZrr, - VCVTQQ2PDZrr, - VCVTTPD2QQZrr, - VCVTTPD2UQQZrr, - VCVTTPS2DQZrr, - VCVTTPS2UDQZrr, - VCVTUDQ2PSZrr, - VCVTUQQ2PDZrr)>; - -def SKXWriteResGroup51 : SchedWriteRes<[SKXPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup51], (instregex "VEXPANDPD(Z|Z128|Z256)rr", - "VEXPANDPS(Z|Z128|Z256)rr", - "VPEXPANDD(Z|Z128|Z256)rr", - "VPEXPANDQ(Z|Z128|Z256)rr", - "VPMOVDB(Z|Z128|Z256)rr", - "VPMOVDW(Z|Z128|Z256)rr", - "VPMOVQB(Z|Z128|Z256)rr", - "VPMOVQW(Z|Z128|Z256)rr", - "VPMOVSDB(Z|Z128|Z256)rr", - "VPMOVSDW(Z|Z128|Z256)rr", - "VPMOVSQB(Z|Z128|Z256)rr", - "VPMOVSQD(Z|Z128|Z256)rr", - "VPMOVSQW(Z|Z128|Z256)rr", - "VPMOVSWB(Z|Z128|Z256)rr", - "VPMOVUSDB(Z|Z128|Z256)rr", - "VPMOVUSDW(Z|Z128|Z256)rr", - "VPMOVUSQB(Z|Z128|Z256)rr", - "VPMOVUSQD(Z|Z128|Z256)rr", - "VPMOVUSWB(Z|Z128|Z256)rr", - "VPMOVWB(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup52 : SchedWriteRes<[SKXPort1,SKXPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup52], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def SKXWriteResGroup52_16 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup52_16], (instrs IMUL16r, MUL16r)>; - -def SKXWriteResGroup54 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup54], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m", - "VPMOVQD(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup55 : SchedWriteRes<[SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[SKXWriteResGroup55], (instrs FNCLEX)>; - -def SKXWriteResGroup56 : SchedWriteRes<[SKXPort015,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup56], (instrs VZEROUPPER)>; - -def SKXWriteResGroup57 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup57], (instregex "LAR(16|32|64)rr")>; - -def SKXWriteResGroup58 : SchedWriteRes<[SKXPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup58], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; // TODO: Should this be SKXWriteResGroup71? - -def SKXWriteResGroup61 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup61], (instregex "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "VCVTDQ2PDZ128rr", - "VCVTPD2DQZ128rr", - "(V?)CVT(T?)PD2DQrr", - "VCVTPD2PSZ128rr", - "(V?)CVTPD2PSrr", - "VCVTPD2UDQZ128rr", - "VCVTPS2PDZ128rr", - "(V?)CVTPS2PDrr", - "VCVTPS2QQZ128rr", - "VCVTPS2UQQZ128rr", - "VCVTQQ2PSZ128rr", - "(V?)CVTSD2SS(Z?)rr", - "(V?)CVTSI(64)?2SDrr", - "VCVTSI2SSZrr", - "(V?)CVTSI2SSrr", - "VCVTSI(64)?2SDZrr", - "VCVTSS2SDZrr", - "(V?)CVTSS2SDrr", - "VCVTTPD2DQZ128rr", - "VCVTTPD2UDQZ128rr", - "VCVTTPS2QQZ128rr", - "VCVTTPS2UQQZ128rr", - "VCVTUDQ2PDZ128rr", - "VCVTUQQ2PSZ128rr", - "VCVTUSI2SSZrr", - "VCVTUSI(64)?2SDZrr")>; - -def SKXWriteResGroup62 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup62], (instregex "VPCONFLICTQZ128rr")>; - -def SKXWriteResGroup63 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup63], (instregex "STR(16|32|64)r")>; - -def SKXWriteResGroup64 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup64], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def SKXWriteResGroup65 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup65], (instregex "VCVTPS2PHZ128mr(b?)", - "VCVTPS2PHZ256mr(b?)", - "VCVTPS2PHZmr(b?)")>; - -def SKXWriteResGroup66 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup66], (instregex "VPMOVDB(Z|Z128|Z256)mr(b?)", - "VPMOVDW(Z|Z128|Z256)mr(b?)", - "VPMOVQB(Z|Z128|Z256)mr(b?)", - "VPMOVQW(Z|Z128|Z256)mr(b?)", - "VPMOVSDB(Z|Z128|Z256)mr(b?)", - "VPMOVSDW(Z|Z128|Z256)mr(b?)", - "VPMOVSQB(Z|Z128|Z256)mr(b?)", - "VPMOVSQD(Z|Z128|Z256)mr(b?)", - "VPMOVSQW(Z|Z128|Z256)mr(b?)", - "VPMOVSWB(Z|Z128|Z256)mr(b?)", - "VPMOVUSDB(Z|Z128|Z256)mr(b?)", - "VPMOVUSDW(Z|Z128|Z256)mr(b?)", - "VPMOVUSQB(Z|Z128|Z256)mr(b?)", - "VPMOVUSQD(Z|Z128|Z256)mr(b?)", - "VPMOVUSQW(Z|Z128|Z256)mr(b?)", - "VPMOVUSWB(Z|Z128|Z256)mr(b?)", - "VPMOVWB(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup67 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[SKXWriteResGroup67], (instrs XSETBV)>; - -def SKXWriteResGroup68 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SKXWriteResGroup68], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SKXWriteResGroup69 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[SKXWriteResGroup69], (instregex "PUSHF(16|64)")>; - -def SKXWriteResGroup71 : SchedWriteRes<[SKXPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup71], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def SKXWriteResGroup72 : SchedWriteRes<[SKXPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup72], (instregex "MMX_CVTPI2PSirr", - "VCOMPRESSPD(Z|Z128|Z256)rr", - "VCOMPRESSPS(Z|Z128|Z256)rr", - "VPCOMPRESSD(Z|Z128|Z256)rr", - "VPCOMPRESSQ(Z|Z128|Z256)rr", - "VPERMW(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup73 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup73], (instregex "MMX_PADDSBirm", - "MMX_PADDSWirm", - "MMX_PADDUSBirm", - "MMX_PADDUSWirm", - "MMX_PAVGBirm", - "MMX_PAVGWirm", - "MMX_PCMPEQBirm", - "MMX_PCMPEQDirm", - "MMX_PCMPEQWirm", - "MMX_PCMPGTBirm", - "MMX_PCMPGTDirm", - "MMX_PCMPGTWirm", - "MMX_PMAXSWirm", - "MMX_PMAXUBirm", - "MMX_PMINSWirm", - "MMX_PMINUBirm", - "MMX_PSUBSBirm", - "MMX_PSUBSWirm", - "MMX_PSUBUSBirm", - "MMX_PSUBUSWirm")>; - -def SKXWriteResGroup76 : SchedWriteRes<[SKXPort6,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup76], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def SKXWriteResGroup78 : SchedWriteRes<[SKXPort23,SKXPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup78], (instregex "BT(16|32|64)mi8")>; - -def SKXWriteResGroup79 : SchedWriteRes<[SKXPort23,SKXPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup79], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def SKXWriteResGroup80 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup80], (instregex "VMOV(64to|QI2)PQIZrm(b?)", - "VMOVDI2PDIZrm(b?)")>; - -def SKXWriteResGroup81 : SchedWriteRes<[SKXPort23,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup81], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[SKXWriteResGroup81], (instregex "POP(16|32|64)rmr")>; - -def SKXWriteResGroup82 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup82], (instregex "(V?)CVTSI642SSrr", - "VCVTSI642SSZrr", - "VCVTUSI642SSZrr")>; - -def SKXWriteResGroup84 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup84], (instregex "SLDT(16|32|64)r")>; - -def SKXWriteResGroup86 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup86], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SKXWriteResGroup87 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup87], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def SKXWriteResGroup88 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[SKXWriteResGroup88], (instrs STD)>; - -def SKXWriteResGroup89 : SchedWriteRes<[SKXPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup89], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def SKXWriteResGroup90 : SchedWriteRes<[SKXPort01,SKXPort5]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup90], (instregex "VCVTDQ2PDYrr")>; - -def SKXWriteResGroup92 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup92], (instregex "VMOVSDZrm(b?)", - "VMOVSSZrm(b?)")>; - -def SKXWriteResGroup92a : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup92a], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def SKXWriteResGroup93 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup93], (instregex "VCVTDQ2PDZ256rr", - "VCVTPD2DQ(Y|Z256)rr", - "VCVTPD2PS(Y|Z256)rr", - "VCVTPD2UDQZ256rr", - "VCVTPS2PD(Y|Z256)rr", - "VCVTPS2QQZ256rr", - "VCVTPS2UQQZ256rr", - "VCVTQQ2PSZ256rr", - "VCVTTPD2DQ(Y|Z256)rr", - "VCVTTPD2UDQZ256rr", - "VCVTTPS2QQZ256rr", - "VCVTTPS2UQQZ256rr", - "VCVTUDQ2PDZ256rr", - "VCVTUQQ2PSZ256rr")>; - -def SKXWriteResGroup93z : SchedWriteRes<[SKXPort5,SKXPort05]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup93z], (instrs VCVTDQ2PDZrr, - VCVTPD2DQZrr, - VCVTPD2PSZrr, - VCVTPD2UDQZrr, - VCVTPS2PDZrr, - VCVTPS2QQZrr, - VCVTPS2UQQZrr, - VCVTQQ2PSZrr, - VCVTTPD2DQZrr, - VCVTTPD2UDQZrr, - VCVTTPS2QQZrr, - VCVTTPS2UQQZrr, - VCVTUDQ2PDZrr, - VCVTUQQ2PSZrr)>; - -def SKXWriteResGroup95 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup95], (instregex "VBLENDMPDZ128rm(b?)", - "VBLENDMPSZ128rm(b?)", - "VBROADCASTI32X2Z128m(b?)", - "VBROADCASTSSZ128m(b?)", - "VINSERTF128rm", - "VINSERTI128rm", - "VMOVAPDZ128rm(b?)", - "VMOVAPSZ128rm(b?)", - "VMOVDDUPZ128rm(b?)", - "VMOVDQA32Z128rm(b?)", - "VMOVDQA64Z128rm(b?)", - "VMOVDQU16Z128rm(b?)", - "VMOVDQU32Z128rm(b?)", - "VMOVDQU64Z128rm(b?)", - "VMOVDQU8Z128rm(b?)", - "VMOVNTDQAZ128rm(b?)", - "VMOVSHDUPZ128rm(b?)", - "VMOVSLDUPZ128rm(b?)", - "VMOVUPDZ128rm(b?)", - "VMOVUPSZ128rm(b?)", - "VPADD(B|D|Q|W)Z128rm(b?)", - "(V?)PADD(B|D|Q|W)rm", - "VPBLENDDrmi", - "VPBLENDM(B|D|Q|W)Z128rm(b?)", - "VPBROADCASTDZ128m(b?)", - "VPBROADCASTQZ128m(b?)", - "VPSUB(B|D|Q|W)Z128rm(b?)", - "(V?)PSUB(B|D|Q|W)rm", - "VPTERNLOGDZ128rm(b?)i", - "VPTERNLOGQZ128rm(b?)i")>; - -def SKXWriteResGroup96 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup96], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def SKXWriteResGroup97 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup97], (instregex "VPERMI2W128rr", - "VPERMI2W256rr", - "VPERMI2Wrr", - "VPERMT2W128rr", - "VPERMT2W256rr", - "VPERMT2Wrr")>; - -def SKXWriteResGroup99 : SchedWriteRes<[SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup99], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def SKXWriteResGroup100 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup100], (instregex "VCVTSS2USI64Zrr", - "(V?)CVTSS2SI64(Z?)rr", - "(V?)CVTTSS2SI64(Z?)rr", - "VCVTTSS2USI64Zrr")>; - -def SKXWriteResGroup101 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort05]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup101], (instrs FLDCW16m)>; - -def SKXWriteResGroup103 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup103], (instregex "KMOV(B|D|Q|W)km")>; - -def SKXWriteResGroup104 : SchedWriteRes<[SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup104], (instrs LRETQ, RETQ)>; - -def SKXWriteResGroup106 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup106], (instregex "VCOMPRESSPD(Z|Z128|Z256)mr(b?)", - "VCOMPRESSPS(Z|Z128|Z256)mr(b?)", - "VPCOMPRESSD(Z|Z128|Z256)mr(b?)", - "VPCOMPRESSQ(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup107 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup107], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SKXWriteResGroup108 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup108], (instregex "XADD(8|16|32|64)rm")>; - -def SKXWriteResGroup109 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup109], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def SKXWriteResGroup110 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,2,2,2]; -} -def: InstRW<[SKXWriteResGroup110], (instrs VPSCATTERDQZ128mr, - VPSCATTERQQZ128mr, - VSCATTERDPDZ128mr, - VSCATTERQPDZ128mr)>; - -def SKXWriteResGroup111 : SchedWriteRes<[SKXPort6,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,3,1,2]; -} -def: InstRW<[SKXWriteResGroup111], (instrs LOOP)>; - -def SKXWriteResGroup112 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 11; - let ResourceCycles = [1,4,4,2]; -} -def: InstRW<[SKXWriteResGroup112], (instrs VPSCATTERDQZ256mr, - VPSCATTERQQZ256mr, - VSCATTERDPDZ256mr, - VSCATTERQPDZ256mr)>; - -def SKXWriteResGroup113 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 19; - let ResourceCycles = [1,8,8,2]; -} -def: InstRW<[SKXWriteResGroup113], (instrs VPSCATTERDQZmr, - VPSCATTERQQZmr, - VSCATTERDPDZmr, - VSCATTERQPDZmr)>; - -def SKXWriteResGroup114 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 36; - let ResourceCycles = [1,16,1,16,2]; -} -def: InstRW<[SKXWriteResGroup114], (instrs VSCATTERDPSZmr)>; - -def SKXWriteResGroup118 : SchedWriteRes<[SKXPort1,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup118], (instregex "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def SKXWriteResGroup118_16_1 : SchedWriteRes<[SKXPort1, SKXPort0156, SKXPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup118_16_1], (instrs IMUL16rm, IMUL16rmi, IMUL16rmi8)>; - -def SKXWriteResGroup118_16_2 : SchedWriteRes<[SKXPort1, SKXPort06, SKXPort0156, SKXPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SKXWriteResGroup118_16_2], (instrs IMUL16m, MUL16m)>; - -def SKXWriteResGroup119 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup119], (instregex "FCOM(P?)(32|64)m", - "VFPCLASSSDZrm(b?)", - "VPBROADCASTBYrm", - "VPBROADCASTB(Z|Z256)m(b?)", - "VPBROADCASTWYrm", - "VPBROADCASTW(Z|Z256)m(b?)", - "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def SKXWriteResGroup121 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup121], (instregex "VBLENDMPD(Z|Z256)rm(b?)", - "VBLENDMPS(Z|Z256)rm(b?)", - "VBROADCASTF32X2Z256m(b?)", - "VBROADCASTF32X2Zm(b?)", - "VBROADCASTF32X4Z256rm(b?)", - "VBROADCASTF32X4rm(b?)", - "VBROADCASTF32X8rm(b?)", - "VBROADCASTF64X2Z128rm(b?)", - "VBROADCASTF64X2rm(b?)", - "VBROADCASTF64X4rm(b?)", - "VBROADCASTI32X2Z256m(b?)", - "VBROADCASTI32X2Zm(b?)", - "VBROADCASTI32X4Z256rm(b?)", - "VBROADCASTI32X4rm(b?)", - "VBROADCASTI32X8rm(b?)", - "VBROADCASTI64X2Z128rm(b?)", - "VBROADCASTI64X2rm(b?)", - "VBROADCASTI64X4rm(b?)", - "VBROADCASTSD(Z|Z256)m(b?)", - "VBROADCASTSS(Z|Z256)m(b?)", - "VINSERTF32x4(Z|Z256)rm(b?)", - "VINSERTF32x8Zrm(b?)", - "VINSERTF64x2(Z|Z256)rm(b?)", - "VINSERTF64x4Zrm(b?)", - "VINSERTI32x4(Z|Z256)rm(b?)", - "VINSERTI32x8Zrm(b?)", - "VINSERTI64x2(Z|Z256)rm(b?)", - "VINSERTI64x4Zrm(b?)", - "VMOVAPD(Z|Z256)rm(b?)", - "VMOVAPS(Z|Z256)rm(b?)", - "VMOVDDUP(Z|Z256)rm(b?)", - "VMOVDQA32(Z|Z256)rm(b?)", - "VMOVDQA64(Z|Z256)rm(b?)", - "VMOVDQU16(Z|Z256)rm(b?)", - "VMOVDQU32(Z|Z256)rm(b?)", - "VMOVDQU64(Z|Z256)rm(b?)", - "VMOVDQU8(Z|Z256)rm(b?)", - "VMOVNTDQAZ256rm(b?)", - "VMOVSHDUP(Z|Z256)rm(b?)", - "VMOVSLDUP(Z|Z256)rm(b?)", - "VMOVUPD(Z|Z256)rm(b?)", - "VMOVUPS(Z|Z256)rm(b?)", - "VPADD(B|D|Q|W)Yrm", - "VPADD(B|D|Q|W)(Z|Z256)rm(b?)", - "VPBLENDDYrmi", - "VPBLENDM(B|D|Q|W)(Z|Z256)rm(b?)", - "VPBROADCASTD(Z|Z256)m(b?)", - "VPBROADCASTQ(Z|Z256)m(b?)", - "VPSUB(B|D|Q|W)Yrm", - "VPSUB(B|D|Q|W)(Z|Z256)rm(b?)", - "VPTERNLOGD(Z|Z256)rm(b?)i", - "VPTERNLOGQ(Z|Z256)rm(b?)i")>; - -def SKXWriteResGroup123 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup123], (instregex "MMX_PH(ADD|SUB)SWrm")>; - -def SKXWriteResGroup126 : SchedWriteRes<[SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[SKXWriteResGroup126], (instregex "ROR(8|16|32|64)mCL")>; - -def SKXWriteResGroup127 : SchedWriteRes<[SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup127], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def SKXWriteResGroup128 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[SKXWriteResGroup128], (instregex "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SKXWriteResGroup130 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: SchedAlias; -def: InstRW<[SKXWriteResGroup130], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SKXWriteResGroup131 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 8; - let ResourceCycles = [1,2,1,2,2]; -} -def: InstRW<[SKXWriteResGroup131], (instrs VPSCATTERQDZ128mr, - VPSCATTERQDZ256mr, - VSCATTERQPSZ128mr, - VSCATTERQPSZ256mr)>; - -def SKXWriteResGroup132 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 12; - let ResourceCycles = [1,4,1,4,2]; -} -def: InstRW<[SKXWriteResGroup132], (instrs VPSCATTERDDZ128mr, - VSCATTERDPSZ128mr)>; - -def SKXWriteResGroup133 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 20; - let ResourceCycles = [1,8,1,8,2]; -} -def: InstRW<[SKXWriteResGroup133], (instrs VPSCATTERDDZ256mr, - VSCATTERDPSZ256mr)>; - -def SKXWriteResGroup134 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 36; - let ResourceCycles = [1,16,1,16,2]; -} -def: InstRW<[SKXWriteResGroup134], (instrs VPSCATTERDDZmr)>; - -def SKXWriteResGroup135 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup135], (instregex "MMX_CVTPI2PSirm")>; - -def SKXWriteResGroup136 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup136], (instregex "VALIGNDZ128rm(b?)i", - "VALIGNQZ128rm(b?)i", - "VCMPPDZ128rm(b?)i", - "VCMPPSZ128rm(b?)i", - "VCMPSDZrm", - "VCMPSSZrm", - "VFPCLASSSSZrm(b?)", - "VPCMPBZ128rmi(b?)", - "VPCMPDZ128rmi(b?)", - "VPCMPEQ(B|D|Q|W)Z128rm(b?)", - "VPCMPGT(B|D|Q|W)Z128rm(b?)", - "(V?)PCMPGTQrm", - "VPCMPQZ128rmi(b?)", - "VPCMPU(B|D|Q|W)Z128rmi(b?)", - "VPCMPWZ128rmi(b?)", - "VPERMI2D128rm(b?)", - "VPERMI2PD128rm(b?)", - "VPERMI2PS128rm(b?)", - "VPERMI2Q128rm(b?)", - "VPERMT2D128rm(b?)", - "VPERMT2PD128rm(b?)", - "VPERMT2PS128rm(b?)", - "VPERMT2Q128rm(b?)", - "VPMAXSQZ128rm(b?)", - "VPMAXUQZ128rm(b?)", - "VPMINSQZ128rm(b?)", - "VPMINUQZ128rm(b?)", - "VPMOVSXBDZ128rm(b?)", - "VPMOVSXBQZ128rm(b?)", - "VPMOVSXBWYrm", - "VPMOVSXBWZ128rm(b?)", - "VPMOVSXDQYrm", - "VPMOVSXDQZ128rm(b?)", - "VPMOVSXWDYrm", - "VPMOVSXWDZ128rm(b?)", - "VPMOVSXWQZ128rm(b?)", - "VPMOVZXBDZ128rm(b?)", - "VPMOVZXBQZ128rm(b?)", - "VPMOVZXBWZ128rm(b?)", - "VPMOVZXDQZ128rm(b?)", - "VPMOVZXWDYrm", - "VPMOVZXWDZ128rm(b?)", - "VPMOVZXWQZ128rm(b?)", - "VPTESTMBZ128rm(b?)", - "VPTESTMDZ128rm(b?)", - "VPTESTMQZ128rm(b?)", - "VPTESTMWZ128rm(b?)", - "VPTESTNMBZ128rm(b?)", - "VPTESTNMDZ128rm(b?)", - "VPTESTNMQZ128rm(b?)", - "VPTESTNMWZ128rm(b?)")>; - -def SKXWriteResGroup137 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup137], (instregex "MMX_CVT(T?)PS2PIirm", - "(V?)CVTPS2PDrm")>; - -def SKXWriteResGroup142 : SchedWriteRes<[SKXPort1,SKXPort5,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup142], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def SKXWriteResGroup143 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup143], (instregex "(V?)PHADDSWrm", - "(V?)PHSUBSWrm")>; - -def SKXWriteResGroup146 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup146], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def SKXWriteResGroup148 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup148], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VALIGND(Z|Z256)rm(b?)i", - "VALIGNQ(Z|Z256)rm(b?)i", - "VCMPPD(Z|Z256)rm(b?)i", - "VCMPPS(Z|Z256)rm(b?)i", - "VPCMPB(Z|Z256)rmi(b?)", - "VPCMPD(Z|Z256)rmi(b?)", - "VPCMPEQB(Z|Z256)rm(b?)", - "VPCMPEQD(Z|Z256)rm(b?)", - "VPCMPEQQ(Z|Z256)rm(b?)", - "VPCMPEQW(Z|Z256)rm(b?)", - "VPCMPGTB(Z|Z256)rm(b?)", - "VPCMPGTD(Z|Z256)rm(b?)", - "VPCMPGTQYrm", - "VPCMPGTQ(Z|Z256)rm(b?)", - "VPCMPGTW(Z|Z256)rm(b?)", - "VPCMPQ(Z|Z256)rmi(b?)", - "VPCMPU(B|D|Q|W)Z256rmi(b?)", - "VPCMPU(B|D|Q|W)Zrmi(b?)", - "VPCMPW(Z|Z256)rmi(b?)", - "VPMAXSQ(Z|Z256)rm(b?)", - "VPMAXUQ(Z|Z256)rm(b?)", - "VPMINSQ(Z|Z256)rm(b?)", - "VPMINUQ(Z|Z256)rm(b?)", - "VPTESTM(B|D|Q|W)Z256rm(b?)", - "VPTESTM(B|D|Q|W)Zrm(b?)", - "VPTESTNM(B|D|Q|W)Z256rm(b?)", - "VPTESTNM(B|D|Q|W)Zrm(b?)")>; - -def SKXWriteResGroup149 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup149], (instregex "VCVTDQ2PDZ128rm(b?)", - "VCVTDQ2PSZ128rm(b?)", - "(V?)CVTDQ2PSrm", - "VCVTPD2QQZ128rm(b?)", - "VCVTPD2UQQZ128rm(b?)", - "VCVTPH2PSZ128rm(b?)", - "VCVTPS2DQZ128rm(b?)", - "(V?)CVTPS2DQrm", - "VCVTPS2PDZ128rm(b?)", - "VCVTPS2QQZ128rm(b?)", - "VCVTPS2UDQZ128rm(b?)", - "VCVTPS2UQQZ128rm(b?)", - "VCVTQQ2PDZ128rm(b?)", - "VCVTQQ2PSZ128rm(b?)", - "VCVTSS2SDZrm", - "(V?)CVTSS2SDrm", - "VCVTTPD2QQZ128rm(b?)", - "VCVTTPD2UQQZ128rm(b?)", - "VCVTTPS2DQZ128rm(b?)", - "(V?)CVTTPS2DQrm", - "VCVTTPS2QQZ128rm(b?)", - "VCVTTPS2UDQZ128rm(b?)", - "VCVTTPS2UQQZ128rm(b?)", - "VCVTUDQ2PDZ128rm(b?)", - "VCVTUDQ2PSZ128rm(b?)", - "VCVTUQQ2PDZ128rm(b?)", - "VCVTUQQ2PSZ128rm(b?)")>; - -def SKXWriteResGroup151 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup151], (instregex "VEXPANDPDZ128rm(b?)", - "VEXPANDPSZ128rm(b?)", - "VPEXPANDDZ128rm(b?)", - "VPEXPANDQZ128rm(b?)")>; - -def SKXWriteResGroup153 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup153], (instregex "(V?)CVTSD2SSrm")>; - -def SKXWriteResGroup154 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup154], (instregex "VPHADDSWYrm", - "VPHSUBSWYrm")>; - -def SKXWriteResGroup156 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort06,SKXPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup156], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def SKXWriteResGroup157 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 10; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,3]; -} -def: InstRW<[SKXWriteResGroup157], (instregex "XCHG(8|16|32|64)rm")>; - -def SKXWriteResGroup159 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup160 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup160], (instregex "MUL_F(32|64)m")>; - -def SKXWriteResGroup161 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup161], (instregex "VCVTDQ2PD(Z|Z256)rm(b?)", - "VCVTDQ2PSYrm", - "VCVTDQ2PS(Z|Z256)rm(b?)", - "VCVTPH2PS(Z|Z256)rm(b?)", - "VCVTPS2PDYrm", - "VCVTPS2PD(Z|Z256)rm(b?)", - "VCVTQQ2PD(Z|Z256)rm(b?)", - "VCVTQQ2PSZ256rm(b?)", - "VCVT(T?)PD2QQ(Z|Z256)rm(b?)", - "VCVT(T?)PD2UQQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2DQYrm", - "VCVT(T?)PS2DQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2QQZ256rm(b?)", - "VCVT(T?)PS2UDQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2UQQZ256rm(b?)", - "VCVTUDQ2PD(Z|Z256)rm(b?)", - "VCVTUDQ2PS(Z|Z256)rm(b?)", - "VCVTUQQ2PD(Z|Z256)rm(b?)", - "VCVTUQQ2PSZ256rm(b?)")>; - -def SKXWriteResGroup162 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup162], (instregex "FICOM(P?)(16|32)m", - "VEXPANDPD(Z|Z256)rm(b?)", - "VEXPANDPS(Z|Z256)rm(b?)", - "VPEXPANDD(Z|Z256)rm(b?)", - "VPEXPANDQ(Z|Z256)rm(b?)")>; - -def SKXWriteResGroup163 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup163], (instregex "VCVTSD2SSZrm")>; - -def SKXWriteResGroup164 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup164], (instregex "(V?)CVTDQ2PDrm")>; - -def SKXWriteResGroup166 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup166], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm")>; - -def SKXWriteResGroup167 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup167], (instregex "VPCONFLICTQZ128rm(b?)")>; - -def SKXWriteResGroup169 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,3,2]; -} -def: InstRW<[SKXWriteResGroup169], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def SKXWriteResGroup170 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,5,1,2]; -} -def: InstRW<[SKXWriteResGroup170], (instregex "RCL8rCL")>; - -def SKXWriteResGroup171 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[SKXWriteResGroup171], (instrs LOOPE, LOOPNE)>; - -def SKXWriteResGroup174 : SchedWriteRes<[SKXPort01]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup174], (instregex "VPMULLQ(Z128|Z256)rr")>; - -def SKXWriteResGroup174z : SchedWriteRes<[SKXPort05]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup174z], (instregex "VPMULLQZrr")>; - -def SKXWriteResGroup175 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup175], (instregex "VPERMWZ128rm(b?)")>; - -def SKXWriteResGroup176 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup176], (instregex "VCVT(T?)SD2USIZrm(b?)", - "VCVT(T?)SS2USI64Zrm(b?)")>; - -def SKXWriteResGroup177 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup177], (instregex "VCVT(T?)PS2QQZrm(b?)", - "VCVT(T?)PS2UQQZrm(b?)")>; - -def SKXWriteResGroup179 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup179], (instregex "CVTTSS2SI64rm")>; - -def SKXWriteResGroup180 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup180], (instregex "(ADD|SUB|SUBR)_FI(16|32)m", - "VPERMWZ256rm(b?)", - "VPERMWZrm(b?)")>; - -def SKXWriteResGroup181 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup181], (instregex "VCVTDQ2PDYrm")>; - -def SKXWriteResGroup183 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 13; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup183], (instregex "VPERMI2W128rm(b?)", - "VPERMT2W128rm(b?)")>; - -def SKXWriteResGroup184 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup184_1 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup187 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup187], (instregex "MUL_FI(16|32)m")>; - -def SKXWriteResGroup188 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup188], (instregex "VCVTPD2DQZrm(b?)", - "VCVTPD2PSZrm(b?)", - "VCVTPD2UDQZrm(b?)", - "VCVTQQ2PSZrm(b?)", - "VCVTTPD2DQZrm(b?)", - "VCVTTPD2UDQZrm(b?)", - "VCVTUQQ2PSZrm(b?)")>; - -def SKXWriteResGroup189 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 14; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup189], (instregex "VPERMI2W256rm(b?)", - "VPERMI2Wrm(b?)", - "VPERMT2W256rm(b?)", - "VPERMT2Wrm(b?)")>; - -def SKXWriteResGroup190 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,4,1,3]; -} -def: InstRW<[SKXWriteResGroup190], (instregex "RCR8rCL")>; - -def SKXWriteResGroup191 : SchedWriteRes<[SKXPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup191], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup194 : SchedWriteRes<[SKXPort1,SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 15; - let NumMicroOps = 8; - let ResourceCycles = [1,2,2,1,2]; -} -def: InstRW<[SKXWriteResGroup194], (instregex "VPCONFLICTDZ128rm(b?)")>; - -def SKXWriteResGroup195 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,5,1,1]; -} -def: InstRW<[SKXWriteResGroup195], (instregex "RCL(8|16|32|64)mCL")>; - -def SKXWriteResGroup199 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[SKXWriteResGroup199], (instrs CMPXCHG8B)>; - -def SKXWriteResGroup200 : SchedWriteRes<[SKXPort0156]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[SKXWriteResGroup200], (instrs VZEROALL)>; - -def SKXWriteResGroup201 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 17; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup202 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort05,SKXPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[SKXWriteResGroup202], (instrs XCH_F)>; - -def SKXWriteResGroup205 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 18; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup205], (instregex "VPMULLQZ128rm(b?)")>; - -def SKXWriteResGroup207 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[SKXWriteResGroup207], (instrs CPUID, RDTSC)>; - -def SKXWriteResGroup208 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,4,1,2]; -} -def: InstRW<[SKXWriteResGroup208], (instregex "RCR(8|16|32|64)mCL")>; - -def SKXWriteResGroup209 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup211 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 19; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup211], (instregex "VPMULLQZ256rm(b?)", - "VPMULLQZrm(b?)")>; - -def SKXWriteResGroup214 : SchedWriteRes<[]> { - let Latency = 20; - let NumMicroOps = 0; -} -def: InstRW<[SKXWriteResGroup214], (instrs VGATHERDPSZ128rm, - VGATHERQPSZrm, - VPGATHERDDZ128rm)>; - -def SKXWriteResGroup215 : SchedWriteRes<[SKXPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup215], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup216 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 20; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup218 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup218], (instrs VGATHERQPSZ128rm, - VGATHERQPSZ256rm, - VPGATHERQDZ128rm, - VPGATHERQDZ256rm)>; - -def SKXWriteResGroup219 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup219], (instrs INSB, INSL, INSW)>; - -def SKXWriteResGroup220 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[SKXWriteResGroup220], (instrs MWAITrr)>; - -def SKXWriteResGroup222 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup223 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup223], (instregex "DIV_F(32|64)m")>; - -def SKXWriteResGroup224 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224], (instrs VGATHERDPDZ128rm, - VGATHERQPDZ128rm, - VPGATHERDQZ128rm, - VPGATHERQQZ128rm)>; - -def SKXWriteResGroup224_2 : SchedWriteRes<[SKXPort0, SKXPort23, SKXPort5, SKXPort015]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224_2], (instrs VGATHERDPSrm, - VGATHERDPDrm, - VGATHERQPDrm, - VGATHERQPSrm, - VPGATHERDDrm, - VPGATHERDQrm, - VPGATHERQDrm, - VPGATHERQQrm, - VPGATHERDDrm, - VPGATHERQDrm, - VPGATHERDQrm, - VPGATHERQQrm, - VGATHERDPSrm, - VGATHERQPSrm, - VGATHERDPDrm, - VGATHERQPDrm)>; - -def SKXWriteResGroup224_3 : SchedWriteRes<[SKXPort0, SKXPort23, SKXPort5, SKXPort015]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224_3], (instrs VGATHERDPSYrm, - VGATHERQPDYrm, - VGATHERQPSYrm, - VPGATHERDDYrm, - VPGATHERDQYrm, - VPGATHERQDYrm, - VPGATHERQQYrm, - VPGATHERDDYrm, - VPGATHERQDYrm, - VPGATHERDQYrm, - VPGATHERQQYrm, - VGATHERDPSYrm, - VGATHERQPSYrm, - VGATHERDPDYrm)>; - -def SKXWriteResGroup225 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 22; - let NumMicroOps = 14; - let ResourceCycles = [5,5,4]; -} -def: InstRW<[SKXWriteResGroup225], (instregex "VPCONFLICTDZ128rr", - "VPCONFLICTQZ256rr")>; - -def SKXWriteResGroup228 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[SKXWriteResGroup228], (instrs CMPXCHG16B)>; - -def SKXWriteResGroup233 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 25; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup233], (instregex "DIV_FI(16|32)m")>; - -def SKXWriteResGroup234 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup234], (instrs VGATHERDPDZ256rm, - VGATHERQPDZ256rm, - VPGATHERDQZ256rm, - VPGATHERQDZrm, - VPGATHERQQZ256rm)>; - -def SKXWriteResGroup238 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 26; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup238], (instrs VGATHERDPDZrm, - VGATHERQPDZrm, - VPGATHERDQZrm, - VPGATHERQQZrm)>; - -def SKXWriteResGroup239 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup239], (instregex "DIVR_F(32|64)m")>; - -def SKXWriteResGroup240 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 27; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup240], (instrs VGATHERDPSZ256rm, - VPGATHERDDZ256rm)>; - -def SKXWriteResGroup241 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23,SKXPort0156]> { - let Latency = 28; - let NumMicroOps = 8; - let ResourceCycles = [2,4,1,1]; -} -def: InstRW<[SKXWriteResGroup241], (instregex "IDIV(8|16|32|64)m")>; - -def SKXWriteResGroup242 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 29; - let NumMicroOps = 15; - let ResourceCycles = [5,5,1,4]; -} -def: InstRW<[SKXWriteResGroup242], (instregex "VPCONFLICTQZ256rm(b?)")>; - -def SKXWriteResGroup243 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup243], (instregex "DIVR_FI(16|32)m")>; - -def SKXWriteResGroup245 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 30; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup245], (instrs VGATHERDPSZrm, - VPGATHERDDZrm)>; - -def SKXWriteResGroup247 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort23,SKXPort06,SKXPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[SKXWriteResGroup247], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def SKXWriteResGroup248 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[SKXWriteResGroup248], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def SKXWriteResGroup249 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 37; - let NumMicroOps = 21; - let ResourceCycles = [9,7,5]; -} -def: InstRW<[SKXWriteResGroup249], (instregex "VPCONFLICTDZ256rr", - "VPCONFLICTQZrr")>; - -def SKXWriteResGroup250 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 37; - let NumMicroOps = 31; - let ResourceCycles = [1,8,1,21]; -} -def: InstRW<[SKXWriteResGroup250], (instregex "XRSTOR(64)?")>; - -def SKXWriteResGroup252 : SchedWriteRes<[SKXPort1,SKXPort4,SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort15,SKXPort0156]> { - let Latency = 40; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[SKXWriteResGroup252], (instrs VMCLEARm)>; - -def SKXWriteResGroup253 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 41; - let NumMicroOps = 39; - let ResourceCycles = [1,10,1,1,26]; -} -def: InstRW<[SKXWriteResGroup253], (instrs XSAVE64)>; - -def SKXWriteResGroup254 : SchedWriteRes<[SKXPort5,SKXPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[SKXWriteResGroup254], (instrs RDTSCP)>; - -def SKXWriteResGroup255 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 42; - let NumMicroOps = 40; - let ResourceCycles = [1,11,1,1,26]; -} -def: InstRW<[SKXWriteResGroup255], (instrs XSAVE)>; -def: InstRW<[SKXWriteResGroup255], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def SKXWriteResGroup256 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 44; - let NumMicroOps = 22; - let ResourceCycles = [9,7,1,5]; -} -def: InstRW<[SKXWriteResGroup256], (instregex "VPCONFLICTDZ256rm(b?)", - "VPCONFLICTQZrm(b?)")>; - -def SKXWriteResGroup258 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort05,SKXPort06,SKXPort0156]> { - let Latency = 62; - let NumMicroOps = 64; - let ResourceCycles = [2,8,5,10,39]; -} -def: InstRW<[SKXWriteResGroup258], (instrs FLDENVm)>; - -def SKXWriteResGroup259 : SchedWriteRes<[SKXPort0,SKXPort6,SKXPort23,SKXPort05,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[SKXWriteResGroup259], (instrs FXRSTOR64)>; - -def SKXWriteResGroup260 : SchedWriteRes<[SKXPort0,SKXPort6,SKXPort23,SKXPort05,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[SKXWriteResGroup260], (instrs FXRSTOR)>; - -def SKXWriteResGroup261 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 67; - let NumMicroOps = 35; - let ResourceCycles = [17,11,7]; -} -def: InstRW<[SKXWriteResGroup261], (instregex "VPCONFLICTDZrr")>; - -def SKXWriteResGroup262 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 74; - let NumMicroOps = 36; - let ResourceCycles = [17,11,1,7]; -} -def: InstRW<[SKXWriteResGroup262], (instregex "VPCONFLICTDZrm(b?)")>; - -def SKXWriteResGroup263 : SchedWriteRes<[SKXPort5,SKXPort05,SKXPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[SKXWriteResGroup263], (instrs FNINIT)>; - -def SKXWriteResGroup264 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort05,SKXPort0156]> { - let Latency = 76; - let NumMicroOps = 32; - let ResourceCycles = [7,2,8,3,1,11]; -} -def: InstRW<[SKXWriteResGroup264], (instregex "DIV(16|32|64)r")>; - -def SKXWriteResGroup265 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 102; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[SKXWriteResGroup265], (instregex "IDIV(16|32|64)r")>; - -def SKXWriteResGroup266 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort4,SKXPort5,SKXPort6,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 106; - let NumMicroOps = 100; - let ResourceCycles = [9,1,11,16,1,11,21,30]; -} -def: InstRW<[SKXWriteResGroup266], (instrs FSTENVm)>; - -def SKXWriteResGroup267 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 140; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup267], (instrs PAUSE)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86Schedule.td b/suite/synctools/tablegen/X86/X86Schedule.td deleted file mode 100644 index 6215d58ae1..0000000000 --- a/suite/synctools/tablegen/X86/X86Schedule.td +++ /dev/null @@ -1,661 +0,0 @@ -//===-- X86Schedule.td - X86 Scheduling Definitions --------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// InstrSchedModel annotations for out-of-order CPUs. - -// Instructions with folded loads need to read the memory operand immediately, -// but other register operands don't have to be read until the load is ready. -// These operands are marked with ReadAfterLd. -def ReadAfterLd : SchedRead; - -// Instructions with both a load and a store folded are modeled as a folded -// load + WriteRMW. -def WriteRMW : SchedWrite; - -// Helper to set SchedWrite ExePorts/Latency/ResourceCycles/NumMicroOps. -multiclass X86WriteRes ExePorts, - int Lat, list Res, int UOps> { - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } -} - -// Most instructions can fold loads, so almost every SchedWrite comes in two -// variants: With and without a folded load. -// An X86FoldableSchedWrite holds a reference to the corresponding SchedWrite -// with a folded load. -class X86FoldableSchedWrite : SchedWrite { - // The SchedWrite to use when a load is folded into the instruction. - SchedWrite Folded; -} - -// Multiclass that produces a linked pair of SchedWrites. -multiclass X86SchedWritePair { - // Register-Memory operation. - def Ld : SchedWrite; - // Register-Register operation. - def NAME : X86FoldableSchedWrite { - let Folded = !cast(NAME#"Ld"); - } -} - -// Helpers to mark SchedWrites as unsupported. -multiclass X86WriteResUnsupported { - let Unsupported = 1 in { - def : WriteRes; - } -} -multiclass X86WriteResPairUnsupported { - let Unsupported = 1 in { - def : WriteRes; - def : WriteRes; - } -} - -// Multiclass that wraps X86FoldableSchedWrite for each vector width. -class X86SchedWriteWidths { - X86FoldableSchedWrite Scl = sScl; // Scalar float/double operations. - X86FoldableSchedWrite MMX = sScl; // MMX operations. - X86FoldableSchedWrite XMM = s128; // XMM operations. - X86FoldableSchedWrite YMM = s256; // YMM operations. - X86FoldableSchedWrite ZMM = s512; // ZMM operations. -} - -// Multiclass that wraps X86SchedWriteWidths for each fp vector type. -class X86SchedWriteSizes { - X86SchedWriteWidths PS = sPS; - X86SchedWriteWidths PD = sPD; -} - -// Multiclass that wraps move/load/store triple for a vector width. -class X86SchedWriteMoveLS { - SchedWrite RR = MoveRR; - SchedWrite RM = LoadRM; - SchedWrite MR = StoreMR; -} - -// Multiclass that wraps X86SchedWriteMoveLS for each vector width. -class X86SchedWriteMoveLSWidths { - X86SchedWriteMoveLS Scl = sScl; // Scalar float/double operations. - X86SchedWriteMoveLS MMX = sScl; // MMX operations. - X86SchedWriteMoveLS XMM = s128; // XMM operations. - X86SchedWriteMoveLS YMM = s256; // YMM operations. - X86SchedWriteMoveLS ZMM = s512; // ZMM operations. -} - -// Loads, stores, and moves, not folded with other operations. -def WriteLoad : SchedWrite; -def WriteStore : SchedWrite; -def WriteStoreNT : SchedWrite; -def WriteMove : SchedWrite; - -// Arithmetic. -defm WriteALU : X86SchedWritePair; // Simple integer ALU op. -defm WriteADC : X86SchedWritePair; // Integer ALU + flags op. -def WriteALURMW : WriteSequence<[WriteALULd, WriteStore]>; -def WriteADCRMW : WriteSequence<[WriteADCLd, WriteStore]>; -defm WriteIMul : X86SchedWritePair; // Integer multiplication. -defm WriteIMul64 : X86SchedWritePair; // Integer 64-bit multiplication. -def WriteIMulH : SchedWrite; // Integer multiplication, high part. -def WriteLEA : SchedWrite; // LEA instructions can't fold loads. - -def WriteBSWAP32 : SchedWrite; // Byte Order (Endianness) 32-bit Swap. -def WriteBSWAP64 : SchedWrite; // Byte Order (Endianness) 64-bit Swap. - -// Integer division. -defm WriteDiv8 : X86SchedWritePair; -defm WriteDiv16 : X86SchedWritePair; -defm WriteDiv32 : X86SchedWritePair; -defm WriteDiv64 : X86SchedWritePair; -defm WriteIDiv8 : X86SchedWritePair; -defm WriteIDiv16 : X86SchedWritePair; -defm WriteIDiv32 : X86SchedWritePair; -defm WriteIDiv64 : X86SchedWritePair; - -defm WriteBSF : X86SchedWritePair; // Bit scan forward. -defm WriteBSR : X86SchedWritePair; // Bit scan reverse. -defm WritePOPCNT : X86SchedWritePair; // Bit population count. -defm WriteLZCNT : X86SchedWritePair; // Leading zero count. -defm WriteTZCNT : X86SchedWritePair; // Trailing zero count. -defm WriteCMOV : X86SchedWritePair; // Conditional move. -defm WriteCMOV2 : X86SchedWritePair; // Conditional (CF + ZF flag) move. -def WriteFCMOV : SchedWrite; // X87 conditional move. -def WriteSETCC : SchedWrite; // Set register based on condition code. -def WriteSETCCStore : SchedWrite; -def WriteLAHFSAHF : SchedWrite; // Load/Store flags in AH. -def WriteBitTest : SchedWrite; // Bit Test - TODO add memory folding support - -// Integer shifts and rotates. -defm WriteShift : X86SchedWritePair; -// Double shift instructions. -def WriteSHDrri : SchedWrite; -def WriteSHDrrcl : SchedWrite; -def WriteSHDmri : SchedWrite; -def WriteSHDmrcl : SchedWrite; - -// BMI1 BEXTR, BMI2 BZHI -defm WriteBEXTR : X86SchedWritePair; -defm WriteBZHI : X86SchedWritePair; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def WriteZero : SchedWrite; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm WriteJump : X86SchedWritePair; - -// Floating point. This covers both scalar and vector operations. -def WriteFLD0 : SchedWrite; -def WriteFLD1 : SchedWrite; -def WriteFLDC : SchedWrite; -def WriteFLoad : SchedWrite; -def WriteFLoadX : SchedWrite; -def WriteFLoadY : SchedWrite; -def WriteFMaskedLoad : SchedWrite; -def WriteFMaskedLoadY : SchedWrite; -def WriteFStore : SchedWrite; -def WriteFStoreX : SchedWrite; -def WriteFStoreY : SchedWrite; -def WriteFStoreNT : SchedWrite; -def WriteFStoreNTX : SchedWrite; -def WriteFStoreNTY : SchedWrite; -def WriteFMaskedStore : SchedWrite; -def WriteFMaskedStoreY : SchedWrite; -def WriteFMove : SchedWrite; -def WriteFMoveX : SchedWrite; -def WriteFMoveY : SchedWrite; - -defm WriteFAdd : X86SchedWritePair; // Floating point add/sub. -defm WriteFAddX : X86SchedWritePair; // Floating point add/sub (XMM). -defm WriteFAddY : X86SchedWritePair; // Floating point add/sub (YMM). -defm WriteFAddZ : X86SchedWritePair; // Floating point add/sub (ZMM). -defm WriteFAdd64 : X86SchedWritePair; // Floating point double add/sub. -defm WriteFAdd64X : X86SchedWritePair; // Floating point double add/sub (XMM). -defm WriteFAdd64Y : X86SchedWritePair; // Floating point double add/sub (YMM). -defm WriteFAdd64Z : X86SchedWritePair; // Floating point double add/sub (ZMM). -defm WriteFCmp : X86SchedWritePair; // Floating point compare. -defm WriteFCmpX : X86SchedWritePair; // Floating point compare (XMM). -defm WriteFCmpY : X86SchedWritePair; // Floating point compare (YMM). -defm WriteFCmpZ : X86SchedWritePair; // Floating point compare (ZMM). -defm WriteFCmp64 : X86SchedWritePair; // Floating point double compare. -defm WriteFCmp64X : X86SchedWritePair; // Floating point double compare (XMM). -defm WriteFCmp64Y : X86SchedWritePair; // Floating point double compare (YMM). -defm WriteFCmp64Z : X86SchedWritePair; // Floating point double compare (ZMM). -defm WriteFCom : X86SchedWritePair; // Floating point compare to flags. -defm WriteFMul : X86SchedWritePair; // Floating point multiplication. -defm WriteFMulX : X86SchedWritePair; // Floating point multiplication (XMM). -defm WriteFMulY : X86SchedWritePair; // Floating point multiplication (YMM). -defm WriteFMulZ : X86SchedWritePair; // Floating point multiplication (YMM). -defm WriteFMul64 : X86SchedWritePair; // Floating point double multiplication. -defm WriteFMul64X : X86SchedWritePair; // Floating point double multiplication (XMM). -defm WriteFMul64Y : X86SchedWritePair; // Floating point double multiplication (YMM). -defm WriteFMul64Z : X86SchedWritePair; // Floating point double multiplication (ZMM). -defm WriteFDiv : X86SchedWritePair; // Floating point division. -defm WriteFDivX : X86SchedWritePair; // Floating point division (XMM). -defm WriteFDivY : X86SchedWritePair; // Floating point division (YMM). -defm WriteFDivZ : X86SchedWritePair; // Floating point division (ZMM). -defm WriteFDiv64 : X86SchedWritePair; // Floating point double division. -defm WriteFDiv64X : X86SchedWritePair; // Floating point double division (XMM). -defm WriteFDiv64Y : X86SchedWritePair; // Floating point double division (YMM). -defm WriteFDiv64Z : X86SchedWritePair; // Floating point double division (ZMM). -defm WriteFSqrt : X86SchedWritePair; // Floating point square root. -defm WriteFSqrtX : X86SchedWritePair; // Floating point square root (XMM). -defm WriteFSqrtY : X86SchedWritePair; // Floating point square root (YMM). -defm WriteFSqrtZ : X86SchedWritePair; // Floating point square root (ZMM). -defm WriteFSqrt64 : X86SchedWritePair; // Floating point double square root. -defm WriteFSqrt64X : X86SchedWritePair; // Floating point double square root (XMM). -defm WriteFSqrt64Y : X86SchedWritePair; // Floating point double square root (YMM). -defm WriteFSqrt64Z : X86SchedWritePair; // Floating point double square root (ZMM). -defm WriteFSqrt80 : X86SchedWritePair; // Floating point long double square root. -defm WriteFRcp : X86SchedWritePair; // Floating point reciprocal estimate. -defm WriteFRcpX : X86SchedWritePair; // Floating point reciprocal estimate (XMM). -defm WriteFRcpY : X86SchedWritePair; // Floating point reciprocal estimate (YMM). -defm WriteFRcpZ : X86SchedWritePair; // Floating point reciprocal estimate (ZMM). -defm WriteFRsqrt : X86SchedWritePair; // Floating point reciprocal square root estimate. -defm WriteFRsqrtX: X86SchedWritePair; // Floating point reciprocal square root estimate (XMM). -defm WriteFRsqrtY: X86SchedWritePair; // Floating point reciprocal square root estimate (YMM). -defm WriteFRsqrtZ: X86SchedWritePair; // Floating point reciprocal square root estimate (ZMM). -defm WriteFMA : X86SchedWritePair; // Fused Multiply Add. -defm WriteFMAX : X86SchedWritePair; // Fused Multiply Add (XMM). -defm WriteFMAY : X86SchedWritePair; // Fused Multiply Add (YMM). -defm WriteFMAZ : X86SchedWritePair; // Fused Multiply Add (ZMM). -defm WriteDPPD : X86SchedWritePair; // Floating point double dot product. -defm WriteDPPS : X86SchedWritePair; // Floating point single dot product. -defm WriteDPPSY : X86SchedWritePair; // Floating point single dot product (YMM). -defm WriteDPPSZ : X86SchedWritePair; // Floating point single dot product (ZMM). -defm WriteFSign : X86SchedWritePair; // Floating point fabs/fchs. -defm WriteFRnd : X86SchedWritePair; // Floating point rounding. -defm WriteFRndY : X86SchedWritePair; // Floating point rounding (YMM). -defm WriteFRndZ : X86SchedWritePair; // Floating point rounding (ZMM). -defm WriteFLogic : X86SchedWritePair; // Floating point and/or/xor logicals. -defm WriteFLogicY : X86SchedWritePair; // Floating point and/or/xor logicals (YMM). -defm WriteFLogicZ : X86SchedWritePair; // Floating point and/or/xor logicals (ZMM). -defm WriteFTest : X86SchedWritePair; // Floating point TEST instructions. -defm WriteFTestY : X86SchedWritePair; // Floating point TEST instructions (YMM). -defm WriteFTestZ : X86SchedWritePair; // Floating point TEST instructions (ZMM). -defm WriteFShuffle : X86SchedWritePair; // Floating point vector shuffles. -defm WriteFShuffleY : X86SchedWritePair; // Floating point vector shuffles (YMM). -defm WriteFShuffleZ : X86SchedWritePair; // Floating point vector shuffles (ZMM). -defm WriteFVarShuffle : X86SchedWritePair; // Floating point vector variable shuffles. -defm WriteFVarShuffleY : X86SchedWritePair; // Floating point vector variable shuffles (YMM). -defm WriteFVarShuffleZ : X86SchedWritePair; // Floating point vector variable shuffles (ZMM). -defm WriteFBlend : X86SchedWritePair; // Floating point vector blends. -defm WriteFBlendY : X86SchedWritePair; // Floating point vector blends (YMM). -defm WriteFBlendZ : X86SchedWritePair; // Floating point vector blends (ZMM). -defm WriteFVarBlend : X86SchedWritePair; // Fp vector variable blends. -defm WriteFVarBlendY : X86SchedWritePair; // Fp vector variable blends (YMM). -defm WriteFVarBlendZ : X86SchedWritePair; // Fp vector variable blends (YMZMM). - -// FMA Scheduling helper class. -class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Horizontal Add/Sub (float and integer) -defm WriteFHAdd : X86SchedWritePair; -defm WriteFHAddY : X86SchedWritePair; -defm WriteFHAddZ : X86SchedWritePair; -defm WritePHAdd : X86SchedWritePair; -defm WritePHAddX : X86SchedWritePair; -defm WritePHAddY : X86SchedWritePair; -defm WritePHAddZ : X86SchedWritePair; - -// Vector integer operations. -def WriteVecLoad : SchedWrite; -def WriteVecLoadX : SchedWrite; -def WriteVecLoadY : SchedWrite; -def WriteVecLoadNT : SchedWrite; -def WriteVecLoadNTY : SchedWrite; -def WriteVecMaskedLoad : SchedWrite; -def WriteVecMaskedLoadY : SchedWrite; -def WriteVecStore : SchedWrite; -def WriteVecStoreX : SchedWrite; -def WriteVecStoreY : SchedWrite; -def WriteVecStoreNT : SchedWrite; -def WriteVecStoreNTY : SchedWrite; -def WriteVecMaskedStore : SchedWrite; -def WriteVecMaskedStoreY : SchedWrite; -def WriteVecMove : SchedWrite; -def WriteVecMoveX : SchedWrite; -def WriteVecMoveY : SchedWrite; -def WriteVecMoveToGpr : SchedWrite; -def WriteVecMoveFromGpr : SchedWrite; - -defm WriteVecALU : X86SchedWritePair; // Vector integer ALU op, no logicals. -defm WriteVecALUX : X86SchedWritePair; // Vector integer ALU op, no logicals (XMM). -defm WriteVecALUY : X86SchedWritePair; // Vector integer ALU op, no logicals (YMM). -defm WriteVecALUZ : X86SchedWritePair; // Vector integer ALU op, no logicals (ZMM). -defm WriteVecLogic : X86SchedWritePair; // Vector integer and/or/xor logicals. -defm WriteVecLogicX : X86SchedWritePair; // Vector integer and/or/xor logicals (XMM). -defm WriteVecLogicY : X86SchedWritePair; // Vector integer and/or/xor logicals (YMM). -defm WriteVecLogicZ : X86SchedWritePair; // Vector integer and/or/xor logicals (ZMM). -defm WriteVecTest : X86SchedWritePair; // Vector integer TEST instructions. -defm WriteVecTestY : X86SchedWritePair; // Vector integer TEST instructions (YMM). -defm WriteVecTestZ : X86SchedWritePair; // Vector integer TEST instructions (ZMM). -defm WriteVecShift : X86SchedWritePair; // Vector integer shifts (default). -defm WriteVecShiftX : X86SchedWritePair; // Vector integer shifts (XMM). -defm WriteVecShiftY : X86SchedWritePair; // Vector integer shifts (YMM). -defm WriteVecShiftZ : X86SchedWritePair; // Vector integer shifts (ZMM). -defm WriteVecShiftImm : X86SchedWritePair; // Vector integer immediate shifts (default). -defm WriteVecShiftImmX: X86SchedWritePair; // Vector integer immediate shifts (XMM). -defm WriteVecShiftImmY: X86SchedWritePair; // Vector integer immediate shifts (YMM). -defm WriteVecShiftImmZ: X86SchedWritePair; // Vector integer immediate shifts (ZMM). -defm WriteVecIMul : X86SchedWritePair; // Vector integer multiply (default). -defm WriteVecIMulX : X86SchedWritePair; // Vector integer multiply (XMM). -defm WriteVecIMulY : X86SchedWritePair; // Vector integer multiply (YMM). -defm WriteVecIMulZ : X86SchedWritePair; // Vector integer multiply (ZMM). -defm WritePMULLD : X86SchedWritePair; // Vector PMULLD. -defm WritePMULLDY : X86SchedWritePair; // Vector PMULLD (YMM). -defm WritePMULLDZ : X86SchedWritePair; // Vector PMULLD (ZMM). -defm WriteShuffle : X86SchedWritePair; // Vector shuffles. -defm WriteShuffleX : X86SchedWritePair; // Vector shuffles (XMM). -defm WriteShuffleY : X86SchedWritePair; // Vector shuffles (YMM). -defm WriteShuffleZ : X86SchedWritePair; // Vector shuffles (ZMM). -defm WriteVarShuffle : X86SchedWritePair; // Vector variable shuffles. -defm WriteVarShuffleX : X86SchedWritePair; // Vector variable shuffles (XMM). -defm WriteVarShuffleY : X86SchedWritePair; // Vector variable shuffles (YMM). -defm WriteVarShuffleZ : X86SchedWritePair; // Vector variable shuffles (ZMM). -defm WriteBlend : X86SchedWritePair; // Vector blends. -defm WriteBlendY : X86SchedWritePair; // Vector blends (YMM). -defm WriteBlendZ : X86SchedWritePair; // Vector blends (ZMM). -defm WriteVarBlend : X86SchedWritePair; // Vector variable blends. -defm WriteVarBlendY : X86SchedWritePair; // Vector variable blends (YMM). -defm WriteVarBlendZ : X86SchedWritePair; // Vector variable blends (ZMM). -defm WritePSADBW : X86SchedWritePair; // Vector PSADBW. -defm WritePSADBWX : X86SchedWritePair; // Vector PSADBW (XMM). -defm WritePSADBWY : X86SchedWritePair; // Vector PSADBW (YMM). -defm WritePSADBWZ : X86SchedWritePair; // Vector PSADBW (ZMM). -defm WriteMPSAD : X86SchedWritePair; // Vector MPSAD. -defm WriteMPSADY : X86SchedWritePair; // Vector MPSAD (YMM). -defm WriteMPSADZ : X86SchedWritePair; // Vector MPSAD (ZMM). -defm WritePHMINPOS : X86SchedWritePair; // Vector PHMINPOS. - -// Vector insert/extract operations. -defm WriteVecInsert : X86SchedWritePair; // Insert gpr to vector element. -def WriteVecExtract : SchedWrite; // Extract vector element to gpr. -def WriteVecExtractSt : SchedWrite; // Extract vector element and store. - -// MOVMSK operations. -def WriteFMOVMSK : SchedWrite; -def WriteVecMOVMSK : SchedWrite; -def WriteVecMOVMSKY : SchedWrite; -def WriteMMXMOVMSK : SchedWrite; - -// Conversion between integer and float. -defm WriteCvtSD2I : X86SchedWritePair; // Double -> Integer. -defm WriteCvtPD2I : X86SchedWritePair; // Double -> Integer (XMM). -defm WriteCvtPD2IY : X86SchedWritePair; // Double -> Integer (YMM). -defm WriteCvtPD2IZ : X86SchedWritePair; // Double -> Integer (ZMM). - -defm WriteCvtSS2I : X86SchedWritePair; // Float -> Integer. -defm WriteCvtPS2I : X86SchedWritePair; // Float -> Integer (XMM). -defm WriteCvtPS2IY : X86SchedWritePair; // Float -> Integer (YMM). -defm WriteCvtPS2IZ : X86SchedWritePair; // Float -> Integer (ZMM). - -defm WriteCvtI2SD : X86SchedWritePair; // Integer -> Double. -defm WriteCvtI2PD : X86SchedWritePair; // Integer -> Double (XMM). -defm WriteCvtI2PDY : X86SchedWritePair; // Integer -> Double (YMM). -defm WriteCvtI2PDZ : X86SchedWritePair; // Integer -> Double (ZMM). - -defm WriteCvtI2SS : X86SchedWritePair; // Integer -> Float. -defm WriteCvtI2PS : X86SchedWritePair; // Integer -> Float (XMM). -defm WriteCvtI2PSY : X86SchedWritePair; // Integer -> Float (YMM). -defm WriteCvtI2PSZ : X86SchedWritePair; // Integer -> Float (ZMM). - -defm WriteCvtSS2SD : X86SchedWritePair; // Float -> Double size conversion. -defm WriteCvtPS2PD : X86SchedWritePair; // Float -> Double size conversion (XMM). -defm WriteCvtPS2PDY : X86SchedWritePair; // Float -> Double size conversion (YMM). -defm WriteCvtPS2PDZ : X86SchedWritePair; // Float -> Double size conversion (ZMM). - -defm WriteCvtSD2SS : X86SchedWritePair; // Double -> Float size conversion. -defm WriteCvtPD2PS : X86SchedWritePair; // Double -> Float size conversion (XMM). -defm WriteCvtPD2PSY : X86SchedWritePair; // Double -> Float size conversion (YMM). -defm WriteCvtPD2PSZ : X86SchedWritePair; // Double -> Float size conversion (ZMM). - -defm WriteCvtPH2PS : X86SchedWritePair; // Half -> Float size conversion. -defm WriteCvtPH2PSY : X86SchedWritePair; // Half -> Float size conversion (YMM). -defm WriteCvtPH2PSZ : X86SchedWritePair; // Half -> Float size conversion (ZMM). - -def WriteCvtPS2PH : SchedWrite; // // Float -> Half size conversion. -def WriteCvtPS2PHY : SchedWrite; // // Float -> Half size conversion (YMM). -def WriteCvtPS2PHZ : SchedWrite; // // Float -> Half size conversion (ZMM). -def WriteCvtPS2PHSt : SchedWrite; // // Float -> Half + store size conversion. -def WriteCvtPS2PHYSt : SchedWrite; // // Float -> Half + store size conversion (YMM). -def WriteCvtPS2PHZSt : SchedWrite; // // Float -> Half + store size conversion (ZMM). - -// CRC32 instruction. -defm WriteCRC32 : X86SchedWritePair; - -// Strings instructions. -// Packed Compare Implicit Length Strings, Return Mask -defm WritePCmpIStrM : X86SchedWritePair; -// Packed Compare Explicit Length Strings, Return Mask -defm WritePCmpEStrM : X86SchedWritePair; -// Packed Compare Implicit Length Strings, Return Index -defm WritePCmpIStrI : X86SchedWritePair; -// Packed Compare Explicit Length Strings, Return Index -defm WritePCmpEStrI : X86SchedWritePair; - -// AES instructions. -defm WriteAESDecEnc : X86SchedWritePair; // Decryption, encryption. -defm WriteAESIMC : X86SchedWritePair; // InvMixColumn. -defm WriteAESKeyGen : X86SchedWritePair; // Key Generation. - -// Carry-less multiplication instructions. -defm WriteCLMul : X86SchedWritePair; - -// EMMS/FEMMS -def WriteEMMS : SchedWrite; - -// Load/store MXCSR -def WriteLDMXCSR : SchedWrite; -def WriteSTMXCSR : SchedWrite; - -// Catch-all for expensive system instructions. -def WriteSystem : SchedWrite; - -// AVX2. -defm WriteFShuffle256 : X86SchedWritePair; // Fp 256-bit width vector shuffles. -defm WriteFVarShuffle256 : X86SchedWritePair; // Fp 256-bit width variable shuffles. -defm WriteShuffle256 : X86SchedWritePair; // 256-bit width vector shuffles. -defm WriteVarShuffle256 : X86SchedWritePair; // 256-bit width vector variable shuffles. -defm WriteVarVecShift : X86SchedWritePair; // Variable vector shifts. -defm WriteVarVecShiftY : X86SchedWritePair; // Variable vector shifts (YMM). -defm WriteVarVecShiftZ : X86SchedWritePair; // Variable vector shifts (ZMM). - -// Old microcoded instructions that nobody use. -def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def WriteFence : SchedWrite; - -// Nop, not very useful expect it provides a model for nops! -def WriteNop : SchedWrite; - -// Move/Load/Store wrappers. -def WriteFMoveLS - : X86SchedWriteMoveLS; -def WriteFMoveLSX - : X86SchedWriteMoveLS; -def WriteFMoveLSY - : X86SchedWriteMoveLS; -def SchedWriteFMoveLS - : X86SchedWriteMoveLSWidths; - -def WriteFMoveLSNT - : X86SchedWriteMoveLS; -def WriteFMoveLSNTX - : X86SchedWriteMoveLS; -def WriteFMoveLSNTY - : X86SchedWriteMoveLS; -def SchedWriteFMoveLSNT - : X86SchedWriteMoveLSWidths; - -def WriteVecMoveLS - : X86SchedWriteMoveLS; -def WriteVecMoveLSX - : X86SchedWriteMoveLS; -def WriteVecMoveLSY - : X86SchedWriteMoveLS; -def SchedWriteVecMoveLS - : X86SchedWriteMoveLSWidths; - -def WriteVecMoveLSNT - : X86SchedWriteMoveLS; -def WriteVecMoveLSNTX - : X86SchedWriteMoveLS; -def WriteVecMoveLSNTY - : X86SchedWriteMoveLS; -def SchedWriteVecMoveLSNT - : X86SchedWriteMoveLSWidths; - -// Vector width wrappers. -def SchedWriteFAdd - : X86SchedWriteWidths; -def SchedWriteFAdd64 - : X86SchedWriteWidths; -def SchedWriteFHAdd - : X86SchedWriteWidths; -def SchedWriteFCmp - : X86SchedWriteWidths; -def SchedWriteFCmp64 - : X86SchedWriteWidths; -def SchedWriteFMul - : X86SchedWriteWidths; -def SchedWriteFMul64 - : X86SchedWriteWidths; -def SchedWriteFMA - : X86SchedWriteWidths; -def SchedWriteDPPD - : X86SchedWriteWidths; -def SchedWriteDPPS - : X86SchedWriteWidths; -def SchedWriteFDiv - : X86SchedWriteWidths; -def SchedWriteFDiv64 - : X86SchedWriteWidths; -def SchedWriteFSqrt - : X86SchedWriteWidths; -def SchedWriteFSqrt64 - : X86SchedWriteWidths; -def SchedWriteFRcp - : X86SchedWriteWidths; -def SchedWriteFRsqrt - : X86SchedWriteWidths; -def SchedWriteFRnd - : X86SchedWriteWidths; -def SchedWriteFLogic - : X86SchedWriteWidths; -def SchedWriteFTest - : X86SchedWriteWidths; - -def SchedWriteFShuffle - : X86SchedWriteWidths; -def SchedWriteFVarShuffle - : X86SchedWriteWidths; -def SchedWriteFBlend - : X86SchedWriteWidths; -def SchedWriteFVarBlend - : X86SchedWriteWidths; - -def SchedWriteCvtDQ2PD - : X86SchedWriteWidths; -def SchedWriteCvtDQ2PS - : X86SchedWriteWidths; -def SchedWriteCvtPD2DQ - : X86SchedWriteWidths; -def SchedWriteCvtPS2DQ - : X86SchedWriteWidths; -def SchedWriteCvtPS2PD - : X86SchedWriteWidths; -def SchedWriteCvtPD2PS - : X86SchedWriteWidths; - -def SchedWriteVecALU - : X86SchedWriteWidths; -def SchedWritePHAdd - : X86SchedWriteWidths; -def SchedWriteVecLogic - : X86SchedWriteWidths; -def SchedWriteVecTest - : X86SchedWriteWidths; -def SchedWriteVecShift - : X86SchedWriteWidths; -def SchedWriteVecShiftImm - : X86SchedWriteWidths; -def SchedWriteVarVecShift - : X86SchedWriteWidths; -def SchedWriteVecIMul - : X86SchedWriteWidths; -def SchedWritePMULLD - : X86SchedWriteWidths; -def SchedWriteMPSAD - : X86SchedWriteWidths; -def SchedWritePSADBW - : X86SchedWriteWidths; - -def SchedWriteShuffle - : X86SchedWriteWidths; -def SchedWriteVarShuffle - : X86SchedWriteWidths; -def SchedWriteBlend - : X86SchedWriteWidths; -def SchedWriteVarBlend - : X86SchedWriteWidths; - -// Vector size wrappers. -def SchedWriteFAddSizes - : X86SchedWriteSizes; -def SchedWriteFCmpSizes - : X86SchedWriteSizes; -def SchedWriteFMulSizes - : X86SchedWriteSizes; -def SchedWriteFDivSizes - : X86SchedWriteSizes; -def SchedWriteFSqrtSizes - : X86SchedWriteSizes; -def SchedWriteFLogicSizes - : X86SchedWriteSizes; -def SchedWriteFShuffleSizes - : X86SchedWriteSizes; - -//===----------------------------------------------------------------------===// -// Generic Processor Scheduler Models. - -// IssueWidth is analogous to the number of decode units. Core and its -// descendants, including Nehalem and SandyBridge have 4 decoders. -// Resources beyond the decoder operate on micro-ops and are buffered -// so adjacent micro-ops don't directly compete. -// -// MicroOpBufferSize > 1 indicates that RAW dependencies can be -// decoded in the same cycle. The value 32 is a reasonably arbitrary -// number of in-flight instructions. -// -// HighLatency=10 is optimistic. X86InstrInfo::isHighLatencyDef -// indicates high latency opcodes. Alternatively, InstrItinData -// entries may be included here to define specific operand -// latencies. Since these latencies are not used for pipeline hazards, -// they do not need to be exact. -// -// The GenericX86Model contains no instruction schedules -// and disables PostRAScheduler. -class GenericX86Model : SchedMachineModel { - let IssueWidth = 4; - let MicroOpBufferSize = 32; - let LoadLatency = 4; - let HighLatency = 10; - let PostRAScheduler = 0; - let CompleteModel = 0; -} - -def GenericModel : GenericX86Model; - -// Define a model with the PostRAScheduler enabled. -def GenericPostRAModel : GenericX86Model { - let PostRAScheduler = 1; -} diff --git a/suite/synctools/tablegen/X86/X86ScheduleAtom.td b/suite/synctools/tablegen/X86/X86ScheduleAtom.td deleted file mode 100644 index daa6fc73cc..0000000000 --- a/suite/synctools/tablegen/X86/X86ScheduleAtom.td +++ /dev/null @@ -1,917 +0,0 @@ -//===- X86ScheduleAtom.td - X86 Atom Scheduling Definitions -*- tablegen -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the schedule class data for the Intel Atom -// in order (Saltwell-32nm/Bonnell-45nm) processors. -// -//===----------------------------------------------------------------------===// - -// -// Scheduling information derived from the "Intel 64 and IA32 Architectures -// Optimization Reference Manual", Chapter 13, Section 4. - -// Atom machine model. -def AtomModel : SchedMachineModel { - let IssueWidth = 2; // Allows 2 instructions per scheduling group. - let MicroOpBufferSize = 0; // In-order execution, always hide latency. - let LoadLatency = 3; // Expected cycles, may be overridden. - let HighLatency = 30;// Expected, may be overridden. - - // On the Atom, the throughput for taken branches is 2 cycles. For small - // simple loops, expand by a small factor to hide the backedge cost. - let LoopMicroOpBufferSize = 10; - let PostRAScheduler = 1; - let CompleteModel = 0; -} - -let SchedModel = AtomModel in { - -// Functional Units -def AtomPort0 : ProcResource<1>; // ALU: ALU0, shift/rotate, load/store - // SIMD/FP: SIMD ALU, Shuffle,SIMD/FP multiply, divide -def AtomPort1 : ProcResource<1>; // ALU: ALU1, bit processing, jump, and LEA - // SIMD/FP: SIMD ALU, FP Adder - -def AtomPort01 : ProcResGroup<[AtomPort0, AtomPort1]>; - -// Loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when dispatched by the schedulers. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass AtomWriteResPair RRPorts, - list RMPorts, - int RRLat = 1, int RMLat = 1, - list RRRes = [1], - list RMRes = [1]> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = RRLat; - let ResourceCycles = RRRes; - } - - // Memory variant also uses a cycle on JLAGU and adds 3 cycles to the - // latency. - def : WriteRes { - let Latency = RMLat; - let ResourceCycles = RMRes; - } -} - -// A folded store needs a cycle on Port0 for the store data. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Arithmetic. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteRes; // x87 conditional move. - -def : WriteRes; -def : WriteRes { - let Latency = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 2; - let ResourceCycles = [2]; -} -def : WriteRes; - -defm : X86WriteResUnsupported; - -// This is for simple LEAs with one or two input operands. -def : WriteRes; - -def AtomWriteIMul16Ld : SchedWriteRes<[AtomPort01]> { - let Latency = 8; - let ResourceCycles = [8]; -} -def : InstRW<[AtomWriteIMul16Ld], (instrs MUL16m, IMUL16m)>; - -def AtomWriteIMul32 : SchedWriteRes<[AtomPort01]> { - let Latency = 6; - let ResourceCycles = [6]; -} -def : InstRW<[AtomWriteIMul32], (instrs MUL32r, IMUL32r)>; - -def AtomWriteIMul64I : SchedWriteRes<[AtomPort01]> { - let Latency = 14; - let ResourceCycles = [14]; -} -def : InstRW<[AtomWriteIMul64I], (instrs IMUL64rri8, IMUL64rri32, - IMUL64rmi8, IMUL64rmi32)>; - -// Bit counts. -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -// BMI1 BEXTR, BMI2 BZHI -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Integer shifts and rotates. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Loads, stores, and moves, not folded with other operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -//////////////////////////////////////////////////////////////////////////////// -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; - -//////////////////////////////////////////////////////////////////////////////// -// Special case scheduling classes. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; - -// Nops don't have dependencies, so there's no actual latency, but we set this -// to '1' to tell the scheduler that the nop uses an ALU slot for a cycle. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Floating point. This covers both scalar and vector operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Conversions. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector integer operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector insert/extract operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -def : WriteRes; -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// SSE42 String instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// MOVMSK Instructions. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } -defm : X86WriteResUnsupported; -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } - -//////////////////////////////////////////////////////////////////////////////// -// AES instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -//////////////////////////////////////////////////////////////////////////////// -// Carry-less multiplication instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Load/store MXCSR. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 5; let ResourceCycles = [5]; } -def : WriteRes { let Latency = 15; let ResourceCycles = [15]; } - -//////////////////////////////////////////////////////////////////////////////// -// Special Cases. -//////////////////////////////////////////////////////////////////////////////// - -// Port0 -def AtomWrite0_1 : SchedWriteRes<[AtomPort0]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite0_1], (instrs FXAM, LD_Frr, - MOVSX64rr32)>; -def : SchedAlias; -def : SchedAlias; -def : InstRW<[AtomWrite0_1], (instregex "(RCL|RCR|ROL|ROR|SAR|SHL|SHR)(8|16|32|64)m", - "MOV(S|Z)X(32|64)rr(8|8_NOREX|16)")>; - -def AtomWrite0_5 : SchedWriteRes<[AtomPort0]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite0_5], (instregex "IMUL32(rm|rr)")>; - -// Port1 -def AtomWrite1_1 : SchedWriteRes<[AtomPort1]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite1_1], (instrs FCOMPP)>; -def : InstRW<[AtomWrite1_1], (instregex "UCOM_F(P|PP)?r", - "BT(C|R|S)?(16|32|64)(rr|ri8)")>; - -def AtomWrite1_5 : SchedWriteRes<[AtomPort1]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite1_5], (instrs MMX_CVTPI2PSirr, MMX_CVTPI2PSirm, - MMX_CVTPS2PIirr, MMX_CVTTPS2PIirr)>; - -// Port0 and Port1 -def AtomWrite0_1_1 : SchedWriteRes<[AtomPort0, AtomPort1]> { - let Latency = 1; - let ResourceCycles = [1, 1]; -} -def : InstRW<[AtomWrite0_1_1], (instrs POP32r, POP64r, - POP16rmr, POP32rmr, POP64rmr, - PUSH16r, PUSH32r, PUSH64r, - PUSHi16, PUSHi32, - PUSH16rmr, PUSH32rmr, PUSH64rmr, - PUSH16i8, PUSH32i8, PUSH64i8, PUSH64i32, - XCH_F)>; -def : InstRW<[AtomWrite0_1_1], (instregex "RETI(L|Q|W)$", - "IRET(16|32|64)?")>; - -def AtomWrite0_1_5 : SchedWriteRes<[AtomPort0, AtomPort1]> { - let Latency = 5; - let ResourceCycles = [5, 5]; -} -def : InstRW<[AtomWrite0_1_5], (instrs MMX_CVTPS2PIirm, MMX_CVTTPS2PIirm)>; -def : InstRW<[AtomWrite0_1_5], (instregex "ILD_F(16|32|64)")>; - -// Port0 or Port1 -def AtomWrite01_1 : SchedWriteRes<[AtomPort01]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite01_1], (instrs FDECSTP, FFREE, FFREEP, FINCSTP, WAIT, - LFENCE, - STOSB, STOSL, STOSQ, STOSW, - MOVSSrr, MOVSSrr_REV, - PSLLDQri, PSRLDQri)>; -def : InstRW<[AtomWrite01_1], (instregex "MMX_PACK(SSDW|SSWB|USWB)irr", - "MMX_PUNPCKH(BW|DQ|WD)irr")>; - -def AtomWrite01_2 : SchedWriteRes<[AtomPort01]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def : InstRW<[AtomWrite01_2], (instrs LEAVE, LEAVE64, POP16r, - PUSH16rmm, PUSH32rmm, PUSH64rmm, - LODSB, LODSL, LODSQ, LODSW, - SCASB, SCASL, SCASQ, SCASW)>; -def : InstRW<[AtomWrite01_2], (instregex "BT(C|R|S)(16|32|64)mi8", - "PUSH(CS|DS|ES|FS|GS|SS)(16|32|64)", - "XADD(8|16|32|64)rr", - "XCHG(8|16|32|64)(ar|rr)", - "(ST|ISTT)_F(P)?(16|32|64)?(m|rr)", - "MMX_P(ADD|SUB)Qirr", - "MOV(S|Z)X16rr8", - "MOV(UPS|UPD|DQU)mr", - "MASKMOVDQU(64)?", - "P(ADD|SUB)Qrr")>; - -def AtomWrite01_3 : SchedWriteRes<[AtomPort01]> { - let Latency = 3; - let ResourceCycles = [3]; -} -def : InstRW<[AtomWrite01_3], (instrs CLD, LDDQUrm, - CMPSB, CMPSL, CMPSQ, CMPSW, - MOVSB, MOVSL, MOVSQ, MOVSW, - POP16rmm, POP32rmm, POP64rmm)>; -def : InstRW<[AtomWrite01_3], (instregex "XADD(8|16|32|64)rm", - "XCHG(8|16|32|64)rm", - "PH(ADD|SUB)Drr", - "MOV(S|Z)X16rm8", - "MMX_P(ADD|SUB)Qirm", - "MOV(UPS|UPD|DQU)rm", - "P(ADD|SUB)Qrm")>; - -def AtomWrite01_4 : SchedWriteRes<[AtomPort01]> { - let Latency = 4; - let ResourceCycles = [4]; -} -def : InstRW<[AtomWrite01_4], (instrs CBW, CWD, CWDE, CDQ, CDQE, CQO, - JCXZ, JECXZ, JRCXZ, - LD_F80m)>; -def : InstRW<[AtomWrite01_4], (instregex "PH(ADD|SUB)Drm", - "(MMX_)?PEXTRWrr(_REV)?")>; - -def AtomWrite01_5 : SchedWriteRes<[AtomPort01]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite01_5], (instrs FLDCW16m, ST_FP80m)>; -def : InstRW<[AtomWrite01_5], (instregex "MMX_PH(ADD|SUB)S?Wrr")>; - -def AtomWrite01_6 : SchedWriteRes<[AtomPort01]> { - let Latency = 6; - let ResourceCycles = [6]; -} -def : InstRW<[AtomWrite01_6], (instrs CMPXCHG8rm, INTO, XLAT, - SHLD16rrCL, SHRD16rrCL, - SHLD16rri8, SHRD16rri8, - SHLD16mrCL, SHRD16mrCL, - SHLD16mri8, SHRD16mri8)>; -def : InstRW<[AtomWrite01_6], (instregex "IMUL16rr", - "IST_F(P)?(16|32|64)?m", - "MMX_PH(ADD|SUB)S?Wrm")>; - -def AtomWrite01_7 : SchedWriteRes<[AtomPort01]> { - let Latency = 7; - let ResourceCycles = [7]; -} -def : InstRW<[AtomWrite01_7], (instrs AAD8i8)>; - -def AtomWrite01_8 : SchedWriteRes<[AtomPort01]> { - let Latency = 8; - let ResourceCycles = [8]; -} -def : InstRW<[AtomWrite01_8], (instrs LOOPE, - PUSHA16, PUSHA32, - SHLD64rrCL, SHRD64rrCL, - FNSTCW16m)>; - -def AtomWrite01_9 : SchedWriteRes<[AtomPort01]> { - let Latency = 9; - let ResourceCycles = [9]; -} -def : InstRW<[AtomWrite01_9], (instrs BT16mr, BT32mr, BT64mr, - POPA16, POPA32, - PUSHF16, PUSHF32, PUSHF64, - SHLD64mrCL, SHRD64mrCL, - SHLD64mri8, SHRD64mri8, - SHLD64rri8, SHRD64rri8, - CMPXCHG8rr)>; -def : InstRW<[AtomWrite01_9], (instregex "(U)?COM_FI", "TST_F", - "(U)?COMIS(D|S)rr", - "CVT(T)?SS2SI64rr(_Int)?")>; - -def AtomWrite01_10 : SchedWriteRes<[AtomPort01]> { - let Latency = 10; - let ResourceCycles = [10]; -} -def : SchedAlias; -def : InstRW<[AtomWrite01_10], (instregex "(U)?COMIS(D|S)rm", - "CVT(T)?SS2SI64rm(_Int)?")>; - -def AtomWrite01_11 : SchedWriteRes<[AtomPort01]> { - let Latency = 11; - let ResourceCycles = [11]; -} -def : InstRW<[AtomWrite01_11], (instrs BOUNDS16rm, BOUNDS32rm)>; -def : InstRW<[AtomWrite01_11], (instregex "BT(C|R|S)(16|32|64)mr")>; - -def AtomWrite01_13 : SchedWriteRes<[AtomPort01]> { - let Latency = 13; - let ResourceCycles = [13]; -} -def : InstRW<[AtomWrite01_13], (instrs AAA, AAS)>; - -def AtomWrite01_14 : SchedWriteRes<[AtomPort01]> { - let Latency = 14; - let ResourceCycles = [14]; -} -def : InstRW<[AtomWrite01_14], (instrs CMPXCHG16rm, CMPXCHG32rm, CMPXCHG64rm)>; - -def AtomWrite01_15 : SchedWriteRes<[AtomPort01]> { - let Latency = 15; - let ResourceCycles = [15]; -} -def : InstRW<[AtomWrite01_15], (instrs CMPXCHG16rr, CMPXCHG32rr, CMPXCHG64rr)>; - -def AtomWrite01_17 : SchedWriteRes<[AtomPort01]> { - let Latency = 17; - let ResourceCycles = [17]; -} -def : InstRW<[AtomWrite01_17], (instrs LOOPNE, PAUSE)>; - -def AtomWrite01_18 : SchedWriteRes<[AtomPort01]> { - let Latency = 18; - let ResourceCycles = [18]; -} -def : InstRW<[AtomWrite01_18], (instrs CMPXCHG8B, DAA, LOOP)>; - -def AtomWrite01_20 : SchedWriteRes<[AtomPort01]> { - let Latency = 20; - let ResourceCycles = [20]; -} -def : InstRW<[AtomWrite01_20], (instrs DAS)>; - -def AtomWrite01_21 : SchedWriteRes<[AtomPort01]> { - let Latency = 21; - let ResourceCycles = [21]; -} -def : InstRW<[AtomWrite01_21], (instrs AAM8i8, STD)>; - -def AtomWrite01_22 : SchedWriteRes<[AtomPort01]> { - let Latency = 22; - let ResourceCycles = [22]; -} -def : InstRW<[AtomWrite01_22], (instrs CMPXCHG16B)>; - -def AtomWrite01_23 : SchedWriteRes<[AtomPort01]> { - let Latency = 23; - let ResourceCycles = [23]; -} -def : InstRW<[AtomWrite01_23], (instrs ARPL16mr, ARPL16rr)>; - -def AtomWrite01_25 : SchedWriteRes<[AtomPort01]> { - let Latency = 25; - let ResourceCycles = [25]; -} -def : InstRW<[AtomWrite01_25], (instrs FNCLEX, FXTRACT)>; - -def AtomWrite01_26 : SchedWriteRes<[AtomPort01]> { - let Latency = 26; - let ResourceCycles = [26]; -} -def : InstRW<[AtomWrite01_26], (instrs POPF32, POPF64)>; - -def AtomWrite01_29 : SchedWriteRes<[AtomPort01]> { - let Latency = 29; - let ResourceCycles = [29]; -} -def : InstRW<[AtomWrite01_29], (instregex "POP(DS|ES|FS|GS)(16|32|64)")>; - -def AtomWrite01_30 : SchedWriteRes<[AtomPort01]> { - let Latency = 30; - let ResourceCycles = [30]; -} -def : InstRW<[AtomWrite01_30], (instrs RDTSC, RDTSCP)>; - -def AtomWrite01_32 : SchedWriteRes<[AtomPort01]> { - let Latency = 32; - let ResourceCycles = [32]; -} -def : InstRW<[AtomWrite01_32], (instrs ENTER, POPF16)>; - -def AtomWrite01_45 : SchedWriteRes<[AtomPort01]> { - let Latency = 45; - let ResourceCycles = [45]; -} -def : InstRW<[AtomWrite01_45], (instrs MONITORrrr)>; - -def AtomWrite01_46 : SchedWriteRes<[AtomPort01]> { - let Latency = 46; - let ResourceCycles = [46]; -} -def : InstRW<[AtomWrite01_46], (instrs FRNDINT, MWAITrr, RDPMC)>; - -def AtomWrite01_48 : SchedWriteRes<[AtomPort01]> { - let Latency = 48; - let ResourceCycles = [48]; -} -def : InstRW<[AtomWrite01_48], (instrs POPSS16, POPSS32)>; - -def AtomWrite01_55 : SchedWriteRes<[AtomPort01]> { - let Latency = 55; - let ResourceCycles = [55]; -} -def : InstRW<[AtomWrite01_55], (instrs FPREM)>; - -def AtomWrite01_59 : SchedWriteRes<[AtomPort01]> { - let Latency = 59; - let ResourceCycles = [59]; -} -def : InstRW<[AtomWrite01_59], (instrs INSB, INSL, INSW)>; - -def AtomWrite01_63 : SchedWriteRes<[AtomPort01]> { - let Latency = 63; - let ResourceCycles = [63]; -} -def : InstRW<[AtomWrite01_63], (instrs FNINIT)>; - -def AtomWrite01_68 : SchedWriteRes<[AtomPort01]> { - let Latency = 68; - let ResourceCycles = [68]; -} -def : InstRW<[AtomWrite01_68], (instrs OUT8rr, OUT16rr, OUT32rr)>; - -def AtomWrite01_71 : SchedWriteRes<[AtomPort01]> { - let Latency = 71; - let ResourceCycles = [71]; -} -def : InstRW<[AtomWrite01_71], (instrs FPREM1, - INVLPG, INVLPGA32, INVLPGA64)>; - -def AtomWrite01_72 : SchedWriteRes<[AtomPort01]> { - let Latency = 72; - let ResourceCycles = [72]; -} -def : InstRW<[AtomWrite01_72], (instrs OUT8ir, OUT16ir, OUT32ir)>; - -def AtomWrite01_74 : SchedWriteRes<[AtomPort01]> { - let Latency = 74; - let ResourceCycles = [74]; -} -def : InstRW<[AtomWrite01_74], (instrs OUTSB, OUTSL, OUTSW)>; - -def AtomWrite01_77 : SchedWriteRes<[AtomPort01]> { - let Latency = 77; - let ResourceCycles = [77]; -} -def : InstRW<[AtomWrite01_77], (instrs FSCALE)>; - -def AtomWrite01_78 : SchedWriteRes<[AtomPort01]> { - let Latency = 78; - let ResourceCycles = [78]; -} -def : InstRW<[AtomWrite01_78], (instrs RDMSR)>; - -def AtomWrite01_79 : SchedWriteRes<[AtomPort01]> { - let Latency = 79; - let ResourceCycles = [79]; -} -def : InstRW<[AtomWrite01_79], (instregex "RET(L|Q|W)?$", - "LRETI?(L|Q|W)")>; - -def AtomWrite01_92 : SchedWriteRes<[AtomPort01]> { - let Latency = 92; - let ResourceCycles = [92]; -} -def : InstRW<[AtomWrite01_92], (instrs IN8ri, IN16ri, IN32ri)>; - -def AtomWrite01_94 : SchedWriteRes<[AtomPort01]> { - let Latency = 94; - let ResourceCycles = [94]; -} -def : InstRW<[AtomWrite01_94], (instrs IN8rr, IN16rr, IN32rr)>; - -def AtomWrite01_99 : SchedWriteRes<[AtomPort01]> { - let Latency = 99; - let ResourceCycles = [99]; -} -def : InstRW<[AtomWrite01_99], (instrs F2XM1)>; - -def AtomWrite01_121 : SchedWriteRes<[AtomPort01]> { - let Latency = 121; - let ResourceCycles = [121]; -} -def : InstRW<[AtomWrite01_121], (instrs CPUID)>; - -def AtomWrite01_127 : SchedWriteRes<[AtomPort01]> { - let Latency = 127; - let ResourceCycles = [127]; -} -def : InstRW<[AtomWrite01_127], (instrs INT)>; - -def AtomWrite01_130 : SchedWriteRes<[AtomPort01]> { - let Latency = 130; - let ResourceCycles = [130]; -} -def : InstRW<[AtomWrite01_130], (instrs INT3)>; - -def AtomWrite01_140 : SchedWriteRes<[AtomPort01]> { - let Latency = 140; - let ResourceCycles = [140]; -} -def : InstRW<[AtomWrite01_140], (instrs FXSAVE, FXSAVE64)>; - -def AtomWrite01_141 : SchedWriteRes<[AtomPort01]> { - let Latency = 141; - let ResourceCycles = [141]; -} -def : InstRW<[AtomWrite01_141], (instrs FXRSTOR, FXRSTOR64)>; - -def AtomWrite01_146 : SchedWriteRes<[AtomPort01]> { - let Latency = 146; - let ResourceCycles = [146]; -} -def : InstRW<[AtomWrite01_146], (instrs FYL2X)>; - -def AtomWrite01_147 : SchedWriteRes<[AtomPort01]> { - let Latency = 147; - let ResourceCycles = [147]; -} -def : InstRW<[AtomWrite01_147], (instrs FYL2XP1)>; - -def AtomWrite01_168 : SchedWriteRes<[AtomPort01]> { - let Latency = 168; - let ResourceCycles = [168]; -} -def : InstRW<[AtomWrite01_168], (instrs FPTAN)>; - -def AtomWrite01_174 : SchedWriteRes<[AtomPort01]> { - let Latency = 174; - let ResourceCycles = [174]; -} -def : InstRW<[AtomWrite01_174], (instrs FSINCOS)>; -def : InstRW<[AtomWrite01_174], (instregex "(COS|SIN)_F")>; - -def AtomWrite01_183 : SchedWriteRes<[AtomPort01]> { - let Latency = 183; - let ResourceCycles = [183]; -} -def : InstRW<[AtomWrite01_183], (instrs FPATAN)>; - -def AtomWrite01_202 : SchedWriteRes<[AtomPort01]> { - let Latency = 202; - let ResourceCycles = [202]; -} -def : InstRW<[AtomWrite01_202], (instrs WRMSR)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86ScheduleBtVer2.td b/suite/synctools/tablegen/X86/X86ScheduleBtVer2.td deleted file mode 100644 index 719e71cd25..0000000000 --- a/suite/synctools/tablegen/X86/X86ScheduleBtVer2.td +++ /dev/null @@ -1,682 +0,0 @@ -//=- X86ScheduleBtVer2.td - X86 BtVer2 (Jaguar) Scheduling ---*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for AMD btver2 (Jaguar) to support -// instruction scheduling and other instruction cost heuristics. Based off AMD Software -// Optimization Guide for AMD Family 16h Processors & Instruction Latency appendix. -// -//===----------------------------------------------------------------------===// - -def BtVer2Model : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and btver2 can - // decode 2 instructions per cycle. - let IssueWidth = 2; - let MicroOpBufferSize = 64; // Retire Control Unit - let LoadLatency = 5; // FPU latency (worse case cf Integer 3 cycle latency) - let HighLatency = 25; - let MispredictPenalty = 14; // Minimum branch misdirection penalty - let PostRAScheduler = 1; - - // FIXME: SSE4/AVX is unimplemented. This flag is set to allow - // the scheduler to assign a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = BtVer2Model in { - -// Jaguar can issue up to 6 micro-ops in one cycle -def JALU0 : ProcResource<1>; // Integer Pipe0: integer ALU0 (also handle FP->INT jam) -def JALU1 : ProcResource<1>; // Integer Pipe1: integer ALU1/MUL/DIV -def JLAGU : ProcResource<1>; // Integer Pipe2: LAGU -def JSAGU : ProcResource<1>; // Integer Pipe3: SAGU (also handles 3-operand LEA) -def JFPU0 : ProcResource<1>; // Vector/FPU Pipe0: VALU0/VIMUL/FPA -def JFPU1 : ProcResource<1>; // Vector/FPU Pipe1: VALU1/STC/FPM - -// The Integer PRF for Jaguar is 64 entries, and it holds the architectural and -// speculative version of the 64-bit integer registers. -// Reference: www.realworldtech.com/jaguar/4/ -// -// The processor always keeps the different parts of an integer register -// together. An instruction that writes to a part of a register will therefore -// have a false dependence on any previous write to the same register or any -// part of it. -// Reference: Section 21.10 "AMD Bobcat and Jaguar pipeline: Partial register -// access" - Agner Fog's "microarchitecture.pdf". -def JIntegerPRF : RegisterFile<64, [GR64, CCR]>; - -// The Jaguar FP Retire Queue renames SIMD and FP uOps onto a pool of 72 SSE -// registers. Operations on 256-bit data types are cracked into two COPs. -// Reference: www.realworldtech.com/jaguar/4/ -def JFpuPRF: RegisterFile<72, [VR64, VR128, VR256], [1, 1, 2]>; - -// The retire control unit (RCU) can track up to 64 macro-ops in-flight. It can -// retire up to two macro-ops per cycle. -// Reference: "Software Optimization Guide for AMD Family 16h Processors" -def JRCU : RetireControlUnit<64, 2>; - -// Integer Pipe Scheduler -def JALU01 : ProcResGroup<[JALU0, JALU1]> { - let BufferSize=20; -} - -// AGU Pipe Scheduler -def JLSAGU : ProcResGroup<[JLAGU, JSAGU]> { - let BufferSize=12; -} - -// Fpu Pipe Scheduler -def JFPU01 : ProcResGroup<[JFPU0, JFPU1]> { - let BufferSize=18; -} - -// Functional units -def JDiv : ProcResource<1>; // integer division -def JMul : ProcResource<1>; // integer multiplication -def JVALU0 : ProcResource<1>; // vector integer -def JVALU1 : ProcResource<1>; // vector integer -def JVIMUL : ProcResource<1>; // vector integer multiplication -def JSTC : ProcResource<1>; // vector store/convert -def JFPM : ProcResource<1>; // FP multiplication -def JFPA : ProcResource<1>; // FP addition - -// Functional unit groups -def JFPX : ProcResGroup<[JFPA, JFPM]>; -def JVALU : ProcResGroup<[JVALU0, JVALU1]>; - -// Integer loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when dispatched by the schedulers. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass JWriteResIntPair ExePorts, - int Lat, list Res = [], int UOps = 1> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on JLAGU and adds 3 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 3); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = UOps; - } -} - -multiclass JWriteResFpuPair ExePorts, - int Lat, list Res = [], int UOps = 1> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on JLAGU and adds 5 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 5); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = UOps; - } -} - -multiclass JWriteResYMMPair ExePorts, - int Lat, list Res = [2], int UOps = 2> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses 2 cycles on JLAGU and adds 5 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 5); - let ResourceCycles = !listconcat([2], Res); - let NumMicroOps = UOps; - } -} - -// A folded store needs a cycle on the SAGU for the store data. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Arithmetic. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; // i8/i16/i32 multiplication -defm : JWriteResIntPair; // i64 multiplication -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; - -defm : JWriteResIntPair; - -defm : JWriteResIntPair; // Conditional move. -defm : JWriteResIntPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -def : WriteRes; - -// Bit counts. -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : JWriteResIntPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Integer shifts and rotates. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Loads, stores, and moves, not folded with other operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 5; } -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// Load/store MXCSR. -// FIXME: These are copy and pasted from WriteLoad/Store. -def : WriteRes { let Latency = 5; } -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -//////////////////////////////////////////////////////////////////////////////// -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; - -//////////////////////////////////////////////////////////////////////////////// -// Special case scheduling classes. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; - -// Nops don't have dependencies, so there's no actual latency, but we set this -// to '1' to tell the scheduler that the nop uses an ALU slot for a cycle. -def : WriteRes { let Latency = 1; } - -//////////////////////////////////////////////////////////////////////////////// -// Floating point. This covers both scalar and vector operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Conversions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -// FIXME: f+3 ST, LD+STC latency -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector integer operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector insert/extract operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// SSE42 String instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// MOVMSK Instructions. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -defm : X86WriteResUnsupported; -def : WriteRes { let Latency = 3; } - -//////////////////////////////////////////////////////////////////////////////// -// AES Instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Carry-less multiplication instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// SSE4A instructions. -//////////////////////////////////////////////////////////////////////////////// - -def JWriteINSERTQ: SchedWriteRes<[JFPU01, JVALU]> { - let Latency = 2; - let ResourceCycles = [1, 4]; -} -def : InstRW<[JWriteINSERTQ], (instrs INSERTQ, INSERTQI)>; - -//////////////////////////////////////////////////////////////////////////////// -// AVX instructions. -//////////////////////////////////////////////////////////////////////////////// - -def JWriteVBROADCASTYLd: SchedWriteRes<[JLAGU, JFPU01, JFPX]> { - let Latency = 6; - let ResourceCycles = [1, 2, 4]; - let NumMicroOps = 2; -} -def : InstRW<[JWriteVBROADCASTYLd, ReadAfterLd], (instrs VBROADCASTSDYrm, - VBROADCASTSSYrm)>; - -def JWriteJVZEROALL: SchedWriteRes<[]> { - let Latency = 90; - let NumMicroOps = 73; -} -def : InstRW<[JWriteJVZEROALL], (instrs VZEROALL)>; - -def JWriteJVZEROUPPER: SchedWriteRes<[]> { - let Latency = 46; - let NumMicroOps = 37; -} -def : InstRW<[JWriteJVZEROUPPER], (instrs VZEROUPPER)>; - -/////////////////////////////////////////////////////////////////////////////// -// SchedWriteVariant definitions. -/////////////////////////////////////////////////////////////////////////////// - -def JWriteZeroLatency : SchedWriteRes<[]> { - let Latency = 0; -} - -// Certain instructions that use the same register for both source -// operands do not have a real dependency on the previous contents of the -// register, and thus, do not have to wait before completing. They can be -// optimized out at register renaming stage. -// Reference: Section 10.8 of the "Software Optimization Guide for AMD Family -// 15h Processors". -// Reference: Agner's Fog "The microarchitecture of Intel, AMD and VIA CPUs", -// Section 21.8 [Dependency-breaking instructions]. - -def JWriteZeroIdiom : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteALU]> -]>; -def : InstRW<[JWriteZeroIdiom], (instrs SUB32rr, SUB64rr, - XOR32rr, XOR64rr)>; - -def JWriteFZeroIdiom : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteFLogic]> -]>; -def : InstRW<[JWriteFZeroIdiom], (instrs XORPSrr, VXORPSrr, XORPDrr, VXORPDrr, - ANDNPSrr, VANDNPSrr, - ANDNPDrr, VANDNPDrr)>; - -def JWriteVZeroIdiomLogic : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecLogic]> -]>; -def : InstRW<[JWriteVZeroIdiomLogic], (instrs MMX_PXORirr, MMX_PANDNirr)>; - -def JWriteVZeroIdiomLogicX : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecLogicX]> -]>; -def : InstRW<[JWriteVZeroIdiomLogicX], (instrs PXORrr, VPXORrr, - PANDNrr, VPANDNrr)>; - -def JWriteVZeroIdiomALU : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecALU]> -]>; -def : InstRW<[JWriteVZeroIdiomALU], (instrs MMX_PSUBBirr, MMX_PSUBDirr, - MMX_PSUBQirr, MMX_PSUBWirr, - MMX_PCMPGTBirr, MMX_PCMPGTDirr, - MMX_PCMPGTWirr)>; - -def JWriteVZeroIdiomALUX : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecALUX]> -]>; -def : InstRW<[JWriteVZeroIdiomALUX], (instrs PSUBBrr, VPSUBBrr, - PSUBDrr, VPSUBDrr, - PSUBQrr, VPSUBQrr, - PSUBWrr, VPSUBWrr, - PCMPGTBrr, VPCMPGTBrr, - PCMPGTDrr, VPCMPGTDrr, - PCMPGTQrr, VPCMPGTQrr, - PCMPGTWrr, VPCMPGTWrr)>; - -// This write is used for slow LEA instructions. -def JWrite3OpsLEA : SchedWriteRes<[JALU1, JSAGU]> { - let Latency = 2; -} - -// On Jaguar, a slow LEA is either a 3Ops LEA (base, index, offset), or an LEA -// with a `Scale` value different than 1. -def JSlowLEAPredicate : MCSchedPredicate< - CheckAny<[ - // A 3-operand LEA (base, index, offset). - IsThreeOperandsLEAFn, - // An LEA with a "Scale" different than 1. - CheckAll<[ - CheckIsImmOperand<2>, - CheckNot> - ]> - ]> ->; - -def JWriteLEA : SchedWriteVariant<[ - SchedVar, - SchedVar, [WriteLEA]> -]>; - -def : InstRW<[JWriteLEA], (instrs LEA32r, LEA64r, LEA64_32r)>; - -def JSlowLEA16r : SchedWriteRes<[JALU01]> { - let Latency = 3; - let ResourceCycles = [4]; -} - -def : InstRW<[JSlowLEA16r], (instrs LEA16r)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86ScheduleSLM.td b/suite/synctools/tablegen/X86/X86ScheduleSLM.td deleted file mode 100644 index b1e8430137..0000000000 --- a/suite/synctools/tablegen/X86/X86ScheduleSLM.td +++ /dev/null @@ -1,486 +0,0 @@ -//=- X86ScheduleSLM.td - X86 Silvermont Scheduling -----------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Intel Silvermont to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SLMModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SLM can decode 2 - // instructions per cycle. - let IssueWidth = 2; - let MicroOpBufferSize = 32; // Based on the reorder buffer. - let LoadLatency = 3; - let MispredictPenalty = 10; - let PostRAScheduler = 1; - - // For small loops, expand by a small factor to hide the backedge cost. - let LoopMicroOpBufferSize = 10; - - // FIXME: SSE4 is unimplemented. This flag is set to allow - // the scheduler to assign a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SLMModel in { - -// Silvermont has 5 reservation stations for micro-ops -def SLM_IEC_RSV0 : ProcResource<1>; -def SLM_IEC_RSV1 : ProcResource<1>; -def SLM_FPC_RSV0 : ProcResource<1> { let BufferSize = 1; } -def SLM_FPC_RSV1 : ProcResource<1> { let BufferSize = 1; } -def SLM_MEC_RSV : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SLM_IEC_RSV01 : ProcResGroup<[SLM_IEC_RSV0, SLM_IEC_RSV1]>; -def SLM_FPC_RSV01 : ProcResGroup<[SLM_FPC_RSV0, SLM_FPC_RSV1]>; - -def SLMDivider : ProcResource<1>; -def SLMFPMultiplier : ProcResource<1>; -def SLMFPDivider : ProcResource<1>; - -// Loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SLMWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 3> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on MEC_RSV and adds LoadLat cycles to - // the latency (default = 3). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = UOps; - } -} - -// A folded store needs a cycle on MEC_RSV for the store data, but it does not -// need an extra port cycle to recompute the address. -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; - -// Load/store MXCSR. -// FIXME: These are probably wrong. They are copy pasted from WriteStore/Load. -def : WriteRes; -def : WriteRes { let Latency = 3; } - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; -def : WriteRes { - // FIXME Latency and NumMicrOps? - let ResourceCycles = [2,1]; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; - -// Conversion between integer and float. -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -// Vector integer operations. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -// FIXME: The below is closer to correct, but caused some perf regressions. -//defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; - -// Vector insert/extract operations. -defm : SLMWriteResPair; - -def : WriteRes; -def : WriteRes { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -// String instructions. -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 13; - let ResourceCycles = [13]; -} -def : WriteRes { - let Latency = 13; - let ResourceCycles = [13, 1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17]; -} -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17, 1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17]; -} -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17, 1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 21; - let ResourceCycles = [21]; -} -def : WriteRes { - let Latency = 21; - let ResourceCycles = [21, 1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } - -// AES Instructions. -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 10; - let ResourceCycles = [10]; -} -def : WriteRes { - let Latency = 10; - let ResourceCycles = [10, 1]; -} - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -// AVX/FMA is not supported on that architecture, but we should define the basic -// scheduling resources anyway. -def : WriteRes; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86ScheduleZnver1.td b/suite/synctools/tablegen/X86/X86ScheduleZnver1.td deleted file mode 100644 index 7184b850a1..0000000000 --- a/suite/synctools/tablegen/X86/X86ScheduleZnver1.td +++ /dev/null @@ -1,1544 +0,0 @@ -//=- X86ScheduleZnver1.td - X86 Znver1 Scheduling -------------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Znver1 to support instruction -// scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def Znver1Model : SchedMachineModel { - // Zen can decode 4 instructions per cycle. - let IssueWidth = 4; - // Based on the reorder buffer we define MicroOpBufferSize - let MicroOpBufferSize = 192; - let LoadLatency = 4; - let MispredictPenalty = 17; - let HighLatency = 25; - let PostRAScheduler = 1; - - // FIXME: This variable is required for incomplete model. - // We haven't catered all instructions. - // So, we reset the value of this variable so as to - // say that the model is incomplete. - let CompleteModel = 0; -} - -let SchedModel = Znver1Model in { - -// Zen can issue micro-ops to 10 different units in one cycle. -// These are -// * Four integer ALU units (ZALU0, ZALU1, ZALU2, ZALU3) -// * Two AGU units (ZAGU0, ZAGU1) -// * Four FPU units (ZFPU0, ZFPU1, ZFPU2, ZFPU3) -// AGUs feed load store queues @two loads and 1 store per cycle. - -// Four ALU units are defined below -def ZnALU0 : ProcResource<1>; -def ZnALU1 : ProcResource<1>; -def ZnALU2 : ProcResource<1>; -def ZnALU3 : ProcResource<1>; - -// Two AGU units are defined below -def ZnAGU0 : ProcResource<1>; -def ZnAGU1 : ProcResource<1>; - -// Four FPU units are defined below -def ZnFPU0 : ProcResource<1>; -def ZnFPU1 : ProcResource<1>; -def ZnFPU2 : ProcResource<1>; -def ZnFPU3 : ProcResource<1>; - -// FPU grouping -def ZnFPU013 : ProcResGroup<[ZnFPU0, ZnFPU1, ZnFPU3]>; -def ZnFPU01 : ProcResGroup<[ZnFPU0, ZnFPU1]>; -def ZnFPU12 : ProcResGroup<[ZnFPU1, ZnFPU2]>; -def ZnFPU13 : ProcResGroup<[ZnFPU1, ZnFPU3]>; -def ZnFPU23 : ProcResGroup<[ZnFPU2, ZnFPU3]>; -def ZnFPU02 : ProcResGroup<[ZnFPU0, ZnFPU2]>; -def ZnFPU03 : ProcResGroup<[ZnFPU0, ZnFPU3]>; - -// Below are the grouping of the units. -// Micro-ops to be issued to multiple units are tackled this way. - -// ALU grouping -// ZnALU03 - 0,3 grouping -def ZnALU03: ProcResGroup<[ZnALU0, ZnALU3]>; - -// 56 Entry (14x4 entries) Int Scheduler -def ZnALU : ProcResGroup<[ZnALU0, ZnALU1, ZnALU2, ZnALU3]> { - let BufferSize=56; -} - -// 28 Entry (14x2) AGU group. AGUs can't be used for all ALU operations -// but are relevant for some instructions -def ZnAGU : ProcResGroup<[ZnAGU0, ZnAGU1]> { - let BufferSize=28; -} - -// Integer Multiplication issued on ALU1. -def ZnMultiplier : ProcResource<1>; - -// Integer division issued on ALU2. -def ZnDivider : ProcResource<1>; - -// 4 Cycles load-to use Latency is captured -def : ReadAdvance; - -// The Integer PRF for Zen is 168 entries, and it holds the architectural and -// speculative version of the 64-bit integer registers. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -def ZnIntegerPRF : RegisterFile<168, [GR64, CCR]>; - -// 36 Entry (9x4 entries) floating-point Scheduler -def ZnFPU : ProcResGroup<[ZnFPU0, ZnFPU1, ZnFPU2, ZnFPU3]> { -let BufferSize=36; -} - -// The Zen FP Retire Queue renames SIMD and FP uOps onto a pool of 160 128-bit -// registers. Operations on 256-bit data types are cracked into two COPs. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -def ZnFpuPRF: RegisterFile<160, [VR64, VR128, VR256], [1, 1, 2]>; - -// The unit can track up to 192 macro ops in-flight. -// The retire unit handles in-order commit of up to 8 macro ops per cycle. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -// To be noted, the retire unit is shared between integer and FP ops. -// In SMT mode it is 96 entry per thread. But, we do not use the conservative -// value here because there is currently no way to fully mode the SMT mode, -// so there is no point in trying. -def ZnRCU : RetireControlUnit<192, 8>; - -// FIXME: there are 72 read buffers and 44 write buffers. - -// (a folded load is an instruction that loads and does some operation) -// Ex: ADDPD xmm,[mem]-> This instruction has two micro-ops -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops. -// a. load and -// b. addpd -// This multiclass is for folded loads for integer units. -multiclass ZnWriteResPair ExePorts, - int Lat, list Res = [], int UOps = 1, - int LoadLat = 4, int LoadUOps = 1> { - // Register variant takes 1-cycle on Execution Port. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on ZnAGU - // adds LoadLat cycles to the latency (default = 4). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = !add(UOps, LoadUOps); - } -} - -// This multiclass is for folded loads for floating point units. -multiclass ZnWriteResFpuPair ExePorts, - int Lat, list Res = [], int UOps = 1, - int LoadLat = 7, int LoadUOps = 0> { - // Register variant takes 1-cycle on Execution Port. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on ZnAGU - // adds LoadLat cycles to the latency (default = 7). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = !add(UOps, LoadUOps); - } -} - -// WriteRMW is set for instructions with Memory write -// operation in codegen -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 8; } - -def : WriteRes; -def : WriteRes; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResPair; - -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -defm : ZnWriteResPair; -defm : ZnWriteResFpuPair; - -defm : ZnWriteResPair; -defm : ZnWriteResPair; -def : WriteRes; -def : WriteRes; -defm : X86WriteRes; -def : WriteRes; - -// Bit counts. -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -// BMI1 BEXTR, BMI2 BZHI -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// IDIV -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// IMULH -def : WriteRes{ - let Latency = 4; -} - -// Floating point operations -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; // FIXME: Should folds require 1 extra uops? -defm : ZnWriteResFpuPair; // FIXME: Should folds require 1 extra uops? -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -//defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; - -// Vector integer operations which uses FPU units -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; // FIXME -defm : ZnWriteResFpuPair; // FIXME -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; - -// Vector Shift Operations -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -defm : ZnWriteResFpuPair; - -def : WriteRes { - let Latency = 2; - let ResourceCycles = [1, 2]; -} -def : WriteRes { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1, 2, 3]; -} - -// MOVMSK Instructions. -def : WriteRes; -def : WriteRes; -def : WriteRes; - -def : WriteRes { - let NumMicroOps = 2; - let Latency = 2; - let ResourceCycles = [2]; -} - -// AES Instructions. -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; - -def : WriteRes; -def : WriteRes; - -// Following instructions with latency=100 are microcoded. -// We set long latency so as to block the entire pipeline. -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; - -// Microcoded Instructions -def ZnWriteMicrocoded : SchedWriteRes<[]> { - let Latency = 100; -} - -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -//=== Regex based InstRW ===// -// Notation: -// - r: register. -// - m = memory. -// - i = immediate -// - mm: 64 bit mmx register. -// - x = 128 bit xmm register. -// - (x)mm = mmx or xmm register. -// - y = 256 bit ymm register. -// - v = any vector register. - -//=== Integer Instructions ===// -//-- Move instructions --// -// MOV. -// r16,m. -def : InstRW<[WriteALULd, ReadAfterLd], (instregex "MOV16rm")>; - -// MOVSX, MOVZX. -// r,m. -def : InstRW<[WriteLoad], (instregex "MOV(S|Z)X32rm(8|16)")>; - -// XCHG. -// r,r. -def ZnWriteXCHG : SchedWriteRes<[ZnALU]> { - let NumMicroOps = 2; - let ResourceCycles = [2]; -} - -def : InstRW<[ZnWriteXCHG], (instregex "XCHG(8|16|32|64)rr", "XCHG(16|32|64)ar")>; - -// r,m. -def ZnWriteXCHGrm : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 5; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteXCHGrm, ReadAfterLd], (instregex "XCHG(8|16|32|64)rm")>; - -def : InstRW<[WriteMicrocoded], (instrs XLAT)>; - -// POP16. -// r. -def ZnWritePop16r : SchedWriteRes<[ZnAGU]>{ - let Latency = 5; - let NumMicroOps = 2; -} -def : InstRW<[ZnWritePop16r], (instregex "POP16rmm")>; -def : InstRW<[WriteMicrocoded], (instregex "POPF(16|32)")>; -def : InstRW<[WriteMicrocoded], (instregex "POPA(16|32)")>; - - -// PUSH. -// r. Has default values. -// m. -def ZnWritePUSH : SchedWriteRes<[ZnAGU]>{ - let Latency = 4; -} -def : InstRW<[ZnWritePUSH], (instregex "PUSH(16|32)rmm")>; - -//PUSHF -def : InstRW<[WriteMicrocoded], (instregex "PUSHF(16|32)")>; - -// PUSHA. -def ZnWritePushA : SchedWriteRes<[ZnAGU]> { - let Latency = 8; -} -def : InstRW<[ZnWritePushA], (instregex "PUSHA(16|32)")>; - -//LAHF -def : InstRW<[WriteMicrocoded], (instrs LAHF)>; - -// MOVBE. -// r,m. -def ZnWriteMOVBE : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 5; -} -def : InstRW<[ZnWriteMOVBE, ReadAfterLd], (instregex "MOVBE(16|32|64)rm")>; - -// m16,r16. -def : InstRW<[ZnWriteMOVBE], (instregex "MOVBE(16|32|64)mr")>; - -//-- Arithmetic instructions --// - -// ADD SUB. -// m,r/i. -def : InstRW<[WriteALULd], (instregex "(ADD|SUB)(8|16|32|64)m(r|i)", - "(ADD|SUB)(8|16|32|64)mi8", - "(ADD|SUB)64mi32")>; - -// ADC SBB. -// m,r/i. -def : InstRW<[WriteALULd], - (instregex "(ADC|SBB)(8|16|32|64)m(r|i)", - "(ADC|SBB)(16|32|64)mi8", - "(ADC|SBB)64mi32")>; - -// INC DEC NOT NEG. -// m. -def : InstRW<[WriteALULd], - (instregex "(INC|DEC|NOT|NEG)(8|16|32|64)m")>; - -// MUL IMUL. -// r16. -def ZnWriteMul16 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMul16], (instrs IMUL16r, MUL16r)>; -def : InstRW<[ZnWriteMul16], (instrs IMUL16rr, IMUL16rri, IMUL16rri8)>; // TODO: is this right? -def : InstRW<[ZnWriteMul16], (instrs IMUL16rm, IMUL16rmi, IMUL16rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m16. -def ZnWriteMul16Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMul16Ld, ReadAfterLd], (instrs IMUL16m, MUL16m)>; - -// r32. -def ZnWriteMul32 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMul32], (instrs IMUL32r, MUL32r)>; -def : InstRW<[ZnWriteMul32], (instrs IMUL32rr, IMUL32rri, IMUL32rri8)>; // TODO: is this right? -def : InstRW<[ZnWriteMul32], (instrs IMUL32rm, IMUL32rmi, IMUL32rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m32. -def ZnWriteMul32Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMul32Ld, ReadAfterLd], (instrs IMUL32m, MUL32m)>; - -// r64. -def ZnWriteMul64 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 4; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteMul64], (instrs IMUL64r, MUL64r)>; -def : InstRW<[ZnWriteMul64], (instrs IMUL64rr, IMUL64rri8, IMUL64rri32)>; // TODO: is this right? -def : InstRW<[ZnWriteMul64], (instrs IMUL64rm, IMUL64rmi32, IMUL64rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m64. -def ZnWriteMul64Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 9; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteMul64Ld, ReadAfterLd], (instrs IMUL64m, MUL64m)>; - -// MULX. -// r32,r32,r32. -def ZnWriteMulX32 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteMulX32], (instrs MULX32rr)>; - -// r32,r32,m32. -def ZnWriteMulX32Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; - let ResourceCycles = [1, 2, 2]; -} -def : InstRW<[ZnWriteMulX32Ld, ReadAfterLd], (instrs MULX32rm)>; - -// r64,r64,r64. -def ZnWriteMulX64 : SchedWriteRes<[ZnALU1]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMulX64], (instrs MULX64rr)>; - -// r64,r64,m64. -def ZnWriteMulX64Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMulX64Ld, ReadAfterLd], (instrs MULX64rm)>; - -//-- Control transfer instructions --// - -// J(E|R)CXZ. -def ZnWriteJCXZ : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteJCXZ], (instrs JCXZ, JECXZ, JRCXZ)>; - -// INTO -def : InstRW<[WriteMicrocoded], (instrs INTO)>; - -// LOOP. -def ZnWriteLOOP : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteLOOP], (instrs LOOP)>; - -// LOOP(N)E, LOOP(N)Z -def ZnWriteLOOPE : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteLOOPE], (instrs LOOPE, LOOPNE)>; - -// CALL. -// r. -def ZnWriteCALLr : SchedWriteRes<[ZnAGU, ZnALU03]>; -def : InstRW<[ZnWriteCALLr], (instregex "CALL(16|32)r")>; - -def : InstRW<[WriteMicrocoded], (instregex "CALL(16|32)m")>; - -// RET. -def ZnWriteRET : SchedWriteRes<[ZnALU03]> { - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteRET], (instregex "RET(L|Q|W)", "LRET(L|Q|W)", - "IRET(16|32|64)")>; - -//-- Logic instructions --// - -// AND OR XOR. -// m,r/i. -def : InstRW<[WriteALULd], - (instregex "(AND|OR|XOR)(8|16|32|64)m(r|i)", - "(AND|OR|XOR)(8|16|32|64)mi8", "(AND|OR|XOR)64mi32")>; - -// Define ALU latency variants -def ZnWriteALULat2 : SchedWriteRes<[ZnALU]> { - let Latency = 2; -} -def ZnWriteALULat2Ld : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 6; -} - -// BT. -// m,i. -def : InstRW<[WriteShiftLd], (instregex "BT(16|32|64)mi8")>; - -// BTR BTS BTC. -// r,r,i. -def ZnWriteBTRSC : SchedWriteRes<[ZnALU]> { - let Latency = 2; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteBTRSC], (instregex "BT(R|S|C)(16|32|64)r(r|i8)")>; - -// m,r,i. -def ZnWriteBTRSCm : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 6; - let NumMicroOps = 2; -} -// m,r,i. -def : InstRW<[ZnWriteBTRSCm], (instregex "BT(R|S|C)(16|32|64)m(r|i8)")>; - -// BLSI BLSMSK BLSR. -// r,r. -def : InstRW<[ZnWriteALULat2], (instregex "BLS(I|MSK|R)(32|64)rr")>; -// r,m. -def : InstRW<[ZnWriteALULat2Ld], (instregex "BLS(I|MSK|R)(32|64)rm")>; - -// CLD STD. -def : InstRW<[WriteALU], (instrs STD, CLD)>; - -// PDEP PEXT. -// r,r,r. -def : InstRW<[WriteMicrocoded], (instregex "PDEP(32|64)rr", "PEXT(32|64)rr")>; -// r,r,m. -def : InstRW<[WriteMicrocoded], (instregex "PDEP(32|64)rm", "PEXT(32|64)rm")>; - -// RCR RCL. -// m,i. -def : InstRW<[WriteMicrocoded], (instregex "RC(R|L)(8|16|32|64)m(1|i|CL)")>; - -// SHR SHL SAR. -// m,i. -def : InstRW<[WriteShiftLd], (instregex "S(A|H)(R|L)(8|16|32|64)m(i|1)")>; - -// SHRD SHLD. -// m,r -def : InstRW<[WriteShiftLd], (instregex "SH(R|L)D(16|32|64)mri8")>; - -// r,r,cl. -def : InstRW<[WriteMicrocoded], (instregex "SH(R|L)D(16|32|64)rrCL")>; - -// m,r,cl. -def : InstRW<[WriteMicrocoded], (instregex "SH(R|L)D(16|32|64)mrCL")>; - -//-- Misc instructions --// -// CMPXCHG. -def ZnWriteCMPXCHG : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 8; - let NumMicroOps = 5; -} -def : InstRW<[ZnWriteCMPXCHG], (instregex "CMPXCHG(8|16|32|64)rm")>; - -// CMPXCHG8B. -def ZnWriteCMPXCHG8B : SchedWriteRes<[ZnAGU, ZnALU]> { - let NumMicroOps = 18; -} -def : InstRW<[ZnWriteCMPXCHG8B], (instrs CMPXCHG8B)>; - -def : InstRW<[WriteMicrocoded], (instrs CMPXCHG16B)>; - -// LEAVE -def ZnWriteLEAVE : SchedWriteRes<[ZnALU, ZnAGU]> { - let Latency = 8; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteLEAVE], (instregex "LEAVE")>; - -// PAUSE. -def : InstRW<[WriteMicrocoded], (instrs PAUSE)>; - -// RDTSC. -def : InstRW<[WriteMicrocoded], (instregex "RDTSC")>; - -// RDPMC. -def : InstRW<[WriteMicrocoded], (instrs RDPMC)>; - -// RDRAND. -def : InstRW<[WriteMicrocoded], (instregex "RDRAND(16|32|64)r")>; - -// XGETBV. -def : InstRW<[WriteMicrocoded], (instregex "XGETBV")>; - -//-- String instructions --// -// CMPS. -def : InstRW<[WriteMicrocoded], (instregex "CMPS(B|L|Q|W)")>; - -// LODSB/W. -def : InstRW<[WriteMicrocoded], (instregex "LODS(B|W)")>; - -// LODSD/Q. -def : InstRW<[WriteMicrocoded], (instregex "LODS(L|Q)")>; - -// MOVS. -def : InstRW<[WriteMicrocoded], (instregex "MOVS(B|L|Q|W)")>; - -// SCAS. -def : InstRW<[WriteMicrocoded], (instregex "SCAS(B|W|L|Q)")>; - -// STOS -def : InstRW<[WriteMicrocoded], (instregex "STOS(B|L|Q|W)")>; - -// XADD. -def : InstRW<[WriteMicrocoded], (instregex "XADD(8|16|32|64)rm")>; - -//=== Floating Point x87 Instructions ===// -//-- Move instructions --// - -def ZnWriteFLDr : SchedWriteRes<[ZnFPU13]> ; - -def ZnWriteSTr: SchedWriteRes<[ZnFPU23]> { - let Latency = 5; - let NumMicroOps = 2; -} - -// LD_F. -// r. -def : InstRW<[ZnWriteFLDr], (instregex "LD_Frr")>; - -// m. -def ZnWriteLD_F80m : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteLD_F80m], (instregex "LD_F80m")>; - -// FBLD. -def : InstRW<[WriteMicrocoded], (instregex "FBLDm")>; - -// FST(P). -// r. -def : InstRW<[ZnWriteSTr], (instregex "ST_(F|FP)rr")>; - -// m80. -def ZnWriteST_FP80m : SchedWriteRes<[ZnAGU, ZnFPU23]> { - let Latency = 5; -} -def : InstRW<[ZnWriteST_FP80m], (instregex "ST_FP80m")>; - -// FBSTP. -// m80. -def : InstRW<[WriteMicrocoded], (instregex "FBSTPm")>; - -def ZnWriteFXCH : SchedWriteRes<[ZnFPU]>; - -// FXCHG. -def : InstRW<[ZnWriteFXCH], (instrs XCH_F)>; - -// FILD. -def ZnWriteFILD : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteFILD], (instregex "ILD_F(16|32|64)m")>; - -// FIST(P) FISTTP. -def ZnWriteFIST : SchedWriteRes<[ZnAGU, ZnFPU23]> { - let Latency = 12; -} -def : InstRW<[ZnWriteFIST], (instregex "IS(T|TT)_(F|FP)(16|32|64)m")>; - -def ZnWriteFPU13 : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let Latency = 8; -} - -def ZnWriteFPU3 : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; -} - -// FLDZ. -def : SchedAlias; - -// FLD1. -def : SchedAlias; - -// FLDPI FLDL2E etc. -def : SchedAlias; - -// FNSTSW. -// AX. -def : InstRW<[WriteMicrocoded], (instrs FNSTSW16r)>; - -// m16. -def : InstRW<[WriteMicrocoded], (instrs FNSTSWm)>; - -// FLDCW. -def : InstRW<[WriteMicrocoded], (instrs FLDCW16m)>; - -// FNSTCW. -def : InstRW<[WriteMicrocoded], (instrs FNSTCW16m)>; - -// FINCSTP FDECSTP. -def : InstRW<[ZnWriteFPU3], (instrs FINCSTP, FDECSTP)>; - -// FFREE. -def : InstRW<[ZnWriteFPU3], (instregex "FFREE")>; - -// FNSAVE. -def : InstRW<[WriteMicrocoded], (instregex "FSAVEm")>; - -// FRSTOR. -def : InstRW<[WriteMicrocoded], (instregex "FRSTORm")>; - -//-- Arithmetic instructions --// - -def ZnWriteFPU3Lat1 : SchedWriteRes<[ZnFPU3]> ; - -def ZnWriteFPU0Lat1 : SchedWriteRes<[ZnFPU0]> ; - -def ZnWriteFPU0Lat1Ld : SchedWriteRes<[ZnAGU, ZnFPU0]> { - let Latency = 8; -} - -// FCHS. -def : InstRW<[ZnWriteFPU3Lat1], (instregex "CHS_F")>; - -// FCOM(P) FUCOM(P). -// r. -def : InstRW<[ZnWriteFPU0Lat1], (instregex "COM(P?)_FST0r", "UCOM_F(P?)r")>; -// m. -def : InstRW<[ZnWriteFPU0Lat1Ld], (instregex "FCOM(P?)(32|64)m")>; - -// FCOMPP FUCOMPP. -// r. -def : InstRW<[ZnWriteFPU0Lat1], (instrs FCOMPP, UCOM_FPPr)>; - -def ZnWriteFPU02 : SchedWriteRes<[ZnAGU, ZnFPU02]> -{ - let Latency = 9; -} - -// FCOMI(P) FUCOMI(P). -// m. -def : InstRW<[ZnWriteFPU02], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -def ZnWriteFPU03 : SchedWriteRes<[ZnAGU, ZnFPU03]> -{ - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,3]; -} - -// FICOM(P). -def : InstRW<[ZnWriteFPU03], (instregex "FICOM(P?)(16|32)m")>; - -// FTST. -def : InstRW<[ZnWriteFPU0Lat1], (instregex "TST_F")>; - -// FXAM. -def : InstRW<[ZnWriteFPU3Lat1], (instrs FXAM)>; - -// FPREM. -def : InstRW<[WriteMicrocoded], (instrs FPREM)>; - -// FPREM1. -def : InstRW<[WriteMicrocoded], (instrs FPREM1)>; - -// FRNDINT. -def : InstRW<[WriteMicrocoded], (instrs FRNDINT)>; - -// FSCALE. -def : InstRW<[WriteMicrocoded], (instrs FSCALE)>; - -// FXTRACT. -def : InstRW<[WriteMicrocoded], (instrs FXTRACT)>; - -// FNOP. -def : InstRW<[ZnWriteFPU0Lat1], (instrs FNOP)>; - -// WAIT. -def : InstRW<[ZnWriteFPU0Lat1], (instrs WAIT)>; - -// FNCLEX. -def : InstRW<[WriteMicrocoded], (instrs FNCLEX)>; - -// FNINIT. -def : InstRW<[WriteMicrocoded], (instrs FNINIT)>; - -//=== Integer MMX and XMM Instructions ===// - -// PACKSSWB/DW. -// mm <- mm. -def ZnWriteFPU12 : SchedWriteRes<[ZnFPU12]> ; -def ZnWriteFPU12Y : SchedWriteRes<[ZnFPU12]> { - let NumMicroOps = 2; -} -def ZnWriteFPU12m : SchedWriteRes<[ZnAGU, ZnFPU12]> ; -def ZnWriteFPU12Ym : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; - let NumMicroOps = 2; -} - -def : InstRW<[ZnWriteFPU12], (instrs MMX_PACKSSDWirr, - MMX_PACKSSWBirr, - MMX_PACKUSWBirr)>; -def : InstRW<[ZnWriteFPU12m], (instrs MMX_PACKSSDWirm, - MMX_PACKSSWBirm, - MMX_PACKUSWBirm)>; - -// VPMOVSX/ZX BW BD BQ WD WQ DQ. -// y <- x. -def : InstRW<[ZnWriteFPU12Y], (instregex "VPMOV(SX|ZX)(BW|BD|BQ|WD|WQ|DQ)Yrr")>; -def : InstRW<[ZnWriteFPU12Ym], (instregex "VPMOV(SX|ZX)(BW|BD|BQ|WD|WQ|DQ)Yrm")>; - -def ZnWriteFPU013 : SchedWriteRes<[ZnFPU013]> ; -def ZnWriteFPU013Y : SchedWriteRes<[ZnFPU013]> { - let Latency = 2; -} -def ZnWriteFPU013m : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 8; - let NumMicroOps = 2; -} -def ZnWriteFPU013Ld : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 8; - let NumMicroOps = 2; -} -def ZnWriteFPU013LdY : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 9; - let NumMicroOps = 2; -} - -// PBLENDW. -// x,x,i / v,v,v,i -def : InstRW<[ZnWriteFPU013], (instregex "(V?)PBLENDWrri")>; -// ymm -def : InstRW<[ZnWriteFPU013Y], (instrs VPBLENDWYrri)>; - -// x,m,i / v,v,m,i -def : InstRW<[ZnWriteFPU013Ld], (instregex "(V?)PBLENDWrmi")>; -// y,m,i -def : InstRW<[ZnWriteFPU013LdY], (instrs VPBLENDWYrmi)>; - -def ZnWriteFPU01 : SchedWriteRes<[ZnFPU01]> ; -def ZnWriteFPU01Y : SchedWriteRes<[ZnFPU01]> { - let NumMicroOps = 2; -} - -// VPBLENDD. -// v,v,v,i. -def : InstRW<[ZnWriteFPU01], (instrs VPBLENDDrri)>; -// ymm -def : InstRW<[ZnWriteFPU01Y], (instrs VPBLENDDYrri)>; - -// v,v,m,i -def ZnWriteFPU01Op2 : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let NumMicroOps = 2; - let Latency = 8; - let ResourceCycles = [1, 2]; -} -def ZnWriteFPU01Op2Y : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let NumMicroOps = 2; - let Latency = 9; - let ResourceCycles = [1, 3]; -} -def : InstRW<[ZnWriteFPU01Op2], (instrs VPBLENDDrmi)>; -def : InstRW<[ZnWriteFPU01Op2Y], (instrs VPBLENDDYrmi)>; - -// MASKMOVQ. -def : InstRW<[WriteMicrocoded], (instregex "MMX_MASKMOVQ(64)?")>; - -// MASKMOVDQU. -def : InstRW<[WriteMicrocoded], (instregex "(V?)MASKMOVDQU(64)?")>; - -// VPMASKMOVD. -// ymm -def : InstRW<[WriteMicrocoded], - (instregex "VPMASKMOVD(Y?)rm")>; -// m, v,v. -def : InstRW<[WriteMicrocoded], (instregex "VPMASKMOV(D|Q)(Y?)mr")>; - -// VPBROADCAST B/W. -// x, m8/16. -def ZnWriteVPBROADCAST128Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteVPBROADCAST128Ld], - (instregex "VPBROADCAST(B|W)rm")>; - -// y, m8/16 -def ZnWriteVPBROADCAST256Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteVPBROADCAST256Ld], - (instregex "VPBROADCAST(B|W)Yrm")>; - -// VPGATHER. -def : InstRW<[WriteMicrocoded], (instregex "VPGATHER(Q|D)(Q|D)(Y?)rm")>; - -//-- Arithmetic instructions --// - -// HADD, HSUB PS/PD -// PHADD|PHSUB (S) W/D. -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -// PCMPGTQ. -def ZnWritePCMPGTQr : SchedWriteRes<[ZnFPU03]>; -def : InstRW<[ZnWritePCMPGTQr], (instregex "(V?)PCMPGTQ(Y?)rr")>; - -// x <- x,m. -def ZnWritePCMPGTQm : SchedWriteRes<[ZnAGU, ZnFPU03]> { - let Latency = 8; -} -// ymm. -def ZnWritePCMPGTQYm : SchedWriteRes<[ZnAGU, ZnFPU03]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; -} -def : InstRW<[ZnWritePCMPGTQm], (instregex "(V?)PCMPGTQrm")>; -def : InstRW<[ZnWritePCMPGTQYm], (instrs VPCMPGTQYrm)>; - -//-- Logic instructions --// - -// PSLL,PSRL,PSRA W/D/Q. -// x,x / v,v,x. -def ZnWritePShift : SchedWriteRes<[ZnFPU2]> ; -def ZnWritePShiftY : SchedWriteRes<[ZnFPU2]> { - let Latency = 2; -} - -// PSLL,PSRL DQ. -def : InstRW<[ZnWritePShift], (instregex "(V?)PS(R|L)LDQri")>; -def : InstRW<[ZnWritePShiftY], (instregex "(V?)PS(R|L)LDQYri")>; - -//=== Floating Point XMM and YMM Instructions ===// -//-- Move instructions --// - -// VPERM2F128. -def : InstRW<[WriteMicrocoded], (instrs VPERM2F128rr)>; -def : InstRW<[WriteMicrocoded], (instrs VPERM2F128rm)>; - -def ZnWriteBROADCAST : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let NumMicroOps = 2; - let Latency = 8; -} -// VBROADCASTF128. -def : InstRW<[ZnWriteBROADCAST], (instrs VBROADCASTF128)>; - -// EXTRACTPS. -// r32,x,i. -def ZnWriteEXTRACTPSr : SchedWriteRes<[ZnFPU12, ZnFPU2]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteEXTRACTPSr], (instregex "(V?)EXTRACTPSrr")>; - -def ZnWriteEXTRACTPSm : SchedWriteRes<[ZnAGU,ZnFPU12, ZnFPU2]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [5, 1, 2]; -} -// m32,x,i. -def : InstRW<[ZnWriteEXTRACTPSm], (instregex "(V?)EXTRACTPSmr")>; - -// VEXTRACTF128. -// x,y,i. -def : InstRW<[ZnWriteFPU013], (instrs VEXTRACTF128rr)>; - -// m128,y,i. -def : InstRW<[ZnWriteFPU013m], (instrs VEXTRACTF128mr)>; - -def ZnWriteVINSERT128r: SchedWriteRes<[ZnFPU013]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def ZnWriteVINSERT128Ld: SchedWriteRes<[ZnAGU,ZnFPU013]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -// VINSERTF128. -// y,y,x,i. -def : InstRW<[ZnWriteVINSERT128r], (instrs VINSERTF128rr)>; -def : InstRW<[ZnWriteVINSERT128Ld], (instrs VINSERTF128rm)>; - -// VGATHER. -def : InstRW<[WriteMicrocoded], (instregex "VGATHER(Q|D)(PD|PS)(Y?)rm")>; - -//-- Conversion instructions --// -def ZnWriteCVTPD2PSr: SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -def ZnWriteCVTPD2PSYr: SchedWriteRes<[ZnFPU3]> { - let Latency = 5; -} - -// CVTPD2PS. -// x,x. -def : SchedAlias; -// y,y. -def : SchedAlias; -// z,z. -defm : X86WriteResUnsupported; - -def ZnWriteCVTPD2PSLd: SchedWriteRes<[ZnAGU,ZnFPU03]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; -} -// x,m128. -def : SchedAlias; - -// x,m256. -def ZnWriteCVTPD2PSYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; -} -def : SchedAlias; -// z,m512 -defm : X86WriteResUnsupported; - -// CVTSD2SS. -// x,x. -// Same as WriteCVTPD2PSr -def : SchedAlias; - -// x,m64. -def : SchedAlias; - -// CVTPS2PD. -// x,x. -def ZnWriteCVTPS2PDr : SchedWriteRes<[ZnFPU3]> { - let Latency = 3; -} -def : SchedAlias; - -// x,m64. -// y,m128. -def ZnWriteCVTPS2PDLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 10; - let NumMicroOps = 2; -} -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -// y,x. -def ZnWriteVCVTPS2PDY : SchedWriteRes<[ZnFPU3]> { - let Latency = 3; -} -def : SchedAlias; -defm : X86WriteResUnsupported; - -// CVTSS2SD. -// x,x. -def ZnWriteCVTSS2SDr : SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -def : SchedAlias; - -// x,m32. -def ZnWriteCVTSS2SDLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : SchedAlias; - -def ZnWriteCVTDQ2PDr: SchedWriteRes<[ZnFPU12,ZnFPU3]> { - let Latency = 5; -} -// CVTDQ2PD. -// x,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instregex "(V)?CVTDQ2PDrr")>; - -// Same as xmm -// y,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instrs VCVTDQ2PDYrr)>; - -def ZnWriteCVTPD2DQr: SchedWriteRes<[ZnFPU12, ZnFPU3]> { - let Latency = 5; -} -// CVT(T)PD2DQ. -// x,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instregex "(V?)CVT(T?)PD2DQrr")>; - -def ZnWriteCVTPD2DQLd: SchedWriteRes<[ZnAGU,ZnFPU12,ZnFPU3]> { - let Latency = 12; - let NumMicroOps = 2; -} -// x,m128. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "(V?)CVT(T?)PD2DQrm")>; -// same as xmm handling -// x,y. -def : InstRW<[ZnWriteCVTPD2DQr], (instregex "VCVT(T?)PD2DQYrr")>; -// x,m256. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "VCVT(T?)PD2DQYrm")>; - -def ZnWriteCVTPS2PIr: SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -// CVT(T)PS2PI. -// mm,x. -def : InstRW<[ZnWriteCVTPS2PIr], (instregex "MMX_CVT(T?)PS2PIirr")>; - -// CVTPI2PD. -// x,mm. -def : InstRW<[ZnWriteCVTPS2PDr], (instrs MMX_CVTPI2PDirr)>; - -// CVT(T)PD2PI. -// mm,x. -def : InstRW<[ZnWriteCVTPS2PIr], (instregex "MMX_CVT(T?)PD2PIirr")>; - -def ZnWriteCVSTSI2SSr: SchedWriteRes<[ZnFPU3]> { - let Latency = 5; -} - -// same as CVTPD2DQr -// CVT(T)SS2SI. -// r32,x. -def : InstRW<[ZnWriteCVTPD2DQr], (instregex "(V?)CVT(T?)SS2SI(64)?rr")>; -// same as CVTPD2DQm -// r32,m32. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "(V?)CVT(T?)SS2SI(64)?rm")>; - -def ZnWriteCVSTSI2SDr: SchedWriteRes<[ZnFPU013, ZnFPU3]> { - let Latency = 5; -} -// CVTSI2SD. -// x,r32/64. -def : InstRW<[ZnWriteCVSTSI2SDr], (instregex "(V?)CVTSI(64)?2SDrr")>; - - -def ZnWriteCVSTSI2SIr: SchedWriteRes<[ZnFPU3, ZnFPU2]> { - let Latency = 5; -} -def ZnWriteCVSTSI2SILd: SchedWriteRes<[ZnAGU, ZnFPU3, ZnFPU2]> { - let Latency = 12; -} -// CVTSD2SI. -// r32/64 -def : InstRW<[ZnWriteCVSTSI2SIr], (instregex "(V?)CVT(T?)SD2SI(64)?rr")>; -// r32,m32. -def : InstRW<[ZnWriteCVSTSI2SILd], (instregex "(V?)CVT(T?)SD2SI(64)?rm")>; - -// VCVTPS2PH. -// x,v,i. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; -// m,v,i. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -// VCVTPH2PS. -// v,x. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; -// v,m. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -//-- SSE4A instructions --// -// EXTRQ -def ZnWriteEXTRQ: SchedWriteRes<[ZnFPU12, ZnFPU2]> { - let Latency = 2; -} -def : InstRW<[ZnWriteEXTRQ], (instregex "EXTRQ")>; - -// INSERTQ -def ZnWriteINSERTQ: SchedWriteRes<[ZnFPU03,ZnFPU1]> { - let Latency = 4; -} -def : InstRW<[ZnWriteINSERTQ], (instregex "INSERTQ")>; - -//-- SHA instructions --// -// SHA256MSG2 -def : InstRW<[WriteMicrocoded], (instregex "SHA256MSG2(Y?)r(r|m)")>; - -// SHA1MSG1, SHA256MSG1 -// x,x. -def ZnWriteSHA1MSG1r : SchedWriteRes<[ZnFPU12]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def : InstRW<[ZnWriteSHA1MSG1r], (instregex "SHA(1|256)MSG1rr")>; -// x,m. -def ZnWriteSHA1MSG1Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 9; - let ResourceCycles = [1,2]; -} -def : InstRW<[ZnWriteSHA1MSG1Ld], (instregex "SHA(1|256)MSG1rm")>; - -// SHA1MSG2 -// x,x. -def ZnWriteSHA1MSG2r : SchedWriteRes<[ZnFPU12]> ; -def : InstRW<[ZnWriteSHA1MSG2r], (instregex "SHA1MSG2rr")>; -// x,m. -def ZnWriteSHA1MSG2Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; -} -def : InstRW<[ZnWriteSHA1MSG2Ld], (instregex "SHA1MSG2rm")>; - -// SHA1NEXTE -// x,x. -def ZnWriteSHA1NEXTEr : SchedWriteRes<[ZnFPU1]> ; -def : InstRW<[ZnWriteSHA1NEXTEr], (instregex "SHA1NEXTErr")>; -// x,m. -def ZnWriteSHA1NEXTELd : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 8; -} -def : InstRW<[ZnWriteSHA1NEXTELd], (instregex "SHA1NEXTErm")>; - -// SHA1RNDS4 -// x,x. -def ZnWriteSHA1RNDS4r : SchedWriteRes<[ZnFPU1]> { - let Latency = 6; -} -def : InstRW<[ZnWriteSHA1RNDS4r], (instregex "SHA1RNDS4rr")>; -// x,m. -def ZnWriteSHA1RNDS4Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 13; -} -def : InstRW<[ZnWriteSHA1RNDS4Ld], (instregex "SHA1RNDS4rm")>; - -// SHA256RNDS2 -// x,x. -def ZnWriteSHA256RNDS2r : SchedWriteRes<[ZnFPU1]> { - let Latency = 4; -} -def : InstRW<[ZnWriteSHA256RNDS2r], (instregex "SHA256RNDS2rr")>; -// x,m. -def ZnWriteSHA256RNDS2Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 11; -} -def : InstRW<[ZnWriteSHA256RNDS2Ld], (instregex "SHA256RNDS2rm")>; - -//-- Arithmetic instructions --// - -// HADD, HSUB PS/PD -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -// VDIVPS. -// TODO - convert to ZnWriteResFpuPair -// y,y,y. -def ZnWriteVDIVPSYr : SchedWriteRes<[ZnFPU3]> { - let Latency = 12; - let ResourceCycles = [12]; -} -def : SchedAlias; - -// y,y,m256. -def ZnWriteVDIVPSYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1, 19]; -} -def : SchedAlias; - -// VDIVPD. -// TODO - convert to ZnWriteResFpuPair -// y,y,y. -def ZnWriteVDIVPDY : SchedWriteRes<[ZnFPU3]> { - let Latency = 15; - let ResourceCycles = [15]; -} -def : SchedAlias; - -// y,y,m256. -def ZnWriteVDIVPDYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,22]; -} -def : SchedAlias; - -// DPPS. -// x,x,i / v,v,v,i. -def : SchedAlias; -def : SchedAlias; - -// x,m,i / v,v,m,i. -def : SchedAlias; -def : SchedAlias; - -// DPPD. -// x,x,i. -def : SchedAlias; - -// x,m,i. -def : SchedAlias; - -// RSQRTSS -// TODO - convert to ZnWriteResFpuPair -// x,x. -def ZnWriteRSQRTSSr : SchedWriteRes<[ZnFPU02]> { - let Latency = 5; -} -def : SchedAlias; - -// x,m128. -def ZnWriteRSQRTSSLd: SchedWriteRes<[ZnAGU, ZnFPU02]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; // FIXME: Is this right? -} -def : SchedAlias; - -// RSQRTPS -// TODO - convert to ZnWriteResFpuPair -// y,y. -def ZnWriteRSQRTPSYr : SchedWriteRes<[ZnFPU01]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : SchedAlias; - -// y,m256. -def ZnWriteRSQRTPSYLd : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let Latency = 12; - let NumMicroOps = 2; -} -def : SchedAlias; - -//-- Other instructions --// - -// VZEROUPPER. -def : InstRW<[WriteMicrocoded], (instrs VZEROUPPER)>; - -// VZEROALL. -def : InstRW<[WriteMicrocoded], (instrs VZEROALL)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/X86_reduce.td b/suite/synctools/tablegen/X86/X86_reduce.td deleted file mode 100644 index cf2ce68908..0000000000 --- a/suite/synctools/tablegen/X86/X86_reduce.td +++ /dev/null @@ -1,459 +0,0 @@ -//===-- X86.td - Target definition file for the Intel X86 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a target description file for the Intel i386 architecture, referred -// to here as the "X86" architecture. -// -//===----------------------------------------------------------------------===// - -// Get the target-independent interfaces which we are implementing... -// -include "llvm/Target/Target.td" - -//===----------------------------------------------------------------------===// -// X86 Subtarget state -// - -def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", - "64-bit mode (x86_64)">; -def Mode32Bit : SubtargetFeature<"32bit-mode", "In32BitMode", "true", - "32-bit mode (80386)">; -def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true", - "16-bit mode (i8086)">; - -//===----------------------------------------------------------------------===// -// X86 Subtarget features -//===----------------------------------------------------------------------===// - -def FeatureX87 : SubtargetFeature<"x87","HasX87", "true", - "Enable X87 float instructions">; - -def FeatureNOPL : SubtargetFeature<"nopl", "HasNOPL", "true", - "Enable NOPL instruction">; - -def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", - "Enable conditional move instructions">; - -def FeaturePOPCNT : SubtargetFeature<"popcnt", "HasPOPCNT", "true", - "Support POPCNT instruction">; - -def FeatureFXSR : SubtargetFeature<"fxsr", "HasFXSR", "true", - "Support fxsave/fxrestore instructions">; - -def FeatureXSAVE : SubtargetFeature<"xsave", "HasXSAVE", "true", - "Support xsave instructions">; - -def FeatureXSAVEOPT: SubtargetFeature<"xsaveopt", "HasXSAVEOPT", "true", - "Support xsaveopt instructions">; - -def FeatureXSAVEC : SubtargetFeature<"xsavec", "HasXSAVEC", "true", - "Support xsavec instructions">; - -def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true", - "Support xsaves instructions">; - -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions", - // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. - [FeatureCMOV]>; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions", - [FeatureSSE1]>; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions", - [FeatureSSE2]>; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions", - [FeatureSSE3]>; -def FeatureSSE41 : SubtargetFeature<"sse4.1", "X86SSELevel", "SSE41", - "Enable SSE 4.1 instructions", - [FeatureSSSE3]>; -def FeatureSSE42 : SubtargetFeature<"sse4.2", "X86SSELevel", "SSE42", - "Enable SSE 4.2 instructions", - [FeatureSSE41]>; -// The MMX subtarget feature is separate from the rest of the SSE features -// because it's important (for odd compatibility reasons) to be able to -// turn it off explicitly while allowing SSE+ to be on. -def FeatureMMX : SubtargetFeature<"mmx","X863DNowLevel", "MMX", - "Enable MMX instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions", - [FeatureMMX]>; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions", - [Feature3DNow]>; -// All x86-64 hardware has SSE2, but we don't mark SSE2 as an implied -// feature, because SSE2 can be disabled (e.g. for compiling OS kernels) -// without disabling 64-bit mode. -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions", - [FeatureCMOV]>; -def FeatureCMPXCHG16B : SubtargetFeature<"cx16", "HasCmpxchg16b", "true", - "64-bit with cmpxchg16b", - [Feature64Bit]>; -def FeatureSlowSHLD : SubtargetFeature<"slow-shld", "IsSHLDSlow", "true", - "SHLD instruction is slow">; -def FeatureSlowPMULLD : SubtargetFeature<"slow-pmulld", "IsPMULLDSlow", "true", - "PMULLD instruction is slow">; -// FIXME: This should not apply to CPUs that do not have SSE. -def FeatureSlowUAMem16 : SubtargetFeature<"slow-unaligned-mem-16", - "IsUAMem16Slow", "true", - "Slow unaligned 16-byte memory access">; -def FeatureSlowUAMem32 : SubtargetFeature<"slow-unaligned-mem-32", - "IsUAMem32Slow", "true", - "Slow unaligned 32-byte memory access">; -def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true", - "Support SSE 4a instructions", - [FeatureSSE3]>; - -def FeatureAVX : SubtargetFeature<"avx", "X86SSELevel", "AVX", - "Enable AVX instructions", - [FeatureSSE42]>; -def FeatureAVX2 : SubtargetFeature<"avx2", "X86SSELevel", "AVX2", - "Enable AVX2 instructions", - [FeatureAVX]>; -def FeatureFMA : SubtargetFeature<"fma", "HasFMA", "true", - "Enable three-operand fused multiple-add", - [FeatureAVX]>; -def FeatureF16C : SubtargetFeature<"f16c", "HasF16C", "true", - "Support 16-bit floating point conversion instructions", - [FeatureAVX]>; -def FeatureAVX512 : SubtargetFeature<"avx512f", "X86SSELevel", "AVX512F", - "Enable AVX-512 instructions", - [FeatureAVX2, FeatureFMA, FeatureF16C]>; -def FeatureERI : SubtargetFeature<"avx512er", "HasERI", "true", - "Enable AVX-512 Exponential and Reciprocal Instructions", - [FeatureAVX512]>; -def FeatureCDI : SubtargetFeature<"avx512cd", "HasCDI", "true", - "Enable AVX-512 Conflict Detection Instructions", - [FeatureAVX512]>; -def FeatureVPOPCNTDQ : SubtargetFeature<"avx512vpopcntdq", "HasVPOPCNTDQ", - "true", "Enable AVX-512 Population Count Instructions", - [FeatureAVX512]>; -def FeaturePFI : SubtargetFeature<"avx512pf", "HasPFI", "true", - "Enable AVX-512 PreFetch Instructions", - [FeatureAVX512]>; -def FeaturePREFETCHWT1 : SubtargetFeature<"prefetchwt1", "HasPREFETCHWT1", - "true", - "Prefetch with Intent to Write and T1 Hint">; -def FeatureDQI : SubtargetFeature<"avx512dq", "HasDQI", "true", - "Enable AVX-512 Doubleword and Quadword Instructions", - [FeatureAVX512]>; -def FeatureBWI : SubtargetFeature<"avx512bw", "HasBWI", "true", - "Enable AVX-512 Byte and Word Instructions", - [FeatureAVX512]>; -def FeatureVLX : SubtargetFeature<"avx512vl", "HasVLX", "true", - "Enable AVX-512 Vector Length eXtensions", - [FeatureAVX512]>; -def FeatureVBMI : SubtargetFeature<"avx512vbmi", "HasVBMI", "true", - "Enable AVX-512 Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureVBMI2 : SubtargetFeature<"avx512vbmi2", "HasVBMI2", "true", - "Enable AVX-512 further Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureIFMA : SubtargetFeature<"avx512ifma", "HasIFMA", "true", - "Enable AVX-512 Integer Fused Multiple-Add", - [FeatureAVX512]>; -def FeaturePKU : SubtargetFeature<"pku", "HasPKU", "true", - "Enable protection keys">; -def FeatureVNNI : SubtargetFeature<"avx512vnni", "HasVNNI", "true", - "Enable AVX-512 Vector Neural Network Instructions", - [FeatureAVX512]>; -def FeatureBITALG : SubtargetFeature<"avx512bitalg", "HasBITALG", "true", - "Enable AVX-512 Bit Algorithms", - [FeatureBWI]>; -def FeaturePCLMUL : SubtargetFeature<"pclmul", "HasPCLMUL", "true", - "Enable packed carry-less multiplication instructions", - [FeatureSSE2]>; -def FeatureGFNI : SubtargetFeature<"gfni", "HasGFNI", "true", - "Enable Galois Field Arithmetic Instructions", - [FeatureSSE2]>; -def FeatureVPCLMULQDQ : SubtargetFeature<"vpclmulqdq", "HasVPCLMULQDQ", "true", - "Enable vpclmulqdq instructions", - [FeatureAVX, FeaturePCLMUL]>; -def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", - "Enable four-operand fused multiple-add", - [FeatureAVX, FeatureSSE4A]>; -def FeatureXOP : SubtargetFeature<"xop", "HasXOP", "true", - "Enable XOP instructions", - [FeatureFMA4]>; -def FeatureSSEUnalignedMem : SubtargetFeature<"sse-unaligned-mem", - "HasSSEUnalignedMem", "true", - "Allow unaligned memory operands with SSE instructions">; -def FeatureAES : SubtargetFeature<"aes", "HasAES", "true", - "Enable AES instructions", - [FeatureSSE2]>; -def FeatureVAES : SubtargetFeature<"vaes", "HasVAES", "true", - "Promote selected AES instructions to AVX512/AVX registers", - [FeatureAVX, FeatureAES]>; -def FeatureTBM : SubtargetFeature<"tbm", "HasTBM", "true", - "Enable TBM instructions">; -def FeatureLWP : SubtargetFeature<"lwp", "HasLWP", "true", - "Enable LWP instructions">; -def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true", - "Support MOVBE instruction">; -def FeatureRDRAND : SubtargetFeature<"rdrnd", "HasRDRAND", "true", - "Support RDRAND instruction">; -def FeatureFSGSBase : SubtargetFeature<"fsgsbase", "HasFSGSBase", "true", - "Support FS/GS Base instructions">; -def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true", - "Support LZCNT instruction">; -def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true", - "Support BMI instructions">; -def FeatureBMI2 : SubtargetFeature<"bmi2", "HasBMI2", "true", - "Support BMI2 instructions">; -def FeatureRTM : SubtargetFeature<"rtm", "HasRTM", "true", - "Support RTM instructions">; -def FeatureADX : SubtargetFeature<"adx", "HasADX", "true", - "Support ADX instructions">; -def FeatureSHA : SubtargetFeature<"sha", "HasSHA", "true", - "Enable SHA instructions", - [FeatureSSE2]>; -def FeatureSHSTK : SubtargetFeature<"shstk", "HasSHSTK", "true", - "Support CET Shadow-Stack instructions">; -def FeaturePRFCHW : SubtargetFeature<"prfchw", "HasPRFCHW", "true", - "Support PRFCHW instructions">; -def FeatureRDSEED : SubtargetFeature<"rdseed", "HasRDSEED", "true", - "Support RDSEED instruction">; -def FeatureLAHFSAHF : SubtargetFeature<"sahf", "HasLAHFSAHF", "true", - "Support LAHF and SAHF instructions">; -def FeatureMWAITX : SubtargetFeature<"mwaitx", "HasMWAITX", "true", - "Enable MONITORX/MWAITX timer functionality">; -def FeatureCLZERO : SubtargetFeature<"clzero", "HasCLZERO", "true", - "Enable Cache Line Zero">; -def FeatureCLDEMOTE : SubtargetFeature<"cldemote", "HasCLDEMOTE", "true", - "Enable Cache Demote">; -def FeaturePTWRITE : SubtargetFeature<"ptwrite", "HasPTWRITE", "true", - "Support ptwrite instruction">; -def FeatureMPX : SubtargetFeature<"mpx", "HasMPX", "true", - "Support MPX instructions">; -def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true", - "Use LEA for adjusting the stack pointer">; -def FeatureSlowDivide32 : SubtargetFeature<"idivl-to-divb", - "HasSlowDivide32", "true", - "Use 8-bit divide for positive values less than 256">; -def FeatureSlowDivide64 : SubtargetFeature<"idivq-to-divl", - "HasSlowDivide64", "true", - "Use 32-bit divide for positive values less than 2^32">; -def FeaturePadShortFunctions : SubtargetFeature<"pad-short-functions", - "PadShortFunctions", "true", - "Pad short functions">; -def FeatureINVPCID : SubtargetFeature<"invpcid", "HasINVPCID", "true", - "Invalidate Process-Context Identifier">; -def FeatureSGX : SubtargetFeature<"sgx", "HasSGX", "true", - "Enable Software Guard Extensions">; -def FeatureCLFLUSHOPT : SubtargetFeature<"clflushopt", "HasCLFLUSHOPT", "true", - "Flush A Cache Line Optimized">; -def FeatureCLWB : SubtargetFeature<"clwb", "HasCLWB", "true", - "Cache Line Write Back">; -def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", - "Write Back No Invalidate">; -def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", - "Support RDPID instructions">; -def FeatureWAITPKG : SubtargetFeature<"waitpkg", "HasWAITPKG", "true", - "Wait and pause enhancements">; -// On some processors, instructions that implicitly take two memory operands are -// slow. In practice, this means that CALL, PUSH, and POP with memory operands -// should be avoided in favor of a MOV + register CALL/PUSH/POP. -def FeatureSlowTwoMemOps : SubtargetFeature<"slow-two-mem-ops", - "SlowTwoMemOps", "true", - "Two memory operand instructions are slow">; -def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true", - "LEA instruction needs inputs at AG stage">; -def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true", - "LEA instruction with certain arguments is slow">; -def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true", - "LEA instruction with 3 ops or certain registers is slow">; -def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true", - "INC and DEC instructions are slower than ADD and SUB">; -def FeatureSoftFloat - : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software floating point features.">; -def FeaturePOPCNTFalseDeps : SubtargetFeature<"false-deps-popcnt", - "HasPOPCNTFalseDeps", "true", - "POPCNT has a false dependency on dest register">; -def FeatureLZCNTFalseDeps : SubtargetFeature<"false-deps-lzcnt-tzcnt", - "HasLZCNTFalseDeps", "true", - "LZCNT/TZCNT have a false dependency on dest register">; -def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true", - "platform configuration instruction">; -// On recent X86 (port bound) processors, its preferable to combine to a single shuffle -// using a variable mask over multiple fixed shuffles. -def FeatureFastVariableShuffle - : SubtargetFeature<"fast-variable-shuffle", - "HasFastVariableShuffle", - "true", "Shuffles with variable masks are fast">; -// On some X86 processors, there is no performance hazard to writing only the -// lower parts of a YMM or ZMM register without clearing the upper part. -def FeatureFastPartialYMMorZMMWrite - : SubtargetFeature<"fast-partial-ymm-or-zmm-write", - "HasFastPartialYMMorZMMWrite", - "true", "Partial writes to YMM/ZMM registers are fast">; -// FeatureFastScalarFSQRT should be enabled if scalar FSQRT has shorter latency -// than the corresponding NR code. FeatureFastVectorFSQRT should be enabled if -// vector FSQRT has higher throughput than the corresponding NR code. -// The idea is that throughput bound code is likely to be vectorized, so for -// vectorized code we should care about the throughput of SQRT operations. -// But if the code is scalar that probably means that the code has some kind of -// dependency and we should care more about reducing the latency. -def FeatureFastScalarFSQRT - : SubtargetFeature<"fast-scalar-fsqrt", "HasFastScalarFSQRT", - "true", "Scalar SQRT is fast (disable Newton-Raphson)">; -def FeatureFastVectorFSQRT - : SubtargetFeature<"fast-vector-fsqrt", "HasFastVectorFSQRT", - "true", "Vector SQRT is fast (disable Newton-Raphson)">; -// If lzcnt has equivalent latency/throughput to most simple integer ops, it can -// be used to replace test/set sequences. -def FeatureFastLZCNT - : SubtargetFeature< - "fast-lzcnt", "HasFastLZCNT", "true", - "LZCNT instructions are as fast as most simple integer ops">; -// If the target can efficiently decode NOPs upto 11-bytes in length. -def FeatureFast11ByteNOP - : SubtargetFeature< - "fast-11bytenop", "HasFast11ByteNOP", "true", - "Target can quickly decode up to 11 byte NOPs">; -// If the target can efficiently decode NOPs upto 15-bytes in length. -def FeatureFast15ByteNOP - : SubtargetFeature< - "fast-15bytenop", "HasFast15ByteNOP", "true", - "Target can quickly decode up to 15 byte NOPs">; -// Sandy Bridge and newer processors can use SHLD with the same source on both -// inputs to implement rotate to avoid the partial flag update of the normal -// rotate instructions. -def FeatureFastSHLDRotate - : SubtargetFeature< - "fast-shld-rotate", "HasFastSHLDRotate", "true", - "SHLD can be used as a faster rotate">; - -// Ivy Bridge and newer processors have enhanced REP MOVSB and STOSB (aka -// "string operations"). See "REP String Enhancement" in the Intel Software -// Development Manual. This feature essentially means that REP MOVSB will copy -// using the largest available size instead of copying bytes one by one, making -// it at least as fast as REPMOVS{W,D,Q}. -def FeatureERMSB - : SubtargetFeature< - "ermsb", "HasERMSB", "true", - "REP MOVS/STOS are fast">; - -// Sandy Bridge and newer processors have many instructions that can be -// fused with conditional branches and pass through the CPU as a single -// operation. -def FeatureMacroFusion - : SubtargetFeature<"macrofusion", "HasMacroFusion", "true", - "Various instructions can be fused with conditional branches">; - -// Gather is available since Haswell (AVX2 set). So technically, we can -// generate Gathers on all AVX2 processors. But the overhead on HSW is high. -// Skylake Client processor has faster Gathers than HSW and performance is -// similar to Skylake Server (AVX-512). -def FeatureHasFastGather - : SubtargetFeature<"fast-gather", "HasFastGather", "true", - "Indicates if gather is reasonably fast.">; - -def FeaturePrefer256Bit - : SubtargetFeature<"prefer-256-bit", "Prefer256Bit", "true", - "Prefer 256-bit AVX instructions">; - -// Enable mitigation of some aspects of speculative execution related -// vulnerabilities by removing speculatable indirect branches. This disables -// jump-table formation, rewrites explicit `indirectbr` instructions into -// `switch` instructions, and uses a special construct called a "retpoline" to -// prevent speculation of the remaining indirect branches (indirect calls and -// tail calls). -def FeatureRetpoline - : SubtargetFeature<"retpoline", "UseRetpoline", "true", - "Remove speculation of indirect branches from the " - "generated code, either by avoiding them entirely or " - "lowering them with a speculation blocking construct.">; - -// Rely on external thunks for the emitted retpoline calls. This allows users -// to provide their own custom thunk definitions in highly specialized -// environments such as a kernel that does boot-time hot patching. -def FeatureRetpolineExternalThunk - : SubtargetFeature< - "retpoline-external-thunk", "UseRetpolineExternalThunk", "true", - "Enable retpoline, but with an externally provided thunk.", - [FeatureRetpoline]>; - -// Direct Move instructions. -def FeatureMOVDIRI : SubtargetFeature<"movdiri", "HasMOVDIRI", "true", - "Support movdiri instruction">; -def FeatureMOVDIR64B : SubtargetFeature<"movdir64b", "HasMOVDIR64B", "true", - "Support movdir64b instruction">; - -//===----------------------------------------------------------------------===// -// Register File Description -//===----------------------------------------------------------------------===// - -include "X86RegisterInfo.td" -include "X86RegisterBanks.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "X86Schedule.td" -include "X86InstrInfo_reduce.td" - -def X86InstrInfo : InstrInfo; - -//===----------------------------------------------------------------------===// -// Assembly Parser -//===----------------------------------------------------------------------===// - -def ATTAsmParserVariant : AsmParserVariant { - int Variant = 0; - - // Variant name. - string Name = "att"; - - // Discard comments in assembly strings. - string CommentDelimiter = "#"; - - // Recognize hard coded registers. - string RegisterPrefix = "%"; -} - -def IntelAsmParserVariant : AsmParserVariant { - int Variant = 1; - - // Variant name. - string Name = "intel"; - - // Discard comments in assembly strings. - string CommentDelimiter = ";"; - - // Recognize hard coded registers. - string RegisterPrefix = ""; -} - -//===----------------------------------------------------------------------===// -// Assembly Printers -//===----------------------------------------------------------------------===// - -// The X86 target supports two different syntaxes for emitting machine code. -// This is controlled by the -x86-asm-syntax={att|intel} -def ATTAsmWriter : AsmWriter { - string AsmWriterClassName = "ATTInstPrinter"; - int Variant = 0; -} -def IntelAsmWriter : AsmWriter { - string AsmWriterClassName = "IntelInstPrinter"; - int Variant = 1; -} - -def X86 : Target { - // Information about the instructions... - let InstructionSet = X86InstrInfo; - let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant]; - let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; - let AllowRegisterRenaming = 1; -} diff --git a/suite/synctools/tablegen/X86/back/X86.td b/suite/synctools/tablegen/X86/back/X86.td deleted file mode 100644 index 63c2dc4da6..0000000000 --- a/suite/synctools/tablegen/X86/back/X86.td +++ /dev/null @@ -1,1203 +0,0 @@ -//===-- X86.td - Target definition file for the Intel X86 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a target description file for the Intel i386 architecture, referred -// to here as the "X86" architecture. -// -//===----------------------------------------------------------------------===// - -// Get the target-independent interfaces which we are implementing... -// -include "llvm/Target/Target.td" - -//===----------------------------------------------------------------------===// -// X86 Subtarget state -// - -def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", - "64-bit mode (x86_64)">; -def Mode32Bit : SubtargetFeature<"32bit-mode", "In32BitMode", "true", - "32-bit mode (80386)">; -def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true", - "16-bit mode (i8086)">; - -//===----------------------------------------------------------------------===// -// X86 Subtarget features -//===----------------------------------------------------------------------===// - -def FeatureX87 : SubtargetFeature<"x87","HasX87", "true", - "Enable X87 float instructions">; - -def FeatureNOPL : SubtargetFeature<"nopl", "HasNOPL", "true", - "Enable NOPL instruction">; - -def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", - "Enable conditional move instructions">; - -def FeaturePOPCNT : SubtargetFeature<"popcnt", "HasPOPCNT", "true", - "Support POPCNT instruction">; - -def FeatureFXSR : SubtargetFeature<"fxsr", "HasFXSR", "true", - "Support fxsave/fxrestore instructions">; - -def FeatureXSAVE : SubtargetFeature<"xsave", "HasXSAVE", "true", - "Support xsave instructions">; - -def FeatureXSAVEOPT: SubtargetFeature<"xsaveopt", "HasXSAVEOPT", "true", - "Support xsaveopt instructions">; - -def FeatureXSAVEC : SubtargetFeature<"xsavec", "HasXSAVEC", "true", - "Support xsavec instructions">; - -def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true", - "Support xsaves instructions">; - -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions", - // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. - [FeatureCMOV]>; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions", - [FeatureSSE1]>; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions", - [FeatureSSE2]>; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions", - [FeatureSSE3]>; -def FeatureSSE41 : SubtargetFeature<"sse4.1", "X86SSELevel", "SSE41", - "Enable SSE 4.1 instructions", - [FeatureSSSE3]>; -def FeatureSSE42 : SubtargetFeature<"sse4.2", "X86SSELevel", "SSE42", - "Enable SSE 4.2 instructions", - [FeatureSSE41]>; -// The MMX subtarget feature is separate from the rest of the SSE features -// because it's important (for odd compatibility reasons) to be able to -// turn it off explicitly while allowing SSE+ to be on. -def FeatureMMX : SubtargetFeature<"mmx","X863DNowLevel", "MMX", - "Enable MMX instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions", - [FeatureMMX]>; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions", - [Feature3DNow]>; -// All x86-64 hardware has SSE2, but we don't mark SSE2 as an implied -// feature, because SSE2 can be disabled (e.g. for compiling OS kernels) -// without disabling 64-bit mode. -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions", - [FeatureCMOV]>; -def FeatureCMPXCHG16B : SubtargetFeature<"cx16", "HasCmpxchg16b", "true", - "64-bit with cmpxchg16b", - [Feature64Bit]>; -def FeatureSlowSHLD : SubtargetFeature<"slow-shld", "IsSHLDSlow", "true", - "SHLD instruction is slow">; -def FeatureSlowPMULLD : SubtargetFeature<"slow-pmulld", "IsPMULLDSlow", "true", - "PMULLD instruction is slow">; -// FIXME: This should not apply to CPUs that do not have SSE. -def FeatureSlowUAMem16 : SubtargetFeature<"slow-unaligned-mem-16", - "IsUAMem16Slow", "true", - "Slow unaligned 16-byte memory access">; -def FeatureSlowUAMem32 : SubtargetFeature<"slow-unaligned-mem-32", - "IsUAMem32Slow", "true", - "Slow unaligned 32-byte memory access">; -def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true", - "Support SSE 4a instructions", - [FeatureSSE3]>; - -def FeatureAVX : SubtargetFeature<"avx", "X86SSELevel", "AVX", - "Enable AVX instructions", - [FeatureSSE42]>; -def FeatureAVX2 : SubtargetFeature<"avx2", "X86SSELevel", "AVX2", - "Enable AVX2 instructions", - [FeatureAVX]>; -def FeatureFMA : SubtargetFeature<"fma", "HasFMA", "true", - "Enable three-operand fused multiple-add", - [FeatureAVX]>; -def FeatureF16C : SubtargetFeature<"f16c", "HasF16C", "true", - "Support 16-bit floating point conversion instructions", - [FeatureAVX]>; -def FeatureAVX512 : SubtargetFeature<"avx512f", "X86SSELevel", "AVX512F", - "Enable AVX-512 instructions", - [FeatureAVX2, FeatureFMA, FeatureF16C]>; -def FeatureERI : SubtargetFeature<"avx512er", "HasERI", "true", - "Enable AVX-512 Exponential and Reciprocal Instructions", - [FeatureAVX512]>; -def FeatureCDI : SubtargetFeature<"avx512cd", "HasCDI", "true", - "Enable AVX-512 Conflict Detection Instructions", - [FeatureAVX512]>; -def FeatureVPOPCNTDQ : SubtargetFeature<"avx512vpopcntdq", "HasVPOPCNTDQ", - "true", "Enable AVX-512 Population Count Instructions", - [FeatureAVX512]>; -def FeaturePFI : SubtargetFeature<"avx512pf", "HasPFI", "true", - "Enable AVX-512 PreFetch Instructions", - [FeatureAVX512]>; -def FeaturePREFETCHWT1 : SubtargetFeature<"prefetchwt1", "HasPREFETCHWT1", - "true", - "Prefetch with Intent to Write and T1 Hint">; -def FeatureDQI : SubtargetFeature<"avx512dq", "HasDQI", "true", - "Enable AVX-512 Doubleword and Quadword Instructions", - [FeatureAVX512]>; -def FeatureBWI : SubtargetFeature<"avx512bw", "HasBWI", "true", - "Enable AVX-512 Byte and Word Instructions", - [FeatureAVX512]>; -def FeatureVLX : SubtargetFeature<"avx512vl", "HasVLX", "true", - "Enable AVX-512 Vector Length eXtensions", - [FeatureAVX512]>; -def FeatureVBMI : SubtargetFeature<"avx512vbmi", "HasVBMI", "true", - "Enable AVX-512 Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureVBMI2 : SubtargetFeature<"avx512vbmi2", "HasVBMI2", "true", - "Enable AVX-512 further Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureIFMA : SubtargetFeature<"avx512ifma", "HasIFMA", "true", - "Enable AVX-512 Integer Fused Multiple-Add", - [FeatureAVX512]>; -def FeaturePKU : SubtargetFeature<"pku", "HasPKU", "true", - "Enable protection keys">; -def FeatureVNNI : SubtargetFeature<"avx512vnni", "HasVNNI", "true", - "Enable AVX-512 Vector Neural Network Instructions", - [FeatureAVX512]>; -def FeatureBITALG : SubtargetFeature<"avx512bitalg", "HasBITALG", "true", - "Enable AVX-512 Bit Algorithms", - [FeatureBWI]>; -def FeaturePCLMUL : SubtargetFeature<"pclmul", "HasPCLMUL", "true", - "Enable packed carry-less multiplication instructions", - [FeatureSSE2]>; -def FeatureGFNI : SubtargetFeature<"gfni", "HasGFNI", "true", - "Enable Galois Field Arithmetic Instructions", - [FeatureSSE2]>; -def FeatureVPCLMULQDQ : SubtargetFeature<"vpclmulqdq", "HasVPCLMULQDQ", "true", - "Enable vpclmulqdq instructions", - [FeatureAVX, FeaturePCLMUL]>; -def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", - "Enable four-operand fused multiple-add", - [FeatureAVX, FeatureSSE4A]>; -def FeatureXOP : SubtargetFeature<"xop", "HasXOP", "true", - "Enable XOP instructions", - [FeatureFMA4]>; -def FeatureSSEUnalignedMem : SubtargetFeature<"sse-unaligned-mem", - "HasSSEUnalignedMem", "true", - "Allow unaligned memory operands with SSE instructions">; -def FeatureAES : SubtargetFeature<"aes", "HasAES", "true", - "Enable AES instructions", - [FeatureSSE2]>; -def FeatureVAES : SubtargetFeature<"vaes", "HasVAES", "true", - "Promote selected AES instructions to AVX512/AVX registers", - [FeatureAVX, FeatureAES]>; -def FeatureTBM : SubtargetFeature<"tbm", "HasTBM", "true", - "Enable TBM instructions">; -def FeatureLWP : SubtargetFeature<"lwp", "HasLWP", "true", - "Enable LWP instructions">; -def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true", - "Support MOVBE instruction">; -def FeatureRDRAND : SubtargetFeature<"rdrnd", "HasRDRAND", "true", - "Support RDRAND instruction">; -def FeatureFSGSBase : SubtargetFeature<"fsgsbase", "HasFSGSBase", "true", - "Support FS/GS Base instructions">; -def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true", - "Support LZCNT instruction">; -def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true", - "Support BMI instructions">; -def FeatureBMI2 : SubtargetFeature<"bmi2", "HasBMI2", "true", - "Support BMI2 instructions">; -def FeatureRTM : SubtargetFeature<"rtm", "HasRTM", "true", - "Support RTM instructions">; -def FeatureADX : SubtargetFeature<"adx", "HasADX", "true", - "Support ADX instructions">; -def FeatureSHA : SubtargetFeature<"sha", "HasSHA", "true", - "Enable SHA instructions", - [FeatureSSE2]>; -def FeatureSHSTK : SubtargetFeature<"shstk", "HasSHSTK", "true", - "Support CET Shadow-Stack instructions">; -def FeaturePRFCHW : SubtargetFeature<"prfchw", "HasPRFCHW", "true", - "Support PRFCHW instructions">; -def FeatureRDSEED : SubtargetFeature<"rdseed", "HasRDSEED", "true", - "Support RDSEED instruction">; -def FeatureLAHFSAHF : SubtargetFeature<"sahf", "HasLAHFSAHF", "true", - "Support LAHF and SAHF instructions">; -def FeatureMWAITX : SubtargetFeature<"mwaitx", "HasMWAITX", "true", - "Enable MONITORX/MWAITX timer functionality">; -def FeatureCLZERO : SubtargetFeature<"clzero", "HasCLZERO", "true", - "Enable Cache Line Zero">; -def FeatureCLDEMOTE : SubtargetFeature<"cldemote", "HasCLDEMOTE", "true", - "Enable Cache Demote">; -def FeaturePTWRITE : SubtargetFeature<"ptwrite", "HasPTWRITE", "true", - "Support ptwrite instruction">; -def FeatureMPX : SubtargetFeature<"mpx", "HasMPX", "true", - "Support MPX instructions">; -def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true", - "Use LEA for adjusting the stack pointer">; -def FeatureSlowDivide32 : SubtargetFeature<"idivl-to-divb", - "HasSlowDivide32", "true", - "Use 8-bit divide for positive values less than 256">; -def FeatureSlowDivide64 : SubtargetFeature<"idivq-to-divl", - "HasSlowDivide64", "true", - "Use 32-bit divide for positive values less than 2^32">; -def FeaturePadShortFunctions : SubtargetFeature<"pad-short-functions", - "PadShortFunctions", "true", - "Pad short functions">; -def FeatureINVPCID : SubtargetFeature<"invpcid", "HasINVPCID", "true", - "Invalidate Process-Context Identifier">; -def FeatureSGX : SubtargetFeature<"sgx", "HasSGX", "true", - "Enable Software Guard Extensions">; -def FeatureCLFLUSHOPT : SubtargetFeature<"clflushopt", "HasCLFLUSHOPT", "true", - "Flush A Cache Line Optimized">; -def FeatureCLWB : SubtargetFeature<"clwb", "HasCLWB", "true", - "Cache Line Write Back">; -def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", - "Write Back No Invalidate">; -def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", - "Support RDPID instructions">; -def FeatureWAITPKG : SubtargetFeature<"waitpkg", "HasWAITPKG", "true", - "Wait and pause enhancements">; -// On some processors, instructions that implicitly take two memory operands are -// slow. In practice, this means that CALL, PUSH, and POP with memory operands -// should be avoided in favor of a MOV + register CALL/PUSH/POP. -def FeatureSlowTwoMemOps : SubtargetFeature<"slow-two-mem-ops", - "SlowTwoMemOps", "true", - "Two memory operand instructions are slow">; -def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true", - "LEA instruction needs inputs at AG stage">; -def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true", - "LEA instruction with certain arguments is slow">; -def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true", - "LEA instruction with 3 ops or certain registers is slow">; -def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true", - "INC and DEC instructions are slower than ADD and SUB">; -def FeatureSoftFloat - : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software floating point features.">; -def FeaturePOPCNTFalseDeps : SubtargetFeature<"false-deps-popcnt", - "HasPOPCNTFalseDeps", "true", - "POPCNT has a false dependency on dest register">; -def FeatureLZCNTFalseDeps : SubtargetFeature<"false-deps-lzcnt-tzcnt", - "HasLZCNTFalseDeps", "true", - "LZCNT/TZCNT have a false dependency on dest register">; -def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true", - "platform configuration instruction">; -// On recent X86 (port bound) processors, its preferable to combine to a single shuffle -// using a variable mask over multiple fixed shuffles. -def FeatureFastVariableShuffle - : SubtargetFeature<"fast-variable-shuffle", - "HasFastVariableShuffle", - "true", "Shuffles with variable masks are fast">; -// On some X86 processors, there is no performance hazard to writing only the -// lower parts of a YMM or ZMM register without clearing the upper part. -def FeatureFastPartialYMMorZMMWrite - : SubtargetFeature<"fast-partial-ymm-or-zmm-write", - "HasFastPartialYMMorZMMWrite", - "true", "Partial writes to YMM/ZMM registers are fast">; -// FeatureFastScalarFSQRT should be enabled if scalar FSQRT has shorter latency -// than the corresponding NR code. FeatureFastVectorFSQRT should be enabled if -// vector FSQRT has higher throughput than the corresponding NR code. -// The idea is that throughput bound code is likely to be vectorized, so for -// vectorized code we should care about the throughput of SQRT operations. -// But if the code is scalar that probably means that the code has some kind of -// dependency and we should care more about reducing the latency. -def FeatureFastScalarFSQRT - : SubtargetFeature<"fast-scalar-fsqrt", "HasFastScalarFSQRT", - "true", "Scalar SQRT is fast (disable Newton-Raphson)">; -def FeatureFastVectorFSQRT - : SubtargetFeature<"fast-vector-fsqrt", "HasFastVectorFSQRT", - "true", "Vector SQRT is fast (disable Newton-Raphson)">; -// If lzcnt has equivalent latency/throughput to most simple integer ops, it can -// be used to replace test/set sequences. -def FeatureFastLZCNT - : SubtargetFeature< - "fast-lzcnt", "HasFastLZCNT", "true", - "LZCNT instructions are as fast as most simple integer ops">; -// If the target can efficiently decode NOPs upto 11-bytes in length. -def FeatureFast11ByteNOP - : SubtargetFeature< - "fast-11bytenop", "HasFast11ByteNOP", "true", - "Target can quickly decode up to 11 byte NOPs">; -// If the target can efficiently decode NOPs upto 15-bytes in length. -def FeatureFast15ByteNOP - : SubtargetFeature< - "fast-15bytenop", "HasFast15ByteNOP", "true", - "Target can quickly decode up to 15 byte NOPs">; -// Sandy Bridge and newer processors can use SHLD with the same source on both -// inputs to implement rotate to avoid the partial flag update of the normal -// rotate instructions. -def FeatureFastSHLDRotate - : SubtargetFeature< - "fast-shld-rotate", "HasFastSHLDRotate", "true", - "SHLD can be used as a faster rotate">; - -// Ivy Bridge and newer processors have enhanced REP MOVSB and STOSB (aka -// "string operations"). See "REP String Enhancement" in the Intel Software -// Development Manual. This feature essentially means that REP MOVSB will copy -// using the largest available size instead of copying bytes one by one, making -// it at least as fast as REPMOVS{W,D,Q}. -def FeatureERMSB - : SubtargetFeature< - "ermsb", "HasERMSB", "true", - "REP MOVS/STOS are fast">; - -// Sandy Bridge and newer processors have many instructions that can be -// fused with conditional branches and pass through the CPU as a single -// operation. -def FeatureMacroFusion - : SubtargetFeature<"macrofusion", "HasMacroFusion", "true", - "Various instructions can be fused with conditional branches">; - -// Gather is available since Haswell (AVX2 set). So technically, we can -// generate Gathers on all AVX2 processors. But the overhead on HSW is high. -// Skylake Client processor has faster Gathers than HSW and performance is -// similar to Skylake Server (AVX-512). -def FeatureHasFastGather - : SubtargetFeature<"fast-gather", "HasFastGather", "true", - "Indicates if gather is reasonably fast.">; - -def FeaturePrefer256Bit - : SubtargetFeature<"prefer-256-bit", "Prefer256Bit", "true", - "Prefer 256-bit AVX instructions">; - -// Enable mitigation of some aspects of speculative execution related -// vulnerabilities by removing speculatable indirect branches. This disables -// jump-table formation, rewrites explicit `indirectbr` instructions into -// `switch` instructions, and uses a special construct called a "retpoline" to -// prevent speculation of the remaining indirect branches (indirect calls and -// tail calls). -def FeatureRetpoline - : SubtargetFeature<"retpoline", "UseRetpoline", "true", - "Remove speculation of indirect branches from the " - "generated code, either by avoiding them entirely or " - "lowering them with a speculation blocking construct.">; - -// Rely on external thunks for the emitted retpoline calls. This allows users -// to provide their own custom thunk definitions in highly specialized -// environments such as a kernel that does boot-time hot patching. -def FeatureRetpolineExternalThunk - : SubtargetFeature< - "retpoline-external-thunk", "UseRetpolineExternalThunk", "true", - "Enable retpoline, but with an externally provided thunk.", - [FeatureRetpoline]>; - -// Direct Move instructions. -def FeatureMOVDIRI : SubtargetFeature<"movdiri", "HasMOVDIRI", "true", - "Support movdiri instruction">; -def FeatureMOVDIR64B : SubtargetFeature<"movdir64b", "HasMOVDIR64B", "true", - "Support movdir64b instruction">; - -//===----------------------------------------------------------------------===// -// Register File Description -//===----------------------------------------------------------------------===// - -include "X86RegisterInfo.td" -include "X86RegisterBanks.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "X86Schedule.td" -include "X86InstrInfo.td" -include "X86SchedPredicates.td" - -def X86InstrInfo : InstrInfo; - -//===----------------------------------------------------------------------===// -// X86 processors supported. -//===----------------------------------------------------------------------===// - -include "X86ScheduleAtom.td" -include "X86SchedSandyBridge.td" -include "X86SchedHaswell.td" -include "X86SchedBroadwell.td" -include "X86ScheduleSLM.td" -include "X86ScheduleZnver1.td" -include "X86ScheduleBtVer2.td" -include "X86SchedSkylakeClient.td" -include "X86SchedSkylakeServer.td" - -def ProcIntelAtom : SubtargetFeature<"atom", "X86ProcFamily", "IntelAtom", - "Intel Atom processors">; -def ProcIntelSLM : SubtargetFeature<"slm", "X86ProcFamily", "IntelSLM", - "Intel Silvermont processors">; -def ProcIntelGLM : SubtargetFeature<"glm", "X86ProcFamily", "IntelGLM", - "Intel Goldmont processors">; -def ProcIntelGLP : SubtargetFeature<"glp", "X86ProcFamily", "IntelGLP", - "Intel Goldmont Plus processors">; -def ProcIntelTRM : SubtargetFeature<"tremont", "X86ProcFamily", "IntelTRM", - "Intel Tremont processors">; -def ProcIntelHSW : SubtargetFeature<"haswell", "X86ProcFamily", - "IntelHaswell", "Intel Haswell processors">; -def ProcIntelBDW : SubtargetFeature<"broadwell", "X86ProcFamily", - "IntelBroadwell", "Intel Broadwell processors">; -def ProcIntelSKL : SubtargetFeature<"skylake", "X86ProcFamily", - "IntelSkylake", "Intel Skylake processors">; -def ProcIntelKNL : SubtargetFeature<"knl", "X86ProcFamily", - "IntelKNL", "Intel Knights Landing processors">; -def ProcIntelSKX : SubtargetFeature<"skx", "X86ProcFamily", - "IntelSKX", "Intel Skylake Server processors">; -def ProcIntelCNL : SubtargetFeature<"cannonlake", "X86ProcFamily", - "IntelCannonlake", "Intel Cannonlake processors">; -def ProcIntelICL : SubtargetFeature<"icelake-client", "X86ProcFamily", - "IntelIcelakeClient", "Intel Icelake processors">; -def ProcIntelICX : SubtargetFeature<"icelake-server", "X86ProcFamily", - "IntelIcelakeServer", "Intel Icelake Server processors">; - -class Proc Features> - : ProcessorModel; - -def : Proc<"generic", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i386", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i486", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"i586", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"pentium", [FeatureX87, FeatureSlowUAMem16]>; -def : Proc<"pentium-mmx", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; - -def : Proc<"i686", [FeatureX87, FeatureSlowUAMem16, FeatureCMOV]>; -def : Proc<"pentiumpro", [FeatureX87, FeatureSlowUAMem16, FeatureCMOV, - FeatureNOPL]>; - -def : Proc<"pentium2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureCMOV, FeatureFXSR, FeatureNOPL]>; - -foreach P = ["pentium3", "pentium3m"] in { - def : Proc; -} - -// Enable the PostRAScheduler for SSE2 and SSE3 class cpus. -// The intent is to enable it for pentium4 which is the current default -// processor in a vanilla 32-bit clang compilation when no specific -// architecture is specified. This generally gives a nice performance -// increase on silvermont, with largely neutral behavior on other -// contemporary large core processors. -// pentium-m, pentium4m, prescott and nocona are included as a preventative -// measure to avoid performance surprises, in case clang's default cpu -// changes slightly. - -def : ProcessorModel<"pentium-m", GenericPostRAModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureSSE2, FeatureFXSR, FeatureNOPL]>; - -foreach P = ["pentium4", "pentium4m"] in { - def : ProcessorModel; -} - -// Intel Quark. -def : Proc<"lakemont", []>; - -// Intel Core Duo. -def : ProcessorModel<"yonah", SandyBridgeModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, - FeatureFXSR, FeatureNOPL]>; - -// NetBurst. -def : ProcessorModel<"prescott", GenericPostRAModel, - [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, - FeatureFXSR, FeatureNOPL]>; -def : ProcessorModel<"nocona", GenericPostRAModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSE3, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B -]>; - -// Intel Core 2 Solo/Duo. -def : ProcessorModel<"core2", SandyBridgeModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSSE3, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureLAHFSAHF, - FeatureMacroFusion -]>; -def : ProcessorModel<"penryn", SandyBridgeModel, [ - FeatureX87, - FeatureSlowUAMem16, - FeatureMMX, - FeatureSSE41, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureLAHFSAHF, - FeatureMacroFusion -]>; - -// Atom CPUs. -class BonnellProc : ProcessorModel; -def : BonnellProc<"bonnell">; -def : BonnellProc<"atom">; // Pin the generic name to the baseline. - -class SilvermontProc : ProcessorModel; -def : SilvermontProc<"silvermont">; -def : SilvermontProc<"slm">; // Legacy alias. - -class ProcessorFeatures Inherited, - list NewFeatures> { - list Value = !listconcat(Inherited, NewFeatures); -} - -class ProcModel ProcFeatures, - list OtherFeatures> : - ProcessorModel; - -def GLMFeatures : ProcessorFeatures<[], [ - FeatureX87, - FeatureMMX, - FeatureSSE42, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeatureMOVBE, - FeaturePOPCNT, - FeaturePCLMUL, - FeatureAES, - FeaturePRFCHW, - FeatureSlowTwoMemOps, - FeatureSlowLEA, - FeatureSlowIncDec, - FeatureLAHFSAHF, - FeatureMPX, - FeatureSHA, - FeatureRDRAND, - FeatureRDSEED, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureXSAVEC, - FeatureXSAVES, - FeatureCLFLUSHOPT, - FeatureFSGSBase -]>; - -class GoldmontProc : ProcModel; -def : GoldmontProc<"goldmont">; - -def GLPFeatures : ProcessorFeatures; - -class GoldmontPlusProc : ProcModel; -def : GoldmontPlusProc<"goldmont-plus">; - -class TremontProc : ProcModel; -def : TremontProc<"tremont">; - -// "Arrandale" along with corei3 and corei5 -class NehalemProc : ProcessorModel; -def : NehalemProc<"nehalem">; -def : NehalemProc<"corei7">; - -// Westmere is a similar machine to nehalem with some additional features. -// Westmere is the corei3/i5/i7 path from nehalem to sandybridge -class WestmereProc : ProcessorModel; -def : WestmereProc<"westmere">; - -// SSE is not listed here since llvm treats AVX as a reimplementation of SSE, -// rather than a superset. -def SNBFeatures : ProcessorFeatures<[], [ - FeatureX87, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeaturePOPCNT, - FeatureAES, - FeatureSlowDivide64, - FeaturePCLMUL, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureLAHFSAHF, - FeatureSlow3OpsLEA, - FeatureFastScalarFSQRT, - FeatureFastSHLDRotate, - FeatureSlowIncDec, - FeatureMacroFusion -]>; - -class SandyBridgeProc : ProcModel; -def : SandyBridgeProc<"sandybridge">; -def : SandyBridgeProc<"corei7-avx">; // Legacy alias. - -def IVBFeatures : ProcessorFeatures; - -class IvyBridgeProc : ProcModel; -def : IvyBridgeProc<"ivybridge">; -def : IvyBridgeProc<"core-avx-i">; // Legacy alias. - -def HSWFeatures : ProcessorFeatures; - -class HaswellProc : ProcModel; -def : HaswellProc<"haswell">; -def : HaswellProc<"core-avx2">; // Legacy alias. - -def BDWFeatures : ProcessorFeatures; -class BroadwellProc : ProcModel; -def : BroadwellProc<"broadwell">; - -def SKLFeatures : ProcessorFeatures; - -class SkylakeClientProc : ProcModel; -def : SkylakeClientProc<"skylake">; - -def KNLFeatures : ProcessorFeatures; - -// FIXME: define KNL model -class KnightsLandingProc : ProcModel; -def : KnightsLandingProc<"knl">; - -class KnightsMillProc : ProcModel; -def : KnightsMillProc<"knm">; // TODO Add AVX5124FMAPS/AVX5124VNNIW features - -def SKXFeatures : ProcessorFeatures; - -class SkylakeServerProc : ProcModel; -def : SkylakeServerProc<"skylake-avx512">; -def : SkylakeServerProc<"skx">; // Legacy alias. - -def CNLFeatures : ProcessorFeatures; - -class CannonlakeProc : ProcModel; -def : CannonlakeProc<"cannonlake">; - -def ICLFeatures : ProcessorFeatures; - -class IcelakeClientProc : ProcModel; -def : IcelakeClientProc<"icelake-client">; - -class IcelakeServerProc : ProcModel; -def : IcelakeServerProc<"icelake-server">; - -// AMD CPUs. - -def : Proc<"k6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"k6-2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"k6-3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; - -foreach P = ["athlon", "athlon-tbird"] in { - def : Proc; -} - -foreach P = ["athlon-4", "athlon-xp", "athlon-mp"] in { - def : Proc; -} - -foreach P = ["k8", "opteron", "athlon64", "athlon-fx"] in { - def : Proc; -} - -foreach P = ["k8-sse3", "opteron-sse3", "athlon64-sse3"] in { - def : Proc; -} - -foreach P = ["amdfam10", "barcelona"] in { - def : Proc; -} - -// Bobcat -def : Proc<"btver1", [ - FeatureX87, - FeatureMMX, - FeatureSSSE3, - FeatureSSE4A, - FeatureFXSR, - FeatureNOPL, - FeatureCMPXCHG16B, - FeaturePRFCHW, - FeatureLZCNT, - FeaturePOPCNT, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast15ByteNOP -]>; - -// Jaguar -def : ProcessorModel<"btver2", BtVer2Model, [ - FeatureX87, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureCMPXCHG16B, - FeaturePRFCHW, - FeatureAES, - FeaturePCLMUL, - FeatureBMI, - FeatureF16C, - FeatureMOVBE, - FeatureLZCNT, - FeatureFastLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast15ByteNOP, - FeatureFastPartialYMMorZMMWrite -]>; - -// Bulldozer -def : Proc<"bdver1", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureLWP, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; -// Piledriver -def : Proc<"bdver2", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureSlowSHLD, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; - -// Steamroller -def : Proc<"bdver3", [ - FeatureX87, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureMMX, - FeatureAVX, - FeatureFXSR, - FeatureNOPL, - FeatureSSE4A, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureFSGSBase, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMacroFusion -]>; - -// Excavator -def : Proc<"bdver4", [ - FeatureX87, - FeatureMMX, - FeatureAVX2, - FeatureFXSR, - FeatureNOPL, - FeatureXOP, - FeatureFMA4, - FeatureCMPXCHG16B, - FeatureAES, - FeaturePRFCHW, - FeaturePCLMUL, - FeatureF16C, - FeatureLZCNT, - FeaturePOPCNT, - FeatureXSAVE, - FeatureBMI, - FeatureBMI2, - FeatureTBM, - FeatureLWP, - FeatureFMA, - FeatureXSAVEOPT, - FeatureSlowSHLD, - FeatureFSGSBase, - FeatureLAHFSAHF, - FeatureFast11ByteNOP, - FeatureMWAITX, - FeatureMacroFusion -]>; - -// Znver1 -def: ProcessorModel<"znver1", Znver1Model, [ - FeatureADX, - FeatureAES, - FeatureAVX2, - FeatureBMI, - FeatureBMI2, - FeatureCLFLUSHOPT, - FeatureCLZERO, - FeatureCMPXCHG16B, - FeatureF16C, - FeatureFMA, - FeatureFSGSBase, - FeatureFXSR, - FeatureNOPL, - FeatureFastLZCNT, - FeatureLAHFSAHF, - FeatureLZCNT, - FeatureFast15ByteNOP, - FeatureMacroFusion, - FeatureMMX, - FeatureMOVBE, - FeatureMWAITX, - FeaturePCLMUL, - FeaturePOPCNT, - FeaturePRFCHW, - FeatureRDRAND, - FeatureRDSEED, - FeatureSHA, - FeatureSSE4A, - FeatureSlowSHLD, - FeatureX87, - FeatureXSAVE, - FeatureXSAVEC, - FeatureXSAVEOPT, - FeatureXSAVES]>; - -def : Proc<"geode", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA]>; - -def : Proc<"winchip-c6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"winchip2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3-2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, - FeatureSSE1, FeatureFXSR]>; - -// We also provide a generic 64-bit specific x86 processor model which tries to -// be good for modern chips without enabling instruction set encodings past the -// basic SSE2 and 64-bit ones. It disables slow things from any mainstream and -// modern 64-bit x86 chip, and enables features that are generally beneficial. -// -// We currently use the Sandy Bridge model as the default scheduling model as -// we use it across Nehalem, Westmere, Sandy Bridge, and Ivy Bridge which -// covers a huge swath of x86 processors. If there are specific scheduling -// knobs which need to be tuned differently for AMD chips, we might consider -// forming a common base for them. -def : ProcessorModel<"x86-64", SandyBridgeModel, [ - FeatureX87, - FeatureMMX, - FeatureSSE2, - FeatureFXSR, - FeatureNOPL, - Feature64Bit, - FeatureSlow3OpsLEA, - FeatureSlowIncDec, - FeatureMacroFusion -]>; - -//===----------------------------------------------------------------------===// -// Calling Conventions -//===----------------------------------------------------------------------===// - -include "X86CallingConv.td" - - -//===----------------------------------------------------------------------===// -// Assembly Parser -//===----------------------------------------------------------------------===// - -def ATTAsmParserVariant : AsmParserVariant { - int Variant = 0; - - // Variant name. - string Name = "att"; - - // Discard comments in assembly strings. - string CommentDelimiter = "#"; - - // Recognize hard coded registers. - string RegisterPrefix = "%"; -} - -def IntelAsmParserVariant : AsmParserVariant { - int Variant = 1; - - // Variant name. - string Name = "intel"; - - // Discard comments in assembly strings. - string CommentDelimiter = ";"; - - // Recognize hard coded registers. - string RegisterPrefix = ""; -} - -//===----------------------------------------------------------------------===// -// Assembly Printers -//===----------------------------------------------------------------------===// - -// The X86 target supports two different syntaxes for emitting machine code. -// This is controlled by the -x86-asm-syntax={att|intel} -def ATTAsmWriter : AsmWriter { - string AsmWriterClassName = "ATTInstPrinter"; - int Variant = 0; -} -def IntelAsmWriter : AsmWriter { - string AsmWriterClassName = "IntelInstPrinter"; - int Variant = 1; -} - -def X86 : Target { - // Information about the instructions... - let InstructionSet = X86InstrInfo; - let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant]; - let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; - let AllowRegisterRenaming = 1; -} - -//===----------------------------------------------------------------------===// -// Pfm Counters -//===----------------------------------------------------------------------===// - -include "X86PfmCounters.td" diff --git a/suite/synctools/tablegen/X86/back/X86CallingConv.td b/suite/synctools/tablegen/X86/back/X86CallingConv.td deleted file mode 100644 index fcc9a296de..0000000000 --- a/suite/synctools/tablegen/X86/back/X86CallingConv.td +++ /dev/null @@ -1,1150 +0,0 @@ -//===-- X86CallingConv.td - Calling Conventions X86 32/64 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This describes the calling conventions for the X86-32 and X86-64 -// architectures. -// -//===----------------------------------------------------------------------===// - -/// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget - : CCIf" - "(State.getMachineFunction().getSubtarget()).", F), - A>; - -/// CCIfNotSubtarget - Match if the current subtarget doesn't has a feature F. -class CCIfNotSubtarget - : CCIf" - "(State.getMachineFunction().getSubtarget()).", F), - A>; - -// Register classes for RegCall -class RC_X86_RegCall { - list GPR_8 = []; - list GPR_16 = []; - list GPR_32 = []; - list GPR_64 = []; - list FP_CALL = [FP0]; - list FP_RET = [FP0, FP1]; - list XMM = []; - list YMM = []; - list ZMM = []; -} - -// RegCall register classes for 32 bits -def RC_X86_32_RegCall : RC_X86_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL]; - let GPR_16 = [AX, CX, DX, DI, SI]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI]; - let GPR_64 = [RAX]; ///< Not actually used, but AssignToReg can't handle [] - ///< \todo Fix AssignToReg to enable empty lists - let XMM = [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]; - let YMM = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7]; - let ZMM = [ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7]; -} - -class RC_X86_64_RegCall : RC_X86_RegCall { - let XMM = [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]; - let YMM = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, - YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15]; - let ZMM = [ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7, - ZMM8, ZMM9, ZMM10, ZMM11, ZMM12, ZMM13, ZMM14, ZMM15]; -} - -def RC_X86_64_RegCall_Win : RC_X86_64_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL, R8B, R9B, R10B, R11B, R12B, R14B, R15B]; - let GPR_16 = [AX, CX, DX, DI, SI, R8W, R9W, R10W, R11W, R12W, R14W, R15W]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI, R8D, R9D, R10D, R11D, R12D, R14D, R15D]; - let GPR_64 = [RAX, RCX, RDX, RDI, RSI, R8, R9, R10, R11, R12, R14, R15]; -} - -def RC_X86_64_RegCall_SysV : RC_X86_64_RegCall { - let GPR_8 = [AL, CL, DL, DIL, SIL, R8B, R9B, R12B, R13B, R14B, R15B]; - let GPR_16 = [AX, CX, DX, DI, SI, R8W, R9W, R12W, R13W, R14W, R15W]; - let GPR_32 = [EAX, ECX, EDX, EDI, ESI, R8D, R9D, R12D, R13D, R14D, R15D]; - let GPR_64 = [RAX, RCX, RDX, RDI, RSI, R8, R9, R12, R13, R14, R15]; -} - -// X86-64 Intel regcall calling convention. -multiclass X86_RegCall_base { -def CC_#NAME : CallingConv<[ - // Handles byval parameters. - CCIfSubtarget<"is64Bit()", CCIfByVal>>, - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // Promote v8i1/v16i1/v32i1 arguments to i32. - CCIfType<[v8i1, v16i1, v32i1], CCPromoteToType>, - - // bool, char, int, enum, long, pointer --> GPR - CCIfType<[i32], CCAssignToReg>, - - // long long, __int64 --> GPR - CCIfType<[i64], CCAssignToReg>, - - // __mmask64 (v64i1) --> GPR64 (for x64) or 2 x GPR32 (for IA32) - CCIfType<[v64i1], CCPromoteToType>, - CCIfSubtarget<"is64Bit()", CCIfType<[i64], - CCAssignToReg>>, - CCIfSubtarget<"is32Bit()", CCIfType<[i64], - CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>, - - // float, double, float128 --> XMM - // In the case of SSE disabled --> save to stack - CCIfType<[f32, f64, f128], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // long double --> FP - CCIfType<[f80], CCAssignToReg>, - - // __m128, __m128i, __m128d --> XMM - // In the case of SSE disabled --> save to stack - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m256, __m256i, __m256d --> YMM - // In the case of SSE disabled --> save to stack - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", CCAssignToReg>>, - - // __m512, __m512i, __m512d --> ZMM - // In the case of SSE disabled --> save to stack - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()",CCAssignToReg>>, - - // If no register was found -> assign to stack - - // In 64 bit, assign 64/32 bit values to 8 byte stack - CCIfSubtarget<"is64Bit()", CCIfType<[i32, i64, f32, f64], - CCAssignToStack<8, 8>>>, - - // In 32 bit, assign 64/32 bit values to 8/4 byte stack - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - CCIfType<[i64, f64], CCAssignToStack<8, 4>>, - - // MMX type gets 8 byte slot in stack , while alignment depends on target - CCIfSubtarget<"is64Bit()", CCIfType<[x86mmx], CCAssignToStack<8, 8>>>, - CCIfType<[x86mmx], CCAssignToStack<8, 4>>, - - // float 128 get stack slots whose size and alignment depends - // on the subtarget. - CCIfType<[f80, f128], CCAssignToStack<0, 0>>, - - // Vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToStack<16, 16>>, - - // 256-bit vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v16i32, v8i64, v16f32, v8f64], CCAssignToStack<64, 64>> -]>; - -def RetCC_#NAME : CallingConv<[ - // Promote i1, v1i1, v8i1 arguments to i8. - CCIfType<[i1, v1i1, v8i1], CCPromoteToType>, - - // Promote v16i1 arguments to i16. - CCIfType<[v16i1], CCPromoteToType>, - - // Promote v32i1 arguments to i32. - CCIfType<[v32i1], CCPromoteToType>, - - // bool, char, int, enum, long, pointer --> GPR - CCIfType<[i8], CCAssignToReg>, - CCIfType<[i16], CCAssignToReg>, - CCIfType<[i32], CCAssignToReg>, - - // long long, __int64 --> GPR - CCIfType<[i64], CCAssignToReg>, - - // __mmask64 (v64i1) --> GPR64 (for x64) or 2 x GPR32 (for IA32) - CCIfType<[v64i1], CCPromoteToType>, - CCIfSubtarget<"is64Bit()", CCIfType<[i64], - CCAssignToReg>>, - CCIfSubtarget<"is32Bit()", CCIfType<[i64], - CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>, - - // long double --> FP - CCIfType<[f80], CCAssignToReg>, - - // float, double, float128 --> XMM - CCIfType<[f32, f64, f128], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m128, __m128i, __m128d --> XMM - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", CCAssignToReg>>, - - // __m256, __m256i, __m256d --> YMM - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", CCAssignToReg>>, - - // __m512, __m512i, __m512d --> ZMM - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()", CCAssignToReg>> -]>; -} - -//===----------------------------------------------------------------------===// -// Return Value Calling Conventions -//===----------------------------------------------------------------------===// - -// Return-value conventions common to all X86 CC's. -def RetCC_X86Common : CallingConv<[ - // Scalar values are returned in AX first, then DX. For i8, the ABI - // requires the values to be in AL and AH, however this code uses AL and DL - // instead. This is because using AH for the second register conflicts with - // the way LLVM does multiple return values -- a return of {i16,i8} would end - // up in AX and AH, which overlap. Front-ends wishing to conform to the ABI - // for functions that return two i8 values are currently expected to pack the - // values into an i16 (which uses AX, and thus AL:AH). - // - // For code that doesn't care about the ABI, we allow returning more than two - // integer values in registers. - CCIfType<[v1i1], CCPromoteToType>, - CCIfType<[i1], CCPromoteToType>, - CCIfType<[i8] , CCAssignToReg<[AL, DL, CL]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>, - CCIfType<[i64], CCAssignToReg<[RAX, RDX, RCX]>>, - - // Boolean vectors of AVX-512 are returned in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // Vector types are returned in XMM0 and XMM1, when they fit. XMM2 and XMM3 - // can only be used by ABI non-compliant code. If the target doesn't have XMM - // registers, it won't have vector types. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // 256-bit vectors are returned in YMM0 and XMM1, when they fit. YMM2 and YMM3 - // can only be used by ABI non-compliant code. This vector type is only - // supported while using the AVX target feature. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>, - - // 512-bit vectors are returned in ZMM0 and ZMM1, when they fit. ZMM2 and ZMM3 - // can only be used by ABI non-compliant code. This vector type is only - // supported while using the AVX-512 target feature. - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCAssignToReg<[ZMM0,ZMM1,ZMM2,ZMM3]>>, - - // MMX vector types are always returned in MM0. If the target doesn't have - // MM0, it doesn't support these vector types. - CCIfType<[x86mmx], CCAssignToReg<[MM0]>>, - - // Long double types are always returned in FP0 (even with SSE), - // except on Win64. - CCIfNotSubtarget<"isTargetWin64()", CCIfType<[f80], CCAssignToReg<[FP0, FP1]>>> -]>; - -// X86-32 C return-value convention. -def RetCC_X86_32_C : CallingConv<[ - // The X86-32 calling convention returns FP values in FP0, unless marked - // with "inreg" (used here to distinguish one kind of reg from another, - // weirdly; this is really the sse-regparm calling convention) in which - // case they use XMM0, otherwise it is the same as the common X86 calling - // conv. - CCIfInReg>>>, - CCIfType<[f32,f64], CCAssignToReg<[FP0, FP1]>>, - CCDelegateTo -]>; - -// X86-32 FastCC return-value convention. -def RetCC_X86_32_Fast : CallingConv<[ - // The X86-32 fastcc returns 1, 2, or 3 FP values in XMM0-2 if the target has - // SSE2. - // This can happen when a float, 2 x float, or 3 x float vector is split by - // target lowering, and is returned in 1-3 sse regs. - CCIfType<[f32], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, - CCIfType<[f64], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, - - // For integers, ECX can be used as an extra return register - CCIfType<[i8], CCAssignToReg<[AL, DL, CL]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>, - - // Otherwise, it is the same as the common X86 calling convention. - CCDelegateTo -]>; - -// Intel_OCL_BI return-value convention. -def RetCC_Intel_OCL_BI : CallingConv<[ - // Vector types are returned in XMM0,XMM1,XMMM2 and XMM3. - CCIfType<[f32, f64, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // 256-bit FP vectors - // No more than 4 registers - CCIfType<[v8f32, v4f64, v8i32, v4i64], - CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>, - - // 512-bit FP vectors - CCIfType<[v16f32, v8f64, v16i32, v8i64], - CCAssignToReg<[ZMM0,ZMM1,ZMM2,ZMM3]>>, - - // i32, i64 in the standard way - CCDelegateTo -]>; - -// X86-32 HiPE return-value convention. -def RetCC_X86_32_HiPE : CallingConv<[ - // Promote all types to i32 - CCIfType<[i8, i16], CCPromoteToType>, - - // Return: HP, P, VAL1, VAL2 - CCIfType<[i32], CCAssignToReg<[ESI, EBP, EAX, EDX]>> -]>; - -// X86-32 Vectorcall return-value convention. -def RetCC_X86_32_VectorCall : CallingConv<[ - // Floating Point types are returned in XMM0,XMM1,XMMM2 and XMM3. - CCIfType<[f32, f64, f128], - CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, - - // Return integers in the standard way. - CCDelegateTo -]>; - -// X86-64 C return-value convention. -def RetCC_X86_64_C : CallingConv<[ - // The X86-64 calling convention always returns FP values in XMM0. - CCIfType<[f32], CCAssignToReg<[XMM0, XMM1]>>, - CCIfType<[f64], CCAssignToReg<[XMM0, XMM1]>>, - CCIfType<[f128], CCAssignToReg<[XMM0, XMM1]>>, - - // MMX vector types are always returned in XMM0. - CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1]>>, - - CCIfSwiftError>>, - - CCDelegateTo -]>; - -// X86-Win64 C return-value convention. -def RetCC_X86_Win64_C : CallingConv<[ - // The X86-Win64 calling convention always returns __m64 values in RAX. - CCIfType<[x86mmx], CCBitConvertToType>, - - // Otherwise, everything is the same as 'normal' X86-64 C CC. - CCDelegateTo -]>; - -// X86-64 vectorcall return-value convention. -def RetCC_X86_64_Vectorcall : CallingConv<[ - // Vectorcall calling convention always returns FP values in XMMs. - CCIfType<[f32, f64, f128], - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // Otherwise, everything is the same as Windows X86-64 C CC. - CCDelegateTo -]>; - -// X86-64 HiPE return-value convention. -def RetCC_X86_64_HiPE : CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: HP, P, VAL1, VAL2 - CCIfType<[i64], CCAssignToReg<[R15, RBP, RAX, RDX]>> -]>; - -// X86-64 WebKit_JS return-value convention. -def RetCC_X86_64_WebKit_JS : CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: RAX - CCIfType<[i64], CCAssignToReg<[RAX]>> -]>; - -def RetCC_X86_64_Swift : CallingConv<[ - - CCIfSwiftError>>, - - // For integers, ECX, R8D can be used as extra return registers. - CCIfType<[v1i1], CCPromoteToType>, - CCIfType<[i1], CCPromoteToType>, - CCIfType<[i8] , CCAssignToReg<[AL, DL, CL, R8B]>>, - CCIfType<[i16], CCAssignToReg<[AX, DX, CX, R8W]>>, - CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX, R8D]>>, - CCIfType<[i64], CCAssignToReg<[RAX, RDX, RCX, R8]>>, - - // XMM0, XMM1, XMM2 and XMM3 can be used to return FP values. - CCIfType<[f32], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[f64], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[f128], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // MMX vector types are returned in XMM0, XMM1, XMM2 and XMM3. - CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - CCDelegateTo -]>; - -// X86-64 AnyReg return-value convention. No explicit register is specified for -// the return-value. The register allocator is allowed and expected to choose -// any free register. -// -// This calling convention is currently only supported by the stackmap and -// patchpoint intrinsics. All other uses will result in an assert on Debug -// builds. On Release builds we fallback to the X86 C calling convention. -def RetCC_X86_64_AnyReg : CallingConv<[ - CCCustom<"CC_X86_AnyReg_Error"> -]>; - -// X86-64 HHVM return-value convention. -def RetCC_X86_64_HHVM: CallingConv<[ - // Promote all types to i64 - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Return: could return in any GP register save RSP and R12. - CCIfType<[i64], CCAssignToReg<[RBX, RBP, RDI, RSI, RDX, RCX, R8, R9, - RAX, R10, R11, R13, R14, R15]>> -]>; - - -defm X86_32_RegCall : - X86_RegCall_base; -defm X86_Win64_RegCall : - X86_RegCall_base; -defm X86_SysV64_RegCall : - X86_RegCall_base; - -// This is the root return-value convention for the X86-32 backend. -def RetCC_X86_32 : CallingConv<[ - // If FastCC, use RetCC_X86_32_Fast. - CCIfCC<"CallingConv::Fast", CCDelegateTo>, - // If HiPE, use RetCC_X86_32_HiPE. - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Otherwise, use RetCC_X86_32_C. - CCDelegateTo -]>; - -// This is the root return-value convention for the X86-64 backend. -def RetCC_X86_64 : CallingConv<[ - // HiPE uses RetCC_X86_64_HiPE - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - - // Handle JavaScript calls. - CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, - CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, - - // Handle Swift calls. - CCIfCC<"CallingConv::Swift", CCDelegateTo>, - - // Handle explicit CC selection - CCIfCC<"CallingConv::Win64", CCDelegateTo>, - CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, - - // Handle Vectorcall CC - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - - // Handle HHVM calls. - CCIfCC<"CallingConv::HHVM", CCDelegateTo>, - - CCIfCC<"CallingConv::X86_RegCall", - CCIfSubtarget<"isTargetWin64()", - CCDelegateTo>>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Mingw64 and native Win64 use Win64 CC - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - - // Otherwise, drop to normal X86-64 CC - CCDelegateTo -]>; - -// This is the return-value convention used for the entire X86 backend. -def RetCC_X86 : CallingConv<[ - - // Check if this is the Intel OpenCL built-ins calling convention - CCIfCC<"CallingConv::Intel_OCL_BI", CCDelegateTo>, - - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -//===----------------------------------------------------------------------===// -// X86-64 Argument Calling Conventions -//===----------------------------------------------------------------------===// - -def CC_X86_64_C : CallingConv<[ - // Handles byval parameters. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in R10. - CCIfNest>>, - CCIfNest>, - - // Pass SwiftSelf in a callee saved register. - CCIfSwiftSelf>>, - - // A SwiftError is passed in R12. - CCIfSwiftError>>, - - // For Swift Calling Convention, pass sret in %rax. - CCIfCC<"CallingConv::Swift", - CCIfSRet>>>, - - // The first 6 integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, - CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, - - // The first 8 MMX vector arguments are passed in XMM registers on Darwin. - CCIfType<[x86mmx], - CCIfSubtarget<"isTargetDarwin()", - CCIfSubtarget<"hasSSE2()", - CCPromoteToType>>>, - - // Boolean vectors of AVX-512 are passed in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // The first 8 FP/Vector arguments are passed in XMM registers. - CCIfType<[f32, f64, f128, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>>>, - - // The first 8 256-bit vector arguments are passed in YMM registers, unless - // this is a vararg function. - // FIXME: This isn't precisely correct; the x86-64 ABI document says that - // fixed arguments to vararg functions are supposed to be passed in - // registers. Actually modeling that would be a lot of work, though. - CCIfNotVarArg>>>, - - // The first 8 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, - - // Long doubles get stack slots whose size and alignment depends on the - // subtarget. - CCIfType<[f80, f128], CCAssignToStack<0, 0>>, - - // Vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, - - // 256-bit vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v16i32, v8i64, v16f32, v8f64], - CCAssignToStack<64, 64>> -]>; - -// Calling convention for X86-64 HHVM. -def CC_X86_64_HHVM : CallingConv<[ - // Use all/any GP registers for args, except RSP. - CCIfType<[i64], CCAssignToReg<[RBX, R12, RBP, R15, - RDI, RSI, RDX, RCX, R8, R9, - RAX, R10, R11, R13, R14]>> -]>; - -// Calling convention for helper functions in HHVM. -def CC_X86_64_HHVM_C : CallingConv<[ - // Pass the first argument in RBP. - CCIfType<[i64], CCAssignToReg<[RBP]>>, - - // Otherwise it's the same as the regular C calling convention. - CCDelegateTo -]>; - -// Calling convention used on Win64 -def CC_X86_Win64_C : CallingConv<[ - // FIXME: Handle byval stuff. - // FIXME: Handle varargs. - - // Promote i1/v1i1 arguments to i8. - CCIfType<[i1, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in R10. - CCIfNest>, - - // A SwiftError is passed in R12. - CCIfSwiftError>>, - - // 128 bit vectors are passed by pointer - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCPassIndirect>, - - - // 256 bit vectors are passed by pointer - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], CCPassIndirect>, - - // 512 bit vectors are passed by pointer - CCIfType<[v16i32, v16f32, v8f64, v8i64], CCPassIndirect>, - - // Long doubles are passed by pointer - CCIfType<[f80], CCPassIndirect>, - - // The first 4 MMX vector arguments are passed in GPRs. - CCIfType<[x86mmx], CCBitConvertToType>, - - // The first 4 integer arguments are passed in integer registers. - CCIfType<[i8 ], CCAssignToRegWithShadow<[CL , DL , R8B , R9B ], - [XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[i16], CCAssignToRegWithShadow<[CX , DX , R8W , R9W ], - [XMM0, XMM1, XMM2, XMM3]>>, - CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], - [XMM0, XMM1, XMM2, XMM3]>>, - - // Do not pass the sret argument in RCX, the Win64 thiscall calling - // convention requires "this" to be passed in RCX. - CCIfCC<"CallingConv::X86_ThisCall", - CCIfSRet>>>, - - CCIfType<[i64], CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], - [XMM0, XMM1, XMM2, XMM3]>>, - - // The first 4 FP/Vector arguments are passed in XMM registers. - CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToRegWithShadow<[XMM0, XMM1, XMM2, XMM3], - [RCX , RDX , R8 , R9 ]>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i8, i16, i32, i64, f32, f64], CCAssignToStack<8, 8>> -]>; - -def CC_X86_Win64_VectorCall : CallingConv<[ - CCCustom<"CC_X86_64_VectorCall">, - - // Delegate to fastcall to handle integer types. - CCDelegateTo -]>; - - -def CC_X86_64_GHC : CallingConv<[ - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, SpLim - CCIfType<[i64], - CCAssignToReg<[R13, RBP, R12, RBX, R14, RSI, RDI, R8, R9, R15]>>, - - // Pass in STG registers: F1, F2, F3, F4, D1, D2 - CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCIfSubtarget<"hasSSE1()", - CCAssignToReg<[XMM1, XMM2, XMM3, XMM4, XMM5, XMM6]>>>, - // AVX - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", - CCAssignToReg<[YMM1, YMM2, YMM3, YMM4, YMM5, YMM6]>>>, - // AVX-512 - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCIfSubtarget<"hasAVX512()", - CCAssignToReg<[ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6]>>> -]>; - -def CC_X86_64_HiPE : CallingConv<[ - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Pass in VM's registers: HP, P, ARG0, ARG1, ARG2, ARG3 - CCIfType<[i64], CCAssignToReg<[R15, RBP, RSI, RDX, RCX, R8]>>, - - // Integer/FP values get stored in stack slots that are 8 bytes in size and - // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>> -]>; - -def CC_X86_64_WebKit_JS : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Only the first integer argument is passed in register. - CCIfType<[i32], CCAssignToReg<[EAX]>>, - CCIfType<[i64], CCAssignToReg<[RAX]>>, - - // The remaining integer arguments are passed on the stack. 32bit integer and - // floating-point arguments are aligned to 4 byte and stored in 4 byte slots. - // 64bit integer and floating-point arguments are aligned to 8 byte and stored - // in 8 byte stack slots. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - CCIfType<[i64, f64], CCAssignToStack<8, 8>> -]>; - -// No explicit register is specified for the AnyReg calling convention. The -// register allocator may assign the arguments to any free register. -// -// This calling convention is currently only supported by the stackmap and -// patchpoint intrinsics. All other uses will result in an assert on Debug -// builds. On Release builds we fallback to the X86 C calling convention. -def CC_X86_64_AnyReg : CallingConv<[ - CCCustom<"CC_X86_AnyReg_Error"> -]>; - -//===----------------------------------------------------------------------===// -// X86 C Calling Convention -//===----------------------------------------------------------------------===// - -/// CC_X86_32_Vector_Common - In all X86-32 calling conventions, extra vector -/// values are spilled on the stack. -def CC_X86_32_Vector_Common : CallingConv<[ - // Other SSE vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, - - // 256-bit AVX vectors get 32-byte stack slots that are 32-byte aligned. - CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // 512-bit AVX 512-bit vectors get 64-byte stack slots that are 64-byte aligned. - CCIfType<[v64i8, v32i16, v16i32, v8i64, v16f32, v8f64], - CCAssignToStack<64, 64>> -]>; - -// CC_X86_32_Vector_Standard - The first 3 vector arguments are passed in -// vector registers -def CC_X86_32_Vector_Standard : CallingConv<[ - // SSE vector arguments are passed in XMM registers. - CCIfNotVarArg>>, - - // AVX 256-bit vector arguments are passed in YMM registers. - CCIfNotVarArg>>>, - - // AVX 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>, - - CCDelegateTo -]>; - -// CC_X86_32_Vector_Darwin - The first 4 vector arguments are passed in -// vector registers. -def CC_X86_32_Vector_Darwin : CallingConv<[ - // SSE vector arguments are passed in XMM registers. - CCIfNotVarArg>>, - - // AVX 256-bit vector arguments are passed in YMM registers. - CCIfNotVarArg>>>, - - // AVX 512-bit vector arguments are passed in ZMM registers. - CCIfNotVarArg>>, - - CCDelegateTo -]>; - -/// CC_X86_32_Common - In all X86-32 calling conventions, extra integers and FP -/// values are spilled on the stack. -def CC_X86_32_Common : CallingConv<[ - // Handles byval parameters. - CCIfByVal>, - - // The first 3 float or double arguments, if marked 'inreg' and if the call - // is not a vararg call and if SSE2 is available, are passed in SSE registers. - CCIfNotVarArg>>>>, - - // The first 3 __m64 vector arguments are passed in mmx registers if the - // call is not a vararg call. - CCIfNotVarArg>>, - - // Integer/Float values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - - // Doubles get 8-byte slots that are 4-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 4>>, - - // Long doubles get slots whose size depends on the subtarget. - CCIfType<[f80], CCAssignToStack<0, 4>>, - - // Boolean vectors of AVX-512 are passed in SIMD registers. - // The call from AVX to AVX-512 function should work, - // since the boolean types in AVX/AVX2 are promoted by default. - CCIfType<[v2i1], CCPromoteToType>, - CCIfType<[v4i1], CCPromoteToType>, - CCIfType<[v8i1], CCPromoteToType>, - CCIfType<[v16i1], CCPromoteToType>, - CCIfType<[v32i1], CCPromoteToType>, - CCIfType<[v64i1], CCPromoteToType>, - - // __m64 vectors get 8-byte stack slots that are 4-byte aligned. They are - // passed in the parameter area. - CCIfType<[x86mmx], CCAssignToStack<8, 4>>, - - // Darwin passes vectors in a form that differs from the i386 psABI - CCIfSubtarget<"isTargetDarwin()", CCDelegateTo>, - - // Otherwise, drop to 'normal' X86-32 CC - CCDelegateTo -]>; - -def CC_X86_32_C : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in ECX. - CCIfNest>, - - // The first 3 integer arguments, if marked 'inreg' and if the call is not - // a vararg call, are passed in integer registers. - CCIfNotVarArg>>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_MCU : CallingConv<[ - // Handles byval parameters. Note that, like FastCC, we can't rely on - // the delegation to CC_X86_32_Common because that happens after code that - // puts arguments in registers. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // If the call is not a vararg call, some arguments may be passed - // in integer registers. - CCIfNotVarArg>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_FastCall : CallingConv<[ - // Promote i1 to i8. - CCIfType<[i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in EAX. - CCIfNest>, - - // The first 2 integer arguments are passed in ECX/EDX - CCIfInReg>>, - CCIfInReg>>, - CCIfInReg>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_Win32_VectorCall : CallingConv<[ - // Pass floating point in XMMs - CCCustom<"CC_X86_32_VectorCall">, - - // Delegate to fastcall to handle integer types. - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Common : CallingConv<[ - // The first integer argument is passed in ECX - CCIfType<[i32], CCAssignToReg<[ECX]>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Mingw : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - CCDelegateTo -]>; - -def CC_X86_32_ThisCall_Win : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // Pass sret arguments indirectly through stack. - CCIfSRet>, - - CCDelegateTo -]>; - -def CC_X86_32_ThisCall : CallingConv<[ - CCIfSubtarget<"isTargetCygMing()", CCDelegateTo>, - CCDelegateTo -]>; - -def CC_X86_32_FastCC : CallingConv<[ - // Handles byval parameters. Note that we can't rely on the delegation - // to CC_X86_32_Common for this because that happens after code that - // puts arguments in registers. - CCIfByVal>, - - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, - - // The 'nest' parameter, if any, is passed in EAX. - CCIfNest>, - - // The first 2 integer arguments are passed in ECX/EDX - CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>, - - // The first 3 float or double arguments, if the call is not a vararg - // call and if SSE2 is available, are passed in SSE registers. - CCIfNotVarArg>>>, - - // Doubles get 8-byte slots that are 8-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 8>>, - - // Otherwise, same as everything else. - CCDelegateTo -]>; - -def CC_X86_32_GHC : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1 - CCIfType<[i32], CCAssignToReg<[EBX, EBP, EDI, ESI]>> -]>; - -def CC_X86_32_HiPE : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType>, - - // Pass in VM's registers: HP, P, ARG0, ARG1, ARG2 - CCIfType<[i32], CCAssignToReg<[ESI, EBP, EAX, EDX, ECX]>>, - - // Integer/Float values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>> -]>; - -// X86-64 Intel OpenCL built-ins calling convention. -def CC_Intel_OCL_BI : CallingConv<[ - - CCIfType<[i32], CCIfSubtarget<"isTargetWin64()", CCAssignToReg<[ECX, EDX, R8D, R9D]>>>, - CCIfType<[i64], CCIfSubtarget<"isTargetWin64()", CCAssignToReg<[RCX, RDX, R8, R9 ]>>>, - - CCIfType<[i32], CCIfSubtarget<"is64Bit()", CCAssignToReg<[EDI, ESI, EDX, ECX]>>>, - CCIfType<[i64], CCIfSubtarget<"is64Bit()", CCAssignToReg<[RDI, RSI, RDX, RCX]>>>, - - CCIfType<[i32], CCAssignToStack<4, 4>>, - - // The SSE vector arguments are passed in XMM registers. - CCIfType<[f32, f64, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, - - // The 256-bit vector arguments are passed in YMM registers. - CCIfType<[v8f32, v4f64, v8i32, v4i64], - CCAssignToReg<[YMM0, YMM1, YMM2, YMM3]>>, - - // The 512-bit vector arguments are passed in ZMM registers. - CCIfType<[v16f32, v8f64, v16i32, v8i64], - CCAssignToReg<[ZMM0, ZMM1, ZMM2, ZMM3]>>, - - // Pass masks in mask registers - CCIfType<[v16i1, v8i1], CCAssignToReg<[K1]>>, - - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -def CC_X86_32_Intr : CallingConv<[ - CCAssignToStack<4, 4> -]>; - -def CC_X86_64_Intr : CallingConv<[ - CCAssignToStack<8, 8> -]>; - -//===----------------------------------------------------------------------===// -// X86 Root Argument Calling Conventions -//===----------------------------------------------------------------------===// - -// This is the root argument convention for the X86-32 backend. -def CC_X86_32 : CallingConv<[ - // X86_INTR calling convention is valid in MCU target and should override the - // MCU calling convention. Thus, this should be checked before isTargetMCU(). - CCIfCC<"CallingConv::X86_INTR", CCDelegateTo>, - CCIfSubtarget<"isTargetMCU()", CCDelegateTo>, - CCIfCC<"CallingConv::X86_FastCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_ThisCall", CCDelegateTo>, - CCIfCC<"CallingConv::Fast", CCDelegateTo>, - CCIfCC<"CallingConv::GHC", CCDelegateTo>, - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - - // Otherwise, drop to normal X86-32 CC - CCDelegateTo -]>; - -// This is the root argument convention for the X86-64 backend. -def CC_X86_64 : CallingConv<[ - CCIfCC<"CallingConv::GHC", CCDelegateTo>, - CCIfCC<"CallingConv::HiPE", CCDelegateTo>, - CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, - CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, - CCIfCC<"CallingConv::Win64", CCDelegateTo>, - CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, - CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, - CCIfCC<"CallingConv::HHVM", CCDelegateTo>, - CCIfCC<"CallingConv::HHVM_C", CCDelegateTo>, - CCIfCC<"CallingConv::X86_RegCall", - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>>, - CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, - CCIfCC<"CallingConv::X86_INTR", CCDelegateTo>, - - // Mingw64 and native Win64 use Win64 CC - CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, - - // Otherwise, drop to normal X86-64 CC - CCDelegateTo -]>; - -// This is the argument convention used for the entire X86 backend. -def CC_X86 : CallingConv<[ - CCIfCC<"CallingConv::Intel_OCL_BI", CCDelegateTo>, - CCIfSubtarget<"is64Bit()", CCDelegateTo>, - CCDelegateTo -]>; - -//===----------------------------------------------------------------------===// -// Callee-saved Registers. -//===----------------------------------------------------------------------===// - -def CSR_NoRegs : CalleeSavedRegs<(add)>; - -def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>; -def CSR_64 : CalleeSavedRegs<(add RBX, R12, R13, R14, R15, RBP)>; - -def CSR_64_SwiftError : CalleeSavedRegs<(sub CSR_64, R12)>; - -def CSR_32EHRet : CalleeSavedRegs<(add EAX, EDX, CSR_32)>; -def CSR_64EHRet : CalleeSavedRegs<(add RAX, RDX, CSR_64)>; - -def CSR_Win64_NoSSE : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, R13, R14, R15)>; - -def CSR_Win64 : CalleeSavedRegs<(add CSR_Win64_NoSSE, - (sequence "XMM%u", 6, 15))>; - -def CSR_Win64_SwiftError : CalleeSavedRegs<(sub CSR_Win64, R12)>; - -// The function used by Darwin to obtain the address of a thread-local variable -// uses rdi to pass a single parameter and rax for the return value. All other -// GPRs are preserved. -def CSR_64_TLS_Darwin : CalleeSavedRegs<(add CSR_64, RCX, RDX, RSI, - R8, R9, R10, R11)>; - -// CSRs that are handled by prologue, epilogue. -def CSR_64_CXX_TLS_Darwin_PE : CalleeSavedRegs<(add RBP)>; - -// CSRs that are handled explicitly via copies. -def CSR_64_CXX_TLS_Darwin_ViaCopy : CalleeSavedRegs<(sub CSR_64_TLS_Darwin, RBP)>; - -// All GPRs - except r11 -def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI, - R8, R9, R10, RSP)>; - -// All registers - except r11 -def CSR_64_RT_AllRegs : CalleeSavedRegs<(add CSR_64_RT_MostRegs, - (sequence "XMM%u", 0, 15))>; -def CSR_64_RT_AllRegs_AVX : CalleeSavedRegs<(add CSR_64_RT_MostRegs, - (sequence "YMM%u", 0, 15))>; - -def CSR_64_MostRegs : CalleeSavedRegs<(add RBX, RCX, RDX, RSI, RDI, R8, R9, R10, - R11, R12, R13, R14, R15, RBP, - (sequence "XMM%u", 0, 15))>; - -def CSR_32_AllRegs : CalleeSavedRegs<(add EAX, EBX, ECX, EDX, EBP, ESI, - EDI)>; -def CSR_32_AllRegs_SSE : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "XMM%u", 0, 7))>; -def CSR_32_AllRegs_AVX : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "YMM%u", 0, 7))>; -def CSR_32_AllRegs_AVX512 : CalleeSavedRegs<(add CSR_32_AllRegs, - (sequence "ZMM%u", 0, 7), - (sequence "K%u", 0, 7))>; - -def CSR_64_AllRegs : CalleeSavedRegs<(add CSR_64_MostRegs, RAX)>; -def CSR_64_AllRegs_NoSSE : CalleeSavedRegs<(add RAX, RBX, RCX, RDX, RSI, RDI, R8, R9, - R10, R11, R12, R13, R14, R15, RBP)>; -def CSR_64_AllRegs_AVX : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX, - (sequence "YMM%u", 0, 15)), - (sequence "XMM%u", 0, 15))>; -def CSR_64_AllRegs_AVX512 : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX, - (sequence "ZMM%u", 0, 31), - (sequence "K%u", 0, 7)), - (sequence "XMM%u", 0, 15))>; - -// Standard C + YMM6-15 -def CSR_Win64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, - R13, R14, R15, - (sequence "YMM%u", 6, 15))>; - -def CSR_Win64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, - R12, R13, R14, R15, - (sequence "ZMM%u", 6, 21), - K4, K5, K6, K7)>; -//Standard C + XMM 8-15 -def CSR_64_Intel_OCL_BI : CalleeSavedRegs<(add CSR_64, - (sequence "XMM%u", 8, 15))>; - -//Standard C + YMM 8-15 -def CSR_64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add CSR_64, - (sequence "YMM%u", 8, 15))>; - -def CSR_64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RDI, RSI, R14, R15, - (sequence "ZMM%u", 16, 31), - K4, K5, K6, K7)>; - -// Only R12 is preserved for PHP calls in HHVM. -def CSR_64_HHVM : CalleeSavedRegs<(add R12)>; - -// Register calling convention preserves few GPR and XMM8-15 -def CSR_32_RegCall_NoSSE : CalleeSavedRegs<(add ESI, EDI, EBX, EBP, ESP)>; -def CSR_32_RegCall : CalleeSavedRegs<(add CSR_32_RegCall_NoSSE, - (sequence "XMM%u", 4, 7))>; -def CSR_Win64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, RSP, - (sequence "R%u", 10, 15))>; -def CSR_Win64_RegCall : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE, - (sequence "XMM%u", 8, 15))>; -def CSR_SysV64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, RSP, - (sequence "R%u", 12, 15))>; -def CSR_SysV64_RegCall : CalleeSavedRegs<(add CSR_SysV64_RegCall_NoSSE, - (sequence "XMM%u", 8, 15))>; - diff --git a/suite/synctools/tablegen/X86/back/X86Capstone.td b/suite/synctools/tablegen/X86/back/X86Capstone.td deleted file mode 100644 index ca21b63a01..0000000000 --- a/suite/synctools/tablegen/X86/back/X86Capstone.td +++ /dev/null @@ -1,7 +0,0 @@ -// Capstone definitions fix for X86 LLVM instructions. - -let Defs = [EFLAGS] in - def INT1 : I<0xf1, RawFrm, (outs), (ins), "int1", []>; - -// def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", [], IIC_FNCLEX>; -def FSETPM : I<0xDB, MRM_E4, (outs), (ins), "fsetpm", []>; diff --git a/suite/synctools/tablegen/X86/back/X86CapstoneFull.td b/suite/synctools/tablegen/X86/back/X86CapstoneFull.td deleted file mode 100644 index 5bd4095dd9..0000000000 --- a/suite/synctools/tablegen/X86/back/X86CapstoneFull.td +++ /dev/null @@ -1,103 +0,0 @@ -// Capstone definitions fix for X86 LLVM instructions. - -let Defs = [EFLAGS] in - def INT1 : I<0xf1, RawFrm, (outs), (ins), "int1", []>; - -def FSETPM : I<0xDB, MRM_E4, (outs), (ins), "fsetpm", []>; - -// Capstone: comment out below lines for X86 Reduce mode - -/* -// X87 Floating Point Stack. -include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -include "X86InstrFMA.td" - -// XOP -include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -include "X86InstrSSE.td" -include "X86InstrAVX512.td" -include "X86InstrMMX.td" -include "X86Instr3DNow.td" - -// MPX instructions -include "X86InstrMPX.td" - -//include "X86InstrTSX.td" -include "X86InstrSGX.td" - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -def : InstAlias<"fxch", (XCH_F ST1), 0>; -def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; - -def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; -*/ diff --git a/suite/synctools/tablegen/X86/back/X86CapstoneReduce.td b/suite/synctools/tablegen/X86/back/X86CapstoneReduce.td deleted file mode 100644 index 2c0920e74a..0000000000 --- a/suite/synctools/tablegen/X86/back/X86CapstoneReduce.td +++ /dev/null @@ -1,101 +0,0 @@ -// Capstone definitions fix for X86 LLVM instructions. - -let Defs = [EFLAGS] in - def INT1 : I<0xf1, RawFrm, (outs), (ins), "int1", []>; - -def FSETPM : I<0xDB, MRM_E4, (outs), (ins), "fsetpm", []>; - -// Capstone: comment out below lines for X86 Reduce mode - -// X87 Floating Point Stack. -//include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -//include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -//include "X86InstrFMA.td" - -// XOP -//include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -//include "X86InstrSSE.td" -//include "X86InstrAVX512.td" -//include "X86InstrMMX.td" -//include "X86Instr3DNow.td" - -// MPX instructions -//include "X86InstrMPX.td" - -//include "X86InstrTSX.td" -//include "X86InstrSGX.td" - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -//def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -//def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -//def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -//def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -//def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -//def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -//def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -//def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -//def : InstAlias<"fxch", (XCH_F ST1), 0>; -//def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -//def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -//def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -//def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -//def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -//def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -//def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -//def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -//defm : FpUnaryAlias<"fadd", ADD_FST0r>; -//defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -//defm : FpUnaryAlias<"fsub", SUB_FST0r>; -//defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -//defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -//defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -//defm : FpUnaryAlias<"fmul", MUL_FST0r>; -//defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -//defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -//defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -//defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -//defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -//defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -//defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -//defm : FpUnaryAlias<"fcompi", COM_FIPr>; -//defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -//def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -//def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -//def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -//def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -//def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -//def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; -// -//def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -//def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -//def : InstAlias<"movd\t{$src, $dst|$dst, $src}", -// (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; diff --git a/suite/synctools/tablegen/X86/back/X86Instr3DNow.td b/suite/synctools/tablegen/X86/back/X86Instr3DNow.td deleted file mode 100644 index 46dc6bf766..0000000000 --- a/suite/synctools/tablegen/X86/back/X86Instr3DNow.td +++ /dev/null @@ -1,111 +0,0 @@ -//===-- X86Instr3DNow.td - The 3DNow! Instruction Set ------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the 3DNow! instruction set, which extends MMX to support -// floating point and also adds a few more random instructions for good measure. -// -//===----------------------------------------------------------------------===// - -class I3DNow o, Format F, dag outs, dag ins, string asm, list pat> - : I, Requires<[Has3DNow]> { -} - -class I3DNow_binop o, Format F, dag ins, string Mnemonic, list pat> - : I3DNow, ThreeDNow { - let Constraints = "$src1 = $dst"; -} - -class I3DNow_conv o, Format F, dag ins, string Mnemonic, list pat> - : I3DNow, ThreeDNow; - -multiclass I3DNow_binop_rm_int opc, string Mn, - X86FoldableSchedWrite sched, bit Commutable = 0, - string Ver = ""> { - let isCommutable = Commutable in - def rr : I3DNow_binop( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, VR64:$src2))]>, - Sched<[sched]>; - def rm : I3DNow_binop( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, - (bitconvert (load_mmx addr:$src2))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass I3DNow_conv_rm_int opc, string Mn, - X86FoldableSchedWrite sched, string Ver = ""> { - def rr : I3DNow_conv( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src))]>, - Sched<[sched]>; - def rm : I3DNow_conv( - !strconcat("int_x86_3dnow", Ver, "_", Mn)) - (bitconvert (load_mmx addr:$src))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -defm PAVGUSB : I3DNow_binop_rm_int<0xBF, "pavgusb", SchedWriteVecALU.MMX, 1>; -defm PF2ID : I3DNow_conv_rm_int<0x1D, "pf2id", WriteCvtPS2I>; -defm PFACC : I3DNow_binop_rm_int<0xAE, "pfacc", WriteFAdd>; -defm PFADD : I3DNow_binop_rm_int<0x9E, "pfadd", WriteFAdd, 1>; -defm PFCMPEQ : I3DNow_binop_rm_int<0xB0, "pfcmpeq", WriteFAdd, 1>; -defm PFCMPGE : I3DNow_binop_rm_int<0x90, "pfcmpge", WriteFAdd>; -defm PFCMPGT : I3DNow_binop_rm_int<0xA0, "pfcmpgt", WriteFAdd>; -defm PFMAX : I3DNow_binop_rm_int<0xA4, "pfmax", WriteFAdd>; -defm PFMIN : I3DNow_binop_rm_int<0x94, "pfmin", WriteFAdd>; -defm PFMUL : I3DNow_binop_rm_int<0xB4, "pfmul", WriteFAdd, 1>; -defm PFRCP : I3DNow_conv_rm_int<0x96, "pfrcp", WriteFAdd>; -defm PFRCPIT1 : I3DNow_binop_rm_int<0xA6, "pfrcpit1", WriteFAdd>; -defm PFRCPIT2 : I3DNow_binop_rm_int<0xB6, "pfrcpit2", WriteFAdd>; -defm PFRSQIT1 : I3DNow_binop_rm_int<0xA7, "pfrsqit1", WriteFAdd>; -defm PFRSQRT : I3DNow_conv_rm_int<0x97, "pfrsqrt", WriteFAdd>; -defm PFSUB : I3DNow_binop_rm_int<0x9A, "pfsub", WriteFAdd, 1>; -defm PFSUBR : I3DNow_binop_rm_int<0xAA, "pfsubr", WriteFAdd, 1>; -defm PI2FD : I3DNow_conv_rm_int<0x0D, "pi2fd", WriteCvtI2PS>; -defm PMULHRW : I3DNow_binop_rm_int<0xB7, "pmulhrw", SchedWriteVecIMul.MMX, 1>; - -let SchedRW = [WriteEMMS] in -def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms", - [(int_x86_mmx_femms)]>, TB; - -// PREFETCHWT1 is supported we want to use it for everything but T0. -def PrefetchWLevel : PatFrag<(ops), (i32 imm), [{ - return N->getSExtValue() == 3 || !Subtarget->hasPREFETCHWT1(); -}]>; - -// Use PREFETCHWT1 for NTA, T2, T1. -def PrefetchWT1Level : ImmLeaf; - -let SchedRW = [WriteLoad] in { -let Predicates = [Has3DNow, NoSSEPrefetch] in -def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr), - "prefetch\t$addr", - [(prefetch addr:$addr, imm, imm, (i32 1))]>, TB; - -def PREFETCHW : I<0x0D, MRM1m, (outs), (ins i8mem:$addr), "prefetchw\t$addr", - [(prefetch addr:$addr, (i32 1), (i32 PrefetchWLevel), (i32 1))]>, - TB, Requires<[HasPrefetchW]>; - -def PREFETCHWT1 : I<0x0D, MRM2m, (outs), (ins i8mem:$addr), "prefetchwt1\t$addr", - [(prefetch addr:$addr, (i32 1), (i32 PrefetchWT1Level), (i32 1))]>, - TB, Requires<[HasPREFETCHWT1]>; -} - -// "3DNowA" instructions -defm PF2IW : I3DNow_conv_rm_int<0x1C, "pf2iw", WriteCvtPS2I, "a">; -defm PI2FW : I3DNow_conv_rm_int<0x0C, "pi2fw", WriteCvtI2PS, "a">; -defm PFNACC : I3DNow_binop_rm_int<0x8A, "pfnacc", WriteFAdd, 0, "a">; -defm PFPNACC : I3DNow_binop_rm_int<0x8E, "pfpnacc", WriteFAdd, 0, "a">; -defm PSWAPD : I3DNow_conv_rm_int<0xBB, "pswapd", SchedWriteShuffle.MMX, "a">; diff --git a/suite/synctools/tablegen/X86/back/X86InstrAVX512.td b/suite/synctools/tablegen/X86/back/X86InstrAVX512.td deleted file mode 100644 index fcb3723121..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrAVX512.td +++ /dev/null @@ -1,11968 +0,0 @@ -//===-- X86InstrAVX512.td - AVX512 Instruction Set ---------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 AVX512 instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -// Group template arguments that can be derived from the vector type (EltNum x -// EltVT). These are things like the register class for the writemask, etc. -// The idea is to pass one of these as the template argument rather than the -// individual arguments. -// The template is also used for scalar types, in this case numelts is 1. -class X86VectorVTInfo { - RegisterClass RC = rc; - ValueType EltVT = eltvt; - int NumElts = numelts; - - // Corresponding mask register class. - RegisterClass KRC = !cast("VK" # NumElts); - - // Corresponding write-mask register class. - RegisterClass KRCWM = !cast("VK" # NumElts # "WM"); - - // The mask VT. - ValueType KVT = !cast("v" # NumElts # "i1"); - - // Suffix used in the instruction mnemonic. - string Suffix = suffix; - - // VTName is a string name for vector VT. For vector types it will be - // v # NumElts # EltVT, so for vector of 8 elements of i32 it will be v8i32 - // It is a little bit complex for scalar types, where NumElts = 1. - // In this case we build v4f32 or v2f64 - string VTName = "v" # !if (!eq (NumElts, 1), - !if (!eq (EltVT.Size, 32), 4, - !if (!eq (EltVT.Size, 64), 2, NumElts)), NumElts) # EltVT; - - // The vector VT. - ValueType VT = !cast(VTName); - - string EltTypeName = !cast(EltVT); - // Size of the element type in bits, e.g. 32 for v16i32. - string EltSizeName = !subst("i", "", !subst("f", "", EltTypeName)); - int EltSize = EltVT.Size; - - // "i" for integer types and "f" for floating-point types - string TypeVariantName = !subst(EltSizeName, "", EltTypeName); - - // Size of RC in bits, e.g. 512 for VR512. - int Size = VT.Size; - - // The corresponding memory operand, e.g. i512mem for VR512. - X86MemOperand MemOp = !cast(TypeVariantName # Size # "mem"); - X86MemOperand ScalarMemOp = !cast(EltVT # "mem"); - // FP scalar memory operand for intrinsics - ssmem/sdmem. - Operand IntScalarMemOp = !if (!eq (EltTypeName, "f32"), !cast("ssmem"), - !if (!eq (EltTypeName, "f64"), !cast("sdmem"), ?)); - - // Load patterns - // Note: For 128/256-bit integer VT we choose loadv2i64/loadv4i64 - // due to load promotion during legalization - PatFrag LdFrag = !cast("load" # - !if (!eq (TypeVariantName, "i"), - !if (!eq (Size, 128), "v2i64", - !if (!eq (Size, 256), "v4i64", - !if (!eq (Size, 512), "v8i64", - VTName))), VTName)); - - PatFrag AlignedLdFrag = !cast("alignedload" # - !if (!eq (TypeVariantName, "i"), - !if (!eq (Size, 128), "v2i64", - !if (!eq (Size, 256), "v4i64", - !if (!eq (Size, 512), "v8i64", - VTName))), VTName)); - - PatFrag ScalarLdFrag = !cast("load" # EltVT); - - ComplexPattern ScalarIntMemCPat = !if (!eq (EltTypeName, "f32"), - !cast("sse_load_f32"), - !if (!eq (EltTypeName, "f64"), - !cast("sse_load_f64"), - ?)); - - // The string to specify embedded broadcast in assembly. - string BroadcastStr = "{1to" # NumElts # "}"; - - // 8-bit compressed displacement tuple/subvector format. This is only - // defined for NumElts <= 8. - CD8VForm CD8TupleForm = !if (!eq (!srl(NumElts, 4), 0), - !cast("CD8VT" # NumElts), ?); - - SubRegIndex SubRegIdx = !if (!eq (Size, 128), sub_xmm, - !if (!eq (Size, 256), sub_ymm, ?)); - - Domain ExeDomain = !if (!eq (EltTypeName, "f32"), SSEPackedSingle, - !if (!eq (EltTypeName, "f64"), SSEPackedDouble, - SSEPackedInt)); - - RegisterClass FRC = !if (!eq (EltTypeName, "f32"), FR32X, FR64X); - - // A vector type of the same width with element type i64. This is used to - // create patterns for logic ops. - ValueType i64VT = !cast("v" # !srl(Size, 6) # "i64"); - - // A vector type of the same width with element type i32. This is used to - // create the canonical constant zero node ImmAllZerosV. - ValueType i32VT = !cast("v" # !srl(Size, 5) # "i32"); - dag ImmAllZerosV = (VT (bitconvert (i32VT immAllZerosV))); - - string ZSuffix = !if (!eq (Size, 128), "Z128", - !if (!eq (Size, 256), "Z256", "Z")); -} - -def v64i8_info : X86VectorVTInfo<64, i8, VR512, "b">; -def v32i16_info : X86VectorVTInfo<32, i16, VR512, "w">; -def v16i32_info : X86VectorVTInfo<16, i32, VR512, "d">; -def v8i64_info : X86VectorVTInfo<8, i64, VR512, "q">; -def v16f32_info : X86VectorVTInfo<16, f32, VR512, "ps">; -def v8f64_info : X86VectorVTInfo<8, f64, VR512, "pd">; - -// "x" in v32i8x_info means RC = VR256X -def v32i8x_info : X86VectorVTInfo<32, i8, VR256X, "b">; -def v16i16x_info : X86VectorVTInfo<16, i16, VR256X, "w">; -def v8i32x_info : X86VectorVTInfo<8, i32, VR256X, "d">; -def v4i64x_info : X86VectorVTInfo<4, i64, VR256X, "q">; -def v8f32x_info : X86VectorVTInfo<8, f32, VR256X, "ps">; -def v4f64x_info : X86VectorVTInfo<4, f64, VR256X, "pd">; - -def v16i8x_info : X86VectorVTInfo<16, i8, VR128X, "b">; -def v8i16x_info : X86VectorVTInfo<8, i16, VR128X, "w">; -def v4i32x_info : X86VectorVTInfo<4, i32, VR128X, "d">; -def v2i64x_info : X86VectorVTInfo<2, i64, VR128X, "q">; -def v4f32x_info : X86VectorVTInfo<4, f32, VR128X, "ps">; -def v2f64x_info : X86VectorVTInfo<2, f64, VR128X, "pd">; - -// We map scalar types to the smallest (128-bit) vector type -// with the appropriate element type. This allows to use the same masking logic. -def i32x_info : X86VectorVTInfo<1, i32, GR32, "si">; -def i64x_info : X86VectorVTInfo<1, i64, GR64, "sq">; -def f32x_info : X86VectorVTInfo<1, f32, VR128X, "ss">; -def f64x_info : X86VectorVTInfo<1, f64, VR128X, "sd">; - -class AVX512VLVectorVTInfo { - X86VectorVTInfo info512 = i512; - X86VectorVTInfo info256 = i256; - X86VectorVTInfo info128 = i128; -} - -def avx512vl_i8_info : AVX512VLVectorVTInfo; -def avx512vl_i16_info : AVX512VLVectorVTInfo; -def avx512vl_i32_info : AVX512VLVectorVTInfo; -def avx512vl_i64_info : AVX512VLVectorVTInfo; -def avx512vl_f32_info : AVX512VLVectorVTInfo; -def avx512vl_f64_info : AVX512VLVectorVTInfo; - -class X86KVectorVTInfo { - RegisterClass KRC = _krc; - RegisterClass KRCWM = _krcwm; - ValueType KVT = _vt; -} - -def v1i1_info : X86KVectorVTInfo; -def v2i1_info : X86KVectorVTInfo; -def v4i1_info : X86KVectorVTInfo; -def v8i1_info : X86KVectorVTInfo; -def v16i1_info : X86KVectorVTInfo; -def v32i1_info : X86KVectorVTInfo; -def v64i1_info : X86KVectorVTInfo; - -// This multiclass generates the masking variants from the non-masking -// variant. It only provides the assembly pieces for the masking variants. -// It assumes custom ISel patterns for masking which can be provided as -// template arguments. -multiclass AVX512_maskable_custom O, Format F, - dag Outs, - dag Ins, dag MaskingIns, dag ZeroMaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern, - list MaskingPattern, - list ZeroMaskingPattern, - string MaskingConstraint = "", - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable> { - let isCommutable = IsCommutable in - def NAME: AVX512; - - // Prefer over VMOV*rrk Pat<> - let isCommutable = IsKCommutable in - def NAME#k: AVX512, - EVEX_K { - // In case of the 3src subclass this is overridden with a let. - string Constraints = MaskingConstraint; - } - - // Zero mask does not add any restrictions to commute operands transformation. - // So, it is Ok to use IsCommutable instead of IsKCommutable. - let isCommutable = IsKZCommutable in // Prefer over VMOV*rrkz Pat<> - def NAME#kz: AVX512, - EVEX_KZ; -} - - -// Common base class of AVX512_maskable and AVX512_maskable_3src. -multiclass AVX512_maskable_common O, Format F, X86VectorVTInfo _, - dag Outs, - dag Ins, dag MaskingIns, dag ZeroMaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskingRHS, - SDNode Select = vselect, - string MaskingConstraint = "", - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable> : - AVX512_maskable_custom; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -// This version uses a separate dag for non-masking and masking. -multiclass AVX512_maskable_split O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskRHS, - bit IsCommutable = 0, bit IsKCommutable = 0, - SDNode Select = vselect> : - AVX512_maskable_custom; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -multiclass AVX512_maskable O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, bit IsKCommutable = 0, - bit IsKZCommutable = IsCommutable, - SDNode Select = vselect> : - AVX512_maskable_common; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the scalar instruction. -multiclass AVX512_maskable_scalar O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0> : - AVX512_maskable; - -// Similar to AVX512_maskable but in this case one of the source operands -// ($src1) is already tied to $dst so we just use that for the preserved -// vector elements. NOTE that the NonTiedIns (the ins dag) should exclude -// $src1. -multiclass AVX512_maskable_3src O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, - bit IsKCommutable = 0, - SDNode Select = vselect, - bit MaskOnly = 0> : - AVX512_maskable_common; - -// Similar to AVX512_maskable_3src but in this case the input VT for the tied -// operand differs from the output VT. This requires a bitconvert on -// the preserved vector going into the vselect. -// NOTE: The unmasked pattern is disabled. -multiclass AVX512_maskable_3src_cast O, Format F, X86VectorVTInfo OutVT, - X86VectorVTInfo InVT, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, bit IsCommutable = 0> : - AVX512_maskable_common; - -multiclass AVX512_maskable_3src_scalar O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, - bit IsCommutable = 0, - bit IsKCommutable = 0, - bit MaskOnly = 0> : - AVX512_maskable_3src; - -multiclass AVX512_maskable_in_asm O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern> : - AVX512_maskable_custom; - -multiclass AVX512_maskable_3src_in_asm O, Format F, X86VectorVTInfo _, - dag Outs, dag NonTiedIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern> : - AVX512_maskable_custom; - -// Instruction with mask that puts result in mask register, -// like "compare" and "vptest" -multiclass AVX512_maskable_custom_cmp O, Format F, - dag Outs, - dag Ins, dag MaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - list Pattern, - list MaskingPattern, - bit IsCommutable = 0> { - let isCommutable = IsCommutable in - def NAME: AVX512; - - def NAME#k: AVX512, EVEX_K; -} - -multiclass AVX512_maskable_common_cmp O, Format F, X86VectorVTInfo _, - dag Outs, - dag Ins, dag MaskingIns, - string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskingRHS, - bit IsCommutable = 0> : - AVX512_maskable_custom_cmp; - -multiclass AVX512_maskable_cmp O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, bit IsCommutable = 0> : - AVX512_maskable_common_cmp; - -multiclass AVX512_maskable_cmp_alt O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm> : - AVX512_maskable_custom_cmp; - -// This multiclass generates the unconditional/non-masking, the masking and -// the zero-masking variant of the vector instruction. In the masking case, the -// preserved vector elements come from a new dummy input operand tied to $dst. -multiclass AVX512_maskable_logic O, Format F, X86VectorVTInfo _, - dag Outs, dag Ins, string OpcodeStr, - string AttSrcAsm, string IntelSrcAsm, - dag RHS, dag MaskedRHS, - bit IsCommutable = 0, SDNode Select = vselect> : - AVX512_maskable_custom; - - -// Alias instruction that maps zero vector to pxor / xorp* for AVX-512. -// This is expanded by ExpandPostRAPseudos to an xorps / vxorps, and then -// swizzled by ExecutionDomainFix to pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteZero] in { -def AVX512_512_SET0 : I<0, Pseudo, (outs VR512:$dst), (ins), "", - [(set VR512:$dst, (v16i32 immAllZerosV))]>; -def AVX512_512_SETALLONES : I<0, Pseudo, (outs VR512:$dst), (ins), "", - [(set VR512:$dst, (v16i32 immAllOnesV))]>; -} - -// Alias instructions that allow VPTERNLOG to be used with a mask to create -// a mix of all ones and all zeros elements. This is done this way to force -// the same register to be used as input for all three sources. -let isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteVecALU] in { -def AVX512_512_SEXT_MASK_32 : I<0, Pseudo, (outs VR512:$dst), - (ins VK16WM:$mask), "", - [(set VR512:$dst, (vselect (v16i1 VK16WM:$mask), - (v16i32 immAllOnesV), - (v16i32 immAllZerosV)))]>; -def AVX512_512_SEXT_MASK_64 : I<0, Pseudo, (outs VR512:$dst), - (ins VK8WM:$mask), "", - [(set VR512:$dst, (vselect (v8i1 VK8WM:$mask), - (bc_v8i64 (v16i32 immAllOnesV)), - (bc_v8i64 (v16i32 immAllZerosV))))]>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [HasAVX512], SchedRW = [WriteZero] in { -def AVX512_128_SET0 : I<0, Pseudo, (outs VR128X:$dst), (ins), "", - [(set VR128X:$dst, (v4i32 immAllZerosV))]>; -def AVX512_256_SET0 : I<0, Pseudo, (outs VR256X:$dst), (ins), "", - [(set VR256X:$dst, (v8i32 immAllZerosV))]>; -} - -// Alias instructions that map fld0 to xorps for sse or vxorps for avx. -// This is expanded by ExpandPostRAPseudos. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero], Predicates = [HasAVX512] in { - def AVX512_FsFLD0SS : I<0, Pseudo, (outs FR32X:$dst), (ins), "", - [(set FR32X:$dst, fp32imm0)]>; - def AVX512_FsFLD0SD : I<0, Pseudo, (outs FR64X:$dst), (ins), "", - [(set FR64X:$dst, fpimm0)]>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - VECTOR INSERT -// - -// Supports two different pattern operators for mask and unmasked ops. Allows -// null_frag to be passed for one. -multiclass vinsert_for_size_split { - let hasSideEffects = 0, ExeDomain = To.ExeDomain in { - defm rr : AVX512_maskable_split, - AVX512AIi8Base, EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - defm rm : AVX512_maskable_split, AVX512AIi8Base, EVEX_4V, - EVEX_CD8, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -// Passes the same pattern operator for masked and unmasked ops. -multiclass vinsert_for_size : - vinsert_for_size_split; - -multiclass vinsert_for_size_lowering p> { - let Predicates = p in { - def : Pat<(vinsert_insert:$ins - (To.VT To.RC:$src1), (From.VT From.RC:$src2), (iPTR imm)), - (To.VT (!cast(InstrStr#"rr") - To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins)))>; - - def : Pat<(vinsert_insert:$ins - (To.VT To.RC:$src1), - (From.VT (bitconvert (From.LdFrag addr:$src2))), - (iPTR imm)), - (To.VT (!cast(InstrStr#"rm") - To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins)))>; - } -} - -multiclass vinsert_for_type { - - let Predicates = [HasVLX] in - defm NAME # "32x4Z256" : vinsert_for_size, - X86VectorVTInfo< 8, EltVT32, VR256X>, - vinsert128_insert, sched>, EVEX_V256; - - defm NAME # "32x4Z" : vinsert_for_size, - X86VectorVTInfo<16, EltVT32, VR512>, - vinsert128_insert, sched>, EVEX_V512; - - defm NAME # "64x4Z" : vinsert_for_size, - X86VectorVTInfo< 8, EltVT64, VR512>, - vinsert256_insert, sched>, VEX_W, EVEX_V512; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasVLX, HasDQI] in - defm NAME # "64x2Z256" : vinsert_for_size_split, - X86VectorVTInfo< 4, EltVT64, VR256X>, - null_frag, vinsert128_insert, sched>, - VEX_W1X, EVEX_V256; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasDQI] in { - defm NAME # "64x2Z" : vinsert_for_size_split, - X86VectorVTInfo< 8, EltVT64, VR512>, - null_frag, vinsert128_insert, sched>, - VEX_W, EVEX_V512; - - defm NAME # "32x8Z" : vinsert_for_size_split, - X86VectorVTInfo<16, EltVT32, VR512>, - null_frag, vinsert256_insert, sched>, - EVEX_V512; - } -} - -// FIXME: Is there a better scheduler class for VINSERTF/VINSERTI? -defm VINSERTF : vinsert_for_type; -defm VINSERTI : vinsert_for_type; - -// Codegen pattern with the alternative types, -// Even with AVX512DQ we'll still use these for unmasked operations. -defm : vinsert_for_size_lowering<"VINSERTF32x4Z256", v2f64x_info, v4f64x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v2i64x_info, v4i64x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; - -defm : vinsert_for_size_lowering<"VINSERTF32x4Z", v2f64x_info, v8f64_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v2i64x_info, v8i64_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; - -defm : vinsert_for_size_lowering<"VINSERTF64x4Z", v8f32x_info, v16f32_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v8i32x_info, v16i32_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; - -// Codegen pattern with the alternative types insert VEC128 into VEC256 -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v8i16x_info, v16i16x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z256", v16i8x_info, v32i8x_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasVLX]>; -// Codegen pattern with the alternative types insert VEC128 into VEC512 -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v8i16x_info, v32i16_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI32x4Z", v16i8x_info, v64i8_info, - vinsert128_insert, INSERT_get_vinsert128_imm, [HasAVX512]>; -// Codegen pattern with the alternative types insert VEC256 into VEC512 -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v16i16x_info, v32i16_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_size_lowering<"VINSERTI64x4Z", v32i8x_info, v64i8_info, - vinsert256_insert, INSERT_get_vinsert256_imm, [HasAVX512]>; - - -multiclass vinsert_for_mask_cast p> { -let Predicates = p in { - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT From.RC:$src2), - (iPTR imm))), - Cast.RC:$src0)), - (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT - (bitconvert - (From.LdFrag addr:$src2))), - (iPTR imm))), - Cast.RC:$src0)), - (!cast(InstrStr#"rmk") - Cast.RC:$src0, Cast.KRCWM:$mask, To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT From.RC:$src2), - (iPTR imm))), - Cast.ImmAllZerosV)), - (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, To.RC:$src1, From.RC:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; - def : Pat<(Cast.VT - (vselect Cast.KRCWM:$mask, - (bitconvert - (vinsert_insert:$ins (To.VT To.RC:$src1), - (From.VT - (bitconvert - (From.LdFrag addr:$src2))), - (iPTR imm))), - Cast.ImmAllZerosV)), - (!cast(InstrStr#"rmkz") - Cast.KRCWM:$mask, To.RC:$src1, addr:$src2, - (INSERT_get_vinsert_imm To.RC:$ins))>; -} -} - -defm : vinsert_for_mask_cast<"VINSERTF32x4Z256", v2f64x_info, v4f64x_info, - v8f32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v4f32x_info, v8f32x_info, - v4f64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v2i64x_info, v4i64x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v8i16x_info, v16i16x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z256", v16i8x_info, v32i8x_info, - v8i32x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v4i32x_info, v8i32x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v8i16x_info, v16i16x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z256", v16i8x_info, v32i8x_info, - v4i64x_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI, HasVLX]>; - -defm : vinsert_for_mask_cast<"VINSERTF32x4Z", v2f64x_info, v8f64_info, - v16f32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTF64x2Z", v4f32x_info, v16f32_info, - v8f64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v2i64x_info, v8i64_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v8i16x_info, v32i16_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI32x4Z", v16i8x_info, v64i8_info, - v16i32_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v4i32x_info, v16i32_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v8i16x_info, v32i16_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x2Z", v16i8x_info, v64i8_info, - v8i64_info, vinsert128_insert, - INSERT_get_vinsert128_imm, [HasDQI]>; - -defm : vinsert_for_mask_cast<"VINSERTF32x8Z", v4f64x_info, v8f64_info, - v16f32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTF64x4Z", v8f32x_info, v16f32_info, - v8f64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; - -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v4i64x_info, v8i64_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v16i16x_info, v32i16_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI32x8Z", v32i8x_info, v64i8_info, - v16i32_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasDQI]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v8i32x_info, v16i32_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v16i16x_info, v32i16_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; -defm : vinsert_for_mask_cast<"VINSERTI64x4Z", v32i8x_info, v64i8_info, - v8i64_info, vinsert256_insert, - INSERT_get_vinsert256_imm, [HasAVX512]>; - -// vinsertps - insert f32 to XMM -let ExeDomain = SSEPackedSingle in { -def VINSERTPSZrr : AVX512AIi8<0x21, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2, u8imm:$src3), - "vinsertps\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR128X:$dst, (X86insertps VR128X:$src1, VR128X:$src2, imm:$src3))]>, - EVEX_4V, Sched<[SchedWriteFShuffle.XMM]>; -def VINSERTPSZrm: AVX512AIi8<0x21, MRMSrcMem, (outs VR128X:$dst), - (ins VR128X:$src1, f32mem:$src2, u8imm:$src3), - "vinsertps\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR128X:$dst, (X86insertps VR128X:$src1, - (v4f32 (scalar_to_vector (loadf32 addr:$src2))), - imm:$src3))]>, - EVEX_4V, EVEX_CD8<32, CD8VT1>, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 VECTOR EXTRACT -//--- - -// Supports two different pattern operators for mask and unmasked ops. Allows -// null_frag to be passed for one. -multiclass vextract_for_size_split { - - let hasSideEffects = 0, ExeDomain = To.ExeDomain in { - defm rr : AVX512_maskable_split, - AVX512AIi8Base, EVEX, Sched<[SchedRR]>; - - def mr : AVX512AIi8, EVEX, - Sched<[SchedMR]>; - - let mayStore = 1, hasSideEffects = 0 in - def mrk : AVX512AIi8, - EVEX_K, EVEX, Sched<[SchedMR]>, NotMemoryFoldable; - } -} - -// Passes the same pattern operator for masked and unmasked ops. -multiclass vextract_for_size : - vextract_for_size_split; - -// Codegen pattern for the alternative types -multiclass vextract_for_size_lowering p> { - let Predicates = p in { - def : Pat<(vextract_extract:$ext (From.VT From.RC:$src1), (iPTR imm)), - (To.VT (!cast(InstrStr#"rr") - From.RC:$src1, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; - def : Pat<(store (To.VT (vextract_extract:$ext (From.VT From.RC:$src1), - (iPTR imm))), addr:$dst), - (!cast(InstrStr#"mr") addr:$dst, From.RC:$src1, - (EXTRACT_get_vextract_imm To.RC:$ext))>; - } -} - -multiclass vextract_for_type { - let Predicates = [HasAVX512] in { - defm NAME # "32x4Z" : vextract_for_size, - X86VectorVTInfo< 4, EltVT32, VR128X>, - vextract128_extract, SchedRR, SchedMR>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; - defm NAME # "64x4Z" : vextract_for_size, - X86VectorVTInfo< 4, EltVT64, VR256X>, - vextract256_extract, SchedRR, SchedMR>, - VEX_W, EVEX_V512, EVEX_CD8<64, CD8VT4>; - } - let Predicates = [HasVLX] in - defm NAME # "32x4Z256" : vextract_for_size, - X86VectorVTInfo< 4, EltVT32, VR128X>, - vextract128_extract, SchedRR, SchedMR>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasVLX, HasDQI] in - defm NAME # "64x2Z256" : vextract_for_size_split, - X86VectorVTInfo< 2, EltVT64, VR128X>, - null_frag, vextract128_extract, SchedRR, SchedMR>, - VEX_W1X, EVEX_V256, EVEX_CD8<64, CD8VT2>; - - // Even with DQI we'd like to only use these instructions for masking. - let Predicates = [HasDQI] in { - defm NAME # "64x2Z" : vextract_for_size_split, - X86VectorVTInfo< 2, EltVT64, VR128X>, - null_frag, vextract128_extract, SchedRR, SchedMR>, - VEX_W, EVEX_V512, EVEX_CD8<64, CD8VT2>; - defm NAME # "32x8Z" : vextract_for_size_split, - X86VectorVTInfo< 8, EltVT32, VR256X>, - null_frag, vextract256_extract, SchedRR, SchedMR>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; - } -} - -// TODO - replace WriteFStore/WriteVecStore with X86SchedWriteMoveLSWidths types. -defm VEXTRACTF : vextract_for_type; -defm VEXTRACTI : vextract_for_type; - -// extract_subvector codegen patterns with the alternative types. -// Even with AVX512DQ we'll still use these for unmasked operations. -defm : vextract_for_size_lowering<"VEXTRACTF32x4Z", v8f64_info, v2f64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v8i64_info, v2i64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; - -defm : vextract_for_size_lowering<"VEXTRACTF64x4Z", v16f32_info, v8f32x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v16i32_info, v8i32x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; - -defm : vextract_for_size_lowering<"VEXTRACTF32x4Z256", v4f64x_info, v2f64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v4i64x_info, v2i64x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; - -// Codegen pattern with the alternative types extract VEC128 from VEC256 -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v16i16x_info, v8i16x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z256", v32i8x_info, v16i8x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasVLX]>; - -// Codegen pattern with the alternative types extract VEC128 from VEC512 -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v32i16_info, v8i16x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI32x4Z", v64i8_info, v16i8x_info, - vextract128_extract, EXTRACT_get_vextract128_imm, [HasAVX512]>; -// Codegen pattern with the alternative types extract VEC256 from VEC512 -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v32i16_info, v16i16x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_size_lowering<"VEXTRACTI64x4Z", v64i8_info, v32i8x_info, - vextract256_extract, EXTRACT_get_vextract256_imm, [HasAVX512]>; - - -// A 128-bit extract from bits [255:128] of a 512-bit vector should use a -// smaller extract to enable EVEX->VEX. -let Predicates = [NoVLX] in { -def : Pat<(v2i64 (extract_subvector (v8i64 VR512:$src), (iPTR 2))), - (v2i64 (VEXTRACTI128rr - (v4i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v2f64 (extract_subvector (v8f64 VR512:$src), (iPTR 2))), - (v2f64 (VEXTRACTF128rr - (v4f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4i32 (extract_subvector (v16i32 VR512:$src), (iPTR 4))), - (v4i32 (VEXTRACTI128rr - (v8i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4f32 (extract_subvector (v16f32 VR512:$src), (iPTR 4))), - (v4f32 (VEXTRACTF128rr - (v8f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v8i16 (extract_subvector (v32i16 VR512:$src), (iPTR 8))), - (v8i16 (VEXTRACTI128rr - (v16i16 (EXTRACT_SUBREG (v32i16 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v16i8 (extract_subvector (v64i8 VR512:$src), (iPTR 16))), - (v16i8 (VEXTRACTI128rr - (v32i8 (EXTRACT_SUBREG (v64i8 VR512:$src), sub_ymm)), - (iPTR 1)))>; -} - -// A 128-bit extract from bits [255:128] of a 512-bit vector should use a -// smaller extract to enable EVEX->VEX. -let Predicates = [HasVLX] in { -def : Pat<(v2i64 (extract_subvector (v8i64 VR512:$src), (iPTR 2))), - (v2i64 (VEXTRACTI32x4Z256rr - (v4i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v2f64 (extract_subvector (v8f64 VR512:$src), (iPTR 2))), - (v2f64 (VEXTRACTF32x4Z256rr - (v4f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4i32 (extract_subvector (v16i32 VR512:$src), (iPTR 4))), - (v4i32 (VEXTRACTI32x4Z256rr - (v8i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v4f32 (extract_subvector (v16f32 VR512:$src), (iPTR 4))), - (v4f32 (VEXTRACTF32x4Z256rr - (v8f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v8i16 (extract_subvector (v32i16 VR512:$src), (iPTR 8))), - (v8i16 (VEXTRACTI32x4Z256rr - (v16i16 (EXTRACT_SUBREG (v32i16 VR512:$src), sub_ymm)), - (iPTR 1)))>; -def : Pat<(v16i8 (extract_subvector (v64i8 VR512:$src), (iPTR 16))), - (v16i8 (VEXTRACTI32x4Z256rr - (v32i8 (EXTRACT_SUBREG (v64i8 VR512:$src), sub_ymm)), - (iPTR 1)))>; -} - - -// Additional patterns for handling a bitcast between the vselect and the -// extract_subvector. -multiclass vextract_for_mask_cast p> { -let Predicates = p in { - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (vextract_extract:$ext - (From.VT From.RC:$src), (iPTR imm)))), - To.RC:$src0)), - (Cast.VT (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, From.RC:$src, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; - - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (vextract_extract:$ext - (From.VT From.RC:$src), (iPTR imm)))), - Cast.ImmAllZerosV)), - (Cast.VT (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, From.RC:$src, - (EXTRACT_get_vextract_imm To.RC:$ext)))>; -} -} - -defm : vextract_for_mask_cast<"VEXTRACTF32x4Z256", v4f64x_info, v2f64x_info, - v4f32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x2Z256", v8f32x_info, v4f32x_info, - v2f64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v4i64x_info, v2i64x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v16i16x_info, v8i16x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z256", v32i8x_info, v16i8x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v8i32x_info, v4i32x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v16i16x_info, v8i16x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z256", v32i8x_info, v16i8x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI, HasVLX]>; - -defm : vextract_for_mask_cast<"VEXTRACTF32x4Z", v8f64_info, v2f64x_info, - v4f32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x2Z", v16f32_info, v4f32x_info, - v2f64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v8i64_info, v2i64x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v32i16_info, v8i16x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x4Z", v64i8_info, v16i8x_info, - v4i32x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v16i32_info, v4i32x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v32i16_info, v8i16x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x2Z", v64i8_info, v16i8x_info, - v2i64x_info, vextract128_extract, - EXTRACT_get_vextract128_imm, [HasDQI]>; - -defm : vextract_for_mask_cast<"VEXTRACTF32x8Z", v8f64_info, v4f64x_info, - v8f32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTF64x4Z", v16f32_info, v8f32x_info, - v4f64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; - -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v8i64_info, v4i64x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v32i16_info, v16i16x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI32x8Z", v64i8_info, v32i8x_info, - v8i32x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasDQI]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v16i32_info, v8i32x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v32i16_info, v16i16x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; -defm : vextract_for_mask_cast<"VEXTRACTI64x4Z", v64i8_info, v32i8x_info, - v4i64x_info, vextract256_extract, - EXTRACT_get_vextract256_imm, [HasAVX512]>; - -// vextractps - extract 32 bits from XMM -def VEXTRACTPSZrr : AVX512AIi8<0x17, MRMDestReg, (outs GR32:$dst), - (ins VR128X:$src1, u8imm:$src2), - "vextractps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, (extractelt (bc_v4i32 (v4f32 VR128X:$src1)), imm:$src2))]>, - EVEX, VEX_WIG, Sched<[WriteVecExtract]>; - -def VEXTRACTPSZmr : AVX512AIi8<0x17, MRMDestMem, (outs), - (ins f32mem:$dst, VR128X:$src1, u8imm:$src2), - "vextractps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(store (extractelt (bc_v4i32 (v4f32 VR128X:$src1)), imm:$src2), - addr:$dst)]>, - EVEX, VEX_WIG, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecExtractSt]>; - -//===---------------------------------------------------------------------===// -// AVX-512 BROADCAST -//--- -// broadcast with a scalar argument. -multiclass avx512_broadcast_scalar opc, string OpcodeStr, - string Name, - X86VectorVTInfo DestInfo, X86VectorVTInfo SrcInfo> { - def : Pat<(DestInfo.VT (X86VBroadcast SrcInfo.FRC:$src)), - (!cast(Name#DestInfo.ZSuffix#r) - (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; - def : Pat<(DestInfo.VT (vselect DestInfo.KRCWM:$mask, - (X86VBroadcast SrcInfo.FRC:$src), - DestInfo.RC:$src0)), - (!cast(Name#DestInfo.ZSuffix#rk) - DestInfo.RC:$src0, DestInfo.KRCWM:$mask, - (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; - def : Pat<(DestInfo.VT (vselect DestInfo.KRCWM:$mask, - (X86VBroadcast SrcInfo.FRC:$src), - DestInfo.ImmAllZerosV)), - (!cast(Name#DestInfo.ZSuffix#rkz) - DestInfo.KRCWM:$mask, (SrcInfo.VT (COPY_TO_REGCLASS SrcInfo.FRC:$src, SrcInfo.RC)))>; -} - -// Split version to allow mask and broadcast node to be different types. This -// helps support the 32x2 broadcasts. -multiclass avx512_broadcast_rm_split opc, string OpcodeStr, - string Name, - SchedWrite SchedRR, SchedWrite SchedRM, - X86VectorVTInfo MaskInfo, - X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo, - SDPatternOperator UnmaskedOp = X86VBroadcast> { - let ExeDomain = DestInfo.ExeDomain, hasSideEffects = 0 in { - defm r : AVX512_maskable_split, - T8PD, EVEX, Sched<[SchedRR]>; - let mayLoad = 1 in - defm m : AVX512_maskable_split, - T8PD, EVEX, EVEX_CD8, - Sched<[SchedRM]>; - } - - def : Pat<(MaskInfo.VT - (bitconvert - (DestInfo.VT (UnmaskedOp - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src))))))), - (!cast(Name#MaskInfo.ZSuffix#m) addr:$src)>; - def : Pat<(MaskInfo.VT (vselect MaskInfo.KRCWM:$mask, - (bitconvert - (DestInfo.VT - (X86VBroadcast - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src)))))), - MaskInfo.RC:$src0)), - (!cast(Name#DestInfo.ZSuffix#mk) - MaskInfo.RC:$src0, MaskInfo.KRCWM:$mask, addr:$src)>; - def : Pat<(MaskInfo.VT (vselect MaskInfo.KRCWM:$mask, - (bitconvert - (DestInfo.VT - (X86VBroadcast - (SrcInfo.VT (scalar_to_vector - (SrcInfo.ScalarLdFrag addr:$src)))))), - MaskInfo.ImmAllZerosV)), - (!cast(Name#MaskInfo.ZSuffix#mkz) - MaskInfo.KRCWM:$mask, addr:$src)>; -} - -// Helper class to force mask and broadcast result to same type. -multiclass avx512_broadcast_rm opc, string OpcodeStr, string Name, - SchedWrite SchedRR, SchedWrite SchedRM, - X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo> : - avx512_broadcast_rm_split; - -multiclass avx512_fp_broadcast_sd opc, string OpcodeStr, - AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in { - defm Z : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V512; - } - - let Predicates = [HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V256; - } -} - -multiclass avx512_fp_broadcast_ss opc, string OpcodeStr, - AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in { - defm Z : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V512; - } - - let Predicates = [HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V256; - defm Z128 : avx512_broadcast_rm, - avx512_broadcast_scalar, - EVEX_V128; - } -} -defm VBROADCASTSS : avx512_fp_broadcast_ss<0x18, "vbroadcastss", - avx512vl_f32_info>; -defm VBROADCASTSD : avx512_fp_broadcast_sd<0x19, "vbroadcastsd", - avx512vl_f64_info>, VEX_W1X; - -multiclass avx512_int_broadcast_reg opc, SchedWrite SchedRR, - X86VectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC> { - let ExeDomain = _.ExeDomain in - defm r : AVX512_maskable, T8PD, EVEX, - Sched<[SchedRR]>; -} - -multiclass avx512_int_broadcastbw_reg opc, string Name, SchedWrite SchedRR, - X86VectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC, SubRegIndex Subreg> { - let hasSideEffects = 0, ExeDomain = _.ExeDomain in - defm r : AVX512_maskable_custom, T8PD, EVEX, Sched<[SchedRR]>; - - def : Pat <(_.VT (OpNode SrcRC:$src)), - (!cast(Name#r) - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; - - def : Pat <(vselect _.KRCWM:$mask, (_.VT (OpNode SrcRC:$src)), _.RC:$src0), - (!cast(Name#rk) _.RC:$src0, _.KRCWM:$mask, - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; - - def : Pat <(vselect _.KRCWM:$mask, (_.VT (OpNode SrcRC:$src)), _.ImmAllZerosV), - (!cast(Name#rkz) _.KRCWM:$mask, - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SrcRC:$src, Subreg)))>; -} - -multiclass avx512_int_broadcastbw_reg_vl opc, string Name, - AVX512VLVectorVTInfo _, SDPatternOperator OpNode, - RegisterClass SrcRC, SubRegIndex Subreg, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_int_broadcastbw_reg, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_int_broadcastbw_reg, EVEX_V256; - defm Z128 : avx512_int_broadcastbw_reg, EVEX_V128; - } -} - -multiclass avx512_int_broadcast_reg_vl opc, AVX512VLVectorVTInfo _, - SDPatternOperator OpNode, - RegisterClass SrcRC, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_int_broadcast_reg, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_int_broadcast_reg, EVEX_V256; - defm Z128 : avx512_int_broadcast_reg, EVEX_V128; - } -} - -defm VPBROADCASTBr : avx512_int_broadcastbw_reg_vl<0x7A, "VPBROADCASTBr", - avx512vl_i8_info, X86VBroadcast, GR8, sub_8bit, HasBWI>; -defm VPBROADCASTWr : avx512_int_broadcastbw_reg_vl<0x7B, "VPBROADCASTWr", - avx512vl_i16_info, X86VBroadcast, GR16, sub_16bit, - HasBWI>; -defm VPBROADCASTDr : avx512_int_broadcast_reg_vl<0x7C, avx512vl_i32_info, - X86VBroadcast, GR32, HasAVX512>; -defm VPBROADCASTQr : avx512_int_broadcast_reg_vl<0x7C, avx512vl_i64_info, - X86VBroadcast, GR64, HasAVX512>, VEX_W; - -// Provide aliases for broadcast from the same register class that -// automatically does the extract. -multiclass avx512_int_broadcast_rm_lowering { - def : Pat<(DestInfo.VT (X86VBroadcast (SrcInfo.VT SrcInfo.RC:$src))), - (!cast(Name#DestInfo.ZSuffix#"r") - (ExtInfo.VT (EXTRACT_SUBREG (SrcInfo.VT SrcInfo.RC:$src), sub_xmm)))>; -} - -multiclass avx512_int_broadcast_rm_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd> { - let Predicates = [prd] in { - defm Z : avx512_broadcast_rm, - avx512_int_broadcast_rm_lowering, - EVEX_V512; - // Defined separately to avoid redefinition. - defm Z_Alt : avx512_int_broadcast_rm_lowering; - } - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_broadcast_rm, - avx512_int_broadcast_rm_lowering, - EVEX_V256; - defm Z128 : avx512_broadcast_rm, - EVEX_V128; - } -} - -defm VPBROADCASTB : avx512_int_broadcast_rm_vl<0x78, "vpbroadcastb", - avx512vl_i8_info, HasBWI>; -defm VPBROADCASTW : avx512_int_broadcast_rm_vl<0x79, "vpbroadcastw", - avx512vl_i16_info, HasBWI>; -defm VPBROADCASTD : avx512_int_broadcast_rm_vl<0x58, "vpbroadcastd", - avx512vl_i32_info, HasAVX512>; -defm VPBROADCASTQ : avx512_int_broadcast_rm_vl<0x59, "vpbroadcastq", - avx512vl_i64_info, HasAVX512>, VEX_W1X; - -multiclass avx512_subvec_broadcast_rm opc, string OpcodeStr, - X86VectorVTInfo _Dst, X86VectorVTInfo _Src> { - defm rm : AVX512_maskable, - Sched<[SchedWriteShuffle.YMM.Folded]>, - AVX5128IBase, EVEX; -} - -// This should be used for the AVX512DQ broadcast instructions. It disables -// the unmasked patterns so that we only use the DQ instructions when masking -// is requested. -multiclass avx512_subvec_broadcast_rm_dq opc, string OpcodeStr, - X86VectorVTInfo _Dst, X86VectorVTInfo _Src> { - let hasSideEffects = 0, mayLoad = 1 in - defm rm : AVX512_maskable_split, - Sched<[SchedWriteShuffle.YMM.Folded]>, - AVX5128IBase, EVEX; -} - -let Predicates = [HasAVX512] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v8i64 (X86VBroadcast (v8i64 (X86vzload addr:$src)))), - (VPBROADCASTQZm addr:$src)>; -} - -let Predicates = [HasVLX] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v2i64 (X86VBroadcast (v2i64 (X86vzload addr:$src)))), - (VPBROADCASTQZ128m addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v4i64 (X86vzload addr:$src)))), - (VPBROADCASTQZ256m addr:$src)>; -} -let Predicates = [HasVLX, HasBWI] in { - // loadi16 is tricky to fold, because !isTypeDesirableForOp, justifiably. - // This means we'll encounter truncated i32 loads; match that here. - def : Pat<(v8i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWZ128m addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWZ256m addr:$src)>; - def : Pat<(v8i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWZ128m addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWZ256m addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 BROADCAST SUBVECTORS -// - -defm VBROADCASTI32X4 : avx512_subvec_broadcast_rm<0x5a, "vbroadcasti32x4", - v16i32_info, v4i32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTF32X4 : avx512_subvec_broadcast_rm<0x1a, "vbroadcastf32x4", - v16f32_info, v4f32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTI64X4 : avx512_subvec_broadcast_rm<0x5b, "vbroadcasti64x4", - v8i64_info, v4i64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT4>; -defm VBROADCASTF64X4 : avx512_subvec_broadcast_rm<0x1b, "vbroadcastf64x4", - v8f64_info, v4f64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT4>; - -let Predicates = [HasAVX512] in { -def : Pat<(v16f32 (X86SubVBroadcast (loadv8f32 addr:$src))), - (VBROADCASTF64X4rm addr:$src)>; -def : Pat<(v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; -def : Pat<(v32i16 (X86SubVBroadcast (bc_v16i16 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; -def : Pat<(v64i8 (X86SubVBroadcast (bc_v32i8 (loadv4i64 addr:$src)))), - (VBROADCASTI64X4rm addr:$src)>; - -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. -def : Pat<(v8f64 (X86SubVBroadcast (v4f64 VR256X:$src))), - (VINSERTF64x4Zrr (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v4f64 VR256X:$src), 1)>; -def : Pat<(v16f32 (X86SubVBroadcast (v8f32 VR256X:$src))), - (VINSERTF64x4Zrr (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v8f32 VR256X:$src), 1)>; -def : Pat<(v8i64 (X86SubVBroadcast (v4i64 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v4i64 VR256X:$src), 1)>; -def : Pat<(v16i32 (X86SubVBroadcast (v8i32 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v8i32 VR256X:$src), 1)>; -def : Pat<(v32i16 (X86SubVBroadcast (v16i16 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v16i16 VR256X:$src), 1)>; -def : Pat<(v64i8 (X86SubVBroadcast (v32i8 VR256X:$src))), - (VINSERTI64x4Zrr (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (v32i8 VR256X:$src), 1)>; - -def : Pat<(v8f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF32X4rm addr:$src)>; -def : Pat<(v8i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI32X4rm addr:$src)>; -def : Pat<(v32i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4rm addr:$src)>; -def : Pat<(v64i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4rm addr:$src)>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - (bc_v16f32 (v16i32 immAllZerosV))), - (VBROADCASTF32X4rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - VR512:$src0), - (VBROADCASTF32X4rmk VR512:$src0, VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - (v16i32 immAllZerosV)), - (VBROADCASTI32X4rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - VR512:$src0), - (VBROADCASTI32X4rmk VR512:$src0, VK16WM:$mask, addr:$src)>; - -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv8f32 addr:$src)))), - (bc_v8f64 (v16i32 immAllZerosV))), - (VBROADCASTF64X4rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv8f32 addr:$src)))), - VR512:$src0), - (VBROADCASTF64X4rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src))))), - (bc_v8i64 (v16i32 immAllZerosV))), - (VBROADCASTI64X4rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v8i32 (loadv4i64 addr:$src))))), - VR512:$src0), - (VBROADCASTI64X4rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -} - -let Predicates = [HasVLX] in { -defm VBROADCASTI32X4Z256 : avx512_subvec_broadcast_rm<0x5a, "vbroadcasti32x4", - v8i32x_info, v4i32x_info>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; -defm VBROADCASTF32X4Z256 : avx512_subvec_broadcast_rm<0x1a, "vbroadcastf32x4", - v8f32x_info, v4f32x_info>, - EVEX_V256, EVEX_CD8<32, CD8VT4>; - -def : Pat<(v4f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF32X4Z256rm addr:$src)>; -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI32X4Z256rm addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4Z256rm addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI32X4Z256rm addr:$src)>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK8WM:$mask, - (bc_v8f32 (v4f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - (bc_v8f32 (v8i32 immAllZerosV))), - (VBROADCASTF32X4Z256rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f32 (v4f64 (X86SubVBroadcast (loadv2f64 addr:$src)))), - VR256X:$src0), - (VBROADCASTF32X4Z256rmk VR256X:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i32 (v4i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - (v8i32 immAllZerosV)), - (VBROADCASTI32X4Z256rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i32 (v4i64 (X86SubVBroadcast (loadv2i64 addr:$src)))), - VR256X:$src0), - (VBROADCASTI32X4Z256rmk VR256X:$src0, VK8WM:$mask, addr:$src)>; - - -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. -def : Pat<(v4f64 (X86SubVBroadcast (v2f64 VR128X:$src))), - (VINSERTF32x4Z256rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v2f64 VR128X:$src), 1)>; -def : Pat<(v8f32 (X86SubVBroadcast (v4f32 VR128X:$src))), - (VINSERTF32x4Z256rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v4f32 VR128X:$src), 1)>; -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v2i64 VR128X:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v4i32 VR128X:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v8i16 VR128X:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128X:$src))), - (VINSERTI32x4Z256rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (v16i8 VR128X:$src), 1)>; -} - -let Predicates = [HasVLX, HasDQI] in { -defm VBROADCASTI64X2Z128 : avx512_subvec_broadcast_rm_dq<0x5a, "vbroadcasti64x2", - v4i64x_info, v2i64x_info>, VEX_W1X, - EVEX_V256, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTF64X2Z128 : avx512_subvec_broadcast_rm_dq<0x1a, "vbroadcastf64x2", - v4f64x_info, v2f64x_info>, VEX_W1X, - EVEX_V256, EVEX_CD8<64, CD8VT2>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK4WM:$mask, - (bc_v4f64 (v8f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - (bc_v4f64 (v8i32 immAllZerosV))), - (VBROADCASTF64X2Z128rmkz VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4f64 (v8f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - VR256X:$src0), - (VBROADCASTF64X2Z128rmk VR256X:$src0, VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4i64 (v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - (bc_v4i64 (v8i32 immAllZerosV))), - (VBROADCASTI64X2Z128rmkz VK4WM:$mask, addr:$src)>; -def : Pat<(vselect VK4WM:$mask, - (bc_v4i64 (v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - VR256X:$src0), - (VBROADCASTI64X2Z128rmk VR256X:$src0, VK4WM:$mask, addr:$src)>; -} - -let Predicates = [HasDQI] in { -defm VBROADCASTI64X2 : avx512_subvec_broadcast_rm_dq<0x5a, "vbroadcasti64x2", - v8i64_info, v2i64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTI32X8 : avx512_subvec_broadcast_rm_dq<0x5b, "vbroadcasti32x8", - v16i32_info, v8i32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; -defm VBROADCASTF64X2 : avx512_subvec_broadcast_rm_dq<0x1a, "vbroadcastf64x2", - v8f64_info, v2f64x_info>, VEX_W, - EVEX_V512, EVEX_CD8<64, CD8VT2>; -defm VBROADCASTF32X8 : avx512_subvec_broadcast_rm_dq<0x1b, "vbroadcastf32x8", - v16f32_info, v8f32x_info>, - EVEX_V512, EVEX_CD8<32, CD8VT8>; - -// Patterns for selects of bitcasted operations. -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv4f64 addr:$src)))), - (bc_v16f32 (v16i32 immAllZerosV))), - (VBROADCASTF32X8rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16f32 (v8f64 (X86SubVBroadcast (loadv4f64 addr:$src)))), - VR512:$src0), - (VBROADCASTF32X8rmk VR512:$src0, VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv4i64 addr:$src)))), - (v16i32 immAllZerosV)), - (VBROADCASTI32X8rmkz VK16WM:$mask, addr:$src)>; -def : Pat<(vselect VK16WM:$mask, - (bc_v16i32 (v8i64 (X86SubVBroadcast (loadv4i64 addr:$src)))), - VR512:$src0), - (VBROADCASTI32X8rmk VR512:$src0, VK16WM:$mask, addr:$src)>; - -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - (bc_v8f64 (v16i32 immAllZerosV))), - (VBROADCASTF64X2rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8f64 (v16f32 (X86SubVBroadcast (loadv4f32 addr:$src)))), - VR512:$src0), - (VBROADCASTF64X2rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - (bc_v8i64 (v16i32 immAllZerosV))), - (VBROADCASTI64X2rmkz VK8WM:$mask, addr:$src)>; -def : Pat<(vselect VK8WM:$mask, - (bc_v8i64 (v16i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src))))), - VR512:$src0), - (VBROADCASTI64X2rmk VR512:$src0, VK8WM:$mask, addr:$src)>; -} - -multiclass avx512_common_broadcast_32x2 opc, string OpcodeStr, - AVX512VLVectorVTInfo _Dst, AVX512VLVectorVTInfo _Src> { - let Predicates = [HasDQI] in - defm Z : avx512_broadcast_rm_split, - EVEX_V512; - let Predicates = [HasDQI, HasVLX] in - defm Z256 : avx512_broadcast_rm_split, - EVEX_V256; -} - -multiclass avx512_common_broadcast_i32x2 opc, string OpcodeStr, - AVX512VLVectorVTInfo _Dst, AVX512VLVectorVTInfo _Src> : - avx512_common_broadcast_32x2 { - - let Predicates = [HasDQI, HasVLX] in - defm Z128 : avx512_broadcast_rm_split, - EVEX_V128; -} - -defm VBROADCASTI32X2 : avx512_common_broadcast_i32x2<0x59, "vbroadcasti32x2", - avx512vl_i32_info, avx512vl_i64_info>; -defm VBROADCASTF32X2 : avx512_common_broadcast_32x2<0x19, "vbroadcastf32x2", - avx512vl_f32_info, avx512vl_f64_info>; - -let Predicates = [HasVLX] in { -def : Pat<(v8f32 (X86VBroadcast (v8f32 VR256X:$src))), - (VBROADCASTSSZ256r (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))>; -def : Pat<(v4f64 (X86VBroadcast (v4f64 VR256X:$src))), - (VBROADCASTSDZ256r (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))>; -} - -def : Pat<(v16f32 (X86VBroadcast (v16f32 VR512:$src))), - (VBROADCASTSSZr (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)))>; -def : Pat<(v16f32 (X86VBroadcast (v8f32 VR256X:$src))), - (VBROADCASTSSZr (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))>; - -def : Pat<(v8f64 (X86VBroadcast (v8f64 VR512:$src))), - (VBROADCASTSDZr (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)))>; -def : Pat<(v8f64 (X86VBroadcast (v4f64 VR256X:$src))), - (VBROADCASTSDZr (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))>; - -//===----------------------------------------------------------------------===// -// AVX-512 BROADCAST MASK TO VECTOR REGISTER -//--- -multiclass avx512_mask_broadcastm opc, string OpcodeStr, - X86VectorVTInfo _, RegisterClass KRC> { - def rr : AVX512XS8I, - EVEX, Sched<[WriteShuffle]>; -} - -multiclass avx512_mask_broadcast opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, RegisterClass KRC> { - let Predicates = [HasCDI] in - defm Z : avx512_mask_broadcastm, EVEX_V512; - let Predicates = [HasCDI, HasVLX] in { - defm Z256 : avx512_mask_broadcastm, EVEX_V256; - defm Z128 : avx512_mask_broadcastm, EVEX_V128; - } -} - -defm VPBROADCASTMW2D : avx512_mask_broadcast<0x3A, "vpbroadcastmw2d", - avx512vl_i32_info, VK16>; -defm VPBROADCASTMB2Q : avx512_mask_broadcast<0x2A, "vpbroadcastmb2q", - avx512vl_i64_info, VK8>, VEX_W; - -//===----------------------------------------------------------------------===// -// -- VPERMI2 - 3 source operands form -- -multiclass avx512_perm_i opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, - hasSideEffects = 0 in { - defm rr: AVX512_maskable_3src_cast, - EVEX_4V, AVX5128IBase, Sched<[sched]>; - - let mayLoad = 1 in - defm rm: AVX512_maskable_3src_cast, - EVEX_4V, AVX5128IBase, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_perm_i_mb opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, - hasSideEffects = 0, mayLoad = 1 in - defm rmb: AVX512_maskable_3src_cast, - AVX5128IBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_perm_i_sizes opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo ShuffleMask> { - defm NAME: avx512_perm_i, - avx512_perm_i_mb, EVEX_V512; - let Predicates = [HasVLX] in { - defm NAME#128: avx512_perm_i, - avx512_perm_i_mb, EVEX_V128; - defm NAME#256: avx512_perm_i, - avx512_perm_i_mb, EVEX_V256; - } -} - -multiclass avx512_perm_i_sizes_bw opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo Idx, - Predicate Prd> { - let Predicates = [Prd] in - defm NAME: avx512_perm_i, EVEX_V512; - let Predicates = [Prd, HasVLX] in { - defm NAME#128: avx512_perm_i, EVEX_V128; - defm NAME#256: avx512_perm_i, EVEX_V256; - } -} - -defm VPERMI2D : avx512_perm_i_sizes<0x76, "vpermi2d", WriteVarShuffle256, - avx512vl_i32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMI2Q : avx512_perm_i_sizes<0x76, "vpermi2q", WriteVarShuffle256, - avx512vl_i64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPERMI2W : avx512_perm_i_sizes_bw<0x75, "vpermi2w", WriteVarShuffle256, - avx512vl_i16_info, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPERMI2B : avx512_perm_i_sizes_bw<0x75, "vpermi2b", WriteVarShuffle256, - avx512vl_i8_info, avx512vl_i8_info, HasVBMI>, - EVEX_CD8<8, CD8VF>; -defm VPERMI2PS : avx512_perm_i_sizes<0x77, "vpermi2ps", WriteFVarShuffle256, - avx512vl_f32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMI2PD : avx512_perm_i_sizes<0x77, "vpermi2pd", WriteFVarShuffle256, - avx512vl_f64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; - -// Extra patterns to deal with extra bitcasts due to passthru and index being -// different types on the fp versions. -multiclass avx512_perm_i_lowering { - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 (_.VT _.RC:$src2), - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), _.RC:$src3), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rrk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 _.RC:$src2, - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), - (_.LdFrag addr:$src3)), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rmk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86VPermt2 _.RC:$src2, - (IdxVT.VT (bitconvert (CastVT.VT _.RC:$src1))), - (X86VBroadcast (_.ScalarLdFrag addr:$src3))), - (_.VT (bitconvert (CastVT.VT _.RC:$src1))))), - (!cast(InstrStr#"rmbk") _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3)>; -} - -// TODO: Should we add more casts? The vXi64 case is common due to ABI. -defm : avx512_perm_i_lowering<"VPERMI2PS", v16f32_info, v16i32_info, v8i64_info>; -defm : avx512_perm_i_lowering<"VPERMI2PS256", v8f32x_info, v8i32x_info, v4i64x_info>; -defm : avx512_perm_i_lowering<"VPERMI2PS128", v4f32x_info, v4i32x_info, v2i64x_info>; - -// VPERMT2 -multiclass avx512_perm_t opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable_3src, - EVEX_4V, AVX5128IBase, Sched<[sched]>; - - defm rm: AVX512_maskable_3src, - EVEX_4V, AVX5128IBase, Sched<[sched.Folded, ReadAfterLd]>; - } -} -multiclass avx512_perm_t_mb opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo IdxVT> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in - defm rmb: AVX512_maskable_3src, - AVX5128IBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_perm_t_sizes opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo ShuffleMask> { - defm NAME: avx512_perm_t, - avx512_perm_t_mb, EVEX_V512; - let Predicates = [HasVLX] in { - defm NAME#128: avx512_perm_t, - avx512_perm_t_mb, EVEX_V128; - defm NAME#256: avx512_perm_t, - avx512_perm_t_mb, EVEX_V256; - } -} - -multiclass avx512_perm_t_sizes_bw opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - AVX512VLVectorVTInfo Idx, Predicate Prd> { - let Predicates = [Prd] in - defm NAME: avx512_perm_t, EVEX_V512; - let Predicates = [Prd, HasVLX] in { - defm NAME#128: avx512_perm_t, EVEX_V128; - defm NAME#256: avx512_perm_t, EVEX_V256; - } -} - -defm VPERMT2D : avx512_perm_t_sizes<0x7E, "vpermt2d", WriteVarShuffle256, - avx512vl_i32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMT2Q : avx512_perm_t_sizes<0x7E, "vpermt2q", WriteVarShuffle256, - avx512vl_i64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPERMT2W : avx512_perm_t_sizes_bw<0x7D, "vpermt2w", WriteVarShuffle256, - avx512vl_i16_info, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPERMT2B : avx512_perm_t_sizes_bw<0x7D, "vpermt2b", WriteVarShuffle256, - avx512vl_i8_info, avx512vl_i8_info, HasVBMI>, - EVEX_CD8<8, CD8VF>; -defm VPERMT2PS : avx512_perm_t_sizes<0x7F, "vpermt2ps", WriteFVarShuffle256, - avx512vl_f32_info, avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VPERMT2PD : avx512_perm_t_sizes<0x7F, "vpermt2pd", WriteFVarShuffle256, - avx512vl_f64_info, avx512vl_i64_info>, VEX_W, EVEX_CD8<64, CD8VF>; - -//===----------------------------------------------------------------------===// -// AVX-512 - BLEND using mask -// - -multiclass WriteFVarBlendask opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - def rr : AVX5128I, - EVEX_4V, Sched<[sched]>; - def rrk : AVX5128I, EVEX_4V, EVEX_K, Sched<[sched]>; - def rrkz : AVX5128I, EVEX_4V, EVEX_KZ, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in { - def rm : AVX5128I, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX5128I, EVEX_4V, EVEX_K, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - def rmkz : AVX5128I, EVEX_4V, EVEX_KZ, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - } - } -} -multiclass WriteFVarBlendask_rmb opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let mayLoad = 1, hasSideEffects = 0 in { - def rmbk : AVX5128I, - EVEX_4V, EVEX_K, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - - def rmbkz : AVX5128I, - EVEX_4V, EVEX_KZ, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - - def rmb : AVX5128I, - EVEX_4V, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass blendmask_dq opc, string OpcodeStr, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - defm Z : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z256 : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V256; - defm Z128 : WriteFVarBlendask, - WriteFVarBlendask_rmb, - EVEX_V128; - } -} - -multiclass blendmask_bw opc, string OpcodeStr, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasBWI] in - defm Z : WriteFVarBlendask, - EVEX_V512; - - let Predicates = [HasBWI, HasVLX] in { - defm Z256 : WriteFVarBlendask, - EVEX_V256; - defm Z128 : WriteFVarBlendask, - EVEX_V128; - } -} - -defm VBLENDMPS : blendmask_dq<0x65, "vblendmps", SchedWriteFVarBlend, - avx512vl_f32_info>; -defm VBLENDMPD : blendmask_dq<0x65, "vblendmpd", SchedWriteFVarBlend, - avx512vl_f64_info>, VEX_W; -defm VPBLENDMD : blendmask_dq<0x64, "vpblendmd", SchedWriteVarBlend, - avx512vl_i32_info>; -defm VPBLENDMQ : blendmask_dq<0x64, "vpblendmq", SchedWriteVarBlend, - avx512vl_i64_info>, VEX_W; -defm VPBLENDMB : blendmask_bw<0x66, "vpblendmb", SchedWriteVarBlend, - avx512vl_i8_info>; -defm VPBLENDMW : blendmask_bw<0x66, "vpblendmw", SchedWriteVarBlend, - avx512vl_i16_info>, VEX_W; - -//===----------------------------------------------------------------------===// -// Compare Instructions -//===----------------------------------------------------------------------===// - -// avx512_cmp_scalar - AVX512 CMPSS and CMPSD - -multiclass avx512_cmp_scalar { - defm rr_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (OpNode (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc)>, EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - defm rm_Int : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.IntScalarMemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (OpNode (_.VT _.RC:$src1), _.ScalarIntMemCPat:$src2, - imm:$cc)>, EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rrb_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "{sae}, $src2, $src1", "$src1, $src2, {sae}", - (OpNodeRnd (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc, - (i32 FROUND_NO_EXC))>, - EVEX_4V, EVEX_B, Sched<[sched]>; - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rri_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs VK1:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, EVEX_4V, - Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - defm rmi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - - defm rrb_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, {sae}, $src2, $src1","$src1, $src2, {sae}, $cc">, - EVEX_4V, EVEX_B, Sched<[sched]>, NotMemoryFoldable; - }// let isAsmParserOnly = 1, hasSideEffects = 0 - - let isCodeGenOnly = 1 in { - let isCommutable = 1 in - def rr : AVX512Ii8<0xC2, MRMSrcReg, - (outs _.KRC:$dst), (ins _.FRC:$src1, _.FRC:$src2, AVXCC:$cc), - !strconcat("vcmp${cc}", _.Suffix, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - _.FRC:$src2, - imm:$cc))]>, - EVEX_4V, Sched<[sched]>; - def rm : AVX512Ii8<0xC2, MRMSrcMem, - (outs _.KRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2, AVXCC:$cc), - !strconcat("vcmp${cc}", _.Suffix, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2), - imm:$cc))]>, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let Predicates = [HasAVX512] in { - let ExeDomain = SSEPackedSingle in - defm VCMPSSZ : avx512_cmp_scalar, AVX512XSIi8Base; - let ExeDomain = SSEPackedDouble in - defm VCMPSDZ : avx512_cmp_scalar, AVX512XDIi8Base, VEX_W; -} - -multiclass avx512_icmp_packed opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable> { - let isCommutable = IsCommutable in - def rr : AVX512BI, - EVEX_4V, Sched<[sched]>; - def rm : AVX512BI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isCommutable = IsCommutable in - def rrk : AVX512BI, - EVEX_4V, EVEX_K, Sched<[sched]>; - def rmk : AVX512BI, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_icmp_packed_rmb opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable> : - avx512_icmp_packed { - def rmb : AVX512BI, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmbk : AVX512BI, - EVEX_4V, EVEX_K, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_icmp_packed_vl opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_icmp_packed, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_packed, EVEX_V256; - defm Z128 : avx512_icmp_packed, EVEX_V128; - } -} - -multiclass avx512_icmp_packed_rmb_vl opc, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, - Predicate prd, bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_icmp_packed_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_packed_rmb, EVEX_V256; - defm Z128 : avx512_icmp_packed_rmb, EVEX_V128; - } -} - -// This fragment treats X86cmpm as commutable to help match loads in both -// operands for PCMPEQ. -def X86setcc_commute : SDNode<"ISD::SETCC", SDTSetCC, [SDNPCommutative]>; -def X86pcmpeqm_c : PatFrag<(ops node:$src1, node:$src2), - (X86setcc_commute node:$src1, node:$src2, SETEQ)>; -def X86pcmpgtm : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETGT)>; - -// AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't -// increase the pattern complexity the way an immediate would. -let AddedComplexity = 2 in { -// FIXME: Is there a better scheduler class for VPCMP? -defm VPCMPEQB : avx512_icmp_packed_vl<0x74, "vpcmpeqb", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i8_info, HasBWI, 1>, - EVEX_CD8<8, CD8VF>, VEX_WIG; - -defm VPCMPEQW : avx512_icmp_packed_vl<0x75, "vpcmpeqw", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i16_info, HasBWI, 1>, - EVEX_CD8<16, CD8VF>, VEX_WIG; - -defm VPCMPEQD : avx512_icmp_packed_rmb_vl<0x76, "vpcmpeqd", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i32_info, HasAVX512, 1>, - EVEX_CD8<32, CD8VF>; - -defm VPCMPEQQ : avx512_icmp_packed_rmb_vl<0x29, "vpcmpeqq", X86pcmpeqm_c, - SchedWriteVecALU, avx512vl_i64_info, HasAVX512, 1>, - T8PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VPCMPGTB : avx512_icmp_packed_vl<0x64, "vpcmpgtb", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>, VEX_WIG; - -defm VPCMPGTW : avx512_icmp_packed_vl<0x65, "vpcmpgtw", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - EVEX_CD8<16, CD8VF>, VEX_WIG; - -defm VPCMPGTD : avx512_icmp_packed_rmb_vl<0x66, "vpcmpgtd", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i32_info, HasAVX512>, - EVEX_CD8<32, CD8VF>; - -defm VPCMPGTQ : avx512_icmp_packed_rmb_vl<0x37, "vpcmpgtq", X86pcmpgtm, - SchedWriteVecALU, avx512vl_i64_info, HasAVX512>, - T8PD, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_icmp_cc opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> { - let isCommutable = 1 in - def rri : AVX512AIi8, - EVEX_4V, Sched<[sched]>; - def rmi : AVX512AIi8, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isCommutable = 1 in - def rrik : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched]>; - def rmik : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rri_alt : AVX512AIi8, - EVEX_4V, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmi_alt : AVX512AIi8, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - def rrik_alt : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmik_alt : AVX512AIi8, - EVEX_4V, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - - def : Pat<(_.KVT (CommFrag:$cc (bitconvert (_.LdFrag addr:$src2)), - (_.VT _.RC:$src1), cond)), - (!cast(Name#_.ZSuffix#"rmi") - _.RC:$src1, addr:$src2, (CommFrag.OperandTransform $cc))>; - - def : Pat<(and _.KRCWM:$mask, - (_.KVT (CommFrag:$cc (bitconvert (_.LdFrag addr:$src2)), - (_.VT _.RC:$src1), cond))), - (!cast(Name#_.ZSuffix#"rmik") - _.KRCWM:$mask, _.RC:$src1, addr:$src2, - (CommFrag.OperandTransform $cc))>; -} - -multiclass avx512_icmp_cc_rmb opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> : - avx512_icmp_cc { - def rmib : AVX512AIi8, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmibk : AVX512AIi8, - EVEX_4V, EVEX_K, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0, mayLoad = 1 in { - def rmib_alt : AVX512AIi8, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - def rmibk_alt : AVX512AIi8, - EVEX_4V, EVEX_K, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - - def : Pat<(_.KVT (CommFrag:$cc (X86VBroadcast (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), cond)), - (!cast(Name#_.ZSuffix#"rmib") - _.RC:$src1, addr:$src2, (CommFrag.OperandTransform $cc))>; - - def : Pat<(and _.KRCWM:$mask, - (_.KVT (CommFrag:$cc (X86VBroadcast - (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), cond))), - (!cast(Name#_.ZSuffix#"rmibk") - _.KRCWM:$mask, _.RC:$src1, addr:$src2, - (CommFrag.OperandTransform $cc))>; -} - -multiclass avx512_icmp_cc_vl opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_icmp_cc, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_cc, EVEX_V256; - defm Z128 : avx512_icmp_cc, EVEX_V128; - } -} - -multiclass avx512_icmp_cc_rmb_vl opc, string Suffix, PatFrag Frag, - PatFrag CommFrag, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_icmp_cc_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_icmp_cc_rmb, EVEX_V256; - defm Z128 : avx512_icmp_cc_rmb, EVEX_V128; - } -} - -def X86pcmpm_imm : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - -// Swapped operand version of the above. -def X86pcmpm_imm_commute : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - SSECC = X86::getSwappedVPCMPImm(SSECC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - -def X86pcmpm : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -// Same as above, but commutes immediate. Use for load folding. -def X86pcmpm_commute : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm_commute>; - -def X86pcmpum : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -// Same as above, but commutes immediate. Use for load folding. -def X86pcmpum_commute : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm_commute>; - -// FIXME: Is there a better scheduler class for VPCMP/VPCMPU? -defm VPCMPB : avx512_icmp_cc_vl<0x3F, "b", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>; -defm VPCMPUB : avx512_icmp_cc_vl<0x3E, "ub", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i8_info, HasBWI>, - EVEX_CD8<8, CD8VF>; - -defm VPCMPW : avx512_icmp_cc_vl<0x3F, "w", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; -defm VPCMPUW : avx512_icmp_cc_vl<0x3E, "uw", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i16_info, HasBWI>, - VEX_W, EVEX_CD8<16, CD8VF>; - -defm VPCMPD : avx512_icmp_cc_rmb_vl<0x1F, "d", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i32_info, - HasAVX512>, EVEX_CD8<32, CD8VF>; -defm VPCMPUD : avx512_icmp_cc_rmb_vl<0x1E, "ud", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i32_info, - HasAVX512>, EVEX_CD8<32, CD8VF>; - -defm VPCMPQ : avx512_icmp_cc_rmb_vl<0x1F, "q", X86pcmpm, X86pcmpm_commute, - SchedWriteVecALU, avx512vl_i64_info, - HasAVX512>, VEX_W, EVEX_CD8<64, CD8VF>; -defm VPCMPUQ : avx512_icmp_cc_rmb_vl<0x1E, "uq", X86pcmpum, X86pcmpum_commute, - SchedWriteVecALU, avx512vl_i64_info, - HasAVX512>, VEX_W, EVEX_CD8<64, CD8VF>; - -multiclass avx512_vcmp_common { - defm rri : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), (ins _.RC:$src1, _.RC:$src2,AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (X86cmpm (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc), 1>, - Sched<[sched]>; - - defm rmi : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst),(ins _.RC:$src1, _.MemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "$src2, $src1", "$src1, $src2", - (X86cmpm (_.VT _.RC:$src1), - (_.VT (bitconvert (_.LdFrag addr:$src2))), - imm:$cc)>, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rmbi : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "${src2}"##_.BroadcastStr##", $src1", - "$src1, ${src2}"##_.BroadcastStr, - (X86cmpm (_.VT _.RC:$src1), - (_.VT (X86VBroadcast(_.ScalarLdFrag addr:$src2))), - imm:$cc)>, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rri_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - Sched<[sched]>, NotMemoryFoldable; - - let mayLoad = 1 in { - defm rmi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.MemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc">, - Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - - defm rmbi_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, ${src2}"##_.BroadcastStr##", $src1", - "$src1, ${src2}"##_.BroadcastStr##", $cc">, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - } - - // Patterns for selecting with loads in other operand. - def : Pat<(X86cmpm (_.LdFrag addr:$src2), (_.VT _.RC:$src1), - CommutableCMPCC:$cc), - (!cast(Name#_.ZSuffix#"rmi") _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(and _.KRCWM:$mask, (X86cmpm (_.LdFrag addr:$src2), - (_.VT _.RC:$src1), - CommutableCMPCC:$cc)), - (!cast(Name#_.ZSuffix#"rmik") _.KRCWM:$mask, - _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(X86cmpm (X86VBroadcast (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), CommutableCMPCC:$cc), - (!cast(Name#_.ZSuffix#"rmbi") _.RC:$src1, addr:$src2, - imm:$cc)>; - - def : Pat<(and _.KRCWM:$mask, (X86cmpm (X86VBroadcast - (_.ScalarLdFrag addr:$src2)), - (_.VT _.RC:$src1), - CommutableCMPCC:$cc)), - (!cast(Name#_.ZSuffix#"rmbik") _.KRCWM:$mask, - _.RC:$src1, addr:$src2, - imm:$cc)>; -} - -multiclass avx512_vcmp_sae { - // comparison code form (VCMP[EQ/LT/LE/...] - defm rrib : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst),(ins _.RC:$src1, _.RC:$src2, AVXCC:$cc), - "vcmp${cc}"#_.Suffix, - "{sae}, $src2, $src1", "$src1, $src2, {sae}", - (X86cmpmRnd (_.VT _.RC:$src1), - (_.VT _.RC:$src2), - imm:$cc, - (i32 FROUND_NO_EXC))>, - EVEX_B, Sched<[sched]>; - - let isAsmParserOnly = 1, hasSideEffects = 0 in { - defm rrib_alt : AVX512_maskable_cmp_alt<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, {sae}, $src2, $src1", - "$src1, $src2, {sae}, $cc">, - EVEX_B, Sched<[sched]>, NotMemoryFoldable; - } -} - -multiclass avx512_vcmp { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcmp_common, - avx512_vcmp_sae, EVEX_V512; - - } - let Predicates = [HasAVX512,HasVLX] in { - defm Z128 : avx512_vcmp_common, EVEX_V128; - defm Z256 : avx512_vcmp_common, EVEX_V256; - } -} - -defm VCMPPD : avx512_vcmp, - AVX512PDIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VCMPPS : avx512_vcmp, - AVX512PSIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - -// Patterns to select fp compares with load as first operand. -let Predicates = [HasAVX512] in { - def : Pat<(v1i1 (X86cmpms (loadf64 addr:$src2), FR64X:$src1, - CommutableCMPCC:$cc)), - (VCMPSDZrm FR64X:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v1i1 (X86cmpms (loadf32 addr:$src2), FR32X:$src1, - CommutableCMPCC:$cc)), - (VCMPSSZrm FR32X:$src1, addr:$src2, imm:$cc)>; -} - -// ---------------------------------------------------------------- -// FPClass -//handle fpclass instruction mask = op(reg_scalar,imm) -// op(mem_scalar,imm) -multiclass avx512_scalar_fpclass opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - Predicate prd> { - let Predicates = [prd], ExeDomain = _.ExeDomain in { - def rr : AVX512, - Sched<[sched]>; - def rrk : AVX512, - EVEX_K, Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX512, - EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle fpclass instruction mask = fpclass(reg_vec, reg_vec, imm) -// fpclass(reg_vec, mem_vec, imm) -// fpclass(reg_vec, broadcast(eltVt), imm) -multiclass avx512_vector_fpclass opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string mem, string broadcast>{ - let ExeDomain = _.ExeDomain in { - def rr : AVX512, - Sched<[sched]>; - def rrk : AVX512, - EVEX_K, Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; - def rmk : AVX512, - EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - def rmb : AVX512, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - def rmbk : AVX512, - EVEX_B, EVEX_K, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_vector_fpclass_all opc, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - string broadcast>{ - let Predicates = [prd] in { - defm Z : avx512_vector_fpclass, EVEX_V512; - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_vector_fpclass, EVEX_V128; - defm Z256 : avx512_vector_fpclass, EVEX_V256; - } -} - -multiclass avx512_fp_fpclass_all opcVec, - bits<8> opcScalar, SDNode VecOpNode, - SDNode ScalarOpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm PS : avx512_vector_fpclass_all, - EVEX_CD8<32, CD8VF>; - defm PD : avx512_vector_fpclass_all, - EVEX_CD8<64, CD8VF> , VEX_W; - defm SSZ : avx512_scalar_fpclass, - EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_scalar_fpclass, - EVEX_CD8<64, CD8VT1>, VEX_W; -} - -defm VFPCLASS : avx512_fp_fpclass_all<"vfpclass", 0x66, 0x67, X86Vfpclass, - X86Vfpclasss, SchedWriteFCmp, HasDQI>, - AVX512AIi8Base, EVEX; - -//----------------------------------------------------------------- -// Mask register copy, including -// - copy between mask registers -// - load/store mask registers -// - copy from GPR to mask register and vice versa -// -multiclass avx512_mask_mov opc_kk, bits<8> opc_km, bits<8> opc_mk, - string OpcodeStr, RegisterClass KRC, - ValueType vvt, X86MemOperand x86memop> { - let isMoveReg = 1, hasSideEffects = 0, SchedRW = [WriteMove] in - def kk : I, - Sched<[WriteMove]>; - def km : I, - Sched<[WriteLoad]>; - def mk : I, - Sched<[WriteStore]>; -} - -multiclass avx512_mask_mov_gpr opc_kr, bits<8> opc_rk, - string OpcodeStr, - RegisterClass KRC, RegisterClass GRC> { - let hasSideEffects = 0 in { - def kr : I, - Sched<[WriteMove]>; - def rk : I, - Sched<[WriteMove]>; - } -} - -let Predicates = [HasDQI] in - defm KMOVB : avx512_mask_mov<0x90, 0x90, 0x91, "kmovb", VK8, v8i1, i8mem>, - avx512_mask_mov_gpr<0x92, 0x93, "kmovb", VK8, GR32>, - VEX, PD; - -let Predicates = [HasAVX512] in - defm KMOVW : avx512_mask_mov<0x90, 0x90, 0x91, "kmovw", VK16, v16i1, i16mem>, - avx512_mask_mov_gpr<0x92, 0x93, "kmovw", VK16, GR32>, - VEX, PS; - -let Predicates = [HasBWI] in { - defm KMOVD : avx512_mask_mov<0x90, 0x90, 0x91, "kmovd", VK32, v32i1,i32mem>, - VEX, PD, VEX_W; - defm KMOVD : avx512_mask_mov_gpr<0x92, 0x93, "kmovd", VK32, GR32>, - VEX, XD; - defm KMOVQ : avx512_mask_mov<0x90, 0x90, 0x91, "kmovq", VK64, v64i1, i64mem>, - VEX, PS, VEX_W; - defm KMOVQ : avx512_mask_mov_gpr<0x92, 0x93, "kmovq", VK64, GR64>, - VEX, XD, VEX_W; -} - -// GR from/to mask register -def : Pat<(v16i1 (bitconvert (i16 GR16:$src))), - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), GR16:$src, sub_16bit)), VK16)>; -def : Pat<(i16 (bitconvert (v16i1 VK16:$src))), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS VK16:$src, GR32)), sub_16bit)>; - -def : Pat<(v8i1 (bitconvert (i8 GR8:$src))), - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), GR8:$src, sub_8bit)), VK8)>; -def : Pat<(i8 (bitconvert (v8i1 VK8:$src))), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS VK8:$src, GR32)), sub_8bit)>; - -def : Pat<(i32 (zext (i16 (bitconvert (v16i1 VK16:$src))))), - (KMOVWrk VK16:$src)>; -def : Pat<(i32 (anyext (i16 (bitconvert (v16i1 VK16:$src))))), - (COPY_TO_REGCLASS VK16:$src, GR32)>; - -def : Pat<(i32 (zext (i8 (bitconvert (v8i1 VK8:$src))))), - (KMOVBrk VK8:$src)>, Requires<[HasDQI]>; -def : Pat<(i32 (anyext (i8 (bitconvert (v8i1 VK8:$src))))), - (COPY_TO_REGCLASS VK8:$src, GR32)>; - -def : Pat<(v32i1 (bitconvert (i32 GR32:$src))), - (COPY_TO_REGCLASS GR32:$src, VK32)>; -def : Pat<(i32 (bitconvert (v32i1 VK32:$src))), - (COPY_TO_REGCLASS VK32:$src, GR32)>; -def : Pat<(v64i1 (bitconvert (i64 GR64:$src))), - (COPY_TO_REGCLASS GR64:$src, VK64)>; -def : Pat<(i64 (bitconvert (v64i1 VK64:$src))), - (COPY_TO_REGCLASS VK64:$src, GR64)>; - -// Load/store kreg -let Predicates = [HasDQI] in { - def : Pat<(store VK1:$src, addr:$dst), - (KMOVBmk addr:$dst, (COPY_TO_REGCLASS VK1:$src, VK8))>; - - def : Pat<(v1i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK1)>; - def : Pat<(v2i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK2)>; - def : Pat<(v4i1 (load addr:$src)), - (COPY_TO_REGCLASS (KMOVBkm addr:$src), VK4)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v8i1 (bitconvert (i8 (load addr:$src)))), - (COPY_TO_REGCLASS (MOVZX32rm8 addr:$src), VK8)>; -} - -let Predicates = [HasAVX512] in { - multiclass operation_gpr_mask_copy_lowering { - def : Pat<(maskVT (scalar_to_vector GR32:$src)), - (COPY_TO_REGCLASS GR32:$src, maskRC)>; - - def : Pat<(maskVT (scalar_to_vector GR8:$src)), - (COPY_TO_REGCLASS (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src, sub_8bit), maskRC)>; - } - - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - defm : operation_gpr_mask_copy_lowering; - - def : Pat<(insert_subvector (v16i1 immAllZerosV), - (v1i1 (scalar_to_vector GR8:$src)), (iPTR 0)), - (COPY_TO_REGCLASS - (KMOVWkr (AND32ri8 - (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src, sub_8bit), - (i32 1))), VK16)>; -} - -// Mask unary operation -// - KNOT -multiclass avx512_mask_unop opc, string OpcodeStr, - RegisterClass KRC, SDPatternOperator OpNode, - X86FoldableSchedWrite sched, Predicate prd> { - let Predicates = [prd] in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_unop_all opc, string OpcodeStr, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched> { - defm B : avx512_mask_unop, VEX, PD; - defm W : avx512_mask_unop, VEX, PS; - defm D : avx512_mask_unop, VEX, PD, VEX_W; - defm Q : avx512_mask_unop, VEX, PS, VEX_W; -} - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KNOT : avx512_mask_unop_all<0x44, "knot", vnot, SchedWriteVecLogic.XMM>; - -// KNL does not support KMOVB, 8-bit mask is promoted to 16-bit -let Predicates = [HasAVX512, NoDQI] in -def : Pat<(vnot VK8:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK8:$src, VK16)), VK8)>; - -def : Pat<(vnot VK4:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK4:$src, VK16)), VK4)>; -def : Pat<(vnot VK2:$src), - (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK2:$src, VK16)), VK2)>; - -// Mask binary operation -// - KAND, KANDN, KOR, KXNOR, KXOR -multiclass avx512_mask_binop opc, string OpcodeStr, - RegisterClass KRC, SDPatternOperator OpNode, - X86FoldableSchedWrite sched, Predicate prd, - bit IsCommutable> { - let Predicates = [prd], isCommutable = IsCommutable in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_binop_all opc, string OpcodeStr, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched, bit IsCommutable, - Predicate prdW = HasAVX512> { - defm B : avx512_mask_binop, VEX_4V, VEX_L, PD; - defm W : avx512_mask_binop, VEX_4V, VEX_L, PS; - defm D : avx512_mask_binop, VEX_4V, VEX_L, VEX_W, PD; - defm Q : avx512_mask_binop, VEX_4V, VEX_L, VEX_W, PS; -} - -def andn : PatFrag<(ops node:$i0, node:$i1), (and (not node:$i0), node:$i1)>; -def xnor : PatFrag<(ops node:$i0, node:$i1), (not (xor node:$i0, node:$i1))>; -// These nodes use 'vnot' instead of 'not' to support vectors. -def vandn : PatFrag<(ops node:$i0, node:$i1), (and (vnot node:$i0), node:$i1)>; -def vxnor : PatFrag<(ops node:$i0, node:$i1), (vnot (xor node:$i0, node:$i1))>; - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KAND : avx512_mask_binop_all<0x41, "kand", and, SchedWriteVecLogic.XMM, 1>; -defm KOR : avx512_mask_binop_all<0x45, "kor", or, SchedWriteVecLogic.XMM, 1>; -defm KXNOR : avx512_mask_binop_all<0x46, "kxnor", vxnor, SchedWriteVecLogic.XMM, 1>; -defm KXOR : avx512_mask_binop_all<0x47, "kxor", xor, SchedWriteVecLogic.XMM, 1>; -defm KANDN : avx512_mask_binop_all<0x42, "kandn", vandn, SchedWriteVecLogic.XMM, 0>; -defm KADD : avx512_mask_binop_all<0x4A, "kadd", X86kadd, SchedWriteVecLogic.XMM, 1, HasDQI>; - -multiclass avx512_binop_pat { - // With AVX512F, 8-bit mask is promoted to 16-bit mask, - // for the DQI set, this type is legal and KxxxB instruction is used - let Predicates = [NoDQI] in - def : Pat<(VOpNode VK8:$src1, VK8:$src2), - (COPY_TO_REGCLASS - (Inst (COPY_TO_REGCLASS VK8:$src1, VK16), - (COPY_TO_REGCLASS VK8:$src2, VK16)), VK8)>; - - // All types smaller than 8 bits require conversion anyway - def : Pat<(OpNode VK1:$src1, VK1:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK1:$src1, VK16), - (COPY_TO_REGCLASS VK1:$src2, VK16)), VK1)>; - def : Pat<(VOpNode VK2:$src1, VK2:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK2:$src1, VK16), - (COPY_TO_REGCLASS VK2:$src2, VK16)), VK1)>; - def : Pat<(VOpNode VK4:$src1, VK4:$src2), - (COPY_TO_REGCLASS (Inst - (COPY_TO_REGCLASS VK4:$src1, VK16), - (COPY_TO_REGCLASS VK4:$src2, VK16)), VK1)>; -} - -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; -defm : avx512_binop_pat; - -// Mask unpacking -multiclass avx512_mask_unpck { - let Predicates = [prd] in { - let hasSideEffects = 0 in - def rr : I<0x4b, MRMSrcReg, (outs KRC:$dst), - (ins KRC:$src1, KRC:$src2), - "kunpck"#Suffix#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - VEX_4V, VEX_L, Sched<[sched]>; - - def : Pat<(VT (concat_vectors KRCSrc:$src1, KRCSrc:$src2)), - (!cast(NAME##rr) - (COPY_TO_REGCLASS KRCSrc:$src2, KRC), - (COPY_TO_REGCLASS KRCSrc:$src1, KRC))>; - } -} - -defm KUNPCKBW : avx512_mask_unpck<"bw", VK16, v16i1, VK8, WriteShuffle, HasAVX512>, PD; -defm KUNPCKWD : avx512_mask_unpck<"wd", VK32, v32i1, VK16, WriteShuffle, HasBWI>, PS; -defm KUNPCKDQ : avx512_mask_unpck<"dq", VK64, v64i1, VK32, WriteShuffle, HasBWI>, PS, VEX_W; - -// Mask bit testing -multiclass avx512_mask_testop opc, string OpcodeStr, RegisterClass KRC, - SDNode OpNode, X86FoldableSchedWrite sched, - Predicate prd> { - let Predicates = [prd], Defs = [EFLAGS] in - def rr : I, - Sched<[sched]>; -} - -multiclass avx512_mask_testop_w opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - Predicate prdW = HasAVX512> { - defm B : avx512_mask_testop, - VEX, PD; - defm W : avx512_mask_testop, - VEX, PS; - defm Q : avx512_mask_testop, - VEX, PS, VEX_W; - defm D : avx512_mask_testop, - VEX, PD, VEX_W; -} - -// TODO - do we need a X86SchedWriteWidths::KMASK type? -defm KORTEST : avx512_mask_testop_w<0x98, "kortest", X86kortest, SchedWriteVecLogic.XMM>; -defm KTEST : avx512_mask_testop_w<0x99, "ktest", X86ktest, SchedWriteVecLogic.XMM, HasDQI>; - -// Mask shift -multiclass avx512_mask_shiftop opc, string OpcodeStr, RegisterClass KRC, - SDNode OpNode, X86FoldableSchedWrite sched> { - let Predicates = [HasAVX512] in - def ri : Ii8, - Sched<[sched]>; -} - -multiclass avx512_mask_shiftop_w opc1, bits<8> opc2, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched> { - defm W : avx512_mask_shiftop, VEX, TAPD, VEX_W; - let Predicates = [HasDQI] in - defm B : avx512_mask_shiftop, VEX, TAPD; - let Predicates = [HasBWI] in { - defm Q : avx512_mask_shiftop, VEX, TAPD, VEX_W; - defm D : avx512_mask_shiftop, VEX, TAPD; - } -} - -defm KSHIFTL : avx512_mask_shiftop_w<0x32, 0x33, "kshiftl", X86kshiftl, WriteShuffle>; -defm KSHIFTR : avx512_mask_shiftop_w<0x30, 0x31, "kshiftr", X86kshiftr, WriteShuffle>; - -// Patterns for comparing 128/256-bit integer vectors using 512-bit instruction. -multiclass axv512_icmp_packed_no_vlx_lowering { - def : Pat<(Narrow.KVT (Frag (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2))), - (COPY_TO_REGCLASS - (!cast(InstStr#"Zrr") - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx))), - Narrow.KRC)>; - - def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (Frag (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2)))), - (COPY_TO_REGCLASS - (!cast(InstStr#"Zrrk") - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx))), - Narrow.KRC)>; -} - -// Patterns for comparing 128/256-bit integer vectors using 512-bit instruction. -multiclass axv512_icmp_packed_cc_no_vlx_lowering { -def : Pat<(Narrow.KVT (Frag:$cc (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), cond)), - (COPY_TO_REGCLASS - (!cast(InstStr##Zrri) - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - (Frag.OperandTransform $cc)), Narrow.KRC)>; - -def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (Narrow.KVT (Frag:$cc (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), - cond)))), - (COPY_TO_REGCLASS (!cast(InstStr##Zrrik) - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - (Frag.OperandTransform $cc)), Narrow.KRC)>; -} - -// Same as above, but for fp types which don't use PatFrags. -multiclass axv512_cmp_packed_cc_no_vlx_lowering { -def : Pat<(Narrow.KVT (OpNode (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), imm:$cc)), - (COPY_TO_REGCLASS - (!cast(InstStr##Zrri) - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - imm:$cc), Narrow.KRC)>; - -def : Pat<(Narrow.KVT (and Narrow.KRC:$mask, - (OpNode (Narrow.VT Narrow.RC:$src1), - (Narrow.VT Narrow.RC:$src2), imm:$cc))), - (COPY_TO_REGCLASS (!cast(InstStr##Zrrik) - (COPY_TO_REGCLASS Narrow.KRC:$mask, Wide.KRC), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src2, Narrow.SubRegIdx)), - imm:$cc), Narrow.KRC)>; -} - -let Predicates = [HasAVX512, NoVLX] in { - // AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't - // increase the pattern complexity the way an immediate would. - let AddedComplexity = 2 in { - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - } - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; - defm : axv512_cmp_packed_cc_no_vlx_lowering; -} - -let Predicates = [HasBWI, NoVLX] in { - // AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't - // increase the pattern complexity the way an immediate would. - let AddedComplexity = 2 in { - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - - defm : axv512_icmp_packed_no_vlx_lowering; - defm : axv512_icmp_packed_no_vlx_lowering; - } - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; - - defm : axv512_icmp_packed_cc_no_vlx_lowering; - defm : axv512_icmp_packed_cc_no_vlx_lowering; -} - -// Mask setting all 0s or 1s -multiclass avx512_mask_setop { - let Predicates = [HasAVX512] in - let isReMaterializable = 1, isAsCheapAsAMove = 1, isPseudo = 1, - SchedRW = [WriteZero] in - def #NAME# : I<0, Pseudo, (outs KRC:$dst), (ins), "", - [(set KRC:$dst, (VT Val))]>; -} - -multiclass avx512_mask_setop_w { - defm W : avx512_mask_setop; - defm D : avx512_mask_setop; - defm Q : avx512_mask_setop; -} - -defm KSET0 : avx512_mask_setop_w; -defm KSET1 : avx512_mask_setop_w; - -// With AVX-512 only, 8-bit mask is promoted to 16-bit mask. -let Predicates = [HasAVX512] in { - def : Pat<(v8i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK8)>; - def : Pat<(v4i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK4)>; - def : Pat<(v2i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK2)>; - def : Pat<(v1i1 immAllZerosV), (COPY_TO_REGCLASS (KSET0W), VK1)>; - def : Pat<(v8i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK8)>; - def : Pat<(v4i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK4)>; - def : Pat<(v2i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK2)>; - def : Pat<(v1i1 immAllOnesV), (COPY_TO_REGCLASS (KSET1W), VK1)>; -} - -// Patterns for kmask insert_subvector/extract_subvector to/from index=0 -multiclass operation_subvector_mask_lowering { - def : Pat<(subVT (extract_subvector (VT RC:$src), (iPTR 0))), - (subVT (COPY_TO_REGCLASS RC:$src, subRC))>; - - def : Pat<(VT (insert_subvector undef, subRC:$src, (iPTR 0))), - (VT (COPY_TO_REGCLASS subRC:$src, RC))>; -} -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; -defm : operation_subvector_mask_lowering; - -defm : operation_subvector_mask_lowering; - -//===----------------------------------------------------------------------===// -// AVX-512 - Aligned and unaligned load and store -// - -multiclass avx512_load opc, string OpcodeStr, string Name, - X86VectorVTInfo _, PatFrag ld_frag, PatFrag mload, - X86SchedWriteMoveLS Sched, string EVEX2VEXOvrd, - bit NoRMPattern = 0, - SDPatternOperator SelectOprr = vselect> { - let hasSideEffects = 0 in { - let isMoveReg = 1 in - def rr : AVX512PI, EVEX, Sched<[Sched.RR]>, - EVEX2VEXOverride; - def rrkz : AVX512PI, - EVEX, EVEX_KZ, Sched<[Sched.RR]>; - - let mayLoad = 1, canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : AVX512PI, EVEX, Sched<[Sched.RM]>, - EVEX2VEXOverride; - - let Constraints = "$src0 = $dst", isConvertibleToThreeAddress = 1 in { - def rrk : AVX512PI, - EVEX, EVEX_K, Sched<[Sched.RR]>; - def rmk : AVX512PI, - EVEX, EVEX_K, Sched<[Sched.RM]>; - } - def rmkz : AVX512PI, EVEX, EVEX_KZ, Sched<[Sched.RM]>; - } - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, undef)), - (!cast(Name#_.ZSuffix##rmkz) _.KRCWM:$mask, addr:$ptr)>; - - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix##rmkz) _.KRCWM:$mask, addr:$ptr)>; - - def : Pat<(_.VT (mload addr:$ptr, _.KRCWM:$mask, (_.VT _.RC:$src0))), - (!cast(Name#_.ZSuffix##rmk) _.RC:$src0, - _.KRCWM:$mask, addr:$ptr)>; -} - -multiclass avx512_alignedload_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoRMPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_load, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_load, EVEX_V256; - defm Z128 : avx512_load, EVEX_V128; - } -} - -multiclass avx512_load_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoRMPattern = 0, - SDPatternOperator SelectOprr = vselect> { - let Predicates = [prd] in - defm Z : avx512_load, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_load, EVEX_V256; - defm Z128 : avx512_load, EVEX_V128; - } -} - -multiclass avx512_store opc, string OpcodeStr, string BaseName, - X86VectorVTInfo _, PatFrag st_frag, PatFrag mstore, - X86SchedWriteMoveLS Sched, string EVEX2VEXOvrd, - bit NoMRPattern = 0> { - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - let isMoveReg = 1 in - def rr_REV : AVX512PI, EVEX, - FoldGenData, Sched<[Sched.RR]>, - EVEX2VEXOverride; - def rrk_REV : AVX512PI, EVEX, EVEX_K, - FoldGenData, - Sched<[Sched.RR]>; - def rrkz_REV : AVX512PI, EVEX, EVEX_KZ, - FoldGenData, - Sched<[Sched.RR]>; - } - - let hasSideEffects = 0, mayStore = 1 in - def mr : AVX512PI, EVEX, Sched<[Sched.MR]>, - EVEX2VEXOverride; - def mrk : AVX512PI, EVEX, EVEX_K, Sched<[Sched.MR]>, - NotMemoryFoldable; - - def: Pat<(mstore addr:$ptr, _.KRCWM:$mask, (_.VT _.RC:$src)), - (!cast(BaseName#_.ZSuffix#mrk) addr:$ptr, - _.KRCWM:$mask, _.RC:$src)>; - - def : InstAlias(BaseName#_.ZSuffix#"rr_REV") - _.RC:$dst, _.RC:$src), 0>; - def : InstAlias(BaseName#_.ZSuffix#"rrk_REV") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src), 0>; - def : InstAlias(BaseName#_.ZSuffix#"rrkz_REV") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src), 0>; -} - -multiclass avx512_store_vl< bits<8> opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoMRPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_store, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_store, EVEX_V256; - defm Z128 : avx512_store, EVEX_V128; - } -} - -multiclass avx512_alignedstore_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo _, Predicate prd, - X86SchedWriteMoveLSWidths Sched, - string EVEX2VEXOvrd, bit NoMRPattern = 0> { - let Predicates = [prd] in - defm Z : avx512_store, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_store, EVEX_V256; - defm Z128 : avx512_store, EVEX_V128; - } -} - -defm VMOVAPS : avx512_alignedload_vl<0x28, "vmovaps", avx512vl_f32_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPS">, - avx512_alignedstore_vl<0x29, "vmovaps", avx512vl_f32_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPS">, - PS, EVEX_CD8<32, CD8VF>; - -defm VMOVAPD : avx512_alignedload_vl<0x28, "vmovapd", avx512vl_f64_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPD">, - avx512_alignedstore_vl<0x29, "vmovapd", avx512vl_f64_info, - HasAVX512, SchedWriteFMoveLS, "VMOVAPD">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVUPS : avx512_load_vl<0x10, "vmovups", avx512vl_f32_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPS", 0, null_frag>, - avx512_store_vl<0x11, "vmovups", avx512vl_f32_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPS">, - PS, EVEX_CD8<32, CD8VF>; - -defm VMOVUPD : avx512_load_vl<0x10, "vmovupd", avx512vl_f64_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPD", 0, null_frag>, - avx512_store_vl<0x11, "vmovupd", avx512vl_f64_info, HasAVX512, - SchedWriteFMoveLS, "VMOVUPD">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVDQA32 : avx512_alignedload_vl<0x6F, "vmovdqa32", avx512vl_i32_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA", 1>, - avx512_alignedstore_vl<0x7F, "vmovdqa32", avx512vl_i32_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA", 1>, - PD, EVEX_CD8<32, CD8VF>; - -defm VMOVDQA64 : avx512_alignedload_vl<0x6F, "vmovdqa64", avx512vl_i64_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA">, - avx512_alignedstore_vl<0x7F, "vmovdqa64", avx512vl_i64_info, - HasAVX512, SchedWriteVecMoveLS, - "VMOVDQA">, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VMOVDQU8 : avx512_load_vl<0x6F, "vmovdqu8", avx512vl_i8_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - avx512_store_vl<0x7F, "vmovdqu8", avx512vl_i8_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XD, EVEX_CD8<8, CD8VF>; - -defm VMOVDQU16 : avx512_load_vl<0x6F, "vmovdqu16", avx512vl_i16_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - avx512_store_vl<0x7F, "vmovdqu16", avx512vl_i16_info, HasBWI, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XD, VEX_W, EVEX_CD8<16, CD8VF>; - -defm VMOVDQU32 : avx512_load_vl<0x6F, "vmovdqu32", avx512vl_i32_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 1, null_frag>, - avx512_store_vl<0x7F, "vmovdqu32", avx512vl_i32_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 1>, - XS, EVEX_CD8<32, CD8VF>; - -defm VMOVDQU64 : avx512_load_vl<0x6F, "vmovdqu64", avx512vl_i64_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU", 0, null_frag>, - avx512_store_vl<0x7F, "vmovdqu64", avx512vl_i64_info, HasAVX512, - SchedWriteVecMoveLS, "VMOVDQU">, - XS, VEX_W, EVEX_CD8<64, CD8VF>; - -/* -// Special instructions to help with spilling when we don't have VLX. We need -// to load or store from a ZMM register instead. These are converted in -// expandPostRAPseudos. -let isReMaterializable = 1, canFoldAsLoad = 1, - isPseudo = 1, mayLoad = 1, hasSideEffects = 0 in { -def VMOVAPSZ128rm_NOVLX : I<0, Pseudo, (outs VR128X:$dst), (ins f128mem:$src), - "", []>, Sched<[WriteFLoadX]>; -def VMOVAPSZ256rm_NOVLX : I<0, Pseudo, (outs VR256X:$dst), (ins f256mem:$src), - "", []>, Sched<[WriteFLoadY]>; -def VMOVUPSZ128rm_NOVLX : I<0, Pseudo, (outs VR128X:$dst), (ins f128mem:$src), - "", []>, Sched<[WriteFLoadX]>; -def VMOVUPSZ256rm_NOVLX : I<0, Pseudo, (outs VR256X:$dst), (ins f256mem:$src), - "", []>, Sched<[WriteFLoadY]>; -} - -let isPseudo = 1, mayStore = 1, hasSideEffects = 0 in { -def VMOVAPSZ128mr_NOVLX : I<0, Pseudo, (outs), (ins f128mem:$dst, VR128X:$src), - "", []>, Sched<[WriteFStoreX]>; -def VMOVAPSZ256mr_NOVLX : I<0, Pseudo, (outs), (ins f256mem:$dst, VR256X:$src), - "", []>, Sched<[WriteFStoreY]>; -def VMOVUPSZ128mr_NOVLX : I<0, Pseudo, (outs), (ins f128mem:$dst, VR128X:$src), - "", []>, Sched<[WriteFStoreX]>; -def VMOVUPSZ256mr_NOVLX : I<0, Pseudo, (outs), (ins f256mem:$dst, VR256X:$src), - "", []>, Sched<[WriteFStoreY]>; -} -*/ - -def : Pat<(v8i64 (vselect VK8WM:$mask, (bc_v8i64 (v16i32 immAllZerosV)), - (v8i64 VR512:$src))), - (VMOVDQA64Zrrkz (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK8:$mask, VK16)), - VK8), VR512:$src)>; - -def : Pat<(v16i32 (vselect VK16WM:$mask, (v16i32 immAllZerosV), - (v16i32 VR512:$src))), - (VMOVDQA32Zrrkz (KNOTWrr VK16WM:$mask), VR512:$src)>; - -// These patterns exist to prevent the above patterns from introducing a second -// mask inversion when one already exists. -def : Pat<(v8i64 (vselect (xor VK8:$mask, (v8i1 immAllOnesV)), - (bc_v8i64 (v16i32 immAllZerosV)), - (v8i64 VR512:$src))), - (VMOVDQA64Zrrkz VK8:$mask, VR512:$src)>; -def : Pat<(v16i32 (vselect (xor VK16:$mask, (v16i1 immAllOnesV)), - (v16i32 immAllZerosV), - (v16i32 VR512:$src))), - (VMOVDQA32Zrrkz VK16WM:$mask, VR512:$src)>; - -multiclass mask_move_lowering { - def : Pat<(Narrow.VT (vselect (Narrow.KVT Narrow.KRCWM:$mask), - Narrow.RC:$src1, Narrow.RC:$src0)), - (EXTRACT_SUBREG - (Wide.VT - (!cast(InstrStr#"rrk") - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src0, Narrow.SubRegIdx)), - (COPY_TO_REGCLASS Narrow.KRCWM:$mask, Wide.KRCWM), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)))), - Narrow.SubRegIdx)>; - - def : Pat<(Narrow.VT (vselect (Narrow.KVT Narrow.KRCWM:$mask), - Narrow.RC:$src1, Narrow.ImmAllZerosV)), - (EXTRACT_SUBREG - (Wide.VT - (!cast(InstrStr#"rrkz") - (COPY_TO_REGCLASS Narrow.KRCWM:$mask, Wide.KRCWM), - (Wide.VT (INSERT_SUBREG (IMPLICIT_DEF), Narrow.RC:$src1, Narrow.SubRegIdx)))), - Narrow.SubRegIdx)>; -} - -// Patterns for handling v8i1 selects of 256-bit vectors when VLX isn't -// available. Use a 512-bit operation and extract. -let Predicates = [HasAVX512, NoVLX] in { - defm : mask_move_lowering<"VMOVAPSZ", v4f32x_info, v16f32_info>; - defm : mask_move_lowering<"VMOVDQA32Z", v4i32x_info, v16i32_info>; - defm : mask_move_lowering<"VMOVAPSZ", v8f32x_info, v16f32_info>; - defm : mask_move_lowering<"VMOVDQA32Z", v8i32x_info, v16i32_info>; - - defm : mask_move_lowering<"VMOVAPDZ", v2f64x_info, v8f64_info>; - defm : mask_move_lowering<"VMOVDQA64Z", v2i64x_info, v8i64_info>; - defm : mask_move_lowering<"VMOVAPDZ", v4f64x_info, v8f64_info>; - defm : mask_move_lowering<"VMOVDQA64Z", v4i64x_info, v8i64_info>; -} - -let Predicates = [HasBWI, NoVLX] in { - defm : mask_move_lowering<"VMOVDQU8Z", v16i8x_info, v64i8_info>; - defm : mask_move_lowering<"VMOVDQU8Z", v32i8x_info, v64i8_info>; - - defm : mask_move_lowering<"VMOVDQU16Z", v8i16x_info, v32i16_info>; - defm : mask_move_lowering<"VMOVDQU16Z", v16i16x_info, v32i16_info>; -} - -let Predicates = [HasAVX512] in { - // 512-bit store. - def : Pat<(alignedstore (v16i32 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(alignedstore (v32i16 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(alignedstore (v64i8 VR512:$src), addr:$dst), - (VMOVDQA64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v16i32 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v32i16 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; - def : Pat<(store (v64i8 VR512:$src), addr:$dst), - (VMOVDQU64Zmr addr:$dst, VR512:$src)>; -} - -let Predicates = [HasVLX] in { - // 128-bit store. - def : Pat<(alignedstore (v4i32 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignedstore (v8i16 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignedstore (v16i8 VR128X:$src), addr:$dst), - (VMOVDQA64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v4i32 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v8i16 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - def : Pat<(store (v16i8 VR128X:$src), addr:$dst), - (VMOVDQU64Z128mr addr:$dst, VR128X:$src)>; - - // 256-bit store. - def : Pat<(alignedstore (v8i32 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignedstore (v16i16 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignedstore (v32i8 VR256X:$src), addr:$dst), - (VMOVDQA64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v8i32 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v16i16 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; - def : Pat<(store (v32i8 VR256X:$src), addr:$dst), - (VMOVDQU64Z256mr addr:$dst, VR256X:$src)>; -} - -multiclass masked_move_for_extract { - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (extract_subvector - (From.VT From.RC:$src), (iPTR 0)))), - To.RC:$src0)), - (Cast.VT (!cast(InstrStr#"rrk") - Cast.RC:$src0, Cast.KRCWM:$mask, - (To.VT (EXTRACT_SUBREG From.RC:$src, To.SubRegIdx))))>; - - def : Pat<(Cast.VT (vselect Cast.KRCWM:$mask, - (bitconvert - (To.VT (extract_subvector - (From.VT From.RC:$src), (iPTR 0)))), - Cast.ImmAllZerosV)), - (Cast.VT (!cast(InstrStr#"rrkz") - Cast.KRCWM:$mask, - (To.VT (EXTRACT_SUBREG From.RC:$src, To.SubRegIdx))))>; -} - - -let Predicates = [HasVLX] in { -// A masked extract from the first 128-bits of a 256-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z128", v4i64x_info, v2i64x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v8i32x_info, v4i32x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v16i16x_info, v8i16x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v32i8x_info, v16i8x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v4i64x_info, v2i64x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v8i32x_info, v4i32x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v16i16x_info, v8i16x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v32i8x_info, v16i8x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v4f64x_info, v2f64x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v8f32x_info, v4f32x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v4f64x_info, v2f64x_info, v4f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v8f32x_info, v4f32x_info, v4f32x_info>; - -// A masked extract from the first 128-bits of a 512-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z128", v8i64_info, v2i64x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v16i32_info, v4i32x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v32i16_info, v8i16x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z128", v64i8_info, v16i8x_info, v2i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v8i64_info, v2i64x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v16i32_info, v4i32x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v32i16_info, v8i16x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z128", v64i8_info, v16i8x_info, v4i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v8f64_info, v2f64x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ128", v16f32_info, v4f32x_info, v2f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v8f64_info, v2f64x_info, v4f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ128", v16f32_info, v4f32x_info, v4f32x_info>; - -// A masked extract from the first 256-bits of a 512-bit vector can be -// implemented with masked move. -defm : masked_move_for_extract<"VMOVDQA64Z256", v8i64_info, v4i64x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v16i32_info, v8i32x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v32i16_info, v16i16x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA64Z256", v64i8_info, v32i8x_info, v4i64x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v8i64_info, v4i64x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v16i32_info, v8i32x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v32i16_info, v16i16x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVDQA32Z256", v64i8_info, v32i8x_info, v8i32x_info>; -defm : masked_move_for_extract<"VMOVAPDZ256", v8f64_info, v4f64x_info, v4f64x_info>; -defm : masked_move_for_extract<"VMOVAPDZ256", v16f32_info, v8f32x_info, v4f64x_info>; -defm : masked_move_for_extract<"VMOVAPSZ256", v8f64_info, v4f64x_info, v8f32x_info>; -defm : masked_move_for_extract<"VMOVAPSZ256", v16f32_info, v8f32x_info, v8f32x_info>; -} - -// Move Int Doubleword to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVDI2PDIZrr : AVX512BI<0x6E, MRMSrcReg, (outs VR128X:$dst), (ins GR32:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - EVEX, Sched<[WriteVecMoveFromGpr]>; -def VMOVDI2PDIZrm : AVX512BI<0x6E, MRMSrcMem, (outs VR128X:$dst), (ins i32mem:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecLoad]>; -def VMOV64toPQIZrr : AVX512BI<0x6E, MRMSrcReg, (outs VR128X:$dst), (ins GR64:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def VMOV64toPQIZrm : AVX512BI<0x6E, MRMSrcMem, (outs VR128X:$dst), - (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, - EVEX, VEX_W, EVEX_CD8<64, CD8VT1>, Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in { -def VMOV64toSDZrr : AVX512BI<0x6E, MRMSrcReg, (outs FR64X:$dst), (ins GR64:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set FR64X:$dst, (bitconvert GR64:$src))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -def VMOV64toSDZrm : AVX512XSI<0x7E, MRMSrcMem, (outs FR64X:$dst), (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set FR64X:$dst, (bitconvert (loadi64 addr:$src)))]>, - EVEX, VEX_W, EVEX_CD8<8, CD8VT8>, Sched<[WriteVecLoad]>; -def VMOVSDto64Zrr : AVX512BI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64X:$src))]>, - EVEX, VEX_W, Sched<[WriteVecMoveFromGpr]>; -def VMOVSDto64Zmr : AVX512BI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64X:$src)), addr:$dst)]>, - EVEX, VEX_W, Sched<[WriteVecStore]>, - EVEX_CD8<64, CD8VT1>; -} -} // ExeDomain = SSEPackedInt - -// Move Int Doubleword to Single Scalar -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { -def VMOVDI2SSZrr : AVX512BI<0x6E, MRMSrcReg, (outs FR32X:$dst), (ins GR32:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set FR32X:$dst, (bitconvert GR32:$src))]>, - EVEX, Sched<[WriteVecMoveFromGpr]>; - -def VMOVDI2SSZrm : AVX512BI<0x6E, MRMSrcMem, (outs FR32X:$dst), (ins i32mem:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set FR32X:$dst, (bitconvert (loadi32 addr:$src)))]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -// Move doubleword from xmm register to r/m32 -// -let ExeDomain = SSEPackedInt in { -def VMOVPDI2DIZrr : AVX512BI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128X:$src), - (iPTR 0)))]>, - EVEX, Sched<[WriteVecMoveToGpr]>; -def VMOVPDI2DIZmr : AVX512BI<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, VR128X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128X:$src), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -// Move quadword from xmm1 register to r/m64 -// -let ExeDomain = SSEPackedInt in { -def VMOVPQIto64Zrr : I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128X:$src), - (iPTR 0)))]>, - PD, EVEX, VEX_W, Sched<[WriteVecMoveToGpr]>, - Requires<[HasAVX512]>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def VMOVPQIto64Zmr : I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, PD, - EVEX, VEX_W, Sched<[WriteVecStore]>, - Requires<[HasAVX512, In64BitMode]>; - -def VMOVPQI2QIZmr : I<0xD6, MRMDestMem, (outs), - (ins i64mem:$dst, VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(store (extractelt (v2i64 VR128X:$src), (iPTR 0)), - addr:$dst)]>, - EVEX, PD, VEX_W, EVEX_CD8<64, CD8VT1>, - Sched<[WriteVecStore]>, Requires<[HasAVX512]>; - -let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in -def VMOVPQI2QIZrr : AVX512BI<0xD6, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", []>, - EVEX, VEX_W, Sched<[SchedWriteVecLogic.XMM]>; -} // ExeDomain = SSEPackedInt - -def : InstAlias<"vmovq.s\t{$src, $dst|$dst, $src}", - (VMOVPQI2QIZrr VR128X:$dst, VR128X:$src), 0>; - -// Move Scalar Single to Double Int -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { -def VMOVSS2DIZrr : AVX512BI<0x7E, MRMDestReg, (outs GR32:$dst), - (ins FR32X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32X:$src))]>, - EVEX, Sched<[WriteVecMoveToGpr]>; -def VMOVSS2DIZmr : AVX512BI<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, FR32X:$src), - "vmovd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32X:$src)), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT1>, Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -// Move Quadword Int to Packed Quadword Int -// -let ExeDomain = SSEPackedInt in { -def VMOVQI2PQIZrm : AVX512XSI<0x7E, MRMSrcMem, (outs VR128X:$dst), - (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, - EVEX, VEX_W, EVEX_CD8<8, CD8VT8>, Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt - -// Allow "vmovd" but print "vmovq". -def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", - (VMOV64toPQIZrr VR128X:$dst, GR64:$src), 0>; -def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", - (VMOVPQIto64Zrr GR64:$dst, VR128X:$src), 0>; - -//===----------------------------------------------------------------------===// -// AVX-512 MOVSS, MOVSD -//===----------------------------------------------------------------------===// - -multiclass avx512_move_scalar { - let Predicates = [HasAVX512, OptForSize] in - def rr : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (OpNode _.RC:$src1, _.RC:$src2)))], - _.ExeDomain>, EVEX_4V, Sched<[SchedWriteFShuffle.XMM]>; - def rrkz : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.KRCWM:$mask, _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst {${mask}} {z}|", - "$dst {${mask}} {z}, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (X86selects _.KRCWM:$mask, - (_.VT (OpNode _.RC:$src1, _.RC:$src2)), - _.ImmAllZerosV)))], - _.ExeDomain>, EVEX_4V, EVEX_KZ, Sched<[SchedWriteFShuffle.XMM]>; - let Constraints = "$src0 = $dst" in - def rrk : AVX512PI<0x10, MRMSrcReg, (outs _.RC:$dst), - (ins _.RC:$src0, _.KRCWM:$mask, _.RC:$src1, _.RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst {${mask}}|", - "$dst {${mask}}, $src1, $src2}"), - [(set _.RC:$dst, (_.VT (X86selects _.KRCWM:$mask, - (_.VT (OpNode _.RC:$src1, _.RC:$src2)), - (_.VT _.RC:$src0))))], - _.ExeDomain>, EVEX_4V, EVEX_K, Sched<[SchedWriteFShuffle.XMM]>; - let canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : AVX512PI<0x10, MRMSrcMem, (outs _.FRC:$dst), (ins _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(set _.FRC:$dst, (_.ScalarLdFrag addr:$src))], - _.ExeDomain>, EVEX, Sched<[WriteFLoad]>; - let mayLoad = 1, hasSideEffects = 0 in { - let Constraints = "$src0 = $dst" in - def rmk : AVX512PI<0x10, MRMSrcMem, (outs _.RC:$dst), - (ins _.RC:$src0, _.KRCWM:$mask, _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst {${mask}}|", - "$dst {${mask}}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_K, Sched<[WriteFLoad]>; - def rmkz : AVX512PI<0x10, MRMSrcMem, (outs _.RC:$dst), - (ins _.KRCWM:$mask, _.ScalarMemOp:$src), - !strconcat(asm, "\t{$src, $dst {${mask}} {z}|", - "$dst {${mask}} {z}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_KZ, Sched<[WriteFLoad]>; - } - def mr: AVX512PI<0x11, MRMDestMem, (outs), (ins _.ScalarMemOp:$dst, _.FRC:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(store _.FRC:$src, addr:$dst)], _.ExeDomain>, - EVEX, Sched<[WriteFStore]>; - let mayStore = 1, hasSideEffects = 0 in - def mrk: AVX512PI<0x11, MRMDestMem, (outs), - (ins _.ScalarMemOp:$dst, VK1WM:$mask, _.FRC:$src), - !strconcat(asm, "\t{$src, $dst {${mask}}|$dst {${mask}}, $src}"), - [], _.ExeDomain>, EVEX, EVEX_K, Sched<[WriteFStore]>, - NotMemoryFoldable; -} - -defm VMOVSSZ : avx512_move_scalar<"vmovss", X86Movss, f32x_info>, - VEX_LIG, XS, EVEX_CD8<32, CD8VT1>; - -defm VMOVSDZ : avx512_move_scalar<"vmovsd", X86Movsd, f64x_info>, - VEX_LIG, XD, VEX_W, EVEX_CD8<64, CD8VT1>; - - -multiclass avx512_move_scalar_lowering { - -def : Pat<(_.VT (OpNode _.RC:$src0, - (_.VT (scalar_to_vector - (_.EltVT (X86selects VK1WM:$mask, - (_.EltVT _.FRC:$src1), - (_.EltVT _.FRC:$src2))))))), - (!cast(InstrStr#rrk) - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, _.RC)), - VK1WM:$mask, - (_.VT _.RC:$src0), - (_.VT (COPY_TO_REGCLASS _.FRC:$src1, _.RC)))>; - -def : Pat<(_.VT (OpNode _.RC:$src0, - (_.VT (scalar_to_vector - (_.EltVT (X86selects VK1WM:$mask, - (_.EltVT _.FRC:$src1), - (_.EltVT ZeroFP))))))), - (!cast(InstrStr#rrkz) - VK1WM:$mask, - (_.VT _.RC:$src0), - (_.VT (COPY_TO_REGCLASS _.FRC:$src1, _.RC)))>; -} - -multiclass avx512_store_scalar_lowering { - -def : Pat<(masked_store addr:$dst, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -} - -multiclass avx512_store_scalar_lowering_subreg { - -def : Pat<(masked_store addr:$dst, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -} - -// This matches the more recent codegen from clang that avoids emitting a 512 -// bit masked store directly. Codegen will widen 128-bit masked store to 512 -// bits on AVX512F only targets. -multiclass avx512_store_scalar_lowering_subreg2 { - -// AVX512F pattern. -def : Pat<(masked_store addr:$dst, Mask512, - (_.info512.VT (insert_subvector undef, - (_.info128.VT _.info128.RC:$src), - (iPTR 0)))), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; - -// AVX512VL pattern. -def : Pat<(masked_store addr:$dst, Mask128, (_.info128.VT _.info128.RC:$src)), - (!cast(InstrStr#mrk) addr:$dst, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - (COPY_TO_REGCLASS _.info128.RC:$src, _.info128.FRC))>; -} - -multiclass avx512_load_scalar_lowering { - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS MaskRC:$mask, VK1WM), - addr:$srcAddr)>; - -} - -multiclass avx512_load_scalar_lowering_subreg { - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -} - -// This matches the more recent codegen from clang that avoids emitting a 512 -// bit masked load directly. Codegen will widen 128-bit masked load to 512 -// bits on AVX512F only targets. -multiclass avx512_load_scalar_lowering_subreg2 { -// AVX512F patterns. -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask512, - (_.info512.VT (bitconvert - (v16i32 immAllZerosV))))), - (iPTR 0))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (extract_subvector - (_.info512.VT (masked_load addr:$srcAddr, Mask512, - (_.info512.VT (insert_subvector undef, - (_.info128.VT (X86vzmovl _.info128.RC:$src)), - (iPTR 0))))), - (iPTR 0))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -// AVX512Vl patterns. -def : Pat<(_.info128.VT (masked_load addr:$srcAddr, Mask128, - (_.info128.VT (bitconvert (v4i32 immAllZerosV))))), - (!cast(InstrStr#rmkz) - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; - -def : Pat<(_.info128.VT (masked_load addr:$srcAddr, Mask128, - (_.info128.VT (X86vzmovl _.info128.RC:$src)))), - (!cast(InstrStr#rmk) _.info128.RC:$src, - (COPY_TO_REGCLASS (i32 (INSERT_SUBREG (IMPLICIT_DEF), MaskRC:$mask, subreg)), VK1WM), - addr:$srcAddr)>; -} - -defm : avx512_move_scalar_lowering<"VMOVSSZ", X86Movss, fp32imm0, v4f32x_info>; -defm : avx512_move_scalar_lowering<"VMOVSDZ", X86Movsd, fp64imm0, v2f64x_info>; - -defm : avx512_store_scalar_lowering<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (trunc (and GR32:$mask, (i32 1)))))), GR32>; -defm : avx512_store_scalar_lowering_subreg<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (and GR16:$mask, (i16 1))))), GR16, sub_16bit>; -defm : avx512_store_scalar_lowering_subreg<"VMOVSDZ", avx512vl_f64_info, - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), GR8, sub_8bit>; - -defm : avx512_store_scalar_lowering_subreg2<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (insert_subvector - (v16i1 immAllZerosV), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), - (iPTR 0))), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), GR8, sub_8bit>; -defm : avx512_store_scalar_lowering_subreg2<"VMOVSDZ", avx512vl_f64_info, - (v8i1 - (extract_subvector - (v16i1 - (insert_subvector - (v16i1 immAllZerosV), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), - (iPTR 0))), - (iPTR 0))), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), GR8, sub_8bit>; - -defm : avx512_load_scalar_lowering<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (trunc (and GR32:$mask, (i32 1)))))), GR32>; -defm : avx512_load_scalar_lowering_subreg<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (bitconvert (i16 (and GR16:$mask, (i16 1))))), GR16, sub_16bit>; -defm : avx512_load_scalar_lowering_subreg<"VMOVSDZ", avx512vl_f64_info, - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), GR8, sub_8bit>; - -defm : avx512_load_scalar_lowering_subreg2<"VMOVSSZ", avx512vl_f32_info, - (v16i1 (insert_subvector - (v16i1 immAllZerosV), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), - (iPTR 0))), - (v4i1 (extract_subvector - (v8i1 (bitconvert (and GR8:$mask, (i8 1)))), - (iPTR 0))), GR8, sub_8bit>; -defm : avx512_load_scalar_lowering_subreg2<"VMOVSDZ", avx512vl_f64_info, - (v8i1 - (extract_subvector - (v16i1 - (insert_subvector - (v16i1 immAllZerosV), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), - (iPTR 0))), - (iPTR 0))), - (v2i1 (extract_subvector - (v8i1 (bitconvert (i8 (and GR8:$mask, (i8 1))))), - (iPTR 0))), GR8, sub_8bit>; - -def : Pat<(f32 (X86selects VK1WM:$mask, (f32 FR32X:$src1), (f32 FR32X:$src2))), - (COPY_TO_REGCLASS (v4f32 (VMOVSSZrrk - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)), - VK1WM:$mask, (v4f32 (IMPLICIT_DEF)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)))), FR32X)>; - -def : Pat<(f32 (X86selects VK1WM:$mask, (f32 FR32X:$src1), fp32imm0)), - (COPY_TO_REGCLASS (v4f32 (VMOVSSZrrkz VK1WM:$mask, (v4f32 (IMPLICIT_DEF)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)))), FR32X)>; - -def : Pat<(f64 (X86selects VK1WM:$mask, (f64 FR64X:$src1), (f64 FR64X:$src2))), - (COPY_TO_REGCLASS (v2f64 (VMOVSDZrrk - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)), - VK1WM:$mask, (v2f64 (IMPLICIT_DEF)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)))), FR64X)>; - -def : Pat<(f64 (X86selects VK1WM:$mask, (f64 FR64X:$src1), fpimm0)), - (COPY_TO_REGCLASS (v2f64 (VMOVSDZrrkz VK1WM:$mask, (v2f64 (IMPLICIT_DEF)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)))), FR64X)>; - -let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def VMOVSSZrr_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrr">, - Sched<[SchedWriteFShuffle.XMM]>; - - let Constraints = "$src0 = $dst" in - def VMOVSSZrrk_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f32x_info.RC:$src0, f32x_info.KRCWM:$mask, - VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - []>, EVEX_K, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrrk">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSSZrrkz_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f32x_info.KRCWM:$mask, VR128X:$src1, VR128X:$src2), - "vmovss\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - []>, EVEX_KZ, XS, EVEX_4V, VEX_LIG, - FoldGenData<"VMOVSSZrrkz">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSDZrr_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XD, EVEX_4V, VEX_LIG, VEX_W, - FoldGenData<"VMOVSDZrr">, - Sched<[SchedWriteFShuffle.XMM]>; - - let Constraints = "$src0 = $dst" in - def VMOVSDZrrk_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f64x_info.RC:$src0, f64x_info.KRCWM:$mask, - VR128X:$src1, VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - []>, EVEX_K, XD, EVEX_4V, VEX_LIG, - VEX_W, FoldGenData<"VMOVSDZrrk">, - Sched<[SchedWriteFShuffle.XMM]>; - - def VMOVSDZrrkz_REV: AVX512<0x11, MRMDestReg, (outs VR128X:$dst), - (ins f64x_info.KRCWM:$mask, VR128X:$src1, - VR128X:$src2), - "vmovsd\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - []>, EVEX_KZ, XD, EVEX_4V, VEX_LIG, - VEX_W, FoldGenData<"VMOVSDZrrkz">, - Sched<[SchedWriteFShuffle.XMM]>; -} - -def : InstAlias<"vmovss.s\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (VMOVSSZrr_REV VR128X:$dst, VR128X:$src1, VR128X:$src2), 0>; -def : InstAlias<"vmovss.s\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - (VMOVSSZrrk_REV VR128X:$dst, VK1WM:$mask, - VR128X:$src1, VR128X:$src2), 0>; -def : InstAlias<"vmovss.s\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - (VMOVSSZrrkz_REV VR128X:$dst, VK1WM:$mask, - VR128X:$src1, VR128X:$src2), 0>; -def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (VMOVSDZrr_REV VR128X:$dst, VR128X:$src1, VR128X:$src2), 0>; -def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst {${mask}}|"# - "$dst {${mask}}, $src1, $src2}", - (VMOVSDZrrk_REV VR128X:$dst, VK1WM:$mask, - VR128X:$src1, VR128X:$src2), 0>; -def : InstAlias<"vmovsd.s\t{$src2, $src1, $dst {${mask}} {z}|"# - "$dst {${mask}} {z}, $src1, $src2}", - (VMOVSDZrrkz_REV VR128X:$dst, VK1WM:$mask, - VR128X:$src1, VR128X:$src2), 0>; - -let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128X:$src))), - (VMOVSSZrr (v4f32 (AVX512_128_SET0)), VR128X:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128X:$src))), - (VMOVSSZrr (v4i32 (AVX512_128_SET0)), VR128X:$src)>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSZrr (v4f32 (AVX512_128_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256X:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSZrr (v4i32 (AVX512_128_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256X:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDZrr (v2f64 (AVX512_128_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256X:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256X:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDZrr (v2i64 (AVX512_128_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256X:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v16f32 (X86vzmovl (v16f32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSZrr (v4f32 (AVX512_128_SET0)), - (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (v16i32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSZrr (v4i32 (AVX512_128_SET0)), - (v4i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v8f64 (X86vzmovl (v8f64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDZrr (v2f64 (AVX512_128_SET0)), - (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v8i64 (X86vzmovl (v8i64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDZrr (v2i64 (AVX512_128_SET0)), - (v2i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_xmm)))), sub_xmm)>; - -} - -// Use 128-bit blends for OptForSpeed since BLENDs have better throughput than -// VMOVSS/SD. Unfortunately, loses the ability to use XMM16-31. -let Predicates = [HasAVX512, OptForSpeed] in { - def : Pat<(v16f32 (X86vzmovl (v16f32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VBLENDPSrri (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v16f32 VR512:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (v16i32 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VPBLENDWrri (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v16i32 VR512:$src), sub_xmm)), - (i8 3))), sub_xmm)>; - - def : Pat<(v8f64 (X86vzmovl (v8f64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VBLENDPDrri (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v8f64 VR512:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v8i64 (X86vzmovl (v8i64 VR512:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VPBLENDWrri (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v8i64 VR512:$src), sub_xmm)), - (i8 0xf))), sub_xmm)>; -} - -let Predicates = [HasAVX512] in { - - // MOVSSrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)>; - - // MOVSDrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSDZrm addr:$src), VR128X)>; - - // Represent the same patterns above but in the form they appear for - // 256-bit types - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v8f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v8f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - - // Represent the same patterns above but in the form they appear for - // 512-bit types - def : Pat<(v16i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v16f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v16f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSZrm addr:$src), sub_xmm)>; - def : Pat<(v8f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - def : Pat<(v8f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDZrm addr:$src), sub_xmm)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector (loadi64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128X:$src), (iPTR 0))), - addr:$dst), - (VMOVSSZmr addr:$dst, (COPY_TO_REGCLASS (v4f32 VR128X:$src), FR32X))>; -} - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVZPQILo2PQIZrr : AVX512XSI<0x7E, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128X:$dst, (v2i64 (X86vzmovl - (v2i64 VR128X:$src))))]>, - EVEX, VEX_W; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (VMOVDI2PDIZrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (VMOV64toPQIZrr GR64:$src)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIZrr GR64:$src)), sub_xmm)>; - - def : Pat<(v8i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIZrr GR64:$src)), sub_xmm)>; - - // AVX 128-bit movd/movq instruction write zeros in the high 128-bit part. - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (VMOVDI2PDIZrm addr:$src)>; - def : Pat<(v8i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (VMOVQI2PQIZrm addr:$src)>; - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128X:$src))), - (VMOVZPQILo2PQIZrr VR128X:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), - (VMOVQI2PQIZrm addr:$src)>; - def : Pat<(v4i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; - - // Use regular 128-bit instructions to match 256-bit scalar_to_vec+zext. - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrr GR32:$src)), sub_xmm)>; - def : Pat<(v16i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrr GR32:$src)), sub_xmm)>; - - // Use regular 128-bit instructions to match 512-bit scalar_to_vec+zext. - def : Pat<(v16i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIZrm addr:$src)), sub_xmm)>; - def : Pat<(v8i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIZrm addr:$src)), sub_xmm)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Non-temporals -//===----------------------------------------------------------------------===// - -def VMOVNTDQAZrm : AVX512PI<0x2A, MRMSrcMem, (outs VR512:$dst), - (ins i512mem:$src), "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.ZMM.RM]>, - EVEX, T8PD, EVEX_V512, EVEX_CD8<64, CD8VF>; - -let Predicates = [HasVLX] in { - def VMOVNTDQAZ256rm : AVX512PI<0x2A, MRMSrcMem, (outs VR256X:$dst), - (ins i256mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.YMM.RM]>, - EVEX, T8PD, EVEX_V256, EVEX_CD8<64, CD8VF>; - - def VMOVNTDQAZ128rm : AVX512PI<0x2A, MRMSrcMem, (outs VR128X:$dst), - (ins i128mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", - [], SSEPackedInt>, Sched<[SchedWriteVecMoveLS.XMM.RM]>, - EVEX, T8PD, EVEX_V128, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_movnt opc, string OpcodeStr, X86VectorVTInfo _, - X86SchedWriteMoveLS Sched, - PatFrag st_frag = alignednontemporalstore> { - let SchedRW = [Sched.MR], AddedComplexity = 400 in - def mr : AVX512PI, EVEX, EVEX_CD8<_.EltSize, CD8VF>; -} - -multiclass avx512_movnt_vl opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteMoveLSWidths Sched> { - let Predicates = [HasAVX512] in - defm Z : avx512_movnt, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_movnt, EVEX_V256; - defm Z128 : avx512_movnt, EVEX_V128; - } -} - -defm VMOVNTDQ : avx512_movnt_vl<0xE7, "vmovntdq", avx512vl_i64_info, - SchedWriteVecMoveLSNT>, PD; -defm VMOVNTPD : avx512_movnt_vl<0x2B, "vmovntpd", avx512vl_f64_info, - SchedWriteFMoveLSNT>, PD, VEX_W; -defm VMOVNTPS : avx512_movnt_vl<0x2B, "vmovntps", avx512vl_f32_info, - SchedWriteFMoveLSNT>, PS; - -let Predicates = [HasAVX512], AddedComplexity = 400 in { - def : Pat<(alignednontemporalstore (v16i32 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - def : Pat<(alignednontemporalstore (v32i16 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - def : Pat<(alignednontemporalstore (v64i8 VR512:$src), addr:$dst), - (VMOVNTDQZmr addr:$dst, VR512:$src)>; - - def : Pat<(v8f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; - def : Pat<(v16f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; - def : Pat<(v8i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZrm addr:$src)>; -} - -let Predicates = [HasVLX], AddedComplexity = 400 in { - def : Pat<(alignednontemporalstore (v8i32 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignednontemporalstore (v16i16 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - def : Pat<(alignednontemporalstore (v32i8 VR256X:$src), addr:$dst), - (VMOVNTDQZ256mr addr:$dst, VR256X:$src)>; - - def : Pat<(v4f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - def : Pat<(v8f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - def : Pat<(v4i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ256rm addr:$src)>; - - def : Pat<(alignednontemporalstore (v4i32 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128X:$src), addr:$dst), - (VMOVNTDQZ128mr addr:$dst, VR128X:$src)>; - - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAZ128rm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Integer arithmetic -// -multiclass avx512_binop_rm opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, AVX512BIBase, EVEX_4V, - Sched<[sched]>; - - defm rm : AVX512_maskable, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_binop_rmb opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable = 0> : - avx512_binop_rm { - defm rmb : AVX512_maskable, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_binop_rm_vl opc, string OpcodeStr, SDNode OpNode, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_binop_rm, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_binop_rm, EVEX_V256; - defm Z128 : avx512_binop_rm, EVEX_V128; - } -} - -multiclass avx512_binop_rmb_vl opc, string OpcodeStr, SDNode OpNode, - AVX512VLVectorVTInfo VTInfo, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - let Predicates = [prd] in - defm Z : avx512_binop_rmb, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_binop_rmb, EVEX_V256; - defm Z128 : avx512_binop_rmb, EVEX_V128; - } -} - -multiclass avx512_binop_rm_vl_q opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rmb_vl, - VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_binop_rm_vl_d opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rmb_vl, EVEX_CD8<32, CD8VF>; -} - -multiclass avx512_binop_rm_vl_w opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl, EVEX_CD8<16, CD8VF>, - VEX_WIG; -} - -multiclass avx512_binop_rm_vl_b opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate prd, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl, EVEX_CD8<8, CD8VF>, - VEX_WIG; -} - -multiclass avx512_binop_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd, bit IsCommutable = 0> { - defm Q : avx512_binop_rm_vl_q; - - defm D : avx512_binop_rm_vl_d; -} - -multiclass avx512_binop_rm_vl_bw opc_b, bits<8> opc_w, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd, bit IsCommutable = 0> { - defm W : avx512_binop_rm_vl_w; - - defm B : avx512_binop_rm_vl_b; -} - -multiclass avx512_binop_rm_vl_all opc_b, bits<8> opc_w, - bits<8> opc_d, bits<8> opc_q, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit IsCommutable = 0> { - defm NAME : avx512_binop_rm_vl_dq, - avx512_binop_rm_vl_bw; -} - -multiclass avx512_binop_rm2 opc, string OpcodeStr, - X86FoldableSchedWrite sched, - SDNode OpNode,X86VectorVTInfo _Src, - X86VectorVTInfo _Dst, X86VectorVTInfo _Brdct, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, - AVX512BIBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; - - defm rmb : AVX512_maskable, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -defm VPADD : avx512_binop_rm_vl_all<0xFC, 0xFD, 0xFE, 0xD4, "vpadd", add, - SchedWriteVecALU, 1>; -defm VPSUB : avx512_binop_rm_vl_all<0xF8, 0xF9, 0xFA, 0xFB, "vpsub", sub, - SchedWriteVecALU, 0>; -defm VPADDS : avx512_binop_rm_vl_bw<0xEC, 0xED, "vpadds", X86adds, - SchedWriteVecALU, HasBWI, 1>; -defm VPSUBS : avx512_binop_rm_vl_bw<0xE8, 0xE9, "vpsubs", X86subs, - SchedWriteVecALU, HasBWI, 0>; -defm VPADDUS : avx512_binop_rm_vl_bw<0xDC, 0xDD, "vpaddus", X86addus, - SchedWriteVecALU, HasBWI, 1>; -defm VPSUBUS : avx512_binop_rm_vl_bw<0xD8, 0xD9, "vpsubus", X86subus, - SchedWriteVecALU, HasBWI, 0>; -defm VPMULLD : avx512_binop_rm_vl_d<0x40, "vpmulld", mul, - SchedWritePMULLD, HasAVX512, 1>, T8PD; -defm VPMULLW : avx512_binop_rm_vl_w<0xD5, "vpmullw", mul, - SchedWriteVecIMul, HasBWI, 1>; -defm VPMULLQ : avx512_binop_rm_vl_q<0x40, "vpmullq", mul, - SchedWriteVecIMul, HasDQI, 1>, T8PD, - NotEVEX2VEXConvertible; -defm VPMULHW : avx512_binop_rm_vl_w<0xE5, "vpmulhw", mulhs, SchedWriteVecIMul, - HasBWI, 1>; -defm VPMULHUW : avx512_binop_rm_vl_w<0xE4, "vpmulhuw", mulhu, SchedWriteVecIMul, - HasBWI, 1>; -defm VPMULHRSW : avx512_binop_rm_vl_w<0x0B, "vpmulhrsw", X86mulhrs, - SchedWriteVecIMul, HasBWI, 1>, T8PD; -defm VPAVG : avx512_binop_rm_vl_bw<0xE0, 0xE3, "vpavg", X86avg, - SchedWriteVecALU, HasBWI, 1>; -defm VPMULDQ : avx512_binop_rm_vl_q<0x28, "vpmuldq", X86pmuldq, - SchedWriteVecIMul, HasAVX512, 1>, T8PD; -defm VPMULUDQ : avx512_binop_rm_vl_q<0xF4, "vpmuludq", X86pmuludq, - SchedWriteVecIMul, HasAVX512, 1>; - -multiclass avx512_binop_all opc, string OpcodeStr, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _SrcVTInfo, - AVX512VLVectorVTInfo _DstVTInfo, - SDNode OpNode, Predicate prd, bit IsCommutable = 0> { - let Predicates = [prd] in - defm NAME#Z : avx512_binop_rm2, - EVEX_V512, EVEX_CD8<64, CD8VF>, VEX_W; - let Predicates = [HasVLX, prd] in { - defm NAME#Z256 : avx512_binop_rm2, - EVEX_V256, EVEX_CD8<64, CD8VF>, VEX_W; - defm NAME#Z128 : avx512_binop_rm2, - EVEX_V128, EVEX_CD8<64, CD8VF>, VEX_W; - } -} - -defm VPMULTISHIFTQB : avx512_binop_all<0x83, "vpmultishiftqb", SchedWriteVecALU, - avx512vl_i8_info, avx512vl_i8_info, - X86multishift, HasVBMI, 0>, T8PD; - -multiclass avx512_packs_rmb opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _Src, X86VectorVTInfo _Dst, - X86FoldableSchedWrite sched> { - defm rmb : AVX512_maskable, - EVEX_4V, EVEX_B, EVEX_CD8<_Src.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_packs_rm opc, string OpcodeStr, - SDNode OpNode,X86VectorVTInfo _Src, - X86VectorVTInfo _Dst, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - defm rr : AVX512_maskable, - EVEX_CD8<_Src.EltSize, CD8VF>, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - EVEX_4V, EVEX_CD8<_Src.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_packs_all_i32_i16 opc, string OpcodeStr, - SDNode OpNode> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, - avx512_packs_rmb, EVEX_V512; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, - avx512_packs_rmb, - EVEX_V256; - defm NAME#Z128 : avx512_packs_rm, - avx512_packs_rmb, - EVEX_V128; - } -} -multiclass avx512_packs_all_i16_i8 opc, string OpcodeStr, - SDNode OpNode> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, EVEX_V512, VEX_WIG; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, - EVEX_V256, VEX_WIG; - defm NAME#Z128 : avx512_packs_rm, - EVEX_V128, VEX_WIG; - } -} - -multiclass avx512_vpmadd opc, string OpcodeStr, - SDNode OpNode, AVX512VLVectorVTInfo _Src, - AVX512VLVectorVTInfo _Dst, bit IsCommutable = 0> { - let Predicates = [HasBWI] in - defm NAME#Z : avx512_packs_rm, EVEX_V512; - let Predicates = [HasBWI, HasVLX] in { - defm NAME#Z256 : avx512_packs_rm, EVEX_V256; - defm NAME#Z128 : avx512_packs_rm, EVEX_V128; - } -} - -defm VPACKSSDW : avx512_packs_all_i32_i16<0x6B, "vpackssdw", X86Packss>, AVX512BIBase; -defm VPACKUSDW : avx512_packs_all_i32_i16<0x2b, "vpackusdw", X86Packus>, AVX5128IBase; -defm VPACKSSWB : avx512_packs_all_i16_i8 <0x63, "vpacksswb", X86Packss>, AVX512BIBase; -defm VPACKUSWB : avx512_packs_all_i16_i8 <0x67, "vpackuswb", X86Packus>, AVX512BIBase; - -defm VPMADDUBSW : avx512_vpmadd<0x04, "vpmaddubsw", X86vpmaddubsw, - avx512vl_i8_info, avx512vl_i16_info>, AVX512BIBase, T8PD, VEX_WIG; -defm VPMADDWD : avx512_vpmadd<0xF5, "vpmaddwd", X86vpmaddwd, - avx512vl_i16_info, avx512vl_i32_info, 1>, AVX512BIBase, VEX_WIG; - -defm VPMAXSB : avx512_binop_rm_vl_b<0x3C, "vpmaxsb", smax, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMAXSW : avx512_binop_rm_vl_w<0xEE, "vpmaxsw", smax, - SchedWriteVecALU, HasBWI, 1>; -defm VPMAXSD : avx512_binop_rm_vl_d<0x3D, "vpmaxsd", smax, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMAXSQ : avx512_binop_rm_vl_q<0x3D, "vpmaxsq", smax, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMAXUB : avx512_binop_rm_vl_b<0xDE, "vpmaxub", umax, - SchedWriteVecALU, HasBWI, 1>; -defm VPMAXUW : avx512_binop_rm_vl_w<0x3E, "vpmaxuw", umax, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMAXUD : avx512_binop_rm_vl_d<0x3F, "vpmaxud", umax, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMAXUQ : avx512_binop_rm_vl_q<0x3F, "vpmaxuq", umax, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMINSB : avx512_binop_rm_vl_b<0x38, "vpminsb", smin, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMINSW : avx512_binop_rm_vl_w<0xEA, "vpminsw", smin, - SchedWriteVecALU, HasBWI, 1>; -defm VPMINSD : avx512_binop_rm_vl_d<0x39, "vpminsd", smin, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMINSQ : avx512_binop_rm_vl_q<0x39, "vpminsq", smin, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -defm VPMINUB : avx512_binop_rm_vl_b<0xDA, "vpminub", umin, - SchedWriteVecALU, HasBWI, 1>; -defm VPMINUW : avx512_binop_rm_vl_w<0x3A, "vpminuw", umin, - SchedWriteVecALU, HasBWI, 1>, T8PD; -defm VPMINUD : avx512_binop_rm_vl_d<0x3B, "vpminud", umin, - SchedWriteVecALU, HasAVX512, 1>, T8PD; -defm VPMINUQ : avx512_binop_rm_vl_q<0x3B, "vpminuq", umin, - SchedWriteVecALU, HasAVX512, 1>, T8PD, - NotEVEX2VEXConvertible; - -// PMULLQ: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasDQI, NoVLX] in { - def : Pat<(v4i64 (mul (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (mul (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -// PMULLQ: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasDQI, NoVLX] in { - def : Pat<(v4i64 (mul (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (mul (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG - (VPMULLQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -multiclass avx512_min_max_lowering { - def : Pat<(v4i64 (OpNode VR256X:$src1, VR256X:$src2)), - (EXTRACT_SUBREG - (Instr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(v2i64 (OpNode VR128X:$src1, VR128X:$src2)), - (EXTRACT_SUBREG - (Instr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; -} - -let Predicates = [HasAVX512, NoVLX] in { - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; - defm : avx512_min_max_lowering; -} - -//===----------------------------------------------------------------------===// -// AVX-512 Logical Instructions -//===----------------------------------------------------------------------===// - -// OpNodeMsk is the OpNode to use when element size is important. OpNode will -// be set to null_frag for 32-bit elements. -multiclass avx512_logic_rm opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86FoldableSchedWrite sched, - X86VectorVTInfo _, bit IsCommutable = 0> { - let hasSideEffects = 0 in - defm rr : AVX512_maskable_logic, AVX512BIBase, EVEX_4V, - Sched<[sched]>; - - let hasSideEffects = 0, mayLoad = 1 in - defm rm : AVX512_maskable_logic, - AVX512BIBase, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} - -// OpNodeMsk is the OpNode to use where element size is important. So use -// for all of the broadcast patterns. -multiclass avx512_logic_rmb opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86FoldableSchedWrite sched, X86VectorVTInfo _, - bit IsCommutable = 0> : - avx512_logic_rm { - defm rmb : AVX512_maskable_logic, - AVX512BIBase, EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_logic_rmb_vl opc, string OpcodeStr, - SDPatternOperator OpNode, - SDNode OpNodeMsk, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, - bit IsCommutable = 0> { - let Predicates = [HasAVX512] in - defm Z : avx512_logic_rmb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_logic_rmb, EVEX_V256; - defm Z128 : avx512_logic_rmb, EVEX_V128; - } -} - -multiclass avx512_logic_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - bit IsCommutable = 0> { - defm Q : avx512_logic_rmb_vl, - VEX_W, EVEX_CD8<64, CD8VF>; - defm D : avx512_logic_rmb_vl, - EVEX_CD8<32, CD8VF>; -} - -defm VPAND : avx512_logic_rm_vl_dq<0xDB, 0xDB, "vpand", and, - SchedWriteVecLogic, 1>; -defm VPOR : avx512_logic_rm_vl_dq<0xEB, 0xEB, "vpor", or, - SchedWriteVecLogic, 1>; -defm VPXOR : avx512_logic_rm_vl_dq<0xEF, 0xEF, "vpxor", xor, - SchedWriteVecLogic, 1>; -defm VPANDN : avx512_logic_rm_vl_dq<0xDF, 0xDF, "vpandn", X86andnp, - SchedWriteVecLogic>; - -//===----------------------------------------------------------------------===// -// AVX-512 FP arithmetic -//===----------------------------------------------------------------------===// - -multiclass avx512_fp_scalar opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, SDNode VecNode, - X86FoldableSchedWrite sched, bit IsCommutable> { - let ExeDomain = _.ExeDomain in { - defm rr_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rm_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - let isCodeGenOnly = 1, Predicates = [HasAVX512] in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = IsCommutable; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } - } -} - -multiclass avx512_fp_scalar_round opc, string OpcodeStr,X86VectorVTInfo _, - SDNode VecNode, X86FoldableSchedWrite sched, - bit IsCommutable = 0> { - let ExeDomain = _.ExeDomain in - defm rrb_Int : AVX512_maskable_scalar, - EVEX_B, EVEX_RC, Sched<[sched]>; -} -multiclass avx512_fp_scalar_sae opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, SDNode VecNode, SDNode SaeNode, - X86FoldableSchedWrite sched, bit IsCommutable> { - let ExeDomain = _.ExeDomain in { - defm rr_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rm_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, Predicates = [HasAVX512] in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = IsCommutable; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } - - defm rrb_Int : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - } -} - -multiclass avx512_binop_s_round opc, string OpcodeStr, SDNode OpNode, - SDNode VecNode, X86SchedWriteSizes sched, - bit IsCommutable> { - defm SSZ : avx512_fp_scalar, - avx512_fp_scalar_round, - XS, EVEX_4V, VEX_LIG, EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalar, - avx512_fp_scalar_round, - XD, VEX_W, EVEX_4V, VEX_LIG, EVEX_CD8<64, CD8VT1>; -} - -multiclass avx512_binop_s_sae opc, string OpcodeStr, SDNode OpNode, - SDNode VecNode, SDNode SaeNode, - X86SchedWriteSizes sched, bit IsCommutable> { - defm SSZ : avx512_fp_scalar_sae, - XS, EVEX_4V, VEX_LIG, EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalar_sae, - XD, VEX_W, EVEX_4V, VEX_LIG, EVEX_CD8<64, CD8VT1>; -} -defm VADD : avx512_binop_s_round<0x58, "vadd", fadd, X86faddRnds, - SchedWriteFAddSizes, 1>; -defm VMUL : avx512_binop_s_round<0x59, "vmul", fmul, X86fmulRnds, - SchedWriteFMulSizes, 1>; -defm VSUB : avx512_binop_s_round<0x5C, "vsub", fsub, X86fsubRnds, - SchedWriteFAddSizes, 0>; -defm VDIV : avx512_binop_s_round<0x5E, "vdiv", fdiv, X86fdivRnds, - SchedWriteFDivSizes, 0>; -defm VMIN : avx512_binop_s_sae<0x5D, "vmin", X86fmin, X86fmins, X86fminRnds, - SchedWriteFCmpSizes, 0>; -defm VMAX : avx512_binop_s_sae<0x5F, "vmax", X86fmax, X86fmaxs, X86fmaxRnds, - SchedWriteFCmpSizes, 0>; - -// MIN/MAX nodes are commutable under "unsafe-fp-math". In this case we use -// X86fminc and X86fmaxc instead of X86fmin and X86fmax -multiclass avx512_comutable_binop_s opc, string OpcodeStr, - X86VectorVTInfo _, SDNode OpNode, - X86FoldableSchedWrite sched> { - let isCodeGenOnly = 1, Predicates = [HasAVX512], ExeDomain = _.ExeDomain in { - def rr : I< opc, MRMSrcReg, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.FRC:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, _.FRC:$src2))]>, - Sched<[sched]> { - let isCommutable = 1; - } - def rm : I< opc, MRMSrcMem, (outs _.FRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set _.FRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2)))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} -defm VMINCSSZ : avx512_comutable_binop_s<0x5D, "vminss", f32x_info, X86fminc, - SchedWriteFCmp.Scl>, XS, EVEX_4V, - VEX_LIG, EVEX_CD8<32, CD8VT1>; - -defm VMINCSDZ : avx512_comutable_binop_s<0x5D, "vminsd", f64x_info, X86fminc, - SchedWriteFCmp.Scl>, XD, VEX_W, EVEX_4V, - VEX_LIG, EVEX_CD8<64, CD8VT1>; - -defm VMAXCSSZ : avx512_comutable_binop_s<0x5F, "vmaxss", f32x_info, X86fmaxc, - SchedWriteFCmp.Scl>, XS, EVEX_4V, - VEX_LIG, EVEX_CD8<32, CD8VT1>; - -defm VMAXCSDZ : avx512_comutable_binop_s<0x5F, "vmaxsd", f64x_info, X86fmaxc, - SchedWriteFCmp.Scl>, XD, VEX_W, EVEX_4V, - VEX_LIG, EVEX_CD8<64, CD8VT1>; - -multiclass avx512_fp_packed opc, string OpcodeStr, SDPatternOperator OpNode, - X86VectorVTInfo _, X86FoldableSchedWrite sched, - bit IsCommutable, - bit IsKZCommutable = IsCommutable> { - let ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm rr: AVX512_maskable, - EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in { - defm rm: AVX512_maskable, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - EVEX_4V, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } - } -} - -multiclass avx512_fp_round_packed opc, string OpcodeStr, - SDPatternOperator OpNodeRnd, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrb: AVX512_maskable, - EVEX_4V, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fp_sae_packed opc, string OpcodeStr, - SDPatternOperator OpNodeRnd, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrb: AVX512_maskable, - EVEX_4V, EVEX_B, Sched<[sched]>; -} - -multiclass avx512_fp_binop_p opc, string OpcodeStr, SDPatternOperator OpNode, - Predicate prd, X86SchedWriteSizes sched, - bit IsCommutable = 0, - bit IsPD128Commutable = IsCommutable> { - let Predicates = [prd] in { - defm PSZ : avx512_fp_packed, EVEX_V512, PS, - EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_packed, EVEX_V512, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - } - - // Define only if AVX512VL feature is present. - let Predicates = [prd, HasVLX] in { - defm PSZ128 : avx512_fp_packed, EVEX_V128, PS, - EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp_packed, EVEX_V256, PS, - EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp_packed, EVEX_V128, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp_packed, EVEX_V256, PD, VEX_W, - EVEX_CD8<64, CD8VF>; - } -} - -multiclass avx512_fp_binop_p_round opc, string OpcodeStr, SDNode OpNodeRnd, - X86SchedWriteSizes sched> { - defm PSZ : avx512_fp_round_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_round_packed, - EVEX_V512, PD, VEX_W,EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_fp_binop_p_sae opc, string OpcodeStr, SDNode OpNodeRnd, - X86SchedWriteSizes sched> { - defm PSZ : avx512_fp_sae_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_sae_packed, - EVEX_V512, PD, VEX_W,EVEX_CD8<64, CD8VF>; -} - -defm VADD : avx512_fp_binop_p<0x58, "vadd", fadd, HasAVX512, - SchedWriteFAddSizes, 1>, - avx512_fp_binop_p_round<0x58, "vadd", X86faddRnd, SchedWriteFAddSizes>; -defm VMUL : avx512_fp_binop_p<0x59, "vmul", fmul, HasAVX512, - SchedWriteFMulSizes, 1>, - avx512_fp_binop_p_round<0x59, "vmul", X86fmulRnd, SchedWriteFMulSizes>; -defm VSUB : avx512_fp_binop_p<0x5C, "vsub", fsub, HasAVX512, - SchedWriteFAddSizes>, - avx512_fp_binop_p_round<0x5C, "vsub", X86fsubRnd, SchedWriteFAddSizes>; -defm VDIV : avx512_fp_binop_p<0x5E, "vdiv", fdiv, HasAVX512, - SchedWriteFDivSizes>, - avx512_fp_binop_p_round<0x5E, "vdiv", X86fdivRnd, SchedWriteFDivSizes>; -defm VMIN : avx512_fp_binop_p<0x5D, "vmin", X86fmin, HasAVX512, - SchedWriteFCmpSizes, 0>, - avx512_fp_binop_p_sae<0x5D, "vmin", X86fminRnd, SchedWriteFCmpSizes>; -defm VMAX : avx512_fp_binop_p<0x5F, "vmax", X86fmax, HasAVX512, - SchedWriteFCmpSizes, 0>, - avx512_fp_binop_p_sae<0x5F, "vmax", X86fmaxRnd, SchedWriteFCmpSizes>; -let isCodeGenOnly = 1 in { - defm VMINC : avx512_fp_binop_p<0x5D, "vmin", X86fminc, HasAVX512, - SchedWriteFCmpSizes, 1>; - defm VMAXC : avx512_fp_binop_p<0x5F, "vmax", X86fmaxc, HasAVX512, - SchedWriteFCmpSizes, 1>; -} -defm VAND : avx512_fp_binop_p<0x54, "vand", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; -defm VANDN : avx512_fp_binop_p<0x55, "vandn", null_frag, HasDQI, - SchedWriteFLogicSizes, 0>; -defm VOR : avx512_fp_binop_p<0x56, "vor", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; -defm VXOR : avx512_fp_binop_p<0x57, "vxor", null_frag, HasDQI, - SchedWriteFLogicSizes, 1>; - -// Patterns catch floating point selects with bitcasted integer logic ops. -multiclass avx512_fp_logical_lowering { -let Predicates = [prd] in { - // Masked register-register logical operations. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, _.RC:$src2))), - _.RC:$src0)), - (!cast(InstrStr#rrk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#rrkz) _.KRCWM:$mask, _.RC:$src1, - _.RC:$src2)>; - // Masked register-memory logical operations. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, - (load addr:$src2)))), - _.RC:$src0)), - (!cast(InstrStr#rmk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert (_.i64VT (OpNode _.RC:$src1, (load addr:$src2)))), - _.ImmAllZerosV)), - (!cast(InstrStr#rmkz) _.KRCWM:$mask, _.RC:$src1, - addr:$src2)>; - // Register-broadcast logical operations. - def : Pat<(_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT (X86VBroadcast - (_.ScalarLdFrag addr:$src2)))))), - (!cast(InstrStr#rmb) _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert - (_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT - (X86VBroadcast - (_.ScalarLdFrag addr:$src2))))))), - _.RC:$src0)), - (!cast(InstrStr#rmbk) _.RC:$src0, _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (bitconvert - (_.i64VT (OpNode _.RC:$src1, - (bitconvert (_.VT - (X86VBroadcast - (_.ScalarLdFrag addr:$src2))))))), - _.ImmAllZerosV)), - (!cast(InstrStr#rmbkz) _.KRCWM:$mask, - _.RC:$src1, addr:$src2)>; -} -} - -multiclass avx512_fp_logical_lowering_sizes { - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; - defm : avx512_fp_logical_lowering; -} - -defm : avx512_fp_logical_lowering_sizes<"VPAND", and>; -defm : avx512_fp_logical_lowering_sizes<"VPOR", or>; -defm : avx512_fp_logical_lowering_sizes<"VPXOR", xor>; -defm : avx512_fp_logical_lowering_sizes<"VPANDN", X86andnp>; - -let Predicates = [HasVLX,HasDQI] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86for FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VORPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86fxor FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VXORPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - def : Pat<(f64 (X86fandn FR64X:$src1, FR64X:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDNPDZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src1, VR128X)), - (v2f64 (COPY_TO_REGCLASS FR64X:$src2, VR128X)))), - FR64X)>; - - def : Pat<(f32 (X86fand FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86for FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VORPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86fxor FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VXORPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; - def : Pat<(f32 (X86fandn FR32X:$src1, FR32X:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDNPSZ128rr (v4f32 (COPY_TO_REGCLASS FR32X:$src1, VR128X)), - (v4f32 (COPY_TO_REGCLASS FR32X:$src2, VR128X)))), - FR32X)>; -} - -multiclass avx512_fp_scalef_p opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable, - EVEX_4V, Sched<[sched]>; - defm rm: AVX512_maskable, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - EVEX_4V, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp_scalef_scalar opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr: AVX512_maskable_scalar, - Sched<[sched]>; - defm rm: AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp_scalef_all opc, bits<8> opcScaler, string OpcodeStr, - SDNode OpNode, SDNode OpNodeScal, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp_scalef_p, - avx512_fp_round_packed, - EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp_scalef_p, - avx512_fp_round_packed, - EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; - defm SSZ : avx512_fp_scalef_scalar, - avx512_fp_scalar_round, - EVEX_4V,EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp_scalef_scalar, - avx512_fp_scalar_round, - EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; - - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp_scalef_p, - EVEX_V128, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp_scalef_p, - EVEX_V256, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp_scalef_p, - EVEX_V128, VEX_W, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp_scalef_p, - EVEX_V256, VEX_W, EVEX_CD8<64, CD8VF>; - } -} -defm VSCALEF : avx512_fp_scalef_all<0x2C, 0x2D, "vscalef", X86scalef, X86scalefs, - SchedWriteFAdd>, T8PD, NotEVEX2VEXConvertible; - -//===----------------------------------------------------------------------===// -// AVX-512 VPTESTM instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_vptest opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string Name> { - let ExeDomain = _.ExeDomain in { - let isCommutable = 1 in - defm rr : AVX512_maskable_cmp, - EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable_cmp, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } - - // Patterns for compare with 0 that just use the same source twice. - def : Pat<(_.KVT (OpNode _.RC:$src, _.ImmAllZerosV)), - (_.KVT (!cast(Name # _.ZSuffix # "rr") - _.RC:$src, _.RC:$src))>; - - def : Pat<(_.KVT (and _.KRC:$mask, (OpNode _.RC:$src, _.ImmAllZerosV))), - (_.KVT (!cast(Name # _.ZSuffix # "rrk") - _.KRC:$mask, _.RC:$src, _.RC:$src))>; -} - -multiclass avx512_vptest_mb opc, string OpcodeStr, PatFrag OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rmb : AVX512_maskable_cmp, - EVEX_B, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass avx512_vptest_lowering { - def : Pat<(_.KVT (OpNode (bitconvert (_.i64VT (and _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV)), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name # "Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src1, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src2, _.SubRegIdx)), - _.KRC))>; - - def : Pat<(_.KVT (and _.KRC:$mask, - (OpNode (bitconvert (_.i64VT (and _.RC:$src1, _.RC:$src2))), - _.ImmAllZerosV))), - (COPY_TO_REGCLASS - (!cast(Name # "Zrrk") - (COPY_TO_REGCLASS _.KRC:$mask, ExtendInfo.KRC), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src1, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src2, _.SubRegIdx)), - _.KRC)>; - - def : Pat<(_.KVT (OpNode _.RC:$src, _.ImmAllZerosV)), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name # "Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC))>; - - def : Pat<(_.KVT (and _.KRC:$mask, (OpNode _.RC:$src, _.ImmAllZerosV))), - (COPY_TO_REGCLASS - (!cast(Name # "Zrrk") - (COPY_TO_REGCLASS _.KRC:$mask, ExtendInfo.KRC), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx), - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC)>; -} - -multiclass avx512_vptest_dq_sizes opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_vptest, - avx512_vptest_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_vptest, - avx512_vptest_mb, EVEX_V256; - defm Z128 : avx512_vptest, - avx512_vptest_mb, EVEX_V128; - } - let Predicates = [HasAVX512, NoVLX] in { - defm Z256_Alt : avx512_vptest_lowering< OpNode, _.info512, _.info256, NAME>; - defm Z128_Alt : avx512_vptest_lowering< OpNode, _.info512, _.info128, NAME>; - } -} - -multiclass avx512_vptest_dq opc, string OpcodeStr, PatFrag OpNode, - X86SchedWriteWidths sched> { - defm D : avx512_vptest_dq_sizes; - defm Q : avx512_vptest_dq_sizes, VEX_W; -} - -multiclass avx512_vptest_wb opc, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in { - defm WZ: avx512_vptest, EVEX_V512, VEX_W; - defm BZ: avx512_vptest, EVEX_V512; - } - let Predicates = [HasVLX, HasBWI] in { - - defm WZ256: avx512_vptest, EVEX_V256, VEX_W; - defm WZ128: avx512_vptest, EVEX_V128, VEX_W; - defm BZ256: avx512_vptest, EVEX_V256; - defm BZ128: avx512_vptest, EVEX_V128; - } - - let Predicates = [HasAVX512, NoVLX] in { - defm BZ256_Alt : avx512_vptest_lowering; - defm BZ128_Alt : avx512_vptest_lowering; - defm WZ256_Alt : avx512_vptest_lowering; - defm WZ128_Alt : avx512_vptest_lowering; - } -} - -// These patterns are used to match vptestm/vptestnm. We don't treat pcmpeqm -// as commutable here because we already canonicalized all zeros vectors to the -// RHS during lowering. -def X86pcmpeqm : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETEQ)>; -def X86pcmpnem : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETNE)>; - -multiclass avx512_vptest_all_forms opc_wb, bits<8> opc_dq, string OpcodeStr, - PatFrag OpNode, X86SchedWriteWidths sched> : - avx512_vptest_wb, - avx512_vptest_dq; - -defm VPTESTM : avx512_vptest_all_forms<0x26, 0x27, "vptestm", X86pcmpnem, - SchedWriteVecLogic>, T8PD; -defm VPTESTNM : avx512_vptest_all_forms<0x26, 0x27, "vptestnm", X86pcmpeqm, - SchedWriteVecLogic>, T8XS; - -//===----------------------------------------------------------------------===// -// AVX-512 Shift instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_shift_rmi opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm ri : AVX512_maskable, - Sched<[sched]>; - defm mi : AVX512_maskable, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_shift_rmbi opc, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm mbi : AVX512_maskable, - EVEX_B, Sched<[sched.Folded]>; -} - -multiclass avx512_shift_rrm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, ValueType SrcVT, - PatFrag bc_frag, X86VectorVTInfo _> { - // src2 is always 128-bit - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, - AVX512BIBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX512BIBase, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_shift_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, ValueType SrcVT, - PatFrag bc_frag, AVX512VLVectorVTInfo VTInfo, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_shift_rrm, EVEX_V512, - EVEX_CD8 ; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_shift_rrm, EVEX_V256, - EVEX_CD8; - defm Z128 : avx512_shift_rrm, EVEX_V128, - EVEX_CD8; - } -} - -multiclass avx512_shift_types opcd, bits<8> opcq, bits<8> opcw, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit NotEVEX2VEXConvertibleQ = 0> { - defm D : avx512_shift_sizes; - let notEVEX2VEXConvertible = NotEVEX2VEXConvertibleQ in - defm Q : avx512_shift_sizes, VEX_W; - defm W : avx512_shift_sizes; -} - -multiclass avx512_shift_rmi_sizes opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasAVX512] in - defm Z: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z256: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V256; - defm Z128: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V128; - } -} - -multiclass avx512_shift_rmi_w opcw, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm WZ: avx512_shift_rmi, EVEX_V512, VEX_WIG; - let Predicates = [HasVLX, HasBWI] in { - defm WZ256: avx512_shift_rmi, EVEX_V256, VEX_WIG; - defm WZ128: avx512_shift_rmi, EVEX_V128, VEX_WIG; - } -} - -multiclass avx512_shift_rmi_dq opcd, bits<8> opcq, - Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - bit NotEVEX2VEXConvertibleQ = 0> { - defm D: avx512_shift_rmi_sizes, EVEX_CD8<32, CD8VF>; - let notEVEX2VEXConvertible = NotEVEX2VEXConvertibleQ in - defm Q: avx512_shift_rmi_sizes, EVEX_CD8<64, CD8VF>, VEX_W; -} - -defm VPSRL : avx512_shift_rmi_dq<0x72, 0x73, MRM2r, MRM2m, "vpsrl", X86vsrli, - SchedWriteVecShiftImm>, - avx512_shift_rmi_w<0x71, MRM2r, MRM2m, "vpsrlw", X86vsrli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSLL : avx512_shift_rmi_dq<0x72, 0x73, MRM6r, MRM6m, "vpsll", X86vshli, - SchedWriteVecShiftImm>, - avx512_shift_rmi_w<0x71, MRM6r, MRM6m, "vpsllw", X86vshli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSRA : avx512_shift_rmi_dq<0x72, 0x72, MRM4r, MRM4m, "vpsra", X86vsrai, - SchedWriteVecShiftImm, 1>, - avx512_shift_rmi_w<0x71, MRM4r, MRM4m, "vpsraw", X86vsrai, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPROR : avx512_shift_rmi_dq<0x72, 0x72, MRM0r, MRM0m, "vpror", X86vrotri, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; -defm VPROL : avx512_shift_rmi_dq<0x72, 0x72, MRM1r, MRM1m, "vprol", X86vrotli, - SchedWriteVecShiftImm>, AVX512BIi8Base, EVEX_4V; - -defm VPSLL : avx512_shift_types<0xF2, 0xF3, 0xF1, "vpsll", X86vshl, - SchedWriteVecShift>; -defm VPSRA : avx512_shift_types<0xE2, 0xE2, 0xE1, "vpsra", X86vsra, - SchedWriteVecShift, 1>; -defm VPSRL : avx512_shift_types<0xD2, 0xD3, 0xD1, "vpsrl", X86vsrl, - SchedWriteVecShift>; - -// Use 512bit VPSRA/VPSRAI version to implement v2i64/v4i64 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v4i64 (X86vsra (v4i64 VR256X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - VR128X:$src2)), sub_ymm)>; - - def : Pat<(v2i64 (X86vsra (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - VR128X:$src2)), sub_xmm)>; - - def : Pat<(v4i64 (X86vsrai (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v2i64 (X86vsrai (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPSRAQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; -} - -//===-------------------------------------------------------------------===// -// Variable Bit Shifts -//===-------------------------------------------------------------------===// - -multiclass avx512_var_shift opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, - AVX5128IBase, EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable, - AVX5128IBase, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_var_shift_mb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rmb : AVX512_maskable, - AVX5128IBase, EVEX_B, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_var_shift_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_var_shift, - avx512_var_shift_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V256; - defm Z128 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V128; - } -} - -multiclass avx512_var_shift_types opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - defm D : avx512_var_shift_sizes; - defm Q : avx512_var_shift_sizes, VEX_W; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass avx512_var_shift_lowering p> { - let Predicates = p in { - def : Pat<(_.info256.VT (OpNode (_.info256.VT _.info256.RC:$src1), - (_.info256.VT _.info256.RC:$src2))), - (EXTRACT_SUBREG - (!cast(OpcodeStr#"Zrr") - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR256X:$src1, sub_ymm), - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR256X:$src2, sub_ymm)), - sub_ymm)>; - - def : Pat<(_.info128.VT (OpNode (_.info128.VT _.info128.RC:$src1), - (_.info128.VT _.info128.RC:$src2))), - (EXTRACT_SUBREG - (!cast(OpcodeStr#"Zrr") - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR128X:$src1, sub_xmm), - (INSERT_SUBREG (_.info512.VT (IMPLICIT_DEF)), VR128X:$src2, sub_xmm)), - sub_xmm)>; - } -} -multiclass avx512_var_shift_w opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm WZ: avx512_var_shift, - EVEX_V512, VEX_W; - let Predicates = [HasVLX, HasBWI] in { - - defm WZ256: avx512_var_shift, - EVEX_V256, VEX_W; - defm WZ128: avx512_var_shift, - EVEX_V128, VEX_W; - } -} - -defm VPSLLV : avx512_var_shift_types<0x47, "vpsllv", shl, SchedWriteVarVecShift>, - avx512_var_shift_w<0x12, "vpsllvw", shl, SchedWriteVarVecShift>; - -defm VPSRAV : avx512_var_shift_types<0x46, "vpsrav", sra, SchedWriteVarVecShift>, - avx512_var_shift_w<0x11, "vpsravw", sra, SchedWriteVarVecShift>; - -defm VPSRLV : avx512_var_shift_types<0x45, "vpsrlv", srl, SchedWriteVarVecShift>, - avx512_var_shift_w<0x10, "vpsrlvw", srl, SchedWriteVarVecShift>; - -defm VPRORV : avx512_var_shift_types<0x14, "vprorv", rotr, SchedWriteVarVecShift>; -defm VPROLV : avx512_var_shift_types<0x15, "vprolv", rotl, SchedWriteVarVecShift>; - -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; -defm : avx512_var_shift_lowering; - -// Special handing for handling VPSRAV intrinsics. -multiclass avx512_var_shift_int_lowering p> { - let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, _.RC:$src2)), - (!cast(InstrStr#_.ZSuffix#rr) _.RC:$src1, - _.RC:$src2)>; - def : Pat<(_.VT (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2)))), - (!cast(InstrStr#_.ZSuffix##rm) - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix#rrk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2))), - _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix##rmk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix#rrkz) _.KRC:$mask, - _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (bitconvert (_.LdFrag addr:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix##rmkz) _.KRC:$mask, - _.RC:$src1, addr:$src2)>; - } -} - -multiclass avx512_var_shift_int_lowering_mb p> : - avx512_var_shift_int_lowering { - let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2)))), - (!cast(InstrStr#_.ZSuffix##rmb) - _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2))), - _.RC:$src0)), - (!cast(InstrStr#_.ZSuffix##rmbk) _.RC:$src0, - _.KRC:$mask, _.RC:$src1, addr:$src2)>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src2))), - _.ImmAllZerosV)), - (!cast(InstrStr#_.ZSuffix##rmbkz) _.KRC:$mask, - _.RC:$src1, addr:$src2)>; - } -} - -defm : avx512_var_shift_int_lowering<"VPSRAVW", v8i16x_info, [HasVLX, HasBWI]>; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v16i16x_info, [HasVLX, HasBWI]>; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v32i16_info, [HasBWI]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v4i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v8i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v16i32_info, [HasAVX512]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v2i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v4i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v8i64_info, [HasAVX512]>; - -// Use 512bit VPROL/VPROLI version to implement v2i64/v4i64 + v4i32/v8i32 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (rotl (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (rotl (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v4i32 (rotl (v4i32 VR128X:$src1), (v4i32 VR128X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v8i32 (rotl (v8i32 VR256X:$src1), (v8i32 VR256X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v2i64 (X86vrotli (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v4i64 (X86vrotli (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPROLQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v4i32 (X86vrotli (v4i32 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v8i32 (X86vrotli (v8i32 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPROLDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; -} - -// Use 512bit VPROR/VPRORI version to implement v2i64/v4i64 + v4i32/v8i32 in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (rotr (v2i64 VR128X:$src1), (v2i64 VR128X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (rotr (v4i64 VR256X:$src1), (v4i64 VR256X:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORVQZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v4i32 (rotr (v4i32 VR128X:$src1), (v4i32 VR128X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src2, sub_xmm)))), - sub_xmm)>; - def : Pat<(v8i32 (rotr (v8i32 VR256X:$src1), (v8i32 VR256X:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORVDZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src2, sub_ymm)))), - sub_ymm)>; - - def : Pat<(v2i64 (X86vrotri (v2i64 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v4i64 (X86vrotri (v4i64 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v8i64 - (VPRORQZri - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; - - def : Pat<(v4i32 (X86vrotri (v4i32 VR128X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR128X:$src1, sub_xmm)), - imm:$src2)), sub_xmm)>; - def : Pat<(v8i32 (X86vrotri (v8i32 VR256X:$src1), (i8 imm:$src2))), - (EXTRACT_SUBREG (v16i32 - (VPRORDZri - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), VR256X:$src1, sub_ymm)), - imm:$src2)), sub_ymm)>; -} - -//===-------------------------------------------------------------------===// -// 1-src variable permutation VPERMW/D/Q -//===-------------------------------------------------------------------===// - -multiclass avx512_vperm_dq_sizes opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasAVX512] in - defm Z : avx512_var_shift, - avx512_var_shift_mb, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in - defm Z256 : avx512_var_shift, - avx512_var_shift_mb, EVEX_V256; -} - -multiclass avx512_vpermi_dq_sizes opc, Format ImmFormR, Format ImmFormM, - string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo VTInfo> { - let Predicates = [HasAVX512] in - defm Z: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in - defm Z256: avx512_shift_rmi, - avx512_shift_rmbi, EVEX_V256; -} - -multiclass avx512_vperm_bw opc, string OpcodeStr, - Predicate prd, SDNode OpNode, - X86FoldableSchedWrite sched, AVX512VLVectorVTInfo _> { - let Predicates = [prd] in - defm Z: avx512_var_shift, - EVEX_V512 ; - let Predicates = [HasVLX, prd] in { - defm Z256: avx512_var_shift, - EVEX_V256 ; - defm Z128: avx512_var_shift, - EVEX_V128 ; - } -} - -defm VPERMW : avx512_vperm_bw<0x8D, "vpermw", HasBWI, X86VPermv, - WriteVarShuffle256, avx512vl_i16_info>, VEX_W; -defm VPERMB : avx512_vperm_bw<0x8D, "vpermb", HasVBMI, X86VPermv, - WriteVarShuffle256, avx512vl_i8_info>; - -defm VPERMD : avx512_vperm_dq_sizes<0x36, "vpermd", X86VPermv, - WriteVarShuffle256, avx512vl_i32_info>; -defm VPERMQ : avx512_vperm_dq_sizes<0x36, "vpermq", X86VPermv, - WriteVarShuffle256, avx512vl_i64_info>, VEX_W; -defm VPERMPS : avx512_vperm_dq_sizes<0x16, "vpermps", X86VPermv, - WriteFVarShuffle256, avx512vl_f32_info>; -defm VPERMPD : avx512_vperm_dq_sizes<0x16, "vpermpd", X86VPermv, - WriteFVarShuffle256, avx512vl_f64_info>, VEX_W; - -defm VPERMQ : avx512_vpermi_dq_sizes<0x00, MRMSrcReg, MRMSrcMem, "vpermq", - X86VPermi, WriteShuffle256, avx512vl_i64_info>, - EVEX, AVX512AIi8Base, EVEX_CD8<64, CD8VF>, VEX_W; -defm VPERMPD : avx512_vpermi_dq_sizes<0x01, MRMSrcReg, MRMSrcMem, "vpermpd", - X86VPermi, WriteFShuffle256, avx512vl_f64_info>, - EVEX, AVX512AIi8Base, EVEX_CD8<64, CD8VF>, VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPERMIL -//===----------------------------------------------------------------------===// - -multiclass avx512_permil_vec OpcVar, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo Ctrl> { - defm rr: AVX512_maskable, - T8PD, EVEX_4V, Sched<[sched]>; - defm rm: AVX512_maskable, - T8PD, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmb: AVX512_maskable, - T8PD, EVEX_4V, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_permil_vec_common OpcVar, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, - AVX512VLVectorVTInfo Ctrl> { - let Predicates = [HasAVX512] in { - defm Z : avx512_permil_vec, EVEX_V512; - } - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_permil_vec, EVEX_V128; - defm Z256 : avx512_permil_vec, EVEX_V256; - } -} - -multiclass avx512_permil OpcImm, bits<8> OpcVar, - AVX512VLVectorVTInfo _, AVX512VLVectorVTInfo Ctrl>{ - defm NAME: avx512_permil_vec_common; - defm NAME: avx512_shift_rmi_sizes, - EVEX, AVX512AIi8Base, EVEX_CD8<_.info128.EltSize, CD8VF>; -} - -let ExeDomain = SSEPackedSingle in -defm VPERMILPS : avx512_permil<"vpermilps", 0x04, 0x0C, avx512vl_f32_info, - avx512vl_i32_info>; -let ExeDomain = SSEPackedDouble in -defm VPERMILPD : avx512_permil<"vpermilpd", 0x05, 0x0D, avx512vl_f64_info, - avx512vl_i64_info>, VEX_W1X; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPSHUFD, VPSHUFLW, VPSHUFHW -//===----------------------------------------------------------------------===// - -defm VPSHUFD : avx512_shift_rmi_sizes<0x70, MRMSrcReg, MRMSrcMem, "vpshufd", - X86PShufd, SchedWriteShuffle, avx512vl_i32_info>, - EVEX, AVX512BIi8Base, EVEX_CD8<32, CD8VF>; -defm VPSHUFH : avx512_shift_rmi_w<0x70, MRMSrcReg, MRMSrcMem, "vpshufhw", - X86PShufhw, SchedWriteShuffle>, - EVEX, AVX512XSIi8Base; -defm VPSHUFL : avx512_shift_rmi_w<0x70, MRMSrcReg, MRMSrcMem, "vpshuflw", - X86PShuflw, SchedWriteShuffle>, - EVEX, AVX512XDIi8Base; - -//===----------------------------------------------------------------------===// -// AVX-512 - VPSHUFB -//===----------------------------------------------------------------------===// - -multiclass avx512_pshufb_sizes opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasBWI] in - defm Z: avx512_var_shift, - EVEX_V512; - - let Predicates = [HasVLX, HasBWI] in { - defm Z256: avx512_var_shift, - EVEX_V256; - defm Z128: avx512_var_shift, - EVEX_V128; - } -} - -defm VPSHUFB: avx512_pshufb_sizes<0x00, "vpshufb", X86pshufb, - SchedWriteVarShuffle>, VEX_WIG; - -//===----------------------------------------------------------------------===// -// Move Low to High and High to Low packed FP Instructions -//===----------------------------------------------------------------------===// - -def VMOVLHPSZrr : AVX512PSI<0x16, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovlhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128X:$dst, (v4f32 (X86Movlhps VR128X:$src1, VR128X:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, EVEX_4V; -let isCommutable = 1 in -def VMOVHLPSZrr : AVX512PSI<0x12, MRMSrcReg, (outs VR128X:$dst), - (ins VR128X:$src1, VR128X:$src2), - "vmovhlps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128X:$dst, (v4f32 (X86Movhlps VR128X:$src1, VR128X:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, EVEX_4V, NotMemoryFoldable; - -//===----------------------------------------------------------------------===// -// VMOVHPS/PD VMOVLPS Instructions -// All patterns was taken from SSS implementation. -//===----------------------------------------------------------------------===// - -multiclass avx512_mov_hilo_packed opc, string OpcodeStr, - SDPatternOperator OpNode, - X86VectorVTInfo _> { - let hasSideEffects = 0, mayLoad = 1, ExeDomain = _.ExeDomain in - def rm : AVX512, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>, EVEX_4V; -} - -// No patterns for MOVLPS/MOVHPS as the Movlhps node should only be created in -// SSE1. And MOVLPS pattern is even more complex. -defm VMOVHPSZ128 : avx512_mov_hilo_packed<0x16, "vmovhps", null_frag, - v4f32x_info>, EVEX_CD8<32, CD8VT2>, PS; -defm VMOVHPDZ128 : avx512_mov_hilo_packed<0x16, "vmovhpd", X86Unpckl, - v2f64x_info>, EVEX_CD8<64, CD8VT1>, PD, VEX_W; -defm VMOVLPSZ128 : avx512_mov_hilo_packed<0x12, "vmovlps", null_frag, - v4f32x_info>, EVEX_CD8<32, CD8VT2>, PS; -defm VMOVLPDZ128 : avx512_mov_hilo_packed<0x12, "vmovlpd", X86Movsd, - v2f64x_info>, EVEX_CD8<64, CD8VT1>, PD, VEX_W; - -let Predicates = [HasAVX512] in { - // VMOVHPD patterns - def : Pat<(v2f64 (X86Unpckl VR128X:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (VMOVHPDZ128rm VR128X:$src1, addr:$src2)>; -} - -let SchedRW = [WriteFStore] in { -def VMOVHPSZ128mr : AVX512PSI<0x17, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128X:$src)), - (bc_v2f64 (v4f32 VR128X:$src))), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT2>; -def VMOVHPDZ128mr : AVX512PDI<0x17, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128X:$src, VR128X:$src)), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<64, CD8VT1>, VEX_W; -def VMOVLPSZ128mr : AVX512PSI<0x13, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128X:$src)), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<32, CD8VT2>; -def VMOVLPDZ128mr : AVX512PDI<0x13, MRMDestMem, (outs), - (ins f64mem:$dst, VR128X:$src), - "vmovlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128X:$src), - (iPTR 0))), addr:$dst)]>, - EVEX, EVEX_CD8<64, CD8VT1>, VEX_W; -} // SchedRW - -let Predicates = [HasAVX512] in { - // VMOVHPD patterns - def : Pat<(store (f64 (extractelt - (v2f64 (X86VPermilpi VR128X:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (VMOVHPDZ128mr addr:$dst, VR128X:$src)>; -} -//===----------------------------------------------------------------------===// -// FMA - Fused Multiply Operations -// - -multiclass avx512_fma3p_213_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_213_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_213_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_213_rm, - avx512_fma3_213_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_213_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_213_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_213_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd> { - defm PS : avx512_fma3p_213_common; - defm PD : avx512_fma3p_213_common, - VEX_W; -} - -defm VFMADD213 : avx512_fma3p_213_f<0xA8, "vfmadd213", X86Fmadd, X86FmaddRnd>; -defm VFMSUB213 : avx512_fma3p_213_f<0xAA, "vfmsub213", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB213 : avx512_fma3p_213_f<0xA6, "vfmaddsub213", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD213 : avx512_fma3p_213_f<0xA7, "vfmsubadd213", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD213 : avx512_fma3p_213_f<0xAC, "vfnmadd213", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB213 : avx512_fma3p_213_f<0xAE, "vfnmsub213", X86Fnmsub, X86FnmsubRnd>; - - -multiclass avx512_fma3p_231_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, AVX512FMA3Base, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_231_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_231_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_231_rm, - avx512_fma3_231_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_231_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_231_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_231_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd > { - defm PS : avx512_fma3p_231_common; - defm PD : avx512_fma3p_231_common, - VEX_W; -} - -defm VFMADD231 : avx512_fma3p_231_f<0xB8, "vfmadd231", X86Fmadd, X86FmaddRnd>; -defm VFMSUB231 : avx512_fma3p_231_f<0xBA, "vfmsub231", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB231 : avx512_fma3p_231_f<0xB6, "vfmaddsub231", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD231 : avx512_fma3p_231_f<0xB7, "vfmsubadd231", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD231 : avx512_fma3p_231_f<0xBC, "vfnmadd231", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB231 : avx512_fma3p_231_f<0xBE, "vfnmsub231", X86Fnmsub, X86FnmsubRnd>; - -multiclass avx512_fma3p_132_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fma3_132_round opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Suff> { - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain, hasSideEffects = 0 in - defm rb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_fma3p_132_common opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, - AVX512VLVectorVTInfo _, string Suff> { - let Predicates = [HasAVX512] in { - defm Z : avx512_fma3p_132_rm, - avx512_fma3_132_round, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasAVX512] in { - defm Z256 : avx512_fma3p_132_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_fma3p_132_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -multiclass avx512_fma3p_132_f opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd > { - defm PS : avx512_fma3p_132_common; - defm PD : avx512_fma3p_132_common, - VEX_W; -} - -defm VFMADD132 : avx512_fma3p_132_f<0x98, "vfmadd132", X86Fmadd, X86FmaddRnd>; -defm VFMSUB132 : avx512_fma3p_132_f<0x9A, "vfmsub132", X86Fmsub, X86FmsubRnd>; -defm VFMADDSUB132 : avx512_fma3p_132_f<0x96, "vfmaddsub132", X86Fmaddsub, X86FmaddsubRnd>; -defm VFMSUBADD132 : avx512_fma3p_132_f<0x97, "vfmsubadd132", X86Fmsubadd, X86FmsubaddRnd>; -defm VFNMADD132 : avx512_fma3p_132_f<0x9C, "vfnmadd132", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB132 : avx512_fma3p_132_f<0x9E, "vfnmsub132", X86Fnmsub, X86FnmsubRnd>; - -// Scalar FMA -multiclass avx512_fma3s_common opc, string OpcodeStr, X86VectorVTInfo _, - dag RHS_r, dag RHS_m, dag RHS_b, bit MaskOnlyReg> { -let Constraints = "$src1 = $dst", hasSideEffects = 0 in { - defm r_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, Sched<[SchedWriteFMA.Scl]>; - - let mayLoad = 1 in - defm m_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, Sched<[SchedWriteFMA.Scl.Folded, ReadAfterLd]>; - - defm rb_Int: AVX512_maskable_3src_scalar, - AVX512FMA3Base, EVEX_B, EVEX_RC, Sched<[SchedWriteFMA.Scl]>; - - let isCodeGenOnly = 1, isCommutable = 1 in { - def r : AVX512FMA3S, Sched<[SchedWriteFMA.Scl]>; - def m : AVX512FMA3S, Sched<[SchedWriteFMA.Scl.Folded, ReadAfterLd]>; - - def rb : AVX512FMA3S, EVEX_B, EVEX_RC, - Sched<[SchedWriteFMA.Scl]>; - }// isCodeGenOnly = 1 -}// Constraints = "$src1 = $dst" -} - -multiclass avx512_fma3s_all opc213, bits<8> opc231, bits<8> opc132, - string OpcodeStr, SDNode OpNode, SDNode OpNodeRnd, - X86VectorVTInfo _, string SUFF> { - let ExeDomain = _.ExeDomain in { - defm NAME#213#SUFF#Z: avx512_fma3s_common; - - defm NAME#231#SUFF#Z: avx512_fma3s_common; - - // One pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - defm NAME#132#SUFF#Z: avx512_fma3s_common; - } -} - -multiclass avx512_fma3s opc213, bits<8> opc231, bits<8> opc132, - string OpcodeStr, SDNode OpNode, SDNode OpNodeRnd> { - let Predicates = [HasAVX512] in { - defm NAME : avx512_fma3s_all, - EVEX_CD8<32, CD8VT1>, VEX_LIG; - defm NAME : avx512_fma3s_all, - EVEX_CD8<64, CD8VT1>, VEX_LIG, VEX_W; - } -} - -defm VFMADD : avx512_fma3s<0xA9, 0xB9, 0x99, "vfmadd", X86Fmadd, X86FmaddRnd>; -defm VFMSUB : avx512_fma3s<0xAB, 0xBB, 0x9B, "vfmsub", X86Fmsub, X86FmsubRnd>; -defm VFNMADD : avx512_fma3s<0xAD, 0xBD, 0x9D, "vfnmadd", X86Fnmadd, X86FnmaddRnd>; -defm VFNMSUB : avx512_fma3s<0xAF, 0xBF, 0x9F, "vfnmsub", X86Fnmsub, X86FnmsubRnd>; - -multiclass avx512_scalar_fma_patterns { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3))))), - (!cast(Prefix#"213"#Suffix#"Zr_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zr_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)))))), - (!cast(Prefix#"213"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3), _.FRC:$src2))))), - (!cast(Prefix#"132"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zm_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zr_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3), _.FRC:$src2), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"132"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zr_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zm_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zr_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zr_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)))>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (_.ScalarLdFrag addr:$src3)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2, (_.ScalarLdFrag addr:$src3)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"132"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (Op _.FRC:$src2, (_.ScalarLdFrag addr:$src3), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zm_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), addr:$src3)>; - - // Patterns with rounding mode. - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Int") - VR128X:$src1, (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)), - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Intk") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src3, (i32 imm:$rc)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"213"#Suffix#"Zrb_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - - def : Pat<(_.VT (Move (_.VT VR128X:$src1), (_.VT (scalar_to_vector - (X86selects VK1WM:$mask, - (RndOp _.FRC:$src2, _.FRC:$src3, - (_.EltVT (extractelt (_.VT VR128X:$src1), (iPTR 0))), - (i32 imm:$rc)), - (_.EltVT ZeroFP)))))), - (!cast(Prefix#"231"#Suffix#"Zrb_Intkz") - VR128X:$src1, VK1WM:$mask, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)), - (_.VT (COPY_TO_REGCLASS _.FRC:$src3, VR128X)), imm:$rc)>; - } -} - -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; - -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; -defm : avx512_scalar_fma_patterns; - -//===----------------------------------------------------------------------===// -// AVX-512 Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit IFMA -//===----------------------------------------------------------------------===// -let Constraints = "$src1 = $dst" in { -multiclass avx512_pmadd52_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - // NOTE: The SDNode have the multiply operands first with the add last. - // This enables commuted load patterns to be autogenerated by tablegen. - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - - defm m: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched.Folded, ReadAfterLd]>; - - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} -} // Constraints = "$src1 = $dst" - -multiclass avx512_pmadd52_common opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo _> { - let Predicates = [HasIFMA] in { - defm Z : avx512_pmadd52_rm, - EVEX_V512, EVEX_CD8<_.info512.EltSize, CD8VF>; - } - let Predicates = [HasVLX, HasIFMA] in { - defm Z256 : avx512_pmadd52_rm, - EVEX_V256, EVEX_CD8<_.info256.EltSize, CD8VF>; - defm Z128 : avx512_pmadd52_rm, - EVEX_V128, EVEX_CD8<_.info128.EltSize, CD8VF>; - } -} - -defm VPMADD52LUQ : avx512_pmadd52_common<0xb4, "vpmadd52luq", x86vpmadd52l, - SchedWriteVecIMul, avx512vl_i64_info>, - VEX_W; -defm VPMADD52HUQ : avx512_pmadd52_common<0xb5, "vpmadd52huq", x86vpmadd52h, - SchedWriteVecIMul, avx512vl_i64_info>, - VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 Scalar convert from sign integer to float/double -//===----------------------------------------------------------------------===// - -multiclass avx512_vcvtsi opc, SDNode OpNode, X86FoldableSchedWrite sched, - RegisterClass SrcRC, X86VectorVTInfo DstVT, - X86MemOperand x86memop, PatFrag ld_frag, string asm> { - let hasSideEffects = 0 in { - def rr : SI, - EVEX_4V, Sched<[sched]>; - let mayLoad = 1 in - def rm : SI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - } // hasSideEffects = 0 - let isCodeGenOnly = 1 in { - def rr_Int : SI, - EVEX_4V, Sched<[sched]>; - - def rm_Int : SI, - EVEX_4V, Sched<[sched.Folded, ReadAfterLd]>; - }//isCodeGenOnly = 1 -} - -multiclass avx512_vcvtsi_round opc, SDNode OpNode, - X86FoldableSchedWrite sched, RegisterClass SrcRC, - X86VectorVTInfo DstVT, string asm> { - def rrb_Int : SI, - EVEX_4V, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_vcvtsi_common opc, SDNode OpNode, - X86FoldableSchedWrite sched, - RegisterClass SrcRC, X86VectorVTInfo DstVT, - X86MemOperand x86memop, PatFrag ld_frag, string asm> { - defm NAME : avx512_vcvtsi_round, - avx512_vcvtsi, VEX_LIG; -} - -let Predicates = [HasAVX512] in { -defm VCVTSI2SSZ : avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SS, GR32, - v4f32x_info, i32mem, loadi32, "cvtsi2ss{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSI642SSZ: avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SS, GR64, - v4f32x_info, i64mem, loadi64, "cvtsi2ss{q}">, - XS, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTSI2SDZ : avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SD, GR32, - v2f64x_info, i32mem, loadi32, "cvtsi2sd{l}">, - XD, EVEX_CD8<32, CD8VT1>; -defm VCVTSI642SDZ: avx512_vcvtsi_common<0x2A, X86SintToFpRnd, WriteCvtI2SD, GR64, - v2f64x_info, i64mem, loadi64, "cvtsi2sd{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -def : InstAlias<"vcvtsi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTSI2SSZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; -def : InstAlias<"vcvtsi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTSI2SDZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; - -def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f32 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; - -def : Pat<(f32 (sint_to_fp GR32:$src)), - (VCVTSI2SSZrr (f32 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f32 (sint_to_fp GR64:$src)), - (VCVTSI642SSZrr (f32 (IMPLICIT_DEF)), GR64:$src)>; -def : Pat<(f64 (sint_to_fp GR32:$src)), - (VCVTSI2SDZrr (f64 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f64 (sint_to_fp GR64:$src)), - (VCVTSI642SDZrr (f64 (IMPLICIT_DEF)), GR64:$src)>; - -defm VCVTUSI2SSZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SS, GR32, - v4f32x_info, i32mem, loadi32, - "cvtusi2ss{l}">, XS, EVEX_CD8<32, CD8VT1>; -defm VCVTUSI642SSZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SS, GR64, - v4f32x_info, i64mem, loadi64, "cvtusi2ss{q}">, - XS, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTUSI2SDZ : avx512_vcvtsi<0x7B, X86UintToFpRnd, WriteCvtI2SD, GR32, v2f64x_info, - i32mem, loadi32, "cvtusi2sd{l}">, - XD, VEX_LIG, EVEX_CD8<32, CD8VT1>; -defm VCVTUSI642SDZ : avx512_vcvtsi_common<0x7B, X86UintToFpRnd, WriteCvtI2SD, GR64, - v2f64x_info, i64mem, loadi64, "cvtusi2sd{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -def : InstAlias<"vcvtusi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTUSI2SSZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; -def : InstAlias<"vcvtusi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTUSI2SDZrm FR64X:$dst, FR64X:$src1, i32mem:$src), 0, "att">; - -def : Pat<(f32 (uint_to_fp (loadi32 addr:$src))), - (VCVTUSI2SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f32 (uint_to_fp (loadi64 addr:$src))), - (VCVTUSI642SSZrm (f32 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (uint_to_fp (loadi32 addr:$src))), - (VCVTUSI2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; -def : Pat<(f64 (uint_to_fp (loadi64 addr:$src))), - (VCVTUSI642SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>; - -def : Pat<(f32 (uint_to_fp GR32:$src)), - (VCVTUSI2SSZrr (f32 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f32 (uint_to_fp GR64:$src)), - (VCVTUSI642SSZrr (f32 (IMPLICIT_DEF)), GR64:$src)>; -def : Pat<(f64 (uint_to_fp GR32:$src)), - (VCVTUSI2SDZrr (f64 (IMPLICIT_DEF)), GR32:$src)>; -def : Pat<(f64 (uint_to_fp GR64:$src)), - (VCVTUSI642SDZrr (f64 (IMPLICIT_DEF)), GR64:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 Scalar convert from float/double to integer -//===----------------------------------------------------------------------===// - -multiclass avx512_cvt_s_int_round opc, X86VectorVTInfo SrcVT, - X86VectorVTInfo DstVT, SDNode OpNode, - X86FoldableSchedWrite sched, string asm, - string aliasStr, - bit CodeGenOnly = 1> { - let Predicates = [HasAVX512] in { - def rr_Int : SI, - EVEX, VEX_LIG, Sched<[sched]>; - def rrb_Int : SI, - EVEX, VEX_LIG, EVEX_B, EVEX_RC, - Sched<[sched]>; - let isCodeGenOnly = CodeGenOnly, ForceDisassemble = CodeGenOnly in - def rm_Int : SI, - EVEX, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - - def : InstAlias<"v" # asm # aliasStr # "\t{$src, $dst|$dst, $src}", - (!cast(NAME # "rr_Int") DstVT.RC:$dst, SrcVT.RC:$src), 0, "att">; - def : InstAlias<"v" # asm # aliasStr # "\t{$rc, $src, $dst|$dst, $src, $rc}", - (!cast(NAME # "rrb_Int") DstVT.RC:$dst, SrcVT.RC:$src, AVX512RC:$rc), 0, "att">; - } // Predicates = [HasAVX512] -} - -multiclass avx512_cvt_s_int_round_aliases opc, X86VectorVTInfo SrcVT, - X86VectorVTInfo DstVT, SDNode OpNode, - X86FoldableSchedWrite sched, string asm, - string aliasStr> : - avx512_cvt_s_int_round { - let Predicates = [HasAVX512] in { - def : InstAlias<"v" # asm # aliasStr # "\t{$src, $dst|$dst, $src}", - (!cast(NAME # "rm_Int") DstVT.RC:$dst, - SrcVT.IntScalarMemOp:$src), 0, "att">; - } // Predicates = [HasAVX512] -} - -// Convert float/double to signed/unsigned int 32/64 -defm VCVTSS2SIZ: avx512_cvt_s_int_round<0x2D, f32x_info, i32x_info, - X86cvts2si, WriteCvtSS2I, "cvtss2si", "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2SI64Z: avx512_cvt_s_int_round<0x2D, f32x_info, i64x_info, - X86cvts2si, WriteCvtSS2I, "cvtss2si", "{q}">, - XS, VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2USIZ: avx512_cvt_s_int_round_aliases<0x79, f32x_info, i32x_info, - X86cvts2usi, WriteCvtSS2I, "cvtss2usi", "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTSS2USI64Z: avx512_cvt_s_int_round_aliases<0x79, f32x_info, i64x_info, - X86cvts2usi, WriteCvtSS2I, "cvtss2usi", "{q}">, - XS, VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTSD2SIZ: avx512_cvt_s_int_round<0x2D, f64x_info, i32x_info, - X86cvts2si, WriteCvtSD2I, "cvtsd2si", "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2SI64Z: avx512_cvt_s_int_round<0x2D, f64x_info, i64x_info, - X86cvts2si, WriteCvtSD2I, "cvtsd2si", "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2USIZ: avx512_cvt_s_int_round_aliases<0x79, f64x_info, i32x_info, - X86cvts2usi, WriteCvtSD2I, "cvtsd2usi", "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTSD2USI64Z: avx512_cvt_s_int_round_aliases<0x79, f64x_info, i64x_info, - X86cvts2usi, WriteCvtSD2I, "cvtsd2usi", "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -// The SSE version of these instructions are disabled for AVX512. -// Therefore, the SSE intrinsics are mapped to the AVX512 instructions. -let Predicates = [HasAVX512] in { - def : Pat<(i32 (int_x86_sse_cvtss2si (v4f32 VR128X:$src))), - (VCVTSS2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse_cvtss2si sse_load_f32:$src)), - (VCVTSS2SIZrm_Int sse_load_f32:$src)>; - def : Pat<(i64 (int_x86_sse_cvtss2si64 (v4f32 VR128X:$src))), - (VCVTSS2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse_cvtss2si64 sse_load_f32:$src)), - (VCVTSS2SI64Zrm_Int sse_load_f32:$src)>; - def : Pat<(i32 (int_x86_sse2_cvtsd2si (v2f64 VR128X:$src))), - (VCVTSD2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse2_cvtsd2si sse_load_f64:$src)), - (VCVTSD2SIZrm_Int sse_load_f64:$src)>; - def : Pat<(i64 (int_x86_sse2_cvtsd2si64 (v2f64 VR128X:$src))), - (VCVTSD2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse2_cvtsd2si64 sse_load_f64:$src)), - (VCVTSD2SI64Zrm_Int sse_load_f64:$src)>; -} // HasAVX512 - -// Patterns used for matching vcvtsi2s{s,d} intrinsic sequences from clang -// which produce unnecessary vmovs{s,d} instructions -let Predicates = [HasAVX512] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (VCVTSI642SSZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (VCVTSI2SSZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (VCVTSI642SDZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (VCVTSI2SDZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp GR64:$src)))))), - (VCVTUSI642SSZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp (loadi64 addr:$src))))))), - (VCVTUSI642SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp GR32:$src)))))), - (VCVTUSI2SSZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector (f32 (uint_to_fp (loadi32 addr:$src))))))), - (VCVTUSI2SSZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp GR64:$src)))))), - (VCVTUSI642SDZrr_Int VR128X:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp (loadi64 addr:$src))))))), - (VCVTUSI642SDZrm_Int VR128X:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp GR32:$src)))))), - (VCVTUSI2SDZrr_Int VR128X:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector (f64 (uint_to_fp (loadi32 addr:$src))))))), - (VCVTUSI2SDZrm_Int VR128X:$dst, addr:$src)>; -} // Predicates = [HasAVX512] - -// Convert float/double to signed/unsigned int 32/64 with truncation -multiclass avx512_cvt_s_all opc, string asm, X86VectorVTInfo _SrcRC, - X86VectorVTInfo _DstRC, SDNode OpNode, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - string aliasStr, bit CodeGenOnly = 1>{ -let Predicates = [HasAVX512] in { - let isCodeGenOnly = 1 in { - def rr : AVX512, - EVEX, Sched<[sched]>; - def rm : AVX512, - EVEX, Sched<[sched.Folded, ReadAfterLd]>; - } - - def rr_Int : AVX512, - EVEX, VEX_LIG, Sched<[sched]>; - def rrb_Int : AVX512, - EVEX,VEX_LIG , EVEX_B, Sched<[sched]>; - let isCodeGenOnly = CodeGenOnly, ForceDisassemble = CodeGenOnly in - def rm_Int : AVX512, - EVEX, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - - def : InstAlias(NAME # "rr_Int") _DstRC.RC:$dst, _SrcRC.RC:$src), 0, "att">; - def : InstAlias(NAME # "rrb_Int") _DstRC.RC:$dst, _SrcRC.RC:$src), 0, "att">; -} //HasAVX512 -} - -multiclass avx512_cvt_s_all_unsigned opc, string asm, - X86VectorVTInfo _SrcRC, - X86VectorVTInfo _DstRC, SDNode OpNode, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - string aliasStr> : - avx512_cvt_s_all { -let Predicates = [HasAVX512] in { - def : InstAlias(NAME # "rm_Int") _DstRC.RC:$dst, - _SrcRC.IntScalarMemOp:$src), 0, "att">; -} -} - -defm VCVTTSS2SIZ: avx512_cvt_s_all<0x2C, "vcvttss2si", f32x_info, i32x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSS2I, "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSS2SI64Z: avx512_cvt_s_all<0x2C, "vcvttss2si", f32x_info, i64x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSS2I, "{q}">, - VEX_W, XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSD2SIZ: avx512_cvt_s_all<0x2C, "vcvttsd2si", f64x_info, i32x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSD2I, "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTTSD2SI64Z: avx512_cvt_s_all<0x2C, "vcvttsd2si", f64x_info, i64x_info, - fp_to_sint, X86cvtts2IntRnd, WriteCvtSD2I, "{q}">, - VEX_W, XD, EVEX_CD8<64, CD8VT1>; - -defm VCVTTSS2USIZ: avx512_cvt_s_all_unsigned<0x78, "vcvttss2usi", f32x_info, i32x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSS2I, "{l}">, - XS, EVEX_CD8<32, CD8VT1>; -defm VCVTTSS2USI64Z: avx512_cvt_s_all_unsigned<0x78, "vcvttss2usi", f32x_info, i64x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSS2I, "{q}">, - XS,VEX_W, EVEX_CD8<32, CD8VT1>; -defm VCVTTSD2USIZ: avx512_cvt_s_all_unsigned<0x78, "vcvttsd2usi", f64x_info, i32x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSD2I, "{l}">, - XD, EVEX_CD8<64, CD8VT1>; -defm VCVTTSD2USI64Z: avx512_cvt_s_all_unsigned<0x78, "vcvttsd2usi", f64x_info, i64x_info, - fp_to_uint, X86cvtts2UIntRnd, WriteCvtSD2I, "{q}">, - XD, VEX_W, EVEX_CD8<64, CD8VT1>; - -let Predicates = [HasAVX512] in { - def : Pat<(i32 (int_x86_sse_cvttss2si (v4f32 VR128X:$src))), - (VCVTTSS2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse_cvttss2si sse_load_f32:$src)), - (VCVTTSS2SIZrm_Int ssmem:$src)>; - def : Pat<(i64 (int_x86_sse_cvttss2si64 (v4f32 VR128X:$src))), - (VCVTTSS2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse_cvttss2si64 sse_load_f32:$src)), - (VCVTTSS2SI64Zrm_Int ssmem:$src)>; - def : Pat<(i32 (int_x86_sse2_cvttsd2si (v2f64 VR128X:$src))), - (VCVTTSD2SIZrr_Int VR128X:$src)>; - def : Pat<(i32 (int_x86_sse2_cvttsd2si sse_load_f64:$src)), - (VCVTTSD2SIZrm_Int sdmem:$src)>; - def : Pat<(i64 (int_x86_sse2_cvttsd2si64 (v2f64 VR128X:$src))), - (VCVTTSD2SI64Zrr_Int VR128X:$src)>; - def : Pat<(i64 (int_x86_sse2_cvttsd2si64 sse_load_f64:$src)), - (VCVTTSD2SI64Zrm_Int sdmem:$src)>; -} // HasAVX512 - -//===----------------------------------------------------------------------===// -// AVX-512 Convert form float to double and back -//===----------------------------------------------------------------------===// - -multiclass avx512_cvt_fp_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNode, - X86FoldableSchedWrite sched> { - defm rr_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, Sched<[sched]>; - defm rm_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr : I, - EVEX_4V, VEX_LIG, Sched<[sched]>; - let mayLoad = 1 in - def rm : I, - EVEX_4V, VEX_LIG, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -// Scalar Conversion with SAE - suppress all exceptions -multiclass avx512_cvt_fp_sae_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, EVEX_B, Sched<[sched]>; -} - -// Scalar Conversion with rounding control (RC) -multiclass avx512_cvt_fp_rc_scalar opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb_Int : AVX512_maskable_scalar, - EVEX_4V, VEX_LIG, Sched<[sched]>, - EVEX_B, EVEX_RC; -} -multiclass avx512_cvt_fp_scalar_sd2ss opc, string OpcodeStr, - SDNode OpNodeRnd, X86FoldableSchedWrite sched, - X86VectorVTInfo _src, X86VectorVTInfo _dst> { - let Predicates = [HasAVX512] in { - defm Z : avx512_cvt_fp_scalar, - avx512_cvt_fp_rc_scalar, VEX_W, EVEX_CD8<64, CD8VT1>, XD; - } -} - -multiclass avx512_cvt_fp_scalar_ss2sd opc, string OpcodeStr, SDNode OpNodeRnd, - X86FoldableSchedWrite sched, - X86VectorVTInfo _src, X86VectorVTInfo _dst> { - let Predicates = [HasAVX512] in { - defm Z : avx512_cvt_fp_scalar, - avx512_cvt_fp_sae_scalar, - EVEX_CD8<32, CD8VT1>, XS; - } -} -defm VCVTSD2SS : avx512_cvt_fp_scalar_sd2ss<0x5A, "vcvtsd2ss", - X86froundRnd, WriteCvtSD2SS, f64x_info, - f32x_info>; -defm VCVTSS2SD : avx512_cvt_fp_scalar_ss2sd<0x5A, "vcvtss2sd", - X86fpextRnd, WriteCvtSS2SD, f32x_info, - f64x_info>; - -def : Pat<(f64 (fpextend FR32X:$src)), - (VCVTSS2SDZrr (f64 (IMPLICIT_DEF)), FR32X:$src)>, - Requires<[HasAVX512]>; -def : Pat<(f64 (fpextend (loadf32 addr:$src))), - (VCVTSS2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[HasAVX512, OptForSize]>; - -def : Pat<(f64 (extloadf32 addr:$src)), - (VCVTSS2SDZrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[HasAVX512, OptForSize]>; - -def : Pat<(f64 (extloadf32 addr:$src)), - (VCVTSS2SDZrr (f64 (IMPLICIT_DEF)), (VMOVSSZrm addr:$src))>, - Requires<[HasAVX512, OptForSpeed]>; - -def : Pat<(f32 (fpround FR64X:$src)), - (VCVTSD2SSZrr (f32 (IMPLICIT_DEF)), FR64X:$src)>, - Requires<[HasAVX512]>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128X:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128X:$src, (iPTR 0))))))))), - (VCVTSD2SSZrr_Int VR128X:$dst, VR128X:$src)>, - Requires<[HasAVX512]>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128X:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128X:$src, (iPTR 0))))))))), - (VCVTSS2SDZrr_Int VR128X:$dst, VR128X:$src)>, - Requires<[HasAVX512]>; - -//===----------------------------------------------------------------------===// -// AVX-512 Vector convert from signed/unsigned integer to float/double -// and from float/double to signed/unsigned integer -//===----------------------------------------------------------------------===// - -multiclass avx512_vcvt_fp opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNode, - X86FoldableSchedWrite sched, - string Broadcast = _.BroadcastStr, - string Alias = "", X86MemOperand MemOp = _Src.MemOp> { - - defm rr : AVX512_maskable, - EVEX, Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, Sched<[sched.Folded]>; - - defm rmb : AVX512_maskable, EVEX, EVEX_B, - Sched<[sched.Folded]>; -} -// Conversion with SAE - suppress all exceptions -multiclass avx512_vcvt_fp_sae opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb : AVX512_maskable, - EVEX, EVEX_B, Sched<[sched]>; -} - -// Conversion with rounding control (RC) -multiclass avx512_vcvt_fp_rc opc, string OpcodeStr, X86VectorVTInfo _, - X86VectorVTInfo _Src, SDNode OpNodeRnd, - X86FoldableSchedWrite sched> { - defm rrb : AVX512_maskable, - EVEX, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -// Extend Float to Double -multiclass avx512_cvtps2pd opc, string OpcodeStr, - X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Truncate Double to Float -multiclass avx512_cvtpd2ps opc, string OpcodeStr, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - def : InstAlias(NAME # "Z128rm") VR128X:$dst, f128mem:$src), 0, "intel">; - def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - def : InstAlias(NAME # "Z256rm") VR128X:$dst, f256mem:$src), 0, "intel">; - } -} - -defm VCVTPD2PS : avx512_cvtpd2ps<0x5A, "vcvtpd2ps", SchedWriteCvtPD2PS>, - VEX_W, PD, EVEX_CD8<64, CD8VF>; -defm VCVTPS2PD : avx512_cvtps2pd<0x5A, "vcvtps2pd", SchedWriteCvtPS2PD>, - PS, EVEX_CD8<32, CD8VH>; - -def : Pat<(v8f64 (extloadv8f32 addr:$src)), - (VCVTPS2PDZrm addr:$src)>; - -let Predicates = [HasVLX] in { - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128X:$src)))))), - (VCVTPD2PSZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (loadv2f64 addr:$src)))))), - (VCVTPD2PSZ128rm addr:$src)>; - def : Pat<(v2f64 (extloadv2f32 addr:$src)), - (VCVTPS2PDZ128rm addr:$src)>; - def : Pat<(v4f64 (extloadv4f32 addr:$src)), - (VCVTPS2PDZ256rm addr:$src)>; -} - -// Convert Signed/Unsigned Doubleword to Double -multiclass avx512_cvtdq2pd opc, string OpcodeStr, SDNode OpNode, - SDNode OpNode128, X86SchedWriteWidths sched> { - // No rounding in this op - let Predicates = [HasAVX512] in - defm Z : avx512_vcvt_fp, EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Doubleword to Float -multiclass avx512_cvtdq2ps opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Doubleword with truncation -multiclass avx512_cvttps2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Doubleword -multiclass avx512_cvtps2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Double to Signed/Unsigned Doubleword with truncation -multiclass avx512_cvttpd2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parser. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - def : InstAlias(NAME # "Z128rm") VR128X:$dst, i128mem:$src), 0, "intel">; - def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - def : InstAlias(NAME # "Z256rm") VR128X:$dst, i256mem:$src), 0, "intel">; - } -} - -// Convert Double to Signed/Unsigned Doubleword -multiclass avx512_cvtpd2dq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasAVX512] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parcer. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - - def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - def : InstAlias(NAME # "Z128rm") VR128X:$dst, f128mem:$src), 0, "intel">; - def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - def : InstAlias(NAME # "Z256rm") VR128X:$dst, f256mem:$src), 0, "intel">; - } -} - -// Convert Double to Signed/Unsigned Quardword -multiclass avx512_cvtpd2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Double to Signed/Unsigned Quardword with truncation -multiclass avx512_cvttpd2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Quardword to Double -multiclass avx512_cvtqq2pd opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - defm Z128 : avx512_vcvt_fp, EVEX_V128, NotEVEX2VEXConvertible; - defm Z256 : avx512_vcvt_fp, EVEX_V256, NotEVEX2VEXConvertible; - } -} - -// Convert Float to Signed/Unsigned Quardword -multiclass avx512_cvtps2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // Explicitly specified broadcast string, since we take only 2 elements - // from v4f32x_info source - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Float to Signed/Unsigned Quardword with truncation -multiclass avx512_cvttps2qq opc, string OpcodeStr, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_sae, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // Explicitly specified broadcast string, since we take only 2 elements - // from v4f32x_info source - defm Z128 : avx512_vcvt_fp, EVEX_V128; - defm Z256 : avx512_vcvt_fp, EVEX_V256; - } -} - -// Convert Signed/Unsigned Quardword to Float -multiclass avx512_cvtqq2ps opc, string OpcodeStr, SDNode OpNode, - SDNode OpNode128, SDNode OpNodeRnd, - X86SchedWriteWidths sched> { - let Predicates = [HasDQI] in { - defm Z : avx512_vcvt_fp, - avx512_vcvt_fp_rc, EVEX_V512; - } - let Predicates = [HasDQI, HasVLX] in { - // we need "x"/"y" suffixes in order to distinguish between 128 and 256 - // memory forms of these instructions in Asm Parcer. They have the same - // dest type - 'v4i32x_info'. We also specify the broadcast string explicitly - // due to the same reason. - defm Z128 : avx512_vcvt_fp, EVEX_V128, - NotEVEX2VEXConvertible; - defm Z256 : avx512_vcvt_fp, EVEX_V256, - NotEVEX2VEXConvertible; - - def : InstAlias(NAME # "Z128rr") VR128X:$dst, VR128X:$src), 0>; - def : InstAlias(NAME # "Z128rm") VR128X:$dst, i128mem:$src), 0, "intel">; - def : InstAlias(NAME # "Z256rr") VR128X:$dst, VR256X:$src), 0>; - def : InstAlias(NAME # "Z256rm") VR128X:$dst, i256mem:$src), 0, "intel">; - } -} - -defm VCVTDQ2PD : avx512_cvtdq2pd<0xE6, "vcvtdq2pd", sint_to_fp, X86VSintToFP, - SchedWriteCvtDQ2PD>, XS, EVEX_CD8<32, CD8VH>; - -defm VCVTDQ2PS : avx512_cvtdq2ps<0x5B, "vcvtdq2ps", sint_to_fp, - X86VSintToFpRnd, SchedWriteCvtDQ2PS>, - PS, EVEX_CD8<32, CD8VF>; - -defm VCVTTPS2DQ : avx512_cvttps2dq<0x5B, "vcvttps2dq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPS2DQ>, - XS, EVEX_CD8<32, CD8VF>; - -defm VCVTTPD2DQ : avx512_cvttpd2dq<0xE6, "vcvttpd2dq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPD2DQ>, - PD, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2UDQ : avx512_cvttps2dq<0x78, "vcvttps2udq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPS2DQ>, PS, - EVEX_CD8<32, CD8VF>; - -defm VCVTTPD2UDQ : avx512_cvttpd2dq<0x78, "vcvttpd2udq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPD2DQ>, - PS, VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTUDQ2PD : avx512_cvtdq2pd<0x7A, "vcvtudq2pd", uint_to_fp, - X86VUintToFP, SchedWriteCvtDQ2PD>, XS, - EVEX_CD8<32, CD8VH>; - -defm VCVTUDQ2PS : avx512_cvtdq2ps<0x7A, "vcvtudq2ps", uint_to_fp, - X86VUintToFpRnd, SchedWriteCvtDQ2PS>, XD, - EVEX_CD8<32, CD8VF>; - -defm VCVTPS2DQ : avx512_cvtps2dq<0x5B, "vcvtps2dq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VF>; - -defm VCVTPD2DQ : avx512_cvtpd2dq<0xE6, "vcvtpd2dq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPD2DQ>, XD, - VEX_W, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2UDQ : avx512_cvtps2dq<0x79, "vcvtps2udq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPS2DQ>, - PS, EVEX_CD8<32, CD8VF>; - -defm VCVTPD2UDQ : avx512_cvtpd2dq<0x79, "vcvtpd2udq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PS, EVEX_CD8<64, CD8VF>; - -defm VCVTPD2QQ : avx512_cvtpd2qq<0x7B, "vcvtpd2qq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2QQ : avx512_cvtps2qq<0x7B, "vcvtps2qq", X86cvtp2Int, - X86cvtp2IntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTPD2UQQ : avx512_cvtpd2qq<0x79, "vcvtpd2uqq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTPS2UQQ : avx512_cvtps2qq<0x79, "vcvtps2uqq", X86cvtp2UInt, - X86cvtp2UIntRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTTPD2QQ : avx512_cvttpd2qq<0x7A, "vcvttpd2qq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2QQ : avx512_cvttps2qq<0x7A, "vcvttps2qq", X86cvttp2si, - X86cvttp2siRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTTPD2UQQ : avx512_cvttpd2qq<0x78, "vcvttpd2uqq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPD2DQ>, VEX_W, - PD, EVEX_CD8<64, CD8VF>; - -defm VCVTTPS2UQQ : avx512_cvttps2qq<0x78, "vcvttps2uqq", X86cvttp2ui, - X86cvttp2uiRnd, SchedWriteCvtPS2DQ>, PD, - EVEX_CD8<32, CD8VH>; - -defm VCVTQQ2PD : avx512_cvtqq2pd<0xE6, "vcvtqq2pd", sint_to_fp, - X86VSintToFpRnd, SchedWriteCvtDQ2PD>, VEX_W, XS, - EVEX_CD8<64, CD8VF>; - -defm VCVTUQQ2PD : avx512_cvtqq2pd<0x7A, "vcvtuqq2pd", uint_to_fp, - X86VUintToFpRnd, SchedWriteCvtDQ2PD>, VEX_W, XS, - EVEX_CD8<64, CD8VF>; - -defm VCVTQQ2PS : avx512_cvtqq2ps<0x5B, "vcvtqq2ps", sint_to_fp, X86VSintToFP, - X86VSintToFpRnd, SchedWriteCvtDQ2PS>, VEX_W, PS, - EVEX_CD8<64, CD8VF>; - -defm VCVTUQQ2PS : avx512_cvtqq2ps<0x7A, "vcvtuqq2ps", uint_to_fp, X86VUintToFP, - X86VUintToFpRnd, SchedWriteCvtDQ2PS>, VEX_W, XD, - EVEX_CD8<64, CD8VF>; - -let Predicates = [HasAVX512] in { - def : Pat<(v16i32 (fp_to_sint (v16f32 VR512:$src))), - (VCVTTPS2DQZrr VR512:$src)>; - def : Pat<(v16i32 (fp_to_sint (loadv16f32 addr:$src))), - (VCVTTPS2DQZrm addr:$src)>; - - def : Pat<(v16i32 (fp_to_uint (v16f32 VR512:$src))), - (VCVTTPS2UDQZrr VR512:$src)>; - def : Pat<(v16i32 (fp_to_uint (loadv16f32 addr:$src))), - (VCVTTPS2UDQZrm addr:$src)>; - - def : Pat<(v8i32 (fp_to_sint (v8f64 VR512:$src))), - (VCVTTPD2DQZrr VR512:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f64 addr:$src))), - (VCVTTPD2DQZrm addr:$src)>; - - def : Pat<(v8i32 (fp_to_uint (v8f64 VR512:$src))), - (VCVTTPD2UDQZrr VR512:$src)>; - def : Pat<(v8i32 (fp_to_uint (loadv8f64 addr:$src))), - (VCVTTPD2UDQZrm addr:$src)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128X:$src))), - (VCVTTPS2DQZ128rr VR128X:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2DQZ128rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_uint (v4f32 VR128X:$src))), - (VCVTTPS2UDQZ128rr VR128X:$src)>; - def : Pat<(v4i32 (fp_to_uint (loadv4f32 addr:$src))), - (VCVTTPS2UDQZ128rm addr:$src)>; - - def : Pat<(v8i32 (fp_to_sint (v8f32 VR256X:$src))), - (VCVTTPS2DQZ256rr VR256X:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2DQZ256rm addr:$src)>; - - def : Pat<(v8i32 (fp_to_uint (v8f32 VR256X:$src))), - (VCVTTPS2UDQZ256rr VR256X:$src)>; - def : Pat<(v8i32 (fp_to_uint (loadv8f32 addr:$src))), - (VCVTTPS2UDQZ256rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_sint (v4f64 VR256X:$src))), - (VCVTTPD2DQZ256rr VR256X:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2DQZ256rm addr:$src)>; - - def : Pat<(v4i32 (fp_to_uint (v4f64 VR256X:$src))), - (VCVTTPD2UDQZ256rr VR256X:$src)>; - def : Pat<(v4i32 (fp_to_uint (loadv4f64 addr:$src))), - (VCVTTPD2UDQZ256rm addr:$src)>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v8i64 (fp_to_sint (v8f32 VR256X:$src))), - (VCVTTPS2QQZrr VR256X:$src)>; - def : Pat<(v8i64 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2QQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_uint (v8f32 VR256X:$src))), - (VCVTTPS2UQQZrr VR256X:$src)>; - def : Pat<(v8i64 (fp_to_uint (loadv8f32 addr:$src))), - (VCVTTPS2UQQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_sint (v8f64 VR512:$src))), - (VCVTTPD2QQZrr VR512:$src)>; - def : Pat<(v8i64 (fp_to_sint (loadv8f64 addr:$src))), - (VCVTTPD2QQZrm addr:$src)>; - - def : Pat<(v8i64 (fp_to_uint (v8f64 VR512:$src))), - (VCVTTPD2UQQZrr VR512:$src)>; - def : Pat<(v8i64 (fp_to_uint (loadv8f64 addr:$src))), - (VCVTTPD2UQQZrm addr:$src)>; -} - -let Predicates = [HasDQI, HasVLX] in { - def : Pat<(v4i64 (fp_to_sint (v4f32 VR128X:$src))), - (VCVTTPS2QQZ256rr VR128X:$src)>; - def : Pat<(v4i64 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2QQZ256rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_uint (v4f32 VR128X:$src))), - (VCVTTPS2UQQZ256rr VR128X:$src)>; - def : Pat<(v4i64 (fp_to_uint (loadv4f32 addr:$src))), - (VCVTTPS2UQQZ256rm addr:$src)>; - - def : Pat<(v2i64 (fp_to_sint (v2f64 VR128X:$src))), - (VCVTTPD2QQZ128rr VR128X:$src)>; - def : Pat<(v2i64 (fp_to_sint (loadv2f64 addr:$src))), - (VCVTTPD2QQZ128rm addr:$src)>; - - def : Pat<(v2i64 (fp_to_uint (v2f64 VR128X:$src))), - (VCVTTPD2UQQZ128rr VR128X:$src)>; - def : Pat<(v2i64 (fp_to_uint (loadv2f64 addr:$src))), - (VCVTTPD2UQQZ128rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_sint (v4f64 VR256X:$src))), - (VCVTTPD2QQZ256rr VR256X:$src)>; - def : Pat<(v4i64 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2QQZ256rm addr:$src)>; - - def : Pat<(v4i64 (fp_to_uint (v4f64 VR256X:$src))), - (VCVTTPD2UQQZ256rr VR256X:$src)>; - def : Pat<(v4i64 (fp_to_uint (loadv4f64 addr:$src))), - (VCVTTPD2UQQZ256rm addr:$src)>; -} - -let Predicates = [HasAVX512, NoVLX] in { -def : Pat<(v8i32 (fp_to_uint (v8f32 VR256X:$src1))), - (EXTRACT_SUBREG (v16i32 (VCVTTPS2UDQZrr - (v16f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4i32 (fp_to_uint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v16i32 (VCVTTPS2UDQZrr - (v16f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i32 (fp_to_uint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i32 (VCVTTPD2UDQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v8f32 (uint_to_fp (v8i32 VR256X:$src1))), - (EXTRACT_SUBREG (v16f32 (VCVTUDQ2PSZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (uint_to_fp (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v16f32 (VCVTUDQ2PSZrr - (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (uint_to_fp (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUDQ2PDZrr - (v8i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v2f64 (X86VUintToFP (v4i32 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUDQ2PDZrr - (v8i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; -} - -let Predicates = [HasAVX512, HasVLX] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128X:$src)))))), - (VCVTPD2DQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src)))))), - (VCVTPD2DQZ128rm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2UInt (v2f64 VR128X:$src)))))), - (VCVTPD2UDQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128X:$src)))))), - (VCVTTPD2DQZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (loadv2f64 addr:$src)))))), - (VCVTTPD2DQZ128rm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2ui (v2f64 VR128X:$src)))))), - (VCVTTPD2UDQZ128rr VR128X:$src)>; - - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTDQ2PDZ128rm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTDQ2PDZ128rm addr:$src)>; - - def : Pat<(v2f64 (X86VUintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTUDQ2PDZ128rm addr:$src)>; - def : Pat<(v2f64 (X86VUintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTUDQ2PDZ128rm addr:$src)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v8f32 (fpround (loadv8f64 addr:$src))), - (VCVTPD2PSZrm addr:$src)>; - def : Pat<(v8f64 (extloadv8f32 addr:$src)), - (VCVTPS2PDZrm addr:$src)>; -} - -let Predicates = [HasDQI, HasVLX] in { - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86VSintToFP (v2i64 VR128X:$src)))))), - (VCVTQQ2PSZ128rr VR128X:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86VUintToFP (v2i64 VR128X:$src)))))), - (VCVTUQQ2PSZ128rr VR128X:$src)>; -} - -let Predicates = [HasDQI, NoVLX] in { -def : Pat<(v2i64 (fp_to_sint (v2f64 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2QQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i64 (fp_to_sint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPS2QQZrr - (v8f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v4i64 (fp_to_sint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2QQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v2i64 (fp_to_uint (v2f64 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2UQQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4i64 (fp_to_uint (v4f32 VR128X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPS2UQQZrr - (v8f32 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_ymm)>; - -def : Pat<(v4i64 (fp_to_uint (v4f64 VR256X:$src1))), - (EXTRACT_SUBREG (v8i64 (VCVTTPD2UQQZrr - (v8f64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (sint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f32 (VCVTQQ2PSZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v2f64 (sint_to_fp (v2i64 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (sint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; - -def : Pat<(v4f32 (uint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f32 (VCVTUQQ2PSZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_xmm)>; - -def : Pat<(v2f64 (uint_to_fp (v2i64 VR128X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR128X:$src1, sub_xmm)))), sub_xmm)>; - -def : Pat<(v4f64 (uint_to_fp (v4i64 VR256X:$src1))), - (EXTRACT_SUBREG (v8f64 (VCVTUQQ2PDZrr - (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src1, sub_ymm)))), sub_ymm)>; -} - -//===----------------------------------------------------------------------===// -// Half precision conversion instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_cvtph2ps { - defm rr : AVX512_maskable<0x13, MRMSrcReg, _dest ,(outs _dest.RC:$dst), - (ins _src.RC:$src), "vcvtph2ps", "$src", "$src", - (X86cvtph2ps (_src.VT _src.RC:$src))>, - T8PD, Sched<[sched]>; - defm rm : AVX512_maskable<0x13, MRMSrcMem, _dest, (outs _dest.RC:$dst), - (ins x86memop:$src), "vcvtph2ps", "$src", "$src", - (X86cvtph2ps (_src.VT - (bitconvert - (ld_frag addr:$src))))>, - T8PD, Sched<[sched.Folded]>; -} - -multiclass avx512_cvtph2ps_sae { - defm rrb : AVX512_maskable<0x13, MRMSrcReg, _dest, (outs _dest.RC:$dst), - (ins _src.RC:$src), "vcvtph2ps", - "{sae}, $src", "$src, {sae}", - (X86cvtph2psRnd (_src.VT _src.RC:$src), - (i32 FROUND_NO_EXC))>, - T8PD, EVEX_B, Sched<[sched]>; -} - -let Predicates = [HasAVX512] in - defm VCVTPH2PSZ : avx512_cvtph2ps, - avx512_cvtph2ps_sae, - EVEX, EVEX_V512, EVEX_CD8<32, CD8VH>; - -let Predicates = [HasVLX] in { - defm VCVTPH2PSZ256 : avx512_cvtph2ps, EVEX, EVEX_V256, - EVEX_CD8<32, CD8VH>; - defm VCVTPH2PSZ128 : avx512_cvtph2ps, EVEX, EVEX_V128, - EVEX_CD8<32, CD8VH>; - - // Pattern match vcvtph2ps of a scalar i64 load. - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzmovl_v2i64 addr:$src)))), - (VCVTPH2PSZ128rm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzload_v2i64 addr:$src)))), - (VCVTPH2PSZ128rm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (bitconvert - (v2i64 (scalar_to_vector (loadi64 addr:$src))))))), - (VCVTPH2PSZ128rm addr:$src)>; -} - -multiclass avx512_cvtps2ph { - defm rr : AVX512_maskable<0x1D, MRMDestReg, _dest ,(outs _dest.RC:$dst), - (ins _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph", "$src2, $src1", "$src1, $src2", - (X86cvtps2ph (_src.VT _src.RC:$src1), - (i32 imm:$src2)), 0, 0>, - AVX512AIi8Base, Sched<[RR]>; - let hasSideEffects = 0, mayStore = 1 in { - def mr : AVX512AIi8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[MR]>; - def mrk : AVX512AIi8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, _dest.KRCWM:$mask, _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst {${mask}}|$dst {${mask}}, $src1, $src2}", []>, - EVEX_K, Sched<[MR]>, NotMemoryFoldable; - } -} - -multiclass avx512_cvtps2ph_sae { - let hasSideEffects = 0 in - defm rrb : AVX512_maskable_in_asm<0x1D, MRMDestReg, _dest, - (outs _dest.RC:$dst), - (ins _src.RC:$src1, i32u8imm:$src2), - "vcvtps2ph", "$src2, {sae}, $src1", "$src1, {sae}, $src2", []>, - EVEX_B, AVX512AIi8Base, Sched<[Sched]>; -} - -let Predicates = [HasAVX512] in { - defm VCVTPS2PHZ : avx512_cvtps2ph, - avx512_cvtps2ph_sae, - EVEX, EVEX_V512, EVEX_CD8<32, CD8VH>; - let Predicates = [HasVLX] in { - defm VCVTPS2PHZ256 : avx512_cvtps2ph, - EVEX, EVEX_V256, EVEX_CD8<32, CD8VH>; - defm VCVTPS2PHZ128 : avx512_cvtps2ph, - EVEX, EVEX_V128, EVEX_CD8<32, CD8VH>; - } - - def : Pat<(store (f64 (extractelt - (bc_v2f64 (v8i16 (X86cvtps2ph VR128X:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHZ128mr addr:$dst, VR128X:$src1, imm:$src2)>; - def : Pat<(store (i64 (extractelt - (bc_v2i64 (v8i16 (X86cvtps2ph VR128X:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHZ128mr addr:$dst, VR128X:$src1, imm:$src2)>; - def : Pat<(store (v8i16 (X86cvtps2ph VR256X:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHZ256mr addr:$dst, VR256X:$src1, imm:$src2)>; - def : Pat<(store (v16i16 (X86cvtps2ph VR512:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHZmr addr:$dst, VR512:$src1, imm:$src2)>; -} - -// Patterns for matching conversions from float to half-float and vice versa. -let Predicates = [HasVLX] in { - // Use MXCSR.RC for rounding instead of explicitly specifying the default - // rounding mode (Nearest-Even, encoded as 0). Both are equivalent in the - // configurations we support (the default). However, falling back to MXCSR is - // more consistent with other instructions, which are always controlled by it. - // It's encoded as 0b100. - def : Pat<(fp_to_f16 FR32X:$src), - (i16 (EXTRACT_SUBREG (VMOVPDI2DIZrr (v8i16 (VCVTPS2PHZ128rr - (v4f32 (COPY_TO_REGCLASS FR32X:$src, VR128X)), 4))), sub_16bit))>; - - def : Pat<(f16_to_fp GR16:$src), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSZ128rr - (v8i16 (COPY_TO_REGCLASS (MOVSX32rr16 GR16:$src), VR128X)))), FR32X)) >; - - def : Pat<(f16_to_fp (i16 (fp_to_f16 FR32X:$src))), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSZ128rr - (v8i16 (VCVTPS2PHZ128rr - (v4f32 (COPY_TO_REGCLASS FR32X:$src, VR128X)), 4)))), FR32X)) >; -} - -// Unordered/Ordered scalar fp compare with Sea and set EFLAGS -multiclass avx512_ord_cmp_sae opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def rrb: AVX512, - EVEX, EVEX_B, VEX_LIG, EVEX_V128, Sched<[sched]>; -} - -let Defs = [EFLAGS], Predicates = [HasAVX512] in { - defm VUCOMISSZ : avx512_ord_cmp_sae<0x2E, v4f32x_info, "vucomiss", WriteFCom>, - AVX512PSIi8Base, EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : avx512_ord_cmp_sae<0x2E, v2f64x_info, "vucomisd", WriteFCom>, - AVX512PDIi8Base, VEX_W, EVEX_CD8<64, CD8VT1>; - defm VCOMISSZ : avx512_ord_cmp_sae<0x2F, v4f32x_info, "vcomiss", WriteFCom>, - AVX512PSIi8Base, EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : avx512_ord_cmp_sae<0x2F, v2f64x_info, "vcomisd", WriteFCom>, - AVX512PDIi8Base, VEX_W, EVEX_CD8<64, CD8VT1>; -} - -let Defs = [EFLAGS], Predicates = [HasAVX512] in { - defm VUCOMISSZ : sse12_ord_cmp<0x2E, FR32X, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : sse12_ord_cmp<0x2E, FR64X, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - let Pattern = [] in { - defm VCOMISSZ : sse12_ord_cmp<0x2F, FR32X, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : sse12_ord_cmp<0x2F, FR64X, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - } - let isCodeGenOnly = 1 in { - defm VUCOMISSZ : sse12_ord_cmp_int<0x2E, VR128X, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VUCOMISDZ : sse12_ord_cmp_int<0x2E, VR128X, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - - defm VCOMISSZ : sse12_ord_cmp_int<0x2F, VR128X, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS, EVEX, VEX_LIG, - EVEX_CD8<32, CD8VT1>; - defm VCOMISDZ : sse12_ord_cmp_int<0x2F, VR128X, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD, EVEX, - VEX_LIG, VEX_W, EVEX_CD8<64, CD8VT1>; - } -} - -/// avx512_fp14_s rcp14ss, rcp14sd, rsqrt14ss, rsqrt14sd -multiclass avx512_fp14_s opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let Predicates = [HasAVX512], ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable_scalar, - EVEX_4V, Sched<[sched]>; - defm rm : AVX512_maskable_scalar, EVEX_4V, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -defm VRCP14SSZ : avx512_fp14_s<0x4D, "vrcp14ss", X86rcp14s, SchedWriteFRcp.Scl, - f32x_info>, EVEX_CD8<32, CD8VT1>, - T8PD; -defm VRCP14SDZ : avx512_fp14_s<0x4D, "vrcp14sd", X86rcp14s, SchedWriteFRcp.Scl, - f64x_info>, VEX_W, EVEX_CD8<64, CD8VT1>, - T8PD; -defm VRSQRT14SSZ : avx512_fp14_s<0x4F, "vrsqrt14ss", X86rsqrt14s, - SchedWriteFRsqrt.Scl, f32x_info>, - EVEX_CD8<32, CD8VT1>, T8PD; -defm VRSQRT14SDZ : avx512_fp14_s<0x4F, "vrsqrt14sd", X86rsqrt14s, - SchedWriteFRsqrt.Scl, f64x_info>, VEX_W, - EVEX_CD8<64, CD8VT1>, T8PD; - -/// avx512_fp14_p rcp14ps, rcp14pd, rsqrt14ps, rsqrt14pd -multiclass avx512_fp14_p opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable, EVEX, T8PD, - Sched<[sched]>; - defm m: AVX512_maskable, EVEX, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb: AVX512_maskable, - EVEX, T8PD, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fp14_p_vl_all opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp14_p, EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp14_p, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; - - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp14_p, - EVEX_V128, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp14_p, - EVEX_V256, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp14_p, - EVEX_V128, VEX_W, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp14_p, - EVEX_V256, VEX_W, EVEX_CD8<64, CD8VF>; - } -} - -defm VRSQRT14 : avx512_fp14_p_vl_all<0x4E, "vrsqrt14", X86rsqrt14, SchedWriteFRsqrt>; -defm VRCP14 : avx512_fp14_p_vl_all<0x4C, "vrcp14", X86rcp14, SchedWriteFRcp>; - -/// avx512_fp28_s rcp28ss, rcp28sd, rsqrt28ss, rsqrt28sd -multiclass avx512_fp28_s opc, string OpcodeStr,X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in { - defm r : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rb : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - - defm m : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_eri_s opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched> { - defm SSZ : avx512_fp28_s, - EVEX_CD8<32, CD8VT1>; - defm SDZ : avx512_fp28_s, - EVEX_CD8<64, CD8VT1>, VEX_W; -} - -let Predicates = [HasERI] in { - defm VRCP28 : avx512_eri_s<0xCB, "vrcp28", X86rcp28s, SchedWriteFRcp.Scl>, - T8PD, EVEX_4V; - defm VRSQRT28 : avx512_eri_s<0xCD, "vrsqrt28", X86rsqrt28s, - SchedWriteFRsqrt.Scl>, T8PD, EVEX_4V; -} - -defm VGETEXP : avx512_eri_s<0x43, "vgetexp", X86fgetexpRnds, - SchedWriteFRnd.Scl>, T8PD, EVEX_4V; -/// avx512_fp28_p rcp28ps, rcp28pd, rsqrt28ps, rsqrt28pd - -multiclass avx512_fp28_p opc, string OpcodeStr, X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in { - defm r : AVX512_maskable, - Sched<[sched]>; - - defm m : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - - defm mb : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} -multiclass avx512_fp28_p_round opc, string OpcodeStr, X86VectorVTInfo _, - SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = _.ExeDomain in - defm rb : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_eri opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm PSZ : avx512_fp28_p, - avx512_fp28_p_round, - T8PD, EVEX_V512, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_fp28_p, - avx512_fp28_p_round, - T8PD, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_fp_unaryop_packed opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_fp28_p, - EVEX_V128, T8PD, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_fp28_p, - EVEX_V256, T8PD, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_fp28_p, - EVEX_V128, VEX_W, T8PD, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_fp28_p, - EVEX_V256, VEX_W, T8PD, EVEX_CD8<64, CD8VF>; - } -} - -let Predicates = [HasERI] in { - defm VRSQRT28 : avx512_eri<0xCC, "vrsqrt28", X86rsqrt28, SchedWriteFRsqrt>, EVEX; - defm VRCP28 : avx512_eri<0xCA, "vrcp28", X86rcp28, SchedWriteFRcp>, EVEX; - defm VEXP2 : avx512_eri<0xC8, "vexp2", X86exp2, SchedWriteFAdd>, EVEX; -} -defm VGETEXP : avx512_eri<0x42, "vgetexp", X86fgetexpRnd, SchedWriteFRnd>, - avx512_fp_unaryop_packed<0x42, "vgetexp", X86fgetexpRnd, - SchedWriteFRnd>, EVEX; - -multiclass avx512_sqrt_packed_round opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in - defm rb: AVX512_maskable, - EVEX, EVEX_B, EVEX_RC, Sched<[sched]>; -} - -multiclass avx512_sqrt_packed opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in { - defm r: AVX512_maskable, EVEX, - Sched<[sched]>; - defm m: AVX512_maskable, EVEX, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb: AVX512_maskable, - EVEX, EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_sqrt_packed_all opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm PSZ : avx512_sqrt_packed, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_sqrt_packed, - EVEX_V512, VEX_W, PD, EVEX_CD8<64, CD8VF>; - // Define only if AVX512VL feature is present. - let Predicates = [HasVLX] in { - defm PSZ128 : avx512_sqrt_packed, - EVEX_V128, PS, EVEX_CD8<32, CD8VF>; - defm PSZ256 : avx512_sqrt_packed, - EVEX_V256, PS, EVEX_CD8<32, CD8VF>; - defm PDZ128 : avx512_sqrt_packed, - EVEX_V128, VEX_W, PD, EVEX_CD8<64, CD8VF>; - defm PDZ256 : avx512_sqrt_packed, - EVEX_V256, VEX_W, PD, EVEX_CD8<64, CD8VF>; - } -} - -multiclass avx512_sqrt_packed_all_round opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm PSZ : avx512_sqrt_packed_round, - EVEX_V512, PS, EVEX_CD8<32, CD8VF>; - defm PDZ : avx512_sqrt_packed_round, - EVEX_V512, VEX_W, PD, EVEX_CD8<64, CD8VF>; -} - -multiclass avx512_sqrt_scalar opc, string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo _, string Name> { - let ExeDomain = _.ExeDomain in { - defm r_Int : AVX512_maskable_scalar, - Sched<[sched]>; - defm m_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - defm rb_Int : AVX512_maskable_scalar, - EVEX_B, EVEX_RC, Sched<[sched]>; - - let isCodeGenOnly = 1, hasSideEffects = 0, Predicates=[HasAVX512] in { - def r : I, - Sched<[sched]>; - let mayLoad = 1 in - def m : I, - Sched<[sched.Folded, ReadAfterLd]>; - } - } - - let Predicates = [HasAVX512] in { - def : Pat<(_.EltVT (fsqrt _.FRC:$src)), - (!cast(Name#Zr) - (_.EltVT (IMPLICIT_DEF)), _.FRC:$src)>; - } - - let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(_.EltVT (fsqrt (load addr:$src))), - (!cast(Name#Zm) - (_.EltVT (IMPLICIT_DEF)), addr:$src)>; - } -} - -multiclass avx512_sqrt_scalar_all opc, string OpcodeStr, - X86SchedWriteSizes sched> { - defm SSZ : avx512_sqrt_scalar, - EVEX_CD8<32, CD8VT1>, EVEX_4V, XS; - defm SDZ : avx512_sqrt_scalar, - EVEX_CD8<64, CD8VT1>, EVEX_4V, XD, VEX_W; -} - -defm VSQRT : avx512_sqrt_packed_all<0x51, "vsqrt", SchedWriteFSqrtSizes>, - avx512_sqrt_packed_all_round<0x51, "vsqrt", SchedWriteFSqrtSizes>; - -defm VSQRT : avx512_sqrt_scalar_all<0x51, "vsqrt", SchedWriteFSqrtSizes>, VEX_LIG; - -multiclass avx512_rndscale_scalar opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm r_Int : AVX512_maskable_scalar, - Sched<[sched]>; - - defm rb_Int : AVX512_maskable_scalar, EVEX_B, - Sched<[sched]>; - - defm m_Int : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - - let isCodeGenOnly = 1, hasSideEffects = 0, Predicates = [HasAVX512] in { - def r : I, Sched<[sched]>; - - let mayLoad = 1 in - def m : I, Sched<[sched.Folded, ReadAfterLd]>; - } - } - - let Predicates = [HasAVX512] in { - def : Pat<(ffloor _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0x9)))>; - def : Pat<(fceil _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xa)))>; - def : Pat<(ftrunc _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xb)))>; - def : Pat<(frint _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0x4)))>; - def : Pat<(fnearbyint _.FRC:$src), - (_.EltVT (!cast(NAME##r) (_.EltVT (IMPLICIT_DEF)), - _.FRC:$src, (i32 0xc)))>; - } - - let Predicates = [HasAVX512, OptForSize] in { - def : Pat<(ffloor (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0x9)))>; - def : Pat<(fceil (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xa)))>; - def : Pat<(ftrunc (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xb)))>; - def : Pat<(frint (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0x4)))>; - def : Pat<(fnearbyint (_.ScalarLdFrag addr:$src)), - (_.EltVT (!cast(NAME##m) (_.EltVT (IMPLICIT_DEF)), - addr:$src, (i32 0xc)))>; - } -} - -defm VRNDSCALESSZ : avx512_rndscale_scalar<0x0A, "vrndscaless", - SchedWriteFRnd.Scl, f32x_info>, - AVX512AIi8Base, EVEX_4V, - EVEX_CD8<32, CD8VT1>; - -defm VRNDSCALESDZ : avx512_rndscale_scalar<0x0B, "vrndscalesd", - SchedWriteFRnd.Scl, f64x_info>, - VEX_W, AVX512AIi8Base, EVEX_4V, - EVEX_CD8<64, CD8VT1>; - -multiclass avx512_masked_scalar { - let Predicates = [BasePredicate] in { - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects Mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - (extractelt _.VT:$dst, (iPTR 0))))), - (!cast("V"#OpcPrefix#r_Intk) - _.VT:$dst, OutMask, _.VT:$src2, _.VT:$src1)>; - - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects Mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - ZeroFP))), - (!cast("V"#OpcPrefix#r_Intkz) - OutMask, _.VT:$src2, _.VT:$src1)>; - } -} - -defm : avx512_masked_scalar; -defm : avx512_masked_scalar; - -multiclass avx512_masked_scalar_imm ImmV, Predicate BasePredicate> { - let Predicates = [BasePredicate] in { - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects VK1WM:$mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), - (extractelt _.VT:$dst, (iPTR 0))))), - (!cast("V"#OpcPrefix#Zr_Intk) - _.VT:$dst, VK1WM:$mask, _.VT:$src1, _.VT:$src2, (i32 ImmV))>; - - def : Pat<(Move _.VT:$src1, (scalar_to_vector (X86selects VK1WM:$mask, - (OpNode (extractelt _.VT:$src2, (iPTR 0))), ZeroFP))), - (!cast("V"#OpcPrefix#Zr_Intkz) - VK1WM:$mask, _.VT:$src1, _.VT:$src2, (i32 ImmV))>; - } -} - -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; -defm : avx512_masked_scalar_imm; - - -//------------------------------------------------- -// Integer truncate and extend operations -//------------------------------------------------- - -multiclass avx512_trunc_common opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo SrcInfo, - X86VectorVTInfo DestInfo, X86MemOperand x86memop> { - let ExeDomain = DestInfo.ExeDomain in - defm rr : AVX512_maskable, - EVEX, T8XS, Sched<[sched]>; - - let mayStore = 1, hasSideEffects = 0, ExeDomain = DestInfo.ExeDomain in { - def mr : AVX512XS8I, - EVEX, Sched<[sched.Folded]>; - - def mrk : AVX512XS8I, - EVEX, EVEX_K, Sched<[sched.Folded]>, NotMemoryFoldable; - }//mayStore = 1, hasSideEffects = 0 -} - -multiclass avx512_trunc_mr_lowering { - - def : Pat<(truncFrag (SrcInfo.VT SrcInfo.RC:$src), addr:$dst), - (!cast(Name#SrcInfo.ZSuffix##mr) - addr:$dst, SrcInfo.RC:$src)>; - - def : Pat<(mtruncFrag addr:$dst, SrcInfo.KRCWM:$mask, - (SrcInfo.VT SrcInfo.RC:$src)), - (!cast(Name#SrcInfo.ZSuffix##mrk) - addr:$dst, SrcInfo.KRCWM:$mask, SrcInfo.RC:$src)>; -} - -multiclass avx512_trunc opc, string OpcodeStr, SDNode OpNode128, - SDNode OpNode256, SDNode OpNode512, X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTSrcInfo, - X86VectorVTInfo DestInfoZ128, - X86VectorVTInfo DestInfoZ256, X86VectorVTInfo DestInfoZ, - X86MemOperand x86memopZ128, X86MemOperand x86memopZ256, - X86MemOperand x86memopZ, PatFrag truncFrag, - PatFrag mtruncFrag, Predicate prd = HasAVX512>{ - - let Predicates = [HasVLX, prd] in { - defm Z128: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V128; - - defm Z256: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V256; - } - let Predicates = [prd] in - defm Z: avx512_trunc_common, - avx512_trunc_mr_lowering, EVEX_V512; -} - -multiclass avx512_trunc_qb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<8, CD8VO>; -} - -multiclass avx512_trunc_qw opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VQ>; -} - -multiclass avx512_trunc_qd opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<32, CD8VH>; -} - -multiclass avx512_trunc_db opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<8, CD8VQ>; -} - -multiclass avx512_trunc_dw opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VH>; -} - -multiclass avx512_trunc_wb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag StoreNode, - PatFrag MaskedStoreNode, SDNode InVecNode = OpNode> { - defm NAME: avx512_trunc, EVEX_CD8<16, CD8VH>; -} - -defm VPMOVQB : avx512_trunc_qb<0x32, "vpmovqb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSQB : avx512_trunc_qb<0x22, "vpmovsqb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSQB : avx512_trunc_qb<0x12, "vpmovusqb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -defm VPMOVQW : avx512_trunc_qw<0x34, "vpmovqw", trunc, WriteShuffle256, - truncstorevi16, masked_truncstorevi16, X86vtrunc>; -defm VPMOVSQW : avx512_trunc_qw<0x24, "vpmovsqw", X86vtruncs, WriteShuffle256, - truncstore_s_vi16, masked_truncstore_s_vi16>; -defm VPMOVUSQW : avx512_trunc_qw<0x14, "vpmovusqw", X86vtruncus, WriteShuffle256, - truncstore_us_vi16, masked_truncstore_us_vi16>; - -defm VPMOVQD : avx512_trunc_qd<0x35, "vpmovqd", trunc, WriteShuffle256, - truncstorevi32, masked_truncstorevi32, X86vtrunc>; -defm VPMOVSQD : avx512_trunc_qd<0x25, "vpmovsqd", X86vtruncs, WriteShuffle256, - truncstore_s_vi32, masked_truncstore_s_vi32>; -defm VPMOVUSQD : avx512_trunc_qd<0x15, "vpmovusqd", X86vtruncus, WriteShuffle256, - truncstore_us_vi32, masked_truncstore_us_vi32>; - -defm VPMOVDB : avx512_trunc_db<0x31, "vpmovdb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSDB : avx512_trunc_db<0x21, "vpmovsdb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSDB : avx512_trunc_db<0x11, "vpmovusdb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -defm VPMOVDW : avx512_trunc_dw<0x33, "vpmovdw", trunc, WriteShuffle256, - truncstorevi16, masked_truncstorevi16, X86vtrunc>; -defm VPMOVSDW : avx512_trunc_dw<0x23, "vpmovsdw", X86vtruncs, WriteShuffle256, - truncstore_s_vi16, masked_truncstore_s_vi16>; -defm VPMOVUSDW : avx512_trunc_dw<0x13, "vpmovusdw", X86vtruncus, WriteShuffle256, - truncstore_us_vi16, masked_truncstore_us_vi16>; - -defm VPMOVWB : avx512_trunc_wb<0x30, "vpmovwb", trunc, WriteShuffle256, - truncstorevi8, masked_truncstorevi8, X86vtrunc>; -defm VPMOVSWB : avx512_trunc_wb<0x20, "vpmovswb", X86vtruncs, WriteShuffle256, - truncstore_s_vi8, masked_truncstore_s_vi8>; -defm VPMOVUSWB : avx512_trunc_wb<0x10, "vpmovuswb", X86vtruncus, WriteShuffle256, - truncstore_us_vi8, masked_truncstore_us_vi8>; - -let Predicates = [HasAVX512, NoVLX] in { -def: Pat<(v8i16 (trunc (v8i32 VR256X:$src))), - (v8i16 (EXTRACT_SUBREG - (v16i16 (VPMOVDWZrr (v16i32 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm)))), sub_xmm))>; -def: Pat<(v4i32 (trunc (v4i64 VR256X:$src))), - (v4i32 (EXTRACT_SUBREG - (v8i32 (VPMOVQDZrr (v8i64 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm)))), sub_xmm))>; -} - -let Predicates = [HasBWI, NoVLX] in { -def: Pat<(v16i8 (trunc (v16i16 VR256X:$src))), - (v16i8 (EXTRACT_SUBREG (VPMOVWBZrr (v32i16 (INSERT_SUBREG (IMPLICIT_DEF), - VR256X:$src, sub_ymm))), sub_xmm))>; -} - -multiclass WriteShuffle256_common opc, string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo DestInfo, X86VectorVTInfo SrcInfo, - X86MemOperand x86memop, PatFrag LdFrag, SDNode OpNode>{ - let ExeDomain = DestInfo.ExeDomain in { - defm rr : AVX512_maskable, - EVEX, Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, Sched<[sched.Folded]>; - } -} - -multiclass WriteShuffle256_BW opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasBWI] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasBWI] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VH>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_BD opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VQ>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_BQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi8")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<8, CD8VO>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_WD opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi16")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<16, CD8VH>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_WQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi16")> { - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V128, VEX_WIG; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<16, CD8VQ>, T8PD, EVEX_V512, VEX_WIG; - } -} - -multiclass WriteShuffle256_DQ opc, string OpcodeStr, - SDNode OpNode, SDNode InVecNode, string ExtTy, - X86FoldableSchedWrite sched, PatFrag LdFrag = !cast(ExtTy#"extloadvi32")> { - - let Predicates = [HasVLX, HasAVX512] in { - defm Z128: WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V128; - - defm Z256: WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V256; - } - let Predicates = [HasAVX512] in { - defm Z : WriteShuffle256_common, - EVEX_CD8<32, CD8VH>, T8PD, EVEX_V512; - } -} - -defm VPMOVZXBW : WriteShuffle256_BW<0x30, "vpmovzxbw", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXBD : WriteShuffle256_BD<0x31, "vpmovzxbd", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXBQ : WriteShuffle256_BQ<0x32, "vpmovzxbq", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXWD : WriteShuffle256_WD<0x33, "vpmovzxwd", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXWQ : WriteShuffle256_WQ<0x34, "vpmovzxwq", X86vzext, zext_invec, "z", WriteShuffle256>; -defm VPMOVZXDQ : WriteShuffle256_DQ<0x35, "vpmovzxdq", X86vzext, zext_invec, "z", WriteShuffle256>; - -defm VPMOVSXBW: WriteShuffle256_BW<0x20, "vpmovsxbw", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXBD: WriteShuffle256_BD<0x21, "vpmovsxbd", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXBQ: WriteShuffle256_BQ<0x22, "vpmovsxbq", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXWD: WriteShuffle256_WD<0x23, "vpmovsxwd", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXWQ: WriteShuffle256_WQ<0x24, "vpmovsxwq", X86vsext, sext_invec, "s", WriteShuffle256>; -defm VPMOVSXDQ: WriteShuffle256_DQ<0x25, "vpmovsxdq", X86vsext, sext_invec, "s", WriteShuffle256>; - - -multiclass AVX512_pmovx_patterns { - // 128-bit patterns - let Predicates = [HasVLX, HasBWI] in { - def : Pat<(v8i16 (InVecOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (bc_v16i8 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - def : Pat<(v8i16 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ128rm) addr:$src)>; - } - let Predicates = [HasVLX] in { - def : Pat<(v4i32 (InVecOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v16i8 (v4i32 (scalar_to_vector (extloadi32i16 addr:$src)))))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ128rm) addr:$src)>; - - def : Pat<(v4i32 (InVecOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v8i16 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - def : Pat<(v4i32 (InVecOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v8i16 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v8i16 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ128rm) addr:$src)>; - - def : Pat<(v2i64 (InVecOp (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v4i32 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - def : Pat<(v2i64 (InVecOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ128rm) addr:$src)>; - } - // 256-bit patterns - let Predicates = [HasVLX, HasBWI] in { - def : Pat<(v16i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWZ256rm) addr:$src)>; - } - let Predicates = [HasVLX] in { - def : Pat<(v8i32 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZ256rm) addr:$src)>; - - def : Pat<(v8i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZ256rm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQZ256rm) addr:$src)>; - } - // 512-bit patterns - let Predicates = [HasBWI] in { - def : Pat<(v32i16 (ExtOp (bc_v32i8 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#BWZrm) addr:$src)>; - } - let Predicates = [HasAVX512] in { - def : Pat<(v16i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BQZrm) addr:$src)>; - def : Pat<(v8i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQZrm) addr:$src)>; - - def : Pat<(v16i32 (ExtOp (bc_v16i16 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#WDZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQZrm) addr:$src)>; - - def : Pat<(v8i64 (ExtOp (bc_v8i32 (loadv4i64 addr:$src)))), - (!cast(OpcPrefix#DQZrm) addr:$src)>; - } -} - -defm : AVX512_pmovx_patterns<"VPMOVSX", X86vsext, sext_invec>; -defm : AVX512_pmovx_patterns<"VPMOVZX", X86vzext, zext_invec>; - -//===----------------------------------------------------------------------===// -// GATHER - SCATTER Operations - -// FIXME: Improve scheduling of gather/scatter instructions. -multiclass avx512_gather opc, string OpcodeStr, X86VectorVTInfo _, - X86MemOperand memop, PatFrag GatherNode, - RegisterClass MaskRC = _.KRCWM> { - let Constraints = "@earlyclobber $dst, $src1 = $dst, $mask = $mask_wb", - ExeDomain = _.ExeDomain in - def rm : AVX5128I, EVEX, EVEX_K, - EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteLoad]>; -} - -multiclass avx512_gather_q_pd dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_gather, EVEX_V512, VEX_W; - defm NAME##Q##SUFF##Z: avx512_gather, EVEX_V512, VEX_W; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_gather, EVEX_V256, VEX_W; - defm NAME##Q##SUFF##Z256: avx512_gather, EVEX_V256, VEX_W; - defm NAME##D##SUFF##Z128: avx512_gather, EVEX_V128, VEX_W; - defm NAME##Q##SUFF##Z128: avx512_gather, EVEX_V128, VEX_W; -} -} - -multiclass avx512_gather_d_ps dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_gather, EVEX_V512; - defm NAME##Q##SUFF##Z: avx512_gather, EVEX_V512; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_gather, EVEX_V256; - defm NAME##Q##SUFF##Z256: avx512_gather, EVEX_V256; - defm NAME##D##SUFF##Z128: avx512_gather, EVEX_V128; - defm NAME##Q##SUFF##Z128: avx512_gather, - EVEX_V128; -} -} - - -defm VGATHER : avx512_gather_q_pd<0x92, 0x93, avx512vl_f64_info, "vgather", "PD">, - avx512_gather_d_ps<0x92, 0x93, avx512vl_f32_info, "vgather", "PS">; - -defm VPGATHER : avx512_gather_q_pd<0x90, 0x91, avx512vl_i64_info, "vpgather", "Q">, - avx512_gather_d_ps<0x90, 0x91, avx512vl_i32_info, "vpgather", "D">; - -multiclass avx512_scatter opc, string OpcodeStr, X86VectorVTInfo _, - X86MemOperand memop, PatFrag ScatterNode, - RegisterClass MaskRC = _.KRCWM> { - -let mayStore = 1, Constraints = "$mask = $mask_wb", ExeDomain = _.ExeDomain in - - def mr : AVX5128I, - EVEX, EVEX_K, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[WriteStore]>; -} - -multiclass avx512_scatter_q_pd dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_scatter, EVEX_V512, VEX_W; - defm NAME##Q##SUFF##Z: avx512_scatter, EVEX_V512, VEX_W; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_scatter, EVEX_V256, VEX_W; - defm NAME##Q##SUFF##Z256: avx512_scatter, EVEX_V256, VEX_W; - defm NAME##D##SUFF##Z128: avx512_scatter, EVEX_V128, VEX_W; - defm NAME##Q##SUFF##Z128: avx512_scatter, EVEX_V128, VEX_W; -} -} - -multiclass avx512_scatter_d_ps dopc, bits<8> qopc, - AVX512VLVectorVTInfo _, string OpcodeStr, string SUFF> { - defm NAME##D##SUFF##Z: avx512_scatter, EVEX_V512; - defm NAME##Q##SUFF##Z: avx512_scatter, EVEX_V512; -let Predicates = [HasVLX] in { - defm NAME##D##SUFF##Z256: avx512_scatter, EVEX_V256; - defm NAME##Q##SUFF##Z256: avx512_scatter, EVEX_V256; - defm NAME##D##SUFF##Z128: avx512_scatter, EVEX_V128; - defm NAME##Q##SUFF##Z128: avx512_scatter, - EVEX_V128; -} -} - -defm VSCATTER : avx512_scatter_q_pd<0xA2, 0xA3, avx512vl_f64_info, "vscatter", "PD">, - avx512_scatter_d_ps<0xA2, 0xA3, avx512vl_f32_info, "vscatter", "PS">; - -defm VPSCATTER : avx512_scatter_q_pd<0xA0, 0xA1, avx512vl_i64_info, "vpscatter", "Q">, - avx512_scatter_d_ps<0xA0, 0xA1, avx512vl_i32_info, "vpscatter", "D">; - -// prefetch -multiclass avx512_gather_scatter_prefetch opc, Format F, string OpcodeStr, - RegisterClass KRC, X86MemOperand memop> { - let Predicates = [HasPFI], mayLoad = 1, mayStore = 1 in - def m : AVX5128I, - EVEX, EVEX_K, Sched<[WriteLoad]>; -} - -defm VGATHERPF0DPS: avx512_gather_scatter_prefetch<0xC6, MRM1m, "vgatherpf0dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF0QPS: avx512_gather_scatter_prefetch<0xC7, MRM1m, "vgatherpf0qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF0DPD: avx512_gather_scatter_prefetch<0xC6, MRM1m, "vgatherpf0dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF0QPD: avx512_gather_scatter_prefetch<0xC7, MRM1m, "vgatherpf0qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF1DPS: avx512_gather_scatter_prefetch<0xC6, MRM2m, "vgatherpf1dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF1QPS: avx512_gather_scatter_prefetch<0xC7, MRM2m, "vgatherpf1qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VGATHERPF1DPD: avx512_gather_scatter_prefetch<0xC6, MRM2m, "vgatherpf1dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VGATHERPF1QPD: avx512_gather_scatter_prefetch<0xC7, MRM2m, "vgatherpf1qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF0DPS: avx512_gather_scatter_prefetch<0xC6, MRM5m, "vscatterpf0dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF0QPS: avx512_gather_scatter_prefetch<0xC7, MRM5m, "vscatterpf0qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF0DPD: avx512_gather_scatter_prefetch<0xC6, MRM5m, "vscatterpf0dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF0QPD: avx512_gather_scatter_prefetch<0xC7, MRM5m, "vscatterpf0qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF1DPS: avx512_gather_scatter_prefetch<0xC6, MRM6m, "vscatterpf1dps", - VK16WM, vz512mem>, EVEX_V512, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF1QPS: avx512_gather_scatter_prefetch<0xC7, MRM6m, "vscatterpf1qps", - VK8WM, vz256mem>, EVEX_V512, EVEX_CD8<64, CD8VT1>; - -defm VSCATTERPF1DPD: avx512_gather_scatter_prefetch<0xC6, MRM6m, "vscatterpf1dpd", - VK8WM, vy512xmem>, EVEX_V512, VEX_W, EVEX_CD8<32, CD8VT1>; - -defm VSCATTERPF1QPD: avx512_gather_scatter_prefetch<0xC7, MRM6m, "vscatterpf1qpd", - VK8WM, vz512mem>, EVEX_V512, VEX_W, EVEX_CD8<64, CD8VT1>; - -multiclass cvt_by_vec_width opc, X86VectorVTInfo Vec, string OpcodeStr > { -def rr : AVX512XS8I, - EVEX, Sched<[WriteMove]>; // TODO - WriteVecTrunc? -} - -multiclass cvt_mask_by_elt_width opc, AVX512VLVectorVTInfo VTInfo, - string OpcodeStr, Predicate prd> { -let Predicates = [prd] in - defm Z : cvt_by_vec_width, EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : cvt_by_vec_width, EVEX_V256; - defm Z128 : cvt_by_vec_width, EVEX_V128; - } -} - -defm VPMOVM2B : cvt_mask_by_elt_width<0x28, avx512vl_i8_info, "vpmovm2" , HasBWI>; -defm VPMOVM2W : cvt_mask_by_elt_width<0x28, avx512vl_i16_info, "vpmovm2", HasBWI> , VEX_W; -defm VPMOVM2D : cvt_mask_by_elt_width<0x38, avx512vl_i32_info, "vpmovm2", HasDQI>; -defm VPMOVM2Q : cvt_mask_by_elt_width<0x38, avx512vl_i64_info, "vpmovm2", HasDQI> , VEX_W; - -multiclass convert_vector_to_mask_common opc, X86VectorVTInfo _, string OpcodeStr > { - def rr : AVX512XS8I, - EVEX, Sched<[WriteMove]>; -} - -// Use 512bit version to implement 128/256 bit in case NoVLX. -multiclass convert_vector_to_mask_lowering { - - def : Pat<(_.KVT (X86pcmpgtm _.ImmAllZerosV, (_.VT _.RC:$src))), - (_.KVT (COPY_TO_REGCLASS - (!cast(Name#"Zrr") - (INSERT_SUBREG (ExtendInfo.VT (IMPLICIT_DEF)), - _.RC:$src, _.SubRegIdx)), - _.KRC))>; -} - -multiclass avx512_convert_vector_to_mask opc, string OpcodeStr, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : convert_vector_to_mask_common , - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : convert_vector_to_mask_common, - EVEX_V256; - defm Z128 : convert_vector_to_mask_common, - EVEX_V128; - } - let Predicates = [prd, NoVLX] in { - defm Z256_Alt : convert_vector_to_mask_lowering; - defm Z128_Alt : convert_vector_to_mask_lowering; - } -} - -defm VPMOVB2M : avx512_convert_vector_to_mask<0x29, "vpmovb2m", - avx512vl_i8_info, HasBWI>; -defm VPMOVW2M : avx512_convert_vector_to_mask<0x29, "vpmovw2m", - avx512vl_i16_info, HasBWI>, VEX_W; -defm VPMOVD2M : avx512_convert_vector_to_mask<0x39, "vpmovd2m", - avx512vl_i32_info, HasDQI>; -defm VPMOVQ2M : avx512_convert_vector_to_mask<0x39, "vpmovq2m", - avx512vl_i64_info, HasDQI>, VEX_W; - -// Patterns for handling sext from a mask register to v16i8/v16i16 when DQI -// is available, but BWI is not. We can't handle this in lowering because -// a target independent DAG combine likes to combine sext and trunc. -let Predicates = [HasDQI, NoBWI] in { - def : Pat<(v16i8 (sext (v16i1 VK16:$src))), - (VPMOVDBZrr (v16i32 (VPMOVM2DZrr VK16:$src)))>; - def : Pat<(v16i16 (sext (v16i1 VK16:$src))), - (VPMOVDWZrr (v16i32 (VPMOVM2DZrr VK16:$src)))>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - COMPRESS and EXPAND -// - -multiclass compress_by_vec_width_common opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - defm rr : AVX512_maskable, AVX5128IBase, - Sched<[sched]>; - - let mayStore = 1, hasSideEffects = 0 in - def mr : AVX5128I, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded]>; - - def mrk : AVX5128I, - EVEX_K, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded]>; -} - -multiclass compress_by_vec_width_lowering { - def : Pat<(X86mCompressingStore addr:$dst, _.KRCWM:$mask, - (_.VT _.RC:$src)), - (!cast(Name#_.ZSuffix##mrk) - addr:$dst, _.KRCWM:$mask, _.RC:$src)>; -} - -multiclass compress_by_elt_width opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in - defm Z : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V512; - - let Predicates = [Pred, HasVLX] in { - defm Z256 : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V256; - defm Z128 : compress_by_vec_width_common, - compress_by_vec_width_lowering, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPCOMPRESS? -defm VPCOMPRESSD : compress_by_elt_width <0x8B, "vpcompressd", WriteVarShuffle256, - avx512vl_i32_info>, EVEX, NotMemoryFoldable; -defm VPCOMPRESSQ : compress_by_elt_width <0x8B, "vpcompressq", WriteVarShuffle256, - avx512vl_i64_info>, EVEX, VEX_W, NotMemoryFoldable; -defm VCOMPRESSPS : compress_by_elt_width <0x8A, "vcompressps", WriteVarShuffle256, - avx512vl_f32_info>, EVEX, NotMemoryFoldable; -defm VCOMPRESSPD : compress_by_elt_width <0x8A, "vcompresspd", WriteVarShuffle256, - avx512vl_f64_info>, EVEX, VEX_W, NotMemoryFoldable; - -// expand -multiclass expand_by_vec_width opc, X86VectorVTInfo _, - string OpcodeStr, X86FoldableSchedWrite sched> { - defm rr : AVX512_maskable, AVX5128IBase, - Sched<[sched]>; - - defm rm : AVX512_maskable, - AVX5128IBase, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass expand_by_vec_width_lowering { - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, undef)), - (!cast(Name#_.ZSuffix##rmkz) - _.KRCWM:$mask, addr:$src)>; - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix##rmkz) - _.KRCWM:$mask, addr:$src)>; - - def : Pat<(_.VT (X86mExpandingLoad addr:$src, _.KRCWM:$mask, - (_.VT _.RC:$src0))), - (!cast(Name#_.ZSuffix##rmk) - _.RC:$src0, _.KRCWM:$mask, addr:$src)>; -} - -multiclass expand_by_elt_width opc, string OpcodeStr, - X86FoldableSchedWrite sched, - AVX512VLVectorVTInfo VTInfo, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in - defm Z : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V512; - - let Predicates = [Pred, HasVLX] in { - defm Z256 : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V256; - defm Z128 : expand_by_vec_width, - expand_by_vec_width_lowering, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPEXPAND? -defm VPEXPANDD : expand_by_elt_width <0x89, "vpexpandd", WriteVarShuffle256, - avx512vl_i32_info>, EVEX; -defm VPEXPANDQ : expand_by_elt_width <0x89, "vpexpandq", WriteVarShuffle256, - avx512vl_i64_info>, EVEX, VEX_W; -defm VEXPANDPS : expand_by_elt_width <0x88, "vexpandps", WriteVarShuffle256, - avx512vl_f32_info>, EVEX; -defm VEXPANDPD : expand_by_elt_width <0x88, "vexpandpd", WriteVarShuffle256, - avx512vl_f64_info>, EVEX, VEX_W; - -//handle instruction reg_vec1 = op(reg_vec,imm) -// op(mem_vec,imm) -// op(broadcast(eltVt),imm) -//all instruction created with FROUND_CURRENT -multiclass avx512_unary_fp_packed_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_unary_fp_sae_packed_imm opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrib : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_common_unary_fp_sae_packed_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in { - defm Z : avx512_unary_fp_packed_imm, - avx512_unary_fp_sae_packed_imm, EVEX_V512; - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_unary_fp_packed_imm, EVEX_V128; - defm Z256 : avx512_unary_fp_packed_imm, EVEX_V256; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -// op(reg_vec2,broadcast(eltVt),imm) -//all instruction created with FROUND_CURRENT -multiclass avx512_fp_packed_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -multiclass avx512_3Op_rm_imm8 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo DestInfo, - X86VectorVTInfo SrcInfo>{ - let ExeDomain = DestInfo.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_vec,imm) -// op(reg_vec2,broadcast(eltVt),imm) -multiclass avx512_3Op_imm8 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _>: - avx512_3Op_rm_imm8{ - - let ExeDomain = _.ExeDomain in - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -//handle scalar instruction reg_vec1 = op(reg_vec2,reg_vec3,imm) -// op(reg_vec2,mem_scalar,imm) -multiclass avx512_fp_scalar_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_scalar, - Sched<[sched]>; - defm rmi : AVX512_maskable_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -//handle instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_fp_sae_packed_imm opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm rrib : AVX512_maskable, - EVEX_B, Sched<[sched]>; -} - -//handle scalar instruction reg_vec1 = op(reg_vec2,reg_vec3,imm),{sae} -multiclass avx512_fp_sae_scalar_imm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in - defm NAME#rrib : AVX512_maskable_scalar, - EVEX_B, Sched<[sched]>; -} - -multiclass avx512_common_fp_sae_packed_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in { - defm Z : avx512_fp_packed_imm, - avx512_fp_sae_packed_imm, - EVEX_V512; - - } - let Predicates = [prd, HasVLX] in { - defm Z128 : avx512_fp_packed_imm, - EVEX_V128; - defm Z256 : avx512_fp_packed_imm, - EVEX_V256; - } -} - -multiclass avx512_common_3Op_rm_imm8 opc, SDNode OpNode, string OpStr, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo DestInfo, - AVX512VLVectorVTInfo SrcInfo, Predicate Pred = HasBWI> { - let Predicates = [Pred] in { - defm Z : avx512_3Op_rm_imm8, EVEX_V512, AVX512AIi8Base, EVEX_4V; - } - let Predicates = [Pred, HasVLX] in { - defm Z128 : avx512_3Op_rm_imm8, EVEX_V128, AVX512AIi8Base, EVEX_4V; - defm Z256 : avx512_3Op_rm_imm8, EVEX_V256, AVX512AIi8Base, EVEX_4V; - } -} - -multiclass avx512_common_3Op_imm8 opc, SDNode OpNode, X86SchedWriteWidths sched, - Predicate Pred = HasAVX512> { - let Predicates = [Pred] in { - defm Z : avx512_3Op_imm8, - EVEX_V512; - } - let Predicates = [Pred, HasVLX] in { - defm Z128 : avx512_3Op_imm8, - EVEX_V128; - defm Z256 : avx512_3Op_imm8, - EVEX_V256; - } -} - -multiclass avx512_common_fp_sae_scalar_imm opc, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd> { - let Predicates = [prd] in { - defm Z : avx512_fp_scalar_imm, - avx512_fp_sae_scalar_imm; - } -} - -multiclass avx512_common_unary_fp_sae_packed_imm_all opcPs, bits<8> opcPd, SDNode OpNode, - SDNode OpNodeRnd, X86SchedWriteWidths sched, Predicate prd>{ - defm PS : avx512_common_unary_fp_sae_packed_imm, - EVEX_CD8<32, CD8VF>; - defm PD : avx512_common_unary_fp_sae_packed_imm, - EVEX_CD8<64, CD8VF>, VEX_W; -} - -defm VREDUCE : avx512_common_unary_fp_sae_packed_imm_all<"vreduce", 0x56, 0x56, - X86VReduce, X86VReduceRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, EVEX; -defm VRNDSCALE : avx512_common_unary_fp_sae_packed_imm_all<"vrndscale", 0x08, 0x09, - X86VRndScale, X86VRndScaleRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, EVEX; -defm VGETMANT : avx512_common_unary_fp_sae_packed_imm_all<"vgetmant", 0x26, 0x26, - X86VGetMant, X86VGetMantRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, EVEX; - -defm VRANGEPD : avx512_common_fp_sae_packed_imm<"vrangepd", avx512vl_f64_info, - 0x50, X86VRange, X86VRangeRnd, - SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VRANGEPS : avx512_common_fp_sae_packed_imm<"vrangeps", avx512vl_f32_info, - 0x50, X86VRange, X86VRangeRnd, - SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - -defm VRANGESD: avx512_common_fp_sae_scalar_imm<"vrangesd", - f64x_info, 0x51, X86Ranges, X86RangesRnd, SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VRANGESS: avx512_common_fp_sae_scalar_imm<"vrangess", f32x_info, - 0x51, X86Ranges, X86RangesRnd, SchedWriteFAdd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - -defm VREDUCESD: avx512_common_fp_sae_scalar_imm<"vreducesd", f64x_info, - 0x57, X86Reduces, X86ReducesRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VREDUCESS: avx512_common_fp_sae_scalar_imm<"vreducess", f32x_info, - 0x57, X86Reduces, X86ReducesRnd, SchedWriteFRnd, HasDQI>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - -defm VGETMANTSD: avx512_common_fp_sae_scalar_imm<"vgetmantsd", f64x_info, - 0x27, X86GetMants, X86GetMantsRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VGETMANTSS: avx512_common_fp_sae_scalar_imm<"vgetmantss", f32x_info, - 0x27, X86GetMants, X86GetMantsRnd, SchedWriteFRnd, HasAVX512>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; - - -multiclass AVX512_rndscale_lowering { - // Register - def : Pat<(_.VT (ffloor _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (frint _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc _.RC:$src)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rri") - _.RC:$src, (i32 0xB))>; - - // Merge-masking - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc _.RC:$src), _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrik") - _.RC:$dst, _.KRCWM:$mask, _.RC:$src, (i32 0xB))>; - - // Zero-masking - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc _.RC:$src), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rrikz") - _.KRCWM:$mask, _.RC:$src, (i32 0xB))>; - - // Load - def : Pat<(_.VT (ffloor (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xA))>; - def : Pat<(_.VT (frint (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc (_.LdFrag addr:$src))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmi") - addr:$src, (i32 0xB))>; - - // Merge-masking + load - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc (_.LdFrag addr:$src)), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Zero-masking + load - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ffloor (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fnearbyint (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (fceil (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (frint (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, (ftrunc (_.LdFrag addr:$src)), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmikz") - _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Broadcast load - def : Pat<(_.VT (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0x9))>; - def : Pat<(_.VT (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xC))>; - def : Pat<(_.VT (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xA))>; - def : Pat<(_.VT (frint (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0x4))>; - def : Pat<(_.VT (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src)))), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbi") - addr:$src, (i32 0xB))>; - - // Merge-masking + broadcast load - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (frint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.RC:$dst)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbik") - _.RC:$dst, _.KRCWM:$mask, addr:$src, (i32 0xB))>; - - // Zero-masking + broadcast load - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ffloor (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0x9))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fnearbyint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xC))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (fceil (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xA))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (frint (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0x4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (ftrunc (X86VBroadcast (_.ScalarLdFrag addr:$src))), - _.ImmAllZerosV)), - (!cast("VRNDSCALE"#Suffix#_.ZSuffix#"rmbikz") - _.KRCWM:$mask, addr:$src, (i32 0xB))>; -} - -let Predicates = [HasAVX512] in { - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; -} - -let Predicates = [HasVLX] in { - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; - defm : AVX512_rndscale_lowering; -} - -multiclass avx512_shuff_packed_128_common opc, string OpcodeStr, - X86FoldableSchedWrite sched, - X86VectorVTInfo _, - X86VectorVTInfo CastInfo, - string EVEX2VEXOvrd> { - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>, EVEX2VEXOverride; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>, - EVEX2VEXOverride; - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_shuff_packed_128 opc, - string EVEX2VEXOvrd>{ - let Predicates = [HasAVX512] in - defm Z : avx512_shuff_packed_128_common, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in - defm Z256 : avx512_shuff_packed_128_common, EVEX_V256; -} - -defm VSHUFF32X4 : avx512_shuff_packed_128<"vshuff32x4", WriteFShuffle256, - avx512vl_f32_info, avx512vl_f64_info, 0x23, "VPERM2F128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; -defm VSHUFF64X2 : avx512_shuff_packed_128<"vshuff64x2", WriteFShuffle256, - avx512vl_f64_info, avx512vl_f64_info, 0x23, "VPERM2F128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -defm VSHUFI32X4 : avx512_shuff_packed_128<"vshufi32x4", WriteFShuffle256, - avx512vl_i32_info, avx512vl_i64_info, 0x43, "VPERM2I128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; -defm VSHUFI64X2 : avx512_shuff_packed_128<"vshufi64x2", WriteFShuffle256, - avx512vl_i64_info, avx512vl_i64_info, 0x43, "VPERM2I128">, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; - -let Predicates = [HasAVX512] in { -// Provide fallback in case the load node that is used in the broadcast -// patterns above is used by additional users, which prevents the pattern -// selection. -def : Pat<(v8f64 (X86SubVBroadcast (v2f64 VR128X:$src))), - (VSHUFF64X2Zrri (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8f64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -def : Pat<(v8i64 (X86SubVBroadcast (v2i64 VR128X:$src))), - (VSHUFI64X2Zrri (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v16f32 (X86SubVBroadcast (v4f32 VR128X:$src))), - (VSHUFF32X4Zrri (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v16f32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -def : Pat<(v16i32 (X86SubVBroadcast (v4i32 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v16i32 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v32i16 (X86SubVBroadcast (v8i16 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v32i16 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; - -def : Pat<(v64i8 (X86SubVBroadcast (v16i8 VR128X:$src))), - (VSHUFI32X4Zrri (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v64i8 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - 0)>; -} - -multiclass avx512_valign opc, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - // NOTE: EVEX2VEXOverride changed back to Unset for 256-bit at the - // instantiation of this class. - let ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable, - Sched<[sched]>, EVEX2VEXOverride<"VPALIGNRrri">; - defm rmi : AVX512_maskable, - Sched<[sched.Folded, ReadAfterLd]>, - EVEX2VEXOverride<"VPALIGNRrmi">; - - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_valign_common { - let Predicates = [HasAVX512] in { - defm Z : avx512_valign<0x03, OpcodeStr, sched.ZMM, _.info512>, - AVX512AIi8Base, EVEX_4V, EVEX_V512; - } - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_valign<0x03, OpcodeStr, sched.XMM, _.info128>, - AVX512AIi8Base, EVEX_4V, EVEX_V128; - // We can't really override the 256-bit version so change it back to unset. - let EVEX2VEXOverride = ? in - defm Z256 : avx512_valign<0x03, OpcodeStr, sched.YMM, _.info256>, - AVX512AIi8Base, EVEX_4V, EVEX_V256; - } -} - -defm VALIGND: avx512_valign_common<"valignd", SchedWriteShuffle, - avx512vl_i32_info>, EVEX_CD8<32, CD8VF>; -defm VALIGNQ: avx512_valign_common<"valignq", SchedWriteShuffle, - avx512vl_i64_info>, EVEX_CD8<64, CD8VF>, - VEX_W; - -defm VPALIGNR: avx512_common_3Op_rm_imm8<0x0F, X86PAlignr, "vpalignr", - SchedWriteShuffle, avx512vl_i8_info, - avx512vl_i8_info>, EVEX_CD8<8, CD8VF>; - -// Fragments to help convert valignq into masked valignd. Or valignq/valignd -// into vpalignr. -def ValignqImm32XForm : SDNodeXFormgetZExtValue() * 2, SDLoc(N)); -}]>; -def ValignqImm8XForm : SDNodeXFormgetZExtValue() * 8, SDLoc(N)); -}]>; -def ValigndImm8XForm : SDNodeXFormgetZExtValue() * 4, SDLoc(N)); -}]>; - -multiclass avx512_vpalign_mask_lowering { - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, From.RC:$src2, - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rrik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, To.RC:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, From.RC:$src2, - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rrikz") To.KRCWM:$mask, - To.RC:$src1, To.RC:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert (To.LdFrag addr:$src2)), - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rmik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert (To.LdFrag addr:$src2)), - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rmikz") To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; -} - -multiclass avx512_vpalign_mask_lowering_mb : - avx512_vpalign_mask_lowering { - def : Pat<(From.VT (OpNode From.RC:$src1, - (bitconvert (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3)), - (!cast(OpcodeStr#"rmbi") To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert - (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3))), - To.RC:$src0)), - (!cast(OpcodeStr#"rmbik") To.RC:$src0, To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; - - def : Pat<(To.VT (vselect To.KRCWM:$mask, - (bitconvert - (From.VT (OpNode From.RC:$src1, - (bitconvert - (To.VT (X86VBroadcast - (To.ScalarLdFrag addr:$src2)))), - imm:$src3))), - To.ImmAllZerosV)), - (!cast(OpcodeStr#"rmbikz") To.KRCWM:$mask, - To.RC:$src1, addr:$src2, - (ImmXForm imm:$src3))>; -} - -let Predicates = [HasAVX512] in { - // For 512-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ", X86VAlign, v8i64_info, - v16i32_info, ValignqImm32XForm>; -} - -let Predicates = [HasVLX] in { - // For 128-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ128", X86VAlign, v2i64x_info, - v4i32x_info, ValignqImm32XForm>; - // For 256-bit we lower to the widest element type we can. So we only need - // to handle converting valignq to valignd. - defm : avx512_vpalign_mask_lowering_mb<"VALIGNDZ256", X86VAlign, v4i64x_info, - v8i32x_info, ValignqImm32XForm>; -} - -let Predicates = [HasVLX, HasBWI] in { - // We can turn 128 and 256 bit VALIGND/VALIGNQ into VPALIGNR. - defm : avx512_vpalign_mask_lowering<"VPALIGNRZ128", X86VAlign, v2i64x_info, - v16i8x_info, ValignqImm8XForm>; - defm : avx512_vpalign_mask_lowering<"VPALIGNRZ128", X86VAlign, v4i32x_info, - v16i8x_info, ValigndImm8XForm>; -} - -defm VDBPSADBW: avx512_common_3Op_rm_imm8<0x42, X86dbpsadbw, "vdbpsadbw", - SchedWritePSADBW, avx512vl_i16_info, avx512vl_i8_info>, - EVEX_CD8<8, CD8VF>, NotEVEX2VEXConvertible; - -multiclass avx512_unary_rm opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, EVEX, AVX5128IBase, - Sched<[sched]>; - - defm rm : AVX512_maskable, - EVEX, AVX5128IBase, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_unary_rmb opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> : - avx512_unary_rm { - defm rmb : AVX512_maskable, - EVEX, AVX5128IBase, EVEX_B, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded]>; -} - -multiclass avx512_unary_rm_vl opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, - AVX512VLVectorVTInfo VTInfo, Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_unary_rm, - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_unary_rm, - EVEX_V256; - defm Z128 : avx512_unary_rm, - EVEX_V128; - } -} - -multiclass avx512_unary_rmb_vl opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTInfo, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_unary_rmb, - EVEX_V512; - - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_unary_rmb, - EVEX_V256; - defm Z128 : avx512_unary_rmb, - EVEX_V128; - } -} - -multiclass avx512_unary_rm_vl_dq opc_d, bits<8> opc_q, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm Q : avx512_unary_rmb_vl, VEX_W; - defm D : avx512_unary_rmb_vl; -} - -multiclass avx512_unary_rm_vl_bw opc_b, bits<8> opc_w, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched, - Predicate prd> { - defm W : avx512_unary_rm_vl, VEX_WIG; - defm B : avx512_unary_rm_vl, VEX_WIG; -} - -multiclass avx512_unary_rm_vl_all opc_b, bits<8> opc_w, - bits<8> opc_d, bits<8> opc_q, - string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME : avx512_unary_rm_vl_dq, - avx512_unary_rm_vl_bw; -} - -defm VPABS : avx512_unary_rm_vl_all<0x1C, 0x1D, 0x1E, 0x1F, "vpabs", abs, - SchedWriteVecALU>; - -// VPABS: Use 512bit version to implement 128/256 bit in case NoVLX. -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v4i64 (abs VR256X:$src)), - (EXTRACT_SUBREG - (VPABSQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm)), - sub_ymm)>; - def : Pat<(v2i64 (abs VR128X:$src)), - (EXTRACT_SUBREG - (VPABSQZrr - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm)), - sub_xmm)>; -} - -// Use 512bit version to implement 128/256 bit. -multiclass avx512_unary_lowering { - let Predicates = [prd, NoVLX] in { - def : Pat<(_.info256.VT(OpNode _.info256.RC:$src1)), - (EXTRACT_SUBREG - (!cast(InstrStr # "Zrr") - (INSERT_SUBREG(_.info512.VT(IMPLICIT_DEF)), - _.info256.RC:$src1, - _.info256.SubRegIdx)), - _.info256.SubRegIdx)>; - - def : Pat<(_.info128.VT(OpNode _.info128.RC:$src1)), - (EXTRACT_SUBREG - (!cast(InstrStr # "Zrr") - (INSERT_SUBREG(_.info512.VT(IMPLICIT_DEF)), - _.info128.RC:$src1, - _.info128.SubRegIdx)), - _.info128.SubRegIdx)>; - } -} - -defm VPLZCNT : avx512_unary_rm_vl_dq<0x44, 0x44, "vplzcnt", ctlz, - SchedWriteVecIMul, HasCDI>; - -// FIXME: Is there a better scheduler class for VPCONFLICT? -defm VPCONFLICT : avx512_unary_rm_vl_dq<0xC4, 0xC4, "vpconflict", X86Conflict, - SchedWriteVecALU, HasCDI>; - -// VPLZCNT: Use 512bit version to implement 128/256 bit in case NoVLX. -defm : avx512_unary_lowering<"VPLZCNTQ", ctlz, avx512vl_i64_info, HasCDI>; -defm : avx512_unary_lowering<"VPLZCNTD", ctlz, avx512vl_i32_info, HasCDI>; - -//===---------------------------------------------------------------------===// -// Counts number of ones - VPOPCNTD and VPOPCNTQ -//===---------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for VPOPCNTD/VPOPCNTQ? -defm VPOPCNT : avx512_unary_rm_vl_dq<0x55, 0x55, "vpopcnt", ctpop, - SchedWriteVecALU, HasVPOPCNTDQ>; - -defm : avx512_unary_lowering<"VPOPCNTQ", ctpop, avx512vl_i64_info, HasVPOPCNTDQ>; -defm : avx512_unary_lowering<"VPOPCNTD", ctpop, avx512vl_i32_info, HasVPOPCNTDQ>; - -//===---------------------------------------------------------------------===// -// Replicate Single FP - MOVSHDUP and MOVSLDUP -//===---------------------------------------------------------------------===// - -multiclass avx512_replicate opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME: avx512_unary_rm_vl, XS; -} - -defm VMOVSHDUP : avx512_replicate<0x16, "vmovshdup", X86Movshdup, - SchedWriteFShuffle>; -defm VMOVSLDUP : avx512_replicate<0x12, "vmovsldup", X86Movsldup, - SchedWriteFShuffle>; - -//===----------------------------------------------------------------------===// -// AVX-512 - MOVDDUP -//===----------------------------------------------------------------------===// - -multiclass avx512_movddup_128 opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _> { - let ExeDomain = _.ExeDomain in { - defm rr : AVX512_maskable, EVEX, - Sched<[sched]>; - defm rm : AVX512_maskable, - EVEX, EVEX_CD8<_.EltSize, CD8VH>, - Sched<[sched.Folded]>; - } -} - -multiclass avx512_movddup_common opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTInfo> { - defm Z : avx512_unary_rm, EVEX_V512; - - let Predicates = [HasAVX512, HasVLX] in { - defm Z256 : avx512_unary_rm, EVEX_V256; - defm Z128 : avx512_movddup_128, EVEX_V128; - } -} - -multiclass avx512_movddup opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched> { - defm NAME: avx512_movddup_common, XD, VEX_W; -} - -defm VMOVDDUP : avx512_movddup<0x12, "vmovddup", X86Movddup, SchedWriteFShuffle>; - -let Predicates = [HasVLX] in { -def : Pat<(v2f64 (X86VBroadcast (loadf64 addr:$src))), - (VMOVDDUPZ128rm addr:$src)>; -def : Pat<(v2f64 (X86VBroadcast f64:$src)), - (VMOVDDUPZ128rr (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; -def : Pat<(v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (VMOVDDUPZ128rm addr:$src)>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast f64:$src)), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rrk VR128X:$src0, VK2WM:$mask, - (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast f64:$src)), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rrkz VK2WM:$mask, (v2f64 (COPY_TO_REGCLASS FR64X:$src, VR128X)))>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadf64 addr:$src))), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rmk VR128X:$src0, VK2WM:$mask, addr:$src)>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadf64 addr:$src))), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rmkz VK2WM:$mask, addr:$src)>; - -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (v2f64 VR128X:$src0)), - (VMOVDDUPZ128rmk VR128X:$src0, VK2WM:$mask, addr:$src)>; -def : Pat<(vselect (v2i1 VK2WM:$mask), (v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (bitconvert (v4i32 immAllZerosV))), - (VMOVDDUPZ128rmkz VK2WM:$mask, addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - Unpack Instructions -//===----------------------------------------------------------------------===// - -defm VUNPCKH : avx512_fp_binop_p<0x15, "vunpckh", X86Unpckh, HasAVX512, - SchedWriteFShuffleSizes, 0, 1>; -defm VUNPCKL : avx512_fp_binop_p<0x14, "vunpckl", X86Unpckl, HasAVX512, - SchedWriteFShuffleSizes>; - -defm VPUNPCKLBW : avx512_binop_rm_vl_b<0x60, "vpunpcklbw", X86Unpckl, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKHBW : avx512_binop_rm_vl_b<0x68, "vpunpckhbw", X86Unpckh, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKLWD : avx512_binop_rm_vl_w<0x61, "vpunpcklwd", X86Unpckl, - SchedWriteShuffle, HasBWI>; -defm VPUNPCKHWD : avx512_binop_rm_vl_w<0x69, "vpunpckhwd", X86Unpckh, - SchedWriteShuffle, HasBWI>; - -defm VPUNPCKLDQ : avx512_binop_rm_vl_d<0x62, "vpunpckldq", X86Unpckl, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKHDQ : avx512_binop_rm_vl_d<0x6A, "vpunpckhdq", X86Unpckh, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKLQDQ : avx512_binop_rm_vl_q<0x6C, "vpunpcklqdq", X86Unpckl, - SchedWriteShuffle, HasAVX512>; -defm VPUNPCKHQDQ : avx512_binop_rm_vl_q<0x6D, "vpunpckhqdq", X86Unpckh, - SchedWriteShuffle, HasAVX512>; - -//===----------------------------------------------------------------------===// -// AVX-512 - Extract & Insert Integer Instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_extract_elt_bw_m opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _> { - def mr : AVX512Ii8, - EVEX, EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteVecExtractSt]>; -} - -multiclass avx512_extract_elt_b { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8<0x14, MRMDestReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, - (X86pextrb (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, TAPD, Sched<[WriteVecExtract]>; - - defm NAME : avx512_extract_elt_bw_m<0x14, OpcodeStr, X86pextrb, _>, TAPD; - } -} - -multiclass avx512_extract_elt_w { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8<0xC5, MRMSrcReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, - (X86pextrw (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, PD, Sched<[WriteVecExtract]>; - - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in - def rr_REV : AVX512Ii8<0x15, MRMDestReg, (outs GR32orGR64:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - EVEX, TAPD, FoldGenData, - Sched<[WriteVecExtract]>; - - defm NAME : avx512_extract_elt_bw_m<0x15, OpcodeStr, X86pextrw, _>, TAPD; - } -} - -multiclass avx512_extract_elt_dq { - let Predicates = [HasDQI] in { - def rr : AVX512Ii8<0x16, MRMDestReg, (outs GRC:$dst), - (ins _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GRC:$dst, - (extractelt (_.VT _.RC:$src1), imm:$src2))]>, - EVEX, TAPD, Sched<[WriteVecExtract]>; - - def mr : AVX512Ii8<0x16, MRMDestMem, (outs), - (ins _.ScalarMemOp:$dst, _.RC:$src1, u8imm:$src2), - OpcodeStr#"\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(store (extractelt (_.VT _.RC:$src1), - imm:$src2),addr:$dst)]>, - EVEX, EVEX_CD8<_.EltSize, CD8VT1>, TAPD, - Sched<[WriteVecExtractSt]>; - } -} - -defm VPEXTRBZ : avx512_extract_elt_b<"vpextrb", v16i8x_info>, VEX_WIG; -defm VPEXTRWZ : avx512_extract_elt_w<"vpextrw", v8i16x_info>, VEX_WIG; -defm VPEXTRDZ : avx512_extract_elt_dq<"vpextrd", v4i32x_info, GR32>; -defm VPEXTRQZ : avx512_extract_elt_dq<"vpextrq", v2i64x_info, GR64>, VEX_W; - -multiclass avx512_insert_elt_m opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, PatFrag LdFrag> { - def rm : AVX512Ii8, - EVEX_4V, EVEX_CD8<_.EltSize, CD8VT1>, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -multiclass avx512_insert_elt_bw opc, string OpcodeStr, SDNode OpNode, - X86VectorVTInfo _, PatFrag LdFrag> { - let Predicates = [HasBWI] in { - def rr : AVX512Ii8, EVEX_4V, - Sched<[WriteVecInsert]>; - - defm NAME : avx512_insert_elt_m; - } -} - -multiclass avx512_insert_elt_dq opc, string OpcodeStr, - X86VectorVTInfo _, RegisterClass GRC> { - let Predicates = [HasDQI] in { - def rr : AVX512Ii8, - EVEX_4V, TAPD, Sched<[WriteVecInsert]>; - - defm NAME : avx512_insert_elt_m, TAPD; - } -} - -defm VPINSRBZ : avx512_insert_elt_bw<0x20, "vpinsrb", X86pinsrb, v16i8x_info, - extloadi8>, TAPD, VEX_WIG; -defm VPINSRWZ : avx512_insert_elt_bw<0xC4, "vpinsrw", X86pinsrw, v8i16x_info, - extloadi16>, PD, VEX_WIG; -defm VPINSRDZ : avx512_insert_elt_dq<0x22, "vpinsrd", v4i32x_info, GR32>; -defm VPINSRQZ : avx512_insert_elt_dq<0x22, "vpinsrq", v2i64x_info, GR64>, VEX_W; - -//===----------------------------------------------------------------------===// -// VSHUFPS - VSHUFPD Operations -//===----------------------------------------------------------------------===// - -multiclass avx512_shufp{ - defm NAME: avx512_common_3Op_imm8, - EVEX_CD8, - AVX512AIi8Base, EVEX_4V; -} - -defm VSHUFPS: avx512_shufp<"vshufps", avx512vl_i32_info, avx512vl_f32_info>, PS; -defm VSHUFPD: avx512_shufp<"vshufpd", avx512vl_i64_info, avx512vl_f64_info>, PD, VEX_W; - -//===----------------------------------------------------------------------===// -// AVX-512 - Byte shift Left/Right -//===----------------------------------------------------------------------===// - -// FIXME: The SSE/AVX names are PSLLDQri etc. - should we add the i here as well? -multiclass avx512_shift_packed opc, SDNode OpNode, Format MRMr, - Format MRMm, string OpcodeStr, - X86FoldableSchedWrite sched, X86VectorVTInfo _>{ - def rr : AVX512, - Sched<[sched]>; - def rm : AVX512, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_shift_packed_all opc, SDNode OpNode, Format MRMr, - Format MRMm, string OpcodeStr, - X86SchedWriteWidths sched, Predicate prd>{ - let Predicates = [prd] in - defm Z : avx512_shift_packed, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_shift_packed, EVEX_V256; - defm Z128 : avx512_shift_packed, EVEX_V128; - } -} -defm VPSLLDQ : avx512_shift_packed_all<0x73, X86vshldq, MRM7r, MRM7m, "vpslldq", - SchedWriteShuffle, HasBWI>, - AVX512PDIi8Base, EVEX_4V, VEX_WIG; -defm VPSRLDQ : avx512_shift_packed_all<0x73, X86vshrdq, MRM3r, MRM3m, "vpsrldq", - SchedWriteShuffle, HasBWI>, - AVX512PDIi8Base, EVEX_4V, VEX_WIG; - -multiclass avx512_psadbw_packed opc, SDNode OpNode, - string OpcodeStr, X86FoldableSchedWrite sched, - X86VectorVTInfo _dst, X86VectorVTInfo _src> { - def rr : AVX512BI, - Sched<[sched]>; - def rm : AVX512BI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass avx512_psadbw_packed_all opc, SDNode OpNode, - string OpcodeStr, X86SchedWriteWidths sched, - Predicate prd> { - let Predicates = [prd] in - defm Z : avx512_psadbw_packed, EVEX_V512; - let Predicates = [prd, HasVLX] in { - defm Z256 : avx512_psadbw_packed, EVEX_V256; - defm Z128 : avx512_psadbw_packed, EVEX_V128; - } -} - -defm VPSADBW : avx512_psadbw_packed_all<0xf6, X86psadbw, "vpsadbw", - SchedWritePSADBW, HasBWI>, EVEX_4V, VEX_WIG; - -// Transforms to swizzle an immediate to enable better matching when -// memory operand isn't in the right place. -def VPTERNLOG321_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 1/4 and 3/6. - uint8_t NewImm = Imm & 0xa5; - if (Imm & 0x02) NewImm |= 0x10; - if (Imm & 0x10) NewImm |= 0x02; - if (Imm & 0x08) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG213_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 2/4 and 3/5. - uint8_t NewImm = Imm & 0xc3; - if (Imm & 0x04) NewImm |= 0x10; - if (Imm & 0x10) NewImm |= 0x04; - if (Imm & 0x08) NewImm |= 0x20; - if (Imm & 0x20) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG132_imm8 : SDNodeXFormgetZExtValue(); - // Swap bits 1/2 and 5/6. - uint8_t NewImm = Imm & 0x99; - if (Imm & 0x02) NewImm |= 0x04; - if (Imm & 0x04) NewImm |= 0x02; - if (Imm & 0x20) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x20; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG231_imm8 : SDNodeXFormgetZExtValue(); - // Move bits 1->2, 2->4, 3->6, 4->1, 5->3, 6->5 - uint8_t NewImm = Imm & 0x81; - if (Imm & 0x02) NewImm |= 0x04; - if (Imm & 0x04) NewImm |= 0x10; - if (Imm & 0x08) NewImm |= 0x40; - if (Imm & 0x10) NewImm |= 0x02; - if (Imm & 0x20) NewImm |= 0x08; - if (Imm & 0x40) NewImm |= 0x20; - return getI8Imm(NewImm, SDLoc(N)); -}]>; -def VPTERNLOG312_imm8 : SDNodeXFormgetZExtValue(); - // Move bits 1->4, 2->1, 3->5, 4->2, 5->6, 6->3 - uint8_t NewImm = Imm & 0x81; - if (Imm & 0x02) NewImm |= 0x10; - if (Imm & 0x04) NewImm |= 0x02; - if (Imm & 0x08) NewImm |= 0x20; - if (Imm & 0x10) NewImm |= 0x04; - if (Imm & 0x20) NewImm |= 0x40; - if (Imm & 0x40) NewImm |= 0x08; - return getI8Imm(NewImm, SDLoc(N)); -}]>; - -multiclass avx512_ternlog opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - string Name>{ - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src, - AVX512AIi8Base, EVEX_4V, Sched<[sched]>; - defm rmi : AVX512_maskable_3src, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable_3src, EVEX_B, - AVX512AIi8Base, EVEX_4V, EVEX_CD8<_.EltSize, CD8VF>, - Sched<[sched.Folded, ReadAfterLd]>; - }// Constraints = "$src1 = $dst" - - // Additional patterns for matching passthru operand in other positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src3, _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rrik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, _.RC:$src3, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rrik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, _.RC:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - - // Additional patterns for matching loads in other positions. - def : Pat<(_.VT (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (OpNode _.RC:$src1, - (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching zero masking with loads in other - // positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmikz) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmikz) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching masked loads with different - // operand orders. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, - (bitconvert (_.LdFrag addr:$src3)), (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG231_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (bitconvert (_.LdFrag addr:$src3)), - _.RC:$src1, _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG312_imm8 imm:$src4))>; - - // Additional patterns for matching broadcasts in other positions. - def : Pat<(_.VT (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmbi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4))), - (!cast(Name#_.ZSuffix#rmbi) _.RC:$src1, _.RC:$src2, - addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching zero masking with broadcasts in other - // positions. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmbikz) _.RC:$src1, - _.KRCWM:$mask, _.RC:$src2, addr:$src3, - (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.ImmAllZerosV)), - (!cast(Name#_.ZSuffix#rmbikz) _.RC:$src1, - _.KRCWM:$mask, _.RC:$src2, addr:$src3, - (VPTERNLOG132_imm8 imm:$src4))>; - - // Additional patterns for matching masked broadcasts with different - // operand orders. - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG132_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src2, _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG321_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, _.RC:$src1, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - (i8 imm:$src4)), _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG213_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode _.RC:$src2, - (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src1, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG231_imm8 imm:$src4))>; - def : Pat<(_.VT (vselect _.KRCWM:$mask, - (OpNode (X86VBroadcast (_.ScalarLdFrag addr:$src3)), - _.RC:$src1, _.RC:$src2, (i8 imm:$src4)), - _.RC:$src1)), - (!cast(Name#_.ZSuffix#rmbik) _.RC:$src1, _.KRCWM:$mask, - _.RC:$src2, addr:$src3, (VPTERNLOG312_imm8 imm:$src4))>; -} - -multiclass avx512_common_ternlog { - let Predicates = [HasAVX512] in - defm Z : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.ZMM, - _.info512, NAME>, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.XMM, - _.info128, NAME>, EVEX_V128; - defm Z256 : avx512_ternlog<0x25, OpcodeStr, X86vpternlog, sched.YMM, - _.info256, NAME>, EVEX_V256; - } -} - -defm VPTERNLOGD : avx512_common_ternlog<"vpternlogd", SchedWriteVecALU, - avx512vl_i32_info>; -defm VPTERNLOGQ : avx512_common_ternlog<"vpternlogq", SchedWriteVecALU, - avx512vl_i64_info>, VEX_W; - -// Patterns to implement vnot using vpternlog instead of creating all ones -// using pcmpeq or vpternlog and then xoring with that. The value 15 is chosen -// so that the result is only dependent on src0. But we use the same source -// for all operands to prevent a false dependency. -// TODO: We should maybe have a more generalized algorithm for folding to -// vpternlog. -let Predicates = [HasAVX512] in { - def : Pat<(v8i64 (xor VR512:$src, (bc_v8i64 (v16i32 immAllOnesV)))), - (VPTERNLOGQZrri VR512:$src, VR512:$src, VR512:$src, (i8 15))>; -} - -let Predicates = [HasAVX512, NoVLX] in { - def : Pat<(v2i64 (xor VR128X:$src, (bc_v2i64 (v4i32 immAllOnesV)))), - (EXTRACT_SUBREG - (VPTERNLOGQZrri - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR128X:$src, sub_xmm), - (i8 15)), sub_xmm)>; - def : Pat<(v4i64 (xor VR256X:$src, (bc_v4i64 (v8i32 immAllOnesV)))), - (EXTRACT_SUBREG - (VPTERNLOGQZrri - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (INSERT_SUBREG (v8i64 (IMPLICIT_DEF)), VR256X:$src, sub_ymm), - (i8 15)), sub_ymm)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v2i64 (xor VR128X:$src, (bc_v2i64 (v4i32 immAllOnesV)))), - (VPTERNLOGQZ128rri VR128X:$src, VR128X:$src, VR128X:$src, (i8 15))>; - def : Pat<(v4i64 (xor VR256X:$src, (bc_v4i64 (v8i32 immAllOnesV)))), - (VPTERNLOGQZ256rri VR256X:$src, VR256X:$src, VR256X:$src, (i8 15))>; -} - -//===----------------------------------------------------------------------===// -// AVX-512 - FixupImm -//===----------------------------------------------------------------------===// - -multiclass avx512_fixupimm_packed opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo TblVT>{ - let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src, Sched<[sched]>; - defm rmi : AVX512_maskable_3src, - Sched<[sched.Folded, ReadAfterLd]>; - defm rmbi : AVX512_maskable_3src, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - } // Constraints = "$src1 = $dst" -} - -multiclass avx512_fixupimm_packed_sae opc, string OpcodeStr, - SDNode OpNode, X86FoldableSchedWrite sched, - X86VectorVTInfo _, X86VectorVTInfo TblVT>{ -let Constraints = "$src1 = $dst", ExeDomain = _.ExeDomain in { - defm rrib : AVX512_maskable_3src, - EVEX_B, Sched<[sched]>; - } -} - -multiclass avx512_fixupimm_scalar opc, string OpcodeStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo _, - X86VectorVTInfo _src3VT> { - let Constraints = "$src1 = $dst" , Predicates = [HasAVX512], - ExeDomain = _.ExeDomain in { - defm rri : AVX512_maskable_3src_scalar, Sched<[sched]>; - defm rrib : AVX512_maskable_3src_scalar, - EVEX_B, Sched<[sched.Folded, ReadAfterLd]>; - defm rmi : AVX512_maskable_3src_scalar, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass avx512_fixupimm_packed_all { - let Predicates = [HasAVX512] in - defm Z : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.ZMM, - _Vec.info512, _Tbl.info512>, - avx512_fixupimm_packed_sae<0x54, "vfixupimm", X86VFixupimm, sched.ZMM, - _Vec.info512, _Tbl.info512>, AVX512AIi8Base, - EVEX_4V, EVEX_V512; - let Predicates = [HasAVX512, HasVLX] in { - defm Z128 : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.XMM, - _Vec.info128, _Tbl.info128>, AVX512AIi8Base, - EVEX_4V, EVEX_V128; - defm Z256 : avx512_fixupimm_packed<0x54, "vfixupimm", X86VFixupimm, sched.YMM, - _Vec.info256, _Tbl.info256>, AVX512AIi8Base, - EVEX_4V, EVEX_V256; - } -} - -defm VFIXUPIMMSSZ : avx512_fixupimm_scalar<0x55, "vfixupimm", X86VFixupimmScalar, - SchedWriteFAdd.Scl, f32x_info, v4i32x_info>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<32, CD8VT1>; -defm VFIXUPIMMSDZ : avx512_fixupimm_scalar<0x55, "vfixupimm", X86VFixupimmScalar, - SchedWriteFAdd.Scl, f64x_info, v2i64x_info>, - AVX512AIi8Base, VEX_LIG, EVEX_4V, EVEX_CD8<64, CD8VT1>, VEX_W; -defm VFIXUPIMMPS : avx512_fixupimm_packed_all, EVEX_CD8<32, CD8VF>; -defm VFIXUPIMMPD : avx512_fixupimm_packed_all, EVEX_CD8<64, CD8VF>, VEX_W; - -// Patterns used to select SSE scalar fp arithmetic instructions from -// either: -// -// (1) a scalar fp operation followed by a blend -// -// The effect is that the backend no longer emits unnecessary vector -// insert instructions immediately after SSE scalar fp instructions -// like addss or mulss. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// A[0] += B[0]; -// return A; -// } -// -// Previously we generated: -// addss %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 -// -// (2) a vector packed single/double fp operation followed by a vector insert -// -// The effect is that the backend converts the packed fp instruction -// followed by a vector insert into a single SSE scalar fp instruction. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// __m128 C = A + B; -// return (__m128) {c[0], a[1], a[2], a[3]}; -// } -// -// Previously we generated: -// addps %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 - -// TODO: Some canonicalization in lowering would simplify the number of -// patterns we have to try to match. -multiclass AVX512_scalar_math_fp_patterns { - let Predicates = [HasAVX512] in { - // extracted scalar math op with insert via movss - def : Pat<(MoveNode - (_.VT VR128X:$dst), - (_.VT (scalar_to_vector - (Op (_.EltVT (extractelt (_.VT VR128X:$dst), (iPTR 0))), - _.FRC:$src)))), - (!cast("V"#OpcPrefix#Zrr_Int) _.VT:$dst, - (_.VT (COPY_TO_REGCLASS _.FRC:$src, VR128X)))>; - - // extracted masked scalar math op with insert via movss - def : Pat<(MoveNode (_.VT VR128X:$src1), - (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT - (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2), - _.FRC:$src0))), - (!cast("V"#OpcPrefix#Zrr_Intk) - (_.VT (COPY_TO_REGCLASS _.FRC:$src0, VR128X)), - VK1WM:$mask, _.VT:$src1, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)))>; - - // extracted masked scalar math op with insert via movss - def : Pat<(MoveNode (_.VT VR128X:$src1), - (scalar_to_vector - (X86selects VK1WM:$mask, - (Op (_.EltVT - (extractelt (_.VT VR128X:$src1), (iPTR 0))), - _.FRC:$src2), (_.EltVT ZeroFP)))), - (!cast("V"#OpcPrefix#Zrr_Intkz) - VK1WM:$mask, _.VT:$src1, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)))>; - } -} - -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; - -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; -defm : AVX512_scalar_math_fp_patterns; - -multiclass AVX512_scalar_unary_math_patterns { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move _.VT:$dst, - (scalar_to_vector (OpNode (extractelt _.VT:$src, 0))))), - (!cast("V"#OpcPrefix#Zr_Int) _.VT:$dst, _.VT:$src)>; - } -} - -defm : AVX512_scalar_unary_math_patterns; -defm : AVX512_scalar_unary_math_patterns; - -multiclass AVX512_scalar_unary_math_imm_patterns ImmV> { - let Predicates = [HasAVX512] in { - def : Pat<(_.VT (Move _.VT:$dst, - (scalar_to_vector (OpNode (extractelt _.VT:$src, 0))))), - (!cast("V"#OpcPrefix#Zr_Int) _.VT:$dst, _.VT:$src, - (i32 ImmV))>; - } -} - -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; -defm : AVX512_scalar_unary_math_imm_patterns; - -//===----------------------------------------------------------------------===// -// AES instructions -//===----------------------------------------------------------------------===// - -multiclass avx512_vaes Op, string OpStr, string IntPrefix> { - let Predicates = [HasVLX, HasVAES] in { - defm Z128 : AESI_binop_rm_int(IntPrefix), - loadv2i64, 0, VR128X, i128mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V128, VEX_WIG; - defm Z256 : AESI_binop_rm_int(IntPrefix##"_256"), - loadv4i64, 0, VR256X, i256mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V256, VEX_WIG; - } - let Predicates = [HasAVX512, HasVAES] in - defm Z : AESI_binop_rm_int(IntPrefix##"_512"), - loadv8i64, 0, VR512, i512mem>, - EVEX_4V, EVEX_CD8<64, CD8VF>, EVEX_V512, VEX_WIG; -} - -defm VAESENC : avx512_vaes<0xDC, "vaesenc", "int_x86_aesni_aesenc">; -defm VAESENCLAST : avx512_vaes<0xDD, "vaesenclast", "int_x86_aesni_aesenclast">; -defm VAESDEC : avx512_vaes<0xDE, "vaesdec", "int_x86_aesni_aesdec">; -defm VAESDECLAST : avx512_vaes<0xDF, "vaesdeclast", "int_x86_aesni_aesdeclast">; - -//===----------------------------------------------------------------------===// -// PCLMUL instructions - Carry less multiplication -//===----------------------------------------------------------------------===// - -let Predicates = [HasAVX512, HasVPCLMULQDQ] in -defm VPCLMULQDQZ : vpclmulqdq, - EVEX_4V, EVEX_V512, EVEX_CD8<64, CD8VF>, VEX_WIG; - -let Predicates = [HasVLX, HasVPCLMULQDQ] in { -defm VPCLMULQDQZ128 : vpclmulqdq, - EVEX_4V, EVEX_V128, EVEX_CD8<64, CD8VF>, VEX_WIG; - -defm VPCLMULQDQZ256: vpclmulqdq, EVEX_4V, EVEX_V256, - EVEX_CD8<64, CD8VF>, VEX_WIG; -} - -// Aliases -defm : vpclmulqdq_aliases<"VPCLMULQDQZ", VR512, i512mem>; -defm : vpclmulqdq_aliases<"VPCLMULQDQZ128", VR128X, i128mem>; -defm : vpclmulqdq_aliases<"VPCLMULQDQZ256", VR256X, i256mem>; - -//===----------------------------------------------------------------------===// -// VBMI2 -//===----------------------------------------------------------------------===// - -multiclass VBMI2_shift_var_rm Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> { - let Constraints = "$src1 = $dst", - ExeDomain = VTI.ExeDomain in { - defm r: AVX512_maskable_3src, - AVX512FMA3Base, Sched<[sched]>; - defm m: AVX512_maskable_3src, - AVX512FMA3Base, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -multiclass VBMI2_shift_var_rmb Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> - : VBMI2_shift_var_rm { - let Constraints = "$src1 = $dst", - ExeDomain = VTI.ExeDomain in - defm mb: AVX512_maskable_3src, - AVX512FMA3Base, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VBMI2_shift_var_rm_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTI> { - let Predicates = [HasVBMI2] in - defm Z : VBMI2_shift_var_rm, - EVEX_V512; - let Predicates = [HasVBMI2, HasVLX] in { - defm Z256 : VBMI2_shift_var_rm, - EVEX_V256; - defm Z128 : VBMI2_shift_var_rm, - EVEX_V128; - } -} - -multiclass VBMI2_shift_var_rmb_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched, AVX512VLVectorVTInfo VTI> { - let Predicates = [HasVBMI2] in - defm Z : VBMI2_shift_var_rmb, - EVEX_V512; - let Predicates = [HasVBMI2, HasVLX] in { - defm Z256 : VBMI2_shift_var_rmb, - EVEX_V256; - defm Z128 : VBMI2_shift_var_rmb, - EVEX_V128; - } -} -multiclass VBMI2_shift_var wOp, bits<8> dqOp, string Prefix, - SDNode OpNode, X86SchedWriteWidths sched> { - defm W : VBMI2_shift_var_rm_common, VEX_W, EVEX_CD8<16, CD8VF>; - defm D : VBMI2_shift_var_rmb_common, EVEX_CD8<32, CD8VF>; - defm Q : VBMI2_shift_var_rmb_common, VEX_W, EVEX_CD8<64, CD8VF>; -} - -multiclass VBMI2_shift_imm wOp, bits<8> dqOp, string Prefix, - SDNode OpNode, X86SchedWriteWidths sched> { - defm W : avx512_common_3Op_rm_imm8, - VEX_W, EVEX_CD8<16, CD8VF>; - defm D : avx512_common_3Op_imm8, AVX512AIi8Base, EVEX_4V, EVEX_CD8<32, CD8VF>; - defm Q : avx512_common_3Op_imm8, AVX512AIi8Base, EVEX_4V, EVEX_CD8<64, CD8VF>, VEX_W; -} - -// Concat & Shift -defm VPSHLDV : VBMI2_shift_var<0x70, 0x71, "vpshldv", X86VShldv, SchedWriteVecIMul>; -defm VPSHRDV : VBMI2_shift_var<0x72, 0x73, "vpshrdv", X86VShrdv, SchedWriteVecIMul>; -defm VPSHLD : VBMI2_shift_imm<0x70, 0x71, "vpshld", X86VShld, SchedWriteVecIMul>; -defm VPSHRD : VBMI2_shift_imm<0x72, 0x73, "vpshrd", X86VShrd, SchedWriteVecIMul>; - -// Compress -defm VPCOMPRESSB : compress_by_elt_width<0x63, "vpcompressb", WriteVarShuffle256, - avx512vl_i8_info, HasVBMI2>, EVEX, - NotMemoryFoldable; -defm VPCOMPRESSW : compress_by_elt_width <0x63, "vpcompressw", WriteVarShuffle256, - avx512vl_i16_info, HasVBMI2>, EVEX, VEX_W, - NotMemoryFoldable; -// Expand -defm VPEXPANDB : expand_by_elt_width <0x62, "vpexpandb", WriteVarShuffle256, - avx512vl_i8_info, HasVBMI2>, EVEX; -defm VPEXPANDW : expand_by_elt_width <0x62, "vpexpandw", WriteVarShuffle256, - avx512vl_i16_info, HasVBMI2>, EVEX, VEX_W; - -//===----------------------------------------------------------------------===// -// VNNI -//===----------------------------------------------------------------------===// - -let Constraints = "$src1 = $dst" in -multiclass VNNI_rmb Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI> { - defm r : AVX512_maskable_3src, - EVEX_4V, T8PD, Sched<[sched]>; - defm m : AVX512_maskable_3src, - EVEX_4V, EVEX_CD8<32, CD8VF>, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; - defm mb : AVX512_maskable_3src, - EVEX_4V, EVEX_CD8<32, CD8VF>, EVEX_B, - T8PD, Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VNNI_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasVNNI] in - defm Z : VNNI_rmb, EVEX_V512; - let Predicates = [HasVNNI, HasVLX] in { - defm Z256 : VNNI_rmb, EVEX_V256; - defm Z128 : VNNI_rmb, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPDP? -defm VPDPBUSD : VNNI_common<0x50, "vpdpbusd", X86Vpdpbusd, SchedWriteVecIMul>; -defm VPDPBUSDS : VNNI_common<0x51, "vpdpbusds", X86Vpdpbusds, SchedWriteVecIMul>; -defm VPDPWSSD : VNNI_common<0x52, "vpdpwssd", X86Vpdpwssd, SchedWriteVecIMul>; -defm VPDPWSSDS : VNNI_common<0x53, "vpdpwssds", X86Vpdpwssds, SchedWriteVecIMul>; - -//===----------------------------------------------------------------------===// -// Bit Algorithms -//===----------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for VPOPCNTB/VPOPCNTW? -defm VPOPCNTB : avx512_unary_rm_vl<0x54, "vpopcntb", ctpop, SchedWriteVecALU, - avx512vl_i8_info, HasBITALG>; -defm VPOPCNTW : avx512_unary_rm_vl<0x54, "vpopcntw", ctpop, SchedWriteVecALU, - avx512vl_i16_info, HasBITALG>, VEX_W; - -defm : avx512_unary_lowering<"VPOPCNTB", ctpop, avx512vl_i8_info, HasBITALG>; -defm : avx512_unary_lowering<"VPOPCNTW", ctpop, avx512vl_i16_info, HasBITALG>; - -multiclass VPSHUFBITQMB_rm { - defm rr : AVX512_maskable_cmp<0x8F, MRMSrcReg, VTI, (outs VTI.KRC:$dst), - (ins VTI.RC:$src1, VTI.RC:$src2), - "vpshufbitqmb", - "$src2, $src1", "$src1, $src2", - (X86Vpshufbitqmb (VTI.VT VTI.RC:$src1), - (VTI.VT VTI.RC:$src2))>, EVEX_4V, T8PD, - Sched<[sched]>; - defm rm : AVX512_maskable_cmp<0x8F, MRMSrcMem, VTI, (outs VTI.KRC:$dst), - (ins VTI.RC:$src1, VTI.MemOp:$src2), - "vpshufbitqmb", - "$src2, $src1", "$src1, $src2", - (X86Vpshufbitqmb (VTI.VT VTI.RC:$src1), - (VTI.VT (bitconvert (VTI.LdFrag addr:$src2))))>, - EVEX_4V, EVEX_CD8<8, CD8VF>, T8PD, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass VPSHUFBITQMB_common { - let Predicates = [HasBITALG] in - defm Z : VPSHUFBITQMB_rm, EVEX_V512; - let Predicates = [HasBITALG, HasVLX] in { - defm Z256 : VPSHUFBITQMB_rm, EVEX_V256; - defm Z128 : VPSHUFBITQMB_rm, EVEX_V128; - } -} - -// FIXME: Is there a better scheduler class for VPSHUFBITQMB? -defm VPSHUFBITQMB : VPSHUFBITQMB_common; - -//===----------------------------------------------------------------------===// -// GFNI -//===----------------------------------------------------------------------===// - -multiclass GF2P8MULB_avx512_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasGFNI, HasAVX512, HasBWI] in - defm Z : avx512_binop_rm, - EVEX_V512; - let Predicates = [HasGFNI, HasVLX, HasBWI] in { - defm Z256 : avx512_binop_rm, - EVEX_V256; - defm Z128 : avx512_binop_rm, - EVEX_V128; - } -} - -defm VGF2P8MULB : GF2P8MULB_avx512_common<0xCF, "vgf2p8mulb", X86GF2P8mulb, - SchedWriteVecALU>, - EVEX_CD8<8, CD8VF>, T8PD; - -multiclass GF2P8AFFINE_avx512_rmb_imm Op, string OpStr, SDNode OpNode, - X86FoldableSchedWrite sched, X86VectorVTInfo VTI, - X86VectorVTInfo BcstVTI> - : avx512_3Op_rm_imm8 { - let ExeDomain = VTI.ExeDomain in - defm rmbi : AVX512_maskable, EVEX_B, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass GF2P8AFFINE_avx512_common Op, string OpStr, SDNode OpNode, - X86SchedWriteWidths sched> { - let Predicates = [HasGFNI, HasAVX512, HasBWI] in - defm Z : GF2P8AFFINE_avx512_rmb_imm, EVEX_V512; - let Predicates = [HasGFNI, HasVLX, HasBWI] in { - defm Z256 : GF2P8AFFINE_avx512_rmb_imm, EVEX_V256; - defm Z128 : GF2P8AFFINE_avx512_rmb_imm, EVEX_V128; - } -} - -defm VGF2P8AFFINEINVQB : GF2P8AFFINE_avx512_common<0xCF, "vgf2p8affineinvqb", - X86GF2P8affineinvqb, SchedWriteVecIMul>, - EVEX_4V, EVEX_CD8<8, CD8VF>, VEX_W, AVX512AIi8Base; -defm VGF2P8AFFINEQB : GF2P8AFFINE_avx512_common<0xCE, "vgf2p8affineqb", - X86GF2P8affineqb, SchedWriteVecIMul>, - EVEX_4V, EVEX_CD8<8, CD8VF>, VEX_W, AVX512AIi8Base; - - -//===----------------------------------------------------------------------===// -// AVX5124FMAPS -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0, mayLoad = 1, ExeDomain = SSEPackedSingle, - Constraints = "$src1 = $dst" in { -defm V4FMADDPSrm : AVX512_maskable_3src_in_asm<0x9A, MRMSrcMem, v16f32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "v4fmaddps", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm V4FNMADDPSrm : AVX512_maskable_3src_in_asm<0xAA, MRMSrcMem, v16f32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "v4fnmaddps", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm V4FMADDSSrm : AVX512_maskable_3src_in_asm<0x9B, MRMSrcMem, f32x_info, - (outs VR128X:$dst), (ins VR128X:$src2, f128mem:$src3), - "v4fmaddss", "$src3, $src2", "$src2, $src3", - []>, EVEX_V128, EVEX_4V, T8XD, EVEX_CD8<32, CD8VF>, - Sched<[SchedWriteFMA.Scl.Folded]>; - -defm V4FNMADDSSrm : AVX512_maskable_3src_in_asm<0xAB, MRMSrcMem, f32x_info, - (outs VR128X:$dst), (ins VR128X:$src2, f128mem:$src3), - "v4fnmaddss", "$src3, $src2", "$src2, $src3", - []>, EVEX_V128, EVEX_4V, T8XD, EVEX_CD8<32, CD8VF>, - Sched<[SchedWriteFMA.Scl.Folded]>; -} - -//===----------------------------------------------------------------------===// -// AVX5124VNNIW -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0, mayLoad = 1, ExeDomain = SSEPackedInt, - Constraints = "$src1 = $dst" in { -defm VP4DPWSSDrm : AVX512_maskable_3src_in_asm<0x52, MRMSrcMem, v16i32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "vp4dpwssd", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; - -defm VP4DPWSSDSrm : AVX512_maskable_3src_in_asm<0x53, MRMSrcMem, v16i32_info, - (outs VR512:$dst), (ins VR512:$src2, f128mem:$src3), - "vp4dpwssds", "$src3, $src2", "$src2, $src3", - []>, EVEX_V512, EVEX_4V, T8XD, EVEX_CD8<32, CD8VQ>, - Sched<[SchedWriteFMA.ZMM.Folded]>; -} - diff --git a/suite/synctools/tablegen/X86/back/X86InstrArithmetic.td b/suite/synctools/tablegen/X86/back/X86InstrArithmetic.td deleted file mode 100644 index c444fa7619..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrArithmetic.td +++ /dev/null @@ -1,1338 +0,0 @@ -//===-- X86InstrArithmetic.td - Integer Arithmetic Instrs --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the integer arithmetic instructions in the X86 -// architecture. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// LEA - Load Effective Address -let SchedRW = [WriteLEA] in { -let hasSideEffects = 0 in -def LEA16r : I<0x8D, MRMSrcMem, - (outs GR16:$dst), (ins anymem:$src), - "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize16; -let isReMaterializable = 1 in -def LEA32r : I<0x8D, MRMSrcMem, - (outs GR32:$dst), (ins anymem:$src), - "lea{l}\t{$src|$dst}, {$dst|$src}", - [(set GR32:$dst, lea32addr:$src)]>, - OpSize32, Requires<[Not64BitMode]>; - -def LEA64_32r : I<0x8D, MRMSrcMem, - (outs GR32:$dst), (ins lea64_32mem:$src), - "lea{l}\t{$src|$dst}, {$dst|$src}", - [(set GR32:$dst, lea64_32addr:$src)]>, - OpSize32, Requires<[In64BitMode]>; - -let isReMaterializable = 1 in -def LEA64r : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src), - "lea{q}\t{$src|$dst}, {$dst|$src}", - [(set GR64:$dst, lea64addr:$src)]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Fixed-Register Multiplication and Division Instructions. -// - -// SchedModel info for instruction that loads one value and gets the second -// (and possibly third) value from a register. -// This is used for instructions that put the memory operands before other -// uses. -class SchedLoadReg : Sched<[SW, - // Memory operand. - ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, - // Register reads (implicit or explicit). - ReadAfterLd, ReadAfterLd]>; - -// Extra precision multiplication - -// AL is really implied by AX, but the registers in Defs must match the -// SDNode results (i8, i32). -// AL,AH = AL*GR8 -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def MUL8r : I<0xF6, MRM4r, (outs), (ins GR8:$src), "mul{b}\t$src", - // FIXME: Used for 8-bit mul, ignore result upper 8 bits. - // This probably ought to be moved to a def : Pat<> if the - // syntax can be accepted. - [(set AL, (mul AL, GR8:$src)), - (implicit EFLAGS)]>, Sched<[WriteIMul]>; -// AX,DX = AX*GR16 -let Defs = [AX,DX,EFLAGS], Uses = [AX], hasSideEffects = 0 in -def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src), - "mul{w}\t$src", - []>, OpSize16, Sched<[WriteIMul]>; -// EAX,EDX = EAX*GR32 -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in -def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src), - "mul{l}\t$src", - [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>, - OpSize32, Sched<[WriteIMul]>; -// RAX,RDX = RAX*GR64 -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 in -def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src), - "mul{q}\t$src", - [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>, - Sched<[WriteIMul64]>; -// AL,AH = AL*[mem8] -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src), - "mul{b}\t$src", - // FIXME: Used for 8-bit mul, ignore result upper 8 bits. - // This probably ought to be moved to a def : Pat<> if the - // syntax can be accepted. - [(set AL, (mul AL, (loadi8 addr:$src))), - (implicit EFLAGS)]>, SchedLoadReg; -// AX,DX = AX*[mem16] -let mayLoad = 1, hasSideEffects = 0 in { -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src), - "mul{w}\t$src", []>, OpSize16, SchedLoadReg; -// EAX,EDX = EAX*[mem32] -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src), - "mul{l}\t$src", []>, OpSize32, SchedLoadReg; -// RAX,RDX = RAX*[mem64] -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src), - "mul{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} - -let hasSideEffects = 0 in { -// AL,AH = AL*GR8 -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>, - Sched<[WriteIMul]>; -// AX,DX = AX*GR16 -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>, - OpSize16, Sched<[WriteIMul]>; -// EAX,EDX = EAX*GR32 -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>, - OpSize32, Sched<[WriteIMul]>; -// RAX,RDX = RAX*GR64 -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", []>, - Sched<[WriteIMul64]>; - -let mayLoad = 1 in { -// AL,AH = AL*[mem8] -let Defs = [AL,EFLAGS,AX], Uses = [AL] in -def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src), - "imul{b}\t$src", []>, SchedLoadReg; -// AX,DX = AX*[mem16] -let Defs = [AX,DX,EFLAGS], Uses = [AX] in -def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src), - "imul{w}\t$src", []>, OpSize16, SchedLoadReg; -// EAX,EDX = EAX*[mem32] -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in -def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src), - "imul{l}\t$src", []>, OpSize32, SchedLoadReg; -// RAX,RDX = RAX*[mem64] -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in -def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src), - "imul{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} -} // hasSideEffects - - -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst" in { - -let isCommutable = 1 in { -// X = IMUL Y, Z --> X = IMUL Z, Y -// Register-Register Signed Integer Multiply -def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2), - "imul{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, GR16:$src2))]>, - Sched<[WriteIMul]>, TB, OpSize16; -def IMUL32rr : I<0xAF, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2), - "imul{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, GR32:$src2))]>, - Sched<[WriteIMul]>, TB, OpSize32; -def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "imul{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, GR64:$src2))]>, - Sched<[WriteIMul64]>, TB; -} // isCommutable - -// Register-Memory Signed Integer Multiply -def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$src1, i16mem:$src2), - "imul{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, (loadi16 addr:$src2)))]>, - Sched<[WriteIMul.Folded, ReadAfterLd]>, TB, OpSize16; -def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "imul{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, (loadi32 addr:$src2)))]>, - Sched<[WriteIMul.Folded, ReadAfterLd]>, TB, OpSize32; -def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "imul{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, (loadi64 addr:$src2)))]>, - Sched<[WriteIMul64.Folded, ReadAfterLd]>, TB; -} // Constraints = "$src1 = $dst" - -} // Defs = [EFLAGS] - -// Surprisingly enough, these are not two address instructions! -let Defs = [EFLAGS] in { -// Register-Integer Signed Integer Multiply -def IMUL16rri : Ii16<0x69, MRMSrcReg, // GR16 = GR16*I16 - (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, imm:$src2))]>, - Sched<[WriteIMul]>, OpSize16; -def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, // GR16 = GR16*I8 - (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag GR16:$src1, i16immSExt8:$src2))]>, - Sched<[WriteIMul]>, OpSize16; -def IMUL32rri : Ii32<0x69, MRMSrcReg, // GR32 = GR32*I32 - (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, imm:$src2))]>, - Sched<[WriteIMul]>, OpSize32; -def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // GR32 = GR32*I8 - (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag GR32:$src1, i32immSExt8:$src2))]>, - Sched<[WriteIMul]>, OpSize32; -def IMUL64rri32 : RIi32S<0x69, MRMSrcReg, // GR64 = GR64*I32 - (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, i64immSExt32:$src2))]>, - Sched<[WriteIMul64]>; -def IMUL64rri8 : RIi8<0x6B, MRMSrcReg, // GR64 = GR64*I8 - (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag GR64:$src1, i64immSExt8:$src2))]>, - Sched<[WriteIMul64]>; - -// Memory-Integer Signed Integer Multiply -def IMUL16rmi : Ii16<0x69, MRMSrcMem, // GR16 = [mem16]*I16 - (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag (loadi16 addr:$src1), imm:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize16; -def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem, // GR16 = [mem16]*I8 - (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2), - "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR16:$dst, EFLAGS, - (X86smul_flag (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize16; -def IMUL32rmi : Ii32<0x69, MRMSrcMem, // GR32 = [mem32]*I32 - (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag (loadi32 addr:$src1), imm:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize32; -def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8 - (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2), - "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, EFLAGS, - (X86smul_flag (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - Sched<[WriteIMul.Folded]>, OpSize32; -def IMUL64rmi32 : RIi32S<0x69, MRMSrcMem, // GR64 = [mem64]*I32 - (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag (loadi64 addr:$src1), - i64immSExt32:$src2))]>, - Sched<[WriteIMul64.Folded]>; -def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8 - (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2), - "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR64:$dst, EFLAGS, - (X86smul_flag (loadi64 addr:$src1), - i64immSExt8:$src2))]>, - Sched<[WriteIMul64.Folded]>; -} // Defs = [EFLAGS] - -// unsigned division/remainder -let hasSideEffects = 1 in { // so that we don't speculatively execute -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH - "div{b}\t$src", []>, Sched<[WriteDiv8]>; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX - "div{w}\t$src", []>, Sched<[WriteDiv16]>, OpSize16; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in -def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX - "div{l}\t$src", []>, Sched<[WriteDiv32]>, OpSize32; -// RDX:RAX/r64 = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src), - "div{q}\t$src", []>, Sched<[WriteDiv64]>; - -let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH - "div{b}\t$src", []>, SchedLoadReg; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX - "div{w}\t$src", []>, OpSize16, SchedLoadReg; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX -def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), - "div{l}\t$src", []>, SchedLoadReg, OpSize32; -// RDX:RAX/[mem64] = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), - "div{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} - -// Signed division/remainder. -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH - "idiv{b}\t$src", []>, Sched<[WriteIDiv8]>; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX - "idiv{w}\t$src", []>, Sched<[WriteIDiv16]>, OpSize16; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in -def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX - "idiv{l}\t$src", []>, Sched<[WriteIDiv32]>, OpSize32; -// RDX:RAX/r64 = RAX,RDX -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in -def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src), - "idiv{q}\t$src", []>, Sched<[WriteIDiv64]>; - -let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in -def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH - "idiv{b}\t$src", []>, SchedLoadReg; -let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in -def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX - "idiv{w}\t$src", []>, OpSize16, SchedLoadReg; -let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX -def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), - "idiv{l}\t$src", []>, OpSize32, SchedLoadReg; -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX -def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src), - "idiv{q}\t$src", []>, SchedLoadReg, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 - -//===----------------------------------------------------------------------===// -// Two address Instructions. -// - -// unary instructions -let CodeSize = 2 in { -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1), - "neg{b}\t$dst", - [(set GR8:$dst, (ineg GR8:$src1)), - (implicit EFLAGS)]>; -def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "neg{w}\t$dst", - [(set GR16:$dst, (ineg GR16:$src1)), - (implicit EFLAGS)]>, OpSize16; -def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "neg{l}\t$dst", - [(set GR32:$dst, (ineg GR32:$src1)), - (implicit EFLAGS)]>, OpSize32; -def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst", - [(set GR64:$dst, (ineg GR64:$src1)), - (implicit EFLAGS)]>; -} // Constraints = "$src1 = $dst", SchedRW - -// Read-modify-write negate. -let SchedRW = [WriteALURMW] in { -def NEG8m : I<0xF6, MRM3m, (outs), (ins i8mem :$dst), - "neg{b}\t$dst", - [(store (ineg (loadi8 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>; -def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst), - "neg{w}\t$dst", - [(store (ineg (loadi16 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, OpSize16; -def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst), - "neg{l}\t$dst", - [(store (ineg (loadi32 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst", - [(store (ineg (loadi64 addr:$dst)), addr:$dst), - (implicit EFLAGS)]>, - Requires<[In64BitMode]>; -} // SchedRW -} // Defs = [EFLAGS] - - -// Note: NOT does not set EFLAGS! - -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1), - "not{b}\t$dst", - [(set GR8:$dst, (not GR8:$src1))]>; -def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "not{w}\t$dst", - [(set GR16:$dst, (not GR16:$src1))]>, OpSize16; -def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "not{l}\t$dst", - [(set GR32:$dst, (not GR32:$src1))]>, OpSize32; -def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src1), "not{q}\t$dst", - [(set GR64:$dst, (not GR64:$src1))]>; -} // Constraints = "$src1 = $dst", SchedRW - -let SchedRW = [WriteALURMW] in { -def NOT8m : I<0xF6, MRM2m, (outs), (ins i8mem :$dst), - "not{b}\t$dst", - [(store (not (loadi8 addr:$dst)), addr:$dst)]>; -def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst), - "not{w}\t$dst", - [(store (not (loadi16 addr:$dst)), addr:$dst)]>, - OpSize16; -def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst), - "not{l}\t$dst", - [(store (not (loadi32 addr:$dst)), addr:$dst)]>, - OpSize32; -def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst", - [(store (not (loadi64 addr:$dst)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW -} // CodeSize - -// TODO: inc/dec is slow for P4, but fast for Pentium-M. -let Defs = [EFLAGS] in { -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -let CodeSize = 2 in -def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "inc{b}\t$dst", - [(set GR8:$dst, EFLAGS, (X86inc_flag GR8:$src1))]>; -let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA. -def INC16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "inc{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86inc_flag GR16:$src1))]>, OpSize16; -def INC32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "inc{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86inc_flag GR32:$src1))]>, OpSize32; -def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86inc_flag GR64:$src1))]>; -} // isConvertibleToThreeAddress = 1, CodeSize = 2 - -// Short forms only valid in 32-bit mode. Selected during MCInst lowering. -let CodeSize = 1, hasSideEffects = 0 in { -def INC16r_alt : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1), - "inc{w}\t$dst", []>, - OpSize16, Requires<[Not64BitMode]>; -def INC32r_alt : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1), - "inc{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // CodeSize = 1, hasSideEffects = 0 -} // Constraints = "$src1 = $dst", SchedRW - -let CodeSize = 2, SchedRW = [WriteALURMW] in { -let Predicates = [UseIncDec] in { - def INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst", - [(store (add (loadi8 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>; - def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst", - [(store (add (loadi16 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>, OpSize16; - def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst", - [(store (add (loadi32 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -} // Predicates -let Predicates = [UseIncDec, In64BitMode] in { - def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst", - [(store (add (loadi64 addr:$dst), 1), addr:$dst), - (implicit EFLAGS)]>; -} // Predicates -} // CodeSize = 2, SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { -let CodeSize = 2 in -def DEC8r : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "dec{b}\t$dst", - [(set GR8:$dst, EFLAGS, (X86dec_flag GR8:$src1))]>; -let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA. -def DEC16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "dec{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86dec_flag GR16:$src1))]>, OpSize16; -def DEC32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "dec{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86dec_flag GR32:$src1))]>, OpSize32; -def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src1), "dec{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86dec_flag GR64:$src1))]>; -} // isConvertibleToThreeAddress = 1, CodeSize = 2 - -// Short forms only valid in 32-bit mode. Selected during MCInst lowering. -let CodeSize = 1, hasSideEffects = 0 in { -def DEC16r_alt : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1), - "dec{w}\t$dst", []>, - OpSize16, Requires<[Not64BitMode]>; -def DEC32r_alt : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1), - "dec{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // CodeSize = 1, hasSideEffects = 0 -} // Constraints = "$src1 = $dst", SchedRW - - -let CodeSize = 2, SchedRW = [WriteALURMW] in { -let Predicates = [UseIncDec] in { - def DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst", - [(store (add (loadi8 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>; - def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst", - [(store (add (loadi16 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>, OpSize16; - def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst", - [(store (add (loadi32 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>, OpSize32; -} // Predicates -let Predicates = [UseIncDec, In64BitMode] in { - def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst", - [(store (add (loadi64 addr:$dst), -1), addr:$dst), - (implicit EFLAGS)]>; -} // Predicates -} // CodeSize = 2, SchedRW -} // Defs = [EFLAGS] - -/// X86TypeInfo - This is a bunch of information that describes relevant X86 -/// information about value types. For example, it can tell you what the -/// register class and preferred load to use. -class X86TypeInfo { - /// VT - This is the value type itself. - ValueType VT = vt; - - /// InstrSuffix - This is the suffix used on instructions with this type. For - /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q". - string InstrSuffix = instrsuffix; - - /// RegClass - This is the register class associated with this type. For - /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64. - RegisterClass RegClass = regclass; - - /// LoadNode - This is the load node associated with this type. For - /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64. - PatFrag LoadNode = loadnode; - - /// MemOperand - This is the memory operand associated with this type. For - /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem. - X86MemOperand MemOperand = memoperand; - - /// ImmEncoding - This is the encoding of an immediate of this type. For - /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32 - /// since the immediate fields of i64 instructions is a 32-bit sign extended - /// value. - ImmType ImmEncoding = immkind; - - /// ImmOperand - This is the operand kind of an immediate of this type. For - /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 -> - /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign - /// extended value. - Operand ImmOperand = immoperand; - - /// ImmOperator - This is the operator that should be used to match an - /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32). - SDPatternOperator ImmOperator = immoperator; - - /// Imm8Operand - This is the operand kind to use for an imm8 of this type. - /// For example, i8 -> , i16 -> i16i8imm, i32 -> i32i8imm. This is - /// only used for instructions that have a sign-extended imm8 field form. - Operand Imm8Operand = imm8operand; - - /// Imm8Operator - This is the operator that should be used to match an 8-bit - /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8). - SDPatternOperator Imm8Operator = imm8operator; - - /// HasOddOpcode - This bit is true if the instruction should have an odd (as - /// opposed to even) opcode. Operations on i8 are usually even, operations on - /// other datatypes are odd. - bit HasOddOpcode = hasOddOpcode; - - /// OpSize - Selects whether the instruction needs a 0x66 prefix based on - /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this - /// to Opsize16. i32 sets this to OpSize32. - OperandSize OpSize = opSize; - - /// HasREX_WPrefix - This bit is set to true if the instruction should have - /// the 0x40 REX prefix. This is set for i64 types. - bit HasREX_WPrefix = hasREX_WPrefix; -} - -def invalid_node : SDNode<"<>", SDTIntLeaf,[],"<>">; - - -def Xi8 : X86TypeInfo; -def Xi16 : X86TypeInfo; -def Xi32 : X86TypeInfo; -def Xi64 : X86TypeInfo; - -/// ITy - This instruction base class takes the type info for the instruction. -/// Using this, it: -/// 1. Concatenates together the instruction mnemonic with the appropriate -/// suffix letter, a tab, and the arguments. -/// 2. Infers whether the instruction should have a 0x66 prefix byte. -/// 3. Infers whether the instruction should have a 0x40 REX_W prefix. -/// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations) -/// or 1 (for i16,i32,i64 operations). -class ITy opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins, - string mnemonic, string args, list pattern> - : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4}, - opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode }, - f, outs, ins, - !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> { - - // Infer instruction prefixes from type info. - let OpSize = typeinfo.OpSize; - let hasREX_WPrefix = typeinfo.HasREX_WPrefix; -} - -// BinOpRR - Instructions like "add reg, reg, reg". -class BinOpRR opcode, string mnemonic, X86TypeInfo typeinfo, - dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]>; - -// BinOpRR_F - Instructions like "cmp reg, Reg", where the pattern has -// just a EFLAGS as a result. -class BinOpRR_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode> - : BinOpRR; - -// BinOpRR_RF - Instructions like "add reg, reg, reg", where the pattern has -// both a regclass and EFLAGS as a result. -class BinOpRR_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRR; - -// BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has -// both a regclass and EFLAGS as a result, and has EFLAGS as input. -class BinOpRR_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRR; - -// BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding). -class BinOpRR_Rev opcode, string mnemonic, X86TypeInfo typeinfo, - X86FoldableSchedWrite sched = WriteALU> - : ITy, - Sched<[sched]> { - // The disassembler should know about this, but not the asmparser. - let isCodeGenOnly = 1; - let ForceDisassemble = 1; - let hasSideEffects = 0; -} - -// BinOpRR_RDD_Rev - Instructions like "adc reg, reg, reg" (reversed encoding). -class BinOpRR_RFF_Rev opcode, string mnemonic, X86TypeInfo typeinfo> - : BinOpRR_Rev; - -// BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding). -class BinOpRR_F_Rev opcode, string mnemonic, X86TypeInfo typeinfo> - : ITy, - Sched<[WriteALU]> { - // The disassembler should know about this, but not the asmparser. - let isCodeGenOnly = 1; - let ForceDisassemble = 1; - let hasSideEffects = 0; -} - -// BinOpRM - Instructions like "add reg, reg, [mem]". -class BinOpRM opcode, string mnemonic, X86TypeInfo typeinfo, - dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched.Folded, ReadAfterLd]>; - -// BinOpRM_F - Instructions like "cmp reg, [mem]". -class BinOpRM_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRM_RF - Instructions like "add reg, reg, [mem]". -class BinOpRM_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRM_RFF - Instructions like "adc reg, reg, [mem]". -class BinOpRM_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpRM; - -// BinOpRI - Instructions like "add reg, reg, imm". -class BinOpRI opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]> { - let ImmT = typeinfo.ImmEncoding; -} - -// BinOpRI_F - Instructions like "cmp reg, imm". -class BinOpRI_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI; - -// BinOpRI_RF - Instructions like "add reg, reg, imm". -class BinOpRI_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpRI; -// BinOpRI_RFF - Instructions like "adc reg, reg, imm". -class BinOpRI_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpRI; - -// BinOpRI8 - Instructions like "add reg, reg, imm8". -class BinOpRI8 opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, dag outlist, X86FoldableSchedWrite sched, list pattern> - : ITy, - Sched<[sched]> { - let ImmT = Imm8; // Always 8-bit immediate. -} - -// BinOpRI8_F - Instructions like "cmp reg, imm8". -class BinOpRI8_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpRI8_RF - Instructions like "add reg, reg, imm8". -class BinOpRI8_RF opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpRI8_RFF - Instructions like "adc reg, reg, imm8". -class BinOpRI8_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpRI8; - -// BinOpMR - Instructions like "add [mem], reg". -class BinOpMR opcode, string mnemonic, X86TypeInfo typeinfo, - list pattern> - : ITy; - -// BinOpMR_RMW - Instructions like "add [mem], reg". -class BinOpMR_RMW opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpMR, Sched<[WriteALURMW]>; - -// BinOpMR_RMW_FF - Instructions like "adc [mem], reg". -class BinOpMR_RMW_FF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode> - : BinOpMR, Sched<[WriteADCRMW]>; - -// BinOpMR_F - Instructions like "cmp [mem], reg". -class BinOpMR_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode> - : BinOpMR, - Sched<[WriteALULd, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, ReadDefault, ReadAfterLd]>; - -// BinOpMI - Instructions like "add [mem], imm". -class BinOpMI opcode, string mnemonic, X86TypeInfo typeinfo, - Format f, list pattern> - : ITy { - let ImmT = typeinfo.ImmEncoding; -} - -// BinOpMI_RMW - Instructions like "add [mem], imm". -class BinOpMI_RMW opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpMI, Sched<[WriteALURMW]>; -// BinOpMI_RMW_FF - Instructions like "adc [mem], imm". -class BinOpMI_RMW_FF opcode, string mnemonic, X86TypeInfo typeinfo, - SDNode opnode, Format f> - : BinOpMI, Sched<[WriteADCRMW]>; - -// BinOpMI_F - Instructions like "cmp [mem], imm". -class BinOpMI_F opcode, string mnemonic, X86TypeInfo typeinfo, - SDPatternOperator opnode, Format f> - : BinOpMI, - Sched<[WriteALULd]>; - -// BinOpMI8 - Instructions like "add [mem], imm8". -class BinOpMI8 pattern> - : ITy<0x82, f, typeinfo, - (outs), (ins typeinfo.MemOperand:$dst, typeinfo.Imm8Operand:$src), - mnemonic, "{$src, $dst|$dst, $src}", pattern> { - let ImmT = Imm8; // Always 8-bit immediate. -} - -// BinOpMI8_RMW - Instructions like "add [mem], imm8". -class BinOpMI8_RMW - : BinOpMI8, Sched<[WriteALURMW]>; - -// BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8". -class BinOpMI8_RMW_FF - : BinOpMI8, Sched<[WriteADCRMW]>; - -// BinOpMI8_F - Instructions like "cmp [mem], imm8". -class BinOpMI8_F - : BinOpMI8, - Sched<[WriteALULd]>; - -// BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS. -class BinOpAI opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands, X86FoldableSchedWrite sched = WriteALU> - : ITy, Sched<[sched]> { - let ImmT = typeinfo.ImmEncoding; - let Uses = [areg]; - let Defs = [areg, EFLAGS]; - let hasSideEffects = 0; -} - -// BinOpAI_RFF - Instructions like "adc %eax, %eax, imm", that implicitly define -// and use EFLAGS. -class BinOpAI_RFF opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands> - : BinOpAI { - let Uses = [areg, EFLAGS]; -} - -// BinOpAI_F - Instructions like "cmp %eax, %eax, imm", that imp-def EFLAGS. -class BinOpAI_F opcode, string mnemonic, X86TypeInfo typeinfo, - Register areg, string operands> - : BinOpAI { - let Defs = [EFLAGS]; -} - -/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is -/// defined with "(set GPR:$dst, EFLAGS, (...". -/// -/// It would be nice to get rid of the second and third argument here, but -/// tblgen can't handle dependent type references aggressively enough: PR8330 -multiclass ArithBinOp_RF BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnodeflag, SDNode opnode, - bit CommutableRR, bit ConvertibleToThreeAddress> { - let Defs = [EFLAGS] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_RF; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_RF; - def NAME#32rr : BinOpRR_RF; - def NAME#64rr : BinOpRR_RF; - } // isConvertibleToThreeAddress - } // isCommutable - - def NAME#8rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_RF; - def NAME#16rm : BinOpRM_RF; - def NAME#32rm : BinOpRM_RF; - def NAME#64rm : BinOpRM_RF; - - def NAME#8ri : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>; - def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>; - def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>; - - def NAME#16ri : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>; - def NAME#32ri : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>; - def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>; - } - } // Constraints = "$src1 = $dst" - - let mayLoad = 1, mayStore = 1 in { - def NAME#8mr : BinOpMR_RMW; - def NAME#16mr : BinOpMR_RMW; - def NAME#32mr : BinOpMR_RMW; - def NAME#64mr : BinOpMR_RMW; - } - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_RMW; - def NAME#32mi8 : BinOpMI8_RMW; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_RMW; - - def NAME#8mi : BinOpMI_RMW<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_RMW<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_RMW<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_RMW<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - let Constraints = "$src1 = $dst" in - def NAME#8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1, mayStore = 1 in - def NAME#8mi8 : BinOpMI8_RMW; - } - } // Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI; - def NAME#16i16 : BinOpAI; - def NAME#32i32 : BinOpAI; - def NAME#64i32 : BinOpAI; -} - -/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is -/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and -/// SBB. -/// -/// It would be nice to get rid of the second and third argument here, but -/// tblgen can't handle dependent type references aggressively enough: PR8330 -multiclass ArithBinOp_RFF BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnode, bit CommutableRR, - bit ConvertibleToThreeAddress> { - let Uses = [EFLAGS], Defs = [EFLAGS] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_RFF; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_RFF; - def NAME#32rr : BinOpRR_RFF; - def NAME#64rr : BinOpRR_RFF; - } // isConvertibleToThreeAddress - } // isCommutable - - def NAME#8rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_RFF_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_RFF_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_RFF; - def NAME#16rm : BinOpRM_RFF; - def NAME#32rm : BinOpRM_RFF; - def NAME#64rm : BinOpRM_RFF; - - def NAME#8ri : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>; - - def NAME#16ri : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>; - } - } // Constraints = "$src1 = $dst" - - def NAME#8mr : BinOpMR_RMW_FF; - def NAME#16mr : BinOpMR_RMW_FF; - def NAME#32mr : BinOpMR_RMW_FF; - def NAME#64mr : BinOpMR_RMW_FF; - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_RMW_FF; - def NAME#32mi8 : BinOpMI8_RMW_FF; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_RMW_FF; - - def NAME#8mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_RMW_FF<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - let Constraints = "$src1 = $dst" in - def NAME#8ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1, mayStore = 1 in - def NAME#8mi8 : BinOpMI8_RMW_FF; - } - } // Uses = [EFLAGS], Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI_RFF; - def NAME#16i16 : BinOpAI_RFF; - def NAME#32i32 : BinOpAI_RFF; - def NAME#64i32 : BinOpAI_RFF; -} - -/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is -/// defined with "(set EFLAGS, (...". It would be really nice to find a way -/// to factor this with the other ArithBinOp_*. -/// -multiclass ArithBinOp_F BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4, - string mnemonic, Format RegMRM, Format MemMRM, - SDNode opnode, - bit CommutableRR, bit ConvertibleToThreeAddress> { - let Defs = [EFLAGS] in { - let isCommutable = CommutableRR in { - def NAME#8rr : BinOpRR_F; - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - def NAME#16rr : BinOpRR_F; - def NAME#32rr : BinOpRR_F; - def NAME#64rr : BinOpRR_F; - } - } // isCommutable - - def NAME#8rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#16rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#32rr_REV : BinOpRR_F_Rev, FoldGenData; - def NAME#64rr_REV : BinOpRR_F_Rev, FoldGenData; - - def NAME#8rm : BinOpRM_F; - def NAME#16rm : BinOpRM_F; - def NAME#32rm : BinOpRM_F; - def NAME#64rm : BinOpRM_F; - - def NAME#8ri : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>; - - let isConvertibleToThreeAddress = ConvertibleToThreeAddress in { - // NOTE: These are order specific, we want the ri8 forms to be listed - // first so that they are slightly preferred to the ri forms. - def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>; - - def NAME#16ri : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>; - def NAME#32ri : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>; - def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>; - } - - def NAME#8mr : BinOpMR_F; - def NAME#16mr : BinOpMR_F; - def NAME#32mr : BinOpMR_F; - def NAME#64mr : BinOpMR_F; - - // NOTE: These are order specific, we want the mi8 forms to be listed - // first so that they are slightly preferred to the mi forms. - def NAME#16mi8 : BinOpMI8_F; - def NAME#32mi8 : BinOpMI8_F; - let Predicates = [In64BitMode] in - def NAME#64mi8 : BinOpMI8_F; - - def NAME#8mi : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>; - def NAME#16mi : BinOpMI_F<0x80, mnemonic, Xi16, opnode, MemMRM>; - def NAME#32mi : BinOpMI_F<0x80, mnemonic, Xi32, opnode, MemMRM>; - let Predicates = [In64BitMode] in - def NAME#64mi32 : BinOpMI_F<0x80, mnemonic, Xi64, opnode, MemMRM>; - - // These are for the disassembler since 0x82 opcode behaves like 0x80, but - // not in 64-bit mode. - let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1, - hasSideEffects = 0 in { - def NAME#8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, null_frag, RegMRM>; - let mayLoad = 1 in - def NAME#8mi8 : BinOpMI8_F; - } - } // Defs = [EFLAGS] - - def NAME#8i8 : BinOpAI_F; - def NAME#16i16 : BinOpAI_F; - def NAME#32i32 : BinOpAI_F; - def NAME#64i32 : BinOpAI_F; -} - - -defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m, - X86and_flag, and, 1, 0>; -defm OR : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m, - X86or_flag, or, 1, 0>; -defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m, - X86xor_flag, xor, 1, 0>; -defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m, - X86add_flag, add, 1, 1>; -let isCompare = 1 in { -defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m, - X86sub_flag, sub, 0, 0>; -} - -// Arithmetic. -defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag, - 1, 0>; -defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag, - 0, 0>; - -let isCompare = 1 in { -defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>; -} - - -//===----------------------------------------------------------------------===// -// Semantically, test instructions are similar like AND, except they don't -// generate a result. From an encoding perspective, they are very different: -// they don't have all the usual imm8 and REV forms, and are encoded into a -// different space. -def X86testpat : PatFrag<(ops node:$lhs, node:$rhs), - (X86cmp (and_su node:$lhs, node:$rhs), 0)>; - -let isCompare = 1 in { - let Defs = [EFLAGS] in { - let isCommutable = 1 in { - def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat>; - def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat>; - def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat>; - def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat>; - } // isCommutable - - def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , X86testpat>; - def TEST16mr : BinOpMR_F<0x84, "test", Xi16, X86testpat>; - def TEST32mr : BinOpMR_F<0x84, "test", Xi32, X86testpat>; - def TEST64mr : BinOpMR_F<0x84, "test", Xi64, X86testpat>; - - def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>; - def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>; - def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>; - let Predicates = [In64BitMode] in - def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>; - - def TEST8mi : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>; - def TEST16mi : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM0m>; - def TEST32mi : BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM0m>; - let Predicates = [In64BitMode] in - def TEST64mi32 : BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM0m>; - } // Defs = [EFLAGS] - - def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL, - "{$src, %al|al, $src}">; - def TEST16i16 : BinOpAI_F<0xA8, "test", Xi16, AX, - "{$src, %ax|ax, $src}">; - def TEST32i32 : BinOpAI_F<0xA8, "test", Xi32, EAX, - "{$src, %eax|eax, $src}">; - def TEST64i32 : BinOpAI_F<0xA8, "test", Xi64, RAX, - "{$src, %rax|rax, $src}">; -} // isCompare - -//===----------------------------------------------------------------------===// -// ANDN Instruction -// -multiclass bmi_andn { - def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))]>, - Sched<[WriteALU]>; - def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, EFLAGS, - (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))]>, - Sched<[WriteALULd, ReadAfterLd]>; -} - -// Complexity is reduced to give and with immediate a chance to match first. -let Predicates = [HasBMI], Defs = [EFLAGS], AddedComplexity = -6 in { - defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8PS, VEX_4V; - defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8PS, VEX_4V, VEX_W; -} - -let Predicates = [HasBMI], AddedComplexity = -6 in { - def : Pat<(and (not GR32:$src1), GR32:$src2), - (ANDN32rr GR32:$src1, GR32:$src2)>; - def : Pat<(and (not GR64:$src1), GR64:$src2), - (ANDN64rr GR64:$src1, GR64:$src2)>; - def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)), - (ANDN32rm GR32:$src1, addr:$src2)>; - def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)), - (ANDN64rm GR64:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// MULX Instruction -// -multiclass bmi_mulx { -let hasSideEffects = 0 in { - let isCommutable = 1 in - def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), - []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>; - - let mayLoad = 1 in - def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), - []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>; -} -} - -let Predicates = [HasBMI2] in { - let Uses = [EDX] in - defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem, WriteIMul>; - let Uses = [RDX] in - defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem, WriteIMul64>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// ADCX and ADOX Instructions -// -let Predicates = [HasADX], Defs = [EFLAGS], Uses = [EFLAGS], - Constraints = "$src1 = $dst", AddedComplexity = 10 in { - let SchedRW = [WriteADC] in { - def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "adcx{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86adc_flag GR32:$src1, GR32:$src2, EFLAGS))]>, T8PD; - def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "adcx{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86adc_flag GR64:$src1, GR64:$src2, EFLAGS))]>, T8PD; - - // We don't have patterns for ADOX yet. - let hasSideEffects = 0 in { - def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - - def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - } // hasSideEffects = 0 - } // SchedRW - - let mayLoad = 1, SchedRW = [WriteADCLd, ReadAfterLd] in { - def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "adcx{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, EFLAGS, - (X86adc_flag GR32:$src1, (loadi32 addr:$src2), EFLAGS))]>, - T8PD; - - def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "adcx{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, EFLAGS, - (X86adc_flag GR64:$src1, (loadi64 addr:$src2), EFLAGS))]>, - T8PD; - - // We don't have patterns for ADOX yet. - let hasSideEffects = 0 in { - def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$src1, i32mem:$src2), - "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - - def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$src1, i64mem:$src2), - "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS; - } // hasSideEffects = 0 - } // mayLoad = 1, SchedRW = [WriteADCLd] -} diff --git a/suite/synctools/tablegen/X86/back/X86InstrCMovSetCC.td b/suite/synctools/tablegen/X86/back/X86InstrCMovSetCC.td deleted file mode 100644 index eda4ba5ae6..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrCMovSetCC.td +++ /dev/null @@ -1,116 +0,0 @@ -//===-- X86InstrCMovSetCC.td - Conditional Move and SetCC --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 conditional move and set on condition -// instructions. -// -//===----------------------------------------------------------------------===// - - -// CMOV instructions. -multiclass CMOV opc, string Mnemonic, X86FoldableSchedWrite Sched, - PatLeaf CondNode> { - let Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst", - isCommutable = 1, SchedRW = [Sched] in { - def NAME#16rr - : I, - TB, OpSize16; - def NAME#32rr - : I, - TB, OpSize32; - def NAME#64rr - :RI, TB; - } - - let Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst", - SchedRW = [Sched.Folded, ReadAfterLd] in { - def NAME#16rm - : I, TB, OpSize16; - def NAME#32rm - : I, TB, OpSize32; - def NAME#64rm - :RI, TB; - } // Uses = [EFLAGS], Predicates = [HasCMov], Constraints = "$src1 = $dst" -} // end multiclass - - -// Conditional Moves. -defm CMOVO : CMOV<0x40, "cmovo" , WriteCMOV, X86_COND_O>; -defm CMOVNO : CMOV<0x41, "cmovno", WriteCMOV, X86_COND_NO>; -defm CMOVB : CMOV<0x42, "cmovb" , WriteCMOV, X86_COND_B>; -defm CMOVAE : CMOV<0x43, "cmovae", WriteCMOV, X86_COND_AE>; -defm CMOVE : CMOV<0x44, "cmove" , WriteCMOV, X86_COND_E>; -defm CMOVNE : CMOV<0x45, "cmovne", WriteCMOV, X86_COND_NE>; -defm CMOVBE : CMOV<0x46, "cmovbe", WriteCMOV2, X86_COND_BE>; -defm CMOVA : CMOV<0x47, "cmova" , WriteCMOV2, X86_COND_A>; -defm CMOVS : CMOV<0x48, "cmovs" , WriteCMOV, X86_COND_S>; -defm CMOVNS : CMOV<0x49, "cmovns", WriteCMOV, X86_COND_NS>; -defm CMOVP : CMOV<0x4A, "cmovp" , WriteCMOV, X86_COND_P>; -defm CMOVNP : CMOV<0x4B, "cmovnp", WriteCMOV, X86_COND_NP>; -defm CMOVL : CMOV<0x4C, "cmovl" , WriteCMOV, X86_COND_L>; -defm CMOVGE : CMOV<0x4D, "cmovge", WriteCMOV, X86_COND_GE>; -defm CMOVLE : CMOV<0x4E, "cmovle", WriteCMOV, X86_COND_LE>; -defm CMOVG : CMOV<0x4F, "cmovg" , WriteCMOV, X86_COND_G>; - - -// SetCC instructions. -multiclass SETCC opc, string Mnemonic, PatLeaf OpNode> { - let Uses = [EFLAGS] in { - def r : I, - TB, Sched<[WriteSETCC]>; - def m : I, - TB, Sched<[WriteSETCCStore]>; - } // Uses = [EFLAGS] -} - -defm SETO : SETCC<0x90, "seto", X86_COND_O>; // is overflow bit set -defm SETNO : SETCC<0x91, "setno", X86_COND_NO>; // is overflow bit not set -defm SETB : SETCC<0x92, "setb", X86_COND_B>; // unsigned less than -defm SETAE : SETCC<0x93, "setae", X86_COND_AE>; // unsigned greater or equal -defm SETE : SETCC<0x94, "sete", X86_COND_E>; // equal to -defm SETNE : SETCC<0x95, "setne", X86_COND_NE>; // not equal to -defm SETBE : SETCC<0x96, "setbe", X86_COND_BE>; // unsigned less than or equal -defm SETA : SETCC<0x97, "seta", X86_COND_A>; // unsigned greater than -defm SETS : SETCC<0x98, "sets", X86_COND_S>; // is signed bit set -defm SETNS : SETCC<0x99, "setns", X86_COND_NS>; // is not signed -defm SETP : SETCC<0x9A, "setp", X86_COND_P>; // is parity bit set -defm SETNP : SETCC<0x9B, "setnp", X86_COND_NP>; // is parity bit not set -defm SETL : SETCC<0x9C, "setl", X86_COND_L>; // signed less than -defm SETGE : SETCC<0x9D, "setge", X86_COND_GE>; // signed greater or equal -defm SETLE : SETCC<0x9E, "setle", X86_COND_LE>; // signed less than or equal -defm SETG : SETCC<0x9F, "setg", X86_COND_G>; // signed greater than - -// SALC is an undocumented instruction. Information for this instruction can be found -// here http://www.rcollins.org/secrets/opcodes/SALC.html -// Set AL if carry. -let Uses = [EFLAGS], Defs = [AL], SchedRW = [WriteALU] in { - def SALC : I<0xD6, RawFrm, (outs), (ins), "salc", []>, Requires<[Not64BitMode]>; -} diff --git a/suite/synctools/tablegen/X86/back/X86InstrCompiler.td b/suite/synctools/tablegen/X86/back/X86InstrCompiler.td deleted file mode 100644 index 76b93bdada..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrCompiler.td +++ /dev/null @@ -1,2103 +0,0 @@ -//===- X86InstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the various pseudo instructions used by the compiler, -// as well as Pat patterns used during instruction selection. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Pattern Matching Support - -def GetLo32XForm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def GetLo8XForm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - - -//===----------------------------------------------------------------------===// -// Random Pseudo Instructions. - -// PIC base construction. This expands to code that looks like this: -// call $next_inst -// popl %destreg" -let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP], - SchedRW = [WriteJump] in - def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label), - "", []>; - -// 64-bit large code model PIC base construction. -let hasSideEffects = 0, mayLoad = 1, isNotDuplicable = 1, SchedRW = [WriteJump] in - def MOVGOT64r : PseudoI<(outs GR64:$reg), - (ins GR64:$scratch, i64i32imm_pcrel:$got), []>; - -// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into -// a stack adjustment and the codegen must know that they may modify the stack -// pointer before prolog-epilog rewriting occurs. -// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become -// sub / add which can clobber EFLAGS. -let Defs = [ESP, EFLAGS, SSP], Uses = [ESP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), - "#ADJCALLSTACKDOWN", []>, Requires<[NotLP64]>; -def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), - "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)]>, - Requires<[NotLP64]>; -} -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN32 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[NotLP64]>; - - -// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into -// a stack adjustment and the codegen must know that they may modify the stack -// pointer before prolog-epilog rewriting occurs. -// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become -// sub / add which can clobber EFLAGS. -let Defs = [RSP, EFLAGS, SSP], Uses = [RSP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), - "#ADJCALLSTACKDOWN", []>, Requires<[IsLP64]>; -def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), - "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)]>, - Requires<[IsLP64]>; -} -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN64 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[IsLP64]>; - -let SchedRW = [WriteSystem] in { - -// x86-64 va_start lowering magic. -let usesCustomInserter = 1, Defs = [EFLAGS] in { -def VASTART_SAVE_XMM_REGS : I<0, Pseudo, - (outs), - (ins GR8:$al, - i64imm:$regsavefi, i64imm:$offset, - variable_ops), - "#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset", - [(X86vastart_save_xmm_regs GR8:$al, - imm:$regsavefi, - imm:$offset), - (implicit EFLAGS)]>; - -// The VAARG_64 pseudo-instruction takes the address of the va_list, -// and places the address of the next argument into a register. -let Defs = [EFLAGS] in -def VAARG_64 : I<0, Pseudo, - (outs GR64:$dst), - (ins i8mem:$ap, i32imm:$size, i8imm:$mode, i32imm:$align), - "#VAARG_64 $dst, $ap, $size, $mode, $align", - [(set GR64:$dst, - (X86vaarg64 addr:$ap, imm:$size, imm:$mode, imm:$align)), - (implicit EFLAGS)]>; - - -// When using segmented stacks these are lowered into instructions which first -// check if the current stacklet has enough free memory. If it does, memory is -// allocated by bumping the stack pointer. Otherwise memory is allocated from -// the heap. - -let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in -def SEG_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size), - "# variable sized alloca for segmented stacks", - [(set GR32:$dst, - (X86SegAlloca GR32:$size))]>, - Requires<[NotLP64]>; - -let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in -def SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size), - "# variable sized alloca for segmented stacks", - [(set GR64:$dst, - (X86SegAlloca GR64:$size))]>, - Requires<[In64BitMode]>; -} - -// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows -// targets. These calls are needed to probe the stack when allocating more than -// 4k bytes in one go. Touching the stack at 4K increments is necessary to -// ensure that the guard pages used by the OS virtual memory manager are -// allocated in correct sequence. -// The main point of having separate instruction are extra unmodelled effects -// (compared to ordinary calls) like stack pointer change. - -let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in -def WIN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR32:$size)]>, - Requires<[NotLP64]>; - -let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in -def WIN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR64:$size)]>, - Requires<[In64BitMode]>; -} // SchedRW - -// These instructions XOR the frame pointer into a GPR. They are used in some -// stack protection schemes. These are post-RA pseudos because we only know the -// frame register after register allocation. -let Constraints = "$src = $dst", isPseudo = 1, Defs = [EFLAGS] in { - def XOR32_FP : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src), - "xorl\t$$FP, $src", []>, - Requires<[NotLP64]>, Sched<[WriteALU]>; - def XOR64_FP : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src), - "xorq\t$$FP $src", []>, - Requires<[In64BitMode]>, Sched<[WriteALU]>; -} - -//===----------------------------------------------------------------------===// -// EH Pseudo Instructions -// -let SchedRW = [WriteSystem] in { -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, isCodeGenOnly = 1 in { -def EH_RETURN : I<0xC3, RawFrm, (outs), (ins GR32:$addr), - "ret\t#eh_return, addr: $addr", - [(X86ehret GR32:$addr)]>, Sched<[WriteJumpLd]>; - -} - -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, isCodeGenOnly = 1 in { -def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), - "ret\t#eh_return, addr: $addr", - [(X86ehret GR64:$addr)]>, Sched<[WriteJumpLd]>; - -} - -let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, - isCodeGenOnly = 1, isReturn = 1 in { - def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>; - - // CATCHRET needs a custom inserter for SEH. - let usesCustomInserter = 1 in - def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst, brtarget32:$from), - "# CATCHRET", - [(catchret bb:$dst, bb:$from)]>; -} - -let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1, - usesCustomInserter = 1 in -def CATCHPAD : I<0, Pseudo, (outs), (ins), "# CATCHPAD", [(catchpad)]>; - -// This instruction is responsible for re-establishing stack pointers after an -// exception has been caught and we are rejoining normal control flow in the -// parent function or funclet. It generally sets ESP and EBP, and optionally -// ESI. It is only needed for 32-bit WinEH, as the runtime restores CSRs for us -// elsewhere. -let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1 in -def EH_RESTORE : I<0, Pseudo, (outs), (ins), "# EH_RESTORE", []>; - -let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, - usesCustomInserter = 1 in { - def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf), - "#EH_SJLJ_SETJMP32", - [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>, - Requires<[Not64BitMode]>; - def EH_SjLj_SetJmp64 : I<0, Pseudo, (outs GR32:$dst), (ins i64mem:$buf), - "#EH_SJLJ_SETJMP64", - [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>, - Requires<[In64BitMode]>; - let isTerminator = 1 in { - def EH_SjLj_LongJmp32 : I<0, Pseudo, (outs), (ins i32mem:$buf), - "#EH_SJLJ_LONGJMP32", - [(X86eh_sjlj_longjmp addr:$buf)]>, - Requires<[Not64BitMode]>; - def EH_SjLj_LongJmp64 : I<0, Pseudo, (outs), (ins i64mem:$buf), - "#EH_SJLJ_LONGJMP64", - [(X86eh_sjlj_longjmp addr:$buf)]>, - Requires<[In64BitMode]>; - } -} - -let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in { - def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst), - "#EH_SjLj_Setup\t$dst", []>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Pseudo instructions used by unwind info. -// -let isPseudo = 1, SchedRW = [WriteSystem] in { - def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg), - "#SEH_PushReg $reg", []>; - def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst), - "#SEH_SaveReg $reg, $dst", []>; - def SEH_SaveXMM : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst), - "#SEH_SaveXMM $reg, $dst", []>; - def SEH_StackAlloc : I<0, Pseudo, (outs), (ins i32imm:$size), - "#SEH_StackAlloc $size", []>; - def SEH_SetFrame : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$offset), - "#SEH_SetFrame $reg, $offset", []>; - def SEH_PushFrame : I<0, Pseudo, (outs), (ins i1imm:$mode), - "#SEH_PushFrame $mode", []>; - def SEH_EndPrologue : I<0, Pseudo, (outs), (ins), - "#SEH_EndPrologue", []>; - def SEH_Epilogue : I<0, Pseudo, (outs), (ins), - "#SEH_Epilogue", []>; -} - -//===----------------------------------------------------------------------===// -// Pseudo instructions used by segmented stacks. -// - -// This is lowered into a RET instruction by MCInstLower. We need -// this so that we don't have to have a MachineBasicBlock which ends -// with a RET and also has successors. -let isPseudo = 1, SchedRW = [WriteJumpLd] in { -def MORESTACK_RET: I<0, Pseudo, (outs), (ins), "", []>; - -// This instruction is lowered to a RET followed by a MOV. The two -// instructions are not generated on a higher level since then the -// verifier sees a MachineBasicBlock ending with a non-terminator. -def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), "", []>; -} - -//===----------------------------------------------------------------------===// -// Alias Instructions -//===----------------------------------------------------------------------===// - -// Alias instruction mapping movr0 to xor. -// FIXME: remove when we can teach regalloc that xor reg, reg is ok. -let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, AddedComplexity = 10 in -def MOV32r0 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, 0)]>, Sched<[WriteZero]>; - -// Other widths can also make use of the 32-bit xor, which may have a smaller -// encoding and avoid partial register updates. -let AddedComplexity = 10 in { -def : Pat<(i8 0), (EXTRACT_SUBREG (MOV32r0), sub_8bit)>; -def : Pat<(i16 0), (EXTRACT_SUBREG (MOV32r0), sub_16bit)>; -def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)>; -} - -let Predicates = [OptForSize, Not64BitMode], - AddedComplexity = 10 in { - let SchedRW = [WriteALU] in { - // Pseudo instructions for materializing 1 and -1 using XOR+INC/DEC, - // which only require 3 bytes compared to MOV32ri which requires 5. - let Defs = [EFLAGS], isReMaterializable = 1, isPseudo = 1 in { - def MOV32r1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, 1)]>; - def MOV32r_1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, -1)]>; - } - } // SchedRW - - // MOV16ri is 4 bytes, so the instructions above are smaller. - def : Pat<(i16 1), (EXTRACT_SUBREG (MOV32r1), sub_16bit)>; - def : Pat<(i16 -1), (EXTRACT_SUBREG (MOV32r_1), sub_16bit)>; -} - -let isReMaterializable = 1, isPseudo = 1, AddedComplexity = 5, - SchedRW = [WriteALU] in { -// AddedComplexity higher than MOV64ri but lower than MOV32r0 and MOV32r1. -def MOV32ImmSExti8 : I<0, Pseudo, (outs GR32:$dst), (ins i32i8imm:$src), "", - [(set GR32:$dst, i32immSExt8:$src)]>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -def MOV64ImmSExti8 : I<0, Pseudo, (outs GR64:$dst), (ins i64i8imm:$src), "", - [(set GR64:$dst, i64immSExt8:$src)]>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -} - -// Materialize i64 constant where top 32-bits are zero. This could theoretically -// use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however -// that would make it more difficult to rematerialize. -let isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, hasSideEffects = 0, SchedRW = [WriteMove] in -def MOV32ri64 : I<0, Pseudo, (outs GR32:$dst), (ins i64i32imm:$src), "", []>; - -// This 64-bit pseudo-move can be used for both a 64-bit constant that is -// actually the zero-extension of a 32-bit constant and for labels in the -// x86-64 small code model. -def mov64imm32 : ComplexPattern; - -let AddedComplexity = 1 in -def : Pat<(i64 mov64imm32:$src), - (SUBREG_TO_REG (i64 0), (MOV32ri64 mov64imm32:$src), sub_32bit)>; - -// Use sbb to materialize carry bit. -let Uses = [EFLAGS], Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteALU] in { -// FIXME: These are pseudo ops that should be replaced with Pat<> patterns. -// However, Pat<> can't replicate the destination reg into the inputs of the -// result. -def SETB_C8r : I<0, Pseudo, (outs GR8:$dst), (ins), "", - [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C16r : I<0, Pseudo, (outs GR16:$dst), (ins), "", - [(set GR16:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C32r : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def SETB_C64r : I<0, Pseudo, (outs GR64:$dst), (ins), "", - [(set GR64:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -} // isCodeGenOnly - - -def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i64 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C64r)>; - -def : Pat<(i16 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i64 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C64r)>; - -// We canonicalize 'setb' to "(and (sbb reg,reg), 1)" on the hope that the and -// will be eliminated and that the sbb can be extended up to a wider type. When -// this happens, it is great. However, if we are left with an 8-bit sbb and an -// and, we might as well just match it as a setb. -def : Pat<(and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1), - (SETBr)>; - -// (add OP, SETB) -> (adc OP, 0) -def : Pat<(add (and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR8:$op), - (ADC8ri GR8:$op, 0)>; -def : Pat<(add (and (i32 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR32:$op), - (ADC32ri8 GR32:$op, 0)>; -def : Pat<(add (and (i64 (X86setcc_c X86_COND_B, EFLAGS)), 1), GR64:$op), - (ADC64ri8 GR64:$op, 0)>; - -// (sub OP, SETB) -> (sbb OP, 0) -def : Pat<(sub GR8:$op, (and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB8ri GR8:$op, 0)>; -def : Pat<(sub GR32:$op, (and (i32 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB32ri8 GR32:$op, 0)>; -def : Pat<(sub GR64:$op, (and (i64 (X86setcc_c X86_COND_B, EFLAGS)), 1)), - (SBB64ri8 GR64:$op, 0)>; - -// (sub OP, SETCC_CARRY) -> (adc OP, 0) -def : Pat<(sub GR8:$op, (i8 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC8ri GR8:$op, 0)>; -def : Pat<(sub GR32:$op, (i32 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC32ri8 GR32:$op, 0)>; -def : Pat<(sub GR64:$op, (i64 (X86setcc_c X86_COND_B, EFLAGS))), - (ADC64ri8 GR64:$op, 0)>; - -//===----------------------------------------------------------------------===// -// String Pseudo Instructions -// -let SchedRW = [WriteMicrocoded] in { -let Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI], isCodeGenOnly = 1 in { -def REP_MOVSB_32 : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", - [(X86rep_movs i8)]>, REP, - Requires<[Not64BitMode]>; -def REP_MOVSW_32 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", - [(X86rep_movs i16)]>, REP, OpSize16, - Requires<[Not64BitMode]>; -def REP_MOVSD_32 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", - [(X86rep_movs i32)]>, REP, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI], isCodeGenOnly = 1 in { -def REP_MOVSB_64 : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", - [(X86rep_movs i8)]>, REP, - Requires<[In64BitMode]>; -def REP_MOVSW_64 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", - [(X86rep_movs i16)]>, REP, OpSize16, - Requires<[In64BitMode]>; -def REP_MOVSD_64 : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", - [(X86rep_movs i32)]>, REP, OpSize32, - Requires<[In64BitMode]>; -def REP_MOVSQ_64 : RI<0xA5, RawFrm, (outs), (ins), "{rep;movsq|rep movsq}", - [(X86rep_movs i64)]>, REP, - Requires<[In64BitMode]>; -} - -// FIXME: Should use "(X86rep_stos AL)" as the pattern. -let Defs = [ECX,EDI], isCodeGenOnly = 1 in { - let Uses = [AL,ECX,EDI] in - def REP_STOSB_32 : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", - [(X86rep_stos i8)]>, REP, - Requires<[Not64BitMode]>; - let Uses = [AX,ECX,EDI] in - def REP_STOSW_32 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", - [(X86rep_stos i16)]>, REP, OpSize16, - Requires<[Not64BitMode]>; - let Uses = [EAX,ECX,EDI] in - def REP_STOSD_32 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", - [(X86rep_stos i32)]>, REP, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RCX,RDI], isCodeGenOnly = 1 in { - let Uses = [AL,RCX,RDI] in - def REP_STOSB_64 : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", - [(X86rep_stos i8)]>, REP, - Requires<[In64BitMode]>; - let Uses = [AX,RCX,RDI] in - def REP_STOSW_64 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", - [(X86rep_stos i16)]>, REP, OpSize16, - Requires<[In64BitMode]>; - let Uses = [RAX,RCX,RDI] in - def REP_STOSD_64 : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", - [(X86rep_stos i32)]>, REP, OpSize32, - Requires<[In64BitMode]>; - - let Uses = [RAX,RCX,RDI] in - def REP_STOSQ_64 : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", - [(X86rep_stos i64)]>, REP, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Thread Local Storage Instructions -// -let SchedRW = [WriteSystem] in { - -// ELF TLS Support -// All calls clobber the non-callee saved registers. ESP is marked as -// a use to prevent stack-pointer assignments that appear immediately -// before calls from potentially appearing dead. -let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, - ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, - MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, - XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF], - usesCustomInserter = 1, Uses = [ESP, SSP] in { -def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLS_addr32", - [(X86tlsaddr tls32addr:$sym)]>, - Requires<[Not64BitMode]>; -def TLS_base_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLS_base_addr32", - [(X86tlsbaseaddr tls32baseaddr:$sym)]>, - Requires<[Not64BitMode]>; -} - -// All calls clobber the non-callee saved registers. RSP is marked as -// a use to prevent stack-pointer assignments that appear immediately -// before calls from potentially appearing dead. -let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, - ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, - MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, - XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF], - usesCustomInserter = 1, Uses = [RSP, SSP] in { -def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLS_addr64", - [(X86tlsaddr tls64addr:$sym)]>, - Requires<[In64BitMode]>; -def TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLS_base_addr64", - [(X86tlsbaseaddr tls64baseaddr:$sym)]>, - Requires<[In64BitMode]>; -} - -// Darwin TLS Support -// For i386, the address of the thunk is passed on the stack, on return the -// address of the variable is in %eax. %ecx is trashed during the function -// call. All other registers are preserved. -let Defs = [EAX, ECX, EFLAGS, DF], - Uses = [ESP, SSP], - usesCustomInserter = 1 in -def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym), - "# TLSCall_32", - [(X86TLSCall addr:$sym)]>, - Requires<[Not64BitMode]>; - -// For x86_64, the address of the thunk is passed in %rdi, but the -// pseudo directly use the symbol, so do not add an implicit use of -// %rdi. The lowering will do the right thing with RDI. -// On return the address of the variable is in %rax. All other -// registers are preserved. -let Defs = [RAX, EFLAGS, DF], - Uses = [RSP, SSP], - usesCustomInserter = 1 in -def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym), - "# TLSCall_64", - [(X86TLSCall addr:$sym)]>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Conditional Move Pseudo Instructions - -// CMOV* - Used to implement the SELECT DAG operation. Expanded after -// instruction selection into a branch sequence. -multiclass CMOVrr_PSEUDO { - def CMOV#NAME : I<0, Pseudo, - (outs RC:$dst), (ins RC:$t, RC:$f, i8imm:$cond), - "#CMOV_"#NAME#" PSEUDO!", - [(set RC:$dst, (VT (X86cmov RC:$t, RC:$f, imm:$cond, - EFLAGS)))]>; -} - -let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in { - // X86 doesn't have 8-bit conditional moves. Use a customInserter to - // emit control flow. An alternative to this is to mark i8 SELECT as Promote, - // however that requires promoting the operands, and can induce additional - // i8 register pressure. - defm _GR8 : CMOVrr_PSEUDO; - - let Predicates = [NoCMov] in { - defm _GR32 : CMOVrr_PSEUDO; - defm _GR16 : CMOVrr_PSEUDO; - } // Predicates = [NoCMov] - - // fcmov doesn't handle all possible EFLAGS, provide a fallback if there is no - // SSE1/SSE2. - let Predicates = [FPStackf32] in - defm _RFP32 : CMOVrr_PSEUDO; - - let Predicates = [FPStackf64] in - defm _RFP64 : CMOVrr_PSEUDO; - - defm _RFP80 : CMOVrr_PSEUDO; - - defm _FR32 : CMOVrr_PSEUDO; - defm _FR64 : CMOVrr_PSEUDO; - defm _F128 : CMOVrr_PSEUDO; - defm _V4F32 : CMOVrr_PSEUDO; - defm _V2F64 : CMOVrr_PSEUDO; - defm _V2I64 : CMOVrr_PSEUDO; - defm _V8F32 : CMOVrr_PSEUDO; - defm _V4F64 : CMOVrr_PSEUDO; - defm _V4I64 : CMOVrr_PSEUDO; - defm _V8I64 : CMOVrr_PSEUDO; - defm _V8F64 : CMOVrr_PSEUDO; - defm _V16F32 : CMOVrr_PSEUDO; - defm _V8I1 : CMOVrr_PSEUDO; - defm _V16I1 : CMOVrr_PSEUDO; - defm _V32I1 : CMOVrr_PSEUDO; - defm _V64I1 : CMOVrr_PSEUDO; -} // usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] - -//===----------------------------------------------------------------------===// -// Normal-Instructions-With-Lock-Prefix Pseudo Instructions -//===----------------------------------------------------------------------===// - -// FIXME: Use normal instructions and add lock prefix dynamically. - -// Memory barriers - -// TODO: Get this to fold the constant into the instruction. -let isCodeGenOnly = 1, Defs = [EFLAGS] in -def OR32mrLocked : I<0x09, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$zero), - "or{l}\t{$zero, $dst|$dst, $zero}", []>, - Requires<[Not64BitMode]>, OpSize32, LOCK, - Sched<[WriteALULd, WriteRMW]>; - -let hasSideEffects = 1 in -def Int_MemBarrier : I<0, Pseudo, (outs), (ins), - "#MEMBARRIER", - [(X86MemBarrier)]>, Sched<[WriteLoad]>; - -// RegOpc corresponds to the mr version of the instruction -// ImmOpc corresponds to the mi version of the instruction -// ImmOpc8 corresponds to the mi8 version of the instruction -// ImmMod corresponds to the instruction format of the mi and mi8 versions -multiclass LOCK_ArithBinOp RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8, - Format ImmMod, SDNode Op, string mnemonic> { -let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { - -def NAME#8mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 0 }, - MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), - !strconcat(mnemonic, "{b}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR8:$src2))]>, LOCK; - -def NAME#16mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR16:$src2))]>, - OpSize16, LOCK; - -def NAME#32mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR32:$src2))]>, - OpSize32, LOCK; - -def NAME#64mr : RI<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, - RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, - MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR64:$src2))]>, LOCK; - -def NAME#8mi : Ii8<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 0 }, - ImmMod, (outs), (ins i8mem :$dst, i8imm :$src2), - !strconcat(mnemonic, "{b}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i8 imm:$src2)))]>, LOCK; - -def NAME#16mi : Ii16<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i16mem :$dst, i16imm :$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i16 imm:$src2)))]>, - OpSize16, LOCK; - -def NAME#32mi : Ii32<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i32mem :$dst, i32imm :$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i32 imm:$src2)))]>, - OpSize32, LOCK; - -def NAME#64mi32 : RIi32S<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, - ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, - ImmMod, (outs), (ins i64mem :$dst, i64i32imm :$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt32:$src2))]>, - LOCK; - -def NAME#16mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i16mem :$dst, i16i8imm :$src2), - !strconcat(mnemonic, "{w}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i16immSExt8:$src2))]>, - OpSize16, LOCK; - -def NAME#32mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i32mem :$dst, i32i8imm :$src2), - !strconcat(mnemonic, "{l}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i32immSExt8:$src2))]>, - OpSize32, LOCK; - -def NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, - ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, - ImmMod, (outs), (ins i64mem :$dst, i64i8imm :$src2), - !strconcat(mnemonic, "{q}\t", - "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt8:$src2))]>, - LOCK; -} - -} - -defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, X86lock_add, "add">; -defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, X86lock_sub, "sub">; -defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">; -defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">; -defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">; - -multiclass LOCK_ArithUnOp Opc8, bits<8> Opc, Format Form, - string frag, string mnemonic> { -let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { -def NAME#8m : I(frag # "_8") addr:$dst))]>, - LOCK; -def NAME#16m : I(frag # "_16") addr:$dst))]>, - OpSize16, LOCK; -def NAME#32m : I(frag # "_32") addr:$dst))]>, - OpSize32, LOCK; -def NAME#64m : RI(frag # "_64") addr:$dst))]>, - LOCK; -} -} - -multiclass unary_atomic_intrin { - def _8 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; - }]>; - def _16 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; - }]>; - def _32 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; - }]>; - def _64 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i64; - }]>; -} - -defm X86lock_inc : unary_atomic_intrin; -defm X86lock_dec : unary_atomic_intrin; - -defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, "X86lock_inc", "inc">; -defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, "X86lock_dec", "dec">; - -// Atomic compare and swap. -multiclass LCMPXCHG_UnOp Opc, Format Form, string mnemonic, - SDPatternOperator frag, X86MemOperand x86memop> { -let isCodeGenOnly = 1, usesCustomInserter = 1 in { - def NAME : I, TB, LOCK; -} -} - -multiclass LCMPXCHG_BinOp Opc8, bits<8> Opc, Format Form, - string mnemonic, SDPatternOperator frag> { -let isCodeGenOnly = 1, SchedRW = [WriteALULd, WriteRMW] in { - let Defs = [AL, EFLAGS], Uses = [AL] in - def NAME#8 : I, TB, LOCK; - let Defs = [AX, EFLAGS], Uses = [AX] in - def NAME#16 : I, TB, OpSize16, LOCK; - let Defs = [EAX, EFLAGS], Uses = [EAX] in - def NAME#32 : I, TB, OpSize32, LOCK; - let Defs = [RAX, EFLAGS], Uses = [RAX] in - def NAME#64 : RI, TB, LOCK; -} -} - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX], - SchedRW = [WriteALULd, WriteRMW] in { -defm LCMPXCHG8B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg8b", X86cas8, i64mem>; -} - -// This pseudo must be used when the frame uses RBX as -// the base pointer. Indeed, in such situation RBX is a reserved -// register and the register allocator will ignore any use/def of -// it. In other words, the register will not fix the clobbering of -// RBX that will happen when setting the arguments for the instruction. -// -// Unlike the actual related instruction, we mark that this one -// defines EBX (instead of using EBX). -// The rationale is that we will define RBX during the expansion of -// the pseudo. The argument feeding EBX is ebx_input. -// -// The additional argument, $ebx_save, is a temporary register used to -// save the value of RBX across the actual instruction. -// -// To make sure the register assigned to $ebx_save does not interfere with -// the definition of the actual instruction, we use a definition $dst which -// is tied to $rbx_save. That way, the live-range of $rbx_save spans across -// the instruction and we are sure we will have a valid register to restore -// the value of RBX. -let Defs = [EAX, EDX, EBX, EFLAGS], Uses = [EAX, ECX, EDX], - SchedRW = [WriteALULd, WriteRMW], isCodeGenOnly = 1, isPseudo = 1, - Constraints = "$ebx_save = $dst", usesCustomInserter = 1 in { -def LCMPXCHG8B_SAVE_EBX : - I<0, Pseudo, (outs GR32:$dst), - (ins i64mem:$ptr, GR32:$ebx_input, GR32:$ebx_save), - !strconcat("cmpxchg8b", "\t$ptr"), - [(set GR32:$dst, (X86cas8save_ebx addr:$ptr, GR32:$ebx_input, - GR32:$ebx_save))]>; -} - - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX], - Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW] in { -defm LCMPXCHG16B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg16b", - X86cas16, i128mem>, REX_W; -} - -// Same as LCMPXCHG8B_SAVE_RBX but for the 16 Bytes variant. -let Defs = [RAX, RDX, RBX, EFLAGS], Uses = [RAX, RCX, RDX], - Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW], - isCodeGenOnly = 1, isPseudo = 1, Constraints = "$rbx_save = $dst", - usesCustomInserter = 1 in { -def LCMPXCHG16B_SAVE_RBX : - I<0, Pseudo, (outs GR64:$dst), - (ins i128mem:$ptr, GR64:$rbx_input, GR64:$rbx_save), - !strconcat("cmpxchg16b", "\t$ptr"), - [(set GR64:$dst, (X86cas16save_rbx addr:$ptr, GR64:$rbx_input, - GR64:$rbx_save))]>; -} - -defm LCMPXCHG : LCMPXCHG_BinOp<0xB0, 0xB1, MRMDestMem, "cmpxchg", X86cas>; - -// Atomic exchange and add -multiclass ATOMIC_LOAD_BINOP opc8, bits<8> opc, string mnemonic, - string frag> { - let Constraints = "$val = $dst", Defs = [EFLAGS], isCodeGenOnly = 1, - SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8 : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16 : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32 : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64 : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm LXADD : ATOMIC_LOAD_BINOP<0xc0, 0xc1, "xadd", "atomic_load_add">, TB, LOCK; - -/* The following multiclass tries to make sure that in code like - * x.store (immediate op x.load(acquire), release) - * and - * x.store (register op x.load(acquire), release) - * an operation directly on memory is generated instead of wasting a register. - * It is not automatic as atomic_store/load are only lowered to MOV instructions - * extremely late to prevent them from being accidentally reordered in the backend - * (see below the RELEASE_MOV* / ACQUIRE_MOV* pseudo-instructions) - */ -multiclass RELEASE_BINOP_MI { - def NAME#8mi : I<0, Pseudo, (outs), (ins i8mem:$dst, i8imm:$src), - "#BINOP "#NAME#"8mi PSEUDO!", - [(atomic_store_8 addr:$dst, (op - (atomic_load_8 addr:$dst), (i8 imm:$src)))]>; - def NAME#8mr : I<0, Pseudo, (outs), (ins i8mem:$dst, GR8:$src), - "#BINOP "#NAME#"8mr PSEUDO!", - [(atomic_store_8 addr:$dst, (op - (atomic_load_8 addr:$dst), GR8:$src))]>; - // NAME#16 is not generated as 16-bit arithmetic instructions are considered - // costly and avoided as far as possible by this backend anyway - def NAME#32mi : I<0, Pseudo, (outs), (ins i32mem:$dst, i32imm:$src), - "#BINOP "#NAME#"32mi PSEUDO!", - [(atomic_store_32 addr:$dst, (op - (atomic_load_32 addr:$dst), (i32 imm:$src)))]>; - def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, GR32:$src), - "#BINOP "#NAME#"32mr PSEUDO!", - [(atomic_store_32 addr:$dst, (op - (atomic_load_32 addr:$dst), GR32:$src))]>; - def NAME#64mi32 : I<0, Pseudo, (outs), (ins i64mem:$dst, i64i32imm:$src), - "#BINOP "#NAME#"64mi32 PSEUDO!", - [(atomic_store_64 addr:$dst, (op - (atomic_load_64 addr:$dst), (i64immSExt32:$src)))]>; - def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, GR64:$src), - "#BINOP "#NAME#"64mr PSEUDO!", - [(atomic_store_64 addr:$dst, (op - (atomic_load_64 addr:$dst), GR64:$src))]>; -} -let Defs = [EFLAGS], SchedRW = [WriteMicrocoded] in { - defm RELEASE_ADD : RELEASE_BINOP_MI; - defm RELEASE_AND : RELEASE_BINOP_MI; - defm RELEASE_OR : RELEASE_BINOP_MI; - defm RELEASE_XOR : RELEASE_BINOP_MI; - // Note: we don't deal with sub, because substractions of constants are - // optimized into additions before this code can run. -} - -// Same as above, but for floating-point. -// FIXME: imm version. -// FIXME: Version that doesn't clobber $src, using AVX's VADDSS. -// FIXME: This could also handle SIMD operations with *ps and *pd instructions. -let usesCustomInserter = 1, SchedRW = [WriteMicrocoded] in { -multiclass RELEASE_FP_BINOP_MI { - def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, FR32:$src), - "#BINOP "#NAME#"32mr PSEUDO!", - [(atomic_store_32 addr:$dst, - (i32 (bitconvert (op - (f32 (bitconvert (i32 (atomic_load_32 addr:$dst)))), - FR32:$src))))]>, Requires<[HasSSE1]>; - def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, FR64:$src), - "#BINOP "#NAME#"64mr PSEUDO!", - [(atomic_store_64 addr:$dst, - (i64 (bitconvert (op - (f64 (bitconvert (i64 (atomic_load_64 addr:$dst)))), - FR64:$src))))]>, Requires<[HasSSE2]>; -} -defm RELEASE_FADD : RELEASE_FP_BINOP_MI; -// FIXME: Add fsub, fmul, fdiv, ... -} - -multiclass RELEASE_UNOP { - def NAME#8m : I<0, Pseudo, (outs), (ins i8mem:$dst), - "#UNOP "#NAME#"8m PSEUDO!", - [(atomic_store_8 addr:$dst, dag8)]>; - def NAME#16m : I<0, Pseudo, (outs), (ins i16mem:$dst), - "#UNOP "#NAME#"16m PSEUDO!", - [(atomic_store_16 addr:$dst, dag16)]>; - def NAME#32m : I<0, Pseudo, (outs), (ins i32mem:$dst), - "#UNOP "#NAME#"32m PSEUDO!", - [(atomic_store_32 addr:$dst, dag32)]>; - def NAME#64m : I<0, Pseudo, (outs), (ins i64mem:$dst), - "#UNOP "#NAME#"64m PSEUDO!", - [(atomic_store_64 addr:$dst, dag64)]>; -} - -let Defs = [EFLAGS], Predicates = [UseIncDec], SchedRW = [WriteMicrocoded] in { - defm RELEASE_INC : RELEASE_UNOP< - (add (atomic_load_8 addr:$dst), (i8 1)), - (add (atomic_load_16 addr:$dst), (i16 1)), - (add (atomic_load_32 addr:$dst), (i32 1)), - (add (atomic_load_64 addr:$dst), (i64 1))>; - defm RELEASE_DEC : RELEASE_UNOP< - (add (atomic_load_8 addr:$dst), (i8 -1)), - (add (atomic_load_16 addr:$dst), (i16 -1)), - (add (atomic_load_32 addr:$dst), (i32 -1)), - (add (atomic_load_64 addr:$dst), (i64 -1))>; -} -/* -TODO: These don't work because the type inference of TableGen fails. -TODO: find a way to fix it. -let Defs = [EFLAGS] in { - defm RELEASE_NEG : RELEASE_UNOP< - (ineg (atomic_load_8 addr:$dst)), - (ineg (atomic_load_16 addr:$dst)), - (ineg (atomic_load_32 addr:$dst)), - (ineg (atomic_load_64 addr:$dst))>; -} -// NOT doesn't set flags. -defm RELEASE_NOT : RELEASE_UNOP< - (not (atomic_load_8 addr:$dst)), - (not (atomic_load_16 addr:$dst)), - (not (atomic_load_32 addr:$dst)), - (not (atomic_load_64 addr:$dst))>; -*/ - -let SchedRW = [WriteMicrocoded] in { -def RELEASE_MOV8mi : I<0, Pseudo, (outs), (ins i8mem:$dst, i8imm:$src), - "#RELEASE_MOV8mi PSEUDO!", - [(atomic_store_8 addr:$dst, (i8 imm:$src))]>; -def RELEASE_MOV16mi : I<0, Pseudo, (outs), (ins i16mem:$dst, i16imm:$src), - "#RELEASE_MOV16mi PSEUDO!", - [(atomic_store_16 addr:$dst, (i16 imm:$src))]>; -def RELEASE_MOV32mi : I<0, Pseudo, (outs), (ins i32mem:$dst, i32imm:$src), - "#RELEASE_MOV32mi PSEUDO!", - [(atomic_store_32 addr:$dst, (i32 imm:$src))]>; -def RELEASE_MOV64mi32 : I<0, Pseudo, (outs), (ins i64mem:$dst, i64i32imm:$src), - "#RELEASE_MOV64mi32 PSEUDO!", - [(atomic_store_64 addr:$dst, i64immSExt32:$src)]>; - -def RELEASE_MOV8mr : I<0, Pseudo, (outs), (ins i8mem :$dst, GR8 :$src), - "#RELEASE_MOV8mr PSEUDO!", - [(atomic_store_8 addr:$dst, GR8 :$src)]>; -def RELEASE_MOV16mr : I<0, Pseudo, (outs), (ins i16mem:$dst, GR16:$src), - "#RELEASE_MOV16mr PSEUDO!", - [(atomic_store_16 addr:$dst, GR16:$src)]>; -def RELEASE_MOV32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, GR32:$src), - "#RELEASE_MOV32mr PSEUDO!", - [(atomic_store_32 addr:$dst, GR32:$src)]>; -def RELEASE_MOV64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, GR64:$src), - "#RELEASE_MOV64mr PSEUDO!", - [(atomic_store_64 addr:$dst, GR64:$src)]>; - -def ACQUIRE_MOV8rm : I<0, Pseudo, (outs GR8 :$dst), (ins i8mem :$src), - "#ACQUIRE_MOV8rm PSEUDO!", - [(set GR8:$dst, (atomic_load_8 addr:$src))]>; -def ACQUIRE_MOV16rm : I<0, Pseudo, (outs GR16:$dst), (ins i16mem:$src), - "#ACQUIRE_MOV16rm PSEUDO!", - [(set GR16:$dst, (atomic_load_16 addr:$src))]>; -def ACQUIRE_MOV32rm : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$src), - "#ACQUIRE_MOV32rm PSEUDO!", - [(set GR32:$dst, (atomic_load_32 addr:$src))]>; -def ACQUIRE_MOV64rm : I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$src), - "#ACQUIRE_MOV64rm PSEUDO!", - [(set GR64:$dst, (atomic_load_64 addr:$src))]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// DAG Pattern Matching Rules -//===----------------------------------------------------------------------===// - -// Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves -// binary size compared to a regular MOV, but it introduces an unnecessary -// load, so is not suitable for regular or optsize functions. -let Predicates = [OptForMinSize] in { -def : Pat<(store (i16 0), addr:$dst), (AND16mi8 addr:$dst, 0)>; -def : Pat<(store (i32 0), addr:$dst), (AND32mi8 addr:$dst, 0)>; -def : Pat<(store (i64 0), addr:$dst), (AND64mi8 addr:$dst, 0)>; -def : Pat<(store (i16 -1), addr:$dst), (OR16mi8 addr:$dst, -1)>; -def : Pat<(store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>; -def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>; -} - -// In kernel code model, we can get the address of a label -// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of -// the MOV64ri32 should accept these. -def : Pat<(i64 (X86Wrapper tconstpool :$dst)), - (MOV64ri32 tconstpool :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tjumptable :$dst)), - (MOV64ri32 tjumptable :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), - (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper texternalsym:$dst)), - (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper mcsym:$dst)), - (MOV64ri32 mcsym:$dst)>, Requires<[KernelCode]>; -def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), - (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>; - -// If we have small model and -static mode, it is safe to store global addresses -// directly as immediates. FIXME: This is really a hack, the 'imm' predicate -// for MOV64mi32 should handle this sort of thing. -def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tconstpool:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tjumptable:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tglobaladdr:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst), - (MOV64mi32 addr:$dst, texternalsym:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper mcsym:$src)), addr:$dst), - (MOV64mi32 addr:$dst, mcsym:$src)>, - Requires<[NearData, IsNotPIC]>; -def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst), - (MOV64mi32 addr:$dst, tblockaddress:$src)>, - Requires<[NearData, IsNotPIC]>; - -def : Pat<(i32 (X86RecoverFrameAlloc mcsym:$dst)), (MOV32ri mcsym:$dst)>; -def : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>; - -// Calls - -// tls has some funny stuff here... -// This corresponds to movabs $foo@tpoff, %rax -def : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)), - (MOV64ri32 tglobaltlsaddr :$dst)>; -// This corresponds to add $foo@tpoff, %rax -def : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)), - (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>; - - -// Direct PC relative function call for small code model. 32-bit displacement -// sign extended to 64-bit. -def : Pat<(X86call (i64 tglobaladdr:$dst)), - (CALL64pcrel32 tglobaladdr:$dst)>; -def : Pat<(X86call (i64 texternalsym:$dst)), - (CALL64pcrel32 texternalsym:$dst)>; - -// Tailcall stuff. The TCRETURN instructions execute after the epilog, so they -// can never use callee-saved registers. That is the purpose of the GR64_TC -// register classes. -// -// The only volatile register that is never used by the calling convention is -// %r11. This happens when calling a vararg function with 6 arguments. -// -// Match an X86tcret that uses less than 7 volatile registers. -def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off), - (X86tcret node:$ptr, node:$off), [{ - // X86tcret args: (*chain, ptr, imm, regs..., glue) - unsigned NumRegs = 0; - for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) - if (isa(N->getOperand(i)) && ++NumRegs > 6) - return false; - return true; -}]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (TCRETURNri ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, NotUseRetpoline]>; - -// FIXME: This is disabled for 32-bit PIC mode because the global base -// register which is part of the address mode may be assigned a -// callee-saved register. -def : Pat<(X86tcret (load addr:$dst), imm:$off), - (TCRETURNmi addr:$dst, imm:$off)>, - Requires<[Not64BitMode, IsNotPIC, NotUseRetpoline]>; - -def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off), - (TCRETURNdi tglobaladdr:$dst, imm:$off)>, - Requires<[NotLP64]>; - -def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off), - (TCRETURNdi texternalsym:$dst, imm:$off)>, - Requires<[NotLP64]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (TCRETURNri64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; - -// Don't fold loads into X86tcret requiring more than 6 regs. -// There wouldn't be enough scratch registers for base+index. -def : Pat<(X86tcret_6regs (load addr:$dst), imm:$off), - (TCRETURNmi64 addr:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, UseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN32 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, UseRetpoline]>; - -def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off), - (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>, - Requires<[IsLP64]>; - -def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off), - (TCRETURNdi64 texternalsym:$dst, imm:$off)>, - Requires<[IsLP64]>; - -// Normal calls, with various flavors of addresses. -def : Pat<(X86call (i32 tglobaladdr:$dst)), - (CALLpcrel32 tglobaladdr:$dst)>; -def : Pat<(X86call (i32 texternalsym:$dst)), - (CALLpcrel32 texternalsym:$dst)>; -def : Pat<(X86call (i32 imm:$dst)), - (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>; - -// Comparisons. - -// TEST R,R is smaller than CMP R,0 -def : Pat<(X86cmp GR8:$src1, 0), - (TEST8rr GR8:$src1, GR8:$src1)>; -def : Pat<(X86cmp GR16:$src1, 0), - (TEST16rr GR16:$src1, GR16:$src1)>; -def : Pat<(X86cmp GR32:$src1, 0), - (TEST32rr GR32:$src1, GR32:$src1)>; -def : Pat<(X86cmp GR64:$src1, 0), - (TEST64rr GR64:$src1, GR64:$src1)>; - -// Conditional moves with folded loads with operands swapped and conditions -// inverted. -multiclass CMOVmr { - let Predicates = [HasCMov] in { - def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS), - (Inst16 GR16:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS), - (Inst32 GR32:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS), - (Inst64 GR64:$src2, addr:$src1)>; - } -} - -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; -defm : CMOVmr; - -// zextload bool -> zextload byte -// i1 stored in one byte in zero-extended form. -// Upper bits cleanup should be executed before Store. -def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(zextloadi64i1 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; - -// extload bool -> extload byte -// When extloading from 16-bit and smaller memory locations into 64-bit -// registers, use zero-extending loads so that the entire 64-bit register is -// defined, avoiding partial-register updates. - -def : Pat<(extloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(extloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(extloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(extloadi32i8 addr:$src), (MOVZX32rm8 addr:$src)>; -def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>; - -// For other extloads, use subregs, since the high contents of the register are -// defined after an extload. -def : Pat<(extloadi64i1 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i8 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i16 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>; -def : Pat<(extloadi64i32 addr:$src), - (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>; - -// anyext. Define these to do an explicit zero-extend to -// avoid partial-register updates. -def : Pat<(i16 (anyext GR8 :$src)), (EXTRACT_SUBREG - (MOVZX32rr8 GR8 :$src), sub_16bit)>; -def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>; - -// Except for i16 -> i32 since isel expect i16 ops to be promoted to i32. -def : Pat<(i32 (anyext GR16:$src)), - (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, sub_16bit)>; - -def : Pat<(i64 (anyext GR8 :$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8 :$src), sub_32bit)>; -def : Pat<(i64 (anyext GR16:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16 :$src), sub_32bit)>; -def : Pat<(i64 (anyext GR32:$src)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>; - - -// Any instruction that defines a 32-bit result leaves the high half of the -// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may -// be copying from a truncate. Any other 32-bit operation will zero-extend -// up to 64 bits. AssertSext/AssertZext aren't saying anything about the upper -// 32 bits, they're probably just qualifying a CopyFromReg. -def def32 : PatLeaf<(i32 GR32:$src), [{ - return N->getOpcode() != ISD::TRUNCATE && - N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && - N->getOpcode() != ISD::CopyFromReg && - N->getOpcode() != ISD::AssertSext && - N->getOpcode() != ISD::AssertZext; -}]>; - -// In the case of a 32-bit def that is known to implicitly zero-extend, -// we can use a SUBREG_TO_REG. -def : Pat<(i64 (zext def32:$src)), - (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>; - -//===----------------------------------------------------------------------===// -// Pattern match OR as ADD -//===----------------------------------------------------------------------===// - -// If safe, we prefer to pattern match OR as ADD at isel time. ADD can be -// 3-addressified into an LEA instruction to avoid copies. However, we also -// want to finally emit these instructions as an or at the end of the code -// generator to make the generated code easier to read. To do this, we select -// into "disjoint bits" pseudo ops. - -// Treat an 'or' node is as an 'add' if the or'ed bits are known to be zero. -def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ - if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) - return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); - - KnownBits Known0; - CurDAG->computeKnownBits(N->getOperand(0), Known0, 0); - KnownBits Known1; - CurDAG->computeKnownBits(N->getOperand(1), Known1, 0); - return (~Known0.Zero & ~Known1.Zero) == 0; -}]>; - - -// (or x1, x2) -> (add x1, x2) if two operands are known not to share bits. -// Try this before the selecting to OR. -let AddedComplexity = 5, SchedRW = [WriteALU] in { - -let isConvertibleToThreeAddress = 1, - Constraints = "$src1 = $dst", Defs = [EFLAGS] in { -let isCommutable = 1 in { -def ADD16rr_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "", // orw/addw REG, REG - [(set GR16:$dst, (or_is_add GR16:$src1, GR16:$src2))]>; -def ADD32rr_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "", // orl/addl REG, REG - [(set GR32:$dst, (or_is_add GR32:$src1, GR32:$src2))]>; -def ADD64rr_DB : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "", // orq/addq REG, REG - [(set GR64:$dst, (or_is_add GR64:$src1, GR64:$src2))]>; -} // isCommutable - -// NOTE: These are order specific, we want the ri8 forms to be listed -// first so that they are slightly preferred to the ri forms. - -def ADD16ri8_DB : I<0, Pseudo, - (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "", // orw/addw REG, imm8 - [(set GR16:$dst,(or_is_add GR16:$src1,i16immSExt8:$src2))]>; -def ADD16ri_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "", // orw/addw REG, imm - [(set GR16:$dst, (or_is_add GR16:$src1, imm:$src2))]>; - -def ADD32ri8_DB : I<0, Pseudo, - (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "", // orl/addl REG, imm8 - [(set GR32:$dst,(or_is_add GR32:$src1,i32immSExt8:$src2))]>; -def ADD32ri_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), - "", // orl/addl REG, imm - [(set GR32:$dst, (or_is_add GR32:$src1, imm:$src2))]>; - - -def ADD64ri8_DB : I<0, Pseudo, - (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "", // orq/addq REG, imm8 - [(set GR64:$dst, (or_is_add GR64:$src1, - i64immSExt8:$src2))]>; -def ADD64ri32_DB : I<0, Pseudo, - (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), - "", // orq/addq REG, imm - [(set GR64:$dst, (or_is_add GR64:$src1, - i64immSExt32:$src2))]>; -} -} // AddedComplexity, SchedRW - -//===----------------------------------------------------------------------===// -// Pattern match SUB as XOR -//===----------------------------------------------------------------------===// - -// An immediate in the LHS of a subtract can't be encoded in the instruction. -// If there is no possibility of a borrow we can use an XOR instead of a SUB -// to enable the immediate to be folded. -// TODO: Move this to a DAG combine? - -def sub_is_xor : PatFrag<(ops node:$lhs, node:$rhs), (sub node:$lhs, node:$rhs),[{ - if (ConstantSDNode *CN = dyn_cast(N->getOperand(0))) { - KnownBits Known; - CurDAG->computeKnownBits(N->getOperand(1), Known); - - // If all possible ones in the RHS are set in the LHS then there can't be - // a borrow and we can use xor. - return (~Known.Zero).isSubsetOf(CN->getAPIntValue()); - } - - return false; -}]>; - -let AddedComplexity = 5 in { -def : Pat<(sub_is_xor imm:$src2, GR8:$src1), - (XOR8ri GR8:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i16immSExt8:$src2, GR16:$src1), - (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(sub_is_xor imm:$src2, GR16:$src1), - (XOR16ri GR16:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i32immSExt8:$src2, GR32:$src1), - (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(sub_is_xor imm:$src2, GR32:$src1), - (XOR32ri GR32:$src1, imm:$src2)>; -def : Pat<(sub_is_xor i64immSExt8:$src2, GR64:$src1), - (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(sub_is_xor i64immSExt32:$src2, GR64:$src1), - (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; -} - -//===----------------------------------------------------------------------===// -// Some peepholes -//===----------------------------------------------------------------------===// - -// Odd encoding trick: -128 fits into an 8-bit immediate field while -// +128 doesn't, so in this special case use a sub instead of an add. -def : Pat<(add GR16:$src1, 128), - (SUB16ri8 GR16:$src1, -128)>; -def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst), - (SUB16mi8 addr:$dst, -128)>; - -def : Pat<(add GR32:$src1, 128), - (SUB32ri8 GR32:$src1, -128)>; -def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst), - (SUB32mi8 addr:$dst, -128)>; - -def : Pat<(add GR64:$src1, 128), - (SUB64ri8 GR64:$src1, -128)>; -def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst), - (SUB64mi8 addr:$dst, -128)>; - -// The same trick applies for 32-bit immediate fields in 64-bit -// instructions. -def : Pat<(add GR64:$src1, 0x0000000080000000), - (SUB64ri32 GR64:$src1, 0xffffffff80000000)>; -def : Pat<(store (add (loadi64 addr:$dst), 0x0000000080000000), addr:$dst), - (SUB64mi32 addr:$dst, 0xffffffff80000000)>; - -// To avoid needing to materialize an immediate in a register, use a 32-bit and -// with implicit zero-extension instead of a 64-bit and if the immediate has at -// least 32 bits of leading zeros. If in addition the last 32 bits can be -// represented with a sign extension of a 8 bit constant, use that. -// This can also reduce instruction size by eliminating the need for the REX -// prefix. - -// AddedComplexity is needed to give priority over i64immSExt8 and i64immSExt32. -let AddedComplexity = 1 in { -def : Pat<(and GR64:$src, i64immZExt32SExt8:$imm), - (SUBREG_TO_REG - (i64 0), - (AND32ri8 - (EXTRACT_SUBREG GR64:$src, sub_32bit), - (i32 (GetLo8XForm imm:$imm))), - sub_32bit)>; - -def : Pat<(and GR64:$src, i64immZExt32:$imm), - (SUBREG_TO_REG - (i64 0), - (AND32ri - (EXTRACT_SUBREG GR64:$src, sub_32bit), - (i32 (GetLo32XForm imm:$imm))), - sub_32bit)>; -} // AddedComplexity = 1 - - -// AddedComplexity is needed due to the increased complexity on the -// i64immZExt32SExt8 and i64immZExt32 patterns above. Applying this to all -// the MOVZX patterns keeps thems together in DAGIsel tables. -let AddedComplexity = 1 in { -// r & (2^16-1) ==> movz -def : Pat<(and GR32:$src1, 0xffff), - (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>; -// r & (2^8-1) ==> movz -def : Pat<(and GR32:$src1, 0xff), - (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>; -// r & (2^8-1) ==> movz -def : Pat<(and GR16:$src1, 0xff), - (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)), - sub_16bit)>; - -// r & (2^32-1) ==> movz -def : Pat<(and GR64:$src, 0x00000000FFFFFFFF), - (SUBREG_TO_REG (i64 0), - (MOV32rr (EXTRACT_SUBREG GR64:$src, sub_32bit)), - sub_32bit)>; -// r & (2^16-1) ==> movz -def : Pat<(and GR64:$src, 0xffff), - (SUBREG_TO_REG (i64 0), - (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR64:$src, sub_16bit))), - sub_32bit)>; -// r & (2^8-1) ==> movz -def : Pat<(and GR64:$src, 0xff), - (SUBREG_TO_REG (i64 0), - (MOVZX32rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit))), - sub_32bit)>; -} // AddedComplexity = 1 - - -// Try to use BTS/BTR/BTC for single bit operations on the upper 32-bits. - -def BTRXForm : SDNodeXFormgetAPIntValue().countTrailingOnes(), SDLoc(N)); -}]>; - -def BTCBTSXForm : SDNodeXFormgetAPIntValue().countTrailingZeros(), SDLoc(N)); -}]>; - -def BTRMask64 : ImmLeaf(Imm) && !isInt<32>(Imm) && isPowerOf2_64(~Imm); -}]>; - -def BTCBTSMask64 : ImmLeaf(Imm) && isPowerOf2_64(Imm); -}]>; - -// For now only do this for optsize. -let AddedComplexity = 1, Predicates=[OptForSize] in { - def : Pat<(and GR64:$src1, BTRMask64:$mask), - (BTR64ri8 GR64:$src1, (BTRXForm imm:$mask))>; - def : Pat<(or GR64:$src1, BTCBTSMask64:$mask), - (BTS64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; - def : Pat<(xor GR64:$src1, BTCBTSMask64:$mask), - (BTC64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>; -} - - -// sext_inreg patterns -def : Pat<(sext_inreg GR32:$src, i16), - (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>; -def : Pat<(sext_inreg GR32:$src, i8), - (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>; - -def : Pat<(sext_inreg GR16:$src, i8), - (EXTRACT_SUBREG (MOVSX32rr8 (EXTRACT_SUBREG GR16:$src, sub_8bit)), - sub_16bit)>; - -def : Pat<(sext_inreg GR64:$src, i32), - (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>; -def : Pat<(sext_inreg GR64:$src, i16), - (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>; -def : Pat<(sext_inreg GR64:$src, i8), - (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>; - -// sext, sext_load, zext, zext_load -def: Pat<(i16 (sext GR8:$src)), - (EXTRACT_SUBREG (MOVSX32rr8 GR8:$src), sub_16bit)>; -def: Pat<(sextloadi16i8 addr:$src), - (EXTRACT_SUBREG (MOVSX32rm8 addr:$src), sub_16bit)>; -def: Pat<(i16 (zext GR8:$src)), - (EXTRACT_SUBREG (MOVZX32rr8 GR8:$src), sub_16bit)>; -def: Pat<(zextloadi16i8 addr:$src), - (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>; - -// trunc patterns -def : Pat<(i16 (trunc GR32:$src)), - (EXTRACT_SUBREG GR32:$src, sub_16bit)>; -def : Pat<(i8 (trunc GR32:$src)), - (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), - sub_8bit)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc GR16:$src)), - (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), - sub_8bit)>, - Requires<[Not64BitMode]>; -def : Pat<(i32 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_32bit)>; -def : Pat<(i16 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_16bit)>; -def : Pat<(i8 (trunc GR64:$src)), - (EXTRACT_SUBREG GR64:$src, sub_8bit)>; -def : Pat<(i8 (trunc GR32:$src)), - (EXTRACT_SUBREG GR32:$src, sub_8bit)>, - Requires<[In64BitMode]>; -def : Pat<(i8 (trunc GR16:$src)), - (EXTRACT_SUBREG GR16:$src, sub_8bit)>, - Requires<[In64BitMode]>; - -def immff00_ffff : ImmLeaf= 0xff00 && Imm <= 0xffff; -}]>; - -// h-register tricks -def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc (srl_su (i32 (anyext GR16:$src)), (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))), - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(srl GR16:$src, (i8 8)), - (EXTRACT_SUBREG - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_16bit)>; -def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; -def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; -def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; -def : Pat<(srl (and_su GR32:$src, immff00_ffff), (i8 8)), - (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; - -// h-register tricks. -// For now, be conservative on x86-64 and use an h-register extract only if the -// value is immediately zero-extended or stored, which are somewhat common -// cases. This uses a bunch of code to prevent a register requiring a REX prefix -// from being allocated in the same instruction as the h register, as there's -// currently no way to describe this requirement to the register allocator. - -// h-register extract and zero-extend. -def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi)), - sub_32bit)>; -def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_32bit)>; -def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))), - (SUBREG_TO_REG - (i64 0), - (MOVZX32rr8_NOREX - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_32bit)>; - -// h-register extract and store. -def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi))>; -def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>, - Requires<[In64BitMode]>; -def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), - (MOV8mr_NOREX - addr:$dst, - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>, - Requires<[In64BitMode]>; - - -// (shl x, 1) ==> (add x, x) -// Note that if x is undef (immediate or otherwise), we could theoretically -// end up with the two uses of x getting different values, producing a result -// where the least significant bit is not 0. However, the probability of this -// happening is considered low enough that this is officially not a -// "real problem". -def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr GR8 :$src1, GR8 :$src1)>; -def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; -def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; -def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; - -// Helper imms to check if a mask doesn't change significant shift/rotate bits. -def immShift8 : ImmLeaf(Imm) >= 3; -}]>; -def immShift16 : ImmLeaf(Imm) >= 4; -}]>; -def immShift32 : ImmLeaf(Imm) >= 5; -}]>; -def immShift64 : ImmLeaf(Imm) >= 6; -}]>; - -// Shift amount is implicitly masked. -multiclass MaskedShiftAmountPats { - // (shift x (and y, 31)) ==> (shift x, y) - def : Pat<(frag GR8:$src1, (and CL, immShift32)), - (!cast(name # "8rCL") GR8:$src1)>; - def : Pat<(frag GR16:$src1, (and CL, immShift32)), - (!cast(name # "16rCL") GR16:$src1)>; - def : Pat<(frag GR32:$src1, (and CL, immShift32)), - (!cast(name # "32rCL") GR32:$src1)>; - def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "8mCL") addr:$dst)>; - def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "16mCL") addr:$dst)>; - def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "32mCL") addr:$dst)>; - - // (shift x (and y, 63)) ==> (shift x, y) - def : Pat<(frag GR64:$src1, (and CL, immShift64)), - (!cast(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), - (!cast(name # "64mCL") addr:$dst)>; -} - -defm : MaskedShiftAmountPats; -defm : MaskedShiftAmountPats; -defm : MaskedShiftAmountPats; - -// ROL/ROR instructions allow a stronger mask optimization than shift for 8- and -// 16-bit. We can remove a mask of any (bitwidth - 1) on the rotation amount -// because over-rotating produces the same result. This is noted in the Intel -// docs with: "tempCOUNT <- (COUNT & COUNTMASK) MOD SIZE". Masking the rotation -// amount could affect EFLAGS results, but that does not matter because we are -// not tracking flags for these nodes. -multiclass MaskedRotateAmountPats { - // (rot x (and y, BitWidth - 1)) ==> (rot x, y) - def : Pat<(frag GR8:$src1, (and CL, immShift8)), - (!cast(name # "8rCL") GR8:$src1)>; - def : Pat<(frag GR16:$src1, (and CL, immShift16)), - (!cast(name # "16rCL") GR16:$src1)>; - def : Pat<(frag GR32:$src1, (and CL, immShift32)), - (!cast(name # "32rCL") GR32:$src1)>; - def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift8)), addr:$dst), - (!cast(name # "8mCL") addr:$dst)>; - def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift16)), addr:$dst), - (!cast(name # "16mCL") addr:$dst)>; - def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast(name # "32mCL") addr:$dst)>; - - // (rot x (and y, 63)) ==> (rot x, y) - def : Pat<(frag GR64:$src1, (and CL, immShift64)), - (!cast(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), - (!cast(name # "64mCL") addr:$dst)>; -} - - -defm : MaskedRotateAmountPats; -defm : MaskedRotateAmountPats; - -// Double shift amount is implicitly masked. -multiclass MaskedDoubleShiftAmountPats { - // (shift x (and y, 31)) ==> (shift x, y) - def : Pat<(frag GR16:$src1, GR16:$src2, (and CL, immShift32)), - (!cast(name # "16rrCL") GR16:$src1, GR16:$src2)>; - def : Pat<(frag GR32:$src1, GR32:$src2, (and CL, immShift32)), - (!cast(name # "32rrCL") GR32:$src1, GR32:$src2)>; - - // (shift x (and y, 63)) ==> (shift x, y) - def : Pat<(frag GR64:$src1, GR64:$src2, (and CL, immShift64)), - (!cast(name # "64rrCL") GR64:$src1, GR64:$src2)>; -} - -defm : MaskedDoubleShiftAmountPats; -defm : MaskedDoubleShiftAmountPats; - -let Predicates = [HasBMI2] in { - let AddedComplexity = 1 in { - def : Pat<(sra GR32:$src1, (and GR8:$src2, immShift32)), - (SARX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra GR64:$src1, (and GR8:$src2, immShift64)), - (SARX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl GR32:$src1, (and GR8:$src2, immShift32)), - (SHRX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl GR64:$src1, (and GR8:$src2, immShift64)), - (SHRX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl GR32:$src1, (and GR8:$src2, immShift32)), - (SHLX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl GR64:$src1, (and GR8:$src2, immShift64)), - (SHLX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } - - def : Pat<(sra (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SARX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SARX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHRX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHRX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHLX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHLX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} - -// Use BTR/BTS/BTC for clearing/setting/toggling a bit in a variable location. -multiclass one_bit_patterns { - def : Pat<(and RC:$src1, (rotl -2, GR8:$src2)), - (BTR RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(or RC:$src1, (shl 1, GR8:$src2)), - (BTS RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(xor RC:$src1, (shl 1, GR8:$src2)), - (BTC RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - // Similar to above, but removing unneeded masking of the shift amount. - def : Pat<(and RC:$src1, (rotl -2, (and GR8:$src2, ImmShift))), - (BTR RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(or RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), - (BTS RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(xor RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), - (BTC RC:$src1, - (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} - -defm : one_bit_patterns; -defm : one_bit_patterns; -defm : one_bit_patterns; - - -// (anyext (setcc_carry)) -> (setcc_carry) -def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C16r)>; -def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; -def : Pat<(i32 (anyext (i16 (X86setcc_c X86_COND_B, EFLAGS)))), - (SETB_C32r)>; - -//===----------------------------------------------------------------------===// -// EFLAGS-defining Patterns -//===----------------------------------------------------------------------===// - -// add reg, reg -def : Pat<(add GR8 :$src1, GR8 :$src2), (ADD8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(add GR16:$src1, GR16:$src2), (ADD16rr GR16:$src1, GR16:$src2)>; -def : Pat<(add GR32:$src1, GR32:$src2), (ADD32rr GR32:$src1, GR32:$src2)>; -def : Pat<(add GR64:$src1, GR64:$src2), (ADD64rr GR64:$src1, GR64:$src2)>; - -// add reg, mem -def : Pat<(add GR8:$src1, (loadi8 addr:$src2)), - (ADD8rm GR8:$src1, addr:$src2)>; -def : Pat<(add GR16:$src1, (loadi16 addr:$src2)), - (ADD16rm GR16:$src1, addr:$src2)>; -def : Pat<(add GR32:$src1, (loadi32 addr:$src2)), - (ADD32rm GR32:$src1, addr:$src2)>; -def : Pat<(add GR64:$src1, (loadi64 addr:$src2)), - (ADD64rm GR64:$src1, addr:$src2)>; - -// add reg, imm -def : Pat<(add GR8 :$src1, imm:$src2), (ADD8ri GR8:$src1 , imm:$src2)>; -def : Pat<(add GR16:$src1, imm:$src2), (ADD16ri GR16:$src1, imm:$src2)>; -def : Pat<(add GR32:$src1, imm:$src2), (ADD32ri GR32:$src1, imm:$src2)>; -def : Pat<(add GR16:$src1, i16immSExt8:$src2), - (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(add GR32:$src1, i32immSExt8:$src2), - (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(add GR64:$src1, i64immSExt8:$src2), - (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(add GR64:$src1, i64immSExt32:$src2), - (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// sub reg, reg -def : Pat<(sub GR8 :$src1, GR8 :$src2), (SUB8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(sub GR16:$src1, GR16:$src2), (SUB16rr GR16:$src1, GR16:$src2)>; -def : Pat<(sub GR32:$src1, GR32:$src2), (SUB32rr GR32:$src1, GR32:$src2)>; -def : Pat<(sub GR64:$src1, GR64:$src2), (SUB64rr GR64:$src1, GR64:$src2)>; - -// sub reg, mem -def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)), - (SUB8rm GR8:$src1, addr:$src2)>; -def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)), - (SUB16rm GR16:$src1, addr:$src2)>; -def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)), - (SUB32rm GR32:$src1, addr:$src2)>; -def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)), - (SUB64rm GR64:$src1, addr:$src2)>; - -// sub reg, imm -def : Pat<(sub GR8:$src1, imm:$src2), - (SUB8ri GR8:$src1, imm:$src2)>; -def : Pat<(sub GR16:$src1, imm:$src2), - (SUB16ri GR16:$src1, imm:$src2)>; -def : Pat<(sub GR32:$src1, imm:$src2), - (SUB32ri GR32:$src1, imm:$src2)>; -def : Pat<(sub GR16:$src1, i16immSExt8:$src2), - (SUB16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(sub GR32:$src1, i32immSExt8:$src2), - (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(sub GR64:$src1, i64immSExt8:$src2), - (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(sub GR64:$src1, i64immSExt32:$src2), - (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// sub 0, reg -def : Pat<(X86sub_flag 0, GR8 :$src), (NEG8r GR8 :$src)>; -def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>; -def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>; -def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>; - -// sub reg, relocImm -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt8_su:$src2), - (SUB64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>; -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt32_su:$src2), - (SUB64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>; - -// mul reg, reg -def : Pat<(mul GR16:$src1, GR16:$src2), - (IMUL16rr GR16:$src1, GR16:$src2)>; -def : Pat<(mul GR32:$src1, GR32:$src2), - (IMUL32rr GR32:$src1, GR32:$src2)>; -def : Pat<(mul GR64:$src1, GR64:$src2), - (IMUL64rr GR64:$src1, GR64:$src2)>; - -// mul reg, mem -def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)), - (IMUL16rm GR16:$src1, addr:$src2)>; -def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)), - (IMUL32rm GR32:$src1, addr:$src2)>; -def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)), - (IMUL64rm GR64:$src1, addr:$src2)>; - -// mul reg, imm -def : Pat<(mul GR16:$src1, imm:$src2), - (IMUL16rri GR16:$src1, imm:$src2)>; -def : Pat<(mul GR32:$src1, imm:$src2), - (IMUL32rri GR32:$src1, imm:$src2)>; -def : Pat<(mul GR16:$src1, i16immSExt8:$src2), - (IMUL16rri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(mul GR32:$src1, i32immSExt8:$src2), - (IMUL32rri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(mul GR64:$src1, i64immSExt8:$src2), - (IMUL64rri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(mul GR64:$src1, i64immSExt32:$src2), - (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>; - -// reg = mul mem, imm -def : Pat<(mul (loadi16 addr:$src1), imm:$src2), - (IMUL16rmi addr:$src1, imm:$src2)>; -def : Pat<(mul (loadi32 addr:$src1), imm:$src2), - (IMUL32rmi addr:$src1, imm:$src2)>; -def : Pat<(mul (loadi16 addr:$src1), i16immSExt8:$src2), - (IMUL16rmi8 addr:$src1, i16immSExt8:$src2)>; -def : Pat<(mul (loadi32 addr:$src1), i32immSExt8:$src2), - (IMUL32rmi8 addr:$src1, i32immSExt8:$src2)>; -def : Pat<(mul (loadi64 addr:$src1), i64immSExt8:$src2), - (IMUL64rmi8 addr:$src1, i64immSExt8:$src2)>; -def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2), - (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>; - -// Increment/Decrement reg. -// Do not make INC/DEC if it is slow -let Predicates = [UseIncDec] in { - def : Pat<(add GR8:$src, 1), (INC8r GR8:$src)>; - def : Pat<(add GR16:$src, 1), (INC16r GR16:$src)>; - def : Pat<(add GR32:$src, 1), (INC32r GR32:$src)>; - def : Pat<(add GR64:$src, 1), (INC64r GR64:$src)>; - def : Pat<(add GR8:$src, -1), (DEC8r GR8:$src)>; - def : Pat<(add GR16:$src, -1), (DEC16r GR16:$src)>; - def : Pat<(add GR32:$src, -1), (DEC32r GR32:$src)>; - def : Pat<(add GR64:$src, -1), (DEC64r GR64:$src)>; -} - -// or reg/reg. -def : Pat<(or GR8 :$src1, GR8 :$src2), (OR8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(or GR16:$src1, GR16:$src2), (OR16rr GR16:$src1, GR16:$src2)>; -def : Pat<(or GR32:$src1, GR32:$src2), (OR32rr GR32:$src1, GR32:$src2)>; -def : Pat<(or GR64:$src1, GR64:$src2), (OR64rr GR64:$src1, GR64:$src2)>; - -// or reg/mem -def : Pat<(or GR8:$src1, (loadi8 addr:$src2)), - (OR8rm GR8:$src1, addr:$src2)>; -def : Pat<(or GR16:$src1, (loadi16 addr:$src2)), - (OR16rm GR16:$src1, addr:$src2)>; -def : Pat<(or GR32:$src1, (loadi32 addr:$src2)), - (OR32rm GR32:$src1, addr:$src2)>; -def : Pat<(or GR64:$src1, (loadi64 addr:$src2)), - (OR64rm GR64:$src1, addr:$src2)>; - -// or reg/imm -def : Pat<(or GR8:$src1 , imm:$src2), (OR8ri GR8 :$src1, imm:$src2)>; -def : Pat<(or GR16:$src1, imm:$src2), (OR16ri GR16:$src1, imm:$src2)>; -def : Pat<(or GR32:$src1, imm:$src2), (OR32ri GR32:$src1, imm:$src2)>; -def : Pat<(or GR16:$src1, i16immSExt8:$src2), - (OR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(or GR32:$src1, i32immSExt8:$src2), - (OR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(or GR64:$src1, i64immSExt8:$src2), - (OR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(or GR64:$src1, i64immSExt32:$src2), - (OR64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// xor reg/reg -def : Pat<(xor GR8 :$src1, GR8 :$src2), (XOR8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(xor GR16:$src1, GR16:$src2), (XOR16rr GR16:$src1, GR16:$src2)>; -def : Pat<(xor GR32:$src1, GR32:$src2), (XOR32rr GR32:$src1, GR32:$src2)>; -def : Pat<(xor GR64:$src1, GR64:$src2), (XOR64rr GR64:$src1, GR64:$src2)>; - -// xor reg/mem -def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)), - (XOR8rm GR8:$src1, addr:$src2)>; -def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)), - (XOR16rm GR16:$src1, addr:$src2)>; -def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)), - (XOR32rm GR32:$src1, addr:$src2)>; -def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)), - (XOR64rm GR64:$src1, addr:$src2)>; - -// xor reg/imm -def : Pat<(xor GR8:$src1, imm:$src2), - (XOR8ri GR8:$src1, imm:$src2)>; -def : Pat<(xor GR16:$src1, imm:$src2), - (XOR16ri GR16:$src1, imm:$src2)>; -def : Pat<(xor GR32:$src1, imm:$src2), - (XOR32ri GR32:$src1, imm:$src2)>; -def : Pat<(xor GR16:$src1, i16immSExt8:$src2), - (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(xor GR32:$src1, i32immSExt8:$src2), - (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(xor GR64:$src1, i64immSExt8:$src2), - (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(xor GR64:$src1, i64immSExt32:$src2), - (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// and reg/reg -def : Pat<(and GR8 :$src1, GR8 :$src2), (AND8rr GR8 :$src1, GR8 :$src2)>; -def : Pat<(and GR16:$src1, GR16:$src2), (AND16rr GR16:$src1, GR16:$src2)>; -def : Pat<(and GR32:$src1, GR32:$src2), (AND32rr GR32:$src1, GR32:$src2)>; -def : Pat<(and GR64:$src1, GR64:$src2), (AND64rr GR64:$src1, GR64:$src2)>; - -// and reg/mem -def : Pat<(and GR8:$src1, (loadi8 addr:$src2)), - (AND8rm GR8:$src1, addr:$src2)>; -def : Pat<(and GR16:$src1, (loadi16 addr:$src2)), - (AND16rm GR16:$src1, addr:$src2)>; -def : Pat<(and GR32:$src1, (loadi32 addr:$src2)), - (AND32rm GR32:$src1, addr:$src2)>; -def : Pat<(and GR64:$src1, (loadi64 addr:$src2)), - (AND64rm GR64:$src1, addr:$src2)>; - -// and reg/imm -def : Pat<(and GR8:$src1, imm:$src2), - (AND8ri GR8:$src1, imm:$src2)>; -def : Pat<(and GR16:$src1, imm:$src2), - (AND16ri GR16:$src1, imm:$src2)>; -def : Pat<(and GR32:$src1, imm:$src2), - (AND32ri GR32:$src1, imm:$src2)>; -def : Pat<(and GR16:$src1, i16immSExt8:$src2), - (AND16ri8 GR16:$src1, i16immSExt8:$src2)>; -def : Pat<(and GR32:$src1, i32immSExt8:$src2), - (AND32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(and GR64:$src1, i64immSExt8:$src2), - (AND64ri8 GR64:$src1, i64immSExt8:$src2)>; -def : Pat<(and GR64:$src1, i64immSExt32:$src2), - (AND64ri32 GR64:$src1, i64immSExt32:$src2)>; - -// Bit scan instruction patterns to match explicit zero-undef behavior. -def : Pat<(cttz_zero_undef GR16:$src), (BSF16rr GR16:$src)>; -def : Pat<(cttz_zero_undef GR32:$src), (BSF32rr GR32:$src)>; -def : Pat<(cttz_zero_undef GR64:$src), (BSF64rr GR64:$src)>; -def : Pat<(cttz_zero_undef (loadi16 addr:$src)), (BSF16rm addr:$src)>; -def : Pat<(cttz_zero_undef (loadi32 addr:$src)), (BSF32rm addr:$src)>; -def : Pat<(cttz_zero_undef (loadi64 addr:$src)), (BSF64rm addr:$src)>; - -// When HasMOVBE is enabled it is possible to get a non-legalized -// register-register 16 bit bswap. This maps it to a ROL instruction. -let Predicates = [HasMOVBE] in { - def : Pat<(bswap GR16:$src), (ROL16ri GR16:$src, (i8 8))>; -} - -// These patterns are selected by some custom code in X86ISelDAGToDAG.cpp that -// custom combines and+srl into BEXTR. We use these patterns to avoid a bunch -// of manual code for folding loads. -let Predicates = [HasBMI, NoTBM] in { - def : Pat<(X86bextr GR32:$src1, (i32 imm:$src2)), - (BEXTR32rr GR32:$src1, (MOV32ri imm:$src2))>; - def : Pat<(X86bextr (loadi32 addr:$src1), (i32 imm:$src2)), - (BEXTR32rm addr:$src1, (MOV32ri imm:$src2))>; - def : Pat<(X86bextr GR64:$src1, mov64imm32:$src2), - (BEXTR64rr GR64:$src1, - (SUBREG_TO_REG (i64 0), - (MOV32ri64 mov64imm32:$src2), - sub_32bit))>; - def : Pat<(X86bextr (loadi64 addr:$src1), mov64imm32:$src2), - (BEXTR64rm addr:$src1, - (SUBREG_TO_REG (i64 0), - (MOV32ri64 mov64imm32:$src2), - sub_32bit))>; -} // HasBMI, NoTBM diff --git a/suite/synctools/tablegen/X86/back/X86InstrControl.td b/suite/synctools/tablegen/X86/back/X86InstrControl.td deleted file mode 100644 index 3271b43e3f..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrControl.td +++ /dev/null @@ -1,413 +0,0 @@ -//===-- X86InstrControl.td - Control Flow Instructions -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 jump, return, call, and related instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Control Flow Instructions. -// - -// Return instructions. -// -// The X86retflag return instructions are variadic because we may add ST0 and -// ST1 arguments when returning values on the x87 stack. -let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1, FPForm = SpecialFP, SchedRW = [WriteJumpLd] in { - def RETL : I <0xC3, RawFrm, (outs), (ins variable_ops), - "ret{l}", []>, OpSize32, Requires<[Not64BitMode]>; - def RETQ : I <0xC3, RawFrm, (outs), (ins variable_ops), - "ret{q}", []>, OpSize32, Requires<[In64BitMode]>; - def RETW : I <0xC3, RawFrm, (outs), (ins), - "ret{w}", []>, OpSize16; - def RETIL : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), - "ret{l}\t$amt", []>, OpSize32, Requires<[Not64BitMode]>; - def RETIQ : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), - "ret{q}\t$amt", []>, OpSize32, Requires<[In64BitMode]>; - def RETIW : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt), - "ret{w}\t$amt", []>, OpSize16; - def LRETL : I <0xCB, RawFrm, (outs), (ins), - "{l}ret{l|f}", []>, OpSize32; - def LRETQ : RI <0xCB, RawFrm, (outs), (ins), - "{l}ret{|f}q", []>, Requires<[In64BitMode]>; - def LRETW : I <0xCB, RawFrm, (outs), (ins), - "{l}ret{w|f}", []>, OpSize16; - def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{l|f}\t$amt", []>, OpSize32; - def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{|f}q\t$amt", []>, Requires<[In64BitMode]>; - def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), - "{l}ret{w|f}\t$amt", []>, OpSize16; - - // The machine return from interrupt instruction, but sometimes we need to - // perform a post-epilogue stack adjustment. Codegen emits the pseudo form - // which expands to include an SP adjustment if necessary. - def IRET16 : I <0xcf, RawFrm, (outs), (ins), "iret{w}", []>, - OpSize16; - def IRET32 : I <0xcf, RawFrm, (outs), (ins), "iret{l|d}", []>, OpSize32; - def IRET64 : RI <0xcf, RawFrm, (outs), (ins), "iretq", []>, Requires<[In64BitMode]>; - // let isCodeGenOnly = 1 in - // def IRET : PseudoI<(outs), (ins i32imm:$adj), [(X86iret timm:$adj)]>; - // def RET : PseudoI<(outs), (ins i32imm:$adj, variable_ops), [(X86retflag timm:$adj)]>; -} - -// Unconditional branches. -let isBarrier = 1, isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in { - def JMP_1 : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst), - "jmp\t$dst", [(br bb:$dst)]>; - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def JMP_2 : Ii16PCRel<0xE9, RawFrm, (outs), (ins brtarget16:$dst), - "jmp\t$dst", []>, OpSize16; - def JMP_4 : Ii32PCRel<0xE9, RawFrm, (outs), (ins brtarget32:$dst), - "jmp\t$dst", []>, OpSize32; - } -} - -// Conditional Branches. -let isBranch = 1, isTerminator = 1, Uses = [EFLAGS], SchedRW = [WriteJump] in { - multiclass ICBr opc1, bits<8> opc4, string asm, PatFrag Cond> { - def _1 : Ii8PCRel ; - let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { - def _2 : Ii16PCRel, OpSize16, TB; - def _4 : Ii32PCRel, TB, OpSize32; - } - } -} - -defm JO : ICBr<0x70, 0x80, "jo\t$dst" , X86_COND_O>; -defm JNO : ICBr<0x71, 0x81, "jno\t$dst", X86_COND_NO>; -defm JB : ICBr<0x72, 0x82, "jb\t$dst" , X86_COND_B>; -defm JAE : ICBr<0x73, 0x83, "jae\t$dst", X86_COND_AE>; -defm JE : ICBr<0x74, 0x84, "je\t$dst" , X86_COND_E>; -defm JNE : ICBr<0x75, 0x85, "jne\t$dst", X86_COND_NE>; -defm JBE : ICBr<0x76, 0x86, "jbe\t$dst", X86_COND_BE>; -defm JA : ICBr<0x77, 0x87, "ja\t$dst" , X86_COND_A>; -defm JS : ICBr<0x78, 0x88, "js\t$dst" , X86_COND_S>; -defm JNS : ICBr<0x79, 0x89, "jns\t$dst", X86_COND_NS>; -defm JP : ICBr<0x7A, 0x8A, "jp\t$dst" , X86_COND_P>; -defm JNP : ICBr<0x7B, 0x8B, "jnp\t$dst", X86_COND_NP>; -defm JL : ICBr<0x7C, 0x8C, "jl\t$dst" , X86_COND_L>; -defm JGE : ICBr<0x7D, 0x8D, "jge\t$dst", X86_COND_GE>; -defm JLE : ICBr<0x7E, 0x8E, "jle\t$dst", X86_COND_LE>; -defm JG : ICBr<0x7F, 0x8F, "jg\t$dst" , X86_COND_G>; - -// jcx/jecx/jrcx instructions. -let isBranch = 1, isTerminator = 1, hasSideEffects = 0, SchedRW = [WriteJump] in { - // These are the 32-bit versions of this instruction for the asmparser. In - // 32-bit mode, the address size prefix is jcxz and the unprefixed version is - // jecxz. - let Uses = [CX] in - def JCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jcxz\t$dst", []>, AdSize16, Requires<[Not64BitMode]>; - let Uses = [ECX] in - def JECXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jecxz\t$dst", []>, AdSize32; - - let Uses = [RCX] in - def JRCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), - "jrcxz\t$dst", []>, AdSize64, Requires<[In64BitMode]>; -} - -// Indirect branches -let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { - def JMP16r : I<0xFF, MRM4r, (outs), (ins GR16:$dst), "jmp{w}\t{*}$dst", - [(brind GR16:$dst)]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJump]>; - def JMP16m : I<0xFF, MRM4m, (outs), (ins i16mem:$dst), "jmp{w}\t{*}$dst", - [(brind (loadi16 addr:$dst))]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJumpLd]>; - - def JMP32r : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst", - [(brind GR32:$dst)]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJump]>; - def JMP32m : I<0xFF, MRM4m, (outs), (ins i32mem:$dst), "jmp{l}\t{*}$dst", - [(brind (loadi32 addr:$dst))]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJumpLd]>; - - def JMP64r : I<0xFF, MRM4r, (outs), (ins GR64:$dst), "jmp{q}\t{*}$dst", - [(brind GR64:$dst)]>, Requires<[In64BitMode]>, - Sched<[WriteJump]>; - def JMP64m : I<0xFF, MRM4m, (outs), (ins i64mem:$dst), "jmp{q}\t{*}$dst", - [(brind (loadi64 addr:$dst))]>, Requires<[In64BitMode]>, - Sched<[WriteJumpLd]>; - - // Non-tracking jumps for IBT, use with caution. - let isCodeGenOnly = 1 in { - def JMP16r_NT : I<0xFF, MRM4r, (outs), (ins GR16 : $dst), "jmp{w}\t{*}$dst", - [(X86NoTrackBrind GR16 : $dst)]>, Requires<[Not64BitMode]>, - OpSize16, Sched<[WriteJump]>, NOTRACK; - - def JMP16m_NT : I<0xFF, MRM4m, (outs), (ins i16mem : $dst), "jmp{w}\t{*}$dst", - [(X86NoTrackBrind (loadi16 addr : $dst))]>, - Requires<[Not64BitMode]>, OpSize16, Sched<[WriteJumpLd]>, - NOTRACK; - - def JMP32r_NT : I<0xFF, MRM4r, (outs), (ins GR32 : $dst), "jmp{l}\t{*}$dst", - [(X86NoTrackBrind GR32 : $dst)]>, Requires<[Not64BitMode]>, - OpSize32, Sched<[WriteJump]>, NOTRACK; - def JMP32m_NT : I<0xFF, MRM4m, (outs), (ins i32mem : $dst), "jmp{l}\t{*}$dst", - [(X86NoTrackBrind (loadi32 addr : $dst))]>, - Requires<[Not64BitMode]>, OpSize32, Sched<[WriteJumpLd]>, - NOTRACK; - - def JMP64r_NT : I<0xFF, MRM4r, (outs), (ins GR64 : $dst), "jmp{q}\t{*}$dst", - [(X86NoTrackBrind GR64 : $dst)]>, Requires<[In64BitMode]>, - Sched<[WriteJump]>, NOTRACK; - def JMP64m_NT : I<0xFF, MRM4m, (outs), (ins i64mem : $dst), "jmp{q}\t{*}$dst", - [(X86NoTrackBrind(loadi64 addr : $dst))]>, - Requires<[In64BitMode]>, Sched<[WriteJumpLd]>, NOTRACK; - } - - let Predicates = [Not64BitMode], AsmVariantName = "att" in { - def FARJMP16i : Iseg16<0xEA, RawFrmImm16, (outs), - (ins i16imm:$off, i16imm:$seg), - "ljmp{w}\t$seg : $off", []>, - OpSize16, Sched<[WriteJump]>; - def FARJMP32i : Iseg32<0xEA, RawFrmImm16, (outs), - (ins i32imm:$off, i16imm:$seg), - "ljmp{l}\t$seg : $off", []>, - OpSize32, Sched<[WriteJump]>; - } - def FARJMP64 : RI<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "ljmp{q}\t{*}$dst", []>, Sched<[WriteJump]>, Requires<[In64BitMode]>; - - let AsmVariantName = "att" in - def FARJMP16m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "ljmp{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; - def FARJMP32m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), - "{l}jmp{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; -} - -// Loop instructions -let SchedRW = [WriteJump] in { -def LOOP : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", []>; -def LOOPE : Ii8PCRel<0xE1, RawFrm, (outs), (ins brtarget8:$dst), "loope\t$dst", []>; -def LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins brtarget8:$dst), "loopne\t$dst", []>; -} - -//===----------------------------------------------------------------------===// -// Call Instructions... -// -let isCall = 1 in - // All calls clobber the non-callee saved registers. ESP is marked as - // a use to prevent stack-pointer assignments that appear immediately - // before calls from potentially appearing dead. Uses for argument - // registers are added manually. - let Uses = [ESP, SSP] in { - def CALLpcrel32 : Ii32PCRel<0xE8, RawFrm, - (outs), (ins i32imm_pcrel:$dst), - "call{l}\t$dst", []>, OpSize32, - Requires<[Not64BitMode]>, Sched<[WriteJump]>; - let hasSideEffects = 0 in - def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm, - (outs), (ins i16imm_pcrel:$dst), - "call{w}\t$dst", []>, OpSize16, - Sched<[WriteJump]>; - def CALL16r : I<0xFF, MRM2r, (outs), (ins GR16:$dst), - "call{w}\t{*}$dst", [(X86call GR16:$dst)]>, - OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>; - def CALL16m : I<0xFF, MRM2m, (outs), (ins i16mem:$dst), - "call{w}\t{*}$dst", [(X86call (loadi16 addr:$dst))]>, - OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>; - def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst), - "call{l}\t{*}$dst", [(X86call GR32:$dst)]>, OpSize32, - Requires<[Not64BitMode,NotUseRetpoline]>, Sched<[WriteJump]>; - def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst), - "call{l}\t{*}$dst", [(X86call (loadi32 addr:$dst))]>, - OpSize32, - Requires<[Not64BitMode,FavorMemIndirectCall,NotUseRetpoline]>, - Sched<[WriteJumpLd]>; - - // Non-tracking calls for IBT, use with caution. - let isCodeGenOnly = 1 in { - def CALL16r_NT : I<0xFF, MRM2r, (outs), (ins GR16 : $dst), - "call{w}\t{*}$dst",[(X86NoTrackCall GR16 : $dst)]>, - OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; - def CALL16m_NT : I<0xFF, MRM2m, (outs), (ins i16mem : $dst), - "call{w}\t{*}$dst",[(X86NoTrackCall(loadi16 addr : $dst))]>, - OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>, NOTRACK; - def CALL32r_NT : I<0xFF, MRM2r, (outs), (ins GR32 : $dst), - "call{l}\t{*}$dst",[(X86NoTrackCall GR32 : $dst)]>, - OpSize32, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; - def CALL32m_NT : I<0xFF, MRM2m, (outs), (ins i32mem : $dst), - "call{l}\t{*}$dst",[(X86NoTrackCall(loadi32 addr : $dst))]>, - OpSize32, Requires<[Not64BitMode,FavorMemIndirectCall]>, - Sched<[WriteJumpLd]>, NOTRACK; - } - - let Predicates = [Not64BitMode], AsmVariantName = "att" in { - def FARCALL16i : Iseg16<0x9A, RawFrmImm16, (outs), - (ins i16imm:$off, i16imm:$seg), - "lcall{w}\t$seg : $off", []>, - OpSize16, Sched<[WriteJump]>; - def FARCALL32i : Iseg32<0x9A, RawFrmImm16, (outs), - (ins i32imm:$off, i16imm:$seg), - "lcall{l}\t$seg : $off", []>, - OpSize32, Sched<[WriteJump]>; - } - - def FARCALL16m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "lcall{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; - def FARCALL32m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "{l}call{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; - } - - -/* -// Tail call stuff. -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [ESP, SSP] in { - def TCRETURNdi : PseudoI<(outs), - (ins i32imm_pcrel:$dst, i32imm:$offset), []>, NotMemoryFoldable; - def TCRETURNri : PseudoI<(outs), - (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>, NotMemoryFoldable; - let mayLoad = 1 in - def TCRETURNmi : PseudoI<(outs), - (ins i32mem_TC:$dst, i32imm:$offset), []>; - - // FIXME: The should be pseudo instructions that are lowered when going to - // mcinst. - def TAILJMPd : Ii32PCRel<0xE9, RawFrm, (outs), - (ins i32imm_pcrel:$dst), "jmp\t$dst", []>; - - def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "", []>; // FIXME: Remove encoding when JIT is dead. - let mayLoad = 1 in - def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem_TC:$dst), - "jmp{l}\t{*}$dst", []>; -} - -// Conditional tail calls are similar to the above, but they are branches -// rather than barriers, and they use EFLAGS. -let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [ESP, EFLAGS, SSP] in { - def TCRETURNdicc : PseudoI<(outs), - (ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>; - - // This gets substituted to a conditional jump instruction in MC lowering. - def TAILJMPd_CC : Ii32PCRel<0x80, RawFrm, (outs), - (ins i32imm_pcrel:$dst, i32imm:$cond), "", []>; -} -*/ - - -//===----------------------------------------------------------------------===// -// Call Instructions... -// - -// RSP is marked as a use to prevent stack-pointer assignments that appear -// immediately before calls from potentially appearing dead. Uses for argument -// registers are added manually. -let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in { - // NOTE: this pattern doesn't match "X86call imm", because we do not know - // that the offset between an arbitrary immediate and the call will fit in - // the 32-bit pcrel field that we have. - def CALL64pcrel32 : Ii32PCRel<0xE8, RawFrm, - (outs), (ins i64i32imm_pcrel:$dst), - "call{q}\t$dst", []>, OpSize32, - Requires<[In64BitMode]>; - def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst), - "call{q}\t{*}$dst", [(X86call GR64:$dst)]>, - Requires<[In64BitMode,NotUseRetpoline]>; - def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst), - "call{q}\t{*}$dst", [(X86call (loadi64 addr:$dst))]>, - Requires<[In64BitMode,FavorMemIndirectCall, - NotUseRetpoline]>; - - // Non-tracking calls for IBT, use with caution. - let isCodeGenOnly = 1 in { - def CALL64r_NT : I<0xFF, MRM2r, (outs), (ins GR64 : $dst), - "call{q}\t{*}$dst",[(X86NoTrackCall GR64 : $dst)]>, - Requires<[In64BitMode]>, NOTRACK; - def CALL64m_NT : I<0xFF, MRM2m, (outs), (ins i64mem : $dst), - "call{q}\t{*}$dst", - [(X86NoTrackCall(loadi64 addr : $dst))]>, - Requires<[In64BitMode,FavorMemIndirectCall]>, NOTRACK; - } - - def FARCALL64 : RI<0xFF, MRM3m, (outs), (ins opaquemem:$dst), - "lcall{q}\t{*}$dst", []>; -} - -/* -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, - isCodeGenOnly = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in { - def TCRETURNdi64 : PseudoI<(outs), - (ins i64i32imm_pcrel:$dst, i32imm:$offset), - []>; - def TCRETURNri64 : PseudoI<(outs), - (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>, NotMemoryFoldable; - let mayLoad = 1 in - def TCRETURNmi64 : PseudoI<(outs), - (ins i64mem_TC:$dst, i32imm:$offset), []>, NotMemoryFoldable; - - def TAILJMPd64 : Ii32PCRel<0xE9, RawFrm, (outs), (ins i64i32imm_pcrel:$dst), - "jmp\t$dst", []>; - - def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "jmp{q}\t{*}$dst", []>; - - let mayLoad = 1 in - def TAILJMPm64 : I<0xFF, MRM4m, (outs), (ins i64mem_TC:$dst), - "jmp{q}\t{*}$dst", []>; - - // Win64 wants indirect jumps leaving the function to have a REX_W prefix. - let hasREX_WPrefix = 1 in { - def TAILJMPr64_REX : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst), - "rex64 jmp{q}\t{*}$dst", []>; - - let mayLoad = 1 in - def TAILJMPm64_REX : I<0xFF, MRM4m, (outs), (ins i64mem_TC:$dst), - "rex64 jmp{q}\t{*}$dst", []>; - } -} - -let isPseudo = 1, isCall = 1, isCodeGenOnly = 1, - Uses = [RSP, SSP], - usesCustomInserter = 1, - SchedRW = [WriteJump] in { - def RETPOLINE_CALL32 : - PseudoI<(outs), (ins GR32:$dst), [(X86call GR32:$dst)]>, - Requires<[Not64BitMode,UseRetpoline]>; - - def RETPOLINE_CALL64 : - PseudoI<(outs), (ins GR64:$dst), [(X86call GR64:$dst)]>, - Requires<[In64BitMode,UseRetpoline]>; - - // Retpoline variant of indirect tail calls. - let isTerminator = 1, isReturn = 1, isBarrier = 1 in { - def RETPOLINE_TCRETURN64 : - PseudoI<(outs), (ins GR64:$dst, i32imm:$offset), []>; - def RETPOLINE_TCRETURN32 : - PseudoI<(outs), (ins GR32:$dst, i32imm:$offset), []>; - } -} - -// Conditional tail calls are similar to the above, but they are branches -// rather than barriers, and they use EFLAGS. -let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, - isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in - let Uses = [RSP, EFLAGS, SSP] in { - def TCRETURNdi64cc : PseudoI<(outs), - (ins i64i32imm_pcrel:$dst, i32imm:$offset, - i32imm:$cond), []>; - - // This gets substituted to a conditional jump instruction in MC lowering. - def TAILJMPd64_CC : Ii32PCRel<0x80, RawFrm, (outs), - (ins i64i32imm_pcrel:$dst, i32imm:$cond), "", []>; -} -*/ diff --git a/suite/synctools/tablegen/X86/back/X86InstrExtension.td b/suite/synctools/tablegen/X86/back/X86InstrExtension.td deleted file mode 100644 index 421792c559..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrExtension.td +++ /dev/null @@ -1,204 +0,0 @@ -//===-- X86InstrExtension.td - Sign and Zero Extensions ----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the sign and zero extension operations. -// -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0 in { - let Defs = [AX], Uses = [AL] in // AX = signext(AL) - def CBW : I<0x98, RawFrm, (outs), (ins), - "{cbtw|cbw}", []>, OpSize16, Sched<[WriteALU]>; - let Defs = [EAX], Uses = [AX] in // EAX = signext(AX) - def CWDE : I<0x98, RawFrm, (outs), (ins), - "{cwtl|cwde}", []>, OpSize32, Sched<[WriteALU]>; - - let Defs = [AX,DX], Uses = [AX] in // DX:AX = signext(AX) - def CWD : I<0x99, RawFrm, (outs), (ins), - "{cwtd|cwd}", []>, OpSize16, Sched<[WriteALU]>; - let Defs = [EAX,EDX], Uses = [EAX] in // EDX:EAX = signext(EAX) - def CDQ : I<0x99, RawFrm, (outs), (ins), - "{cltd|cdq}", []>, OpSize32, Sched<[WriteALU]>; - - - let Defs = [RAX], Uses = [EAX] in // RAX = signext(EAX) - def CDQE : RI<0x98, RawFrm, (outs), (ins), - "{cltq|cdqe}", []>, Sched<[WriteALU]>; - - let Defs = [RAX,RDX], Uses = [RAX] in // RDX:RAX = signext(RAX) - def CQO : RI<0x99, RawFrm, (outs), (ins), - "{cqto|cqo}", []>, Sched<[WriteALU]>; -} - -// Sign/Zero extenders -let hasSideEffects = 0 in { -def MOVSX16rr8 : I<0xBE, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src), - "movs{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVSX16rm8 : I<0xBE, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src), - "movs{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALULd]>; -} // hasSideEffects = 0 -def MOVSX32rr8 : I<0xBE, MRMSrcReg, (outs GR32:$dst), (ins GR8:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sext GR8:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVSX32rm8 : I<0xBE, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sextloadi32i8 addr:$src))]>, TB, - OpSize32, Sched<[WriteALULd]>; -def MOVSX32rr16: I<0xBF, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), - "movs{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sext GR16:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVSX32rm16: I<0xBF, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "movs{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (sextloadi32i16 addr:$src))]>, - OpSize32, TB, Sched<[WriteALULd]>; - -let hasSideEffects = 0 in { -def MOVZX16rr8 : I<0xB6, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src), - "movz{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX16rm8 : I<0xB6, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src), - "movz{bw|x}\t{$src, $dst|$dst, $src}", []>, - TB, OpSize16, Sched<[WriteALULd]>; -} // hasSideEffects = 0 -def MOVZX32rr8 : I<0xB6, MRMSrcReg, (outs GR32:$dst), (ins GR8 :$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zext GR8:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVZX32rm8 : I<0xB6, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zextloadi32i8 addr:$src))]>, TB, - OpSize32, Sched<[WriteALULd]>; -def MOVZX32rr16: I<0xB7, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), - "movz{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zext GR16:$src))]>, TB, - OpSize32, Sched<[WriteALU]>; -def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "movz{wl|x}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, - TB, OpSize32, Sched<[WriteALULd]>; - -// These instructions exist as a consequence of operand size prefix having -// control of the destination size, but not the input size. Only support them -// for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOVSX16rr16: I<0xBF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "movs{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALU]>, NotMemoryFoldable; -def MOVZX16rr16: I<0xB7, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "movz{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALU]>, NotMemoryFoldable; -let mayLoad = 1 in { -def MOVSX16rm16: I<0xBF, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movs{ww|x}\t{$src, $dst|$dst, $src}", - []>, OpSize16, TB, Sched<[WriteALULd]>, NotMemoryFoldable; -def MOVZX16rm16: I<0xB7, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movz{ww|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize16, Sched<[WriteALULd]>, NotMemoryFoldable; -} // mayLoad = 1 -} // isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 - -// These are the same as the regular MOVZX32rr8 and MOVZX32rm8 -// except that they use GR32_NOREX for the output operand register class -// instead of GR32. This allows them to operate on h registers on x86-64. -let hasSideEffects = 0, isCodeGenOnly = 1 in { -def MOVZX32rr8_NOREX : I<0xB6, MRMSrcReg, - (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX32rm8_NOREX : I<0xB6, MRMSrcMem, - (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src), - "movz{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALULd]>; - -def MOVSX32rr8_NOREX : I<0xBE, MRMSrcReg, - (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVSX32rm8_NOREX : I<0xBE, MRMSrcMem, - (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src), - "movs{bl|x}\t{$src, $dst|$dst, $src}", - []>, TB, OpSize32, Sched<[WriteALULd]>; -} - -// MOVSX64rr8 always has a REX prefix and it has an 8-bit register -// operand, which makes it a rare instruction with an 8-bit register -// operand that can never access an h register. If support for h registers -// were generalized, this would require a special register class. -def MOVSX64rr8 : RI<0xBE, MRMSrcReg, (outs GR64:$dst), (ins GR8 :$src), - "movs{bq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR8:$src))]>, TB, - Sched<[WriteALU]>; -def MOVSX64rm8 : RI<0xBE, MRMSrcMem, (outs GR64:$dst), (ins i8mem :$src), - "movs{bq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i8 addr:$src))]>, - TB, Sched<[WriteALULd]>; -def MOVSX64rr16: RI<0xBF, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), - "movs{wq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR16:$src))]>, TB, - Sched<[WriteALU]>; -def MOVSX64rm16: RI<0xBF, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "movs{wq|x}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i16 addr:$src))]>, - TB, Sched<[WriteALULd]>; -def MOVSX64rr32: RI<0x63, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "movs{lq|xd}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sext GR32:$src))]>, - Sched<[WriteALU]>, Requires<[In64BitMode]>; -def MOVSX64rm32: RI<0x63, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), - "movs{lq|xd}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (sextloadi64i32 addr:$src))]>, - Sched<[WriteALULd]>, Requires<[In64BitMode]>; - -// movzbq and movzwq encodings for the disassembler -let hasSideEffects = 0 in { -def MOVZX64rr8 : RI<0xB6, MRMSrcReg, (outs GR64:$dst), (ins GR8:$src), - "movz{bq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX64rm8 : RI<0xB6, MRMSrcMem, (outs GR64:$dst), (ins i8mem:$src), - "movz{bq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALULd]>; -def MOVZX64rr16 : RI<0xB7, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), - "movz{wq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALU]>; -let mayLoad = 1 in -def MOVZX64rm16 : RI<0xB7, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "movz{wq|x}\t{$src, $dst|$dst, $src}", []>, - TB, Sched<[WriteALULd]>; -} - -// 64-bit zero-extension patterns use SUBREG_TO_REG and an operation writing a -// 32-bit register. -def : Pat<(i64 (zext GR8:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8:$src), sub_32bit)>; -def : Pat<(zextloadi64i8 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; - -def : Pat<(i64 (zext GR16:$src)), - (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16:$src), sub_32bit)>; -def : Pat<(zextloadi64i16 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>; - -// The preferred way to do 32-bit-to-64-bit zero extension on x86-64 is to use a -// SUBREG_TO_REG to utilize implicit zero-extension, however this isn't possible -// when the 32-bit value is defined by a truncate or is copied from something -// where the high bits aren't necessarily all zero. In such cases, we fall back -// to these explicit zext instructions. -def : Pat<(i64 (zext GR32:$src)), - (SUBREG_TO_REG (i64 0), (MOV32rr GR32:$src), sub_32bit)>; -def : Pat<(i64 (zextloadi64i32 addr:$src)), - (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrFMA.td b/suite/synctools/tablegen/X86/back/X86InstrFMA.td deleted file mode 100644 index 18277417a3..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrFMA.td +++ /dev/null @@ -1,636 +0,0 @@ -//===-- X86InstrFMA.td - FMA Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes FMA (Fused Multiply-Add) instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// FMA3 - Intel 3 operand Fused Multiply-Add instructions -//===----------------------------------------------------------------------===// - -// For all FMA opcodes declared in fma3p_rm_* and fma3s_rm_* multiclasses -// defined below, both the register and memory variants are commutable. -// For the register form the commutable operands are 1, 2 and 3. -// For the memory variant the folded operand must be in 3. Thus, -// in that case, only the operands 1 and 2 can be swapped. -// Commuting some of operands may require the opcode change. -// FMA*213*: -// operands 1 and 2 (memory & register forms): *213* --> *213*(no changes); -// operands 1 and 3 (register forms only): *213* --> *231*; -// operands 2 and 3 (register forms only): *213* --> *132*. -// FMA*132*: -// operands 1 and 2 (memory & register forms): *132* --> *231*; -// operands 1 and 3 (register forms only): *132* --> *132*(no changes); -// operands 2 and 3 (register forms only): *132* --> *213*. -// FMA*231*: -// operands 1 and 2 (memory & register forms): *231* --> *132*; -// operands 1 and 3 (register forms only): *231* --> *213*; -// operands 2 and 3 (register forms only): *231* --> *231*(no changes). - -multiclass fma3p_rm_213 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - def r : FMA3, - Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3p_rm_231 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3, Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3p_rm_132 opc, string OpcodeStr, RegisterClass RC, - ValueType VT, X86MemOperand x86memop, PatFrag MemFrag, - SDNode Op, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - let mayLoad = 1 in - def m : FMA3, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", hasSideEffects = 0, isCommutable = 1 in -multiclass fma3p_forms opc132, bits<8> opc213, bits<8> opc231, - string OpcodeStr, string PackTy, string Suff, - PatFrag MemFrag128, PatFrag MemFrag256, - SDNode Op, ValueType OpTy128, ValueType OpTy256, - X86SchedWriteWidths sched> { - defm NAME#213#Suff : fma3p_rm_213; - defm NAME#231#Suff : fma3p_rm_231; - defm NAME#132#Suff : fma3p_rm_132; - - defm NAME#213#Suff#Y : fma3p_rm_213, - VEX_L; - defm NAME#231#Suff#Y : fma3p_rm_231, - VEX_L; - defm NAME#132#Suff#Y : fma3p_rm_132, - VEX_L; -} - -// Fused Multiply-Add -let ExeDomain = SSEPackedSingle in { - defm VFMADD : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "ps", "PS", - loadv4f32, loadv8f32, X86Fmadd, v4f32, v8f32, - SchedWriteFMA>; - defm VFMSUB : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "ps", "PS", - loadv4f32, loadv8f32, X86Fmsub, v4f32, v8f32, - SchedWriteFMA>; - defm VFMADDSUB : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "ps", "PS", - loadv4f32, loadv8f32, X86Fmaddsub, v4f32, v8f32, - SchedWriteFMA>; - defm VFMSUBADD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "ps", "PS", - loadv4f32, loadv8f32, X86Fmsubadd, v4f32, v8f32, - SchedWriteFMA>; -} - -let ExeDomain = SSEPackedDouble in { - defm VFMADD : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "pd", "PD", - loadv2f64, loadv4f64, X86Fmadd, v2f64, - v4f64, SchedWriteFMA>, VEX_W; - defm VFMSUB : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "pd", "PD", - loadv2f64, loadv4f64, X86Fmsub, v2f64, - v4f64, SchedWriteFMA>, VEX_W; - defm VFMADDSUB : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "pd", "PD", - loadv2f64, loadv4f64, X86Fmaddsub, - v2f64, v4f64, SchedWriteFMA>, VEX_W; - defm VFMSUBADD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "pd", "PD", - loadv2f64, loadv4f64, X86Fmsubadd, - v2f64, v4f64, SchedWriteFMA>, VEX_W; -} - -// Fused Negative Multiply-Add -let ExeDomain = SSEPackedSingle in { - defm VFNMADD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "ps", "PS", loadv4f32, - loadv8f32, X86Fnmadd, v4f32, v8f32, SchedWriteFMA>; - defm VFNMSUB : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "ps", "PS", loadv4f32, - loadv8f32, X86Fnmsub, v4f32, v8f32, SchedWriteFMA>; -} -let ExeDomain = SSEPackedDouble in { - defm VFNMADD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "pd", "PD", loadv2f64, - loadv4f64, X86Fnmadd, v2f64, v4f64, SchedWriteFMA>, VEX_W; - defm VFNMSUB : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "pd", "PD", loadv2f64, - loadv4f64, X86Fnmsub, v2f64, v4f64, SchedWriteFMA>, VEX_W; -} - -// All source register operands of FMA opcodes defined in fma3s_rm multiclass -// can be commuted. In many cases such commute transformation requires an opcode -// adjustment, for example, commuting the operands 1 and 2 in FMA*132 form -// would require an opcode change to FMA*231: -// FMA*132* reg1, reg2, reg3; // reg1 * reg3 + reg2; -// --> -// FMA*231* reg2, reg1, reg3; // reg1 * reg3 + reg2; -// Please see more detailed comment at the very beginning of the section -// defining FMA3 opcodes above. -multiclass fma3s_rm_213 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, - X86FoldableSchedWrite sched> { - def r : FMA3S, - Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3s_rm_231 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3S, Sched<[sched]>; - - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -multiclass fma3s_rm_132 opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - SDPatternOperator OpNode, X86FoldableSchedWrite sched> { - let hasSideEffects = 0 in - def r : FMA3S, Sched<[sched]>; - - // Pattern is 312 order so that the load is in a different place from the - // 213 and 231 patterns this helps tablegen's duplicate pattern detection. - let mayLoad = 1 in - def m : FMA3S, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", isCommutable = 1, hasSideEffects = 0 in -multiclass fma3s_forms opc132, bits<8> opc213, bits<8> opc231, - string OpStr, string PackTy, string Suff, - SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched> { - defm NAME#213#Suff : fma3s_rm_213; - defm NAME#231#Suff : fma3s_rm_231; - defm NAME#132#Suff : fma3s_rm_132; -} - -// These FMA*_Int instructions are defined specially for being used when -// the scalar FMA intrinsics are lowered to machine instructions, and in that -// sense, they are similar to existing ADD*_Int, SUB*_Int, MUL*_Int, etc. -// instructions. -// -// All of the FMA*_Int opcodes are defined as commutable here. -// Commuting the 2nd and 3rd source register operands of FMAs is quite trivial -// and the corresponding optimizations have been developed. -// Commuting the 1st operand of FMA*_Int requires some additional analysis, -// the commute optimization is legal only if all users of FMA*_Int use only -// the lowest element of the FMA*_Int instruction. Even though such analysis -// may be not implemented yet we allow the routines doing the actual commute -// transformation to decide if one or another instruction is commutable or not. -let Constraints = "$src1 = $dst", isCommutable = 1, isCodeGenOnly = 1, - hasSideEffects = 0 in -multiclass fma3s_rm_int opc, string OpcodeStr, - Operand memopr, RegisterClass RC, - X86FoldableSchedWrite sched> { - def r_Int : FMA3S_Int, Sched<[sched]>; - - let mayLoad = 1 in - def m_Int : FMA3S_Int, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; -} - -// The FMA 213 form is created for lowering of scalar FMA intrinscis -// to machine instructions. -// The FMA 132 form can trivially be get by commuting the 2nd and 3rd operands -// of FMA 213 form. -// The FMA 231 form can be get only by commuting the 1st operand of 213 or 132 -// forms and is possible only after special analysis of all uses of the initial -// instruction. Such analysis do not exist yet and thus introducing the 231 -// form of FMA*_Int instructions is done using an optimistic assumption that -// such analysis will be implemented eventually. -multiclass fma3s_int_forms opc132, bits<8> opc213, bits<8> opc231, - string OpStr, string PackTy, string Suff, - RegisterClass RC, Operand memop, - X86FoldableSchedWrite sched> { - defm NAME#132#Suff : fma3s_rm_int; - defm NAME#213#Suff : fma3s_rm_int; - defm NAME#231#Suff : fma3s_rm_int; -} - -multiclass fma3s opc132, bits<8> opc213, bits<8> opc231, - string OpStr, SDNode OpNode, X86FoldableSchedWrite sched> { - let ExeDomain = SSEPackedSingle in - defm NAME : fma3s_forms, - fma3s_int_forms; - - let ExeDomain = SSEPackedDouble in - defm NAME : fma3s_forms, - fma3s_int_forms, VEX_W; -} - -defm VFMADD : fma3s<0x99, 0xA9, 0xB9, "vfmadd", X86Fmadd, - SchedWriteFMA.Scl>, VEX_LIG; -defm VFMSUB : fma3s<0x9B, 0xAB, 0xBB, "vfmsub", X86Fmsub, - SchedWriteFMA.Scl>, VEX_LIG; - -defm VFNMADD : fma3s<0x9D, 0xAD, 0xBD, "vfnmadd", X86Fnmadd, - SchedWriteFMA.Scl>, VEX_LIG; -defm VFNMSUB : fma3s<0x9F, 0xAF, 0xBF, "vfnmsub", X86Fnmsub, - SchedWriteFMA.Scl>, VEX_LIG; - -multiclass scalar_fma_patterns { - let Predicates = [HasFMA, NoAVX512] in { - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - RC:$src3))))), - (!cast(Prefix#"213"#Suffix#"r_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, RC:$src3, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"r_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, - (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - (mem_frag addr:$src3)))))), - (!cast(Prefix#"213"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op (EltVT (extractelt (VT VR128:$src1), (iPTR 0))), - (mem_frag addr:$src3), RC:$src2))))), - (!cast(Prefix#"132"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - - def : Pat<(VT (Move (VT VR128:$src1), (VT (scalar_to_vector - (Op RC:$src2, (mem_frag addr:$src3), - (EltVT (extractelt (VT VR128:$src1), (iPTR 0)))))))), - (!cast(Prefix#"231"#Suffix#"m_Int") - VR128:$src1, (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - addr:$src3)>; - } -} - -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; - -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; -defm : scalar_fma_patterns; - -//===----------------------------------------------------------------------===// -// FMA4 - AMD 4 operand Fused Multiply-Add instructions -//===----------------------------------------------------------------------===// - -multiclass fma4s opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType OpVT, SDNode OpNode, - PatFrag mem_frag, X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rr : FMA4S, VEX_W, VEX_LIG, - Sched<[sched]>; - def rm : FMA4S, VEX_W, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : FMA4S, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src3 - ReadAfterLd]>; -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : FMA4S, - VEX_LIG, FoldGenData, Sched<[sched]>; -} - -multiclass fma4s_int opc, string OpcodeStr, Operand memop, - ValueType VT, X86FoldableSchedWrite sched> { -let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr_Int : FMA4S_Int, VEX_W, VEX_LIG, Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : FMA4S_Int, VEX_W, VEX_LIG, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - let mayLoad = 1 in - def mr_Int : FMA4S_Int, - VEX_LIG, Sched<[sched.Folded, ReadAfterLd, - // memop:$src2 - ReadDefault, ReadDefault, ReadDefault, - ReadDefault, ReadDefault, - // VR128::$src3 - ReadAfterLd]>; - def rr_Int_REV : FMA4S_Int, VEX_LIG, FoldGenData, Sched<[sched]>; -} // isCodeGenOnly = 1 -} - -multiclass fma4p opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT128, ValueType OpVT256, - PatFrag ld_frag128, PatFrag ld_frag256, - X86SchedWriteWidths sched> { - let isCommutable = 1 in - def rr : FMA4, - VEX_W, Sched<[sched.XMM]>; - def rm : FMA4, VEX_W, - Sched<[sched.XMM.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : FMA4, - Sched<[sched.XMM.Folded, ReadAfterLd, - // f128mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR128::$src3 - ReadAfterLd]>; - let isCommutable = 1 in - def Yrr : FMA4, - VEX_W, VEX_L, Sched<[sched.YMM]>; - def Yrm : FMA4, VEX_W, VEX_L, - Sched<[sched.YMM.Folded, ReadAfterLd, ReadAfterLd]>; - def Ymr : FMA4, VEX_L, - Sched<[sched.YMM.Folded, ReadAfterLd, - // f256mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR256::$src3 - ReadAfterLd]>; -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { - def rr_REV : FMA4, - Sched<[sched.XMM]>, FoldGenData; - def Yrr_REV : FMA4, - VEX_L, Sched<[sched.YMM]>, FoldGenData; -} // isCodeGenOnly = 1 -} - -let ExeDomain = SSEPackedSingle in { - // Scalar Instructions - defm VFMADDSS4 : fma4s<0x6A, "vfmaddss", FR32, f32mem, f32, X86Fmadd, loadf32, - SchedWriteFMA.Scl>, - fma4s_int<0x6A, "vfmaddss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFMSUBSS4 : fma4s<0x6E, "vfmsubss", FR32, f32mem, f32, X86Fmsub, loadf32, - SchedWriteFMA.Scl>, - fma4s_int<0x6E, "vfmsubss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFNMADDSS4 : fma4s<0x7A, "vfnmaddss", FR32, f32mem, f32, - X86Fnmadd, loadf32, SchedWriteFMA.Scl>, - fma4s_int<0x7A, "vfnmaddss", ssmem, v4f32, - SchedWriteFMA.Scl>; - defm VFNMSUBSS4 : fma4s<0x7E, "vfnmsubss", FR32, f32mem, f32, - X86Fnmsub, loadf32, SchedWriteFMA.Scl>, - fma4s_int<0x7E, "vfnmsubss", ssmem, v4f32, - SchedWriteFMA.Scl>; - // Packed Instructions - defm VFMADDPS4 : fma4p<0x68, "vfmaddps", X86Fmadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMSUBPS4 : fma4p<0x6C, "vfmsubps", X86Fmsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFNMADDPS4 : fma4p<0x78, "vfnmaddps", X86Fnmadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFNMSUBPS4 : fma4p<0x7C, "vfnmsubps", X86Fnmsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMADDSUBPS4 : fma4p<0x5C, "vfmaddsubps", X86Fmaddsub, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; - defm VFMSUBADDPS4 : fma4p<0x5E, "vfmsubaddps", X86Fmsubadd, v4f32, v8f32, - loadv4f32, loadv8f32, SchedWriteFMA>; -} - -let ExeDomain = SSEPackedDouble in { - // Scalar Instructions - defm VFMADDSD4 : fma4s<0x6B, "vfmaddsd", FR64, f64mem, f64, X86Fmadd, loadf64, - SchedWriteFMA.Scl>, - fma4s_int<0x6B, "vfmaddsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFMSUBSD4 : fma4s<0x6F, "vfmsubsd", FR64, f64mem, f64, X86Fmsub, loadf64, - SchedWriteFMA.Scl>, - fma4s_int<0x6F, "vfmsubsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFNMADDSD4 : fma4s<0x7B, "vfnmaddsd", FR64, f64mem, f64, - X86Fnmadd, loadf64, SchedWriteFMA.Scl>, - fma4s_int<0x7B, "vfnmaddsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - defm VFNMSUBSD4 : fma4s<0x7F, "vfnmsubsd", FR64, f64mem, f64, - X86Fnmsub, loadf64, SchedWriteFMA.Scl>, - fma4s_int<0x7F, "vfnmsubsd", sdmem, v2f64, - SchedWriteFMA.Scl>; - // Packed Instructions - defm VFMADDPD4 : fma4p<0x69, "vfmaddpd", X86Fmadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMSUBPD4 : fma4p<0x6D, "vfmsubpd", X86Fmsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFNMADDPD4 : fma4p<0x79, "vfnmaddpd", X86Fnmadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFNMSUBPD4 : fma4p<0x7D, "vfnmsubpd", X86Fnmsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMADDSUBPD4 : fma4p<0x5D, "vfmaddsubpd", X86Fmaddsub, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; - defm VFMSUBADDPD4 : fma4p<0x5F, "vfmsubaddpd", X86Fmsubadd, v2f64, v4f64, - loadv2f64, loadv4f64, SchedWriteFMA>; -} - -multiclass scalar_fma4_patterns { - let Predicates = [HasFMA4] in { - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, RC:$src2, RC:$src3))))), - (!cast(Name#"rr_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), - (VT (COPY_TO_REGCLASS RC:$src2, VR128)), - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, RC:$src2, - (mem_frag addr:$src3)))))), - (!cast(Name#"rm_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), - (VT (COPY_TO_REGCLASS RC:$src2, VR128)), addr:$src3)>; - - def : Pat<(VT (X86vzmovl (VT (scalar_to_vector - (Op RC:$src1, (mem_frag addr:$src2), - RC:$src3))))), - (!cast(Name#"mr_Int") - (VT (COPY_TO_REGCLASS RC:$src1, VR128)), addr:$src2, - (VT (COPY_TO_REGCLASS RC:$src3, VR128)))>; - } -} - -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; - -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; -defm : scalar_fma4_patterns; diff --git a/suite/synctools/tablegen/X86/back/X86InstrFPStack.td b/suite/synctools/tablegen/X86/back/X86InstrFPStack.td deleted file mode 100644 index a21f077927..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrFPStack.td +++ /dev/null @@ -1,748 +0,0 @@ -//===- X86InstrFPStack.td - FPU Instruction Set ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 x87 FPU instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// FPStack specific DAG Nodes. -//===----------------------------------------------------------------------===// - -def SDTX86FpGet2 : SDTypeProfile<2, 0, [SDTCisVT<0, f80>, - SDTCisVT<1, f80>]>; -def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>, - SDTCisVT<2, OtherVT>]>; -def SDTX86Fnstsw : SDTypeProfile<1, 1, [SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; -def SDTX86FpToIMem : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; - -def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; - -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, - [SDNPHasChain, SDNPInGlue, SDNPMayStore, - SDNPMemOperand]>; -def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fildflag : SDNode<"X86ISD::FILD_FLAG", SDTX86Fild, - [SDNPHasChain, SDNPOutGlue, SDNPMayLoad, - SDNPMemOperand]>; -def X86fp_stsw : SDNode<"X86ISD::FNSTSW16r", SDTX86Fnstsw>; -def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, - [SDNPHasChain, SDNPMayStore, SDNPSideEffect, - SDNPMemOperand]>; - -//===----------------------------------------------------------------------===// -// FPStack pattern fragments -//===----------------------------------------------------------------------===// - -def fpimm0 : FPImmLeaf; - -def fpimmneg0 : FPImmLeaf; - -def fpimm1 : FPImmLeaf; - -def fpimmneg1 : FPImmLeaf; - -/* -// Some 'special' instructions - expanded after instruction selection. -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - def FP32_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP32:$src), - [(X86fp_to_i16mem RFP32:$src, addr:$dst)]>; - def FP32_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP32:$src), - [(X86fp_to_i32mem RFP32:$src, addr:$dst)]>; - def FP32_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP32:$src), - [(X86fp_to_i64mem RFP32:$src, addr:$dst)]>; - def FP64_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP64:$src), - [(X86fp_to_i16mem RFP64:$src, addr:$dst)]>; - def FP64_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP64:$src), - [(X86fp_to_i32mem RFP64:$src, addr:$dst)]>; - def FP64_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP64:$src), - [(X86fp_to_i64mem RFP64:$src, addr:$dst)]>; - def FP80_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP80:$src), - [(X86fp_to_i16mem RFP80:$src, addr:$dst)]>; - def FP80_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP80:$src), - [(X86fp_to_i32mem RFP80:$src, addr:$dst)]>; - def FP80_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP80:$src), - [(X86fp_to_i64mem RFP80:$src, addr:$dst)]>; -} -*/ - -// All FP Stack operations are represented with four instructions here. The -// first three instructions, generated by the instruction selector, use "RFP32" -// "RFP64" or "RFP80" registers: traditional register files to reference 32-bit, -// 64-bit or 80-bit floating point values. These sizes apply to the values, -// not the registers, which are always 80 bits; RFP32, RFP64 and RFP80 can be -// copied to each other without losing information. These instructions are all -// pseudo instructions and use the "_Fp" suffix. -// In some cases there are additional variants with a mixture of different -// register sizes. -// The second instruction is defined with FPI, which is the actual instruction -// emitted by the assembler. These use "RST" registers, although frequently -// the actual register(s) used are implicit. These are always 80 bits. -// The FP stackifier pass converts one to the other after register allocation -// occurs. -// -// Note that the FpI instruction should have instruction selection info (e.g. -// a pattern) and the FPI instruction should have emission info (e.g. opcode -// encoding and asm printing info). - -// FpIf32, FpIf64 - Floating Point Pseudo Instruction template. -// f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. -// f64 instructions can use SSE2 and are predicated on FPStackf64 == !SSE2. -// f80 instructions cannot use SSE and use neither of these. -class FpIf32 pattern> : - FpI_, Requires<[FPStackf32]>; -class FpIf64 pattern> : - FpI_, Requires<[FPStackf64]>; - -// Factoring for arithmetic. -multiclass FPBinary_rr { -// Register op register -> register -// These are separated out because they have no reversed form. -def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), TwoArgFP, - [(set RFP32:$dst, (OpNode RFP32:$src1, RFP32:$src2))]>; -def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), TwoArgFP, - [(set RFP64:$dst, (OpNode RFP64:$src1, RFP64:$src2))]>; -def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), TwoArgFP, - [(set RFP80:$dst, (OpNode RFP80:$src1, RFP80:$src2))]>; -} -// The FopST0 series are not included here because of the irregularities -// in where the 'r' goes in assembly output. -// These instructions cannot address 80-bit memory. -multiclass FPBinary { -let mayLoad = 1, hasSideEffects = 1 in { -// ST(0) = ST(0) + [mem] -def _Fp32m : FpIf32<(outs RFP32:$dst), - (ins RFP32:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (loadf32 addr:$src2))), - (set RFP32:$dst, - (OpNode (loadf32 addr:$src2), RFP32:$src1)))]>; -def _Fp64m : FpIf64<(outs RFP64:$dst), - (ins RFP64:$src1, f64mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (loadf64 addr:$src2))), - (set RFP64:$dst, - (OpNode (loadf64 addr:$src2), RFP64:$src1)))]>; -def _Fp64m32: FpIf64<(outs RFP64:$dst), - (ins RFP64:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (f64 (extloadf32 addr:$src2)))), - (set RFP64:$dst, - (OpNode (f64 (extloadf32 addr:$src2)), RFP64:$src1)))]>; -def _Fp80m32: FpI_<(outs RFP80:$dst), - (ins RFP80:$src1, f32mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (f80 (extloadf32 addr:$src2)))), - (set RFP80:$dst, - (OpNode (f80 (extloadf32 addr:$src2)), RFP80:$src1)))]>; -def _Fp80m64: FpI_<(outs RFP80:$dst), - (ins RFP80:$src1, f64mem:$src2), OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2)))), - (set RFP80:$dst, - (OpNode (f80 (extloadf64 addr:$src2)), RFP80:$src1)))]>; -def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), - !strconcat("f", asmstring, "{s}\t$src")>; -def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), - !strconcat("f", asmstring, "{l}\t$src")>; -// ST(0) = ST(0) + [memint] -def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (X86fild addr:$src2, i16))), - (set RFP32:$dst, - (OpNode (X86fild addr:$src2, i16), RFP32:$src1)))]>; -def _FpI32m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP32:$dst, - (OpNode RFP32:$src1, (X86fild addr:$src2, i32))), - (set RFP32:$dst, - (OpNode (X86fild addr:$src2, i32), RFP32:$src1)))]>; -def _FpI16m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (X86fild addr:$src2, i16))), - (set RFP64:$dst, - (OpNode (X86fild addr:$src2, i16), RFP64:$src1)))]>; -def _FpI32m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP64:$dst, - (OpNode RFP64:$src1, (X86fild addr:$src2, i32))), - (set RFP64:$dst, - (OpNode (X86fild addr:$src2, i32), RFP64:$src1)))]>; -def _FpI16m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i16mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (X86fild addr:$src2, i16))), - (set RFP80:$dst, - (OpNode (X86fild addr:$src2, i16), RFP80:$src1)))]>; -def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), - OneArgFPRW, - [!if(Forward, - (set RFP80:$dst, - (OpNode RFP80:$src1, (X86fild addr:$src2, i32))), - (set RFP80:$dst, - (OpNode (X86fild addr:$src2, i32), RFP80:$src1)))]>; -def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), - !strconcat("fi", asmstring, "{s}\t$src")>; -def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), - !strconcat("fi", asmstring, "{l}\t$src")>; -} // mayLoad = 1, hasSideEffects = 1 -} - -let Defs = [FPSW] in { -// FPBinary_rr just defines pseudo-instructions, no need to set a scheduling -// resources. -let hasNoSchedulingInfo = 1 in { -defm ADD : FPBinary_rr; -defm SUB : FPBinary_rr; -defm MUL : FPBinary_rr; -defm DIV : FPBinary_rr; -} - -// Sets the scheduling resources for the actual NAME#_Fm definitions. -let SchedRW = [WriteFAddLd] in { -defm ADD : FPBinary; -defm SUB : FPBinary; -defm SUBR: FPBinary; -} - -let SchedRW = [WriteFMulLd] in { -defm MUL : FPBinary; -} - -let SchedRW = [WriteFDivLd] in { -defm DIV : FPBinary; -defm DIVR: FPBinary; -} -} // Defs = [FPSW] - -class FPST0rInst - : FPI<0xD8, fp, (outs), (ins RST:$op), asm>; -class FPrST0Inst - : FPI<0xDC, fp, (outs), (ins RST:$op), asm>; -class FPrST0PInst - : FPI<0xDE, fp, (outs), (ins RST:$op), asm>; - -// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion -// of some of the 'reverse' forms of the fsub and fdiv instructions. As such, -// we have to put some 'r's in and take them out of weird places. -let SchedRW = [WriteFAdd] in { -def ADD_FST0r : FPST0rInst ; -def ADD_FrST0 : FPrST0Inst ; -def ADD_FPrST0 : FPrST0PInst; -def SUBR_FST0r : FPST0rInst ; -def SUB_FrST0 : FPrST0Inst ; -def SUB_FPrST0 : FPrST0PInst; -def SUB_FST0r : FPST0rInst ; -def SUBR_FrST0 : FPrST0Inst ; -def SUBR_FPrST0 : FPrST0PInst; -} // SchedRW -let SchedRW = [WriteFCom] in { -def COM_FST0r : FPST0rInst ; -def COMP_FST0r : FPST0rInst ; -} // SchedRW -let SchedRW = [WriteFMul] in { -def MUL_FST0r : FPST0rInst ; -def MUL_FrST0 : FPrST0Inst ; -def MUL_FPrST0 : FPrST0PInst; -} // SchedRW -let SchedRW = [WriteFDiv] in { -def DIVR_FST0r : FPST0rInst ; -def DIV_FrST0 : FPrST0Inst ; -def DIV_FPrST0 : FPrST0PInst; -def DIV_FST0r : FPST0rInst ; -def DIVR_FrST0 : FPrST0Inst ; -def DIVR_FPrST0 : FPrST0PInst; -} // SchedRW - -// Unary operations. -multiclass FPUnary { -def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), OneArgFPRW, - [(set RFP32:$dst, (OpNode RFP32:$src))]>; -def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), OneArgFPRW, - [(set RFP64:$dst, (OpNode RFP64:$src))]>; -def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, - [(set RFP80:$dst, (OpNode RFP80:$src))]>; -def _F : FPI<0xD9, fp, (outs), (ins), asmstring>; -} - -let Defs = [FPSW] in { - -let SchedRW = [WriteFSign] in { -defm CHS : FPUnary; -defm ABS : FPUnary; -} - -let SchedRW = [WriteFSqrt80] in -defm SQRT: FPUnary; - -let SchedRW = [WriteMicrocoded] in { -defm SIN : FPUnary; -defm COS : FPUnary; -} - -let SchedRW = [WriteFCom] in { -let hasSideEffects = 0 in { -def TST_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; -def TST_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; -def TST_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; -} // hasSideEffects - -def TST_F : FPI<0xD9, MRM_E4, (outs), (ins), "ftst">; -} // SchedRW -} // Defs = [FPSW] - -// Versions of FP instructions that take a single memory operand. Added for the -// disassembler; remove as they are included with patterns elsewhere. -let SchedRW = [WriteFComLd] in { -def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; -def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; - -def FCOM64m : FPI<0xDC, MRM2m, (outs), (ins f64mem:$src), "fcom{l}\t$src">; -def FCOMP64m : FPI<0xDC, MRM3m, (outs), (ins f64mem:$src), "fcomp{l}\t$src">; - -def FICOM16m : FPI<0xDE, MRM2m, (outs), (ins i16mem:$src), "ficom{s}\t$src">; -def FICOMP16m: FPI<0xDE, MRM3m, (outs), (ins i16mem:$src), "ficomp{s}\t$src">; - -def FICOM32m : FPI<0xDA, MRM2m, (outs), (ins i32mem:$src), "ficom{l}\t$src">; -def FICOMP32m: FPI<0xDA, MRM3m, (outs), (ins i32mem:$src), "ficomp{l}\t$src">; -} // SchedRW - -let SchedRW = [WriteMicrocoded] in { -def FLDENVm : FPI<0xD9, MRM4m, (outs), (ins f32mem:$src), "fldenv\t$src">; -def FSTENVm : FPI<0xD9, MRM6m, (outs), (ins f32mem:$dst), "fnstenv\t$dst">; - -def FRSTORm : FPI<0xDD, MRM4m, (outs), (ins f32mem:$dst), "frstor\t$dst">; -def FSAVEm : FPI<0xDD, MRM6m, (outs), (ins f32mem:$dst), "fnsave\t$dst">; -def FNSTSWm : FPI<0xDD, MRM7m, (outs), (ins i16mem:$dst), "fnstsw\t$dst">; - -def FBLDm : FPI<0xDF, MRM4m, (outs), (ins f80mem:$src), "fbld\ttbyte ptr $src">; -def FBSTPm : FPI<0xDF, MRM6m, (outs), (ins f80mem:$dst), "fbstp\ttbyte ptr $dst">; -} // SchedRW - -// Floating point cmovs. -class FpIf32CMov pattern> : - FpI_, Requires<[FPStackf32, HasCMov]>; -class FpIf64CMov pattern> : - FpI_, Requires<[FPStackf64, HasCMov]>; - -multiclass FPCMov { - def _Fp32 : FpIf32CMov<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), - CondMovFP, - [(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2, - cc, EFLAGS))]>; - def _Fp64 : FpIf64CMov<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), - CondMovFP, - [(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2, - cc, EFLAGS))]>; - def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), - CondMovFP, - [(set RFP80:$dst, (X86cmov RFP80:$src1, RFP80:$src2, - cc, EFLAGS))]>, - Requires<[HasCMov]>; -} - -let Defs = [FPSW] in { -let SchedRW = [WriteFCMOV] in { -let Uses = [EFLAGS], Constraints = "$src1 = $dst" in { -defm CMOVB : FPCMov; -defm CMOVBE : FPCMov; -defm CMOVE : FPCMov; -defm CMOVP : FPCMov; -defm CMOVNB : FPCMov; -defm CMOVNBE: FPCMov; -defm CMOVNE : FPCMov; -defm CMOVNP : FPCMov; -} // Uses = [EFLAGS], Constraints = "$src1 = $dst" - -let Predicates = [HasCMov] in { -// These are not factored because there's no clean way to pass DA/DB. -def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RST:$op), - "fcmovb\t{$op, %st(0)|st(0), $op}">; -def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RST:$op), - "fcmovbe\t{$op, %st(0)|st(0), $op}">; -def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RST:$op), - "fcmove\t{$op, %st(0)|st(0), $op}">; -def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RST:$op), - "fcmovu\t{$op, %st(0)|st(0), $op}">; -def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RST:$op), - "fcmovnb\t{$op, %st(0)|st(0), $op}">; -def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RST:$op), - "fcmovnbe\t{$op, %st(0)|st(0), $op}">; -def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RST:$op), - "fcmovne\t{$op, %st(0)|st(0), $op}">; -def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RST:$op), - "fcmovnu\t{$op, %st(0)|st(0), $op}">; -} // Predicates = [HasCMov] -} // SchedRW - -// Floating point loads & stores. -let SchedRW = [WriteLoad] in { -let canFoldAsLoad = 1 in { -def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP32:$dst, (loadf32 addr:$src))]>; -let isReMaterializable = 1 in - def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, - [(set RFP64:$dst, (loadf64 addr:$src))]>; -def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, - [(set RFP80:$dst, (loadf80 addr:$src))]>; -} // canFoldAsLoad -def LD_Fp32m64 : FpIf64<(outs RFP64:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP64:$dst, (f64 (extloadf32 addr:$src)))]>; -def LD_Fp64m80 : FpI_<(outs RFP80:$dst), (ins f64mem:$src), ZeroArgFP, - [(set RFP80:$dst, (f80 (extloadf64 addr:$src)))]>; -def LD_Fp32m80 : FpI_<(outs RFP80:$dst), (ins f32mem:$src), ZeroArgFP, - [(set RFP80:$dst, (f80 (extloadf32 addr:$src)))]>; -def ILD_Fp16m32: FpIf32<(outs RFP32:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m32: FpIf32<(outs RFP32:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m32: FpIf32<(outs RFP32:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP32:$dst, (X86fild addr:$src, i64))]>; -def ILD_Fp16m64: FpIf64<(outs RFP64:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m64: FpIf64<(outs RFP64:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m64: FpIf64<(outs RFP64:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP64:$dst, (X86fild addr:$src, i64))]>; -def ILD_Fp16m80: FpI_<(outs RFP80:$dst), (ins i16mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i16))]>; -def ILD_Fp32m80: FpI_<(outs RFP80:$dst), (ins i32mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i32))]>; -def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, - [(set RFP80:$dst, (X86fild addr:$src, i64))]>; -} // SchedRW - -let SchedRW = [WriteStore] in { -def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, - [(store RFP32:$src, addr:$op)]>; -def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, - [(truncstoref32 RFP64:$src, addr:$op)]>; -def ST_Fp64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, - [(store RFP64:$src, addr:$op)]>; -def ST_Fp80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, - [(truncstoref32 RFP80:$src, addr:$op)]>; -def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, - [(truncstoref64 RFP80:$src, addr:$op)]>; -// FST does not support 80-bit memory target; FSTP must be used. - -let mayStore = 1, hasSideEffects = 0 in { -def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; -def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; -def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; -def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; -def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; -} // mayStore - -def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, - [(store RFP80:$src, addr:$op)]>; - -let mayStore = 1, hasSideEffects = 0 in { -def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, []>; -def IST_Fp16m64 : FpIf64<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp32m64 : FpIf64<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, []>; -def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; -def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; -def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; -} // mayStore -} // SchedRW - -let mayLoad = 1, SchedRW = [WriteLoad] in { -def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; -def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; -def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; -def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; -def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; -def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; -} -let mayStore = 1, SchedRW = [WriteStore] in { -def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; -def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; -def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; -def ST_FP64m : FPI<0xDD, MRM3m, (outs), (ins f64mem:$dst), "fstp{l}\t$dst">; -def ST_FP80m : FPI<0xDB, MRM7m, (outs), (ins f80mem:$dst), "fstp{t}\t$dst">; -def IST_F16m : FPI<0xDF, MRM2m, (outs), (ins i16mem:$dst), "fist{s}\t$dst">; -def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; -def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; -def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; -def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; -} - -// FISTTP requires SSE3 even though it's a FPStack op. -let Predicates = [HasSSE3], SchedRW = [WriteStore] in { -def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; -def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i32mem RFP32:$src, addr:$op)]>; -def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, - [(X86fp_to_i64mem RFP32:$src, addr:$op)]>; -def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i16mem RFP64:$src, addr:$op)]>; -def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i32mem RFP64:$src, addr:$op)]>; -def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, - [(X86fp_to_i64mem RFP64:$src, addr:$op)]>; -def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i16mem RFP80:$src, addr:$op)]>; -def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i32mem RFP80:$src, addr:$op)]>; -def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, - [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; -} // Predicates = [HasSSE3] - -let mayStore = 1, SchedRW = [WriteStore] in { -def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; -def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; -def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; -} - -// FP Stack manipulation instructions. -let SchedRW = [WriteMove] in { -def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RST:$op), "fld\t$op">; -def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RST:$op), "fst\t$op">; -def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RST:$op), "fstp\t$op">; -def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RST:$op), "fxch\t$op">; -} - -// Floating point constant loads. -let isReMaterializable = 1, SchedRW = [WriteZero] in { -def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, - [(set RFP32:$dst, fpimm0)]>; -def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, - [(set RFP32:$dst, fpimm1)]>; -def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, - [(set RFP64:$dst, fpimm0)]>; -def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, - [(set RFP64:$dst, fpimm1)]>; -def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, - [(set RFP80:$dst, fpimm0)]>; -def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, - [(set RFP80:$dst, fpimm1)]>; -} - -let SchedRW = [WriteFLD0] in -def LD_F0 : FPI<0xD9, MRM_EE, (outs), (ins), "fldz">; - -let SchedRW = [WriteFLD1] in -def LD_F1 : FPI<0xD9, MRM_E8, (outs), (ins), "fld1">; - -let SchedRW = [WriteFLDC], Defs = [FPSW] in { -def FLDL2T : I<0xD9, MRM_E9, (outs), (ins), "fldl2t", []>; -def FLDL2E : I<0xD9, MRM_EA, (outs), (ins), "fldl2e", []>; -def FLDPI : I<0xD9, MRM_EB, (outs), (ins), "fldpi", []>; -def FLDLG2 : I<0xD9, MRM_EC, (outs), (ins), "fldlg2", []>; -def FLDLN2 : I<0xD9, MRM_ED, (outs), (ins), "fldln2", []>; -} // SchedRW - -// Floating point compares. -let SchedRW = [WriteFCom] in { -def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP32:$lhs, RFP32:$rhs)))]>; -def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP64:$lhs, RFP64:$rhs)))]>; -def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set FPSW, (trunc (X86cmp RFP80:$lhs, RFP80:$rhs)))]>; -} // SchedRW -} // Defs = [FPSW] - -let SchedRW = [WriteFCom] in { -// CC = ST(0) cmp ST(i) -let Defs = [EFLAGS, FPSW] in { -def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; -def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; -def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; -} - -let Defs = [FPSW], Uses = [ST0] in { -def UCOM_Fr : FPI<0xDD, MRM4r, // FPSW = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucom\t$reg">; -def UCOM_FPr : FPI<0xDD, MRM5r, // FPSW = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucomp\t$reg">; -def UCOM_FPPr : FPI<0xDA, MRM_E9, // cmp ST(0) with ST(1), pop, pop - (outs), (ins), "fucompp">; -} - -let Defs = [EFLAGS, FPSW], Uses = [ST0] in { -def UCOM_FIr : FPI<0xDB, MRM5r, // CC = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucomi\t$reg">; -def UCOM_FIPr : FPI<0xDF, MRM5r, // CC = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucompi\t$reg">; -} - -let Defs = [EFLAGS, FPSW] in { -def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RST:$reg), "fcomi\t$reg">; -def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RST:$reg), "fcompi\t$reg">; -} -} // SchedRW - -// Floating point flag ops. -let SchedRW = [WriteALU] in { -let Defs = [AX], Uses = [FPSW] in -def FNSTSW16r : I<0xDF, MRM_E0, // AX = fp flags - (outs), (ins), "fnstsw\t{%ax|ax}", - [(set AX, (X86fp_stsw FPSW))]>; -let Defs = [FPSW] in -def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world - (outs), (ins i16mem:$dst), "fnstcw\t$dst", - [(X86fp_cwd_get16 addr:$dst)]>; -} // SchedRW -let Defs = [FPSW], mayLoad = 1 in -def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] - (outs), (ins i16mem:$dst), "fldcw\t$dst", []>, - Sched<[WriteLoad]>; - -// FPU control instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [FPSW] in { -def FNINIT : I<0xDB, MRM_E3, (outs), (ins), "fninit", []>; -def FFREE : FPI<0xDD, MRM0r, (outs), (ins RST:$reg), "ffree\t$reg">; -def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RST:$reg), "ffreep\t$reg">; - -def FPNCEST0r : FPI<0xD9, MRM3r, (outs RST:$op), (ins), - "fstpnce\t{%st(0), $op|$op, st(0)}">; - -def FENI8087_NOP : I<0xDB, MRM_E0, (outs), (ins), "feni8087_nop", []>; - -def FDISI8087_NOP : I<0xDB, MRM_E1, (outs), (ins), "fdisi8087_nop", []>; - -// Clear exceptions -def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", []>; -} // Defs = [FPSW] -} // SchedRW - -// Operand-less floating-point instructions for the disassembler. -def FNOP : I<0xD9, MRM_D0, (outs), (ins), "fnop", []>, Sched<[WriteNop]>; - -let SchedRW = [WriteMicrocoded] in { -let Defs = [FPSW] in { -def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; -def FXAM : I<0xD9, MRM_E5, (outs), (ins), "fxam", []>; -def F2XM1 : I<0xD9, MRM_F0, (outs), (ins), "f2xm1", []>; -def FYL2X : I<0xD9, MRM_F1, (outs), (ins), "fyl2x", []>; -def FPTAN : I<0xD9, MRM_F2, (outs), (ins), "fptan", []>; -def FPATAN : I<0xD9, MRM_F3, (outs), (ins), "fpatan", []>; -def FXTRACT : I<0xD9, MRM_F4, (outs), (ins), "fxtract", []>; -def FPREM1 : I<0xD9, MRM_F5, (outs), (ins), "fprem1", []>; -def FDECSTP : I<0xD9, MRM_F6, (outs), (ins), "fdecstp", []>; -def FINCSTP : I<0xD9, MRM_F7, (outs), (ins), "fincstp", []>; -def FPREM : I<0xD9, MRM_F8, (outs), (ins), "fprem", []>; -def FYL2XP1 : I<0xD9, MRM_F9, (outs), (ins), "fyl2xp1", []>; -def FSINCOS : I<0xD9, MRM_FB, (outs), (ins), "fsincos", []>; -def FRNDINT : I<0xD9, MRM_FC, (outs), (ins), "frndint", []>; -def FSCALE : I<0xD9, MRM_FD, (outs), (ins), "fscale", []>; -def FCOMPP : I<0xDE, MRM_D9, (outs), (ins), "fcompp", []>; -} // Defs = [FPSW] - -def FXSAVE : I<0xAE, MRM0m, (outs), (ins opaquemem:$dst), - "fxsave\t$dst", [(int_x86_fxsave addr:$dst)]>, TB, - Requires<[HasFXSR]>; -def FXSAVE64 : RI<0xAE, MRM0m, (outs), (ins opaquemem:$dst), - "fxsave64\t$dst", [(int_x86_fxsave64 addr:$dst)]>, - TB, Requires<[HasFXSR, In64BitMode]>; -def FXRSTOR : I<0xAE, MRM1m, (outs), (ins opaquemem:$src), - "fxrstor\t$src", [(int_x86_fxrstor addr:$src)]>, - TB, Requires<[HasFXSR]>; -def FXRSTOR64 : RI<0xAE, MRM1m, (outs), (ins opaquemem:$src), - "fxrstor64\t$src", [(int_x86_fxrstor64 addr:$src)]>, - TB, Requires<[HasFXSR, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Non-Instruction Patterns -//===----------------------------------------------------------------------===// - -// Required for RET of f32 / f64 / f80 values. -def : Pat<(X86fld addr:$src, f32), (LD_Fp32m addr:$src)>; -def : Pat<(X86fld addr:$src, f64), (LD_Fp64m addr:$src)>; -def : Pat<(X86fld addr:$src, f80), (LD_Fp80m addr:$src)>; - -// Required for CALL which return f32 / f64 / f80 values. -def : Pat<(X86fst RFP32:$src, addr:$op, f32), (ST_Fp32m addr:$op, RFP32:$src)>; -def : Pat<(X86fst RFP64:$src, addr:$op, f32), (ST_Fp64m32 addr:$op, - RFP64:$src)>; -def : Pat<(X86fst RFP64:$src, addr:$op, f64), (ST_Fp64m addr:$op, RFP64:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f32), (ST_Fp80m32 addr:$op, - RFP80:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f64), (ST_Fp80m64 addr:$op, - RFP80:$src)>; -def : Pat<(X86fst RFP80:$src, addr:$op, f80), (ST_FpP80m addr:$op, - RFP80:$src)>; - -// Floating point constant -0.0 and -1.0 -def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; -def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; -def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; -def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; -def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; -def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; - -// Used to conv. i64 to f64 since there isn't a SSE version. -def : Pat<(X86fildflag addr:$src, i64), (ILD_Fp64m64 addr:$src)>; - -// FP extensions map onto simple pseudo-value conversions if they are to/from -// the FP stack. -def : Pat<(f64 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, - Requires<[FPStackf32]>; -def : Pat<(f80 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, - Requires<[FPStackf32]>; -def : Pat<(f80 (fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, - Requires<[FPStackf64]>; - -// FP truncations map onto simple pseudo-value conversions if they are to/from -// the FP stack. We have validated that only value-preserving truncations make -// it through isel. -def : Pat<(f32 (fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, - Requires<[FPStackf32]>; -def : Pat<(f32 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, - Requires<[FPStackf32]>; -def : Pat<(f64 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, - Requires<[FPStackf64]>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrFormats.td b/suite/synctools/tablegen/X86/back/X86InstrFormats.td deleted file mode 100644 index 47d4719d30..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrFormats.td +++ /dev/null @@ -1,993 +0,0 @@ -//===-- X86InstrFormats.td - X86 Instruction Formats -------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -// Format specifies the encoding used by the instruction. This is part of the -// ad-hoc solution used to emit machine instruction encodings by our machine -// code emitter. -class Format val> { - bits<7> Value = val; -} - -def Pseudo : Format<0>; -def RawFrm : Format<1>; -def AddRegFrm : Format<2>; -def RawFrmMemOffs : Format<3>; -def RawFrmSrc : Format<4>; -def RawFrmDst : Format<5>; -def RawFrmDstSrc : Format<6>; -def RawFrmImm8 : Format<7>; -def RawFrmImm16 : Format<8>; -def MRMDestMem : Format<32>; -def MRMSrcMem : Format<33>; -def MRMSrcMem4VOp3 : Format<34>; -def MRMSrcMemOp4 : Format<35>; -def MRMXm : Format<39>; -def MRM0m : Format<40>; def MRM1m : Format<41>; def MRM2m : Format<42>; -def MRM3m : Format<43>; def MRM4m : Format<44>; def MRM5m : Format<45>; -def MRM6m : Format<46>; def MRM7m : Format<47>; -def MRMDestReg : Format<48>; -def MRMSrcReg : Format<49>; -def MRMSrcReg4VOp3 : Format<50>; -def MRMSrcRegOp4 : Format<51>; -def MRMXr : Format<55>; -def MRM0r : Format<56>; def MRM1r : Format<57>; def MRM2r : Format<58>; -def MRM3r : Format<59>; def MRM4r : Format<60>; def MRM5r : Format<61>; -def MRM6r : Format<62>; def MRM7r : Format<63>; -def MRM_C0 : Format<64>; def MRM_C1 : Format<65>; def MRM_C2 : Format<66>; -def MRM_C3 : Format<67>; def MRM_C4 : Format<68>; def MRM_C5 : Format<69>; -def MRM_C6 : Format<70>; def MRM_C7 : Format<71>; def MRM_C8 : Format<72>; -def MRM_C9 : Format<73>; def MRM_CA : Format<74>; def MRM_CB : Format<75>; -def MRM_CC : Format<76>; def MRM_CD : Format<77>; def MRM_CE : Format<78>; -def MRM_CF : Format<79>; def MRM_D0 : Format<80>; def MRM_D1 : Format<81>; -def MRM_D2 : Format<82>; def MRM_D3 : Format<83>; def MRM_D4 : Format<84>; -def MRM_D5 : Format<85>; def MRM_D6 : Format<86>; def MRM_D7 : Format<87>; -def MRM_D8 : Format<88>; def MRM_D9 : Format<89>; def MRM_DA : Format<90>; -def MRM_DB : Format<91>; def MRM_DC : Format<92>; def MRM_DD : Format<93>; -def MRM_DE : Format<94>; def MRM_DF : Format<95>; def MRM_E0 : Format<96>; -def MRM_E1 : Format<97>; def MRM_E2 : Format<98>; def MRM_E3 : Format<99>; -def MRM_E4 : Format<100>; def MRM_E5 : Format<101>; def MRM_E6 : Format<102>; -def MRM_E7 : Format<103>; def MRM_E8 : Format<104>; def MRM_E9 : Format<105>; -def MRM_EA : Format<106>; def MRM_EB : Format<107>; def MRM_EC : Format<108>; -def MRM_ED : Format<109>; def MRM_EE : Format<110>; def MRM_EF : Format<111>; -def MRM_F0 : Format<112>; def MRM_F1 : Format<113>; def MRM_F2 : Format<114>; -def MRM_F3 : Format<115>; def MRM_F4 : Format<116>; def MRM_F5 : Format<117>; -def MRM_F6 : Format<118>; def MRM_F7 : Format<119>; def MRM_F8 : Format<120>; -def MRM_F9 : Format<121>; def MRM_FA : Format<122>; def MRM_FB : Format<123>; -def MRM_FC : Format<124>; def MRM_FD : Format<125>; def MRM_FE : Format<126>; -def MRM_FF : Format<127>; - -// ImmType - This specifies the immediate type used by an instruction. This is -// part of the ad-hoc solution used to emit machine instruction encodings by our -// machine code emitter. -class ImmType val> { - bits<4> Value = val; -} -def NoImm : ImmType<0>; -def Imm8 : ImmType<1>; -def Imm8PCRel : ImmType<2>; -def Imm8Reg : ImmType<3>; // Register encoded in [7:4]. -def Imm16 : ImmType<4>; -def Imm16PCRel : ImmType<5>; -def Imm32 : ImmType<6>; -def Imm32PCRel : ImmType<7>; -def Imm32S : ImmType<8>; -def Imm64 : ImmType<9>; - -// FPFormat - This specifies what form this FP instruction has. This is used by -// the Floating-Point stackifier pass. -class FPFormat val> { - bits<3> Value = val; -} -def NotFP : FPFormat<0>; -def ZeroArgFP : FPFormat<1>; -def OneArgFP : FPFormat<2>; -def OneArgFPRW : FPFormat<3>; -def TwoArgFP : FPFormat<4>; -def CompareFP : FPFormat<5>; -def CondMovFP : FPFormat<6>; -def SpecialFP : FPFormat<7>; - -// Class specifying the SSE execution domain, used by the SSEDomainFix pass. -// Keep in sync with tables in X86InstrInfo.cpp. -class Domain val> { - bits<2> Value = val; -} -def GenericDomain : Domain<0>; -def SSEPackedSingle : Domain<1>; -def SSEPackedDouble : Domain<2>; -def SSEPackedInt : Domain<3>; - -// Class specifying the vector form of the decompressed -// displacement of 8-bit. -class CD8VForm val> { - bits<3> Value = val; -} -def CD8VF : CD8VForm<0>; // v := VL -def CD8VH : CD8VForm<1>; // v := VL/2 -def CD8VQ : CD8VForm<2>; // v := VL/4 -def CD8VO : CD8VForm<3>; // v := VL/8 -// The tuple (subvector) forms. -def CD8VT1 : CD8VForm<4>; // v := 1 -def CD8VT2 : CD8VForm<5>; // v := 2 -def CD8VT4 : CD8VForm<6>; // v := 4 -def CD8VT8 : CD8VForm<7>; // v := 8 - -// Class specifying the prefix used an opcode extension. -class Prefix val> { - bits<3> Value = val; -} -def NoPrfx : Prefix<0>; -def PD : Prefix<1>; -def XS : Prefix<2>; -def XD : Prefix<3>; -def PS : Prefix<4>; // Similar to NoPrfx, but disassembler uses this to know - // that other instructions with this opcode use PD/XS/XD - // and if any of those is not supported they shouldn't - // decode to this instruction. e.g. ANDSS/ANDSD don't - // exist, but the 0xf2/0xf3 encoding shouldn't - // disable to ANDPS. - -// Class specifying the opcode map. -class Map val> { - bits<3> Value = val; -} -def OB : Map<0>; -def TB : Map<1>; -def T8 : Map<2>; -def TA : Map<3>; -def XOP8 : Map<4>; -def XOP9 : Map<5>; -def XOPA : Map<6>; -def ThreeDNow : Map<7>; - -// Class specifying the encoding -class Encoding val> { - bits<2> Value = val; -} -def EncNormal : Encoding<0>; -def EncVEX : Encoding<1>; -def EncXOP : Encoding<2>; -def EncEVEX : Encoding<3>; - -// Operand size for encodings that change based on mode. -class OperandSize val> { - bits<2> Value = val; -} -def OpSizeFixed : OperandSize<0>; // Never needs a 0x66 prefix. -def OpSize16 : OperandSize<1>; // Needs 0x66 prefix in 32-bit mode. -def OpSize32 : OperandSize<2>; // Needs 0x66 prefix in 16-bit mode. - -// Address size for encodings that change based on mode. -class AddressSize val> { - bits<2> Value = val; -} -def AdSizeX : AddressSize<0>; // Address size determined using addr operand. -def AdSize16 : AddressSize<1>; // Encodes a 16-bit address. -def AdSize32 : AddressSize<2>; // Encodes a 32-bit address. -def AdSize64 : AddressSize<3>; // Encodes a 64-bit address. - -// Prefix byte classes which are used to indicate to the ad-hoc machine code -// emitter that various prefix bytes are required. -class OpSize16 { OperandSize OpSize = OpSize16; } -class OpSize32 { OperandSize OpSize = OpSize32; } -class AdSize16 { AddressSize AdSize = AdSize16; } -class AdSize32 { AddressSize AdSize = AdSize32; } -class AdSize64 { AddressSize AdSize = AdSize64; } -class REX_W { bit hasREX_WPrefix = 1; } -class LOCK { bit hasLockPrefix = 1; } -class REP { bit hasREPPrefix = 1; } -class TB { Map OpMap = TB; } -class T8 { Map OpMap = T8; } -class TA { Map OpMap = TA; } -class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; } -class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; } -class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; } -class ThreeDNow { Map OpMap = ThreeDNow; } -class OBXS { Prefix OpPrefix = XS; } -class PS : TB { Prefix OpPrefix = PS; } -class PD : TB { Prefix OpPrefix = PD; } -class XD : TB { Prefix OpPrefix = XD; } -class XS : TB { Prefix OpPrefix = XS; } -class T8PS : T8 { Prefix OpPrefix = PS; } -class T8PD : T8 { Prefix OpPrefix = PD; } -class T8XD : T8 { Prefix OpPrefix = XD; } -class T8XS : T8 { Prefix OpPrefix = XS; } -class TAPS : TA { Prefix OpPrefix = PS; } -class TAPD : TA { Prefix OpPrefix = PD; } -class TAXD : TA { Prefix OpPrefix = XD; } -class VEX { Encoding OpEnc = EncVEX; } -class VEX_W { bits<2> VEX_WPrefix = 1; } -class VEX_WIG { bits<2> VEX_WPrefix = 2; } -// Special version of VEX_W that can be changed to VEX.W==0 for EVEX2VEX. -// FIXME: We should consider adding separate bits for VEX_WIG and the extra -// part of W1X. This would probably simplify the tablegen emitters and -// the TSFlags creation below. -class VEX_W1X { bits<2> VEX_WPrefix = 3; } -class VEX_4V : VEX { bit hasVEX_4V = 1; } -class VEX_L { bit hasVEX_L = 1; } -class VEX_LIG { bit ignoresVEX_L = 1; } -class EVEX { Encoding OpEnc = EncEVEX; } -class EVEX_4V : EVEX { bit hasVEX_4V = 1; } -class EVEX_K { bit hasEVEX_K = 1; } -class EVEX_KZ : EVEX_K { bit hasEVEX_Z = 1; } -class EVEX_B { bit hasEVEX_B = 1; } -class EVEX_RC { bit hasEVEX_RC = 1; } -class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; } -class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; } -class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; } -class NOTRACK { bit hasNoTrackPrefix = 1; } - -// Specify AVX512 8-bit compressed displacement encoding based on the vector -// element size in bits (8, 16, 32, 64) and the CDisp8 form. -class EVEX_CD8 { - int CD8_EltSize = !srl(esize, 3); - bits<3> CD8_Form = form.Value; -} - -class XOP { Encoding OpEnc = EncXOP; } -class XOP_4V : XOP { bit hasVEX_4V = 1; } - -// Specify the alternative register form instruction to replace the current -// instruction in case it was picked during generation of memory folding tables -class FoldGenData { - string FoldGenRegForm = _RegisterForm; -} - -// Provide a specific instruction to be used by the EVEX2VEX conversion. -class EVEX2VEXOverride { - string EVEX2VEXOverride = VEXInstrName; -} - -// Mark the instruction as "illegal to memory fold/unfold" -class NotMemoryFoldable { bit isMemoryFoldable = 0; } - -// Prevent EVEX->VEX conversion from considering this instruction. -class NotEVEX2VEXConvertible { bit notEVEX2VEXConvertible = 1; } - -class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, - string AsmStr, Domain d = GenericDomain> - : Instruction { - let Namespace = "X86"; - - bits<8> Opcode = opcod; - Format Form = f; - bits<7> FormBits = Form.Value; - ImmType ImmT = i; - - dag OutOperandList = outs; - dag InOperandList = ins; - string AsmString = AsmStr; - - // If this is a pseudo instruction, mark it isCodeGenOnly. - let isCodeGenOnly = !eq(!cast(f), "Pseudo"); - - // - // Attributes specific to X86 instructions... - // - bit ForceDisassemble = 0; // Force instruction to disassemble even though it's - // isCodeGenonly. Needed to hide an ambiguous - // AsmString from the parser, but still disassemble. - - OperandSize OpSize = OpSizeFixed; // Does this instruction's encoding change - // based on operand size of the mode? - bits<2> OpSizeBits = OpSize.Value; - AddressSize AdSize = AdSizeX; // Does this instruction's encoding change - // based on address size of the mode? - bits<2> AdSizeBits = AdSize.Value; - - Prefix OpPrefix = NoPrfx; // Which prefix byte does this inst have? - bits<3> OpPrefixBits = OpPrefix.Value; - Map OpMap = OB; // Which opcode map does this inst have? - bits<3> OpMapBits = OpMap.Value; - bit hasREX_WPrefix = 0; // Does this inst require the REX.W prefix? - FPFormat FPForm = NotFP; // What flavor of FP instruction is this? - bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix? - Domain ExeDomain = d; - bit hasREPPrefix = 0; // Does this inst have a REP prefix? - Encoding OpEnc = EncNormal; // Encoding used by this instruction - bits<2> OpEncBits = OpEnc.Value; - bits<2> VEX_WPrefix = 0; // Does this inst set the VEX_W field? - bit hasVEX_4V = 0; // Does this inst require the VEX.VVVV field? - bit hasVEX_L = 0; // Does this inst use large (256-bit) registers? - bit ignoresVEX_L = 0; // Does this instruction ignore the L-bit - bit hasEVEX_K = 0; // Does this inst require masking? - bit hasEVEX_Z = 0; // Does this inst set the EVEX_Z field? - bit hasEVEX_L2 = 0; // Does this inst set the EVEX_L2 field? - bit hasEVEX_B = 0; // Does this inst set the EVEX_B field? - bits<3> CD8_Form = 0; // Compressed disp8 form - vector-width. - // Declare it int rather than bits<4> so that all bits are defined when - // assigning to bits<7>. - int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes. - bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction. - bit hasNoTrackPrefix = 0; // Does this inst has 0x3E (NoTrack) prefix? - - bits<2> EVEX_LL; - let EVEX_LL{0} = hasVEX_L; - let EVEX_LL{1} = hasEVEX_L2; - // Vector size in bytes. - bits<7> VectSize = !shl(16, EVEX_LL); - - // The scaling factor for AVX512's compressed displacement is either - // - the size of a power-of-two number of elements or - // - the size of a single element for broadcasts or - // - the total vector size divided by a power-of-two number. - // Possible values are: 0 (non-AVX512 inst), 1, 2, 4, 8, 16, 32 and 64. - bits<7> CD8_Scale = !if (!eq (OpEnc.Value, EncEVEX.Value), - !if (CD8_Form{2}, - !shl(CD8_EltSize, CD8_Form{1-0}), - !if (hasEVEX_B, - CD8_EltSize, - !srl(VectSize, CD8_Form{1-0}))), 0); - - // Used in the memory folding generation (TableGen backend) to point to an alternative - // instruction to replace the current one in case it got picked during generation. - string FoldGenRegForm = ?; - - // Used to prevent an explicit EVEX2VEX override for this instruction. - string EVEX2VEXOverride = ?; - - bit isMemoryFoldable = 1; // Is it allowed to memory fold/unfold this instruction? - bit notEVEX2VEXConvertible = 0; // Prevent EVEX->VEX conversion. - - // TSFlags layout should be kept in sync with X86BaseInfo.h. - let TSFlags{6-0} = FormBits; - let TSFlags{8-7} = OpSizeBits; - let TSFlags{10-9} = AdSizeBits; - // No need for 3rd bit, we don't need to distinguish NoPrfx from PS. - let TSFlags{12-11} = OpPrefixBits{1-0}; - let TSFlags{15-13} = OpMapBits; - let TSFlags{16} = hasREX_WPrefix; - let TSFlags{20-17} = ImmT.Value; - let TSFlags{23-21} = FPForm.Value; - let TSFlags{24} = hasLockPrefix; - let TSFlags{25} = hasREPPrefix; - let TSFlags{27-26} = ExeDomain.Value; - let TSFlags{29-28} = OpEncBits; - let TSFlags{37-30} = Opcode; - // Currently no need for second bit in TSFlags - W Ignore is equivalent to 0. - let TSFlags{38} = VEX_WPrefix{0}; - let TSFlags{39} = hasVEX_4V; - let TSFlags{40} = hasVEX_L; - let TSFlags{41} = hasEVEX_K; - let TSFlags{42} = hasEVEX_Z; - let TSFlags{43} = hasEVEX_L2; - let TSFlags{44} = hasEVEX_B; - // If we run out of TSFlags bits, it's possible to encode this in 3 bits. - let TSFlags{51-45} = CD8_Scale; - let TSFlags{52} = hasEVEX_RC; - let TSFlags{53} = hasNoTrackPrefix; -} - -class PseudoI pattern> - : X86Inst<0, Pseudo, NoImm, oops, iops, ""> { - let Pattern = pattern; -} - -class I o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8 o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8Reg o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii8PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} -class Ii32S o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii64 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii16PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Ii32PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -// FPStack Instruction Templates: -// FPI - Floating Point Instruction template. -class FPI o, Format F, dag outs, dag ins, string asm> - : I {} - -// FpI_ - Floating Point Pseudo Instruction template. Not Predicated. -class FpI_ pattern> - : PseudoI { - let FPForm = fp; -} - -// Templates for instructions that use a 16- or 32-bit segmented address as -// their only operand: lcall (FAR CALL) and ljmp (FAR JMP) -// -// Iseg16 - 16-bit segment selector, 16-bit offset -// Iseg32 - 16-bit segment selector, 32-bit offset - -class Iseg16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -class Iseg32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; - let CodeSize = 3; -} - -// SI - SSE 1 & 2 scalar instructions -class SI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SI - SSE 1 & 2 scalar intrinsics - vex form available on AVX512 -class SI_Int o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} -// SIi8 - SSE 1 & 2 scalar instructions - vex form available on AVX512 -class SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - [UseSSE2]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// PI - SSE 1 & 2 packed instructions -class PI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// MMXPI - SSE 1 & 2 packed instructions with MMX operands -class MMXPI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpPrefix.Value, PD.Value), [HasMMX, HasSSE2], - [HasMMX, HasSSE1]); -} - -// PIi8 - SSE 1 & 2 packed instructions with immediate -class PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SSE1 Instruction Templates: -// -// SSI - SSE1 instructions with XS prefix. -// PSI - SSE1 instructions with PS prefix. -// PSIi8 - SSE1 instructions with ImmT == Imm8 and PS prefix. -// VSSI - SSE1 instructions with XS prefix in AVX form. -// VPSI - SSE1 instructions with PS prefix in AVX form, packed single. - -class SSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE1]>; -class SSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE1]>; -class PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[UseSSE1]>; -class PSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, - Requires<[UseSSE1]>; -class VSSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX]>; - -// SSE2 Instruction Templates: -// -// SDI - SSE2 instructions with XD prefix. -// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix. -// S2SI - SSE2 instructions with XS prefix. -// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix. -// PDI - SSE2 instructions with PD prefix, packed double domain. -// PDIi8 - SSE2 instructions with ImmT == Imm8 and PD prefix. -// VSDI - SSE2 scalar instructions with XD prefix in AVX form. -// VPDI - SSE2 vector instructions with PD prefix in AVX form, -// packed double domain. -// VS2I - SSE2 scalar instructions with PD prefix in AVX form. -// S2I - SSE2 scalar instructions with PD prefix. -// MMXSDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix as well as -// MMX operands. -// MMXSSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix as well as -// MMX operands. - -class SDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, Requires<[UseSSE2]>; -class SDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[UseSSE2]>; -class S2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE2]>; -class S2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE2]>; -class PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE2]>; -class PDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[UseSSE2]>; -class VSDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseAVX]>; -class VS2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - PD, Requires<[HasAVX]>; -class VS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseAVX]>; -class S2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[UseSSE2]>; -class MMXSDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX, HasSSE2]>; -class MMXS2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX, HasSSE2]>; - -// SSE3 Instruction Templates: -// -// S3I - SSE3 instructions with PD prefixes. -// S3SI - SSE3 instructions with XS prefix. -// S3DI - SSE3 instructions with XD prefix. - -class S3SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[UseSSE3]>; -class S3DI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseSSE3]>; -class S3I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE3]>; - - -// SSSE3 Instruction Templates: -// -// SS38I - SSSE3 instructions with T8 prefix. -// SS3AI - SSSE3 instructions with TA prefix. -// MMXSS38I - SSSE3 instructions with T8 prefix and MMX operands. -// MMXSS3AI - SSSE3 instructions with TA prefix and MMX operands. -// -// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version -// uses the MMX registers. The 64-bit versions are grouped with the MMX -// classes. They need to be enabled even if AVX is enabled. - -class SS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSSE3]>; -class SS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSSE3]>; -class MMXSS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PS, - Requires<[HasMMX, HasSSSE3]>; -class MMXSS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPS, - Requires<[HasMMX, HasSSSE3]>; - -// SSE4.1 Instruction Templates: -// -// SS48I - SSE 4.1 instructions with T8 prefix. -// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8. -// -class SS48I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE41]>; -class SS4AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE41]>; - -// SSE4.2 Instruction Templates: -// -// SS428I - SSE 4.2 instructions with T8 prefix. -class SS428I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE42]>; - -// SS42FI - SSE 4.2 instructions with T8XD prefix. -// NOTE: 'HasSSE42' is used as SS42FI is only used for CRC32 insns. -class SS42FI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XD, Requires<[HasSSE42]>; - -// SS42AI = SSE 4.2 instructions with TA prefix -class SS42AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE42]>; - -// AVX Instruction Templates: -// Instructions introduced in AVX (no SSE equivalent forms) -// -// AVX8I - AVX instructions with T8PD prefix. -// AVXAIi8 - AVX instructions with TAPD prefix and ImmT = Imm8. -class AVX8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX]>; -class AVXAIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX]>; - -// AVX2 Instruction Templates: -// Instructions introduced in AVX2 (no SSE equivalent forms) -// -// AVX28I - AVX2 instructions with T8PD prefix. -// AVX2AIi8 - AVX2 instructions with TAPD prefix and ImmT = Imm8. -class AVX28I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX2]>; -class AVX2AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX2]>; - - -// AVX-512 Instruction Templates: -// Instructions introduced in AVX-512 (no SSE equivalent forms) -// -// AVX5128I - AVX-512 instructions with T8PD prefix. -// AVX512AIi8 - AVX-512 instructions with TAPD prefix and ImmT = Imm8. -// AVX512PDI - AVX-512 instructions with PD, double packed. -// AVX512PSI - AVX-512 instructions with PS, single packed. -// AVX512XS8I - AVX-512 instructions with T8 and XS prefixes. -// AVX512XSI - AVX-512 instructions with XS prefix, generic domain. -// AVX512BI - AVX-512 instructions with PD, int packed domain. -// AVX512SI - AVX-512 scalar instructions with PD prefix. - -class AVX5128I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX512]>; -class AVX5128IBase : T8PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512XS8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XS, - Requires<[HasAVX512]>; -class AVX512XSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX512]>; -class AVX512XDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[HasAVX512]>; -class AVX512BI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512BIBase : PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512BIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[HasAVX512]>; -class AVX512BIi8Base : PD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XSIi8Base : XS { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XDIi8Base : XD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512PSIi8Base : PS { - Domain ExeDomain = SSEPackedSingle; - ImmType ImmT = Imm8; -} -class AVX512PDIi8Base : PD { - Domain ExeDomain = SSEPackedDouble; - ImmType ImmT = Imm8; -} -class AVX512AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX512]>; -class AVX512AIi8Base : TAPD { - ImmType ImmT = Imm8; -} -class AVX512Ii8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - Requires<[HasAVX512]>; -class AVX512PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX512]>; -class AVX512PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8, Requires<[HasAVX512]>; -class AVX512PI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : I, Requires<[HasAVX512]>; -class AVX512FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - EVEX_4V, Requires<[HasAVX512]>; -class AVX512FMA3Base : T8PD, EVEX_4V; - -class AVX512 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, Requires<[HasAVX512]>; - -// AES Instruction Templates: -// -// AES8I -// These use the same encoding as the SSE4.2 T8 and TA encodings. -class AES8I o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - Requires<[NoAVX, HasAES]>; - -class AESAI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[NoAVX, HasAES]>; - -// PCLMUL Instruction Templates -class PCLMULIi8 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8, TAPD; - -// FMA3 Instruction Templates -class FMA3 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoVLX]>; -class FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoAVX512]>; -class FMA3S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoAVX512]>; - -// FMA4 Instruction Templates -class FMA4 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoVLX]>; -class FMA4S o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoAVX512]>; -class FMA4S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4]>; - -// XOP 2, 3 and 4 Operand Instruction Template -class IXOP o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - XOP9, Requires<[HasXOP]>; - -// XOP 2 and 3 Operand Instruction Templates with imm byte -class IXOPi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - XOP8, Requires<[HasXOP]>; -// XOP 4 Operand Instruction Templates with imm byte -class IXOPi8Reg o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8Reg, - XOP8, Requires<[HasXOP]>; - -// XOP 5 operand instruction (VEX encoding!) -class IXOP5 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, Requires<[HasXOP]>; - -// X86-64 Instruction templates... -// - -class RI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, REX_W; -class RIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, REX_W; -class RIi16 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii16, REX_W; -class RIi32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32, REX_W; -class RIi32S o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32S, REX_W; -class RIi64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii64, REX_W; - -class RS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : S2I, REX_W; -class VRS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : VS2I, VEX_W; - -// MMX Instruction templates -// - -// MMXI - MMX instructions with TB prefix. -// MMXI32 - MMX instructions with TB prefix valid only in 32 bit mode. -// MMXI64 - MMX instructions with TB prefix valid only in 64 bit mode. -// MMX2I - MMX / SSE2 instructions with PD prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXID - MMX instructions with XD prefix. -// MMXIS - MMX instructions with XS prefix. -class MMXI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX]>; -class MMXI32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,Not64BitMode]>; -class MMXI64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,In64BitMode]>; -class MMXRI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, REX_W, Requires<[HasMMX]>; -class MMX2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[HasMMX]>; -class MMXIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, Requires<[HasMMX]>; -class MMXID o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX]>; -class MMXIS o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX]>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrFragmentsSIMD.td b/suite/synctools/tablegen/X86/back/X86InstrFragmentsSIMD.td deleted file mode 100644 index 7392759079..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrFragmentsSIMD.td +++ /dev/null @@ -1,1075 +0,0 @@ -//===-- X86InstrFragmentsSIMD.td - x86 SIMD ISA ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides pattern fragments useful for SIMD instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MMX specific DAG Nodes. -//===----------------------------------------------------------------------===// - -// Low word of MMX to GPR. -def MMX_X86movd2w : SDNode<"X86ISD::MMX_MOVD2W", SDTypeProfile<1, 1, - [SDTCisVT<0, i32>, SDTCisVT<1, x86mmx>]>>; -// GPR to low word of MMX. -def MMX_X86movw2d : SDNode<"X86ISD::MMX_MOVW2D", SDTypeProfile<1, 1, - [SDTCisVT<0, x86mmx>, SDTCisVT<1, i32>]>>; - -//===----------------------------------------------------------------------===// -// MMX Pattern Fragments -//===----------------------------------------------------------------------===// - -def load_mmx : PatFrag<(ops node:$ptr), (x86mmx (load node:$ptr))>; - -//===----------------------------------------------------------------------===// -// SSE specific DAG Nodes. -//===----------------------------------------------------------------------===// - -def SDTX86VFCMP : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>]>; - -def X86fmin : SDNode<"X86ISD::FMIN", SDTFPBinOp>; -def X86fmax : SDNode<"X86ISD::FMAX", SDTFPBinOp>; -def X86fmins : SDNode<"X86ISD::FMINS", SDTFPBinOp>; -def X86fmaxs : SDNode<"X86ISD::FMAXS", SDTFPBinOp>; - -// Commutative and Associative FMIN and FMAX. -def X86fminc : SDNode<"X86ISD::FMINC", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fmaxc : SDNode<"X86ISD::FMAXC", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; - -def X86fand : SDNode<"X86ISD::FAND", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86for : SDNode<"X86ISD::FOR", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fxor : SDNode<"X86ISD::FXOR", SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def X86fandn : SDNode<"X86ISD::FANDN", SDTFPBinOp>; -def X86frsqrt : SDNode<"X86ISD::FRSQRT", SDTFPUnaryOp>; -def X86frcp : SDNode<"X86ISD::FRCP", SDTFPUnaryOp>; -def X86fhadd : SDNode<"X86ISD::FHADD", SDTFPBinOp>; -def X86fhsub : SDNode<"X86ISD::FHSUB", SDTFPBinOp>; -def X86hadd : SDNode<"X86ISD::HADD", SDTIntBinOp>; -def X86hsub : SDNode<"X86ISD::HSUB", SDTIntBinOp>; -def X86comi : SDNode<"X86ISD::COMI", SDTX86CmpTest>; -def X86ucomi : SDNode<"X86ISD::UCOMI", SDTX86CmpTest>; -def X86cmps : SDNode<"X86ISD::FSETCC", SDTX86Cmps>; -def X86pshufb : SDNode<"X86ISD::PSHUFB", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i8>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86psadbw : SDNode<"X86ISD::PSADBW", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>, [SDNPCommutative]>; -def X86dbpsadbw : SDNode<"X86ISD::DBPSADBW", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>, SDTCisInt<3>]>>; -def X86andnp : SDNode<"X86ISD::ANDNP", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86multishift : SDNode<"X86ISD::MULTISHIFT", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<1,2>]>>; -def X86pextrb : SDNode<"X86ISD::PEXTRB", - SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, v16i8>, - SDTCisPtrTy<2>]>>; -def X86pextrw : SDNode<"X86ISD::PEXTRW", - SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, v8i16>, - SDTCisPtrTy<2>]>>; -def X86pinsrb : SDNode<"X86ISD::PINSRB", - SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; -def X86pinsrw : SDNode<"X86ISD::PINSRW", - SDTypeProfile<1, 3, [SDTCisVT<0, v8i16>, SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; -def X86insertps : SDNode<"X86ISD::INSERTPS", - SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisSameAs<0,1>, - SDTCisVT<2, v4f32>, SDTCisVT<3, i8>]>>; -def X86vzmovl : SDNode<"X86ISD::VZEXT_MOVL", - SDTypeProfile<1, 1, [SDTCisSameAs<0,1>]>>; - -def X86vzload : SDNode<"X86ISD::VZEXT_LOAD", SDTLoad, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; - -def X86vzext : SDNode<"X86ISD::VZEXT", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<1, 0>]>>; - -def X86vsext : SDNode<"X86ISD::VSEXT", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<1, 0>]>>; - -def SDTVtrunc : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisInt<1>, - SDTCisOpSmallerThanOp<0, 1>]>; - -def X86vtrunc : SDNode<"X86ISD::VTRUNC", SDTVtrunc>; -def X86vtruncs : SDNode<"X86ISD::VTRUNCS", SDTVtrunc>; -def X86vtruncus : SDNode<"X86ISD::VTRUNCUS", SDTVtrunc>; - -def X86vfpext : SDNode<"X86ISD::VFPEXT", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f64>, - SDTCVecEltisVT<1, f32>, - SDTCisSameSizeAs<0, 1>]>>; -def X86vfpround: SDNode<"X86ISD::VFPROUND", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, f64>, - SDTCisSameSizeAs<0, 1>]>>; - -def X86froundRnd: SDNode<"X86ISD::VFPROUNDS_RND", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, f32>, - SDTCisSameAs<0, 1>, - SDTCVecEltisVT<2, f64>, - SDTCisSameSizeAs<0, 2>, - SDTCisVT<3, i32>]>>; - -def X86fpextRnd : SDNode<"X86ISD::VFPEXTS_RND", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, f64>, - SDTCisSameAs<0, 1>, - SDTCVecEltisVT<2, f32>, - SDTCisSameSizeAs<0, 2>, - SDTCisVT<3, i32>]>>; - -def X86vshiftimm : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisVT<2, i8>, SDTCisInt<0>]>; - -def X86vshldq : SDNode<"X86ISD::VSHLDQ", X86vshiftimm>; -def X86vshrdq : SDNode<"X86ISD::VSRLDQ", X86vshiftimm>; -def X86cmpp : SDNode<"X86ISD::CMPP", SDTX86VFCMP>; -def X86pcmpeq : SDNode<"X86ISD::PCMPEQ", SDTIntBinOp, [SDNPCommutative]>; -def X86pcmpgt : SDNode<"X86ISD::PCMPGT", SDTIntBinOp>; - -def X86CmpMaskCC : - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCVecEltisVT<0, i1>, - SDTCisVec<1>, SDTCisSameAs<2, 1>, - SDTCisSameNumEltsAs<0, 1>, SDTCisVT<3, i8>]>; -def X86CmpMaskCCRound : - SDTypeProfile<1, 4, [SDTCisVec<0>,SDTCVecEltisVT<0, i1>, - SDTCisVec<1>, SDTCisFP<1>, SDTCisSameAs<2, 1>, - SDTCisSameNumEltsAs<0, 1>, SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; -def X86CmpMaskCCScalar : - SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisFP<1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>]>; - -def X86CmpMaskCCScalarRound : - SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisFP<1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -def X86cmpm : SDNode<"X86ISD::CMPM", X86CmpMaskCC>; -// Hack to make CMPM commutable in tablegen patterns for load folding. -def X86cmpm_c : SDNode<"X86ISD::CMPM", X86CmpMaskCC, [SDNPCommutative]>; -def X86cmpmRnd : SDNode<"X86ISD::CMPM_RND", X86CmpMaskCCRound>; -def X86cmpms : SDNode<"X86ISD::FSETCCM", X86CmpMaskCCScalar>; -def X86cmpmsRnd : SDNode<"X86ISD::FSETCCM_RND", X86CmpMaskCCScalarRound>; - -def X86phminpos: SDNode<"X86ISD::PHMINPOS", - SDTypeProfile<1, 1, [SDTCisVT<0, v8i16>, SDTCisVT<1, v8i16>]>>; - -def X86vshiftuniform : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisVec<2>, SDTCisInt<0>, - SDTCisInt<1>]>; - -def X86vshl : SDNode<"X86ISD::VSHL", X86vshiftuniform>; -def X86vsrl : SDNode<"X86ISD::VSRL", X86vshiftuniform>; -def X86vsra : SDNode<"X86ISD::VSRA", X86vshiftuniform>; - -def X86vshiftvariable : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisInt<0>]>; - -def X86vsrav : SDNode<"X86ISD::VSRAV", X86vshiftvariable>; - -def X86vshli : SDNode<"X86ISD::VSHLI", X86vshiftimm>; -def X86vsrli : SDNode<"X86ISD::VSRLI", X86vshiftimm>; -def X86vsrai : SDNode<"X86ISD::VSRAI", X86vshiftimm>; - -def X86kshiftl : SDNode<"X86ISD::KSHIFTL", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisSameAs<0, 1>, - SDTCisVT<2, i8>]>>; -def X86kshiftr : SDNode<"X86ISD::KSHIFTR", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisSameAs<0, 1>, - SDTCisVT<2, i8>]>>; - -def X86kadd : SDNode<"X86ISD::KADD", SDTIntBinOp, [SDNPCommutative]>; - -def X86vrotli : SDNode<"X86ISD::VROTLI", X86vshiftimm>; -def X86vrotri : SDNode<"X86ISD::VROTRI", X86vshiftimm>; - -def X86vpshl : SDNode<"X86ISD::VPSHL", X86vshiftvariable>; -def X86vpsha : SDNode<"X86ISD::VPSHA", X86vshiftvariable>; - -def X86vpcom : SDNode<"X86ISD::VPCOM", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>, SDTCisInt<0>]>>; -def X86vpcomu : SDNode<"X86ISD::VPCOMU", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>, SDTCisInt<0>]>>; -def X86vpermil2 : SDNode<"X86ISD::VPERMIL2", - SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisFP<0>, SDTCisInt<3>, - SDTCisSameNumEltsAs<0, 3>, - SDTCisSameSizeAs<0,3>, - SDTCisVT<4, i8>]>>; -def X86vpperm : SDNode<"X86ISD::VPPERM", - SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisSameAs<0, 3>]>>; - -def SDTX86CmpPTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisVec<1>, - SDTCisSameAs<2, 1>]>; - -def X86addus : SDNode<"X86ISD::ADDUS", SDTIntBinOp, [SDNPCommutative]>; -def X86subus : SDNode<"X86ISD::SUBUS", SDTIntBinOp>; -def X86adds : SDNode<"X86ISD::ADDS", SDTIntBinOp, [SDNPCommutative]>; -def X86subs : SDNode<"X86ISD::SUBS", SDTIntBinOp>; -def X86mulhrs : SDNode<"X86ISD::MULHRS", SDTIntBinOp, [SDNPCommutative]>; -def X86avg : SDNode<"X86ISD::AVG" , SDTIntBinOp, [SDNPCommutative]>; -def X86ptest : SDNode<"X86ISD::PTEST", SDTX86CmpPTest>; -def X86testp : SDNode<"X86ISD::TESTP", SDTX86CmpPTest>; -def X86kortest : SDNode<"X86ISD::KORTEST", SDTX86CmpPTest>; -def X86ktest : SDNode<"X86ISD::KTEST", SDTX86CmpPTest>; - -def X86movmsk : SDNode<"X86ISD::MOVMSK", - SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVec<1>]>>; - -def X86selects : SDNode<"X86ISD::SELECTS", - SDTypeProfile<1, 3, [SDTCisVT<1, v1i1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<2, 3>]>>; - -def X86pmuludq : SDNode<"X86ISD::PMULUDQ", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; -def X86pmuldq : SDNode<"X86ISD::PMULDQ", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i64>, - SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; - -def X86extrqi : SDNode<"X86ISD::EXTRQI", - SDTypeProfile<1, 3, [SDTCisVT<0, v2i64>, SDTCisSameAs<0,1>, - SDTCisVT<2, i8>, SDTCisVT<3, i8>]>>; -def X86insertqi : SDNode<"X86ISD::INSERTQI", - SDTypeProfile<1, 4, [SDTCisVT<0, v2i64>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisVT<3, i8>, - SDTCisVT<4, i8>]>>; - -// Specific shuffle nodes - At some point ISD::VECTOR_SHUFFLE will always get -// translated into one of the target nodes below during lowering. -// Note: this is a work in progress... -def SDTShuff1Op : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>; -def SDTShuff2Op : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>]>; -def SDTShuff2OpFP : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisFP<0>, - SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>; - -def SDTShuff2OpM : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisFP<0>, SDTCisInt<2>, - SDTCisSameNumEltsAs<0,2>, - SDTCisSameSizeAs<0,2>]>; -def SDTShuff2OpI : SDTypeProfile<1, 2, [SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisVT<2, i8>]>; -def SDTShuff3OpI : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, SDTCisVT<3, i8>]>; -def SDTFPBinOpImm: SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i32>]>; -def SDTFPBinOpImmRound: SDTypeProfile<1, 4, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i32>, - SDTCisVT<4, i32>]>; -def SDTFPTernaryOpImmRound: SDTypeProfile<1, 5, [SDTCisFP<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisInt<3>, - SDTCisSameSizeAs<0, 3>, - SDTCisSameNumEltsAs<0, 3>, - SDTCisVT<4, i32>, - SDTCisVT<5, i32>]>; -def SDTFPUnaryOpImm: SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisVT<2, i32>]>; -def SDTFPUnaryOpImmRound: SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i32>]>; - -def SDTVBroadcast : SDTypeProfile<1, 1, [SDTCisVec<0>]>; -def SDTVBroadcastm : SDTypeProfile<1, 1, [SDTCisVec<0>, - SDTCisInt<0>, SDTCisInt<1>]>; - -def SDTBlend : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisVT<3, i8>]>; - -def SDTTernlog : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>, SDTCisVT<4, i8>]>; - -def SDTFPBinOpRound : SDTypeProfile<1, 3, [ // fadd_round, fmul_round, etc. - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0>, SDTCisVT<3, i32>]>; - -def SDTFPUnaryOpRound : SDTypeProfile<1, 2, [ // fsqrt_round, fgetexp_round, etc. - SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisVT<2, i32>]>; - -def SDTFmaRound : SDTypeProfile<1, 4, [SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>, - SDTCisFP<0>, SDTCisVT<4, i32>]>; - -def X86PAlignr : SDNode<"X86ISD::PALIGNR", - SDTypeProfile<1, 3, [SDTCVecEltisVT<0, i8>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisVT<3, i8>]>>; -def X86VAlign : SDNode<"X86ISD::VALIGN", SDTShuff3OpI>; - -def X86VShld : SDNode<"X86ISD::VSHLD", SDTShuff3OpI>; -def X86VShrd : SDNode<"X86ISD::VSHRD", SDTShuff3OpI>; -def X86VShldv : SDNode<"X86ISD::VSHLDV", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>]>>; -def X86VShrdv : SDNode<"X86ISD::VSHRDV", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, - SDTCisSameAs<0,2>, - SDTCisSameAs<0,3>]>>; - -def X86Conflict : SDNode<"X86ISD::CONFLICT", SDTIntUnaryOp>; - -def X86PShufd : SDNode<"X86ISD::PSHUFD", SDTShuff2OpI>; -def X86PShufhw : SDNode<"X86ISD::PSHUFHW", SDTShuff2OpI>; -def X86PShuflw : SDNode<"X86ISD::PSHUFLW", SDTShuff2OpI>; - -def X86Shufp : SDNode<"X86ISD::SHUFP", SDTShuff3OpI>; -def X86Shuf128 : SDNode<"X86ISD::SHUF128", SDTShuff3OpI>; - -def X86Movddup : SDNode<"X86ISD::MOVDDUP", SDTShuff1Op>; -def X86Movshdup : SDNode<"X86ISD::MOVSHDUP", SDTShuff1Op>; -def X86Movsldup : SDNode<"X86ISD::MOVSLDUP", SDTShuff1Op>; - -def X86Movsd : SDNode<"X86ISD::MOVSD", SDTShuff2OpFP>; -def X86Movss : SDNode<"X86ISD::MOVSS", SDTShuff2OpFP>; - -def X86Movlhps : SDNode<"X86ISD::MOVLHPS", SDTShuff2OpFP>; -def X86Movhlps : SDNode<"X86ISD::MOVHLPS", SDTShuff2OpFP>; - -def SDTPack : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, - SDTCisVec<1>, SDTCisInt<1>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>, - SDTCisOpSmallerThanOp<0, 1>]>; -def X86Packss : SDNode<"X86ISD::PACKSS", SDTPack>; -def X86Packus : SDNode<"X86ISD::PACKUS", SDTPack>; - -def X86Unpckl : SDNode<"X86ISD::UNPCKL", SDTShuff2Op>; -def X86Unpckh : SDNode<"X86ISD::UNPCKH", SDTShuff2Op>; - -def X86vpmaddubsw : SDNode<"X86ISD::VPMADDUBSW", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, i8>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>>; -def X86vpmaddwd : SDNode<"X86ISD::VPMADDWD", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i32>, - SDTCVecEltisVT<1, i16>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<1,2>]>, - [SDNPCommutative]>; - -def X86VPermilpv : SDNode<"X86ISD::VPERMILPV", SDTShuff2OpM>; -def X86VPermilpi : SDNode<"X86ISD::VPERMILPI", SDTShuff2OpI>; -def X86VPermv : SDNode<"X86ISD::VPERMV", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<1>, - SDTCisSameNumEltsAs<0,1>, - SDTCisSameSizeAs<0,1>, - SDTCisSameAs<0,2>]>>; -def X86VPermi : SDNode<"X86ISD::VPERMI", SDTShuff2OpI>; -def X86VPermt2 : SDNode<"X86ISD::VPERMV3", - SDTypeProfile<1, 3, [SDTCisVec<0>, - SDTCisSameAs<0,1>, SDTCisInt<2>, - SDTCisVec<2>, SDTCisSameNumEltsAs<0, 2>, - SDTCisSameSizeAs<0,2>, - SDTCisSameAs<0,3>]>, []>; - -def X86vpternlog : SDNode<"X86ISD::VPTERNLOG", SDTTernlog>; - -def X86VPerm2x128 : SDNode<"X86ISD::VPERM2X128", SDTShuff3OpI>; - -def X86VFixupimm : SDNode<"X86ISD::VFIXUPIMM", SDTFPTernaryOpImmRound>; -def X86VFixupimmScalar : SDNode<"X86ISD::VFIXUPIMMS", SDTFPTernaryOpImmRound>; -def X86VRange : SDNode<"X86ISD::VRANGE", SDTFPBinOpImm>; -def X86VRangeRnd : SDNode<"X86ISD::VRANGE_RND", SDTFPBinOpImmRound>; -def X86VReduce : SDNode<"X86ISD::VREDUCE", SDTFPUnaryOpImm>; -def X86VReduceRnd : SDNode<"X86ISD::VREDUCE_RND", SDTFPUnaryOpImmRound>; -def X86VRndScale : SDNode<"X86ISD::VRNDSCALE", SDTFPUnaryOpImm>; -def X86VRndScaleRnd: SDNode<"X86ISD::VRNDSCALE_RND", SDTFPUnaryOpImmRound>; -def X86VGetMant : SDNode<"X86ISD::VGETMANT", SDTFPUnaryOpImm>; -def X86VGetMantRnd : SDNode<"X86ISD::VGETMANT_RND", SDTFPUnaryOpImmRound>; -def X86Vfpclass : SDNode<"X86ISD::VFPCLASS", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i1>, - SDTCisFP<1>, - SDTCisSameNumEltsAs<0,1>, - SDTCisVT<2, i32>]>, []>; -def X86Vfpclasss : SDNode<"X86ISD::VFPCLASSS", - SDTypeProfile<1, 2, [SDTCisVT<0, v1i1>, - SDTCisFP<1>, SDTCisVT<2, i32>]>,[]>; - -def X86SubVBroadcast : SDNode<"X86ISD::SUBV_BROADCAST", - SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSubVecOfVec<1, 0>]>, []>; - -def X86VBroadcast : SDNode<"X86ISD::VBROADCAST", SDTVBroadcast>; -def X86VBroadcastm : SDNode<"X86ISD::VBROADCASTM", SDTVBroadcastm>; - -def X86Blendi : SDNode<"X86ISD::BLENDI", SDTBlend>; - -def X86Addsub : SDNode<"X86ISD::ADDSUB", SDTFPBinOp>; - -def X86faddRnd : SDNode<"X86ISD::FADD_RND", SDTFPBinOpRound>; -def X86faddRnds : SDNode<"X86ISD::FADDS_RND", SDTFPBinOpRound>; -def X86fsubRnd : SDNode<"X86ISD::FSUB_RND", SDTFPBinOpRound>; -def X86fsubRnds : SDNode<"X86ISD::FSUBS_RND", SDTFPBinOpRound>; -def X86fmulRnd : SDNode<"X86ISD::FMUL_RND", SDTFPBinOpRound>; -def X86fmulRnds : SDNode<"X86ISD::FMULS_RND", SDTFPBinOpRound>; -def X86fdivRnd : SDNode<"X86ISD::FDIV_RND", SDTFPBinOpRound>; -def X86fdivRnds : SDNode<"X86ISD::FDIVS_RND", SDTFPBinOpRound>; -def X86fmaxRnd : SDNode<"X86ISD::FMAX_RND", SDTFPBinOpRound>; -def X86fmaxRnds : SDNode<"X86ISD::FMAXS_RND", SDTFPBinOpRound>; -def X86fminRnd : SDNode<"X86ISD::FMIN_RND", SDTFPBinOpRound>; -def X86fminRnds : SDNode<"X86ISD::FMINS_RND", SDTFPBinOpRound>; -def X86scalef : SDNode<"X86ISD::SCALEF", SDTFPBinOpRound>; -def X86scalefs : SDNode<"X86ISD::SCALEFS", SDTFPBinOpRound>; -def X86fsqrtRnd : SDNode<"X86ISD::FSQRT_RND", SDTFPUnaryOpRound>; -def X86fsqrtRnds : SDNode<"X86ISD::FSQRTS_RND", SDTFPBinOpRound>; -def X86fgetexpRnd : SDNode<"X86ISD::FGETEXP_RND", SDTFPUnaryOpRound>; -def X86fgetexpRnds : SDNode<"X86ISD::FGETEXPS_RND", SDTFPBinOpRound>; - -def X86Fmadd : SDNode<"ISD::FMA", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fnmadd : SDNode<"X86ISD::FNMADD", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmsub : SDNode<"X86ISD::FMSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fnmsub : SDNode<"X86ISD::FNMSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmaddsub : SDNode<"X86ISD::FMADDSUB", SDTFPTernaryOp, [SDNPCommutative]>; -def X86Fmsubadd : SDNode<"X86ISD::FMSUBADD", SDTFPTernaryOp, [SDNPCommutative]>; - -def X86FmaddRnd : SDNode<"X86ISD::FMADD_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FnmaddRnd : SDNode<"X86ISD::FNMADD_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmsubRnd : SDNode<"X86ISD::FMSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FnmsubRnd : SDNode<"X86ISD::FNMSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmaddsubRnd : SDNode<"X86ISD::FMADDSUB_RND", SDTFmaRound, [SDNPCommutative]>; -def X86FmsubaddRnd : SDNode<"X86ISD::FMSUBADD_RND", SDTFmaRound, [SDNPCommutative]>; - -def SDTIFma : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>]>; -def x86vpmadd52l : SDNode<"X86ISD::VPMADD52L", SDTIFma, [SDNPCommutative]>; -def x86vpmadd52h : SDNode<"X86ISD::VPMADD52H", SDTIFma, [SDNPCommutative]>; - -def X86rsqrt14 : SDNode<"X86ISD::RSQRT14", SDTFPUnaryOp>; -def X86rcp14 : SDNode<"X86ISD::RCP14", SDTFPUnaryOp>; - -// VNNI -def SDTVnni : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisSameAs<1,3>]>; -def X86Vpdpbusd : SDNode<"X86ISD::VPDPBUSD", SDTVnni>; -def X86Vpdpbusds : SDNode<"X86ISD::VPDPBUSDS", SDTVnni>; -def X86Vpdpwssd : SDNode<"X86ISD::VPDPWSSD", SDTVnni>; -def X86Vpdpwssds : SDNode<"X86ISD::VPDPWSSDS", SDTVnni>; - -def X86rsqrt28 : SDNode<"X86ISD::RSQRT28", SDTFPUnaryOpRound>; -def X86rcp28 : SDNode<"X86ISD::RCP28", SDTFPUnaryOpRound>; -def X86exp2 : SDNode<"X86ISD::EXP2", SDTFPUnaryOpRound>; - -def X86rsqrt14s : SDNode<"X86ISD::RSQRT14S", SDTFPBinOp>; -def X86rcp14s : SDNode<"X86ISD::RCP14S", SDTFPBinOp>; -def X86rsqrt28s : SDNode<"X86ISD::RSQRT28S", SDTFPBinOpRound>; -def X86rcp28s : SDNode<"X86ISD::RCP28S", SDTFPBinOpRound>; -def X86Ranges : SDNode<"X86ISD::VRANGES", SDTFPBinOpImm>; -def X86RndScales : SDNode<"X86ISD::VRNDSCALES", SDTFPBinOpImm>; -def X86Reduces : SDNode<"X86ISD::VREDUCES", SDTFPBinOpImm>; -def X86GetMants : SDNode<"X86ISD::VGETMANTS", SDTFPBinOpImm>; -def X86RangesRnd : SDNode<"X86ISD::VRANGES_RND", SDTFPBinOpImmRound>; -def X86RndScalesRnd : SDNode<"X86ISD::VRNDSCALES_RND", SDTFPBinOpImmRound>; -def X86ReducesRnd : SDNode<"X86ISD::VREDUCES_RND", SDTFPBinOpImmRound>; -def X86GetMantsRnd : SDNode<"X86ISD::VGETMANTS_RND", SDTFPBinOpImmRound>; - -def X86compress: SDNode<"X86ISD::COMPRESS", SDTypeProfile<1, 1, - [SDTCisSameAs<0, 1>, SDTCisVec<1>]>, []>; -def X86expand : SDNode<"X86ISD::EXPAND", SDTypeProfile<1, 1, - [SDTCisSameAs<0, 1>, SDTCisVec<1>]>, []>; - -// vpshufbitqmb -def X86Vpshufbitqmb : SDNode<"X86ISD::VPSHUFBITQMB", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<1,2>, - SDTCVecEltisVT<0,i1>, - SDTCisSameNumEltsAs<0,1>]>>; - -def SDTintToFPRound: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisFP<0>, - SDTCisSameAs<0,1>, SDTCisInt<2>, - SDTCisVT<3, i32>]>; - -def SDTFloatToInt: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisFP<1>]>; -def SDTFloatToIntRnd: SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisInt<0>, SDTCisFP<1>, - SDTCisVT<2, i32>]>; -def SDTSFloatToIntRnd: SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisFP<1>, - SDTCisVec<1>, SDTCisVT<2, i32>]>; - -def SDTVintToFP: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisFP<0>, SDTCisInt<1>]>; -def SDTVintToFPRound: SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisFP<0>, SDTCisInt<1>, - SDTCisVT<2, i32>]>; - -// Scalar -def X86SintToFpRnd : SDNode<"X86ISD::SCALAR_SINT_TO_FP_RND", SDTintToFPRound>; -def X86UintToFpRnd : SDNode<"X86ISD::SCALAR_UINT_TO_FP_RND", SDTintToFPRound>; - -def X86cvtts2IntRnd : SDNode<"X86ISD::CVTTS2SI_RND", SDTSFloatToIntRnd>; -def X86cvtts2UIntRnd : SDNode<"X86ISD::CVTTS2UI_RND", SDTSFloatToIntRnd>; - -def X86cvts2si : SDNode<"X86ISD::CVTS2SI_RND", SDTSFloatToIntRnd>; -def X86cvts2usi : SDNode<"X86ISD::CVTS2UI_RND", SDTSFloatToIntRnd>; - -// Vector with rounding mode - -// cvtt fp-to-int staff -def X86cvttp2siRnd : SDNode<"X86ISD::CVTTP2SI_RND", SDTFloatToIntRnd>; -def X86cvttp2uiRnd : SDNode<"X86ISD::CVTTP2UI_RND", SDTFloatToIntRnd>; - -def X86VSintToFpRnd : SDNode<"X86ISD::SINT_TO_FP_RND", SDTVintToFPRound>; -def X86VUintToFpRnd : SDNode<"X86ISD::UINT_TO_FP_RND", SDTVintToFPRound>; - -// cvt fp-to-int staff -def X86cvtp2IntRnd : SDNode<"X86ISD::CVTP2SI_RND", SDTFloatToIntRnd>; -def X86cvtp2UIntRnd : SDNode<"X86ISD::CVTP2UI_RND", SDTFloatToIntRnd>; - -// Vector without rounding mode - -// cvtt fp-to-int staff -def X86cvttp2si : SDNode<"X86ISD::CVTTP2SI", SDTFloatToInt>; -def X86cvttp2ui : SDNode<"X86ISD::CVTTP2UI", SDTFloatToInt>; - -def X86VSintToFP : SDNode<"X86ISD::CVTSI2P", SDTVintToFP>; -def X86VUintToFP : SDNode<"X86ISD::CVTUI2P", SDTVintToFP>; - -// cvt int-to-fp staff -def X86cvtp2Int : SDNode<"X86ISD::CVTP2SI", SDTFloatToInt>; -def X86cvtp2UInt : SDNode<"X86ISD::CVTP2UI", SDTFloatToInt>; - - -def X86cvtph2ps : SDNode<"X86ISD::CVTPH2PS", - SDTypeProfile<1, 1, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, i16>]> >; - -def X86cvtph2psRnd : SDNode<"X86ISD::CVTPH2PS_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, i16>, - SDTCisVT<2, i32>]> >; - -def X86cvtps2ph : SDNode<"X86ISD::CVTPS2PH", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, i16>, - SDTCVecEltisVT<1, f32>, - SDTCisVT<2, i32>]> >; -def X86vfpextRnd : SDNode<"X86ISD::VFPEXT_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f64>, - SDTCVecEltisVT<1, f32>, - SDTCisOpSmallerThanOp<1, 0>, - SDTCisVT<2, i32>]>>; -def X86vfproundRnd: SDNode<"X86ISD::VFPROUND_RND", - SDTypeProfile<1, 2, [SDTCVecEltisVT<0, f32>, - SDTCVecEltisVT<1, f64>, - SDTCisOpSmallerThanOp<0, 1>, - SDTCisVT<2, i32>]>>; - -// galois field arithmetic -def X86GF2P8affineinvqb : SDNode<"X86ISD::GF2P8AFFINEINVQB", SDTBlend>; -def X86GF2P8affineqb : SDNode<"X86ISD::GF2P8AFFINEQB", SDTBlend>; -def X86GF2P8mulb : SDNode<"X86ISD::GF2P8MULB", SDTIntBinOp>; - -//===----------------------------------------------------------------------===// -// SSE Complex Patterns -//===----------------------------------------------------------------------===// - -// These are 'extloads' from a scalar to the low element of a vector, zeroing -// the top elements. These are used for the SSE 'ss' and 'sd' instruction -// forms. -def sse_load_f32 : ComplexPattern; -def sse_load_f64 : ComplexPattern; - -def ssmem : Operand { - let PrintMethod = "printf32mem"; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} -def sdmem : Operand { - let PrintMethod = "printf64mem"; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -//===----------------------------------------------------------------------===// -// SSE pattern fragments -//===----------------------------------------------------------------------===// - -// Vector load wrappers to prevent folding of non-temporal aligned loads on -// supporting targets. -def vecload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - return !useNonTemporalLoad(cast(N)); -}]>; - -// 128-bit load pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def loadv4f32 : PatFrag<(ops node:$ptr), (v4f32 (vecload node:$ptr))>; -def loadv2f64 : PatFrag<(ops node:$ptr), (v2f64 (vecload node:$ptr))>; -def loadv2i64 : PatFrag<(ops node:$ptr), (v2i64 (vecload node:$ptr))>; - -// 256-bit load pattern fragments -// NOTE: all 256-bit integer vector loads are promoted to v4i64 -def loadv8f32 : PatFrag<(ops node:$ptr), (v8f32 (vecload node:$ptr))>; -def loadv4f64 : PatFrag<(ops node:$ptr), (v4f64 (vecload node:$ptr))>; -def loadv4i64 : PatFrag<(ops node:$ptr), (v4i64 (vecload node:$ptr))>; - -// 512-bit load pattern fragments -def loadv16f32 : PatFrag<(ops node:$ptr), (v16f32 (vecload node:$ptr))>; -def loadv8f64 : PatFrag<(ops node:$ptr), (v8f64 (vecload node:$ptr))>; -def loadv8i64 : PatFrag<(ops node:$ptr), (v8i64 (vecload node:$ptr))>; - -// 128-/256-/512-bit extload pattern fragments -def extloadv2f32 : PatFrag<(ops node:$ptr), (v2f64 (extloadvf32 node:$ptr))>; -def extloadv4f32 : PatFrag<(ops node:$ptr), (v4f64 (extloadvf32 node:$ptr))>; -def extloadv8f32 : PatFrag<(ops node:$ptr), (v8f64 (extloadvf32 node:$ptr))>; - -// Like 'store', but always requires vector size alignment. -def alignedstore : PatFrag<(ops node:$val, node:$ptr), - (store node:$val, node:$ptr), [{ - auto *St = cast(N); - return St->getAlignment() >= St->getMemoryVT().getStoreSize(); -}]>; - -// Like 'load', but always requires 128-bit vector alignment. -def alignedvecload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - auto *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize() && - !useNonTemporalLoad(cast(N)); -}]>; - -// 128-bit aligned load pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def alignedloadv4f32 : PatFrag<(ops node:$ptr), - (v4f32 (alignedvecload node:$ptr))>; -def alignedloadv2f64 : PatFrag<(ops node:$ptr), - (v2f64 (alignedvecload node:$ptr))>; -def alignedloadv2i64 : PatFrag<(ops node:$ptr), - (v2i64 (alignedvecload node:$ptr))>; - -// 256-bit aligned load pattern fragments -// NOTE: all 256-bit integer vector loads are promoted to v4i64 -def alignedloadv8f32 : PatFrag<(ops node:$ptr), - (v8f32 (alignedvecload node:$ptr))>; -def alignedloadv4f64 : PatFrag<(ops node:$ptr), - (v4f64 (alignedvecload node:$ptr))>; -def alignedloadv4i64 : PatFrag<(ops node:$ptr), - (v4i64 (alignedvecload node:$ptr))>; - -// 512-bit aligned load pattern fragments -def alignedloadv16f32 : PatFrag<(ops node:$ptr), - (v16f32 (alignedvecload node:$ptr))>; -def alignedloadv8f64 : PatFrag<(ops node:$ptr), - (v8f64 (alignedvecload node:$ptr))>; -def alignedloadv8i64 : PatFrag<(ops node:$ptr), - (v8i64 (alignedvecload node:$ptr))>; - -// Like 'vecload', but uses special alignment checks suitable for use in -// memory operands in most SSE instructions, which are required to -// be naturally aligned on some targets but not on others. If the subtarget -// allows unaligned accesses, match any load, though this may require -// setting a feature bit in the processor (on startup, for example). -// Opteron 10h and later implement such a feature. -def memop : PatFrag<(ops node:$ptr), (vecload node:$ptr), [{ - auto *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -// 128-bit memop pattern fragments -// NOTE: all 128-bit integer vector loads are promoted to v2i64 -def memopv4f32 : PatFrag<(ops node:$ptr), (v4f32 (memop node:$ptr))>; -def memopv2f64 : PatFrag<(ops node:$ptr), (v2f64 (memop node:$ptr))>; -def memopv2i64 : PatFrag<(ops node:$ptr), (v2i64 (memop node:$ptr))>; - -def X86masked_gather : SDNode<"X86ISD::MGATHER", - SDTypeProfile<2, 3, [SDTCisVec<0>, - SDTCisVec<1>, SDTCisInt<1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<1, 3>, - SDTCisPtrTy<4>]>, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; - -def X86masked_scatter : SDNode<"X86ISD::MSCATTER", - SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisVec<1>, - SDTCisSameAs<0, 2>, - SDTCVecEltisVT<0, i1>, - SDTCisPtrTy<3>]>, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def mgatherv4i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v4i32; -}]>; - -def mgatherv8i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v8i32; -}]>; - -def mgatherv2i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v2i64; -}]>; -def mgatherv4i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v4i64; -}]>; -def mgatherv8i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v8i64; -}]>; -def mgatherv16i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_gather node:$src1, node:$src2, node:$src3) , [{ - X86MaskedGatherSDNode *Mgt = cast(N); - return Mgt->getIndex().getValueType() == MVT::v16i32; -}]>; - -def mscatterv2i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v2i64; -}]>; - -def mscatterv4i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v4i32; -}]>; - -def mscatterv4i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v4i64; -}]>; - -def mscatterv8i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v8i32; -}]>; - -def mscatterv8i64 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v8i64; -}]>; -def mscatterv16i32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86masked_scatter node:$src1, node:$src2, node:$src3) , [{ - X86MaskedScatterSDNode *Sc = cast(N); - return Sc->getIndex().getValueType() == MVT::v16i32; -}]>; - -// 128-bit bitconvert pattern fragments -def bc_v4f32 : PatFrag<(ops node:$in), (v4f32 (bitconvert node:$in))>; -def bc_v2f64 : PatFrag<(ops node:$in), (v2f64 (bitconvert node:$in))>; -def bc_v16i8 : PatFrag<(ops node:$in), (v16i8 (bitconvert node:$in))>; -def bc_v8i16 : PatFrag<(ops node:$in), (v8i16 (bitconvert node:$in))>; -def bc_v4i32 : PatFrag<(ops node:$in), (v4i32 (bitconvert node:$in))>; -def bc_v2i64 : PatFrag<(ops node:$in), (v2i64 (bitconvert node:$in))>; - -// 256-bit bitconvert pattern fragments -def bc_v32i8 : PatFrag<(ops node:$in), (v32i8 (bitconvert node:$in))>; -def bc_v16i16 : PatFrag<(ops node:$in), (v16i16 (bitconvert node:$in))>; -def bc_v8i32 : PatFrag<(ops node:$in), (v8i32 (bitconvert node:$in))>; -def bc_v4i64 : PatFrag<(ops node:$in), (v4i64 (bitconvert node:$in))>; -def bc_v8f32 : PatFrag<(ops node:$in), (v8f32 (bitconvert node:$in))>; -def bc_v4f64 : PatFrag<(ops node:$in), (v4f64 (bitconvert node:$in))>; - -// 512-bit bitconvert pattern fragments -def bc_v64i8 : PatFrag<(ops node:$in), (v64i8 (bitconvert node:$in))>; -def bc_v16i32 : PatFrag<(ops node:$in), (v16i32 (bitconvert node:$in))>; -def bc_v8i64 : PatFrag<(ops node:$in), (v8i64 (bitconvert node:$in))>; -def bc_v8f64 : PatFrag<(ops node:$in), (v8f64 (bitconvert node:$in))>; -def bc_v16f32 : PatFrag<(ops node:$in), (v16f32 (bitconvert node:$in))>; - -def vzmovl_v2i64 : PatFrag<(ops node:$src), - (bitconvert (v2i64 (X86vzmovl - (v2i64 (scalar_to_vector (loadi64 node:$src))))))>; -def vzmovl_v4i32 : PatFrag<(ops node:$src), - (bitconvert (v4i32 (X86vzmovl - (v4i32 (scalar_to_vector (loadi32 node:$src))))))>; - -def vzload_v2i64 : PatFrag<(ops node:$src), - (bitconvert (v2i64 (X86vzload node:$src)))>; - - -def fp32imm0 : PatLeaf<(f32 fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def fp64imm0 : PatLeaf<(f64 fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def I8Imm : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def FROUND_NO_EXC : PatLeaf<(i32 8)>; -def FROUND_CURRENT : PatLeaf<(i32 4)>; - -// BYTE_imm - Transform bit immediates into byte immediates. -def BYTE_imm : SDNodeXForm> 3 - return getI32Imm(N->getZExtValue() >> 3, SDLoc(N)); -}]>; - -// EXTRACT_get_vextract128_imm xform function: convert extract_subvector index -// to VEXTRACTF128/VEXTRACTI128 imm. -def EXTRACT_get_vextract128_imm : SDNodeXForm; - -// INSERT_get_vinsert128_imm xform function: convert insert_subvector index to -// VINSERTF128/VINSERTI128 imm. -def INSERT_get_vinsert128_imm : SDNodeXForm; - -// EXTRACT_get_vextract256_imm xform function: convert extract_subvector index -// to VEXTRACTF64x4 imm. -def EXTRACT_get_vextract256_imm : SDNodeXForm; - -// INSERT_get_vinsert256_imm xform function: convert insert_subvector index to -// VINSERTF64x4 imm. -def INSERT_get_vinsert256_imm : SDNodeXForm; - -def vextract128_extract : PatFrag<(ops node:$bigvec, node:$index), - (extract_subvector node:$bigvec, - node:$index), [{}], - EXTRACT_get_vextract128_imm>; - -def vinsert128_insert : PatFrag<(ops node:$bigvec, node:$smallvec, - node:$index), - (insert_subvector node:$bigvec, node:$smallvec, - node:$index), [{}], - INSERT_get_vinsert128_imm>; - -def vextract256_extract : PatFrag<(ops node:$bigvec, node:$index), - (extract_subvector node:$bigvec, - node:$index), [{}], - EXTRACT_get_vextract256_imm>; - -def vinsert256_insert : PatFrag<(ops node:$bigvec, node:$smallvec, - node:$index), - (insert_subvector node:$bigvec, node:$smallvec, - node:$index), [{}], - INSERT_get_vinsert256_imm>; - -def X86mload : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return !cast(N)->isExpandingLoad() && - cast(N)->getExtensionType() == ISD::NON_EXTLOAD; -}]>; - -def masked_load_aligned128 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 16; -}]>; - -def masked_load_aligned256 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 32; -}]>; - -def masked_load_aligned512 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mload node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 64; -}]>; - -def masked_load_unaligned : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return !cast(N)->isExpandingLoad() && - cast(N)->getExtensionType() == ISD::NON_EXTLOAD; -}]>; - -def X86mExpandingLoad : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_load node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isExpandingLoad(); -}]>; - -// Masked store fragments. -// X86mstore can't be implemented in core DAG files because some targets -// do not support vector types (llvm-tblgen will fail). -def X86mstore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return (!cast(N)->isTruncatingStore()) && - (!cast(N)->isCompressingStore()); -}]>; - -def masked_store_aligned128 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 16; -}]>; - -def masked_store_aligned256 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 32; -}]>; - -def masked_store_aligned512 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getAlignment() >= 64; -}]>; - -def masked_store_unaligned : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return (!cast(N)->isTruncatingStore()) && - (!cast(N)->isCompressingStore()); -}]>; - -def X86mCompressingStore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isCompressingStore(); -}]>; - -// masked truncstore fragments -// X86mtruncstore can't be implemented in core DAG files because some targets -// doesn't support vector type ( llvm-tblgen will fail) -def X86mtruncstore : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (masked_store node:$src1, node:$src2, node:$src3), [{ - return cast(N)->isTruncatingStore(); -}]>; -def masked_truncstorevi8 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; -def masked_truncstorevi16 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; -def masked_truncstorevi32 : - PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86mtruncstore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def X86TruncSStore : SDNode<"X86ISD::VTRUNCSTORES", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86TruncUSStore : SDNode<"X86ISD::VTRUNCSTOREUS", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86MTruncSStore : SDNode<"X86ISD::VMTRUNCSTORES", SDTMaskedStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def X86MTruncUSStore : SDNode<"X86ISD::VMTRUNCSTOREUS", SDTMaskedStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def truncstore_s_vi8 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def truncstore_us_vi8 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def truncstore_s_vi16 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def truncstore_us_vi16 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def truncstore_s_vi32 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def truncstore_us_vi32 : PatFrag<(ops node:$val, node:$ptr), - (X86TruncUSStore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def masked_truncstore_s_vi8 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def masked_truncstore_us_vi8 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; - -def masked_truncstore_s_vi16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def masked_truncstore_us_vi16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; - -def masked_truncstore_s_vi32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; - -def masked_truncstore_us_vi32 : PatFrag<(ops node:$src1, node:$src2, node:$src3), - (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrInfo.td b/suite/synctools/tablegen/X86/back/X86InstrInfo.td deleted file mode 100644 index b43ea8ff23..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrInfo.td +++ /dev/null @@ -1,3580 +0,0 @@ -//===-- X86InstrInfo.td - Main X86 Instruction Definition --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instruction set, defining the instructions, and -// properties of the instructions which are needed for code generation, machine -// code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 specific DAG Nodes. -// - -def SDTIntShiftDOp: SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisInt<3>]>; - -def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<1, 2>]>; - -def SDTX86Cmps : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; -//def SDTX86Cmpss : SDTypeProfile<1, 3, [SDTCisVT<0, f32>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; - -def SDTX86Cmov : SDTypeProfile<1, 4, - [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -// Unary and binary operator instructions that set EFLAGS as a side-effect. -def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, - [SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS -def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<4, i32>]>; -// RES1, RES2, FLAGS = op LHS, RHS -def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; -def SDTX86BrCond : SDTypeProfile<0, 3, - [SDTCisVT<0, OtherVT>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86SetCC : SDTypeProfile<1, 2, - [SDTCisVT<0, i8>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; -def SDTX86SetCC_C : SDTypeProfile<1, 2, - [SDTCisInt<0>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; - -def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, - SDTCisVT<2, i8>]>; -def SDTX86caspair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86caspairSaveEbx8 : SDTypeProfile<1, 3, - [SDTCisVT<0, i32>, SDTCisPtrTy<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; -def SDTX86caspairSaveRbx16 : SDTypeProfile<1, 3, - [SDTCisVT<0, i64>, SDTCisPtrTy<1>, - SDTCisVT<2, i64>, SDTCisVT<3, i64>]>; - -def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, - SDTCisInt<2>]>; - -def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>]>; - -def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; - -def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; -def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; - -def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, - SDTCisVT<1, iPTR>, - SDTCisVT<2, iPTR>]>; - -def SDT_X86VAARG_64 : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; - -def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; - -def SDTX86Void : SDTypeProfile<0, 0, []>; - -def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - -def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86WIN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; - -def SDT_X86MEMBARRIER : SDTypeProfile<0, 0, []>; - -def X86MemBarrier : SDNode<"X86ISD::MEMBARRIER", SDT_X86MEMBARRIER, - [SDNPHasChain,SDNPSideEffect]>; -def X86MFence : SDNode<"X86ISD::MFENCE", SDT_X86MEMBARRIER, - [SDNPHasChain]>; - - -def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; -def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; -def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; -def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; - -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; -def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; - -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, - [SDNPHasChain]>; -def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; - -def X86sahf : SDNode<"X86ISD::SAHF", SDTX86sahf>; - -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8save_ebx : SDNode<"X86ISD::LCMPXCHG8_SAVE_EBX_DAG", - SDTX86caspairSaveEbx8, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def X86cas16save_rbx : SDNode<"X86ISD::LCMPXCHG16_SAVE_RBX_DAG", - SDTX86caspairSaveRbx16, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; - -def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue]>; - -def X86vastart_save_xmm_regs : - SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", - SDT_X86VASTART_SAVE_XMM_REGS, - [SDNPHasChain, SDNPVariadic]>; -def X86vaarg64 : - SDNode<"X86ISD::VAARG_64", SDT_X86VAARG_64, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86callseq_start : - SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def X86callseq_end : - SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; -def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, - [SDNPHasChain]>; - -def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; -def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad]>; - -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdtscp : SDNode<"X86ISD::RDTSCP_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdpmc : SDNode<"X86ISD::RDPMC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; - -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; -def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; - -def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", - SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, - SDTCisInt<1>]>>; - -def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, - [SDNPHasChain]>; - -def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", - SDTypeProfile<1, 1, [SDTCisInt<0>, - SDTCisPtrTy<1>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", - SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", - SDTypeProfile<0, 0, []>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; -def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, - [SDNPCommutative]>; -def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; -def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; - -def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>; -def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>; -def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, - [SDNPCommutative]>; - -def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86lock_inc : SDNode<"X86ISD::LINC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_dec : SDNode<"X86ISD::LDEC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; - -def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; - -def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA, - [SDNPHasChain, SDNPOutGlue]>; - -def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, - [SDNPHasChain]>; - -def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86lwpins : SDNode<"X86ISD::LWPINS", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; - -def X86umwait : SDNode<"X86ISD::UMWAIT", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tpause : SDNode<"X86ISD::TPAUSE", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -//===----------------------------------------------------------------------===// -// X86 Operand Definitions. -// - -// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for -// the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; - -// *mem - Operand definitions for the funky X86 addressing mode operands. -// -def X86MemAsmOperand : AsmOperandClass { - let Name = "Mem"; -} -let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { - def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } - def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } - def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } - def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } - def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } - def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } - def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } - def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } - // Gather mem operands - def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } - def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } - def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } - def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } - def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } - - def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } - def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } - def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } - def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } - def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } - def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } - def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } - def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } -} - -def X86AbsMemAsmOperand : AsmOperandClass { - let Name = "AbsMem"; - let SuperClasses = [X86MemAsmOperand]; -} - -class X86MemOperand : Operand { - let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = parserMatchClass; - let OperandType = "OPERAND_MEMORY"; -} - -// Gather mem operands -class X86VMemOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); -} - -def anymem : X86MemOperand<"printanymem">; - -// FIXME: Right now we allow any size during parsing, but we might want to -// restrict to only unsized memory. -def opaquemem : X86MemOperand<"printopaquemem">; - -def i8mem : X86MemOperand<"printi8mem", X86Mem8AsmOperand>; -def i16mem : X86MemOperand<"printi16mem", X86Mem16AsmOperand>; -def i32mem : X86MemOperand<"printi32mem", X86Mem32AsmOperand>; -def i64mem : X86MemOperand<"printi64mem", X86Mem64AsmOperand>; -def i128mem : X86MemOperand<"printi128mem", X86Mem128AsmOperand>; -def i256mem : X86MemOperand<"printi256mem", X86Mem256AsmOperand>; -def i512mem : X86MemOperand<"printi512mem", X86Mem512AsmOperand>; -def f32mem : X86MemOperand<"printf32mem", X86Mem32AsmOperand>; -def f64mem : X86MemOperand<"printf64mem", X86Mem64AsmOperand>; -def f80mem : X86MemOperand<"printf80mem", X86Mem80AsmOperand>; -def f128mem : X86MemOperand<"printf128mem", X86Mem128AsmOperand>; -def f256mem : X86MemOperand<"printf256mem", X86Mem256AsmOperand>; -def f512mem : X86MemOperand<"printf512mem", X86Mem512AsmOperand>; - -def v512mem : X86VMemOperand; - -// Gather mem operands -def vx64mem : X86VMemOperand; -def vx128mem : X86VMemOperand; -def vx256mem : X86VMemOperand; -def vy128mem : X86VMemOperand; -def vy256mem : X86VMemOperand; - -def vx64xmem : X86VMemOperand; -def vx128xmem : X86VMemOperand; -def vx256xmem : X86VMemOperand; -def vy128xmem : X86VMemOperand; -def vy256xmem : X86VMemOperand; -def vy512xmem : X86VMemOperand; -def vz256mem : X86VMemOperand; -def vz512mem : X86VMemOperand; - -// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead -// of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; - -def i8mem_NOREX : Operand { - let PrintMethod = "printi8mem"; - let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, - SEGMENT_REG); - let ParserMatchClass = X86Mem8AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// GPRs available for tailcall. -// It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; - -// Special i32mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i32mem_TC : Operand { - let PrintMethod = "printi32mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, - i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// Special i64mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i64mem_TC : Operand { - let PrintMethod = "printi64mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, - ptr_rc_tailcall, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -let OperandType = "OPERAND_PCREL", - ParserMatchClass = X86AbsMemAsmOperand, - PrintMethod = "printPCRelImm" in { -def i32imm_pcrel : Operand; -def i16imm_pcrel : Operand; - -// Branch targets have OtherVT type and print as pc-relative values. -def brtarget : Operand; -def brtarget8 : Operand; - -} - -// Special parser to detect 16-bit mode to select 16-bit displacement. -def X86AbsMem16AsmOperand : AsmOperandClass { - let Name = "AbsMem16"; - let RenderMethod = "addAbsMemOperands"; - let SuperClasses = [X86AbsMemAsmOperand]; -} - -// Branch targets have OtherVT type and print as pc-relative values. -let OperandType = "OPERAND_PCREL", - PrintMethod = "printPCRelImm" in { -let ParserMatchClass = X86AbsMem16AsmOperand in - def brtarget16 : Operand; -let ParserMatchClass = X86AbsMemAsmOperand in - def brtarget32 : Operand; -} - -let RenderMethod = "addSrcIdxOperands" in { - def X86SrcIdx8Operand : AsmOperandClass { - let Name = "SrcIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86SrcIdx16Operand : AsmOperandClass { - let Name = "SrcIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86SrcIdx32Operand : AsmOperandClass { - let Name = "SrcIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86SrcIdx64Operand : AsmOperandClass { - let Name = "SrcIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addSrcIdxOperands" - -let RenderMethod = "addDstIdxOperands" in { - def X86DstIdx8Operand : AsmOperandClass { - let Name = "DstIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86DstIdx16Operand : AsmOperandClass { - let Name = "DstIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86DstIdx32Operand : AsmOperandClass { - let Name = "DstIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86DstIdx64Operand : AsmOperandClass { - let Name = "DstIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addDstIdxOperands" - -let RenderMethod = "addMemOffsOperands" in { - def X86MemOffs16_8AsmOperand : AsmOperandClass { - let Name = "MemOffs16_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs16_16AsmOperand : AsmOperandClass { - let Name = "MemOffs16_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs16_32AsmOperand : AsmOperandClass { - let Name = "MemOffs16_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_8AsmOperand : AsmOperandClass { - let Name = "MemOffs32_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs32_16AsmOperand : AsmOperandClass { - let Name = "MemOffs32_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs32_32AsmOperand : AsmOperandClass { - let Name = "MemOffs32_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_64AsmOperand : AsmOperandClass { - let Name = "MemOffs32_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } - def X86MemOffs64_8AsmOperand : AsmOperandClass { - let Name = "MemOffs64_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs64_16AsmOperand : AsmOperandClass { - let Name = "MemOffs64_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs64_32AsmOperand : AsmOperandClass { - let Name = "MemOffs64_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs64_64AsmOperand : AsmOperandClass { - let Name = "MemOffs64_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addMemOffsOperands" - -class X86SrcIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); -} - -class X86DstIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc); -} - -def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; -def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; -def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; -def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; -def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; -def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; -def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; -def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; - -class X86MemOffsOperand - : X86MemOperand { - let MIOperandInfo = (ops immOperand, SEGMENT_REG); -} - -def offset16_8 : X86MemOffsOperand; -def offset16_16 : X86MemOffsOperand; -def offset16_32 : X86MemOffsOperand; -def offset32_8 : X86MemOffsOperand; -def offset32_16 : X86MemOffsOperand; -def offset32_32 : X86MemOffsOperand; -def offset32_64 : X86MemOffsOperand; -def offset64_8 : X86MemOffsOperand; -def offset64_16 : X86MemOffsOperand; -def offset64_32 : X86MemOffsOperand; -def offset64_64 : X86MemOffsOperand; - -def SSECC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVXCC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVX512ICC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def XOPCC : Operand { - let PrintMethod = "printXOPCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -class ImmSExtAsmOperandClass : AsmOperandClass { - let SuperClasses = [ImmAsmOperand]; - let RenderMethod = "addImmOperands"; -} - -def X86GR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR32orGR64"; -} - -def GR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR32orGR64AsmOperand; -} -def AVX512RCOperand : AsmOperandClass { - let Name = "AVX512RC"; -} -def AVX512RC : Operand { - let PrintMethod = "printRoundingControl"; - let OperandType = "OPERAND_IMMEDIATE"; - let ParserMatchClass = AVX512RCOperand; -} - -// Sign-extended immediate classes. We don't need to define the full lattice -// here because there is no instruction with an ambiguity between ImmSExti64i32 -// and ImmSExti32i8. -// -// The strange ranges come from the fact that the assembler always works with -// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" -// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). - -// [0, 0x7FFFFFFF] | -// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i32"; -} - -// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti16i8"; - let SuperClasses = [ImmSExti64i32AsmOperand]; -} - -// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti32i8"; -} - -// [0, 0x0000007F] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i8"; - let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, - ImmSExti64i32AsmOperand]; -} - -// Unsigned immediate used by SSE/AVX instructions -// [0, 0xFF] -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmUnsignedi8AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi8"; - let RenderMethod = "addImmOperands"; -} - -// A couple of more descriptive operand definitions. -// 16-bits but only 8 bits are significant. -def i16i8imm : Operand { - let ParserMatchClass = ImmSExti16i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} -// 32-bits but only 8 bits are significant. -def i32i8imm : Operand { - let ParserMatchClass = ImmSExti32i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant. -def i64i32imm : Operand { - let ParserMatchClass = ImmSExti64i32AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 8 bits are significant. -def i64i8imm : Operand { - let ParserMatchClass = ImmSExti64i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 8-bit immediate used by SSE/AVX instructions. -def u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 32-bit immediate but only 8-bits are significant and they are unsigned. -// Used by some SSE/AVX instructions that use intrinsics. -def i32u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant, and those bits are treated as being -// pc relative. -def i64i32imm_pcrel : Operand { - let PrintMethod = "printPCRelImm"; - let ParserMatchClass = X86AbsMemAsmOperand; - let OperandType = "OPERAND_PCREL"; -} - -def lea64_32mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -// Memory operands that use 64-bit pointers in both ILP32 and LP64. -def lea64mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - - -//===----------------------------------------------------------------------===// -// X86 Complex Pattern Definitions. -// - -// Define X86-specific addressing mode. -def addr : ComplexPattern; -def lea32addr : ComplexPattern; -// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. -def lea64_32addr : ComplexPattern; - -def tls32addr : ComplexPattern; - -def tls32baseaddr : ComplexPattern; - -def lea64addr : ComplexPattern; - -def tls64addr : ComplexPattern; - -def tls64baseaddr : ComplexPattern; - -def vectoraddr : ComplexPattern; - -// A relocatable immediate is either an immediate operand or an operand that can -// be relocated by the linker to an immediate, such as a regular symbol in -// non-PIC code. -def relocImm : ComplexPattern; - -//===----------------------------------------------------------------------===// -// X86 Instruction Predicate Definitions. -def TruePredicate : Predicate<"true">; - -def HasCMov : Predicate<"Subtarget->hasCMov()">; -def NoCMov : Predicate<"!Subtarget->hasCMov()">; - -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def Has3DNow : Predicate<"Subtarget->has3DNow()">; -def Has3DNowA : Predicate<"Subtarget->has3DNowA()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; -def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; -def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; -def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; -def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; -def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; -def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; -def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; -def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; -def NoAVX : Predicate<"!Subtarget->hasAVX()">; -def HasAVX : Predicate<"Subtarget->hasAVX()">; -def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; -def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; -def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; -def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; -def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; -def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; -def HasCDI : Predicate<"Subtarget->hasCDI()">; -def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; -def HasPFI : Predicate<"Subtarget->hasPFI()">; -def HasERI : Predicate<"Subtarget->hasERI()">; -def HasDQI : Predicate<"Subtarget->hasDQI()">; -def NoDQI : Predicate<"!Subtarget->hasDQI()">; -def HasBWI : Predicate<"Subtarget->hasBWI()">; -def NoBWI : Predicate<"!Subtarget->hasBWI()">; -def HasVLX : Predicate<"Subtarget->hasVLX()">; -def NoVLX : Predicate<"!Subtarget->hasVLX()">; -def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; -def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; -def PKU : Predicate<"Subtarget->hasPKU()">; -def HasVNNI : Predicate<"Subtarget->hasVNNI()">; - -def HasBITALG : Predicate<"Subtarget->hasBITALG()">; -def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; -def HasAES : Predicate<"Subtarget->hasAES()">; -def HasVAES : Predicate<"Subtarget->hasVAES()">; -def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; -def HasFXSR : Predicate<"Subtarget->hasFXSR()">; -def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; -def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; -def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; -def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; -def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; -def NoVLX_Or_NoVPCLMULQDQ : - Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; -def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; -def HasGFNI : Predicate<"Subtarget->hasGFNI()">; -def HasFMA : Predicate<"Subtarget->hasFMA()">; -def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; -def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; -def HasXOP : Predicate<"Subtarget->hasXOP()">; -def HasTBM : Predicate<"Subtarget->hasTBM()">; -def NoTBM : Predicate<"!Subtarget->hasTBM()">; -def HasLWP : Predicate<"Subtarget->hasLWP()">; -def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; -def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; -def HasF16C : Predicate<"Subtarget->hasF16C()">; -def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; -def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; -def HasBMI : Predicate<"Subtarget->hasBMI()">; -def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; -def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; -def HasVBMI : Predicate<"Subtarget->hasVBMI()">; -def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; -def HasIFMA : Predicate<"Subtarget->hasIFMA()">; -def HasRTM : Predicate<"Subtarget->hasRTM()">; -def HasADX : Predicate<"Subtarget->hasADX()">; -def HasSHA : Predicate<"Subtarget->hasSHA()">; -def HasSGX : Predicate<"Subtarget->hasSGX()">; -def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; -def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; -def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; -def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; -def HasPrefetchW : Predicate<"Subtarget->hasPRFCHW()">; -def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; -def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; -def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; -def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; -def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; -def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; -def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; -def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; -def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; -def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; -def HasMPX : Predicate<"Subtarget->hasMPX()">; -def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; -def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; -def HasCLWB : Predicate<"Subtarget->hasCLWB()">; -def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; -def HasRDPID : Predicate<"Subtarget->hasRDPID()">; -def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; -def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; -def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; -def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; -def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, - AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, - AssemblerPredicate<"Mode64Bit", "64-bit mode">; -def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; -def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; -def In16BitMode : Predicate<"Subtarget->is16Bit()">, - AssemblerPredicate<"Mode16Bit", "16-bit mode">; -def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, - AssemblerPredicate<"!Mode16Bit", "Not 16-bit mode">; -def In32BitMode : Predicate<"Subtarget->is32Bit()">, - AssemblerPredicate<"Mode32Bit", "32-bit mode">; -def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; -def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; -def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" - "Subtarget->getFrameLowering()->hasFP(*MF)"> { - let RecomputePerFunction = 1; -} -def IsPS4 : Predicate<"Subtarget->isTargetPS4()">; -def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">; -def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; -def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; -def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; -def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" - "TM.getCodeModel() == CodeModel::Kernel">; -def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; - -// We could compute these on a per-module basis but doing so requires accessing -// the Function object through the Subtarget and objections were raised -// to that (see post-commit review comments for r301750). -let RecomputePerFunction = 1 in { - def OptForSize : Predicate<"MF->getFunction().optForSize()">; - def OptForMinSize : Predicate<"MF->getFunction().optForMinSize()">; - def OptForSpeed : Predicate<"!MF->getFunction().optForSize()">; - def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " - "MF->getFunction().optForSize()">; - def NoSSE41_Or_OptForSize : Predicate<"MF->getFunction().optForSize() || " - "!Subtarget->hasSSE41()">; -} - -def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; -def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; -def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; -def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; -def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; -def HasERMSB : Predicate<"Subtarget->hasERMSB()">; -def HasMFence : Predicate<"Subtarget->hasMFence()">; -def UseRetpoline : Predicate<"Subtarget->useRetpoline()">; -def NotUseRetpoline : Predicate<"!Subtarget->useRetpoline()">; - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -include "X86InstrFormats.td" - -//===----------------------------------------------------------------------===// -// Pattern fragments. -// - -// X86 specific condition code. These correspond to CondCode in -// X86InstrInfo.h. They must be kept in synch. -def X86_COND_A : PatLeaf<(i8 0)>; // alt. COND_NBE -def X86_COND_AE : PatLeaf<(i8 1)>; // alt. COND_NC -def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C -def X86_COND_BE : PatLeaf<(i8 3)>; // alt. COND_NA -def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z -def X86_COND_G : PatLeaf<(i8 5)>; // alt. COND_NLE -def X86_COND_GE : PatLeaf<(i8 6)>; // alt. COND_NL -def X86_COND_L : PatLeaf<(i8 7)>; // alt. COND_NGE -def X86_COND_LE : PatLeaf<(i8 8)>; // alt. COND_NG -def X86_COND_NE : PatLeaf<(i8 9)>; // alt. COND_NZ -def X86_COND_NO : PatLeaf<(i8 10)>; -def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO -def X86_COND_NS : PatLeaf<(i8 12)>; -def X86_COND_O : PatLeaf<(i8 13)>; -def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE -def X86_COND_S : PatLeaf<(i8 15)>; - -def i16immSExt8 : ImmLeaf(Imm); }]>; -def i32immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt32 : ImmLeaf(Imm); }]>; - -// FIXME: Ideally we would just replace the above i*immSExt* matchers with -// relocImm-based matchers, but then FastISel would be unable to use them. -def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<8>(N); -}]>; -def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<32>(N); -}]>; - -// If we have multiple users of an immediate, it's much smaller to reuse -// the register, rather than encode the immediate in every instruction. -// This has the risk of increasing register pressure from stretched live -// ranges, however, the immediates should be trivial to rematerialize by -// the RA in the event of high register pressure. -// TODO : This is currently enabled for stores and binary ops. There are more -// cases for which this can be enabled, though this catches the bulk of the -// issues. -// TODO2 : This should really also be enabled under O2, but there's currently -// an issue with RA where we don't pull the constants into their users -// when we rematerialize them. I'll follow-up on enabling O2 after we fix that -// issue. -// TODO3 : This is currently limited to single basic blocks (DAG creation -// pulls block immediates to the top and merges them if necessary). -// Eventually, it would be nice to allow ConstantHoisting to merge constants -// globally for potentially added savings. -// -def imm8_su : PatLeaf<(i8 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm16_su : PatLeaf<(i16 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm32_su : PatLeaf<(i32 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit -// unsigned field. -def i64immZExt32 : ImmLeaf(Imm); }]>; - -def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); -}]>; - -// Helper fragments for loads. - -// It's safe to fold a zextload/extload from i1 as a regular i8 load. The -// upper bits are guaranteed to be zero and we were going to emit a MOV8rm -// which might get folded during peephole anyway. -def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || - ExtType == ISD::ZEXTLOAD; -}]>; - -// It's always safe to treat a anyext i16 load as a i32 load if the i16 is -// known to be 32-bit aligned or better. Ditto for i8 to i16. -def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 2 && !LD->isVolatile(); - return false; -}]>; - -def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 4 && !LD->isVolatile(); - return false; -}]>; - -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; -def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; -def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; -def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; -def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; -def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; -def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; -def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; -def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; - -def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; -def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; -def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; -def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; -def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; -def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; -def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; -def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; -def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; -def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; - -def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; -def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; -def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; -def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; -def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>; - - -// An 'and' node with a single use. -def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'srl' node with a single use. -def srl_su : PatFrag<(ops node:$lhs, node:$rhs), (srl node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'trunc' node with a single use. -def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ - return N->hasOneUse(); -}]>; - -//===----------------------------------------------------------------------===// -// Instruction list. -// - -// Nop -let hasSideEffects = 0, SchedRW = [WriteNop] in { - def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; - def NOOPW : I<0x1f, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPL : I<0x1f, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQ : RI<0x1f, MRMXm, (outs), (ins i64mem:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - // Also allow register so we can assemble/disassemble - def NOOPWr : I<0x1f, MRMXr, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPLr : I<0x1f, MRMXr, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQr : RI<0x1f, MRMXr, (outs), (ins GR64:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - def NOOPW_19 : I<0x19, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_19 : I<0x19, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1a : I<0x1a, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1a : I<0x1a, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1b : I<0x1b, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1b : I<0x1b, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1c : I<0x1c, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1c : I<0x1c, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1d : I<0x1d, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1d : I<0x1d, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1e : I<0x1e, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1e : I<0x1e, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m4 : I<0x18, MRM4m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m4 : I<0x18, MRM4m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r4 : I<0x18, MRM4r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r4 : I<0x18, MRM4r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m5 : I<0x18, MRM5m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m5 : I<0x18, MRM5m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r5 : I<0x18, MRM5r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r5 : I<0x18, MRM5r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m6 : I<0x18, MRM6m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m6 : I<0x18, MRM6m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r6 : I<0x18, MRM6r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r6 : I<0x18, MRM6r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m7 : I<0x18, MRM7m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m7 : I<0x18, MRM7m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r7 : I<0x18, MRM7r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r7 : I<0x18, MRM7r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; -} - - -// Constructing a stack frame. -def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl), - "enter\t$len, $lvl", []>, Sched<[WriteMicrocoded]>; - -let SchedRW = [WriteALU] in { -let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, hasSideEffects=0 in -def LEAVE : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[Not64BitMode]>; - -let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, hasSideEffects = 0 in -def LEAVE64 : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Miscellaneous Instructions. -// - -/* -let isBarrier = 1, hasSideEffects = 1, usesCustomInserter = 1, - SchedRW = [WriteSystem] in - def Int_eh_sjlj_setup_dispatch - : PseudoI<(outs), (ins), [(X86eh_sjlj_setup_dispatch)]>; -*/ - -let Defs = [ESP], Uses = [ESP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP16r : I<0x58, AddRegFrm, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16; -def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP16rmr: I<0x8F, MRM0r, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16, NotMemoryFoldable; -def POP32rmr: I<0x8F, MRM0r, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayStore = 1, mayLoad = 1, SchedRW = [WriteRMW] in { -def POP16rmm: I<0x8F, MRM0m, (outs), (ins i16mem:$dst), "pop{w}\t$dst", []>, - OpSize16; -def POP32rmm: I<0x8F, MRM0m, (outs), (ins i32mem:$dst), "pop{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayStore, mayLoad, WriteRMW - -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH16r : I<0x50, AddRegFrm, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16; -def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH16rmr: I<0xFF, MRM6r, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16, NotMemoryFoldable; -def PUSH32rmr: I<0xFF, MRM6r, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 - -def PUSH16i8 : Ii8<0x6a, RawFrm, (outs), (ins i16i8imm:$imm), - "push{w}\t$imm", []>, OpSize16; -def PUSHi16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), - "push{w}\t$imm", []>, OpSize16; - -def PUSH32i8 : Ii8<0x6a, RawFrm, (outs), (ins i32i8imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -def PUSHi32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -} // mayStore, SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH16rmm: I<0xFF, MRM6m, (outs), (ins i16mem:$src), "push{w}\t$src", []>, - OpSize16; -def PUSH32rmm: I<0xFF, MRM6m, (outs), (ins i32mem:$src), "push{l}\t$src", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayLoad, mayStore, SchedRW - -} - -/* -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW], Defs = [ESP] in { - let Uses = [ESP] in - def RDFLAGS32 : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_flags_read_u32))]>, - Requires<[Not64BitMode]>; - - let Uses = [RSP] in - def RDFLAGS64 : PseudoI<(outs GR64:$dst), (ins), - [(set GR64:$dst, (int_x86_flags_read_u64))]>, - Requires<[In64BitMode]>; -} - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW] in { - let Defs = [ESP, EFLAGS, DF], Uses = [ESP] in - def WRFLAGS32 : PseudoI<(outs), (ins GR32:$src), - [(int_x86_flags_write_u32 GR32:$src)]>, - Requires<[Not64BitMode]>; - - let Defs = [RSP, EFLAGS, DF], Uses = [RSP] in - def WRFLAGS64 : PseudoI<(outs), (ins GR64:$src), - [(int_x86_flags_write_u64 GR64:$src)]>, - Requires<[In64BitMode]>; -} -*/ - -let Defs = [ESP, EFLAGS, DF], Uses = [ESP], mayLoad = 1, hasSideEffects=0, - SchedRW = [WriteLoad] in { -def POPF16 : I<0x9D, RawFrm, (outs), (ins), "popf{w}", []>, OpSize16; -def POPF32 : I<0x9D, RawFrm, (outs), (ins), "popf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [ESP], Uses = [ESP, EFLAGS, DF], mayStore = 1, hasSideEffects=0, - SchedRW = [WriteStore] in { -def PUSHF16 : I<0x9C, RawFrm, (outs), (ins), "pushf{w}", []>, OpSize16; -def PUSHF32 : I<0x9C, RawFrm, (outs), (ins), "pushf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in -def POP64rmm: I<0x8F, MRM0m, (outs), (ins i64mem:$dst), "pop{q}\t$dst", []>, - OpSize32, Requires<[In64BitMode]>; -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayStore, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>, - OpSize32, Requires<[In64BitMode]>; -} // mayLoad, mayStore, SchedRW -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects = 0, mayStore = 1, - SchedRW = [WriteStore] in { -def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -def PUSH64i32 : Ii32S<0x68, RawFrm, (outs), (ins i64i32imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -} - -let Defs = [RSP, EFLAGS, DF], Uses = [RSP], mayLoad = 1, hasSideEffects=0 in -def POPF64 : I<0x9D, RawFrm, (outs), (ins), "popfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteLoad]>; -let Defs = [RSP], Uses = [RSP, EFLAGS, DF], mayStore = 1, hasSideEffects=0 in -def PUSHF64 : I<0x9C, RawFrm, (outs), (ins), "pushfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteStore]>; - -let Defs = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], Uses = [ESP], - mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteLoad] in { -def POPA32 : I<0x61, RawFrm, (outs), (ins), "popal", []>, - OpSize32, Requires<[Not64BitMode]>; -def POPA16 : I<0x61, RawFrm, (outs), (ins), "popaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} -let Defs = [ESP], Uses = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], - mayStore = 1, hasSideEffects = 0, SchedRW = [WriteStore] in { -def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pushal", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHA16 : I<0x60, RawFrm, (outs), (ins), "pushaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} - -let Constraints = "$src = $dst", SchedRW = [WriteBSWAP32] in { -// This instruction is a consequence of BSWAP32r observing operand size. The -// encoding is valid, but the behavior is undefined. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in -def BSWAP16r_BAD : I<0xC8, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "bswap{w}\t$dst", []>, OpSize16, TB; -// GR32 = bswap GR32 -def BSWAP32r : I<0xC8, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "bswap{l}\t$dst", - [(set GR32:$dst, (bswap GR32:$src))]>, OpSize32, TB; - -let SchedRW = [WriteBSWAP64] in -def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "bswap{q}\t$dst", - [(set GR64:$dst, (bswap GR64:$src))]>, TB; -} // Constraints = "$src = $dst", SchedRW - -// Bit scan instructions. -let Defs = [EFLAGS] in { -def BSF16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSF]>; -def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSFLd]>; -def BSF32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSF]>; -def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSFLd]>; -def BSF64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf GR64:$src))]>, - PS, Sched<[WriteBSF]>; -def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSFLd]>; - -def BSR16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSR]>; -def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSRLd]>; -def BSR32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSR]>; -def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSRLd]>; -def BSR64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr GR64:$src))]>, - PS, Sched<[WriteBSR]>; -def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSRLd]>; -} // Defs = [EFLAGS] - -let SchedRW = [WriteMicrocoded] in { -let Defs = [EDI,ESI], Uses = [EDI,ESI,DF] in { -def MOVSB : I<0xA4, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "movsb\t{$src, $dst|$dst, $src}", []>; -def MOVSW : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "movsw\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOVSL : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "movs{l|d}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOVSQ : RI<0xA5, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "movsq\t{$src, $dst|$dst, $src}", []>, - Requires<[In64BitMode]>; -} - -let Defs = [EDI], Uses = [AL,EDI,DF] in -def STOSB : I<0xAA, RawFrmDst, (outs), (ins dstidx8:$dst), - "stosb\t{%al, $dst|$dst, al}", []>; -let Defs = [EDI], Uses = [AX,EDI,DF] in -def STOSW : I<0xAB, RawFrmDst, (outs), (ins dstidx16:$dst), - "stosw\t{%ax, $dst|$dst, ax}", []>, OpSize16; -let Defs = [EDI], Uses = [EAX,EDI,DF] in -def STOSL : I<0xAB, RawFrmDst, (outs), (ins dstidx32:$dst), - "stos{l|d}\t{%eax, $dst|$dst, eax}", []>, OpSize32; -let Defs = [RDI], Uses = [RAX,RDI,DF] in -def STOSQ : RI<0xAB, RawFrmDst, (outs), (ins dstidx64:$dst), - "stosq\t{%rax, $dst|$dst, rax}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,EFLAGS], Uses = [AL,EDI,DF] in -def SCASB : I<0xAE, RawFrmDst, (outs), (ins dstidx8:$dst), - "scasb\t{$dst, %al|al, $dst}", []>; -let Defs = [EDI,EFLAGS], Uses = [AX,EDI,DF] in -def SCASW : I<0xAF, RawFrmDst, (outs), (ins dstidx16:$dst), - "scasw\t{$dst, %ax|ax, $dst}", []>, OpSize16; -let Defs = [EDI,EFLAGS], Uses = [EAX,EDI,DF] in -def SCASL : I<0xAF, RawFrmDst, (outs), (ins dstidx32:$dst), - "scas{l|d}\t{$dst, %eax|eax, $dst}", []>, OpSize32; -let Defs = [EDI,EFLAGS], Uses = [RAX,EDI,DF] in -def SCASQ : RI<0xAF, RawFrmDst, (outs), (ins dstidx64:$dst), - "scasq\t{$dst, %rax|rax, $dst}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,ESI,EFLAGS], Uses = [EDI,ESI,DF] in { -def CMPSB : I<0xA6, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "cmpsb\t{$dst, $src|$src, $dst}", []>; -def CMPSW : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "cmpsw\t{$dst, $src|$src, $dst}", []>, OpSize16; -def CMPSL : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "cmps{l|d}\t{$dst, $src|$src, $dst}", []>, OpSize32; -def CMPSQ : RI<0xA7, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "cmpsq\t{$dst, $src|$src, $dst}", []>, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Move Instructions. -// -let SchedRW = [WriteMove] in { -let hasSideEffects = 0, isMoveReg = 1 in { -def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>; -def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, imm:$src)]>, OpSize16; -def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, relocImm:$src)]>, OpSize32; -def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, i64immSExt32:$src)]>; -} -let isReMaterializable = 1 in { -def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), - "movabs{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, relocImm:$src)]>; -} - -// Longer forms that use a ModR/M byte. Needed for disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOV8ri_alt : Ii8 <0xC6, MRM0r, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8ri">; -def MOV16ri_alt : Ii16<0xC7, MRM0r, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16ri">; -def MOV32ri_alt : Ii32<0xC7, MRM0r, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32ri">; -} -} // SchedRW - -let SchedRW = [WriteStore] in { -def MOV8mi : Ii8 <0xC6, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store (i8 imm8_su:$src), addr:$dst)]>; -def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store (i16 imm16_su:$src), addr:$dst)]>, OpSize16; -def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store (i32 imm32_su:$src), addr:$dst)]>, OpSize32; -def MOV64mi32 : RIi32S<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store i64immSExt32_su:$src, addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { - -/// Memory offset versions of moves. The immediate is an address mode sized -/// offset from the segment base. -let SchedRW = [WriteALU] in { -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao32 : Ii32<0xA0, RawFrmMemOffs, (outs), (ins offset32_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, - AdSize32; -let Defs = [AX] in -def MOV16ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize32; -let Defs = [EAX] in -def MOV32ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize32; -let Defs = [RAX] in -def MOV64ao32 : RIi32<0xA1, RawFrmMemOffs, (outs), (ins offset32_64:$src), - "mov{q}\t{$src, %rax|rax, $src}", []>, - AdSize32; - -let Defs = [AL] in -def MOV8ao16 : Ii16<0xA0, RawFrmMemOffs, (outs), (ins offset16_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, AdSize16; -let Defs = [AX] in -def MOV16ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize16; -let Defs = [EAX] in -def MOV32ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - AdSize16, OpSize32; -} // mayLoad -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o32a : Ii32<0xA2, RawFrmMemOffs, (outs), (ins offset32_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize32; -let Uses = [AX] in -def MOV16o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize32; -let Uses = [EAX] in -def MOV32o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize32; -let Uses = [RAX] in -def MOV64o32a : RIi32<0xA3, RawFrmMemOffs, (outs), (ins offset32_64:$dst), - "mov{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize32; - -let Uses = [AL] in -def MOV8o16a : Ii16<0xA2, RawFrmMemOffs, (outs), (ins offset16_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize16; -let Uses = [AX] in -def MOV16o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize16; -let Uses = [EAX] in -def MOV32o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize16; -} // mayStore - -// These forms all have full 64-bit absolute addresses in their instructions -// and use the movabs mnemonic to indicate this specific form. -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao64 : Ii64<0xA0, RawFrmMemOffs, (outs), (ins offset64_8:$src), - "movabs{b}\t{$src, %al|al, $src}", []>, - AdSize64; -let Defs = [AX] in -def MOV16ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_16:$src), - "movabs{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize64; -let Defs = [EAX] in -def MOV32ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_32:$src), - "movabs{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize64; -let Defs = [RAX] in -def MOV64ao64 : RIi64<0xA1, RawFrmMemOffs, (outs), (ins offset64_64:$src), - "movabs{q}\t{$src, %rax|rax, $src}", []>, - AdSize64; -} // mayLoad - -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o64a : Ii64<0xA2, RawFrmMemOffs, (outs), (ins offset64_8:$dst), - "movabs{b}\t{%al, $dst|$dst, al}", []>, - AdSize64; -let Uses = [AX] in -def MOV16o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_16:$dst), - "movabs{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize64; -let Uses = [EAX] in -def MOV32o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_32:$dst), - "movabs{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize64; -let Uses = [RAX] in -def MOV64o64a : RIi64<0xA3, RawFrmMemOffs, (outs), (ins offset64_64:$dst), - "movabs{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize64; -} // mayStore -} // SchedRW -} // hasSideEffects = 0 - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [WriteMove], isMoveReg = 1 in { -def MOV8rr_REV : I<0x8A, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8rr">; -def MOV16rr_REV : I<0x8B, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16rr">; -def MOV32rr_REV : I<0x8B, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32rr">; -def MOV64rr_REV : RI<0x8B, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV64rr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -//def : InstAlias<"mov{b}.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0>; -//def : InstAlias<"mov{w}.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0>; -//def : InstAlias<"mov{l}.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0>; -//def : InstAlias<"mov{q}.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0>; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0, "att">; - -let canFoldAsLoad = 1, isReMaterializable = 1, SchedRW = [WriteLoad] in { -def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, (loadi8 addr:$src))]>; -def MOV16rm : I<0x8B, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (loadi16 addr:$src))]>, OpSize16; -def MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (loadi32 addr:$src))]>, OpSize32; -def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (load addr:$src))]>; -} - -let SchedRW = [WriteStore] in { -def MOV8mr : I<0x88, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store GR16:$src, addr:$dst)]>, OpSize16; -def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store GR32:$src, addr:$dst)]>, OpSize32; -def MOV64mr : RI<0x89, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store GR64:$src, addr:$dst)]>; -} // SchedRW - -// Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so -// that they can be used for copying and storing h registers, which can't be -// encoded when a REX prefix is present. -let isCodeGenOnly = 1 in { -let hasSideEffects = 0, isMoveReg = 1 in -def MOV8rr_NOREX : I<0x88, MRMDestReg, - (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteMove]>; -let mayStore = 1, hasSideEffects = 0 in -def MOV8mr_NOREX : I<0x88, MRMDestMem, - (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteStore]>; -let mayLoad = 1, hasSideEffects = 0, - canFoldAsLoad = 1, isReMaterializable = 1 in -def MOV8rm_NOREX : I<0x8A, MRMSrcMem, - (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteLoad]>; -} - - -// Condition code ops, incl. set if equal/not equal/... -let SchedRW = [WriteLAHFSAHF] in { -let Defs = [EFLAGS], Uses = [AH] in -def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", - [(set EFLAGS, (X86sahf AH))]>, - Requires<[HasLAHFSAHF]>; -let Defs = [AH], Uses = [EFLAGS], hasSideEffects = 0 in -def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>, // AH = flags - Requires<[HasLAHFSAHF]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Bit tests instructions: BT, BTS, BTR, BTC. - -let Defs = [EFLAGS] in { -let SchedRW = [WriteBitTest] in { -def BT16rr : I<0xA3, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, GR16:$src2))]>, - OpSize16, TB, NotMemoryFoldable; -def BT32rr : I<0xA3, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, GR32:$src2))]>, - OpSize32, TB, NotMemoryFoldable; -def BT64rr : RI<0xA3, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, GR64:$src2))]>, TB, - NotMemoryFoldable; -} // SchedRW - -// Unlike with the register+register form, the memory+register form of the -// bt instruction does not ignore the high bits of the index. From ISel's -// perspective, this is pretty bizarre. Make these instructions disassembly -// only for now. These instructions are also slow on modern CPUs so that's -// another reason to avoid generating them. - -let mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteALULd] in { - def BT16mr : I<0xA3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - []>, OpSize16, TB, NotMemoryFoldable; - def BT32mr : I<0xA3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - []>, OpSize32, TB, NotMemoryFoldable; - def BT64mr : RI<0xA3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - []>, TB, NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest] in { -def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, i64immSExt8:$src2))]>, TB; -} // SchedRW - -// Note that these instructions aren't slow because that only applies when the -// other operand is in a register. When it's an immediate, bt is still fast. -let SchedRW = [WriteALU] in { -def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi64 addr:$src1), - i64immSExt8:$src2))]>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16rr : I<0xBB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32rr : I<0xBB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64rr : RI<0xBB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mr : I<0xBB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32mr : I<0xBB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64mr : RI<0xBB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16rr : I<0xB3, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32rr : I<0xB3, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64rr : RI<0xB3, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mr : I<0xB3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32mr : I<0xB3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64mr : RI<0xB3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16rr : I<0xAB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32rr : I<0xAB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64rr : RI<0xAB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mr : I<0xAB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32mr : I<0xAB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64mr : RI<0xAB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 -} // Defs = [EFLAGS] - - -//===----------------------------------------------------------------------===// -// Atomic support -// - -// Atomic swap. These are just normal xchg instructions. But since a memory -// operand is referenced, the atomicity is ensured. -multiclass ATOMIC_SWAP opc8, bits<8> opc, string mnemonic, string frag> { - let Constraints = "$val = $dst", SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8rm : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16rm : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32rm : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64rm : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm XCHG : ATOMIC_SWAP<0x86, 0x87, "xchg", "atomic_swap">, NotMemoryFoldable; - -// Swap between registers. -let SchedRW = [WriteALU] in { -let Constraints = "$src1 = $dst1, $src2 = $dst2", hasSideEffects = 0 in { -def XCHG8rr : I<0x86, MRMSrcReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xchg{b}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -def XCHG16rr : I<0x87, MRMSrcReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xchg{w}\t{$src1, $src2|$src2, $src1}", []>, - OpSize16, NotMemoryFoldable; -def XCHG32rr : I<0x87, MRMSrcReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xchg{l}\t{$src1, $src2|$src2, $src1}", []>, - OpSize32, NotMemoryFoldable; -def XCHG64rr : RI<0x87, MRMSrcReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1 ,GR64:$src2), - "xchg{q}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -} - -def NOOP19rr: I<0x19, MRMSrcReg, (outs), (ins GR32:$val, GR32:$src), - "nop\t{$val, $src|$src, $val}", []>, TB, - OpSize32; - -// Swap between EAX and other registers. -let Constraints = "$src = $dst", hasSideEffects = 0 in { -let Uses = [AX], Defs = [AX] in -def XCHG16ar : I<0x90, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "xchg{w}\t{%ax, $src|$src, ax}", []>, OpSize16; -let Uses = [EAX], Defs = [EAX] in -def XCHG32ar : I<0x90, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "xchg{l}\t{%eax, $src|$src, eax}", []>, OpSize32; -let Uses = [RAX], Defs = [RAX] in -def XCHG64ar : RI<0x90, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "xchg{q}\t{%rax, $src|$src, rax}", []>; -} -} // SchedRW - -let hasSideEffects = 0, Constraints = "$src1 = $dst1, $src2 = $dst2", - Defs = [EFLAGS], SchedRW = [WriteALU] in { -def XADD8rr : I<0xC0, MRMDestReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xadd{b}\t{$src2, $src1|$src1, $src2}", []>, TB; -def XADD16rr : I<0xC1, MRMDestReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xadd{w}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize16; -def XADD32rr : I<0xC1, MRMDestReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xadd{l}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize32; -def XADD64rr : RI<0xC1, MRMDestReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1, GR64:$src2), - "xadd{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, hasSideEffects = 0, Constraints = "$val = $dst", - Defs = [EFLAGS], SchedRW = [WriteALULd, WriteRMW] in { -def XADD8rm : I<0xC0, MRMSrcMem, (outs GR8:$dst), - (ins GR8:$val, i8mem:$ptr), - "xadd{b}\t{$val, $ptr|$ptr, $val}", []>, TB; -def XADD16rm : I<0xC1, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$val, i16mem:$ptr), - "xadd{w}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize16; -def XADD32rm : I<0xC1, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$val, i32mem:$ptr), - "xadd{l}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize32; -def XADD64rm : RI<0xC1, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$val, i64mem:$ptr), - "xadd{q}\t{$val, $ptr|$ptr, $val}", []>, TB; - -} - -let SchedRW = [WriteALU], hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rr : I<0xB0, MRMDestReg, (outs GR8:$dst), (ins GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rr : I<0xB1, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rr : I<0xB1, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rr : RI<0xB1, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -} // SchedRW, hasSideEffects - -let SchedRW = [WriteALULd, WriteRMW], mayLoad = 1, mayStore = 1, - hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rm : I<0xB0, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rm : I<0xB1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rm : I<0xB1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rm : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in -def CMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$dst), - "cmpxchg8b\t$dst", []>, TB; - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX] in -def CMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$dst), - "cmpxchg16b\t$dst", []>, - TB, Requires<[HasCmpxchg16b, In64BitMode]>; -} // SchedRW, mayLoad, mayStore, hasSideEffects - - -// Lock instruction prefix -let SchedRW = [WriteMicrocoded] in -def LOCK_PREFIX : I<0xF0, RawFrm, (outs), (ins), "lock", []>; - -let SchedRW = [WriteNop] in { - -// Rex64 instruction prefix -def REX64_PREFIX : I<0x48, RawFrm, (outs), (ins), "rex64", []>, - Requires<[In64BitMode]>; - -// Data16 instruction prefix -def DATA16_PREFIX : I<0x66, RawFrm, (outs), (ins), "data16", []>; -} // SchedRW - -// Repeat string operation instruction prefixes -let Defs = [ECX], Uses = [ECX,DF], SchedRW = [WriteMicrocoded] in { -// Repeat (used with INS, OUTS, MOVS, LODS and STOS) -def REP_PREFIX : I<0xF3, RawFrm, (outs), (ins), "rep", []>; -// Repeat while not equal (used with CMPS and SCAS) -def REPNE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "repne", []>; -} - -// String manipulation instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [AL,ESI], Uses = [ESI,DF] in -def LODSB : I<0xAC, RawFrmSrc, (outs), (ins srcidx8:$src), - "lodsb\t{$src, %al|al, $src}", []>; -let Defs = [AX,ESI], Uses = [ESI,DF] in -def LODSW : I<0xAD, RawFrmSrc, (outs), (ins srcidx16:$src), - "lodsw\t{$src, %ax|ax, $src}", []>, OpSize16; -let Defs = [EAX,ESI], Uses = [ESI,DF] in -def LODSL : I<0xAD, RawFrmSrc, (outs), (ins srcidx32:$src), - "lods{l|d}\t{$src, %eax|eax, $src}", []>, OpSize32; -let Defs = [RAX,ESI], Uses = [ESI,DF] in -def LODSQ : RI<0xAD, RawFrmSrc, (outs), (ins srcidx64:$src), - "lodsq\t{$src, %rax|rax, $src}", []>, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteSystem] in { -let Defs = [ESI], Uses = [DX,ESI,DF] in { -def OUTSB : I<0x6E, RawFrmSrc, (outs), (ins srcidx8:$src), - "outsb\t{$src, %dx|dx, $src}", []>; -def OUTSW : I<0x6F, RawFrmSrc, (outs), (ins srcidx16:$src), - "outsw\t{$src, %dx|dx, $src}", []>, OpSize16; -def OUTSL : I<0x6F, RawFrmSrc, (outs), (ins srcidx32:$src), - "outs{l|d}\t{$src, %dx|dx, $src}", []>, OpSize32; -} - -let Defs = [EDI], Uses = [DX,EDI,DF] in { -def INSB : I<0x6C, RawFrmDst, (outs), (ins dstidx8:$dst), - "insb\t{%dx, $dst|$dst, dx}", []>; -def INSW : I<0x6D, RawFrmDst, (outs), (ins dstidx16:$dst), - "insw\t{%dx, $dst|$dst, dx}", []>, OpSize16; -def INSL : I<0x6D, RawFrmDst, (outs), (ins dstidx32:$dst), - "ins{l|d}\t{%dx, $dst|$dst, dx}", []>, OpSize32; -} -} - -// EFLAGS management instructions. -let SchedRW = [WriteALU], Defs = [EFLAGS], Uses = [EFLAGS] in { -def CLC : I<0xF8, RawFrm, (outs), (ins), "clc", []>; -def STC : I<0xF9, RawFrm, (outs), (ins), "stc", []>; -def CMC : I<0xF5, RawFrm, (outs), (ins), "cmc", []>; -} - -// DF management instructions. -let SchedRW = [WriteALU], Defs = [DF] in { -def CLD : I<0xFC, RawFrm, (outs), (ins), "cld", []>; -def STD : I<0xFD, RawFrm, (outs), (ins), "std", []>; -} - -// Table lookup instructions -let Uses = [AL,EBX], Defs = [AL], hasSideEffects = 0, mayLoad = 1 in -def XLAT : I<0xD7, RawFrm, (outs), (ins), "xlatb", []>, Sched<[WriteLoad]>; - -let SchedRW = [WriteMicrocoded] in { -// ASCII Adjust After Addition -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAA : I<0x37, RawFrm, (outs), (ins), "aaa", []>, - Requires<[Not64BitMode]>; - -// ASCII Adjust AX Before Division -let Uses = [AX], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAD8i8 : Ii8<0xD5, RawFrm, (outs), (ins i8imm:$src), - "aad\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AX After Multiply -let Uses = [AL], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAM8i8 : Ii8<0xD4, RawFrm, (outs), (ins i8imm:$src), - "aam\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AL After Subtraction - sets -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAS : I<0x3F, RawFrm, (outs), (ins), "aas", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Addition -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAA : I<0x27, RawFrm, (outs), (ins), "daa", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Subtraction -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAS : I<0x2F, RawFrm, (outs), (ins), "das", []>, - Requires<[Not64BitMode]>; -} // SchedRW - -let SchedRW = [WriteSystem] in { -// Check Array Index Against Bounds -// Note: "bound" does not have reversed operands in at&t syntax. -def BOUNDS16rm : I<0x62, MRMSrcMem, (outs GR16:$dst), (ins i32mem:$src), - "bound\t$dst, $src", []>, OpSize16, - Requires<[Not64BitMode]>; -def BOUNDS32rm : I<0x62, MRMSrcMem, (outs GR32:$dst), (ins i64mem:$src), - "bound\t$dst, $src", []>, OpSize32, - Requires<[Not64BitMode]>; - -// Adjust RPL Field of Segment Selector -def ARPL16rr : I<0x63, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -let mayStore = 1 in -def ARPL16mr : I<0x63, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVBE Instructions -// -let Predicates = [HasMOVBE] in { - let SchedRW = [WriteALULd] in { - def MOVBE16rm : I<0xF0, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (bswap (loadi16 addr:$src)))]>, - OpSize16, T8PS; - def MOVBE32rm : I<0xF0, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bswap (loadi32 addr:$src)))]>, - OpSize32, T8PS; - def MOVBE64rm : RI<0xF0, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bswap (loadi64 addr:$src)))]>, - T8PS; - } - let SchedRW = [WriteStore] in { - def MOVBE16mr : I<0xF1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(store (bswap GR16:$src), addr:$dst)]>, - OpSize16, T8PS; - def MOVBE32mr : I<0xF1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(store (bswap GR32:$src), addr:$dst)]>, - OpSize32, T8PS; - def MOVBE64mr : RI<0xF1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(store (bswap GR64:$src), addr:$dst)]>, - T8PS; - } -} - -//===----------------------------------------------------------------------===// -// RDRAND Instruction -// -let Predicates = [HasRDRAND], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDRAND16r : I<0xC7, MRM6r, (outs GR16:$dst), (ins), - "rdrand{w}\t$dst", [(set GR16:$dst, EFLAGS, (X86rdrand))]>, - OpSize16, PS; - def RDRAND32r : I<0xC7, MRM6r, (outs GR32:$dst), (ins), - "rdrand{l}\t$dst", [(set GR32:$dst, EFLAGS, (X86rdrand))]>, - OpSize32, PS; - def RDRAND64r : RI<0xC7, MRM6r, (outs GR64:$dst), (ins), - "rdrand{q}\t$dst", [(set GR64:$dst, EFLAGS, (X86rdrand))]>, - PS; -} - -//===----------------------------------------------------------------------===// -// RDSEED Instruction -// -let Predicates = [HasRDSEED], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDSEED16r : I<0xC7, MRM7r, (outs GR16:$dst), (ins), "rdseed{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86rdseed))]>, OpSize16, PS; - def RDSEED32r : I<0xC7, MRM7r, (outs GR32:$dst), (ins), "rdseed{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86rdseed))]>, OpSize32, PS; - def RDSEED64r : RI<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdseed{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86rdseed))]>, PS; -} - -//===----------------------------------------------------------------------===// -// LZCNT Instruction -// -let Predicates = [HasLZCNT], Defs = [EFLAGS] in { - def LZCNT16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteLZCNT]>; - def LZCNT16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteLZCNTLd]>; - - def LZCNT32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteLZCNT]>; - def LZCNT32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteLZCNTLd]>; - - def LZCNT64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteLZCNT]>; - def LZCNT64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteLZCNTLd]>; -} - -//===----------------------------------------------------------------------===// -// BMI Instructions -// -let Predicates = [HasBMI], Defs = [EFLAGS] in { - def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteTZCNT]>; - def TZCNT16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteTZCNTLd]>; - - def TZCNT32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteTZCNT]>; - def TZCNT32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteTZCNTLd]>; - - def TZCNT64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteTZCNT]>; - def TZCNT64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteTZCNTLd]>; -} - -multiclass bmi_bls { -let hasSideEffects = 0 in { - def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALU]>; - let mayLoad = 1 in - def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALULd]>; -} -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>; - defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W; - defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>; - defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W; - defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>; - defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate BMI instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasBMI] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, -1)), - (BLSR32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, -1)), - (BLSR64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, -1)), - (BLSMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, -1)), - (BLSMSK64rr GR64:$src)>; - - def : Pat<(and GR32:$src, (ineg GR32:$src)), - (BLSI32rr GR32:$src)>; - def : Pat<(and GR64:$src, (ineg GR64:$src)), - (BLSI64rr GR64:$src)>; -} - -multiclass bmi_bextr opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BEXTR32 : bmi_bextr<0xF7, "bextr{l}", GR32, i32mem, - X86bextr, loadi32, WriteBEXTR>; - defm BEXTR64 : bmi_bextr<0xF7, "bextr{q}", GR64, i64mem, - X86bextr, loadi64, WriteBEXTR>, VEX_W; -} - -multiclass bmi_bzhi opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, Intrinsic Int, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI2], Defs = [EFLAGS] in { - defm BZHI32 : bmi_bzhi<0xF5, "bzhi{l}", GR32, i32mem, - int_x86_bmi_bzhi_32, loadi32, WriteBZHI>; - defm BZHI64 : bmi_bzhi<0xF5, "bzhi{q}", GR64, i64mem, - int_x86_bmi_bzhi_64, loadi64, WriteBZHI>, VEX_W; -} - -def CountTrailingOnes : SDNodeXFormgetZExtValue()), SDLoc(N)); -}]>; - -def BEXTRMaskXForm : SDNodeXFormgetZExtValue()); - return getI32Imm(Length << 8, SDLoc(N)); -}]>; - -def AndMask64 : ImmLeaf(Imm); -}]>; - -// Use BEXTR for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI, NoBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTR64rr GR64:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTR64rm addr:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; -} - -// Use BZHI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; -} - -let Predicates = [HasBMI2] in { - multiclass _bmi_bzhi_pattern { - def : Pat; - def : Pat; - } - - multiclass bmi_bzhi_patterns { - // x & ((1 << y) - 1) - defm : _bmi_bzhi_pattern<(and RC:$src, (add (shl 1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (add (shl 1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & ~(-1 << y) - defm : _bmi_bzhi_pattern<(and RC:$src, (xor (shl -1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (xor (shl -1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & (-1 >> (bitwidth - y)) - defm : _bmi_bzhi_pattern<(and RC:$src, (srl -1, (sub bitwidth, GR8:$lz))), - (and (x86memop addr:$src), - (srl -1, (sub bitwidth, GR8:$lz))), - RC, VT, DstInst, DstMemInst>; - - // x << (bitwidth - y) >> (bitwidth - y) - defm : _bmi_bzhi_pattern<(srl (shl RC:$src, (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - (srl (shl (x86memop addr:$src), - (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - RC, VT, DstInst, DstMemInst>; - } - - defm : bmi_bzhi_patterns; - defm : bmi_bzhi_patterns; - - // x & (-1 >> (32 - y)) - def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(and (loadi32 addr:$src), (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x & (-1 >> (64 - y)) - def : Pat<(and GR64:$src, (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - - // x << (32 - y) >> (32 - y) - def : Pat<(srl (shl GR32:$src, (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(srl (shl (loadi32 addr:$src), (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x << (64 - y) >> (64 - y) - def : Pat<(srl (shl GR64:$src, (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(srl (shl (loadi64 addr:$src), (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; -} // HasBMI2 - -multiclass bmi_pdep_pext { - def rr : I<0xF5, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, RC:$src2))]>, - VEX_4V, Sched<[WriteALU]>; - def rm : I<0xF5, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, (ld_frag addr:$src2)))]>, - VEX_4V, Sched<[WriteALULd, ReadAfterLd]>; -} - -let Predicates = [HasBMI2] in { - defm PDEP32 : bmi_pdep_pext<"pdep{l}", GR32, i32mem, - int_x86_bmi_pdep_32, loadi32>, T8XD; - defm PDEP64 : bmi_pdep_pext<"pdep{q}", GR64, i64mem, - int_x86_bmi_pdep_64, loadi64>, T8XD, VEX_W; - defm PEXT32 : bmi_pdep_pext<"pext{l}", GR32, i32mem, - int_x86_bmi_pext_32, loadi32>, T8XS; - defm PEXT64 : bmi_pdep_pext<"pext{q}", GR64, i64mem, - int_x86_bmi_pext_64, loadi64>, T8XS, VEX_W; -} - -//===----------------------------------------------------------------------===// -// TBM Instructions -// -let Predicates = [HasTBM], Defs = [EFLAGS] in { - -multiclass tbm_ternary_imm opc, RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - SDNode OpNode, Operand immtype, - SDPatternOperator immoperator, - X86FoldableSchedWrite Sched> { - def ri : Ii32, - XOP, XOPA, Sched<[Sched]>; - def mi : Ii32, - XOP, XOPA, Sched<[Sched.Folded]>; -} - -defm BEXTRI32 : tbm_ternary_imm<0x10, GR32, "bextr{l}", i32mem, loadi32, - X86bextr, i32imm, imm, WriteBEXTR>; -let ImmT = Imm32S in -defm BEXTRI64 : tbm_ternary_imm<0x10, GR64, "bextr{q}", i64mem, loadi64, - X86bextr, i64i32imm, - i64immSExt32, WriteBEXTR>, VEX_W; - -multiclass tbm_binary_rm opc, Format FormReg, Format FormMem, - RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, X86FoldableSchedWrite Sched> { -let hasSideEffects = 0 in { - def rr : I, - XOP_4V, XOP9, Sched<[Sched]>; - let mayLoad = 1 in - def rm : I, - XOP_4V, XOP9, Sched<[Sched.Folded]>; -} -} - -multiclass tbm_binary_intr opc, string OpcodeStr, - X86FoldableSchedWrite Sched, - Format FormReg, Format FormMem> { - defm NAME#32 : tbm_binary_rm; - defm NAME#64 : tbm_binary_rm, VEX_W; -} - -defm BLCFILL : tbm_binary_intr<0x01, "blcfill", WriteALU, MRM1r, MRM1m>; -defm BLCI : tbm_binary_intr<0x02, "blci", WriteALU, MRM6r, MRM6m>; -defm BLCIC : tbm_binary_intr<0x01, "blcic", WriteALU, MRM5r, MRM5m>; -defm BLCMSK : tbm_binary_intr<0x02, "blcmsk", WriteALU, MRM1r, MRM1m>; -defm BLCS : tbm_binary_intr<0x01, "blcs", WriteALU, MRM3r, MRM3m>; -defm BLSFILL : tbm_binary_intr<0x01, "blsfill", WriteALU, MRM2r, MRM2m>; -defm BLSIC : tbm_binary_intr<0x01, "blsic", WriteALU, MRM6r, MRM6m>; -defm T1MSKC : tbm_binary_intr<0x01, "t1mskc", WriteALU, MRM7r, MRM7m>; -defm TZMSK : tbm_binary_intr<0x01, "tzmsk", WriteALU, MRM4r, MRM4m>; -} // HasTBM, EFLAGS - -// Use BEXTRI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>; - - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>; -} - -//===----------------------------------------------------------------------===// -// Lightweight Profiling Instructions - -let Predicates = [HasLWP], SchedRW = [WriteSystem] in { - -def LLWPCB : I<0x12, MRM0r, (outs), (ins GR32:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR32:$src)]>, XOP, XOP9; -def SLWPCB : I<0x12, MRM1r, (outs GR32:$dst), (ins), "slwpcb\t$dst", - [(set GR32:$dst, (int_x86_slwpcb))]>, XOP, XOP9; - -def LLWPCB64 : I<0x12, MRM0r, (outs), (ins GR64:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR64:$src)]>, XOP, XOP9, VEX_W; -def SLWPCB64 : I<0x12, MRM1r, (outs GR64:$dst), (ins), "slwpcb\t$dst", - [(set GR64:$dst, (int_x86_slwpcb))]>, XOP, XOP9, VEX_W; - -multiclass lwpins_intr { - def rri : Ii32<0x12, MRM0r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, GR32:$src1, imm:$cntl))]>, - XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM0m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, (loadi32 addr:$src1), imm:$cntl))]>, - XOP_4V, XOPA; -} - -let Defs = [EFLAGS] in { - defm LWPINS32 : lwpins_intr; - defm LWPINS64 : lwpins_intr, VEX_W; -} // EFLAGS - -multiclass lwpval_intr { - def rri : Ii32<0x12, MRM1r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, GR32:$src1, imm:$cntl)]>, XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM1m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, (loadi32 addr:$src1), imm:$cntl)]>, - XOP_4V, XOPA; -} - -defm LWPVAL32 : lwpval_intr; -defm LWPVAL64 : lwpval_intr, VEX_W; - -} // HasLWP, SchedRW - -//===----------------------------------------------------------------------===// -// MONITORX/MWAITX Instructions -// -let SchedRW = [ WriteSystem ] in { -/* - let usesCustomInserter = 1 in { - def MONITORX : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_monitorx addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[ HasMWAITX ]>; - } -*/ - - let Uses = [ EAX, ECX, EDX ] in { - def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", []>, - TB, Requires<[ HasMWAITX ]>; - } - - let Uses = [ ECX, EAX, EBX ] in { - def MWAITXrrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx", - [(int_x86_mwaitx ECX, EAX, EBX)]>, - TB, Requires<[ HasMWAITX ]>; - } -} // SchedRW - -def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrrr)>, - Requires<[ Not64BitMode ]>; -def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrrr)>, - Requires<[ In64BitMode ]>; - -def : InstAlias<"monitorx\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORXrrr)>, - Requires<[ Not64BitMode ]>; -def : InstAlias<"monitorx\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORXrrr)>, - Requires<[ In64BitMode ]>; - -//===----------------------------------------------------------------------===// -// WAITPKG Instructions -// -let SchedRW = [WriteSystem] in { - def UMONITOR16 : I<0xAE, MRM6r, (outs), (ins GR16:$src), - "umonitor\t$src", [(int_x86_umonitor GR16:$src)]>, - XS, AdSize16, Requires<[HasWAITPKG, Not64BitMode]>; - def UMONITOR32 : I<0xAE, MRM6r, (outs), (ins GR32:$src), - "umonitor\t$src", [(int_x86_umonitor GR32:$src)]>, - XS, AdSize32, Requires<[HasWAITPKG]>; - def UMONITOR64 : I<0xAE, MRM6r, (outs), (ins GR64:$src), - "umonitor\t$src", [(int_x86_umonitor GR64:$src)]>, - XS, AdSize64, Requires<[HasWAITPKG, In64BitMode]>; - let Uses = [EAX, EDX], Defs = [EFLAGS] in { - def UMWAIT : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "umwait\t$src", - [(set EFLAGS, (X86umwait GR32orGR64:$src, EDX, EAX))]>, - XD, Requires<[HasWAITPKG]>; - def TPAUSE : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "tpause\t$src", - [(set EFLAGS, (X86tpause GR32orGR64:$src, EDX, EAX))]>, - PD, Requires<[HasWAITPKG]>, NotMemoryFoldable; - } -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIRI - Move doubleword/quadword as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIRI32 : I<0xF9, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore32 addr:$dst, GR32:$src)]>, - T8, Requires<[HasMOVDIRI]>; -def MOVDIRI64 : RI<0xF9, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore64 addr:$dst, GR64:$src)]>, - T8, Requires<[In64BitMode, HasMOVDIRI]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIR64B - Move 64 bytes as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIR64B16 : I<0xF8, MRMSrcMem, (outs), (ins GR16:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", []>, - T8PD, AdSize16, Requires<[HasMOVDIR64B, Not64BitMode]>; -def MOVDIR64B32 : I<0xF8, MRMSrcMem, (outs), (ins GR32:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR32:$dst, addr:$src)]>, - T8PD, AdSize32, Requires<[HasMOVDIR64B]>; -def MOVDIR64B64 : I<0xF8, MRMSrcMem, (outs), (ins GR64:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR64:$dst, addr:$src)]>, - T8PD, AdSize64, Requires<[HasMOVDIR64B, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CLZERO Instruction -// -let SchedRW = [WriteSystem] in { - let Uses = [EAX] in - def CLZEROr : I<0x01, MRM_FC, (outs), (ins), "clzero", []>, - TB, Requires<[HasCLZERO]>; - -/* - let usesCustomInserter = 1 in { - def CLZERO : PseudoI<(outs), (ins i32mem:$src1), - [(int_x86_clzero addr:$src1)]>, Requires<[HasCLZERO]>; - } -*/ -} // SchedRW - -def : InstAlias<"clzero\t{%eax|eax}", (CLZEROr)>, Requires<[Not64BitMode]>; -def : InstAlias<"clzero\t{%rax|rax}", (CLZEROr)>, Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate TBM instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasTBM] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, 1)), - (BLCFILL32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, 1)), - (BLCFILL64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (not (add GR32:$src, 1))), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (not (add GR64:$src, 1))), - (BLCI64rr GR64:$src)>; - - // Extra patterns because opt can optimize the above patterns to this. - def : Pat<(or GR32:$src, (sub -2, GR32:$src)), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (sub -2, GR64:$src)), - (BLCI64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, 1)), - (BLCIC32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, 1)), - (BLCIC64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, 1)), - (BLCMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, 1)), - (BLCMSK64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, 1)), - (BLCS32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, 1)), - (BLCS64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, -1)), - (BLSFILL32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, -1)), - (BLSFILL64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, -1)), - (BLSIC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, -1)), - (BLSIC64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, 1)), - (T1MSKC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, 1)), - (T1MSKC64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, -1)), - (TZMSK32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, -1)), - (TZMSK64rr GR64:$src)>; -} // HasTBM - -//===----------------------------------------------------------------------===// -// Memory Instructions -// - -let Predicates = [HasCLFLUSHOPT], SchedRW = [WriteLoad] in -def CLFLUSHOPT : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflushopt\t$src", [(int_x86_clflushopt addr:$src)]>, PD; - -let Predicates = [HasCLWB], SchedRW = [WriteLoad] in -def CLWB : I<0xAE, MRM6m, (outs), (ins i8mem:$src), "clwb\t$src", - [(int_x86_clwb addr:$src)]>, PD, NotMemoryFoldable; - -let Predicates = [HasCLDEMOTE], SchedRW = [WriteLoad] in -def CLDEMOTE : I<0x1C, MRM0m, (outs), (ins i8mem:$src), "cldemote\t$src", - [(int_x86_cldemote addr:$src)]>, TB; - -//===----------------------------------------------------------------------===// -// Subsystems. -//===----------------------------------------------------------------------===// - -include "X86Capstone.td" - -include "X86InstrArithmetic.td" -include "X86InstrCMovSetCC.td" -include "X86InstrExtension.td" -include "X86InstrControl.td" -include "X86InstrShiftRotate.td" - -// X87 Floating Point Stack. -include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -include "X86InstrFMA.td" - -// XOP -include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -include "X86InstrSSE.td" -include "X86InstrAVX512.td" -include "X86InstrMMX.td" -include "X86Instr3DNow.td" - -// MPX instructions -include "X86InstrMPX.td" - -include "X86InstrVMX.td" -include "X86InstrSVM.td" - -include "X86InstrTSX.td" -include "X86InstrSGX.td" - -// System instructions. -include "X86InstrSystem.td" - -// Compiler Pseudo Instructions and Pat Patterns -//include "X86InstrCompiler.td" -//include "X86InstrVecCompiler.td" - -//===----------------------------------------------------------------------===// -// Assembler Mnemonic Aliases -//===----------------------------------------------------------------------===// - -def : MnemonicAlias<"call", "callw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"call", "calll", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"call", "callq", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"cbw", "cbtw", "att">; -def : MnemonicAlias<"cwde", "cwtl", "att">; -def : MnemonicAlias<"cwd", "cwtd", "att">; -def : MnemonicAlias<"cdq", "cltd", "att">; -def : MnemonicAlias<"cdqe", "cltq", "att">; -def : MnemonicAlias<"cqo", "cqto", "att">; - -// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq. -def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>; - -def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"loopz", "loope">; -def : MnemonicAlias<"loopnz", "loopne">; - -def : MnemonicAlias<"pop", "popw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pop", "popl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pop", "popq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popf", "popfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"popf", "popfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popfd", "popfl", "att">; - -// FIXME: This is wrong for "push reg". "push %bx" should turn into pushw in -// all modes. However: "push (addr)" and "push $42" should default to -// pushl/pushq depending on the current mode. Similar for "pop %bx" -def : MnemonicAlias<"push", "pushw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"push", "pushl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"push", "pushq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pushf", "pushfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushfd", "pushfl", "att">; - -def : MnemonicAlias<"popad", "popal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"pushad", "pushal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"popa", "popaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "intel">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "intel">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"popa", "popaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "att">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"repe", "rep">; -def : MnemonicAlias<"repz", "rep">; -def : MnemonicAlias<"repnz", "repne">; - -def : MnemonicAlias<"ret", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"ret", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"ret", "retq", "att">, Requires<[In64BitMode]>; - -// Apply 'ret' behavior to 'retn' -def : MnemonicAlias<"retn", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"retn", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"retn", "retq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"retn", "ret", "intel">; - -def : MnemonicAlias<"sal", "shl", "intel">; -def : MnemonicAlias<"salb", "shlb", "att">; -def : MnemonicAlias<"salw", "shlw", "att">; -def : MnemonicAlias<"sall", "shll", "att">; -def : MnemonicAlias<"salq", "shlq", "att">; - -def : MnemonicAlias<"smovb", "movsb", "att">; -def : MnemonicAlias<"smovw", "movsw", "att">; -def : MnemonicAlias<"smovl", "movsl", "att">; -def : MnemonicAlias<"smovq", "movsq", "att">; - -def : MnemonicAlias<"ud2a", "ud2", "att">; -def : MnemonicAlias<"verrw", "verr", "att">; - -// MS recognizes 'xacquire'/'xrelease' as 'acquire'/'release' -def : MnemonicAlias<"acquire", "xacquire", "intel">; -def : MnemonicAlias<"release", "xrelease", "intel">; - -// System instruction aliases. -def : MnemonicAlias<"iret", "iretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"iret", "iretl", "att">, Requires<[Not16BitMode]>; -def : MnemonicAlias<"sysret", "sysretl", "att">; -def : MnemonicAlias<"sysexit", "sysexitl", "att">; - -def : MnemonicAlias<"lgdt", "lgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"lidt", "lidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lidt", "lidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lidt", "lidtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sidt", "sidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sidt", "sidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sidt", "sidtq", "att">, Requires<[In64BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"lidt", "lidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lidt", "lidtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sidt", "sidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sidt", "sidtd", "intel">, Requires<[In32BitMode]>; - - -// Floating point stack aliases. -def : MnemonicAlias<"fcmovz", "fcmove", "att">; -def : MnemonicAlias<"fcmova", "fcmovnbe", "att">; -def : MnemonicAlias<"fcmovnae", "fcmovb", "att">; -def : MnemonicAlias<"fcmovna", "fcmovbe", "att">; -def : MnemonicAlias<"fcmovae", "fcmovnb", "att">; -def : MnemonicAlias<"fcomip", "fcompi">; -def : MnemonicAlias<"fildq", "fildll", "att">; -def : MnemonicAlias<"fistpq", "fistpll", "att">; -def : MnemonicAlias<"fisttpq", "fisttpll", "att">; -def : MnemonicAlias<"fldcww", "fldcw", "att">; -def : MnemonicAlias<"fnstcww", "fnstcw", "att">; -def : MnemonicAlias<"fnstsww", "fnstsw", "att">; -def : MnemonicAlias<"fucomip", "fucompi">; -def : MnemonicAlias<"fwait", "wait">; - -def : MnemonicAlias<"fxsaveq", "fxsave64", "att">; -def : MnemonicAlias<"fxrstorq", "fxrstor64", "att">; -def : MnemonicAlias<"xsaveq", "xsave64", "att">; -def : MnemonicAlias<"xrstorq", "xrstor64", "att">; -def : MnemonicAlias<"xsaveoptq", "xsaveopt64", "att">; -def : MnemonicAlias<"xrstorsq", "xrstors64", "att">; -def : MnemonicAlias<"xsavecq", "xsavec64", "att">; -def : MnemonicAlias<"xsavesq", "xsaves64", "att">; - -class CondCodeAlias - : MnemonicAlias; - -/// IntegerCondCodeMnemonicAlias - This multiclass defines a bunch of -/// MnemonicAlias's that canonicalize the condition code in a mnemonic, for -/// example "setz" -> "sete". -multiclass IntegerCondCodeMnemonicAlias { - def C : CondCodeAlias; // setc -> setb - def Z : CondCodeAlias; // setz -> sete - def NA : CondCodeAlias; // setna -> setbe - def NB : CondCodeAlias; // setnb -> setae - def NC : CondCodeAlias; // setnc -> setae - def NG : CondCodeAlias; // setng -> setle - def NL : CondCodeAlias; // setnl -> setge - def NZ : CondCodeAlias; // setnz -> setne - def PE : CondCodeAlias; // setpe -> setp - def PO : CondCodeAlias; // setpo -> setnp - - def NAE : CondCodeAlias; // setnae -> setb - def NBE : CondCodeAlias; // setnbe -> seta - def NGE : CondCodeAlias; // setnge -> setl - def NLE : CondCodeAlias; // setnle -> setg -} - -// Aliases for set -defm : IntegerCondCodeMnemonicAlias<"set", "">; -// Aliases for j -defm : IntegerCondCodeMnemonicAlias<"j", "">; -// Aliases for cmov{w,l,q} -defm : IntegerCondCodeMnemonicAlias<"cmov", "w", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "l", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "q", "att">; -// No size suffix for intel-style asm. -defm : IntegerCondCodeMnemonicAlias<"cmov", "", "intel">; - - -//===----------------------------------------------------------------------===// -// Assembler Instruction Aliases -//===----------------------------------------------------------------------===// - -// aad/aam default to base 10 if no operand is specified. -def : InstAlias<"aad", (AAD8i8 10)>, Requires<[Not64BitMode]>; -def : InstAlias<"aam", (AAM8i8 10)>, Requires<[Not64BitMode]>; - -// Disambiguate the mem/imm form of bt-without-a-suffix as btl. -// Likewise for btc/btr/bts. -def : InstAlias<"bt\t{$imm, $mem|$mem, $imm}", - (BT32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"btc\t{$imm, $mem|$mem, $imm}", - (BTC32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"btr\t{$imm, $mem|$mem, $imm}", - (BTR32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"bts\t{$imm, $mem|$mem, $imm}", - (BTS32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; - -// clr aliases. -def : InstAlias<"clr{b}\t$reg", (XOR8rr GR8 :$reg, GR8 :$reg), 0>; -def : InstAlias<"clr{w}\t$reg", (XOR16rr GR16:$reg, GR16:$reg), 0>; -def : InstAlias<"clr{l}\t$reg", (XOR32rr GR32:$reg, GR32:$reg), 0>; -def : InstAlias<"clr{q}\t$reg", (XOR64rr GR64:$reg, GR64:$reg), 0>; - -// lods aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"lodsb\t$src", (LODSB srcidx8:$src), 0>; -def : InstAlias<"lodsw\t$src", (LODSW srcidx16:$src), 0>; -def : InstAlias<"lods{l|d}\t$src", (LODSL srcidx32:$src), 0>; -def : InstAlias<"lodsq\t$src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -def : InstAlias<"lods\t{$src, %al|al, $src}", (LODSB srcidx8:$src), 0>; -def : InstAlias<"lods\t{$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>; -def : InstAlias<"lods\t{$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>; -def : InstAlias<"lods\t{$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -def : InstAlias<"lods\t$src", (LODSB srcidx8:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSW srcidx16:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSL srcidx32:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSQ srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - - -// stos aliases. Accept the source being omitted because it's implicit in -// the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the source. -def : InstAlias<"stosb\t$dst", (STOSB dstidx8:$dst), 0>; -def : InstAlias<"stosw\t$dst", (STOSW dstidx16:$dst), 0>; -def : InstAlias<"stos{l|d}\t$dst", (STOSL dstidx32:$dst), 0>; -def : InstAlias<"stosq\t$dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"stos\t{%al, $dst|$dst, al}", (STOSB dstidx8:$dst), 0>; -def : InstAlias<"stos\t{%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>; -def : InstAlias<"stos\t{%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>; -def : InstAlias<"stos\t{%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"stos\t$dst", (STOSB dstidx8:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSW dstidx16:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSL dstidx32:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - - -// scas aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"scasb\t$dst", (SCASB dstidx8:$dst), 0>; -def : InstAlias<"scasw\t$dst", (SCASW dstidx16:$dst), 0>; -def : InstAlias<"scas{l|d}\t$dst", (SCASL dstidx32:$dst), 0>; -def : InstAlias<"scasq\t$dst", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"scas\t{$dst, %al|al, $dst}", (SCASB dstidx8:$dst), 0>; -def : InstAlias<"scas\t{$dst, %ax|ax, $dst}", (SCASW dstidx16:$dst), 0>; -def : InstAlias<"scas\t{$dst, %eax|eax, $dst}", (SCASL dstidx32:$dst), 0>; -def : InstAlias<"scas\t{$dst, %rax|rax, $dst}", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"scas\t$dst", (SCASB dstidx8:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASW dstidx16:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASL dstidx32:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - -// cmps aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// movs aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// div and idiv aliases for explicit A register. -def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>; -def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>; -def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32r GR32:$src)>; -def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64r GR64:$src)>; -def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8m i8mem :$src)>; -def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16m i16mem:$src)>; -def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32m i32mem:$src)>; -def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64m i64mem:$src)>; -def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8r GR8 :$src)>; -def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16r GR16:$src)>; -def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32r GR32:$src)>; -def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64r GR64:$src)>; -def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8m i8mem :$src)>; -def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16m i16mem:$src)>; -def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32m i32mem:$src)>; -def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64m i64mem:$src)>; - - - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -def : InstAlias<"fxch", (XCH_F ST1), 0>; -def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; - -def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// lcall and ljmp aliases. This seems to be an odd mapping in 64-bit mode, but -// this is compatible with what GAS does. -def : InstAlias<"lcall\t$seg : $off", (FARCALL32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -def : InstAlias<"ljmp\t$seg : $off", (FARJMP32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -def : InstAlias<"lcall\t{*}$dst", (FARCALL32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -def : InstAlias<"ljmp\t{*}$dst", (FARJMP32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -def : InstAlias<"lcall\t$seg : $off", (FARCALL16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -def : InstAlias<"ljmp\t$seg : $off", (FARJMP16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -def : InstAlias<"lcall\t{*}$dst", (FARCALL16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; -def : InstAlias<"ljmp\t{*}$dst", (FARJMP16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; - -def : InstAlias<"jmp\t{*}$dst", (JMP64m i64mem:$dst), 0, "att">, Requires<[In64BitMode]>; -def : InstAlias<"jmp\t{*}$dst", (JMP32m i32mem:$dst), 0, "att">, Requires<[In32BitMode]>; -def : InstAlias<"jmp\t{*}$dst", (JMP16m i16mem:$dst), 0, "att">, Requires<[In16BitMode]>; - - -// "imul , B" is an alias for "imul , B, B". -def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri GR16:$r, GR16:$r, i16imm:$imm), 0>; -def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri8 GR16:$r, GR16:$r, i16i8imm:$imm), 0>; -def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri GR32:$r, GR32:$r, i32imm:$imm), 0>; -def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri8 GR32:$r, GR32:$r, i32i8imm:$imm), 0>; -def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri32 GR64:$r, GR64:$r, i64i32imm:$imm), 0>; -def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri8 GR64:$r, GR64:$r, i64i8imm:$imm), 0>; - -// ins aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSB dstidx8:$dst), 0, "intel">; -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSW dstidx16:$dst), 0, "intel">; -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSL dstidx32:$dst), 0, "intel">; - -// outs aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the source. -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSB srcidx8:$src), 0, "intel">; -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSW srcidx16:$src), 0, "intel">; -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSL srcidx32:$src), 0, "intel">; - -// inb %dx -> inb %al, %dx -def : InstAlias<"inb\t{%dx|dx}", (IN8rr), 0>; -def : InstAlias<"inw\t{%dx|dx}", (IN16rr), 0>; -def : InstAlias<"inl\t{%dx|dx}", (IN32rr), 0>; -def : InstAlias<"inb\t$port", (IN8ri u8imm:$port), 0>; -def : InstAlias<"inw\t$port", (IN16ri u8imm:$port), 0>; -def : InstAlias<"inl\t$port", (IN32ri u8imm:$port), 0>; - - -// jmp and call aliases for lcall and ljmp. jmp $42,$5 -> ljmp -def : InstAlias<"call\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -def : InstAlias<"jmp\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -def : InstAlias<"call\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -def : InstAlias<"jmp\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -def : InstAlias<"callw\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"jmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"calll\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"jmpl\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; - -// Match 'movq , ' as an alias for movabsq. -def : InstAlias<"mov{q}\t{$imm, $reg|$reg, $imm}", (MOV64ri GR64:$reg, i64imm:$imm), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; - -// movsx aliases -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rr8 GR16:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr8 GR32:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr16 GR32:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr8 GR64:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr16 GR64:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr32 GR64:$dst, GR32:$src), 0, "att">; - -// movzx aliases -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rr8 GR16:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr8 GR32:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr16 GR32:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr8 GR64:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// Note: No GR32->GR64 movzx form. - -// outb %dx -> outb %al, %dx -def : InstAlias<"outb\t{%dx|dx}", (OUT8rr), 0>; -def : InstAlias<"outw\t{%dx|dx}", (OUT16rr), 0>; -def : InstAlias<"outl\t{%dx|dx}", (OUT32rr), 0>; -def : InstAlias<"outb\t$port", (OUT8ir u8imm:$port), 0>; -def : InstAlias<"outw\t$port", (OUT16ir u8imm:$port), 0>; -def : InstAlias<"outl\t$port", (OUT32ir u8imm:$port), 0>; - -// 'sldt ' can be encoded with either sldtw or sldtq with the same -// effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity -// errors, since its encoding is the most compact. -def : InstAlias<"sldt $mem", (SLDT16m i16mem:$mem), 0>; - -// shld/shrd op,op -> shld op, op, CL -def : InstAlias<"shld{w}\t{$r2, $r1|$r1, $r2}", (SHLD16rrCL GR16:$r1, GR16:$r2), 0>; -def : InstAlias<"shld{l}\t{$r2, $r1|$r1, $r2}", (SHLD32rrCL GR32:$r1, GR32:$r2), 0>; -def : InstAlias<"shld{q}\t{$r2, $r1|$r1, $r2}", (SHLD64rrCL GR64:$r1, GR64:$r2), 0>; -def : InstAlias<"shrd{w}\t{$r2, $r1|$r1, $r2}", (SHRD16rrCL GR16:$r1, GR16:$r2), 0>; -def : InstAlias<"shrd{l}\t{$r2, $r1|$r1, $r2}", (SHRD32rrCL GR32:$r1, GR32:$r2), 0>; -def : InstAlias<"shrd{q}\t{$r2, $r1|$r1, $r2}", (SHRD64rrCL GR64:$r1, GR64:$r2), 0>; - -def : InstAlias<"shld{w}\t{$reg, $mem|$mem, $reg}", (SHLD16mrCL i16mem:$mem, GR16:$reg), 0>; -def : InstAlias<"shld{l}\t{$reg, $mem|$mem, $reg}", (SHLD32mrCL i32mem:$mem, GR32:$reg), 0>; -def : InstAlias<"shld{q}\t{$reg, $mem|$mem, $reg}", (SHLD64mrCL i64mem:$mem, GR64:$reg), 0>; -def : InstAlias<"shrd{w}\t{$reg, $mem|$mem, $reg}", (SHRD16mrCL i16mem:$mem, GR16:$reg), 0>; -def : InstAlias<"shrd{l}\t{$reg, $mem|$mem, $reg}", (SHRD32mrCL i32mem:$mem, GR32:$reg), 0>; -def : InstAlias<"shrd{q}\t{$reg, $mem|$mem, $reg}", (SHRD64mrCL i64mem:$mem, GR64:$reg), 0>; - -/* FIXME: This is disabled because the asm matcher is currently incapable of - * matching a fixed immediate like $1. -// "shl X, $1" is an alias for "shl X". -multiclass ShiftRotateByOneAlias { - def : InstAlias(!strconcat(Opc, "8r1")) GR8:$op)>; - def : InstAlias(!strconcat(Opc, "16r1")) GR16:$op)>; - def : InstAlias(!strconcat(Opc, "32r1")) GR32:$op)>; - def : InstAlias(!strconcat(Opc, "64r1")) GR64:$op)>; - def : InstAlias(!strconcat(Opc, "8m1")) i8mem:$op)>; - def : InstAlias(!strconcat(Opc, "16m1")) i16mem:$op)>; - def : InstAlias(!strconcat(Opc, "32m1")) i32mem:$op)>; - def : InstAlias(!strconcat(Opc, "64m1")) i64mem:$op)>; -} - -defm : ShiftRotateByOneAlias<"rcl", "RCL">; -defm : ShiftRotateByOneAlias<"rcr", "RCR">; -defm : ShiftRotateByOneAlias<"rol", "ROL">; -defm : ShiftRotateByOneAlias<"ror", "ROR">; -FIXME */ - -// test: We accept "testX , " and "testX , " as synonyms. -def : InstAlias<"test{b}\t{$mem, $val|$val, $mem}", - (TEST8mr i8mem :$mem, GR8 :$val), 0>; -def : InstAlias<"test{w}\t{$mem, $val|$val, $mem}", - (TEST16mr i16mem:$mem, GR16:$val), 0>; -def : InstAlias<"test{l}\t{$mem, $val|$val, $mem}", - (TEST32mr i32mem:$mem, GR32:$val), 0>; -def : InstAlias<"test{q}\t{$mem, $val|$val, $mem}", - (TEST64mr i64mem:$mem, GR64:$val), 0>; - -// xchg: We accept "xchgX , " and "xchgX , " as synonyms. -def : InstAlias<"xchg{b}\t{$mem, $val|$val, $mem}", - (XCHG8rm GR8 :$val, i8mem :$mem), 0>; -def : InstAlias<"xchg{w}\t{$mem, $val|$val, $mem}", - (XCHG16rm GR16:$val, i16mem:$mem), 0>; -def : InstAlias<"xchg{l}\t{$mem, $val|$val, $mem}", - (XCHG32rm GR32:$val, i32mem:$mem), 0>; -def : InstAlias<"xchg{q}\t{$mem, $val|$val, $mem}", - (XCHG64rm GR64:$val, i64mem:$mem), 0>; - -// xchg: We accept "xchgX , %eax" and "xchgX %eax, " as synonyms. -def : InstAlias<"xchg{w}\t{%ax, $src|$src, ax}", (XCHG16ar GR16:$src), 0>; -def : InstAlias<"xchg{l}\t{%eax, $src|$src, eax}", (XCHG32ar GR32:$src), 0>; -def : InstAlias<"xchg{q}\t{%rax, $src|$src, rax}", (XCHG64ar GR64:$src), 0>; - -// In 64-bit mode, xchg %eax, %eax can't be encoded with the 0x90 opcode we -// would get by default because it's defined as NOP. But xchg %eax, %eax implies -// implicit zeroing of the upper 32 bits. So alias to the longer encoding. -def : InstAlias<"xchg{l}\t{%eax, %eax|eax, eax}", - (XCHG32rr EAX, EAX), 0>, Requires<[In64BitMode]>; - -// xchg %rax, %rax is a nop in x86-64 and can be encoded as such. Without this -// we emit an unneeded REX.w prefix. -def : InstAlias<"xchg{q}\t{%rax, %rax|rax, rax}", (NOOP), 0>; - -// These aliases exist to get the parser to prioritize matching 8-bit -// immediate encodings over matching the implicit ax/eax/rax encodings. By -// explicitly mentioning the A register here, these entries will be ordered -// first due to the more explicit immediate type. -def : InstAlias<"adc{w}\t{$imm, %ax|ax, $imm}", (ADC16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"add{w}\t{$imm, %ax|ax, $imm}", (ADD16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"and{w}\t{$imm, %ax|ax, $imm}", (AND16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"cmp{w}\t{$imm, %ax|ax, $imm}", (CMP16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"or{w}\t{$imm, %ax|ax, $imm}", (OR16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"sbb{w}\t{$imm, %ax|ax, $imm}", (SBB16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"sub{w}\t{$imm, %ax|ax, $imm}", (SUB16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"xor{w}\t{$imm, %ax|ax, $imm}", (XOR16ri8 AX, i16i8imm:$imm), 0>; - -def : InstAlias<"adc{l}\t{$imm, %eax|eax, $imm}", (ADC32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"add{l}\t{$imm, %eax|eax, $imm}", (ADD32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"and{l}\t{$imm, %eax|eax, $imm}", (AND32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"cmp{l}\t{$imm, %eax|eax, $imm}", (CMP32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"or{l}\t{$imm, %eax|eax, $imm}", (OR32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"sbb{l}\t{$imm, %eax|eax, $imm}", (SBB32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"sub{l}\t{$imm, %eax|eax, $imm}", (SUB32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"xor{l}\t{$imm, %eax|eax, $imm}", (XOR32ri8 EAX, i32i8imm:$imm), 0>; - -def : InstAlias<"adc{q}\t{$imm, %rax|rax, $imm}", (ADC64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"add{q}\t{$imm, %rax|rax, $imm}", (ADD64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"and{q}\t{$imm, %rax|rax, $imm}", (AND64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"cmp{q}\t{$imm, %rax|rax, $imm}", (CMP64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"or{q}\t{$imm, %rax|rax, $imm}", (OR64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"sbb{q}\t{$imm, %rax|rax, $imm}", (SBB64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"sub{q}\t{$imm, %rax|rax, $imm}", (SUB64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"xor{q}\t{$imm, %rax|rax, $imm}", (XOR64ri8 RAX, i64i8imm:$imm), 0>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrInfo_reduce.td b/suite/synctools/tablegen/X86/back/X86InstrInfo_reduce.td deleted file mode 100644 index 9aa8425b17..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrInfo_reduce.td +++ /dev/null @@ -1,3572 +0,0 @@ -//===-- X86InstrInfo.td - Main X86 Instruction Definition --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instruction set, defining the instructions, and -// properties of the instructions which are needed for code generation, machine -// code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// X86 specific DAG Nodes. -// - -def SDTIntShiftDOp: SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisInt<3>]>; - -def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<1, 2>]>; - -def SDTX86Cmps : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; -//def SDTX86Cmpss : SDTypeProfile<1, 3, [SDTCisVT<0, f32>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; - -def SDTX86Cmov : SDTypeProfile<1, 4, - [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -// Unary and binary operator instructions that set EFLAGS as a side-effect. -def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, - [SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS -def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<4, i32>]>; -// RES1, RES2, FLAGS = op LHS, RHS -def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; -def SDTX86BrCond : SDTypeProfile<0, 3, - [SDTCisVT<0, OtherVT>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86SetCC : SDTypeProfile<1, 2, - [SDTCisVT<0, i8>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; -def SDTX86SetCC_C : SDTypeProfile<1, 2, - [SDTCisInt<0>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; - -def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, - SDTCisVT<2, i8>]>; -def SDTX86caspair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86caspairSaveEbx8 : SDTypeProfile<1, 3, - [SDTCisVT<0, i32>, SDTCisPtrTy<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; -def SDTX86caspairSaveRbx16 : SDTypeProfile<1, 3, - [SDTCisVT<0, i64>, SDTCisPtrTy<1>, - SDTCisVT<2, i64>, SDTCisVT<3, i64>]>; - -def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, - SDTCisInt<2>]>; - -def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>]>; - -def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; - -def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; -def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; - -def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, - SDTCisVT<1, iPTR>, - SDTCisVT<2, iPTR>]>; - -def SDT_X86VAARG_64 : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; - -def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; - -def SDTX86Void : SDTypeProfile<0, 0, []>; - -def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - -def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86WIN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; - -def SDT_X86MEMBARRIER : SDTypeProfile<0, 0, []>; - -def X86MemBarrier : SDNode<"X86ISD::MEMBARRIER", SDT_X86MEMBARRIER, - [SDNPHasChain,SDNPSideEffect]>; -def X86MFence : SDNode<"X86ISD::MFENCE", SDT_X86MEMBARRIER, - [SDNPHasChain]>; - - -def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; -def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; -def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; -def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; - -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; -def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; - -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, - [SDNPHasChain]>; -def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; - -def X86sahf : SDNode<"X86ISD::SAHF", SDTX86sahf>; - -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86caspair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8save_ebx : SDNode<"X86ISD::LCMPXCHG8_SAVE_EBX_DAG", - SDTX86caspairSaveEbx8, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def X86cas16save_rbx : SDNode<"X86ISD::LCMPXCHG16_SAVE_RBX_DAG", - SDTX86caspairSaveRbx16, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, - SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; - -def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue]>; - -def X86vastart_save_xmm_regs : - SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", - SDT_X86VASTART_SAVE_XMM_REGS, - [SDNPHasChain, SDNPVariadic]>; -def X86vaarg64 : - SDNode<"X86ISD::VAARG_64", SDT_X86VAARG_64, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86callseq_start : - SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def X86callseq_end : - SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; -def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, - [SDNPHasChain]>; - -def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; -def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad]>; - -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdtscp : SDNode<"X86ISD::RDTSCP_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; -def X86rdpmc : SDNode<"X86ISD::RDPMC_DAG", SDTX86Void, - [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; - -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; -def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; - -def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", - SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, - SDTCisInt<1>]>>; - -def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, - [SDNPHasChain]>; - -def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", - SDTypeProfile<1, 1, [SDTCisInt<0>, - SDTCisPtrTy<1>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", - SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", - SDTypeProfile<0, 0, []>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; -def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, - [SDNPCommutative]>; -def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; -def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; - -def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>; -def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>; -def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, - [SDNPCommutative]>; - -def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86lock_inc : SDNode<"X86ISD::LINC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_dec : SDNode<"X86ISD::LDEC", SDTLockUnaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; - -def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; - -def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA, - [SDNPHasChain, SDNPOutGlue]>; - -def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, - [SDNPHasChain]>; - -def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86lwpins : SDNode<"X86ISD::LWPINS", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; - -def X86umwait : SDNode<"X86ISD::UMWAIT", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tpause : SDNode<"X86ISD::TPAUSE", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -//===----------------------------------------------------------------------===// -// X86 Operand Definitions. -// - -// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for -// the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; - -// *mem - Operand definitions for the funky X86 addressing mode operands. -// -def X86MemAsmOperand : AsmOperandClass { - let Name = "Mem"; -} -let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { - def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } - def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } - def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } - def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } - def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } - def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } - def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } - def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } - // Gather mem operands - def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } - def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } - def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } - def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } - def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } - - def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } - def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } - def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } - def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } - def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } - def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } - def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } - def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } -} - -def X86AbsMemAsmOperand : AsmOperandClass { - let Name = "AbsMem"; - let SuperClasses = [X86MemAsmOperand]; -} - -class X86MemOperand : Operand { - let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = parserMatchClass; - let OperandType = "OPERAND_MEMORY"; -} - -// Gather mem operands -class X86VMemOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); -} - -def anymem : X86MemOperand<"printanymem">; - -// FIXME: Right now we allow any size during parsing, but we might want to -// restrict to only unsized memory. -def opaquemem : X86MemOperand<"printopaquemem">; - -def i8mem : X86MemOperand<"printi8mem", X86Mem8AsmOperand>; -def i16mem : X86MemOperand<"printi16mem", X86Mem16AsmOperand>; -def i32mem : X86MemOperand<"printi32mem", X86Mem32AsmOperand>; -def i64mem : X86MemOperand<"printi64mem", X86Mem64AsmOperand>; -def i128mem : X86MemOperand<"printi128mem", X86Mem128AsmOperand>; -def i256mem : X86MemOperand<"printi256mem", X86Mem256AsmOperand>; -def i512mem : X86MemOperand<"printi512mem", X86Mem512AsmOperand>; -def f32mem : X86MemOperand<"printf32mem", X86Mem32AsmOperand>; -def f64mem : X86MemOperand<"printf64mem", X86Mem64AsmOperand>; -def f80mem : X86MemOperand<"printf80mem", X86Mem80AsmOperand>; -def f128mem : X86MemOperand<"printf128mem", X86Mem128AsmOperand>; -def f256mem : X86MemOperand<"printf256mem", X86Mem256AsmOperand>; -def f512mem : X86MemOperand<"printf512mem", X86Mem512AsmOperand>; - -def v512mem : X86VMemOperand; - -// Gather mem operands -def vx64mem : X86VMemOperand; -def vx128mem : X86VMemOperand; -def vx256mem : X86VMemOperand; -def vy128mem : X86VMemOperand; -def vy256mem : X86VMemOperand; - -def vx64xmem : X86VMemOperand; -def vx128xmem : X86VMemOperand; -def vx256xmem : X86VMemOperand; -def vy128xmem : X86VMemOperand; -def vy256xmem : X86VMemOperand; -def vy512xmem : X86VMemOperand; -def vz256mem : X86VMemOperand; -def vz512mem : X86VMemOperand; - -// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead -// of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; - -def i8mem_NOREX : Operand { - let PrintMethod = "printi8mem"; - let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, - SEGMENT_REG); - let ParserMatchClass = X86Mem8AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// GPRs available for tailcall. -// It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; - -// Special i32mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i32mem_TC : Operand { - let PrintMethod = "printi32mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, - i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem32AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// Special i64mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i64mem_TC : Operand { - let PrintMethod = "printi64mem"; - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, - ptr_rc_tailcall, i32imm, SEGMENT_REG); - let ParserMatchClass = X86Mem64AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -let OperandType = "OPERAND_PCREL", - ParserMatchClass = X86AbsMemAsmOperand, - PrintMethod = "printPCRelImm" in { -def i32imm_pcrel : Operand; -def i16imm_pcrel : Operand; - -// Branch targets have OtherVT type and print as pc-relative values. -def brtarget : Operand; -def brtarget8 : Operand; - -} - -// Special parser to detect 16-bit mode to select 16-bit displacement. -def X86AbsMem16AsmOperand : AsmOperandClass { - let Name = "AbsMem16"; - let RenderMethod = "addAbsMemOperands"; - let SuperClasses = [X86AbsMemAsmOperand]; -} - -// Branch targets have OtherVT type and print as pc-relative values. -let OperandType = "OPERAND_PCREL", - PrintMethod = "printPCRelImm" in { -let ParserMatchClass = X86AbsMem16AsmOperand in - def brtarget16 : Operand; -let ParserMatchClass = X86AbsMemAsmOperand in - def brtarget32 : Operand; -} - -let RenderMethod = "addSrcIdxOperands" in { - def X86SrcIdx8Operand : AsmOperandClass { - let Name = "SrcIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86SrcIdx16Operand : AsmOperandClass { - let Name = "SrcIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86SrcIdx32Operand : AsmOperandClass { - let Name = "SrcIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86SrcIdx64Operand : AsmOperandClass { - let Name = "SrcIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addSrcIdxOperands" - -let RenderMethod = "addDstIdxOperands" in { - def X86DstIdx8Operand : AsmOperandClass { - let Name = "DstIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86DstIdx16Operand : AsmOperandClass { - let Name = "DstIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86DstIdx32Operand : AsmOperandClass { - let Name = "DstIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86DstIdx64Operand : AsmOperandClass { - let Name = "DstIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addDstIdxOperands" - -let RenderMethod = "addMemOffsOperands" in { - def X86MemOffs16_8AsmOperand : AsmOperandClass { - let Name = "MemOffs16_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs16_16AsmOperand : AsmOperandClass { - let Name = "MemOffs16_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs16_32AsmOperand : AsmOperandClass { - let Name = "MemOffs16_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_8AsmOperand : AsmOperandClass { - let Name = "MemOffs32_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs32_16AsmOperand : AsmOperandClass { - let Name = "MemOffs32_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs32_32AsmOperand : AsmOperandClass { - let Name = "MemOffs32_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_64AsmOperand : AsmOperandClass { - let Name = "MemOffs32_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } - def X86MemOffs64_8AsmOperand : AsmOperandClass { - let Name = "MemOffs64_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs64_16AsmOperand : AsmOperandClass { - let Name = "MemOffs64_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs64_32AsmOperand : AsmOperandClass { - let Name = "MemOffs64_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs64_64AsmOperand : AsmOperandClass { - let Name = "MemOffs64_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addMemOffsOperands" - -class X86SrcIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); -} - -class X86DstIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc); -} - -def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; -def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; -def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; -def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; -def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; -def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; -def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; -def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; - -class X86MemOffsOperand - : X86MemOperand { - let MIOperandInfo = (ops immOperand, SEGMENT_REG); -} - -def offset16_8 : X86MemOffsOperand; -def offset16_16 : X86MemOffsOperand; -def offset16_32 : X86MemOffsOperand; -def offset32_8 : X86MemOffsOperand; -def offset32_16 : X86MemOffsOperand; -def offset32_32 : X86MemOffsOperand; -def offset32_64 : X86MemOffsOperand; -def offset64_8 : X86MemOffsOperand; -def offset64_16 : X86MemOffsOperand; -def offset64_32 : X86MemOffsOperand; -def offset64_64 : X86MemOffsOperand; - -def SSECC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVXCC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def AVX512ICC : Operand { - let PrintMethod = "printSSEAVXCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def XOPCC : Operand { - let PrintMethod = "printXOPCC"; - let OperandType = "OPERAND_IMMEDIATE"; -} - -class ImmSExtAsmOperandClass : AsmOperandClass { - let SuperClasses = [ImmAsmOperand]; - let RenderMethod = "addImmOperands"; -} - -def X86GR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR32orGR64"; -} - -def GR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR32orGR64AsmOperand; -} -def AVX512RCOperand : AsmOperandClass { - let Name = "AVX512RC"; -} -def AVX512RC : Operand { - let PrintMethod = "printRoundingControl"; - let OperandType = "OPERAND_IMMEDIATE"; - let ParserMatchClass = AVX512RCOperand; -} - -// Sign-extended immediate classes. We don't need to define the full lattice -// here because there is no instruction with an ambiguity between ImmSExti64i32 -// and ImmSExti32i8. -// -// The strange ranges come from the fact that the assembler always works with -// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" -// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). - -// [0, 0x7FFFFFFF] | -// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i32"; -} - -// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti16i8"; - let SuperClasses = [ImmSExti64i32AsmOperand]; -} - -// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti32i8"; -} - -// [0, 0x0000007F] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i8"; - let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, - ImmSExti64i32AsmOperand]; -} - -// Unsigned immediate used by SSE/AVX instructions -// [0, 0xFF] -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmUnsignedi8AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi8"; - let RenderMethod = "addImmOperands"; -} - -// A couple of more descriptive operand definitions. -// 16-bits but only 8 bits are significant. -def i16i8imm : Operand { - let ParserMatchClass = ImmSExti16i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} -// 32-bits but only 8 bits are significant. -def i32i8imm : Operand { - let ParserMatchClass = ImmSExti32i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant. -def i64i32imm : Operand { - let ParserMatchClass = ImmSExti64i32AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 8 bits are significant. -def i64i8imm : Operand { - let ParserMatchClass = ImmSExti64i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 8-bit immediate used by SSE/AVX instructions. -def u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 32-bit immediate but only 8-bits are significant and they are unsigned. -// Used by some SSE/AVX instructions that use intrinsics. -def i32u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant, and those bits are treated as being -// pc relative. -def i64i32imm_pcrel : Operand { - let PrintMethod = "printPCRelImm"; - let ParserMatchClass = X86AbsMemAsmOperand; - let OperandType = "OPERAND_PCREL"; -} - -def lea64_32mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -// Memory operands that use 64-bit pointers in both ILP32 and LP64. -def lea64mem : Operand { - let PrintMethod = "printanymem"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - - -//===----------------------------------------------------------------------===// -// X86 Complex Pattern Definitions. -// - -// Define X86-specific addressing mode. -def addr : ComplexPattern; -def lea32addr : ComplexPattern; -// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. -def lea64_32addr : ComplexPattern; - -def tls32addr : ComplexPattern; - -def tls32baseaddr : ComplexPattern; - -def lea64addr : ComplexPattern; - -def tls64addr : ComplexPattern; - -def tls64baseaddr : ComplexPattern; - -def vectoraddr : ComplexPattern; - -// A relocatable immediate is either an immediate operand or an operand that can -// be relocated by the linker to an immediate, such as a regular symbol in -// non-PIC code. -def relocImm : ComplexPattern; - -//===----------------------------------------------------------------------===// -// X86 Instruction Predicate Definitions. -def TruePredicate : Predicate<"true">; - -def HasCMov : Predicate<"Subtarget->hasCMov()">; -def NoCMov : Predicate<"!Subtarget->hasCMov()">; - -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def Has3DNow : Predicate<"Subtarget->has3DNow()">; -def Has3DNowA : Predicate<"Subtarget->has3DNowA()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; -def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; -def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; -def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; -def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; -def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; -def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; -def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; -def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; -def NoAVX : Predicate<"!Subtarget->hasAVX()">; -def HasAVX : Predicate<"Subtarget->hasAVX()">; -def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; -def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; -def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; -def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; -def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; -def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; -def HasCDI : Predicate<"Subtarget->hasCDI()">; -def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; -def HasPFI : Predicate<"Subtarget->hasPFI()">; -def HasERI : Predicate<"Subtarget->hasERI()">; -def HasDQI : Predicate<"Subtarget->hasDQI()">; -def NoDQI : Predicate<"!Subtarget->hasDQI()">; -def HasBWI : Predicate<"Subtarget->hasBWI()">; -def NoBWI : Predicate<"!Subtarget->hasBWI()">; -def HasVLX : Predicate<"Subtarget->hasVLX()">; -def NoVLX : Predicate<"!Subtarget->hasVLX()">; -def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; -def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; -def PKU : Predicate<"Subtarget->hasPKU()">; -def HasVNNI : Predicate<"Subtarget->hasVNNI()">; - -def HasBITALG : Predicate<"Subtarget->hasBITALG()">; -def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; -def HasAES : Predicate<"Subtarget->hasAES()">; -def HasVAES : Predicate<"Subtarget->hasVAES()">; -def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; -def HasFXSR : Predicate<"Subtarget->hasFXSR()">; -def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; -def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; -def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; -def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; -def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; -def NoVLX_Or_NoVPCLMULQDQ : - Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; -def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; -def HasGFNI : Predicate<"Subtarget->hasGFNI()">; -def HasFMA : Predicate<"Subtarget->hasFMA()">; -def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; -def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; -def HasXOP : Predicate<"Subtarget->hasXOP()">; -def HasTBM : Predicate<"Subtarget->hasTBM()">; -def NoTBM : Predicate<"!Subtarget->hasTBM()">; -def HasLWP : Predicate<"Subtarget->hasLWP()">; -def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; -def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; -def HasF16C : Predicate<"Subtarget->hasF16C()">; -def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; -def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; -def HasBMI : Predicate<"Subtarget->hasBMI()">; -def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; -def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; -def HasVBMI : Predicate<"Subtarget->hasVBMI()">; -def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; -def HasIFMA : Predicate<"Subtarget->hasIFMA()">; -def HasRTM : Predicate<"Subtarget->hasRTM()">; -def HasADX : Predicate<"Subtarget->hasADX()">; -def HasSHA : Predicate<"Subtarget->hasSHA()">; -def HasSGX : Predicate<"Subtarget->hasSGX()">; -def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; -def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; -def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; -def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; -def HasPrefetchW : Predicate<"Subtarget->hasPRFCHW()">; -def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; -def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; -def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; -def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; -def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; -def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; -def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; -def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; -def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; -def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; -def HasMPX : Predicate<"Subtarget->hasMPX()">; -def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; -def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; -def HasCLWB : Predicate<"Subtarget->hasCLWB()">; -def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; -def HasRDPID : Predicate<"Subtarget->hasRDPID()">; -def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; -def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; -def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; -def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; -def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, - AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, - AssemblerPredicate<"Mode64Bit", "64-bit mode">; -def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; -def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; -def In16BitMode : Predicate<"Subtarget->is16Bit()">, - AssemblerPredicate<"Mode16Bit", "16-bit mode">; -def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, - AssemblerPredicate<"!Mode16Bit", "Not 16-bit mode">; -def In32BitMode : Predicate<"Subtarget->is32Bit()">, - AssemblerPredicate<"Mode32Bit", "32-bit mode">; -def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; -def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; -def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" - "Subtarget->getFrameLowering()->hasFP(*MF)"> { - let RecomputePerFunction = 1; -} -def IsPS4 : Predicate<"Subtarget->isTargetPS4()">; -def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">; -def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; -def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; -def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; -def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" - "TM.getCodeModel() == CodeModel::Kernel">; -def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; - -// We could compute these on a per-module basis but doing so requires accessing -// the Function object through the Subtarget and objections were raised -// to that (see post-commit review comments for r301750). -let RecomputePerFunction = 1 in { - def OptForSize : Predicate<"MF->getFunction().optForSize()">; - def OptForMinSize : Predicate<"MF->getFunction().optForMinSize()">; - def OptForSpeed : Predicate<"!MF->getFunction().optForSize()">; - def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " - "MF->getFunction().optForSize()">; - def NoSSE41_Or_OptForSize : Predicate<"MF->getFunction().optForSize() || " - "!Subtarget->hasSSE41()">; -} - -def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; -def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; -def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; -def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; -def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; -def HasERMSB : Predicate<"Subtarget->hasERMSB()">; -def HasMFence : Predicate<"Subtarget->hasMFence()">; -def UseRetpoline : Predicate<"Subtarget->useRetpoline()">; -def NotUseRetpoline : Predicate<"!Subtarget->useRetpoline()">; - -//===----------------------------------------------------------------------===// -// X86 Instruction Format Definitions. -// - -include "X86InstrFormats.td" - -//===----------------------------------------------------------------------===// -// Pattern fragments. -// - -// X86 specific condition code. These correspond to CondCode in -// X86InstrInfo.h. They must be kept in synch. -def X86_COND_A : PatLeaf<(i8 0)>; // alt. COND_NBE -def X86_COND_AE : PatLeaf<(i8 1)>; // alt. COND_NC -def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C -def X86_COND_BE : PatLeaf<(i8 3)>; // alt. COND_NA -def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z -def X86_COND_G : PatLeaf<(i8 5)>; // alt. COND_NLE -def X86_COND_GE : PatLeaf<(i8 6)>; // alt. COND_NL -def X86_COND_L : PatLeaf<(i8 7)>; // alt. COND_NGE -def X86_COND_LE : PatLeaf<(i8 8)>; // alt. COND_NG -def X86_COND_NE : PatLeaf<(i8 9)>; // alt. COND_NZ -def X86_COND_NO : PatLeaf<(i8 10)>; -def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO -def X86_COND_NS : PatLeaf<(i8 12)>; -def X86_COND_O : PatLeaf<(i8 13)>; -def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE -def X86_COND_S : PatLeaf<(i8 15)>; - -def i16immSExt8 : ImmLeaf(Imm); }]>; -def i32immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt32 : ImmLeaf(Imm); }]>; - -// FIXME: Ideally we would just replace the above i*immSExt* matchers with -// relocImm-based matchers, but then FastISel would be unable to use them. -def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<8>(N); -}]>; -def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ - return isSExtRelocImm<32>(N); -}]>; - -// If we have multiple users of an immediate, it's much smaller to reuse -// the register, rather than encode the immediate in every instruction. -// This has the risk of increasing register pressure from stretched live -// ranges, however, the immediates should be trivial to rematerialize by -// the RA in the event of high register pressure. -// TODO : This is currently enabled for stores and binary ops. There are more -// cases for which this can be enabled, though this catches the bulk of the -// issues. -// TODO2 : This should really also be enabled under O2, but there's currently -// an issue with RA where we don't pull the constants into their users -// when we rematerialize them. I'll follow-up on enabling O2 after we fix that -// issue. -// TODO3 : This is currently limited to single basic blocks (DAG creation -// pulls block immediates to the top and merges them if necessary). -// Eventually, it would be nice to allow ConstantHoisting to merge constants -// globally for potentially added savings. -// -def imm8_su : PatLeaf<(i8 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm16_su : PatLeaf<(i16 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def imm32_su : PatLeaf<(i32 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit -// unsigned field. -def i64immZExt32 : ImmLeaf(Imm); }]>; - -def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); -}]>; - -// Helper fragments for loads. - -// It's safe to fold a zextload/extload from i1 as a regular i8 load. The -// upper bits are guaranteed to be zero and we were going to emit a MOV8rm -// which might get folded during peephole anyway. -def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || - ExtType == ISD::ZEXTLOAD; -}]>; - -// It's always safe to treat a anyext i16 load as a i32 load if the i16 is -// known to be 32-bit aligned or better. Ditto for i8 to i16. -def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 2 && !LD->isVolatile(); - return false; -}]>; - -def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 4 && !LD->isVolatile(); - return false; -}]>; - -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; -def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; -def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; -def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; -def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; -def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; -def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; -def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; -def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; - -def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; -def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; -def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; -def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; -def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; -def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; -def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; -def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; -def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; -def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; - -def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; -def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; -def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; -def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; -def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>; - - -// An 'and' node with a single use. -def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'srl' node with a single use. -def srl_su : PatFrag<(ops node:$lhs, node:$rhs), (srl node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; -// An 'trunc' node with a single use. -def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ - return N->hasOneUse(); -}]>; - -//===----------------------------------------------------------------------===// -// Instruction list. -// - -// Nop -let hasSideEffects = 0, SchedRW = [WriteNop] in { - def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; - def NOOPW : I<0x1f, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPL : I<0x1f, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQ : RI<0x1f, MRMXm, (outs), (ins i64mem:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - // Also allow register so we can assemble/disassemble - def NOOPWr : I<0x1f, MRMXr, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16, NotMemoryFoldable; - def NOOPLr : I<0x1f, MRMXr, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32, NotMemoryFoldable; - def NOOPQr : RI<0x1f, MRMXr, (outs), (ins GR64:$zero), - "nop{q}\t$zero", []>, TB, NotMemoryFoldable, - Requires<[In64BitMode]>; - def NOOPW_19 : I<0x19, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_19 : I<0x19, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1a : I<0x1a, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1a : I<0x1a, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - //def NOOPW_1b : I<0x1b, MRMXm, (outs), (ins i16mem:$zero), - // "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1b : I<0x1b, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1c : I<0x1c, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - //def NOOPL_1c : I<0x1c, MRMXm, (outs), (ins i32mem:$zero), - // "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1d : I<0x1d, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1d : I<0x1d, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - def NOOPW_1e : I<0x1e, MRMXm, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOPL_1e : I<0x1e, MRMXm, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m4 : I<0x18, MRM4m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m4 : I<0x18, MRM4m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r4 : I<0x18, MRM4r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r4 : I<0x18, MRM4r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m5 : I<0x18, MRM5m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m5 : I<0x18, MRM5m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r5 : I<0x18, MRM5r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r5 : I<0x18, MRM5r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m6 : I<0x18, MRM6m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m6 : I<0x18, MRM6m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r6 : I<0x18, MRM6r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r6 : I<0x18, MRM6r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16m7 : I<0x18, MRM7m, (outs), (ins i16mem:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_m7 : I<0x18, MRM7m, (outs), (ins i32mem:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; - - def NOOP18_16r7 : I<0x18, MRM7r, (outs), (ins GR16:$zero), - "nop{w}\t$zero", []>, TB, OpSize16; - def NOOP18_r7 : I<0x18, MRM7r, (outs), (ins GR32:$zero), - "nop{l}\t$zero", []>, TB, OpSize32; -} - - -// Constructing a stack frame. -def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl), - "enter\t$len, $lvl", []>, Sched<[WriteMicrocoded]>; - -let SchedRW = [WriteALU] in { -let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, hasSideEffects=0 in -def LEAVE : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[Not64BitMode]>; - -let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, hasSideEffects = 0 in -def LEAVE64 : I<0xC9, RawFrm, (outs), (ins), "leave", []>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Miscellaneous Instructions. -// - -let isBarrier = 1, hasSideEffects = 1, usesCustomInserter = 1, - SchedRW = [WriteSystem] in - def Int_eh_sjlj_setup_dispatch - : PseudoI<(outs), (ins), [(X86eh_sjlj_setup_dispatch)]>; - -let Defs = [ESP], Uses = [ESP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP16r : I<0x58, AddRegFrm, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16; -def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP16rmr: I<0x8F, MRM0r, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, - OpSize16, NotMemoryFoldable; -def POP32rmr: I<0x8F, MRM0r, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayStore = 1, mayLoad = 1, SchedRW = [WriteRMW] in { -def POP16rmm: I<0x8F, MRM0m, (outs), (ins i16mem:$dst), "pop{w}\t$dst", []>, - OpSize16; -def POP32rmm: I<0x8F, MRM0m, (outs), (ins i32mem:$dst), "pop{l}\t$dst", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayStore, mayLoad, WriteRMW - -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH16r : I<0x50, AddRegFrm, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16; -def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH16rmr: I<0xFF, MRM6r, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, - OpSize16, NotMemoryFoldable; -def PUSH32rmr: I<0xFF, MRM6r, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>, - OpSize32, Requires<[Not64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 - -def PUSH16i8 : Ii8<0x6a, RawFrm, (outs), (ins i16i8imm:$imm), - "push{w}\t$imm", []>, OpSize16; -def PUSHi16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), - "push{w}\t$imm", []>, OpSize16; - -def PUSH32i8 : Ii8<0x6a, RawFrm, (outs), (ins i32i8imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -def PUSHi32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), - "push{l}\t$imm", []>, OpSize32, - Requires<[Not64BitMode]>; -} // mayStore, SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH16rmm: I<0xFF, MRM6m, (outs), (ins i16mem:$src), "push{w}\t$src", []>, - OpSize16; -def PUSH32rmm: I<0xFF, MRM6m, (outs), (ins i32mem:$src), "push{l}\t$src", []>, - OpSize32, Requires<[Not64BitMode]>; -} // mayLoad, mayStore, SchedRW - -} - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW], Defs = [ESP] in { - let Uses = [ESP] in - def RDFLAGS32 : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_flags_read_u32))]>, - Requires<[Not64BitMode]>; - - let Uses = [RSP] in - def RDFLAGS64 : PseudoI<(outs GR64:$dst), (ins), - [(set GR64:$dst, (int_x86_flags_read_u64))]>, - Requires<[In64BitMode]>; -} - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1, - SchedRW = [WriteRMW] in { - let Defs = [ESP, EFLAGS, DF], Uses = [ESP] in - def WRFLAGS32 : PseudoI<(outs), (ins GR32:$src), - [(int_x86_flags_write_u32 GR32:$src)]>, - Requires<[Not64BitMode]>; - - let Defs = [RSP, EFLAGS, DF], Uses = [RSP] in - def WRFLAGS64 : PseudoI<(outs), (ins GR64:$src), - [(int_x86_flags_write_u64 GR64:$src)]>, - Requires<[In64BitMode]>; -} - -let Defs = [ESP, EFLAGS, DF], Uses = [ESP], mayLoad = 1, hasSideEffects=0, - SchedRW = [WriteLoad] in { -def POPF16 : I<0x9D, RawFrm, (outs), (ins), "popf{w}", []>, OpSize16; -def POPF32 : I<0x9D, RawFrm, (outs), (ins), "popf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [ESP], Uses = [ESP, EFLAGS, DF], mayStore = 1, hasSideEffects=0, - SchedRW = [WriteStore] in { -def PUSHF16 : I<0x9C, RawFrm, (outs), (ins), "pushf{w}", []>, OpSize16; -def PUSHF32 : I<0x9C, RawFrm, (outs), (ins), "pushf{l|d}", []>, OpSize32, - Requires<[Not64BitMode]>; -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects=0 in { -let mayLoad = 1, SchedRW = [WriteLoad] in { -def POP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayLoad, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in -def POP64rmm: I<0x8F, MRM0m, (outs), (ins i64mem:$dst), "pop{q}\t$dst", []>, - OpSize32, Requires<[In64BitMode]>; -let mayStore = 1, SchedRW = [WriteStore] in { -def PUSH64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>; -// Long form for the disassembler. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>, - OpSize32, Requires<[In64BitMode]>, NotMemoryFoldable; -} // isCodeGenOnly = 1, ForceDisassemble = 1 -} // mayStore, SchedRW -let mayLoad = 1, mayStore = 1, SchedRW = [WriteRMW] in { -def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>, - OpSize32, Requires<[In64BitMode]>; -} // mayLoad, mayStore, SchedRW -} - -let Defs = [RSP], Uses = [RSP], hasSideEffects = 0, mayStore = 1, - SchedRW = [WriteStore] in { -def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -def PUSH64i32 : Ii32S<0x68, RawFrm, (outs), (ins i64i32imm:$imm), - "push{q}\t$imm", []>, OpSize32, - Requires<[In64BitMode]>; -} - -let Defs = [RSP, EFLAGS, DF], Uses = [RSP], mayLoad = 1, hasSideEffects=0 in -def POPF64 : I<0x9D, RawFrm, (outs), (ins), "popfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteLoad]>; -let Defs = [RSP], Uses = [RSP, EFLAGS, DF], mayStore = 1, hasSideEffects=0 in -def PUSHF64 : I<0x9C, RawFrm, (outs), (ins), "pushfq", []>, - OpSize32, Requires<[In64BitMode]>, Sched<[WriteStore]>; - -let Defs = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], Uses = [ESP], - mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteLoad] in { -def POPA32 : I<0x61, RawFrm, (outs), (ins), "popal", []>, - OpSize32, Requires<[Not64BitMode]>; -def POPA16 : I<0x61, RawFrm, (outs), (ins), "popaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} -let Defs = [ESP], Uses = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], - mayStore = 1, hasSideEffects = 0, SchedRW = [WriteStore] in { -def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pushal", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHA16 : I<0x60, RawFrm, (outs), (ins), "pushaw", []>, - OpSize16, Requires<[Not64BitMode]>; -} - -let Constraints = "$src = $dst", SchedRW = [WriteBSWAP32] in { -// This instruction is a consequence of BSWAP32r observing operand size. The -// encoding is valid, but the behavior is undefined. -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in -def BSWAP16r_BAD : I<0xC8, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "bswap{w}\t$dst", []>, OpSize16, TB; -// GR32 = bswap GR32 -def BSWAP32r : I<0xC8, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "bswap{l}\t$dst", - [(set GR32:$dst, (bswap GR32:$src))]>, OpSize32, TB; - -let SchedRW = [WriteBSWAP64] in -def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "bswap{q}\t$dst", - [(set GR64:$dst, (bswap GR64:$src))]>, TB; -} // Constraints = "$src = $dst", SchedRW - -// Bit scan instructions. -let Defs = [EFLAGS] in { -def BSF16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSF]>; -def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsf{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsf (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSFLd]>; -def BSF32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSF]>; -def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsf{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsf (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSFLd]>; -def BSF64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf GR64:$src))]>, - PS, Sched<[WriteBSF]>; -def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsf{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsf (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSFLd]>; - -def BSR16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr GR16:$src))]>, - PS, OpSize16, Sched<[WriteBSR]>; -def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "bsr{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, EFLAGS, (X86bsr (loadi16 addr:$src)))]>, - PS, OpSize16, Sched<[WriteBSRLd]>; -def BSR32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr GR32:$src))]>, - PS, OpSize32, Sched<[WriteBSR]>; -def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "bsr{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, EFLAGS, (X86bsr (loadi32 addr:$src)))]>, - PS, OpSize32, Sched<[WriteBSRLd]>; -def BSR64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr GR64:$src))]>, - PS, Sched<[WriteBSR]>; -def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "bsr{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, EFLAGS, (X86bsr (loadi64 addr:$src)))]>, - PS, Sched<[WriteBSRLd]>; -} // Defs = [EFLAGS] - -let SchedRW = [WriteMicrocoded] in { -let Defs = [EDI,ESI], Uses = [EDI,ESI,DF] in { -def MOVSB : I<0xA4, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "movsb\t{$src, $dst|$dst, $src}", []>; -def MOVSW : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "movsw\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOVSL : I<0xA5, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "movs{l|d}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOVSQ : RI<0xA5, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "movsq\t{$src, $dst|$dst, $src}", []>, - Requires<[In64BitMode]>; -} - -let Defs = [EDI], Uses = [AL,EDI,DF] in -def STOSB : I<0xAA, RawFrmDst, (outs), (ins dstidx8:$dst), - "stosb\t{%al, $dst|$dst, al}", []>; -let Defs = [EDI], Uses = [AX,EDI,DF] in -def STOSW : I<0xAB, RawFrmDst, (outs), (ins dstidx16:$dst), - "stosw\t{%ax, $dst|$dst, ax}", []>, OpSize16; -let Defs = [EDI], Uses = [EAX,EDI,DF] in -def STOSL : I<0xAB, RawFrmDst, (outs), (ins dstidx32:$dst), - "stos{l|d}\t{%eax, $dst|$dst, eax}", []>, OpSize32; -let Defs = [RDI], Uses = [RAX,RDI,DF] in -def STOSQ : RI<0xAB, RawFrmDst, (outs), (ins dstidx64:$dst), - "stosq\t{%rax, $dst|$dst, rax}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,EFLAGS], Uses = [AL,EDI,DF] in -def SCASB : I<0xAE, RawFrmDst, (outs), (ins dstidx8:$dst), - "scasb\t{$dst, %al|al, $dst}", []>; -let Defs = [EDI,EFLAGS], Uses = [AX,EDI,DF] in -def SCASW : I<0xAF, RawFrmDst, (outs), (ins dstidx16:$dst), - "scasw\t{$dst, %ax|ax, $dst}", []>, OpSize16; -let Defs = [EDI,EFLAGS], Uses = [EAX,EDI,DF] in -def SCASL : I<0xAF, RawFrmDst, (outs), (ins dstidx32:$dst), - "scas{l|d}\t{$dst, %eax|eax, $dst}", []>, OpSize32; -let Defs = [EDI,EFLAGS], Uses = [RAX,EDI,DF] in -def SCASQ : RI<0xAF, RawFrmDst, (outs), (ins dstidx64:$dst), - "scasq\t{$dst, %rax|rax, $dst}", []>, - Requires<[In64BitMode]>; - -let Defs = [EDI,ESI,EFLAGS], Uses = [EDI,ESI,DF] in { -def CMPSB : I<0xA6, RawFrmDstSrc, (outs), (ins dstidx8:$dst, srcidx8:$src), - "cmpsb\t{$dst, $src|$src, $dst}", []>; -def CMPSW : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx16:$dst, srcidx16:$src), - "cmpsw\t{$dst, $src|$src, $dst}", []>, OpSize16; -def CMPSL : I<0xA7, RawFrmDstSrc, (outs), (ins dstidx32:$dst, srcidx32:$src), - "cmps{l|d}\t{$dst, $src|$src, $dst}", []>, OpSize32; -def CMPSQ : RI<0xA7, RawFrmDstSrc, (outs), (ins dstidx64:$dst, srcidx64:$src), - "cmpsq\t{$dst, $src|$src, $dst}", []>, - Requires<[In64BitMode]>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Move Instructions. -// -let SchedRW = [WriteMove] in { -let hasSideEffects = 0, isMoveReg = 1 in { -def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>; -def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -} - -let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, imm:$src)]>, OpSize16; -def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, relocImm:$src)]>, OpSize32; -def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, i64immSExt32:$src)]>; -} -let isReMaterializable = 1 in { -def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), - "movabs{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, relocImm:$src)]>; -} - -// Longer forms that use a ModR/M byte. Needed for disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOV8ri_alt : Ii8 <0xC6, MRM0r, (outs GR8 :$dst), (ins i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8ri">; -def MOV16ri_alt : Ii16<0xC7, MRM0r, (outs GR16:$dst), (ins i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16ri">; -def MOV32ri_alt : Ii32<0xC7, MRM0r, (outs GR32:$dst), (ins i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32ri">; -} -} // SchedRW - -let SchedRW = [WriteStore] in { -def MOV8mi : Ii8 <0xC6, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store (i8 imm8_su:$src), addr:$dst)]>; -def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store (i16 imm16_su:$src), addr:$dst)]>, OpSize16; -def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store (i32 imm32_su:$src), addr:$dst)]>, OpSize32; -def MOV64mi32 : RIi32S<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store i64immSExt32_su:$src, addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { - -/// Memory offset versions of moves. The immediate is an address mode sized -/// offset from the segment base. -let SchedRW = [WriteALU] in { -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao32 : Ii32<0xA0, RawFrmMemOffs, (outs), (ins offset32_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, - AdSize32; -let Defs = [AX] in -def MOV16ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize32; -let Defs = [EAX] in -def MOV32ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize32; -let Defs = [RAX] in -def MOV64ao32 : RIi32<0xA1, RawFrmMemOffs, (outs), (ins offset32_64:$src), - "mov{q}\t{$src, %rax|rax, $src}", []>, - AdSize32; - -let Defs = [AL] in -def MOV8ao16 : Ii16<0xA0, RawFrmMemOffs, (outs), (ins offset16_8:$src), - "mov{b}\t{$src, %al|al, $src}", []>, AdSize16; -let Defs = [AX] in -def MOV16ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_16:$src), - "mov{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize16; -let Defs = [EAX] in -def MOV32ao16 : Ii16<0xA1, RawFrmMemOffs, (outs), (ins offset16_32:$src), - "mov{l}\t{$src, %eax|eax, $src}", []>, - AdSize16, OpSize32; -} // mayLoad -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o32a : Ii32<0xA2, RawFrmMemOffs, (outs), (ins offset32_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize32; -let Uses = [AX] in -def MOV16o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize32; -let Uses = [EAX] in -def MOV32o32a : Ii32<0xA3, RawFrmMemOffs, (outs), (ins offset32_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize32; -let Uses = [RAX] in -def MOV64o32a : RIi32<0xA3, RawFrmMemOffs, (outs), (ins offset32_64:$dst), - "mov{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize32; - -let Uses = [AL] in -def MOV8o16a : Ii16<0xA2, RawFrmMemOffs, (outs), (ins offset16_8:$dst), - "mov{b}\t{%al, $dst|$dst, al}", []>, AdSize16; -let Uses = [AX] in -def MOV16o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_16:$dst), - "mov{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize16; -let Uses = [EAX] in -def MOV32o16a : Ii16<0xA3, RawFrmMemOffs, (outs), (ins offset16_32:$dst), - "mov{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize16; -} // mayStore - -// These forms all have full 64-bit absolute addresses in their instructions -// and use the movabs mnemonic to indicate this specific form. -let mayLoad = 1 in { -let Defs = [AL] in -def MOV8ao64 : Ii64<0xA0, RawFrmMemOffs, (outs), (ins offset64_8:$src), - "movabs{b}\t{$src, %al|al, $src}", []>, - AdSize64; -let Defs = [AX] in -def MOV16ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_16:$src), - "movabs{w}\t{$src, %ax|ax, $src}", []>, - OpSize16, AdSize64; -let Defs = [EAX] in -def MOV32ao64 : Ii64<0xA1, RawFrmMemOffs, (outs), (ins offset64_32:$src), - "movabs{l}\t{$src, %eax|eax, $src}", []>, - OpSize32, AdSize64; -let Defs = [RAX] in -def MOV64ao64 : RIi64<0xA1, RawFrmMemOffs, (outs), (ins offset64_64:$src), - "movabs{q}\t{$src, %rax|rax, $src}", []>, - AdSize64; -} // mayLoad - -let mayStore = 1 in { -let Uses = [AL] in -def MOV8o64a : Ii64<0xA2, RawFrmMemOffs, (outs), (ins offset64_8:$dst), - "movabs{b}\t{%al, $dst|$dst, al}", []>, - AdSize64; -let Uses = [AX] in -def MOV16o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_16:$dst), - "movabs{w}\t{%ax, $dst|$dst, ax}", []>, - OpSize16, AdSize64; -let Uses = [EAX] in -def MOV32o64a : Ii64<0xA3, RawFrmMemOffs, (outs), (ins offset64_32:$dst), - "movabs{l}\t{%eax, $dst|$dst, eax}", []>, - OpSize32, AdSize64; -let Uses = [RAX] in -def MOV64o64a : RIi64<0xA3, RawFrmMemOffs, (outs), (ins offset64_64:$dst), - "movabs{q}\t{%rax, $dst|$dst, rax}", []>, - AdSize64; -} // mayStore -} // SchedRW -} // hasSideEffects = 0 - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [WriteMove], isMoveReg = 1 in { -def MOV8rr_REV : I<0x8A, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV8rr">; -def MOV16rr_REV : I<0x8B, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - FoldGenData<"MOV16rr">; -def MOV32rr_REV : I<0x8B, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - FoldGenData<"MOV32rr">; -def MOV64rr_REV : RI<0x8B, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOV64rr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -//def : InstAlias<"mov{b}.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0>; -//def : InstAlias<"mov{w}.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0>; -//def : InstAlias<"mov{l}.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0>; -//def : InstAlias<"mov{q}.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0>; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV8rr_REV GR8:$dst, GR8:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV16rr_REV GR16:$dst, GR16:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV32rr_REV GR32:$dst, GR32:$src), 0, "att">; -//def : InstAlias<"mov.s\t{$src, $dst|$dst, $src}", -// (MOV64rr_REV GR64:$dst, GR64:$src), 0, "att">; - -let canFoldAsLoad = 1, isReMaterializable = 1, SchedRW = [WriteLoad] in { -def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(set GR8:$dst, (loadi8 addr:$src))]>; -def MOV16rm : I<0x8B, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (loadi16 addr:$src))]>, OpSize16; -def MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (loadi32 addr:$src))]>, OpSize32; -def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (load addr:$src))]>; -} - -let SchedRW = [WriteStore] in { -def MOV8mr : I<0x88, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src), - "mov{b}\t{$src, $dst|$dst, $src}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", - [(store GR16:$src, addr:$dst)]>, OpSize16; -def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", - [(store GR32:$src, addr:$dst)]>, OpSize32; -def MOV64mr : RI<0x89, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", - [(store GR64:$src, addr:$dst)]>; -} // SchedRW - -// Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so -// that they can be used for copying and storing h registers, which can't be -// encoded when a REX prefix is present. -let isCodeGenOnly = 1 in { -let hasSideEffects = 0, isMoveReg = 1 in -def MOV8rr_NOREX : I<0x88, MRMDestReg, - (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteMove]>; -let mayStore = 1, hasSideEffects = 0 in -def MOV8mr_NOREX : I<0x88, MRMDestMem, - (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteStore]>; -let mayLoad = 1, hasSideEffects = 0, - canFoldAsLoad = 1, isReMaterializable = 1 in -def MOV8rm_NOREX : I<0x8A, MRMSrcMem, - (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), - "mov{b}\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteLoad]>; -} - - -// Condition code ops, incl. set if equal/not equal/... -let SchedRW = [WriteLAHFSAHF] in { -let Defs = [EFLAGS], Uses = [AH] in -def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", - [(set EFLAGS, (X86sahf AH))]>, - Requires<[HasLAHFSAHF]>; -let Defs = [AH], Uses = [EFLAGS], hasSideEffects = 0 in -def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>, // AH = flags - Requires<[HasLAHFSAHF]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Bit tests instructions: BT, BTS, BTR, BTC. - -let Defs = [EFLAGS] in { -let SchedRW = [WriteBitTest] in { -def BT16rr : I<0xA3, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, GR16:$src2))]>, - OpSize16, TB, NotMemoryFoldable; -def BT32rr : I<0xA3, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, GR32:$src2))]>, - OpSize32, TB, NotMemoryFoldable; -def BT64rr : RI<0xA3, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, GR64:$src2))]>, TB, - NotMemoryFoldable; -} // SchedRW - -// Unlike with the register+register form, the memory+register form of the -// bt instruction does not ignore the high bits of the index. From ISel's -// perspective, this is pretty bizarre. Make these instructions disassembly -// only for now. These instructions are also slow on modern CPUs so that's -// another reason to avoid generating them. - -let mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteALULd] in { - def BT16mr : I<0xA3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - []>, OpSize16, TB, NotMemoryFoldable; - def BT32mr : I<0xA3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - []>, OpSize32, TB, NotMemoryFoldable; - def BT64mr : RI<0xA3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - []>, TB, NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest] in { -def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR16:$src1, i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR32:$src1, i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt GR64:$src1, i64immSExt8:$src2))]>, TB; -} // SchedRW - -// Note that these instructions aren't slow because that only applies when the -// other operand is in a register. When it's an immediate, bt is still fast. -let SchedRW = [WriteALU] in { -def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bt{w}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi16 addr:$src1), - i16immSExt8:$src2))]>, - OpSize16, TB; -def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bt{l}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi32 addr:$src1), - i32immSExt8:$src2))]>, - OpSize32, TB; -def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bt{q}\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86bt (loadi64 addr:$src1), - i64immSExt8:$src2))]>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -let hasSideEffects = 0 in { -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16rr : I<0xBB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32rr : I<0xBB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64rr : RI<0xBB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mr : I<0xBB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTC32mr : I<0xBB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTC64mr : RI<0xBB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16rr : I<0xB3, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32rr : I<0xB3, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64rr : RI<0xB3, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mr : I<0xB3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTR32mr : I<0xB3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTR64mr : RI<0xB3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "btr{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB; -def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "btr{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB; -def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16rr : I<0xAB, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32rr : I<0xAB, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64rr : RI<0xAB, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mr : I<0xAB, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, - OpSize16, TB, NotMemoryFoldable; -def BTS32mr : I<0xAB, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, - OpSize32, TB, NotMemoryFoldable; -def BTS64mr : RI<0xAB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - NotMemoryFoldable; -} - -let SchedRW = [WriteBitTest], Constraints = "$src1 = $dst" in { -def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, SchedRW = [WriteALULd, WriteRMW] in { -def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16i8imm:$src2), - "bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB; -def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32i8imm:$src2), - "bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB; -def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64i8imm:$src2), - "bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB, - Requires<[In64BitMode]>; -} -} // hasSideEffects = 0 -} // Defs = [EFLAGS] - - -//===----------------------------------------------------------------------===// -// Atomic support -// - -// Atomic swap. These are just normal xchg instructions. But since a memory -// operand is referenced, the atomicity is ensured. -multiclass ATOMIC_SWAP opc8, bits<8> opc, string mnemonic, string frag> { - let Constraints = "$val = $dst", SchedRW = [WriteALULd, WriteRMW] in { - def NAME#8rm : I(frag # "_8") addr:$ptr, GR8:$val))]>; - def NAME#16rm : I(frag # "_16") addr:$ptr, GR16:$val))]>, - OpSize16; - def NAME#32rm : I(frag # "_32") addr:$ptr, GR32:$val))]>, - OpSize32; - def NAME#64rm : RI(frag # "_64") addr:$ptr, GR64:$val))]>; - } -} - -defm XCHG : ATOMIC_SWAP<0x86, 0x87, "xchg", "atomic_swap">, NotMemoryFoldable; - -// Swap between registers. -let SchedRW = [WriteALU] in { -let Constraints = "$src1 = $dst1, $src2 = $dst2", hasSideEffects = 0 in { -def XCHG8rr : I<0x86, MRMSrcReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xchg{b}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -def XCHG16rr : I<0x87, MRMSrcReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xchg{w}\t{$src1, $src2|$src2, $src1}", []>, - OpSize16, NotMemoryFoldable; -def XCHG32rr : I<0x87, MRMSrcReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xchg{l}\t{$src1, $src2|$src2, $src1}", []>, - OpSize32, NotMemoryFoldable; -def XCHG64rr : RI<0x87, MRMSrcReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1 ,GR64:$src2), - "xchg{q}\t{$src1, $src2|$src2, $src1}", []>, NotMemoryFoldable; -} - -def NOOP19rr: I<0x19, MRMSrcReg, (outs), (ins GR32:$val, GR32:$src), - "nop\t{$val, $src|$src, $val}", []>, TB, - OpSize32; - -// Swap between EAX and other registers. -let Constraints = "$src = $dst", hasSideEffects = 0 in { -let Uses = [AX], Defs = [AX] in -def XCHG16ar : I<0x90, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), - "xchg{w}\t{%ax, $src|$src, ax}", []>, OpSize16; -let Uses = [EAX], Defs = [EAX] in -def XCHG32ar : I<0x90, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), - "xchg{l}\t{%eax, $src|$src, eax}", []>, OpSize32; -let Uses = [RAX], Defs = [RAX] in -def XCHG64ar : RI<0x90, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), - "xchg{q}\t{%rax, $src|$src, rax}", []>; -} -} // SchedRW - -let hasSideEffects = 0, Constraints = "$src1 = $dst1, $src2 = $dst2", - Defs = [EFLAGS], SchedRW = [WriteALU] in { -def XADD8rr : I<0xC0, MRMDestReg, (outs GR8:$dst1, GR8:$dst2), - (ins GR8:$src1, GR8:$src2), - "xadd{b}\t{$src2, $src1|$src1, $src2}", []>, TB; -def XADD16rr : I<0xC1, MRMDestReg, (outs GR16:$dst1, GR16:$dst2), - (ins GR16:$src1, GR16:$src2), - "xadd{w}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize16; -def XADD32rr : I<0xC1, MRMDestReg, (outs GR32:$dst1, GR32:$dst2), - (ins GR32:$src1, GR32:$src2), - "xadd{l}\t{$src2, $src1|$src1, $src2}", []>, TB, OpSize32; -def XADD64rr : RI<0xC1, MRMDestReg, (outs GR64:$dst1, GR64:$dst2), - (ins GR64:$src1, GR64:$src2), - "xadd{q}\t{$src2, $src1|$src1, $src2}", []>, TB; -} // SchedRW - -let mayLoad = 1, mayStore = 1, hasSideEffects = 0, Constraints = "$val = $dst", - Defs = [EFLAGS], SchedRW = [WriteALULd, WriteRMW] in { -def XADD8rm : I<0xC0, MRMSrcMem, (outs GR8:$dst), - (ins GR8:$val, i8mem:$ptr), - "xadd{b}\t{$val, $ptr|$ptr, $val}", []>, TB; -def XADD16rm : I<0xC1, MRMSrcMem, (outs GR16:$dst), - (ins GR16:$val, i16mem:$ptr), - "xadd{w}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize16; -def XADD32rm : I<0xC1, MRMSrcMem, (outs GR32:$dst), - (ins GR32:$val, i32mem:$ptr), - "xadd{l}\t{$val, $ptr|$ptr, $val}", []>, TB, - OpSize32; -def XADD64rm : RI<0xC1, MRMSrcMem, (outs GR64:$dst), - (ins GR64:$val, i64mem:$ptr), - "xadd{q}\t{$val, $ptr|$ptr, $val}", []>, TB; - -} - -let SchedRW = [WriteALU], hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rr : I<0xB0, MRMDestReg, (outs GR8:$dst), (ins GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rr : I<0xB1, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rr : I<0xB1, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rr : RI<0xB1, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -} // SchedRW, hasSideEffects - -let SchedRW = [WriteALULd, WriteRMW], mayLoad = 1, mayStore = 1, - hasSideEffects = 0 in { -let Defs = [AL, EFLAGS], Uses = [AL] in -def CMPXCHG8rm : I<0xB0, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src), - "cmpxchg{b}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; -let Defs = [AX, EFLAGS], Uses = [AX] in -def CMPXCHG16rm : I<0xB1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "cmpxchg{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16, - NotMemoryFoldable; -let Defs = [EAX, EFLAGS], Uses = [EAX] in -def CMPXCHG32rm : I<0xB1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "cmpxchg{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32, - NotMemoryFoldable; -let Defs = [RAX, EFLAGS], Uses = [RAX] in -def CMPXCHG64rm : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "cmpxchg{q}\t{$src, $dst|$dst, $src}", []>, TB, - NotMemoryFoldable; - -let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in -def CMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$dst), - "cmpxchg8b\t$dst", []>, TB; - -let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX] in -def CMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$dst), - "cmpxchg16b\t$dst", []>, - TB, Requires<[HasCmpxchg16b, In64BitMode]>; -} // SchedRW, mayLoad, mayStore, hasSideEffects - - -// Lock instruction prefix -let SchedRW = [WriteMicrocoded] in -def LOCK_PREFIX : I<0xF0, RawFrm, (outs), (ins), "lock", []>; - -let SchedRW = [WriteNop] in { - -// Rex64 instruction prefix -def REX64_PREFIX : I<0x48, RawFrm, (outs), (ins), "rex64", []>, - Requires<[In64BitMode]>; - -// Data16 instruction prefix -def DATA16_PREFIX : I<0x66, RawFrm, (outs), (ins), "data16", []>; -} // SchedRW - -// Repeat string operation instruction prefixes -let Defs = [ECX], Uses = [ECX,DF], SchedRW = [WriteMicrocoded] in { -// Repeat (used with INS, OUTS, MOVS, LODS and STOS) -def REP_PREFIX : I<0xF3, RawFrm, (outs), (ins), "rep", []>; -// Repeat while not equal (used with CMPS and SCAS) -def REPNE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "repne", []>; -} - -// String manipulation instructions -let SchedRW = [WriteMicrocoded] in { -let Defs = [AL,ESI], Uses = [ESI,DF] in -def LODSB : I<0xAC, RawFrmSrc, (outs), (ins srcidx8:$src), - "lodsb\t{$src, %al|al, $src}", []>; -let Defs = [AX,ESI], Uses = [ESI,DF] in -def LODSW : I<0xAD, RawFrmSrc, (outs), (ins srcidx16:$src), - "lodsw\t{$src, %ax|ax, $src}", []>, OpSize16; -let Defs = [EAX,ESI], Uses = [ESI,DF] in -def LODSL : I<0xAD, RawFrmSrc, (outs), (ins srcidx32:$src), - "lods{l|d}\t{$src, %eax|eax, $src}", []>, OpSize32; -let Defs = [RAX,ESI], Uses = [ESI,DF] in -def LODSQ : RI<0xAD, RawFrmSrc, (outs), (ins srcidx64:$src), - "lodsq\t{$src, %rax|rax, $src}", []>, - Requires<[In64BitMode]>; -} - -let SchedRW = [WriteSystem] in { -let Defs = [ESI], Uses = [DX,ESI,DF] in { -def OUTSB : I<0x6E, RawFrmSrc, (outs), (ins srcidx8:$src), - "outsb\t{$src, %dx|dx, $src}", []>; -def OUTSW : I<0x6F, RawFrmSrc, (outs), (ins srcidx16:$src), - "outsw\t{$src, %dx|dx, $src}", []>, OpSize16; -def OUTSL : I<0x6F, RawFrmSrc, (outs), (ins srcidx32:$src), - "outs{l|d}\t{$src, %dx|dx, $src}", []>, OpSize32; -} - -let Defs = [EDI], Uses = [DX,EDI,DF] in { -def INSB : I<0x6C, RawFrmDst, (outs), (ins dstidx8:$dst), - "insb\t{%dx, $dst|$dst, dx}", []>; -def INSW : I<0x6D, RawFrmDst, (outs), (ins dstidx16:$dst), - "insw\t{%dx, $dst|$dst, dx}", []>, OpSize16; -def INSL : I<0x6D, RawFrmDst, (outs), (ins dstidx32:$dst), - "ins{l|d}\t{%dx, $dst|$dst, dx}", []>, OpSize32; -} -} - -// EFLAGS management instructions. -let SchedRW = [WriteALU], Defs = [EFLAGS], Uses = [EFLAGS] in { -def CLC : I<0xF8, RawFrm, (outs), (ins), "clc", []>; -def STC : I<0xF9, RawFrm, (outs), (ins), "stc", []>; -def CMC : I<0xF5, RawFrm, (outs), (ins), "cmc", []>; -} - -// DF management instructions. -let SchedRW = [WriteALU], Defs = [DF] in { -def CLD : I<0xFC, RawFrm, (outs), (ins), "cld", []>; -def STD : I<0xFD, RawFrm, (outs), (ins), "std", []>; -} - -// Table lookup instructions -let Uses = [AL,EBX], Defs = [AL], hasSideEffects = 0, mayLoad = 1 in -def XLAT : I<0xD7, RawFrm, (outs), (ins), "xlatb", []>, Sched<[WriteLoad]>; - -let SchedRW = [WriteMicrocoded] in { -// ASCII Adjust After Addition -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAA : I<0x37, RawFrm, (outs), (ins), "aaa", []>, - Requires<[Not64BitMode]>; - -// ASCII Adjust AX Before Division -let Uses = [AX], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAD8i8 : Ii8<0xD5, RawFrm, (outs), (ins i8imm:$src), - "aad\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AX After Multiply -let Uses = [AL], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAM8i8 : Ii8<0xD4, RawFrm, (outs), (ins i8imm:$src), - "aam\t$src", []>, Requires<[Not64BitMode]>; - -// ASCII Adjust AL After Subtraction - sets -let Uses = [AL,EFLAGS], Defs = [AX,EFLAGS], hasSideEffects = 0 in -def AAS : I<0x3F, RawFrm, (outs), (ins), "aas", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Addition -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAA : I<0x27, RawFrm, (outs), (ins), "daa", []>, - Requires<[Not64BitMode]>; - -// Decimal Adjust AL after Subtraction -let Uses = [AL,EFLAGS], Defs = [AL,EFLAGS], hasSideEffects = 0 in -def DAS : I<0x2F, RawFrm, (outs), (ins), "das", []>, - Requires<[Not64BitMode]>; -} // SchedRW - -let SchedRW = [WriteSystem] in { -// Check Array Index Against Bounds -// Note: "bound" does not have reversed operands in at&t syntax. -def BOUNDS16rm : I<0x62, MRMSrcMem, (outs GR16:$dst), (ins i32mem:$src), - "bound\t$dst, $src", []>, OpSize16, - Requires<[Not64BitMode]>; -def BOUNDS32rm : I<0x62, MRMSrcMem, (outs GR32:$dst), (ins i64mem:$src), - "bound\t$dst, $src", []>, OpSize32, - Requires<[Not64BitMode]>; - -// Adjust RPL Field of Segment Selector -def ARPL16rr : I<0x63, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -let mayStore = 1 in -def ARPL16mr : I<0x63, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "arpl\t{$src, $dst|$dst, $src}", []>, - Requires<[Not64BitMode]>, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVBE Instructions -// -let Predicates = [HasMOVBE] in { - let SchedRW = [WriteALULd] in { - def MOVBE16rm : I<0xF0, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (bswap (loadi16 addr:$src)))]>, - OpSize16, T8PS; - def MOVBE32rm : I<0xF0, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bswap (loadi32 addr:$src)))]>, - OpSize32, T8PS; - def MOVBE64rm : RI<0xF0, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bswap (loadi64 addr:$src)))]>, - T8PS; - } - let SchedRW = [WriteStore] in { - def MOVBE16mr : I<0xF1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), - "movbe{w}\t{$src, $dst|$dst, $src}", - [(store (bswap GR16:$src), addr:$dst)]>, - OpSize16, T8PS; - def MOVBE32mr : I<0xF1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movbe{l}\t{$src, $dst|$dst, $src}", - [(store (bswap GR32:$src), addr:$dst)]>, - OpSize32, T8PS; - def MOVBE64mr : RI<0xF1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movbe{q}\t{$src, $dst|$dst, $src}", - [(store (bswap GR64:$src), addr:$dst)]>, - T8PS; - } -} - -//===----------------------------------------------------------------------===// -// RDRAND Instruction -// -let Predicates = [HasRDRAND], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDRAND16r : I<0xC7, MRM6r, (outs GR16:$dst), (ins), - "rdrand{w}\t$dst", [(set GR16:$dst, EFLAGS, (X86rdrand))]>, - OpSize16, PS; - def RDRAND32r : I<0xC7, MRM6r, (outs GR32:$dst), (ins), - "rdrand{l}\t$dst", [(set GR32:$dst, EFLAGS, (X86rdrand))]>, - OpSize32, PS; - def RDRAND64r : RI<0xC7, MRM6r, (outs GR64:$dst), (ins), - "rdrand{q}\t$dst", [(set GR64:$dst, EFLAGS, (X86rdrand))]>, - PS; -} - -//===----------------------------------------------------------------------===// -// RDSEED Instruction -// -let Predicates = [HasRDSEED], Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def RDSEED16r : I<0xC7, MRM7r, (outs GR16:$dst), (ins), "rdseed{w}\t$dst", - [(set GR16:$dst, EFLAGS, (X86rdseed))]>, OpSize16, PS; - def RDSEED32r : I<0xC7, MRM7r, (outs GR32:$dst), (ins), "rdseed{l}\t$dst", - [(set GR32:$dst, EFLAGS, (X86rdseed))]>, OpSize32, PS; - def RDSEED64r : RI<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdseed{q}\t$dst", - [(set GR64:$dst, EFLAGS, (X86rdseed))]>, PS; -} - -//===----------------------------------------------------------------------===// -// LZCNT Instruction -// -let Predicates = [HasLZCNT], Defs = [EFLAGS] in { - def LZCNT16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteLZCNT]>; - def LZCNT16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctlz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteLZCNTLd]>; - - def LZCNT32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteLZCNT]>; - def LZCNT32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "lzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctlz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteLZCNTLd]>; - - def LZCNT64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteLZCNT]>; - def LZCNT64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "lzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctlz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteLZCNTLd]>; -} - -//===----------------------------------------------------------------------===// -// BMI Instructions -// -let Predicates = [HasBMI], Defs = [EFLAGS] in { - def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz GR16:$src)), (implicit EFLAGS)]>, - XS, OpSize16, Sched<[WriteTZCNT]>; - def TZCNT16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "tzcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (cttz (loadi16 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize16, Sched<[WriteTZCNTLd]>; - - def TZCNT32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz GR32:$src)), (implicit EFLAGS)]>, - XS, OpSize32, Sched<[WriteTZCNT]>; - def TZCNT32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "tzcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (cttz (loadi32 addr:$src))), - (implicit EFLAGS)]>, XS, OpSize32, Sched<[WriteTZCNTLd]>; - - def TZCNT64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz GR64:$src)), (implicit EFLAGS)]>, - XS, Sched<[WriteTZCNT]>; - def TZCNT64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "tzcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (cttz (loadi64 addr:$src))), - (implicit EFLAGS)]>, XS, Sched<[WriteTZCNTLd]>; -} - -multiclass bmi_bls { -let hasSideEffects = 0 in { - def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALU]>; - let mayLoad = 1 in - def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src), - !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, - T8PS, VEX_4V, Sched<[WriteALULd]>; -} -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>; - defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W; - defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>; - defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W; - defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>; - defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W; -} - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate BMI instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasBMI] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, -1)), - (BLSR32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, -1)), - (BLSR64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, -1)), - (BLSMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, -1)), - (BLSMSK64rr GR64:$src)>; - - def : Pat<(and GR32:$src, (ineg GR32:$src)), - (BLSI32rr GR32:$src)>; - def : Pat<(and GR64:$src, (ineg GR64:$src)), - (BLSI64rr GR64:$src)>; -} - -multiclass bmi_bextr opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI], Defs = [EFLAGS] in { - defm BEXTR32 : bmi_bextr<0xF7, "bextr{l}", GR32, i32mem, - X86bextr, loadi32, WriteBEXTR>; - defm BEXTR64 : bmi_bextr<0xF7, "bextr{q}", GR64, i64mem, - X86bextr, loadi64, WriteBEXTR>, VEX_W; -} - -multiclass bmi_bzhi opc, string mnemonic, RegisterClass RC, - X86MemOperand x86memop, Intrinsic Int, - PatFrag ld_frag, X86FoldableSchedWrite Sched> { - def rr : I, - T8PS, VEX, Sched<[Sched]>; - def rm : I, T8PS, VEX, - Sched<[Sched.Folded, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} - -let Predicates = [HasBMI2], Defs = [EFLAGS] in { - defm BZHI32 : bmi_bzhi<0xF5, "bzhi{l}", GR32, i32mem, - int_x86_bmi_bzhi_32, loadi32, WriteBZHI>; - defm BZHI64 : bmi_bzhi<0xF5, "bzhi{q}", GR64, i64mem, - int_x86_bmi_bzhi_64, loadi64, WriteBZHI>, VEX_W; -} - -def CountTrailingOnes : SDNodeXFormgetZExtValue()), SDLoc(N)); -}]>; - -def BEXTRMaskXForm : SDNodeXFormgetZExtValue()); - return getI32Imm(Length << 8, SDLoc(N)); -}]>; - -def AndMask64 : ImmLeaf(Imm); -}]>; - -// Use BEXTR for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI, NoBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTR64rr GR64:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTR64rm addr:$src, - (SUBREG_TO_REG (i64 0), - (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; -} - -// Use BZHI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasBMI2, NoTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; -} - -let Predicates = [HasBMI2] in { - multiclass _bmi_bzhi_pattern { - def : Pat; - def : Pat; - } - - multiclass bmi_bzhi_patterns { - // x & ((1 << y) - 1) - defm : _bmi_bzhi_pattern<(and RC:$src, (add (shl 1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (add (shl 1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & ~(-1 << y) - defm : _bmi_bzhi_pattern<(and RC:$src, (xor (shl -1, GR8:$lz), -1)), - (and (x86memop addr:$src), - (xor (shl -1, GR8:$lz), -1)), - RC, VT, DstInst, DstMemInst>; - - // x & (-1 >> (bitwidth - y)) - defm : _bmi_bzhi_pattern<(and RC:$src, (srl -1, (sub bitwidth, GR8:$lz))), - (and (x86memop addr:$src), - (srl -1, (sub bitwidth, GR8:$lz))), - RC, VT, DstInst, DstMemInst>; - - // x << (bitwidth - y) >> (bitwidth - y) - defm : _bmi_bzhi_pattern<(srl (shl RC:$src, (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - (srl (shl (x86memop addr:$src), - (sub bitwidth, GR8:$lz)), - (sub bitwidth, GR8:$lz)), - RC, VT, DstInst, DstMemInst>; - } - - defm : bmi_bzhi_patterns; - defm : bmi_bzhi_patterns; - - // x & (-1 >> (32 - y)) - def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(and (loadi32 addr:$src), (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x & (-1 >> (64 - y)) - def : Pat<(and GR64:$src, (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(and (loadi64 addr:$src), (srl -1, (i8 (trunc (sub 64, GR32:$lz))))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - - // x << (32 - y) >> (32 - y) - def : Pat<(srl (shl GR32:$src, (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rr GR32:$src, GR32:$lz)>; - def : Pat<(srl (shl (loadi32 addr:$src), (i8 (trunc (sub 32, GR32:$lz)))), - (i8 (trunc (sub 32, GR32:$lz)))), - (BZHI32rm addr:$src, GR32:$lz)>; - - // x << (64 - y) >> (64 - y) - def : Pat<(srl (shl GR64:$src, (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rr GR64:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; - def : Pat<(srl (shl (loadi64 addr:$src), (i8 (trunc (sub 64, GR32:$lz)))), - (i8 (trunc (sub 64, GR32:$lz)))), - (BZHI64rm addr:$src, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>; -} // HasBMI2 - -multiclass bmi_pdep_pext { - def rr : I<0xF5, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, RC:$src2))]>, - VEX_4V, Sched<[WriteALU]>; - def rm : I<0xF5, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set RC:$dst, (Int RC:$src1, (ld_frag addr:$src2)))]>, - VEX_4V, Sched<[WriteALULd, ReadAfterLd]>; -} - -let Predicates = [HasBMI2] in { - defm PDEP32 : bmi_pdep_pext<"pdep{l}", GR32, i32mem, - int_x86_bmi_pdep_32, loadi32>, T8XD; - defm PDEP64 : bmi_pdep_pext<"pdep{q}", GR64, i64mem, - int_x86_bmi_pdep_64, loadi64>, T8XD, VEX_W; - defm PEXT32 : bmi_pdep_pext<"pext{l}", GR32, i32mem, - int_x86_bmi_pext_32, loadi32>, T8XS; - defm PEXT64 : bmi_pdep_pext<"pext{q}", GR64, i64mem, - int_x86_bmi_pext_64, loadi64>, T8XS, VEX_W; -} - -//===----------------------------------------------------------------------===// -// TBM Instructions -// -let Predicates = [HasTBM], Defs = [EFLAGS] in { - -multiclass tbm_ternary_imm opc, RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - SDNode OpNode, Operand immtype, - SDPatternOperator immoperator, - X86FoldableSchedWrite Sched> { - def ri : Ii32, - XOP, XOPA, Sched<[Sched]>; - def mi : Ii32, - XOP, XOPA, Sched<[Sched.Folded]>; -} - -defm BEXTRI32 : tbm_ternary_imm<0x10, GR32, "bextr{l}", i32mem, loadi32, - X86bextr, i32imm, imm, WriteBEXTR>; -let ImmT = Imm32S in -defm BEXTRI64 : tbm_ternary_imm<0x10, GR64, "bextr{q}", i64mem, loadi64, - X86bextr, i64i32imm, - i64immSExt32, WriteBEXTR>, VEX_W; - -multiclass tbm_binary_rm opc, Format FormReg, Format FormMem, - RegisterClass RC, string OpcodeStr, - X86MemOperand x86memop, X86FoldableSchedWrite Sched> { -let hasSideEffects = 0 in { - def rr : I, - XOP_4V, XOP9, Sched<[Sched]>; - let mayLoad = 1 in - def rm : I, - XOP_4V, XOP9, Sched<[Sched.Folded]>; -} -} - -multiclass tbm_binary_intr opc, string OpcodeStr, - X86FoldableSchedWrite Sched, - Format FormReg, Format FormMem> { - defm NAME#32 : tbm_binary_rm; - defm NAME#64 : tbm_binary_rm, VEX_W; -} - -defm BLCFILL : tbm_binary_intr<0x01, "blcfill", WriteALU, MRM1r, MRM1m>; -defm BLCI : tbm_binary_intr<0x02, "blci", WriteALU, MRM6r, MRM6m>; -defm BLCIC : tbm_binary_intr<0x01, "blcic", WriteALU, MRM5r, MRM5m>; -defm BLCMSK : tbm_binary_intr<0x02, "blcmsk", WriteALU, MRM1r, MRM1m>; -defm BLCS : tbm_binary_intr<0x01, "blcs", WriteALU, MRM3r, MRM3m>; -defm BLSFILL : tbm_binary_intr<0x01, "blsfill", WriteALU, MRM2r, MRM2m>; -defm BLSIC : tbm_binary_intr<0x01, "blsic", WriteALU, MRM6r, MRM6m>; -defm T1MSKC : tbm_binary_intr<0x01, "t1mskc", WriteALU, MRM7r, MRM7m>; -defm TZMSK : tbm_binary_intr<0x01, "tzmsk", WriteALU, MRM4r, MRM4m>; -} // HasTBM, EFLAGS - -// Use BEXTRI for 64-bit 'and' with large immediate 'mask'. -let Predicates = [HasTBM] in { - def : Pat<(and GR64:$src, AndMask64:$mask), - (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>; - - def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), - (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>; -} - -//===----------------------------------------------------------------------===// -// Lightweight Profiling Instructions - -let Predicates = [HasLWP], SchedRW = [WriteSystem] in { - -def LLWPCB : I<0x12, MRM0r, (outs), (ins GR32:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR32:$src)]>, XOP, XOP9; -def SLWPCB : I<0x12, MRM1r, (outs GR32:$dst), (ins), "slwpcb\t$dst", - [(set GR32:$dst, (int_x86_slwpcb))]>, XOP, XOP9; - -def LLWPCB64 : I<0x12, MRM0r, (outs), (ins GR64:$src), "llwpcb\t$src", - [(int_x86_llwpcb GR64:$src)]>, XOP, XOP9, VEX_W; -def SLWPCB64 : I<0x12, MRM1r, (outs GR64:$dst), (ins), "slwpcb\t$dst", - [(set GR64:$dst, (int_x86_slwpcb))]>, XOP, XOP9, VEX_W; - -multiclass lwpins_intr { - def rri : Ii32<0x12, MRM0r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, GR32:$src1, imm:$cntl))]>, - XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM0m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(set EFLAGS, (X86lwpins RC:$src0, (loadi32 addr:$src1), imm:$cntl))]>, - XOP_4V, XOPA; -} - -let Defs = [EFLAGS] in { - defm LWPINS32 : lwpins_intr; - defm LWPINS64 : lwpins_intr, VEX_W; -} // EFLAGS - -multiclass lwpval_intr { - def rri : Ii32<0x12, MRM1r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, GR32:$src1, imm:$cntl)]>, XOP_4V, XOPA; - let mayLoad = 1 in - def rmi : Ii32<0x12, MRM1m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl), - "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}", - [(Int RC:$src0, (loadi32 addr:$src1), imm:$cntl)]>, - XOP_4V, XOPA; -} - -defm LWPVAL32 : lwpval_intr; -defm LWPVAL64 : lwpval_intr, VEX_W; - -} // HasLWP, SchedRW - -//===----------------------------------------------------------------------===// -// MONITORX/MWAITX Instructions -// -let SchedRW = [ WriteSystem ] in { - let usesCustomInserter = 1 in { - def MONITORX : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_monitorx addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[ HasMWAITX ]>; - } - - let Uses = [ EAX, ECX, EDX ] in { - def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", []>, - TB, Requires<[ HasMWAITX ]>; - } - - let Uses = [ ECX, EAX, EBX ] in { - def MWAITXrrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx", - [(int_x86_mwaitx ECX, EAX, EBX)]>, - TB, Requires<[ HasMWAITX ]>; - } -} // SchedRW - -def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrrr)>, - Requires<[ Not64BitMode ]>; -def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrrr)>, - Requires<[ In64BitMode ]>; - -def : InstAlias<"monitorx\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORXrrr)>, - Requires<[ Not64BitMode ]>; -def : InstAlias<"monitorx\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORXrrr)>, - Requires<[ In64BitMode ]>; - -//===----------------------------------------------------------------------===// -// WAITPKG Instructions -// -let SchedRW = [WriteSystem] in { - def UMONITOR16 : I<0xAE, MRM6r, (outs), (ins GR16:$src), - "umonitor\t$src", [(int_x86_umonitor GR16:$src)]>, - XS, AdSize16, Requires<[HasWAITPKG, Not64BitMode]>; - def UMONITOR32 : I<0xAE, MRM6r, (outs), (ins GR32:$src), - "umonitor\t$src", [(int_x86_umonitor GR32:$src)]>, - XS, AdSize32, Requires<[HasWAITPKG]>; - def UMONITOR64 : I<0xAE, MRM6r, (outs), (ins GR64:$src), - "umonitor\t$src", [(int_x86_umonitor GR64:$src)]>, - XS, AdSize64, Requires<[HasWAITPKG, In64BitMode]>; - let Uses = [EAX, EDX], Defs = [EFLAGS] in { - def UMWAIT : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "umwait\t$src", - [(set EFLAGS, (X86umwait GR32orGR64:$src, EDX, EAX))]>, - XD, Requires<[HasWAITPKG]>; - def TPAUSE : I<0xAE, MRM6r, - (outs), (ins GR32orGR64:$src), "tpause\t$src", - [(set EFLAGS, (X86tpause GR32orGR64:$src, EDX, EAX))]>, - PD, Requires<[HasWAITPKG]>, NotMemoryFoldable; - } -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIRI - Move doubleword/quadword as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIRI32 : I<0xF9, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore32 addr:$dst, GR32:$src)]>, - T8, Requires<[HasMOVDIRI]>; -def MOVDIRI64 : RI<0xF9, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movdiri\t{$src, $dst|$dst, $src}", - [(int_x86_directstore64 addr:$dst, GR64:$src)]>, - T8, Requires<[In64BitMode, HasMOVDIRI]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// MOVDIR64B - Move 64 bytes as direct store -// -let SchedRW = [WriteStore] in { -def MOVDIR64B16 : I<0xF8, MRMSrcMem, (outs), (ins GR16:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", []>, - T8PD, AdSize16, Requires<[HasMOVDIR64B, Not64BitMode]>; -def MOVDIR64B32 : I<0xF8, MRMSrcMem, (outs), (ins GR32:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR32:$dst, addr:$src)]>, - T8PD, AdSize32, Requires<[HasMOVDIR64B]>; -def MOVDIR64B64 : I<0xF8, MRMSrcMem, (outs), (ins GR64:$dst, i512mem:$src), - "movdir64b\t{$src, $dst|$dst, $src}", - [(int_x86_movdir64b GR64:$dst, addr:$src)]>, - T8PD, AdSize64, Requires<[HasMOVDIR64B, In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CLZERO Instruction -// -let SchedRW = [WriteSystem] in { - let Uses = [EAX] in - def CLZEROr : I<0x01, MRM_FC, (outs), (ins), "clzero", []>, - TB, Requires<[HasCLZERO]>; - - let usesCustomInserter = 1 in { - def CLZERO : PseudoI<(outs), (ins i32mem:$src1), - [(int_x86_clzero addr:$src1)]>, Requires<[HasCLZERO]>; - } -} // SchedRW - -def : InstAlias<"clzero\t{%eax|eax}", (CLZEROr)>, Requires<[Not64BitMode]>; -def : InstAlias<"clzero\t{%rax|rax}", (CLZEROr)>, Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate TBM instructions. -//===----------------------------------------------------------------------===// - -let Predicates = [HasTBM] in { - // FIXME: patterns for the load versions are not implemented - def : Pat<(and GR32:$src, (add GR32:$src, 1)), - (BLCFILL32rr GR32:$src)>; - def : Pat<(and GR64:$src, (add GR64:$src, 1)), - (BLCFILL64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (not (add GR32:$src, 1))), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (not (add GR64:$src, 1))), - (BLCI64rr GR64:$src)>; - - // Extra patterns because opt can optimize the above patterns to this. - def : Pat<(or GR32:$src, (sub -2, GR32:$src)), - (BLCI32rr GR32:$src)>; - def : Pat<(or GR64:$src, (sub -2, GR64:$src)), - (BLCI64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, 1)), - (BLCIC32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, 1)), - (BLCIC64rr GR64:$src)>; - - def : Pat<(xor GR32:$src, (add GR32:$src, 1)), - (BLCMSK32rr GR32:$src)>; - def : Pat<(xor GR64:$src, (add GR64:$src, 1)), - (BLCMSK64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, 1)), - (BLCS32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, 1)), - (BLCS64rr GR64:$src)>; - - def : Pat<(or GR32:$src, (add GR32:$src, -1)), - (BLSFILL32rr GR32:$src)>; - def : Pat<(or GR64:$src, (add GR64:$src, -1)), - (BLSFILL64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, -1)), - (BLSIC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, -1)), - (BLSIC64rr GR64:$src)>; - - def : Pat<(or (not GR32:$src), (add GR32:$src, 1)), - (T1MSKC32rr GR32:$src)>; - def : Pat<(or (not GR64:$src), (add GR64:$src, 1)), - (T1MSKC64rr GR64:$src)>; - - def : Pat<(and (not GR32:$src), (add GR32:$src, -1)), - (TZMSK32rr GR32:$src)>; - def : Pat<(and (not GR64:$src), (add GR64:$src, -1)), - (TZMSK64rr GR64:$src)>; -} // HasTBM - -//===----------------------------------------------------------------------===// -// Memory Instructions -// - -let Predicates = [HasCLFLUSHOPT], SchedRW = [WriteLoad] in -def CLFLUSHOPT : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflushopt\t$src", [(int_x86_clflushopt addr:$src)]>, PD; - -let Predicates = [HasCLWB], SchedRW = [WriteLoad] in -def CLWB : I<0xAE, MRM6m, (outs), (ins i8mem:$src), "clwb\t$src", - [(int_x86_clwb addr:$src)]>, PD, NotMemoryFoldable; - -let Predicates = [HasCLDEMOTE], SchedRW = [WriteLoad] in -def CLDEMOTE : I<0x1C, MRM0m, (outs), (ins i8mem:$src), "cldemote\t$src", - [(int_x86_cldemote addr:$src)]>, TB; - -//===----------------------------------------------------------------------===// -// Subsystems. -//===----------------------------------------------------------------------===// - -include "X86Capstone.td" - -include "X86InstrArithmetic.td" -include "X86InstrCMovSetCC.td" -include "X86InstrExtension.td" -include "X86InstrControl.td" -include "X86InstrShiftRotate.td" - -// X87 Floating Point Stack. -//include "X86InstrFPStack.td" - -// SIMD support (SSE, MMX and AVX) -//include "X86InstrFragmentsSIMD.td" - -// FMA - Fused Multiply-Add support (requires FMA) -//include "X86InstrFMA.td" - -// XOP -//include "X86InstrXOP.td" - -// SSE, MMX and 3DNow! vector support. -//include "X86InstrSSE.td" -//include "X86InstrAVX512.td" -//include "X86InstrMMX.td" -//include "X86Instr3DNow.td" - -// MPX instructions -//include "X86InstrMPX.td" - -include "X86InstrVMX.td" -include "X86InstrSVM.td" - -//include "X86InstrTSX.td" -//include "X86InstrSGX.td" - -// System instructions. -include "X86InstrSystem.td" - -// Compiler Pseudo Instructions and Pat Patterns -//include "X86InstrCompiler.td" -//include "X86InstrVecCompiler.td" - -//===----------------------------------------------------------------------===// -// Assembler Mnemonic Aliases -//===----------------------------------------------------------------------===// - -def : MnemonicAlias<"call", "callw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"call", "calll", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"call", "callq", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"cbw", "cbtw", "att">; -def : MnemonicAlias<"cwde", "cwtl", "att">; -def : MnemonicAlias<"cwd", "cwtd", "att">; -def : MnemonicAlias<"cdq", "cltd", "att">; -def : MnemonicAlias<"cdqe", "cltq", "att">; -def : MnemonicAlias<"cqo", "cqto", "att">; - -// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq. -def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>; - -def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>; - -def : MnemonicAlias<"loopz", "loope">; -def : MnemonicAlias<"loopnz", "loopne">; - -def : MnemonicAlias<"pop", "popw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pop", "popl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pop", "popq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popf", "popfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"popf", "popfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popf", "popfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"popfd", "popfl", "att">; - -// FIXME: This is wrong for "push reg". "push %bx" should turn into pushw in -// all modes. However: "push (addr)" and "push $42" should default to -// pushl/pushq depending on the current mode. Similar for "pop %bx" -def : MnemonicAlias<"push", "pushw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"push", "pushl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"push", "pushq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pushf", "pushfl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushf", "pushfq", "intel">, Requires<[In64BitMode]>; -def : MnemonicAlias<"pushfd", "pushfl", "att">; - -def : MnemonicAlias<"popad", "popal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"pushad", "pushal", "intel">, Requires<[Not64BitMode]>; -def : MnemonicAlias<"popa", "popaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "intel">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "intel">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "intel">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"popa", "popaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"pusha", "pushaw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"popa", "popal", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"pusha", "pushal", "att">, Requires<[In32BitMode]>; - -def : MnemonicAlias<"repe", "rep">; -def : MnemonicAlias<"repz", "rep">; -def : MnemonicAlias<"repnz", "repne">; - -def : MnemonicAlias<"ret", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"ret", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"ret", "retq", "att">, Requires<[In64BitMode]>; - -// Apply 'ret' behavior to 'retn' -def : MnemonicAlias<"retn", "retw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"retn", "retl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"retn", "retq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"retn", "ret", "intel">; - -def : MnemonicAlias<"sal", "shl", "intel">; -def : MnemonicAlias<"salb", "shlb", "att">; -def : MnemonicAlias<"salw", "shlw", "att">; -def : MnemonicAlias<"sall", "shll", "att">; -def : MnemonicAlias<"salq", "shlq", "att">; - -def : MnemonicAlias<"smovb", "movsb", "att">; -def : MnemonicAlias<"smovw", "movsw", "att">; -def : MnemonicAlias<"smovl", "movsl", "att">; -def : MnemonicAlias<"smovq", "movsq", "att">; - -def : MnemonicAlias<"ud2a", "ud2", "att">; -def : MnemonicAlias<"verrw", "verr", "att">; - -// MS recognizes 'xacquire'/'xrelease' as 'acquire'/'release' -def : MnemonicAlias<"acquire", "xacquire", "intel">; -def : MnemonicAlias<"release", "xrelease", "intel">; - -// System instruction aliases. -def : MnemonicAlias<"iret", "iretw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"iret", "iretl", "att">, Requires<[Not16BitMode]>; -def : MnemonicAlias<"sysret", "sysretl", "att">; -def : MnemonicAlias<"sysexit", "sysexitl", "att">; - -def : MnemonicAlias<"lgdt", "lgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lgdt", "lgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"lidt", "lidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"lidt", "lidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"lidt", "lidtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sgdt", "sgdtq", "att">, Requires<[In64BitMode]>; -def : MnemonicAlias<"sidt", "sidtw", "att">, Requires<[In16BitMode]>; -def : MnemonicAlias<"sidt", "sidtl", "att">, Requires<[In32BitMode]>; -def : MnemonicAlias<"sidt", "sidtq", "att">, Requires<[In64BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lgdt", "lgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"lidt", "lidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"lidt", "lidtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sgdt", "sgdtd", "intel">, Requires<[In32BitMode]>; -//def : MnemonicAlias<"sidt", "sidtw", "intel">, Requires<[In16BitMode]>; -//def : MnemonicAlias<"sidt", "sidtd", "intel">, Requires<[In32BitMode]>; - - -// Floating point stack aliases. -def : MnemonicAlias<"fcmovz", "fcmove", "att">; -def : MnemonicAlias<"fcmova", "fcmovnbe", "att">; -def : MnemonicAlias<"fcmovnae", "fcmovb", "att">; -def : MnemonicAlias<"fcmovna", "fcmovbe", "att">; -def : MnemonicAlias<"fcmovae", "fcmovnb", "att">; -def : MnemonicAlias<"fcomip", "fcompi">; -def : MnemonicAlias<"fildq", "fildll", "att">; -def : MnemonicAlias<"fistpq", "fistpll", "att">; -def : MnemonicAlias<"fisttpq", "fisttpll", "att">; -def : MnemonicAlias<"fldcww", "fldcw", "att">; -def : MnemonicAlias<"fnstcww", "fnstcw", "att">; -def : MnemonicAlias<"fnstsww", "fnstsw", "att">; -def : MnemonicAlias<"fucomip", "fucompi">; -def : MnemonicAlias<"fwait", "wait">; - -def : MnemonicAlias<"fxsaveq", "fxsave64", "att">; -def : MnemonicAlias<"fxrstorq", "fxrstor64", "att">; -def : MnemonicAlias<"xsaveq", "xsave64", "att">; -def : MnemonicAlias<"xrstorq", "xrstor64", "att">; -def : MnemonicAlias<"xsaveoptq", "xsaveopt64", "att">; -def : MnemonicAlias<"xrstorsq", "xrstors64", "att">; -def : MnemonicAlias<"xsavecq", "xsavec64", "att">; -def : MnemonicAlias<"xsavesq", "xsaves64", "att">; - -class CondCodeAlias - : MnemonicAlias; - -/// IntegerCondCodeMnemonicAlias - This multiclass defines a bunch of -/// MnemonicAlias's that canonicalize the condition code in a mnemonic, for -/// example "setz" -> "sete". -multiclass IntegerCondCodeMnemonicAlias { - def C : CondCodeAlias; // setc -> setb - def Z : CondCodeAlias; // setz -> sete - def NA : CondCodeAlias; // setna -> setbe - def NB : CondCodeAlias; // setnb -> setae - def NC : CondCodeAlias; // setnc -> setae - def NG : CondCodeAlias; // setng -> setle - def NL : CondCodeAlias; // setnl -> setge - def NZ : CondCodeAlias; // setnz -> setne - def PE : CondCodeAlias; // setpe -> setp - def PO : CondCodeAlias; // setpo -> setnp - - def NAE : CondCodeAlias; // setnae -> setb - def NBE : CondCodeAlias; // setnbe -> seta - def NGE : CondCodeAlias; // setnge -> setl - def NLE : CondCodeAlias; // setnle -> setg -} - -// Aliases for set -defm : IntegerCondCodeMnemonicAlias<"set", "">; -// Aliases for j -defm : IntegerCondCodeMnemonicAlias<"j", "">; -// Aliases for cmov{w,l,q} -defm : IntegerCondCodeMnemonicAlias<"cmov", "w", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "l", "att">; -defm : IntegerCondCodeMnemonicAlias<"cmov", "q", "att">; -// No size suffix for intel-style asm. -defm : IntegerCondCodeMnemonicAlias<"cmov", "", "intel">; - - -//===----------------------------------------------------------------------===// -// Assembler Instruction Aliases -//===----------------------------------------------------------------------===// - -// aad/aam default to base 10 if no operand is specified. -def : InstAlias<"aad", (AAD8i8 10)>, Requires<[Not64BitMode]>; -def : InstAlias<"aam", (AAM8i8 10)>, Requires<[Not64BitMode]>; - -// Disambiguate the mem/imm form of bt-without-a-suffix as btl. -// Likewise for btc/btr/bts. -def : InstAlias<"bt\t{$imm, $mem|$mem, $imm}", - (BT32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"btc\t{$imm, $mem|$mem, $imm}", - (BTC32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"btr\t{$imm, $mem|$mem, $imm}", - (BTR32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; -def : InstAlias<"bts\t{$imm, $mem|$mem, $imm}", - (BTS32mi8 i32mem:$mem, i32i8imm:$imm), 0, "att">; - -// clr aliases. -def : InstAlias<"clr{b}\t$reg", (XOR8rr GR8 :$reg, GR8 :$reg), 0>; -def : InstAlias<"clr{w}\t$reg", (XOR16rr GR16:$reg, GR16:$reg), 0>; -def : InstAlias<"clr{l}\t$reg", (XOR32rr GR32:$reg, GR32:$reg), 0>; -def : InstAlias<"clr{q}\t$reg", (XOR64rr GR64:$reg, GR64:$reg), 0>; - -// lods aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"lodsb\t$src", (LODSB srcidx8:$src), 0>; -def : InstAlias<"lodsw\t$src", (LODSW srcidx16:$src), 0>; -def : InstAlias<"lods{l|d}\t$src", (LODSL srcidx32:$src), 0>; -def : InstAlias<"lodsq\t$src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -def : InstAlias<"lods\t{$src, %al|al, $src}", (LODSB srcidx8:$src), 0>; -def : InstAlias<"lods\t{$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>; -def : InstAlias<"lods\t{$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>; -def : InstAlias<"lods\t{$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>; -def : InstAlias<"lods\t$src", (LODSB srcidx8:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSW srcidx16:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSL srcidx32:$src), 0, "intel">; -def : InstAlias<"lods\t$src", (LODSQ srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - - -// stos aliases. Accept the source being omitted because it's implicit in -// the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the source. -def : InstAlias<"stosb\t$dst", (STOSB dstidx8:$dst), 0>; -def : InstAlias<"stosw\t$dst", (STOSW dstidx16:$dst), 0>; -def : InstAlias<"stos{l|d}\t$dst", (STOSL dstidx32:$dst), 0>; -def : InstAlias<"stosq\t$dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"stos\t{%al, $dst|$dst, al}", (STOSB dstidx8:$dst), 0>; -def : InstAlias<"stos\t{%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>; -def : InstAlias<"stos\t{%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>; -def : InstAlias<"stos\t{%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"stos\t$dst", (STOSB dstidx8:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSW dstidx16:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSL dstidx32:$dst), 0, "intel">; -def : InstAlias<"stos\t$dst", (STOSQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - - -// scas aliases. Accept the destination being omitted because it's implicit -// in the mnemonic, or the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"scasb\t$dst", (SCASB dstidx8:$dst), 0>; -def : InstAlias<"scasw\t$dst", (SCASW dstidx16:$dst), 0>; -def : InstAlias<"scas{l|d}\t$dst", (SCASL dstidx32:$dst), 0>; -def : InstAlias<"scasq\t$dst", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"scas\t{$dst, %al|al, $dst}", (SCASB dstidx8:$dst), 0>; -def : InstAlias<"scas\t{$dst, %ax|ax, $dst}", (SCASW dstidx16:$dst), 0>; -def : InstAlias<"scas\t{$dst, %eax|eax, $dst}", (SCASL dstidx32:$dst), 0>; -def : InstAlias<"scas\t{$dst, %rax|rax, $dst}", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>; -def : InstAlias<"scas\t$dst", (SCASB dstidx8:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASW dstidx16:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASL dstidx32:$dst), 0, "intel">; -def : InstAlias<"scas\t$dst", (SCASQ dstidx64:$dst), 0, "intel">, Requires<[In64BitMode]>; - -// cmps aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// movs aliases. Mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSB dstidx8:$dst, srcidx8:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSW dstidx16:$dst, srcidx16:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSL dstidx32:$dst, srcidx32:$src), 0, "intel">; -def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSQ dstidx64:$dst, srcidx64:$src), 0, "intel">, Requires<[In64BitMode]>; - -// div and idiv aliases for explicit A register. -def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>; -def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>; -def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32r GR32:$src)>; -def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64r GR64:$src)>; -def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8m i8mem :$src)>; -def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16m i16mem:$src)>; -def : InstAlias<"div{l}\t{$src, %eax|eax, $src}", (DIV32m i32mem:$src)>; -def : InstAlias<"div{q}\t{$src, %rax|rax, $src}", (DIV64m i64mem:$src)>; -def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8r GR8 :$src)>; -def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16r GR16:$src)>; -def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32r GR32:$src)>; -def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64r GR64:$src)>; -def : InstAlias<"idiv{b}\t{$src, %al|al, $src}", (IDIV8m i8mem :$src)>; -def : InstAlias<"idiv{w}\t{$src, %ax|ax, $src}", (IDIV16m i16mem:$src)>; -def : InstAlias<"idiv{l}\t{$src, %eax|eax, $src}", (IDIV32m i32mem:$src)>; -def : InstAlias<"idiv{q}\t{$src, %rax|rax, $src}", (IDIV64m i64mem:$src)>; - - - -// Various unary fpstack operations default to operating on ST1. -// For example, "fxch" -> "fxch %st(1)" -def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; -def: InstAlias<"fadd", (ADD_FPrST0 ST1), 0>; -def : InstAlias<"fsub{|r}p", (SUBR_FPrST0 ST1), 0>; -def : InstAlias<"fsub{r|}p", (SUB_FPrST0 ST1), 0>; -def : InstAlias<"fmul", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fmulp", (MUL_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{|r}p", (DIVR_FPrST0 ST1), 0>; -def : InstAlias<"fdiv{r|}p", (DIV_FPrST0 ST1), 0>; -def : InstAlias<"fxch", (XCH_F ST1), 0>; -def : InstAlias<"fcom", (COM_FST0r ST1), 0>; -def : InstAlias<"fcomp", (COMP_FST0r ST1), 0>; -def : InstAlias<"fcomi", (COM_FIr ST1), 0>; -def : InstAlias<"fcompi", (COM_FIPr ST1), 0>; -def : InstAlias<"fucom", (UCOM_Fr ST1), 0>; -def : InstAlias<"fucomp", (UCOM_FPr ST1), 0>; -def : InstAlias<"fucomi", (UCOM_FIr ST1), 0>; -def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; - -// Handle fmul/fadd/fsub/fdiv instructions with explicitly written st(0) op. -// For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate -// instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with -// gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; -} - -defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; - - -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they -// commute. We also allow fdiv[r]p/fsubrp even though they don't commute, -// solely because gas supports it. -def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; - -def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; - -// lcall and ljmp aliases. This seems to be an odd mapping in 64-bit mode, but -// this is compatible with what GAS does. -def : InstAlias<"lcall\t$seg : $off", (FARCALL32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -def : InstAlias<"ljmp\t$seg : $off", (FARJMP32i i32imm:$off, i16imm:$seg), 0>, Requires<[In32BitMode]>; -def : InstAlias<"lcall\t{*}$dst", (FARCALL32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -def : InstAlias<"ljmp\t{*}$dst", (FARJMP32m opaquemem:$dst), 0>, Requires<[Not16BitMode]>; -def : InstAlias<"lcall\t$seg : $off", (FARCALL16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -def : InstAlias<"ljmp\t$seg : $off", (FARJMP16i i16imm:$off, i16imm:$seg), 0>, Requires<[In16BitMode]>; -def : InstAlias<"lcall\t{*}$dst", (FARCALL16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; -def : InstAlias<"ljmp\t{*}$dst", (FARJMP16m opaquemem:$dst), 0>, Requires<[In16BitMode]>; - -def : InstAlias<"jmp\t{*}$dst", (JMP64m i64mem:$dst), 0, "att">, Requires<[In64BitMode]>; -def : InstAlias<"jmp\t{*}$dst", (JMP32m i32mem:$dst), 0, "att">, Requires<[In32BitMode]>; -def : InstAlias<"jmp\t{*}$dst", (JMP16m i16mem:$dst), 0, "att">, Requires<[In16BitMode]>; - - -// "imul , B" is an alias for "imul , B, B". -def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri GR16:$r, GR16:$r, i16imm:$imm), 0>; -def : InstAlias<"imul{w}\t{$imm, $r|$r, $imm}", (IMUL16rri8 GR16:$r, GR16:$r, i16i8imm:$imm), 0>; -def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri GR32:$r, GR32:$r, i32imm:$imm), 0>; -def : InstAlias<"imul{l}\t{$imm, $r|$r, $imm}", (IMUL32rri8 GR32:$r, GR32:$r, i32i8imm:$imm), 0>; -def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri32 GR64:$r, GR64:$r, i64i32imm:$imm), 0>; -def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri8 GR64:$r, GR64:$r, i64i8imm:$imm), 0>; - -// ins aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the destination. -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSB dstidx8:$dst), 0, "intel">; -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSW dstidx16:$dst), 0, "intel">; -def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSL dstidx32:$dst), 0, "intel">; - -// outs aliases. Accept the mnemonic suffix being omitted because it's implicit -// in the source. -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSB srcidx8:$src), 0, "intel">; -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSW srcidx16:$src), 0, "intel">; -def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSL srcidx32:$src), 0, "intel">; - -// inb %dx -> inb %al, %dx -def : InstAlias<"inb\t{%dx|dx}", (IN8rr), 0>; -def : InstAlias<"inw\t{%dx|dx}", (IN16rr), 0>; -def : InstAlias<"inl\t{%dx|dx}", (IN32rr), 0>; -def : InstAlias<"inb\t$port", (IN8ri u8imm:$port), 0>; -def : InstAlias<"inw\t$port", (IN16ri u8imm:$port), 0>; -def : InstAlias<"inl\t$port", (IN32ri u8imm:$port), 0>; - - -// jmp and call aliases for lcall and ljmp. jmp $42,$5 -> ljmp -def : InstAlias<"call\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -def : InstAlias<"jmp\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[In16BitMode]>; -def : InstAlias<"call\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -def : InstAlias<"jmp\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[In32BitMode]>; -def : InstAlias<"callw\t$seg, $off", (FARCALL16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"jmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"calll\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; -def : InstAlias<"jmpl\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>; - -// Match 'movq , ' as an alias for movabsq. -def : InstAlias<"mov{q}\t{$imm, $reg|$reg, $imm}", (MOV64ri GR64:$reg, i64imm:$imm), 0>; - -// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas, -// which supports this due to an old AMD documentation bug when 64-bit mode was -// created. -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; - -// movsx aliases -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rr8 GR16:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr8 GR32:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX32rr16 GR32:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr8 GR64:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr16 GR64:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movsx\t{$src, $dst|$dst, $src}", (MOVSX64rr32 GR64:$dst, GR32:$src), 0, "att">; - -// movzx aliases -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rr8 GR16:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX16rm8 GR16:$dst, i8mem:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr8 GR32:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX32rr16 GR32:$dst, GR16:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr8 GR64:$dst, GR8:$src), 0, "att">; -def : InstAlias<"movzx\t{$src, $dst|$dst, $src}", (MOVZX64rr16 GR64:$dst, GR16:$src), 0, "att">; -// Note: No GR32->GR64 movzx form. - -// outb %dx -> outb %al, %dx -def : InstAlias<"outb\t{%dx|dx}", (OUT8rr), 0>; -def : InstAlias<"outw\t{%dx|dx}", (OUT16rr), 0>; -def : InstAlias<"outl\t{%dx|dx}", (OUT32rr), 0>; -def : InstAlias<"outb\t$port", (OUT8ir u8imm:$port), 0>; -def : InstAlias<"outw\t$port", (OUT16ir u8imm:$port), 0>; -def : InstAlias<"outl\t$port", (OUT32ir u8imm:$port), 0>; - -// 'sldt ' can be encoded with either sldtw or sldtq with the same -// effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity -// errors, since its encoding is the most compact. -def : InstAlias<"sldt $mem", (SLDT16m i16mem:$mem), 0>; - -// shld/shrd op,op -> shld op, op, CL -def : InstAlias<"shld{w}\t{$r2, $r1|$r1, $r2}", (SHLD16rrCL GR16:$r1, GR16:$r2), 0>; -def : InstAlias<"shld{l}\t{$r2, $r1|$r1, $r2}", (SHLD32rrCL GR32:$r1, GR32:$r2), 0>; -def : InstAlias<"shld{q}\t{$r2, $r1|$r1, $r2}", (SHLD64rrCL GR64:$r1, GR64:$r2), 0>; -def : InstAlias<"shrd{w}\t{$r2, $r1|$r1, $r2}", (SHRD16rrCL GR16:$r1, GR16:$r2), 0>; -def : InstAlias<"shrd{l}\t{$r2, $r1|$r1, $r2}", (SHRD32rrCL GR32:$r1, GR32:$r2), 0>; -def : InstAlias<"shrd{q}\t{$r2, $r1|$r1, $r2}", (SHRD64rrCL GR64:$r1, GR64:$r2), 0>; - -def : InstAlias<"shld{w}\t{$reg, $mem|$mem, $reg}", (SHLD16mrCL i16mem:$mem, GR16:$reg), 0>; -def : InstAlias<"shld{l}\t{$reg, $mem|$mem, $reg}", (SHLD32mrCL i32mem:$mem, GR32:$reg), 0>; -def : InstAlias<"shld{q}\t{$reg, $mem|$mem, $reg}", (SHLD64mrCL i64mem:$mem, GR64:$reg), 0>; -def : InstAlias<"shrd{w}\t{$reg, $mem|$mem, $reg}", (SHRD16mrCL i16mem:$mem, GR16:$reg), 0>; -def : InstAlias<"shrd{l}\t{$reg, $mem|$mem, $reg}", (SHRD32mrCL i32mem:$mem, GR32:$reg), 0>; -def : InstAlias<"shrd{q}\t{$reg, $mem|$mem, $reg}", (SHRD64mrCL i64mem:$mem, GR64:$reg), 0>; - -/* FIXME: This is disabled because the asm matcher is currently incapable of - * matching a fixed immediate like $1. -// "shl X, $1" is an alias for "shl X". -multiclass ShiftRotateByOneAlias { - def : InstAlias(!strconcat(Opc, "8r1")) GR8:$op)>; - def : InstAlias(!strconcat(Opc, "16r1")) GR16:$op)>; - def : InstAlias(!strconcat(Opc, "32r1")) GR32:$op)>; - def : InstAlias(!strconcat(Opc, "64r1")) GR64:$op)>; - def : InstAlias(!strconcat(Opc, "8m1")) i8mem:$op)>; - def : InstAlias(!strconcat(Opc, "16m1")) i16mem:$op)>; - def : InstAlias(!strconcat(Opc, "32m1")) i32mem:$op)>; - def : InstAlias(!strconcat(Opc, "64m1")) i64mem:$op)>; -} - -defm : ShiftRotateByOneAlias<"rcl", "RCL">; -defm : ShiftRotateByOneAlias<"rcr", "RCR">; -defm : ShiftRotateByOneAlias<"rol", "ROL">; -defm : ShiftRotateByOneAlias<"ror", "ROR">; -FIXME */ - -// test: We accept "testX , " and "testX , " as synonyms. -def : InstAlias<"test{b}\t{$mem, $val|$val, $mem}", - (TEST8mr i8mem :$mem, GR8 :$val), 0>; -def : InstAlias<"test{w}\t{$mem, $val|$val, $mem}", - (TEST16mr i16mem:$mem, GR16:$val), 0>; -def : InstAlias<"test{l}\t{$mem, $val|$val, $mem}", - (TEST32mr i32mem:$mem, GR32:$val), 0>; -def : InstAlias<"test{q}\t{$mem, $val|$val, $mem}", - (TEST64mr i64mem:$mem, GR64:$val), 0>; - -// xchg: We accept "xchgX , " and "xchgX , " as synonyms. -def : InstAlias<"xchg{b}\t{$mem, $val|$val, $mem}", - (XCHG8rm GR8 :$val, i8mem :$mem), 0>; -def : InstAlias<"xchg{w}\t{$mem, $val|$val, $mem}", - (XCHG16rm GR16:$val, i16mem:$mem), 0>; -def : InstAlias<"xchg{l}\t{$mem, $val|$val, $mem}", - (XCHG32rm GR32:$val, i32mem:$mem), 0>; -def : InstAlias<"xchg{q}\t{$mem, $val|$val, $mem}", - (XCHG64rm GR64:$val, i64mem:$mem), 0>; - -// xchg: We accept "xchgX , %eax" and "xchgX %eax, " as synonyms. -def : InstAlias<"xchg{w}\t{%ax, $src|$src, ax}", (XCHG16ar GR16:$src), 0>; -def : InstAlias<"xchg{l}\t{%eax, $src|$src, eax}", (XCHG32ar GR32:$src), 0>; -def : InstAlias<"xchg{q}\t{%rax, $src|$src, rax}", (XCHG64ar GR64:$src), 0>; - -// In 64-bit mode, xchg %eax, %eax can't be encoded with the 0x90 opcode we -// would get by default because it's defined as NOP. But xchg %eax, %eax implies -// implicit zeroing of the upper 32 bits. So alias to the longer encoding. -def : InstAlias<"xchg{l}\t{%eax, %eax|eax, eax}", - (XCHG32rr EAX, EAX), 0>, Requires<[In64BitMode]>; - -// xchg %rax, %rax is a nop in x86-64 and can be encoded as such. Without this -// we emit an unneeded REX.w prefix. -def : InstAlias<"xchg{q}\t{%rax, %rax|rax, rax}", (NOOP), 0>; - -// These aliases exist to get the parser to prioritize matching 8-bit -// immediate encodings over matching the implicit ax/eax/rax encodings. By -// explicitly mentioning the A register here, these entries will be ordered -// first due to the more explicit immediate type. -def : InstAlias<"adc{w}\t{$imm, %ax|ax, $imm}", (ADC16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"add{w}\t{$imm, %ax|ax, $imm}", (ADD16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"and{w}\t{$imm, %ax|ax, $imm}", (AND16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"cmp{w}\t{$imm, %ax|ax, $imm}", (CMP16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"or{w}\t{$imm, %ax|ax, $imm}", (OR16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"sbb{w}\t{$imm, %ax|ax, $imm}", (SBB16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"sub{w}\t{$imm, %ax|ax, $imm}", (SUB16ri8 AX, i16i8imm:$imm), 0>; -def : InstAlias<"xor{w}\t{$imm, %ax|ax, $imm}", (XOR16ri8 AX, i16i8imm:$imm), 0>; - -def : InstAlias<"adc{l}\t{$imm, %eax|eax, $imm}", (ADC32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"add{l}\t{$imm, %eax|eax, $imm}", (ADD32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"and{l}\t{$imm, %eax|eax, $imm}", (AND32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"cmp{l}\t{$imm, %eax|eax, $imm}", (CMP32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"or{l}\t{$imm, %eax|eax, $imm}", (OR32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"sbb{l}\t{$imm, %eax|eax, $imm}", (SBB32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"sub{l}\t{$imm, %eax|eax, $imm}", (SUB32ri8 EAX, i32i8imm:$imm), 0>; -def : InstAlias<"xor{l}\t{$imm, %eax|eax, $imm}", (XOR32ri8 EAX, i32i8imm:$imm), 0>; - -def : InstAlias<"adc{q}\t{$imm, %rax|rax, $imm}", (ADC64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"add{q}\t{$imm, %rax|rax, $imm}", (ADD64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"and{q}\t{$imm, %rax|rax, $imm}", (AND64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"cmp{q}\t{$imm, %rax|rax, $imm}", (CMP64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"or{q}\t{$imm, %rax|rax, $imm}", (OR64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"sbb{q}\t{$imm, %rax|rax, $imm}", (SBB64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"sub{q}\t{$imm, %rax|rax, $imm}", (SUB64ri8 RAX, i64i8imm:$imm), 0>; -def : InstAlias<"xor{q}\t{$imm, %rax|rax, $imm}", (XOR64ri8 RAX, i64i8imm:$imm), 0>; diff --git a/suite/synctools/tablegen/X86/back/X86InstrMMX.td b/suite/synctools/tablegen/X86/back/X86InstrMMX.td deleted file mode 100644 index aefeffedfc..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrMMX.td +++ /dev/null @@ -1,612 +0,0 @@ -//===-- X86InstrMMX.td - Describe the MMX Instruction Set --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 MMX instruction set, defining the instructions, -// and properties of the instructions which are needed for code generation, -// machine code emission, and analysis. -// -// All instructions that use MMX should be in this file, even if they also use -// SSE. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MMX Multiclasses -//===----------------------------------------------------------------------===// - -// Alias instruction that maps zero vector to pxor mmx. -// This is expanded by ExpandPostRAPseudos to an pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { -def MMX_SET0 : I<0, Pseudo, (outs VR64:$dst), (ins), "", []>; -} - -let Constraints = "$src1 = $dst" in { - // MMXI_binop_rm_int - Simple MMX binary operator based on intrinsic. - // When this is cleaned up, remove the FIXME from X86RecognizableInstr.cpp. - multiclass MMXI_binop_rm_int opc, string OpcodeStr, Intrinsic IntId, - X86FoldableSchedWrite sched, bit Commutable = 0, - X86MemOperand OType = i64mem> { - def irr : MMXI, - Sched<[sched]> { - let isCommutable = Commutable; - } - def irm : MMXI, - Sched<[sched.Folded, ReadAfterLd]>; - } - - multiclass MMXI_binop_rmi_int opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, Intrinsic IntId, - Intrinsic IntId2, X86FoldableSchedWrite sched, - X86FoldableSchedWrite schedImm> { - def rr : MMXI, - Sched<[sched]>; - def rm : MMXI, - Sched<[sched.Folded, ReadAfterLd]>; - def ri : MMXIi8, - Sched<[schedImm]>; - } -} - -/// Unary MMX instructions requiring SSSE3. -multiclass SS3I_unop_rm_int_mm opc, string OpcodeStr, - Intrinsic IntId64, X86FoldableSchedWrite sched> { - def rr : MMXSS38I, - Sched<[sched]>; - - def rm : MMXSS38I, - Sched<[sched.Folded]>; -} - -/// Binary MMX instructions requiring SSSE3. -let ImmT = NoImm, Constraints = "$src1 = $dst" in { -multiclass SS3I_binop_rm_int_mm opc, string OpcodeStr, - Intrinsic IntId64, X86FoldableSchedWrite sched, - bit Commutable = 0> { - let isCommutable = Commutable in - def rr : MMXSS38I, - Sched<[sched]>; - def rm : MMXSS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -/// PALIGN MMX instructions (require SSSE3). -multiclass ssse3_palign_mm { - def rri : MMXSS3AI<0x0F, MRMSrcReg, (outs VR64:$dst), - (ins VR64:$src1, VR64:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - [(set VR64:$dst, (IntId VR64:$src1, VR64:$src2, (i8 imm:$src3)))]>, - Sched<[sched]>; - def rmi : MMXSS3AI<0x0F, MRMSrcMem, (outs VR64:$dst), - (ins VR64:$src1, i64mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - [(set VR64:$dst, (IntId VR64:$src1, - (bitconvert (load_mmx addr:$src2)), (i8 imm:$src3)))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass sse12_cvt_pint opc, RegisterClass SrcRC, RegisterClass DstRC, - Intrinsic Int, X86MemOperand x86memop, PatFrag ld_frag, - string asm, X86FoldableSchedWrite sched, Domain d> { - def irr : MMXPI, - Sched<[sched]>; - def irm : MMXPI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_pint_3addr opc, RegisterClass SrcRC, - RegisterClass DstRC, Intrinsic Int, X86MemOperand x86memop, - PatFrag ld_frag, string asm, Domain d> { - def irr : MMXPI, - Sched<[WriteCvtI2PS]>; - def irm : MMXPI, - Sched<[WriteCvtI2PS.Folded]>; -} - -//===----------------------------------------------------------------------===// -// MMX EMMS Instruction -//===----------------------------------------------------------------------===// - -let SchedRW = [WriteEMMS] in -def MMX_EMMS : MMXI<0x77, RawFrm, (outs), (ins), "emms", [(int_x86_mmx_emms)]>; - -//===----------------------------------------------------------------------===// -// MMX Scalar Instructions -//===----------------------------------------------------------------------===// - -// Data Transfer Instructions -def MMX_MOVD64rr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (scalar_to_vector GR32:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -def MMX_MOVD64rm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (scalar_to_vector (loadi32 addr:$src))))]>, - Sched<[WriteVecLoad]>; - -let Predicates = [HasMMX] in { - def : Pat<(x86mmx (MMX_X86movw2d GR32:$src)), - (MMX_MOVD64rr GR32:$src)>; - def : Pat<(x86mmx (MMX_X86movw2d (i32 0))), - (MMX_SET0)>; - def : Pat<(x86mmx (MMX_X86movw2d (loadi32 addr:$src))), - (MMX_MOVD64rm addr:$src)>; -} - -let mayStore = 1 in -def MMX_MOVD64mr : MMXI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR64:$src), - "movd\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecStore]>; - -def MMX_MOVD64grr : MMXI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR64:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, - (MMX_X86movd2w (x86mmx VR64:$src)))]>, - Sched<[WriteVecMoveToGpr]>, FoldGenData<"MMX_MOVD64rr">; - -let isBitcast = 1 in -def MMX_MOVD64to64rr : MMXRI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, (bitconvert GR64:$src))]>, - Sched<[WriteVecMoveFromGpr]>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def MMX_MOVD64to64rm : MMXRI<0x6E, MRMSrcMem, (outs VR64:$dst), - (ins i64mem:$src), "movq\t{$src, $dst|$dst, $src}", - []>, Sched<[SchedWriteVecMoveLS.MMX.RM]>; - -let isBitcast = 1 in { -def MMX_MOVD64from64rr : MMXRI<0x7E, MRMDestReg, - (outs GR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert VR64:$src))]>, - Sched<[WriteVecMoveToGpr]>; -let SchedRW = [WriteVecMove], hasSideEffects = 0, isMoveReg = 1 in { -def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>; -let isCodeGenOnly = 1, ForceDisassemble = 1 in -def MMX_MOVQ64rr_REV : MMXI<0x7F, MRMDestReg, (outs VR64:$dst), (ins VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MMX_MOVQ64rr">; -} // SchedRW, hasSideEffects, isMoveReg -} // isBitcast - -def : InstAlias<"movq.s\t{$src, $dst|$dst, $src}", - (MMX_MOVQ64rr_REV VR64:$dst, VR64:$src), 0>; - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def MMX_MOVD64from64rm : MMXRI<0x7E, MRMDestMem, - (outs), (ins i64mem:$dst, VR64:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.MMX.MR]>; - -let SchedRW = [SchedWriteVecMoveLS.MMX.RM] in { -let canFoldAsLoad = 1 in -def MMX_MOVQ64rm : MMXI<0x6F, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, (load_mmx addr:$src))]>; -} // SchedRW - -let SchedRW = [SchedWriteVecMoveLS.MMX.MR] in -def MMX_MOVQ64mr : MMXI<0x7F, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (x86mmx VR64:$src), addr:$dst)]>; - -let SchedRW = [SchedWriteVecMoveLS.XMM.RR] in { -def MMX_MOVDQ2Qrr : MMXSDIi8<0xD6, MRMSrcReg, (outs VR64:$dst), - (ins VR128:$src), "movdq2q\t{$src, $dst|$dst, $src}", - [(set VR64:$dst, - (x86mmx (bitconvert - (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))))))]>; - -def MMX_MOVQ2DQrr : MMXS2SIi8<0xD6, MRMSrcReg, (outs VR128:$dst), - (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 - (scalar_to_vector - (i64 (bitconvert (x86mmx VR64:$src))))))]>; - -let isCodeGenOnly = 1, hasSideEffects = 1 in { -def MMX_MOVQ2FR64rr: MMXS2SIi8<0xD6, MRMSrcReg, (outs FR64:$dst), - (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", - []>; - -def MMX_MOVFR642Qrr: MMXSDIi8<0xD6, MRMSrcReg, (outs VR64:$dst), - (ins FR64:$src), "movdq2q\t{$src, $dst|$dst, $src}", - []>; -} -} // SchedRW - -let Predicates = [HasMMX, HasSSE1] in -def MMX_MOVNTQmr : MMXI<0xE7, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), - "movntq\t{$src, $dst|$dst, $src}", - [(int_x86_mmx_movnt_dq addr:$dst, VR64:$src)]>, - Sched<[SchedWriteVecMoveLSNT.MMX.MR]>; - -let Predicates = [HasMMX] in { - // movd to MMX register zero-extends - def : Pat<(x86mmx (X86vzmovl (x86mmx (scalar_to_vector GR32:$src)))), - (MMX_MOVD64rr GR32:$src)>; - def : Pat<(x86mmx (X86vzmovl (x86mmx (scalar_to_vector (loadi32 addr:$src))))), - (MMX_MOVD64rm addr:$src)>; -} - -// Arithmetic Instructions -defm MMX_PABSB : SS3I_unop_rm_int_mm<0x1C, "pabsb", int_x86_ssse3_pabs_b, - SchedWriteVecALU.MMX>; -defm MMX_PABSW : SS3I_unop_rm_int_mm<0x1D, "pabsw", int_x86_ssse3_pabs_w, - SchedWriteVecALU.MMX>; -defm MMX_PABSD : SS3I_unop_rm_int_mm<0x1E, "pabsd", int_x86_ssse3_pabs_d, - SchedWriteVecALU.MMX>; -// -- Addition -defm MMX_PADDB : MMXI_binop_rm_int<0xFC, "paddb", int_x86_mmx_padd_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDW : MMXI_binop_rm_int<0xFD, "paddw", int_x86_mmx_padd_w, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDD : MMXI_binop_rm_int<0xFE, "paddd", int_x86_mmx_padd_d, - SchedWriteVecALU.MMX, 1>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PADDQ : MMXI_binop_rm_int<0xD4, "paddq", int_x86_mmx_padd_q, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDSB : MMXI_binop_rm_int<0xEC, "paddsb" , int_x86_mmx_padds_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDSW : MMXI_binop_rm_int<0xED, "paddsw" , int_x86_mmx_padds_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PADDUSB : MMXI_binop_rm_int<0xDC, "paddusb", int_x86_mmx_paddus_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PADDUSW : MMXI_binop_rm_int<0xDD, "paddusw", int_x86_mmx_paddus_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PHADDW : SS3I_binop_rm_int_mm<0x01, "phaddw", int_x86_ssse3_phadd_w, - SchedWritePHAdd.MMX>; -defm MMX_PHADDD : SS3I_binop_rm_int_mm<0x02, "phaddd", int_x86_ssse3_phadd_d, - SchedWritePHAdd.MMX>; -defm MMX_PHADDSW : SS3I_binop_rm_int_mm<0x03, "phaddsw",int_x86_ssse3_phadd_sw, - SchedWritePHAdd.MMX>; - -// -- Subtraction -defm MMX_PSUBB : MMXI_binop_rm_int<0xF8, "psubb", int_x86_mmx_psub_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBW : MMXI_binop_rm_int<0xF9, "psubw", int_x86_mmx_psub_w, - SchedWriteVecALU.MMX>; -defm MMX_PSUBD : MMXI_binop_rm_int<0xFA, "psubd", int_x86_mmx_psub_d, - SchedWriteVecALU.MMX>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PSUBQ : MMXI_binop_rm_int<0xFB, "psubq", int_x86_mmx_psub_q, - SchedWriteVecALU.MMX>; - -defm MMX_PSUBSB : MMXI_binop_rm_int<0xE8, "psubsb" , int_x86_mmx_psubs_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBSW : MMXI_binop_rm_int<0xE9, "psubsw" , int_x86_mmx_psubs_w, - SchedWriteVecALU.MMX>; - -defm MMX_PSUBUSB : MMXI_binop_rm_int<0xD8, "psubusb", int_x86_mmx_psubus_b, - SchedWriteVecALU.MMX>; -defm MMX_PSUBUSW : MMXI_binop_rm_int<0xD9, "psubusw", int_x86_mmx_psubus_w, - SchedWriteVecALU.MMX>; - -defm MMX_PHSUBW : SS3I_binop_rm_int_mm<0x05, "phsubw", int_x86_ssse3_phsub_w, - SchedWritePHAdd.MMX>; -defm MMX_PHSUBD : SS3I_binop_rm_int_mm<0x06, "phsubd", int_x86_ssse3_phsub_d, - SchedWritePHAdd.MMX>; -defm MMX_PHSUBSW : SS3I_binop_rm_int_mm<0x07, "phsubsw",int_x86_ssse3_phsub_sw, - SchedWritePHAdd.MMX>; - -// -- Multiplication -defm MMX_PMULLW : MMXI_binop_rm_int<0xD5, "pmullw", int_x86_mmx_pmull_w, - SchedWriteVecIMul.MMX, 1>; - -defm MMX_PMULHW : MMXI_binop_rm_int<0xE5, "pmulhw", int_x86_mmx_pmulh_w, - SchedWriteVecIMul.MMX, 1>; -let Predicates = [HasMMX, HasSSE1] in -defm MMX_PMULHUW : MMXI_binop_rm_int<0xE4, "pmulhuw", int_x86_mmx_pmulhu_w, - SchedWriteVecIMul.MMX, 1>; -let Predicates = [HasMMX, HasSSE2] in -defm MMX_PMULUDQ : MMXI_binop_rm_int<0xF4, "pmuludq", int_x86_mmx_pmulu_dq, - SchedWriteVecIMul.MMX, 1>; -defm MMX_PMULHRSW : SS3I_binop_rm_int_mm<0x0B, "pmulhrsw", - int_x86_ssse3_pmul_hr_sw, - SchedWriteVecIMul.MMX, 1>; - -// -- Miscellanea -defm MMX_PMADDWD : MMXI_binop_rm_int<0xF5, "pmaddwd", int_x86_mmx_pmadd_wd, - SchedWriteVecIMul.MMX, 1>; - -defm MMX_PMADDUBSW : SS3I_binop_rm_int_mm<0x04, "pmaddubsw", - int_x86_ssse3_pmadd_ub_sw, - SchedWriteVecIMul.MMX>; -let Predicates = [HasMMX, HasSSE1] in { -defm MMX_PAVGB : MMXI_binop_rm_int<0xE0, "pavgb", int_x86_mmx_pavg_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PAVGW : MMXI_binop_rm_int<0xE3, "pavgw", int_x86_mmx_pavg_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PMINUB : MMXI_binop_rm_int<0xDA, "pminub", int_x86_mmx_pminu_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PMINSW : MMXI_binop_rm_int<0xEA, "pminsw", int_x86_mmx_pmins_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PMAXUB : MMXI_binop_rm_int<0xDE, "pmaxub", int_x86_mmx_pmaxu_b, - SchedWriteVecALU.MMX, 1>; -defm MMX_PMAXSW : MMXI_binop_rm_int<0xEE, "pmaxsw", int_x86_mmx_pmaxs_w, - SchedWriteVecALU.MMX, 1>; - -defm MMX_PSADBW : MMXI_binop_rm_int<0xF6, "psadbw", int_x86_mmx_psad_bw, - SchedWritePSADBW.MMX, 1>; -} - -defm MMX_PSIGNB : SS3I_binop_rm_int_mm<0x08, "psignb", int_x86_ssse3_psign_b, - SchedWriteVecALU.MMX>; -defm MMX_PSIGNW : SS3I_binop_rm_int_mm<0x09, "psignw", int_x86_ssse3_psign_w, - SchedWriteVecALU.MMX>; -defm MMX_PSIGND : SS3I_binop_rm_int_mm<0x0A, "psignd", int_x86_ssse3_psign_d, - SchedWriteVecALU.MMX>; -let Constraints = "$src1 = $dst" in - defm MMX_PALIGNR : ssse3_palign_mm<"palignr", int_x86_mmx_palignr_b, - SchedWriteShuffle.MMX>; - -// Logical Instructions -defm MMX_PAND : MMXI_binop_rm_int<0xDB, "pand", int_x86_mmx_pand, - SchedWriteVecLogic.MMX, 1>; -defm MMX_POR : MMXI_binop_rm_int<0xEB, "por" , int_x86_mmx_por, - SchedWriteVecLogic.MMX, 1>; -defm MMX_PXOR : MMXI_binop_rm_int<0xEF, "pxor", int_x86_mmx_pxor, - SchedWriteVecLogic.MMX, 1>; -defm MMX_PANDN : MMXI_binop_rm_int<0xDF, "pandn", int_x86_mmx_pandn, - SchedWriteVecLogic.MMX>; - -// Shift Instructions -defm MMX_PSRLW : MMXI_binop_rmi_int<0xD1, 0x71, MRM2r, "psrlw", - int_x86_mmx_psrl_w, int_x86_mmx_psrli_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRLD : MMXI_binop_rmi_int<0xD2, 0x72, MRM2r, "psrld", - int_x86_mmx_psrl_d, int_x86_mmx_psrli_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRLQ : MMXI_binop_rmi_int<0xD3, 0x73, MRM2r, "psrlq", - int_x86_mmx_psrl_q, int_x86_mmx_psrli_q, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -defm MMX_PSLLW : MMXI_binop_rmi_int<0xF1, 0x71, MRM6r, "psllw", - int_x86_mmx_psll_w, int_x86_mmx_pslli_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSLLD : MMXI_binop_rmi_int<0xF2, 0x72, MRM6r, "pslld", - int_x86_mmx_psll_d, int_x86_mmx_pslli_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSLLQ : MMXI_binop_rmi_int<0xF3, 0x73, MRM6r, "psllq", - int_x86_mmx_psll_q, int_x86_mmx_pslli_q, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -defm MMX_PSRAW : MMXI_binop_rmi_int<0xE1, 0x71, MRM4r, "psraw", - int_x86_mmx_psra_w, int_x86_mmx_psrai_w, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; -defm MMX_PSRAD : MMXI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad", - int_x86_mmx_psra_d, int_x86_mmx_psrai_d, - SchedWriteVecShift.MMX, - SchedWriteVecShiftImm.MMX>; - -// Comparison Instructions -defm MMX_PCMPEQB : MMXI_binop_rm_int<0x74, "pcmpeqb", int_x86_mmx_pcmpeq_b, - SchedWriteVecALU.MMX>; -defm MMX_PCMPEQW : MMXI_binop_rm_int<0x75, "pcmpeqw", int_x86_mmx_pcmpeq_w, - SchedWriteVecALU.MMX>; -defm MMX_PCMPEQD : MMXI_binop_rm_int<0x76, "pcmpeqd", int_x86_mmx_pcmpeq_d, - SchedWriteVecALU.MMX>; - -defm MMX_PCMPGTB : MMXI_binop_rm_int<0x64, "pcmpgtb", int_x86_mmx_pcmpgt_b, - SchedWriteVecALU.MMX>; -defm MMX_PCMPGTW : MMXI_binop_rm_int<0x65, "pcmpgtw", int_x86_mmx_pcmpgt_w, - SchedWriteVecALU.MMX>; -defm MMX_PCMPGTD : MMXI_binop_rm_int<0x66, "pcmpgtd", int_x86_mmx_pcmpgt_d, - SchedWriteVecALU.MMX>; - -// -- Unpack Instructions -defm MMX_PUNPCKHBW : MMXI_binop_rm_int<0x68, "punpckhbw", - int_x86_mmx_punpckhbw, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKHWD : MMXI_binop_rm_int<0x69, "punpckhwd", - int_x86_mmx_punpckhwd, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKHDQ : MMXI_binop_rm_int<0x6A, "punpckhdq", - int_x86_mmx_punpckhdq, - SchedWriteShuffle.MMX>; -defm MMX_PUNPCKLBW : MMXI_binop_rm_int<0x60, "punpcklbw", - int_x86_mmx_punpcklbw, - SchedWriteShuffle.MMX, - 0, i32mem>; -defm MMX_PUNPCKLWD : MMXI_binop_rm_int<0x61, "punpcklwd", - int_x86_mmx_punpcklwd, - SchedWriteShuffle.MMX, - 0, i32mem>; -defm MMX_PUNPCKLDQ : MMXI_binop_rm_int<0x62, "punpckldq", - int_x86_mmx_punpckldq, - SchedWriteShuffle.MMX, - 0, i32mem>; - -// -- Pack Instructions -defm MMX_PACKSSWB : MMXI_binop_rm_int<0x63, "packsswb", int_x86_mmx_packsswb, - SchedWriteShuffle.MMX>; -defm MMX_PACKSSDW : MMXI_binop_rm_int<0x6B, "packssdw", int_x86_mmx_packssdw, - SchedWriteShuffle.MMX>; -defm MMX_PACKUSWB : MMXI_binop_rm_int<0x67, "packuswb", int_x86_mmx_packuswb, - SchedWriteShuffle.MMX>; - -// -- Shuffle Instructions -defm MMX_PSHUFB : SS3I_binop_rm_int_mm<0x00, "pshufb", int_x86_ssse3_pshuf_b, - SchedWriteVarShuffle.MMX>; - -def MMX_PSHUFWri : MMXIi8<0x70, MRMSrcReg, - (outs VR64:$dst), (ins VR64:$src1, u8imm:$src2), - "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR64:$dst, - (int_x86_sse_pshuf_w VR64:$src1, imm:$src2))]>, - Sched<[SchedWriteShuffle.MMX]>; -def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, - (outs VR64:$dst), (ins i64mem:$src1, u8imm:$src2), - "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR64:$dst, - (int_x86_sse_pshuf_w (load_mmx addr:$src1), - imm:$src2))]>, - Sched<[SchedWriteShuffle.MMX.Folded]>; - -// -- Conversion Instructions -defm MMX_CVTPS2PI : sse12_cvt_pint<0x2D, VR128, VR64, int_x86_sse_cvtps2pi, - f64mem, load, "cvtps2pi\t{$src, $dst|$dst, $src}", - WriteCvtPS2I, SSEPackedSingle>, PS; -defm MMX_CVTPD2PI : sse12_cvt_pint<0x2D, VR128, VR64, int_x86_sse_cvtpd2pi, - f128mem, memop, "cvtpd2pi\t{$src, $dst|$dst, $src}", - WriteCvtPD2I, SSEPackedDouble>, PD; -defm MMX_CVTTPS2PI : sse12_cvt_pint<0x2C, VR128, VR64, int_x86_sse_cvttps2pi, - f64mem, load, "cvttps2pi\t{$src, $dst|$dst, $src}", - WriteCvtPS2I, SSEPackedSingle>, PS; -defm MMX_CVTTPD2PI : sse12_cvt_pint<0x2C, VR128, VR64, int_x86_sse_cvttpd2pi, - f128mem, memop, "cvttpd2pi\t{$src, $dst|$dst, $src}", - WriteCvtPD2I, SSEPackedDouble>, PD; -defm MMX_CVTPI2PD : sse12_cvt_pint<0x2A, VR64, VR128, int_x86_sse_cvtpi2pd, - i64mem, load, "cvtpi2pd\t{$src, $dst|$dst, $src}", - WriteCvtI2PD, SSEPackedDouble>, PD; -let Constraints = "$src1 = $dst" in { - defm MMX_CVTPI2PS : sse12_cvt_pint_3addr<0x2A, VR64, VR128, - int_x86_sse_cvtpi2ps, - i64mem, load, "cvtpi2ps\t{$src2, $dst|$dst, $src2}", - SSEPackedSingle>, PS; -} - -// Extract / Insert -let Predicates = [HasMMX, HasSSE1] in -def MMX_PEXTRWrr: MMXIi8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR64:$src1, i32u8imm:$src2), - "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (int_x86_mmx_pextr_w VR64:$src1, - imm:$src2))]>, - Sched<[WriteVecExtract]>; -let Constraints = "$src1 = $dst" in { -let Predicates = [HasMMX, HasSSE1] in { - def MMX_PINSRWrr : MMXIi8<0xC4, MRMSrcReg, - (outs VR64:$dst), - (ins VR64:$src1, GR32orGR64:$src2, i32u8imm:$src3), - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR64:$dst, (int_x86_mmx_pinsr_w VR64:$src1, - GR32orGR64:$src2, imm:$src3))]>, - Sched<[WriteVecInsert]>; - - def MMX_PINSRWrm : MMXIi8<0xC4, MRMSrcMem, - (outs VR64:$dst), - (ins VR64:$src1, i16mem:$src2, i32u8imm:$src3), - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR64:$dst, (int_x86_mmx_pinsr_w VR64:$src1, - (i32 (anyext (loadi16 addr:$src2))), - imm:$src3))]>, - Sched<[WriteVecInsertLd, ReadAfterLd]>; -} -} - -// Mask creation -let Predicates = [HasMMX, HasSSE1] in -def MMX_PMOVMSKBrr : MMXI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR64:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, - (int_x86_mmx_pmovmskb VR64:$src))]>, - Sched<[WriteMMXMOVMSK]>; - -// Low word of XMM to MMX. -def MMX_X86movdq2q : SDNode<"X86ISD::MOVDQ2Q", SDTypeProfile<1, 1, - [SDTCisVT<0, x86mmx>, SDTCisVT<1, v2i64>]>>; - -def : Pat<(x86mmx (MMX_X86movdq2q VR128:$src)), - (x86mmx (MMX_MOVDQ2Qrr VR128:$src))>; - -def : Pat<(x86mmx (MMX_X86movdq2q (loadv2i64 addr:$src))), - (x86mmx (MMX_MOVQ64rm addr:$src))>; - -// Misc. -let SchedRW = [SchedWriteShuffle.MMX] in { -let Uses = [EDI], Predicates = [HasMMX, HasSSE1,Not64BitMode] in -def MMX_MASKMOVQ : MMXI32<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), - "maskmovq\t{$mask, $src|$src, $mask}", - [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, EDI)]>; -let Uses = [RDI], Predicates = [HasMMX, HasSSE1,In64BitMode] in -def MMX_MASKMOVQ64: MMXI64<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), - "maskmovq\t{$mask, $src|$src, $mask}", - [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, RDI)]>; -} - -// 64-bit bit convert. -let Predicates = [HasMMX, HasSSE2] in { -def : Pat<(f64 (bitconvert (x86mmx VR64:$src))), - (MMX_MOVQ2FR64rr VR64:$src)>; -def : Pat<(x86mmx (bitconvert (f64 FR64:$src))), - (MMX_MOVFR642Qrr FR64:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvtp2Int (v4f32 VR128:$src)))))), - (MMX_CVTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvttp2si (v4f32 VR128:$src)))))), - (MMX_CVTTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (fp_to_sint (v4f32 VR128:$src)))))), - (MMX_CVTTPS2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (MMX_CVTPD2PIirr VR128:$src)>; -def : Pat<(x86mmx (MMX_X86movdq2q - (bc_v2i64 (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (MMX_CVTTPD2PIirr VR128:$src)>; -} diff --git a/suite/synctools/tablegen/X86/back/X86InstrMPX.td b/suite/synctools/tablegen/X86/back/X86InstrMPX.td deleted file mode 100644 index c1a8cc7c5f..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrMPX.td +++ /dev/null @@ -1,80 +0,0 @@ -//===-- X86InstrMPX.td - MPX Instruction Set ---------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 MPX instruction set, defining the -// instructions, and properties of the instructions which are needed for code -// generation, machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -// FIXME: Investigate a better scheduler class once MPX is used inside LLVM. -let SchedRW = [WriteSystem] in { - -multiclass mpx_bound_make opc, string OpcodeStr> { - def 32rm: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rm: I, - Requires<[HasMPX, In64BitMode]>; -} - -defm BNDMK : mpx_bound_make<0x1B, "bndmk">, XS; - -multiclass mpx_bound_check opc, string OpcodeStr> { - def 32rm: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rm: I, - Requires<[HasMPX, In64BitMode]>; - - def 32rr: I, - Requires<[HasMPX, Not64BitMode]>; - def 64rr: I, - Requires<[HasMPX, In64BitMode]>; -} -defm BNDCL : mpx_bound_check<0x1A, "bndcl">, XS, NotMemoryFoldable; -defm BNDCU : mpx_bound_check<0x1A, "bndcu">, XD, NotMemoryFoldable; -defm BNDCN : mpx_bound_check<0x1B, "bndcn">, XD, NotMemoryFoldable; - -def BNDMOVrr : I<0x1A, MRMSrcReg, (outs BNDR:$dst), (ins BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX]>, NotMemoryFoldable; -let mayLoad = 1 in { -def BNDMOV32rm : I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins i64mem:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, Not64BitMode]>, NotMemoryFoldable; -def BNDMOV64rm : I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins i128mem:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, In64BitMode]>, NotMemoryFoldable; -} -let isCodeGenOnly = 1, ForceDisassemble = 1 in -def BNDMOVrr_REV : I<0x1B, MRMDestReg, (outs BNDR:$dst), (ins BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX]>, NotMemoryFoldable; -let mayStore = 1 in { -def BNDMOV32mr : I<0x1B, MRMDestMem, (outs), (ins i64mem:$dst, BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, Not64BitMode]>, NotMemoryFoldable; -def BNDMOV64mr : I<0x1B, MRMDestMem, (outs), (ins i128mem:$dst, BNDR:$src), - "bndmov\t{$src, $dst|$dst, $src}", []>, PD, - Requires<[HasMPX, In64BitMode]>, NotMemoryFoldable; - -def BNDSTXmr: I<0x1B, MRMDestMem, (outs), (ins anymem:$dst, BNDR:$src), - "bndstx\t{$src, $dst|$dst, $src}", []>, PS, - Requires<[HasMPX]>; -} -let mayLoad = 1 in -def BNDLDXrm: I<0x1A, MRMSrcMem, (outs BNDR:$dst), (ins anymem:$src), - "bndldx\t{$src, $dst|$dst, $src}", []>, PS, - Requires<[HasMPX]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrSGX.td b/suite/synctools/tablegen/X86/back/X86InstrSGX.td deleted file mode 100644 index 488cc44380..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrSGX.td +++ /dev/null @@ -1,30 +0,0 @@ -//===-- X86InstrSGX.td - SGX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel SGX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SGX instructions - -let SchedRW = [WriteSystem], Predicates = [HasSGX] in { -// ENCLS - Execute an Enclave System Function of Specified Leaf Number -def ENCLS : I<0x01, MRM_CF, (outs), (ins), - "encls", []>, TB; - -// ENCLU - Execute an Enclave User Function of Specified Leaf Number -def ENCLU : I<0x01, MRM_D7, (outs), (ins), - "enclu", []>, TB; - -// ENCLV - Execute an Enclave VMM Function of Specified Leaf Number -def ENCLV : I<0x01, MRM_C0, (outs), (ins), - "enclv", []>, TB; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrSSE.td b/suite/synctools/tablegen/X86/back/X86InstrSSE.td deleted file mode 100644 index 54db88114a..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrSSE.td +++ /dev/null @@ -1,8256 +0,0 @@ -//===-- X86InstrSSE.td - SSE Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 SSE instruction set, defining the instructions, -// and properties of the instructions which are needed for code generation, -// machine code emission, and analysis. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 Instructions Classes -//===----------------------------------------------------------------------===// - -/// sse12_fp_scalar - SSE 1 & 2 scalar instructions class -multiclass sse12_fp_scalar opc, string OpcodeStr, SDNode OpNode, - RegisterClass RC, X86MemOperand x86memop, - Domain d, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in { - def rr : SI, - Sched<[sched]>; - } - def rm : SI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// sse12_fp_scalar_int - SSE 1 & 2 scalar instructions intrinsics class -multiclass sse12_fp_scalar_int opc, string OpcodeStr, - SDPatternOperator OpNode, RegisterClass RC, - ValueType VT, string asm, Operand memopr, - ComplexPattern mem_cpat, Domain d, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { -let isCodeGenOnly = 1, hasSideEffects = 0 in { - def rr_Int : SI_Int, - Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : SI_Int, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -/// sse12_fp_packed - SSE 1 & 2 packed instructions class -multiclass sse12_fp_packed opc, string OpcodeStr, SDNode OpNode, - RegisterClass RC, ValueType vt, - X86MemOperand x86memop, PatFrag mem_frag, - Domain d, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : PI, - Sched<[sched]>; - let mayLoad = 1 in - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// sse12_fp_packed_logical_rm - SSE 1 & 2 packed instructions class -multiclass sse12_fp_packed_logical_rm opc, RegisterClass RC, Domain d, - string OpcodeStr, X86MemOperand x86memop, - X86FoldableSchedWrite sched, - list pat_rr, list pat_rm, - bit Is2Addr = 1> { - let isCommutable = 1, hasSideEffects = 0 in - def rr : PI, - Sched<[sched]>; - let hasSideEffects = 0, mayLoad = 1 in - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - - -/* -// Alias instructions that map fld0 to xorps for sse or vxorps for avx. -// This is expanded by ExpandPostRAPseudos. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { - def FsFLD0SS : I<0, Pseudo, (outs FR32:$dst), (ins), "", - [(set FR32:$dst, fp32imm0)]>, Requires<[HasSSE1, NoAVX512]>; - def FsFLD0SD : I<0, Pseudo, (outs FR64:$dst), (ins), "", - [(set FR64:$dst, fpimm0)]>, Requires<[HasSSE2, NoAVX512]>; -} -*/ - -//===----------------------------------------------------------------------===// -// AVX & SSE - Zero/One Vectors -//===----------------------------------------------------------------------===// - -// Alias instruction that maps zero vector to pxor / xorp* for sse. -// This is expanded by ExpandPostRAPseudos to an xorps / vxorps, and then -// swizzled by ExecutionDomainFix to pxor. -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { -def V_SET0 : I<0, Pseudo, (outs VR128:$dst), (ins), "", - [(set VR128:$dst, (v4f32 immAllZerosV))]>; -} - -let Predicates = [NoAVX512] in -def : Pat<(v4i32 immAllZerosV), (V_SET0)>; - - -// The same as done above but for AVX. The 256-bit AVX1 ISA doesn't support PI, -// and doesn't need it because on sandy bridge the register is set to zero -// at the rename stage without using any execution unit, so SET0PSY -// and SET0PDY can be used for vector int instructions without penalty -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, Predicates = [NoAVX512], SchedRW = [WriteZero] in { -def AVX_SET0 : I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllZerosV))]>; -} - -// We set canFoldAsLoad because this can be converted to a constant-pool -// load of an all-ones value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, - isPseudo = 1, SchedRW = [WriteZero] in { - def V_SETALLONES : I<0, Pseudo, (outs VR128:$dst), (ins), "", - [(set VR128:$dst, (v4i32 immAllOnesV))]>; - let Predicates = [HasAVX1Only, OptForMinSize] in { - def AVX1_SETALLONES: I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllOnesV))]>; - } - let Predicates = [HasAVX2] in - def AVX2_SETALLONES : I<0, Pseudo, (outs VR256:$dst), (ins), "", - [(set VR256:$dst, (v8i32 immAllOnesV))]>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move FP Scalar Instructions -// -// Move Instructions. Register-to-register movss/movsd is not used for FR32/64 -// register copies because it's a partial register update; Register-to-register -// movss/movsd is not modeled as an INSERT_SUBREG because INSERT_SUBREG requires -// that the insert be implementable in terms of a copy, and just mentioned, we -// don't use movss/movsd for copies. -//===----------------------------------------------------------------------===// - -multiclass sse12_move_rr { - let isCommutable = 1 in - def rr : SI<0x10, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - !strconcat(base_opc, asm_opr), - [(set VR128:$dst, (vt (OpNode VR128:$src1, VR128:$src2)))], d>, - Sched<[SchedWriteFShuffle.XMM]>; - - // For the disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - !strconcat(base_opc, asm_opr), []>, - Sched<[SchedWriteFShuffle.XMM]>, FoldGenData; -} - -multiclass sse12_move { - // AVX - let Predicates = [UseAVX, OptForSize] in - defm V#NAME : sse12_move_rr, - VEX_4V, VEX_LIG, VEX_WIG; - - def V#NAME#mr : SI<0x11, MRMDestMem, (outs), (ins x86memop:$dst, RC:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(store RC:$src, addr:$dst)], d>, - VEX, VEX_LIG, Sched<[WriteFStore]>, VEX_WIG; - // SSE1 & 2 - let Constraints = "$src1 = $dst" in { - let Predicates = [pred, NoSSE41_Or_OptForSize] in - defm NAME : sse12_move_rr; - } - - def NAME#mr : SI<0x11, MRMDestMem, (outs), (ins x86memop:$dst, RC:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(store RC:$src, addr:$dst)], d>, - Sched<[WriteFStore]>; - - def : InstAlias<"v"#OpcodeStr#".s\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (!cast("V"#NAME#"rr_REV") - VR128:$dst, VR128:$src1, VR128:$src2), 0>; - def : InstAlias(NAME#"rr_REV") - VR128:$dst, VR128:$src2), 0>; -} - -// Loading from memory automatically zeroing upper bits. -multiclass sse12_move_rm { - def V#NAME#rm : SI<0x10, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set RC:$dst, (mem_pat addr:$src))], d>, - VEX, VEX_LIG, Sched<[WriteFLoad]>, VEX_WIG; - def NAME#rm : SI<0x10, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set RC:$dst, (mem_pat addr:$src))], d>, - Sched<[WriteFLoad]>; -} - -defm MOVSS : sse12_move, XS; -defm MOVSD : sse12_move, XD; - -let canFoldAsLoad = 1, isReMaterializable = 1 in { - defm MOVSS : sse12_move_rm, XS; - defm MOVSD : sse12_move_rm, XD; -} - -// Patterns -let Predicates = [UseAVX] in { - // MOVSSrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSSrm addr:$src), VR128)>; - - // MOVSDrm zeros the high parts of the register; represent this - // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (VMOVSDrm addr:$src), VR128)>; - - // Represent the same patterns above but in the form they appear for - // 256-bit types - def : Pat<(v8f32 (X86vzmovl (insert_subvector undef, - (v4f32 (scalar_to_vector (loadf32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_xmm)>; - def : Pat<(v8f32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzmovl (insert_subvector undef, - (v2f64 (scalar_to_vector (loadf64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_xmm)>; - def : Pat<(v4f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_xmm)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - addr:$dst), - (VMOVSSmr addr:$dst, (COPY_TO_REGCLASS (v4f32 VR128:$src), FR32))>; -} - -let Predicates = [UseAVX, OptForSize] in { - // Move scalar to XMM zero-extended, zeroing a VR128 then do a - // MOVSS to the lower bits. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (VMOVSSrr (v4f32 (V_SET0)), VR128:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (VMOVSSrr (v4i32 (V_SET0)), VR128:$src)>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VMOVSSrr (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), sub_xmm)))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VMOVSSrr (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256:$src), sub_xmm)))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VMOVSDrr (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), sub_xmm)))), - sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VMOVSDrr (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256:$src), sub_xmm)))), - sub_xmm)>; -} - -let Predicates = [UseSSE1] in { - let Predicates = [UseSSE1, NoSSE41_Or_OptForSize] in { - // Move scalar to XMM zero-extended, zeroing a VR128 then do a - // MOVSS to the lower bits. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (MOVSSrr (v4f32 (V_SET0)), VR128:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (MOVSSrr (v4i32 (V_SET0)), VR128:$src)>; - } - - // MOVSSrm already zeros the high parts of the register. - def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - def : Pat<(v4f32 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (MOVSSrm addr:$src), VR128)>; - - // Extract and store. - def : Pat<(store (f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - addr:$dst), - (MOVSSmr addr:$dst, (COPY_TO_REGCLASS VR128:$src, FR32))>; -} - -let Predicates = [UseSSE2] in { - // MOVSDrm already zeros the high parts of the register. - def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; - def : Pat<(v2f64 (X86vzload addr:$src)), - (COPY_TO_REGCLASS (MOVSDrm addr:$src), VR128)>; -} - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -def : InstAlias<"vmovss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (VMOVSSrr_REV VR128L:$dst, VR128:$src1, VR128H:$src2), 0>; -def : InstAlias<"vmovsd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (VMOVSDrr_REV VR128L:$dst, VR128:$src1, VR128H:$src2), 0>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Aligned/Unaligned FP Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_mov_packed opc, RegisterClass RC, - X86MemOperand x86memop, PatFrag ld_frag, - string asm, Domain d, - X86SchedWriteMoveLS sched> { -let hasSideEffects = 0, isMoveReg = 1 in - def rr : PI, - Sched<[sched.RR]>; -let canFoldAsLoad = 1, isReMaterializable = 1 in - def rm : PI, - Sched<[sched.RM]>; -} - -let Predicates = [HasAVX, NoVLX] in { -defm VMOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS, VEX, VEX_WIG; -defm VMOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD, VEX, VEX_WIG; -defm VMOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS, VEX, VEX_WIG; -defm VMOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD, VEX, VEX_WIG; - -defm VMOVAPSY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv8f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.YMM>, - PS, VEX, VEX_L, VEX_WIG; -defm VMOVAPDY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv4f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.YMM>, - PD, VEX, VEX_L, VEX_WIG; -defm VMOVUPSY : sse12_mov_packed<0x10, VR256, f256mem, loadv8f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.YMM>, - PS, VEX, VEX_L, VEX_WIG; -defm VMOVUPDY : sse12_mov_packed<0x10, VR256, f256mem, loadv4f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.YMM>, - PD, VEX, VEX_L, VEX_WIG; -} - -let Predicates = [UseSSE1] in { -defm MOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS; -defm MOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32, "movups", - SSEPackedSingle, SchedWriteFMoveLS.XMM>, - PS; -} -let Predicates = [UseSSE2] in { -defm MOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, "movapd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD; -defm MOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64, "movupd", - SSEPackedDouble, SchedWriteFMoveLS.XMM>, - PD; -} - -let Predicates = [HasAVX, NoVLX] in { -let SchedRW = [SchedWriteFMoveLS.XMM.MR] in { -def VMOVAPSmr : VPSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f32 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVAPDmr : VPDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v2f64 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVUPSmr : VPSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v4f32 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVUPDmr : VPDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v2f64 VR128:$src), addr:$dst)]>, - VEX, VEX_WIG; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLS.YMM.MR] in { -def VMOVAPSYmr : VPSI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v8f32 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVAPDYmr : VPDI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f64 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVUPSYmr : VPSI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v8f32 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -def VMOVUPDYmr : VPDI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v4f64 VR256:$src), addr:$dst)]>, - VEX, VEX_L, VEX_WIG; -} // SchedRW -} // Predicate - -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - isMoveReg = 1 in { -let SchedRW = [SchedWriteFMoveLS.XMM.RR] in { - def VMOVAPSrr_REV : VPSI<0x29, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVAPSrr">; - def VMOVAPDrr_REV : VPDI<0x29, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVAPDrr">; - def VMOVUPSrr_REV : VPSI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVUPSrr">; - def VMOVUPDrr_REV : VPDI<0x11, MRMDestReg, (outs VR128:$dst), - (ins VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_WIG, FoldGenData<"VMOVUPDrr">; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLS.YMM.RR] in { - def VMOVAPSYrr_REV : VPSI<0x29, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVAPSYrr">; - def VMOVAPDYrr_REV : VPDI<0x29, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVAPDYrr">; - def VMOVUPSYrr_REV : VPSI<0x11, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVUPSYrr">; - def VMOVUPDYrr_REV : VPDI<0x11, MRMDestReg, (outs VR256:$dst), - (ins VR256:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVUPDYrr">; -} // SchedRW -} // Predicate - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -def : InstAlias<"vmovaps\t{$src, $dst|$dst, $src}", - (VMOVAPSrr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovapd\t{$src, $dst|$dst, $src}", - (VMOVAPDrr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovups\t{$src, $dst|$dst, $src}", - (VMOVUPSrr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovupd\t{$src, $dst|$dst, $src}", - (VMOVUPDrr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovaps\t{$src, $dst|$dst, $src}", - (VMOVAPSYrr_REV VR256L:$dst, VR256H:$src), 0>; -def : InstAlias<"vmovapd\t{$src, $dst|$dst, $src}", - (VMOVAPDYrr_REV VR256L:$dst, VR256H:$src), 0>; -def : InstAlias<"vmovups\t{$src, $dst|$dst, $src}", - (VMOVUPSYrr_REV VR256L:$dst, VR256H:$src), 0>; -def : InstAlias<"vmovupd\t{$src, $dst|$dst, $src}", - (VMOVUPDYrr_REV VR256L:$dst, VR256H:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -def : InstAlias<"vmovaps.s\t{$src, $dst|$dst, $src}", - (VMOVAPSrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovapd.s\t{$src, $dst|$dst, $src}", - (VMOVAPDrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovups.s\t{$src, $dst|$dst, $src}", - (VMOVUPSrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovupd.s\t{$src, $dst|$dst, $src}", - (VMOVUPDrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovaps.s\t{$src, $dst|$dst, $src}", - (VMOVAPSYrr_REV VR256:$dst, VR256:$src), 0>; -def : InstAlias<"vmovapd.s\t{$src, $dst|$dst, $src}", - (VMOVAPDYrr_REV VR256:$dst, VR256:$src), 0>; -def : InstAlias<"vmovups.s\t{$src, $dst|$dst, $src}", - (VMOVUPSYrr_REV VR256:$dst, VR256:$src), 0>; -def : InstAlias<"vmovupd.s\t{$src, $dst|$dst, $src}", - (VMOVUPDYrr_REV VR256:$dst, VR256:$src), 0>; - -let SchedRW = [SchedWriteFMoveLS.XMM.MR] in { -def MOVAPSmr : PSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", - [(alignedstore (v4f32 VR128:$src), addr:$dst)]>; -def MOVAPDmr : PDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", - [(alignedstore (v2f64 VR128:$src), addr:$dst)]>; -def MOVUPSmr : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movups\t{$src, $dst|$dst, $src}", - [(store (v4f32 VR128:$src), addr:$dst)]>; -def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(store (v2f64 VR128:$src), addr:$dst)]>; -} // SchedRW - -// For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - isMoveReg = 1, SchedRW = [SchedWriteFMoveLS.XMM.RR] in { - def MOVAPSrr_REV : PSI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movaps\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVAPSrr">; - def MOVAPDrr_REV : PDI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movapd\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVAPDrr">; - def MOVUPSrr_REV : PSI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movups\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVUPSrr">; - def MOVUPDrr_REV : PDI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVUPDrr">; -} - -// Reversed version with ".s" suffix for GAS compatibility. -def : InstAlias<"movaps.s\t{$src, $dst|$dst, $src}", - (MOVAPSrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"movapd.s\t{$src, $dst|$dst, $src}", - (MOVAPDrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"movups.s\t{$src, $dst|$dst, $src}", - (MOVUPSrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"movupd.s\t{$src, $dst|$dst, $src}", - (MOVUPDrr_REV VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in { - // 256-bit load/store need to use floating point load/store in case we don't - // have AVX2. Execution domain fixing will convert to integer if AVX2 is - // available and changing the domain is beneficial. - def : Pat<(alignedloadv4i64 addr:$src), - (VMOVAPSYrm addr:$src)>; - def : Pat<(loadv4i64 addr:$src), - (VMOVUPSYrm addr:$src)>; - def : Pat<(alignedstore (v4i64 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v8i32 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v16i16 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(alignedstore (v32i8 VR256:$src), addr:$dst), - (VMOVAPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v4i64 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v8i32 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v16i16 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; - def : Pat<(store (v32i8 VR256:$src), addr:$dst), - (VMOVUPSYmr addr:$dst, VR256:$src)>; -} - -// Use movaps / movups for SSE integer load / store (one byte shorter). -// The instructions selected below are then converted to MOVDQA/MOVDQU -// during the SSE domain pass. -let Predicates = [UseSSE1] in { - def : Pat<(alignedloadv2i64 addr:$src), - (MOVAPSrm addr:$src)>; - def : Pat<(loadv2i64 addr:$src), - (MOVUPSrm addr:$src)>; - - def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v2i64 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v4i32 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v8i16 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; - def : Pat<(store (v16i8 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Low packed FP Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_mov_hilo_packed_baseopc, SDNode pdnode, - string base_opc, string asm_opr> { - // No pattern as they need be special cased between high and low. - let hasSideEffects = 0, mayLoad = 1 in - def PSrm : PI, PS, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; - - def PDrm : PI, PD, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -multiclass sse12_mov_hilo_packedopc, SDPatternOperator pdnode, - string base_opc> { - let Predicates = [UseAVX] in - defm V#NAME : sse12_mov_hilo_packed_base, - VEX_4V, VEX_WIG; - - let Constraints = "$src1 = $dst" in - defm NAME : sse12_mov_hilo_packed_base; -} - -defm MOVL : sse12_mov_hilo_packed<0x12, X86Movsd, "movlp">; - -let SchedRW = [WriteFStore] in { -let Predicates = [UseAVX] in { -def VMOVLPSmr : VPSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128:$src)), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -def VMOVLPDmr : VPDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -}// UseAVX -def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (bc_v2f64 (v4f32 VR128:$src)), - (iPTR 0))), addr:$dst)]>; -def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movlpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt (v2f64 VR128:$src), - (iPTR 0))), addr:$dst)]>; -} // SchedRW - -let Predicates = [UseSSE1] in { - // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS - def : Pat<(store (i64 (extractelt (bc_v2i64 (v4f32 VR128:$src2)), - (iPTR 0))), addr:$src1), - (MOVLPSmr addr:$src1, VR128:$src2)>; - - // This pattern helps select MOVLPS on SSE1 only targets. With SSE2 we'll - // end up with a movsd or blend instead of shufp. - // No need for aligned load, we're only loading 64-bits. - def : Pat<(X86Shufp (loadv4f32 addr:$src2), VR128:$src1, (i8 -28)), - (MOVLPSrm VR128:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Hi packed FP Instructions -//===----------------------------------------------------------------------===// - -defm MOVH : sse12_mov_hilo_packed<0x16, X86Unpckl, "movhp">; - -let SchedRW = [WriteFStore] in { -// v2f64 extract element 1 is always custom lowered to unpack high to low -// and extract element 0 so the non-store version isn't too horrible. -let Predicates = [UseAVX] in { -def VMOVHPSmr : VPSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128:$src)), - (bc_v2f64 (v4f32 VR128:$src))), - (iPTR 0))), addr:$dst)]>, VEX, VEX_WIG; -def VMOVHPDmr : VPDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128:$src, VR128:$src)), - (iPTR 0))), addr:$dst)]>, VEX, VEX_WIG; -} // UseAVX -def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhps\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (X86Unpckh (bc_v2f64 (v4f32 VR128:$src)), - (bc_v2f64 (v4f32 VR128:$src))), - (iPTR 0))), addr:$dst)]>; -def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movhpd\t{$src, $dst|$dst, $src}", - [(store (f64 (extractelt - (v2f64 (X86Unpckh VR128:$src, VR128:$src)), - (iPTR 0))), addr:$dst)]>; -} // SchedRW - -let Predicates = [UseAVX] in { - // Also handle an i64 load because that may get selected as a faster way to - // load the data. - def : Pat<(v2f64 (X86Unpckl VR128:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (VMOVHPDrm VR128:$src1, addr:$src2)>; - - def : Pat<(store (f64 (extractelt - (v2f64 (X86VPermilpi VR128:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (VMOVHPDmr addr:$dst, VR128:$src)>; -} - -let Predicates = [UseSSE1] in { - // This pattern helps select MOVHPS on SSE1 only targets. With SSE2 we'll - // end up with a movsd or blend instead of shufp. - // No need for aligned load, we're only loading 64-bits. - def : Pat<(X86Movlhps VR128:$src1, (loadv4f32 addr:$src2)), - (MOVHPSrm VR128:$src1, addr:$src2)>; -} - -let Predicates = [UseSSE2] in { - // MOVHPD patterns - - // Also handle an i64 load because that may get selected as a faster way to - // load the data. - def : Pat<(v2f64 (X86Unpckl VR128:$src1, - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src2)))))), - (MOVHPDrm VR128:$src1, addr:$src2)>; - - def : Pat<(store (f64 (extractelt - (v2f64 (X86Shufp VR128:$src, VR128:$src, (i8 1))), - (iPTR 0))), addr:$dst), - (MOVHPDmr addr:$dst, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Move Low to High and High to Low packed FP Instructions -//===----------------------------------------------------------------------===// - -let Predicates = [UseAVX] in { - def VMOVLHPSrr : VPSI<0x16, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movlhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movlhps VR128:$src1, VR128:$src2)))]>, - VEX_4V, Sched<[SchedWriteFShuffle.XMM]>, VEX_WIG; - let isCommutable = 1 in - def VMOVHLPSrr : VPSI<0x12, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movhlps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movhlps VR128:$src1, VR128:$src2)))]>, - VEX_4V, Sched<[SchedWriteFShuffle.XMM]>, VEX_WIG, - NotMemoryFoldable; -} -let Constraints = "$src1 = $dst" in { - def MOVLHPSrr : PSI<0x16, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movlhps\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movlhps VR128:$src1, VR128:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>; - let isCommutable = 1 in - def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2), - "movhlps\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v4f32 (X86Movhlps VR128:$src1, VR128:$src2)))]>, - Sched<[SchedWriteFShuffle.XMM]>, NotMemoryFoldable; -} - -// TODO: This is largely to trick fastisel into ignoring the pattern. -def UnpckhUnary : PatFrag<(ops node:$src1, node:$src2), - (X86Unpckh node:$src1, node:$src2), [{ - return N->getOperand(0) == N->getOperand(1); -}]>; - -let Predicates = [UseSSE2] in { - // TODO: This is a hack pattern to allow lowering to emit unpckh instead of - // movhlps for sse2 without changing a bunch of tests. - def : Pat<(v2f64 (UnpckhUnary VR128:$src, VR128:$src)), - (MOVHLPSrr VR128:$src, VR128:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Conversion Instructions -//===----------------------------------------------------------------------===// - -multiclass sse12_cvt_s opc, RegisterClass SrcRC, RegisterClass DstRC, - SDNode OpNode, X86MemOperand x86memop, PatFrag ld_frag, - string asm, X86FoldableSchedWrite sched> { - def rr : SI, - Sched<[sched]>; - def rm : SI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_p opc, RegisterClass RC, X86MemOperand x86memop, - ValueType DstTy, ValueType SrcTy, PatFrag ld_frag, - string asm, Domain d, X86FoldableSchedWrite sched> { -let hasSideEffects = 0 in { - def rr : I, - Sched<[sched]>; - let mayLoad = 1 in - def rm : I, - Sched<[sched.Folded]>; -} -} - -multiclass sse12_vcvt_avx opc, RegisterClass SrcRC, RegisterClass DstRC, - X86MemOperand x86memop, string asm, - X86FoldableSchedWrite sched> { -let hasSideEffects = 0, Predicates = [UseAVX] in { - def rr : SI, - Sched<[sched]>; - let mayLoad = 1 in - def rm : SI, - Sched<[sched.Folded, ReadAfterLd]>; -} // hasSideEffects = 0 -} - -let Predicates = [UseAVX] in { -defm VCVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, - XS, VEX, VEX_LIG; -defm VCVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, - XS, VEX, VEX_W, VEX_LIG; -defm VCVTTSD2SI : sse12_cvt_s<0x2C, FR64, GR32, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, - XD, VEX, VEX_LIG; -defm VCVTTSD2SI64 : sse12_cvt_s<0x2C, FR64, GR64, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, - XD, VEX, VEX_W, VEX_LIG; - -def : InstAlias<"vcvttss2si{l}\t{$src, $dst|$dst, $src}", - (VCVTTSS2SIrr GR32:$dst, FR32:$src), 0, "att">; -def : InstAlias<"vcvttss2si{l}\t{$src, $dst|$dst, $src}", - (VCVTTSS2SIrm GR32:$dst, f32mem:$src), 0, "att">; -def : InstAlias<"vcvttsd2si{l}\t{$src, $dst|$dst, $src}", - (VCVTTSD2SIrr GR32:$dst, FR64:$src), 0, "att">; -def : InstAlias<"vcvttsd2si{l}\t{$src, $dst|$dst, $src}", - (VCVTTSD2SIrm GR32:$dst, f64mem:$src), 0, "att">; -def : InstAlias<"vcvttss2si{q}\t{$src, $dst|$dst, $src}", - (VCVTTSS2SI64rr GR64:$dst, FR32:$src), 0, "att">; -def : InstAlias<"vcvttss2si{q}\t{$src, $dst|$dst, $src}", - (VCVTTSS2SI64rm GR64:$dst, f32mem:$src), 0, "att">; -def : InstAlias<"vcvttsd2si{q}\t{$src, $dst|$dst, $src}", - (VCVTTSD2SI64rr GR64:$dst, FR64:$src), 0, "att">; -def : InstAlias<"vcvttsd2si{q}\t{$src, $dst|$dst, $src}", - (VCVTTSD2SI64rm GR64:$dst, f64mem:$src), 0, "att">; -} -// The assembler can recognize rr 64-bit instructions by seeing a rxx -// register, but the same isn't true when only using memory operands, -// provide other assembly "l" and "q" forms to address this explicitly -// where appropriate to do so. -defm VCVTSI2SS : sse12_vcvt_avx<0x2A, GR32, FR32, i32mem, "cvtsi2ss{l}", - WriteCvtI2SS>, XS, VEX_4V, VEX_LIG; -defm VCVTSI642SS : sse12_vcvt_avx<0x2A, GR64, FR32, i64mem, "cvtsi2ss{q}", - WriteCvtI2SS>, XS, VEX_4V, VEX_W, VEX_LIG; -defm VCVTSI2SD : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd{l}", - WriteCvtI2SD>, XD, VEX_4V, VEX_LIG; -defm VCVTSI642SD : sse12_vcvt_avx<0x2A, GR64, FR64, i64mem, "cvtsi2sd{q}", - WriteCvtI2SD>, XD, VEX_4V, VEX_W, VEX_LIG; - -let Predicates = [UseAVX] in { - def : InstAlias<"vcvtsi2ss\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTSI2SSrm FR64:$dst, FR64:$src1, i32mem:$src), 0, "att">; - def : InstAlias<"vcvtsi2sd\t{$src, $src1, $dst|$dst, $src1, $src}", - (VCVTSI2SDrm FR64:$dst, FR64:$src1, i32mem:$src), 0, "att">; - - def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SSrm (f32 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f32 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SSrm (f32 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f64 (sint_to_fp (loadi32 addr:$src))), - (VCVTSI2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>; - def : Pat<(f64 (sint_to_fp (loadi64 addr:$src))), - (VCVTSI642SDrm (f64 (IMPLICIT_DEF)), addr:$src)>; - - def : Pat<(f32 (sint_to_fp GR32:$src)), - (VCVTSI2SSrr (f32 (IMPLICIT_DEF)), GR32:$src)>; - def : Pat<(f32 (sint_to_fp GR64:$src)), - (VCVTSI642SSrr (f32 (IMPLICIT_DEF)), GR64:$src)>; - def : Pat<(f64 (sint_to_fp GR32:$src)), - (VCVTSI2SDrr (f64 (IMPLICIT_DEF)), GR32:$src)>; - def : Pat<(f64 (sint_to_fp GR64:$src)), - (VCVTSI642SDrr (f64 (IMPLICIT_DEF)), GR64:$src)>; -} - -defm CVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, XS; -defm CVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, - "cvttss2si\t{$src, $dst|$dst, $src}", - WriteCvtSS2I>, XS, REX_W; -defm CVTTSD2SI : sse12_cvt_s<0x2C, FR64, GR32, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, XD; -defm CVTTSD2SI64 : sse12_cvt_s<0x2C, FR64, GR64, fp_to_sint, f64mem, loadf64, - "cvttsd2si\t{$src, $dst|$dst, $src}", - WriteCvtSD2I>, XD, REX_W; -defm CVTSI2SS : sse12_cvt_s<0x2A, GR32, FR32, sint_to_fp, i32mem, loadi32, - "cvtsi2ss{l}\t{$src, $dst|$dst, $src}", - WriteCvtI2SS>, XS; -defm CVTSI642SS : sse12_cvt_s<0x2A, GR64, FR32, sint_to_fp, i64mem, loadi64, - "cvtsi2ss{q}\t{$src, $dst|$dst, $src}", - WriteCvtI2SS>, XS, REX_W; -defm CVTSI2SD : sse12_cvt_s<0x2A, GR32, FR64, sint_to_fp, i32mem, loadi32, - "cvtsi2sd{l}\t{$src, $dst|$dst, $src}", - WriteCvtI2SD>, XD; -defm CVTSI642SD : sse12_cvt_s<0x2A, GR64, FR64, sint_to_fp, i64mem, loadi64, - "cvtsi2sd{q}\t{$src, $dst|$dst, $src}", - WriteCvtI2SD>, XD, REX_W; - -def : InstAlias<"cvttss2si{l}\t{$src, $dst|$dst, $src}", - (CVTTSS2SIrr GR32:$dst, FR32:$src), 0, "att">; -def : InstAlias<"cvttss2si{l}\t{$src, $dst|$dst, $src}", - (CVTTSS2SIrm GR32:$dst, f32mem:$src), 0, "att">; -def : InstAlias<"cvttsd2si{l}\t{$src, $dst|$dst, $src}", - (CVTTSD2SIrr GR32:$dst, FR64:$src), 0, "att">; -def : InstAlias<"cvttsd2si{l}\t{$src, $dst|$dst, $src}", - (CVTTSD2SIrm GR32:$dst, f64mem:$src), 0, "att">; -def : InstAlias<"cvttss2si{q}\t{$src, $dst|$dst, $src}", - (CVTTSS2SI64rr GR64:$dst, FR32:$src), 0, "att">; -def : InstAlias<"cvttss2si{q}\t{$src, $dst|$dst, $src}", - (CVTTSS2SI64rm GR64:$dst, f32mem:$src), 0, "att">; -def : InstAlias<"cvttsd2si{q}\t{$src, $dst|$dst, $src}", - (CVTTSD2SI64rr GR64:$dst, FR64:$src), 0, "att">; -def : InstAlias<"cvttsd2si{q}\t{$src, $dst|$dst, $src}", - (CVTTSD2SI64rm GR64:$dst, f64mem:$src), 0, "att">; - -def : InstAlias<"cvtsi2ss\t{$src, $dst|$dst, $src}", - (CVTSI2SSrm FR64:$dst, i32mem:$src), 0, "att">; -def : InstAlias<"cvtsi2sd\t{$src, $dst|$dst, $src}", - (CVTSI2SDrm FR64:$dst, i32mem:$src), 0, "att">; - -// Conversion Instructions Intrinsics - Match intrinsics which expect MM -// and/or XMM operand(s). - -// FIXME: We probably want to match the rm form only when optimizing for -// size, to avoid false dependencies (see sse_fp_unop_s for details) -multiclass sse12_cvt_sint opc, RegisterClass SrcRC, RegisterClass DstRC, - Intrinsic Int, Operand memop, ComplexPattern mem_cpat, - string asm, X86FoldableSchedWrite sched> { - def rr_Int : SI, - Sched<[sched]>; - def rm_Int : SI, - Sched<[sched.Folded]>; -} - -multiclass sse12_cvt_sint_3addr opc, RegisterClass SrcRC, - RegisterClass DstRC, X86MemOperand x86memop, - string asm, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { -let hasSideEffects = 0 in { - def rr_Int : SI, Sched<[sched]>; - let mayLoad = 1 in - def rm_Int : SI, Sched<[sched.Folded, ReadAfterLd]>; -} -} - -let Predicates = [UseAVX] in { -defm VCVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, - int_x86_sse2_cvtsd2si, sdmem, sse_load_f64, "cvtsd2si", - WriteCvtSD2I>, XD, VEX, VEX_LIG; -defm VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, - int_x86_sse2_cvtsd2si64, sdmem, sse_load_f64, "cvtsd2si", - WriteCvtSD2I>, XD, VEX, VEX_W, VEX_LIG; -} -defm CVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si, - sdmem, sse_load_f64, "cvtsd2si", WriteCvtSD2I>, XD; -defm CVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse2_cvtsd2si64, - sdmem, sse_load_f64, "cvtsd2si", WriteCvtSD2I>, XD, REX_W; - - -let isCodeGenOnly = 1 in { - let Predicates = [UseAVX] in { - defm VCVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2ss{l}", WriteCvtI2SS, 0>, XS, VEX_4V; - defm VCVTSI642SS : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2ss{q}", WriteCvtI2SS, 0>, XS, VEX_4V, VEX_W; - defm VCVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2sd{l}", WriteCvtI2SD, 0>, XD, VEX_4V; - defm VCVTSI642SD : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2sd{q}", WriteCvtI2SD, 0>, XD, VEX_4V, VEX_W; - } - let Constraints = "$src1 = $dst" in { - defm CVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2ss{l}", WriteCvtI2SS>, XS; - defm CVTSI642SS : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2ss{q}", WriteCvtI2SS>, XS, REX_W; - defm CVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - i32mem, "cvtsi2sd{l}", WriteCvtI2SD>, XD; - defm CVTSI642SD : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - i64mem, "cvtsi2sd{q}", WriteCvtI2SD>, XD, REX_W; - } -} // isCodeGenOnly = 1 - -/// SSE 1 Only - -// Aliases for intrinsics -let isCodeGenOnly = 1 in { -let Predicates = [UseAVX] in { -defm VCVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, - ssmem, sse_load_f32, "cvttss2si", - WriteCvtSS2I>, XS, VEX; -defm VCVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse_cvttss2si64, ssmem, sse_load_f32, - "cvttss2si", WriteCvtSS2I>, - XS, VEX, VEX_W; -defm VCVTTSD2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse2_cvttsd2si, - sdmem, sse_load_f64, "cvttsd2si", - WriteCvtSS2I>, XD, VEX; -defm VCVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse2_cvttsd2si64, sdmem, sse_load_f64, - "cvttsd2si", WriteCvtSS2I>, - XD, VEX, VEX_W; -} -defm CVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, - ssmem, sse_load_f32, "cvttss2si", - WriteCvtSS2I>, XS; -defm CVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse_cvttss2si64, ssmem, sse_load_f32, - "cvttss2si", WriteCvtSS2I>, XS, REX_W; -defm CVTTSD2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse2_cvttsd2si, - sdmem, sse_load_f64, "cvttsd2si", - WriteCvtSD2I>, XD; -defm CVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, - int_x86_sse2_cvttsd2si64, sdmem, sse_load_f64, - "cvttsd2si", WriteCvtSD2I>, XD, REX_W; -} // isCodeGenOnly = 1 - -let Predicates = [UseAVX] in { -defm VCVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, VEX, VEX_LIG; -defm VCVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, VEX, VEX_W, VEX_LIG; -} -defm CVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS; -defm CVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64, - ssmem, sse_load_f32, "cvtss2si", - WriteCvtSS2I>, XS, REX_W; - -defm VCVTDQ2PS : sse12_cvt_p<0x5B, VR128, i128mem, v4f32, v4i32, loadv2i64, - "vcvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PS>, - PS, VEX, Requires<[HasAVX, NoVLX]>, VEX_WIG; -defm VCVTDQ2PSY : sse12_cvt_p<0x5B, VR256, i256mem, v8f32, v8i32, loadv4i64, - "vcvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PSY>, - PS, VEX, VEX_L, Requires<[HasAVX, NoVLX]>, VEX_WIG; - -defm CVTDQ2PS : sse12_cvt_p<0x5B, VR128, i128mem, v4f32, v4i32, memopv2i64, - "cvtdq2ps\t{$src, $dst|$dst, $src}", - SSEPackedSingle, WriteCvtI2PS>, - PS, Requires<[UseSSE2]>; - -let Predicates = [UseAVX] in { -def : InstAlias<"vcvtss2si{l}\t{$src, $dst|$dst, $src}", - (VCVTSS2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -def : InstAlias<"vcvtss2si{l}\t{$src, $dst|$dst, $src}", - (VCVTSS2SIrm_Int GR32:$dst, ssmem:$src), 0, "att">; -def : InstAlias<"vcvtsd2si{l}\t{$src, $dst|$dst, $src}", - (VCVTSD2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -def : InstAlias<"vcvtsd2si{l}\t{$src, $dst|$dst, $src}", - (VCVTSD2SIrm_Int GR32:$dst, sdmem:$src), 0, "att">; -def : InstAlias<"vcvtss2si{q}\t{$src, $dst|$dst, $src}", - (VCVTSS2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -def : InstAlias<"vcvtss2si{q}\t{$src, $dst|$dst, $src}", - (VCVTSS2SI64rm_Int GR64:$dst, ssmem:$src), 0, "att">; -def : InstAlias<"vcvtsd2si{q}\t{$src, $dst|$dst, $src}", - (VCVTSD2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -def : InstAlias<"vcvtsd2si{q}\t{$src, $dst|$dst, $src}", - (VCVTSD2SI64rm_Int GR64:$dst, sdmem:$src), 0, "att">; -} - -def : InstAlias<"cvtss2si{l}\t{$src, $dst|$dst, $src}", - (CVTSS2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -def : InstAlias<"cvtss2si{l}\t{$src, $dst|$dst, $src}", - (CVTSS2SIrm_Int GR32:$dst, ssmem:$src), 0, "att">; -def : InstAlias<"cvtsd2si{l}\t{$src, $dst|$dst, $src}", - (CVTSD2SIrr_Int GR32:$dst, VR128:$src), 0, "att">; -def : InstAlias<"cvtsd2si{l}\t{$src, $dst|$dst, $src}", - (CVTSD2SIrm_Int GR32:$dst, sdmem:$src), 0, "att">; -def : InstAlias<"cvtss2si{q}\t{$src, $dst|$dst, $src}", - (CVTSS2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -def : InstAlias<"cvtss2si{q}\t{$src, $dst|$dst, $src}", - (CVTSS2SI64rm_Int GR64:$dst, ssmem:$src), 0, "att">; -def : InstAlias<"cvtsd2si{q}\t{$src, $dst|$dst, $src}", - (CVTSD2SI64rr_Int GR64:$dst, VR128:$src), 0, "att">; -def : InstAlias<"cvtsd2si{q}\t{$src, $dst|$dst, $src}", - (CVTSD2SI64rm_Int GR64:$dst, sdmem:$src), 0, "att">; - -/// SSE 2 Only - -// Convert scalar double to scalar single -let hasSideEffects = 0, Predicates = [UseAVX] in { -def VCVTSD2SSrr : VSDI<0x5A, MRMSrcReg, (outs FR32:$dst), - (ins FR32:$src1, FR64:$src2), - "cvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSD2SS]>; -let mayLoad = 1 in -def VCVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), - (ins FR32:$src1, f64mem:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XD, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -} - -def : Pat<(f32 (fpround FR64:$src)), - (VCVTSD2SSrr (f32 (IMPLICIT_DEF)), FR64:$src)>, - Requires<[UseAVX]>; - -def CVTSD2SSrr : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src), - "cvtsd2ss\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (fpround FR64:$src))]>, - Sched<[WriteCvtSD2SS]>; -def CVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), - "cvtsd2ss\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (fpround (loadf64 addr:$src)))]>, - XD, Requires<[UseSSE2, OptForSize]>, - Sched<[WriteCvtSD2SS.Folded]>; - -let isCodeGenOnly = 1 in { -def VCVTSD2SSrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_sse2_cvtsd2ss VR128:$src1, VR128:$src2))]>, - XD, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSD2SS]>; -def VCVTSD2SSrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, sdmem:$src2), - "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (int_x86_sse2_cvtsd2ss - VR128:$src1, sse_load_f64:$src2))]>, - XD, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -let Constraints = "$src1 = $dst" in { -def CVTSD2SSrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "cvtsd2ss\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (int_x86_sse2_cvtsd2ss VR128:$src1, VR128:$src2))]>, - XD, Requires<[UseSSE2]>, Sched<[WriteCvtSD2SS]>; -def CVTSD2SSrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, sdmem:$src2), - "cvtsd2ss\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, (int_x86_sse2_cvtsd2ss - VR128:$src1, sse_load_f64:$src2))]>, - XD, Requires<[UseSSE2]>, - Sched<[WriteCvtSD2SS.Folded, ReadAfterLd]>; -} -} // isCodeGenOnly = 1 - -// Convert scalar single to scalar double -// SSE2 instructions with XS prefix -let hasSideEffects = 0 in { -def VCVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), - (ins FR64:$src1, FR32:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XS, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSS2SD]>, Requires<[UseAVX]>; -let mayLoad = 1 in -def VCVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), - (ins FR64:$src1, f32mem:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - XS, VEX_4V, VEX_LIG, VEX_WIG, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>, - Requires<[UseAVX, OptForSize]>; -} - -def : Pat<(f64 (fpextend FR32:$src)), - (VCVTSS2SDrr (f64 (IMPLICIT_DEF)), FR32:$src)>, Requires<[UseAVX]>; -def : Pat<(fpextend (loadf32 addr:$src)), - (VCVTSS2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>, Requires<[UseAVX, OptForSize]>; - -def : Pat<(extloadf32 addr:$src), - (VCVTSS2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>, - Requires<[UseAVX, OptForSize]>; -def : Pat<(extloadf32 addr:$src), - (VCVTSS2SDrr (f64 (IMPLICIT_DEF)), (VMOVSSrm addr:$src))>, - Requires<[UseAVX, OptForSpeed]>; - -def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src), - "cvtss2sd\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (fpextend FR32:$src))]>, - XS, Requires<[UseSSE2]>, Sched<[WriteCvtSS2SD]>; -def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), - "cvtss2sd\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (extloadf32 addr:$src))]>, - XS, Requires<[UseSSE2, OptForSize]>, - Sched<[WriteCvtSS2SD.Folded]>; - -// extload f32 -> f64. This matches load+fpextend because we have a hack in -// the isel (PreprocessForFPConvert) that can introduce loads after dag -// combine. -// Since these loads aren't folded into the fpextend, we have to match it -// explicitly here. -def : Pat<(fpextend (loadf32 addr:$src)), - (CVTSS2SDrm addr:$src)>, Requires<[UseSSE2, OptForSize]>; -def : Pat<(extloadf32 addr:$src), - (CVTSS2SDrr (MOVSSrm addr:$src))>, Requires<[UseSSE2, OptForSpeed]>; - -let isCodeGenOnly = 1, hasSideEffects = 0 in { -def VCVTSS2SDrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, VEX_4V, VEX_WIG, - Requires<[HasAVX]>, Sched<[WriteCvtSS2SD]>; -let mayLoad = 1 in -def VCVTSS2SDrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, ssmem:$src2), - "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, XS, VEX_4V, VEX_WIG, Requires<[HasAVX]>, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>; -let Constraints = "$src1 = $dst" in { // SSE2 instructions with XS prefix -def CVTSS2SDrr_Int: I<0x5A, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "cvtss2sd\t{$src2, $dst|$dst, $src2}", - []>, XS, Requires<[UseSSE2]>, - Sched<[WriteCvtSS2SD]>; -let mayLoad = 1 in -def CVTSS2SDrm_Int: I<0x5A, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, ssmem:$src2), - "cvtss2sd\t{$src2, $dst|$dst, $src2}", - []>, XS, Requires<[UseSSE2]>, - Sched<[WriteCvtSS2SD.Folded, ReadAfterLd]>; -} -} // isCodeGenOnly = 1 - -// Patterns used for matching (v)cvtsi2ss, (v)cvtsi2sd, (v)cvtsd2ss and -// (v)cvtss2sd intrinsic sequences from clang which produce unnecessary -// vmovs{s,d} instructions -let Predicates = [UseAVX] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128:$src, (iPTR 0))))))))), - (VCVTSD2SSrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128:$src, (iPTR 0))))))))), - (VCVTSS2SDrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (VCVTSI642SSrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (VCVTSI2SSrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (VCVTSI642SDrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (VCVTSI642SDrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (VCVTSI2SDrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (VCVTSI2SDrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseAVX] - -let Predicates = [UseSSE2] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector - (f32 (fpround (f64 (extractelt VR128:$src, (iPTR 0))))))))), - (CVTSD2SSrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector - (f64 (fpextend (f32 (extractelt VR128:$src, (iPTR 0))))))))), - (CVTSS2SDrr_Int VR128:$dst, VR128:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR64:$src)))))), - (CVTSI642SDrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi64 addr:$src))))))), - (CVTSI642SDrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp GR32:$src)))))), - (CVTSI2SDrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v2f64 (X86Movsd - (v2f64 VR128:$dst), - (v2f64 (scalar_to_vector (f64 (sint_to_fp (loadi32 addr:$src))))))), - (CVTSI2SDrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseSSE2] - -let Predicates = [UseSSE1] in { -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR64:$src)))))), - (CVTSI642SSrr_Int VR128:$dst, GR64:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi64 addr:$src))))))), - (CVTSI642SSrm_Int VR128:$dst, addr:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp GR32:$src)))))), - (CVTSI2SSrr_Int VR128:$dst, GR32:$src)>; - -def : Pat<(v4f32 (X86Movss - (v4f32 VR128:$dst), - (v4f32 (scalar_to_vector (f32 (sint_to_fp (loadi32 addr:$src))))))), - (CVTSI2SSrm_Int VR128:$dst, addr:$src)>; -} // Predicates = [UseSSE1] - -let Predicates = [HasAVX, NoVLX] in { -// Convert packed single/double fp to doubleword -def VCVTPS2DQrr : VPDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4i32 (X86cvtp2Int (v4f32 VR128:$src))))]>, - VEX, Sched<[WriteCvtPS2I]>, VEX_WIG; -def VCVTPS2DQrm : VPDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv4f32 addr:$src))))]>, - VEX, Sched<[WriteCvtPS2ILd]>, VEX_WIG; -def VCVTPS2DQYrr : VPDI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvtp2Int (v8f32 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IY]>, VEX_WIG; -def VCVTPS2DQYrm : VPDI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvtp2Int (loadv8f32 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IYLd]>, VEX_WIG; -} -def CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4i32 (X86cvtp2Int (v4f32 VR128:$src))))]>, - Sched<[WriteCvtPS2I]>; -def CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (memopv4f32 addr:$src))))]>, - Sched<[WriteCvtPS2ILd]>; - - -// Convert Packed Double FP to Packed DW Integers -let Predicates = [HasAVX, NoVLX] in { -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. -def VCVTPD2DQrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v2f64 VR128:$src))))]>, - VEX, Sched<[WriteCvtPD2I]>, VEX_WIG; - -// XMM only -def : InstAlias<"vcvtpd2dqx\t{$src, $dst|$dst, $src}", - (VCVTPD2DQrr VR128:$dst, VR128:$src), 0>; -def VCVTPD2DQrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "vcvtpd2dq{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src))))]>, VEX, - Sched<[WriteCvtPD2ILd]>, VEX_WIG; -def : InstAlias<"vcvtpd2dqx\t{$src, $dst|$dst, $src}", - (VCVTPD2DQrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -def VCVTPD2DQYrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "vcvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v4f64 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IY]>, VEX_WIG; -def VCVTPD2DQYrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "vcvtpd2dq{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (loadv4f64 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IYLd]>, VEX_WIG; -def : InstAlias<"vcvtpd2dqy\t{$src, $dst|$dst, $src}", - (VCVTPD2DQYrr VR128:$dst, VR256:$src), 0>; -def : InstAlias<"vcvtpd2dqy\t{$src, $dst|$dst, $src}", - (VCVTPD2DQYrm VR128:$dst, f256mem:$src), 0, "intel">; -} - -def CVTPD2DQrm : SDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (memopv2f64 addr:$src))))]>, - Sched<[WriteCvtPD2ILd]>; -def CVTPD2DQrr : SDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvtp2Int (v2f64 VR128:$src))))]>, - Sched<[WriteCvtPD2I]>; - -// Convert with truncation packed single/double fp to doubleword -// SSE2 packed instructions with XS prefix -let Predicates = [HasAVX, NoVLX] in { -def VCVTTPS2DQrr : VS2SI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f32 VR128:$src))))]>, - VEX, Sched<[WriteCvtPS2I]>, VEX_WIG; -def VCVTTPS2DQrm : VS2SI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv4f32 addr:$src))))]>, - VEX, Sched<[WriteCvtPS2ILd]>, VEX_WIG; -def VCVTTPS2DQYrr : VS2SI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvttp2si (v8f32 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPS2IY]>, VEX_WIG; -def VCVTTPS2DQYrm : VS2SI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v8i32 (X86cvttp2si (loadv8f32 addr:$src))))]>, - VEX, VEX_L, - Sched<[WriteCvtPS2IYLd]>, VEX_WIG; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), - (VCVTTPS2DQrr VR128:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f32 addr:$src))), - (VCVTTPS2DQrm addr:$src)>; - def : Pat<(v8i32 (fp_to_sint (v8f32 VR256:$src))), - (VCVTTPS2DQYrr VR256:$src)>; - def : Pat<(v8i32 (fp_to_sint (loadv8f32 addr:$src))), - (VCVTTPS2DQYrm addr:$src)>; -} - -def CVTTPS2DQrr : S2SI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f32 VR128:$src))))]>, - Sched<[WriteCvtPS2I]>; -def CVTTPS2DQrm : S2SI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttps2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (memopv4f32 addr:$src))))]>, - Sched<[WriteCvtPS2ILd]>; - -let Predicates = [UseSSE2] in { - def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), - (CVTTPS2DQrr VR128:$src)>; - def : Pat<(v4i32 (fp_to_sint (memopv4f32 addr:$src))), - (CVTTPS2DQrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in -def VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v2f64 VR128:$src))))]>, - VEX, Sched<[WriteCvtPD2I]>, VEX_WIG; - -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. - -// XMM only -def : InstAlias<"vcvttpd2dqx\t{$src, $dst|$dst, $src}", - (VCVTTPD2DQrr VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in -def VCVTTPD2DQrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvttpd2dq{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv2f64 addr:$src))))]>, - VEX, Sched<[WriteCvtPD2ILd]>, VEX_WIG; -def : InstAlias<"vcvttpd2dqx\t{$src, $dst|$dst, $src}", - (VCVTTPD2DQrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -let Predicates = [HasAVX, NoVLX] in { -def VCVTTPD2DQYrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v4f64 VR256:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IY]>, VEX_WIG; -def VCVTTPD2DQYrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "cvttpd2dq{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (loadv4f64 addr:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtPD2IYLd]>, VEX_WIG; -} -def : InstAlias<"vcvttpd2dqy\t{$src, $dst|$dst, $src}", - (VCVTTPD2DQYrr VR128:$dst, VR256:$src), 0>; -def : InstAlias<"vcvttpd2dqy\t{$src, $dst|$dst, $src}", - (VCVTTPD2DQYrm VR128:$dst, f256mem:$src), 0, "intel">; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (fp_to_sint (v4f64 VR256:$src))), - (VCVTTPD2DQYrr VR256:$src)>; - def : Pat<(v4i32 (fp_to_sint (loadv4f64 addr:$src))), - (VCVTTPD2DQYrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (VCVTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (loadv2f64 addr:$src)))))), - (VCVTPD2DQrm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (VCVTTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (loadv2f64 addr:$src)))))), - (VCVTTPD2DQrm addr:$src)>; -} // Predicates = [HasAVX, NoVLX] - -def CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (v2f64 VR128:$src))))]>, - Sched<[WriteCvtPD2I]>; -def CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src), - "cvttpd2dq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (X86cvttp2si (memopv2f64 addr:$src))))]>, - Sched<[WriteCvtPD2ILd]>; - -let Predicates = [UseSSE2] in { - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (v2f64 VR128:$src)))))), - (CVTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvtp2Int (memopv2f64 addr:$src)))))), - (CVTPD2DQrm addr:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (v2f64 VR128:$src)))))), - (CVTTPD2DQrr VR128:$src)>; - def : Pat<(X86vzmovl (v2i64 (bitconvert - (v4i32 (X86cvttp2si (memopv2f64 addr:$src)))))), - (CVTTPD2DQrm addr:$src)>; -} // Predicates = [UseSSE2] - -// Convert packed single to packed double -let Predicates = [HasAVX, NoVLX] in { - // SSE2 instructions without OpSize prefix -def VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (X86vfpext (v4f32 VR128:$src))))]>, - PS, VEX, Sched<[WriteCvtPS2PD]>, VEX_WIG; -def VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (extloadv2f32 addr:$src)))]>, - PS, VEX, Sched<[WriteCvtPS2PD.Folded]>, VEX_WIG; -def VCVTPS2PDYrr : I<0x5A, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (v4f64 (fpextend (v4f32 VR128:$src))))]>, - PS, VEX, VEX_L, Sched<[WriteCvtPS2PDY]>, VEX_WIG; -def VCVTPS2PDYrm : I<0x5A, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src), - "vcvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (v4f64 (extloadv4f32 addr:$src)))]>, - PS, VEX, VEX_L, Sched<[WriteCvtPS2PDY.Folded]>, VEX_WIG; -} - -let Predicates = [UseSSE2] in { -def CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (X86vfpext (v4f32 VR128:$src))))]>, - PS, Sched<[WriteCvtPS2PD]>; -def CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "cvtps2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2f64 (extloadv2f32 addr:$src)))]>, - PS, Sched<[WriteCvtPS2PD.Folded]>; -} - -// Convert Packed DW Integers to Packed Double FP -let Predicates = [HasAVX, NoVLX] in { -let hasSideEffects = 0, mayLoad = 1 in -def VCVTDQ2PDrm : S2SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (bc_v4i32 (loadv2i64 addr:$src)))))]>, - VEX, Sched<[WriteCvtI2PDLd]>, VEX_WIG; -def VCVTDQ2PDrr : S2SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (v4i32 VR128:$src))))]>, - VEX, Sched<[WriteCvtI2PD]>, VEX_WIG; -def VCVTDQ2PDYrm : S2SI<0xE6, MRMSrcMem, (outs VR256:$dst), (ins i128mem:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v4f64 (sint_to_fp (bc_v4i32 (loadv2i64 addr:$src)))))]>, - VEX, VEX_L, Sched<[WriteCvtI2PDYLd]>, - VEX_WIG; -def VCVTDQ2PDYrr : S2SI<0xE6, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src), - "vcvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, - (v4f64 (sint_to_fp (v4i32 VR128:$src))))]>, - VEX, VEX_L, Sched<[WriteCvtI2PDY]>, VEX_WIG; -} - -let hasSideEffects = 0, mayLoad = 1 in -def CVTDQ2PDrm : S2SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "cvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (bc_v4i32 (loadv2i64 addr:$src)))))]>, - Sched<[WriteCvtI2PDLd]>; -def CVTDQ2PDrr : S2SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtdq2pd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86VSintToFP (v4i32 VR128:$src))))]>, - Sched<[WriteCvtI2PD]>; - -// AVX register conversion intrinsics -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (VCVTDQ2PDrm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (VCVTDQ2PDrm addr:$src)>; -} // Predicates = [HasAVX, NoVLX] - -// SSE2 register conversion intrinsics -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (CVTDQ2PDrm addr:$src)>; - def : Pat<(v2f64 (X86VSintToFP (bc_v4i32 (v2i64 (X86vzload addr:$src))))), - (CVTDQ2PDrm addr:$src)>; -} // Predicates = [UseSSE2] - -// Convert packed double to packed single -// The assembler can recognize rr 256-bit instructions by seeing a ymm -// register, but the same isn't true when using memory operands instead. -// Provide other assembly rr and rm forms to address this explicitly. -let Predicates = [HasAVX, NoVLX] in -def VCVTPD2PSrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (v2f64 VR128:$src)))]>, - VEX, Sched<[WriteCvtPD2PS]>, VEX_WIG; - -// XMM only -def : InstAlias<"vcvtpd2psx\t{$src, $dst|$dst, $src}", - (VCVTPD2PSrr VR128:$dst, VR128:$src), 0>; -let Predicates = [HasAVX, NoVLX] in -def VCVTPD2PSrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2ps{x}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (loadv2f64 addr:$src)))]>, - VEX, Sched<[WriteCvtPD2PS.Folded]>, VEX_WIG; -def : InstAlias<"vcvtpd2psx\t{$src, $dst|$dst, $src}", - (VCVTPD2PSrm VR128:$dst, f128mem:$src), 0, "intel">; - -// YMM only -let Predicates = [HasAVX, NoVLX] in { -def VCVTPD2PSYrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (fpround VR256:$src))]>, - VEX, VEX_L, Sched<[WriteCvtPD2PSY]>, VEX_WIG; -def VCVTPD2PSYrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), - "cvtpd2ps{y}\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (fpround (loadv4f64 addr:$src)))]>, - VEX, VEX_L, Sched<[WriteCvtPD2PSY.Folded]>, VEX_WIG; -} -def : InstAlias<"vcvtpd2psy\t{$src, $dst|$dst, $src}", - (VCVTPD2PSYrr VR128:$dst, VR256:$src), 0>; -def : InstAlias<"vcvtpd2psy\t{$src, $dst|$dst, $src}", - (VCVTPD2PSYrm VR128:$dst, f256mem:$src), 0, "intel">; - -def CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (v2f64 VR128:$src)))]>, - Sched<[WriteCvtPD2PS]>; -def CVTPD2PSrm : PDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "cvtpd2ps\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (X86vfpround (memopv2f64 addr:$src)))]>, - Sched<[WriteCvtPD2PS.Folded]>; - -// AVX 256-bit register conversion intrinsics -// FIXME: Migrate SSE conversion intrinsics matching to use patterns as below -// whenever possible to avoid declaring two versions of each one. - -let Predicates = [HasAVX, NoVLX] in { - // Match fpround and fpextend for 128/256-bit conversions - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128:$src)))))), - (VCVTPD2PSrr VR128:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (loadv2f64 addr:$src)))))), - (VCVTPD2PSrm addr:$src)>; -} - -let Predicates = [UseSSE2] in { - // Match fpround and fpextend for 128 conversions - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (v2f64 VR128:$src)))))), - (CVTPD2PSrr VR128:$src)>; - def : Pat<(X86vzmovl (v2f64 (bitconvert - (v4f32 (X86vfpround (memopv2f64 addr:$src)))))), - (CVTPD2PSrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Compare Instructions -//===----------------------------------------------------------------------===// - -// sse12_cmp_scalar - sse 1 & 2 compare scalar instructions -multiclass sse12_cmp_scalar { - let isCommutable = 1 in - def rr : SIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, CC:$cc), asm, - [(set RC:$dst, (OpNode (VT RC:$src1), RC:$src2, imm:$cc))]>, - Sched<[sched]>; - def rm : SIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, CC:$cc), asm, - [(set RC:$dst, (OpNode (VT RC:$src1), - (ld_frag addr:$src2), imm:$cc))]>, - Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rr_alt : SIi8<0xC2, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$cc), asm_alt, []>, - Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rm_alt : SIi8<0xC2, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$cc), asm_alt, []>, - Sched<[sched.Folded, ReadAfterLd]>, NotMemoryFoldable; - } -} - -let ExeDomain = SSEPackedSingle in -defm VCMPSS : sse12_cmp_scalar, XS, VEX_4V, VEX_LIG, VEX_WIG; -let ExeDomain = SSEPackedDouble in -defm VCMPSD : sse12_cmp_scalar, - XD, VEX_4V, VEX_LIG, VEX_WIG; - -let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in - defm CMPSS : sse12_cmp_scalar, XS; - let ExeDomain = SSEPackedDouble in - defm CMPSD : sse12_cmp_scalar, XD; -} - -multiclass sse12_cmp_scalar_int { - def rr_Int : SIi8<0xC2, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src, CC:$cc), asm, - [(set VR128:$dst, (Int VR128:$src1, - VR128:$src, imm:$cc))]>, - Sched<[sched]>; -let mayLoad = 1 in - def rm_Int : SIi8<0xC2, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, memop:$src, CC:$cc), asm, - [(set VR128:$dst, (Int VR128:$src1, - mem_cpat:$src, imm:$cc))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let isCodeGenOnly = 1 in { - // Aliases to match intrinsics which expect XMM operand(s). - let ExeDomain = SSEPackedSingle in - defm VCMPSS : sse12_cmp_scalar_int, XS, VEX_4V; - let ExeDomain = SSEPackedDouble in - defm VCMPSD : sse12_cmp_scalar_int, - XD, VEX_4V; - let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in - defm CMPSS : sse12_cmp_scalar_int, XS; - let ExeDomain = SSEPackedDouble in - defm CMPSD : sse12_cmp_scalar_int, XD; -} -} - - -// sse12_ord_cmp - Unordered/Ordered scalar fp compare and set EFLAGS -multiclass sse12_ord_cmp opc, RegisterClass RC, SDNode OpNode, - ValueType vt, X86MemOperand x86memop, - PatFrag ld_frag, string OpcodeStr, - X86FoldableSchedWrite sched> { -let hasSideEffects = 0 in { - def rr: SI, - Sched<[sched]>; -let mayLoad = 1 in - def rm: SI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} - -// sse12_ord_cmp_int - Intrinsic version of sse12_ord_cmp -multiclass sse12_ord_cmp_int opc, RegisterClass RC, SDNode OpNode, - ValueType vt, Operand memop, - ComplexPattern mem_cpat, string OpcodeStr, - X86FoldableSchedWrite sched> { - def rr_Int: SI, - Sched<[sched]>; -let mayLoad = 1 in - def rm_Int: SI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Defs = [EFLAGS] in { - defm VUCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS, VEX, VEX_LIG, VEX_WIG; - defm VUCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD, VEX, VEX_LIG, VEX_WIG; - let Pattern = [] in { - defm VCOMISS : sse12_ord_cmp<0x2F, FR32, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS, VEX, VEX_LIG, VEX_WIG; - defm VCOMISD : sse12_ord_cmp<0x2F, FR64, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD, VEX, VEX_LIG, VEX_WIG; - } - - let isCodeGenOnly = 1 in { - defm VUCOMISS : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS, VEX, VEX_WIG; - defm VUCOMISD : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD, VEX, VEX_WIG; - - defm VCOMISS : sse12_ord_cmp_int<0x2F, VR128, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS, VEX, VEX_WIG; - defm VCOMISD : sse12_ord_cmp_int<0x2F, VR128, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD, VEX, VEX_WIG; - } - defm UCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, - "ucomiss", WriteFCom>, PS; - defm UCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, - "ucomisd", WriteFCom>, PD; - - let Pattern = [] in { - defm COMISS : sse12_ord_cmp<0x2F, FR32, undef, f32, f32mem, loadf32, - "comiss", WriteFCom>, PS; - defm COMISD : sse12_ord_cmp<0x2F, FR64, undef, f64, f64mem, loadf64, - "comisd", WriteFCom>, PD; - } - - let isCodeGenOnly = 1 in { - defm UCOMISS : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v4f32, ssmem, - sse_load_f32, "ucomiss", WriteFCom>, PS; - defm UCOMISD : sse12_ord_cmp_int<0x2E, VR128, X86ucomi, v2f64, sdmem, - sse_load_f64, "ucomisd", WriteFCom>, PD; - - defm COMISS : sse12_ord_cmp_int<0x2F, VR128, X86comi, v4f32, ssmem, - sse_load_f32, "comiss", WriteFCom>, PS; - defm COMISD : sse12_ord_cmp_int<0x2F, VR128, X86comi, v2f64, sdmem, - sse_load_f64, "comisd", WriteFCom>, PD; - } -} // Defs = [EFLAGS] - -// sse12_cmp_packed - sse 1 & 2 compare packed instructions -multiclass sse12_cmp_packed { - let isCommutable = 1 in - def rri : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, CC:$cc), asm, - [(set RC:$dst, (VT (X86cmpp RC:$src1, RC:$src2, imm:$cc)))], d>, - Sched<[sched]>; - def rmi : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, CC:$cc), asm, - [(set RC:$dst, - (VT (X86cmpp RC:$src1, (ld_frag addr:$src2), imm:$cc)))], d>, - Sched<[sched.Folded, ReadAfterLd]>; - - // Accept explicit immediate argument form instead of comparison code. - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def rri_alt : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc), - asm_alt, [], d>, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def rmi_alt : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc), - asm_alt, [], d>, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } -} - -defm VCMPPS : sse12_cmp_packed, PS, VEX_4V, VEX_WIG; -defm VCMPPD : sse12_cmp_packed, PD, VEX_4V, VEX_WIG; -defm VCMPPSY : sse12_cmp_packed, PS, VEX_4V, VEX_L, VEX_WIG; -defm VCMPPDY : sse12_cmp_packed, PD, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in { - defm CMPPS : sse12_cmp_packed, PS; - defm CMPPD : sse12_cmp_packed, PD; -} - -def CommutableCMPCC : PatLeaf<(imm), [{ - uint64_t Imm = N->getZExtValue() & 0x7; - return (Imm == 0x00 || Imm == 0x03 || Imm == 0x04 || Imm == 0x07); -}]>; - -// Patterns to select compares with loads in first operand. -let Predicates = [HasAVX] in { - def : Pat<(v4f64 (X86cmpp (loadv4f64 addr:$src2), VR256:$src1, - CommutableCMPCC:$cc)), - (VCMPPDYrmi VR256:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v8f32 (X86cmpp (loadv8f32 addr:$src2), VR256:$src1, - CommutableCMPCC:$cc)), - (VCMPPSYrmi VR256:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v2f64 (X86cmpp (loadv2f64 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (VCMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(v4f32 (X86cmpp (loadv4f32 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (VCMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, - CommutableCMPCC:$cc)), - (VCMPSDrm FR64:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, - CommutableCMPCC:$cc)), - (VCMPSSrm FR32:$src1, addr:$src2, imm:$cc)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86cmpp (memopv2f64 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, - CommutableCMPCC:$cc)), - (CMPSDrm FR64:$src1, addr:$src2, imm:$cc)>; -} - -let Predicates = [UseSSE1] in { - def : Pat<(v4f32 (X86cmpp (memopv4f32 addr:$src2), VR128:$src1, - CommutableCMPCC:$cc)), - (CMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; - - def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, - CommutableCMPCC:$cc)), - (CMPSSrm FR32:$src1, addr:$src2, imm:$cc)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Shuffle Instructions -//===----------------------------------------------------------------------===// - -/// sse12_shuffle - sse 1 & 2 fp shuffle instructions -multiclass sse12_shuffle { - def rmi : PIi8<0xC6, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$src3), asm, - [(set RC:$dst, (vt (X86Shufp RC:$src1, (mem_frag addr:$src2), - (i8 imm:$src3))))], d>, - Sched<[sched.Folded, ReadAfterLd]>; - def rri : PIi8<0xC6, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), asm, - [(set RC:$dst, (vt (X86Shufp RC:$src1, RC:$src2, - (i8 imm:$src3))))], d>, - Sched<[sched]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VSHUFPS : sse12_shuffle, - PS, VEX_4V, VEX_WIG; - defm VSHUFPSY : sse12_shuffle, - PS, VEX_4V, VEX_L, VEX_WIG; - defm VSHUFPD : sse12_shuffle, - PD, VEX_4V, VEX_WIG; - defm VSHUFPDY : sse12_shuffle, - PD, VEX_4V, VEX_L, VEX_WIG; -} -let Constraints = "$src1 = $dst" in { - defm SHUFPS : sse12_shuffle, PS; - defm SHUFPD : sse12_shuffle, PD; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Unpack FP Instructions -//===----------------------------------------------------------------------===// - -/// sse12_unpack_interleave - sse 1 & 2 fp unpack and interleave -multiclass sse12_unpack_interleave opc, SDNode OpNode, ValueType vt, - PatFrag mem_frag, RegisterClass RC, - X86MemOperand x86memop, string asm, - X86FoldableSchedWrite sched, Domain d, - bit IsCommutable = 0> { - let isCommutable = IsCommutable in - def rr : PI, - Sched<[sched]>; - def rm : PI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX] in { -defm VUNPCKHPS: sse12_unpack_interleave<0x15, X86Unpckh, v4f32, loadv4f32, - VR128, f128mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS, VEX_4V, VEX_WIG; -defm VUNPCKHPD: sse12_unpack_interleave<0x15, X86Unpckh, v2f64, loadv2f64, - VR128, f128mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble, 1>, PD, VEX_4V, VEX_WIG; -defm VUNPCKLPS: sse12_unpack_interleave<0x14, X86Unpckl, v4f32, loadv4f32, - VR128, f128mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS, VEX_4V, VEX_WIG; -defm VUNPCKLPD: sse12_unpack_interleave<0x14, X86Unpckl, v2f64, loadv2f64, - VR128, f128mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble>, PD, VEX_4V, VEX_WIG; - -defm VUNPCKHPSY: sse12_unpack_interleave<0x15, X86Unpckh, v8f32, loadv8f32, - VR256, f256mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedSingle>, PS, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKHPDY: sse12_unpack_interleave<0x15, X86Unpckh, v4f64, loadv4f64, - VR256, f256mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedDouble>, PD, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKLPSY: sse12_unpack_interleave<0x14, X86Unpckl, v8f32, loadv8f32, - VR256, f256mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedSingle>, PS, VEX_4V, VEX_L, VEX_WIG; -defm VUNPCKLPDY: sse12_unpack_interleave<0x14, X86Unpckl, v4f64, loadv4f64, - VR256, f256mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SchedWriteFShuffle.YMM, SSEPackedDouble>, PD, VEX_4V, VEX_L, VEX_WIG; -}// Predicates = [HasAVX, NoVLX] - -let Constraints = "$src1 = $dst" in { - defm UNPCKHPS: sse12_unpack_interleave<0x15, X86Unpckh, v4f32, memopv4f32, - VR128, f128mem, "unpckhps\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS; - defm UNPCKHPD: sse12_unpack_interleave<0x15, X86Unpckh, v2f64, memopv2f64, - VR128, f128mem, "unpckhpd\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble, 1>, PD; - defm UNPCKLPS: sse12_unpack_interleave<0x14, X86Unpckl, v4f32, memopv4f32, - VR128, f128mem, "unpcklps\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedSingle>, PS; - defm UNPCKLPD: sse12_unpack_interleave<0x14, X86Unpckl, v2f64, memopv2f64, - VR128, f128mem, "unpcklpd\t{$src2, $dst|$dst, $src2}", - SchedWriteFShuffle.XMM, SSEPackedDouble>, PD; -} // Constraints = "$src1 = $dst" - -let Predicates = [HasAVX1Only] in { - def : Pat<(v8i32 (X86Unpckl VR256:$src1, (bc_v8i32 (loadv4i64 addr:$src2)))), - (VUNPCKLPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86Unpckl VR256:$src1, VR256:$src2)), - (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v8i32 (X86Unpckh VR256:$src1, (bc_v8i32 (loadv4i64 addr:$src2)))), - (VUNPCKHPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86Unpckh VR256:$src1, VR256:$src2)), - (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>; - - def : Pat<(v4i64 (X86Unpckl VR256:$src1, (loadv4i64 addr:$src2))), - (VUNPCKLPDYrm VR256:$src1, addr:$src2)>; - def : Pat<(v4i64 (X86Unpckl VR256:$src1, VR256:$src2)), - (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (X86Unpckh VR256:$src1, (loadv4i64 addr:$src2))), - (VUNPCKHPDYrm VR256:$src1, addr:$src2)>; - def : Pat<(v4i64 (X86Unpckh VR256:$src1, VR256:$src2)), - (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>; -} - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Extract Floating-Point Sign mask -//===----------------------------------------------------------------------===// - -/// sse12_extr_sign_mask - sse 1 & 2 unpack and interleave -multiclass sse12_extr_sign_mask { - def rr : PI<0x50, MRMSrcReg, (outs GR32orGR64:$dst), (ins RC:$src), - !strconcat(asm, "\t{$src, $dst|$dst, $src}"), - [(set GR32orGR64:$dst, (X86movmsk (vt RC:$src)))], d>, - Sched<[WriteFMOVMSK]>; -} - -let Predicates = [HasAVX] in { - defm VMOVMSKPS : sse12_extr_sign_mask, PS, VEX, VEX_WIG; - defm VMOVMSKPD : sse12_extr_sign_mask, PD, VEX, VEX_WIG; - defm VMOVMSKPSY : sse12_extr_sign_mask, PS, VEX, VEX_L, VEX_WIG; - defm VMOVMSKPDY : sse12_extr_sign_mask, PD, VEX, VEX_L, VEX_WIG; -} - -defm MOVMSKPS : sse12_extr_sign_mask, PS; -defm MOVMSKPD : sse12_extr_sign_mask, PD; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Logical Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -/// PDI_binop_rm - Simple SSE2 binary operator. -multiclass PDI_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit IsCommutable, bit Is2Addr> { - let isCommutable = IsCommutable in - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} // ExeDomain = SSEPackedInt - -multiclass PDI_binop_all opc, string OpcodeStr, SDNode Opcode, - ValueType OpVT128, ValueType OpVT256, - X86SchedWriteWidths sched, bit IsCommutable, - Predicate prd> { -let Predicates = [HasAVX, prd] in - defm V#NAME : PDI_binop_rm, VEX_4V, VEX_WIG; - -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_rm; - -let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : PDI_binop_rm, VEX_4V, VEX_L, VEX_WIG; -} - -// These are ordered here for pattern ordering requirements with the fp versions - -defm PAND : PDI_binop_all<0xDB, "pand", and, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm POR : PDI_binop_all<0xEB, "por", or, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm PXOR : PDI_binop_all<0xEF, "pxor", xor, v2i64, v4i64, - SchedWriteVecLogic, 1, NoVLX>; -defm PANDN : PDI_binop_all<0xDF, "pandn", X86andnp, v2i64, v4i64, - SchedWriteVecLogic, 0, NoVLX>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Logical Instructions -//===----------------------------------------------------------------------===// - -/// sse12_fp_packed_logical - SSE 1 & 2 packed FP logical ops -/// -/// There are no patterns here because isel prefers integer versions for SSE2 -/// and later. There are SSE1 v4f32 patterns later. -multiclass sse12_fp_packed_logical opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { - let Predicates = [HasAVX, NoVLX] in { - defm V#NAME#PSY : sse12_fp_packed_logical_rm, PS, VEX_4V, VEX_L, VEX_WIG; - - defm V#NAME#PDY : sse12_fp_packed_logical_rm, PD, VEX_4V, VEX_L, VEX_WIG; - - defm V#NAME#PS : sse12_fp_packed_logical_rm, PS, VEX_4V, VEX_WIG; - - defm V#NAME#PD : sse12_fp_packed_logical_rm, PD, VEX_4V, VEX_WIG; - } - - let Constraints = "$src1 = $dst" in { - defm PS : sse12_fp_packed_logical_rm, PS; - - defm PD : sse12_fp_packed_logical_rm, PD; - } -} - -defm AND : sse12_fp_packed_logical<0x54, "and", and, SchedWriteFLogic>; -defm OR : sse12_fp_packed_logical<0x56, "or", or, SchedWriteFLogic>; -defm XOR : sse12_fp_packed_logical<0x57, "xor", xor, SchedWriteFLogic>; -let isCommutable = 0 in - defm ANDN : sse12_fp_packed_logical<0x55, "andn", X86andnp, SchedWriteFLogic>; - -// If only AVX1 is supported, we need to handle integer operations with -// floating point instructions since the integer versions aren't available. -let Predicates = [HasAVX1Only] in { - def : Pat<(v4i64 (and VR256:$src1, VR256:$src2)), - (VANDPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (or VR256:$src1, VR256:$src2)), - (VORPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (xor VR256:$src1, VR256:$src2)), - (VXORPSYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v4i64 (X86andnp VR256:$src1, VR256:$src2)), - (VANDNPSYrr VR256:$src1, VR256:$src2)>; - - def : Pat<(and VR256:$src1, (loadv4i64 addr:$src2)), - (VANDPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(or VR256:$src1, (loadv4i64 addr:$src2)), - (VORPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(xor VR256:$src1, (loadv4i64 addr:$src2)), - (VXORPSYrm VR256:$src1, addr:$src2)>; - def : Pat<(X86andnp VR256:$src1, (loadv4i64 addr:$src2)), - (VANDNPSYrm VR256:$src1, addr:$src2)>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoDQI] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86for FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fxor FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VXORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fandn FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (VANDNPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - - def : Pat<(f32 (X86fand FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86for FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fxor FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VXORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fandn FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (VANDNPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; -} - -let Predicates = [UseSSE1] in { - // Use packed logical operations for scalar ops. - def : Pat<(f32 (X86fand FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ANDPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86for FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fxor FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (XORPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; - def : Pat<(f32 (X86fandn FR32:$src1, FR32:$src2)), - (COPY_TO_REGCLASS - (v4f32 (ANDNPSrr (v4f32 (COPY_TO_REGCLASS FR32:$src1, VR128)), - (v4f32 (COPY_TO_REGCLASS FR32:$src2, VR128)))), - FR32)>; -} - -let Predicates = [UseSSE2] in { - // Use packed logical operations for scalar ops. - def : Pat<(f64 (X86fand FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ANDPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86for FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fxor FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (XORPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; - def : Pat<(f64 (X86fandn FR64:$src1, FR64:$src2)), - (COPY_TO_REGCLASS - (v2f64 (ANDNPDrr (v2f64 (COPY_TO_REGCLASS FR64:$src1, VR128)), - (v2f64 (COPY_TO_REGCLASS FR64:$src2, VR128)))), - FR64)>; -} - -// Patterns for packed operations when we don't have integer type available. -def : Pat<(v4f32 (X86fand VR128:$src1, VR128:$src2)), - (ANDPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86for VR128:$src1, VR128:$src2)), - (ORPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86fxor VR128:$src1, VR128:$src2)), - (XORPSrr VR128:$src1, VR128:$src2)>; -def : Pat<(v4f32 (X86fandn VR128:$src1, VR128:$src2)), - (ANDNPSrr VR128:$src1, VR128:$src2)>; - -def : Pat<(X86fand VR128:$src1, (memopv4f32 addr:$src2)), - (ANDPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86for VR128:$src1, (memopv4f32 addr:$src2)), - (ORPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86fxor VR128:$src1, (memopv4f32 addr:$src2)), - (XORPSrm VR128:$src1, addr:$src2)>; -def : Pat<(X86fandn VR128:$src1, (memopv4f32 addr:$src2)), - (ANDNPSrm VR128:$src1, addr:$src2)>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Arithmetic Instructions -//===----------------------------------------------------------------------===// - -/// basic_sse12_fp_binop_xxx - SSE 1 & 2 binops come in both scalar and -/// vector forms. -/// -/// In addition, we also have a special variant of the scalar form here to -/// represent the associated intrinsic operation. This form is unlike the -/// plain scalar form, in that it takes an entire vector (instead of a scalar) -/// and leaves the top elements unmodified (therefore these cannot be commuted). -/// -/// These three forms can each be reg+reg or reg+mem. -/// - -/// FIXME: once all 256-bit intrinsics are matched, cleanup and refactor those -/// classes below -multiclass basic_sse12_fp_binop_p opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteSizes sched> { - let Predicates = [HasAVX, NoVLX] in { - defm V#NAME#PS : sse12_fp_packed, PS, VEX_4V, VEX_WIG; - defm V#NAME#PD : sse12_fp_packed, PD, VEX_4V, VEX_WIG; - - defm V#NAME#PSY : sse12_fp_packed, PS, VEX_4V, VEX_L, VEX_WIG; - defm V#NAME#PDY : sse12_fp_packed, PD, VEX_4V, VEX_L, VEX_WIG; - } - - let Constraints = "$src1 = $dst" in { - defm PS : sse12_fp_packed, PS; - defm PD : sse12_fp_packed, PD; - } -} - -multiclass basic_sse12_fp_binop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteSizes sched> { - defm V#NAME#SS : sse12_fp_scalar, - XS, VEX_4V, VEX_LIG, VEX_WIG; - defm V#NAME#SD : sse12_fp_scalar, - XD, VEX_4V, VEX_LIG, VEX_WIG; - - let Constraints = "$src1 = $dst" in { - defm SS : sse12_fp_scalar, XS; - defm SD : sse12_fp_scalar, XD; - } -} - -multiclass basic_sse12_fp_binop_s_int opc, string OpcodeStr, - SDPatternOperator OpNode, - X86SchedWriteSizes sched> { - defm V#NAME#SS : sse12_fp_scalar_int, XS, VEX_4V, VEX_LIG, VEX_WIG; - defm V#NAME#SD : sse12_fp_scalar_int, XD, VEX_4V, VEX_LIG, VEX_WIG; - - let Constraints = "$src1 = $dst" in { - defm SS : sse12_fp_scalar_int, XS; - defm SD : sse12_fp_scalar_int, XD; - } -} - -// Binary Arithmetic instructions -defm ADD : basic_sse12_fp_binop_p<0x58, "add", fadd, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s<0x58, "add", fadd, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s_int<0x58, "add", null_frag, SchedWriteFAddSizes>; -defm MUL : basic_sse12_fp_binop_p<0x59, "mul", fmul, SchedWriteFMulSizes>, - basic_sse12_fp_binop_s<0x59, "mul", fmul, SchedWriteFMulSizes>, - basic_sse12_fp_binop_s_int<0x59, "mul", null_frag, SchedWriteFMulSizes>; -let isCommutable = 0 in { - defm SUB : basic_sse12_fp_binop_p<0x5C, "sub", fsub, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s<0x5C, "sub", fsub, SchedWriteFAddSizes>, - basic_sse12_fp_binop_s_int<0x5C, "sub", null_frag, SchedWriteFAddSizes>; - defm DIV : basic_sse12_fp_binop_p<0x5E, "div", fdiv, SchedWriteFDivSizes>, - basic_sse12_fp_binop_s<0x5E, "div", fdiv, SchedWriteFDivSizes>, - basic_sse12_fp_binop_s_int<0x5E, "div", null_frag, SchedWriteFDivSizes>; - defm MAX : basic_sse12_fp_binop_p<0x5F, "max", X86fmax, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5F, "max", X86fmax, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s_int<0x5F, "max", X86fmaxs, SchedWriteFCmpSizes>; - defm MIN : basic_sse12_fp_binop_p<0x5D, "min", X86fmin, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5D, "min", X86fmin, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s_int<0x5D, "min", X86fmins, SchedWriteFCmpSizes>; -} - -let isCodeGenOnly = 1 in { - defm MAXC: basic_sse12_fp_binop_p<0x5F, "max", X86fmaxc, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5F, "max", X86fmaxc, SchedWriteFCmpSizes>; - defm MINC: basic_sse12_fp_binop_p<0x5D, "min", X86fminc, SchedWriteFCmpSizes>, - basic_sse12_fp_binop_s<0x5D, "min", X86fminc, SchedWriteFCmpSizes>; -} - -// Patterns used to select SSE scalar fp arithmetic instructions from -// either: -// -// (1) a scalar fp operation followed by a blend -// -// The effect is that the backend no longer emits unnecessary vector -// insert instructions immediately after SSE scalar fp instructions -// like addss or mulss. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// A[0] += B[0]; -// return A; -// } -// -// Previously we generated: -// addss %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 -// -// (2) a vector packed single/double fp operation followed by a vector insert -// -// The effect is that the backend converts the packed fp instruction -// followed by a vector insert into a single SSE scalar fp instruction. -// -// For example, given the following code: -// __m128 foo(__m128 A, __m128 B) { -// __m128 C = A + B; -// return (__m128) {c[0], a[1], a[2], a[3]}; -// } -// -// Previously we generated: -// addps %xmm0, %xmm1 -// movss %xmm1, %xmm0 -// -// We now generate: -// addss %xmm1, %xmm0 - -// TODO: Some canonicalization in lowering would simplify the number of -// patterns we have to try to match. -multiclass scalar_math_patterns { - let Predicates = [BasePredicate] in { - // extracted scalar math op with insert via movss/movsd - def : Pat<(VT (Move (VT VR128:$dst), - (VT (scalar_to_vector - (Op (EltTy (extractelt (VT VR128:$dst), (iPTR 0))), - RC:$src))))), - (!cast(OpcPrefix#rr_Int) VT:$dst, - (VT (COPY_TO_REGCLASS RC:$src, VR128)))>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - // extracted scalar math op with insert via movss/movsd - def : Pat<(VT (Move (VT VR128:$dst), - (VT (scalar_to_vector - (Op (EltTy (extractelt (VT VR128:$dst), (iPTR 0))), - RC:$src))))), - (!cast("V"#OpcPrefix#rr_Int) VT:$dst, - (VT (COPY_TO_REGCLASS RC:$src, VR128)))>; - } -} - -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; - -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; -defm : scalar_math_patterns; - -/// Unop Arithmetic -/// In addition, we also have a special variant of the scalar form here to -/// represent the associated intrinsic operation. This form is unlike the -/// plain scalar form, in that it takes an entire vector (instead of a -/// scalar) and leaves the top elements undefined. -/// -/// And, we have a special variant form for a full-vector intrinsic form. - -/// sse_fp_unop_s - SSE1 unops in scalar form -/// For the non-AVX defs, we need $src1 to be tied to $dst because -/// the HW instructions are 2 operand / destructive. -multiclass sse_fp_unop_s opc, string OpcodeStr, RegisterClass RC, - ValueType ScalarVT, X86MemOperand x86memop, - Operand intmemop, SDNode OpNode, Domain d, - X86FoldableSchedWrite sched, Predicate target> { - let hasSideEffects = 0 in { - def r : I, Sched<[sched]>, - Requires<[target]>; - let mayLoad = 1 in - def m : I, - Sched<[sched.Folded, ReadAfterLd]>, - Requires<[target, OptForSize]>; - - let isCodeGenOnly = 1, Constraints = "$src1 = $dst", ExeDomain = d in { - def r_Int : I, - Sched<[sched]>; - let mayLoad = 1 in - def m_Int : I, - Sched<[sched.Folded, ReadAfterLd]>; - } - } - -} - -multiclass sse_fp_unop_s_intr { - let Predicates = [target] in { - // These are unary operations, but they are modeled as having 2 source operands - // because the high elements of the destination are unchanged in SSE. - def : Pat<(Intr VR128:$src), - (!cast(NAME#r_Int) VR128:$src, VR128:$src)>; - } - // We don't want to fold scalar loads into these instructions unless - // optimizing for size. This is because the folded instruction will have a - // partial register update, while the unfolded sequence will not, e.g. - // movss mem, %xmm0 - // rcpss %xmm0, %xmm0 - // which has a clobber before the rcp, vs. - // rcpss mem, %xmm0 - let Predicates = [target, OptForSize] in { - def : Pat<(Intr int_cpat:$src2), - (!cast(NAME#m_Int) - (vt (IMPLICIT_DEF)), addr:$src2)>; - } -} - -multiclass avx_fp_unop_s_intr { - let Predicates = [target] in { - def : Pat<(Intr VR128:$src), - (!cast(NAME#r_Int) VR128:$src, - VR128:$src)>; - } - let Predicates = [target, OptForSize] in { - def : Pat<(Intr int_cpat:$src2), - (!cast(NAME#m_Int) - (vt (IMPLICIT_DEF)), addr:$src2)>; - } -} - -multiclass avx_fp_unop_s opc, string OpcodeStr, RegisterClass RC, - ValueType ScalarVT, X86MemOperand x86memop, - Operand intmemop, SDNode OpNode, Domain d, - X86FoldableSchedWrite sched, Predicate target> { - let hasSideEffects = 0 in { - def r : I, Sched<[sched]>; - let mayLoad = 1 in - def m : I, Sched<[sched.Folded, ReadAfterLd]>; - let isCodeGenOnly = 1, ExeDomain = d in { - def r_Int : I, Sched<[sched]>; - let mayLoad = 1 in - def m_Int : I, Sched<[sched.Folded, ReadAfterLd]>; - } - } - - // We don't want to fold scalar loads into these instructions unless - // optimizing for size. This is because the folded instruction will have a - // partial register update, while the unfolded sequence will not, e.g. - // vmovss mem, %xmm0 - // vrcpss %xmm0, %xmm0, %xmm0 - // which has a clobber before the rcp, vs. - // vrcpss mem, %xmm0, %xmm0 - // TODO: In theory, we could fold the load, and avoid the stall caused by - // the partial register store, either in BreakFalseDeps or with smarter RA. - let Predicates = [target] in { - def : Pat<(OpNode RC:$src), (!cast(NAME#r) - (ScalarVT (IMPLICIT_DEF)), RC:$src)>; - } - let Predicates = [target, OptForSize] in { - def : Pat<(ScalarVT (OpNode (load addr:$src))), - (!cast(NAME#m) (ScalarVT (IMPLICIT_DEF)), - addr:$src)>; - } -} - -/// sse1_fp_unop_p - SSE1 unops in packed form. -multiclass sse1_fp_unop_p opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, list prds> { -let Predicates = prds in { - def V#NAME#PSr : PSI, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#PSm : PSI, - VEX, Sched<[sched.XMM.Folded]>, VEX_WIG; - def V#NAME#PSYr : PSI, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#PSYm : PSI, - VEX, VEX_L, Sched<[sched.YMM.Folded]>, VEX_WIG; -} - - def PSr : PSI, - Sched<[sched.XMM]>; - def PSm : PSI, - Sched<[sched.XMM.Folded]>; -} - -/// sse2_fp_unop_p - SSE2 unops in vector forms. -multiclass sse2_fp_unop_p opc, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { -let Predicates = [HasAVX, NoVLX] in { - def V#NAME#PDr : PDI, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#PDm : PDI, - VEX, Sched<[sched.XMM.Folded]>, VEX_WIG; - def V#NAME#PDYr : PDI, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#PDYm : PDI, - VEX, VEX_L, Sched<[sched.YMM.Folded]>, VEX_WIG; -} - - def PDr : PDI, - Sched<[sched.XMM]>; - def PDm : PDI, - Sched<[sched.XMM.Folded]>; -} - -multiclass sse1_fp_unop_s_intr opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SS : sse_fp_unop_s_intr("int_x86_sse_"##OpcodeStr##_ss), - UseSSE1, "SS">, XS; - defm V#NAME#SS : avx_fp_unop_s_intr("int_x86_sse_"##OpcodeStr##_ss), - AVXTarget>, - XS, VEX_4V, VEX_LIG, VEX_WIG, NotMemoryFoldable; -} - -multiclass sse1_fp_unop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SS : sse_fp_unop_s, XS; - defm V#NAME#SS : avx_fp_unop_s, - XS, VEX_4V, VEX_LIG, VEX_WIG; -} - -multiclass sse2_fp_unop_s opc, string OpcodeStr, SDNode OpNode, - X86SchedWriteWidths sched, Predicate AVXTarget> { - defm SD : sse_fp_unop_s, XD; - defm V#NAME#SD : avx_fp_unop_s, - XD, VEX_4V, VEX_LIG, VEX_WIG; -} - -// Square root. -defm SQRT : sse1_fp_unop_s<0x51, "sqrt", fsqrt, SchedWriteFSqrt, UseAVX>, - sse1_fp_unop_p<0x51, "sqrt", fsqrt, SchedWriteFSqrt, [HasAVX, NoVLX]>, - sse2_fp_unop_s<0x51, "sqrt", fsqrt, SchedWriteFSqrt64, UseAVX>, - sse2_fp_unop_p<0x51, "sqrt", fsqrt, SchedWriteFSqrt64>; - -// Reciprocal approximations. Note that these typically require refinement -// in order to obtain suitable precision. -defm RSQRT : sse1_fp_unop_s<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, HasAVX>, - sse1_fp_unop_s_intr<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, HasAVX>, - sse1_fp_unop_p<0x52, "rsqrt", X86frsqrt, SchedWriteFRsqrt, [HasAVX]>; -defm RCP : sse1_fp_unop_s<0x53, "rcp", X86frcp, SchedWriteFRcp, HasAVX>, - sse1_fp_unop_s_intr<0x53, "rcp", X86frcp, SchedWriteFRcp, HasAVX>, - sse1_fp_unop_p<0x53, "rcp", X86frcp, SchedWriteFRcp, [HasAVX]>; - -// There is no f64 version of the reciprocal approximation instructions. - -multiclass scalar_unary_math_patterns { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } -} - -multiclass scalar_unary_math_imm_patterns ImmV, - Predicate BasePredicate> { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src, (i32 ImmV))>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [UseAVX] in { - def : Pat<(VT (Move VT:$dst, (scalar_to_vector - (OpNode (extractelt VT:$src, 0))))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src, (i32 ImmV))>; - } -} - -defm : scalar_unary_math_patterns; -defm : scalar_unary_math_patterns; - -multiclass scalar_unary_math_intr_patterns { - let Predicates = [BasePredicate] in { - def : Pat<(VT (Move VT:$dst, (Intr VT:$src))), - (!cast(OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } - - // Repeat for AVX versions of the instructions. - let Predicates = [HasAVX] in { - def : Pat<(VT (Move VT:$dst, (Intr VT:$src))), - (!cast("V"#OpcPrefix#r_Int) VT:$dst, VT:$src)>; - } -} - -defm : scalar_unary_math_intr_patterns; -defm : scalar_unary_math_intr_patterns; - - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Non-temporal stores -//===----------------------------------------------------------------------===// - -let AddedComplexity = 400 in { // Prefer non-temporal versions -let Predicates = [HasAVX, NoVLX] in { -let SchedRW = [SchedWriteFMoveLSNT.XMM.MR] in { -def VMOVNTPSmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG; -def VMOVNTPDmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2f64 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG; -} // SchedRW - -let SchedRW = [SchedWriteFMoveLSNT.YMM.MR] in { -def VMOVNTPSYmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v8f32 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG; -def VMOVNTPDYmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f64 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG; -} // SchedRW - -let ExeDomain = SSEPackedInt in { -def VMOVNTDQmr : VPDI<0xE7, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2i64 VR128:$src), - addr:$dst)]>, VEX, VEX_WIG, - Sched<[SchedWriteVecMoveLSNT.XMM.MR]>; -def VMOVNTDQYmr : VPDI<0xE7, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4i64 VR256:$src), - addr:$dst)]>, VEX, VEX_L, VEX_WIG, - Sched<[SchedWriteVecMoveLSNT.YMM.MR]>; -} // ExeDomain -} // Predicates - -let SchedRW = [SchedWriteFMoveLSNT.XMM.MR] in { -def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>; -def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore(v2f64 VR128:$src), addr:$dst)]>; -} // SchedRW - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecMoveLSNT.XMM.MR] in -def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2i64 VR128:$src), addr:$dst)]>; - -let SchedRW = [WriteStoreNT] in { -// There is no AVX form for instructions below this point -def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movnti{l}\t{$src, $dst|$dst, $src}", - [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, - PS, Requires<[HasSSE2]>; -def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movnti{q}\t{$src, $dst|$dst, $src}", - [(nontemporalstore (i64 GR64:$src), addr:$dst)]>, - PS, Requires<[HasSSE2]>; -} // SchedRW = [WriteStoreNT] - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(alignednontemporalstore (v8i32 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - def : Pat<(alignednontemporalstore (v16i16 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - def : Pat<(alignednontemporalstore (v32i8 VR256:$src), addr:$dst), - (VMOVNTDQYmr addr:$dst, VR256:$src)>; - - def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128:$src), addr:$dst), - (VMOVNTDQmr addr:$dst, VR128:$src)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v8i16 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; - def : Pat<(alignednontemporalstore (v16i8 VR128:$src), addr:$dst), - (MOVNTDQmr addr:$dst, VR128:$src)>; -} - -} // AddedComplexity - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Prefetch and memory fence -//===----------------------------------------------------------------------===// - -// Prefetch intrinsic. -let Predicates = [HasSSEPrefetch], SchedRW = [WriteLoad] in { -def PREFETCHT0 : I<0x18, MRM1m, (outs), (ins i8mem:$src), - "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3), (i32 1))]>, TB; -def PREFETCHT1 : I<0x18, MRM2m, (outs), (ins i8mem:$src), - "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2), (i32 1))]>, TB; -def PREFETCHT2 : I<0x18, MRM3m, (outs), (ins i8mem:$src), - "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1), (i32 1))]>, TB; -def PREFETCHNTA : I<0x18, MRM0m, (outs), (ins i8mem:$src), - "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), (i32 1))]>, TB; -} - -// FIXME: How should flush instruction be modeled? -let SchedRW = [WriteLoad] in { -// Flush cache -def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src), - "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>, - PS, Requires<[HasSSE2]>; -} - -let SchedRW = [WriteNop] in { -// Pause. This "instruction" is encoded as "rep; nop", so even though it -// was introduced with SSE2, it's backward compatible. -def PAUSE : I<0x90, RawFrm, (outs), (ins), - "pause", [(int_x86_sse2_pause)]>, OBXS; -} - -let SchedRW = [WriteFence] in { -// Load, store, and memory fence -// TODO: As with mfence, we may want to ease the availability of sfence/lfence -// to include any 64-bit target. -def SFENCE : I<0xAE, MRM_F8, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>, - PS, Requires<[HasSSE1]>; -def LFENCE : I<0xAE, MRM_E8, (outs), (ins), "lfence", [(int_x86_sse2_lfence)]>, - PS, Requires<[HasSSE2]>; -def MFENCE : I<0xAE, MRM_F0, (outs), (ins), "mfence", [(int_x86_sse2_mfence)]>, - PS, Requires<[HasMFence]>; -} // SchedRW - -def : Pat<(X86MFence), (MFENCE)>; - -//===----------------------------------------------------------------------===// -// SSE 1 & 2 - Load/Store XCSR register -//===----------------------------------------------------------------------===// - -def VLDMXCSR : VPSI<0xAE, MRM2m, (outs), (ins i32mem:$src), - "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, - VEX, Sched<[WriteLDMXCSR]>, VEX_WIG; -def VSTMXCSR : VPSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), - "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, - VEX, Sched<[WriteSTMXCSR]>, VEX_WIG; - -def LDMXCSR : I<0xAE, MRM2m, (outs), (ins i32mem:$src), - "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, - TB, Sched<[WriteLDMXCSR]>; -def STMXCSR : I<0xAE, MRM3m, (outs), (ins i32mem:$dst), - "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, - TB, Sched<[WriteSTMXCSR]>; - -//===---------------------------------------------------------------------===// -// SSE2 - Move Aligned/Unaligned Packed Integer Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -let hasSideEffects = 0 in { -def VMOVDQArr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, VEX, VEX_WIG; -def VMOVDQUrr : VSSI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, VEX, VEX_WIG; -def VMOVDQAYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, VEX, VEX_L, VEX_WIG; -def VMOVDQUYrr : VSSI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, VEX, VEX_L, VEX_WIG; -} - -// For Disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def VMOVDQArr_REV : VPDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, - VEX, VEX_WIG, FoldGenData<"VMOVDQArr">; -def VMOVDQAYrr_REV : VPDI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVDQAYrr">; -def VMOVDQUrr_REV : VSSI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.XMM.RR]>, - VEX, VEX_WIG, FoldGenData<"VMOVDQUrr">; -def VMOVDQUYrr_REV : VSSI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RR]>, - VEX, VEX_L, VEX_WIG, FoldGenData<"VMOVDQUYrr">; -} - -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - hasSideEffects = 0, Predicates = [HasAVX,NoVLX] in { -def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (alignedloadv2i64 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, VEX, VEX_WIG; -def VMOVDQAYrm : VPDI<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, - VEX, VEX_L, VEX_WIG; -def VMOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (loadv2i64 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, - XS, VEX, VEX_WIG; -def VMOVDQUYrm : I<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, - XS, VEX, VEX_L, VEX_WIG; -} - -let mayStore = 1, hasSideEffects = 0, Predicates = [HasAVX,NoVLX] in { -def VMOVDQAmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [(alignedstore (v2i64 VR128:$src), addr:$dst)]>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, VEX, VEX_WIG; -def VMOVDQAYmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLS.YMM.MR]>, VEX, VEX_L, VEX_WIG; -def VMOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(store (v2i64 VR128:$src), addr:$dst)]>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, XS, VEX, VEX_WIG; -def VMOVDQUYmr : I<0x7F, MRMDestMem, (outs), (ins i256mem:$dst, VR256:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, - Sched<[SchedWriteVecMoveLS.YMM.MR]>, XS, VEX, VEX_L, VEX_WIG; -} - -let SchedRW = [SchedWriteVecMoveLS.XMM.RR] in { -let hasSideEffects = 0 in { -def MOVDQArr : PDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>; - -def MOVDQUrr : I<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - XS, Requires<[UseSSE2]>; -} - -// For Disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { -def MOVDQArr_REV : PDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, - FoldGenData<"MOVDQArr">; - -def MOVDQUrr_REV : I<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, - XS, Requires<[UseSSE2]>, FoldGenData<"MOVDQUrr">; -} -} // SchedRW - -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - hasSideEffects = 0, SchedRW = [SchedWriteVecMoveLS.XMM.RM] in { -def MOVDQArm : PDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [/*(set VR128:$dst, (alignedloadv2i64 addr:$src))*/]>; -def MOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [/*(set VR128:$dst, (loadv2i64 addr:$src))*/]>, - XS, Requires<[UseSSE2]>; -} - -let mayStore = 1, hasSideEffects = 0, - SchedRW = [SchedWriteVecMoveLS.XMM.MR] in { -def MOVDQAmr : PDI<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", - [/*(alignedstore (v2i64 VR128:$src), addr:$dst)*/]>; -def MOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [/*(store (v2i64 VR128:$src), addr:$dst)*/]>, - XS, Requires<[UseSSE2]>; -} - -} // ExeDomain = SSEPackedInt - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -def : InstAlias<"vmovdqa\t{$src, $dst|$dst, $src}", - (VMOVDQArr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovdqa\t{$src, $dst|$dst, $src}", - (VMOVDQAYrr_REV VR256L:$dst, VR256H:$src), 0>; -def : InstAlias<"vmovdqu\t{$src, $dst|$dst, $src}", - (VMOVDQUrr_REV VR128L:$dst, VR128H:$src), 0>; -def : InstAlias<"vmovdqu\t{$src, $dst|$dst, $src}", - (VMOVDQUYrr_REV VR256L:$dst, VR256H:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -def : InstAlias<"vmovdqa.s\t{$src, $dst|$dst, $src}", - (VMOVDQArr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovdqa.s\t{$src, $dst|$dst, $src}", - (VMOVDQAYrr_REV VR256:$dst, VR256:$src), 0>; -def : InstAlias<"vmovdqu.s\t{$src, $dst|$dst, $src}", - (VMOVDQUrr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"vmovdqu.s\t{$src, $dst|$dst, $src}", - (VMOVDQUYrr_REV VR256:$dst, VR256:$src), 0>; - -// Reversed version with ".s" suffix for GAS compatibility. -def : InstAlias<"movdqa.s\t{$src, $dst|$dst, $src}", - (MOVDQArr_REV VR128:$dst, VR128:$src), 0>; -def : InstAlias<"movdqu.s\t{$src, $dst|$dst, $src}", - (MOVDQUrr_REV VR128:$dst, VR128:$src), 0>; - -let Predicates = [HasAVX, NoVLX] in { - // Additional patterns for other integer sizes. - def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), - (VMOVDQAmr addr:$dst, VR128:$src)>; - def : Pat<(store (v4i32 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; - def : Pat<(store (v8i16 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; - def : Pat<(store (v16i8 VR128:$src), addr:$dst), - (VMOVDQUmr addr:$dst, VR128:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Arithmetic Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { // SSE integer instructions - -/// PDI_binop_rm2 - Simple SSE2 binary operator with different src and dst types -multiclass PDI_binop_rm2 opc, string OpcodeStr, SDNode OpNode, - ValueType DstVT, ValueType SrcVT, RegisterClass RC, - PatFrag memop_frag, X86MemOperand x86memop, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} -} // ExeDomain = SSEPackedInt - -defm PADDB : PDI_binop_all<0xFC, "paddb", add, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDW : PDI_binop_all<0xFD, "paddw", add, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDD : PDI_binop_all<0xFE, "paddd", add, v4i32, v8i32, - SchedWriteVecALU, 1, NoVLX>; -defm PADDQ : PDI_binop_all<0xD4, "paddq", add, v2i64, v4i64, - SchedWriteVecALU, 1, NoVLX>; -defm PADDSB : PDI_binop_all<0xEC, "paddsb", X86adds, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDSW : PDI_binop_all<0xED, "paddsw", X86adds, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDUSB : PDI_binop_all<0xDC, "paddusb", X86addus, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PADDUSW : PDI_binop_all<0xDD, "paddusw", X86addus, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMULLW : PDI_binop_all<0xD5, "pmullw", mul, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PMULHUW : PDI_binop_all<0xE4, "pmulhuw", mulhu, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PMULHW : PDI_binop_all<0xE5, "pmulhw", mulhs, v8i16, v16i16, - SchedWriteVecIMul, 1, NoVLX_Or_NoBWI>; -defm PSUBB : PDI_binop_all<0xF8, "psubb", sub, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBW : PDI_binop_all<0xF9, "psubw", sub, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBD : PDI_binop_all<0xFA, "psubd", sub, v4i32, v8i32, - SchedWriteVecALU, 0, NoVLX>; -defm PSUBQ : PDI_binop_all<0xFB, "psubq", sub, v2i64, v4i64, - SchedWriteVecALU, 0, NoVLX>; -defm PSUBSB : PDI_binop_all<0xE8, "psubsb", X86subs, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBSW : PDI_binop_all<0xE9, "psubsw", X86subs, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBUSB : PDI_binop_all<0xD8, "psubusb", X86subus, v16i8, v32i8, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PSUBUSW : PDI_binop_all<0xD9, "psubusw", X86subus, v8i16, v16i16, - SchedWriteVecALU, 0, NoVLX_Or_NoBWI>; -defm PMINUB : PDI_binop_all<0xDA, "pminub", umin, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMINSW : PDI_binop_all<0xEA, "pminsw", smin, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMAXUB : PDI_binop_all<0xDE, "pmaxub", umax, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMAXSW : PDI_binop_all<0xEE, "pmaxsw", smax, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PAVGB : PDI_binop_all<0xE0, "pavgb", X86avg, v16i8, v32i8, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PAVGW : PDI_binop_all<0xE3, "pavgw", X86avg, v8i16, v16i16, - SchedWriteVecALU, 1, NoVLX_Or_NoBWI>; -defm PMULUDQ : PDI_binop_all<0xF4, "pmuludq", X86pmuludq, v2i64, v4i64, - SchedWriteVecIMul, 1, NoVLX>; - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in -defm VPMADDWD : PDI_binop_rm2<0xF5, "vpmaddwd", X86vpmaddwd, v4i32, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecIMul.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in -defm VPMADDWDY : PDI_binop_rm2<0xF5, "vpmaddwd", X86vpmaddwd, v8i32, v16i16, - VR256, loadv4i64, i256mem, SchedWriteVecIMul.YMM, - 0>, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in -defm PMADDWD : PDI_binop_rm2<0xF5, "pmaddwd", X86vpmaddwd, v4i32, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecIMul.XMM>; - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in -defm VPSADBW : PDI_binop_rm2<0xF6, "vpsadbw", X86psadbw, v2i64, v16i8, VR128, - loadv2i64, i128mem, SchedWritePSADBW.XMM, 0>, - VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in -defm VPSADBWY : PDI_binop_rm2<0xF6, "vpsadbw", X86psadbw, v4i64, v32i8, VR256, - loadv4i64, i256mem, SchedWritePSADBW.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in -defm PSADBW : PDI_binop_rm2<0xF6, "psadbw", X86psadbw, v2i64, v16i8, VR128, - memopv2i64, i128mem, SchedWritePSADBW.XMM>; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Logical Instructions -//===---------------------------------------------------------------------===// - -multiclass PDI_binop_rmi opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, SDNode OpNode, - SDNode OpNode2, RegisterClass RC, - X86FoldableSchedWrite sched, - X86FoldableSchedWrite schedImm, - ValueType DstVT, ValueType SrcVT, - PatFrag ld_frag, bit Is2Addr = 1> { - // src2 is always 128-bit - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; - def ri : PDIi8, - Sched<[schedImm]>; -} - -multiclass PDI_binop_rmi_all opc, bits<8> opc2, Format ImmForm, - string OpcodeStr, SDNode OpNode, - SDNode OpNode2, ValueType DstVT128, - ValueType DstVT256, ValueType SrcVT, - X86SchedWriteWidths sched, - X86SchedWriteWidths schedImm, Predicate prd> { -let Predicates = [HasAVX, prd] in - defm V#NAME : PDI_binop_rmi, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : PDI_binop_rmi, VEX_4V, VEX_L, - VEX_WIG; -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_rmi; -} - -multiclass PDI_binop_ri opc, Format ImmForm, string OpcodeStr, - SDNode OpNode, RegisterClass RC, ValueType VT, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - def ri : PDIi8, - Sched<[sched]>; -} - -multiclass PDI_binop_ri_all opc, Format ImmForm, string OpcodeStr, - SDNode OpNode, X86SchedWriteWidths sched> { -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in - defm V#NAME : PDI_binop_ri, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in - defm V#NAME#Y : PDI_binop_ri, - VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst" in - defm NAME : PDI_binop_ri; -} - -let ExeDomain = SSEPackedInt in { - defm PSLLW : PDI_binop_rmi_all<0xF1, 0x71, MRM6r, "psllw", X86vshl, X86vshli, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSLLD : PDI_binop_rmi_all<0xF2, 0x72, MRM6r, "pslld", X86vshl, X86vshli, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - defm PSLLQ : PDI_binop_rmi_all<0xF3, 0x73, MRM6r, "psllq", X86vshl, X86vshli, - v2i64, v4i64, v2i64, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSRLW : PDI_binop_rmi_all<0xD1, 0x71, MRM2r, "psrlw", X86vsrl, X86vsrli, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSRLD : PDI_binop_rmi_all<0xD2, 0x72, MRM2r, "psrld", X86vsrl, X86vsrli, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - defm PSRLQ : PDI_binop_rmi_all<0xD3, 0x73, MRM2r, "psrlq", X86vsrl, X86vsrli, - v2i64, v4i64, v2i64, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSRAW : PDI_binop_rmi_all<0xE1, 0x71, MRM4r, "psraw", X86vsra, X86vsrai, - v8i16, v16i16, v8i16, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX_Or_NoBWI>; - defm PSRAD : PDI_binop_rmi_all<0xE2, 0x72, MRM4r, "psrad", X86vsra, X86vsrai, - v4i32, v8i32, v4i32, SchedWriteVecShift, - SchedWriteVecShiftImm, NoVLX>; - - defm PSLLDQ : PDI_binop_ri_all<0x73, MRM7r, "pslldq", X86vshldq, - SchedWriteShuffle>; - defm PSRLDQ : PDI_binop_ri_all<0x73, MRM3r, "psrldq", X86vshrdq, - SchedWriteShuffle>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Comparison Instructions -//===---------------------------------------------------------------------===// - -defm PCMPEQB : PDI_binop_all<0x74, "pcmpeqb", X86pcmpeq, v16i8, v32i8, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPEQW : PDI_binop_all<0x75, "pcmpeqw", X86pcmpeq, v8i16, v16i16, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPEQD : PDI_binop_all<0x76, "pcmpeqd", X86pcmpeq, v4i32, v8i32, - SchedWriteVecALU, 1, TruePredicate>; -defm PCMPGTB : PDI_binop_all<0x64, "pcmpgtb", X86pcmpgt, v16i8, v32i8, - SchedWriteVecALU, 0, TruePredicate>; -defm PCMPGTW : PDI_binop_all<0x65, "pcmpgtw", X86pcmpgt, v8i16, v16i16, - SchedWriteVecALU, 0, TruePredicate>; -defm PCMPGTD : PDI_binop_all<0x66, "pcmpgtd", X86pcmpgt, v4i32, v8i32, - SchedWriteVecALU, 0, TruePredicate>; - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Shuffle Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pshuffle { -let Predicates = [HasAVX, prd] in { - def V#NAME#ri : Ii8<0x70, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode VR128:$src1, (i8 imm:$src2))))]>, - VEX, Sched<[sched.XMM]>, VEX_WIG; - def V#NAME#mi : Ii8<0x70, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode (bitconvert (loadv2i64 addr:$src1)), - (i8 imm:$src2))))]>, VEX, - Sched<[sched.XMM.Folded]>, VEX_WIG; -} - -let Predicates = [HasAVX2, prd] in { - def V#NAME#Yri : Ii8<0x70, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, - (vt256 (OpNode VR256:$src1, (i8 imm:$src2))))]>, - VEX, VEX_L, Sched<[sched.YMM]>, VEX_WIG; - def V#NAME#Ymi : Ii8<0x70, MRMSrcMem, (outs VR256:$dst), - (ins i256mem:$src1, u8imm:$src2), - !strconcat("v", OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, - (vt256 (OpNode (bitconvert (loadv4i64 addr:$src1)), - (i8 imm:$src2))))]>, VEX, VEX_L, - Sched<[sched.YMM.Folded]>, VEX_WIG; -} - -let Predicates = [UseSSE2] in { - def ri : Ii8<0x70, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, u8imm:$src2), - !strconcat(OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode VR128:$src1, (i8 imm:$src2))))]>, - Sched<[sched.XMM]>; - def mi : Ii8<0x70, MRMSrcMem, - (outs VR128:$dst), (ins i128mem:$src1, u8imm:$src2), - !strconcat(OpcodeStr, - "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, - (vt128 (OpNode (bitconvert (memopv2i64 addr:$src1)), - (i8 imm:$src2))))]>, - Sched<[sched.XMM.Folded]>; -} -} -} // ExeDomain = SSEPackedInt - -defm PSHUFD : sse2_pshuffle<"pshufd", v4i32, v8i32, X86PShufd, - SchedWriteShuffle, NoVLX>, PD; -defm PSHUFHW : sse2_pshuffle<"pshufhw", v8i16, v16i16, X86PShufhw, - SchedWriteShuffle, NoVLX_Or_NoBWI>, XS; -defm PSHUFLW : sse2_pshuffle<"pshuflw", v8i16, v16i16, X86PShuflw, - SchedWriteShuffle, NoVLX_Or_NoBWI>, XD; - -//===---------------------------------------------------------------------===// -// Packed Integer Pack Instructions (SSE & AVX) -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pack opc, string OpcodeStr, ValueType OutVT, - ValueType ArgVT, SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass sse4_pack opc, string OpcodeStr, ValueType OutVT, - ValueType ArgVT, SDNode OpNode, RegisterClass RC, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - def rr : SS48I, - Sched<[sched]>; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPACKSSWB : sse2_pack<0x63, "vpacksswb", v16i8, v8i16, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPACKSSDW : sse2_pack<0x6B, "vpackssdw", v8i16, v4i32, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - - defm VPACKUSWB : sse2_pack<0x67, "vpackuswb", v16i8, v8i16, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPACKUSDW : sse4_pack<0x2B, "vpackusdw", v8i16, v4i32, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPACKSSWBY : sse2_pack<0x63, "vpacksswb", v32i8, v16i16, X86Packss, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPACKSSDWY : sse2_pack<0x6B, "vpackssdw", v16i16, v8i32, X86Packss, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - - defm VPACKUSWBY : sse2_pack<0x67, "vpackuswb", v32i8, v16i16, X86Packus, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPACKUSDWY : sse4_pack<0x2B, "vpackusdw", v16i16, v8i32, X86Packus, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L; -} - -let Constraints = "$src1 = $dst" in { - defm PACKSSWB : sse2_pack<0x63, "packsswb", v16i8, v8i16, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PACKSSDW : sse2_pack<0x6B, "packssdw", v8i16, v4i32, X86Packss, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PACKUSWB : sse2_pack<0x67, "packuswb", v16i8, v8i16, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PACKUSDW : sse4_pack<0x2B, "packusdw", v8i16, v4i32, X86Packus, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; -} -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Unpack Instructions -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_unpack opc, string OpcodeStr, ValueType vt, - SDNode OpNode, RegisterClass RC, X86MemOperand x86memop, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : PDI, - Sched<[sched]>; - def rm : PDI, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKLQDQ : sse2_unpack<0x6C, "vpunpcklqdq", v2i64, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; - defm VPUNPCKHQDQ : sse2_unpack<0x6D, "vpunpckhqdq", v2i64, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, loadv2i64, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPUNPCKLBWY : sse2_unpack<0x60, "vpunpcklbw", v32i8, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKLWDY : sse2_unpack<0x61, "vpunpcklwd", v16i16, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHBWY : sse2_unpack<0x68, "vpunpckhbw", v32i8, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHWDY : sse2_unpack<0x69, "vpunpckhwd", v16i16, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPUNPCKLDQY : sse2_unpack<0x62, "vpunpckldq", v8i32, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKLQDQY : sse2_unpack<0x6C, "vpunpcklqdq", v4i64, X86Unpckl, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHDQY : sse2_unpack<0x6A, "vpunpckhdq", v8i32, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPUNPCKHQDQY : sse2_unpack<0x6D, "vpunpckhqdq", v4i64, X86Unpckh, VR256, - i256mem, SchedWriteShuffle.YMM, loadv4i64, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKLQDQ : sse2_unpack<0x6C, "punpcklqdq", v2i64, X86Unpckl, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - - defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; - defm PUNPCKHQDQ : sse2_unpack<0x6D, "punpckhqdq", v2i64, X86Unpckh, VR128, - i128mem, SchedWriteShuffle.XMM, memopv2i64>; -} -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Integer Extract and Insert -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { -multiclass sse2_pinsrw { - def rr : Ii8<0xC4, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, - GR32orGR64:$src2, u8imm:$src3), - !if(Is2Addr, - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - "vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), - [(set VR128:$dst, - (X86pinsrw VR128:$src1, GR32orGR64:$src2, imm:$src3))]>, - Sched<[WriteVecInsert]>; - def rm : Ii8<0xC4, MRMSrcMem, - (outs VR128:$dst), (ins VR128:$src1, - i16mem:$src2, u8imm:$src3), - !if(Is2Addr, - "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", - "vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), - [(set VR128:$dst, - (X86pinsrw VR128:$src1, (extloadi16 addr:$src2), - imm:$src3))]>, - Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -// Extract -let Predicates = [HasAVX, NoBWI] in -def VPEXTRWrr : Ii8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR128:$src1, u8imm:$src2), - "vpextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (X86pextrw (v8i16 VR128:$src1), - imm:$src2))]>, - PD, VEX, Sched<[WriteVecExtract]>; -def PEXTRWrr : PDIi8<0xC5, MRMSrcReg, - (outs GR32orGR64:$dst), (ins VR128:$src1, u8imm:$src2), - "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32orGR64:$dst, (X86pextrw (v8i16 VR128:$src1), - imm:$src2))]>, - Sched<[WriteVecExtract]>; - -// Insert -let Predicates = [HasAVX, NoBWI] in -defm VPINSRW : sse2_pinsrw<0>, PD, VEX_4V; - -let Predicates = [UseSSE2], Constraints = "$src1 = $dst" in -defm PINSRW : sse2_pinsrw, PD; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Packed Mask Creation -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt in { - -def VPMOVMSKBrr : VPDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR128:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v16i8 VR128:$src)))]>, - Sched<[WriteVecMOVMSK]>, VEX, VEX_WIG; - -let Predicates = [HasAVX2] in { -def VPMOVMSKBYrr : VPDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), - (ins VR256:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v32i8 VR256:$src)))]>, - Sched<[WriteVecMOVMSKY]>, VEX, VEX_L, VEX_WIG; -} - -def PMOVMSKBrr : PDI<0xD7, MRMSrcReg, (outs GR32orGR64:$dst), (ins VR128:$src), - "pmovmskb\t{$src, $dst|$dst, $src}", - [(set GR32orGR64:$dst, (X86movmsk (v16i8 VR128:$src)))]>, - Sched<[WriteVecMOVMSK]>; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Conditional Store -//===---------------------------------------------------------------------===// - -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecMoveLS.XMM.MR] in { -let Uses = [EDI], Predicates = [HasAVX,Not64BitMode] in -def VMASKMOVDQU : VPDI<0xF7, MRMSrcReg, (outs), - (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, EDI)]>, - VEX, VEX_WIG; -let Uses = [RDI], Predicates = [HasAVX,In64BitMode] in -def VMASKMOVDQU64 : VPDI<0xF7, MRMSrcReg, (outs), - (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>, - VEX, VEX_WIG; - -let Uses = [EDI], Predicates = [UseSSE2,Not64BitMode] in -def MASKMOVDQU : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, EDI)]>; -let Uses = [RDI], Predicates = [UseSSE2,In64BitMode] in -def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), - "maskmovdqu\t{$mask, $src|$src, $mask}", - [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>; - -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// SSE2 - Move Doubleword/Quadword -//===---------------------------------------------------------------------===// - -//===---------------------------------------------------------------------===// -// Move Int Doubleword to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVDI2PDIrr : VS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; -def VMOVDI2PDIrm : VS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - VEX, Sched<[WriteVecLoad]>; -def VMOV64toPQIrr : VRS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def VMOV64toPQIrm : VRS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - VEX, Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in -def VMOV64toSDrr : VRS2I<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert GR64:$src))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; - -def MOVDI2PDIrr : S2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector GR32:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -def MOVDI2PDIrm : S2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, - Sched<[WriteVecLoad]>; -def MOV64toPQIrr : RS2I<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector GR64:$src)))]>, - Sched<[WriteVecMoveFromGpr]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayLoad = 1 in -def MOV64toPQIrm : RS2I<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecLoad]>; -let isCodeGenOnly = 1 in -def MOV64toSDrr : RS2I<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert GR64:$src))]>, - Sched<[WriteVecMoveFromGpr]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Move Int Doubleword to Single Scalar -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - def VMOVDI2SSrr : VS2I<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert GR32:$src))]>, - VEX, Sched<[WriteVecMoveFromGpr]>; - - def VMOVDI2SSrm : VS2I<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>, - VEX, Sched<[WriteVecLoad]>; - def MOVDI2SSrr : S2I<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert GR32:$src))]>, - Sched<[WriteVecMoveFromGpr]>; - - def MOVDI2SSrm : S2I<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>, - Sched<[WriteVecLoad]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -//===---------------------------------------------------------------------===// -// Move Packed Doubleword Int to Packed Double Int -// -let ExeDomain = SSEPackedInt in { -def VMOVPDI2DIrr : VS2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128:$src), - (iPTR 0)))]>, VEX, - Sched<[WriteVecMoveToGpr]>; -def VMOVPDI2DImr : VS2I<0x7E, MRMDestMem, (outs), - (ins i32mem:$dst, VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; -def MOVPDI2DIrr : S2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (extractelt (v4i32 VR128:$src), - (iPTR 0)))]>, - Sched<[WriteVecMoveToGpr]>; -def MOVPDI2DImr : S2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR128:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (extractelt (v4i32 VR128:$src), - (iPTR 0))), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Move Packed Doubleword Int first element to Doubleword Int -// -let ExeDomain = SSEPackedInt in { -let SchedRW = [WriteVecMoveToGpr] in { -def VMOVPQIto64rr : VRS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128:$src), - (iPTR 0)))]>, - VEX; - -def MOVPQIto64rr : RS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (extractelt (v2i64 VR128:$src), - (iPTR 0)))]>; -} //SchedRW - -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def VMOVPQIto64mr : VRS2I<0x7E, MRMDestMem, (outs), - (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - VEX, Sched<[WriteVecStore]>; -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in -def MOVPQIto64mr : RS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt - -//===---------------------------------------------------------------------===// -// Bitcast FR64 <-> GR64 -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - let Predicates = [UseAVX] in - def VMOV64toSDrm : VS2SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>, - VEX, Sched<[WriteVecLoad]>; - def VMOVSDto64rr : VRS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64:$src))]>, - VEX, Sched<[WriteVecMoveToGpr]>; - def VMOVSDto64mr : VRS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; - - def MOV64toSDrm : S2SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>, - Sched<[WriteVecLoad]>; - def MOVSDto64rr : RS2I<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (bitconvert FR64:$src))]>, - Sched<[WriteVecMoveToGpr]>; - def MOVSDto64mr : RS2I<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -//===---------------------------------------------------------------------===// -// Move Scalar Single to Double Int -// -let ExeDomain = SSEPackedInt, isCodeGenOnly = 1 in { - def VMOVSS2DIrr : VS2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32:$src))]>, - VEX, Sched<[WriteVecMoveToGpr]>; - def VMOVSS2DImr : VS2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>, - VEX, Sched<[WriteVecStore]>; - def MOVSS2DIrr : S2I<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (bitconvert FR32:$src))]>, - Sched<[WriteVecMoveToGpr]>; - def MOVSS2DImr : S2I<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), - "movd\t{$src, $dst|$dst, $src}", - [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>, - Sched<[WriteVecStore]>; -} // ExeDomain = SSEPackedInt, isCodeGenOnly = 1 - -let Predicates = [UseAVX] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (VMOVDI2PDIrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (VMOV64toPQIrr GR64:$src)>; - - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector GR64:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOV64toPQIrr GR64:$src)), sub_xmm)>; - // AVX 128-bit movd/movq instructions write zeros in the high 128-bit part. - // These instructions also write zeros in the high part of a 256-bit register. - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (VMOVDI2PDIrm addr:$src)>; - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector (loadi32 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIrm addr:$src)), sub_xmm)>; - def : Pat<(v8i32 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v4i32 (VMOVDI2PDIrm addr:$src)), sub_xmm)>; - // Use regular 128-bit instructions to match 256-bit scalar_to_vec+zext. - def : Pat<(v8i32 (X86vzmovl (insert_subvector undef, - (v4i32 (scalar_to_vector GR32:$src)),(iPTR 0)))), - (SUBREG_TO_REG (i32 0), (v4i32 (VMOVDI2PDIrr GR32:$src)), sub_xmm)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector GR32:$src)))), - (MOVDI2PDIrr GR32:$src)>; - - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector GR64:$src)))), - (MOV64toPQIrr GR64:$src)>; - def : Pat<(v2i64 (X86vzmovl (v2i64 (scalar_to_vector (zextloadi64i32 addr:$src))))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), - (MOVDI2PDIrm addr:$src)>; - def : Pat<(v4i32 (X86vzload addr:$src)), - (MOVDI2PDIrm addr:$src)>; -} - -// Before the MC layer of LLVM existed, clang emitted "movd" assembly instead of -// "movq" due to MacOS parsing limitation. In order to parse old assembly, we add -// these aliases. -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MOV64toPQIrr VR128:$dst, GR64:$src), 0>; -def : InstAlias<"movd\t{$src, $dst|$dst, $src}", - (MOVPQIto64rr GR64:$dst, VR128:$src), 0>; -// Allow "vmovd" but print "vmovq" since we don't need compatibility for AVX. -def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", - (VMOV64toPQIrr VR128:$dst, GR64:$src), 0>; -def : InstAlias<"vmovd\t{$src, $dst|$dst, $src}", - (VMOVPQIto64rr GR64:$dst, VR128:$src), 0>; - -//===---------------------------------------------------------------------===// -// SSE2 - Move Quadword -//===---------------------------------------------------------------------===// - -//===---------------------------------------------------------------------===// -// Move Quadword Int to Packed Quadword Int -// - -let ExeDomain = SSEPackedInt, SchedRW = [WriteVecLoad] in { -def VMOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, XS, - VEX, Requires<[UseAVX]>, VEX_WIG; -def MOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, - XS, Requires<[UseSSE2]>; // SSE2 instruction with XS Prefix -} // ExeDomain, SchedRW - -//===---------------------------------------------------------------------===// -// Move Packed Quadword Int to Quadword Int -// -let ExeDomain = SSEPackedInt, SchedRW = [WriteVecStore] in { -def VMOVPQI2QImr : VS2I<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))), addr:$dst)]>, - VEX, VEX_WIG; -def MOVPQI2QImr : S2I<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(store (i64 (extractelt (v2i64 VR128:$src), - (iPTR 0))), addr:$dst)]>; -} // ExeDomain, SchedRW - -// For disassembler only -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVPQI2QIrr : VS2I<0xD6, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>, VEX, VEX_WIG; -def MOVPQI2QIrr : S2I<0xD6, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", []>; -} - -// Aliases to help the assembler pick two byte VEX encodings by swapping the -// operands relative to the normal instructions to use VEX.R instead of VEX.B. -def : InstAlias<"vmovq\t{$src, $dst|$dst, $src}", - (VMOVPQI2QIrr VR128L:$dst, VR128H:$src), 0>; - -def : InstAlias<"vmovq.s\t{$src, $dst|$dst, $src}", - (VMOVPQI2QIrr VR128:$dst, VR128:$src), 0>; -def : InstAlias<"movq.s\t{$src, $dst|$dst, $src}", - (MOVPQI2QIrr VR128:$dst, VR128:$src), 0>; - -let Predicates = [UseAVX] in { - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (VMOVQI2PQIrm addr:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), - (VMOVQI2PQIrm addr:$src)>; - def : Pat<(v4i64 (X86vzmovl (insert_subvector undef, - (v2i64 (scalar_to_vector (loadi64 addr:$src))), (iPTR 0)))), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIrm addr:$src)), sub_xmm)>; - def : Pat<(v4i64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (v2i64 (VMOVQI2PQIrm addr:$src)), sub_xmm)>; -} - -let Predicates = [UseSSE2] in { - def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), - (MOVQI2PQIrm addr:$src)>; - def : Pat<(v2i64 (X86vzload addr:$src)), (MOVQI2PQIrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// Moving from XMM to XMM and clear upper 64 bits. Note, there is a bug in -// IA32 document. movq xmm1, xmm2 does clear the high bits. -// -let ExeDomain = SSEPackedInt, SchedRW = [SchedWriteVecLogic.XMM] in { -def VMOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "vmovq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, - XS, VEX, Requires<[UseAVX]>, VEX_WIG; -def MOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movq\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, - XS, Requires<[UseSSE2]>; -} // ExeDomain, SchedRW - -let Predicates = [UseAVX] in { - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), - (VMOVZPQILo2PQIrr VR128:$src)>; -} -let Predicates = [UseSSE2] in { - def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), - (MOVZPQILo2PQIrr VR128:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Replicate Single FP - MOVSHDUP and MOVSLDUP -//===---------------------------------------------------------------------===// - -multiclass sse3_replicate_sfp op, SDNode OpNode, string OpcodeStr, - ValueType vt, RegisterClass RC, PatFrag mem_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched> { -def rr : S3SI, - Sched<[sched]>; -def rm : S3SI, - Sched<[sched.Folded]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VMOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup", - v4f32, VR128, loadv4f32, f128mem, - SchedWriteFShuffle.XMM>, VEX, VEX_WIG; - defm VMOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup", - v4f32, VR128, loadv4f32, f128mem, - SchedWriteFShuffle.XMM>, VEX, VEX_WIG; - defm VMOVSHDUPY : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup", - v8f32, VR256, loadv8f32, f256mem, - SchedWriteFShuffle.YMM>, VEX, VEX_L, VEX_WIG; - defm VMOVSLDUPY : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup", - v8f32, VR256, loadv8f32, f256mem, - SchedWriteFShuffle.YMM>, VEX, VEX_L, VEX_WIG; -} -defm MOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "movshdup", v4f32, VR128, - memopv4f32, f128mem, SchedWriteFShuffle.XMM>; -defm MOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "movsldup", v4f32, VR128, - memopv4f32, f128mem, SchedWriteFShuffle.XMM>; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (X86Movshdup VR128:$src)), - (VMOVSHDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVSHDUPrm addr:$src)>; - def : Pat<(v4i32 (X86Movsldup VR128:$src)), - (VMOVSLDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (loadv2i64 addr:$src)))), - (VMOVSLDUPrm addr:$src)>; - def : Pat<(v8i32 (X86Movshdup VR256:$src)), - (VMOVSHDUPYrr VR256:$src)>; - def : Pat<(v8i32 (X86Movshdup (bc_v8i32 (loadv4i64 addr:$src)))), - (VMOVSHDUPYrm addr:$src)>; - def : Pat<(v8i32 (X86Movsldup VR256:$src)), - (VMOVSLDUPYrr VR256:$src)>; - def : Pat<(v8i32 (X86Movsldup (bc_v8i32 (loadv4i64 addr:$src)))), - (VMOVSLDUPYrm addr:$src)>; -} - -let Predicates = [UseSSE3] in { - def : Pat<(v4i32 (X86Movshdup VR128:$src)), - (MOVSHDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))), - (MOVSHDUPrm addr:$src)>; - def : Pat<(v4i32 (X86Movsldup VR128:$src)), - (MOVSLDUPrr VR128:$src)>; - def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))), - (MOVSLDUPrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Replicate Double FP - MOVDDUP -//===---------------------------------------------------------------------===// - -multiclass sse3_replicate_dfp { -def rr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR128:$dst, (v2f64 (X86Movddup VR128:$src)))]>, - Sched<[sched.XMM]>; -def rm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR128:$dst, - (v2f64 (X86Movddup - (scalar_to_vector (loadf64 addr:$src)))))]>, - Sched<[sched.XMM.Folded]>; -} - -// FIXME: Merge with above classes when there are patterns for the ymm version -multiclass sse3_replicate_dfp_y { -def rr : S3DI<0x12, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR256:$dst, (v4f64 (X86Movddup VR256:$src)))]>, - Sched<[sched.YMM]>; -def rm : S3DI<0x12, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), - !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), - [(set VR256:$dst, - (v4f64 (X86Movddup (loadv4f64 addr:$src))))]>, - Sched<[sched.YMM.Folded]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VMOVDDUP : sse3_replicate_dfp<"vmovddup", SchedWriteFShuffle>, - VEX, VEX_WIG; - defm VMOVDDUPY : sse3_replicate_dfp_y<"vmovddup", SchedWriteFShuffle>, - VEX, VEX_L, VEX_WIG; -} - -defm MOVDDUP : sse3_replicate_dfp<"movddup", SchedWriteFShuffle>; - - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(X86Movddup (loadv2f64 addr:$src)), - (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>; -} - -let Predicates = [UseSSE3] in { - // No need for aligned memory as this only loads 64-bits. - def : Pat<(X86Movddup (loadv2f64 addr:$src)), - (MOVDDUPrm addr:$src)>; -} - -//===---------------------------------------------------------------------===// -// SSE3 - Move Unaligned Integer -//===---------------------------------------------------------------------===// - -let Predicates = [HasAVX] in { - def VLDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vlddqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>, VEX, VEX_WIG; - def VLDDQUYrm : S3DI<0xF0, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vlddqu\t{$src, $dst|$dst, $src}", - [(set VR256:$dst, (int_x86_avx_ldu_dq_256 addr:$src))]>, - Sched<[SchedWriteVecMoveLS.YMM.RM]>, VEX, VEX_L, VEX_WIG; -} // Predicates - -def LDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "lddqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>, - Sched<[SchedWriteVecMoveLS.XMM.RM]>; - -//===---------------------------------------------------------------------===// -// SSE3 - Arithmetic -//===---------------------------------------------------------------------===// - -multiclass sse3_addsub { - def rr : I<0xD0, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2), - !if(Is2Addr, - !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")), - [(set RC:$dst, (vt (X86Addsub RC:$src1, RC:$src2)))]>, - Sched<[sched]>; - def rm : I<0xD0, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2), - !if(Is2Addr, - !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")), - [(set RC:$dst, (vt (X86Addsub RC:$src1, (ld_frag addr:$src2))))]>, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { - let ExeDomain = SSEPackedSingle in { - defm VADDSUBPS : sse3_addsub<"vaddsubps", v4f32, VR128, f128mem, - SchedWriteFAddSizes.PS.XMM, loadv4f32, 0>, - XD, VEX_4V, VEX_WIG; - defm VADDSUBPSY : sse3_addsub<"vaddsubps", v8f32, VR256, f256mem, - SchedWriteFAddSizes.PS.YMM, loadv8f32, 0>, - XD, VEX_4V, VEX_L, VEX_WIG; - } - let ExeDomain = SSEPackedDouble in { - defm VADDSUBPD : sse3_addsub<"vaddsubpd", v2f64, VR128, f128mem, - SchedWriteFAddSizes.PD.XMM, loadv2f64, 0>, - PD, VEX_4V, VEX_WIG; - defm VADDSUBPDY : sse3_addsub<"vaddsubpd", v4f64, VR256, f256mem, - SchedWriteFAddSizes.PD.YMM, loadv4f64, 0>, - PD, VEX_4V, VEX_L, VEX_WIG; - } -} -let Constraints = "$src1 = $dst", Predicates = [UseSSE3] in { - let ExeDomain = SSEPackedSingle in - defm ADDSUBPS : sse3_addsub<"addsubps", v4f32, VR128, f128mem, - SchedWriteFAddSizes.PS.XMM, memopv4f32>, XD; - let ExeDomain = SSEPackedDouble in - defm ADDSUBPD : sse3_addsub<"addsubpd", v2f64, VR128, f128mem, - SchedWriteFAddSizes.PD.XMM, memopv2f64>, PD; -} - -//===---------------------------------------------------------------------===// -// SSE3 Instructions -//===---------------------------------------------------------------------===// - -// Horizontal ops -multiclass S3D_Int o, string OpcodeStr, ValueType vt, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : S3DI, - Sched<[sched]>; - - def rm : S3DI, - Sched<[sched.Folded, ReadAfterLd]>; -} -multiclass S3_Int o, string OpcodeStr, ValueType vt, RegisterClass RC, - X86MemOperand x86memop, SDNode OpNode, - X86FoldableSchedWrite sched, PatFrag ld_frag, - bit Is2Addr = 1> { - def rr : S3I, - Sched<[sched]>; - - def rm : S3I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { - let ExeDomain = SSEPackedSingle in { - defm VHADDPS : S3D_Int<0x7C, "vhaddps", v4f32, VR128, f128mem, - X86fhadd, WriteFHAdd, loadv4f32, 0>, VEX_4V, VEX_WIG; - defm VHSUBPS : S3D_Int<0x7D, "vhsubps", v4f32, VR128, f128mem, - X86fhsub, WriteFHAdd, loadv4f32, 0>, VEX_4V, VEX_WIG; - defm VHADDPSY : S3D_Int<0x7C, "vhaddps", v8f32, VR256, f256mem, - X86fhadd, WriteFHAddY, loadv8f32, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VHSUBPSY : S3D_Int<0x7D, "vhsubps", v8f32, VR256, f256mem, - X86fhsub, WriteFHAddY, loadv8f32, 0>, VEX_4V, VEX_L, VEX_WIG; - } - let ExeDomain = SSEPackedDouble in { - defm VHADDPD : S3_Int<0x7C, "vhaddpd", v2f64, VR128, f128mem, - X86fhadd, WriteFHAdd, loadv2f64, 0>, VEX_4V, VEX_WIG; - defm VHSUBPD : S3_Int<0x7D, "vhsubpd", v2f64, VR128, f128mem, - X86fhsub, WriteFHAdd, loadv2f64, 0>, VEX_4V, VEX_WIG; - defm VHADDPDY : S3_Int<0x7C, "vhaddpd", v4f64, VR256, f256mem, - X86fhadd, WriteFHAddY, loadv4f64, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VHSUBPDY : S3_Int<0x7D, "vhsubpd", v4f64, VR256, f256mem, - X86fhsub, WriteFHAddY, loadv4f64, 0>, VEX_4V, VEX_L, VEX_WIG; - } -} - -let Constraints = "$src1 = $dst" in { - let ExeDomain = SSEPackedSingle in { - defm HADDPS : S3D_Int<0x7C, "haddps", v4f32, VR128, f128mem, X86fhadd, - WriteFHAdd, memopv4f32>; - defm HSUBPS : S3D_Int<0x7D, "hsubps", v4f32, VR128, f128mem, X86fhsub, - WriteFHAdd, memopv4f32>; - } - let ExeDomain = SSEPackedDouble in { - defm HADDPD : S3_Int<0x7C, "haddpd", v2f64, VR128, f128mem, X86fhadd, - WriteFHAdd, memopv2f64>; - defm HSUBPD : S3_Int<0x7D, "hsubpd", v2f64, VR128, f128mem, X86fhsub, - WriteFHAdd, memopv2f64>; - } -} - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Absolute Instructions -//===---------------------------------------------------------------------===// - -/// SS3I_unop_rm_int - Simple SSSE3 unary op whose type can be v*{i8,i16,i32}. -multiclass SS3I_unop_rm opc, string OpcodeStr, ValueType vt, - SDNode OpNode, X86SchedWriteWidths sched, PatFrag ld_frag> { - def rr : SS38I, - Sched<[sched.XMM]>; - - def rm : SS38I, - Sched<[sched.XMM.Folded]>; -} - -/// SS3I_unop_rm_int_y - Simple SSSE3 unary op whose type can be v*{i8,i16,i32}. -multiclass SS3I_unop_rm_y opc, string OpcodeStr, ValueType vt, - SDNode OpNode, X86SchedWriteWidths sched> { - def Yrr : SS38I, - Sched<[sched.YMM]>; - - def Yrm : SS38I, - Sched<[sched.YMM.Folded]>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPABSB : SS3I_unop_rm<0x1C, "vpabsb", v16i8, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; - defm VPABSW : SS3I_unop_rm<0x1D, "vpabsw", v8i16, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; -} -let Predicates = [HasAVX, NoVLX] in { - defm VPABSD : SS3I_unop_rm<0x1E, "vpabsd", v4i32, abs, SchedWriteVecALU, - loadv2i64>, VEX, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPABSB : SS3I_unop_rm_y<0x1C, "vpabsb", v32i8, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; - defm VPABSW : SS3I_unop_rm_y<0x1D, "vpabsw", v16i16, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX] in { - defm VPABSD : SS3I_unop_rm_y<0x1E, "vpabsd", v8i32, abs, SchedWriteVecALU>, - VEX, VEX_L, VEX_WIG; -} - -defm PABSB : SS3I_unop_rm<0x1C, "pabsb", v16i8, abs, SchedWriteVecALU, - memopv2i64>; -defm PABSW : SS3I_unop_rm<0x1D, "pabsw", v8i16, abs, SchedWriteVecALU, - memopv2i64>; -defm PABSD : SS3I_unop_rm<0x1E, "pabsd", v4i32, abs, SchedWriteVecALU, - memopv2i64>; - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Binary Operator Instructions -//===---------------------------------------------------------------------===// - -/// SS3I_binop_rm - Simple SSSE3 bin op -multiclass SS3I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType DstVT, ValueType OpVT, RegisterClass RC, - PatFrag memop_frag, X86MemOperand x86memop, - X86FoldableSchedWrite sched, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS38I, - Sched<[sched]>; - def rm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// SS3I_binop_rm_int - Simple SSSE3 bin op whose type can be v*{i8,i16,i32}. -multiclass SS3I_binop_rm_int opc, string OpcodeStr, - Intrinsic IntId128, X86FoldableSchedWrite sched, - PatFrag ld_frag, bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS38I, - Sched<[sched]>; - def rm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass SS3I_binop_rm_int_y opc, string OpcodeStr, - Intrinsic IntId256, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def Yrr : SS38I, - Sched<[sched]>; - def Yrm : SS38I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let ImmT = NoImm, Predicates = [HasAVX, NoVLX_Or_NoBWI] in { -let isCommutable = 0 in { - defm VPSHUFB : SS3I_binop_rm<0x00, "vpshufb", X86pshufb, v16i8, v16i8, - VR128, loadv2i64, i128mem, - SchedWriteVarShuffle.XMM, 0>, VEX_4V, VEX_WIG; - defm VPMADDUBSW : SS3I_binop_rm<0x04, "vpmaddubsw", X86vpmaddubsw, v8i16, - v16i8, VR128, loadv2i64, i128mem, - SchedWriteVecIMul.XMM, 0>, VEX_4V, VEX_WIG; -} -defm VPMULHRSW : SS3I_binop_rm<0x0B, "vpmulhrsw", X86mulhrs, v8i16, v8i16, - VR128, loadv2i64, i128mem, - SchedWriteVecIMul.XMM, 0>, VEX_4V, VEX_WIG; -} - -let ImmT = NoImm, Predicates = [HasAVX] in { -let isCommutable = 0 in { - defm VPHADDW : SS3I_binop_rm<0x01, "vphaddw", X86hadd, v8i16, v8i16, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHADDD : SS3I_binop_rm<0x02, "vphaddd", X86hadd, v4i32, v4i32, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHSUBW : SS3I_binop_rm<0x05, "vphsubw", X86hsub, v8i16, v8i16, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V, VEX_WIG; - defm VPHSUBD : SS3I_binop_rm<0x06, "vphsubd", X86hsub, v4i32, v4i32, VR128, - loadv2i64, i128mem, - SchedWritePHAdd.XMM, 0>, VEX_4V; - defm VPSIGNB : SS3I_binop_rm_int<0x08, "vpsignb", - int_x86_ssse3_psign_b_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPSIGNW : SS3I_binop_rm_int<0x09, "vpsignw", - int_x86_ssse3_psign_w_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPSIGND : SS3I_binop_rm_int<0x0A, "vpsignd", - int_x86_ssse3_psign_d_128, - SchedWriteVecALU.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPHADDSW : SS3I_binop_rm_int<0x03, "vphaddsw", - int_x86_ssse3_phadd_sw_128, - SchedWritePHAdd.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; - defm VPHSUBSW : SS3I_binop_rm_int<0x07, "vphsubsw", - int_x86_ssse3_phsub_sw_128, - SchedWritePHAdd.XMM, loadv2i64, 0>, VEX_4V, VEX_WIG; -} -} - -let ImmT = NoImm, Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { -let isCommutable = 0 in { - defm VPSHUFBY : SS3I_binop_rm<0x00, "vpshufb", X86pshufb, v32i8, v32i8, - VR256, loadv4i64, i256mem, - SchedWriteVarShuffle.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPMADDUBSWY : SS3I_binop_rm<0x04, "vpmaddubsw", X86vpmaddubsw, v16i16, - v32i8, VR256, loadv4i64, i256mem, - SchedWriteVecIMul.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -} -defm VPMULHRSWY : SS3I_binop_rm<0x0B, "vpmulhrsw", X86mulhrs, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWriteVecIMul.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -} - -let ImmT = NoImm, Predicates = [HasAVX2] in { -let isCommutable = 0 in { - defm VPHADDWY : SS3I_binop_rm<0x01, "vphaddw", X86hadd, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHADDDY : SS3I_binop_rm<0x02, "vphaddd", X86hadd, v8i32, v8i32, VR256, - loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBWY : SS3I_binop_rm<0x05, "vphsubw", X86hsub, v16i16, v16i16, - VR256, loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBDY : SS3I_binop_rm<0x06, "vphsubd", X86hsub, v8i32, v8i32, VR256, - loadv4i64, i256mem, - SchedWritePHAdd.YMM, 0>, VEX_4V, VEX_L; - defm VPSIGNB : SS3I_binop_rm_int_y<0x08, "vpsignb", int_x86_avx2_psign_b, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPSIGNW : SS3I_binop_rm_int_y<0x09, "vpsignw", int_x86_avx2_psign_w, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPSIGND : SS3I_binop_rm_int_y<0x0A, "vpsignd", int_x86_avx2_psign_d, - SchedWriteVecALU.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPHADDSW : SS3I_binop_rm_int_y<0x03, "vphaddsw", - int_x86_avx2_phadd_sw, - SchedWritePHAdd.YMM>, VEX_4V, VEX_L, VEX_WIG; - defm VPHSUBSW : SS3I_binop_rm_int_y<0x07, "vphsubsw", - int_x86_avx2_phsub_sw, - SchedWritePHAdd.YMM>, VEX_4V, VEX_L, VEX_WIG; -} -} - -// None of these have i8 immediate fields. -let ImmT = NoImm, Constraints = "$src1 = $dst" in { -let isCommutable = 0 in { - defm PHADDW : SS3I_binop_rm<0x01, "phaddw", X86hadd, v8i16, v8i16, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHADDD : SS3I_binop_rm<0x02, "phaddd", X86hadd, v4i32, v4i32, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHSUBW : SS3I_binop_rm<0x05, "phsubw", X86hsub, v8i16, v8i16, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PHSUBD : SS3I_binop_rm<0x06, "phsubd", X86hsub, v4i32, v4i32, VR128, - memopv2i64, i128mem, SchedWritePHAdd.XMM>; - defm PSIGNB : SS3I_binop_rm_int<0x08, "psignb", int_x86_ssse3_psign_b_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSIGNW : SS3I_binop_rm_int<0x09, "psignw", int_x86_ssse3_psign_w_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSIGND : SS3I_binop_rm_int<0x0A, "psignd", int_x86_ssse3_psign_d_128, - SchedWriteVecALU.XMM, memopv2i64>; - defm PSHUFB : SS3I_binop_rm<0x00, "pshufb", X86pshufb, v16i8, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVarShuffle.XMM>; - defm PHADDSW : SS3I_binop_rm_int<0x03, "phaddsw", - int_x86_ssse3_phadd_sw_128, - SchedWritePHAdd.XMM, memopv2i64>; - defm PHSUBSW : SS3I_binop_rm_int<0x07, "phsubsw", - int_x86_ssse3_phsub_sw_128, - SchedWritePHAdd.XMM, memopv2i64>; - defm PMADDUBSW : SS3I_binop_rm<0x04, "pmaddubsw", X86vpmaddubsw, v8i16, - v16i8, VR128, memopv2i64, i128mem, - SchedWriteVecIMul.XMM>; -} -defm PMULHRSW : SS3I_binop_rm<0x0B, "pmulhrsw", X86mulhrs, v8i16, v8i16, - VR128, memopv2i64, i128mem, SchedWriteVecIMul.XMM>; -} - -//===---------------------------------------------------------------------===// -// SSSE3 - Packed Align Instruction Patterns -//===---------------------------------------------------------------------===// - -multiclass ssse3_palignr { - let hasSideEffects = 0 in { - def rri : SS3AI<0x0F, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), - !if(Is2Addr, - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - !strconcat(asm, - "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")), - [(set RC:$dst, (VT (X86PAlignr RC:$src1, RC:$src2, (i8 imm:$src3))))]>, - Sched<[sched]>; - let mayLoad = 1 in - def rmi : SS3AI<0x0F, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, u8imm:$src3), - !if(Is2Addr, - !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), - !strconcat(asm, - "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")), - [(set RC:$dst, (VT (X86PAlignr RC:$src1, - (bitconvert (memop_frag addr:$src2)), - (i8 imm:$src3))))]>, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in - defm VPALIGNR : ssse3_palignr<"vpalignr", v16i8, VR128, loadv2i64, i128mem, - SchedWriteShuffle.XMM, 0>, VEX_4V, VEX_WIG; -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in - defm VPALIGNRY : ssse3_palignr<"vpalignr", v32i8, VR256, loadv4i64, i256mem, - SchedWriteShuffle.YMM, 0>, VEX_4V, VEX_L, VEX_WIG; -let Constraints = "$src1 = $dst", Predicates = [UseSSSE3] in - defm PALIGNR : ssse3_palignr<"palignr", v16i8, VR128, memopv2i64, i128mem, - SchedWriteShuffle.XMM>; - -//===---------------------------------------------------------------------===// -// SSSE3 - Thread synchronization -//===---------------------------------------------------------------------===// - -let SchedRW = [WriteSystem] in { -/* -let usesCustomInserter = 1 in { -def MONITOR : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3), - [(int_x86_sse3_monitor addr:$src1, GR32:$src2, GR32:$src3)]>, - Requires<[HasSSE3]>; -} -*/ - -let Uses = [EAX, ECX, EDX] in -def MONITORrrr : I<0x01, MRM_C8, (outs), (ins), "monitor", []>, - TB, Requires<[HasSSE3]>; - -let Uses = [ECX, EAX] in -def MWAITrr : I<0x01, MRM_C9, (outs), (ins), "mwait", - [(int_x86_sse3_mwait ECX, EAX)]>, TB, Requires<[HasSSE3]>; -} // SchedRW - -def : InstAlias<"mwait\t{%eax, %ecx|ecx, eax}", (MWAITrr)>, Requires<[Not64BitMode]>; -def : InstAlias<"mwait\t{%rax, %rcx|rcx, rax}", (MWAITrr)>, Requires<[In64BitMode]>; - -def : InstAlias<"monitor\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORrrr)>, - Requires<[Not64BitMode]>; -def : InstAlias<"monitor\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORrrr)>, - Requires<[In64BitMode]>; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Packed Move with Sign/Zero Extend -//===----------------------------------------------------------------------===// - -multiclass SS41I_pmovx_rrrm opc, string OpcodeStr, X86MemOperand MemOp, - RegisterClass OutRC, RegisterClass InRC, - X86FoldableSchedWrite sched> { - def rr : SS48I, - Sched<[sched]>; - - def rm : SS48I, - Sched<[sched.Folded]>; -} - -multiclass SS41I_pmovx_rm_all opc, string OpcodeStr, - X86MemOperand MemOp, X86MemOperand MemYOp, - Predicate prd> { - defm NAME : SS41I_pmovx_rrrm; - let Predicates = [HasAVX, prd] in - defm V#NAME : SS41I_pmovx_rrrm, - VEX, VEX_WIG; - let Predicates = [HasAVX2, prd] in - defm V#NAME#Y : SS41I_pmovx_rrrm, - VEX, VEX_L, VEX_WIG; -} - -multiclass SS41I_pmovx_rm opc, string OpcodeStr, X86MemOperand MemOp, - X86MemOperand MemYOp, Predicate prd> { - defm PMOVSX#NAME : SS41I_pmovx_rm_all; - defm PMOVZX#NAME : SS41I_pmovx_rm_all; -} - -defm BW : SS41I_pmovx_rm<0x20, "bw", i64mem, i128mem, NoVLX_Or_NoBWI>; -defm WD : SS41I_pmovx_rm<0x23, "wd", i64mem, i128mem, NoVLX>; -defm DQ : SS41I_pmovx_rm<0x25, "dq", i64mem, i128mem, NoVLX>; - -defm BD : SS41I_pmovx_rm<0x21, "bd", i32mem, i64mem, NoVLX>; -defm WQ : SS41I_pmovx_rm<0x24, "wq", i32mem, i64mem, NoVLX>; - -defm BQ : SS41I_pmovx_rm<0x22, "bq", i16mem, i32mem, NoVLX>; - -// AVX2 Patterns -multiclass SS41I_pmovx_avx2_patterns { - // Register-Register patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BWYrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BDYrr) VR128:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BQYrr) VR128:$src)>; - - def : Pat<(v8i32 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WDYrr) VR128:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WQYrr) VR128:$src)>; - - def : Pat<(v4i64 (ExtOp (v4i32 VR128:$src))), - (!cast(OpcPrefix#DQYrr) VR128:$src)>; - } - - // Simple Register-Memory patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - - def : Pat<(v8i32 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - - def : Pat<(v4i64 (!cast(ExtTy#"extloadvi32") addr:$src)), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - } - - // AVX2 Register-Memory patterns - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v16i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - def : Pat<(v16i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWYrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v8i32 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQYrm) addr:$src)>; - - def : Pat<(v8i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - def : Pat<(v8i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQYrm) addr:$src)>; - - def : Pat<(v4i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - def : Pat<(v4i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQYrm) addr:$src)>; - } -} - -defm : SS41I_pmovx_avx2_patterns<"VPMOVSX", "s", X86vsext>; -defm : SS41I_pmovx_avx2_patterns<"VPMOVZX", "z", X86vzext>; - -// SSE4.1/AVX patterns. -multiclass SS41I_pmovx_patterns { - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BWrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BDrr) VR128:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 VR128:$src))), - (!cast(OpcPrefix#BQrr) VR128:$src)>; - - def : Pat<(v4i32 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WDrr) VR128:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 VR128:$src))), - (!cast(OpcPrefix#WQrr) VR128:$src)>; - - def : Pat<(v2i64 (ExtOp (v4i32 VR128:$src))), - (!cast(OpcPrefix#DQrr) VR128:$src)>; - } - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BWrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi8") addr:$src)), - (!cast(OpcPrefix#BQrm) addr:$src)>; - - def : Pat<(v4i32 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi16") addr:$src)), - (!cast(OpcPrefix#WQrm) addr:$src)>; - - def : Pat<(v2i64 (!cast(ExtTy#"extloadvi32") addr:$src)), - (!cast(OpcPrefix#DQrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - def : Pat<(v8i16 (ExtOp (bc_v16i8 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (bc_v16i8 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (v16i8 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - def : Pat<(v8i16 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BWrm) addr:$src)>; - } - let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4i32 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BDrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v16i8 (v4i32 (scalar_to_vector (extloadi32i16 addr:$src)))))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v16i8 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v16i8 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#BQrm) addr:$src)>; - - def : Pat<(v4i32 (ExtOp (bc_v8i16 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v8i16 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v8i16 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - def : Pat<(v4i32 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WDrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v8i16 (v4i32 (scalar_to_vector (loadi32 addr:$src)))))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 (vzmovl_v4i32 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v8i16 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v8i16 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#WQrm) addr:$src)>; - - def : Pat<(v2i64 (ExtOp (bc_v4i32 (v2i64 (scalar_to_vector (loadi64 addr:$src)))))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v4i32 (v2f64 (scalar_to_vector (loadf64 addr:$src)))))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v4i32 (vzmovl_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (v4i32 (vzload_v2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - def : Pat<(v2i64 (ExtOp (bc_v4i32 (loadv2i64 addr:$src)))), - (!cast(OpcPrefix#DQrm) addr:$src)>; - } -} - -defm : SS41I_pmovx_patterns<"VPMOVSX", "s", sext_invec>; -defm : SS41I_pmovx_patterns<"VPMOVZX", "z", zext_invec>; - -let Predicates = [UseSSE41] in { - defm : SS41I_pmovx_patterns<"PMOVSX", "s", sext_invec>; - defm : SS41I_pmovx_patterns<"PMOVZX", "z", zext_invec>; -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Extract Instructions -//===----------------------------------------------------------------------===// - -/// SS41I_binop_ext8 - SSE 4.1 extract 8 bits to 32 bit reg or 8 bit mem -multiclass SS41I_extract8 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - let hasSideEffects = 0, mayStore = 1 in - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPEXTRB : SS41I_extract8<0x14, "vpextrb">, VEX; - -defm PEXTRB : SS41I_extract8<0x14, "pextrb">; - - -/// SS41I_extract16 - SSE 4.1 extract 16 bits to memory destination -multiclass SS41I_extract16 opc, string OpcodeStr> { - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : SS4AIi8, - Sched<[WriteVecExtract]>, FoldGenData; - - let hasSideEffects = 0, mayStore = 1 in - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPEXTRW : SS41I_extract16<0x15, "vpextrw">, VEX; - -defm PEXTRW : SS41I_extract16<0x15, "pextrw">; - - -/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination -multiclass SS41I_extract32 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPEXTRD : SS41I_extract32<0x16, "vpextrd">, VEX; - -defm PEXTRD : SS41I_extract32<0x16, "pextrd">; - -/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination -multiclass SS41I_extract64 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPEXTRQ : SS41I_extract64<0x16, "vpextrq">, VEX, VEX_W; - -defm PEXTRQ : SS41I_extract64<0x16, "pextrq">, REX_W; - -/// SS41I_extractf32 - SSE 4.1 extract 32 bits fp value to int reg or memory -/// destination -multiclass SS41I_extractf32 opc, string OpcodeStr> { - def rr : SS4AIi8, - Sched<[WriteVecExtract]>; - def mr : SS4AIi8, Sched<[WriteVecExtractSt]>; -} - -let ExeDomain = SSEPackedSingle in { - let Predicates = [UseAVX] in - defm VEXTRACTPS : SS41I_extractf32<0x17, "vextractps">, VEX, VEX_WIG; - defm EXTRACTPS : SS41I_extractf32<0x17, "extractps">; -} - -// Also match an EXTRACTPS store when the store is done as f32 instead of i32. -def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)), - imm:$src2))), - addr:$dst), - (VEXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>, - Requires<[HasAVX]>; -def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)), - imm:$src2))), - addr:$dst), - (EXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>, - Requires<[UseSSE41]>; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Insert Instructions -//===----------------------------------------------------------------------===// - -multiclass SS41I_insert8 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoBWI] in - defm VPINSRB : SS41I_insert8<0x20, "vpinsrb", 0>, VEX_4V; -let Constraints = "$src1 = $dst" in - defm PINSRB : SS41I_insert8<0x20, "pinsrb">; - -multiclass SS41I_insert32 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPINSRD : SS41I_insert32<0x22, "vpinsrd", 0>, VEX_4V; -let Constraints = "$src1 = $dst" in - defm PINSRD : SS41I_insert32<0x22, "pinsrd">; - -multiclass SS41I_insert64 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[WriteVecInsert]>; - def rm : SS4AIi8, Sched<[WriteVecInsertLd, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoDQI] in - defm VPINSRQ : SS41I_insert64<0x22, "vpinsrq", 0>, VEX_4V, VEX_W; -let Constraints = "$src1 = $dst" in - defm PINSRQ : SS41I_insert64<0x22, "pinsrq">, REX_W; - -// insertps has a few different modes, there's the first two here below which -// are optimized inserts that won't zero arbitrary elements in the destination -// vector. The next one matches the intrinsic and could zero arbitrary elements -// in the target vector. -multiclass SS41I_insertf32 opc, string asm, bit Is2Addr = 1> { - def rr : SS4AIi8, - Sched<[SchedWriteFShuffle.XMM]>; - def rm : SS4AIi8, - Sched<[SchedWriteFShuffle.XMM.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedSingle in { - let Predicates = [UseAVX] in - defm VINSERTPS : SS41I_insertf32<0x21, "vinsertps", 0>, - VEX_4V, VEX_WIG; - let Constraints = "$src1 = $dst" in - defm INSERTPS : SS41I_insertf32<0x21, "insertps", 1>; -} - -let Predicates = [UseAVX] in { - // If we're inserting an element from a vbroadcast of a load, fold the - // load into the X86insertps instruction. - def : Pat<(v4f32 (X86insertps (v4f32 VR128:$src1), - (X86VBroadcast (loadf32 addr:$src2)), imm:$src3)), - (VINSERTPSrm VR128:$src1, addr:$src2, imm:$src3)>; - def : Pat<(v4f32 (X86insertps (v4f32 VR128:$src1), - (X86VBroadcast (loadv4f32 addr:$src2)), imm:$src3)), - (VINSERTPSrm VR128:$src1, addr:$src2, imm:$src3)>; -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Round Instructions -//===----------------------------------------------------------------------===// - -multiclass sse41_fp_unop_p opc, string OpcodeStr, - X86MemOperand x86memop, RegisterClass RC, - ValueType VT, PatFrag mem_frag, SDNode OpNode, - X86FoldableSchedWrite sched> { - // Intrinsic operation, reg. - // Vector intrinsic operation, reg - def r : SS4AIi8, - Sched<[sched]>; - - // Vector intrinsic operation, mem - def m : SS4AIi8, - Sched<[sched.Folded]>; -} - -multiclass avx_fp_unop_rm opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched> { -let ExeDomain = SSEPackedSingle, hasSideEffects = 0 in { - def SSr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SSm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, hasSideEffects = 0 - -let ExeDomain = SSEPackedDouble, hasSideEffects = 0 in { - def SDr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SDm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, hasSideEffects = 0 -} - -multiclass sse41_fp_unop_s opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched> { -let ExeDomain = SSEPackedSingle, hasSideEffects = 0 in { - def SSr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SSm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, hasSideEffects = 0 - -let ExeDomain = SSEPackedDouble, hasSideEffects = 0 in { - def SDr : SS4AIi8, Sched<[sched]>; - - let mayLoad = 1 in - def SDm : SS4AIi8, Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, hasSideEffects = 0 -} - -multiclass sse41_fp_binop_s opcss, bits<8> opcsd, - string OpcodeStr, X86FoldableSchedWrite sched, - ValueType VT32, ValueType VT64, - SDNode OpNode, bit Is2Addr = 1> { -let ExeDomain = SSEPackedSingle, isCodeGenOnly = 1 in { - def SSr_Int : SS4AIi8, - Sched<[sched]>; - - def SSm_Int : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedSingle, isCodeGenOnly = 1 - -let ExeDomain = SSEPackedDouble, isCodeGenOnly = 1 in { - def SDr_Int : SS4AIi8, - Sched<[sched]>; - - def SDm_Int : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} // ExeDomain = SSEPackedDouble, isCodeGenOnly = 1 -} - -// FP round - roundss, roundps, roundsd, roundpd -let Predicates = [HasAVX, NoVLX] in { - let ExeDomain = SSEPackedSingle in { - // Intrinsic form - defm VROUNDPS : sse41_fp_unop_p<0x08, "vroundps", f128mem, VR128, v4f32, - loadv4f32, X86VRndScale, SchedWriteFRnd.XMM>, - VEX, VEX_WIG; - defm VROUNDPSY : sse41_fp_unop_p<0x08, "vroundps", f256mem, VR256, v8f32, - loadv8f32, X86VRndScale, SchedWriteFRnd.YMM>, - VEX, VEX_L, VEX_WIG; - } - - let ExeDomain = SSEPackedDouble in { - defm VROUNDPD : sse41_fp_unop_p<0x09, "vroundpd", f128mem, VR128, v2f64, - loadv2f64, X86VRndScale, SchedWriteFRnd.XMM>, - VEX, VEX_WIG; - defm VROUNDPDY : sse41_fp_unop_p<0x09, "vroundpd", f256mem, VR256, v4f64, - loadv4f64, X86VRndScale, SchedWriteFRnd.YMM>, - VEX, VEX_L, VEX_WIG; - } -} -let Predicates = [HasAVX, NoAVX512] in { - defm VROUND : sse41_fp_binop_s<0x0A, 0x0B, "vround", SchedWriteFRnd.Scl, - v4f32, v2f64, X86RndScales, 0>, - VEX_4V, VEX_LIG, VEX_WIG; - defm VROUND : avx_fp_unop_rm<0x0A, 0x0B, "vround", SchedWriteFRnd.Scl>, - VEX_4V, VEX_LIG, VEX_WIG; -} - -let Predicates = [UseAVX] in { - def : Pat<(ffloor FR32:$src), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xC))>; - def : Pat<(f32 (fceil FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xA))>; - def : Pat<(f32 (frint FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc FR32:$src)), - (VROUNDSSr (f32 (IMPLICIT_DEF)), FR32:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xC))>; - def : Pat<(f64 (fceil FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xA))>; - def : Pat<(f64 (frint FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc FR64:$src)), - (VROUNDSDr (f64 (IMPLICIT_DEF)), FR64:$src, (i32 0xB))>; -} - -let Predicates = [UseAVX, OptForSize] in { - def : Pat<(ffloor (loadf32 addr:$src)), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xC))>; - def : Pat<(f32 (fceil (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xA))>; - def : Pat<(f32 (frint (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc (loadf32 addr:$src))), - (VROUNDSSm (f32 (IMPLICIT_DEF)), addr:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xC))>; - def : Pat<(f64 (fceil (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xA))>; - def : Pat<(f64 (frint (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc (loadf64 addr:$src))), - (VROUNDSDm (f64 (IMPLICIT_DEF)), addr:$src, (i32 0xB))>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (ffloor VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc VR128:$src)), - (VROUNDPSr VR128:$src, (i32 0xB))>; - - def : Pat<(v4f32 (ffloor (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc (loadv4f32 addr:$src))), - (VROUNDPSm addr:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc VR128:$src)), - (VROUNDPDr VR128:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc (loadv2f64 addr:$src))), - (VROUNDPDm addr:$src, (i32 0xB))>; - - def : Pat<(v8f32 (ffloor VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0x9))>; - def : Pat<(v8f32 (fnearbyint VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xC))>; - def : Pat<(v8f32 (fceil VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xA))>; - def : Pat<(v8f32 (frint VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0x4))>; - def : Pat<(v8f32 (ftrunc VR256:$src)), - (VROUNDPSYr VR256:$src, (i32 0xB))>; - - def : Pat<(v8f32 (ffloor (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0x9))>; - def : Pat<(v8f32 (fnearbyint (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xC))>; - def : Pat<(v8f32 (fceil (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xA))>; - def : Pat<(v8f32 (frint (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0x4))>; - def : Pat<(v8f32 (ftrunc (loadv8f32 addr:$src))), - (VROUNDPSYm addr:$src, (i32 0xB))>; - - def : Pat<(v4f64 (ffloor VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0x9))>; - def : Pat<(v4f64 (fnearbyint VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xC))>; - def : Pat<(v4f64 (fceil VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xA))>; - def : Pat<(v4f64 (frint VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0x4))>; - def : Pat<(v4f64 (ftrunc VR256:$src)), - (VROUNDPDYr VR256:$src, (i32 0xB))>; - - def : Pat<(v4f64 (ffloor (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0x9))>; - def : Pat<(v4f64 (fnearbyint (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xC))>; - def : Pat<(v4f64 (fceil (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xA))>; - def : Pat<(v4f64 (frint (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0x4))>; - def : Pat<(v4f64 (ftrunc (loadv4f64 addr:$src))), - (VROUNDPDYm addr:$src, (i32 0xB))>; -} - -let ExeDomain = SSEPackedSingle in -defm ROUNDPS : sse41_fp_unop_p<0x08, "roundps", f128mem, VR128, v4f32, - memopv4f32, X86VRndScale, SchedWriteFRnd.XMM>; -let ExeDomain = SSEPackedDouble in -defm ROUNDPD : sse41_fp_unop_p<0x09, "roundpd", f128mem, VR128, v2f64, - memopv2f64, X86VRndScale, SchedWriteFRnd.XMM>; - -defm ROUND : sse41_fp_unop_s<0x0A, 0x0B, "round", SchedWriteFRnd.Scl>; - -let Constraints = "$src1 = $dst" in -defm ROUND : sse41_fp_binop_s<0x0A, 0x0B, "round", SchedWriteFRnd.Scl, - v4f32, v2f64, X86RndScales>; - -let Predicates = [UseSSE41] in { - def : Pat<(ffloor FR32:$src), - (ROUNDSSr FR32:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xC))>; - def : Pat<(f32 (fceil FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xA))>; - def : Pat<(f32 (frint FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc FR32:$src)), - (ROUNDSSr FR32:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xC))>; - def : Pat<(f64 (fceil FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xA))>; - def : Pat<(f64 (frint FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc FR64:$src)), - (ROUNDSDr FR64:$src, (i32 0xB))>; -} - -let Predicates = [UseSSE41, OptForSize] in { - def : Pat<(ffloor (loadf32 addr:$src)), - (ROUNDSSm addr:$src, (i32 0x9))>; - def : Pat<(f32 (fnearbyint (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xC))>; - def : Pat<(f32 (fceil (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xA))>; - def : Pat<(f32 (frint (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0x4))>; - def : Pat<(f32 (ftrunc (loadf32 addr:$src))), - (ROUNDSSm addr:$src, (i32 0xB))>; - - def : Pat<(f64 (ffloor (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0x9))>; - def : Pat<(f64 (fnearbyint (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xC))>; - def : Pat<(f64 (fceil (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xA))>; - def : Pat<(f64 (frint (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0x4))>; - def : Pat<(f64 (ftrunc (loadf64 addr:$src))), - (ROUNDSDm addr:$src, (i32 0xB))>; -} - -let Predicates = [UseSSE41] in { - def : Pat<(v4f32 (ffloor VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc VR128:$src)), - (ROUNDPSr VR128:$src, (i32 0xB))>; - - def : Pat<(v4f32 (ffloor (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0x9))>; - def : Pat<(v4f32 (fnearbyint (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xC))>; - def : Pat<(v4f32 (fceil (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xA))>; - def : Pat<(v4f32 (frint (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0x4))>; - def : Pat<(v4f32 (ftrunc (memopv4f32 addr:$src))), - (ROUNDPSm addr:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc VR128:$src)), - (ROUNDPDr VR128:$src, (i32 0xB))>; - - def : Pat<(v2f64 (ffloor (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0x9))>; - def : Pat<(v2f64 (fnearbyint (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xC))>; - def : Pat<(v2f64 (fceil (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xA))>; - def : Pat<(v2f64 (frint (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0x4))>; - def : Pat<(v2f64 (ftrunc (memopv2f64 addr:$src))), - (ROUNDPDm addr:$src, (i32 0xB))>; -} - -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; -defm : scalar_unary_math_imm_patterns; - -//===----------------------------------------------------------------------===// -// SSE4.1 - Packed Bit Test -//===----------------------------------------------------------------------===// - -// ptest instruction we'll lower to this in X86ISelLowering primarily from -// the intel intrinsic that corresponds to this. -let Defs = [EFLAGS], Predicates = [HasAVX] in { -def VPTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (v2i64 VR128:$src2)))]>, - Sched<[SchedWriteVecTest.XMM]>, VEX, VEX_WIG; -def VPTESTrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS,(X86ptest VR128:$src1, (loadv2i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.XMM.Folded, ReadAfterLd]>, - VEX, VEX_WIG; - -def VPTESTYrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR256:$src1, VR256:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR256:$src1, (v4i64 VR256:$src2)))]>, - Sched<[SchedWriteVecTest.YMM]>, VEX, VEX_L, VEX_WIG; -def VPTESTYrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR256:$src1, i256mem:$src2), - "vptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS,(X86ptest VR256:$src1, (loadv4i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.YMM.Folded, ReadAfterLd]>, - VEX, VEX_L, VEX_WIG; -} - -let Defs = [EFLAGS] in { -def PTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), - "ptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (v2i64 VR128:$src2)))]>, - Sched<[SchedWriteVecTest.XMM]>; -def PTESTrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), - "ptest\t{$src2, $src1|$src1, $src2}", - [(set EFLAGS, (X86ptest VR128:$src1, (memopv2i64 addr:$src2)))]>, - Sched<[SchedWriteVecTest.XMM.Folded, ReadAfterLd]>; -} - -// The bit test instructions below are AVX only -multiclass avx_bittest opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, PatFrag mem_frag, ValueType vt, - X86FoldableSchedWrite sched> { - def rr : SS48I, - Sched<[sched]>, VEX; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>, VEX; -} - -let Defs = [EFLAGS], Predicates = [HasAVX] in { -let ExeDomain = SSEPackedSingle in { -defm VTESTPS : avx_bittest<0x0E, "vtestps", VR128, f128mem, loadv4f32, v4f32, - SchedWriteFTest.XMM>; -defm VTESTPSY : avx_bittest<0x0E, "vtestps", VR256, f256mem, loadv8f32, v8f32, - SchedWriteFTest.YMM>, VEX_L; -} -let ExeDomain = SSEPackedDouble in { -defm VTESTPD : avx_bittest<0x0F, "vtestpd", VR128, f128mem, loadv2f64, v2f64, - SchedWriteFTest.XMM>; -defm VTESTPDY : avx_bittest<0x0F, "vtestpd", VR256, f256mem, loadv4f64, v4f64, - SchedWriteFTest.YMM>, VEX_L; -} -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - Misc Instructions -//===----------------------------------------------------------------------===// - -let Defs = [EFLAGS], Predicates = [HasPOPCNT] in { - def POPCNT16rr : I<0xB8, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "popcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctpop GR16:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, OpSize16, XS; - def POPCNT16rm : I<0xB8, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "popcnt{w}\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, (ctpop (loadi16 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, OpSize16, XS; - - def POPCNT32rr : I<0xB8, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "popcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctpop GR32:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, OpSize32, XS; - - def POPCNT32rm : I<0xB8, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "popcnt{l}\t{$src, $dst|$dst, $src}", - [(set GR32:$dst, (ctpop (loadi32 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, OpSize32, XS; - - def POPCNT64rr : RI<0xB8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "popcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctpop GR64:$src)), (implicit EFLAGS)]>, - Sched<[WritePOPCNT]>, XS; - def POPCNT64rm : RI<0xB8, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "popcnt{q}\t{$src, $dst|$dst, $src}", - [(set GR64:$dst, (ctpop (loadi64 addr:$src))), - (implicit EFLAGS)]>, - Sched<[WritePOPCNT.Folded]>, XS; -} - -// SS41I_unop_rm_int_v16 - SSE 4.1 unary operator whose type is v8i16. -multiclass SS41I_unop_rm_int_v16 opc, string OpcodeStr, - SDNode OpNode, PatFrag ld_frag, - X86FoldableSchedWrite Sched> { - def rr : SS48I, - Sched<[Sched]>; - def rm : SS48I, - Sched<[Sched.Folded]>; -} - -// PHMIN has the same profile as PSAD, thus we use the same scheduling -// model, although the naming is misleading. -let Predicates = [HasAVX] in -defm VPHMINPOSUW : SS41I_unop_rm_int_v16<0x41, "vphminposuw", - X86phminpos, loadv2i64, - WritePHMINPOS>, VEX, VEX_WIG; -defm PHMINPOSUW : SS41I_unop_rm_int_v16<0x41, "phminposuw", - X86phminpos, memopv2i64, - WritePHMINPOS>; - -/// SS48I_binop_rm - Simple SSE41 binary operator. -multiclass SS48I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - let isCommutable = 1 in - def rr : SS48I, - Sched<[sched]>; - def rm : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm VPMINSD : SS48I_binop_rm<0x39, "vpminsd", smin, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMINUD : SS48I_binop_rm<0x3B, "vpminud", umin, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXSD : SS48I_binop_rm<0x3D, "vpmaxsd", smax, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXUD : SS48I_binop_rm<0x3F, "vpmaxud", umax, v4i32, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMULDQ : SS48I_binop_rm<0x28, "vpmuldq", X86pmuldq, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecIMul.XMM, 0>, - VEX_4V, VEX_WIG; -} -let Predicates = [HasAVX, NoVLX_Or_NoBWI] in { - defm VPMINSB : SS48I_binop_rm<0x38, "vpminsb", smin, v16i8, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMINUW : SS48I_binop_rm<0x3A, "vpminuw", umin, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXSB : SS48I_binop_rm<0x3C, "vpmaxsb", smax, v16i8, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - defm VPMAXUW : SS48I_binop_rm<0x3E, "vpmaxuw", umax, v8i16, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPMINSDY : SS48I_binop_rm<0x39, "vpminsd", smin, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMINUDY : SS48I_binop_rm<0x3B, "vpminud", umin, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXSDY : SS48I_binop_rm<0x3D, "vpmaxsd", smax, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXUDY : SS48I_binop_rm<0x3F, "vpmaxud", umax, v8i32, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMULDQY : SS48I_binop_rm<0x28, "vpmuldq", X86pmuldq, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecIMul.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - defm VPMINSBY : SS48I_binop_rm<0x38, "vpminsb", smin, v32i8, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMINUWY : SS48I_binop_rm<0x3A, "vpminuw", umin, v16i16, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXSBY : SS48I_binop_rm<0x3C, "vpmaxsb", smax, v32i8, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - defm VPMAXUWY : SS48I_binop_rm<0x3E, "vpmaxuw", umax, v16i16, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm PMINSB : SS48I_binop_rm<0x38, "pminsb", smin, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINSD : SS48I_binop_rm<0x39, "pminsd", smin, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINUD : SS48I_binop_rm<0x3B, "pminud", umin, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMINUW : SS48I_binop_rm<0x3A, "pminuw", umin, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXSB : SS48I_binop_rm<0x3C, "pmaxsb", smax, v16i8, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXSD : SS48I_binop_rm<0x3D, "pmaxsd", smax, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXUD : SS48I_binop_rm<0x3F, "pmaxud", umax, v4i32, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMAXUW : SS48I_binop_rm<0x3E, "pmaxuw", umax, v8i16, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; - defm PMULDQ : SS48I_binop_rm<0x28, "pmuldq", X86pmuldq, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecIMul.XMM, 1>; -} - -let Predicates = [HasAVX, NoVLX] in - defm VPMULLD : SS48I_binop_rm<0x40, "vpmulld", mul, v4i32, VR128, - loadv2i64, i128mem, SchedWritePMULLD.XMM, 0>, - VEX_4V, VEX_WIG; -let Predicates = [HasAVX] in - defm VPCMPEQQ : SS48I_binop_rm<0x29, "vpcmpeqq", X86pcmpeq, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2, NoVLX] in - defm VPMULLDY : SS48I_binop_rm<0x40, "vpmulld", mul, v8i32, VR256, - loadv4i64, i256mem, SchedWritePMULLD.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; -let Predicates = [HasAVX2] in - defm VPCMPEQQY : SS48I_binop_rm<0x29, "vpcmpeqq", X86pcmpeq, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - -let Constraints = "$src1 = $dst" in { - defm PMULLD : SS48I_binop_rm<0x40, "pmulld", mul, v4i32, VR128, - memopv2i64, i128mem, SchedWritePMULLD.XMM, 1>; - defm PCMPEQQ : SS48I_binop_rm<0x29, "pcmpeqq", X86pcmpeq, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM, 1>; -} - -/// SS41I_binop_rmi_int - SSE 4.1 binary operator with 8-bit immediate -multiclass SS41I_binop_rmi_int opc, string OpcodeStr, - Intrinsic IntId, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -/// SS41I_binop_rmi - SSE 4.1 binary operator with 8-bit immediate -multiclass SS41I_binop_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -def BlendCommuteImm2 : SDNodeXFormgetZExtValue() & 0x03; - return getI8Imm(Imm ^ 0x03, SDLoc(N)); -}]>; - -def BlendCommuteImm4 : SDNodeXFormgetZExtValue() & 0x0f; - return getI8Imm(Imm ^ 0x0f, SDLoc(N)); -}]>; - -def BlendCommuteImm8 : SDNodeXFormgetZExtValue() & 0xff; - return getI8Imm(Imm ^ 0xff, SDLoc(N)); -}]>; - -let Predicates = [HasAVX] in { - let isCommutable = 0 in { - defm VMPSADBW : SS41I_binop_rmi_int<0x42, "vmpsadbw", int_x86_sse41_mpsadbw, - VR128, loadv2i64, i128mem, 0, - SchedWriteMPSAD.XMM>, VEX_4V, VEX_WIG; - } - - let ExeDomain = SSEPackedSingle in - defm VDPPS : SS41I_binop_rmi_int<0x40, "vdpps", int_x86_sse41_dpps, - VR128, loadv4f32, f128mem, 0, - SchedWriteDPPS.XMM>, VEX_4V, VEX_WIG; - let ExeDomain = SSEPackedDouble in - defm VDPPD : SS41I_binop_rmi_int<0x41, "vdppd", int_x86_sse41_dppd, - VR128, loadv2f64, f128mem, 0, - SchedWriteDPPD.XMM>, VEX_4V, VEX_WIG; - let ExeDomain = SSEPackedSingle in - defm VDPPSY : SS41I_binop_rmi_int<0x40, "vdpps", int_x86_avx_dp_ps_256, - VR256, loadv8f32, i256mem, 0, - SchedWriteDPPS.YMM>, VEX_4V, VEX_L, VEX_WIG; -} - -let Predicates = [HasAVX2] in { - let isCommutable = 0 in { - defm VMPSADBWY : SS41I_binop_rmi_int<0x42, "vmpsadbw", int_x86_avx2_mpsadbw, - VR256, loadv4i64, i256mem, 0, - SchedWriteMPSAD.YMM>, VEX_4V, VEX_L, VEX_WIG; - } -} - -let Constraints = "$src1 = $dst" in { - let isCommutable = 0 in { - defm MPSADBW : SS41I_binop_rmi_int<0x42, "mpsadbw", int_x86_sse41_mpsadbw, - VR128, memopv2i64, i128mem, 1, - SchedWriteMPSAD.XMM>; - } - - let ExeDomain = SSEPackedSingle in - defm DPPS : SS41I_binop_rmi_int<0x40, "dpps", int_x86_sse41_dpps, - VR128, memopv4f32, f128mem, 1, - SchedWriteDPPS.XMM>; - let ExeDomain = SSEPackedDouble in - defm DPPD : SS41I_binop_rmi_int<0x41, "dppd", int_x86_sse41_dppd, - VR128, memopv2f64, f128mem, 1, - SchedWriteDPPD.XMM>; -} - -/// SS41I_blend_rmi - SSE 4.1 blend with 8-bit immediate -multiclass SS41I_blend_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, bit Is2Addr, Domain d, - X86FoldableSchedWrite sched, SDNodeXForm commuteXForm> { -let ExeDomain = d, Constraints = !if(Is2Addr, "$src1 = $dst", "") in { - let isCommutable = 1 in - def rri : SS4AIi8, - Sched<[sched]>; - def rmi : SS4AIi8, - Sched<[sched.Folded, ReadAfterLd]>; -} - - // Pattern to commute if load is in first source. - def : Pat<(OpVT (OpNode (bitconvert (memop_frag addr:$src2)), - RC:$src1, imm:$src3)), - (!cast(NAME#"rmi") RC:$src1, addr:$src2, - (commuteXForm imm:$src3))>; -} - -let Predicates = [HasAVX] in { - defm VBLENDPS : SS41I_blend_rmi<0x0C, "vblendps", X86Blendi, v4f32, - VR128, loadv4f32, f128mem, 0, SSEPackedSingle, - SchedWriteFBlend.XMM, BlendCommuteImm4>, - VEX_4V, VEX_WIG; - defm VBLENDPSY : SS41I_blend_rmi<0x0C, "vblendps", X86Blendi, v8f32, - VR256, loadv8f32, f256mem, 0, SSEPackedSingle, - SchedWriteFBlend.YMM, BlendCommuteImm8>, - VEX_4V, VEX_L, VEX_WIG; - defm VBLENDPD : SS41I_blend_rmi<0x0D, "vblendpd", X86Blendi, v2f64, - VR128, loadv2f64, f128mem, 0, SSEPackedDouble, - SchedWriteFBlend.XMM, BlendCommuteImm2>, - VEX_4V, VEX_WIG; - defm VBLENDPDY : SS41I_blend_rmi<0x0D, "vblendpd", X86Blendi, v4f64, - VR256, loadv4f64, f256mem, 0, SSEPackedDouble, - SchedWriteFBlend.YMM, BlendCommuteImm4>, - VEX_4V, VEX_L, VEX_WIG; - defm VPBLENDW : SS41I_blend_rmi<0x0E, "vpblendw", X86Blendi, v8i16, - VR128, loadv2i64, i128mem, 0, SSEPackedInt, - SchedWriteBlend.XMM, BlendCommuteImm8>, - VEX_4V, VEX_WIG; -} - -let Predicates = [HasAVX2] in { - defm VPBLENDWY : SS41I_blend_rmi<0x0E, "vpblendw", X86Blendi, v16i16, - VR256, loadv4i64, i256mem, 0, SSEPackedInt, - SchedWriteBlend.YMM, BlendCommuteImm8>, - VEX_4V, VEX_L, VEX_WIG; -} - -defm BLENDPS : SS41I_blend_rmi<0x0C, "blendps", X86Blendi, v4f32, - VR128, memopv4f32, f128mem, 1, SSEPackedSingle, - SchedWriteFBlend.XMM, BlendCommuteImm4>; -defm BLENDPD : SS41I_blend_rmi<0x0D, "blendpd", X86Blendi, v2f64, - VR128, memopv2f64, f128mem, 1, SSEPackedDouble, - SchedWriteFBlend.XMM, BlendCommuteImm2>; -defm PBLENDW : SS41I_blend_rmi<0x0E, "pblendw", X86Blendi, v8i16, - VR128, memopv2i64, i128mem, 1, SSEPackedInt, - SchedWriteBlend.XMM, BlendCommuteImm8>; - -// For insertion into the zero index (low half) of a 256-bit vector, it is -// more efficient to generate a blend with immediate instead of an insert*128. -let Predicates = [HasAVX] in { -def : Pat<(insert_subvector (v4f64 VR256:$src1), (v2f64 VR128:$src2), (iPTR 0)), - (VBLENDPDYrri VR256:$src1, - (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0x3)>; -def : Pat<(insert_subvector (v8f32 VR256:$src1), (v4f32 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -/// SS41I_quaternary_int_avx - AVX SSE 4.1 with 4 operators -multiclass SS41I_quaternary_int_avx opc, string OpcodeStr, - RegisterClass RC, X86MemOperand x86memop, - PatFrag mem_frag, Intrinsic IntId, - X86FoldableSchedWrite sched> { - def rr : Ii8Reg, TAPD, VEX_4V, - Sched<[sched]>; - - def rm : Ii8Reg, TAPD, VEX_4V, - Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC::$src3 - ReadAfterLd]>; -} - -let Predicates = [HasAVX] in { -let ExeDomain = SSEPackedDouble in { -defm VBLENDVPD : SS41I_quaternary_int_avx<0x4B, "vblendvpd", VR128, f128mem, - loadv2f64, int_x86_sse41_blendvpd, - SchedWriteFVarBlend.XMM>; -defm VBLENDVPDY : SS41I_quaternary_int_avx<0x4B, "vblendvpd", VR256, f256mem, - loadv4f64, int_x86_avx_blendv_pd_256, - SchedWriteFVarBlend.YMM>, VEX_L; -} // ExeDomain = SSEPackedDouble -let ExeDomain = SSEPackedSingle in { -defm VBLENDVPS : SS41I_quaternary_int_avx<0x4A, "vblendvps", VR128, f128mem, - loadv4f32, int_x86_sse41_blendvps, - SchedWriteFVarBlend.XMM>; -defm VBLENDVPSY : SS41I_quaternary_int_avx<0x4A, "vblendvps", VR256, f256mem, - loadv8f32, int_x86_avx_blendv_ps_256, - SchedWriteFVarBlend.YMM>, VEX_L; -} // ExeDomain = SSEPackedSingle -defm VPBLENDVB : SS41I_quaternary_int_avx<0x4C, "vpblendvb", VR128, i128mem, - loadv2i64, int_x86_sse41_pblendvb, - SchedWriteVarBlend.XMM>; -} - -let Predicates = [HasAVX2] in { -defm VPBLENDVBY : SS41I_quaternary_int_avx<0x4C, "vpblendvb", VR256, i256mem, - loadv4i64, int_x86_avx2_pblendvb, - SchedWriteVarBlend.YMM>, VEX_L; -} - -let Predicates = [HasAVX] in { - def : Pat<(v16i8 (vselect (v16i8 VR128:$mask), (v16i8 VR128:$src1), - (v16i8 VR128:$src2))), - (VPBLENDVBrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v4i32 (vselect (v4i32 VR128:$mask), (v4i32 VR128:$src1), - (v4i32 VR128:$src2))), - (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v4f32 (vselect (v4i32 VR128:$mask), (v4f32 VR128:$src1), - (v4f32 VR128:$src2))), - (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v2i64 (vselect (v2i64 VR128:$mask), (v2i64 VR128:$src1), - (v2i64 VR128:$src2))), - (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v2f64 (vselect (v2i64 VR128:$mask), (v2f64 VR128:$src1), - (v2f64 VR128:$src2))), - (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>; - def : Pat<(v8i32 (vselect (v8i32 VR256:$mask), (v8i32 VR256:$src1), - (v8i32 VR256:$src2))), - (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v8f32 (vselect (v8i32 VR256:$mask), (v8f32 VR256:$src1), - (v8f32 VR256:$src2))), - (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v4i64 (vselect (v4i64 VR256:$mask), (v4i64 VR256:$src1), - (v4i64 VR256:$src2))), - (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>; - def : Pat<(v4f64 (vselect (v4i64 VR256:$mask), (v4f64 VR256:$src1), - (v4f64 VR256:$src2))), - (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>; -} - -let Predicates = [HasAVX2] in { - def : Pat<(v32i8 (vselect (v32i8 VR256:$mask), (v32i8 VR256:$src1), - (v32i8 VR256:$src2))), - (VPBLENDVBYrr VR256:$src2, VR256:$src1, VR256:$mask)>; -} - -// Prefer a movss or movsd over a blendps when optimizing for size. these were -// changed to use blends because blends have better throughput on sandybridge -// and haswell, but movs[s/d] are 1-2 byte shorter instructions. -let Predicates = [HasAVX, OptForSpeed] in { - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (VBLENDPSrri (v4f32 (V_SET0)), VR128:$src, (i8 1))>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (VPBLENDWrri (v4i32 (V_SET0)), VR128:$src, (i8 3))>; - - def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)), - (VBLENDPSrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss VR128:$src1, (loadv4f32 addr:$src2))), - (VBLENDPSrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss (loadv4f32 addr:$src2), VR128:$src1)), - (VBLENDPSrmi VR128:$src1, addr:$src2, (i8 0xe))>; - - def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)), - (VBLENDPDrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd VR128:$src1, (loadv2f64 addr:$src2))), - (VBLENDPDrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd (loadv2f64 addr:$src2), VR128:$src1)), - (VBLENDPDrmi VR128:$src1, addr:$src2, (i8 2))>; - - // Move low f32 and clear high bits. - def : Pat<(v8f32 (X86vzmovl (v8f32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4f32 (VBLENDPSrri (v4f32 (V_SET0)), - (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v8i32 (X86vzmovl (v8i32 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v4i32 (VPBLENDWrri (v4i32 (V_SET0)), - (v4i32 (EXTRACT_SUBREG (v8i32 VR256:$src), sub_xmm)), - (i8 3))), sub_xmm)>; - - def : Pat<(v4f64 (X86vzmovl (v4f64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2f64 (VBLENDPDrri (v2f64 (V_SET0)), - (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), sub_xmm)), - (i8 1))), sub_xmm)>; - def : Pat<(v4i64 (X86vzmovl (v4i64 VR256:$src))), - (SUBREG_TO_REG (i32 0), - (v2i64 (VPBLENDWrri (v2i64 (V_SET0)), - (v2i64 (EXTRACT_SUBREG (v4i64 VR256:$src), sub_xmm)), - (i8 0xf))), sub_xmm)>; -} - -// Prefer a movss or movsd over a blendps when optimizing for size. these were -// changed to use blends because blends have better throughput on sandybridge -// and haswell, but movs[s/d] are 1-2 byte shorter instructions. -let Predicates = [UseSSE41, OptForSpeed] in { - // With SSE41 we can use blends for these patterns. - def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (BLENDPSrri (v4f32 (V_SET0)), VR128:$src, (i8 1))>; - def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (PBLENDWrri (v4i32 (V_SET0)), VR128:$src, (i8 3))>; - - def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)), - (BLENDPSrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss VR128:$src1, (memopv4f32 addr:$src2))), - (BLENDPSrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v4f32 (X86Movss (memopv4f32 addr:$src2), VR128:$src1)), - (BLENDPSrmi VR128:$src1, addr:$src2, (i8 0xe))>; - - def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)), - (BLENDPDrri VR128:$src1, VR128:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd VR128:$src1, (memopv2f64 addr:$src2))), - (BLENDPDrmi VR128:$src1, addr:$src2, (i8 1))>; - def : Pat<(v2f64 (X86Movsd (memopv2f64 addr:$src2), VR128:$src1)), - (BLENDPDrmi VR128:$src1, addr:$src2, (i8 2))>; -} - - -/// SS41I_ternary_int - SSE 4.1 ternary operator -let Uses = [XMM0], Constraints = "$src1 = $dst" in { - multiclass SS41I_ternary_int opc, string OpcodeStr, PatFrag mem_frag, - X86MemOperand x86memop, Intrinsic IntId, - X86FoldableSchedWrite sched> { - def rr0 : SS48I, - Sched<[sched]>; - - def rm0 : SS48I, - Sched<[sched.Folded, ReadAfterLd]>; - } -} - -let ExeDomain = SSEPackedDouble in -defm BLENDVPD : SS41I_ternary_int<0x15, "blendvpd", memopv2f64, f128mem, - int_x86_sse41_blendvpd, SchedWriteFVarBlend.XMM>; -let ExeDomain = SSEPackedSingle in -defm BLENDVPS : SS41I_ternary_int<0x14, "blendvps", memopv4f32, f128mem, - int_x86_sse41_blendvps, SchedWriteFVarBlend.XMM>; -defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", memopv2i64, i128mem, - int_x86_sse41_pblendvb, SchedWriteVarBlend.XMM>; - -// Aliases with the implicit xmm0 argument -def : InstAlias<"blendvpd\t{$src2, $dst|$dst, $src2}", - (BLENDVPDrr0 VR128:$dst, VR128:$src2), 0>; -def : InstAlias<"blendvpd\t{$src2, $dst|$dst, $src2}", - (BLENDVPDrm0 VR128:$dst, f128mem:$src2), 0>; -def : InstAlias<"blendvps\t{$src2, $dst|$dst, $src2}", - (BLENDVPSrr0 VR128:$dst, VR128:$src2), 0>; -def : InstAlias<"blendvps\t{$src2, $dst|$dst, $src2}", - (BLENDVPSrm0 VR128:$dst, f128mem:$src2), 0>; -def : InstAlias<"pblendvb\t{$src2, $dst|$dst, $src2}", - (PBLENDVBrr0 VR128:$dst, VR128:$src2), 0>; -def : InstAlias<"pblendvb\t{$src2, $dst|$dst, $src2}", - (PBLENDVBrm0 VR128:$dst, i128mem:$src2), 0>; - -let Predicates = [UseSSE41] in { - def : Pat<(v16i8 (vselect (v16i8 XMM0), (v16i8 VR128:$src1), - (v16i8 VR128:$src2))), - (PBLENDVBrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v4i32 (vselect (v4i32 XMM0), (v4i32 VR128:$src1), - (v4i32 VR128:$src2))), - (BLENDVPSrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v4f32 (vselect (v4i32 XMM0), (v4f32 VR128:$src1), - (v4f32 VR128:$src2))), - (BLENDVPSrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v2i64 (vselect (v2i64 XMM0), (v2i64 VR128:$src1), - (v2i64 VR128:$src2))), - (BLENDVPDrr0 VR128:$src2, VR128:$src1)>; - def : Pat<(v2f64 (vselect (v2i64 XMM0), (v2f64 VR128:$src1), - (v2f64 VR128:$src2))), - (BLENDVPDrr0 VR128:$src2, VR128:$src1)>; -} - -let AddedComplexity = 400 in { // Prefer non-temporal versions - -let Predicates = [HasAVX, NoVLX] in -def VMOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.XMM.RM]>, VEX, VEX_WIG; -let Predicates = [HasAVX2, NoVLX] in -def VMOVNTDQAYrm : SS48I<0x2A, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vmovntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.YMM.RM]>, VEX, VEX_L, VEX_WIG; -def MOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movntdqa\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteVecMoveLSNT.XMM.RM]>; - -let Predicates = [HasAVX2, NoVLX] in { - def : Pat<(v8f32 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; - def : Pat<(v4f64 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; - def : Pat<(v4i64 (alignednontemporalload addr:$src)), - (VMOVNTDQAYrm addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (VMOVNTDQArm addr:$src)>; -} - -let Predicates = [UseSSE41] in { - def : Pat<(v4f32 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; - def : Pat<(v2f64 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; - def : Pat<(v2i64 (alignednontemporalload addr:$src)), - (MOVNTDQArm addr:$src)>; -} - -} // AddedComplexity - -//===----------------------------------------------------------------------===// -// SSE4.2 - Compare Instructions -//===----------------------------------------------------------------------===// - -/// SS42I_binop_rm - Simple SSE 4.2 binary operator -multiclass SS42I_binop_rm opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, X86FoldableSchedWrite sched, - bit Is2Addr = 1> { - def rr : SS428I, - Sched<[sched]>; - def rm : SS428I, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX] in - defm VPCMPGTQ : SS42I_binop_rm<0x37, "vpcmpgtq", X86pcmpgt, v2i64, VR128, - loadv2i64, i128mem, SchedWriteVecALU.XMM, 0>, - VEX_4V, VEX_WIG; - -let Predicates = [HasAVX2] in - defm VPCMPGTQY : SS42I_binop_rm<0x37, "vpcmpgtq", X86pcmpgt, v4i64, VR256, - loadv4i64, i256mem, SchedWriteVecALU.YMM, 0>, - VEX_4V, VEX_L, VEX_WIG; - -let Constraints = "$src1 = $dst" in - defm PCMPGTQ : SS42I_binop_rm<0x37, "pcmpgtq", X86pcmpgt, v2i64, VR128, - memopv2i64, i128mem, SchedWriteVecALU.XMM>; - -//===----------------------------------------------------------------------===// -// SSE4.2 - String/text Processing Instructions -//===----------------------------------------------------------------------===// - -multiclass pcmpistrm_SS42AI { - def rr : SS42AI<0x62, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrM]>; - let mayLoad = 1 in - def rm :SS42AI<0x62, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrM.Folded, ReadAfterLd]>; -} - -let Defs = [XMM0, EFLAGS], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPISTRM : pcmpistrm_SS42AI<"vpcmpistrm">, VEX; - defm PCMPISTRM : pcmpistrm_SS42AI<"pcmpistrm"> ; -} - -multiclass SS42AI_pcmpestrm { - def rr : SS42AI<0x60, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrM]>; - let mayLoad = 1 in - def rm : SS42AI<0x60, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrM.Folded, ReadAfterLd]>; -} - -let Defs = [XMM0, EFLAGS], Uses = [EAX, EDX], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPESTRM : SS42AI_pcmpestrm<"vpcmpestrm">, VEX; - defm PCMPESTRM : SS42AI_pcmpestrm<"pcmpestrm">; -} - -multiclass SS42AI_pcmpistri { - def rr : SS42AI<0x63, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrI]>; - let mayLoad = 1 in - def rm : SS42AI<0x63, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), - []>, Sched<[WritePCmpIStrI.Folded, ReadAfterLd]>; -} - -let Defs = [ECX, EFLAGS], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPISTRI : SS42AI_pcmpistri<"vpcmpistri">, VEX; - defm PCMPISTRI : SS42AI_pcmpistri<"pcmpistri">; -} - -multiclass SS42AI_pcmpestri { - def rr : SS42AI<0x61, MRMSrcReg, (outs), - (ins VR128:$src1, VR128:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrI]>; - let mayLoad = 1 in - def rm : SS42AI<0x61, MRMSrcMem, (outs), - (ins VR128:$src1, i128mem:$src3, u8imm:$src5), - !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), - []>, Sched<[WritePCmpEStrI.Folded, ReadAfterLd]>; -} - -let Defs = [ECX, EFLAGS], Uses = [EAX, EDX], hasSideEffects = 0 in { - let Predicates = [HasAVX] in - defm VPCMPESTRI : SS42AI_pcmpestri<"vpcmpestri">, VEX; - defm PCMPESTRI : SS42AI_pcmpestri<"pcmpestri">; -} - -//===----------------------------------------------------------------------===// -// SSE4.2 - CRC Instructions -//===----------------------------------------------------------------------===// - -// No CRC instructions have AVX equivalents - -// crc intrinsic instruction -// This set of instructions are only rm, the only difference is the size -// of r and m. -class SS42I_crc32r opc, string asm, RegisterClass RCOut, - RegisterClass RCIn, SDPatternOperator Int> : - SS42FI, - Sched<[WriteCRC32]>; - -class SS42I_crc32m opc, string asm, RegisterClass RCOut, - X86MemOperand x86memop, SDPatternOperator Int> : - SS42FI, - Sched<[WriteCRC32.Folded, ReadAfterLd]>; - -let Constraints = "$src1 = $dst" in { - def CRC32r32m8 : SS42I_crc32m<0xF0, "crc32{b}", GR32, i8mem, - int_x86_sse42_crc32_32_8>; - def CRC32r32r8 : SS42I_crc32r<0xF0, "crc32{b}", GR32, GR8, - int_x86_sse42_crc32_32_8>; - def CRC32r32m16 : SS42I_crc32m<0xF1, "crc32{w}", GR32, i16mem, - int_x86_sse42_crc32_32_16>, OpSize16; - def CRC32r32r16 : SS42I_crc32r<0xF1, "crc32{w}", GR32, GR16, - int_x86_sse42_crc32_32_16>, OpSize16; - def CRC32r32m32 : SS42I_crc32m<0xF1, "crc32{l}", GR32, i32mem, - int_x86_sse42_crc32_32_32>, OpSize32; - def CRC32r32r32 : SS42I_crc32r<0xF1, "crc32{l}", GR32, GR32, - int_x86_sse42_crc32_32_32>, OpSize32; - def CRC32r64m64 : SS42I_crc32m<0xF1, "crc32{q}", GR64, i64mem, - int_x86_sse42_crc32_64_64>, REX_W; - def CRC32r64r64 : SS42I_crc32r<0xF1, "crc32{q}", GR64, GR64, - int_x86_sse42_crc32_64_64>, REX_W; - let hasSideEffects = 0 in { - let mayLoad = 1 in - def CRC32r64m8 : SS42I_crc32m<0xF0, "crc32{b}", GR64, i8mem, - null_frag>, REX_W; - def CRC32r64r8 : SS42I_crc32r<0xF0, "crc32{b}", GR64, GR8, - null_frag>, REX_W; - } -} - -//===----------------------------------------------------------------------===// -// SHA-NI Instructions -//===----------------------------------------------------------------------===// - -// FIXME: Is there a better scheduler class for SHA than WriteVecIMul? -multiclass SHAI_binop Opc, string OpcodeStr, Intrinsic IntId, - X86FoldableSchedWrite sched, bit UsesXMM0 = 0> { - def rr : I, - T8, Sched<[sched]>; - - def rm : I, T8, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let Constraints = "$src1 = $dst", Predicates = [HasSHA] in { - def SHA1RNDS4rri : Ii8<0xCC, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - "sha1rnds4\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_sha1rnds4 VR128:$src1, VR128:$src2, - (i8 imm:$src3)))]>, TA, - Sched<[SchedWriteVecIMul.XMM]>; - def SHA1RNDS4rmi : Ii8<0xCC, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - "sha1rnds4\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_sha1rnds4 VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2)), - (i8 imm:$src3)))]>, TA, - Sched<[SchedWriteVecIMul.XMM.Folded, ReadAfterLd]>; - - defm SHA1NEXTE : SHAI_binop<0xC8, "sha1nexte", int_x86_sha1nexte, - SchedWriteVecIMul.XMM>; - defm SHA1MSG1 : SHAI_binop<0xC9, "sha1msg1", int_x86_sha1msg1, - SchedWriteVecIMul.XMM>; - defm SHA1MSG2 : SHAI_binop<0xCA, "sha1msg2", int_x86_sha1msg2, - SchedWriteVecIMul.XMM>; - - let Uses=[XMM0] in - defm SHA256RNDS2 : SHAI_binop<0xCB, "sha256rnds2", int_x86_sha256rnds2, - SchedWriteVecIMul.XMM, 1>; - - defm SHA256MSG1 : SHAI_binop<0xCC, "sha256msg1", int_x86_sha256msg1, - SchedWriteVecIMul.XMM>; - defm SHA256MSG2 : SHAI_binop<0xCD, "sha256msg2", int_x86_sha256msg2, - SchedWriteVecIMul.XMM>; -} - -// Aliases with explicit %xmm0 -def : InstAlias<"sha256rnds2\t{$src2, $dst|$dst, $src2}", - (SHA256RNDS2rr VR128:$dst, VR128:$src2), 0>; -def : InstAlias<"sha256rnds2\t{$src2, $dst|$dst, $src2}", - (SHA256RNDS2rm VR128:$dst, i128mem:$src2), 0>; - -//===----------------------------------------------------------------------===// -// AES-NI Instructions -//===----------------------------------------------------------------------===// - -multiclass AESI_binop_rm_int opc, string OpcodeStr, - Intrinsic IntId, PatFrag ld_frag, - bit Is2Addr = 0, RegisterClass RC = VR128, - X86MemOperand MemOp = i128mem> { - let AsmString = OpcodeStr## - !if(Is2Addr, "\t{$src2, $dst|$dst, $src2}", - "\t{$src2, $src1, $dst|$dst, $src1, $src2}") in { - def rr : AES8I, - Sched<[WriteAESDecEnc]>; - def rm : AES8I, - Sched<[WriteAESDecEnc.Folded, ReadAfterLd]>; - } -} - -// Perform One Round of an AES Encryption/Decryption Flow -let Predicates = [HasAVX, NoVLX_Or_NoVAES, HasAES] in { - defm VAESENC : AESI_binop_rm_int<0xDC, "vaesenc", - int_x86_aesni_aesenc, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESENCLAST : AESI_binop_rm_int<0xDD, "vaesenclast", - int_x86_aesni_aesenclast, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESDEC : AESI_binop_rm_int<0xDE, "vaesdec", - int_x86_aesni_aesdec, loadv2i64>, VEX_4V, VEX_WIG; - defm VAESDECLAST : AESI_binop_rm_int<0xDF, "vaesdeclast", - int_x86_aesni_aesdeclast, loadv2i64>, VEX_4V, VEX_WIG; -} - -let Predicates = [NoVLX, HasVAES] in { - defm VAESENCY : AESI_binop_rm_int<0xDC, "vaesenc", - int_x86_aesni_aesenc_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESENCLASTY : AESI_binop_rm_int<0xDD, "vaesenclast", - int_x86_aesni_aesenclast_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESDECY : AESI_binop_rm_int<0xDE, "vaesdec", - int_x86_aesni_aesdec_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; - defm VAESDECLASTY : AESI_binop_rm_int<0xDF, "vaesdeclast", - int_x86_aesni_aesdeclast_256, loadv4i64, 0, VR256, - i256mem>, VEX_4V, VEX_L, VEX_WIG; -} - -let Constraints = "$src1 = $dst" in { - defm AESENC : AESI_binop_rm_int<0xDC, "aesenc", - int_x86_aesni_aesenc, memopv2i64, 1>; - defm AESENCLAST : AESI_binop_rm_int<0xDD, "aesenclast", - int_x86_aesni_aesenclast, memopv2i64, 1>; - defm AESDEC : AESI_binop_rm_int<0xDE, "aesdec", - int_x86_aesni_aesdec, memopv2i64, 1>; - defm AESDECLAST : AESI_binop_rm_int<0xDF, "aesdeclast", - int_x86_aesni_aesdeclast, memopv2i64, 1>; -} - -// Perform the AES InvMixColumn Transformation -let Predicates = [HasAVX, HasAES] in { - def VAESIMCrr : AES8I<0xDB, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1), - "vaesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, - (int_x86_aesni_aesimc VR128:$src1))]>, Sched<[WriteAESIMC]>, - VEX, VEX_WIG; - def VAESIMCrm : AES8I<0xDB, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1), - "vaesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, (int_x86_aesni_aesimc (loadv2i64 addr:$src1)))]>, - Sched<[WriteAESIMC.Folded]>, VEX, VEX_WIG; -} -def AESIMCrr : AES8I<0xDB, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1), - "aesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, - (int_x86_aesni_aesimc VR128:$src1))]>, Sched<[WriteAESIMC]>; -def AESIMCrm : AES8I<0xDB, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1), - "aesimc\t{$src1, $dst|$dst, $src1}", - [(set VR128:$dst, (int_x86_aesni_aesimc (memopv2i64 addr:$src1)))]>, - Sched<[WriteAESIMC.Folded]>; - -// AES Round Key Generation Assist -let Predicates = [HasAVX, HasAES] in { - def VAESKEYGENASSIST128rr : AESAI<0xDF, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - "vaeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist VR128:$src1, imm:$src2))]>, - Sched<[WriteAESKeyGen]>, VEX, VEX_WIG; - def VAESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - "vaeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist (loadv2i64 addr:$src1), imm:$src2))]>, - Sched<[WriteAESKeyGen.Folded]>, VEX, VEX_WIG; -} -def AESKEYGENASSIST128rr : AESAI<0xDF, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, u8imm:$src2), - "aeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist VR128:$src1, imm:$src2))]>, - Sched<[WriteAESKeyGen]>; -def AESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), - (ins i128mem:$src1, u8imm:$src2), - "aeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, - (int_x86_aesni_aeskeygenassist (memopv2i64 addr:$src1), imm:$src2))]>, - Sched<[WriteAESKeyGen.Folded]>; - -//===----------------------------------------------------------------------===// -// PCLMUL Instructions -//===----------------------------------------------------------------------===// - -// Immediate transform to help with commuting. -def PCLMULCommuteImm : SDNodeXFormgetZExtValue(); - return getI8Imm((uint8_t)((Imm >> 4) | (Imm << 4)), SDLoc(N)); -}]>; - -// SSE carry-less Multiplication instructions -let Predicates = [NoAVX, HasPCLMUL] in { - let Constraints = "$src1 = $dst" in { - let isCommutable = 1 in - def PCLMULQDQrr : PCLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, u8imm:$src3), - "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_pclmulqdq VR128:$src1, VR128:$src2, imm:$src3))]>, - Sched<[WriteCLMul]>; - - def PCLMULQDQrm : PCLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2, u8imm:$src3), - "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (int_x86_pclmulqdq VR128:$src1, (memopv2i64 addr:$src2), - imm:$src3))]>, - Sched<[WriteCLMul.Folded, ReadAfterLd]>; - } // Constraints = "$src1 = $dst" - - def : Pat<(int_x86_pclmulqdq (memopv2i64 addr:$src2), VR128:$src1, - (i8 imm:$src3)), - (PCLMULQDQrm VR128:$src1, addr:$src2, - (PCLMULCommuteImm imm:$src3))>; -} // Predicates = [NoAVX, HasPCLMUL] - -// SSE aliases -foreach HI = ["hq","lq"] in -foreach LO = ["hq","lq"] in { - def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - (PCLMULQDQrr VR128:$dst, VR128:$src, - !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; - def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - (PCLMULQDQrm VR128:$dst, i128mem:$src, - !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; -} - -// AVX carry-less Multiplication instructions -multiclass vpclmulqdq { - let isCommutable = 1 in - def rr : PCLMULIi8<0x44, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, RC:$src2, imm:$src3))]>, - Sched<[WriteCLMul]>; - - def rm : PCLMULIi8<0x44, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, MemOp:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, (LdFrag addr:$src2), imm:$src3))]>, - Sched<[WriteCLMul.Folded, ReadAfterLd]>; - - // We can commute a load in the first operand by swapping the sources and - // rotating the immediate. - def : Pat<(IntId (LdFrag addr:$src2), RC:$src1, (i8 imm:$src3)), - (!cast(NAME#"rm") RC:$src1, addr:$src2, - (PCLMULCommuteImm imm:$src3))>; -} - -let Predicates = [HasAVX, NoVLX_Or_NoVPCLMULQDQ, HasPCLMUL] in -defm VPCLMULQDQ : vpclmulqdq, VEX_4V, VEX_WIG; - -let Predicates = [NoVLX, HasVPCLMULQDQ] in -defm VPCLMULQDQY : vpclmulqdq, VEX_4V, VEX_L, VEX_WIG; - -multiclass vpclmulqdq_aliases_impl { - def : InstAlias<"vpclmul"##Hi##Lo##"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (!cast(InstStr # "rr") RC:$dst, RC:$src1, RC:$src2, - !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; - def : InstAlias<"vpclmul"##Hi##Lo##"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (!cast(InstStr # "rm") RC:$dst, RC:$src1, MemOp:$src2, - !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; -} - -multiclass vpclmulqdq_aliases { - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; - defm : vpclmulqdq_aliases_impl; -} - -// AVX aliases -defm : vpclmulqdq_aliases<"VPCLMULQDQ", VR128, i128mem>; -defm : vpclmulqdq_aliases<"VPCLMULQDQY", VR256, i256mem>; - -//===----------------------------------------------------------------------===// -// SSE4A Instructions -//===----------------------------------------------------------------------===// - -let Predicates = [HasSSE4A] in { - -let ExeDomain = SSEPackedInt in { -let Constraints = "$src = $dst" in { -def EXTRQI : Ii8<0x78, MRMXr, (outs VR128:$dst), - (ins VR128:$src, u8imm:$len, u8imm:$idx), - "extrq\t{$idx, $len, $src|$src, $len, $idx}", - [(set VR128:$dst, (X86extrqi VR128:$src, imm:$len, - imm:$idx))]>, - PD, Sched<[SchedWriteVecALU.XMM]>; -def EXTRQ : I<0x79, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$mask), - "extrq\t{$mask, $src|$src, $mask}", - [(set VR128:$dst, (int_x86_sse4a_extrq VR128:$src, - VR128:$mask))]>, - PD, Sched<[SchedWriteVecALU.XMM]>; - -def INSERTQI : Ii8<0x78, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$src2, u8imm:$len, u8imm:$idx), - "insertq\t{$idx, $len, $src2, $src|$src, $src2, $len, $idx}", - [(set VR128:$dst, (X86insertqi VR128:$src, VR128:$src2, - imm:$len, imm:$idx))]>, - XD, Sched<[SchedWriteVecALU.XMM]>; -def INSERTQ : I<0x79, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src, VR128:$mask), - "insertq\t{$mask, $src|$src, $mask}", - [(set VR128:$dst, (int_x86_sse4a_insertq VR128:$src, - VR128:$mask))]>, - XD, Sched<[SchedWriteVecALU.XMM]>; -} -} // ExeDomain = SSEPackedInt - -// Non-temporal (unaligned) scalar stores. -let AddedComplexity = 400 in { // Prefer non-temporal versions -let hasSideEffects = 0, mayStore = 1, SchedRW = [SchedWriteFMoveLSNT.Scl.MR] in { -def MOVNTSS : I<0x2B, MRMDestMem, (outs), (ins f32mem:$dst, VR128:$src), - "movntss\t{$src, $dst|$dst, $src}", []>, XS; - -def MOVNTSD : I<0x2B, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movntsd\t{$src, $dst|$dst, $src}", []>, XD; -} // SchedRW - -def : Pat<(nontemporalstore FR32:$src, addr:$dst), - (MOVNTSS addr:$dst, (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - -def : Pat<(nontemporalstore FR64:$src, addr:$dst), - (MOVNTSD addr:$dst, (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; - -} // AddedComplexity -} // HasSSE4A - -//===----------------------------------------------------------------------===// -// AVX Instructions -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// VBROADCAST - Load from memory and broadcast to all elements of the -// destination operand -// -class avx_broadcast_rm opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType VT, - PatFrag ld_frag, SchedWrite Sched> : - AVX8I, - Sched<[Sched]>, VEX; - -// AVX2 adds register forms -class avx2_broadcast_rr opc, string OpcodeStr, RegisterClass RC, - ValueType ResVT, ValueType OpVT, SchedWrite Sched> : - AVX28I, - Sched<[Sched]>, VEX; - -let ExeDomain = SSEPackedSingle, Predicates = [HasAVX, NoVLX] in { - def VBROADCASTSSrm : avx_broadcast_rm<0x18, "vbroadcastss", VR128, - f32mem, v4f32, loadf32, - SchedWriteFShuffle.XMM.Folded>; - def VBROADCASTSSYrm : avx_broadcast_rm<0x18, "vbroadcastss", VR256, - f32mem, v8f32, loadf32, - SchedWriteFShuffle.XMM.Folded>, VEX_L; -} -let ExeDomain = SSEPackedDouble, Predicates = [HasAVX, NoVLX] in -def VBROADCASTSDYrm : avx_broadcast_rm<0x19, "vbroadcastsd", VR256, f64mem, - v4f64, loadf64, - SchedWriteFShuffle.XMM.Folded>, VEX_L; - -let ExeDomain = SSEPackedSingle, Predicates = [HasAVX2, NoVLX] in { - def VBROADCASTSSrr : avx2_broadcast_rr<0x18, "vbroadcastss", VR128, - v4f32, v4f32, SchedWriteFShuffle.XMM>; - def VBROADCASTSSYrr : avx2_broadcast_rr<0x18, "vbroadcastss", VR256, - v8f32, v4f32, WriteFShuffle256>, VEX_L; -} -let ExeDomain = SSEPackedDouble, Predicates = [HasAVX2, NoVLX] in -def VBROADCASTSDYrr : avx2_broadcast_rr<0x19, "vbroadcastsd", VR256, - v4f64, v2f64, WriteFShuffle256>, VEX_L; - -let Predicates = [HasAVX, NoVLX] in { - def : Pat<(v4f32 (X86VBroadcast (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (VBROADCASTSSrm addr:$src)>; - def : Pat<(v8f32 (X86VBroadcast (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (VBROADCASTSSYrm addr:$src)>; - def : Pat<(v4f64 (X86VBroadcast (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (VBROADCASTSDYrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VBROADCAST*128 - Load from memory and broadcast 128-bit vector to both -// halves of a 256-bit vector. -// -let mayLoad = 1, hasSideEffects = 0, Predicates = [HasAVX2] in -def VBROADCASTI128 : AVX8I<0x5A, MRMSrcMem, (outs VR256:$dst), - (ins i128mem:$src), - "vbroadcasti128\t{$src, $dst|$dst, $src}", []>, - Sched<[WriteShuffleLd]>, VEX, VEX_L; - -let mayLoad = 1, hasSideEffects = 0, Predicates = [HasAVX], - ExeDomain = SSEPackedSingle in -def VBROADCASTF128 : AVX8I<0x1A, MRMSrcMem, (outs VR256:$dst), - (ins f128mem:$src), - "vbroadcastf128\t{$src, $dst|$dst, $src}", []>, - Sched<[SchedWriteFShuffle.XMM.Folded]>, VEX, VEX_L; - -let Predicates = [HasAVX2, NoVLX] in { -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTI128 addr:$src)>; -} - -let Predicates = [HasAVX, NoVLX] in { -def : Pat<(v4f64 (X86SubVBroadcast (loadv2f64 addr:$src))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v8f32 (X86SubVBroadcast (loadv4f32 addr:$src))), - (VBROADCASTF128 addr:$src)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86SubVBroadcast (loadv2i64 addr:$src))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v8i32 (X86SubVBroadcast (bc_v4i32 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v16i16 (X86SubVBroadcast (bc_v8i16 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -def : Pat<(v32i8 (X86SubVBroadcast (bc_v16i8 (loadv2i64 addr:$src)))), - (VBROADCASTF128 addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VINSERTF128 - Insert packed floating-point values -// -let hasSideEffects = 0, ExeDomain = SSEPackedSingle in { -def VINSERTF128rr : AVXAIi8<0x18, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR128:$src2, u8imm:$src3), - "vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteFShuffle256]>, VEX_4V, VEX_L; -let mayLoad = 1 in -def VINSERTF128rm : AVXAIi8<0x18, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f128mem:$src2, u8imm:$src3), - "vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteFShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; -} - -// To create a 256-bit all ones value, we should produce VCMPTRUEPS -// with YMM register containing zero. -// FIXME: Avoid producing vxorps to clear the fake inputs. -let Predicates = [HasAVX1Only] in { -def : Pat<(v8i32 immAllOnesV), (VCMPPSYrri (AVX_SET0), (AVX_SET0), 0xf)>; -} - -multiclass vinsert_lowering { - def : Pat<(vinsert128_insert:$ins (To VR256:$src1), (From VR128:$src2), - (iPTR imm)), - (!cast(InstrStr#rr) VR256:$src1, VR128:$src2, - (INSERT_get_vinsert128_imm VR256:$ins))>; - def : Pat<(vinsert128_insert:$ins (To VR256:$src1), - (From (bitconvert (memop_frag addr:$src2))), - (iPTR imm)), - (!cast(InstrStr#rm) VR256:$src1, addr:$src2, - (INSERT_get_vinsert128_imm VR256:$ins))>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : vinsert_lowering<"VINSERTF128", v4f32, v8f32, loadv4f32>; - defm : vinsert_lowering<"VINSERTF128", v2f64, v4f64, loadv2f64>; -} - -let Predicates = [HasAVX1Only] in { - defm : vinsert_lowering<"VINSERTF128", v2i64, v4i64, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v4i32, v8i32, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v8i16, v16i16, loadv2i64>; - defm : vinsert_lowering<"VINSERTF128", v16i8, v32i8, loadv2i64>; -} - -//===----------------------------------------------------------------------===// -// VEXTRACTF128 - Extract packed floating-point values -// -let hasSideEffects = 0, ExeDomain = SSEPackedSingle in { -def VEXTRACTF128rr : AVXAIi8<0x19, MRMDestReg, (outs VR128:$dst), - (ins VR256:$src1, u8imm:$src2), - "vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, Sched<[WriteFShuffle256]>, VEX, VEX_L; -let mayStore = 1 in -def VEXTRACTF128mr : AVXAIi8<0x19, MRMDestMem, (outs), - (ins f128mem:$dst, VR256:$src1, u8imm:$src2), - "vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}", - []>, Sched<[WriteFStoreX]>, VEX, VEX_L; -} - -multiclass vextract_lowering { - def : Pat<(vextract128_extract:$ext VR256:$src1, (iPTR imm)), - (To (!cast(InstrStr#rr) - (From VR256:$src1), - (EXTRACT_get_vextract128_imm VR128:$ext)))>; - def : Pat<(store (To (vextract128_extract:$ext (From VR256:$src1), - (iPTR imm))), addr:$dst), - (!cast(InstrStr#mr) addr:$dst, VR256:$src1, - (EXTRACT_get_vextract128_imm VR128:$ext))>; -} - -// AVX1 patterns -let Predicates = [HasAVX, NoVLX] in { - defm : vextract_lowering<"VEXTRACTF128", v8f32, v4f32>; - defm : vextract_lowering<"VEXTRACTF128", v4f64, v2f64>; -} - -let Predicates = [HasAVX1Only] in { - defm : vextract_lowering<"VEXTRACTF128", v4i64, v2i64>; - defm : vextract_lowering<"VEXTRACTF128", v8i32, v4i32>; - defm : vextract_lowering<"VEXTRACTF128", v16i16, v8i16>; - defm : vextract_lowering<"VEXTRACTF128", v32i8, v16i8>; -} - -//===----------------------------------------------------------------------===// -// VMASKMOV - Conditional SIMD Packed Loads and Stores -// -multiclass avx_movmask_rm opc_rm, bits<8> opc_mr, string OpcodeStr, - Intrinsic IntLd, Intrinsic IntLd256, - Intrinsic IntSt, Intrinsic IntSt256> { - def rm : AVX8I, - VEX_4V, Sched<[WriteFMaskedLoad]>; - def Yrm : AVX8I, - VEX_4V, VEX_L, Sched<[WriteFMaskedLoadY]>; - def mr : AVX8I, - VEX_4V, Sched<[WriteFMaskedStore]>; - def Ymr : AVX8I, - VEX_4V, VEX_L, Sched<[WriteFMaskedStoreY]>; -} - -let ExeDomain = SSEPackedSingle in -defm VMASKMOVPS : avx_movmask_rm<0x2C, 0x2E, "vmaskmovps", - int_x86_avx_maskload_ps, - int_x86_avx_maskload_ps_256, - int_x86_avx_maskstore_ps, - int_x86_avx_maskstore_ps_256>; -let ExeDomain = SSEPackedDouble in -defm VMASKMOVPD : avx_movmask_rm<0x2D, 0x2F, "vmaskmovpd", - int_x86_avx_maskload_pd, - int_x86_avx_maskload_pd_256, - int_x86_avx_maskstore_pd, - int_x86_avx_maskstore_pd_256>; - -//===----------------------------------------------------------------------===// -// VPERMIL - Permute Single and Double Floating-Point Values -// - -multiclass avx_permil opc_rm, bits<8> opc_rmi, string OpcodeStr, - RegisterClass RC, X86MemOperand x86memop_f, - X86MemOperand x86memop_i, PatFrag i_frag, - ValueType f_vt, ValueType i_vt, - X86FoldableSchedWrite sched, - X86FoldableSchedWrite varsched> { - let Predicates = [HasAVX, NoVLX] in { - def rr : AVX8I, VEX_4V, - Sched<[varsched]>; - def rm : AVX8I, VEX_4V, - Sched<[varsched.Folded, ReadAfterLd]>; - - def ri : AVXAIi8, VEX, - Sched<[sched]>; - def mi : AVXAIi8, VEX, - Sched<[sched.Folded]>; - }// Predicates = [HasAVX, NoVLX] -} - -let ExeDomain = SSEPackedSingle in { - defm VPERMILPS : avx_permil<0x0C, 0x04, "vpermilps", VR128, f128mem, i128mem, - loadv2i64, v4f32, v4i32, SchedWriteFShuffle.XMM, - SchedWriteFVarShuffle.XMM>; - defm VPERMILPSY : avx_permil<0x0C, 0x04, "vpermilps", VR256, f256mem, i256mem, - loadv4i64, v8f32, v8i32, SchedWriteFShuffle.YMM, - SchedWriteFVarShuffle.YMM>, VEX_L; -} -let ExeDomain = SSEPackedDouble in { - defm VPERMILPD : avx_permil<0x0D, 0x05, "vpermilpd", VR128, f128mem, i128mem, - loadv2i64, v2f64, v2i64, SchedWriteFShuffle.XMM, - SchedWriteFVarShuffle.XMM>; - defm VPERMILPDY : avx_permil<0x0D, 0x05, "vpermilpd", VR256, f256mem, i256mem, - loadv4i64, v4f64, v4i64, SchedWriteFShuffle.YMM, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - -//===----------------------------------------------------------------------===// -// VPERM2F128 - Permute Floating-Point Values in 128-bit chunks -// - -let ExeDomain = SSEPackedSingle in { -let isCommutable = 1 in -def VPERM2F128rr : AVXAIi8<0x06, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR256:$src2, u8imm:$src3), - "vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (v4f64 (X86VPerm2x128 VR256:$src1, VR256:$src2, - (i8 imm:$src3))))]>, VEX_4V, VEX_L, - Sched<[WriteFShuffle256]>; -def VPERM2F128rm : AVXAIi8<0x06, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f256mem:$src2, u8imm:$src3), - "vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (X86VPerm2x128 VR256:$src1, (loadv4f64 addr:$src2), - (i8 imm:$src3)))]>, VEX_4V, VEX_L, - Sched<[WriteFShuffle256Ld, ReadAfterLd]>; -} - -// Immediate transform to help with commuting. -def Perm2XCommuteImm : SDNodeXFormgetZExtValue() ^ 0x22, SDLoc(N)); -}]>; - -let Predicates = [HasAVX] in { -// Pattern with load in other operand. -def : Pat<(v4f64 (X86VPerm2x128 (loadv4f64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86VPerm2x128 VR256:$src1, VR256:$src2, (i8 imm:$imm))), - (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>; -def : Pat<(v4i64 (X86VPerm2x128 VR256:$src1, - (loadv4i64 addr:$src2), (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, imm:$imm)>; -// Pattern with load in other operand. -def : Pat<(v4i64 (X86VPerm2x128 (loadv4i64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2F128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; -} - -//===----------------------------------------------------------------------===// -// VZERO - Zero YMM registers -// Note: These instruction do not affect the YMM16-YMM31. -// - -let SchedRW = [WriteSystem] in { -let Defs = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, - YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15] in { - // Zero All YMM registers - def VZEROALL : I<0x77, RawFrm, (outs), (ins), "vzeroall", - [(int_x86_avx_vzeroall)]>, PS, VEX, VEX_L, - Requires<[HasAVX]>, VEX_WIG; - - // Zero Upper bits of YMM registers - def VZEROUPPER : I<0x77, RawFrm, (outs), (ins), "vzeroupper", - [(int_x86_avx_vzeroupper)]>, PS, VEX, - Requires<[HasAVX]>, VEX_WIG; -} // Defs -} // SchedRW - -//===----------------------------------------------------------------------===// -// Half precision conversion instructions -// - -multiclass f16c_ph2ps { - def rr : I<0x13, MRMSrcReg, (outs RC:$dst), (ins VR128:$src), - "vcvtph2ps\t{$src, $dst|$dst, $src}", - [(set RC:$dst, (X86cvtph2ps VR128:$src))]>, - T8PD, VEX, Sched<[sched]>; - let hasSideEffects = 0, mayLoad = 1 in - def rm : I<0x13, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src), - "vcvtph2ps\t{$src, $dst|$dst, $src}", - [(set RC:$dst, (X86cvtph2ps (bc_v8i16 - (loadv2i64 addr:$src))))]>, - T8PD, VEX, Sched<[sched.Folded]>; -} - -multiclass f16c_ps2ph { - def rr : Ii8<0x1D, MRMDestReg, (outs VR128:$dst), - (ins RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (X86cvtps2ph RC:$src1, imm:$src2))]>, - TAPD, VEX, Sched<[RR]>; - let hasSideEffects = 0, mayStore = 1 in - def mr : Ii8<0x1D, MRMDestMem, (outs), - (ins x86memop:$dst, RC:$src1, i32u8imm:$src2), - "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - TAPD, VEX, Sched<[MR]>; -} - -let Predicates = [HasF16C, NoVLX] in { - defm VCVTPH2PS : f16c_ph2ps; - defm VCVTPH2PSY : f16c_ph2ps, VEX_L; - defm VCVTPS2PH : f16c_ps2ph; - defm VCVTPS2PHY : f16c_ps2ph, VEX_L; - - // Pattern match vcvtph2ps of a scalar i64 load. - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzmovl_v2i64 addr:$src)))), - (VCVTPH2PSrm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (vzload_v2i64 addr:$src)))), - (VCVTPH2PSrm addr:$src)>; - def : Pat<(v4f32 (X86cvtph2ps (v8i16 (bitconvert - (v2i64 (scalar_to_vector (loadi64 addr:$src))))))), - (VCVTPH2PSrm addr:$src)>; - - def : Pat<(store (f64 (extractelt - (bc_v2f64 (v8i16 (X86cvtps2ph VR128:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHmr addr:$dst, VR128:$src1, imm:$src2)>; - def : Pat<(store (i64 (extractelt - (bc_v2i64 (v8i16 (X86cvtps2ph VR128:$src1, i32:$src2))), - (iPTR 0))), addr:$dst), - (VCVTPS2PHmr addr:$dst, VR128:$src1, imm:$src2)>; - def : Pat<(store (v8i16 (X86cvtps2ph VR256:$src1, i32:$src2)), addr:$dst), - (VCVTPS2PHYmr addr:$dst, VR256:$src1, imm:$src2)>; -} - -// Patterns for matching conversions from float to half-float and vice versa. -let Predicates = [HasF16C, NoVLX] in { - // Use MXCSR.RC for rounding instead of explicitly specifying the default - // rounding mode (Nearest-Even, encoded as 0). Both are equivalent in the - // configurations we support (the default). However, falling back to MXCSR is - // more consistent with other instructions, which are always controlled by it. - // It's encoded as 0b100. - def : Pat<(fp_to_f16 FR32:$src), - (i16 (EXTRACT_SUBREG (VMOVPDI2DIrr (v8i16 (VCVTPS2PHrr - (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 4))), sub_16bit))>; - - def : Pat<(f16_to_fp GR16:$src), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSrr - (v4i32 (COPY_TO_REGCLASS (MOVSX32rr16 GR16:$src), VR128)))), FR32)) >; - - def : Pat<(f16_to_fp (i16 (fp_to_f16 FR32:$src))), - (f32 (COPY_TO_REGCLASS (v4f32 (VCVTPH2PSrr - (v8i16 (VCVTPS2PHrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 4)))), FR32)) >; -} - -//===----------------------------------------------------------------------===// -// AVX2 Instructions -//===----------------------------------------------------------------------===// - -/// AVX2_blend_rmi - AVX2 blend with 8-bit immediate -multiclass AVX2_blend_rmi opc, string OpcodeStr, SDNode OpNode, - ValueType OpVT, X86FoldableSchedWrite sched, - RegisterClass RC, PatFrag memop_frag, - X86MemOperand x86memop, SDNodeXForm commuteXForm> { - let isCommutable = 1 in - def rri : AVX2AIi8, - Sched<[sched]>, VEX_4V; - def rmi : AVX2AIi8, - Sched<[sched.Folded, ReadAfterLd]>, VEX_4V; - - // Pattern to commute if load is in first source. - def : Pat<(OpVT (OpNode (bitconvert (memop_frag addr:$src2)), - RC:$src1, imm:$src3)), - (!cast(NAME#"rmi") RC:$src1, addr:$src2, - (commuteXForm imm:$src3))>; -} - -defm VPBLENDD : AVX2_blend_rmi<0x02, "vpblendd", X86Blendi, v4i32, - SchedWriteBlend.XMM, VR128, loadv2i64, i128mem, - BlendCommuteImm4>; -defm VPBLENDDY : AVX2_blend_rmi<0x02, "vpblendd", X86Blendi, v8i32, - SchedWriteBlend.YMM, VR256, loadv4i64, i256mem, - BlendCommuteImm8>, VEX_L; - -// For insertion into the zero index (low half) of a 256-bit vector, it is -// more efficient to generate a blend with immediate instead of an insert*128. -let Predicates = [HasAVX2] in { -def : Pat<(insert_subvector (v8i32 VR256:$src1), (v4i32 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v4i64 VR256:$src1), (v2i64 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v16i16 VR256:$src1), (v8i16 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v32i8 VR256:$src1), (v16i8 VR128:$src2), (iPTR 0)), - (VPBLENDDYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(insert_subvector (v8i32 VR256:$src1), (v4i32 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v4i64 VR256:$src1), (v2i64 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v16i16 VR256:$src1), (v8i16 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -def : Pat<(insert_subvector (v32i8 VR256:$src1), (v16i8 VR128:$src2), (iPTR 0)), - (VBLENDPSYrri VR256:$src1, - (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - VR128:$src2, sub_xmm), 0xf)>; -} - -//===----------------------------------------------------------------------===// -// VPBROADCAST - Load from memory and broadcast to all elements of the -// destination operand -// -multiclass avx2_broadcast opc, string OpcodeStr, - X86MemOperand x86memop, PatFrag ld_frag, - ValueType OpVT128, ValueType OpVT256, Predicate prd> { - let Predicates = [HasAVX2, prd] in { - def rr : AVX28I, - Sched<[SchedWriteShuffle.XMM]>, VEX; - def rm : AVX28I, - Sched<[SchedWriteShuffle.XMM.Folded]>, VEX; - def Yrr : AVX28I, - Sched<[WriteShuffle256]>, VEX, VEX_L; - def Yrm : AVX28I, - Sched<[SchedWriteShuffle.XMM.Folded]>, VEX, VEX_L; - - // Provide aliases for broadcast from the same register class that - // automatically does the extract. - def : Pat<(OpVT256 (X86VBroadcast (OpVT256 VR256:$src))), - (!cast(NAME#"Yrr") - (OpVT128 (EXTRACT_SUBREG (OpVT256 VR256:$src),sub_xmm)))>; - } -} - -defm VPBROADCASTB : avx2_broadcast<0x78, "vpbroadcastb", i8mem, loadi8, - v16i8, v32i8, NoVLX_Or_NoBWI>; -defm VPBROADCASTW : avx2_broadcast<0x79, "vpbroadcastw", i16mem, loadi16, - v8i16, v16i16, NoVLX_Or_NoBWI>; -defm VPBROADCASTD : avx2_broadcast<0x58, "vpbroadcastd", i32mem, loadi32, - v4i32, v8i32, NoVLX>; -defm VPBROADCASTQ : avx2_broadcast<0x59, "vpbroadcastq", i64mem, loadi64, - v2i64, v4i64, NoVLX>; - -let Predicates = [HasAVX2, NoVLX] in { - // 32-bit targets will fail to load a i64 directly but can use ZEXT_LOAD. - def : Pat<(v2i64 (X86VBroadcast (v2i64 (X86vzload addr:$src)))), - (VPBROADCASTQrm addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v4i64 (X86vzload addr:$src)))), - (VPBROADCASTQYrm addr:$src)>; - - def : Pat<(v4i32 (X86VBroadcast (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VPBROADCASTDrm addr:$src)>; - def : Pat<(v8i32 (X86VBroadcast (v4i32 (scalar_to_vector (loadi32 addr:$src))))), - (VPBROADCASTDYrm addr:$src)>; - def : Pat<(v2i64 (X86VBroadcast (v2i64 (scalar_to_vector (loadi64 addr:$src))))), - (VPBROADCASTQrm addr:$src)>; - def : Pat<(v4i64 (X86VBroadcast (v2i64 (scalar_to_vector (loadi64 addr:$src))))), - (VPBROADCASTQYrm addr:$src)>; -} -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - // loadi16 is tricky to fold, because !isTypeDesirableForOp, justifiably. - // This means we'll encounter truncated i32 loads; match that here. - def : Pat<(v8i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWrm addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast (i16 (trunc (i32 (load addr:$src)))))), - (VPBROADCASTWYrm addr:$src)>; - def : Pat<(v8i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWrm addr:$src)>; - def : Pat<(v16i16 (X86VBroadcast - (i16 (trunc (i32 (zextloadi16 addr:$src)))))), - (VPBROADCASTWYrm addr:$src)>; -} - -let Predicates = [HasAVX2, NoVLX] in { - // Provide aliases for broadcast from the same register class that - // automatically does the extract. - def : Pat<(v8f32 (X86VBroadcast (v8f32 VR256:$src))), - (VBROADCASTSSYrr (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), - sub_xmm)))>; - def : Pat<(v4f64 (X86VBroadcast (v4f64 VR256:$src))), - (VBROADCASTSDYrr (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), - sub_xmm)))>; -} - -let Predicates = [HasAVX2, NoVLX] in { - // Provide fallback in case the load node that is used in the patterns above - // is used by additional users, which prevents the pattern selection. - def : Pat<(v4f32 (X86VBroadcast FR32:$src)), - (VBROADCASTSSrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - def : Pat<(v8f32 (X86VBroadcast FR32:$src)), - (VBROADCASTSSYrr (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)))>; - def : Pat<(v4f64 (X86VBroadcast FR64:$src)), - (VBROADCASTSDYrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; -} - -let Predicates = [HasAVX2, NoVLX_Or_NoBWI] in { - def : Pat<(v16i8 (X86VBroadcast GR8:$src)), - (VPBROADCASTBrr (v16i8 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR8:$src, sub_8bit)), - VR128)))>; - def : Pat<(v32i8 (X86VBroadcast GR8:$src)), - (VPBROADCASTBYrr (v16i8 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR8:$src, sub_8bit)), - VR128)))>; - - def : Pat<(v8i16 (X86VBroadcast GR16:$src)), - (VPBROADCASTWrr (v8i16 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR16:$src, sub_16bit)), - VR128)))>; - def : Pat<(v16i16 (X86VBroadcast GR16:$src)), - (VPBROADCASTWYrr (v8i16 (COPY_TO_REGCLASS - (i32 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), - GR16:$src, sub_16bit)), - VR128)))>; -} -let Predicates = [HasAVX2, NoVLX] in { - def : Pat<(v4i32 (X86VBroadcast GR32:$src)), - (VPBROADCASTDrr (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)))>; - def : Pat<(v8i32 (X86VBroadcast GR32:$src)), - (VPBROADCASTDYrr (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)))>; - def : Pat<(v2i64 (X86VBroadcast GR64:$src)), - (VPBROADCASTQrr (v2i64 (COPY_TO_REGCLASS GR64:$src, VR128)))>; - def : Pat<(v4i64 (X86VBroadcast GR64:$src)), - (VPBROADCASTQYrr (v2i64 (COPY_TO_REGCLASS GR64:$src, VR128)))>; -} - -// AVX1 broadcast patterns -let Predicates = [HasAVX1Only] in { -def : Pat<(v8i32 (X86VBroadcast (loadi32 addr:$src))), - (VBROADCASTSSYrm addr:$src)>; -def : Pat<(v4i64 (X86VBroadcast (loadi64 addr:$src))), - (VBROADCASTSDYrm addr:$src)>; -def : Pat<(v4i32 (X86VBroadcast (loadi32 addr:$src))), - (VBROADCASTSSrm addr:$src)>; -} - - // Provide fallback in case the load node that is used in the patterns above - // is used by additional users, which prevents the pattern selection. -let Predicates = [HasAVX, NoVLX] in { - // 128bit broadcasts: - def : Pat<(v2f64 (X86VBroadcast f64:$src)), - (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))>; - def : Pat<(v2f64 (X86VBroadcast (loadf64 addr:$src))), - (VMOVDDUPrm addr:$src)>; - - def : Pat<(v2f64 (X86VBroadcast v2f64:$src)), - (VMOVDDUPrr VR128:$src)>; - def : Pat<(v2f64 (X86VBroadcast (loadv2f64 addr:$src))), - (VMOVDDUPrm addr:$src)>; -} - -let Predicates = [HasAVX1Only] in { - def : Pat<(v4f32 (X86VBroadcast FR32:$src)), - (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)>; - def : Pat<(v8f32 (X86VBroadcast FR32:$src)), - (VINSERTF128rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), - (v4f32 (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)), sub_xmm), - (v4f32 (VPERMILPSri (v4f32 (COPY_TO_REGCLASS FR32:$src, VR128)), 0)), 1)>; - def : Pat<(v4f64 (X86VBroadcast FR64:$src)), - (VINSERTF128rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), - (v2f64 (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))), sub_xmm), - (v2f64 (VMOVDDUPrr (v2f64 (COPY_TO_REGCLASS FR64:$src, VR128)))), 1)>; - - def : Pat<(v4i32 (X86VBroadcast GR32:$src)), - (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)>; - def : Pat<(v8i32 (X86VBroadcast GR32:$src)), - (VINSERTF128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)), sub_xmm), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR32:$src, VR128)), 0)), 1)>; - def : Pat<(v4i64 (X86VBroadcast GR64:$src)), - (VINSERTF128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)), sub_xmm), - (v4i32 (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)), 1)>; - - def : Pat<(v2i64 (X86VBroadcast i64:$src)), - (VPSHUFDri (v4i32 (COPY_TO_REGCLASS GR64:$src, VR128)), 0x44)>; - def : Pat<(v2i64 (X86VBroadcast (loadi64 addr:$src))), - (VMOVDDUPrm addr:$src)>; -} - -//===----------------------------------------------------------------------===// -// VPERM - Permute instructions -// - -multiclass avx2_perm opc, string OpcodeStr, PatFrag mem_frag, - ValueType OpVT, X86FoldableSchedWrite Sched, - X86MemOperand memOp> { - let Predicates = [HasAVX2, NoVLX] in { - def Yrr : AVX28I, - Sched<[Sched]>, VEX_4V, VEX_L; - def Yrm : AVX28I, - Sched<[Sched.Folded, ReadAfterLd]>, VEX_4V, VEX_L; - } -} - -defm VPERMD : avx2_perm<0x36, "vpermd", loadv4i64, v8i32, WriteVarShuffle256, - i256mem>; -let ExeDomain = SSEPackedSingle in -defm VPERMPS : avx2_perm<0x16, "vpermps", loadv8f32, v8f32, WriteFVarShuffle256, - f256mem>; - -multiclass avx2_perm_imm opc, string OpcodeStr, PatFrag mem_frag, - ValueType OpVT, X86FoldableSchedWrite Sched, - X86MemOperand memOp> { - let Predicates = [HasAVX2, NoVLX] in { - def Yri : AVX2AIi8, - Sched<[Sched]>, VEX, VEX_L; - def Ymi : AVX2AIi8, - Sched<[Sched.Folded, ReadAfterLd]>, VEX, VEX_L; - } -} - -defm VPERMQ : avx2_perm_imm<0x00, "vpermq", loadv4i64, v4i64, - WriteShuffle256, i256mem>, VEX_W; -let ExeDomain = SSEPackedDouble in -defm VPERMPD : avx2_perm_imm<0x01, "vpermpd", loadv4f64, v4f64, - WriteFShuffle256, f256mem>, VEX_W; - -//===----------------------------------------------------------------------===// -// VPERM2I128 - Permute Floating-Point Values in 128-bit chunks -// -let isCommutable = 1 in -def VPERM2I128rr : AVX2AIi8<0x46, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR256:$src2, u8imm:$src3), - "vperm2i128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (v4i64 (X86VPerm2x128 VR256:$src1, VR256:$src2, - (i8 imm:$src3))))]>, Sched<[WriteShuffle256]>, - VEX_4V, VEX_L; -def VPERM2I128rm : AVX2AIi8<0x46, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, f256mem:$src2, u8imm:$src3), - "vperm2i128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set VR256:$dst, (X86VPerm2x128 VR256:$src1, (loadv4i64 addr:$src2), - (i8 imm:$src3)))]>, - Sched<[WriteShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; - -let Predicates = [HasAVX2] in -def : Pat<(v4i64 (X86VPerm2x128 (loadv4i64 addr:$src2), - VR256:$src1, (i8 imm:$imm))), - (VPERM2I128rm VR256:$src1, addr:$src2, (Perm2XCommuteImm imm:$imm))>; - - -//===----------------------------------------------------------------------===// -// VINSERTI128 - Insert packed integer values -// -let hasSideEffects = 0 in { -def VINSERTI128rr : AVX2AIi8<0x38, MRMSrcReg, (outs VR256:$dst), - (ins VR256:$src1, VR128:$src2, u8imm:$src3), - "vinserti128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteShuffle256]>, VEX_4V, VEX_L; -let mayLoad = 1 in -def VINSERTI128rm : AVX2AIi8<0x38, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, i128mem:$src2, u8imm:$src3), - "vinserti128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - []>, Sched<[WriteShuffle256Ld, ReadAfterLd]>, VEX_4V, VEX_L; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm : vinsert_lowering<"VINSERTI128", v2i64, v4i64, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v4i32, v8i32, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v8i16, v16i16, loadv2i64>; - defm : vinsert_lowering<"VINSERTI128", v16i8, v32i8, loadv2i64>; -} - -//===----------------------------------------------------------------------===// -// VEXTRACTI128 - Extract packed integer values -// -def VEXTRACTI128rr : AVX2AIi8<0x39, MRMDestReg, (outs VR128:$dst), - (ins VR256:$src1, u8imm:$src2), - "vextracti128\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[WriteShuffle256]>, VEX, VEX_L; -let hasSideEffects = 0, mayStore = 1 in -def VEXTRACTI128mr : AVX2AIi8<0x39, MRMDestMem, (outs), - (ins i128mem:$dst, VR256:$src1, u8imm:$src2), - "vextracti128\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, - Sched<[SchedWriteVecMoveLS.XMM.MR]>, VEX, VEX_L; - -let Predicates = [HasAVX2, NoVLX] in { - defm : vextract_lowering<"VEXTRACTI128", v4i64, v2i64>; - defm : vextract_lowering<"VEXTRACTI128", v8i32, v4i32>; - defm : vextract_lowering<"VEXTRACTI128", v16i16, v8i16>; - defm : vextract_lowering<"VEXTRACTI128", v32i8, v16i8>; -} - -//===----------------------------------------------------------------------===// -// VPMASKMOV - Conditional SIMD Integer Packed Loads and Stores -// -multiclass avx2_pmovmask { - def rm : AVX28I<0x8c, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, i128mem:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR128:$dst, (IntLd128 addr:$src2, VR128:$src1))]>, - VEX_4V, Sched<[WriteVecMaskedLoad]>; - def Yrm : AVX28I<0x8c, MRMSrcMem, (outs VR256:$dst), - (ins VR256:$src1, i256mem:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(set VR256:$dst, (IntLd256 addr:$src2, VR256:$src1))]>, - VEX_4V, VEX_L, Sched<[WriteVecMaskedLoadY]>; - def mr : AVX28I<0x8e, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src1, VR128:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(IntSt128 addr:$dst, VR128:$src1, VR128:$src2)]>, - VEX_4V, Sched<[WriteVecMaskedStore]>; - def Ymr : AVX28I<0x8e, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src1, VR256:$src2), - !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - [(IntSt256 addr:$dst, VR256:$src1, VR256:$src2)]>, - VEX_4V, VEX_L, Sched<[WriteVecMaskedStoreY]>; -} - -defm VPMASKMOVD : avx2_pmovmask<"vpmaskmovd", - int_x86_avx2_maskload_d, - int_x86_avx2_maskload_d_256, - int_x86_avx2_maskstore_d, - int_x86_avx2_maskstore_d_256>; -defm VPMASKMOVQ : avx2_pmovmask<"vpmaskmovq", - int_x86_avx2_maskload_q, - int_x86_avx2_maskload_q_256, - int_x86_avx2_maskstore_q, - int_x86_avx2_maskstore_q_256>, VEX_W; - -multiclass maskmov_lowering { - // masked store - def: Pat<(X86mstore addr:$ptr, (MaskVT RC:$mask), (VT RC:$src)), - (!cast(InstrStr#"mr") addr:$ptr, RC:$mask, RC:$src)>; - // masked load - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), undef)), - (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)>; - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), - (VT (bitconvert (ZeroVT immAllZerosV))))), - (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)>; - def: Pat<(VT (X86mload addr:$ptr, (MaskVT RC:$mask), (VT RC:$src0))), - (!cast(BlendStr#"rr") - RC:$src0, - (VT (!cast(InstrStr#"rm") RC:$mask, addr:$ptr)), - RC:$mask)>; -} -let Predicates = [HasAVX] in { - defm : maskmov_lowering<"VMASKMOVPS", VR128, v4f32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VMASKMOVPD", VR128, v2f64, v2i64, "VBLENDVPD", v4i32>; - defm : maskmov_lowering<"VMASKMOVPSY", VR256, v8f32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPDY", VR256, v4f64, v4i64, "VBLENDVPDY", v8i32>; -} -let Predicates = [HasAVX1Only] in { - // load/store i32/i64 not supported use ps/pd version - defm : maskmov_lowering<"VMASKMOVPSY", VR256, v8i32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPDY", VR256, v4i64, v4i64, "VBLENDVPDY", v8i32>; - defm : maskmov_lowering<"VMASKMOVPS", VR128, v4i32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VMASKMOVPD", VR128, v2i64, v2i64, "VBLENDVPD", v4i32>; -} -let Predicates = [HasAVX2] in { - defm : maskmov_lowering<"VPMASKMOVDY", VR256, v8i32, v8i32, "VBLENDVPSY", v8i32>; - defm : maskmov_lowering<"VPMASKMOVQY", VR256, v4i64, v4i64, "VBLENDVPDY", v8i32>; - defm : maskmov_lowering<"VPMASKMOVD", VR128, v4i32, v4i32, "VBLENDVPS", v4i32>; - defm : maskmov_lowering<"VPMASKMOVQ", VR128, v2i64, v2i64, "VBLENDVPD", v4i32>; -} - -//===----------------------------------------------------------------------===// -// SubVector Broadcasts -// Provide fallback in case the load node that is used in the patterns above -// is used by additional users, which prevents the pattern selection. - -let Predicates = [HasAVX2, NoVLX] in { -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2i64 VR128:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4i32 VR128:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v8i16 VR128:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128:$src))), - (VINSERTI128rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v16i8 VR128:$src), 1)>; -} - -let Predicates = [HasAVX, NoVLX] in { -def : Pat<(v4f64 (X86SubVBroadcast (v2f64 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2f64 VR128:$src), 1)>; -def : Pat<(v8f32 (X86SubVBroadcast (v4f32 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4f32 VR128:$src), 1)>; -} - -let Predicates = [HasAVX1Only] in { -def : Pat<(v4i64 (X86SubVBroadcast (v2i64 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v2i64 VR128:$src), 1)>; -def : Pat<(v8i32 (X86SubVBroadcast (v4i32 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v4i32 VR128:$src), 1)>; -def : Pat<(v16i16 (X86SubVBroadcast (v8i16 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v8i16 VR128:$src), 1)>; -def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128:$src))), - (VINSERTF128rr (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128:$src, sub_xmm), - (v16i8 VR128:$src), 1)>; -} - -//===----------------------------------------------------------------------===// -// Variable Bit Shifts -// -multiclass avx2_var_shift opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, ValueType vt256> { - def rr : AVX28I, - VEX_4V, Sched<[SchedWriteVarVecShift.XMM]>; - def rm : AVX28I, - VEX_4V, Sched<[SchedWriteVarVecShift.XMM.Folded, ReadAfterLd]>; - def Yrr : AVX28I, - VEX_4V, VEX_L, Sched<[SchedWriteVarVecShift.YMM]>; - def Yrm : AVX28I, - VEX_4V, VEX_L, Sched<[SchedWriteVarVecShift.YMM.Folded, ReadAfterLd]>; -} - -let Predicates = [HasAVX2, NoVLX] in { - defm VPSLLVD : avx2_var_shift<0x47, "vpsllvd", shl, v4i32, v8i32>; - defm VPSLLVQ : avx2_var_shift<0x47, "vpsllvq", shl, v2i64, v4i64>, VEX_W; - defm VPSRLVD : avx2_var_shift<0x45, "vpsrlvd", srl, v4i32, v8i32>; - defm VPSRLVQ : avx2_var_shift<0x45, "vpsrlvq", srl, v2i64, v4i64>, VEX_W; - defm VPSRAVD : avx2_var_shift<0x46, "vpsravd", sra, v4i32, v8i32>; - - def : Pat<(v4i32 (X86vsrav VR128:$src1, VR128:$src2)), - (VPSRAVDrr VR128:$src1, VR128:$src2)>; - def : Pat<(v4i32 (X86vsrav VR128:$src1, - (bitconvert (loadv2i64 addr:$src2)))), - (VPSRAVDrm VR128:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, VR256:$src2)), - (VPSRAVDYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, - (bitconvert (loadv4i64 addr:$src2)))), - (VPSRAVDYrm VR256:$src1, addr:$src2)>; -} - -//===----------------------------------------------------------------------===// -// VGATHER - GATHER Operations - -// FIXME: Improve scheduling of gather instructions. -multiclass avx2_gather opc, string OpcodeStr, ValueType VTx, - ValueType VTy, PatFrag GatherNode128, - PatFrag GatherNode256, RegisterClass RC256, - X86MemOperand memop128, X86MemOperand memop256, - ValueType MTx = VTx, ValueType MTy = VTy> { - def rm : AVX28I, - VEX, Sched<[WriteLoad]>; - def Yrm : AVX28I, - VEX, VEX_L, Sched<[WriteLoad]>; -} - -let Predicates = [UseAVX2] in { - let mayLoad = 1, hasSideEffects = 0, Constraints - = "@earlyclobber $dst,@earlyclobber $mask_wb, $src1 = $dst, $mask = $mask_wb" - in { - defm VPGATHERDQ : avx2_gather<0x90, "vpgatherdq", v2i64, v4i64, mgatherv4i32, - mgatherv4i32, VR256, vx128mem, vx256mem>, VEX_W; - defm VPGATHERQQ : avx2_gather<0x91, "vpgatherqq", v2i64, v4i64, mgatherv2i64, - mgatherv4i64, VR256, vx128mem, vy256mem>, VEX_W; - defm VPGATHERDD : avx2_gather<0x90, "vpgatherdd", v4i32, v8i32, mgatherv4i32, - mgatherv8i32, VR256, vx128mem, vy256mem>; - defm VPGATHERQD : avx2_gather<0x91, "vpgatherqd", v4i32, v4i32, mgatherv2i64, - mgatherv4i64, VR128, vx64mem, vy128mem>; - - let ExeDomain = SSEPackedDouble in { - defm VGATHERDPD : avx2_gather<0x92, "vgatherdpd", v2f64, v4f64, mgatherv4i32, - mgatherv4i32, VR256, vx128mem, vx256mem, - v2i64, v4i64>, VEX_W; - defm VGATHERQPD : avx2_gather<0x93, "vgatherqpd", v2f64, v4f64, mgatherv2i64, - mgatherv4i64, VR256, vx128mem, vy256mem, - v2i64, v4i64>, VEX_W; - } - - let ExeDomain = SSEPackedSingle in { - defm VGATHERDPS : avx2_gather<0x92, "vgatherdps", v4f32, v8f32, mgatherv4i32, - mgatherv8i32, VR256, vx128mem, vy256mem, - v4i32, v8i32>; - defm VGATHERQPS : avx2_gather<0x93, "vgatherqps", v4f32, v4f32, mgatherv2i64, - mgatherv4i64, VR128, vx64mem, vy128mem, - v4i32, v4i32>; - } - } -} - -//===----------------------------------------------------------------------===// -// Extra selection patterns for f128, f128mem - -// movaps is shorter than movdqa. movaps is in SSE and movdqa is in SSE2. -def : Pat<(alignedstore (f128 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, (COPY_TO_REGCLASS (f128 VR128:$src), VR128))>; -def : Pat<(store (f128 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, (COPY_TO_REGCLASS (f128 VR128:$src), VR128))>; - -def : Pat<(alignedloadf128 addr:$src), - (COPY_TO_REGCLASS (MOVAPSrm addr:$src), VR128)>; -def : Pat<(loadf128 addr:$src), - (COPY_TO_REGCLASS (MOVUPSrm addr:$src), VR128)>; - -// andps is shorter than andpd or pand. andps is SSE and andpd/pand are in SSE2 -def : Pat<(f128 (X86fand VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (ANDPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86fand VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (ANDPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -def : Pat<(f128 (X86for VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (ORPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86for VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (ORPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -def : Pat<(f128 (X86fxor VR128:$src1, (memopf128 addr:$src2))), - (COPY_TO_REGCLASS - (XORPSrm (COPY_TO_REGCLASS VR128:$src1, VR128), f128mem:$src2), - VR128)>; - -def : Pat<(f128 (X86fxor VR128:$src1, VR128:$src2)), - (COPY_TO_REGCLASS - (XORPSrr (COPY_TO_REGCLASS VR128:$src1, VR128), - (COPY_TO_REGCLASS VR128:$src2, VR128)), VR128)>; - -//===----------------------------------------------------------------------===// -// GFNI instructions -//===----------------------------------------------------------------------===// - -multiclass GF2P8MULB_rm { - let ExeDomain = SSEPackedInt, - AsmString = !if(Is2Addr, - OpcodeStr##"\t{$src2, $dst|$dst, $src2}", - OpcodeStr##"\t{$src2, $src1, $dst|$dst, $src1, $src2}") in { - let isCommutable = 1 in - def rr : PDI<0xCF, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), "", - [(set RC:$dst, (OpVT (X86GF2P8mulb RC:$src1, RC:$src2)))]>, - Sched<[SchedWriteVecALU.XMM]>, T8PD; - - def rm : PDI<0xCF, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, X86MemOp:$src2), "", - [(set RC:$dst, (OpVT (X86GF2P8mulb RC:$src1, - (bitconvert (MemOpFrag addr:$src2)))))]>, - Sched<[SchedWriteVecALU.XMM.Folded, ReadAfterLd]>, T8PD; - } -} - -multiclass GF2P8AFFINE_rmi Op, string OpStr, ValueType OpVT, - SDNode OpNode, RegisterClass RC, PatFrag MemOpFrag, - X86MemOperand X86MemOp, bit Is2Addr = 0> { - let AsmString = !if(Is2Addr, - OpStr##"\t{$src3, $src2, $dst|$dst, $src2, $src3}", - OpStr##"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}") in { - def rri : Ii8, Sched<[SchedWriteVecALU.XMM]>; - def rmi : Ii8, - Sched<[SchedWriteVecALU.XMM.Folded, ReadAfterLd]>; - } -} - -multiclass GF2P8AFFINE_common Op, string OpStr, SDNode OpNode> { - let Constraints = "$src1 = $dst", - Predicates = [HasGFNI, UseSSE2] in - defm NAME : GF2P8AFFINE_rmi; - let Predicates = [HasGFNI, HasAVX, NoVLX_Or_NoBWI] in { - defm V##NAME : GF2P8AFFINE_rmi, VEX_4V, VEX_W; - defm V##NAME##Y : GF2P8AFFINE_rmi, VEX_4V, VEX_L, VEX_W; - } -} - -// GF2P8MULB -let Constraints = "$src1 = $dst", - Predicates = [HasGFNI, UseSSE2] in -defm GF2P8MULB : GF2P8MULB_rm<"gf2p8mulb", v16i8, VR128, memopv2i64, - i128mem, 1>; -let Predicates = [HasGFNI, HasAVX, NoVLX_Or_NoBWI] in { - defm VGF2P8MULB : GF2P8MULB_rm<"vgf2p8mulb", v16i8, VR128, loadv2i64, - i128mem>, VEX_4V; - defm VGF2P8MULBY : GF2P8MULB_rm<"vgf2p8mulb", v32i8, VR256, loadv4i64, - i256mem>, VEX_4V, VEX_L; -} -// GF2P8AFFINEINVQB, GF2P8AFFINEQB -let isCommutable = 0 in { - defm GF2P8AFFINEINVQB : GF2P8AFFINE_common<0xCF, "gf2p8affineinvqb", - X86GF2P8affineinvqb>, TAPD; - defm GF2P8AFFINEQB : GF2P8AFFINE_common<0xCE, "gf2p8affineqb", - X86GF2P8affineqb>, TAPD; -} - diff --git a/suite/synctools/tablegen/X86/back/X86InstrSVM.td b/suite/synctools/tablegen/X86/back/X86InstrSVM.td deleted file mode 100644 index 2dc6e8b436..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrSVM.td +++ /dev/null @@ -1,63 +0,0 @@ -//===-- X86InstrSVM.td - SVM Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the AMD SVM instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SVM instructions - -let SchedRW = [WriteSystem] in { -// 0F 01 D9 -def VMMCALL : I<0x01, MRM_D9, (outs), (ins), "vmmcall", []>, TB; - -// 0F 01 DC -def STGI : I<0x01, MRM_DC, (outs), (ins), "stgi", []>, TB; - -// 0F 01 DD -def CLGI : I<0x01, MRM_DD, (outs), (ins), "clgi", []>, TB; - -// 0F 01 DE -let Uses = [EAX] in -def SKINIT : I<0x01, MRM_DE, (outs), (ins), "skinit\t{%eax|eax}", []>, TB; - -// 0F 01 D8 -let Uses = [EAX] in -def VMRUN32 : I<0x01, MRM_D8, (outs), (ins), "vmrun\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMRUN64 : I<0x01, MRM_D8, (outs), (ins), "vmrun\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DA -let Uses = [EAX] in -def VMLOAD32 : I<0x01, MRM_DA, (outs), (ins), "vmload\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMLOAD64 : I<0x01, MRM_DA, (outs), (ins), "vmload\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DB -let Uses = [EAX] in -def VMSAVE32 : I<0x01, MRM_DB, (outs), (ins), "vmsave\t{%eax|eax}", []>, TB, - Requires<[Not64BitMode]>; -let Uses = [RAX] in -def VMSAVE64 : I<0x01, MRM_DB, (outs), (ins), "vmsave\t{%rax|rax}", []>, TB, - Requires<[In64BitMode]>; - -// 0F 01 DF -let Uses = [EAX, ECX] in -def INVLPGA32 : I<0x01, MRM_DF, (outs), (ins), - "invlpga\t{%eax, %ecx|eax, ecx}", []>, TB, Requires<[Not64BitMode]>; -let Uses = [RAX, ECX] in -def INVLPGA64 : I<0x01, MRM_DF, (outs), (ins), - "invlpga\t{%rax, %ecx|rax, ecx}", []>, TB, Requires<[In64BitMode]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrShiftRotate.td b/suite/synctools/tablegen/X86/back/X86InstrShiftRotate.td deleted file mode 100644 index cbcb1f7f7b..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrShiftRotate.td +++ /dev/null @@ -1,1031 +0,0 @@ -//===-- X86InstrShiftRotate.td - Shift and Rotate Instrs ---*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the shift and rotate instructions. -// -//===----------------------------------------------------------------------===// - -// FIXME: Someone needs to smear multipattern goodness all over this file. - -let Defs = [EFLAGS] in { - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SHL8rCL : I<0xD2, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1), - "shl{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (shl GR8:$src1, CL))]>; -def SHL16rCL : I<0xD3, MRM4r, (outs GR16:$dst), (ins GR16:$src1), - "shl{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (shl GR16:$src1, CL))]>, OpSize16; -def SHL32rCL : I<0xD3, MRM4r, (outs GR32:$dst), (ins GR32:$src1), - "shl{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (shl GR32:$src1, CL))]>, OpSize32; -def SHL64rCL : RI<0xD3, MRM4r, (outs GR64:$dst), (ins GR64:$src1), - "shl{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (shl GR64:$src1, CL))]>; -} // Uses = [CL] - -def SAL8rCL : I<0xD2, MRM6r, (outs GR8 :$dst), (ins GR8 :$src1), "sal{b}\t{%cl, $dst|$dst, cl}", []>; -def SAL16rCL : I<0xD3, MRM6r, (outs GR16:$dst), (ins GR16:$src1), - "sal{w}\t{%cl, $dst|$dst, cl}", - []>, OpSize16; -def SAL32rCL : I<0xD3, MRM6r, (outs GR32:$dst), (ins GR32:$src1), - "sal{l}\t{%cl, $dst|$dst, cl}", - []>, OpSize32; -def SAL64rCL : RI<0xD3, MRM6r, (outs GR64:$dst), (ins GR64:$src1), - "sal{q}\t{%cl, $dst|$dst, cl}", - []>; - -def SHL8ri : Ii8<0xC0, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "shl{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (shl GR8:$src1, (i8 imm:$src2)))]>; - -def SAL8ri : Ii8<0xC0, MRM6r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), - "sal{b}\t{$src2, $dst|$dst, $src2}", - []>; - -let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. -def SHL16ri : Ii8<0xC1, MRM4r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "shl{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (shl GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SHL32ri : Ii8<0xC1, MRM4r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "shl{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SHL64ri : RIi8<0xC1, MRM4r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "shl{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (shl GR64:$src1, (i8 imm:$src2)))]>; - -def SAL16ri : Ii8<0xC1, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), - "sal{w}\t{$src2, $dst|$dst, $src2}", - []>, - OpSize16; -def SAL32ri : Ii8<0xC1, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), - "sal{l}\t{$src2, $dst|$dst, $src2}", - []>, - OpSize32; -def SAL64ri : RIi8<0xC1, MRM6r, (outs GR64:$dst), - (ins GR64:$src1, i8imm:$src2), - "sal{q}\t{$src2, $dst|$dst, $src2}", - []>; -} // isConvertibleToThreeAddress = 1 - -// NOTE: We don't include patterns for shifts of a register by one, because -// 'add reg,reg' is cheaper (and we have a Pat pattern for shift-by-one). -let hasSideEffects = 0 in { -def SHL8r1 : I<0xD0, MRM4r, (outs GR8:$dst), (ins GR8:$src1), - "shl{b}\t{$$1, $dst|$dst, 1}", []>; -def SHL16r1 : I<0xD1, MRM4r, (outs GR16:$dst), (ins GR16:$src1), - "shl{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def SHL32r1 : I<0xD1, MRM4r, (outs GR32:$dst), (ins GR32:$src1), - "shl{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def SHL64r1 : RI<0xD1, MRM4r, (outs GR64:$dst), (ins GR64:$src1), - "shl{q}\t{$$1, $dst|$dst, 1}", []>; -def SAL8r1 : I<0xD0, MRM6r, (outs GR8:$dst), (ins GR8:$src1), - "sal{b}\t{$$1, $dst|$dst, 1}", []>; -def SAL16r1 : I<0xD1, MRM6r, (outs GR16:$dst), (ins GR16:$src1), - "sal{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def SAL32r1 : I<0xD1, MRM6r, (outs GR32:$dst), (ins GR32:$src1), - "sal{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def SAL64r1 : RI<0xD1, MRM6r, (outs GR64:$dst), (ins GR64:$src1), - "sal{q}\t{$$1, $dst|$dst, 1}", []>; -} // hasSideEffects = 0 -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -// FIXME: Why do we need an explicit "Uses = [CL]" when the instr has a pattern -// using CL? -let Uses = [CL] in { -def SHL8mCL : I<0xD2, MRM4m, (outs), (ins i8mem :$dst), - "shl{b}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi8 addr:$dst), CL), addr:$dst)]>; -def SHL16mCL : I<0xD3, MRM4m, (outs), (ins i16mem:$dst), - "shl{w}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SHL32mCL : I<0xD3, MRM4m, (outs), (ins i32mem:$dst), - "shl{l}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SHL64mCL : RI<0xD3, MRM4m, (outs), (ins i64mem:$dst), - "shl{q}\t{%cl, $dst|$dst, cl}", - [(store (shl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8mCL : I<0xD2, MRM6m, (outs), (ins i8mem :$dst), - "sal{b}\t{%cl, $dst|$dst, cl}", - []>; -def SAL16mCL : I<0xD3, MRM6m, (outs), (ins i16mem:$dst), - "sal{w}\t{%cl, $dst|$dst, cl}", - []>, - OpSize16; -def SAL32mCL : I<0xD3, MRM6m, (outs), (ins i32mem:$dst), - "sal{l}\t{%cl, $dst|$dst, cl}", - []>, - OpSize32; -def SAL64mCL : RI<0xD3, MRM6m, (outs), (ins i64mem:$dst), - "sal{q}\t{%cl, $dst|$dst, cl}", - []>; -} -def SHL8mi : Ii8<0xC0, MRM4m, (outs), (ins i8mem :$dst, u8imm:$src), - "shl{b}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SHL16mi : Ii8<0xC1, MRM4m, (outs), (ins i16mem:$dst, u8imm:$src), - "shl{w}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SHL32mi : Ii8<0xC1, MRM4m, (outs), (ins i32mem:$dst, u8imm:$src), - "shl{l}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SHL64mi : RIi8<0xC1, MRM4m, (outs), (ins i64mem:$dst, u8imm:$src), - "shl{q}\t{$src, $dst|$dst, $src}", - [(store (shl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8mi : Ii8<0xC0, MRM6m, (outs), (ins i8mem :$dst, i8imm:$src), - "sal{b}\t{$src, $dst|$dst, $src}", - []>; -def SAL16mi : Ii8<0xC1, MRM6m, (outs), (ins i16mem:$dst, i8imm:$src), - "sal{w}\t{$src, $dst|$dst, $src}", - []>, OpSize16; -def SAL32mi : Ii8<0xC1, MRM6m, (outs), (ins i32mem:$dst, i8imm:$src), - "sal{l}\t{$src, $dst|$dst, $src}", - []>, OpSize32; -def SAL64mi : RIi8<0xC1, MRM6m, (outs), (ins i64mem:$dst, i8imm:$src), - "sal{q}\t{$src, $dst|$dst, $src}", - []>; - -// Shift by 1 -def SHL8m1 : I<0xD0, MRM4m, (outs), (ins i8mem :$dst), - "shl{b}\t{$dst|$dst, 1}", - [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SHL16m1 : I<0xD1, MRM4m, (outs), (ins i16mem:$dst), - "shl{w}\t{$dst|$dst, 1}", - [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SHL32m1 : I<0xD1, MRM4m, (outs), (ins i32mem:$dst), - "shl{l}\t{$dst|$dst, 1}", - [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SHL64m1 : RI<0xD1, MRM4m, (outs), (ins i64mem:$dst), - "shl{q}\t{$dst|$dst, 1}", - [(store (shl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -def SAL8m1 : I<0xD0, MRM6m, (outs), (ins i8mem :$dst), - "sal{b}\t{$dst|$dst, 1}", - []>; -def SAL16m1 : I<0xD1, MRM6m, (outs), (ins i16mem:$dst), - "sal{w}\t{$dst|$dst, 1}", - []>, OpSize16; -def SAL32m1 : I<0xD1, MRM6m, (outs), (ins i32mem:$dst), - "sal{l}\t{$dst|$dst, 1}", - []>, OpSize32; -def SAL64m1 : RI<0xD1, MRM6m, (outs), (ins i64mem:$dst), - "sal{q}\t{$dst|$dst, 1}", - []>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SHR8rCL : I<0xD2, MRM5r, (outs GR8 :$dst), (ins GR8 :$src1), - "shr{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (srl GR8:$src1, CL))]>; -def SHR16rCL : I<0xD3, MRM5r, (outs GR16:$dst), (ins GR16:$src1), - "shr{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (srl GR16:$src1, CL))]>, OpSize16; -def SHR32rCL : I<0xD3, MRM5r, (outs GR32:$dst), (ins GR32:$src1), - "shr{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (srl GR32:$src1, CL))]>, OpSize32; -def SHR64rCL : RI<0xD3, MRM5r, (outs GR64:$dst), (ins GR64:$src1), - "shr{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (srl GR64:$src1, CL))]>; -} - -def SHR8ri : Ii8<0xC0, MRM5r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$src2), - "shr{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (srl GR8:$src1, (i8 imm:$src2)))]>; -def SHR16ri : Ii8<0xC1, MRM5r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "shr{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (srl GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SHR32ri : Ii8<0xC1, MRM5r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "shr{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SHR64ri : RIi8<0xC1, MRM5r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$src2), - "shr{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (srl GR64:$src1, (i8 imm:$src2)))]>; - -// Shift right by 1 -def SHR8r1 : I<0xD0, MRM5r, (outs GR8:$dst), (ins GR8:$src1), - "shr{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>; -def SHR16r1 : I<0xD1, MRM5r, (outs GR16:$dst), (ins GR16:$src1), - "shr{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize16; -def SHR32r1 : I<0xD1, MRM5r, (outs GR32:$dst), (ins GR32:$src1), - "shr{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>, OpSize32; -def SHR64r1 : RI<0xD1, MRM5r, (outs GR64:$dst), (ins GR64:$src1), - "shr{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (srl GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def SHR8mCL : I<0xD2, MRM5m, (outs), (ins i8mem :$dst), - "shr{b}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi8 addr:$dst), CL), addr:$dst)]>; -def SHR16mCL : I<0xD3, MRM5m, (outs), (ins i16mem:$dst), - "shr{w}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SHR32mCL : I<0xD3, MRM5m, (outs), (ins i32mem:$dst), - "shr{l}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SHR64mCL : RI<0xD3, MRM5m, (outs), (ins i64mem:$dst), - "shr{q}\t{%cl, $dst|$dst, cl}", - [(store (srl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def SHR8mi : Ii8<0xC0, MRM5m, (outs), (ins i8mem :$dst, u8imm:$src), - "shr{b}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SHR16mi : Ii8<0xC1, MRM5m, (outs), (ins i16mem:$dst, u8imm:$src), - "shr{w}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SHR32mi : Ii8<0xC1, MRM5m, (outs), (ins i32mem:$dst, u8imm:$src), - "shr{l}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SHR64mi : RIi8<0xC1, MRM5m, (outs), (ins i64mem:$dst, u8imm:$src), - "shr{q}\t{$src, $dst|$dst, $src}", - [(store (srl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Shift by 1 -def SHR8m1 : I<0xD0, MRM5m, (outs), (ins i8mem :$dst), - "shr{b}\t{$dst|$dst, 1}", - [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SHR16m1 : I<0xD1, MRM5m, (outs), (ins i16mem:$dst), - "shr{w}\t{$dst|$dst, 1}", - [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SHR32m1 : I<0xD1, MRM5m, (outs), (ins i32mem:$dst), - "shr{l}\t{$dst|$dst, 1}", - [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SHR64m1 : RI<0xD1, MRM5m, (outs), (ins i64mem:$dst), - "shr{q}\t{$dst|$dst, 1}", - [(store (srl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def SAR8rCL : I<0xD2, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1), - "sar{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (sra GR8:$src1, CL))]>; -def SAR16rCL : I<0xD3, MRM7r, (outs GR16:$dst), (ins GR16:$src1), - "sar{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (sra GR16:$src1, CL))]>, - OpSize16; -def SAR32rCL : I<0xD3, MRM7r, (outs GR32:$dst), (ins GR32:$src1), - "sar{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (sra GR32:$src1, CL))]>, - OpSize32; -def SAR64rCL : RI<0xD3, MRM7r, (outs GR64:$dst), (ins GR64:$src1), - "sar{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (sra GR64:$src1, CL))]>; -} - -def SAR8ri : Ii8<0xC0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "sar{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (sra GR8:$src1, (i8 imm:$src2)))]>; -def SAR16ri : Ii8<0xC1, MRM7r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "sar{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (sra GR16:$src1, (i8 imm:$src2)))]>, - OpSize16; -def SAR32ri : Ii8<0xC1, MRM7r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "sar{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>, - OpSize32; -def SAR64ri : RIi8<0xC1, MRM7r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "sar{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (sra GR64:$src1, (i8 imm:$src2)))]>; - -// Shift by 1 -def SAR8r1 : I<0xD0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1), - "sar{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>; -def SAR16r1 : I<0xD1, MRM7r, (outs GR16:$dst), (ins GR16:$src1), - "sar{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize16; -def SAR32r1 : I<0xD1, MRM7r, (outs GR32:$dst), (ins GR32:$src1), - "sar{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>, OpSize32; -def SAR64r1 : RI<0xD1, MRM7r, (outs GR64:$dst), (ins GR64:$src1), - "sar{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (sra GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def SAR8mCL : I<0xD2, MRM7m, (outs), (ins i8mem :$dst), - "sar{b}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi8 addr:$dst), CL), addr:$dst)]>; -def SAR16mCL : I<0xD3, MRM7m, (outs), (ins i16mem:$dst), - "sar{w}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi16 addr:$dst), CL), addr:$dst)]>, - OpSize16; -def SAR32mCL : I<0xD3, MRM7m, (outs), (ins i32mem:$dst), - "sar{l}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi32 addr:$dst), CL), addr:$dst)]>, - OpSize32; -def SAR64mCL : RI<0xD3, MRM7m, (outs), (ins i64mem:$dst), - "sar{q}\t{%cl, $dst|$dst, cl}", - [(store (sra (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def SAR8mi : Ii8<0xC0, MRM7m, (outs), (ins i8mem :$dst, u8imm:$src), - "sar{b}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def SAR16mi : Ii8<0xC1, MRM7m, (outs), (ins i16mem:$dst, u8imm:$src), - "sar{w}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def SAR32mi : Ii8<0xC1, MRM7m, (outs), (ins i32mem:$dst, u8imm:$src), - "sar{l}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def SAR64mi : RIi8<0xC1, MRM7m, (outs), (ins i64mem:$dst, u8imm:$src), - "sar{q}\t{$src, $dst|$dst, $src}", - [(store (sra (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Shift by 1 -def SAR8m1 : I<0xD0, MRM7m, (outs), (ins i8mem :$dst), - "sar{b}\t{$dst|$dst, 1}", - [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def SAR16m1 : I<0xD1, MRM7m, (outs), (ins i16mem:$dst), - "sar{w}\t{$dst|$dst, 1}", - [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def SAR32m1 : I<0xD1, MRM7m, (outs), (ins i32mem:$dst), - "sar{l}\t{$dst|$dst, 1}", - [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def SAR64m1 : RI<0xD1, MRM7m, (outs), (ins i64mem:$dst), - "sar{q}\t{$dst|$dst, 1}", - [(store (sra (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Rotate instructions -//===----------------------------------------------------------------------===// - -let hasSideEffects = 0 in { -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { - -let Uses = [CL, EFLAGS] in { -def RCL8rCL : I<0xD2, MRM2r, (outs GR8:$dst), (ins GR8:$src1), - "rcl{b}\t{%cl, $dst|$dst, cl}", []>; -def RCL16rCL : I<0xD3, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCL32rCL : I<0xD3, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src1), - "rcl{q}\t{%cl, $dst|$dst, cl}", []>; -} // Uses = [CL, EFLAGS] - -let Uses = [EFLAGS] in { -def RCL8r1 : I<0xD0, MRM2r, (outs GR8:$dst), (ins GR8:$src1), - "rcl{b}\t{$$1, $dst|$dst, 1}", []>; -def RCL8ri : Ii8<0xC0, MRM2r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt), - "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL16r1 : I<0xD1, MRM2r, (outs GR16:$dst), (ins GR16:$src1), - "rcl{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def RCL16ri : Ii8<0xC1, MRM2r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt), - "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCL32r1 : I<0xD1, MRM2r, (outs GR32:$dst), (ins GR32:$src1), - "rcl{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def RCL32ri : Ii8<0xC1, MRM2r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt), - "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCL64r1 : RI<0xD1, MRM2r, (outs GR64:$dst), (ins GR64:$src1), - "rcl{q}\t{$$1, $dst|$dst, 1}", []>; -def RCL64ri : RIi8<0xC1, MRM2r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt), - "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; -} // Uses = [EFLAGS] - -let Uses = [CL, EFLAGS] in { -def RCR8rCL : I<0xD2, MRM3r, (outs GR8:$dst), (ins GR8:$src1), - "rcr{b}\t{%cl, $dst|$dst, cl}", []>; -def RCR16rCL : I<0xD3, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCR32rCL : I<0xD3, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCR64rCL : RI<0xD3, MRM3r, (outs GR64:$dst), (ins GR64:$src1), - "rcr{q}\t{%cl, $dst|$dst, cl}", []>; -} // Uses = [CL, EFLAGS] - -let Uses = [EFLAGS] in { -def RCR8r1 : I<0xD0, MRM3r, (outs GR8:$dst), (ins GR8:$src1), - "rcr{b}\t{$$1, $dst|$dst, 1}", []>; -def RCR8ri : Ii8<0xC0, MRM3r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt), - "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR16r1 : I<0xD1, MRM3r, (outs GR16:$dst), (ins GR16:$src1), - "rcr{w}\t{$$1, $dst|$dst, 1}", []>, OpSize16; -def RCR16ri : Ii8<0xC1, MRM3r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt), - "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCR32r1 : I<0xD1, MRM3r, (outs GR32:$dst), (ins GR32:$src1), - "rcr{l}\t{$$1, $dst|$dst, 1}", []>, OpSize32; -def RCR32ri : Ii8<0xC1, MRM3r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt), - "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCR64r1 : RI<0xD1, MRM3r, (outs GR64:$dst), (ins GR64:$src1), - "rcr{q}\t{$$1, $dst|$dst, 1}", []>; -def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt), - "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; -} // Uses = [EFLAGS] - -} // Constraints = "$src = $dst" - -let SchedRW = [WriteShiftLd, WriteRMW], mayStore = 1 in { -let Uses = [EFLAGS] in { -def RCL8m1 : I<0xD0, MRM2m, (outs), (ins i8mem:$dst), - "rcl{b}\t$dst", []>; -def RCL8mi : Ii8<0xC0, MRM2m, (outs), (ins i8mem:$dst, u8imm:$cnt), - "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL16m1 : I<0xD1, MRM2m, (outs), (ins i16mem:$dst), - "rcl{w}\t$dst", []>, OpSize16; -def RCL16mi : Ii8<0xC1, MRM2m, (outs), (ins i16mem:$dst, u8imm:$cnt), - "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCL32m1 : I<0xD1, MRM2m, (outs), (ins i32mem:$dst), - "rcl{l}\t$dst", []>, OpSize32; -def RCL32mi : Ii8<0xC1, MRM2m, (outs), (ins i32mem:$dst, u8imm:$cnt), - "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCL64m1 : RI<0xD1, MRM2m, (outs), (ins i64mem:$dst), - "rcl{q}\t$dst", []>, Requires<[In64BitMode]>; -def RCL64mi : RIi8<0xC1, MRM2m, (outs), (ins i64mem:$dst, u8imm:$cnt), - "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>, - Requires<[In64BitMode]>; - -def RCR8m1 : I<0xD0, MRM3m, (outs), (ins i8mem:$dst), - "rcr{b}\t$dst", []>; -def RCR8mi : Ii8<0xC0, MRM3m, (outs), (ins i8mem:$dst, u8imm:$cnt), - "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR16m1 : I<0xD1, MRM3m, (outs), (ins i16mem:$dst), - "rcr{w}\t$dst", []>, OpSize16; -def RCR16mi : Ii8<0xC1, MRM3m, (outs), (ins i16mem:$dst, u8imm:$cnt), - "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16; -def RCR32m1 : I<0xD1, MRM3m, (outs), (ins i32mem:$dst), - "rcr{l}\t$dst", []>, OpSize32; -def RCR32mi : Ii8<0xC1, MRM3m, (outs), (ins i32mem:$dst, u8imm:$cnt), - "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32; -def RCR64m1 : RI<0xD1, MRM3m, (outs), (ins i64mem:$dst), - "rcr{q}\t$dst", []>, Requires<[In64BitMode]>; -def RCR64mi : RIi8<0xC1, MRM3m, (outs), (ins i64mem:$dst, u8imm:$cnt), - "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>, - Requires<[In64BitMode]>; -} // Uses = [EFLAGS] - -let Uses = [CL, EFLAGS] in { -def RCL8mCL : I<0xD2, MRM2m, (outs), (ins i8mem:$dst), - "rcl{b}\t{%cl, $dst|$dst, cl}", []>; -def RCL16mCL : I<0xD3, MRM2m, (outs), (ins i16mem:$dst), - "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCL32mCL : I<0xD3, MRM2m, (outs), (ins i32mem:$dst), - "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCL64mCL : RI<0xD3, MRM2m, (outs), (ins i64mem:$dst), - "rcl{q}\t{%cl, $dst|$dst, cl}", []>, - Requires<[In64BitMode]>; - -def RCR8mCL : I<0xD2, MRM3m, (outs), (ins i8mem:$dst), - "rcr{b}\t{%cl, $dst|$dst, cl}", []>; -def RCR16mCL : I<0xD3, MRM3m, (outs), (ins i16mem:$dst), - "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16; -def RCR32mCL : I<0xD3, MRM3m, (outs), (ins i32mem:$dst), - "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32; -def RCR64mCL : RI<0xD3, MRM3m, (outs), (ins i64mem:$dst), - "rcr{q}\t{%cl, $dst|$dst, cl}", []>, - Requires<[In64BitMode]>; -} // Uses = [CL, EFLAGS] -} // SchedRW -} // hasSideEffects = 0 - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -// FIXME: provide shorter instructions when imm8 == 1 -let Uses = [CL] in { -def ROL8rCL : I<0xD2, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "rol{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (rotl GR8:$src1, CL))]>; -def ROL16rCL : I<0xD3, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "rol{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (rotl GR16:$src1, CL))]>, OpSize16; -def ROL32rCL : I<0xD3, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "rol{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (rotl GR32:$src1, CL))]>, OpSize32; -def ROL64rCL : RI<0xD3, MRM0r, (outs GR64:$dst), (ins GR64:$src1), - "rol{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (rotl GR64:$src1, CL))]>; -} - -def ROL8ri : Ii8<0xC0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "rol{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 imm:$src2)))]>; -def ROL16ri : Ii8<0xC1, MRM0r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "rol{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 imm:$src2)))]>, OpSize16; -def ROL32ri : Ii8<0xC1, MRM0r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "rol{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>, OpSize32; -def ROL64ri : RIi8<0xC1, MRM0r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "rol{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$src2)))]>; - -// Rotate by 1 -def ROL8r1 : I<0xD0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), - "rol{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>; -def ROL16r1 : I<0xD1, MRM0r, (outs GR16:$dst), (ins GR16:$src1), - "rol{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize16; -def ROL32r1 : I<0xD1, MRM0r, (outs GR32:$dst), (ins GR32:$src1), - "rol{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>, OpSize32; -def ROL64r1 : RI<0xD1, MRM0r, (outs GR64:$dst), (ins GR64:$src1), - "rol{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 1)))]>; -} // Constraints = "$src = $dst", SchedRW - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def ROL8mCL : I<0xD2, MRM0m, (outs), (ins i8mem :$dst), - "rol{b}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi8 addr:$dst), CL), addr:$dst)]>; -def ROL16mCL : I<0xD3, MRM0m, (outs), (ins i16mem:$dst), - "rol{w}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16; -def ROL32mCL : I<0xD3, MRM0m, (outs), (ins i32mem:$dst), - "rol{l}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32; -def ROL64mCL : RI<0xD3, MRM0m, (outs), (ins i64mem:$dst), - "rol{q}\t{%cl, $dst|$dst, cl}", - [(store (rotl (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def ROL8mi : Ii8<0xC0, MRM0m, (outs), (ins i8mem :$dst, u8imm:$src1), - "rol{b}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi8 addr:$dst), (i8 imm:$src1)), addr:$dst)]>; -def ROL16mi : Ii8<0xC1, MRM0m, (outs), (ins i16mem:$dst, u8imm:$src1), - "rol{w}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi16 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - OpSize16; -def ROL32mi : Ii8<0xC1, MRM0m, (outs), (ins i32mem:$dst, u8imm:$src1), - "rol{l}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi32 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - OpSize32; -def ROL64mi : RIi8<0xC1, MRM0m, (outs), (ins i64mem:$dst, u8imm:$src1), - "rol{q}\t{$src1, $dst|$dst, $src1}", - [(store (rotl (loadi64 addr:$dst), (i8 imm:$src1)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Rotate by 1 -def ROL8m1 : I<0xD0, MRM0m, (outs), (ins i8mem :$dst), - "rol{b}\t{$dst|$dst, 1}", - [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; -def ROL16m1 : I<0xD1, MRM0m, (outs), (ins i16mem:$dst), - "rol{w}\t{$dst|$dst, 1}", - [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize16; -def ROL32m1 : I<0xD1, MRM0m, (outs), (ins i32mem:$dst), - "rol{l}\t{$dst|$dst, 1}", - [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>, - OpSize32; -def ROL64m1 : RI<0xD1, MRM0m, (outs), (ins i64mem:$dst), - "rol{q}\t{$dst|$dst, 1}", - [(store (rotl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - -let Constraints = "$src1 = $dst", SchedRW = [WriteShift] in { -let Uses = [CL] in { -def ROR8rCL : I<0xD2, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "ror{b}\t{%cl, $dst|$dst, cl}", - [(set GR8:$dst, (rotr GR8:$src1, CL))]>; -def ROR16rCL : I<0xD3, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "ror{w}\t{%cl, $dst|$dst, cl}", - [(set GR16:$dst, (rotr GR16:$src1, CL))]>, OpSize16; -def ROR32rCL : I<0xD3, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "ror{l}\t{%cl, $dst|$dst, cl}", - [(set GR32:$dst, (rotr GR32:$src1, CL))]>, OpSize32; -def ROR64rCL : RI<0xD3, MRM1r, (outs GR64:$dst), (ins GR64:$src1), - "ror{q}\t{%cl, $dst|$dst, cl}", - [(set GR64:$dst, (rotr GR64:$src1, CL))]>; -} - -def ROR8ri : Ii8<0xC0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2), - "ror{b}\t{$src2, $dst|$dst, $src2}", - [(set GR8:$dst, (rotr GR8:$src1, (i8 relocImm:$src2)))]>; -def ROR16ri : Ii8<0xC1, MRM1r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2), - "ror{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (rotr GR16:$src1, (i8 relocImm:$src2)))]>, - OpSize16; -def ROR32ri : Ii8<0xC1, MRM1r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2), - "ror{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (rotr GR32:$src1, (i8 relocImm:$src2)))]>, - OpSize32; -def ROR64ri : RIi8<0xC1, MRM1r, (outs GR64:$dst), - (ins GR64:$src1, u8imm:$src2), - "ror{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (rotr GR64:$src1, (i8 relocImm:$src2)))]>; - -// Rotate by 1 -def ROR8r1 : I<0xD0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), - "ror{b}\t{$$1, $dst|$dst, 1}", - [(set GR8:$dst, (rotl GR8:$src1, (i8 7)))]>; -def ROR16r1 : I<0xD1, MRM1r, (outs GR16:$dst), (ins GR16:$src1), - "ror{w}\t{$$1, $dst|$dst, 1}", - [(set GR16:$dst, (rotl GR16:$src1, (i8 15)))]>, OpSize16; -def ROR32r1 : I<0xD1, MRM1r, (outs GR32:$dst), (ins GR32:$src1), - "ror{l}\t{$$1, $dst|$dst, 1}", - [(set GR32:$dst, (rotl GR32:$src1, (i8 31)))]>, OpSize32; -def ROR64r1 : RI<0xD1, MRM1r, (outs GR64:$dst), (ins GR64:$src1), - "ror{q}\t{$$1, $dst|$dst, 1}", - [(set GR64:$dst, (rotl GR64:$src1, (i8 63)))]>; -} // Constraints = "$src = $dst", SchedRW - -let SchedRW = [WriteShiftLd, WriteRMW] in { -let Uses = [CL] in { -def ROR8mCL : I<0xD2, MRM1m, (outs), (ins i8mem :$dst), - "ror{b}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi8 addr:$dst), CL), addr:$dst)]>; -def ROR16mCL : I<0xD3, MRM1m, (outs), (ins i16mem:$dst), - "ror{w}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16; -def ROR32mCL : I<0xD3, MRM1m, (outs), (ins i32mem:$dst), - "ror{l}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32; -def ROR64mCL : RI<0xD3, MRM1m, (outs), (ins i64mem:$dst), - "ror{q}\t{%cl, $dst|$dst, cl}", - [(store (rotr (loadi64 addr:$dst), CL), addr:$dst)]>, - Requires<[In64BitMode]>; -} -def ROR8mi : Ii8<0xC0, MRM1m, (outs), (ins i8mem :$dst, u8imm:$src), - "ror{b}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def ROR16mi : Ii8<0xC1, MRM1m, (outs), (ins i16mem:$dst, u8imm:$src), - "ror{w}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize16; -def ROR32mi : Ii8<0xC1, MRM1m, (outs), (ins i32mem:$dst, u8imm:$src), - "ror{l}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - OpSize32; -def ROR64mi : RIi8<0xC1, MRM1m, (outs), (ins i64mem:$dst, u8imm:$src), - "ror{q}\t{$src, $dst|$dst, $src}", - [(store (rotr (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>, - Requires<[In64BitMode]>; - -// Rotate by 1 -def ROR8m1 : I<0xD0, MRM1m, (outs), (ins i8mem :$dst), - "ror{b}\t{$dst|$dst, 1}", - [(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst)]>; -def ROR16m1 : I<0xD1, MRM1m, (outs), (ins i16mem:$dst), - "ror{w}\t{$dst|$dst, 1}", - [(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst)]>, - OpSize16; -def ROR32m1 : I<0xD1, MRM1m, (outs), (ins i32mem:$dst), - "ror{l}\t{$dst|$dst, 1}", - [(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst)]>, - OpSize32; -def ROR64m1 : RI<0xD1, MRM1m, (outs), (ins i64mem:$dst), - "ror{q}\t{$dst|$dst, 1}", - [(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst)]>, - Requires<[In64BitMode]>; -} // SchedRW - - -//===----------------------------------------------------------------------===// -// Double shift instructions (generalizations of rotate) -//===----------------------------------------------------------------------===// - -let Constraints = "$src1 = $dst" in { - -let Uses = [CL], SchedRW = [WriteSHDrrcl] in { -def SHLD16rrCL : I<0xA5, MRMDestReg, (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2), - "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, CL))]>, - TB, OpSize16; -def SHRD16rrCL : I<0xAD, MRMDestReg, (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2), - "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, CL))]>, - TB, OpSize16; -def SHLD32rrCL : I<0xA5, MRMDestReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, CL))]>, - TB, OpSize32; -def SHRD32rrCL : I<0xAD, MRMDestReg, (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2), - "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, CL))]>, - TB, OpSize32; -def SHLD64rrCL : RI<0xA5, MRMDestReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, CL))]>, - TB; -def SHRD64rrCL : RI<0xAD, MRMDestReg, (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2), - "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, CL))]>, - TB; -} // SchedRW - -let isCommutable = 1, SchedRW = [WriteSHDrri] in { // These instructions commute to each other. -def SHLD16rri8 : Ii8<0xA4, MRMDestReg, - (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2, u8imm:$src3), - "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, - (i8 imm:$src3)))]>, - TB, OpSize16; -def SHRD16rri8 : Ii8<0xAC, MRMDestReg, - (outs GR16:$dst), - (ins GR16:$src1, GR16:$src2, u8imm:$src3), - "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, - (i8 imm:$src3)))]>, - TB, OpSize16; -def SHLD32rri8 : Ii8<0xA4, MRMDestReg, - (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2, u8imm:$src3), - "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, - (i8 imm:$src3)))]>, - TB, OpSize32; -def SHRD32rri8 : Ii8<0xAC, MRMDestReg, - (outs GR32:$dst), - (ins GR32:$src1, GR32:$src2, u8imm:$src3), - "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, - (i8 imm:$src3)))]>, - TB, OpSize32; -def SHLD64rri8 : RIi8<0xA4, MRMDestReg, - (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2, u8imm:$src3), - "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, - (i8 imm:$src3)))]>, - TB; -def SHRD64rri8 : RIi8<0xAC, MRMDestReg, - (outs GR64:$dst), - (ins GR64:$src1, GR64:$src2, u8imm:$src3), - "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, - (i8 imm:$src3)))]>, - TB; -} // SchedRW -} // Constraints = "$src = $dst" - -let Uses = [CL], SchedRW = [WriteSHDmrcl] in { -def SHLD16mrCL : I<0xA5, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi16 addr:$dst), GR16:$src2, CL), - addr:$dst)]>, TB, OpSize16; -def SHRD16mrCL : I<0xAD, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), - "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, CL), - addr:$dst)]>, TB, OpSize16; - -def SHLD32mrCL : I<0xA5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi32 addr:$dst), GR32:$src2, CL), - addr:$dst)]>, TB, OpSize32; -def SHRD32mrCL : I<0xAD, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), - "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, CL), - addr:$dst)]>, TB, OpSize32; - -def SHLD64mrCL : RI<0xA5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shld (loadi64 addr:$dst), GR64:$src2, CL), - addr:$dst)]>, TB; -def SHRD64mrCL : RI<0xAD, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), - "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}", - [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, CL), - addr:$dst)]>, TB; -} // SchedRW - -let SchedRW = [WriteSHDmri] in { -def SHLD16mri8 : Ii8<0xA4, MRMDestMem, - (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3), - "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi16 addr:$dst), GR16:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize16; -def SHRD16mri8 : Ii8<0xAC, MRMDestMem, - (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3), - "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize16; - -def SHLD32mri8 : Ii8<0xA4, MRMDestMem, - (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3), - "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi32 addr:$dst), GR32:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize32; -def SHRD32mri8 : Ii8<0xAC, MRMDestMem, - (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3), - "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB, OpSize32; - -def SHLD64mri8 : RIi8<0xA4, MRMDestMem, - (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3), - "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shld (loadi64 addr:$dst), GR64:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB; -def SHRD64mri8 : RIi8<0xAC, MRMDestMem, - (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3), - "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, - (i8 imm:$src3)), addr:$dst)]>, - TB; -} // SchedRW - -} // Defs = [EFLAGS] - -// Sandy Bridge and newer Intel processors support faster rotates using -// SHLD to avoid a partial flag update on the normal rotate instructions. -let Predicates = [HasFastSHLDRotate], AddedComplexity = 5 in { - def : Pat<(rotl GR32:$src, (i8 imm:$shamt)), - (SHLD32rri8 GR32:$src, GR32:$src, imm:$shamt)>; - def : Pat<(rotl GR64:$src, (i8 imm:$shamt)), - (SHLD64rri8 GR64:$src, GR64:$src, imm:$shamt)>; -} - -def ROT32L2R_imm8 : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -def ROT64L2R_imm8 : SDNodeXFormgetZExtValue(), SDLoc(N)); -}]>; - -multiclass bmi_rotate { -let hasSideEffects = 0 in { - def ri : Ii8<0xF0, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, u8imm:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>, TAXD, VEX, Sched<[WriteShift]>; - let mayLoad = 1 in - def mi : Ii8<0xF0, MRMSrcMem, (outs RC:$dst), - (ins x86memop:$src1, u8imm:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>, TAXD, VEX, Sched<[WriteShiftLd]>; -} -} - -multiclass bmi_shift { -let hasSideEffects = 0 in { - def rr : I<0xF7, MRMSrcReg4VOp3, (outs RC:$dst), (ins RC:$src1, RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>, - VEX, Sched<[WriteShift]>; - let mayLoad = 1 in - def rm : I<0xF7, MRMSrcMem4VOp3, - (outs RC:$dst), (ins x86memop:$src1, RC:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>, - VEX, Sched<[WriteShiftLd, - // x86memop:$src1 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC:$src2 - ReadAfterLd]>; -} -} - -let Predicates = [HasBMI2] in { - defm RORX32 : bmi_rotate<"rorx{l}", GR32, i32mem>; - defm RORX64 : bmi_rotate<"rorx{q}", GR64, i64mem>, VEX_W; - defm SARX32 : bmi_shift<"sarx{l}", GR32, i32mem>, T8XS; - defm SARX64 : bmi_shift<"sarx{q}", GR64, i64mem>, T8XS, VEX_W; - defm SHRX32 : bmi_shift<"shrx{l}", GR32, i32mem>, T8XD; - defm SHRX64 : bmi_shift<"shrx{q}", GR64, i64mem>, T8XD, VEX_W; - defm SHLX32 : bmi_shift<"shlx{l}", GR32, i32mem>, T8PD; - defm SHLX64 : bmi_shift<"shlx{q}", GR64, i64mem>, T8PD, VEX_W; - - // Prefer RORX which is non-destructive and doesn't update EFLAGS. - let AddedComplexity = 10 in { - def : Pat<(rotl GR32:$src, (i8 imm:$shamt)), - (RORX32ri GR32:$src, (ROT32L2R_imm8 imm:$shamt))>; - def : Pat<(rotl GR64:$src, (i8 imm:$shamt)), - (RORX64ri GR64:$src, (ROT64L2R_imm8 imm:$shamt))>; - } - - def : Pat<(rotl (loadi32 addr:$src), (i8 imm:$shamt)), - (RORX32mi addr:$src, (ROT32L2R_imm8 imm:$shamt))>; - def : Pat<(rotl (loadi64 addr:$src), (i8 imm:$shamt)), - (RORX64mi addr:$src, (ROT64L2R_imm8 imm:$shamt))>; - - // Prefer SARX/SHRX/SHLX over SAR/SHR/SHL with variable shift BUT not - // immedidate shift, i.e. the following code is considered better - // - // mov %edi, %esi - // shl $imm, %esi - // ... %edi, ... - // - // than - // - // movb $imm, %sil - // shlx %sil, %edi, %esi - // ... %edi, ... - // - let AddedComplexity = 1 in { - def : Pat<(sra GR32:$src1, GR8:$src2), - (SARX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra GR64:$src1, GR8:$src2), - (SARX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl GR32:$src1, GR8:$src2), - (SHRX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl GR64:$src1, GR8:$src2), - (SHRX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl GR32:$src1, GR8:$src2), - (SHLX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl GR64:$src1, GR8:$src2), - (SHLX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } - - // We prefer to use - // mov (%ecx), %esi - // shl $imm, $esi - // - // over - // - // movb $imm, %al - // shlx %al, (%ecx), %esi - // - // This priority is enforced by IsProfitableToFoldLoad. - def : Pat<(sra (loadi32 addr:$src1), GR8:$src2), - (SARX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra (loadi64 addr:$src1), GR8:$src2), - (SARX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl (loadi32 addr:$src1), GR8:$src2), - (SHRX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl (loadi64 addr:$src1), GR8:$src2), - (SHRX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl (loadi32 addr:$src1), GR8:$src2), - (SHLX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl (loadi64 addr:$src1), GR8:$src2), - (SHLX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; -} diff --git a/suite/synctools/tablegen/X86/back/X86InstrSystem.td b/suite/synctools/tablegen/X86/back/X86InstrSystem.td deleted file mode 100644 index c0d51aa3bf..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrSystem.td +++ /dev/null @@ -1,743 +0,0 @@ -//===-- X86InstrSystem.td - System Instructions ------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 instructions that are generally used in -// privileged modes. These are not typically used by the compiler, but are -// supported for the assembler and disassembler. -// -//===----------------------------------------------------------------------===// - -let SchedRW = [WriteSystem] in { -let Defs = [RAX, RDX] in - def RDTSC : I<0x31, RawFrm, (outs), (ins), "rdtsc", [(X86rdtsc)]>, TB; - -let Defs = [RAX, RCX, RDX] in - def RDTSCP : I<0x01, MRM_F9, (outs), (ins), "rdtscp", [(X86rdtscp)]>, TB; - -// CPU flow control instructions - -let mayLoad = 1, mayStore = 0, hasSideEffects = 1, isTrap = 1 in { - def UD2 : I<0x0B, RawFrm, (outs), (ins), "ud2", [(trap)]>, TB; - def UD1 : I<0xB9, RawFrm, (outs), (ins), "ud1", []>, TB; - def UD0 : I<0xFF, RawFrm, (outs), (ins), "ud0", []>, TB; -} - -def HLT : I<0xF4, RawFrm, (outs), (ins), "hlt", []>; -def RSM : I<0xAA, RawFrm, (outs), (ins), "rsm", []>, TB; - -// Interrupt and SysCall Instructions. -let Uses = [EFLAGS] in - def INTO : I<0xce, RawFrm, (outs), (ins), "into", []>, Requires<[Not64BitMode]>; - -def INT3 : I<0xcc, RawFrm, (outs), (ins), "int3", [(int_x86_int (i8 3))]>; -} // SchedRW - -// The long form of "int $3" turns into int3 as a size optimization. -// FIXME: This doesn't work because InstAlias can't match immediate constants. -//def : InstAlias<"int\t$3", (INT3)>; - -let SchedRW = [WriteSystem] in { - -def INT : Ii8<0xcd, RawFrm, (outs), (ins u8imm:$trap), "int\t$trap", - [(int_x86_int imm:$trap)]>; - - -def SYSCALL : I<0x05, RawFrm, (outs), (ins), "syscall", []>, TB; -def SYSRET : I<0x07, RawFrm, (outs), (ins), "sysret{l}", []>, TB; -def SYSRET64 :RI<0x07, RawFrm, (outs), (ins), "sysretq", []>, TB, - Requires<[In64BitMode]>; - -def SYSENTER : I<0x34, RawFrm, (outs), (ins), "sysenter", []>, TB; - -def SYSEXIT : I<0x35, RawFrm, (outs), (ins), "sysexit{l}", []>, TB; -def SYSEXIT64 :RI<0x35, RawFrm, (outs), (ins), "sysexitq", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -def : Pat<(debugtrap), - (INT3)>, Requires<[NotPS4]>; -def : Pat<(debugtrap), - (INT (i8 0x41))>, Requires<[IsPS4]>; - -//===----------------------------------------------------------------------===// -// Input/Output Instructions. -// -let SchedRW = [WriteSystem] in { -let Defs = [AL], Uses = [DX] in -def IN8rr : I<0xEC, RawFrm, (outs), (ins), "in{b}\t{%dx, %al|al, dx}", []>; -let Defs = [AX], Uses = [DX] in -def IN16rr : I<0xED, RawFrm, (outs), (ins), "in{w}\t{%dx, %ax|ax, dx}", []>, - OpSize16; -let Defs = [EAX], Uses = [DX] in -def IN32rr : I<0xED, RawFrm, (outs), (ins), "in{l}\t{%dx, %eax|eax, dx}", []>, - OpSize32; - -let Defs = [AL] in -def IN8ri : Ii8<0xE4, RawFrm, (outs), (ins u8imm:$port), - "in{b}\t{$port, %al|al, $port}", []>; -let Defs = [AX] in -def IN16ri : Ii8<0xE5, RawFrm, (outs), (ins u8imm:$port), - "in{w}\t{$port, %ax|ax, $port}", []>, OpSize16; -let Defs = [EAX] in -def IN32ri : Ii8<0xE5, RawFrm, (outs), (ins u8imm:$port), - "in{l}\t{$port, %eax|eax, $port}", []>, OpSize32; - -let Uses = [DX, AL] in -def OUT8rr : I<0xEE, RawFrm, (outs), (ins), "out{b}\t{%al, %dx|dx, al}", []>; -let Uses = [DX, AX] in -def OUT16rr : I<0xEF, RawFrm, (outs), (ins), "out{w}\t{%ax, %dx|dx, ax}", []>, - OpSize16; -let Uses = [DX, EAX] in -def OUT32rr : I<0xEF, RawFrm, (outs), (ins), "out{l}\t{%eax, %dx|dx, eax}", []>, - OpSize32; - -let Uses = [AL] in -def OUT8ir : Ii8<0xE6, RawFrm, (outs), (ins u8imm:$port), - "out{b}\t{%al, $port|$port, al}", []>; -let Uses = [AX] in -def OUT16ir : Ii8<0xE7, RawFrm, (outs), (ins u8imm:$port), - "out{w}\t{%ax, $port|$port, ax}", []>, OpSize16; -let Uses = [EAX] in -def OUT32ir : Ii8<0xE7, RawFrm, (outs), (ins u8imm:$port), - "out{l}\t{%eax, $port|$port, eax}", []>, OpSize32; - -} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from debug registers - -let SchedRW = [WriteSystem] in { -def MOV32rd : I<0x21, MRMDestReg, (outs GR32:$dst), (ins DEBUG_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64rd : I<0x21, MRMDestReg, (outs GR64:$dst), (ins DEBUG_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; - -def MOV32dr : I<0x23, MRMSrcReg, (outs DEBUG_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64dr : I<0x23, MRMSrcReg, (outs DEBUG_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from control registers - -let SchedRW = [WriteSystem] in { -def MOV32rc : I<0x20, MRMDestReg, (outs GR32:$dst), (ins CONTROL_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64rc : I<0x20, MRMDestReg, (outs GR64:$dst), (ins CONTROL_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; - -def MOV32cr : I<0x22, MRMSrcReg, (outs CONTROL_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[Not64BitMode]>; -def MOV64cr : I<0x22, MRMSrcReg, (outs CONTROL_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>, TB, - Requires<[In64BitMode]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Segment override instruction prefixes - -//let SchedRW = [WriteNop] in { -//def CS_PREFIX : I<0x2E, RawFrm, (outs), (ins), "cs", []>; -//def SS_PREFIX : I<0x36, RawFrm, (outs), (ins), "ss", []>; -//def DS_PREFIX : I<0x3E, RawFrm, (outs), (ins), "ds", []>; -//def ES_PREFIX : I<0x26, RawFrm, (outs), (ins), "es", []>; -//def FS_PREFIX : I<0x64, RawFrm, (outs), (ins), "fs", []>; -//def GS_PREFIX : I<0x65, RawFrm, (outs), (ins), "gs", []>; -//} // SchedRW - -//===----------------------------------------------------------------------===// -// Moves to and from segment registers. -// - -let SchedRW = [WriteMove] in { -def MOV16rs : I<0x8C, MRMDestReg, (outs GR16:$dst), (ins SEGMENT_REG:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32rs : I<0x8C, MRMDestReg, (outs GR32:$dst), (ins SEGMENT_REG:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64rs : RI<0x8C, MRMDestReg, (outs GR64:$dst), (ins SEGMENT_REG:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -let mayStore = 1 in { -def MOV16ms : I<0x8C, MRMDestMem, (outs), (ins i16mem:$dst, SEGMENT_REG:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>; -} -def MOV16sr : I<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR16:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize16; -def MOV32sr : I<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR32:$src), - "mov{l}\t{$src, $dst|$dst, $src}", []>, OpSize32; -def MOV64sr : RI<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR64:$src), - "mov{q}\t{$src, $dst|$dst, $src}", []>; -let mayLoad = 1 in { -def MOV16sm : I<0x8E, MRMSrcMem, (outs SEGMENT_REG:$dst), (ins i16mem:$src), - "mov{w}\t{$src, $dst|$dst, $src}", []>; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Segmentation support instructions. - -let SchedRW = [WriteSystem] in { -def SWAPGS : I<0x01, MRM_F8, (outs), (ins), "swapgs", []>, TB; - -let mayLoad = 1 in -def LAR16rm : I<0x02, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -def LAR16rr : I<0x02, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; - -// i16mem operand in LAR32rm and GR32 operand in LAR32rr is not a typo. -let mayLoad = 1 in -def LAR32rm : I<0x02, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "lar{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -def LAR32rr : I<0x02, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lar{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -// i16mem operand in LAR64rm and GR32 operand in LAR64rr is not a typo. -let mayLoad = 1 in -def LAR64rm : RI<0x02, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "lar{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; -def LAR64rr : RI<0x02, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "lar{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; - -// i16mem operand in LSL32rm and GR32 operand in LSL32rr is not a typo. -let mayLoad = 1 in -def LSL16rm : I<0x03, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), - "lsl{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -def LSL16rr : I<0x03, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), - "lsl{w}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize16, NotMemoryFoldable; -// i16mem operand in LSL64rm and GR32 operand in LSL64rr is not a typo. -let mayLoad = 1 in -def LSL32rm : I<0x03, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), - "lsl{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -def LSL32rr : I<0x03, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "lsl{l}\t{$src, $dst|$dst, $src}", []>, TB, - OpSize32, NotMemoryFoldable; -let mayLoad = 1 in -def LSL64rm : RI<0x03, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), - "lsl{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; -def LSL64rr : RI<0x03, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), - "lsl{q}\t{$src, $dst|$dst, $src}", []>, TB, NotMemoryFoldable; - -def INVLPG : I<0x01, MRM7m, (outs), (ins i8mem:$addr), "invlpg\t$addr", []>, TB; - -def STR16r : I<0x00, MRM1r, (outs GR16:$dst), (ins), - "str{w}\t$dst", []>, TB, OpSize16; -def STR32r : I<0x00, MRM1r, (outs GR32:$dst), (ins), - "str{l}\t$dst", []>, TB, OpSize32; -def STR64r : RI<0x00, MRM1r, (outs GR64:$dst), (ins), - "str{q}\t$dst", []>, TB; -let mayStore = 1 in -def STRm : I<0x00, MRM1m, (outs), (ins i16mem:$dst), "str{w}\t$dst", []>, TB; - -def LTRr : I<0x00, MRM3r, (outs), (ins GR16:$src), "ltr{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LTRm : I<0x00, MRM3m, (outs), (ins i16mem:$src), "ltr{w}\t$src", []>, TB, NotMemoryFoldable; - -def PUSHCS16 : I<0x0E, RawFrm, (outs), (ins), "push{w}\t{%cs|cs}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHCS32 : I<0x0E, RawFrm, (outs), (ins), "push{l}\t{%cs|cs}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHSS16 : I<0x16, RawFrm, (outs), (ins), "push{w}\t{%ss|ss}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHSS32 : I<0x16, RawFrm, (outs), (ins), "push{l}\t{%ss|ss}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHDS16 : I<0x1E, RawFrm, (outs), (ins), "push{w}\t{%ds|ds}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHDS32 : I<0x1E, RawFrm, (outs), (ins), "push{l}\t{%ds|ds}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHES16 : I<0x06, RawFrm, (outs), (ins), "push{w}\t{%es|es}", []>, - OpSize16, Requires<[Not64BitMode]>; -def PUSHES32 : I<0x06, RawFrm, (outs), (ins), "push{l}\t{%es|es}", []>, - OpSize32, Requires<[Not64BitMode]>; -def PUSHFS16 : I<0xa0, RawFrm, (outs), (ins), "push{w}\t{%fs|fs}", []>, - OpSize16, TB; -def PUSHFS32 : I<0xa0, RawFrm, (outs), (ins), "push{l}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def PUSHGS16 : I<0xa8, RawFrm, (outs), (ins), "push{w}\t{%gs|gs}", []>, - OpSize16, TB; -def PUSHGS32 : I<0xa8, RawFrm, (outs), (ins), "push{l}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def PUSHFS64 : I<0xa0, RawFrm, (outs), (ins), "push{q}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; -def PUSHGS64 : I<0xa8, RawFrm, (outs), (ins), "push{q}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -// No "pop cs" instruction. -def POPSS16 : I<0x17, RawFrm, (outs), (ins), "pop{w}\t{%ss|ss}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPSS32 : I<0x17, RawFrm, (outs), (ins), "pop{l}\t{%ss|ss}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPDS16 : I<0x1F, RawFrm, (outs), (ins), "pop{w}\t{%ds|ds}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPDS32 : I<0x1F, RawFrm, (outs), (ins), "pop{l}\t{%ds|ds}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPES16 : I<0x07, RawFrm, (outs), (ins), "pop{w}\t{%es|es}", []>, - OpSize16, Requires<[Not64BitMode]>; -def POPES32 : I<0x07, RawFrm, (outs), (ins), "pop{l}\t{%es|es}", []>, - OpSize32, Requires<[Not64BitMode]>; - -def POPFS16 : I<0xa1, RawFrm, (outs), (ins), "pop{w}\t{%fs|fs}", []>, - OpSize16, TB; -def POPFS32 : I<0xa1, RawFrm, (outs), (ins), "pop{l}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def POPFS64 : I<0xa1, RawFrm, (outs), (ins), "pop{q}\t{%fs|fs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -def POPGS16 : I<0xa9, RawFrm, (outs), (ins), "pop{w}\t{%gs|gs}", []>, - OpSize16, TB; -def POPGS32 : I<0xa9, RawFrm, (outs), (ins), "pop{l}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[Not64BitMode]>; -def POPGS64 : I<0xa9, RawFrm, (outs), (ins), "pop{q}\t{%gs|gs}", []>, TB, - OpSize32, Requires<[In64BitMode]>; - -def LDS16rm : I<0xc5, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lds{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - Requires<[Not64BitMode]>; -def LDS32rm : I<0xc5, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lds{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - Requires<[Not64BitMode]>; - -def LSS16rm : I<0xb2, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lss{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LSS32rm : I<0xb2, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lss{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; -def LSS64rm : RI<0xb2, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lss{q}\t{$src, $dst|$dst, $src}", []>, TB; - -def LES16rm : I<0xc4, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "les{w}\t{$src, $dst|$dst, $src}", []>, OpSize16, - Requires<[Not64BitMode]>; -def LES32rm : I<0xc4, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "les{l}\t{$src, $dst|$dst, $src}", []>, OpSize32, - Requires<[Not64BitMode]>; - -def LFS16rm : I<0xb4, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lfs{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LFS32rm : I<0xb4, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lfs{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; -def LFS64rm : RI<0xb4, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lfs{q}\t{$src, $dst|$dst, $src}", []>, TB; - -def LGS16rm : I<0xb5, MRMSrcMem, (outs GR16:$dst), (ins opaquemem:$src), - "lgs{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize16; -def LGS32rm : I<0xb5, MRMSrcMem, (outs GR32:$dst), (ins opaquemem:$src), - "lgs{l}\t{$src, $dst|$dst, $src}", []>, TB, OpSize32; - -def LGS64rm : RI<0xb5, MRMSrcMem, (outs GR64:$dst), (ins opaquemem:$src), - "lgs\t{$src, $dst|$dst, $src}", []>, TB; - -def VERRr : I<0x00, MRM4r, (outs), (ins GR16:$seg), "verr\t$seg", []>, TB, NotMemoryFoldable; -def VERWr : I<0x00, MRM5r, (outs), (ins GR16:$seg), "verw\t$seg", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in { -def VERRm : I<0x00, MRM4m, (outs), (ins i16mem:$seg), "verr\t$seg", []>, TB, NotMemoryFoldable; -def VERWm : I<0x00, MRM5m, (outs), (ins i16mem:$seg), "verw\t$seg", []>, TB, NotMemoryFoldable; -} -} // SchedRW - -//===----------------------------------------------------------------------===// -// Descriptor-table support instructions - -let SchedRW = [WriteSystem] in { -def SGDT16m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{w}\t$dst", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def SGDT32m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{l}\t$dst", []>, OpSize32, TB, Requires <[Not64BitMode]>; -def SGDT64m : I<0x01, MRM0m, (outs), (ins opaquemem:$dst), - "sgdt{q}\t$dst", []>, TB, Requires <[In64BitMode]>; -def SIDT16m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{w}\t$dst", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def SIDT32m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{l}\t$dst", []>, OpSize32, TB, Requires <[Not64BitMode]>; -def SIDT64m : I<0x01, MRM1m, (outs), (ins opaquemem:$dst), - "sidt{q}\t$dst", []>, TB, Requires <[In64BitMode]>; -def SLDT16r : I<0x00, MRM0r, (outs GR16:$dst), (ins), - "sldt{w}\t$dst", []>, TB, OpSize16; -let mayStore = 1 in -def SLDT16m : I<0x00, MRM0m, (outs), (ins i16mem:$dst), - "sldt{w}\t$dst", []>, TB; -def SLDT32r : I<0x00, MRM0r, (outs GR32:$dst), (ins), - "sldt{l}\t$dst", []>, OpSize32, TB; - -// LLDT is not interpreted specially in 64-bit mode because there is no sign -// extension. -def SLDT64r : RI<0x00, MRM0r, (outs GR64:$dst), (ins), - "sldt{q}\t$dst", []>, TB, Requires<[In64BitMode]>; - -def LGDT16m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{w}\t$src", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def LGDT32m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{l}\t$src", []>, OpSize32, TB, Requires<[Not64BitMode]>; -def LGDT64m : I<0x01, MRM2m, (outs), (ins opaquemem:$src), - "lgdt{q}\t$src", []>, TB, Requires<[In64BitMode]>; -def LIDT16m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{w}\t$src", []>, TB, OpSize16, Requires<[Not64BitMode]>; -def LIDT32m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{l}\t$src", []>, OpSize32, TB, Requires<[Not64BitMode]>; -def LIDT64m : I<0x01, MRM3m, (outs), (ins opaquemem:$src), - "lidt{q}\t$src", []>, TB, Requires<[In64BitMode]>; -def LLDT16r : I<0x00, MRM2r, (outs), (ins GR16:$src), - "lldt{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LLDT16m : I<0x00, MRM2m, (outs), (ins i16mem:$src), - "lldt{w}\t$src", []>, TB, NotMemoryFoldable; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Specialized register support -let SchedRW = [WriteSystem] in { -let Uses = [EAX, ECX, EDX] in -def WRMSR : I<0x30, RawFrm, (outs), (ins), "wrmsr", []>, TB; -let Defs = [EAX, EDX], Uses = [ECX] in -def RDMSR : I<0x32, RawFrm, (outs), (ins), "rdmsr", []>, TB; - -let Defs = [RAX, RDX], Uses = [ECX] in - def RDPMC : I<0x33, RawFrm, (outs), (ins), "rdpmc", [(X86rdpmc)]>, TB; - -def SMSW16r : I<0x01, MRM4r, (outs GR16:$dst), (ins), - "smsw{w}\t$dst", []>, OpSize16, TB; -def SMSW32r : I<0x01, MRM4r, (outs GR32:$dst), (ins), - "smsw{l}\t$dst", []>, OpSize32, TB; -// no m form encodable; use SMSW16m -def SMSW64r : RI<0x01, MRM4r, (outs GR64:$dst), (ins), - "smsw{q}\t$dst", []>, TB; - -// For memory operands, there is only a 16-bit form -def SMSW16m : I<0x01, MRM4m, (outs), (ins i16mem:$dst), - "smsw{w}\t$dst", []>, TB; - -def LMSW16r : I<0x01, MRM6r, (outs), (ins GR16:$src), - "lmsw{w}\t$src", []>, TB, NotMemoryFoldable; -let mayLoad = 1 in -def LMSW16m : I<0x01, MRM6m, (outs), (ins i16mem:$src), - "lmsw{w}\t$src", []>, TB, NotMemoryFoldable; - -let Defs = [EAX, EBX, ECX, EDX], Uses = [EAX, ECX] in - def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Cache instructions -let SchedRW = [WriteSystem] in { -def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB; -def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", [(int_x86_wbinvd)]>, TB; - -// wbnoinvd is like wbinvd, except without invalidation -// encoding: like wbinvd + an 0xF3 prefix -def WBNOINVD : I<0x09, RawFrm, (outs), (ins), "wbnoinvd", - [(int_x86_wbnoinvd)]>, XS, - Requires<[HasWBNOINVD]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// CET instructions -// Use with caution, availability is not predicated on features. -let SchedRW = [WriteSystem] in { - let Uses = [SSP] in { - let Defs = [SSP] in { - def INCSSPD : I<0xAE, MRM5r, (outs), (ins GR32:$src), "incsspd\t$src", - [(int_x86_incsspd GR32:$src)]>, XS; - def INCSSPQ : RI<0xAE, MRM5r, (outs), (ins GR64:$src), "incsspq\t$src", - [(int_x86_incsspq GR64:$src)]>, XS; - } // Defs SSP - - let Constraints = "$src = $dst" in { - def RDSSPD : I<0x1E, MRM1r, (outs GR32:$dst), (ins GR32:$src), - "rdsspd\t$dst", - [(set GR32:$dst, (int_x86_rdsspd GR32:$src))]>, XS; - def RDSSPQ : RI<0x1E, MRM1r, (outs GR64:$dst), (ins GR64:$src), - "rdsspq\t$dst", - [(set GR64:$dst, (int_x86_rdsspq GR64:$src))]>, XS; - } - - let Defs = [SSP] in { - def SAVEPREVSSP : I<0x01, MRM_EA, (outs), (ins), "saveprevssp", - [(int_x86_saveprevssp)]>, XS; - def RSTORSSP : I<0x01, MRM5m, (outs), (ins i32mem:$src), - "rstorssp\t$src", - [(int_x86_rstorssp addr:$src)]>, XS; - } // Defs SSP - } // Uses SSP - - def WRSSD : I<0xF6, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "wrssd\t{$src, $dst|$dst, $src}", - [(int_x86_wrssd GR32:$src, addr:$dst)]>, T8PS; - def WRSSQ : RI<0xF6, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "wrssq\t{$src, $dst|$dst, $src}", - [(int_x86_wrssq GR64:$src, addr:$dst)]>, T8PS; - def WRUSSD : I<0xF5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "wrussd\t{$src, $dst|$dst, $src}", - [(int_x86_wrussd GR32:$src, addr:$dst)]>, T8PD; - def WRUSSQ : RI<0xF5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "wrussq\t{$src, $dst|$dst, $src}", - [(int_x86_wrussq GR64:$src, addr:$dst)]>, T8PD; - - let Defs = [SSP] in { - let Uses = [SSP] in { - def SETSSBSY : I<0x01, MRM_E8, (outs), (ins), "setssbsy", - [(int_x86_setssbsy)]>, XS; - } // Uses SSP - - def CLRSSBSY : I<0xAE, MRM6m, (outs), (ins i32mem:$src), - "clrssbsy\t$src", - [(int_x86_clrssbsy addr:$src)]>, XS; - } // Defs SSP -} // SchedRW - -let SchedRW = [WriteSystem] in { - def ENDBR64 : I<0x1E, MRM_FA, (outs), (ins), "endbr64", []>, XS; - def ENDBR32 : I<0x1E, MRM_FB, (outs), (ins), "endbr32", []>, XS; -} // SchedRW - -//===----------------------------------------------------------------------===// -// XSAVE instructions -let SchedRW = [WriteSystem] in { -let Predicates = [HasXSAVE] in { -let Defs = [EDX, EAX], Uses = [ECX] in - def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB; - -let Uses = [EDX, EAX, ECX] in - def XSETBV : I<0x01, MRM_D1, (outs), (ins), - "xsetbv", - [(int_x86_xsetbv ECX, EDX, EAX)]>, TB; - -} // HasXSAVE - -let Uses = [EDX, EAX] in { -def XSAVE : I<0xAE, MRM4m, (outs), (ins opaquemem:$dst), - "xsave\t$dst", - [(int_x86_xsave addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE]>; -def XSAVE64 : RI<0xAE, MRM4m, (outs), (ins opaquemem:$dst), - "xsave64\t$dst", - [(int_x86_xsave64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE, In64BitMode]>; -def XRSTOR : I<0xAE, MRM5m, (outs), (ins opaquemem:$dst), - "xrstor\t$dst", - [(int_x86_xrstor addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE]>; -def XRSTOR64 : RI<0xAE, MRM5m, (outs), (ins opaquemem:$dst), - "xrstor64\t$dst", - [(int_x86_xrstor64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVE, In64BitMode]>; -def XSAVEOPT : I<0xAE, MRM6m, (outs), (ins opaquemem:$dst), - "xsaveopt\t$dst", - [(int_x86_xsaveopt addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVEOPT]>; -def XSAVEOPT64 : RI<0xAE, MRM6m, (outs), (ins opaquemem:$dst), - "xsaveopt64\t$dst", - [(int_x86_xsaveopt64 addr:$dst, EDX, EAX)]>, PS, Requires<[HasXSAVEOPT, In64BitMode]>; -def XSAVEC : I<0xC7, MRM4m, (outs), (ins opaquemem:$dst), - "xsavec\t$dst", - [(int_x86_xsavec addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVEC]>; -def XSAVEC64 : RI<0xC7, MRM4m, (outs), (ins opaquemem:$dst), - "xsavec64\t$dst", - [(int_x86_xsavec64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVEC, In64BitMode]>; -def XSAVES : I<0xC7, MRM5m, (outs), (ins opaquemem:$dst), - "xsaves\t$dst", - [(int_x86_xsaves addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES]>; -def XSAVES64 : RI<0xC7, MRM5m, (outs), (ins opaquemem:$dst), - "xsaves64\t$dst", - [(int_x86_xsaves64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVE, In64BitMode]>; -def XRSTORS : I<0xC7, MRM3m, (outs), (ins opaquemem:$dst), - "xrstors\t$dst", - [(int_x86_xrstors addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES]>; -def XRSTORS64 : RI<0xC7, MRM3m, (outs), (ins opaquemem:$dst), - "xrstors64\t$dst", - [(int_x86_xrstors64 addr:$dst, EDX, EAX)]>, TB, Requires<[HasXSAVES, In64BitMode]>; -} // Uses -} // SchedRW - -//===----------------------------------------------------------------------===// -// VIA PadLock crypto instructions -let Defs = [RAX, RDI], Uses = [RDX, RDI], SchedRW = [WriteSystem] in - def XSTORE : I<0xa7, MRM_C0, (outs), (ins), "xstore", []>, TB; - -def : InstAlias<"xstorerng", (XSTORE)>; - -let SchedRW = [WriteSystem] in { -let Defs = [RSI, RDI], Uses = [RBX, RDX, RSI, RDI] in { - def XCRYPTECB : I<0xa7, MRM_C8, (outs), (ins), "xcryptecb", []>, TB; - def XCRYPTCBC : I<0xa7, MRM_D0, (outs), (ins), "xcryptcbc", []>, TB; - def XCRYPTCTR : I<0xa7, MRM_D8, (outs), (ins), "xcryptctr", []>, TB; - def XCRYPTCFB : I<0xa7, MRM_E0, (outs), (ins), "xcryptcfb", []>, TB; - def XCRYPTOFB : I<0xa7, MRM_E8, (outs), (ins), "xcryptofb", []>, TB; -} - -let Defs = [RAX, RSI, RDI], Uses = [RAX, RSI, RDI] in { - def XSHA1 : I<0xa6, MRM_C8, (outs), (ins), "xsha1", []>, TB; - def XSHA256 : I<0xa6, MRM_D0, (outs), (ins), "xsha256", []>, TB; -} -let Defs = [RAX, RDX, RSI], Uses = [RAX, RSI] in - def MONTMUL : I<0xa6, MRM_C0, (outs), (ins), "montmul", []>, TB; -} // SchedRW - -/* -//==-----------------------------------------------------------------------===// -// PKU - enable protection key -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - def WRPKRU : PseudoI<(outs), (ins GR32:$src), - [(int_x86_wrpkru GR32:$src)]>; - def RDPKRU : PseudoI<(outs GR32:$dst), (ins), - [(set GR32:$dst, (int_x86_rdpkru))]>; -} -*/ - -let SchedRW = [WriteSystem] in { -let Defs = [EAX, EDX], Uses = [ECX] in - def RDPKRUr : I<0x01, MRM_EE, (outs), (ins), "rdpkru", []>, TB; -let Uses = [EAX, ECX, EDX] in - def WRPKRUr : I<0x01, MRM_EF, (outs), (ins), "wrpkru", []>, TB; -} // SchedRW - -//===----------------------------------------------------------------------===// -// FS/GS Base Instructions -let Predicates = [HasFSGSBase, In64BitMode], SchedRW = [WriteSystem] in { - def RDFSBASE : I<0xAE, MRM0r, (outs GR32:$dst), (ins), - "rdfsbase{l}\t$dst", - [(set GR32:$dst, (int_x86_rdfsbase_32))]>, XS; - def RDFSBASE64 : RI<0xAE, MRM0r, (outs GR64:$dst), (ins), - "rdfsbase{q}\t$dst", - [(set GR64:$dst, (int_x86_rdfsbase_64))]>, XS; - def RDGSBASE : I<0xAE, MRM1r, (outs GR32:$dst), (ins), - "rdgsbase{l}\t$dst", - [(set GR32:$dst, (int_x86_rdgsbase_32))]>, XS; - def RDGSBASE64 : RI<0xAE, MRM1r, (outs GR64:$dst), (ins), - "rdgsbase{q}\t$dst", - [(set GR64:$dst, (int_x86_rdgsbase_64))]>, XS; - def WRFSBASE : I<0xAE, MRM2r, (outs), (ins GR32:$src), - "wrfsbase{l}\t$src", - [(int_x86_wrfsbase_32 GR32:$src)]>, XS; - def WRFSBASE64 : RI<0xAE, MRM2r, (outs), (ins GR64:$src), - "wrfsbase{q}\t$src", - [(int_x86_wrfsbase_64 GR64:$src)]>, XS; - def WRGSBASE : I<0xAE, MRM3r, (outs), (ins GR32:$src), - "wrgsbase{l}\t$src", - [(int_x86_wrgsbase_32 GR32:$src)]>, XS; - def WRGSBASE64 : RI<0xAE, MRM3r, (outs), (ins GR64:$src), - "wrgsbase{q}\t$src", - [(int_x86_wrgsbase_64 GR64:$src)]>, XS; -} - -//===----------------------------------------------------------------------===// -// INVPCID Instruction -let SchedRW = [WriteSystem] in { -def INVPCID32 : I<0x82, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invpcid\t{$src2, $src1|$src1, $src2}", - [(int_x86_invpcid GR32:$src1, addr:$src2)]>, T8PD, - Requires<[Not64BitMode, HasINVPCID]>; -def INVPCID64 : I<0x82, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invpcid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode, HasINVPCID]>; -} // SchedRW - -let Predicates = [In64BitMode, HasINVPCID] in { - // The instruction can only use a 64 bit register as the register argument - // in 64 bit mode, while the intrinsic only accepts a 32 bit argument - // corresponding to it. - // The accepted values for now are 0,1,2,3 anyways (see Intel SDM -- INVCPID - // type),/ so it doesn't hurt us that one can't supply a 64 bit value here. - def : Pat<(int_x86_invpcid GR32:$src1, addr:$src2), - (INVPCID64 - (SUBREG_TO_REG (i64 0), (MOV32rr GR32:$src1), sub_32bit), - addr:$src2)>; -} - - -//===----------------------------------------------------------------------===// -// SMAP Instruction -let Defs = [EFLAGS], SchedRW = [WriteSystem] in { - def CLAC : I<0x01, MRM_CA, (outs), (ins), "clac", []>, TB; - def STAC : I<0x01, MRM_CB, (outs), (ins), "stac", []>, TB; -} - -//===----------------------------------------------------------------------===// -// SMX Instruction -let SchedRW = [WriteSystem] in { -let Uses = [RAX, RBX, RCX, RDX], Defs = [RAX, RBX, RCX] in { - def GETSEC : I<0x37, RawFrm, (outs), (ins), "getsec", []>, TB; -} // Uses, Defs -} // SchedRW - -//===----------------------------------------------------------------------===// -// TS flag control instruction. -let SchedRW = [WriteSystem] in { -def CLTS : I<0x06, RawFrm, (outs), (ins), "clts", []>, TB; -} - -//===----------------------------------------------------------------------===// -// IF (inside EFLAGS) management instructions. -let SchedRW = [WriteSystem], Uses = [EFLAGS], Defs = [EFLAGS] in { -def CLI : I<0xFA, RawFrm, (outs), (ins), "cli", []>; -def STI : I<0xFB, RawFrm, (outs), (ins), "sti", []>; -} - -//===----------------------------------------------------------------------===// -// RDPID Instruction -let SchedRW = [WriteSystem] in { -def RDPID32 : I<0xC7, MRM7r, (outs GR32:$dst), (ins), - "rdpid\t$dst", [(set GR32:$dst, (int_x86_rdpid))]>, XS, - Requires<[Not64BitMode, HasRDPID]>; -def RDPID64 : I<0xC7, MRM7r, (outs GR64:$dst), (ins), "rdpid\t$dst", []>, XS, - Requires<[In64BitMode, HasRDPID]>; -} // SchedRW - -let Predicates = [In64BitMode, HasRDPID] in { - // Due to silly instruction definition, we have to compensate for the - // instruction outputting a 64-bit register. - def : Pat<(int_x86_rdpid), - (EXTRACT_SUBREG (RDPID64), sub_32bit)>; -} - - -//===----------------------------------------------------------------------===// -// PTWRITE Instruction - Write Data to a Processor Trace Packet -let SchedRW = [WriteSystem] in { -def PTWRITEm: I<0xAE, MRM4m, (outs), (ins i32mem:$dst), - "ptwrite{l}\t$dst", [(int_x86_ptwrite32 (loadi32 addr:$dst))]>, XS, - Requires<[HasPTWRITE]>; -def PTWRITE64m : RI<0xAE, MRM4m, (outs), (ins i64mem:$dst), - "ptwrite{q}\t$dst", [(int_x86_ptwrite64 (loadi64 addr:$dst))]>, XS, - Requires<[In64BitMode, HasPTWRITE]>; - -def PTWRITEr : I<0xAE, MRM4r, (outs), (ins GR32:$dst), - "ptwrite{l}\t$dst", [(int_x86_ptwrite32 GR32:$dst)]>, XS, - Requires<[HasPTWRITE]>; -def PTWRITE64r : RI<0xAE, MRM4r, (outs), (ins GR64:$dst), - "ptwrite{q}\t$dst", [(int_x86_ptwrite64 GR64:$dst)]>, XS, - Requires<[In64BitMode, HasPTWRITE]>; -} // SchedRW - -//===----------------------------------------------------------------------===// -// Platform Configuration instruction - -// From ISA docs: -// "This instruction is used to execute functions for configuring platform -// features. -// EAX: Leaf function to be invoked. -// RBX/RCX/RDX: Leaf-specific purpose." -// "Successful execution of the leaf clears RAX (set to zero) and ZF, CF, PF, -// AF, OF, and SF are cleared. In case of failure, the failure reason is -// indicated in RAX with ZF set to 1 and CF, PF, AF, OF, and SF are cleared." -// Thus all these mentioned registers are considered clobbered. - -let SchedRW = [WriteSystem] in { -let Uses = [RAX, RBX, RCX, RDX], Defs = [RAX, RBX, RCX, RDX, EFLAGS] in - def PCONFIG : I<0x01, MRM_C5, (outs), (ins), "pconfig", []>, TB, - Requires<[HasPCONFIG]>; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrTSX.td b/suite/synctools/tablegen/X86/back/X86InstrTSX.td deleted file mode 100644 index 8b9f723a41..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrTSX.td +++ /dev/null @@ -1,60 +0,0 @@ -//===-- X86InstrVMX.td - TSX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel TSX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// TSX instructions - -def X86xtest: SDNode<"X86ISD::XTEST", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -let SchedRW = [WriteSystem] in { - -//let usesCustomInserter = 1 in -//def XBEGIN : I<0, Pseudo, (outs GR32:$dst), (ins), -// "# XBEGIN", [(set GR32:$dst, (int_x86_xbegin))]>, -// Requires<[HasRTM]>; - -let isBranch = 1, isTerminator = 1, Defs = [EAX] in { -def XBEGIN_2 : Ii16PCRel<0xc7, MRM_F8, (outs), (ins brtarget16:$dst), - "xbegin\t$dst", []>, OpSize16; -def XBEGIN_4 : Ii32PCRel<0xc7, MRM_F8, (outs), (ins brtarget32:$dst), - "xbegin\t$dst", []>, OpSize32; -} - -// Pseudo instruction to fake the definition of EAX on the fallback code path. -//let isPseudo = 1, Defs = [EAX] in { -//def XABORT_DEF : I<0, Pseudo, (outs), (ins), "# XABORT DEF", []>; -//} - -def XEND : I<0x01, MRM_D5, (outs), (ins), - "xend", [(int_x86_xend)]>, TB, Requires<[HasRTM]>; - -let Defs = [EFLAGS] in -def XTEST : I<0x01, MRM_D6, (outs), (ins), - "xtest", [(set EFLAGS, (X86xtest))]>, TB, Requires<[HasRTM]>; - -def XABORT : Ii8<0xc6, MRM_F8, (outs), (ins i8imm:$imm), - "xabort\t$imm", - [(int_x86_xabort imm:$imm)]>, Requires<[HasRTM]>; -} // SchedRW - -// HLE prefixes -let SchedRW = [WriteSystem] in { - -let isAsmParserOnly = 1 in { -def XACQUIRE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "xacquire", []>; -def XRELEASE_PREFIX : I<0xF3, RawFrm, (outs), (ins), "xrelease", []>; -} - -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrVMX.td b/suite/synctools/tablegen/X86/back/X86InstrVMX.td deleted file mode 100644 index 06a438ebfc..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrVMX.td +++ /dev/null @@ -1,88 +0,0 @@ -//===-- X86InstrVMX.td - VMX Instruction Set Extension -----*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the instructions that make up the Intel VMX instruction -// set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// VMX instructions - -let SchedRW = [WriteSystem] in { -// 66 0F 38 80 -def INVEPT32 : I<0x80, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invept\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[Not64BitMode]>; -def INVEPT64 : I<0x80, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invept\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode]>; - -// 66 0F 38 81 -def INVVPID32 : I<0x81, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2), - "invvpid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[Not64BitMode]>; -def INVVPID64 : I<0x81, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2), - "invvpid\t{$src2, $src1|$src1, $src2}", []>, T8PD, - Requires<[In64BitMode]>; - -// 0F 01 C1 -def VMCALL : I<0x01, MRM_C1, (outs), (ins), "vmcall", []>, TB; -def VMCLEARm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), - "vmclear\t$vmcs", []>, PD; - -// OF 01 D4 -def VMFUNC : I<0x01, MRM_D4, (outs), (ins), "vmfunc", []>, TB; - -// 0F 01 C2 -def VMLAUNCH : I<0x01, MRM_C2, (outs), (ins), "vmlaunch", []>, TB; - -// 0F 01 C3 -def VMRESUME : I<0x01, MRM_C3, (outs), (ins), "vmresume", []>, TB; -def VMPTRLDm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), - "vmptrld\t$vmcs", []>, PS; -def VMPTRSTm : I<0xC7, MRM7m, (outs), (ins i64mem:$vmcs), - "vmptrst\t$vmcs", []>, PS; -def VMREAD64rr : I<0x78, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), - "vmread{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMREAD32rr : I<0x78, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), - "vmread{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; - -let mayStore = 1 in { -def VMREAD64mr : I<0x78, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "vmread{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMREAD32mr : I<0x78, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "vmread{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; -} // mayStore - -def VMWRITE64rr : I<0x79, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "vmwrite{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMWRITE32rr : I<0x79, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "vmwrite{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; - -let mayLoad = 1 in { -def VMWRITE64rm : I<0x79, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "vmwrite{q}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[In64BitMode]>, - NotMemoryFoldable; -def VMWRITE32rm : I<0x79, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "vmwrite{l}\t{$src, $dst|$dst, $src}", []>, PS, Requires<[Not64BitMode]>, - NotMemoryFoldable; -} // mayLoad - -// 0F 01 C4 -def VMXOFF : I<0x01, MRM_C4, (outs), (ins), "vmxoff", []>, TB; -def VMXON : I<0xC7, MRM6m, (outs), (ins i64mem:$vmxon), - "vmxon\t$vmxon", []>, XS; -} // SchedRW diff --git a/suite/synctools/tablegen/X86/back/X86InstrVecCompiler.td b/suite/synctools/tablegen/X86/back/X86InstrVecCompiler.td deleted file mode 100644 index 322bdb74e2..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrVecCompiler.td +++ /dev/null @@ -1,511 +0,0 @@ -//===- X86InstrVecCompiler.td - Vector Compiler Patterns ---*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the various vector pseudo instructions used by the -// compiler, as well as Pat patterns used during instruction selection. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// No op bitconverts -//===----------------------------------------------------------------------===// - -// Bitcasts between 128-bit vector types. Return the original type since -// no instruction is needed for the conversion -def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v8i16 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v16i8 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v2f64 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v2i64 (bitconvert (v4f32 VR128:$src))), (v2i64 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v2i64 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v8i16 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v16i8 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v2f64 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v4i32 (bitconvert (v4f32 VR128:$src))), (v4i32 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v2i64 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v4i32 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v16i8 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v2f64 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v8i16 (bitconvert (v4f32 VR128:$src))), (v8i16 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v2i64 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v4i32 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v8i16 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v2f64 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v16i8 (bitconvert (v4f32 VR128:$src))), (v16i8 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v2i64 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v8i16 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v16i8 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v2i64 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v4i32 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v8i16 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v16i8 VR128:$src))), (v2f64 VR128:$src)>; -def : Pat<(v2f64 (bitconvert (v4f32 VR128:$src))), (v2f64 VR128:$src)>; - -// Bitcasts between 256-bit vector types. Return the original type since -// no instruction is needed for the conversion -def : Pat<(v4i64 (bitconvert (v8i32 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v16i16 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v32i8 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v8f32 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v4i64 (bitconvert (v4f64 VR256:$src))), (v4i64 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v4i64 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v16i16 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v32i8 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v4f64 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v8i32 (bitconvert (v8f32 VR256:$src))), (v8i32 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v4i64 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v8i32 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v32i8 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v4f64 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v16i16 (bitconvert (v8f32 VR256:$src))), (v16i16 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v4i64 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v8i32 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v16i16 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v4f64 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v32i8 (bitconvert (v8f32 VR256:$src))), (v32i8 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v4i64 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v8i32 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v16i16 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v32i8 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v8f32 (bitconvert (v4f64 VR256:$src))), (v8f32 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v4i64 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v8i32 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v16i16 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v32i8 VR256:$src))), (v4f64 VR256:$src)>; -def : Pat<(v4f64 (bitconvert (v8f32 VR256:$src))), (v4f64 VR256:$src)>; - -// Bitcasts between 512-bit vector types. Return the original type since -// no instruction is needed for the conversion. -def : Pat<(v8f64 (bitconvert (v8i64 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v16i32 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v32i16 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v64i8 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v8f64 (bitconvert (v16f32 VR512:$src))), (v8f64 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v8i64 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v16i32 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v32i16 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v64i8 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v16f32 (bitconvert (v8f64 VR512:$src))), (v16f32 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v16i32 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v32i16 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v64i8 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v8f64 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v8i64 (bitconvert (v16f32 VR512:$src))), (v8i64 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v8i64 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v16f32 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v32i16 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v64i8 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v16i32 (bitconvert (v8f64 VR512:$src))), (v16i32 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v8i64 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v16i32 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v64i8 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v8f64 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v32i16 (bitconvert (v16f32 VR512:$src))), (v32i16 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v8i64 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v16i32 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v32i16 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v8f64 VR512:$src))), (v64i8 VR512:$src)>; -def : Pat<(v64i8 (bitconvert (v16f32 VR512:$src))), (v64i8 VR512:$src)>; - - -//===----------------------------------------------------------------------===// -// Non-instruction patterns -//===----------------------------------------------------------------------===// - -// A vector extract of the first f32/f64 position is a subregister copy -def : Pat<(f32 (extractelt (v4f32 VR128:$src), (iPTR 0))), - (COPY_TO_REGCLASS (v4f32 VR128:$src), FR32)>; -def : Pat<(f64 (extractelt (v2f64 VR128:$src), (iPTR 0))), - (COPY_TO_REGCLASS (v2f64 VR128:$src), FR64)>; - -// Implicitly promote a 32-bit scalar to a vector. -def : Pat<(v4f32 (scalar_to_vector FR32:$src)), - (COPY_TO_REGCLASS FR32:$src, VR128)>; -// Implicitly promote a 64-bit scalar to a vector. -def : Pat<(v2f64 (scalar_to_vector FR64:$src)), - (COPY_TO_REGCLASS FR64:$src, VR128)>; - - -//===----------------------------------------------------------------------===// -// Subvector tricks -//===----------------------------------------------------------------------===// - -// Patterns for insert_subvector/extract_subvector to/from index=0 -multiclass subvector_subreg_lowering { - def : Pat<(subVT (extract_subvector (VT RC:$src), (iPTR 0))), - (subVT (EXTRACT_SUBREG RC:$src, subIdx))>; - - def : Pat<(VT (insert_subvector undef, subRC:$src, (iPTR 0))), - (VT (INSERT_SUBREG (IMPLICIT_DEF), subRC:$src, subIdx))>; -} - -// A 128-bit subvector extract from the first 256-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 256-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - -// A 128-bit subvector extract from the first 512-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 512-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - -// A 128-bit subvector extract from the first 512-bit vector position is a -// subregister copy that needs no instruction. Likewise, a 128-bit subvector -// insert to the first 512-bit vector position is a subregister copy that needs -// no instruction. -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; -defm : subvector_subreg_lowering; - - -multiclass subvector_store_lowering { - def : Pat<(alignedstore (DstTy (extract_subvector - (SrcTy RC:$src), (iPTR 0))), addr:$dst), - (!cast("VMOV"#AlignedStr#"mr") addr:$dst, - (DstTy (EXTRACT_SUBREG RC:$src, SubIdx)))>; - - def : Pat<(store (DstTy (extract_subvector - (SrcTy RC:$src), (iPTR 0))), addr:$dst), - (!cast("VMOV"#UnalignedStr#"mr") addr:$dst, - (DstTy (EXTRACT_SUBREG RC:$src, SubIdx)))>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : subvector_store_lowering<"APD", "UPD", VR256X, v2f64, v4f64, sub_xmm>; - defm : subvector_store_lowering<"APS", "UPS", VR256X, v4f32, v8f32, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v2i64, v4i64, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v4i32, v8i32, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v8i16, v16i16, sub_xmm>; - defm : subvector_store_lowering<"DQA", "DQU", VR256X, v16i8, v32i8, sub_xmm>; -} - -let Predicates = [HasVLX] in { - // Special patterns for storing subvector extracts of lower 128-bits - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ128", "UPDZ128", VR256X, v2f64, v4f64, - sub_xmm>; - defm : subvector_store_lowering<"APSZ128", "UPSZ128", VR256X, v4f32, v8f32, - sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v2i64, - v4i64, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v4i32, - v8i32, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v8i16, - v16i16, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR256X, v16i8, - v32i8, sub_xmm>; - - // Special patterns for storing subvector extracts of lower 128-bits of 512. - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ128", "UPDZ128", VR512, v2f64, v8f64, - sub_xmm>; - defm : subvector_store_lowering<"APSZ128", "UPSZ128", VR512, v4f32, v16f32, - sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v2i64, - v8i64, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v4i32, - v16i32, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v8i16, - v32i16, sub_xmm>; - defm : subvector_store_lowering<"DQA64Z128", "DQU64Z128", VR512, v16i8, - v64i8, sub_xmm>; - - // Special patterns for storing subvector extracts of lower 256-bits of 512. - // Its cheaper to just use VMOVAPS/VMOVUPS instead of VEXTRACTF128mr - defm : subvector_store_lowering<"APDZ256", "UPDZ256", VR512, v4f64, v8f64, - sub_ymm>; - defm : subvector_store_lowering<"APSZ256", "UPSZ256", VR512, v8f32, v16f32, - sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v4i64, - v8i64, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v8i32, - v16i32, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v16i16, - v32i16, sub_ymm>; - defm : subvector_store_lowering<"DQA64Z256", "DQU64Z256", VR512, v32i8, - v64i8, sub_ymm>; -} - -// If we're inserting into an all zeros vector, just use a plain move which -// will zero the upper bits. A post-isel hook will take care of removing -// any moves that we can prove are unnecessary. -multiclass subvec_zero_lowering { - def : Pat<(DstTy (insert_subvector (bitconvert (ZeroTy immAllZerosV)), - (SrcTy RC:$src), (iPTR 0))), - (SUBREG_TO_REG (i64 0), - (SrcTy (!cast("VMOV"#MoveStr#"rr") RC:$src)), SubIdx)>; -} - -let Predicates = [HasAVX, NoVLX] in { - defm : subvec_zero_lowering<"APD", VR128, v4f64, v2f64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"APS", VR128, v8f32, v4f32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v4i64, v2i64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v8i32, v4i32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v16i16, v8i16, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v32i8, v16i8, v8i32, sub_xmm>; -} - -let Predicates = [HasVLX] in { - defm : subvec_zero_lowering<"APDZ128", VR128X, v4f64, v2f64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"APSZ128", VR128X, v8f32, v4f32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v4i64, v2i64, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v8i32, v4i32, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v16i16, v8i16, v8i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v32i8, v16i8, v8i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDZ128", VR128X, v8f64, v2f64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"APSZ128", VR128X, v16f32, v4f32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v8i64, v2i64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v16i32, v4i32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v32i16, v8i16, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA64Z128", VR128X, v64i8, v16i8, v16i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDZ256", VR256X, v8f64, v4f64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"APSZ256", VR256X, v16f32, v8f32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v8i64, v4i64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v16i32, v8i32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v32i16, v16i16, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQA64Z256", VR256X, v64i8, v32i8, v16i32, sub_ymm>; -} - -let Predicates = [HasAVX512, NoVLX] in { - defm : subvec_zero_lowering<"APD", VR128, v8f64, v2f64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"APS", VR128, v16f32, v4f32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v8i64, v2i64, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v16i32, v4i32, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v32i16, v8i16, v16i32, sub_xmm>; - defm : subvec_zero_lowering<"DQA", VR128, v64i8, v16i8, v16i32, sub_xmm>; - - defm : subvec_zero_lowering<"APDY", VR256, v8f64, v4f64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"APSY", VR256, v16f32, v8f32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v8i64, v4i64, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v16i32, v8i32, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v32i16, v16i16, v16i32, sub_ymm>; - defm : subvec_zero_lowering<"DQAY", VR256, v64i8, v32i8, v16i32, sub_ymm>; -} - -class maskzeroupper : - PatLeaf<(vt RC:$src), [{ - return isMaskZeroExtended(N); - }]>; - -def maskzeroupperv1i1 : maskzeroupper; -def maskzeroupperv2i1 : maskzeroupper; -def maskzeroupperv4i1 : maskzeroupper; -def maskzeroupperv8i1 : maskzeroupper; -def maskzeroupperv16i1 : maskzeroupper; -def maskzeroupperv32i1 : maskzeroupper; - -// The patterns determine if we can depend on the upper bits of a mask register -// being zeroed by the previous operation so that we can skip explicit -// zeroing. -let Predicates = [HasBWI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv16i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK16:$src, VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv16i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK16:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv32i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK32:$src, VK64)>; -} - -let Predicates = [HasAVX512] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK16)>; - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv8i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK8:$src, VK16)>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv1i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK1:$src, VK8)>; -} - -let Predicates = [HasVLX, HasDQI] in { - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK8)>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK8)>; -} - -let Predicates = [HasVLX] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK16)>; - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK16)>; -} - -let Predicates = [HasBWI, HasVLX] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK32)>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK32)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv2i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK2:$src, VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - maskzeroupperv4i1:$src, (iPTR 0))), - (COPY_TO_REGCLASS VK4:$src, VK64)>; -} - -// If the bits are not zero we have to fall back to explicitly zeroing by -// using shifts. -let Predicates = [HasAVX512] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK1:$mask, VK16), - (i8 15)), (i8 15))>; - - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK2:$mask, VK16), - (i8 14)), (i8 14))>; - - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK4:$mask, VK16), - (i8 12)), (i8 12))>; -} - -let Predicates = [HasAVX512, NoDQI] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRWri (KSHIFTLWri (COPY_TO_REGCLASS VK8:$mask, VK16), - (i8 8)), (i8 8))>; -} - -let Predicates = [HasDQI] in { - def : Pat<(v16i1 (insert_subvector (v16i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK16)>; - - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK1:$mask, VK8), - (i8 7)), (i8 7))>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK2:$mask, VK8), - (i8 6)), (i8 6))>; - def : Pat<(v8i1 (insert_subvector (v8i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRBri (KSHIFTLBri (COPY_TO_REGCLASS VK4:$mask, VK8), - (i8 4)), (i8 4))>; -} - -let Predicates = [HasBWI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v16i1 VK16:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVWkk VK16:$mask), VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v16i1 VK16:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVWkk VK16:$mask), VK64)>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v32i1 VK32:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVDkk VK32:$mask), VK64)>; -} - -let Predicates = [HasBWI, NoDQI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK8:$mask, VK32), - (i8 24)), (i8 24))>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK8:$mask, VK64), - (i8 56)), (i8 56))>; -} - -let Predicates = [HasBWI, HasDQI] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK32)>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v8i1 VK8:$mask), (iPTR 0))), - (COPY_TO_REGCLASS (KMOVBkk VK8:$mask), VK64)>; -} - -let Predicates = [HasBWI, HasVLX] in { - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK1:$mask, VK32), - (i8 31)), (i8 31))>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK2:$mask, VK32), - (i8 30)), (i8 30))>; - def : Pat<(v32i1 (insert_subvector (v32i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRDri (KSHIFTLDri (COPY_TO_REGCLASS VK4:$mask, VK32), - (i8 28)), (i8 28))>; - - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v1i1 VK1:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK1:$mask, VK64), - (i8 63)), (i8 63))>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v2i1 VK2:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK2:$mask, VK64), - (i8 62)), (i8 62))>; - def : Pat<(v64i1 (insert_subvector (v64i1 immAllZerosV), - (v4i1 VK4:$mask), (iPTR 0))), - (KSHIFTRQri (KSHIFTLQri (COPY_TO_REGCLASS VK4:$mask, VK64), - (i8 60)), (i8 60))>; -} diff --git a/suite/synctools/tablegen/X86/back/X86InstrXOP.td b/suite/synctools/tablegen/X86/back/X86InstrXOP.td deleted file mode 100644 index ff3e3be48a..0000000000 --- a/suite/synctools/tablegen/X86/back/X86InstrXOP.td +++ /dev/null @@ -1,446 +0,0 @@ -//===-- X86InstrXOP.td - XOP Instruction Set ---------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes XOP (eXtended OPerations) -// -//===----------------------------------------------------------------------===// - -multiclass xop2op opc, string OpcodeStr, Intrinsic Int, PatFrag memop> { - def rr : IXOP, XOP, Sched<[SchedWritePHAdd.XMM]>; - def rm : IXOP, XOP, - Sched<[SchedWritePHAdd.XMM.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPHSUBWD : xop2op<0xE2, "vphsubwd", int_x86_xop_vphsubwd, loadv2i64>; - defm VPHSUBDQ : xop2op<0xE3, "vphsubdq", int_x86_xop_vphsubdq, loadv2i64>; - defm VPHSUBBW : xop2op<0xE1, "vphsubbw", int_x86_xop_vphsubbw, loadv2i64>; - defm VPHADDWQ : xop2op<0xC7, "vphaddwq", int_x86_xop_vphaddwq, loadv2i64>; - defm VPHADDWD : xop2op<0xC6, "vphaddwd", int_x86_xop_vphaddwd, loadv2i64>; - defm VPHADDUWQ : xop2op<0xD7, "vphadduwq", int_x86_xop_vphadduwq, loadv2i64>; - defm VPHADDUWD : xop2op<0xD6, "vphadduwd", int_x86_xop_vphadduwd, loadv2i64>; - defm VPHADDUDQ : xop2op<0xDB, "vphaddudq", int_x86_xop_vphaddudq, loadv2i64>; - defm VPHADDUBW : xop2op<0xD1, "vphaddubw", int_x86_xop_vphaddubw, loadv2i64>; - defm VPHADDUBQ : xop2op<0xD3, "vphaddubq", int_x86_xop_vphaddubq, loadv2i64>; - defm VPHADDUBD : xop2op<0xD2, "vphaddubd", int_x86_xop_vphaddubd, loadv2i64>; - defm VPHADDDQ : xop2op<0xCB, "vphadddq", int_x86_xop_vphadddq, loadv2i64>; - defm VPHADDBW : xop2op<0xC1, "vphaddbw", int_x86_xop_vphaddbw, loadv2i64>; - defm VPHADDBQ : xop2op<0xC3, "vphaddbq", int_x86_xop_vphaddbq, loadv2i64>; - defm VPHADDBD : xop2op<0xC2, "vphaddbd", int_x86_xop_vphaddbd, loadv2i64>; -} - -// Scalar load 2 addr operand instructions -multiclass xop2opsld opc, string OpcodeStr, Intrinsic Int, - Operand memop, ComplexPattern mem_cpat, - X86FoldableSchedWrite sched> { - def rr : IXOP, XOP, Sched<[sched]>; - def rm : IXOP, XOP, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass xop2op128 opc, string OpcodeStr, Intrinsic Int, - PatFrag memop, X86FoldableSchedWrite sched> { - def rr : IXOP, XOP, Sched<[sched]>; - def rm : IXOP, XOP, - Sched<[sched.Folded, ReadAfterLd]>; -} - -multiclass xop2op256 opc, string OpcodeStr, Intrinsic Int, - PatFrag memop, X86FoldableSchedWrite sched> { - def Yrr : IXOP, XOP, VEX_L, Sched<[sched]>; - def Yrm : IXOP, XOP, VEX_L, - Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedSingle in { - defm VFRCZSS : xop2opsld<0x82, "vfrczss", int_x86_xop_vfrcz_ss, - ssmem, sse_load_f32, SchedWriteFRnd.Scl>; - defm VFRCZPS : xop2op128<0x80, "vfrczps", int_x86_xop_vfrcz_ps, loadv4f32, - SchedWriteFRnd.XMM>; - defm VFRCZPS : xop2op256<0x80, "vfrczps", int_x86_xop_vfrcz_ps_256, loadv8f32, - SchedWriteFRnd.YMM>; -} - -let ExeDomain = SSEPackedDouble in { - defm VFRCZSD : xop2opsld<0x83, "vfrczsd", int_x86_xop_vfrcz_sd, - sdmem, sse_load_f64, SchedWriteFRnd.Scl>; - defm VFRCZPD : xop2op128<0x81, "vfrczpd", int_x86_xop_vfrcz_pd, loadv2f64, - SchedWriteFRnd.XMM>; - defm VFRCZPD : xop2op256<0x81, "vfrczpd", int_x86_xop_vfrcz_pd_256, loadv4f64, - SchedWriteFRnd.YMM>; -} - -multiclass xop3op opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def rr : IXOP, - XOP, Sched<[sched]>; - def rm : IXOP, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd]>; - def mr : IXOP, - XOP, Sched<[sched.Folded, ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : IXOP, - XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPROTB : xop3op<0x90, "vprotb", rotl, v16i8, SchedWriteVarVecShift.XMM>; - defm VPROTD : xop3op<0x92, "vprotd", rotl, v4i32, SchedWriteVarVecShift.XMM>; - defm VPROTQ : xop3op<0x93, "vprotq", rotl, v2i64, SchedWriteVarVecShift.XMM>; - defm VPROTW : xop3op<0x91, "vprotw", rotl, v8i16, SchedWriteVarVecShift.XMM>; - defm VPSHAB : xop3op<0x98, "vpshab", X86vpsha, v16i8, SchedWriteVarVecShift.XMM>; - defm VPSHAD : xop3op<0x9A, "vpshad", X86vpsha, v4i32, SchedWriteVarVecShift.XMM>; - defm VPSHAQ : xop3op<0x9B, "vpshaq", X86vpsha, v2i64, SchedWriteVarVecShift.XMM>; - defm VPSHAW : xop3op<0x99, "vpshaw", X86vpsha, v8i16, SchedWriteVarVecShift.XMM>; - defm VPSHLB : xop3op<0x94, "vpshlb", X86vpshl, v16i8, SchedWriteVarVecShift.XMM>; - defm VPSHLD : xop3op<0x96, "vpshld", X86vpshl, v4i32, SchedWriteVarVecShift.XMM>; - defm VPSHLQ : xop3op<0x97, "vpshlq", X86vpshl, v2i64, SchedWriteVarVecShift.XMM>; - defm VPSHLW : xop3op<0x95, "vpshlw", X86vpshl, v8i16, SchedWriteVarVecShift.XMM>; -} - -multiclass xop3opimm opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def ri : IXOPi8, - XOP, Sched<[sched]>; - def mi : IXOPi8, - XOP, Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPROTB : xop3opimm<0xC0, "vprotb", X86vrotli, v16i8, - SchedWriteVecShiftImm.XMM>; - defm VPROTD : xop3opimm<0xC2, "vprotd", X86vrotli, v4i32, - SchedWriteVecShiftImm.XMM>; - defm VPROTQ : xop3opimm<0xC3, "vprotq", X86vrotli, v2i64, - SchedWriteVecShiftImm.XMM>; - defm VPROTW : xop3opimm<0xC1, "vprotw", X86vrotli, v8i16, - SchedWriteVecShiftImm.XMM>; -} - -// Instruction where second source can be memory, but third must be register -multiclass xop4opm2 opc, string OpcodeStr, Intrinsic Int, - X86FoldableSchedWrite sched> { - let isCommutable = 1 in - def rr : IXOPi8Reg, XOP_4V, - Sched<[sched]>; - def rm : IXOPi8Reg, XOP_4V, Sched<[sched.Folded, ReadAfterLd]>; -} - -let ExeDomain = SSEPackedInt in { - defm VPMADCSWD : xop4opm2<0xB6, "vpmadcswd", - int_x86_xop_vpmadcswd, SchedWriteVecIMul.XMM>; - defm VPMADCSSWD : xop4opm2<0xA6, "vpmadcsswd", - int_x86_xop_vpmadcsswd, SchedWriteVecIMul.XMM>; - defm VPMACSWW : xop4opm2<0x95, "vpmacsww", - int_x86_xop_vpmacsww, SchedWriteVecIMul.XMM>; - defm VPMACSWD : xop4opm2<0x96, "vpmacswd", - int_x86_xop_vpmacswd, SchedWriteVecIMul.XMM>; - defm VPMACSSWW : xop4opm2<0x85, "vpmacssww", - int_x86_xop_vpmacssww, SchedWriteVecIMul.XMM>; - defm VPMACSSWD : xop4opm2<0x86, "vpmacsswd", - int_x86_xop_vpmacsswd, SchedWriteVecIMul.XMM>; - defm VPMACSSDQL : xop4opm2<0x87, "vpmacssdql", - int_x86_xop_vpmacssdql, SchedWritePMULLD.XMM>; - defm VPMACSSDQH : xop4opm2<0x8F, "vpmacssdqh", - int_x86_xop_vpmacssdqh, SchedWritePMULLD.XMM>; - defm VPMACSSDD : xop4opm2<0x8E, "vpmacssdd", - int_x86_xop_vpmacssdd, SchedWritePMULLD.XMM>; - defm VPMACSDQL : xop4opm2<0x97, "vpmacsdql", - int_x86_xop_vpmacsdql, SchedWritePMULLD.XMM>; - defm VPMACSDQH : xop4opm2<0x9F, "vpmacsdqh", - int_x86_xop_vpmacsdqh, SchedWritePMULLD.XMM>; - defm VPMACSDD : xop4opm2<0x9E, "vpmacsdd", - int_x86_xop_vpmacsdd, SchedWritePMULLD.XMM>; -} - -// IFMA patterns - for cases where we can safely ignore the overflow bits from -// the multiply or easily match with existing intrinsics. -let Predicates = [HasXOP] in { - def : Pat<(v8i16 (add (mul (v8i16 VR128:$src1), (v8i16 VR128:$src2)), - (v8i16 VR128:$src3))), - (VPMACSWWrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v4i32 (add (mul (v4i32 VR128:$src1), (v4i32 VR128:$src2)), - (v4i32 VR128:$src3))), - (VPMACSDDrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v2i64 (add (X86pmuldq (bc_v2i64 (X86PShufd (v4i32 VR128:$src1), (i8 -11))), - (bc_v2i64 (X86PShufd (v4i32 VR128:$src2), (i8 -11)))), - (v2i64 VR128:$src3))), - (VPMACSDQHrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v2i64 (add (X86pmuldq (v2i64 VR128:$src1), (v2i64 VR128:$src2)), - (v2i64 VR128:$src3))), - (VPMACSDQLrr VR128:$src1, VR128:$src2, VR128:$src3)>; - def : Pat<(v4i32 (add (X86vpmaddwd (v8i16 VR128:$src1), (v8i16 VR128:$src2)), - (v4i32 VR128:$src3))), - (VPMADCSWDrr VR128:$src1, VR128:$src2, VR128:$src3)>; -} - -// Transforms to swizzle an immediate to help matching memory operand in first -// operand. -def CommuteVPCOMCC : SDNodeXFormgetZExtValue() & 0x7; - Imm = X86::getSwappedVPCOMImm(Imm); - return getI8Imm(Imm, SDLoc(N)); -}]>; - -// Instruction where second source can be memory, third must be imm8 -multiclass xopvpcom opc, string Suffix, SDNode OpNode, ValueType vt128, - X86FoldableSchedWrite sched> { - let ExeDomain = SSEPackedInt in { // SSE integer instructions - let isCommutable = 1 in - def ri : IXOPi8, - XOP_4V, Sched<[sched]>; - def mi : IXOPi8, - XOP_4V, Sched<[sched.Folded, ReadAfterLd]>; - let isAsmParserOnly = 1, hasSideEffects = 0 in { - def ri_alt : IXOPi8, XOP_4V, Sched<[sched]>, NotMemoryFoldable; - let mayLoad = 1 in - def mi_alt : IXOPi8, XOP_4V, Sched<[sched.Folded, ReadAfterLd]>, - NotMemoryFoldable; - } - } - - def : Pat<(OpNode (bitconvert (loadv2i64 addr:$src2)), - (vt128 VR128:$src1), imm:$cc), - (!cast(NAME#"mi") VR128:$src1, addr:$src2, - (CommuteVPCOMCC imm:$cc))>; -} - -defm VPCOMB : xopvpcom<0xCC, "b", X86vpcom, v16i8, SchedWriteVecALU.XMM>; -defm VPCOMW : xopvpcom<0xCD, "w", X86vpcom, v8i16, SchedWriteVecALU.XMM>; -defm VPCOMD : xopvpcom<0xCE, "d", X86vpcom, v4i32, SchedWriteVecALU.XMM>; -defm VPCOMQ : xopvpcom<0xCF, "q", X86vpcom, v2i64, SchedWriteVecALU.XMM>; -defm VPCOMUB : xopvpcom<0xEC, "ub", X86vpcomu, v16i8, SchedWriteVecALU.XMM>; -defm VPCOMUW : xopvpcom<0xED, "uw", X86vpcomu, v8i16, SchedWriteVecALU.XMM>; -defm VPCOMUD : xopvpcom<0xEE, "ud", X86vpcomu, v4i32, SchedWriteVecALU.XMM>; -defm VPCOMUQ : xopvpcom<0xEF, "uq", X86vpcomu, v2i64, SchedWriteVecALU.XMM>; - -multiclass xop4op opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, X86FoldableSchedWrite sched> { - def rrr : IXOPi8Reg, - XOP_4V, Sched<[sched]>; - def rrm : IXOPi8Reg, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def rmr : IXOPi8Reg, - XOP_4V, Sched<[sched.Folded, ReadAfterLd, - // 128mem:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // VR128:$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8Reg, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPPERM : xop4op<0xA3, "vpperm", X86vpperm, v16i8, - SchedWriteVarShuffle.XMM>; -} - -// Instruction where either second or third source can be memory -multiclass xop4op_int opc, string OpcodeStr, RegisterClass RC, - X86MemOperand x86memop, ValueType VT, - X86FoldableSchedWrite sched> { - def rrr : IXOPi8Reg, XOP_4V, - Sched<[sched]>; - def rrm : IXOPi8Reg, - XOP_4V, VEX_W, Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def rmr : IXOPi8Reg, - XOP_4V, Sched<[sched.Folded, ReadAfterLd, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC::$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8Reg, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedInt in { - defm VPCMOV : xop4op_int<0xA2, "vpcmov", VR128, i128mem, v2i64, - SchedWriteShuffle.XMM>; - defm VPCMOVY : xop4op_int<0xA2, "vpcmov", VR256, i256mem, v4i64, - SchedWriteShuffle.YMM>, VEX_L; -} - -multiclass xop_vpermil2 Opc, string OpcodeStr, RegisterClass RC, - X86MemOperand intmemop, X86MemOperand fpmemop, - ValueType VT, PatFrag FPLdFrag, PatFrag IntLdFrag, - X86FoldableSchedWrite sched> { - def rr : IXOP5, - Sched<[sched]>; - def rm : IXOP5, VEX_W, - Sched<[sched.Folded, ReadAfterLd, ReadAfterLd]>; - def mr : IXOP5, - Sched<[sched.Folded, ReadAfterLd, - // fpmemop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, - // RC:$src3 - ReadAfterLd]>; - // For disassembler - let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rr_REV : IXOP5, VEX_W, Sched<[sched]>, FoldGenData; -} - -let ExeDomain = SSEPackedDouble in { - defm VPERMIL2PD : xop_vpermil2<0x49, "vpermil2pd", VR128, i128mem, f128mem, - v2f64, loadv2f64, loadv2i64, - SchedWriteFVarShuffle.XMM>; - defm VPERMIL2PDY : xop_vpermil2<0x49, "vpermil2pd", VR256, i256mem, f256mem, - v4f64, loadv4f64, loadv4i64, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - -let ExeDomain = SSEPackedSingle in { - defm VPERMIL2PS : xop_vpermil2<0x48, "vpermil2ps", VR128, i128mem, f128mem, - v4f32, loadv4f32, loadv2i64, - SchedWriteFVarShuffle.XMM>; - defm VPERMIL2PSY : xop_vpermil2<0x48, "vpermil2ps", VR256, i256mem, f256mem, - v8f32, loadv8f32, loadv4i64, - SchedWriteFVarShuffle.YMM>, VEX_L; -} - diff --git a/suite/synctools/tablegen/X86/back/X86PfmCounters.td b/suite/synctools/tablegen/X86/back/X86PfmCounters.td deleted file mode 100644 index 093fbafa3f..0000000000 --- a/suite/synctools/tablegen/X86/back/X86PfmCounters.td +++ /dev/null @@ -1,77 +0,0 @@ -//===-- X86PfmCounters.td - X86 Hardware Counters ----------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This describes the available hardware counters for various subtargets. -// -//===----------------------------------------------------------------------===// - -let SchedModel = SandyBridgeModel in { -def SBCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SBPort0Counter : PfmIssueCounter; -def SBPort1Counter : PfmIssueCounter; -def SBPort23Counter : PfmIssueCounter; -def SBPort4Counter : PfmIssueCounter; -def SBPort5Counter : PfmIssueCounter; -} - -let SchedModel = HaswellModel in { -def HWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def HWPort0Counter : PfmIssueCounter; -def HWPort1Counter : PfmIssueCounter; -def HWPort2Counter : PfmIssueCounter; -def HWPort3Counter : PfmIssueCounter; -def HWPort4Counter : PfmIssueCounter; -def HWPort5Counter : PfmIssueCounter; -def HWPort6Counter : PfmIssueCounter; -def HWPort7Counter : PfmIssueCounter; -} - -let SchedModel = BroadwellModel in { -def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def BWPort0Counter : PfmIssueCounter; -def BWPort1Counter : PfmIssueCounter; -def BWPort2Counter : PfmIssueCounter; -def BWPort3Counter : PfmIssueCounter; -def BWPort4Counter : PfmIssueCounter; -def BWPort5Counter : PfmIssueCounter; -def BWPort6Counter : PfmIssueCounter; -def BWPort7Counter : PfmIssueCounter; -} - -let SchedModel = SkylakeClientModel in { -def SKLCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SKLPort0Counter : PfmIssueCounter; -def SKLPort1Counter : PfmIssueCounter; -def SKLPort2Counter : PfmIssueCounter; -def SKLPort3Counter : PfmIssueCounter; -def SKLPort4Counter : PfmIssueCounter; -def SKLPort5Counter : PfmIssueCounter; -def SKLPort6Counter : PfmIssueCounter; -def SKLPort7Counter : PfmIssueCounter; -} - -let SchedModel = SkylakeServerModel in { -def SKXCycleCounter : PfmCycleCounter<"unhalted_core_cycles">; -def SKXPort0Counter : PfmIssueCounter; -def SKXPort1Counter : PfmIssueCounter; -def SKXPort2Counter : PfmIssueCounter; -def SKXPort3Counter : PfmIssueCounter; -def SKXPort4Counter : PfmIssueCounter; -def SKXPort5Counter : PfmIssueCounter; -def SKXPort6Counter : PfmIssueCounter; -def SKXPort7Counter : PfmIssueCounter; -} - -let SchedModel = BtVer2Model in { -def JCycleCounter : PfmCycleCounter<"cpu_clk_unhalted">; -def JFPU0Counter : PfmIssueCounter; -def JFPU1Counter : PfmIssueCounter; -} diff --git a/suite/synctools/tablegen/X86/back/X86RegisterBanks.td b/suite/synctools/tablegen/X86/back/X86RegisterBanks.td deleted file mode 100644 index 6d17cd53a0..0000000000 --- a/suite/synctools/tablegen/X86/back/X86RegisterBanks.td +++ /dev/null @@ -1,17 +0,0 @@ -//=- X86RegisterBank.td - Describe the AArch64 Banks -----*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -/// General Purpose Registers: RAX, RCX,... -def GPRRegBank : RegisterBank<"GPR", [GR64]>; - -/// Floating Point/Vector Registers -def VECRRegBank : RegisterBank<"VECR", [VR512]>; diff --git a/suite/synctools/tablegen/X86/back/X86RegisterInfo.td b/suite/synctools/tablegen/X86/back/X86RegisterInfo.td deleted file mode 100644 index 907d402223..0000000000 --- a/suite/synctools/tablegen/X86/back/X86RegisterInfo.td +++ /dev/null @@ -1,591 +0,0 @@ -//===- X86RegisterInfo.td - Describe the X86 Register File --*- tablegen -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the X86 Register file, defining the registers themselves, -// aliases between the registers, and the register classes built out of the -// registers. -// -//===----------------------------------------------------------------------===// - -class X86Reg Enc, list subregs = []> : Register { - let Namespace = "X86"; - let HWEncoding = Enc; - let SubRegs = subregs; -} - -// Subregister indices. -let Namespace = "X86" in { - def sub_8bit : SubRegIndex<8>; - def sub_8bit_hi : SubRegIndex<8, 8>; - def sub_8bit_hi_phony : SubRegIndex<8, 8>; - def sub_16bit : SubRegIndex<16>; - def sub_16bit_hi : SubRegIndex<16, 16>; - def sub_32bit : SubRegIndex<32>; - def sub_xmm : SubRegIndex<128>; - def sub_ymm : SubRegIndex<256>; -} - -//===----------------------------------------------------------------------===// -// Register definitions... -// - -// In the register alias definitions below, we define which registers alias -// which others. We only specify which registers the small registers alias, -// because the register file generator is smart enough to figure out that -// AL aliases AX if we tell it that AX aliased AL (for example). - -// Dwarf numbering is different for 32-bit and 64-bit, and there are -// variations by target as well. Currently the first entry is for X86-64, -// second - for EH on X86-32/Darwin and third is 'generic' one (X86-32/Linux -// and debug information on X86-32/Darwin) - -// 8-bit registers -// Low registers -def AL : X86Reg<"al", 0>; -def DL : X86Reg<"dl", 2>; -def CL : X86Reg<"cl", 1>; -def BL : X86Reg<"bl", 3>; - -// High registers. On x86-64, these cannot be used in any instruction -// with a REX prefix. -def AH : X86Reg<"ah", 4>; -def DH : X86Reg<"dh", 6>; -def CH : X86Reg<"ch", 5>; -def BH : X86Reg<"bh", 7>; - -// X86-64 only, requires REX. -let CostPerUse = 1 in { -def SIL : X86Reg<"sil", 6>; -def DIL : X86Reg<"dil", 7>; -def BPL : X86Reg<"bpl", 5>; -def SPL : X86Reg<"spl", 4>; -def R8B : X86Reg<"r8b", 8>; -def R9B : X86Reg<"r9b", 9>; -def R10B : X86Reg<"r10b", 10>; -def R11B : X86Reg<"r11b", 11>; -def R12B : X86Reg<"r12b", 12>; -def R13B : X86Reg<"r13b", 13>; -def R14B : X86Reg<"r14b", 14>; -def R15B : X86Reg<"r15b", 15>; -} - -let isArtificial = 1 in { -// High byte of the low 16 bits of the super-register: -def SIH : X86Reg<"", -1>; -def DIH : X86Reg<"", -1>; -def BPH : X86Reg<"", -1>; -def SPH : X86Reg<"", -1>; -def R8BH : X86Reg<"", -1>; -def R9BH : X86Reg<"", -1>; -def R10BH : X86Reg<"", -1>; -def R11BH : X86Reg<"", -1>; -def R12BH : X86Reg<"", -1>; -def R13BH : X86Reg<"", -1>; -def R14BH : X86Reg<"", -1>; -def R15BH : X86Reg<"", -1>; -// High word of the low 32 bits of the super-register: -def HAX : X86Reg<"", -1>; -def HDX : X86Reg<"", -1>; -def HCX : X86Reg<"", -1>; -def HBX : X86Reg<"", -1>; -def HSI : X86Reg<"", -1>; -def HDI : X86Reg<"", -1>; -def HBP : X86Reg<"", -1>; -def HSP : X86Reg<"", -1>; -def HIP : X86Reg<"", -1>; -def R8WH : X86Reg<"", -1>; -def R9WH : X86Reg<"", -1>; -def R10WH : X86Reg<"", -1>; -def R11WH : X86Reg<"", -1>; -def R12WH : X86Reg<"", -1>; -def R13WH : X86Reg<"", -1>; -def R14WH : X86Reg<"", -1>; -def R15WH : X86Reg<"", -1>; -} - -// 16-bit registers -let SubRegIndices = [sub_8bit, sub_8bit_hi], CoveredBySubRegs = 1 in { -def AX : X86Reg<"ax", 0, [AL,AH]>; -def DX : X86Reg<"dx", 2, [DL,DH]>; -def CX : X86Reg<"cx", 1, [CL,CH]>; -def BX : X86Reg<"bx", 3, [BL,BH]>; -} -let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CoveredBySubRegs = 1 in { -def SI : X86Reg<"si", 6, [SIL,SIH]>; -def DI : X86Reg<"di", 7, [DIL,DIH]>; -def BP : X86Reg<"bp", 5, [BPL,BPH]>; -def SP : X86Reg<"sp", 4, [SPL,SPH]>; -} -def IP : X86Reg<"ip", 0>; - -// X86-64 only, requires REX. -let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CostPerUse = 1, - CoveredBySubRegs = 1 in { -def R8W : X86Reg<"r8w", 8, [R8B,R8BH]>; -def R9W : X86Reg<"r9w", 9, [R9B,R9BH]>; -def R10W : X86Reg<"r10w", 10, [R10B,R10BH]>; -def R11W : X86Reg<"r11w", 11, [R11B,R11BH]>; -def R12W : X86Reg<"r12w", 12, [R12B,R12BH]>; -def R13W : X86Reg<"r13w", 13, [R13B,R13BH]>; -def R14W : X86Reg<"r14w", 14, [R14B,R14BH]>; -def R15W : X86Reg<"r15w", 15, [R15B,R15BH]>; -} - -// 32-bit registers -let SubRegIndices = [sub_16bit, sub_16bit_hi], CoveredBySubRegs = 1 in { -def EAX : X86Reg<"eax", 0, [AX, HAX]>, DwarfRegNum<[-2, 0, 0]>; -def EDX : X86Reg<"edx", 2, [DX, HDX]>, DwarfRegNum<[-2, 2, 2]>; -def ECX : X86Reg<"ecx", 1, [CX, HCX]>, DwarfRegNum<[-2, 1, 1]>; -def EBX : X86Reg<"ebx", 3, [BX, HBX]>, DwarfRegNum<[-2, 3, 3]>; -def ESI : X86Reg<"esi", 6, [SI, HSI]>, DwarfRegNum<[-2, 6, 6]>; -def EDI : X86Reg<"edi", 7, [DI, HDI]>, DwarfRegNum<[-2, 7, 7]>; -def EBP : X86Reg<"ebp", 5, [BP, HBP]>, DwarfRegNum<[-2, 4, 5]>; -def ESP : X86Reg<"esp", 4, [SP, HSP]>, DwarfRegNum<[-2, 5, 4]>; -def EIP : X86Reg<"eip", 0, [IP, HIP]>, DwarfRegNum<[-2, 8, 8]>; -} - -// X86-64 only, requires REX -let SubRegIndices = [sub_16bit, sub_16bit_hi], CostPerUse = 1, - CoveredBySubRegs = 1 in { -def R8D : X86Reg<"r8d", 8, [R8W,R8WH]>; -def R9D : X86Reg<"r9d", 9, [R9W,R9WH]>; -def R10D : X86Reg<"r10d", 10, [R10W,R10WH]>; -def R11D : X86Reg<"r11d", 11, [R11W,R11WH]>; -def R12D : X86Reg<"r12d", 12, [R12W,R12WH]>; -def R13D : X86Reg<"r13d", 13, [R13W,R13WH]>; -def R14D : X86Reg<"r14d", 14, [R14W,R14WH]>; -def R15D : X86Reg<"r15d", 15, [R15W,R15WH]>; -} - -// 64-bit registers, X86-64 only -let SubRegIndices = [sub_32bit] in { -def RAX : X86Reg<"rax", 0, [EAX]>, DwarfRegNum<[0, -2, -2]>; -def RDX : X86Reg<"rdx", 2, [EDX]>, DwarfRegNum<[1, -2, -2]>; -def RCX : X86Reg<"rcx", 1, [ECX]>, DwarfRegNum<[2, -2, -2]>; -def RBX : X86Reg<"rbx", 3, [EBX]>, DwarfRegNum<[3, -2, -2]>; -def RSI : X86Reg<"rsi", 6, [ESI]>, DwarfRegNum<[4, -2, -2]>; -def RDI : X86Reg<"rdi", 7, [EDI]>, DwarfRegNum<[5, -2, -2]>; -def RBP : X86Reg<"rbp", 5, [EBP]>, DwarfRegNum<[6, -2, -2]>; -def RSP : X86Reg<"rsp", 4, [ESP]>, DwarfRegNum<[7, -2, -2]>; - -// These also require REX. -let CostPerUse = 1 in { -def R8 : X86Reg<"r8", 8, [R8D]>, DwarfRegNum<[ 8, -2, -2]>; -def R9 : X86Reg<"r9", 9, [R9D]>, DwarfRegNum<[ 9, -2, -2]>; -def R10 : X86Reg<"r10", 10, [R10D]>, DwarfRegNum<[10, -2, -2]>; -def R11 : X86Reg<"r11", 11, [R11D]>, DwarfRegNum<[11, -2, -2]>; -def R12 : X86Reg<"r12", 12, [R12D]>, DwarfRegNum<[12, -2, -2]>; -def R13 : X86Reg<"r13", 13, [R13D]>, DwarfRegNum<[13, -2, -2]>; -def R14 : X86Reg<"r14", 14, [R14D]>, DwarfRegNum<[14, -2, -2]>; -def R15 : X86Reg<"r15", 15, [R15D]>, DwarfRegNum<[15, -2, -2]>; -def RIP : X86Reg<"rip", 0, [EIP]>, DwarfRegNum<[16, -2, -2]>; -}} - -// MMX Registers. These are actually aliased to ST0 .. ST7 -def MM0 : X86Reg<"mm0", 0>, DwarfRegNum<[41, 29, 29]>; -def MM1 : X86Reg<"mm1", 1>, DwarfRegNum<[42, 30, 30]>; -def MM2 : X86Reg<"mm2", 2>, DwarfRegNum<[43, 31, 31]>; -def MM3 : X86Reg<"mm3", 3>, DwarfRegNum<[44, 32, 32]>; -def MM4 : X86Reg<"mm4", 4>, DwarfRegNum<[45, 33, 33]>; -def MM5 : X86Reg<"mm5", 5>, DwarfRegNum<[46, 34, 34]>; -def MM6 : X86Reg<"mm6", 6>, DwarfRegNum<[47, 35, 35]>; -def MM7 : X86Reg<"mm7", 7>, DwarfRegNum<[48, 36, 36]>; - -// Pseudo Floating Point registers -def FP0 : X86Reg<"fp0", 0>; -def FP1 : X86Reg<"fp1", 0>; -def FP2 : X86Reg<"fp2", 0>; -def FP3 : X86Reg<"fp3", 0>; -def FP4 : X86Reg<"fp4", 0>; -def FP5 : X86Reg<"fp5", 0>; -def FP6 : X86Reg<"fp6", 0>; -def FP7 : X86Reg<"fp7", 0>; - -// XMM Registers, used by the various SSE instruction set extensions. -def XMM0: X86Reg<"xmm0", 0>, DwarfRegNum<[17, 21, 21]>; -def XMM1: X86Reg<"xmm1", 1>, DwarfRegNum<[18, 22, 22]>; -def XMM2: X86Reg<"xmm2", 2>, DwarfRegNum<[19, 23, 23]>; -def XMM3: X86Reg<"xmm3", 3>, DwarfRegNum<[20, 24, 24]>; -def XMM4: X86Reg<"xmm4", 4>, DwarfRegNum<[21, 25, 25]>; -def XMM5: X86Reg<"xmm5", 5>, DwarfRegNum<[22, 26, 26]>; -def XMM6: X86Reg<"xmm6", 6>, DwarfRegNum<[23, 27, 27]>; -def XMM7: X86Reg<"xmm7", 7>, DwarfRegNum<[24, 28, 28]>; - -// X86-64 only -let CostPerUse = 1 in { -def XMM8: X86Reg<"xmm8", 8>, DwarfRegNum<[25, -2, -2]>; -def XMM9: X86Reg<"xmm9", 9>, DwarfRegNum<[26, -2, -2]>; -def XMM10: X86Reg<"xmm10", 10>, DwarfRegNum<[27, -2, -2]>; -def XMM11: X86Reg<"xmm11", 11>, DwarfRegNum<[28, -2, -2]>; -def XMM12: X86Reg<"xmm12", 12>, DwarfRegNum<[29, -2, -2]>; -def XMM13: X86Reg<"xmm13", 13>, DwarfRegNum<[30, -2, -2]>; -def XMM14: X86Reg<"xmm14", 14>, DwarfRegNum<[31, -2, -2]>; -def XMM15: X86Reg<"xmm15", 15>, DwarfRegNum<[32, -2, -2]>; - -def XMM16: X86Reg<"xmm16", 16>, DwarfRegNum<[67, -2, -2]>; -def XMM17: X86Reg<"xmm17", 17>, DwarfRegNum<[68, -2, -2]>; -def XMM18: X86Reg<"xmm18", 18>, DwarfRegNum<[69, -2, -2]>; -def XMM19: X86Reg<"xmm19", 19>, DwarfRegNum<[70, -2, -2]>; -def XMM20: X86Reg<"xmm20", 20>, DwarfRegNum<[71, -2, -2]>; -def XMM21: X86Reg<"xmm21", 21>, DwarfRegNum<[72, -2, -2]>; -def XMM22: X86Reg<"xmm22", 22>, DwarfRegNum<[73, -2, -2]>; -def XMM23: X86Reg<"xmm23", 23>, DwarfRegNum<[74, -2, -2]>; -def XMM24: X86Reg<"xmm24", 24>, DwarfRegNum<[75, -2, -2]>; -def XMM25: X86Reg<"xmm25", 25>, DwarfRegNum<[76, -2, -2]>; -def XMM26: X86Reg<"xmm26", 26>, DwarfRegNum<[77, -2, -2]>; -def XMM27: X86Reg<"xmm27", 27>, DwarfRegNum<[78, -2, -2]>; -def XMM28: X86Reg<"xmm28", 28>, DwarfRegNum<[79, -2, -2]>; -def XMM29: X86Reg<"xmm29", 29>, DwarfRegNum<[80, -2, -2]>; -def XMM30: X86Reg<"xmm30", 30>, DwarfRegNum<[81, -2, -2]>; -def XMM31: X86Reg<"xmm31", 31>, DwarfRegNum<[82, -2, -2]>; - -} // CostPerUse - -// YMM0-15 registers, used by AVX instructions and -// YMM16-31 registers, used by AVX-512 instructions. -let SubRegIndices = [sub_xmm] in { - foreach Index = 0-31 in { - def YMM#Index : X86Reg<"ymm"#Index, Index, [!cast("XMM"#Index)]>, - DwarfRegAlias("XMM"#Index)>; - } -} - -// ZMM Registers, used by AVX-512 instructions. -let SubRegIndices = [sub_ymm] in { - foreach Index = 0-31 in { - def ZMM#Index : X86Reg<"zmm"#Index, Index, [!cast("YMM"#Index)]>, - DwarfRegAlias("XMM"#Index)>; - } -} - -// Mask Registers, used by AVX-512 instructions. -def K0 : X86Reg<"k0", 0>, DwarfRegNum<[118, 93, 93]>; -def K1 : X86Reg<"k1", 1>, DwarfRegNum<[119, 94, 94]>; -def K2 : X86Reg<"k2", 2>, DwarfRegNum<[120, 95, 95]>; -def K3 : X86Reg<"k3", 3>, DwarfRegNum<[121, 96, 96]>; -def K4 : X86Reg<"k4", 4>, DwarfRegNum<[122, 97, 97]>; -def K5 : X86Reg<"k5", 5>, DwarfRegNum<[123, 98, 98]>; -def K6 : X86Reg<"k6", 6>, DwarfRegNum<[124, 99, 99]>; -def K7 : X86Reg<"k7", 7>, DwarfRegNum<[125, 100, 100]>; - -// Floating point stack registers. These don't map one-to-one to the FP -// pseudo registers, but we still mark them as aliasing FP registers. That -// way both kinds can be live without exceeding the stack depth. ST registers -// are only live around inline assembly. -def ST0 : X86Reg<"st(0)", 0>, DwarfRegNum<[33, 12, 11]>; -def ST1 : X86Reg<"st(1)", 1>, DwarfRegNum<[34, 13, 12]>; -def ST2 : X86Reg<"st(2)", 2>, DwarfRegNum<[35, 14, 13]>; -def ST3 : X86Reg<"st(3)", 3>, DwarfRegNum<[36, 15, 14]>; -def ST4 : X86Reg<"st(4)", 4>, DwarfRegNum<[37, 16, 15]>; -def ST5 : X86Reg<"st(5)", 5>, DwarfRegNum<[38, 17, 16]>; -def ST6 : X86Reg<"st(6)", 6>, DwarfRegNum<[39, 18, 17]>; -def ST7 : X86Reg<"st(7)", 7>, DwarfRegNum<[40, 19, 18]>; - -// Floating-point status word -def FPSW : X86Reg<"fpsw", 0>; - -// Status flags register. -// -// Note that some flags that are commonly thought of as part of the status -// flags register are modeled separately. Typically this is due to instructions -// reading and updating those flags independently of all the others. We don't -// want to create false dependencies between these instructions and so we use -// a separate register to model them. -def EFLAGS : X86Reg<"flags", 0>; - -// The direction flag. -def DF : X86Reg<"dirflag", 0>; - - -// Segment registers -def CS : X86Reg<"cs", 1>; -def DS : X86Reg<"ds", 3>; -def SS : X86Reg<"ss", 2>; -def ES : X86Reg<"es", 0>; -def FS : X86Reg<"fs", 4>; -def GS : X86Reg<"gs", 5>; - -// Debug registers -def DR0 : X86Reg<"dr0", 0>; -def DR1 : X86Reg<"dr1", 1>; -def DR2 : X86Reg<"dr2", 2>; -def DR3 : X86Reg<"dr3", 3>; -def DR4 : X86Reg<"dr4", 4>; -def DR5 : X86Reg<"dr5", 5>; -def DR6 : X86Reg<"dr6", 6>; -def DR7 : X86Reg<"dr7", 7>; -def DR8 : X86Reg<"dr8", 8>; -def DR9 : X86Reg<"dr9", 9>; -def DR10 : X86Reg<"dr10", 10>; -def DR11 : X86Reg<"dr11", 11>; -def DR12 : X86Reg<"dr12", 12>; -def DR13 : X86Reg<"dr13", 13>; -def DR14 : X86Reg<"dr14", 14>; -def DR15 : X86Reg<"dr15", 15>; - -// Control registers -def CR0 : X86Reg<"cr0", 0>; -def CR1 : X86Reg<"cr1", 1>; -def CR2 : X86Reg<"cr2", 2>; -def CR3 : X86Reg<"cr3", 3>; -def CR4 : X86Reg<"cr4", 4>; -def CR5 : X86Reg<"cr5", 5>; -def CR6 : X86Reg<"cr6", 6>; -def CR7 : X86Reg<"cr7", 7>; -def CR8 : X86Reg<"cr8", 8>; -def CR9 : X86Reg<"cr9", 9>; -def CR10 : X86Reg<"cr10", 10>; -def CR11 : X86Reg<"cr11", 11>; -def CR12 : X86Reg<"cr12", 12>; -def CR13 : X86Reg<"cr13", 13>; -def CR14 : X86Reg<"cr14", 14>; -def CR15 : X86Reg<"cr15", 15>; - -// Pseudo index registers -def EIZ : X86Reg<"eiz", 4>; -def RIZ : X86Reg<"riz", 4>; - -// Bound registers, used in MPX instructions -def BND0 : X86Reg<"bnd0", 0>; -def BND1 : X86Reg<"bnd1", 1>; -def BND2 : X86Reg<"bnd2", 2>; -def BND3 : X86Reg<"bnd3", 3>; - -// CET registers - Shadow Stack Pointer -def SSP : X86Reg<"ssp", 0>; - -//===----------------------------------------------------------------------===// -// Register Class Definitions... now that we have all of the pieces, define the -// top-level register classes. The order specified in the register list is -// implicitly defined to be the register allocation order. -// - -// List call-clobbered registers before callee-save registers. RBX, RBP, (and -// R12, R13, R14, and R15 for X86-64) are callee-save registers. -// In 64-mode, there are 12 additional i8 registers, SIL, DIL, BPL, SPL, and -// R8B, ... R15B. -// Allocate R12 and R13 last, as these require an extra byte when -// encoded in x86_64 instructions. -// FIXME: Allow AH, CH, DH, BH to be used as general-purpose registers in -// 64-bit mode. The main complication is that they cannot be encoded in an -// instruction requiring a REX prefix, while SIL, DIL, BPL, R8D, etc. -// require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d" -// cannot be encoded. -def GR8 : RegisterClass<"X86", [i8], 8, - (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL, - R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B)> { - let AltOrders = [(sub GR8, AH, BH, CH, DH)]; - let AltOrderSelect = [{ - return MF.getSubtarget().is64Bit(); - }]; -} - -let isAllocatable = 0 in -def GRH8 : RegisterClass<"X86", [i8], 8, - (add SIH, DIH, BPH, SPH, R8BH, R9BH, R10BH, R11BH, - R12BH, R13BH, R14BH, R15BH)>; - -def GR16 : RegisterClass<"X86", [i16], 16, - (add AX, CX, DX, SI, DI, BX, BP, SP, - R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W)>; - -let isAllocatable = 0 in -def GRH16 : RegisterClass<"X86", [i16], 16, - (add HAX, HCX, HDX, HSI, HDI, HBX, HBP, HSP, HIP, - R8WH, R9WH, R10WH, R11WH, R12WH, R13WH, R14WH, - R15WH)>; - -def GR32 : RegisterClass<"X86", [i32], 32, - (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, - R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D)>; - -// GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since -// RIP isn't really a register and it can't be used anywhere except in an -// address, but it doesn't cause trouble. -// FIXME: it *does* cause trouble - CheckBaseRegAndIndexReg() has extra -// tests because of the inclusion of RIP in this register class. -def GR64 : RegisterClass<"X86", [i64], 64, - (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - RBX, R14, R15, R12, R13, RBP, RSP, RIP)>; - -// Segment registers for use by MOV instructions (and others) that have a -// segment register as one operand. Always contain a 16-bit segment -// descriptor. -def SEGMENT_REG : RegisterClass<"X86", [i16], 16, (add CS, DS, SS, ES, FS, GS)>; - -// Debug registers. -def DEBUG_REG : RegisterClass<"X86", [i32], 32, (sequence "DR%u", 0, 15)>; - -// Control registers. -def CONTROL_REG : RegisterClass<"X86", [i64], 64, (sequence "CR%u", 0, 15)>; - -// GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD, GR64_ABCD - Subclasses of -// GR8, GR16, GR32, and GR64 which contain just the "a" "b", "c", and "d" -// registers. On x86-32, GR16_ABCD and GR32_ABCD are classes for registers -// that support 8-bit subreg operations. On x86-64, GR16_ABCD, GR32_ABCD, -// and GR64_ABCD are classes for registers that support 8-bit h-register -// operations. -def GR8_ABCD_L : RegisterClass<"X86", [i8], 8, (add AL, CL, DL, BL)>; -def GR8_ABCD_H : RegisterClass<"X86", [i8], 8, (add AH, CH, DH, BH)>; -def GR16_ABCD : RegisterClass<"X86", [i16], 16, (add AX, CX, DX, BX)>; -def GR32_ABCD : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX, EBX)>; -def GR64_ABCD : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RBX)>; -def GR32_TC : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX)>; -def GR64_TC : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RSI, RDI, - R8, R9, R11, RIP)>; -def GR64_TCW64 : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, - R8, R9, R10, R11, RIP)>; - -// GR8_NOREX - GR8 registers which do not require a REX prefix. -def GR8_NOREX : RegisterClass<"X86", [i8], 8, - (add AL, CL, DL, AH, CH, DH, BL, BH)> { - let AltOrders = [(sub GR8_NOREX, AH, BH, CH, DH)]; - let AltOrderSelect = [{ - return MF.getSubtarget().is64Bit(); - }]; -} -// GR16_NOREX - GR16 registers which do not require a REX prefix. -def GR16_NOREX : RegisterClass<"X86", [i16], 16, - (add AX, CX, DX, SI, DI, BX, BP, SP)>; -// GR32_NOREX - GR32 registers which do not require a REX prefix. -def GR32_NOREX : RegisterClass<"X86", [i32], 32, - (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP)>; -// GR64_NOREX - GR64 registers which do not require a REX prefix. -def GR64_NOREX : RegisterClass<"X86", [i64], 64, - (add RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP, RIP)>; - -// GR32_NOSP - GR32 registers except ESP. -def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)>; - -// GR64_NOSP - GR64 registers except RSP (and RIP). -def GR64_NOSP : RegisterClass<"X86", [i64], 64, (sub GR64, RSP, RIP)>; - -// GR32_NOREX_NOSP - GR32 registers which do not require a REX prefix except -// ESP. -def GR32_NOREX_NOSP : RegisterClass<"X86", [i32], 32, - (and GR32_NOREX, GR32_NOSP)>; - -// GR64_NOREX_NOSP - GR64_NOREX registers except RSP. -def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64, - (and GR64_NOREX, GR64_NOSP)>; - -// Register classes used for ABIs that use 32-bit address accesses, -// while using the whole x84_64 ISA. - -// In such cases, it is fine to use RIP as we are sure the 32 high -// bits are not set. We do not need variants for NOSP as RIP is not -// allowed there. -// RIP is not spilled anywhere for now, so stick to 32-bit alignment -// to save on memory space. -// FIXME: We could allow all 64bit registers, but we would need -// something to check that the 32 high bits are not set, -// which we do not have right now. -def LOW32_ADDR_ACCESS : RegisterClass<"X86", [i32], 32, (add GR32, RIP)>; - -// When RBP is used as a base pointer in a 32-bit addresses environment, -// this is also safe to use the full register to access addresses. -// Since RBP will never be spilled, stick to a 32 alignment to save -// on memory consumption. -def LOW32_ADDR_ACCESS_RBP : RegisterClass<"X86", [i32], 32, - (add LOW32_ADDR_ACCESS, RBP)>; - -// A class to support the 'A' assembler constraint: [ER]AX then [ER]DX. -def GR32_AD : RegisterClass<"X86", [i32], 32, (add EAX, EDX)>; -def GR64_AD : RegisterClass<"X86", [i64], 64, (add RAX, RDX)>; - -// Scalar SSE2 floating point registers. -def FR32 : RegisterClass<"X86", [f32], 32, (sequence "XMM%u", 0, 15)>; - -def FR64 : RegisterClass<"X86", [f64], 64, (add FR32)>; - - -// FIXME: This sets up the floating point register files as though they are f64 -// values, though they really are f80 values. This will cause us to spill -// values as 64-bit quantities instead of 80-bit quantities, which is much much -// faster on common hardware. In reality, this should be controlled by a -// command line option or something. - -def RFP32 : RegisterClass<"X86",[f32], 32, (sequence "FP%u", 0, 6)>; -def RFP64 : RegisterClass<"X86",[f64], 32, (add RFP32)>; -def RFP80 : RegisterClass<"X86",[f80], 32, (add RFP32)>; - -// Floating point stack registers (these are not allocatable by the -// register allocator - the floating point stackifier is responsible -// for transforming FPn allocations to STn registers) -def RST : RegisterClass<"X86", [f80, f64, f32], 32, (sequence "ST%u", 0, 7)> { - let isAllocatable = 0; -} - -// Generic vector registers: VR64 and VR128. -// Ensure that float types are declared first - only float is legal on SSE1. -def VR64: RegisterClass<"X86", [x86mmx], 64, (sequence "MM%u", 0, 7)>; -def VR128 : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (add FR32)>; -def VR256 : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 15)>; - -// Special classes that help the assembly parser choose some alternate -// instructions to favor 2-byte VEX encodings. -def VR128L : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (sequence "XMM%u", 0, 7)>; -def VR128H : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (sequence "XMM%u", 8, 15)>; -def VR256L : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 7)>; -def VR256H : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 8, 15)>; - -// Status flags registers. -def CCR : RegisterClass<"X86", [i32], 32, (add EFLAGS)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} -def FPCCR : RegisterClass<"X86", [i16], 16, (add FPSW)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} -def DFCCR : RegisterClass<"X86", [i32], 32, (add DF)> { - let CopyCost = -1; // Don't allow copying of status registers. - let isAllocatable = 0; -} - -// AVX-512 vector/mask registers. -def VR512 : RegisterClass<"X86", [v16f32, v8f64, v64i8, v32i16, v16i32, v8i64], - 512, (sequence "ZMM%u", 0, 31)>; - -// Scalar AVX-512 floating point registers. -def FR32X : RegisterClass<"X86", [f32], 32, (sequence "XMM%u", 0, 31)>; - -def FR64X : RegisterClass<"X86", [f64], 64, (add FR32X)>; - -// Extended VR128 and VR256 for AVX-512 instructions -def VR128X : RegisterClass<"X86", [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64, f128], - 128, (add FR32X)>; -def VR256X : RegisterClass<"X86", [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64], - 256, (sequence "YMM%u", 0, 31)>; - -// Mask registers -def VK1 : RegisterClass<"X86", [v1i1], 16, (sequence "K%u", 0, 7)> {let Size = 16;} -def VK2 : RegisterClass<"X86", [v2i1], 16, (add VK1)> {let Size = 16;} -def VK4 : RegisterClass<"X86", [v4i1], 16, (add VK2)> {let Size = 16;} -def VK8 : RegisterClass<"X86", [v8i1], 16, (add VK4)> {let Size = 16;} -def VK16 : RegisterClass<"X86", [v16i1], 16, (add VK8)> {let Size = 16;} -def VK32 : RegisterClass<"X86", [v32i1], 32, (add VK16)> {let Size = 32;} -def VK64 : RegisterClass<"X86", [v64i1], 64, (add VK32)> {let Size = 64;} - -def VK1WM : RegisterClass<"X86", [v1i1], 16, (sub VK1, K0)> {let Size = 16;} -def VK2WM : RegisterClass<"X86", [v2i1], 16, (sub VK2, K0)> {let Size = 16;} -def VK4WM : RegisterClass<"X86", [v4i1], 16, (sub VK4, K0)> {let Size = 16;} -def VK8WM : RegisterClass<"X86", [v8i1], 16, (sub VK8, K0)> {let Size = 16;} -def VK16WM : RegisterClass<"X86", [v16i1], 16, (add VK8WM)> {let Size = 16;} -def VK32WM : RegisterClass<"X86", [v32i1], 32, (add VK16WM)> {let Size = 32;} -def VK64WM : RegisterClass<"X86", [v64i1], 64, (add VK32WM)> {let Size = 64;} - -// Bound registers -def BNDR : RegisterClass<"X86", [v2i64], 128, (sequence "BND%u", 0, 3)>; diff --git a/suite/synctools/tablegen/X86/back/X86SchedBroadwell.td b/suite/synctools/tablegen/X86/back/X86SchedBroadwell.td deleted file mode 100755 index 6334d9e89a..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedBroadwell.td +++ /dev/null @@ -1,1692 +0,0 @@ -//=- X86SchedBroadwell.td - X86 Broadwell Scheduling ---------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Broadwell to support instruction -// scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def BroadwellModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and BW can decode 4 - // instructions per cycle. - let IssueWidth = 4; - let MicroOpBufferSize = 192; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = BroadwellModel in { - -// Broadwell can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def BWPort0 : ProcResource<1>; -def BWPort1 : ProcResource<1>; -def BWPort2 : ProcResource<1>; -def BWPort3 : ProcResource<1>; -def BWPort4 : ProcResource<1>; -def BWPort5 : ProcResource<1>; -def BWPort6 : ProcResource<1>; -def BWPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def BWPort01 : ProcResGroup<[BWPort0, BWPort1]>; -def BWPort23 : ProcResGroup<[BWPort2, BWPort3]>; -def BWPort237 : ProcResGroup<[BWPort2, BWPort3, BWPort7]>; -def BWPort04 : ProcResGroup<[BWPort0, BWPort4]>; -def BWPort05 : ProcResGroup<[BWPort0, BWPort5]>; -def BWPort06 : ProcResGroup<[BWPort0, BWPort6]>; -def BWPort15 : ProcResGroup<[BWPort1, BWPort5]>; -def BWPort16 : ProcResGroup<[BWPort1, BWPort6]>; -def BWPort56 : ProcResGroup<[BWPort5, BWPort6]>; -def BWPort015 : ProcResGroup<[BWPort0, BWPort1, BWPort5]>; -def BWPort056 : ProcResGroup<[BWPort0, BWPort5, BWPort6]>; -def BWPort0156: ProcResGroup<[BWPort0, BWPort1, BWPort5, BWPort6]>; - -// 60 Entry Unified Scheduler -def BWPortAny : ProcResGroup<[BWPort0, BWPort1, BWPort2, BWPort3, BWPort4, - BWPort5, BWPort6, BWPort7]> { - let BufferSize=60; -} - -// Integer division issued on port 0. -def BWDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def BWFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass BWWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : BWWriteResPair; // Simple integer ALU op. -defm : BWWriteResPair; // Integer ALU + flags op. -defm : BWWriteResPair; // Integer multiplication. -defm : BWWriteResPair; // Integer 64-bit multiplication. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : BWWriteResPair; -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. - -def : WriteRes; // LEA instructions can't fold loads. - -defm : BWWriteResPair; // Conditional move. -defm : BWWriteResPair; // // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. - -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // Bit Test instrs - -// Bit counts. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Integer shifts and rotates. -defm : BWWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// BMI1 BEXTR, BMI2 BZHI -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : BWWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : BWWriteResPair; // Floating point add/sub. -defm : BWWriteResPair; // Floating point add/sub (XMM). -defm : BWWriteResPair; // Floating point add/sub (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double add/sub. -defm : BWWriteResPair; // Floating point double add/sub (XMM). -defm : BWWriteResPair; // Floating point double add/sub (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point compare. -defm : BWWriteResPair; // Floating point compare (XMM). -defm : BWWriteResPair; // Floating point compare (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double compare. -defm : BWWriteResPair; // Floating point double compare (XMM). -defm : BWWriteResPair; // Floating point double compare (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point compare to flags. - -defm : BWWriteResPair; // Floating point multiplication. -defm : BWWriteResPair; // Floating point multiplication (XMM). -defm : BWWriteResPair; // Floating point multiplication (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double multiplication. -defm : BWWriteResPair; // Floating point double multiplication (XMM). -defm : BWWriteResPair; // Floating point double multiplication (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -//defm : BWWriteResPair; // Floating point division. -defm : BWWriteResPair; // Floating point division (XMM). -defm : BWWriteResPair; // Floating point division (YMM). -defm : X86WriteResPairUnsupported; -//defm : BWWriteResPair; // Floating point division. -defm : BWWriteResPair; // Floating point division (XMM). -defm : BWWriteResPair; // Floating point division (YMM). -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; // Floating point square root. -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point square root (XMM). -defm : BWWriteResPair; // Floating point square root (YMM). -defm : X86WriteResPairUnsupported; -defm : X86WriteRes; // Floating point double square root. -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point double square root (XMM). -defm : BWWriteResPair; // Floating point double square root (YMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point long double square root. - -defm : BWWriteResPair; // Floating point reciprocal estimate. -defm : BWWriteResPair; // Floating point reciprocal estimate (XMM). -defm : BWWriteResPair; // Floating point reciprocal estimate (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Floating point reciprocal square root estimate. -defm : BWWriteResPair; // Floating point reciprocal square root estimate (XMM). -defm : BWWriteResPair; // Floating point reciprocal square root estimate (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; // Fused Multiply Add. -defm : BWWriteResPair; // Fused Multiply Add (XMM). -defm : BWWriteResPair; // Fused Multiply Add (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point double dot product. -defm : BWWriteResPair; // Floating point single dot product. -defm : BWWriteResPair; // Floating point single dot product (YMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point fabs/fchs. -defm : X86WriteRes; // Floating point rounding. -defm : X86WriteRes; // Floating point rounding (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : BWWriteResPair; // Floating point and/or/xor logicals. -defm : BWWriteResPair; // Floating point and/or/xor logicals (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point TEST instructions. -defm : BWWriteResPair; // Floating point TEST instructions (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector shuffles. -defm : BWWriteResPair; // Floating point vector shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector variable shuffles. -defm : BWWriteResPair; // Floating point vector variable shuffles. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Floating point vector blends. -defm : BWWriteResPair; // Floating point vector blends. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Fp vector variable blends. -defm : BWWriteResPair; // Fp vector variable blends. -defm : X86WriteResPairUnsupported; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; - -defm : BWWriteResPair; // Vector integer ALU op, no logicals. -defm : BWWriteResPair; // Vector integer ALU op, no logicals. -defm : BWWriteResPair; // Vector integer ALU op, no logicals (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer and/or/xor. -defm : BWWriteResPair; // Vector integer and/or/xor. -defm : BWWriteResPair; // Vector integer and/or/xor (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer TEST instructions. -defm : BWWriteResPair; // Vector integer TEST instructions (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector integer multiply. -defm : BWWriteResPair; // Vector integer multiply. -defm : BWWriteResPair; // Vector integer multiply. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PMULLD. -defm : BWWriteResPair; // Vector PMULLD (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector shuffles. -defm : BWWriteResPair; // Vector shuffles. -defm : BWWriteResPair; // Vector shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector variable shuffles. -defm : BWWriteResPair; // Vector variable shuffles. -defm : BWWriteResPair; // Vector variable shuffles (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector blends. -defm : BWWriteResPair; // Vector blends (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector variable blends. -defm : BWWriteResPair; // Vector variable blends (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector MPSAD. -defm : BWWriteResPair; // Vector MPSAD. -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PSADBW. -defm : BWWriteResPair; // Vector PSADBW. -defm : BWWriteResPair; // Vector PSADBW (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; // Vector integer immediate shifts (XMM). -defm : BWWriteResPair; // Vector integer immediate shifts (YMM/ZMM). -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; // Variable vector shifts. -defm : BWWriteResPair; // Variable vector shifts (YMM/ZMM). -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} - -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 23; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 1; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 14; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 19; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 29; - let NumMicroOps = 11; - let ResourceCycles = [2,7,2]; -} -def : WriteRes { - let Latency = 33; - let NumMicroOps = 11; - let ResourceCycles = [2,7,1,1]; -} - -// Carry-less multiplication instructions. -defm : BWWriteResPair; - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : BWWriteResPair; // Fp 256-bit width vector shuffles. -defm : BWWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : BWWriteResPair; // 256-bit width vector shuffles. -defm : BWWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; -defm : BWWriteResPair; - -// Remaining instrs. - -def BWWriteResGroup1 : SchedWriteRes<[BWPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup1], (instregex "VPSLLVQ(Y?)rr", - "VPSRLVQ(Y?)rr")>; - -def BWWriteResGroup2 : SchedWriteRes<[BWPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup2], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def BWWriteResGroup3 : SchedWriteRes<[BWPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup3], (instregex "MMX_MOVQ2DQrr")>; - -def BWWriteResGroup4 : SchedWriteRes<[BWPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def BWWriteResGroup5 : SchedWriteRes<[BWPort01]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup5], (instrs FINCSTP, FNOP)>; - -def BWWriteResGroup6 : SchedWriteRes<[BWPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup6], (instrs CDQ, CQO)>; - -def BWWriteResGroup7 : SchedWriteRes<[BWPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup7], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def BWWriteResGroup8 : SchedWriteRes<[BWPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup8], (instregex "VPBLENDD(Y?)rri")>; - -def BWWriteResGroup9 : SchedWriteRes<[BWPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup9], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def BWWriteResGroup10 : SchedWriteRes<[BWPort4,BWPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup10], (instregex "FBSTPm", - "ST_FP(32|64|80)m")>; - -def BWWriteResGroup12 : SchedWriteRes<[BWPort01]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup12], (instrs FDECSTP)>; - -def BWWriteResGroup13 : SchedWriteRes<[BWPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup13], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri")>; - -def BWWriteResGroup14 : SchedWriteRes<[BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[BWWriteResGroup14], (instrs LFENCE, - MFENCE, - WAIT, - XGETBV)>; - -def BWWriteResGroup15 : SchedWriteRes<[BWPort0,BWPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup15], (instregex "(V?)CVTPS2PDrr", - "(V?)CVTSS2SDrr")>; - -def BWWriteResGroup16 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup16], (instregex "CLFLUSH")>; - -def BWWriteResGroup17 : SchedWriteRes<[BWPort01,BWPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup17], (instregex "MMX_MOVDQ2Qrr")>; - -def BWWriteResGroup18 : SchedWriteRes<[BWPort237,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup18], (instrs SFENCE)>; - -def BWWriteResGroup20 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup20], (instrs CWD)>; -def: InstRW<[BWWriteResGroup20], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[BWWriteResGroup20], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri", - "SET(A|BE)r")>; - -def BWWriteResGroup22 : SchedWriteRes<[BWPort4,BWPort6,BWPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup22], (instrs FNSTCW16m)>; - -def BWWriteResGroup24 : SchedWriteRes<[BWPort4,BWPort237,BWPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup24], (instregex "MOVBE(16|32|64)mr")>; - -def BWWriteResGroup25 : SchedWriteRes<[BWPort4,BWPort237,BWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup25], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[BWWriteResGroup25], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def BWWriteResGroup27 : SchedWriteRes<[BWPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup27], (instregex "MMX_CVTPI2PSirr", - "PDEP(32|64)rr", - "PEXT(32|64)rr", - "(V?)CVTDQ2PS(Y?)rr")>; - -def BWWriteResGroup27_16 : SchedWriteRes<[BWPort1, BWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup27_16], (instrs IMUL16rri, IMUL16rri8)>; - -def BWWriteResGroup28 : SchedWriteRes<[BWPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup28], (instregex "VPBROADCASTBrr", - "VPBROADCASTWrr")>; - -def BWWriteResGroup30 : SchedWriteRes<[BWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[BWWriteResGroup30], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def BWWriteResGroup33 : SchedWriteRes<[BWPort5,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup33], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def BWWriteResGroup34 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup34], (instregex "CLD")>; - -def BWWriteResGroup35 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup35], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def BWWriteResGroup36 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup36], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def BWWriteResGroup37 : SchedWriteRes<[BWPort4,BWPort6,BWPort237,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup37], (instregex "CALL(16|32|64)r")>; - -def BWWriteResGroup38 : SchedWriteRes<[BWPort4,BWPort237,BWPort06,BWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup38], (instrs CALL64pcrel32)>; -def: InstRW<[BWWriteResGroup38], (instregex "SET(A|BE)m")>; - -def BWWriteResGroup39 : SchedWriteRes<[BWPort0,BWPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup39], (instregex "(V?)CVT(T?)SD2SI64rr", - "(V?)CVT(T?)SD2SIrr", - "(V?)CVT(T?)SS2SI64rr", - "(V?)CVT(T?)SS2SIrr")>; - -def BWWriteResGroup40 : SchedWriteRes<[BWPort0,BWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup40], (instregex "VCVTPS2PDYrr")>; - -def BWWriteResGroup41 : SchedWriteRes<[BWPort0,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup41], (instrs FNSTSW16r)>; - -def BWWriteResGroup42 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup42], (instrs IMUL64r, MUL64r, MULX64rr)>; -def: InstRW<[BWWriteResGroup42], (instregex "MMX_CVTPI2PDirr", - "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVTDQ2PDrr", - "(V?)CVTPD2PSrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI642SDrr", - "(V?)CVTSI2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVT(T?)PD2DQrr")>; - -def BWWriteResGroup42_16 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[BWWriteResGroup42_16], (instrs IMUL16r, MUL16r)>; - -def BWWriteResGroup43 : SchedWriteRes<[BWPort0,BWPort4,BWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup43], (instrs FNSTSWm)>; - -def BWWriteResGroup44 : SchedWriteRes<[BWPort1,BWPort4,BWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup44], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def BWWriteResGroup45 : SchedWriteRes<[BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[BWWriteResGroup45], (instrs FNCLEX)>; - -def BWWriteResGroup46 : SchedWriteRes<[BWPort015,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[BWWriteResGroup46], (instrs VZEROUPPER)>; - -def BWWriteResGroup47 : SchedWriteRes<[BWPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup47], (instregex "(V?)PCMPGTQ(Y?)rr", - "MUL_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup49 : SchedWriteRes<[BWPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup49], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "VBROADCASTSSrm", - "(V?)MOVDDUPrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def BWWriteResGroup50 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup50], (instregex "(V?)CVTSI642SSrr")>; - -def BWWriteResGroup51 : SchedWriteRes<[BWPort1,BWPort6,BWPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup51], (instregex "STR(16|32|64)r")>; - -def BWWriteResGroup52 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup52], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def BWWriteResGroup54 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[BWWriteResGroup54], (instrs PAUSE)>; - -def BWWriteResGroup55 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[BWWriteResGroup55], (instrs XSETBV)>; - -def BWWriteResGroup56 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[BWWriteResGroup56], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def BWWriteResGroup57 : SchedWriteRes<[BWPort4,BWPort237,BWPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[BWWriteResGroup57], (instregex "PUSHF(16|64)")>; - -def BWWriteResGroup58 : SchedWriteRes<[BWPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup58], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def BWWriteResGroup59 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup59], (instregex "(V?)CVTPS2PDrm", - "(V?)CVTSS2SDrm", - "VPSLLVQrm", - "VPSRLVQrm")>; - -def BWWriteResGroup60 : SchedWriteRes<[BWPort1,BWPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup60], (instregex "VCVTDQ2PDYrr", - "VCVTPD2PSYrr", - "VCVT(T?)PD2DQYrr")>; - -def BWWriteResGroup62 : SchedWriteRes<[BWPort6,BWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup62], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def BWWriteResGroup63 : SchedWriteRes<[BWPort23,BWPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup63], (instregex "BT(16|32|64)mi8")>; - -def BWWriteResGroup64 : SchedWriteRes<[BWPort23,BWPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup64], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def BWWriteResGroup65 : SchedWriteRes<[BWPort23,BWPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup65], (instregex "VINSERTF128rm", - "VINSERTI128rm", - "VPBLENDDrmi")>; - -def BWWriteResGroup66 : SchedWriteRes<[BWPort23,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup66], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[BWWriteResGroup66], (instregex "POP(16|32|64)rmr")>; - -def BWWriteResGroup68 : SchedWriteRes<[BWPort1,BWPort6,BWPort06,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup68], (instregex "SLDT(16|32|64)r")>; - -def BWWriteResGroup69 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup69], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def BWWriteResGroup70 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup70], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def BWWriteResGroup71 : SchedWriteRes<[BWPort6,BWPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[BWWriteResGroup71], (instrs STD)>; - -def BWWriteResGroup73 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup73], (instregex "VPSLLVQYrm", - "VPSRLVQYrm")>; - -def BWWriteResGroup74 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup74], (instregex "FCOM(P?)(32|64)m")>; - -def BWWriteResGroup77 : SchedWriteRes<[BWPort23,BWPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup77], (instregex "VPBLENDDYrmi")>; - -def BWWriteResGroup79 : SchedWriteRes<[BWPort5,BWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup79], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def BWWriteResGroup80 : SchedWriteRes<[BWPort23,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[BWWriteResGroup80], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def BWWriteResGroup82 : SchedWriteRes<[BWPort0,BWPort01,BWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup82], (instrs FLDCW16m)>; - -def BWWriteResGroup84 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup84], (instrs LRETQ, RETQ)>; - -def BWWriteResGroup87 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup87], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def BWWriteResGroup88 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup88], (instregex "XADD(8|16|32|64)rm")>; - -def BWWriteResGroup89 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[BWWriteResGroup89], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def BWWriteResGroup90 : SchedWriteRes<[BWPort6,BWPort06,BWPort15,BWPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [2,2,1,2]; -} -def: InstRW<[BWWriteResGroup90], (instrs LOOP)>; - -def BWWriteResGroup91 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup91], (instregex "MMX_CVTPI2PSirm", - "PDEP(32|64)rm", - "PEXT(32|64)rm", - "(V?)CVTDQ2PSrm")>; - -def BWWriteResGroup91_16 : SchedWriteRes<[BWPort1, BWPort0156, BWPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup91_16], (instrs IMUL16rmi, IMUL16rmi8)>; - -def BWWriteResGroup91_16_2 : SchedWriteRes<[BWPort1, BWPort06, BWPort0156, BWPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[BWWriteResGroup91_16_2], (instrs IMUL16m, MUL16m)>; - -def BWWriteResGroup92 : SchedWriteRes<[BWPort5,BWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup92], (instregex "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVSXWQYrm", - "VPMOVZXWDYrm")>; - -def BWWriteResGroup97 : SchedWriteRes<[BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[BWWriteResGroup97], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def BWWriteResGroup98 : SchedWriteRes<[BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[BWWriteResGroup98], (instregex "ROR(8|16|32|64)mCL")>; - -def BWWriteResGroup99 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[BWWriteResGroup99], (instregex "XCHG(8|16|32|64)rm")>; - -def BWWriteResGroup100 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def : SchedAlias; -def: InstRW<[BWWriteResGroup100], (instregex "CMPXCHG(8|16|32|64)rm", - "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def BWWriteResGroup101 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup101], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VCVTPS2DQYrm", - "VCVTTPS2DQYrm")>; - -def BWWriteResGroup105 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup105], (instregex "(V?)CVTSS2SI(64)?rm", - "(V?)CVT(T?)SD2SI64rm", - "(V?)CVT(T?)SD2SIrm", - "VCVTTSS2SI64rm", - "(V?)CVTTSS2SIrm")>; - -def BWWriteResGroup106 : SchedWriteRes<[BWPort0,BWPort5,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup106], (instregex "VCVTPS2PDYrm")>; - -def BWWriteResGroup107 : SchedWriteRes<[BWPort1,BWPort5,BWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup107], (instrs IMUL64m, MUL64m, MULX64rm)>; -def: InstRW<[BWWriteResGroup107], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVTPI2PDirm", - "MMX_CVT(T?)PD2PIirm", - "(V?)CVTDQ2PDrm", - "(V?)CVTSD2SSrm")>; - -def BWWriteResGroup108 : SchedWriteRes<[BWPort5,BWPort23,BWPort015]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup108], (instregex "VPBROADCASTB(Y?)rm", - "VPBROADCASTW(Y?)rm")>; - -def BWWriteResGroup112 : SchedWriteRes<[BWPort23,BWPort06,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[BWWriteResGroup112], (instregex "RDRAND(16|32|64)r")>; - -def BWWriteResGroup113 : SchedWriteRes<[BWPort1,BWPort6,BWPort23,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[BWWriteResGroup113], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def BWWriteResGroup115 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup115], (instregex "(V?)PCMPGTQrm")>; - -def BWWriteResGroup117 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup117], (instregex "FICOM(P?)(16|32)m")>; - -def BWWriteResGroup120 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup120], (instregex "CVTTSS2SI64rm")>; - -def BWWriteResGroup121 : SchedWriteRes<[BWPort1,BWPort23,BWPort06,BWPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[BWWriteResGroup121], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def BWWriteResGroup122_1 : SchedWriteRes<[BWPort0,BWFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; // Really 2.5 cycle throughput -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup123 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup123], (instregex "MUL_F(32|64)m", - "VPCMPGTQYrm")>; - -def BWWriteResGroup128 : SchedWriteRes<[BWPort1,BWPort5,BWPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup128], (instregex "VCVTDQ2PDYrm")>; - -def BWWriteResGroup131 : SchedWriteRes<[BWPort1,BWPort06,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,2,3]; -} -def: InstRW<[BWWriteResGroup131], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def BWWriteResGroup132 : SchedWriteRes<[BWPort1,BWPort06,BWPort15,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,4,1,3]; -} -def: InstRW<[BWWriteResGroup132], (instregex "RCL8rCL")>; - -def BWWriteResGroup133 : SchedWriteRes<[BWPort06,BWPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[BWWriteResGroup133], (instrs LOOPE)>; -def: InstRW<[BWWriteResGroup133], (instrs LOOPNE)>; - -def BWWriteResGroup135 : SchedWriteRes<[BWPort1,BWPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[BWWriteResGroup135], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def BWWriteResGroup139_1 : SchedWriteRes<[BWPort0,BWFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup141 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup141], (instregex "MUL_FI(16|32)m")>; - -def BWWriteResGroup144 : SchedWriteRes<[BWPort1,BWPort6,BWPort23,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 8; - let ResourceCycles = [2,2,1,3]; -} -def: InstRW<[BWWriteResGroup144], (instregex "LAR(16|32|64)rr")>; - -def BWWriteResGroup145 : SchedWriteRes<[BWPort1,BWPort06,BWPort15,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,3,1,4]; -} -def: InstRW<[BWWriteResGroup145], (instregex "RCR8rCL")>; - -def BWWriteResGroup146 : SchedWriteRes<[BWPort0,BWPort1,BWPort6,BWPort0156]> { - let Latency = 14; - let NumMicroOps = 12; - let ResourceCycles = [2,1,4,5]; -} -def: InstRW<[BWWriteResGroup146], (instrs XCH_F)>; - -def BWWriteResGroup147 : SchedWriteRes<[BWPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup147], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup149 : SchedWriteRes<[BWPort1,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,4,1,2]; -} -def: InstRW<[BWWriteResGroup149], (instregex "RCL(8|16|32|64)mCL")>; - -def BWWriteResGroup150 : SchedWriteRes<[BWPort0,BWPort23,BWFPDivider]> { - let Latency = 16; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup153 : SchedWriteRes<[BWPort4,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[BWWriteResGroup153], (instrs CMPXCHG8B)>; - -def BWWriteResGroup154 : SchedWriteRes<[BWPort5]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[BWWriteResGroup154], (instrs VZEROALL)>; - -def BWWriteResGroup159 : SchedWriteRes<[BWPort5,BWPort6,BWPort06,BWPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[BWWriteResGroup159], (instrs CPUID)>; -def: InstRW<[BWWriteResGroup159], (instrs RDTSC)>; - -def BWWriteResGroup160 : SchedWriteRes<[BWPort1,BWPort23,BWPort237,BWPort06,BWPort15,BWPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,3,1,3]; -} -def: InstRW<[BWWriteResGroup160], (instregex "RCR(8|16|32|64)mCL")>; - -def BWWriteResGroup161 : SchedWriteRes<[BWPort0,BWPort23,BWFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def BWWriteResGroup165 : SchedWriteRes<[BWPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[BWWriteResGroup165], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def BWWriteResGroup167 : SchedWriteRes<[BWPort4,BWPort5,BWPort6,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[BWWriteResGroup167], (instrs INSB, INSL, INSW)>; - -def BWWriteResGroup169 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup169], (instregex "DIV_F(32|64)m")>; - -def BWWriteResGroup171 : SchedWriteRes<[BWPort0,BWPort4,BWPort5,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 21; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[BWWriteResGroup171], (instrs CMPXCHG16B)>; - -def BWWriteResGroup172 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 22; - let NumMicroOps = 18; - let ResourceCycles = [1,1,16]; -} -def: InstRW<[BWWriteResGroup172], (instregex "POPF64")>; - -def BWWriteResGroup176 : SchedWriteRes<[BWPort6,BWPort23,BWPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [3,1,15]; -} -def: InstRW<[BWWriteResGroup176], (instregex "XRSTOR(64)?")>; - -def BWWriteResGroup177 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 24; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup177], (instregex "DIV_FI(16|32)m")>; - -def BWWriteResGroup180 : SchedWriteRes<[BWPort0,BWPort23]> { - let Latency = 26; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[BWWriteResGroup180], (instregex "DIVR_F(32|64)m")>; - -def BWWriteResGroup182 : SchedWriteRes<[BWPort0,BWPort1,BWPort23]> { - let Latency = 29; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[BWWriteResGroup182], (instregex "DIVR_FI(16|32)m")>; - -def BWWriteResGroup183_1 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 22; - let NumMicroOps = 7; - let ResourceCycles = [1,3,2,1]; -} -def: InstRW<[BWWriteResGroup183_1], (instrs VGATHERQPDrm)>; - -def BWWriteResGroup183_2 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 23; - let NumMicroOps = 9; - let ResourceCycles = [1,3,4,1]; -} -def: InstRW<[BWWriteResGroup183_2], (instrs VGATHERQPDYrm)>; - -def BWWriteResGroup183_3 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_3], (instrs VGATHERQPSYrm)>; - -def BWWriteResGroup183_4 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 25; - let NumMicroOps = 7; - let ResourceCycles = [1,3,2,1]; -} -def: InstRW<[BWWriteResGroup183_4], (instrs VGATHERDPDrm, - VGATHERDPSrm)>; - -def BWWriteResGroup183_5 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 26; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_5], (instrs VGATHERDPDYrm)>; - -def BWWriteResGroup183_6 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 26; - let NumMicroOps = 14; - let ResourceCycles = [1,4,8,1]; -} -def: InstRW<[BWWriteResGroup183_6], (instrs VGATHERDPSYrm)>; - -def BWWriteResGroup183_7 : SchedWriteRes<[BWPort4, BWPort5, BWPort23, BWPort0156]> { - let Latency = 27; - let NumMicroOps = 9; - let ResourceCycles = [1,5,2,1]; -} -def: InstRW<[BWWriteResGroup183_7], (instrs VGATHERQPSrm)>; - -def BWWriteResGroup185 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 29; - let NumMicroOps = 27; - let ResourceCycles = [1,5,1,1,19]; -} -def: InstRW<[BWWriteResGroup185], (instrs XSAVE64)>; - -def BWWriteResGroup186 : SchedWriteRes<[BWPort4,BWPort6,BWPort23,BWPort237,BWPort0156]> { - let Latency = 30; - let NumMicroOps = 28; - let ResourceCycles = [1,6,1,1,19]; -} -def: InstRW<[BWWriteResGroup186], (instrs XSAVE)>; -def: InstRW<[BWWriteResGroup186], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def BWWriteResGroup190 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23,BWPort0156]> { - let Latency = 34; - let NumMicroOps = 8; - let ResourceCycles = [2,2,2,1,1]; -} -def: InstRW<[BWWriteResGroup190], (instregex "DIV(8|16|32|64)m")>; - -def BWWriteResGroup191 : SchedWriteRes<[BWPort5,BWPort6,BWPort23,BWPort06,BWPort0156]> { - let Latency = 34; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[BWWriteResGroup191], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def BWWriteResGroup193 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort23,BWPort0156]> { - let Latency = 35; - let NumMicroOps = 8; - let ResourceCycles = [2,2,2,1,1]; -} -def: InstRW<[BWWriteResGroup193], (instregex "IDIV(8|16|32|64)m")>; - -def BWWriteResGroup194 : SchedWriteRes<[BWPort5,BWPort6,BWPort23,BWPort237,BWPort06,BWPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[BWWriteResGroup194], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def BWWriteResGroup196 : SchedWriteRes<[BWPort5,BWPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[BWWriteResGroup196], (instrs RDTSCP)>; - -def BWWriteResGroup197 : SchedWriteRes<[BWPort0,BWPort01,BWPort23,BWPort05,BWPort06,BWPort015,BWPort0156]> { - let Latency = 60; - let NumMicroOps = 64; - let ResourceCycles = [2,2,8,1,10,2,39]; -} -def: InstRW<[BWWriteResGroup197], (instrs FLDENVm)>; - -def BWWriteResGroup198 : SchedWriteRes<[BWPort0,BWPort6,BWPort23,BWPort05,BWPort06,BWPort15,BWPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[BWWriteResGroup198], (instrs FXRSTOR64)>; - -def BWWriteResGroup199 : SchedWriteRes<[BWPort0,BWPort6,BWPort23,BWPort05,BWPort06,BWPort15,BWPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[BWWriteResGroup199], (instrs FXRSTOR)>; - -def BWWriteResGroup200 : SchedWriteRes<[BWPort5,BWPort01,BWPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[BWWriteResGroup200], (instrs FNINIT)>; - -def BWWriteResGroup201 : SchedWriteRes<[BWPort0,BWPort1,BWPort5,BWPort6,BWPort01,BWPort0156]> { - let Latency = 80; - let NumMicroOps = 32; - let ResourceCycles = [7,7,3,3,1,11]; -} -def: InstRW<[BWWriteResGroup201], (instregex "DIV(16|32|64)r")>; - -def BWWriteResGroup202 : SchedWriteRes<[BWPort0,BWPort1,BWPort4,BWPort5,BWPort6,BWPort237,BWPort06,BWPort0156]> { - let Latency = 115; - let NumMicroOps = 100; - let ResourceCycles = [9,9,11,8,1,11,21,30]; -} -def: InstRW<[BWWriteResGroup202], (instrs FSTENVm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86SchedHaswell.td b/suite/synctools/tablegen/X86/back/X86SchedHaswell.td deleted file mode 100644 index 876c3e4162..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedHaswell.td +++ /dev/null @@ -1,1975 +0,0 @@ -//=- X86SchedHaswell.td - X86 Haswell Scheduling -------------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Haswell to support instruction -// scheduling and other instruction cost heuristics. -// -// Note that we define some instructions here that are not supported by haswell, -// but we still have to define them because KNL uses the HSW model. -// They are currently tagged with a comment `Unsupported = 1`. -// FIXME: Use Unsupported = 1 once KNL has its own model. -// -//===----------------------------------------------------------------------===// - -def HaswellModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and HW can decode 4 - // instructions per cycle. - let IssueWidth = 4; - let MicroOpBufferSize = 192; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = HaswellModel in { - -// Haswell can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def HWPort0 : ProcResource<1>; -def HWPort1 : ProcResource<1>; -def HWPort2 : ProcResource<1>; -def HWPort3 : ProcResource<1>; -def HWPort4 : ProcResource<1>; -def HWPort5 : ProcResource<1>; -def HWPort6 : ProcResource<1>; -def HWPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def HWPort01 : ProcResGroup<[HWPort0, HWPort1]>; -def HWPort23 : ProcResGroup<[HWPort2, HWPort3]>; -def HWPort237 : ProcResGroup<[HWPort2, HWPort3, HWPort7]>; -def HWPort04 : ProcResGroup<[HWPort0, HWPort4]>; -def HWPort05 : ProcResGroup<[HWPort0, HWPort5]>; -def HWPort06 : ProcResGroup<[HWPort0, HWPort6]>; -def HWPort15 : ProcResGroup<[HWPort1, HWPort5]>; -def HWPort16 : ProcResGroup<[HWPort1, HWPort6]>; -def HWPort56 : ProcResGroup<[HWPort5, HWPort6]>; -def HWPort015 : ProcResGroup<[HWPort0, HWPort1, HWPort5]>; -def HWPort056 : ProcResGroup<[HWPort0, HWPort5, HWPort6]>; -def HWPort0156: ProcResGroup<[HWPort0, HWPort1, HWPort5, HWPort6]>; - -// 60 Entry Unified Scheduler -def HWPortAny : ProcResGroup<[HWPort0, HWPort1, HWPort2, HWPort3, HWPort4, - HWPort5, HWPort6, HWPort7]> { - let BufferSize=60; -} - -// Integer division issued on port 0. -def HWDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def HWFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass HWWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Store_addr on 237. -// Store_data on 4. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes; - -// Arithmetic. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -def : WriteRes { let Latency = 3; } - -// Integer shifts and rotates. -defm : HWWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : HWWriteResPair; // Conditional move. -defm : HWWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : HWWriteResPair; -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -// Conversion between integer and float. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; - -// Vector integer shifts. -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; // Unsupported = 1 - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// String instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 1; } - -// AES Instructions. -def : WriteRes { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 13; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { - let Latency = 14; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 20; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { - let Latency = 29; - let NumMicroOps = 11; - let ResourceCycles = [2,7,2]; -} -def : WriteRes { - let Latency = 34; - let NumMicroOps = 11; - let ResourceCycles = [2,7,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -//================ Exceptions ================// - -//-- Specific Scheduling Models --// - -// Starting with P0. -def HWWriteP0 : SchedWriteRes<[HWPort0]>; - -def HWWriteP01 : SchedWriteRes<[HWPort01]>; - -def HWWrite2P01 : SchedWriteRes<[HWPort01]> { - let NumMicroOps = 2; -} -def HWWrite3P01 : SchedWriteRes<[HWPort01]> { - let NumMicroOps = 3; -} - -def HWWriteP0156_P23 : SchedWriteRes<[HWPort0156, HWPort23]> { - let NumMicroOps = 2; -} - -def HWWrite2P0156_P23 : SchedWriteRes<[HWPort0156, HWPort23]> { - let NumMicroOps = 3; - let ResourceCycles = [2, 1]; -} - -// Starting with P1. -def HWWriteP1 : SchedWriteRes<[HWPort1]>; - - -def HWWrite2P1 : SchedWriteRes<[HWPort1]> { - let NumMicroOps = 2; - let ResourceCycles = [2]; -} - -// Notation: -// - r: register. -// - mm: 64 bit mmx register. -// - x = 128 bit xmm register. -// - (x)mm = mmx or xmm register. -// - y = 256 bit ymm register. -// - v = any vector register. -// - m = memory. - -//=== Integer Instructions ===// -//-- Move instructions --// - -// XLAT. -def HWWriteXLAT : SchedWriteRes<[]> { - let Latency = 7; - let NumMicroOps = 3; -} -def : InstRW<[HWWriteXLAT], (instrs XLAT)>; - -// PUSHA. -def HWWritePushA : SchedWriteRes<[]> { - let NumMicroOps = 19; -} -def : InstRW<[HWWritePushA], (instregex "PUSHA(16|32)")>; - -// POPA. -def HWWritePopA : SchedWriteRes<[]> { - let NumMicroOps = 18; -} -def : InstRW<[HWWritePopA], (instregex "POPA(16|32)")>; - -//-- Arithmetic instructions --// - -// DIV. -// r8. -def HWWriteDiv8 : SchedWriteRes<[HWPort0, HWPort1, HWPort5, HWPort6]> { - let Latency = 22; - let NumMicroOps = 9; -} -def : InstRW<[HWWriteDiv8], (instregex "DIV8r")>; - -// IDIV. -// r8. -def HWWriteIDiv8 : SchedWriteRes<[HWPort0, HWPort1, HWPort5, HWPort6]> { - let Latency = 23; - let NumMicroOps = 9; -} -def : InstRW<[HWWriteIDiv8], (instregex "IDIV8r")>; - -// BT. -// m,r. -def HWWriteBTmr : SchedWriteRes<[]> { - let NumMicroOps = 10; -} -def : InstRW<[HWWriteBTmr], (instregex "BT(16|32|64)mr")>; - -// BTR BTS BTC. -// m,r. -def HWWriteBTRSCmr : SchedWriteRes<[]> { - let NumMicroOps = 11; -} -def : InstRW<[HWWriteBTRSCmr], (instregex "BT(R|S|C)(16|32|64)mr")>; - -//-- Control transfer instructions --// - -// CALL. -// i. -def HWWriteRETI : SchedWriteRes<[HWPort23, HWPort6, HWPort015]> { - let NumMicroOps = 4; - let ResourceCycles = [1, 2, 1]; -} -def : InstRW<[HWWriteRETI], (instregex "RETI(L|Q|W)", "LRETI(L|Q|W)")>; - -// BOUND. -// r,m. -def HWWriteBOUND : SchedWriteRes<[]> { - let NumMicroOps = 15; -} -def : InstRW<[HWWriteBOUND], (instregex "BOUNDS(16|32)rm")>; - -// INTO. -def HWWriteINTO : SchedWriteRes<[]> { - let NumMicroOps = 4; -} -def : InstRW<[HWWriteINTO], (instrs INTO)>; - -//-- String instructions --// - -// LODSB/W. -def : InstRW<[HWWrite2P0156_P23], (instregex "LODS(B|W)")>; - -// LODSD/Q. -def : InstRW<[HWWriteP0156_P23], (instregex "LODS(L|Q)")>; - -// MOVS. -def HWWriteMOVS : SchedWriteRes<[HWPort23, HWPort4, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 5; - let ResourceCycles = [2, 1, 2]; -} -def : InstRW<[HWWriteMOVS], (instrs MOVSB, MOVSL, MOVSQ, MOVSW)>; - -// CMPS. -def HWWriteCMPS : SchedWriteRes<[HWPort23, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 5; - let ResourceCycles = [2, 3]; -} -def : InstRW<[HWWriteCMPS], (instregex "CMPS(B|L|Q|W)")>; - -//-- Other --// - -// RDPMC.f -def HWWriteRDPMC : SchedWriteRes<[]> { - let NumMicroOps = 34; -} -def : InstRW<[HWWriteRDPMC], (instrs RDPMC)>; - -// RDRAND. -def HWWriteRDRAND : SchedWriteRes<[HWPort23, HWPort015]> { - let NumMicroOps = 17; - let ResourceCycles = [1, 16]; -} -def : InstRW<[HWWriteRDRAND], (instregex "RDRAND(16|32|64)r")>; - -//=== Floating Point x87 Instructions ===// -//-- Move instructions --// - -// FLD. -// m80. -def : InstRW<[HWWriteP01], (instregex "LD_Frr")>; - -// FBLD. -// m80. -def HWWriteFBLD : SchedWriteRes<[]> { - let Latency = 47; - let NumMicroOps = 43; -} -def : InstRW<[HWWriteFBLD], (instregex "FBLDm")>; - -// FST(P). -// r. -def : InstRW<[HWWriteP01], (instregex "ST_(F|FP)rr")>; - -// FFREE. -def : InstRW<[HWWriteP01], (instregex "FFREE")>; - -// FNSAVE. -def HWWriteFNSAVE : SchedWriteRes<[]> { - let NumMicroOps = 147; -} -def : InstRW<[HWWriteFNSAVE], (instregex "FSAVEm")>; - -// FRSTOR. -def HWWriteFRSTOR : SchedWriteRes<[]> { - let NumMicroOps = 90; -} -def : InstRW<[HWWriteFRSTOR], (instregex "FRSTORm")>; - -//-- Arithmetic instructions --// - -// FCOMPP FUCOMPP. -// r. -def : InstRW<[HWWrite2P01], (instrs FCOMPP, UCOM_FPPr)>; - -// FCOMI(P) FUCOMI(P). -// m. -def : InstRW<[HWWrite3P01], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -// FTST. -def : InstRW<[HWWriteP1], (instregex "TST_F")>; - -// FXAM. -def : InstRW<[HWWrite2P1], (instrs FXAM)>; - -// FPREM. -def HWWriteFPREM : SchedWriteRes<[]> { - let Latency = 19; - let NumMicroOps = 28; -} -def : InstRW<[HWWriteFPREM], (instrs FPREM)>; - -// FPREM1. -def HWWriteFPREM1 : SchedWriteRes<[]> { - let Latency = 27; - let NumMicroOps = 41; -} -def : InstRW<[HWWriteFPREM1], (instrs FPREM1)>; - -// FRNDINT. -def HWWriteFRNDINT : SchedWriteRes<[]> { - let Latency = 11; - let NumMicroOps = 17; -} -def : InstRW<[HWWriteFRNDINT], (instrs FRNDINT)>; - -//-- Math instructions --// - -// FSCALE. -def HWWriteFSCALE : SchedWriteRes<[]> { - let Latency = 75; // 49-125 - let NumMicroOps = 50; // 25-75 -} -def : InstRW<[HWWriteFSCALE], (instrs FSCALE)>; - -// FXTRACT. -def HWWriteFXTRACT : SchedWriteRes<[]> { - let Latency = 15; - let NumMicroOps = 17; -} -def : InstRW<[HWWriteFXTRACT], (instrs FXTRACT)>; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; -defm : HWWriteResPair; - -//=== Floating Point XMM and YMM Instructions ===// - -// Remaining instrs. - -def HWWriteResGroup0 : SchedWriteRes<[HWPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCAST(D|Q)rm")>; - -def HWWriteResGroup0_1 : SchedWriteRes<[HWPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0_1], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCAST(D|Q)Yrm")>; - -def HWWriteResGroup0_2 : SchedWriteRes<[HWPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup0_2], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; - -def HWWriteResGroup1 : SchedWriteRes<[HWPort4,HWPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup1], (instregex "FBSTPm", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def HWWriteResGroup2 : SchedWriteRes<[HWPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup2], (instregex "VPSLLVQ(Y?)rr", - "VPSRLVQ(Y?)rr")>; - -def HWWriteResGroup3 : SchedWriteRes<[HWPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup3], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def HWWriteResGroup4 : SchedWriteRes<[HWPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup4], (instregex "MMX_MOVQ2DQrr")>; - -def HWWriteResGroup5 : SchedWriteRes<[HWPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup5], (instregex "JMP(16|32|64)r")>; - -def HWWriteResGroup6 : SchedWriteRes<[HWPort01]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def HWWriteResGroup7 : SchedWriteRes<[HWPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup7], (instrs CDQ, CQO)>; - -def HWWriteResGroup8 : SchedWriteRes<[HWPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def HWWriteResGroup9 : SchedWriteRes<[HWPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup9], (instregex "VPBLENDD(Y?)rri")>; - -def HWWriteResGroup10 : SchedWriteRes<[HWPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[HWWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def HWWriteResGroup11 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11], (instregex "(V?)CVTPS2PDrm")>; - -def HWWriteResGroup11_1 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11_1], (instregex "(V?)CVTSS2SDrm", - "VPSLLVQrm", - "VPSRLVQrm")>; - -def HWWriteResGroup11_2 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup11_2], (instregex "VPSLLVQYrm", - "VPSRLVQYrm")>; - -def HWWriteResGroup12 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup12], (instregex "MMX_CVTPI2PSirm", - "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def HWWriteResGroup12_1 : SchedWriteRes<[HWPort1,HWPort0156,HWPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup12_1], (instrs IMUL16rmi, IMUL16rmi8)>; - -def HWWriteResGroup12_2 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156,HWPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[HWWriteResGroup12_2], (instrs IMUL16m, MUL16m)>; - -def HWWriteResGroup13 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup13], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def HWWriteResGroup13_1 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup13_1], (instregex "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def HWWriteResGroup14 : SchedWriteRes<[HWPort6,HWPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup14], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def HWWriteResGroup15 : SchedWriteRes<[HWPort23,HWPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup15], (instregex "BT(16|32|64)mi8")>; - -def HWWriteResGroup16 : SchedWriteRes<[HWPort23,HWPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup16], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def HWWriteResGroup17 : SchedWriteRes<[HWPort23,HWPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup17], (instregex "VINSERTF128rm", - "VINSERTI128rm", - "VPBLENDDrmi")>; - -def HWWriteResGroup17_2 : SchedWriteRes<[HWPort23,HWPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup17_2], (instregex "VPBLENDDYrmi")>; - -def HWWriteResGroup18 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup18], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[HWWriteResGroup18], (instregex "POP(16|32|64)rmr")>; - -def HWWriteResGroup19 : SchedWriteRes<[HWPort237,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup19], (instrs SFENCE)>; - -def HWWriteResGroup21 : SchedWriteRes<[HWPort4,HWPort6,HWPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup21], (instrs FNSTCW16m)>; - -def HWWriteResGroup23 : SchedWriteRes<[HWPort4,HWPort237,HWPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup23], (instregex "MOVBE(32|64)mr")>; - -def HWWriteResGroup23_16 : SchedWriteRes<[HWPort06, HWPort237, HWPort4]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup23_16], (instrs MOVBE16mr)>; - -def HWWriteResGroup24 : SchedWriteRes<[HWPort4,HWPort237,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup24], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[HWWriteResGroup24], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def HWWriteResGroup25 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup25], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def HWWriteResGroup26 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup26], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def HWWriteResGroup28 : SchedWriteRes<[HWPort01]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup28], (instrs FDECSTP)>; - -def HWWriteResGroup29 : SchedWriteRes<[HWPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup29], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri")>; - -def HWWriteResGroup30 : SchedWriteRes<[HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[HWWriteResGroup30], (instrs LFENCE, - MFENCE, - WAIT, - XGETBV)>; - -def HWWriteResGroup31 : SchedWriteRes<[HWPort0,HWPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup31], (instregex "(V?)CVTPS2PDrr", - "(V?)CVTSS2SDrr")>; - -def HWWriteResGroup32 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup32], (instregex "CLFLUSH")>; - -def HWWriteResGroup33 : SchedWriteRes<[HWPort01,HWPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup33], (instregex "MMX_MOVDQ2Qrr")>; - -def HWWriteResGroup35 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup35], (instrs CWD, JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[HWWriteResGroup35], (instregex "SET(A|BE)r")>; - -def HWWriteResGroup36_2 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup36_2], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def HWWriteResGroup37 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup37], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def HWWriteResGroup39 : SchedWriteRes<[HWPort0,HWPort01,HWPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup39], (instrs FLDCW16m)>; - -def HWWriteResGroup41 : SchedWriteRes<[HWPort6,HWPort23,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup41], (instrs LRETQ, RETL, RETQ)>; - -def HWWriteResGroup44 : SchedWriteRes<[HWPort4,HWPort6,HWPort237,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup44], (instregex "CALL(16|32|64)r")>; - -def HWWriteResGroup45 : SchedWriteRes<[HWPort4,HWPort237,HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup45], (instrs CALL64pcrel32)>; -def: InstRW<[HWWriteResGroup45], (instregex "SET(A|BE)m")>; - -def HWWriteResGroup46 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup46], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def HWWriteResGroup47 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup47], (instregex "XADD(8|16|32|64)rm")>; - -def HWWriteResGroup48 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[HWWriteResGroup48], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def HWWriteResGroup50 : SchedWriteRes<[HWPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup50], (instregex "MMX_CVTPI2PSirr", - "PDEP(32|64)rr", - "PEXT(32|64)rr", - "(V?)CVTDQ2PS(Y?)rr")>; - -def HWWriteResGroup50_16i : SchedWriteRes<[HWPort1, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup50_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def HWWriteResGroup51 : SchedWriteRes<[HWPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup51], (instregex "VPBROADCAST(B|W)rr")>; - -def HWWriteResGroup52 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup52], (instregex "(V?)CVTPS2DQrm", - "(V?)CVTTPS2DQrm")>; - -def HWWriteResGroup52_1 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup52_1], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VCVTDQ2PSYrm", - "VCVTPS2DQYrm", - "VCVTTPS2DQYrm")>; - -def HWWriteResGroup53_1 : SchedWriteRes<[HWPort5,HWPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup53_1], (instregex "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVZXWDYrm")>; - -def HWWriteResGroup54 : SchedWriteRes<[HWPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[HWWriteResGroup54], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def HWWriteResGroup57 : SchedWriteRes<[HWPort5,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup57], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def HWWriteResGroup58 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup58], (instregex "CLD")>; - -def HWWriteResGroup59 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup59], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def HWWriteResGroup60 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup60], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def HWWriteResGroup61 : SchedWriteRes<[HWPort0,HWPort4,HWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup61], (instrs FNSTSWm)>; - -def HWWriteResGroup62 : SchedWriteRes<[HWPort1,HWPort4,HWPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup62], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def HWWriteResGroup66 : SchedWriteRes<[HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[HWWriteResGroup66], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def HWWriteResGroup67 : SchedWriteRes<[HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[HWWriteResGroup67], (instregex "ROR(8|16|32|64)mCL")>; - -def HWWriteResGroup68 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[HWWriteResGroup68], (instregex "XCHG(8|16|32|64)rm")>; - -def HWWriteResGroup69 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: InstRW<[HWWriteResGroup69], (instregex "CMPXCHG(8|16|32|64)rm", - "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; -def: SchedAlias; - -def HWWriteResGroup70 : SchedWriteRes<[HWPort0,HWPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup70], (instregex "(V?)CVT(T?)SD2SI(64)?rr", - "(V?)CVT(T?)SS2SI(64)?rr")>; - -def HWWriteResGroup71 : SchedWriteRes<[HWPort0,HWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup71], (instregex "VCVTPS2PDYrr")>; - -def HWWriteResGroup72 : SchedWriteRes<[HWPort0,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup72], (instrs FNSTSW16r)>; - -def HWWriteResGroup73 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup73], (instregex "MMX_CVTPI2PDirr", - "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVTDQ2PDrr", - "(V?)CVTPD2PSrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI(64)?2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVT(T?)PD2DQrr")>; - -def HWWriteResGroup74 : SchedWriteRes<[HWPort1,HWPort6]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup74], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def HWWriteResGroup74_16 : SchedWriteRes<[HWPort1, HWPort06, HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[HWWriteResGroup74_16], (instrs IMUL16r, MUL16r)>; - -def HWWriteResGroup75 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup75], (instregex "FICOM(P?)(16|32)m")>; - -def HWWriteResGroup76 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup76], (instregex "(V?)CVTSD2SI(64)?rm", - "(V?)CVTSS2SI(64)?rm", - "(V?)CVTTSD2SI(64)?rm", - "VCVTTSS2SI64rm", - "(V?)CVTTSS2SIrm")>; - -def HWWriteResGroup77 : SchedWriteRes<[HWPort0,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup77], (instregex "VCVTPS2PDYrm")>; - -def HWWriteResGroup78 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup78], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm", - "(V?)CVTDQ2PDrm")>; - -def HWWriteResGroup78_1 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup78_1], (instregex "MMX_CVTPI2PDirm", - "(V?)CVTSD2SSrm")>; - -def HWWriteResGroup79 : SchedWriteRes<[HWPort1,HWPort6,HWPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup79], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def HWWriteResGroup80 : SchedWriteRes<[HWPort5,HWPort23,HWPort015]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup80], (instregex "VPBROADCAST(B|W)(Y?)rm")>; - -def HWWriteResGroup81 : SchedWriteRes<[HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[HWWriteResGroup81], (instrs FNCLEX)>; - -def HWWriteResGroup82 : SchedWriteRes<[HWPort015,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[HWWriteResGroup82], (instrs VZEROUPPER)>; - -def HWWriteResGroup83 : SchedWriteRes<[HWPort1,HWPort6,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[HWWriteResGroup83], (instregex "LAR(16|32|64)rr")>; - -def HWWriteResGroup87 : SchedWriteRes<[HWPort1,HWPort6,HWPort23,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[HWWriteResGroup87], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def HWWriteResGroup88 : SchedWriteRes<[HWPort4,HWPort237,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[HWWriteResGroup88], (instregex "PUSHF(16|64)")>; - -def HWWriteResGroup89 : SchedWriteRes<[HWPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup89], (instregex "(V?)PCMPGTQ(Y?)rr", - "MUL_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup91_2 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup91_2], (instregex "(V?)PCMPGTQrm")>; - -def HWWriteResGroup91_3 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup91_3], (instregex "MUL_F(32|64)m", - "VPCMPGTQYrm")>; - -def HWWriteResGroup93 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[HWWriteResGroup93], (instregex "(V?)CVTSI642SSrr")>; - -def HWWriteResGroup94 : SchedWriteRes<[HWPort1,HWPort6,HWPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup94], (instregex "STR(16|32|64)r")>; - -def HWWriteResGroup95 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup95], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def HWWriteResGroup97 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup97], (instregex "CVTTSS2SI64rm")>; - -def HWWriteResGroup98 : SchedWriteRes<[HWPort1,HWPort23,HWPort06,HWPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup98], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def HWWriteResGroup99 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[HWWriteResGroup99], (instrs PAUSE)>; - -def HWWriteResGroup100 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[HWWriteResGroup100], (instrs XSETBV)>; - -def HWWriteResGroup101 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[HWWriteResGroup101], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def HWWriteResGroup102 : SchedWriteRes<[HWPort1,HWPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup102], (instregex "VCVTDQ2PDYrr", - "VCVTPD2PSYrr", - "VCVT(T?)PD2DQYrr")>; - -def HWWriteResGroup103 : SchedWriteRes<[HWPort1,HWPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[HWWriteResGroup103], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def HWWriteResGroup104 : SchedWriteRes<[HWPort1,HWPort5,HWPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup104], (instregex "VCVTDQ2PDYrm")>; - -def HWWriteResGroup107 : SchedWriteRes<[HWPort1,HWPort6,HWPort06,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[HWWriteResGroup107], (instregex "SLDT(16|32|64)r")>; - -def HWWriteResGroup108 : SchedWriteRes<[HWPort6,HWPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[HWWriteResGroup108], (instrs STD)>; - -def HWWriteResGroup114 : SchedWriteRes<[HWPort6,HWPort06,HWPort15,HWPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [2,2,1,2]; -} -def: InstRW<[HWWriteResGroup114], (instrs LOOP)>; - -def HWWriteResGroup115 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 15; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup115], (instregex "MUL_FI(16|32)m")>; - -def HWWriteResGroup120 : SchedWriteRes<[HWPort1,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 16; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,4,1,2]; -} -def: InstRW<[HWWriteResGroup120], (instregex "RCL(8|16|32|64)mCL")>; - -def HWWriteResGroup129 : SchedWriteRes<[HWPort1,HWPort06,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,2,3]; -} -def: InstRW<[HWWriteResGroup129], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def HWWriteResGroup130 : SchedWriteRes<[HWPort1,HWPort06,HWPort15,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,4,1,3]; -} -def: InstRW<[HWWriteResGroup130], (instregex "RCL8rCL")>; - -def HWWriteResGroup131 : SchedWriteRes<[HWPort06,HWPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[HWWriteResGroup131], (instrs LOOPE, LOOPNE)>; - -def HWWriteResGroup132 : SchedWriteRes<[HWPort4,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 17; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[HWWriteResGroup132], (instrs CMPXCHG8B)>; - -def HWWriteResGroup135 : SchedWriteRes<[HWPort1,HWPort23,HWPort237,HWPort06,HWPort15,HWPort0156]> { - let Latency = 19; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,3,1,3]; -} -def: InstRW<[HWWriteResGroup135], (instregex "RCR(8|16|32|64)mCL")>; - -def HWWriteResGroup142 : SchedWriteRes<[HWPort1,HWPort06,HWPort15,HWPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,3,1,4]; -} -def: InstRW<[HWWriteResGroup142], (instregex "RCR8rCL")>; - -def HWWriteResGroup143 : SchedWriteRes<[HWPort23,HWPort0156]> { - let Latency = 19; - let NumMicroOps = 15; - let ResourceCycles = [1,14]; -} -def: InstRW<[HWWriteResGroup143], (instregex "POPF16")>; - -def HWWriteResGroup144 : SchedWriteRes<[HWPort4,HWPort5,HWPort6,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 21; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[HWWriteResGroup144], (instrs INSB, INSL, INSW)>; - -def HWWriteResGroup145 : SchedWriteRes<[HWPort5]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[HWWriteResGroup145], (instrs VZEROALL)>; - -def HWWriteResGroup146 : SchedWriteRes<[HWPort0,HWPort4,HWPort5,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 22; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[HWWriteResGroup146], (instrs CMPXCHG16B)>; - -def HWWriteResGroup147 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort01,HWPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[HWWriteResGroup147], (instrs XCH_F)>; - -def HWWriteResGroup149 : SchedWriteRes<[HWPort5,HWPort6,HWPort06,HWPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[HWWriteResGroup149], (instrs CPUID, RDTSC)>; - -def HWWriteResGroup151 : SchedWriteRes<[HWPort6,HWPort23,HWPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [3,1,15]; -} -def: InstRW<[HWWriteResGroup151], (instregex "XRSTOR(64)?")>; - -def HWWriteResGroup154 : SchedWriteRes<[HWPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup154], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup155 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup155], (instregex "DIVR_F(32|64)m")>; - -def HWWriteResGroup156 : SchedWriteRes<[HWPort5,HWPort6,HWPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[HWWriteResGroup156], (instrs MWAITrr)>; - -def HWWriteResGroup161 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup161], (instregex "DIVR_FI(16|32)m")>; - -def HWWriteResGroup162 : SchedWriteRes<[HWPort0]> { - let Latency = 24; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[HWWriteResGroup162], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def HWWriteResGroup163 : SchedWriteRes<[HWPort0,HWPort23]> { - let Latency = 31; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[HWWriteResGroup163], (instregex "DIV_F(32|64)m")>; - -def HWWriteResGroup164 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 30; - let NumMicroOps = 27; - let ResourceCycles = [1,5,1,1,19]; -} -def: InstRW<[HWWriteResGroup164], (instrs XSAVE64)>; - -def HWWriteResGroup165 : SchedWriteRes<[HWPort4,HWPort6,HWPort23,HWPort237,HWPort0156]> { - let Latency = 31; - let NumMicroOps = 28; - let ResourceCycles = [1,6,1,1,19]; -} -def: InstRW<[HWWriteResGroup165], (instrs XSAVE)>; -def: InstRW<[HWWriteResGroup165], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def HWWriteResGroup166 : SchedWriteRes<[HWPort0,HWPort1,HWPort23]> { - let Latency = 34; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[HWWriteResGroup166], (instregex "DIV_FI(16|32)m")>; - -def HWWriteResGroup170 : SchedWriteRes<[HWPort5,HWPort6,HWPort23,HWPort06,HWPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[HWWriteResGroup170], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def HWWriteResGroup171 : SchedWriteRes<[HWPort5,HWPort6,HWPort23,HWPort237,HWPort06,HWPort0156]> { - let Latency = 36; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[HWWriteResGroup171], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def HWWriteResGroup175 : SchedWriteRes<[HWPort1,HWPort4,HWPort5,HWPort6,HWPort23,HWPort237,HWPort15,HWPort0156]> { - let Latency = 41; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[HWWriteResGroup175], (instrs VMCLEARm)>; - -def HWWriteResGroup176 : SchedWriteRes<[HWPort5,HWPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[HWWriteResGroup176], (instrs RDTSCP)>; - -def HWWriteResGroup177 : SchedWriteRes<[HWPort0,HWPort01,HWPort23,HWPort05,HWPort06,HWPort015,HWPort0156]> { - let Latency = 61; - let NumMicroOps = 64; - let ResourceCycles = [2,2,8,1,10,2,39]; -} -def: InstRW<[HWWriteResGroup177], (instrs FLDENVm)>; - -def HWWriteResGroup178 : SchedWriteRes<[HWPort0,HWPort6,HWPort23,HWPort05,HWPort06,HWPort15,HWPort0156]> { - let Latency = 64; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[HWWriteResGroup178], (instrs FXRSTOR64)>; - -def HWWriteResGroup179 : SchedWriteRes<[HWPort0,HWPort6,HWPort23,HWPort05,HWPort06,HWPort15,HWPort0156]> { - let Latency = 64; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[HWWriteResGroup179], (instrs FXRSTOR)>; - -def HWWriteResGroup180 : SchedWriteRes<[HWPort5,HWPort01,HWPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[HWWriteResGroup180], (instrs FNINIT)>; - -def HWWriteResGroup181 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort01,HWPort0156]> { - let Latency = 98; - let NumMicroOps = 32; - let ResourceCycles = [7,7,3,3,1,11]; -} -def: InstRW<[HWWriteResGroup181], (instregex "DIV(16|32|64)r")>; - -def HWWriteResGroup182 : SchedWriteRes<[HWPort0,HWPort1,HWPort5,HWPort6,HWPort06,HWPort0156]> { - let Latency = 112; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[HWWriteResGroup182], (instregex "IDIV(16|32|64)r")>; - -def HWWriteResGroup183 : SchedWriteRes<[HWPort0,HWPort1,HWPort4,HWPort5,HWPort6,HWPort237,HWPort06,HWPort0156]> { - let Latency = 115; - let NumMicroOps = 100; - let ResourceCycles = [9,9,11,8,1,11,21,30]; -} -def: InstRW<[HWWriteResGroup183], (instrs FSTENVm)>; - -def HWWriteResGroup184 : SchedWriteRes<[HWPort0, HWPort5, HWPort15, HWPort015, HWPort06, HWPort23]> { - let Latency = 26; - let NumMicroOps = 12; - let ResourceCycles = [2,2,1,3,2,2]; -} -def: InstRW<[HWWriteResGroup184], (instrs VGATHERDPDrm, - VPGATHERDQrm, - VPGATHERDDrm)>; - -def HWWriteResGroup185 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 24; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup185], (instrs VGATHERQPDYrm, - VPGATHERQQYrm)>; - -def HWWriteResGroup186 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 28; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup186], (instrs VPGATHERQDYrm)>; - -def HWWriteResGroup187 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 25; - let NumMicroOps = 22; - let ResourceCycles = [5,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup187], (instrs VPGATHERQDrm)>; - -def HWWriteResGroup188 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 27; - let NumMicroOps = 20; - let ResourceCycles = [3,3,4,1,5,4]; -} -def: InstRW<[HWWriteResGroup188], (instrs VGATHERDPDYrm, - VPGATHERDQYrm)>; - -def HWWriteResGroup189 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 27; - let NumMicroOps = 34; - let ResourceCycles = [5,3,8,1,9,8]; -} -def: InstRW<[HWWriteResGroup189], (instrs VGATHERDPSYrm, - VPGATHERDDYrm)>; - -def HWWriteResGroup190 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 23; - let NumMicroOps = 14; - let ResourceCycles = [3,3,2,1,3,2]; -} -def: InstRW<[HWWriteResGroup190], (instrs VGATHERQPDrm, - VPGATHERQQrm)>; - -def HWWriteResGroup191 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 28; - let NumMicroOps = 15; - let ResourceCycles = [3,3,2,1,4,2]; -} -def: InstRW<[HWWriteResGroup191], (instrs VGATHERQPSYrm)>; - -def HWWriteResGroup192 : SchedWriteRes<[HWPort0, HWPort5, HWPort06, HWPort15, HWPort015, HWPort23]> { - let Latency = 25; - let NumMicroOps = 15; - let ResourceCycles = [3,3,2,1,4,2]; -} -def: InstRW<[HWWriteResGroup192], (instrs VGATHERQPSrm, - VGATHERDPSrm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86SchedPredicates.td b/suite/synctools/tablegen/X86/back/X86SchedPredicates.td deleted file mode 100644 index 27aaeb1935..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedPredicates.td +++ /dev/null @@ -1,49 +0,0 @@ -//===-- X86SchedPredicates.td - X86 Scheduling Predicates --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines scheduling predicate definitions that are common to -// all X86 subtargets. -// -//===----------------------------------------------------------------------===// - -// A predicate used to identify dependency-breaking instructions that clear the -// content of the destination register. Note that this predicate only checks if -// input registers are the same. This predicate doesn't make any assumptions on -// the expected instruction opcodes, because different processors may implement -// different zero-idioms. -def ZeroIdiomPredicate : CheckSameRegOperand<1, 2>; - -// A predicate used to check if an instruction is a LEA, and if it uses all -// three source operands: base, index, and offset. -def IsThreeOperandsLEAPredicate: CheckAll<[ - CheckOpcode<[LEA32r, LEA64r, LEA64_32r, LEA16r]>, - - // isRegOperand(Base) - CheckIsRegOperand<1>, - CheckNot>, - - // isRegOperand(Index) - CheckIsRegOperand<3>, - CheckNot>, - - // hasLEAOffset(Offset) - CheckAny<[ - CheckAll<[ - CheckIsImmOperand<4>, - CheckNot> - ]>, - CheckNonPortable<"MI.getOperand(4).isGlobal()"> - ]> -]>; - -// This predicate evaluates to true only if the input machine instruction is a -// 3-operands LEA. Tablegen automatically generates a new method for it in -// X86GenInstrInfo. -def IsThreeOperandsLEAFn : - TIIPredicate<"X86", "isThreeOperandsLEA", IsThreeOperandsLEAPredicate>; diff --git a/suite/synctools/tablegen/X86/back/X86SchedSandyBridge.td b/suite/synctools/tablegen/X86/back/X86SchedSandyBridge.td deleted file mode 100644 index 6b7bbdea86..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedSandyBridge.td +++ /dev/null @@ -1,1159 +0,0 @@ -//=- X86SchedSandyBridge.td - X86 Sandy Bridge Scheduling ----*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Sandy Bridge to support instruction -// scheduling and other instruction cost heuristics. -// -// Note that we define some instructions here that are not supported by SNB, -// but we still have to define them because SNB is the default subtarget for -// X86. These instructions are tagged with a comment `Unsupported = 1`. -// -//===----------------------------------------------------------------------===// - -def SandyBridgeModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SB can decode 4 - // instructions per cycle. - // FIXME: Identify instructions that aren't a single fused micro-op. - let IssueWidth = 4; - let MicroOpBufferSize = 168; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 16; - - // Based on the LSD (loop-stream detector) queue size. - let LoopMicroOpBufferSize = 28; - - // This flag is set to allow the scheduler to assign - // a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SandyBridgeModel in { - -// Sandy Bridge can issue micro-ops to 6 different ports in one cycle. - -// Ports 0, 1, and 5 handle all computation. -def SBPort0 : ProcResource<1>; -def SBPort1 : ProcResource<1>; -def SBPort5 : ProcResource<1>; - -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. -def SBPort23 : ProcResource<2>; - -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -def SBPort4 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SBPort01 : ProcResGroup<[SBPort0, SBPort1]>; -def SBPort05 : ProcResGroup<[SBPort0, SBPort5]>; -def SBPort15 : ProcResGroup<[SBPort1, SBPort5]>; -def SBPort015 : ProcResGroup<[SBPort0, SBPort1, SBPort5]>; - -// 54 Entry Unified Scheduler -def SBPortAny : ProcResGroup<[SBPort0, SBPort1, SBPort23, SBPort4, SBPort5]> { - let BufferSize=54; -} - -// Integer division issued on port 0. -def SBDivider : ProcResource<1>; -// FP division and sqrt on port 0. -def SBFPDivider : ProcResource<1>; - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SBWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3 cycle to recompute the address. -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 5; } -def : WriteRes; -def : WriteRes; - -// Arithmetic. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -def : WriteRes { let Latency = 3; } - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -defm : SBWriteResPair; // Conditional move. -defm : SBWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -// NOTE: These don't exist on Sandy Bridge. Ports are guesses. -defm : SBWriteResPair; -defm : SBWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Conversion between integer and float. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -defm : SBWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; // Unsupported = 1 - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; // TODO this is probably wrong for 256/512-bit for the "generic" model -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; - -// Vector integer shifts. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 7; - let NumMicroOps = 2; -} - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 5; - let NumMicroOps = 3; -} - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -//////////////////////////////////////////////////////////////////////////////// -// String instructions. -//////////////////////////////////////////////////////////////////////////////// - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 11; - let ResourceCycles = [8]; -} -def : WriteRes { - let Latency = 11; - let ResourceCycles = [7, 1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 17; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 4; - let ResourceCycles = [8]; -} -def : WriteRes { - let Latency = 4; - let ResourceCycles = [7, 1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 1; } - -// AES Instructions. -def : WriteRes { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def : WriteRes { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} - -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 18; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [11]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [10, 1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 14; - let ResourceCycles = [18]; -} -def : WriteRes { - let Latency = 14; - let ResourceCycles = [17, 1]; -} - -// Load/store MXCSR. -// FIXME: This is probably wrong. Only STMXCSR should require Port4. -def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } -def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -// AVX2/FMA is not supported on that architecture, but we should define the basic -// scheduling resources anyway. -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; -defm : SBWriteResPair; // Unsupported = 1 - -// Remaining SNB instrs. - -def SBWriteResGroup1 : SchedWriteRes<[SBPort1]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup1], (instrs COMP_FST0r, - COM_FST0r, - UCOM_FPr, - UCOM_Fr)>; - -def SBWriteResGroup2 : SchedWriteRes<[SBPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup2], (instrs FDECSTP, FINCSTP, FFREE, FFREEP, FNOP, - LD_Frr, ST_Frr, ST_FPrr)>; -def: InstRW<[SBWriteResGroup2], (instrs LOOP, LOOPE, LOOPNE)>; // FIXME: This seems wrong compared to other Intel CPUs. -def: InstRW<[SBWriteResGroup2], (instrs RETQ)>; - -def SBWriteResGroup4 : SchedWriteRes<[SBPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup4], (instrs CDQ, CQO)>; - -def SBWriteResGroup5 : SchedWriteRes<[SBPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup5], (instregex "MMX_PABS(B|D|W)rr", - "MMX_PADDQirr", - "MMX_PALIGNRrri", - "MMX_PSIGN(B|D|W)rr")>; - -def SBWriteResGroup9 : SchedWriteRes<[SBPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SBWriteResGroup9], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SBWriteResGroup11 : SchedWriteRes<[SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SBWriteResGroup11], (instrs SCASB, - SCASL, - SCASQ, - SCASW)>; - -def SBWriteResGroup12 : SchedWriteRes<[SBPort0,SBPort1]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup12], (instregex "(V?)COMISDrr", - "(V?)COMISSrr", - "(V?)UCOMISDrr", - "(V?)UCOMISSrr")>; - -def SBWriteResGroup15 : SchedWriteRes<[SBPort0,SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup15], (instrs CWD, - FNSTSW16r)>; - -def SBWriteResGroup18 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup18], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SBWriteResGroup18], (instregex "MMX_MOVDQ2Qrr")>; - -def SBWriteResGroup21 : SchedWriteRes<[SBPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup21], (instregex "PUSHFS64")>; - -def SBWriteResGroup21_16i : SchedWriteRes<[SBPort1, SBPort015]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup21_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def SBWriteResGroup22 : SchedWriteRes<[SBPort0,SBPort5]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup22], (instregex "(V?)EXTRACTPSrr")>; - -def SBWriteResGroup23_2 : SchedWriteRes<[SBPort05]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SBWriteResGroup23_2], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SBWriteResGroup25 : SchedWriteRes<[SBPort015]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SBWriteResGroup25], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SBWriteResGroup25_1 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup25_1], (instrs LEAVE, LEAVE64)>; - -def SBWriteResGroup26_2 : SchedWriteRes<[SBPort0,SBPort1,SBPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup26_2], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -def SBWriteResGroup27 : SchedWriteRes<[SBPort0,SBPort1]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup27], (instrs IMUL64r, MUL64r)>; - -def SBWriteResGroup27_1 : SchedWriteRes<[SBPort1,SBPort05,SBPort015]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup27_1], (instrs IMUL32r, MUL32r)>; - -def SBWriteResGroup27_2 : SchedWriteRes<[SBPort1,SBPort05,SBPort015]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup27_2], (instrs IMUL16r, MUL16r)>; - -def SBWriteResGroup29 : SchedWriteRes<[SBPort1,SBPort015]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup29], (instregex "MOV64sr")>; - -def SBWriteResGroup29_2 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup29_2], (instrs PAUSE)>; - -def SBWriteResGroup30 : SchedWriteRes<[SBPort0]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup30], (instregex "(V?)PCMPGTQrr")>; - -def SBWriteResGroup31 : SchedWriteRes<[SBPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup31], (instregex "MOVSX(16|32|64)rm(8|16|32)", - "MOVZX(16|32|64)rm(8|16)")>; - -def SBWriteResGroup33 : SchedWriteRes<[SBPort4,SBPort23]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup33], (instregex "PUSH(16r|32r|64r|64i8)")>; - -def SBWriteResGroup35 : SchedWriteRes<[SBPort1,SBPort5]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup35], (instrs CLI)>; - -def SBWriteResGroup35_2 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup35_2], (instregex "ISTT_FP(16|32|64)m", - "PUSHGS64")>; - -def SBWriteResGroup36 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup36], (instrs CALL64pcrel32)>; -def: InstRW<[SBWriteResGroup36], (instregex "CALL(16|32|64)r", - "(V?)EXTRACTPSmr")>; - -def SBWriteResGroup40 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup40], (instrs STOSB, STOSL, STOSQ, STOSW)>; - -def SBWriteResGroup41 : SchedWriteRes<[SBPort5,SBPort015]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup41], (instrs FNINIT)>; - -def SBWriteResGroup42 : SchedWriteRes<[SBPort05,SBPort015]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup42], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SBWriteResGroup43 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup43], (instregex "SET(A|BE)m")>; - -def SBWriteResGroup45 : SchedWriteRes<[SBPort0,SBPort4,SBPort23,SBPort15]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup45], (instregex "(V?)PEXTR(D|Q)mr", - "PUSHF(16|64)")>; - -def SBWriteResGroup46 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup46], (instregex "CLFLUSH")>; - -def SBWriteResGroup47 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SBWriteResGroup47], (instregex "FXRSTOR")>; - -def SBWriteResGroup48 : SchedWriteRes<[SBPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup48], (instregex "MMX_MOVD64from64rm", - "POP(16|32|64)r", - "VBROADCASTSSrm", - "(V?)MOV64toPQIrm", - "(V?)MOVDDUPrm", - "(V?)MOVDI2PDIrm", - "(V?)MOVQI2PQIrm", - "(V?)MOVSDrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "(V?)MOVSSrm")>; - -def SBWriteResGroup49 : SchedWriteRes<[SBPort5,SBPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup49], (instregex "MOV16sm")>; - -def SBWriteResGroup50 : SchedWriteRes<[SBPort23,SBPort05]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup50], (instregex "BT(16|32|64)mi8")>; - -def SBWriteResGroup51 : SchedWriteRes<[SBPort23,SBPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup51], (instregex "MMX_PABS(B|D|W)rm", - "MMX_PALIGNRrmi", - "MMX_PSIGN(B|D|W)rm")>; - -def SBWriteResGroup52 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup52], (instrs LODSL, LODSQ)>; - -def SBWriteResGroup53 : SchedWriteRes<[SBPort4,SBPort23]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup53], (instregex "ST_F(32|64)m", - "ST_FP(32|64|80)m")>; - -def SBWriteResGroup54 : SchedWriteRes<[SBPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SBWriteResGroup54], (instregex "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm")>; - -def SBWriteResGroup58 : SchedWriteRes<[SBPort23,SBPort05]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup58], (instrs VINSERTF128rm)>; - -def SBWriteResGroup59 : SchedWriteRes<[SBPort23,SBPort15]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup59], (instregex "MMX_PADDQirm")>; - -def SBWriteResGroup62 : SchedWriteRes<[SBPort5,SBPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup62], (instregex "VER(R|W)m")>; - -def SBWriteResGroup63 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SBWriteResGroup63], (instrs LODSB, LODSW)>; - -def SBWriteResGroup64 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup64], (instrs FARJMP64)>; - -def SBWriteResGroup66 : SchedWriteRes<[SBPort0,SBPort4,SBPort23]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup66], (instrs FNSTSWm)>; - -def SBWriteResGroup67 : SchedWriteRes<[SBPort1,SBPort5,SBPort015]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SBWriteResGroup67], (instregex "SLDT(16|32|64)r", - "STR(16|32|64)r")>; - -def SBWriteResGroup68 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup68], (instrs FNSTCW16m)>; -def: InstRW<[SBWriteResGroup68], (instregex "CALL(16|32|64)m")>; - -def SBWriteResGroup69 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SBWriteResGroup69], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SBWriteResGroup77 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup77], (instregex "(V?)(U?)COMI(SD|SS)rm")>; - -def SBWriteResGroup81 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SBWriteResGroup81], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SBWriteResGroup83 : SchedWriteRes<[SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SBWriteResGroup83], (instrs CMPSB, - CMPSL, - CMPSQ, - CMPSW)>; - -def SBWriteResGroup84 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup84], (instrs FLDCW16m)>; - -def SBWriteResGroup85 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup85], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SBWriteResGroup86 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,2,2]; -} -def: InstRW<[SBWriteResGroup86], (instrs MOVSB, MOVSL, MOVSQ, MOVSW)>; -def: InstRW<[SBWriteResGroup86], (instregex "XADD(8|16|32|64)rm")>; - -def SBWriteResGroup87 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SBWriteResGroup87], (instrs FARCALL64)>; - -def SBWriteResGroup93 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93], (instregex "CVT(T?)SD2SI(64)?rm", - "CVT(T?)SS2SI(64)?rm")>; - -def SBWriteResGroup93_1 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93_1], (instrs IMUL64m, MUL64m)>; - -def SBWriteResGroup93_2 : SchedWriteRes<[SBPort1,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SBWriteResGroup93_2], (instrs IMUL32m, MUL32m)>; - -def SBWriteResGroup93_3 : SchedWriteRes<[SBPort1,SBPort05,SBPort015,SBPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SBWriteResGroup93_3], (instrs IMUL16m, MUL16m)>; - -def SBWriteResGroup93_4 : SchedWriteRes<[SBPort1,SBPort015,SBPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup93_4], (instrs IMUL16rmi, IMUL16rmi8)>; - -def SBWriteResGroup95 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup95], (instregex "LD_F(32|64|80)m")>; - -def SBWriteResGroup97 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SBWriteResGroup97], (instregex "IST_F(16|32)m", - "IST_FP(16|32|64)m")>; - -def SBWriteResGroup97_2 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,3]; -} -def: InstRW<[SBWriteResGroup97_2], (instregex "ROL(8|16|32|64)mCL", - "ROR(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SBWriteResGroup98 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,3]; -} -def: SchedAlias; - -def SBWriteResGroup99 : SchedWriteRes<[SBPort4,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,2,2,1]; -} -def: InstRW<[SBWriteResGroup99, ReadAfterLd], (instrs ADC8mr, ADC16mr, ADC32mr, ADC64mr, - SBB8mr, SBB16mr, SBB32mr, SBB64mr)>; - -def SBWriteResGroup100 : SchedWriteRes<[SBPort4,SBPort5,SBPort23,SBPort05,SBPort015]> { - let Latency = 9; - let NumMicroOps = 6; - let ResourceCycles = [1,1,2,1,1]; -} -def: InstRW<[SBWriteResGroup100], (instregex "BT(16|32|64)mr", - "BTC(16|32|64)mr", - "BTR(16|32|64)mr", - "BTS(16|32|64)mr")>; - -def SBWriteResGroup101 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup101], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m")>; - -def SBWriteResGroup104 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup104], (instregex "(V?)PCMPGTQrm")>; - -def SBWriteResGroup106 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup106], (instregex "FICOM(P?)(16|32)m")>; - -def SBWriteResGroup111 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup111], (instregex "MUL_F(32|64)m")>; - -def SBWriteResGroup114 : SchedWriteRes<[SBPort1,SBPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SBWriteResGroup114], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def SBWriteResGroup119 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 15; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup119], (instregex "MUL_FI(16|32)m")>; - -def SBWriteResGroup130 : SchedWriteRes<[SBPort0,SBPort23]> { - let Latency = 31; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SBWriteResGroup130], (instregex "DIV(R?)_F(32|64)m")>; - -def SBWriteResGroup131 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { - let Latency = 34; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SBWriteResGroup131], (instregex "DIV(R?)_FI(16|32)m")>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86SchedSkylakeClient.td b/suite/synctools/tablegen/X86/back/X86SchedSkylakeClient.td deleted file mode 100644 index bda088e151..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedSkylakeClient.td +++ /dev/null @@ -1,1850 +0,0 @@ -//=- X86SchedSkylake.td - X86 Skylake Client Scheduling ------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Skylake Client to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SkylakeClientModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SKylake can - // decode 6 instructions per cycle. - let IssueWidth = 6; - let MicroOpBufferSize = 224; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 14; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SkylakeClientModel in { - -// Skylake Client can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def SKLPort0 : ProcResource<1>; -def SKLPort1 : ProcResource<1>; -def SKLPort2 : ProcResource<1>; -def SKLPort3 : ProcResource<1>; -def SKLPort4 : ProcResource<1>; -def SKLPort5 : ProcResource<1>; -def SKLPort6 : ProcResource<1>; -def SKLPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SKLPort01 : ProcResGroup<[SKLPort0, SKLPort1]>; -def SKLPort23 : ProcResGroup<[SKLPort2, SKLPort3]>; -def SKLPort237 : ProcResGroup<[SKLPort2, SKLPort3, SKLPort7]>; -def SKLPort04 : ProcResGroup<[SKLPort0, SKLPort4]>; -def SKLPort05 : ProcResGroup<[SKLPort0, SKLPort5]>; -def SKLPort06 : ProcResGroup<[SKLPort0, SKLPort6]>; -def SKLPort15 : ProcResGroup<[SKLPort1, SKLPort5]>; -def SKLPort16 : ProcResGroup<[SKLPort1, SKLPort6]>; -def SKLPort56 : ProcResGroup<[SKLPort5, SKLPort6]>; -def SKLPort015 : ProcResGroup<[SKLPort0, SKLPort1, SKLPort5]>; -def SKLPort056 : ProcResGroup<[SKLPort0, SKLPort5, SKLPort6]>; -def SKLPort0156: ProcResGroup<[SKLPort0, SKLPort1, SKLPort5, SKLPort6]>; - -def SKLDivider : ProcResource<1>; // Integer division issued on port 0. -// FP division and sqrt on port 0. -def SKLFPDivider : ProcResource<1>; - -// 60 Entry Unified Scheduler -def SKLPortAny : ProcResGroup<[SKLPort0, SKLPort1, SKLPort2, SKLPort3, SKLPort4, - SKLPort5, SKLPort6, SKLPort7]> { - let BufferSize=60; -} - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SKLWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : SKLWriteResPair; // Simple integer ALU op. -defm : SKLWriteResPair; // Integer ALU + flags op. -defm : SKLWriteResPair; // Integer multiplication. -defm : SKLWriteResPair; // Integer 64-bit multiplication. - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -defm : SKLWriteResPair; - -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. -def : WriteRes; // LEA instructions can't fold loads. - -defm : SKLWriteResPair; // Conditional move. -defm : SKLWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // - -// Bit counts. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Integer shifts and rotates. -defm : SKLWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// BMI1 BEXTR, BMI2 BZHI -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : SKLWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; // Floating point add/sub. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double add/sub. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point compare. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double compare. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point compare to flags. - -defm : SKLWriteResPair; // Floating point multiplication. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double multiplication. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point division. -//defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -//defm : SKLWriteResPair; // Floating point double division. -//defm : SKLWriteResPair; -//defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point square root. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double square root. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point long double square root. - -defm : SKLWriteResPair; // Floating point reciprocal estimate. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Floating point reciprocal square root estimate. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Fused Multiply Add. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point double dot product. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point fabs/fchs. -defm : SKLWriteResPair; // Floating point rounding. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point and/or/xor logicals. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point TEST instructions. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector shuffles. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector shuffles. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Floating point vector blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Fp vector variable blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKLWriteResPair; // Vector integer ALU op, no logicals. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer and/or/xor. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer TEST instructions. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector integer multiply. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PMULLD. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector shuffles. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector shuffles. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector variable blends. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector MPSAD. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PSADBW. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : SKLWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; // Vector integer immediate shifts. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; // Variable vector shifts. -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 20; - let NumMicroOps = 11; - let ResourceCycles = [3,6,2]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 11; - let ResourceCycles = [3,6,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : SKLWriteResPair; // Fp 256-bit width vector shuffles. -defm : SKLWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : SKLWriteResPair; // 256-bit width vector shuffles. -defm : SKLWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; -defm : SKLWriteResPair; - -// Remaining instrs. - -def SKLWriteResGroup1 : SchedWriteRes<[SKLPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup1], (instregex "MMX_PADDS(B|W)irr", - "MMX_PADDUS(B|W)irr", - "MMX_PAVG(B|W)irr", - "MMX_PCMPEQ(B|D|W)irr", - "MMX_PCMPGT(B|D|W)irr", - "MMX_P(MAX|MIN)SWirr", - "MMX_P(MAX|MIN)UBirr", - "MMX_PSUBS(B|W)irr", - "MMX_PSUBUS(B|W)irr")>; - -def SKLWriteResGroup3 : SchedWriteRes<[SKLPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup3], (instregex "COM(P?)_FST0r", - "UCOM_F(P?)r")>; - -def SKLWriteResGroup4 : SchedWriteRes<[SKLPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def SKLWriteResGroup6 : SchedWriteRes<[SKLPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def SKLWriteResGroup7 : SchedWriteRes<[SKLPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup7], (instrs CDQ, CQO, CLAC, STAC)>; - -def SKLWriteResGroup8 : SchedWriteRes<[SKLPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def SKLWriteResGroup9 : SchedWriteRes<[SKLPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup9], (instregex "(V?)PADD(B|D|Q|W)(Y?)rr", - "VPBLENDD(Y?)rri", - "(V?)PSUB(B|D|Q|W)(Y?)rr")>; - -def SKLWriteResGroup10 : SchedWriteRes<[SKLPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[SKLWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def SKLWriteResGroup11 : SchedWriteRes<[SKLPort4,SKLPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup11], (instregex "FBSTPm", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def SKLWriteResGroup13 : SchedWriteRes<[SKLPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup13], (instregex "MMX_MOVQ2DQrr")>; - -def SKLWriteResGroup14 : SchedWriteRes<[SKLPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup14], (instrs FDECSTP)>; -def: InstRW<[SKLWriteResGroup14], (instregex "MMX_MOVDQ2Qrr")>; - -def SKLWriteResGroup15 : SchedWriteRes<[SKLPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup15], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SKLWriteResGroup17 : SchedWriteRes<[SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup17], (instrs LFENCE, - WAIT, - XGETBV)>; - -def SKLWriteResGroup20 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup20], (instregex "CLFLUSH")>; - -def SKLWriteResGroup21 : SchedWriteRes<[SKLPort237,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup21], (instrs SFENCE)>; - -def SKLWriteResGroup23 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup23], (instrs CWD)>; -def: InstRW<[SKLWriteResGroup23], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SKLWriteResGroup23], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri")>; - -def SKLWriteResGroup25 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup25], (instrs FNSTCW16m)>; - -def SKLWriteResGroup27 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup27], (instregex "MOVBE(16|32|64)mr")>; - -def SKLWriteResGroup28 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup28], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[SKLWriteResGroup28], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def SKLWriteResGroup29 : SchedWriteRes<[SKLPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup29], (instregex "PDEP(32|64)rr", - "PEXT(32|64)rr")>; - -def SKLWriteResGroup29_16i : SchedWriteRes<[SKLPort1, SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup29_16i], (instrs IMUL16rri, IMUL16rri8)>; - -def SKLWriteResGroup30 : SchedWriteRes<[SKLPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup30], (instregex "(ADD|SUB|SUBR)_(FPrST0|FST0r|FrST0)", - "VPBROADCASTBrr", - "VPBROADCASTWrr", - "(V?)PCMPGTQ(Y?)rr")>; - -def SKLWriteResGroup32 : SchedWriteRes<[SKLPort0,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup32], (instrs FNSTSW16r)>; - -def SKLWriteResGroup33 : SchedWriteRes<[SKLPort06]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKLWriteResGroup33], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SKLWriteResGroup34 : SchedWriteRes<[SKLPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKLWriteResGroup34], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SKLWriteResGroup35 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup35], (instregex "MMX_PH(ADD|SUB)SWrr")>; - -def SKLWriteResGroup36 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup36], (instregex "(V?)PHADDSW(Y?)rr", - "(V?)PHSUBSW(Y?)rr")>; - -def SKLWriteResGroup39 : SchedWriteRes<[SKLPort5,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup39], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def SKLWriteResGroup40 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup40], (instregex "CLD")>; - -def SKLWriteResGroup41 : SchedWriteRes<[SKLPort237,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup41], (instrs MFENCE)>; - -def SKLWriteResGroup42 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup42], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def SKLWriteResGroup43 : SchedWriteRes<[SKLPort0,SKLPort4,SKLPort237]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup43], (instrs FNSTSWm)>; - -def SKLWriteResGroup44 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort06]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup44], (instregex "SET(A|BE)m")>; - -def SKLWriteResGroup45 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort237,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup45], (instregex "CALL(16|32|64)r")>; - -def SKLWriteResGroup46 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup46], (instrs CALL64pcrel32)>; - -def SKLWriteResGroup47 : SchedWriteRes<[SKLPort0]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup47], (instregex "MUL_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup48 : SchedWriteRes<[SKLPort01]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup48], (instregex "(V?)CVTDQ2PS(Y?)rr", - "(V?)CVT(T?)PS2DQ(Y?)rr")>; - -def SKLWriteResGroup51 : SchedWriteRes<[SKLPort1,SKLPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup51], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def SKLWriteResGroup51_16 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup51_16], (instrs IMUL16r, MUL16r)>; - -def SKLWriteResGroup53 : SchedWriteRes<[SKLPort4,SKLPort5,SKLPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup53], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m")>; - -def SKLWriteResGroup54 : SchedWriteRes<[SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[SKLWriteResGroup54], (instrs FNCLEX)>; - -def SKLWriteResGroup55 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKLWriteResGroup55], (instrs PAUSE)>; - -def SKLWriteResGroup56 : SchedWriteRes<[SKLPort015,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKLWriteResGroup56], (instrs VZEROUPPER)>; - -def SKLWriteResGroup57 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKLWriteResGroup57], (instregex "LAR(16|32|64)rr")>; - -def SKLWriteResGroup58 : SchedWriteRes<[SKLPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup58], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; // TODO: Should this be SKLWriteResGroup67? - -def SKLWriteResGroup59 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup59], (instregex "MMX_CVTPI2PDirr", - "(V?)CVTDQ2PDrr")>; - -def SKLWriteResGroup60 : SchedWriteRes<[SKLPort5,SKLPort015]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup60], (instregex "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "(V?)CVT(T?)PD2DQrr", - "(V?)CVTPD2PSrr", - "(V?)CVTPS2PDrr", - "(V?)CVTSD2SSrr", - "(V?)CVTSI642SDrr", - "(V?)CVTSI2SDrr", - "(V?)CVTSI2SSrr", - "(V?)CVTSS2SDrr")>; - -def SKLWriteResGroup61 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup61], (instregex "STR(16|32|64)r")>; - -def SKLWriteResGroup62 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup62], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def SKLWriteResGroup63 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[SKLWriteResGroup63], (instrs XSETBV)>; - -def SKLWriteResGroup64 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SKLWriteResGroup64], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SKLWriteResGroup65 : SchedWriteRes<[SKLPort4,SKLPort237,SKLPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[SKLWriteResGroup65], (instregex "PUSHF(16|64)")>; - -def SKLWriteResGroup67 : SchedWriteRes<[SKLPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup67], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def SKLWriteResGroup68 : SchedWriteRes<[SKLPort0]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKLWriteResGroup68], (instregex "MMX_CVTPI2PSirr")>; - -def SKLWriteResGroup69 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup69], (instregex "MMX_PADDSBirm", - "MMX_PADDSWirm", - "MMX_PADDUSBirm", - "MMX_PADDUSWirm", - "MMX_PAVGBirm", - "MMX_PAVGWirm", - "MMX_PCMPEQBirm", - "MMX_PCMPEQDirm", - "MMX_PCMPEQWirm", - "MMX_PCMPGTBirm", - "MMX_PCMPGTDirm", - "MMX_PCMPGTWirm", - "MMX_PMAXSWirm", - "MMX_PMAXUBirm", - "MMX_PMINSWirm", - "MMX_PMINUBirm", - "MMX_PSUBSBirm", - "MMX_PSUBSWirm", - "MMX_PSUBUSBirm", - "MMX_PSUBUSWirm")>; - -def SKLWriteResGroup70 : SchedWriteRes<[SKLPort0,SKLPort01]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup70], (instregex "(V?)CVTSS2SI(64)?rr", - "(V?)CVT(T?)SD2SI(64)?rr")>; - -def SKLWriteResGroup72 : SchedWriteRes<[SKLPort6,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup72], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def SKLWriteResGroup74 : SchedWriteRes<[SKLPort23,SKLPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup74], (instregex "BT(16|32|64)mi8")>; - -def SKLWriteResGroup75 : SchedWriteRes<[SKLPort23,SKLPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup75], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def SKLWriteResGroup76 : SchedWriteRes<[SKLPort23,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup76], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[SKLWriteResGroup76], (instregex "POP(16|32|64)rmr")>; - -def SKLWriteResGroup78 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup78], (instregex "(V?)CVTSI642SSrr")>; - -def SKLWriteResGroup80 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup80], (instregex "SLDT(16|32|64)r")>; - -def SKLWriteResGroup82 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup82], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SKLWriteResGroup83 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup83], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def SKLWriteResGroup84 : SchedWriteRes<[SKLPort6,SKLPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[SKLWriteResGroup84], (instrs STD)>; - -def SKLWriteResGroup85 : SchedWriteRes<[SKLPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup85], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def SKLWriteResGroup86 : SchedWriteRes<[SKLPort0,SKLPort5]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup86], (instregex "VCVTDQ2PDYrr")>; - -def SKLWriteResGroup88 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup88], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def SKLWriteResGroup89 : SchedWriteRes<[SKLPort5,SKLPort01]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup89], (instregex "VCVTPD2PSYrr", - "VCVTPS2PDYrr", - "VCVT(T?)PD2DQYrr")>; - -def SKLWriteResGroup91 : SchedWriteRes<[SKLPort23,SKLPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup91], (instregex "(V?)INSERTF128rm", - "(V?)INSERTI128rm", - "(V?)PADD(B|D|Q|W)rm", - "(V?)PBLENDDrmi", - "(V?)PSUB(B|D|Q|W)rm")>; - -def SKLWriteResGroup92 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup92], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def SKLWriteResGroup94 : SchedWriteRes<[SKLPort23,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKLWriteResGroup94], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def SKLWriteResGroup95 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort01]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup95], (instregex "(V?)CVTTSS2SI(64)?rr")>; - -def SKLWriteResGroup96 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort05]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup96], (instrs FLDCW16m)>; - -def SKLWriteResGroup98 : SchedWriteRes<[SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup98], (instrs LRETQ, RETQ)>; - -def SKLWriteResGroup100 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup100], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SKLWriteResGroup101 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup101], (instregex "XADD(8|16|32|64)rm")>; - -def SKLWriteResGroup102 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup102], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def SKLWriteResGroup103 : SchedWriteRes<[SKLPort6,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,3,1,2]; -} -def: InstRW<[SKLWriteResGroup103], (instrs LOOP)>; - -def SKLWriteResGroup107 : SchedWriteRes<[SKLPort1,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup107], (instregex "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def SKLWriteResGroup107_16 : SchedWriteRes<[SKLPort1, SKLPort0156, SKLPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup107_16], (instrs IMUL16rmi, IMUL16rmi8)>; - -def SKLWriteResGroup107_16_2 : SchedWriteRes<[SKLPort1, SKLPort06, SKLPort0156, SKLPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SKLWriteResGroup107_16_2], (instrs IMUL16m, MUL16m)>; - -def SKLWriteResGroup108 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup108], (instregex "FCOM(P?)(32|64)m", - "VPBROADCASTBYrm", - "VPBROADCASTWYrm", - "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def SKLWriteResGroup110 : SchedWriteRes<[SKLPort23,SKLPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup110], (instregex "VPADD(B|D|Q|W)Yrm", - "VPBLENDDYrmi", - "VPSUB(B|D|Q|W)Yrm")>; - -def SKLWriteResGroup112 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKLWriteResGroup112], (instregex "MMX_PH(ADD|SUB)SWrm")>; - -def SKLWriteResGroup115 : SchedWriteRes<[SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[SKLWriteResGroup115], (instregex "ROR(8|16|32|64)mCL")>; - -def SKLWriteResGroup116 : SchedWriteRes<[SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup116], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def SKLWriteResGroup117 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[SKLWriteResGroup117], (instregex "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SKLWriteResGroup119 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: SchedAlias; -def: InstRW<[SKLWriteResGroup119], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SKLWriteResGroup120 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup120], (instregex "MMX_CVTPI2PSirm")>; - -def SKLWriteResGroup121 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup121], (instregex "(V?)PCMPGTQrm", - "VPMOVSXBWYrm", - "VPMOVSXDQYrm", - "VPMOVSXWDYrm", - "VPMOVZXWDYrm")>; - -def SKLWriteResGroup123 : SchedWriteRes<[SKLPort23,SKLPort01]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup123], (instregex "MMX_CVT(T?)PS2PIirm", - "(V?)CVTPS2PDrm")>; - -def SKLWriteResGroup127 : SchedWriteRes<[SKLPort1,SKLPort5,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup127], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def SKLWriteResGroup128 : SchedWriteRes<[SKLPort5,SKLPort01,SKLPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKLWriteResGroup128], (instregex "(V?)PHADDSWrm", - "(V?)PHSUBSWrm")>; - -def SKLWriteResGroup131 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup131], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def SKLWriteResGroup133 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup133], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VPCMPGTQYrm")>; - -def SKLWriteResGroup134 : SchedWriteRes<[SKLPort01,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup134], (instregex "(V?)CVTDQ2PSrm", - "(V?)CVTPS2DQrm", - "(V?)CVTSS2SDrm", - "(V?)CVTTPS2DQrm")>; - -def SKLWriteResGroup138 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup138], (instregex "MMX_CVTPI2PDirm")>; - -def SKLWriteResGroup139 : SchedWriteRes<[SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup139], (instregex "(V?)CVTSD2SSrm")>; - -def SKLWriteResGroup140 : SchedWriteRes<[SKLPort5,SKLPort01,SKLPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKLWriteResGroup140], (instregex "VPHADDSWYrm", - "VPHSUBSWYrm")>; - -def SKLWriteResGroup142 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort06,SKLPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup142], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def SKLWriteResGroup143 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 10; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,3]; -} -def: InstRW<[SKLWriteResGroup143], (instregex "XCHG(8|16|32|64)rm")>; - -def SKLWriteResGroup145 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup146 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup146], (instregex "MUL_F(32|64)m")>; - -def SKLWriteResGroup147 : SchedWriteRes<[SKLPort01,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup147], (instregex "VCVTDQ2PSYrm", - "VCVTPS2PDYrm", - "VCVT(T?)PS2DQYrm")>; - -def SKLWriteResGroup149 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup149], (instregex "FICOM(P?)(16|32)m")>; - -def SKLWriteResGroup150 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup150], (instregex "(V?)CVTDQ2PDrm")>; - -def SKLWriteResGroup151 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort01]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup151], (instregex "(V?)CVTSS2SI64rm", - "(V?)CVT(T?)SD2SI(64)?rm", - "VCVTTSS2SI64rm", - "(V?)CVT(T?)SS2SIrm")>; - -def SKLWriteResGroup152 : SchedWriteRes<[SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup152], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm")>; - -def SKLWriteResGroup154 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,3,2]; -} -def: InstRW<[SKLWriteResGroup154], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def SKLWriteResGroup155 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,5,1,2]; -} -def: InstRW<[SKLWriteResGroup155], (instregex "RCL8rCL")>; - -def SKLWriteResGroup156 : SchedWriteRes<[SKLPort06,SKLPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[SKLWriteResGroup156], (instrs LOOPE, LOOPNE)>; - -def SKLWriteResGroup160 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23,SKLPort01]> { - let Latency = 12; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKLWriteResGroup160], (instregex "CVTTSS2SI64rm")>; - -def SKLWriteResGroup162 : SchedWriteRes<[SKLPort5,SKLPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKLWriteResGroup162], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; - -def SKLWriteResGroup163 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup163], (instregex "VCVTDQ2PDYrm")>; - -def SKLWriteResGroup166 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup166_1 : SchedWriteRes<[SKLPort0,SKLFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup169 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup169], (instregex "MUL_FI(16|32)m")>; - -def SKLWriteResGroup170 : SchedWriteRes<[SKLPort1,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,4,1,3]; -} -def: InstRW<[SKLWriteResGroup170], (instregex "RCR8rCL")>; - -def SKLWriteResGroup171 : SchedWriteRes<[SKLPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup171], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup174 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,5,1,1]; -} -def: InstRW<[SKLWriteResGroup174], (instregex "RCL(8|16|32|64)mCL")>; - -def SKLWriteResGroup177 : SchedWriteRes<[SKLPort4,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[SKLWriteResGroup177], (instrs CMPXCHG8B)>; - -def SKLWriteResGroup178 : SchedWriteRes<[SKLPort0156]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[SKLWriteResGroup178], (instrs VZEROALL)>; - -def SKLWriteResGroup179 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 17; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup180 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort05,SKLPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[SKLWriteResGroup180], (instrs XCH_F)>; - -def SKLWriteResGroup184 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[SKLWriteResGroup184], (instrs CPUID, RDTSC)>; - -def SKLWriteResGroup185 : SchedWriteRes<[SKLPort1,SKLPort23,SKLPort237,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,4,1,2]; -} -def: InstRW<[SKLWriteResGroup185], (instregex "RCR(8|16|32|64)mCL")>; - -def SKLWriteResGroup186 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup189 : SchedWriteRes<[SKLPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKLWriteResGroup189], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def SKLWriteResGroup190 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 20; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup192 : SchedWriteRes<[SKLPort4,SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[SKLWriteResGroup192], (instrs INSB, INSL, INSW)>; - -def SKLWriteResGroup193 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[SKLWriteResGroup193], (instrs MWAITrr)>; - -def SKLWriteResGroup195 : SchedWriteRes<[SKLPort0,SKLPort23,SKLFPDivider]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKLWriteResGroup196 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup196], (instregex "DIV_F(32|64)m")>; - -def SKLWriteResGroup196_1 : SchedWriteRes<[SKLPort0, SKLPort23, SKLPort5, SKLPort015]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup196_1], (instrs VGATHERDPSrm, - VGATHERDPDrm, - VGATHERQPDrm, - VGATHERQPSrm, - VPGATHERDDrm, - VPGATHERDQrm, - VPGATHERQDrm, - VPGATHERQQrm)>; - -def SKLWriteResGroup196_2 : SchedWriteRes<[SKLPort0, SKLPort23, SKLPort5, SKLPort015]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKLWriteResGroup196_2], (instrs VGATHERDPSYrm, - VGATHERQPDYrm, - VGATHERQPSYrm, - VPGATHERDDYrm, - VPGATHERDQYrm, - VPGATHERQDYrm, - VPGATHERQQYrm, - VGATHERDPDYrm)>; - -def SKLWriteResGroup198 : SchedWriteRes<[SKLPort0,SKLPort4,SKLPort5,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[SKLWriteResGroup198], (instrs CMPXCHG16B)>; - -def SKLWriteResGroup202 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 25; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup202], (instregex "DIV_FI(16|32)m")>; - -def SKLWriteResGroup206 : SchedWriteRes<[SKLPort0,SKLPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKLWriteResGroup206], (instregex "DIVR_F(32|64)m")>; - -def SKLWriteResGroup207 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23,SKLPort0156]> { - let Latency = 28; - let NumMicroOps = 8; - let ResourceCycles = [2,4,1,1]; -} -def: InstRW<[SKLWriteResGroup207], (instregex "IDIV(8|16|32|64)m")>; - -def SKLWriteResGroup208 : SchedWriteRes<[SKLPort0,SKLPort5,SKLPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKLWriteResGroup208], (instregex "DIVR_FI(16|32)m")>; - -def SKLWriteResGroup209 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort23,SKLPort06,SKLPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[SKLWriteResGroup209], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def SKLWriteResGroup210 : SchedWriteRes<[SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[SKLWriteResGroup210], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def SKLWriteResGroup211 : SchedWriteRes<[SKLPort1,SKLPort6,SKLPort23,SKLPort0156]> { - let Latency = 37; - let NumMicroOps = 31; - let ResourceCycles = [1,8,1,21]; -} -def: InstRW<[SKLWriteResGroup211], (instregex "XRSTOR(64)?")>; - -def SKLWriteResGroup212 : SchedWriteRes<[SKLPort1,SKLPort4,SKLPort5,SKLPort6,SKLPort23,SKLPort237,SKLPort15,SKLPort0156]> { - let Latency = 40; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[SKLWriteResGroup212], (instrs VMCLEARm)>; - -def SKLWriteResGroup213 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 41; - let NumMicroOps = 39; - let ResourceCycles = [1,10,1,1,26]; -} -def: InstRW<[SKLWriteResGroup213], (instrs XSAVE64)>; - -def SKLWriteResGroup214 : SchedWriteRes<[SKLPort5,SKLPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[SKLWriteResGroup214], (instrs RDTSCP)>; - -def SKLWriteResGroup215 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 42; - let NumMicroOps = 40; - let ResourceCycles = [1,11,1,1,26]; -} -def: InstRW<[SKLWriteResGroup215], (instrs XSAVE)>; -def: InstRW<[SKLWriteResGroup215], (instregex "XSAVEC", "XSAVES")>; - -def SKLWriteResGroup216 : SchedWriteRes<[SKLPort4,SKLPort6,SKLPort23,SKLPort237,SKLPort0156]> { - let Latency = 46; - let NumMicroOps = 44; - let ResourceCycles = [1,11,1,1,30]; -} -def: InstRW<[SKLWriteResGroup216], (instregex "XSAVEOPT")>; - -def SKLWriteResGroup217 : SchedWriteRes<[SKLPort0,SKLPort23,SKLPort05,SKLPort06,SKLPort0156]> { - let Latency = 62; - let NumMicroOps = 64; - let ResourceCycles = [2,8,5,10,39]; -} -def: InstRW<[SKLWriteResGroup217], (instrs FLDENVm)>; - -def SKLWriteResGroup218 : SchedWriteRes<[SKLPort0,SKLPort6,SKLPort23,SKLPort05,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[SKLWriteResGroup218], (instrs FXRSTOR64)>; - -def SKLWriteResGroup219 : SchedWriteRes<[SKLPort0,SKLPort6,SKLPort23,SKLPort05,SKLPort06,SKLPort15,SKLPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[SKLWriteResGroup219], (instrs FXRSTOR)>; - -def SKLWriteResGroup220 : SchedWriteRes<[SKLPort5,SKLPort05,SKLPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[SKLWriteResGroup220], (instrs FNINIT)>; - -def SKLWriteResGroup221 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort05,SKLPort0156]> { - let Latency = 76; - let NumMicroOps = 32; - let ResourceCycles = [7,2,8,3,1,11]; -} -def: InstRW<[SKLWriteResGroup221], (instregex "DIV(16|32|64)r")>; - -def SKLWriteResGroup222 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort5,SKLPort6,SKLPort06,SKLPort0156]> { - let Latency = 102; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[SKLWriteResGroup222], (instregex "IDIV(16|32|64)r")>; - -def SKLWriteResGroup223 : SchedWriteRes<[SKLPort0,SKLPort1,SKLPort4,SKLPort5,SKLPort6,SKLPort237,SKLPort06,SKLPort0156]> { - let Latency = 106; - let NumMicroOps = 100; - let ResourceCycles = [9,1,11,16,1,11,21,30]; -} -def: InstRW<[SKLWriteResGroup223], (instrs FSTENVm)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86SchedSkylakeServer.td b/suite/synctools/tablegen/X86/back/X86SchedSkylakeServer.td deleted file mode 100755 index 9d5f8555c5..0000000000 --- a/suite/synctools/tablegen/X86/back/X86SchedSkylakeServer.td +++ /dev/null @@ -1,2580 +0,0 @@ -//=- X86SchedSkylake.td - X86 Skylake Server Scheduling ------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Skylake Server to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SkylakeServerModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SKylake can - // decode 6 instructions per cycle. - let IssueWidth = 6; - let MicroOpBufferSize = 224; // Based on the reorder buffer. - let LoadLatency = 5; - let MispredictPenalty = 14; - - // Based on the LSD (loop-stream detector) queue size and benchmarking data. - let LoopMicroOpBufferSize = 50; - - // This flag is set to allow the scheduler to assign a default model to - // unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SkylakeServerModel in { - -// Skylake Server can issue micro-ops to 8 different ports in one cycle. - -// Ports 0, 1, 5, and 6 handle all computation. -// Port 4 gets the data half of stores. Store data can be available later than -// the store address, but since we don't model the latency of stores, we can -// ignore that. -// Ports 2 and 3 are identical. They handle loads and the address half of -// stores. Port 7 can handle address calculations. -def SKXPort0 : ProcResource<1>; -def SKXPort1 : ProcResource<1>; -def SKXPort2 : ProcResource<1>; -def SKXPort3 : ProcResource<1>; -def SKXPort4 : ProcResource<1>; -def SKXPort5 : ProcResource<1>; -def SKXPort6 : ProcResource<1>; -def SKXPort7 : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SKXPort01 : ProcResGroup<[SKXPort0, SKXPort1]>; -def SKXPort23 : ProcResGroup<[SKXPort2, SKXPort3]>; -def SKXPort237 : ProcResGroup<[SKXPort2, SKXPort3, SKXPort7]>; -def SKXPort04 : ProcResGroup<[SKXPort0, SKXPort4]>; -def SKXPort05 : ProcResGroup<[SKXPort0, SKXPort5]>; -def SKXPort06 : ProcResGroup<[SKXPort0, SKXPort6]>; -def SKXPort15 : ProcResGroup<[SKXPort1, SKXPort5]>; -def SKXPort16 : ProcResGroup<[SKXPort1, SKXPort6]>; -def SKXPort56 : ProcResGroup<[SKXPort5, SKXPort6]>; -def SKXPort015 : ProcResGroup<[SKXPort0, SKXPort1, SKXPort5]>; -def SKXPort056 : ProcResGroup<[SKXPort0, SKXPort5, SKXPort6]>; -def SKXPort0156: ProcResGroup<[SKXPort0, SKXPort1, SKXPort5, SKXPort6]>; - -def SKXDivider : ProcResource<1>; // Integer division issued on port 0. -// FP division and sqrt on port 0. -def SKXFPDivider : ProcResource<1>; - -// 60 Entry Unified Scheduler -def SKXPortAny : ProcResGroup<[SKXPort0, SKXPort1, SKXPort2, SKXPort3, SKXPort4, - SKXPort5, SKXPort6, SKXPort7]> { - let BufferSize=60; -} - -// Loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SKXWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 5> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to - // the latency (default = 5). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = !add(UOps, 1); - } -} - -// A folded store needs a cycle on port 4 for the store data, and an extra port -// 2/3/7 cycle to recompute the address. -def : WriteRes; - -// Arithmetic. -defm : SKXWriteResPair; // Simple integer ALU op. -defm : SKXWriteResPair; // Integer ALU + flags op. -defm : SKXWriteResPair; // Integer multiplication. -defm : SKXWriteResPair; // Integer 64-bit multiplication. - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; - -def : WriteRes { let Latency = 3; } // Integer multiplication, high part. -def : WriteRes; // LEA instructions can't fold loads. - -defm : SKXWriteResPair; // Conditional move. -defm : SKXWriteResPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} -def : WriteRes; -def : WriteRes; // - -// Integer shifts and rotates. -defm : SKXWriteResPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Bit counts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Loads, stores, and moves, not folded with other operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def : WriteRes; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm : SKXWriteResPair; - -// Floating point. This covers both scalar and vector operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; // Floating point add/sub. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double add/sub. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point compare. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double compare. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point compare to flags. - -defm : SKXWriteResPair; // Floating point multiplication. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double multiplication. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // 10-14 cycles. // Floating point division. -//defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. -//defm : SKXWriteResPair; // 10-14 cycles. // Floating point division. -//defm : SKXWriteResPair; // 10-14 cycles. -//defm : SKXWriteResPair; // 10-14 cycles. -defm : SKXWriteResPair; // 10-14 cycles. - -defm : SKXWriteResPair; // Floating point square root. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double square root. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point long double square root. - -defm : SKXWriteResPair; // Floating point reciprocal estimate. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Floating point reciprocal square root estimate. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; // Fused Multiply Add. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point double dot product. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point fabs/fchs. -defm : SKXWriteResPair; // Floating point rounding. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point and/or/xor logicals. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point TEST instructions. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector variable shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Floating point vector blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Fp vector variable blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// FMA Scheduling helper class. -// class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Vector integer operations. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; // Vector integer ALU op, no logicals. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer and/or/xor. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer TEST instructions. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer multiply. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PMULLD. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector variable shuffles. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector variable blends. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector MPSAD. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PSADBW. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector PHMINPOS. - -// Vector integer shifts. -defm : SKXWriteResPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Vector integer immediate shifts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Variable vector shifts. -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Vector insert/extract operations. -def : WriteRes { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 6; - let NumMicroOps = 2; -} -def: InstRW<[WriteVecInsertLd], (instregex "(V?)MOV(H|L)(PD|PS)rm")>; - -def : WriteRes { - let Latency = 3; - let NumMicroOps = 2; -} -def : WriteRes { - let Latency = 2; - let NumMicroOps = 3; -} - -// Conversion between integer and float. -defm : SKXWriteResPair; // Needs more work: DD vs DQ. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; // Needs more work: DD vs DQ. -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -// Strings instructions. - -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 19; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 10; - let ResourceCycles = [4,3,1,1,1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def : WriteRes { - let Latency = 16; - let NumMicroOps = 4; - let ResourceCycles = [3,1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [4,3,1]; -} -def : WriteRes { - let Latency = 24; - let NumMicroOps = 9; - let ResourceCycles = [4,3,1,1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } -def : WriteRes { let Latency = 2; } - -// AES instructions. -def : WriteRes { // Decryption, encryption. - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -def : WriteRes { // InvMixColumn. - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} - -def : WriteRes { // Key Generation. - let Latency = 20; - let NumMicroOps = 11; - let ResourceCycles = [3,6,2]; -} -def : WriteRes { - let Latency = 25; - let NumMicroOps = 11; - let ResourceCycles = [3,6,1,1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def : WriteRes { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} - -// Catch-all for expensive system instructions. -def : WriteRes { let Latency = 100; } // def WriteSystem : SchedWrite; - -// AVX2. -defm : SKXWriteResPair; // Fp 256-bit width vector shuffles. -defm : SKXWriteResPair; // Fp 256-bit width vector variable shuffles. -defm : SKXWriteResPair; // 256-bit width vector shuffles. -defm : SKXWriteResPair; // 256-bit width vector variable shuffles. - -// Old microcoded instructions that nobody use. -def : WriteRes { let Latency = 100; } // def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def : WriteRes; - -// Load/store MXCSR. -def : WriteRes { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } -def : WriteRes { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } - -// Nop, not very useful expect it provides a model for nops! -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; -defm : SKXWriteResPair; - -// Remaining instrs. - -def SKXWriteResGroup1 : SchedWriteRes<[SKXPort0]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup1], (instregex "KAND(B|D|Q|W)rr", - "KANDN(B|D|Q|W)rr", - "KMOV(B|D|Q|W)kk", - "KNOT(B|D|Q|W)rr", - "KOR(B|D|Q|W)rr", - "KXNOR(B|D|Q|W)rr", - "KXOR(B|D|Q|W)rr", - "MMX_PADDS(B|W)irr", - "MMX_PADDUS(B|W)irr", - "MMX_PAVG(B|W)irr", - "MMX_PCMPEQ(B|D|W)irr", - "MMX_PCMPGT(B|D|W)irr", - "MMX_P(MAX|MIN)SWirr", - "MMX_P(MAX|MIN)UBirr", - "MMX_PSUBS(B|W)irr", - "MMX_PSUBUS(B|W)irr", - "VPMOVB2M(Z|Z128|Z256)rr", - "VPMOVD2M(Z|Z128|Z256)rr", - "VPMOVQ2M(Z|Z128|Z256)rr", - "VPMOVW2M(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup3 : SchedWriteRes<[SKXPort5]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup3], (instregex "COM(P?)_FST0r", - "KMOV(B|D|Q|W)kr", - "UCOM_F(P?)r")>; - -def SKXWriteResGroup4 : SchedWriteRes<[SKXPort6]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup4], (instregex "JMP(16|32|64)r")>; - -def SKXWriteResGroup6 : SchedWriteRes<[SKXPort05]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup6], (instrs FINCSTP, FNOP)>; - -def SKXWriteResGroup7 : SchedWriteRes<[SKXPort06]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup7], (instrs CDQ, CQO, CLAC, STAC)>; - -def SKXWriteResGroup8 : SchedWriteRes<[SKXPort15]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup8], (instregex "ANDN(32|64)rr", - "BLSI(32|64)rr", - "BLSMSK(32|64)rr", - "BLSR(32|64)rr")>; - -def SKXWriteResGroup9 : SchedWriteRes<[SKXPort015]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup9], (instregex "VBLENDMPD(Z128|Z256)rr", - "VBLENDMPS(Z128|Z256)rr", - "VPADD(B|D|Q|W)(Y|Z|Z128|Z256)rr", - "(V?)PADD(B|D|Q|W)rr", - "VPBLENDD(Y?)rri", - "VPBLENDMB(Z128|Z256)rr", - "VPBLENDMD(Z128|Z256)rr", - "VPBLENDMQ(Z128|Z256)rr", - "VPBLENDMW(Z128|Z256)rr", - "VPSUB(B|D|Q|W)(Y|Z|Z128|Z256)rr", - "(V?)PSUB(B|D|Q|W)rr", - "VPTERNLOGD(Z|Z128|Z256)rri", - "VPTERNLOGQ(Z|Z128|Z256)rri")>; - -def SKXWriteResGroup10 : SchedWriteRes<[SKXPort0156]> { - let Latency = 1; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup10], (instrs CBW, CWDE, CDQE, - CMC, STC)>; -def: InstRW<[SKXWriteResGroup10], (instregex "SGDT64m", - "SIDT64m", - "SMSW16m", - "STRm", - "SYSCALL")>; - -def SKXWriteResGroup11 : SchedWriteRes<[SKXPort4,SKXPort237]> { - let Latency = 1; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup11], (instregex "FBSTPm", - "KMOV(B|D|Q|W)mk", - "ST_FP(32|64|80)m", - "VMPTRSTm")>; - -def SKXWriteResGroup13 : SchedWriteRes<[SKXPort5]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup13], (instregex "MMX_MOVQ2DQrr")>; - -def SKXWriteResGroup14 : SchedWriteRes<[SKXPort05]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup14], (instrs FDECSTP)>; -def: InstRW<[SKXWriteResGroup14], (instregex "MMX_MOVDQ2Qrr")>; - -def SKXWriteResGroup15 : SchedWriteRes<[SKXPort06]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup15], (instregex "ROL(8|16|32|64)r1", - "ROL(8|16|32|64)ri", - "ROR(8|16|32|64)r1", - "ROR(8|16|32|64)ri", - "SET(A|BE)r")>; - -def SKXWriteResGroup17 : SchedWriteRes<[SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup17], (instrs LFENCE, - WAIT, - XGETBV)>; - -def SKXWriteResGroup20 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup20], (instregex "CLFLUSH")>; - -def SKXWriteResGroup21 : SchedWriteRes<[SKXPort237,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup21], (instrs SFENCE)>; - -def SKXWriteResGroup23 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup23], (instrs CWD)>; -def: InstRW<[SKXWriteResGroup23], (instrs JCXZ, JECXZ, JRCXZ)>; -def: InstRW<[SKXWriteResGroup23], (instregex "ADC8i8", - "ADC8ri", - "SBB8i8", - "SBB8ri")>; - -def SKXWriteResGroup25 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort237]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup25], (instrs FNSTCW16m)>; - -def SKXWriteResGroup27 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort15]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup27], (instregex "MOVBE(16|32|64)mr")>; - -def SKXWriteResGroup28 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup28], (instrs PUSH16r, PUSH32r, PUSH64r, - STOSB, STOSL, STOSQ, STOSW)>; -def: InstRW<[SKXWriteResGroup28], (instregex "PUSH(16|32|64)rmr", - "PUSH64i8")>; - -def SKXWriteResGroup29 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort15]> { - let Latency = 2; - let NumMicroOps = 5; - let ResourceCycles = [2,2,1]; -} -def: InstRW<[SKXWriteResGroup29], (instregex "VMOVDQU8Zmr(b?)")>; - -def SKXWriteResGroup30 : SchedWriteRes<[SKXPort0]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup30], (instregex "KMOV(B|D|Q|W)rk", - "KORTEST(B|D|Q|W)rr", - "KTEST(B|D|Q|W)rr")>; - -def SKXWriteResGroup31 : SchedWriteRes<[SKXPort1]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup31], (instregex "PDEP(32|64)rr", - "PEXT(32|64)rr")>; - -def SKXWriteResGroup31_16i : SchedWriteRes<[SKXPort1, SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup31_16i], (instrs IMUL16rri, IMUL16rri8)>; - - -def SKXWriteResGroup32 : SchedWriteRes<[SKXPort5]> { - let Latency = 3; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup32], (instregex "(ADD|SUB|SUBR)_(FPrST0|FST0r|FrST0)", - "KADD(B|D|Q|W)rr", - "KSHIFTL(B|D|Q|W)ri", - "KSHIFTR(B|D|Q|W)ri", - "KUNPCKBWrr", - "KUNPCKDQrr", - "KUNPCKWDrr", - "VALIGND(Z|Z128|Z256)rri", - "VALIGNQ(Z|Z128|Z256)rri", - "VCMPPD(Z|Z128|Z256)rri", - "VCMPPS(Z|Z128|Z256)rri", - "VCMPSDZrr", - "VCMPSSZrr", - "VDBPSADBWZrri", // TODO: 512-bit ops require ports 0/1 to be joined. - "VFPCLASSPD(Z|Z128|Z256)rr", - "VFPCLASSPS(Z|Z128|Z256)rr", - "VFPCLASSSDZrr", - "VFPCLASSSSZrr", - "VPBROADCASTBrr", - "VPBROADCASTWrr", - "VPCMPB(Z|Z128|Z256)rri", - "VPCMPD(Z|Z128|Z256)rri", - "VPCMPEQ(B|D|Q|W)(Z|Z128|Z256)rr", - "VPCMPGT(B|D|Q|W)(Z|Z128|Z256)rr", - "(V?)PCMPGTQ(Y?)rr", - "VPCMPQ(Z|Z128|Z256)rri", - "VPCMPU(B|D|Q|W)(Z|Z128|Z256)rri", - "VPCMPW(Z|Z128|Z256)rri", - "VP(MAX|MIN)(S|U)Q(Z|Z128|Z256)rr", - "VPSADBWZrr", // TODO: 512-bit ops require ports 0/1 to be joined. - "VPTEST(N?)M(B|D|Q|W)(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup34 : SchedWriteRes<[SKXPort0,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup34], (instrs FNSTSW16r)>; - -def SKXWriteResGroup35 : SchedWriteRes<[SKXPort06]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup35], (instregex "ROL(8|16|32|64)rCL", - "ROR(8|16|32|64)rCL", - "SAR(8|16|32|64)rCL", - "SHL(8|16|32|64)rCL", - "SHR(8|16|32|64)rCL")>; - -def SKXWriteResGroup36 : SchedWriteRes<[SKXPort0156]> { - let Latency = 2; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup36], (instrs XADD8rr, XADD16rr, XADD32rr, XADD64rr, - XCHG8rr, XCHG16rr, XCHG32rr, XCHG64rr, - XCHG16ar, XCHG32ar, XCHG64ar)>; - -def SKXWriteResGroup37 : SchedWriteRes<[SKXPort0,SKXPort5]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup37], (instregex "MMX_PH(ADD|SUB)SWrr")>; - -def SKXWriteResGroup38 : SchedWriteRes<[SKXPort5,SKXPort01]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup38], (instregex "(V?)PH(ADD|SUB)SW(Y?)rr")>; - -def SKXWriteResGroup41 : SchedWriteRes<[SKXPort5,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup41], (instregex "MMX_PACKSSDWirr", - "MMX_PACKSSWBirr", - "MMX_PACKUSWBirr")>; - -def SKXWriteResGroup42 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup42], (instregex "CLD")>; - -def SKXWriteResGroup43 : SchedWriteRes<[SKXPort237,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup43], (instrs MFENCE)>; - -def SKXWriteResGroup44 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup44], (instregex "RCL(8|16|32|64)r1", - "RCL(8|16|32|64)ri", - "RCR(8|16|32|64)r1", - "RCR(8|16|32|64)ri")>; - -def SKXWriteResGroup45 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237]> { - let Latency = 3; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup45], (instrs FNSTSWm)>; - -def SKXWriteResGroup46 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort06]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup46], (instregex "SET(A|BE)m")>; - -def SKXWriteResGroup47 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort237,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup47], (instregex "CALL(16|32|64)r")>; - -def SKXWriteResGroup48 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 3; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup48], (instrs CALL64pcrel32)>; - -def SKXWriteResGroup49 : SchedWriteRes<[SKXPort0]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup49], (instregex "MUL_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup50 : SchedWriteRes<[SKXPort01]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup50], (instregex "VCVTDQ2PS(Y|Z128|Z256)rr", - "(V?)CVTDQ2PSrr", - "VCVTPD2QQ(Z128|Z256)rr", - "VCVTPD2UQQ(Z128|Z256)rr", - "VCVTPS2DQ(Y|Z128|Z256)rr", - "(V?)CVTPS2DQrr", - "VCVTPS2UDQ(Z128|Z256)rr", - "VCVTQQ2PD(Z128|Z256)rr", - "VCVTTPD2QQ(Z128|Z256)rr", - "VCVTTPD2UQQ(Z128|Z256)rr", - "VCVTTPS2DQ(Z128|Z256)rr", - "(V?)CVTTPS2DQrr", - "VCVTTPS2UDQ(Z128|Z256)rr", - "VCVTUDQ2PS(Z128|Z256)rr", - "VCVTUQQ2PD(Z128|Z256)rr")>; - -def SKXWriteResGroup50z : SchedWriteRes<[SKXPort05]> { - let Latency = 4; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup50z], (instrs VCVTDQ2PSZrr, - VCVTPD2QQZrr, - VCVTPD2UQQZrr, - VCVTPS2DQZrr, - VCVTPS2UDQZrr, - VCVTQQ2PDZrr, - VCVTTPD2QQZrr, - VCVTTPD2UQQZrr, - VCVTTPS2DQZrr, - VCVTTPS2UDQZrr, - VCVTUDQ2PSZrr, - VCVTUQQ2PDZrr)>; - -def SKXWriteResGroup51 : SchedWriteRes<[SKXPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup51], (instregex "VEXPANDPD(Z|Z128|Z256)rr", - "VEXPANDPS(Z|Z128|Z256)rr", - "VPEXPANDD(Z|Z128|Z256)rr", - "VPEXPANDQ(Z|Z128|Z256)rr", - "VPMOVDB(Z|Z128|Z256)rr", - "VPMOVDW(Z|Z128|Z256)rr", - "VPMOVQB(Z|Z128|Z256)rr", - "VPMOVQW(Z|Z128|Z256)rr", - "VPMOVSDB(Z|Z128|Z256)rr", - "VPMOVSDW(Z|Z128|Z256)rr", - "VPMOVSQB(Z|Z128|Z256)rr", - "VPMOVSQD(Z|Z128|Z256)rr", - "VPMOVSQW(Z|Z128|Z256)rr", - "VPMOVSWB(Z|Z128|Z256)rr", - "VPMOVUSDB(Z|Z128|Z256)rr", - "VPMOVUSDW(Z|Z128|Z256)rr", - "VPMOVUSQB(Z|Z128|Z256)rr", - "VPMOVUSQD(Z|Z128|Z256)rr", - "VPMOVUSWB(Z|Z128|Z256)rr", - "VPMOVWB(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup52 : SchedWriteRes<[SKXPort1,SKXPort5]> { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup52], (instrs IMUL64r, MUL64r, MULX64rr)>; - -def SKXWriteResGroup52_16 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup52_16], (instrs IMUL16r, MUL16r)>; - -def SKXWriteResGroup54 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup54], (instregex "IST(T?)_FP(16|32|64)m", - "IST_F(16|32)m", - "VPMOVQD(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup55 : SchedWriteRes<[SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [4]; -} -def: InstRW<[SKXWriteResGroup55], (instrs FNCLEX)>; - -def SKXWriteResGroup56 : SchedWriteRes<[SKXPort015,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup56], (instrs VZEROUPPER)>; - -def SKXWriteResGroup57 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 4; - let ResourceCycles = [1,1,2]; -} -def: InstRW<[SKXWriteResGroup57], (instregex "LAR(16|32|64)rr")>; - -def SKXWriteResGroup58 : SchedWriteRes<[SKXPort23]> { - let Latency = 5; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup58], (instregex "MOVSX(16|32|64)rm16", - "MOVSX(16|32|64)rm32", - "MOVSX(16|32|64)rm8", - "MOVZX(16|32|64)rm16", - "MOVZX(16|32|64)rm8", - "(V?)MOVDDUPrm")>; // TODO: Should this be SKXWriteResGroup71? - -def SKXWriteResGroup61 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup61], (instregex "MMX_CVT(T?)PD2PIirr", - "MMX_CVT(T?)PS2PIirr", - "VCVTDQ2PDZ128rr", - "VCVTPD2DQZ128rr", - "(V?)CVT(T?)PD2DQrr", - "VCVTPD2PSZ128rr", - "(V?)CVTPD2PSrr", - "VCVTPD2UDQZ128rr", - "VCVTPS2PDZ128rr", - "(V?)CVTPS2PDrr", - "VCVTPS2QQZ128rr", - "VCVTPS2UQQZ128rr", - "VCVTQQ2PSZ128rr", - "(V?)CVTSD2SS(Z?)rr", - "(V?)CVTSI(64)?2SDrr", - "VCVTSI2SSZrr", - "(V?)CVTSI2SSrr", - "VCVTSI(64)?2SDZrr", - "VCVTSS2SDZrr", - "(V?)CVTSS2SDrr", - "VCVTTPD2DQZ128rr", - "VCVTTPD2UDQZ128rr", - "VCVTTPS2QQZ128rr", - "VCVTTPS2UQQZ128rr", - "VCVTUDQ2PDZ128rr", - "VCVTUQQ2PSZ128rr", - "VCVTUSI2SSZrr", - "VCVTUSI(64)?2SDZrr")>; - -def SKXWriteResGroup62 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup62], (instregex "VPCONFLICTQZ128rr")>; - -def SKXWriteResGroup63 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort06]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup63], (instregex "STR(16|32|64)r")>; - -def SKXWriteResGroup64 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 4; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup64], (instrs IMUL32r, MUL32r, MULX32rr)>; - -def SKXWriteResGroup65 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort015]> { - let Latency = 5; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup65], (instregex "VCVTPS2PHZ128mr(b?)", - "VCVTPS2PHZ256mr(b?)", - "VCVTPS2PHZmr(b?)")>; - -def SKXWriteResGroup66 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 5; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup66], (instregex "VPMOVDB(Z|Z128|Z256)mr(b?)", - "VPMOVDW(Z|Z128|Z256)mr(b?)", - "VPMOVQB(Z|Z128|Z256)mr(b?)", - "VPMOVQW(Z|Z128|Z256)mr(b?)", - "VPMOVSDB(Z|Z128|Z256)mr(b?)", - "VPMOVSDW(Z|Z128|Z256)mr(b?)", - "VPMOVSQB(Z|Z128|Z256)mr(b?)", - "VPMOVSQD(Z|Z128|Z256)mr(b?)", - "VPMOVSQW(Z|Z128|Z256)mr(b?)", - "VPMOVSWB(Z|Z128|Z256)mr(b?)", - "VPMOVUSDB(Z|Z128|Z256)mr(b?)", - "VPMOVUSDW(Z|Z128|Z256)mr(b?)", - "VPMOVUSQB(Z|Z128|Z256)mr(b?)", - "VPMOVUSQD(Z|Z128|Z256)mr(b?)", - "VPMOVUSQW(Z|Z128|Z256)mr(b?)", - "VPMOVUSWB(Z|Z128|Z256)mr(b?)", - "VPMOVWB(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup67 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [1,4]; -} -def: InstRW<[SKXWriteResGroup67], (instrs XSETBV)>; - -def SKXWriteResGroup68 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 5; - let ResourceCycles = [2,3]; -} -def: InstRW<[SKXWriteResGroup68], (instregex "CMPXCHG(8|16|32|64)rr")>; - -def SKXWriteResGroup69 : SchedWriteRes<[SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 5; - let NumMicroOps = 6; - let ResourceCycles = [1,1,4]; -} -def: InstRW<[SKXWriteResGroup69], (instregex "PUSHF(16|64)")>; - -def SKXWriteResGroup71 : SchedWriteRes<[SKXPort23]> { - let Latency = 6; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup71], (instregex "VBROADCASTSSrm", - "(V?)MOVSHDUPrm", - "(V?)MOVSLDUPrm", - "VPBROADCASTDrm", - "VPBROADCASTQrm")>; - -def SKXWriteResGroup72 : SchedWriteRes<[SKXPort5]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def: InstRW<[SKXWriteResGroup72], (instregex "MMX_CVTPI2PSirr", - "VCOMPRESSPD(Z|Z128|Z256)rr", - "VCOMPRESSPS(Z|Z128|Z256)rr", - "VPCOMPRESSD(Z|Z128|Z256)rr", - "VPCOMPRESSQ(Z|Z128|Z256)rr", - "VPERMW(Z|Z128|Z256)rr")>; - -def SKXWriteResGroup73 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup73], (instregex "MMX_PADDSBirm", - "MMX_PADDSWirm", - "MMX_PADDUSBirm", - "MMX_PADDUSWirm", - "MMX_PAVGBirm", - "MMX_PAVGWirm", - "MMX_PCMPEQBirm", - "MMX_PCMPEQDirm", - "MMX_PCMPEQWirm", - "MMX_PCMPGTBirm", - "MMX_PCMPGTDirm", - "MMX_PCMPGTWirm", - "MMX_PMAXSWirm", - "MMX_PMAXUBirm", - "MMX_PMINSWirm", - "MMX_PMINUBirm", - "MMX_PSUBSBirm", - "MMX_PSUBSWirm", - "MMX_PSUBUSBirm", - "MMX_PSUBUSWirm")>; - -def SKXWriteResGroup76 : SchedWriteRes<[SKXPort6,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup76], (instregex "FARJMP64", - "JMP(16|32|64)m")>; - -def SKXWriteResGroup78 : SchedWriteRes<[SKXPort23,SKXPort06]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup78], (instregex "BT(16|32|64)mi8")>; - -def SKXWriteResGroup79 : SchedWriteRes<[SKXPort23,SKXPort15]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup79], (instregex "ANDN(32|64)rm", - "BLSI(32|64)rm", - "BLSMSK(32|64)rm", - "BLSR(32|64)rm", - "MOVBE(16|32|64)rm")>; - -def SKXWriteResGroup80 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup80], (instregex "VMOV(64to|QI2)PQIZrm(b?)", - "VMOVDI2PDIZrm(b?)")>; - -def SKXWriteResGroup81 : SchedWriteRes<[SKXPort23,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup81], (instrs POP16r, POP32r, POP64r)>; -def: InstRW<[SKXWriteResGroup81], (instregex "POP(16|32|64)rmr")>; - -def SKXWriteResGroup82 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 6; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup82], (instregex "(V?)CVTSI642SSrr", - "VCVTSI642SSZrr", - "VCVTUSI642SSZrr")>; - -def SKXWriteResGroup84 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup84], (instregex "SLDT(16|32|64)r")>; - -def SKXWriteResGroup86 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup86], (instregex "BTC(16|32|64)mi8", - "BTR(16|32|64)mi8", - "BTS(16|32|64)mi8", - "SAR(8|16|32|64)m1", - "SAR(8|16|32|64)mi", - "SHL(8|16|32|64)m1", - "SHL(8|16|32|64)mi", - "SHR(8|16|32|64)m1", - "SHR(8|16|32|64)mi")>; - -def SKXWriteResGroup87 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup87], (instregex "POP(16|32|64)rmm", - "PUSH(16|32|64)rmm")>; - -def SKXWriteResGroup88 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 6; - let NumMicroOps = 6; - let ResourceCycles = [1,5]; -} -def: InstRW<[SKXWriteResGroup88], (instrs STD)>; - -def SKXWriteResGroup89 : SchedWriteRes<[SKXPort23]> { - let Latency = 7; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup89], (instregex "LD_F(32|64|80)m", - "VBROADCASTF128", - "VBROADCASTI128", - "VBROADCASTSDYrm", - "VBROADCASTSSYrm", - "VMOVDDUPYrm", - "VMOVSHDUPYrm", - "VMOVSLDUPYrm", - "VPBROADCASTDYrm", - "VPBROADCASTQYrm")>; - -def SKXWriteResGroup90 : SchedWriteRes<[SKXPort01,SKXPort5]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup90], (instregex "VCVTDQ2PDYrr")>; - -def SKXWriteResGroup92 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup92], (instregex "VMOVSDZrm(b?)", - "VMOVSSZrm(b?)")>; - -def SKXWriteResGroup92a : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 6; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup92a], (instregex "(V?)PMOV(SX|ZX)BDrm", - "(V?)PMOV(SX|ZX)BQrm", - "(V?)PMOV(SX|ZX)BWrm", - "(V?)PMOV(SX|ZX)DQrm", - "(V?)PMOV(SX|ZX)WDrm", - "(V?)PMOV(SX|ZX)WQrm")>; - -def SKXWriteResGroup93 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup93], (instregex "VCVTDQ2PDZ256rr", - "VCVTPD2DQ(Y|Z256)rr", - "VCVTPD2PS(Y|Z256)rr", - "VCVTPD2UDQZ256rr", - "VCVTPS2PD(Y|Z256)rr", - "VCVTPS2QQZ256rr", - "VCVTPS2UQQZ256rr", - "VCVTQQ2PSZ256rr", - "VCVTTPD2DQ(Y|Z256)rr", - "VCVTTPD2UDQZ256rr", - "VCVTTPS2QQZ256rr", - "VCVTTPS2UQQZ256rr", - "VCVTUDQ2PDZ256rr", - "VCVTUQQ2PSZ256rr")>; - -def SKXWriteResGroup93z : SchedWriteRes<[SKXPort5,SKXPort05]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup93z], (instrs VCVTDQ2PDZrr, - VCVTPD2DQZrr, - VCVTPD2PSZrr, - VCVTPD2UDQZrr, - VCVTPS2PDZrr, - VCVTPS2QQZrr, - VCVTPS2UQQZrr, - VCVTQQ2PSZrr, - VCVTTPD2DQZrr, - VCVTTPD2UDQZrr, - VCVTTPS2QQZrr, - VCVTTPS2UQQZrr, - VCVTUDQ2PDZrr, - VCVTUQQ2PSZrr)>; - -def SKXWriteResGroup95 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup95], (instregex "VBLENDMPDZ128rm(b?)", - "VBLENDMPSZ128rm(b?)", - "VBROADCASTI32X2Z128m(b?)", - "VBROADCASTSSZ128m(b?)", - "VINSERTF128rm", - "VINSERTI128rm", - "VMOVAPDZ128rm(b?)", - "VMOVAPSZ128rm(b?)", - "VMOVDDUPZ128rm(b?)", - "VMOVDQA32Z128rm(b?)", - "VMOVDQA64Z128rm(b?)", - "VMOVDQU16Z128rm(b?)", - "VMOVDQU32Z128rm(b?)", - "VMOVDQU64Z128rm(b?)", - "VMOVDQU8Z128rm(b?)", - "VMOVNTDQAZ128rm(b?)", - "VMOVSHDUPZ128rm(b?)", - "VMOVSLDUPZ128rm(b?)", - "VMOVUPDZ128rm(b?)", - "VMOVUPSZ128rm(b?)", - "VPADD(B|D|Q|W)Z128rm(b?)", - "(V?)PADD(B|D|Q|W)rm", - "VPBLENDDrmi", - "VPBLENDM(B|D|Q|W)Z128rm(b?)", - "VPBROADCASTDZ128m(b?)", - "VPBROADCASTQZ128m(b?)", - "VPSUB(B|D|Q|W)Z128rm(b?)", - "(V?)PSUB(B|D|Q|W)rm", - "VPTERNLOGDZ128rm(b?)i", - "VPTERNLOGQZ128rm(b?)i")>; - -def SKXWriteResGroup96 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup96], (instregex "MMX_PACKSSDWirm", - "MMX_PACKSSWBirm", - "MMX_PACKUSWBirm")>; - -def SKXWriteResGroup97 : SchedWriteRes<[SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup97], (instregex "VPERMI2W128rr", - "VPERMI2W256rr", - "VPERMI2Wrr", - "VPERMT2W128rr", - "VPERMT2W256rr", - "VPERMT2Wrr")>; - -def SKXWriteResGroup99 : SchedWriteRes<[SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup99], (instrs LEAVE, LEAVE64, - SCASB, SCASL, SCASQ, SCASW)>; - -def SKXWriteResGroup100 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort015]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup100], (instregex "VCVTSS2USI64Zrr", - "(V?)CVTSS2SI64(Z?)rr", - "(V?)CVTTSS2SI64(Z?)rr", - "VCVTTSS2USI64Zrr")>; - -def SKXWriteResGroup101 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort05]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup101], (instrs FLDCW16m)>; - -def SKXWriteResGroup103 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup103], (instregex "KMOV(B|D|Q|W)km")>; - -def SKXWriteResGroup104 : SchedWriteRes<[SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup104], (instrs LRETQ, RETQ)>; - -def SKXWriteResGroup106 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort237]> { - let Latency = 7; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup106], (instregex "VCOMPRESSPD(Z|Z128|Z256)mr(b?)", - "VCOMPRESSPS(Z|Z128|Z256)mr(b?)", - "VPCOMPRESSD(Z|Z128|Z256)mr(b?)", - "VPCOMPRESSQ(Z|Z128|Z256)mr(b?)")>; - -def SKXWriteResGroup107 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup107], (instregex "ROL(8|16|32|64)m1", - "ROL(8|16|32|64)mi", - "ROR(8|16|32|64)m1", - "ROR(8|16|32|64)mi")>; - -def SKXWriteResGroup108 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup108], (instregex "XADD(8|16|32|64)rm")>; - -def SKXWriteResGroup109 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup109], (instregex "CALL(16|32|64)m", - "FARCALL64")>; - -def SKXWriteResGroup110 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,2,2,2]; -} -def: InstRW<[SKXWriteResGroup110], (instrs VPSCATTERDQZ128mr, - VPSCATTERQQZ128mr, - VSCATTERDPDZ128mr, - VSCATTERQPDZ128mr)>; - -def SKXWriteResGroup111 : SchedWriteRes<[SKXPort6,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 7; - let ResourceCycles = [1,3,1,2]; -} -def: InstRW<[SKXWriteResGroup111], (instrs LOOP)>; - -def SKXWriteResGroup112 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 11; - let ResourceCycles = [1,4,4,2]; -} -def: InstRW<[SKXWriteResGroup112], (instrs VPSCATTERDQZ256mr, - VPSCATTERQQZ256mr, - VSCATTERDPDZ256mr, - VSCATTERQPDZ256mr)>; - -def SKXWriteResGroup113 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 19; - let ResourceCycles = [1,8,8,2]; -} -def: InstRW<[SKXWriteResGroup113], (instrs VPSCATTERDQZmr, - VPSCATTERQQZmr, - VSCATTERDPDZmr, - VSCATTERQPDZmr)>; - -def SKXWriteResGroup114 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 7; - let NumMicroOps = 36; - let ResourceCycles = [1,16,1,16,2]; -} -def: InstRW<[SKXWriteResGroup114], (instrs VSCATTERDPSZmr)>; - -def SKXWriteResGroup118 : SchedWriteRes<[SKXPort1,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup118], (instregex "PDEP(32|64)rm", - "PEXT(32|64)rm")>; - -def SKXWriteResGroup118_16_1 : SchedWriteRes<[SKXPort1, SKXPort0156, SKXPort23]> { - let Latency = 8; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup118_16_1], (instrs IMUL16rm, IMUL16rmi, IMUL16rmi8)>; - -def SKXWriteResGroup118_16_2 : SchedWriteRes<[SKXPort1, SKXPort06, SKXPort0156, SKXPort23]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,1,2,1]; -} -def: InstRW<[SKXWriteResGroup118_16_2], (instrs IMUL16m, MUL16m)>; - -def SKXWriteResGroup119 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup119], (instregex "FCOM(P?)(32|64)m", - "VFPCLASSSDZrm(b?)", - "VPBROADCASTBYrm", - "VPBROADCASTB(Z|Z256)m(b?)", - "VPBROADCASTWYrm", - "VPBROADCASTW(Z|Z256)m(b?)", - "VPMOVSXBDYrm", - "VPMOVSXBQYrm", - "VPMOVSXWQYrm")>; - -def SKXWriteResGroup121 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup121], (instregex "VBLENDMPD(Z|Z256)rm(b?)", - "VBLENDMPS(Z|Z256)rm(b?)", - "VBROADCASTF32X2Z256m(b?)", - "VBROADCASTF32X2Zm(b?)", - "VBROADCASTF32X4Z256rm(b?)", - "VBROADCASTF32X4rm(b?)", - "VBROADCASTF32X8rm(b?)", - "VBROADCASTF64X2Z128rm(b?)", - "VBROADCASTF64X2rm(b?)", - "VBROADCASTF64X4rm(b?)", - "VBROADCASTI32X2Z256m(b?)", - "VBROADCASTI32X2Zm(b?)", - "VBROADCASTI32X4Z256rm(b?)", - "VBROADCASTI32X4rm(b?)", - "VBROADCASTI32X8rm(b?)", - "VBROADCASTI64X2Z128rm(b?)", - "VBROADCASTI64X2rm(b?)", - "VBROADCASTI64X4rm(b?)", - "VBROADCASTSD(Z|Z256)m(b?)", - "VBROADCASTSS(Z|Z256)m(b?)", - "VINSERTF32x4(Z|Z256)rm(b?)", - "VINSERTF32x8Zrm(b?)", - "VINSERTF64x2(Z|Z256)rm(b?)", - "VINSERTF64x4Zrm(b?)", - "VINSERTI32x4(Z|Z256)rm(b?)", - "VINSERTI32x8Zrm(b?)", - "VINSERTI64x2(Z|Z256)rm(b?)", - "VINSERTI64x4Zrm(b?)", - "VMOVAPD(Z|Z256)rm(b?)", - "VMOVAPS(Z|Z256)rm(b?)", - "VMOVDDUP(Z|Z256)rm(b?)", - "VMOVDQA32(Z|Z256)rm(b?)", - "VMOVDQA64(Z|Z256)rm(b?)", - "VMOVDQU16(Z|Z256)rm(b?)", - "VMOVDQU32(Z|Z256)rm(b?)", - "VMOVDQU64(Z|Z256)rm(b?)", - "VMOVDQU8(Z|Z256)rm(b?)", - "VMOVNTDQAZ256rm(b?)", - "VMOVSHDUP(Z|Z256)rm(b?)", - "VMOVSLDUP(Z|Z256)rm(b?)", - "VMOVUPD(Z|Z256)rm(b?)", - "VMOVUPS(Z|Z256)rm(b?)", - "VPADD(B|D|Q|W)Yrm", - "VPADD(B|D|Q|W)(Z|Z256)rm(b?)", - "VPBLENDDYrmi", - "VPBLENDM(B|D|Q|W)(Z|Z256)rm(b?)", - "VPBROADCASTD(Z|Z256)m(b?)", - "VPBROADCASTQ(Z|Z256)m(b?)", - "VPSUB(B|D|Q|W)Yrm", - "VPSUB(B|D|Q|W)(Z|Z256)rm(b?)", - "VPTERNLOGD(Z|Z256)rm(b?)i", - "VPTERNLOGQ(Z|Z256)rm(b?)i")>; - -def SKXWriteResGroup123 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 8; - let NumMicroOps = 4; - let ResourceCycles = [1,2,1]; -} -def: InstRW<[SKXWriteResGroup123], (instregex "MMX_PH(ADD|SUB)SWrm")>; - -def SKXWriteResGroup126 : SchedWriteRes<[SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,3]; -} -def: InstRW<[SKXWriteResGroup126], (instregex "ROR(8|16|32|64)mCL")>; - -def SKXWriteResGroup127 : SchedWriteRes<[SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 5; - let ResourceCycles = [1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup127], (instregex "RCL(8|16|32|64)m1", - "RCL(8|16|32|64)mi", - "RCR(8|16|32|64)m1", - "RCR(8|16|32|64)mi")>; - -def SKXWriteResGroup128 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,3]; -} -def: InstRW<[SKXWriteResGroup128], (instregex "ROL(8|16|32|64)mCL", - "SAR(8|16|32|64)mCL", - "SHL(8|16|32|64)mCL", - "SHR(8|16|32|64)mCL")>; - -def SKXWriteResGroup130 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 6; - let ResourceCycles = [1,1,1,2,1]; -} -def: SchedAlias; -def: InstRW<[SKXWriteResGroup130], (instregex "CMPXCHG(8|16|32|64)rm")>; - -def SKXWriteResGroup131 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 8; - let ResourceCycles = [1,2,1,2,2]; -} -def: InstRW<[SKXWriteResGroup131], (instrs VPSCATTERQDZ128mr, - VPSCATTERQDZ256mr, - VSCATTERQPSZ128mr, - VSCATTERQPSZ256mr)>; - -def SKXWriteResGroup132 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 12; - let ResourceCycles = [1,4,1,4,2]; -} -def: InstRW<[SKXWriteResGroup132], (instrs VPSCATTERDDZ128mr, - VSCATTERDPSZ128mr)>; - -def SKXWriteResGroup133 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 20; - let ResourceCycles = [1,8,1,8,2]; -} -def: InstRW<[SKXWriteResGroup133], (instrs VPSCATTERDDZ256mr, - VSCATTERDPSZ256mr)>; - -def SKXWriteResGroup134 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort237,SKXPort0156]> { - let Latency = 8; - let NumMicroOps = 36; - let ResourceCycles = [1,16,1,16,2]; -} -def: InstRW<[SKXWriteResGroup134], (instrs VPSCATTERDDZmr)>; - -def SKXWriteResGroup135 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup135], (instregex "MMX_CVTPI2PSirm")>; - -def SKXWriteResGroup136 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup136], (instregex "VALIGNDZ128rm(b?)i", - "VALIGNQZ128rm(b?)i", - "VCMPPDZ128rm(b?)i", - "VCMPPSZ128rm(b?)i", - "VCMPSDZrm", - "VCMPSSZrm", - "VFPCLASSSSZrm(b?)", - "VPCMPBZ128rmi(b?)", - "VPCMPDZ128rmi(b?)", - "VPCMPEQ(B|D|Q|W)Z128rm(b?)", - "VPCMPGT(B|D|Q|W)Z128rm(b?)", - "(V?)PCMPGTQrm", - "VPCMPQZ128rmi(b?)", - "VPCMPU(B|D|Q|W)Z128rmi(b?)", - "VPCMPWZ128rmi(b?)", - "VPERMI2D128rm(b?)", - "VPERMI2PD128rm(b?)", - "VPERMI2PS128rm(b?)", - "VPERMI2Q128rm(b?)", - "VPERMT2D128rm(b?)", - "VPERMT2PD128rm(b?)", - "VPERMT2PS128rm(b?)", - "VPERMT2Q128rm(b?)", - "VPMAXSQZ128rm(b?)", - "VPMAXUQZ128rm(b?)", - "VPMINSQZ128rm(b?)", - "VPMINUQZ128rm(b?)", - "VPMOVSXBDZ128rm(b?)", - "VPMOVSXBQZ128rm(b?)", - "VPMOVSXBWYrm", - "VPMOVSXBWZ128rm(b?)", - "VPMOVSXDQYrm", - "VPMOVSXDQZ128rm(b?)", - "VPMOVSXWDYrm", - "VPMOVSXWDZ128rm(b?)", - "VPMOVSXWQZ128rm(b?)", - "VPMOVZXBDZ128rm(b?)", - "VPMOVZXBQZ128rm(b?)", - "VPMOVZXBWZ128rm(b?)", - "VPMOVZXDQZ128rm(b?)", - "VPMOVZXWDYrm", - "VPMOVZXWDZ128rm(b?)", - "VPMOVZXWQZ128rm(b?)", - "VPTESTMBZ128rm(b?)", - "VPTESTMDZ128rm(b?)", - "VPTESTMQZ128rm(b?)", - "VPTESTMWZ128rm(b?)", - "VPTESTNMBZ128rm(b?)", - "VPTESTNMDZ128rm(b?)", - "VPTESTNMQZ128rm(b?)", - "VPTESTNMWZ128rm(b?)")>; - -def SKXWriteResGroup137 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup137], (instregex "MMX_CVT(T?)PS2PIirm", - "(V?)CVTPS2PDrm")>; - -def SKXWriteResGroup142 : SchedWriteRes<[SKXPort1,SKXPort5,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup142], (instrs IMUL64m, MUL64m, MULX64rm)>; - -def SKXWriteResGroup143 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup143], (instregex "(V?)PHADDSWrm", - "(V?)PHSUBSWrm")>; - -def SKXWriteResGroup146 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 9; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup146], (instregex "LAR(16|32|64)rm", - "LSL(16|32|64)rm")>; - -def SKXWriteResGroup148 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup148], (instregex "(ADD|SUB|SUBR)_F(32|64)m", - "ILD_F(16|32|64)m", - "VALIGND(Z|Z256)rm(b?)i", - "VALIGNQ(Z|Z256)rm(b?)i", - "VCMPPD(Z|Z256)rm(b?)i", - "VCMPPS(Z|Z256)rm(b?)i", - "VPCMPB(Z|Z256)rmi(b?)", - "VPCMPD(Z|Z256)rmi(b?)", - "VPCMPEQB(Z|Z256)rm(b?)", - "VPCMPEQD(Z|Z256)rm(b?)", - "VPCMPEQQ(Z|Z256)rm(b?)", - "VPCMPEQW(Z|Z256)rm(b?)", - "VPCMPGTB(Z|Z256)rm(b?)", - "VPCMPGTD(Z|Z256)rm(b?)", - "VPCMPGTQYrm", - "VPCMPGTQ(Z|Z256)rm(b?)", - "VPCMPGTW(Z|Z256)rm(b?)", - "VPCMPQ(Z|Z256)rmi(b?)", - "VPCMPU(B|D|Q|W)Z256rmi(b?)", - "VPCMPU(B|D|Q|W)Zrmi(b?)", - "VPCMPW(Z|Z256)rmi(b?)", - "VPMAXSQ(Z|Z256)rm(b?)", - "VPMAXUQ(Z|Z256)rm(b?)", - "VPMINSQ(Z|Z256)rm(b?)", - "VPMINUQ(Z|Z256)rm(b?)", - "VPTESTM(B|D|Q|W)Z256rm(b?)", - "VPTESTM(B|D|Q|W)Zrm(b?)", - "VPTESTNM(B|D|Q|W)Z256rm(b?)", - "VPTESTNM(B|D|Q|W)Zrm(b?)")>; - -def SKXWriteResGroup149 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 10; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup149], (instregex "VCVTDQ2PDZ128rm(b?)", - "VCVTDQ2PSZ128rm(b?)", - "(V?)CVTDQ2PSrm", - "VCVTPD2QQZ128rm(b?)", - "VCVTPD2UQQZ128rm(b?)", - "VCVTPH2PSZ128rm(b?)", - "VCVTPS2DQZ128rm(b?)", - "(V?)CVTPS2DQrm", - "VCVTPS2PDZ128rm(b?)", - "VCVTPS2QQZ128rm(b?)", - "VCVTPS2UDQZ128rm(b?)", - "VCVTPS2UQQZ128rm(b?)", - "VCVTQQ2PDZ128rm(b?)", - "VCVTQQ2PSZ128rm(b?)", - "VCVTSS2SDZrm", - "(V?)CVTSS2SDrm", - "VCVTTPD2QQZ128rm(b?)", - "VCVTTPD2UQQZ128rm(b?)", - "VCVTTPS2DQZ128rm(b?)", - "(V?)CVTTPS2DQrm", - "VCVTTPS2QQZ128rm(b?)", - "VCVTTPS2UDQZ128rm(b?)", - "VCVTTPS2UQQZ128rm(b?)", - "VCVTUDQ2PDZ128rm(b?)", - "VCVTUDQ2PSZ128rm(b?)", - "VCVTUQQ2PDZ128rm(b?)", - "VCVTUQQ2PSZ128rm(b?)")>; - -def SKXWriteResGroup151 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup151], (instregex "VEXPANDPDZ128rm(b?)", - "VEXPANDPSZ128rm(b?)", - "VPEXPANDDZ128rm(b?)", - "VPEXPANDQZ128rm(b?)")>; - -def SKXWriteResGroup153 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 10; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup153], (instregex "(V?)CVTSD2SSrm")>; - -def SKXWriteResGroup154 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23]> { - let Latency = 10; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup154], (instregex "VPHADDSWYrm", - "VPHSUBSWYrm")>; - -def SKXWriteResGroup156 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort06,SKXPort0156]> { - let Latency = 9; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup156], (instrs IMUL32m, MUL32m, MULX32rm)>; - -def SKXWriteResGroup157 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 10; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,3]; -} -def: InstRW<[SKXWriteResGroup157], (instregex "XCHG(8|16|32|64)rm")>; - -def SKXWriteResGroup159 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 11; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup160 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup160], (instregex "MUL_F(32|64)m")>; - -def SKXWriteResGroup161 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup161], (instregex "VCVTDQ2PD(Z|Z256)rm(b?)", - "VCVTDQ2PSYrm", - "VCVTDQ2PS(Z|Z256)rm(b?)", - "VCVTPH2PS(Z|Z256)rm(b?)", - "VCVTPS2PDYrm", - "VCVTPS2PD(Z|Z256)rm(b?)", - "VCVTQQ2PD(Z|Z256)rm(b?)", - "VCVTQQ2PSZ256rm(b?)", - "VCVT(T?)PD2QQ(Z|Z256)rm(b?)", - "VCVT(T?)PD2UQQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2DQYrm", - "VCVT(T?)PS2DQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2QQZ256rm(b?)", - "VCVT(T?)PS2UDQ(Z|Z256)rm(b?)", - "VCVT(T?)PS2UQQZ256rm(b?)", - "VCVTUDQ2PD(Z|Z256)rm(b?)", - "VCVTUDQ2PS(Z|Z256)rm(b?)", - "VCVTUQQ2PD(Z|Z256)rm(b?)", - "VCVTUQQ2PSZ256rm(b?)")>; - -def SKXWriteResGroup162 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup162], (instregex "FICOM(P?)(16|32)m", - "VEXPANDPD(Z|Z256)rm(b?)", - "VEXPANDPS(Z|Z256)rm(b?)", - "VPEXPANDD(Z|Z256)rm(b?)", - "VPEXPANDQ(Z|Z256)rm(b?)")>; - -def SKXWriteResGroup163 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,2]; -} -def: InstRW<[SKXWriteResGroup163], (instregex "VCVTSD2SSZrm")>; - -def SKXWriteResGroup164 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup164], (instregex "(V?)CVTDQ2PDrm")>; - -def SKXWriteResGroup166 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup166], (instregex "CVTPD2PSrm", - "CVT(T?)PD2DQrm", - "MMX_CVT(T?)PD2PIirm")>; - -def SKXWriteResGroup167 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 11; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup167], (instregex "VPCONFLICTQZ128rm(b?)")>; - -def SKXWriteResGroup169 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 7; - let ResourceCycles = [2,3,2]; -} -def: InstRW<[SKXWriteResGroup169], (instregex "RCL(16|32|64)rCL", - "RCR(16|32|64)rCL")>; - -def SKXWriteResGroup170 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 9; - let ResourceCycles = [1,5,1,2]; -} -def: InstRW<[SKXWriteResGroup170], (instregex "RCL8rCL")>; - -def SKXWriteResGroup171 : SchedWriteRes<[SKXPort06,SKXPort0156]> { - let Latency = 11; - let NumMicroOps = 11; - let ResourceCycles = [2,9]; -} -def: InstRW<[SKXWriteResGroup171], (instrs LOOPE, LOOPNE)>; - -def SKXWriteResGroup174 : SchedWriteRes<[SKXPort01]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup174], (instregex "VPMULLQ(Z128|Z256)rr")>; - -def SKXWriteResGroup174z : SchedWriteRes<[SKXPort05]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [3]; -} -def: InstRW<[SKXWriteResGroup174z], (instregex "VPMULLQZrr")>; - -def SKXWriteResGroup175 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup175], (instregex "VPERMWZ128rm(b?)")>; - -def SKXWriteResGroup176 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup176], (instregex "VCVT(T?)SD2USIZrm(b?)", - "VCVT(T?)SS2USI64Zrm(b?)")>; - -def SKXWriteResGroup177 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup177], (instregex "VCVT(T?)PS2QQZrm(b?)", - "VCVT(T?)PS2UQQZrm(b?)")>; - -def SKXWriteResGroup179 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 12; - let NumMicroOps = 4; - let ResourceCycles = [1,1,1,1]; -} -def: InstRW<[SKXWriteResGroup179], (instregex "CVTTSS2SI64rm")>; - -def SKXWriteResGroup180 : SchedWriteRes<[SKXPort5,SKXPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [2,1]; -} -def: InstRW<[SKXWriteResGroup180], (instregex "(ADD|SUB|SUBR)_FI(16|32)m", - "VPERMWZ256rm(b?)", - "VPERMWZrm(b?)")>; - -def SKXWriteResGroup181 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 13; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup181], (instregex "VCVTDQ2PDYrm")>; - -def SKXWriteResGroup183 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 13; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup183], (instregex "VPERMI2W128rm(b?)", - "VPERMT2W128rm(b?)")>; - -def SKXWriteResGroup184 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,3]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup184_1 : SchedWriteRes<[SKXPort0,SKXFPDivider]> { - let Latency = 14; - let NumMicroOps = 1; - let ResourceCycles = [1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup187 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup187], (instregex "MUL_FI(16|32)m")>; - -def SKXWriteResGroup188 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 14; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup188], (instregex "VCVTPD2DQZrm(b?)", - "VCVTPD2PSZrm(b?)", - "VCVTPD2UDQZrm(b?)", - "VCVTQQ2PSZrm(b?)", - "VCVTTPD2DQZrm(b?)", - "VCVTTPD2UDQZrm(b?)", - "VCVTUQQ2PSZrm(b?)")>; - -def SKXWriteResGroup189 : SchedWriteRes<[SKXPort5,SKXPort23,SKXPort015]> { - let Latency = 14; - let NumMicroOps = 4; - let ResourceCycles = [2,1,1]; -} -def: InstRW<[SKXWriteResGroup189], (instregex "VPERMI2W256rm(b?)", - "VPERMI2Wrm(b?)", - "VPERMT2W256rm(b?)", - "VPERMT2Wrm(b?)")>; - -def SKXWriteResGroup190 : SchedWriteRes<[SKXPort1,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 14; - let NumMicroOps = 10; - let ResourceCycles = [2,4,1,3]; -} -def: InstRW<[SKXWriteResGroup190], (instregex "RCR8rCL")>; - -def SKXWriteResGroup191 : SchedWriteRes<[SKXPort0]> { - let Latency = 15; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup191], (instregex "DIVR_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup194 : SchedWriteRes<[SKXPort1,SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 15; - let NumMicroOps = 8; - let ResourceCycles = [1,2,2,1,2]; -} -def: InstRW<[SKXWriteResGroup194], (instregex "VPCONFLICTDZ128rm(b?)")>; - -def SKXWriteResGroup195 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 15; - let NumMicroOps = 10; - let ResourceCycles = [1,1,1,5,1,1]; -} -def: InstRW<[SKXWriteResGroup195], (instregex "RCL(8|16|32|64)mCL")>; - -def SKXWriteResGroup199 : SchedWriteRes<[SKXPort4,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 16; - let NumMicroOps = 14; - let ResourceCycles = [1,1,1,4,2,5]; -} -def: InstRW<[SKXWriteResGroup199], (instrs CMPXCHG8B)>; - -def SKXWriteResGroup200 : SchedWriteRes<[SKXPort0156]> { - let Latency = 16; - let NumMicroOps = 16; - let ResourceCycles = [16]; -} -def: InstRW<[SKXWriteResGroup200], (instrs VZEROALL)>; - -def SKXWriteResGroup201 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 17; - let NumMicroOps = 2; - let ResourceCycles = [1,1,5]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup202 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort05,SKXPort0156]> { - let Latency = 17; - let NumMicroOps = 15; - let ResourceCycles = [2,1,2,4,2,4]; -} -def: InstRW<[SKXWriteResGroup202], (instrs XCH_F)>; - -def SKXWriteResGroup205 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 18; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup205], (instregex "VPMULLQZ128rm(b?)")>; - -def SKXWriteResGroup207 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 18; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,5]; -} -def: InstRW<[SKXWriteResGroup207], (instrs CPUID, RDTSC)>; - -def SKXWriteResGroup208 : SchedWriteRes<[SKXPort1,SKXPort23,SKXPort237,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 18; - let NumMicroOps = 11; - let ResourceCycles = [2,1,1,4,1,2]; -} -def: InstRW<[SKXWriteResGroup208], (instregex "RCR(8|16|32|64)mCL")>; - -def SKXWriteResGroup209 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup211 : SchedWriteRes<[SKXPort23,SKXPort015]> { - let Latency = 19; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup211], (instregex "VPMULLQZ256rm(b?)", - "VPMULLQZrm(b?)")>; - -def SKXWriteResGroup214 : SchedWriteRes<[]> { - let Latency = 20; - let NumMicroOps = 0; -} -def: InstRW<[SKXWriteResGroup214], (instrs VGATHERDPSZ128rm, - VGATHERQPSZrm, - VPGATHERDDZ128rm)>; - -def SKXWriteResGroup215 : SchedWriteRes<[SKXPort0]> { - let Latency = 20; - let NumMicroOps = 1; - let ResourceCycles = [1]; -} -def: InstRW<[SKXWriteResGroup215], (instregex "DIV_(FPrST0|FST0r|FrST0)")>; - -def SKXWriteResGroup216 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 20; - let NumMicroOps = 2; - let ResourceCycles = [1,1,4]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup218 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup218], (instrs VGATHERQPSZ128rm, - VGATHERQPSZ256rm, - VPGATHERQDZ128rm, - VPGATHERQDZ256rm)>; - -def SKXWriteResGroup219 : SchedWriteRes<[SKXPort4,SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 8; - let ResourceCycles = [1,1,1,1,1,1,2]; -} -def: InstRW<[SKXWriteResGroup219], (instrs INSB, INSL, INSW)>; - -def SKXWriteResGroup220 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort0156]> { - let Latency = 20; - let NumMicroOps = 10; - let ResourceCycles = [1,2,7]; -} -def: InstRW<[SKXWriteResGroup220], (instrs MWAITrr)>; - -def SKXWriteResGroup222 : SchedWriteRes<[SKXPort0,SKXPort23,SKXFPDivider]> { - let Latency = 21; - let NumMicroOps = 2; - let ResourceCycles = [1,1,8]; -} -def : SchedAlias; // TODO - convert to ZnWriteResFpuPair - -def SKXWriteResGroup223 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup223], (instregex "DIV_F(32|64)m")>; - -def SKXWriteResGroup224 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224], (instrs VGATHERDPDZ128rm, - VGATHERQPDZ128rm, - VPGATHERDQZ128rm, - VPGATHERQQZ128rm)>; - -def SKXWriteResGroup224_2 : SchedWriteRes<[SKXPort0, SKXPort23, SKXPort5, SKXPort015]> { - let Latency = 22; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224_2], (instrs VGATHERDPSrm, - VGATHERDPDrm, - VGATHERQPDrm, - VGATHERQPSrm, - VPGATHERDDrm, - VPGATHERDQrm, - VPGATHERQDrm, - VPGATHERQQrm, - VPGATHERDDrm, - VPGATHERQDrm, - VPGATHERDQrm, - VPGATHERQQrm, - VGATHERDPSrm, - VGATHERQPSrm, - VGATHERDPDrm, - VGATHERQPDrm)>; - -def SKXWriteResGroup224_3 : SchedWriteRes<[SKXPort0, SKXPort23, SKXPort5, SKXPort015]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup224_3], (instrs VGATHERDPSYrm, - VGATHERQPDYrm, - VGATHERQPSYrm, - VPGATHERDDYrm, - VPGATHERDQYrm, - VPGATHERQDYrm, - VPGATHERQQYrm, - VPGATHERDDYrm, - VPGATHERQDYrm, - VPGATHERDQYrm, - VPGATHERQQYrm, - VGATHERDPSYrm, - VGATHERQPSYrm, - VGATHERDPDYrm)>; - -def SKXWriteResGroup225 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 22; - let NumMicroOps = 14; - let ResourceCycles = [5,5,4]; -} -def: InstRW<[SKXWriteResGroup225], (instregex "VPCONFLICTDZ128rr", - "VPCONFLICTQZ256rr")>; - -def SKXWriteResGroup228 : SchedWriteRes<[SKXPort0,SKXPort4,SKXPort5,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 23; - let NumMicroOps = 19; - let ResourceCycles = [2,1,4,1,1,4,6]; -} -def: InstRW<[SKXWriteResGroup228], (instrs CMPXCHG16B)>; - -def SKXWriteResGroup233 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 25; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup233], (instregex "DIV_FI(16|32)m")>; - -def SKXWriteResGroup234 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 25; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup234], (instrs VGATHERDPDZ256rm, - VGATHERQPDZ256rm, - VPGATHERDQZ256rm, - VPGATHERQDZrm, - VPGATHERQQZ256rm)>; - -def SKXWriteResGroup238 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 26; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup238], (instrs VGATHERDPDZrm, - VGATHERQPDZrm, - VPGATHERDQZrm, - VPGATHERQQZrm)>; - -def SKXWriteResGroup239 : SchedWriteRes<[SKXPort0,SKXPort23]> { - let Latency = 27; - let NumMicroOps = 2; - let ResourceCycles = [1,1]; -} -def: InstRW<[SKXWriteResGroup239], (instregex "DIVR_F(32|64)m")>; - -def SKXWriteResGroup240 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 27; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup240], (instrs VGATHERDPSZ256rm, - VPGATHERDDZ256rm)>; - -def SKXWriteResGroup241 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23,SKXPort0156]> { - let Latency = 28; - let NumMicroOps = 8; - let ResourceCycles = [2,4,1,1]; -} -def: InstRW<[SKXWriteResGroup241], (instregex "IDIV(8|16|32|64)m")>; - -def SKXWriteResGroup242 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 29; - let NumMicroOps = 15; - let ResourceCycles = [5,5,1,4]; -} -def: InstRW<[SKXWriteResGroup242], (instregex "VPCONFLICTQZ256rm(b?)")>; - -def SKXWriteResGroup243 : SchedWriteRes<[SKXPort0,SKXPort5,SKXPort23]> { - let Latency = 30; - let NumMicroOps = 3; - let ResourceCycles = [1,1,1]; -} -def: InstRW<[SKXWriteResGroup243], (instregex "DIVR_FI(16|32)m")>; - -def SKXWriteResGroup245 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort015,SKXPort0156]> { - let Latency = 30; - let NumMicroOps = 5; - let ResourceCycles = [1,2,1,1]; -} -def: InstRW<[SKXWriteResGroup245], (instrs VGATHERDPSZrm, - VPGATHERDDZrm)>; - -def SKXWriteResGroup247 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort23,SKXPort06,SKXPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,3,4,10]; -} -def: InstRW<[SKXWriteResGroup247], (instregex "IN(8|16|32)ri", - "IN(8|16|32)rr")>; - -def SKXWriteResGroup248 : SchedWriteRes<[SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 35; - let NumMicroOps = 23; - let ResourceCycles = [1,5,2,1,4,10]; -} -def: InstRW<[SKXWriteResGroup248], (instregex "OUT(8|16|32)ir", - "OUT(8|16|32)rr")>; - -def SKXWriteResGroup249 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 37; - let NumMicroOps = 21; - let ResourceCycles = [9,7,5]; -} -def: InstRW<[SKXWriteResGroup249], (instregex "VPCONFLICTDZ256rr", - "VPCONFLICTQZrr")>; - -def SKXWriteResGroup250 : SchedWriteRes<[SKXPort1,SKXPort6,SKXPort23,SKXPort0156]> { - let Latency = 37; - let NumMicroOps = 31; - let ResourceCycles = [1,8,1,21]; -} -def: InstRW<[SKXWriteResGroup250], (instregex "XRSTOR(64)?")>; - -def SKXWriteResGroup252 : SchedWriteRes<[SKXPort1,SKXPort4,SKXPort5,SKXPort6,SKXPort23,SKXPort237,SKXPort15,SKXPort0156]> { - let Latency = 40; - let NumMicroOps = 18; - let ResourceCycles = [1,1,2,3,1,1,1,8]; -} -def: InstRW<[SKXWriteResGroup252], (instrs VMCLEARm)>; - -def SKXWriteResGroup253 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 41; - let NumMicroOps = 39; - let ResourceCycles = [1,10,1,1,26]; -} -def: InstRW<[SKXWriteResGroup253], (instrs XSAVE64)>; - -def SKXWriteResGroup254 : SchedWriteRes<[SKXPort5,SKXPort0156]> { - let Latency = 42; - let NumMicroOps = 22; - let ResourceCycles = [2,20]; -} -def: InstRW<[SKXWriteResGroup254], (instrs RDTSCP)>; - -def SKXWriteResGroup255 : SchedWriteRes<[SKXPort4,SKXPort6,SKXPort23,SKXPort237,SKXPort0156]> { - let Latency = 42; - let NumMicroOps = 40; - let ResourceCycles = [1,11,1,1,26]; -} -def: InstRW<[SKXWriteResGroup255], (instrs XSAVE)>; -def: InstRW<[SKXWriteResGroup255], (instregex "XSAVEC", "XSAVES", "XSAVEOPT")>; - -def SKXWriteResGroup256 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 44; - let NumMicroOps = 22; - let ResourceCycles = [9,7,1,5]; -} -def: InstRW<[SKXWriteResGroup256], (instregex "VPCONFLICTDZ256rm(b?)", - "VPCONFLICTQZrm(b?)")>; - -def SKXWriteResGroup258 : SchedWriteRes<[SKXPort0,SKXPort23,SKXPort05,SKXPort06,SKXPort0156]> { - let Latency = 62; - let NumMicroOps = 64; - let ResourceCycles = [2,8,5,10,39]; -} -def: InstRW<[SKXWriteResGroup258], (instrs FLDENVm)>; - -def SKXWriteResGroup259 : SchedWriteRes<[SKXPort0,SKXPort6,SKXPort23,SKXPort05,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 63; - let NumMicroOps = 88; - let ResourceCycles = [4,4,31,1,2,1,45]; -} -def: InstRW<[SKXWriteResGroup259], (instrs FXRSTOR64)>; - -def SKXWriteResGroup260 : SchedWriteRes<[SKXPort0,SKXPort6,SKXPort23,SKXPort05,SKXPort06,SKXPort15,SKXPort0156]> { - let Latency = 63; - let NumMicroOps = 90; - let ResourceCycles = [4,2,33,1,2,1,47]; -} -def: InstRW<[SKXWriteResGroup260], (instrs FXRSTOR)>; - -def SKXWriteResGroup261 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort015]> { - let Latency = 67; - let NumMicroOps = 35; - let ResourceCycles = [17,11,7]; -} -def: InstRW<[SKXWriteResGroup261], (instregex "VPCONFLICTDZrr")>; - -def SKXWriteResGroup262 : SchedWriteRes<[SKXPort5,SKXPort01,SKXPort23,SKXPort015]> { - let Latency = 74; - let NumMicroOps = 36; - let ResourceCycles = [17,11,1,7]; -} -def: InstRW<[SKXWriteResGroup262], (instregex "VPCONFLICTDZrm(b?)")>; - -def SKXWriteResGroup263 : SchedWriteRes<[SKXPort5,SKXPort05,SKXPort0156]> { - let Latency = 75; - let NumMicroOps = 15; - let ResourceCycles = [6,3,6]; -} -def: InstRW<[SKXWriteResGroup263], (instrs FNINIT)>; - -def SKXWriteResGroup264 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort05,SKXPort0156]> { - let Latency = 76; - let NumMicroOps = 32; - let ResourceCycles = [7,2,8,3,1,11]; -} -def: InstRW<[SKXWriteResGroup264], (instregex "DIV(16|32|64)r")>; - -def SKXWriteResGroup265 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort5,SKXPort6,SKXPort06,SKXPort0156]> { - let Latency = 102; - let NumMicroOps = 66; - let ResourceCycles = [4,2,4,8,14,34]; -} -def: InstRW<[SKXWriteResGroup265], (instregex "IDIV(16|32|64)r")>; - -def SKXWriteResGroup266 : SchedWriteRes<[SKXPort0,SKXPort1,SKXPort4,SKXPort5,SKXPort6,SKXPort237,SKXPort06,SKXPort0156]> { - let Latency = 106; - let NumMicroOps = 100; - let ResourceCycles = [9,1,11,16,1,11,21,30]; -} -def: InstRW<[SKXWriteResGroup266], (instrs FSTENVm)>; - -def SKXWriteResGroup267 : SchedWriteRes<[SKXPort6,SKXPort0156]> { - let Latency = 140; - let NumMicroOps = 4; - let ResourceCycles = [1,3]; -} -def: InstRW<[SKXWriteResGroup267], (instrs PAUSE)>; - -def: InstRW<[WriteZero], (instrs CLC)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86Schedule.td b/suite/synctools/tablegen/X86/back/X86Schedule.td deleted file mode 100644 index 6215d58ae1..0000000000 --- a/suite/synctools/tablegen/X86/back/X86Schedule.td +++ /dev/null @@ -1,661 +0,0 @@ -//===-- X86Schedule.td - X86 Scheduling Definitions --------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// InstrSchedModel annotations for out-of-order CPUs. - -// Instructions with folded loads need to read the memory operand immediately, -// but other register operands don't have to be read until the load is ready. -// These operands are marked with ReadAfterLd. -def ReadAfterLd : SchedRead; - -// Instructions with both a load and a store folded are modeled as a folded -// load + WriteRMW. -def WriteRMW : SchedWrite; - -// Helper to set SchedWrite ExePorts/Latency/ResourceCycles/NumMicroOps. -multiclass X86WriteRes ExePorts, - int Lat, list Res, int UOps> { - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } -} - -// Most instructions can fold loads, so almost every SchedWrite comes in two -// variants: With and without a folded load. -// An X86FoldableSchedWrite holds a reference to the corresponding SchedWrite -// with a folded load. -class X86FoldableSchedWrite : SchedWrite { - // The SchedWrite to use when a load is folded into the instruction. - SchedWrite Folded; -} - -// Multiclass that produces a linked pair of SchedWrites. -multiclass X86SchedWritePair { - // Register-Memory operation. - def Ld : SchedWrite; - // Register-Register operation. - def NAME : X86FoldableSchedWrite { - let Folded = !cast(NAME#"Ld"); - } -} - -// Helpers to mark SchedWrites as unsupported. -multiclass X86WriteResUnsupported { - let Unsupported = 1 in { - def : WriteRes; - } -} -multiclass X86WriteResPairUnsupported { - let Unsupported = 1 in { - def : WriteRes; - def : WriteRes; - } -} - -// Multiclass that wraps X86FoldableSchedWrite for each vector width. -class X86SchedWriteWidths { - X86FoldableSchedWrite Scl = sScl; // Scalar float/double operations. - X86FoldableSchedWrite MMX = sScl; // MMX operations. - X86FoldableSchedWrite XMM = s128; // XMM operations. - X86FoldableSchedWrite YMM = s256; // YMM operations. - X86FoldableSchedWrite ZMM = s512; // ZMM operations. -} - -// Multiclass that wraps X86SchedWriteWidths for each fp vector type. -class X86SchedWriteSizes { - X86SchedWriteWidths PS = sPS; - X86SchedWriteWidths PD = sPD; -} - -// Multiclass that wraps move/load/store triple for a vector width. -class X86SchedWriteMoveLS { - SchedWrite RR = MoveRR; - SchedWrite RM = LoadRM; - SchedWrite MR = StoreMR; -} - -// Multiclass that wraps X86SchedWriteMoveLS for each vector width. -class X86SchedWriteMoveLSWidths { - X86SchedWriteMoveLS Scl = sScl; // Scalar float/double operations. - X86SchedWriteMoveLS MMX = sScl; // MMX operations. - X86SchedWriteMoveLS XMM = s128; // XMM operations. - X86SchedWriteMoveLS YMM = s256; // YMM operations. - X86SchedWriteMoveLS ZMM = s512; // ZMM operations. -} - -// Loads, stores, and moves, not folded with other operations. -def WriteLoad : SchedWrite; -def WriteStore : SchedWrite; -def WriteStoreNT : SchedWrite; -def WriteMove : SchedWrite; - -// Arithmetic. -defm WriteALU : X86SchedWritePair; // Simple integer ALU op. -defm WriteADC : X86SchedWritePair; // Integer ALU + flags op. -def WriteALURMW : WriteSequence<[WriteALULd, WriteStore]>; -def WriteADCRMW : WriteSequence<[WriteADCLd, WriteStore]>; -defm WriteIMul : X86SchedWritePair; // Integer multiplication. -defm WriteIMul64 : X86SchedWritePair; // Integer 64-bit multiplication. -def WriteIMulH : SchedWrite; // Integer multiplication, high part. -def WriteLEA : SchedWrite; // LEA instructions can't fold loads. - -def WriteBSWAP32 : SchedWrite; // Byte Order (Endianness) 32-bit Swap. -def WriteBSWAP64 : SchedWrite; // Byte Order (Endianness) 64-bit Swap. - -// Integer division. -defm WriteDiv8 : X86SchedWritePair; -defm WriteDiv16 : X86SchedWritePair; -defm WriteDiv32 : X86SchedWritePair; -defm WriteDiv64 : X86SchedWritePair; -defm WriteIDiv8 : X86SchedWritePair; -defm WriteIDiv16 : X86SchedWritePair; -defm WriteIDiv32 : X86SchedWritePair; -defm WriteIDiv64 : X86SchedWritePair; - -defm WriteBSF : X86SchedWritePair; // Bit scan forward. -defm WriteBSR : X86SchedWritePair; // Bit scan reverse. -defm WritePOPCNT : X86SchedWritePair; // Bit population count. -defm WriteLZCNT : X86SchedWritePair; // Leading zero count. -defm WriteTZCNT : X86SchedWritePair; // Trailing zero count. -defm WriteCMOV : X86SchedWritePair; // Conditional move. -defm WriteCMOV2 : X86SchedWritePair; // Conditional (CF + ZF flag) move. -def WriteFCMOV : SchedWrite; // X87 conditional move. -def WriteSETCC : SchedWrite; // Set register based on condition code. -def WriteSETCCStore : SchedWrite; -def WriteLAHFSAHF : SchedWrite; // Load/Store flags in AH. -def WriteBitTest : SchedWrite; // Bit Test - TODO add memory folding support - -// Integer shifts and rotates. -defm WriteShift : X86SchedWritePair; -// Double shift instructions. -def WriteSHDrri : SchedWrite; -def WriteSHDrrcl : SchedWrite; -def WriteSHDmri : SchedWrite; -def WriteSHDmrcl : SchedWrite; - -// BMI1 BEXTR, BMI2 BZHI -defm WriteBEXTR : X86SchedWritePair; -defm WriteBZHI : X86SchedWritePair; - -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -def WriteZero : SchedWrite; - -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -defm WriteJump : X86SchedWritePair; - -// Floating point. This covers both scalar and vector operations. -def WriteFLD0 : SchedWrite; -def WriteFLD1 : SchedWrite; -def WriteFLDC : SchedWrite; -def WriteFLoad : SchedWrite; -def WriteFLoadX : SchedWrite; -def WriteFLoadY : SchedWrite; -def WriteFMaskedLoad : SchedWrite; -def WriteFMaskedLoadY : SchedWrite; -def WriteFStore : SchedWrite; -def WriteFStoreX : SchedWrite; -def WriteFStoreY : SchedWrite; -def WriteFStoreNT : SchedWrite; -def WriteFStoreNTX : SchedWrite; -def WriteFStoreNTY : SchedWrite; -def WriteFMaskedStore : SchedWrite; -def WriteFMaskedStoreY : SchedWrite; -def WriteFMove : SchedWrite; -def WriteFMoveX : SchedWrite; -def WriteFMoveY : SchedWrite; - -defm WriteFAdd : X86SchedWritePair; // Floating point add/sub. -defm WriteFAddX : X86SchedWritePair; // Floating point add/sub (XMM). -defm WriteFAddY : X86SchedWritePair; // Floating point add/sub (YMM). -defm WriteFAddZ : X86SchedWritePair; // Floating point add/sub (ZMM). -defm WriteFAdd64 : X86SchedWritePair; // Floating point double add/sub. -defm WriteFAdd64X : X86SchedWritePair; // Floating point double add/sub (XMM). -defm WriteFAdd64Y : X86SchedWritePair; // Floating point double add/sub (YMM). -defm WriteFAdd64Z : X86SchedWritePair; // Floating point double add/sub (ZMM). -defm WriteFCmp : X86SchedWritePair; // Floating point compare. -defm WriteFCmpX : X86SchedWritePair; // Floating point compare (XMM). -defm WriteFCmpY : X86SchedWritePair; // Floating point compare (YMM). -defm WriteFCmpZ : X86SchedWritePair; // Floating point compare (ZMM). -defm WriteFCmp64 : X86SchedWritePair; // Floating point double compare. -defm WriteFCmp64X : X86SchedWritePair; // Floating point double compare (XMM). -defm WriteFCmp64Y : X86SchedWritePair; // Floating point double compare (YMM). -defm WriteFCmp64Z : X86SchedWritePair; // Floating point double compare (ZMM). -defm WriteFCom : X86SchedWritePair; // Floating point compare to flags. -defm WriteFMul : X86SchedWritePair; // Floating point multiplication. -defm WriteFMulX : X86SchedWritePair; // Floating point multiplication (XMM). -defm WriteFMulY : X86SchedWritePair; // Floating point multiplication (YMM). -defm WriteFMulZ : X86SchedWritePair; // Floating point multiplication (YMM). -defm WriteFMul64 : X86SchedWritePair; // Floating point double multiplication. -defm WriteFMul64X : X86SchedWritePair; // Floating point double multiplication (XMM). -defm WriteFMul64Y : X86SchedWritePair; // Floating point double multiplication (YMM). -defm WriteFMul64Z : X86SchedWritePair; // Floating point double multiplication (ZMM). -defm WriteFDiv : X86SchedWritePair; // Floating point division. -defm WriteFDivX : X86SchedWritePair; // Floating point division (XMM). -defm WriteFDivY : X86SchedWritePair; // Floating point division (YMM). -defm WriteFDivZ : X86SchedWritePair; // Floating point division (ZMM). -defm WriteFDiv64 : X86SchedWritePair; // Floating point double division. -defm WriteFDiv64X : X86SchedWritePair; // Floating point double division (XMM). -defm WriteFDiv64Y : X86SchedWritePair; // Floating point double division (YMM). -defm WriteFDiv64Z : X86SchedWritePair; // Floating point double division (ZMM). -defm WriteFSqrt : X86SchedWritePair; // Floating point square root. -defm WriteFSqrtX : X86SchedWritePair; // Floating point square root (XMM). -defm WriteFSqrtY : X86SchedWritePair; // Floating point square root (YMM). -defm WriteFSqrtZ : X86SchedWritePair; // Floating point square root (ZMM). -defm WriteFSqrt64 : X86SchedWritePair; // Floating point double square root. -defm WriteFSqrt64X : X86SchedWritePair; // Floating point double square root (XMM). -defm WriteFSqrt64Y : X86SchedWritePair; // Floating point double square root (YMM). -defm WriteFSqrt64Z : X86SchedWritePair; // Floating point double square root (ZMM). -defm WriteFSqrt80 : X86SchedWritePair; // Floating point long double square root. -defm WriteFRcp : X86SchedWritePair; // Floating point reciprocal estimate. -defm WriteFRcpX : X86SchedWritePair; // Floating point reciprocal estimate (XMM). -defm WriteFRcpY : X86SchedWritePair; // Floating point reciprocal estimate (YMM). -defm WriteFRcpZ : X86SchedWritePair; // Floating point reciprocal estimate (ZMM). -defm WriteFRsqrt : X86SchedWritePair; // Floating point reciprocal square root estimate. -defm WriteFRsqrtX: X86SchedWritePair; // Floating point reciprocal square root estimate (XMM). -defm WriteFRsqrtY: X86SchedWritePair; // Floating point reciprocal square root estimate (YMM). -defm WriteFRsqrtZ: X86SchedWritePair; // Floating point reciprocal square root estimate (ZMM). -defm WriteFMA : X86SchedWritePair; // Fused Multiply Add. -defm WriteFMAX : X86SchedWritePair; // Fused Multiply Add (XMM). -defm WriteFMAY : X86SchedWritePair; // Fused Multiply Add (YMM). -defm WriteFMAZ : X86SchedWritePair; // Fused Multiply Add (ZMM). -defm WriteDPPD : X86SchedWritePair; // Floating point double dot product. -defm WriteDPPS : X86SchedWritePair; // Floating point single dot product. -defm WriteDPPSY : X86SchedWritePair; // Floating point single dot product (YMM). -defm WriteDPPSZ : X86SchedWritePair; // Floating point single dot product (ZMM). -defm WriteFSign : X86SchedWritePair; // Floating point fabs/fchs. -defm WriteFRnd : X86SchedWritePair; // Floating point rounding. -defm WriteFRndY : X86SchedWritePair; // Floating point rounding (YMM). -defm WriteFRndZ : X86SchedWritePair; // Floating point rounding (ZMM). -defm WriteFLogic : X86SchedWritePair; // Floating point and/or/xor logicals. -defm WriteFLogicY : X86SchedWritePair; // Floating point and/or/xor logicals (YMM). -defm WriteFLogicZ : X86SchedWritePair; // Floating point and/or/xor logicals (ZMM). -defm WriteFTest : X86SchedWritePair; // Floating point TEST instructions. -defm WriteFTestY : X86SchedWritePair; // Floating point TEST instructions (YMM). -defm WriteFTestZ : X86SchedWritePair; // Floating point TEST instructions (ZMM). -defm WriteFShuffle : X86SchedWritePair; // Floating point vector shuffles. -defm WriteFShuffleY : X86SchedWritePair; // Floating point vector shuffles (YMM). -defm WriteFShuffleZ : X86SchedWritePair; // Floating point vector shuffles (ZMM). -defm WriteFVarShuffle : X86SchedWritePair; // Floating point vector variable shuffles. -defm WriteFVarShuffleY : X86SchedWritePair; // Floating point vector variable shuffles (YMM). -defm WriteFVarShuffleZ : X86SchedWritePair; // Floating point vector variable shuffles (ZMM). -defm WriteFBlend : X86SchedWritePair; // Floating point vector blends. -defm WriteFBlendY : X86SchedWritePair; // Floating point vector blends (YMM). -defm WriteFBlendZ : X86SchedWritePair; // Floating point vector blends (ZMM). -defm WriteFVarBlend : X86SchedWritePair; // Fp vector variable blends. -defm WriteFVarBlendY : X86SchedWritePair; // Fp vector variable blends (YMM). -defm WriteFVarBlendZ : X86SchedWritePair; // Fp vector variable blends (YMZMM). - -// FMA Scheduling helper class. -class FMASC { X86FoldableSchedWrite Sched = WriteFAdd; } - -// Horizontal Add/Sub (float and integer) -defm WriteFHAdd : X86SchedWritePair; -defm WriteFHAddY : X86SchedWritePair; -defm WriteFHAddZ : X86SchedWritePair; -defm WritePHAdd : X86SchedWritePair; -defm WritePHAddX : X86SchedWritePair; -defm WritePHAddY : X86SchedWritePair; -defm WritePHAddZ : X86SchedWritePair; - -// Vector integer operations. -def WriteVecLoad : SchedWrite; -def WriteVecLoadX : SchedWrite; -def WriteVecLoadY : SchedWrite; -def WriteVecLoadNT : SchedWrite; -def WriteVecLoadNTY : SchedWrite; -def WriteVecMaskedLoad : SchedWrite; -def WriteVecMaskedLoadY : SchedWrite; -def WriteVecStore : SchedWrite; -def WriteVecStoreX : SchedWrite; -def WriteVecStoreY : SchedWrite; -def WriteVecStoreNT : SchedWrite; -def WriteVecStoreNTY : SchedWrite; -def WriteVecMaskedStore : SchedWrite; -def WriteVecMaskedStoreY : SchedWrite; -def WriteVecMove : SchedWrite; -def WriteVecMoveX : SchedWrite; -def WriteVecMoveY : SchedWrite; -def WriteVecMoveToGpr : SchedWrite; -def WriteVecMoveFromGpr : SchedWrite; - -defm WriteVecALU : X86SchedWritePair; // Vector integer ALU op, no logicals. -defm WriteVecALUX : X86SchedWritePair; // Vector integer ALU op, no logicals (XMM). -defm WriteVecALUY : X86SchedWritePair; // Vector integer ALU op, no logicals (YMM). -defm WriteVecALUZ : X86SchedWritePair; // Vector integer ALU op, no logicals (ZMM). -defm WriteVecLogic : X86SchedWritePair; // Vector integer and/or/xor logicals. -defm WriteVecLogicX : X86SchedWritePair; // Vector integer and/or/xor logicals (XMM). -defm WriteVecLogicY : X86SchedWritePair; // Vector integer and/or/xor logicals (YMM). -defm WriteVecLogicZ : X86SchedWritePair; // Vector integer and/or/xor logicals (ZMM). -defm WriteVecTest : X86SchedWritePair; // Vector integer TEST instructions. -defm WriteVecTestY : X86SchedWritePair; // Vector integer TEST instructions (YMM). -defm WriteVecTestZ : X86SchedWritePair; // Vector integer TEST instructions (ZMM). -defm WriteVecShift : X86SchedWritePair; // Vector integer shifts (default). -defm WriteVecShiftX : X86SchedWritePair; // Vector integer shifts (XMM). -defm WriteVecShiftY : X86SchedWritePair; // Vector integer shifts (YMM). -defm WriteVecShiftZ : X86SchedWritePair; // Vector integer shifts (ZMM). -defm WriteVecShiftImm : X86SchedWritePair; // Vector integer immediate shifts (default). -defm WriteVecShiftImmX: X86SchedWritePair; // Vector integer immediate shifts (XMM). -defm WriteVecShiftImmY: X86SchedWritePair; // Vector integer immediate shifts (YMM). -defm WriteVecShiftImmZ: X86SchedWritePair; // Vector integer immediate shifts (ZMM). -defm WriteVecIMul : X86SchedWritePair; // Vector integer multiply (default). -defm WriteVecIMulX : X86SchedWritePair; // Vector integer multiply (XMM). -defm WriteVecIMulY : X86SchedWritePair; // Vector integer multiply (YMM). -defm WriteVecIMulZ : X86SchedWritePair; // Vector integer multiply (ZMM). -defm WritePMULLD : X86SchedWritePair; // Vector PMULLD. -defm WritePMULLDY : X86SchedWritePair; // Vector PMULLD (YMM). -defm WritePMULLDZ : X86SchedWritePair; // Vector PMULLD (ZMM). -defm WriteShuffle : X86SchedWritePair; // Vector shuffles. -defm WriteShuffleX : X86SchedWritePair; // Vector shuffles (XMM). -defm WriteShuffleY : X86SchedWritePair; // Vector shuffles (YMM). -defm WriteShuffleZ : X86SchedWritePair; // Vector shuffles (ZMM). -defm WriteVarShuffle : X86SchedWritePair; // Vector variable shuffles. -defm WriteVarShuffleX : X86SchedWritePair; // Vector variable shuffles (XMM). -defm WriteVarShuffleY : X86SchedWritePair; // Vector variable shuffles (YMM). -defm WriteVarShuffleZ : X86SchedWritePair; // Vector variable shuffles (ZMM). -defm WriteBlend : X86SchedWritePair; // Vector blends. -defm WriteBlendY : X86SchedWritePair; // Vector blends (YMM). -defm WriteBlendZ : X86SchedWritePair; // Vector blends (ZMM). -defm WriteVarBlend : X86SchedWritePair; // Vector variable blends. -defm WriteVarBlendY : X86SchedWritePair; // Vector variable blends (YMM). -defm WriteVarBlendZ : X86SchedWritePair; // Vector variable blends (ZMM). -defm WritePSADBW : X86SchedWritePair; // Vector PSADBW. -defm WritePSADBWX : X86SchedWritePair; // Vector PSADBW (XMM). -defm WritePSADBWY : X86SchedWritePair; // Vector PSADBW (YMM). -defm WritePSADBWZ : X86SchedWritePair; // Vector PSADBW (ZMM). -defm WriteMPSAD : X86SchedWritePair; // Vector MPSAD. -defm WriteMPSADY : X86SchedWritePair; // Vector MPSAD (YMM). -defm WriteMPSADZ : X86SchedWritePair; // Vector MPSAD (ZMM). -defm WritePHMINPOS : X86SchedWritePair; // Vector PHMINPOS. - -// Vector insert/extract operations. -defm WriteVecInsert : X86SchedWritePair; // Insert gpr to vector element. -def WriteVecExtract : SchedWrite; // Extract vector element to gpr. -def WriteVecExtractSt : SchedWrite; // Extract vector element and store. - -// MOVMSK operations. -def WriteFMOVMSK : SchedWrite; -def WriteVecMOVMSK : SchedWrite; -def WriteVecMOVMSKY : SchedWrite; -def WriteMMXMOVMSK : SchedWrite; - -// Conversion between integer and float. -defm WriteCvtSD2I : X86SchedWritePair; // Double -> Integer. -defm WriteCvtPD2I : X86SchedWritePair; // Double -> Integer (XMM). -defm WriteCvtPD2IY : X86SchedWritePair; // Double -> Integer (YMM). -defm WriteCvtPD2IZ : X86SchedWritePair; // Double -> Integer (ZMM). - -defm WriteCvtSS2I : X86SchedWritePair; // Float -> Integer. -defm WriteCvtPS2I : X86SchedWritePair; // Float -> Integer (XMM). -defm WriteCvtPS2IY : X86SchedWritePair; // Float -> Integer (YMM). -defm WriteCvtPS2IZ : X86SchedWritePair; // Float -> Integer (ZMM). - -defm WriteCvtI2SD : X86SchedWritePair; // Integer -> Double. -defm WriteCvtI2PD : X86SchedWritePair; // Integer -> Double (XMM). -defm WriteCvtI2PDY : X86SchedWritePair; // Integer -> Double (YMM). -defm WriteCvtI2PDZ : X86SchedWritePair; // Integer -> Double (ZMM). - -defm WriteCvtI2SS : X86SchedWritePair; // Integer -> Float. -defm WriteCvtI2PS : X86SchedWritePair; // Integer -> Float (XMM). -defm WriteCvtI2PSY : X86SchedWritePair; // Integer -> Float (YMM). -defm WriteCvtI2PSZ : X86SchedWritePair; // Integer -> Float (ZMM). - -defm WriteCvtSS2SD : X86SchedWritePair; // Float -> Double size conversion. -defm WriteCvtPS2PD : X86SchedWritePair; // Float -> Double size conversion (XMM). -defm WriteCvtPS2PDY : X86SchedWritePair; // Float -> Double size conversion (YMM). -defm WriteCvtPS2PDZ : X86SchedWritePair; // Float -> Double size conversion (ZMM). - -defm WriteCvtSD2SS : X86SchedWritePair; // Double -> Float size conversion. -defm WriteCvtPD2PS : X86SchedWritePair; // Double -> Float size conversion (XMM). -defm WriteCvtPD2PSY : X86SchedWritePair; // Double -> Float size conversion (YMM). -defm WriteCvtPD2PSZ : X86SchedWritePair; // Double -> Float size conversion (ZMM). - -defm WriteCvtPH2PS : X86SchedWritePair; // Half -> Float size conversion. -defm WriteCvtPH2PSY : X86SchedWritePair; // Half -> Float size conversion (YMM). -defm WriteCvtPH2PSZ : X86SchedWritePair; // Half -> Float size conversion (ZMM). - -def WriteCvtPS2PH : SchedWrite; // // Float -> Half size conversion. -def WriteCvtPS2PHY : SchedWrite; // // Float -> Half size conversion (YMM). -def WriteCvtPS2PHZ : SchedWrite; // // Float -> Half size conversion (ZMM). -def WriteCvtPS2PHSt : SchedWrite; // // Float -> Half + store size conversion. -def WriteCvtPS2PHYSt : SchedWrite; // // Float -> Half + store size conversion (YMM). -def WriteCvtPS2PHZSt : SchedWrite; // // Float -> Half + store size conversion (ZMM). - -// CRC32 instruction. -defm WriteCRC32 : X86SchedWritePair; - -// Strings instructions. -// Packed Compare Implicit Length Strings, Return Mask -defm WritePCmpIStrM : X86SchedWritePair; -// Packed Compare Explicit Length Strings, Return Mask -defm WritePCmpEStrM : X86SchedWritePair; -// Packed Compare Implicit Length Strings, Return Index -defm WritePCmpIStrI : X86SchedWritePair; -// Packed Compare Explicit Length Strings, Return Index -defm WritePCmpEStrI : X86SchedWritePair; - -// AES instructions. -defm WriteAESDecEnc : X86SchedWritePair; // Decryption, encryption. -defm WriteAESIMC : X86SchedWritePair; // InvMixColumn. -defm WriteAESKeyGen : X86SchedWritePair; // Key Generation. - -// Carry-less multiplication instructions. -defm WriteCLMul : X86SchedWritePair; - -// EMMS/FEMMS -def WriteEMMS : SchedWrite; - -// Load/store MXCSR -def WriteLDMXCSR : SchedWrite; -def WriteSTMXCSR : SchedWrite; - -// Catch-all for expensive system instructions. -def WriteSystem : SchedWrite; - -// AVX2. -defm WriteFShuffle256 : X86SchedWritePair; // Fp 256-bit width vector shuffles. -defm WriteFVarShuffle256 : X86SchedWritePair; // Fp 256-bit width variable shuffles. -defm WriteShuffle256 : X86SchedWritePair; // 256-bit width vector shuffles. -defm WriteVarShuffle256 : X86SchedWritePair; // 256-bit width vector variable shuffles. -defm WriteVarVecShift : X86SchedWritePair; // Variable vector shifts. -defm WriteVarVecShiftY : X86SchedWritePair; // Variable vector shifts (YMM). -defm WriteVarVecShiftZ : X86SchedWritePair; // Variable vector shifts (ZMM). - -// Old microcoded instructions that nobody use. -def WriteMicrocoded : SchedWrite; - -// Fence instructions. -def WriteFence : SchedWrite; - -// Nop, not very useful expect it provides a model for nops! -def WriteNop : SchedWrite; - -// Move/Load/Store wrappers. -def WriteFMoveLS - : X86SchedWriteMoveLS; -def WriteFMoveLSX - : X86SchedWriteMoveLS; -def WriteFMoveLSY - : X86SchedWriteMoveLS; -def SchedWriteFMoveLS - : X86SchedWriteMoveLSWidths; - -def WriteFMoveLSNT - : X86SchedWriteMoveLS; -def WriteFMoveLSNTX - : X86SchedWriteMoveLS; -def WriteFMoveLSNTY - : X86SchedWriteMoveLS; -def SchedWriteFMoveLSNT - : X86SchedWriteMoveLSWidths; - -def WriteVecMoveLS - : X86SchedWriteMoveLS; -def WriteVecMoveLSX - : X86SchedWriteMoveLS; -def WriteVecMoveLSY - : X86SchedWriteMoveLS; -def SchedWriteVecMoveLS - : X86SchedWriteMoveLSWidths; - -def WriteVecMoveLSNT - : X86SchedWriteMoveLS; -def WriteVecMoveLSNTX - : X86SchedWriteMoveLS; -def WriteVecMoveLSNTY - : X86SchedWriteMoveLS; -def SchedWriteVecMoveLSNT - : X86SchedWriteMoveLSWidths; - -// Vector width wrappers. -def SchedWriteFAdd - : X86SchedWriteWidths; -def SchedWriteFAdd64 - : X86SchedWriteWidths; -def SchedWriteFHAdd - : X86SchedWriteWidths; -def SchedWriteFCmp - : X86SchedWriteWidths; -def SchedWriteFCmp64 - : X86SchedWriteWidths; -def SchedWriteFMul - : X86SchedWriteWidths; -def SchedWriteFMul64 - : X86SchedWriteWidths; -def SchedWriteFMA - : X86SchedWriteWidths; -def SchedWriteDPPD - : X86SchedWriteWidths; -def SchedWriteDPPS - : X86SchedWriteWidths; -def SchedWriteFDiv - : X86SchedWriteWidths; -def SchedWriteFDiv64 - : X86SchedWriteWidths; -def SchedWriteFSqrt - : X86SchedWriteWidths; -def SchedWriteFSqrt64 - : X86SchedWriteWidths; -def SchedWriteFRcp - : X86SchedWriteWidths; -def SchedWriteFRsqrt - : X86SchedWriteWidths; -def SchedWriteFRnd - : X86SchedWriteWidths; -def SchedWriteFLogic - : X86SchedWriteWidths; -def SchedWriteFTest - : X86SchedWriteWidths; - -def SchedWriteFShuffle - : X86SchedWriteWidths; -def SchedWriteFVarShuffle - : X86SchedWriteWidths; -def SchedWriteFBlend - : X86SchedWriteWidths; -def SchedWriteFVarBlend - : X86SchedWriteWidths; - -def SchedWriteCvtDQ2PD - : X86SchedWriteWidths; -def SchedWriteCvtDQ2PS - : X86SchedWriteWidths; -def SchedWriteCvtPD2DQ - : X86SchedWriteWidths; -def SchedWriteCvtPS2DQ - : X86SchedWriteWidths; -def SchedWriteCvtPS2PD - : X86SchedWriteWidths; -def SchedWriteCvtPD2PS - : X86SchedWriteWidths; - -def SchedWriteVecALU - : X86SchedWriteWidths; -def SchedWritePHAdd - : X86SchedWriteWidths; -def SchedWriteVecLogic - : X86SchedWriteWidths; -def SchedWriteVecTest - : X86SchedWriteWidths; -def SchedWriteVecShift - : X86SchedWriteWidths; -def SchedWriteVecShiftImm - : X86SchedWriteWidths; -def SchedWriteVarVecShift - : X86SchedWriteWidths; -def SchedWriteVecIMul - : X86SchedWriteWidths; -def SchedWritePMULLD - : X86SchedWriteWidths; -def SchedWriteMPSAD - : X86SchedWriteWidths; -def SchedWritePSADBW - : X86SchedWriteWidths; - -def SchedWriteShuffle - : X86SchedWriteWidths; -def SchedWriteVarShuffle - : X86SchedWriteWidths; -def SchedWriteBlend - : X86SchedWriteWidths; -def SchedWriteVarBlend - : X86SchedWriteWidths; - -// Vector size wrappers. -def SchedWriteFAddSizes - : X86SchedWriteSizes; -def SchedWriteFCmpSizes - : X86SchedWriteSizes; -def SchedWriteFMulSizes - : X86SchedWriteSizes; -def SchedWriteFDivSizes - : X86SchedWriteSizes; -def SchedWriteFSqrtSizes - : X86SchedWriteSizes; -def SchedWriteFLogicSizes - : X86SchedWriteSizes; -def SchedWriteFShuffleSizes - : X86SchedWriteSizes; - -//===----------------------------------------------------------------------===// -// Generic Processor Scheduler Models. - -// IssueWidth is analogous to the number of decode units. Core and its -// descendants, including Nehalem and SandyBridge have 4 decoders. -// Resources beyond the decoder operate on micro-ops and are buffered -// so adjacent micro-ops don't directly compete. -// -// MicroOpBufferSize > 1 indicates that RAW dependencies can be -// decoded in the same cycle. The value 32 is a reasonably arbitrary -// number of in-flight instructions. -// -// HighLatency=10 is optimistic. X86InstrInfo::isHighLatencyDef -// indicates high latency opcodes. Alternatively, InstrItinData -// entries may be included here to define specific operand -// latencies. Since these latencies are not used for pipeline hazards, -// they do not need to be exact. -// -// The GenericX86Model contains no instruction schedules -// and disables PostRAScheduler. -class GenericX86Model : SchedMachineModel { - let IssueWidth = 4; - let MicroOpBufferSize = 32; - let LoadLatency = 4; - let HighLatency = 10; - let PostRAScheduler = 0; - let CompleteModel = 0; -} - -def GenericModel : GenericX86Model; - -// Define a model with the PostRAScheduler enabled. -def GenericPostRAModel : GenericX86Model { - let PostRAScheduler = 1; -} diff --git a/suite/synctools/tablegen/X86/back/X86ScheduleAtom.td b/suite/synctools/tablegen/X86/back/X86ScheduleAtom.td deleted file mode 100644 index daa6fc73cc..0000000000 --- a/suite/synctools/tablegen/X86/back/X86ScheduleAtom.td +++ /dev/null @@ -1,917 +0,0 @@ -//===- X86ScheduleAtom.td - X86 Atom Scheduling Definitions -*- tablegen -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the schedule class data for the Intel Atom -// in order (Saltwell-32nm/Bonnell-45nm) processors. -// -//===----------------------------------------------------------------------===// - -// -// Scheduling information derived from the "Intel 64 and IA32 Architectures -// Optimization Reference Manual", Chapter 13, Section 4. - -// Atom machine model. -def AtomModel : SchedMachineModel { - let IssueWidth = 2; // Allows 2 instructions per scheduling group. - let MicroOpBufferSize = 0; // In-order execution, always hide latency. - let LoadLatency = 3; // Expected cycles, may be overridden. - let HighLatency = 30;// Expected, may be overridden. - - // On the Atom, the throughput for taken branches is 2 cycles. For small - // simple loops, expand by a small factor to hide the backedge cost. - let LoopMicroOpBufferSize = 10; - let PostRAScheduler = 1; - let CompleteModel = 0; -} - -let SchedModel = AtomModel in { - -// Functional Units -def AtomPort0 : ProcResource<1>; // ALU: ALU0, shift/rotate, load/store - // SIMD/FP: SIMD ALU, Shuffle,SIMD/FP multiply, divide -def AtomPort1 : ProcResource<1>; // ALU: ALU1, bit processing, jump, and LEA - // SIMD/FP: SIMD ALU, FP Adder - -def AtomPort01 : ProcResGroup<[AtomPort0, AtomPort1]>; - -// Loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when dispatched by the schedulers. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass AtomWriteResPair RRPorts, - list RMPorts, - int RRLat = 1, int RMLat = 1, - list RRRes = [1], - list RMRes = [1]> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = RRLat; - let ResourceCycles = RRRes; - } - - // Memory variant also uses a cycle on JLAGU and adds 3 cycles to the - // latency. - def : WriteRes { - let Latency = RMLat; - let ResourceCycles = RMRes; - } -} - -// A folded store needs a cycle on Port0 for the store data. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Arithmetic. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteRes; // x87 conditional move. - -def : WriteRes; -def : WriteRes { - let Latency = 2; - let ResourceCycles = [2]; -} -def : WriteRes { - let Latency = 2; - let ResourceCycles = [2]; -} -def : WriteRes; - -defm : X86WriteResUnsupported; - -// This is for simple LEAs with one or two input operands. -def : WriteRes; - -def AtomWriteIMul16Ld : SchedWriteRes<[AtomPort01]> { - let Latency = 8; - let ResourceCycles = [8]; -} -def : InstRW<[AtomWriteIMul16Ld], (instrs MUL16m, IMUL16m)>; - -def AtomWriteIMul32 : SchedWriteRes<[AtomPort01]> { - let Latency = 6; - let ResourceCycles = [6]; -} -def : InstRW<[AtomWriteIMul32], (instrs MUL32r, IMUL32r)>; - -def AtomWriteIMul64I : SchedWriteRes<[AtomPort01]> { - let Latency = 14; - let ResourceCycles = [14]; -} -def : InstRW<[AtomWriteIMul64I], (instrs IMUL64rri8, IMUL64rri32, - IMUL64rmi8, IMUL64rmi32)>; - -// Bit counts. -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -// BMI1 BEXTR, BMI2 BZHI -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Integer shifts and rotates. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Loads, stores, and moves, not folded with other operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -//////////////////////////////////////////////////////////////////////////////// -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; - -//////////////////////////////////////////////////////////////////////////////// -// Special case scheduling classes. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; - -// Nops don't have dependencies, so there's no actual latency, but we set this -// to '1' to tell the scheduler that the nop uses an ALU slot for a cycle. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Floating point. This covers both scalar and vector operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; - -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Conversions. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector integer operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; -def : WriteRes; -defm : X86WriteResUnsupported; - -def : WriteRes; -def : WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector insert/extract operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -def : WriteRes; -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// SSE42 String instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// MOVMSK Instructions. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } -defm : X86WriteResUnsupported; -def : WriteRes { let Latency = 3; let ResourceCycles = [3]; } - -//////////////////////////////////////////////////////////////////////////////// -// AES instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; -defm : AtomWriteResPair; - -//////////////////////////////////////////////////////////////////////////////// -// Carry-less multiplication instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Load/store MXCSR. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 5; let ResourceCycles = [5]; } -def : WriteRes { let Latency = 15; let ResourceCycles = [15]; } - -//////////////////////////////////////////////////////////////////////////////// -// Special Cases. -//////////////////////////////////////////////////////////////////////////////// - -// Port0 -def AtomWrite0_1 : SchedWriteRes<[AtomPort0]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite0_1], (instrs FXAM, LD_Frr, - MOVSX64rr32)>; -def : SchedAlias; -def : SchedAlias; -def : InstRW<[AtomWrite0_1], (instregex "(RCL|RCR|ROL|ROR|SAR|SHL|SHR)(8|16|32|64)m", - "MOV(S|Z)X(32|64)rr(8|8_NOREX|16)")>; - -def AtomWrite0_5 : SchedWriteRes<[AtomPort0]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite0_5], (instregex "IMUL32(rm|rr)")>; - -// Port1 -def AtomWrite1_1 : SchedWriteRes<[AtomPort1]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite1_1], (instrs FCOMPP)>; -def : InstRW<[AtomWrite1_1], (instregex "UCOM_F(P|PP)?r", - "BT(C|R|S)?(16|32|64)(rr|ri8)")>; - -def AtomWrite1_5 : SchedWriteRes<[AtomPort1]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite1_5], (instrs MMX_CVTPI2PSirr, MMX_CVTPI2PSirm, - MMX_CVTPS2PIirr, MMX_CVTTPS2PIirr)>; - -// Port0 and Port1 -def AtomWrite0_1_1 : SchedWriteRes<[AtomPort0, AtomPort1]> { - let Latency = 1; - let ResourceCycles = [1, 1]; -} -def : InstRW<[AtomWrite0_1_1], (instrs POP32r, POP64r, - POP16rmr, POP32rmr, POP64rmr, - PUSH16r, PUSH32r, PUSH64r, - PUSHi16, PUSHi32, - PUSH16rmr, PUSH32rmr, PUSH64rmr, - PUSH16i8, PUSH32i8, PUSH64i8, PUSH64i32, - XCH_F)>; -def : InstRW<[AtomWrite0_1_1], (instregex "RETI(L|Q|W)$", - "IRET(16|32|64)?")>; - -def AtomWrite0_1_5 : SchedWriteRes<[AtomPort0, AtomPort1]> { - let Latency = 5; - let ResourceCycles = [5, 5]; -} -def : InstRW<[AtomWrite0_1_5], (instrs MMX_CVTPS2PIirm, MMX_CVTTPS2PIirm)>; -def : InstRW<[AtomWrite0_1_5], (instregex "ILD_F(16|32|64)")>; - -// Port0 or Port1 -def AtomWrite01_1 : SchedWriteRes<[AtomPort01]> { - let Latency = 1; - let ResourceCycles = [1]; -} -def : InstRW<[AtomWrite01_1], (instrs FDECSTP, FFREE, FFREEP, FINCSTP, WAIT, - LFENCE, - STOSB, STOSL, STOSQ, STOSW, - MOVSSrr, MOVSSrr_REV, - PSLLDQri, PSRLDQri)>; -def : InstRW<[AtomWrite01_1], (instregex "MMX_PACK(SSDW|SSWB|USWB)irr", - "MMX_PUNPCKH(BW|DQ|WD)irr")>; - -def AtomWrite01_2 : SchedWriteRes<[AtomPort01]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def : InstRW<[AtomWrite01_2], (instrs LEAVE, LEAVE64, POP16r, - PUSH16rmm, PUSH32rmm, PUSH64rmm, - LODSB, LODSL, LODSQ, LODSW, - SCASB, SCASL, SCASQ, SCASW)>; -def : InstRW<[AtomWrite01_2], (instregex "BT(C|R|S)(16|32|64)mi8", - "PUSH(CS|DS|ES|FS|GS|SS)(16|32|64)", - "XADD(8|16|32|64)rr", - "XCHG(8|16|32|64)(ar|rr)", - "(ST|ISTT)_F(P)?(16|32|64)?(m|rr)", - "MMX_P(ADD|SUB)Qirr", - "MOV(S|Z)X16rr8", - "MOV(UPS|UPD|DQU)mr", - "MASKMOVDQU(64)?", - "P(ADD|SUB)Qrr")>; - -def AtomWrite01_3 : SchedWriteRes<[AtomPort01]> { - let Latency = 3; - let ResourceCycles = [3]; -} -def : InstRW<[AtomWrite01_3], (instrs CLD, LDDQUrm, - CMPSB, CMPSL, CMPSQ, CMPSW, - MOVSB, MOVSL, MOVSQ, MOVSW, - POP16rmm, POP32rmm, POP64rmm)>; -def : InstRW<[AtomWrite01_3], (instregex "XADD(8|16|32|64)rm", - "XCHG(8|16|32|64)rm", - "PH(ADD|SUB)Drr", - "MOV(S|Z)X16rm8", - "MMX_P(ADD|SUB)Qirm", - "MOV(UPS|UPD|DQU)rm", - "P(ADD|SUB)Qrm")>; - -def AtomWrite01_4 : SchedWriteRes<[AtomPort01]> { - let Latency = 4; - let ResourceCycles = [4]; -} -def : InstRW<[AtomWrite01_4], (instrs CBW, CWD, CWDE, CDQ, CDQE, CQO, - JCXZ, JECXZ, JRCXZ, - LD_F80m)>; -def : InstRW<[AtomWrite01_4], (instregex "PH(ADD|SUB)Drm", - "(MMX_)?PEXTRWrr(_REV)?")>; - -def AtomWrite01_5 : SchedWriteRes<[AtomPort01]> { - let Latency = 5; - let ResourceCycles = [5]; -} -def : InstRW<[AtomWrite01_5], (instrs FLDCW16m, ST_FP80m)>; -def : InstRW<[AtomWrite01_5], (instregex "MMX_PH(ADD|SUB)S?Wrr")>; - -def AtomWrite01_6 : SchedWriteRes<[AtomPort01]> { - let Latency = 6; - let ResourceCycles = [6]; -} -def : InstRW<[AtomWrite01_6], (instrs CMPXCHG8rm, INTO, XLAT, - SHLD16rrCL, SHRD16rrCL, - SHLD16rri8, SHRD16rri8, - SHLD16mrCL, SHRD16mrCL, - SHLD16mri8, SHRD16mri8)>; -def : InstRW<[AtomWrite01_6], (instregex "IMUL16rr", - "IST_F(P)?(16|32|64)?m", - "MMX_PH(ADD|SUB)S?Wrm")>; - -def AtomWrite01_7 : SchedWriteRes<[AtomPort01]> { - let Latency = 7; - let ResourceCycles = [7]; -} -def : InstRW<[AtomWrite01_7], (instrs AAD8i8)>; - -def AtomWrite01_8 : SchedWriteRes<[AtomPort01]> { - let Latency = 8; - let ResourceCycles = [8]; -} -def : InstRW<[AtomWrite01_8], (instrs LOOPE, - PUSHA16, PUSHA32, - SHLD64rrCL, SHRD64rrCL, - FNSTCW16m)>; - -def AtomWrite01_9 : SchedWriteRes<[AtomPort01]> { - let Latency = 9; - let ResourceCycles = [9]; -} -def : InstRW<[AtomWrite01_9], (instrs BT16mr, BT32mr, BT64mr, - POPA16, POPA32, - PUSHF16, PUSHF32, PUSHF64, - SHLD64mrCL, SHRD64mrCL, - SHLD64mri8, SHRD64mri8, - SHLD64rri8, SHRD64rri8, - CMPXCHG8rr)>; -def : InstRW<[AtomWrite01_9], (instregex "(U)?COM_FI", "TST_F", - "(U)?COMIS(D|S)rr", - "CVT(T)?SS2SI64rr(_Int)?")>; - -def AtomWrite01_10 : SchedWriteRes<[AtomPort01]> { - let Latency = 10; - let ResourceCycles = [10]; -} -def : SchedAlias; -def : InstRW<[AtomWrite01_10], (instregex "(U)?COMIS(D|S)rm", - "CVT(T)?SS2SI64rm(_Int)?")>; - -def AtomWrite01_11 : SchedWriteRes<[AtomPort01]> { - let Latency = 11; - let ResourceCycles = [11]; -} -def : InstRW<[AtomWrite01_11], (instrs BOUNDS16rm, BOUNDS32rm)>; -def : InstRW<[AtomWrite01_11], (instregex "BT(C|R|S)(16|32|64)mr")>; - -def AtomWrite01_13 : SchedWriteRes<[AtomPort01]> { - let Latency = 13; - let ResourceCycles = [13]; -} -def : InstRW<[AtomWrite01_13], (instrs AAA, AAS)>; - -def AtomWrite01_14 : SchedWriteRes<[AtomPort01]> { - let Latency = 14; - let ResourceCycles = [14]; -} -def : InstRW<[AtomWrite01_14], (instrs CMPXCHG16rm, CMPXCHG32rm, CMPXCHG64rm)>; - -def AtomWrite01_15 : SchedWriteRes<[AtomPort01]> { - let Latency = 15; - let ResourceCycles = [15]; -} -def : InstRW<[AtomWrite01_15], (instrs CMPXCHG16rr, CMPXCHG32rr, CMPXCHG64rr)>; - -def AtomWrite01_17 : SchedWriteRes<[AtomPort01]> { - let Latency = 17; - let ResourceCycles = [17]; -} -def : InstRW<[AtomWrite01_17], (instrs LOOPNE, PAUSE)>; - -def AtomWrite01_18 : SchedWriteRes<[AtomPort01]> { - let Latency = 18; - let ResourceCycles = [18]; -} -def : InstRW<[AtomWrite01_18], (instrs CMPXCHG8B, DAA, LOOP)>; - -def AtomWrite01_20 : SchedWriteRes<[AtomPort01]> { - let Latency = 20; - let ResourceCycles = [20]; -} -def : InstRW<[AtomWrite01_20], (instrs DAS)>; - -def AtomWrite01_21 : SchedWriteRes<[AtomPort01]> { - let Latency = 21; - let ResourceCycles = [21]; -} -def : InstRW<[AtomWrite01_21], (instrs AAM8i8, STD)>; - -def AtomWrite01_22 : SchedWriteRes<[AtomPort01]> { - let Latency = 22; - let ResourceCycles = [22]; -} -def : InstRW<[AtomWrite01_22], (instrs CMPXCHG16B)>; - -def AtomWrite01_23 : SchedWriteRes<[AtomPort01]> { - let Latency = 23; - let ResourceCycles = [23]; -} -def : InstRW<[AtomWrite01_23], (instrs ARPL16mr, ARPL16rr)>; - -def AtomWrite01_25 : SchedWriteRes<[AtomPort01]> { - let Latency = 25; - let ResourceCycles = [25]; -} -def : InstRW<[AtomWrite01_25], (instrs FNCLEX, FXTRACT)>; - -def AtomWrite01_26 : SchedWriteRes<[AtomPort01]> { - let Latency = 26; - let ResourceCycles = [26]; -} -def : InstRW<[AtomWrite01_26], (instrs POPF32, POPF64)>; - -def AtomWrite01_29 : SchedWriteRes<[AtomPort01]> { - let Latency = 29; - let ResourceCycles = [29]; -} -def : InstRW<[AtomWrite01_29], (instregex "POP(DS|ES|FS|GS)(16|32|64)")>; - -def AtomWrite01_30 : SchedWriteRes<[AtomPort01]> { - let Latency = 30; - let ResourceCycles = [30]; -} -def : InstRW<[AtomWrite01_30], (instrs RDTSC, RDTSCP)>; - -def AtomWrite01_32 : SchedWriteRes<[AtomPort01]> { - let Latency = 32; - let ResourceCycles = [32]; -} -def : InstRW<[AtomWrite01_32], (instrs ENTER, POPF16)>; - -def AtomWrite01_45 : SchedWriteRes<[AtomPort01]> { - let Latency = 45; - let ResourceCycles = [45]; -} -def : InstRW<[AtomWrite01_45], (instrs MONITORrrr)>; - -def AtomWrite01_46 : SchedWriteRes<[AtomPort01]> { - let Latency = 46; - let ResourceCycles = [46]; -} -def : InstRW<[AtomWrite01_46], (instrs FRNDINT, MWAITrr, RDPMC)>; - -def AtomWrite01_48 : SchedWriteRes<[AtomPort01]> { - let Latency = 48; - let ResourceCycles = [48]; -} -def : InstRW<[AtomWrite01_48], (instrs POPSS16, POPSS32)>; - -def AtomWrite01_55 : SchedWriteRes<[AtomPort01]> { - let Latency = 55; - let ResourceCycles = [55]; -} -def : InstRW<[AtomWrite01_55], (instrs FPREM)>; - -def AtomWrite01_59 : SchedWriteRes<[AtomPort01]> { - let Latency = 59; - let ResourceCycles = [59]; -} -def : InstRW<[AtomWrite01_59], (instrs INSB, INSL, INSW)>; - -def AtomWrite01_63 : SchedWriteRes<[AtomPort01]> { - let Latency = 63; - let ResourceCycles = [63]; -} -def : InstRW<[AtomWrite01_63], (instrs FNINIT)>; - -def AtomWrite01_68 : SchedWriteRes<[AtomPort01]> { - let Latency = 68; - let ResourceCycles = [68]; -} -def : InstRW<[AtomWrite01_68], (instrs OUT8rr, OUT16rr, OUT32rr)>; - -def AtomWrite01_71 : SchedWriteRes<[AtomPort01]> { - let Latency = 71; - let ResourceCycles = [71]; -} -def : InstRW<[AtomWrite01_71], (instrs FPREM1, - INVLPG, INVLPGA32, INVLPGA64)>; - -def AtomWrite01_72 : SchedWriteRes<[AtomPort01]> { - let Latency = 72; - let ResourceCycles = [72]; -} -def : InstRW<[AtomWrite01_72], (instrs OUT8ir, OUT16ir, OUT32ir)>; - -def AtomWrite01_74 : SchedWriteRes<[AtomPort01]> { - let Latency = 74; - let ResourceCycles = [74]; -} -def : InstRW<[AtomWrite01_74], (instrs OUTSB, OUTSL, OUTSW)>; - -def AtomWrite01_77 : SchedWriteRes<[AtomPort01]> { - let Latency = 77; - let ResourceCycles = [77]; -} -def : InstRW<[AtomWrite01_77], (instrs FSCALE)>; - -def AtomWrite01_78 : SchedWriteRes<[AtomPort01]> { - let Latency = 78; - let ResourceCycles = [78]; -} -def : InstRW<[AtomWrite01_78], (instrs RDMSR)>; - -def AtomWrite01_79 : SchedWriteRes<[AtomPort01]> { - let Latency = 79; - let ResourceCycles = [79]; -} -def : InstRW<[AtomWrite01_79], (instregex "RET(L|Q|W)?$", - "LRETI?(L|Q|W)")>; - -def AtomWrite01_92 : SchedWriteRes<[AtomPort01]> { - let Latency = 92; - let ResourceCycles = [92]; -} -def : InstRW<[AtomWrite01_92], (instrs IN8ri, IN16ri, IN32ri)>; - -def AtomWrite01_94 : SchedWriteRes<[AtomPort01]> { - let Latency = 94; - let ResourceCycles = [94]; -} -def : InstRW<[AtomWrite01_94], (instrs IN8rr, IN16rr, IN32rr)>; - -def AtomWrite01_99 : SchedWriteRes<[AtomPort01]> { - let Latency = 99; - let ResourceCycles = [99]; -} -def : InstRW<[AtomWrite01_99], (instrs F2XM1)>; - -def AtomWrite01_121 : SchedWriteRes<[AtomPort01]> { - let Latency = 121; - let ResourceCycles = [121]; -} -def : InstRW<[AtomWrite01_121], (instrs CPUID)>; - -def AtomWrite01_127 : SchedWriteRes<[AtomPort01]> { - let Latency = 127; - let ResourceCycles = [127]; -} -def : InstRW<[AtomWrite01_127], (instrs INT)>; - -def AtomWrite01_130 : SchedWriteRes<[AtomPort01]> { - let Latency = 130; - let ResourceCycles = [130]; -} -def : InstRW<[AtomWrite01_130], (instrs INT3)>; - -def AtomWrite01_140 : SchedWriteRes<[AtomPort01]> { - let Latency = 140; - let ResourceCycles = [140]; -} -def : InstRW<[AtomWrite01_140], (instrs FXSAVE, FXSAVE64)>; - -def AtomWrite01_141 : SchedWriteRes<[AtomPort01]> { - let Latency = 141; - let ResourceCycles = [141]; -} -def : InstRW<[AtomWrite01_141], (instrs FXRSTOR, FXRSTOR64)>; - -def AtomWrite01_146 : SchedWriteRes<[AtomPort01]> { - let Latency = 146; - let ResourceCycles = [146]; -} -def : InstRW<[AtomWrite01_146], (instrs FYL2X)>; - -def AtomWrite01_147 : SchedWriteRes<[AtomPort01]> { - let Latency = 147; - let ResourceCycles = [147]; -} -def : InstRW<[AtomWrite01_147], (instrs FYL2XP1)>; - -def AtomWrite01_168 : SchedWriteRes<[AtomPort01]> { - let Latency = 168; - let ResourceCycles = [168]; -} -def : InstRW<[AtomWrite01_168], (instrs FPTAN)>; - -def AtomWrite01_174 : SchedWriteRes<[AtomPort01]> { - let Latency = 174; - let ResourceCycles = [174]; -} -def : InstRW<[AtomWrite01_174], (instrs FSINCOS)>; -def : InstRW<[AtomWrite01_174], (instregex "(COS|SIN)_F")>; - -def AtomWrite01_183 : SchedWriteRes<[AtomPort01]> { - let Latency = 183; - let ResourceCycles = [183]; -} -def : InstRW<[AtomWrite01_183], (instrs FPATAN)>; - -def AtomWrite01_202 : SchedWriteRes<[AtomPort01]> { - let Latency = 202; - let ResourceCycles = [202]; -} -def : InstRW<[AtomWrite01_202], (instrs WRMSR)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86ScheduleBtVer2.td b/suite/synctools/tablegen/X86/back/X86ScheduleBtVer2.td deleted file mode 100644 index 719e71cd25..0000000000 --- a/suite/synctools/tablegen/X86/back/X86ScheduleBtVer2.td +++ /dev/null @@ -1,682 +0,0 @@ -//=- X86ScheduleBtVer2.td - X86 BtVer2 (Jaguar) Scheduling ---*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for AMD btver2 (Jaguar) to support -// instruction scheduling and other instruction cost heuristics. Based off AMD Software -// Optimization Guide for AMD Family 16h Processors & Instruction Latency appendix. -// -//===----------------------------------------------------------------------===// - -def BtVer2Model : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and btver2 can - // decode 2 instructions per cycle. - let IssueWidth = 2; - let MicroOpBufferSize = 64; // Retire Control Unit - let LoadLatency = 5; // FPU latency (worse case cf Integer 3 cycle latency) - let HighLatency = 25; - let MispredictPenalty = 14; // Minimum branch misdirection penalty - let PostRAScheduler = 1; - - // FIXME: SSE4/AVX is unimplemented. This flag is set to allow - // the scheduler to assign a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = BtVer2Model in { - -// Jaguar can issue up to 6 micro-ops in one cycle -def JALU0 : ProcResource<1>; // Integer Pipe0: integer ALU0 (also handle FP->INT jam) -def JALU1 : ProcResource<1>; // Integer Pipe1: integer ALU1/MUL/DIV -def JLAGU : ProcResource<1>; // Integer Pipe2: LAGU -def JSAGU : ProcResource<1>; // Integer Pipe3: SAGU (also handles 3-operand LEA) -def JFPU0 : ProcResource<1>; // Vector/FPU Pipe0: VALU0/VIMUL/FPA -def JFPU1 : ProcResource<1>; // Vector/FPU Pipe1: VALU1/STC/FPM - -// The Integer PRF for Jaguar is 64 entries, and it holds the architectural and -// speculative version of the 64-bit integer registers. -// Reference: www.realworldtech.com/jaguar/4/ -// -// The processor always keeps the different parts of an integer register -// together. An instruction that writes to a part of a register will therefore -// have a false dependence on any previous write to the same register or any -// part of it. -// Reference: Section 21.10 "AMD Bobcat and Jaguar pipeline: Partial register -// access" - Agner Fog's "microarchitecture.pdf". -def JIntegerPRF : RegisterFile<64, [GR64, CCR]>; - -// The Jaguar FP Retire Queue renames SIMD and FP uOps onto a pool of 72 SSE -// registers. Operations on 256-bit data types are cracked into two COPs. -// Reference: www.realworldtech.com/jaguar/4/ -def JFpuPRF: RegisterFile<72, [VR64, VR128, VR256], [1, 1, 2]>; - -// The retire control unit (RCU) can track up to 64 macro-ops in-flight. It can -// retire up to two macro-ops per cycle. -// Reference: "Software Optimization Guide for AMD Family 16h Processors" -def JRCU : RetireControlUnit<64, 2>; - -// Integer Pipe Scheduler -def JALU01 : ProcResGroup<[JALU0, JALU1]> { - let BufferSize=20; -} - -// AGU Pipe Scheduler -def JLSAGU : ProcResGroup<[JLAGU, JSAGU]> { - let BufferSize=12; -} - -// Fpu Pipe Scheduler -def JFPU01 : ProcResGroup<[JFPU0, JFPU1]> { - let BufferSize=18; -} - -// Functional units -def JDiv : ProcResource<1>; // integer division -def JMul : ProcResource<1>; // integer multiplication -def JVALU0 : ProcResource<1>; // vector integer -def JVALU1 : ProcResource<1>; // vector integer -def JVIMUL : ProcResource<1>; // vector integer multiplication -def JSTC : ProcResource<1>; // vector store/convert -def JFPM : ProcResource<1>; // FP multiplication -def JFPA : ProcResource<1>; // FP addition - -// Functional unit groups -def JFPX : ProcResGroup<[JFPA, JFPM]>; -def JVALU : ProcResGroup<[JVALU0, JVALU1]>; - -// Integer loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when dispatched by the schedulers. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass JWriteResIntPair ExePorts, - int Lat, list Res = [], int UOps = 1> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on JLAGU and adds 3 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 3); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = UOps; - } -} - -multiclass JWriteResFpuPair ExePorts, - int Lat, list Res = [], int UOps = 1> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on JLAGU and adds 5 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 5); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = UOps; - } -} - -multiclass JWriteResYMMPair ExePorts, - int Lat, list Res = [2], int UOps = 2> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses 2 cycles on JLAGU and adds 5 cycles to the - // latency. - def : WriteRes { - let Latency = !add(Lat, 5); - let ResourceCycles = !listconcat([2], Res); - let NumMicroOps = UOps; - } -} - -// A folded store needs a cycle on the SAGU for the store data. -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Arithmetic. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; // i8/i16/i32 multiplication -defm : JWriteResIntPair; // i64 multiplication -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; - -defm : JWriteResIntPair; - -defm : JWriteResIntPair; // Conditional move. -defm : JWriteResIntPair; // Conditional (CF + ZF flag) move. -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; // Setcc. -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -def : WriteRes; - -// Bit counts. -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; -defm : JWriteResIntPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : JWriteResIntPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Integer shifts and rotates. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; - -// SHLD/SHRD. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Loads, stores, and moves, not folded with other operations. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 5; } -def : WriteRes; -def : WriteRes; -def : WriteRes; - -// Load/store MXCSR. -// FIXME: These are copy and pasted from WriteLoad/Store. -def : WriteRes { let Latency = 5; } -def : WriteRes; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -//////////////////////////////////////////////////////////////////////////////// -// Idioms that clear a register, like xorps %xmm0, %xmm0. -// These can often bypass execution ports completely. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// Branches don't produce values, so they have no latency, but they still -// consume resources. Indirect branches can fold loads. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResIntPair; - -//////////////////////////////////////////////////////////////////////////////// -// Special case scheduling classes. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; - -// Nops don't have dependencies, so there's no actual latency, but we set this -// to '1' to tell the scheduler that the nop uses an ALU slot for a cycle. -def : WriteRes { let Latency = 1; } - -//////////////////////////////////////////////////////////////////////////////// -// Floating point. This covers both scalar and vector operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Conversions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -// FIXME: f+3 ST, LD+STC latency -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteResUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector integer operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Vector insert/extract operations. -//////////////////////////////////////////////////////////////////////////////// - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -//////////////////////////////////////////////////////////////////////////////// -// SSE42 String instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// MOVMSK Instructions. -//////////////////////////////////////////////////////////////////////////////// - -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -defm : X86WriteResUnsupported; -def : WriteRes { let Latency = 3; } - -//////////////////////////////////////////////////////////////////////////////// -// AES Instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; -defm : JWriteResYMMPair; -defm : JWriteResFpuPair; -defm : JWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -//////////////////////////////////////////////////////////////////////////////// -// Carry-less multiplication instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : JWriteResFpuPair; - -//////////////////////////////////////////////////////////////////////////////// -// SSE4A instructions. -//////////////////////////////////////////////////////////////////////////////// - -def JWriteINSERTQ: SchedWriteRes<[JFPU01, JVALU]> { - let Latency = 2; - let ResourceCycles = [1, 4]; -} -def : InstRW<[JWriteINSERTQ], (instrs INSERTQ, INSERTQI)>; - -//////////////////////////////////////////////////////////////////////////////// -// AVX instructions. -//////////////////////////////////////////////////////////////////////////////// - -def JWriteVBROADCASTYLd: SchedWriteRes<[JLAGU, JFPU01, JFPX]> { - let Latency = 6; - let ResourceCycles = [1, 2, 4]; - let NumMicroOps = 2; -} -def : InstRW<[JWriteVBROADCASTYLd, ReadAfterLd], (instrs VBROADCASTSDYrm, - VBROADCASTSSYrm)>; - -def JWriteJVZEROALL: SchedWriteRes<[]> { - let Latency = 90; - let NumMicroOps = 73; -} -def : InstRW<[JWriteJVZEROALL], (instrs VZEROALL)>; - -def JWriteJVZEROUPPER: SchedWriteRes<[]> { - let Latency = 46; - let NumMicroOps = 37; -} -def : InstRW<[JWriteJVZEROUPPER], (instrs VZEROUPPER)>; - -/////////////////////////////////////////////////////////////////////////////// -// SchedWriteVariant definitions. -/////////////////////////////////////////////////////////////////////////////// - -def JWriteZeroLatency : SchedWriteRes<[]> { - let Latency = 0; -} - -// Certain instructions that use the same register for both source -// operands do not have a real dependency on the previous contents of the -// register, and thus, do not have to wait before completing. They can be -// optimized out at register renaming stage. -// Reference: Section 10.8 of the "Software Optimization Guide for AMD Family -// 15h Processors". -// Reference: Agner's Fog "The microarchitecture of Intel, AMD and VIA CPUs", -// Section 21.8 [Dependency-breaking instructions]. - -def JWriteZeroIdiom : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteALU]> -]>; -def : InstRW<[JWriteZeroIdiom], (instrs SUB32rr, SUB64rr, - XOR32rr, XOR64rr)>; - -def JWriteFZeroIdiom : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteFLogic]> -]>; -def : InstRW<[JWriteFZeroIdiom], (instrs XORPSrr, VXORPSrr, XORPDrr, VXORPDrr, - ANDNPSrr, VANDNPSrr, - ANDNPDrr, VANDNPDrr)>; - -def JWriteVZeroIdiomLogic : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecLogic]> -]>; -def : InstRW<[JWriteVZeroIdiomLogic], (instrs MMX_PXORirr, MMX_PANDNirr)>; - -def JWriteVZeroIdiomLogicX : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecLogicX]> -]>; -def : InstRW<[JWriteVZeroIdiomLogicX], (instrs PXORrr, VPXORrr, - PANDNrr, VPANDNrr)>; - -def JWriteVZeroIdiomALU : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecALU]> -]>; -def : InstRW<[JWriteVZeroIdiomALU], (instrs MMX_PSUBBirr, MMX_PSUBDirr, - MMX_PSUBQirr, MMX_PSUBWirr, - MMX_PCMPGTBirr, MMX_PCMPGTDirr, - MMX_PCMPGTWirr)>; - -def JWriteVZeroIdiomALUX : SchedWriteVariant<[ - SchedVar, [JWriteZeroLatency]>, - SchedVar, [WriteVecALUX]> -]>; -def : InstRW<[JWriteVZeroIdiomALUX], (instrs PSUBBrr, VPSUBBrr, - PSUBDrr, VPSUBDrr, - PSUBQrr, VPSUBQrr, - PSUBWrr, VPSUBWrr, - PCMPGTBrr, VPCMPGTBrr, - PCMPGTDrr, VPCMPGTDrr, - PCMPGTQrr, VPCMPGTQrr, - PCMPGTWrr, VPCMPGTWrr)>; - -// This write is used for slow LEA instructions. -def JWrite3OpsLEA : SchedWriteRes<[JALU1, JSAGU]> { - let Latency = 2; -} - -// On Jaguar, a slow LEA is either a 3Ops LEA (base, index, offset), or an LEA -// with a `Scale` value different than 1. -def JSlowLEAPredicate : MCSchedPredicate< - CheckAny<[ - // A 3-operand LEA (base, index, offset). - IsThreeOperandsLEAFn, - // An LEA with a "Scale" different than 1. - CheckAll<[ - CheckIsImmOperand<2>, - CheckNot> - ]> - ]> ->; - -def JWriteLEA : SchedWriteVariant<[ - SchedVar, - SchedVar, [WriteLEA]> -]>; - -def : InstRW<[JWriteLEA], (instrs LEA32r, LEA64r, LEA64_32r)>; - -def JSlowLEA16r : SchedWriteRes<[JALU01]> { - let Latency = 3; - let ResourceCycles = [4]; -} - -def : InstRW<[JSlowLEA16r], (instrs LEA16r)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86ScheduleSLM.td b/suite/synctools/tablegen/X86/back/X86ScheduleSLM.td deleted file mode 100644 index b1e8430137..0000000000 --- a/suite/synctools/tablegen/X86/back/X86ScheduleSLM.td +++ /dev/null @@ -1,486 +0,0 @@ -//=- X86ScheduleSLM.td - X86 Silvermont Scheduling -----------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Intel Silvermont to support -// instruction scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def SLMModel : SchedMachineModel { - // All x86 instructions are modeled as a single micro-op, and SLM can decode 2 - // instructions per cycle. - let IssueWidth = 2; - let MicroOpBufferSize = 32; // Based on the reorder buffer. - let LoadLatency = 3; - let MispredictPenalty = 10; - let PostRAScheduler = 1; - - // For small loops, expand by a small factor to hide the backedge cost. - let LoopMicroOpBufferSize = 10; - - // FIXME: SSE4 is unimplemented. This flag is set to allow - // the scheduler to assign a default model to unrecognized opcodes. - let CompleteModel = 0; -} - -let SchedModel = SLMModel in { - -// Silvermont has 5 reservation stations for micro-ops -def SLM_IEC_RSV0 : ProcResource<1>; -def SLM_IEC_RSV1 : ProcResource<1>; -def SLM_FPC_RSV0 : ProcResource<1> { let BufferSize = 1; } -def SLM_FPC_RSV1 : ProcResource<1> { let BufferSize = 1; } -def SLM_MEC_RSV : ProcResource<1>; - -// Many micro-ops are capable of issuing on multiple ports. -def SLM_IEC_RSV01 : ProcResGroup<[SLM_IEC_RSV0, SLM_IEC_RSV1]>; -def SLM_FPC_RSV01 : ProcResGroup<[SLM_FPC_RSV0, SLM_FPC_RSV1]>; - -def SLMDivider : ProcResource<1>; -def SLMFPMultiplier : ProcResource<1>; -def SLMFPDivider : ProcResource<1>; - -// Loads are 3 cycles, so ReadAfterLd registers needn't be available until 3 -// cycles after the memory operand. -def : ReadAdvance; - -// Many SchedWrites are defined in pairs with and without a folded load. -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops when queued in the reservation station. -// This multiclass defines the resource usage for variants with and without -// folded loads. -multiclass SLMWriteResPair ExePorts, - int Lat, list Res = [1], int UOps = 1, - int LoadLat = 3> { - // Register variant is using a single cycle on ExePort. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on MEC_RSV and adds LoadLat cycles to - // the latency (default = 3). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !listconcat([1], Res); - let NumMicroOps = UOps; - } -} - -// A folded store needs a cycle on MEC_RSV for the store data, but it does not -// need an extra port cycle to recompute the address. -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; - -// Load/store MXCSR. -// FIXME: These are probably wrong. They are copy pasted from WriteStore/Load. -def : WriteRes; -def : WriteRes { let Latency = 3; } - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteRes; // x87 conditional move. -def : WriteRes; -def : WriteRes { - // FIXME Latency and NumMicrOps? - let ResourceCycles = [2,1]; -} -def : WriteRes; -def : WriteRes; - -// This is for simple LEAs with one or two input operands. -// The complex ones can only execute on port 1, and they require two cycles on -// the port to read all inputs. We don't model that. -def : WriteRes; - -// Bit counts. -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -// BMI1 BEXTR, BMI2 BZHI -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; - -// Scalar and vector floating point. -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -defm : X86WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; - -// Conversion between integer and float. -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -// Vector integer operations. -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes { let Latency = 3; } -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -// FIXME: The below is closer to correct, but caused some perf regressions. -//defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; - -// Vector insert/extract operations. -defm : SLMWriteResPair; - -def : WriteRes; -def : WriteRes { - let Latency = 4; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} - -//////////////////////////////////////////////////////////////////////////////// -// Horizontal add/sub instructions. -//////////////////////////////////////////////////////////////////////////////// - -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; - -// String instructions. -// Packed Compare Implicit Length Strings, Return Mask -def : WriteRes { - let Latency = 13; - let ResourceCycles = [13]; -} -def : WriteRes { - let Latency = 13; - let ResourceCycles = [13, 1]; -} - -// Packed Compare Explicit Length Strings, Return Mask -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17]; -} -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17, 1]; -} - -// Packed Compare Implicit Length Strings, Return Index -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17]; -} -def : WriteRes { - let Latency = 17; - let ResourceCycles = [17, 1]; -} - -// Packed Compare Explicit Length Strings, Return Index -def : WriteRes { - let Latency = 21; - let ResourceCycles = [21]; -} -def : WriteRes { - let Latency = 21; - let ResourceCycles = [21, 1]; -} - -// MOVMSK Instructions. -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } -def : WriteRes { let Latency = 4; } - -// AES Instructions. -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5]; -} -def : WriteRes { - let Latency = 8; - let ResourceCycles = [5, 1]; -} - -// Carry-less multiplication instructions. -def : WriteRes { - let Latency = 10; - let ResourceCycles = [10]; -} -def : WriteRes { - let Latency = 10; - let ResourceCycles = [10, 1]; -} - -def : WriteRes { let Latency = 100; } -def : WriteRes { let Latency = 100; } -def : WriteRes; -def : WriteRes; - -// AVX/FMA is not supported on that architecture, but we should define the basic -// scheduling resources anyway. -def : WriteRes; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : SLMWriteResPair; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; - -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResPairUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86ScheduleZnver1.td b/suite/synctools/tablegen/X86/back/X86ScheduleZnver1.td deleted file mode 100644 index 7184b850a1..0000000000 --- a/suite/synctools/tablegen/X86/back/X86ScheduleZnver1.td +++ /dev/null @@ -1,1544 +0,0 @@ -//=- X86ScheduleZnver1.td - X86 Znver1 Scheduling -------------*- tablegen -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the machine model for Znver1 to support instruction -// scheduling and other instruction cost heuristics. -// -//===----------------------------------------------------------------------===// - -def Znver1Model : SchedMachineModel { - // Zen can decode 4 instructions per cycle. - let IssueWidth = 4; - // Based on the reorder buffer we define MicroOpBufferSize - let MicroOpBufferSize = 192; - let LoadLatency = 4; - let MispredictPenalty = 17; - let HighLatency = 25; - let PostRAScheduler = 1; - - // FIXME: This variable is required for incomplete model. - // We haven't catered all instructions. - // So, we reset the value of this variable so as to - // say that the model is incomplete. - let CompleteModel = 0; -} - -let SchedModel = Znver1Model in { - -// Zen can issue micro-ops to 10 different units in one cycle. -// These are -// * Four integer ALU units (ZALU0, ZALU1, ZALU2, ZALU3) -// * Two AGU units (ZAGU0, ZAGU1) -// * Four FPU units (ZFPU0, ZFPU1, ZFPU2, ZFPU3) -// AGUs feed load store queues @two loads and 1 store per cycle. - -// Four ALU units are defined below -def ZnALU0 : ProcResource<1>; -def ZnALU1 : ProcResource<1>; -def ZnALU2 : ProcResource<1>; -def ZnALU3 : ProcResource<1>; - -// Two AGU units are defined below -def ZnAGU0 : ProcResource<1>; -def ZnAGU1 : ProcResource<1>; - -// Four FPU units are defined below -def ZnFPU0 : ProcResource<1>; -def ZnFPU1 : ProcResource<1>; -def ZnFPU2 : ProcResource<1>; -def ZnFPU3 : ProcResource<1>; - -// FPU grouping -def ZnFPU013 : ProcResGroup<[ZnFPU0, ZnFPU1, ZnFPU3]>; -def ZnFPU01 : ProcResGroup<[ZnFPU0, ZnFPU1]>; -def ZnFPU12 : ProcResGroup<[ZnFPU1, ZnFPU2]>; -def ZnFPU13 : ProcResGroup<[ZnFPU1, ZnFPU3]>; -def ZnFPU23 : ProcResGroup<[ZnFPU2, ZnFPU3]>; -def ZnFPU02 : ProcResGroup<[ZnFPU0, ZnFPU2]>; -def ZnFPU03 : ProcResGroup<[ZnFPU0, ZnFPU3]>; - -// Below are the grouping of the units. -// Micro-ops to be issued to multiple units are tackled this way. - -// ALU grouping -// ZnALU03 - 0,3 grouping -def ZnALU03: ProcResGroup<[ZnALU0, ZnALU3]>; - -// 56 Entry (14x4 entries) Int Scheduler -def ZnALU : ProcResGroup<[ZnALU0, ZnALU1, ZnALU2, ZnALU3]> { - let BufferSize=56; -} - -// 28 Entry (14x2) AGU group. AGUs can't be used for all ALU operations -// but are relevant for some instructions -def ZnAGU : ProcResGroup<[ZnAGU0, ZnAGU1]> { - let BufferSize=28; -} - -// Integer Multiplication issued on ALU1. -def ZnMultiplier : ProcResource<1>; - -// Integer division issued on ALU2. -def ZnDivider : ProcResource<1>; - -// 4 Cycles load-to use Latency is captured -def : ReadAdvance; - -// The Integer PRF for Zen is 168 entries, and it holds the architectural and -// speculative version of the 64-bit integer registers. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -def ZnIntegerPRF : RegisterFile<168, [GR64, CCR]>; - -// 36 Entry (9x4 entries) floating-point Scheduler -def ZnFPU : ProcResGroup<[ZnFPU0, ZnFPU1, ZnFPU2, ZnFPU3]> { -let BufferSize=36; -} - -// The Zen FP Retire Queue renames SIMD and FP uOps onto a pool of 160 128-bit -// registers. Operations on 256-bit data types are cracked into two COPs. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -def ZnFpuPRF: RegisterFile<160, [VR64, VR128, VR256], [1, 1, 2]>; - -// The unit can track up to 192 macro ops in-flight. -// The retire unit handles in-order commit of up to 8 macro ops per cycle. -// Reference: "Software Optimization Guide for AMD Family 17h Processors" -// To be noted, the retire unit is shared between integer and FP ops. -// In SMT mode it is 96 entry per thread. But, we do not use the conservative -// value here because there is currently no way to fully mode the SMT mode, -// so there is no point in trying. -def ZnRCU : RetireControlUnit<192, 8>; - -// FIXME: there are 72 read buffers and 44 write buffers. - -// (a folded load is an instruction that loads and does some operation) -// Ex: ADDPD xmm,[mem]-> This instruction has two micro-ops -// Instructions with folded loads are usually micro-fused, so they only appear -// as two micro-ops. -// a. load and -// b. addpd -// This multiclass is for folded loads for integer units. -multiclass ZnWriteResPair ExePorts, - int Lat, list Res = [], int UOps = 1, - int LoadLat = 4, int LoadUOps = 1> { - // Register variant takes 1-cycle on Execution Port. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on ZnAGU - // adds LoadLat cycles to the latency (default = 4). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = !add(UOps, LoadUOps); - } -} - -// This multiclass is for folded loads for floating point units. -multiclass ZnWriteResFpuPair ExePorts, - int Lat, list Res = [], int UOps = 1, - int LoadLat = 7, int LoadUOps = 0> { - // Register variant takes 1-cycle on Execution Port. - def : WriteRes { - let Latency = Lat; - let ResourceCycles = Res; - let NumMicroOps = UOps; - } - - // Memory variant also uses a cycle on ZnAGU - // adds LoadLat cycles to the latency (default = 7). - def : WriteRes { - let Latency = !add(Lat, LoadLat); - let ResourceCycles = !if(!empty(Res), [], !listconcat([1], Res)); - let NumMicroOps = !add(UOps, LoadUOps); - } -} - -// WriteRMW is set for instructions with Memory write -// operation in codegen -def : WriteRes; - -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes { let Latency = 8; } - -def : WriteRes; -def : WriteRes; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResPair; - -defm : X86WriteRes; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; -defm : X86WriteResUnsupported; - -defm : ZnWriteResPair; -defm : ZnWriteResFpuPair; - -defm : ZnWriteResPair; -defm : ZnWriteResPair; -def : WriteRes; -def : WriteRes; -defm : X86WriteRes; -def : WriteRes; - -// Bit counts. -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// Treat misc copies as a move. -def : InstRW<[WriteMove], (instrs COPY)>; - -// BMI1 BEXTR, BMI2 BZHI -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// IDIV -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; -defm : ZnWriteResPair; - -// IMULH -def : WriteRes{ - let Latency = 4; -} - -// Floating point operations -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; // FIXME: Should folds require 1 extra uops? -defm : ZnWriteResFpuPair; // FIXME: Should folds require 1 extra uops? -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -//defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -//defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; - -// Vector integer operations which uses FPU units -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; - -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; // FIXME -defm : ZnWriteResFpuPair; // FIXME -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; -defm : ZnWriteResFpuPair; - -// Vector Shift Operations -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : X86WriteResPairUnsupported; - -// Vector insert/extract operations. -defm : ZnWriteResFpuPair; - -def : WriteRes { - let Latency = 2; - let ResourceCycles = [1, 2]; -} -def : WriteRes { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [1, 2, 3]; -} - -// MOVMSK Instructions. -def : WriteRes; -def : WriteRes; -def : WriteRes; - -def : WriteRes { - let NumMicroOps = 2; - let Latency = 2; - let ResourceCycles = [2]; -} - -// AES Instructions. -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; - -def : WriteRes; -def : WriteRes; - -// Following instructions with latency=100 are microcoded. -// We set long latency so as to block the entire pipeline. -defm : ZnWriteResFpuPair; -defm : ZnWriteResFpuPair; - -// Microcoded Instructions -def ZnWriteMicrocoded : SchedWriteRes<[]> { - let Latency = 100; -} - -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -//=== Regex based InstRW ===// -// Notation: -// - r: register. -// - m = memory. -// - i = immediate -// - mm: 64 bit mmx register. -// - x = 128 bit xmm register. -// - (x)mm = mmx or xmm register. -// - y = 256 bit ymm register. -// - v = any vector register. - -//=== Integer Instructions ===// -//-- Move instructions --// -// MOV. -// r16,m. -def : InstRW<[WriteALULd, ReadAfterLd], (instregex "MOV16rm")>; - -// MOVSX, MOVZX. -// r,m. -def : InstRW<[WriteLoad], (instregex "MOV(S|Z)X32rm(8|16)")>; - -// XCHG. -// r,r. -def ZnWriteXCHG : SchedWriteRes<[ZnALU]> { - let NumMicroOps = 2; - let ResourceCycles = [2]; -} - -def : InstRW<[ZnWriteXCHG], (instregex "XCHG(8|16|32|64)rr", "XCHG(16|32|64)ar")>; - -// r,m. -def ZnWriteXCHGrm : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 5; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteXCHGrm, ReadAfterLd], (instregex "XCHG(8|16|32|64)rm")>; - -def : InstRW<[WriteMicrocoded], (instrs XLAT)>; - -// POP16. -// r. -def ZnWritePop16r : SchedWriteRes<[ZnAGU]>{ - let Latency = 5; - let NumMicroOps = 2; -} -def : InstRW<[ZnWritePop16r], (instregex "POP16rmm")>; -def : InstRW<[WriteMicrocoded], (instregex "POPF(16|32)")>; -def : InstRW<[WriteMicrocoded], (instregex "POPA(16|32)")>; - - -// PUSH. -// r. Has default values. -// m. -def ZnWritePUSH : SchedWriteRes<[ZnAGU]>{ - let Latency = 4; -} -def : InstRW<[ZnWritePUSH], (instregex "PUSH(16|32)rmm")>; - -//PUSHF -def : InstRW<[WriteMicrocoded], (instregex "PUSHF(16|32)")>; - -// PUSHA. -def ZnWritePushA : SchedWriteRes<[ZnAGU]> { - let Latency = 8; -} -def : InstRW<[ZnWritePushA], (instregex "PUSHA(16|32)")>; - -//LAHF -def : InstRW<[WriteMicrocoded], (instrs LAHF)>; - -// MOVBE. -// r,m. -def ZnWriteMOVBE : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 5; -} -def : InstRW<[ZnWriteMOVBE, ReadAfterLd], (instregex "MOVBE(16|32|64)rm")>; - -// m16,r16. -def : InstRW<[ZnWriteMOVBE], (instregex "MOVBE(16|32|64)mr")>; - -//-- Arithmetic instructions --// - -// ADD SUB. -// m,r/i. -def : InstRW<[WriteALULd], (instregex "(ADD|SUB)(8|16|32|64)m(r|i)", - "(ADD|SUB)(8|16|32|64)mi8", - "(ADD|SUB)64mi32")>; - -// ADC SBB. -// m,r/i. -def : InstRW<[WriteALULd], - (instregex "(ADC|SBB)(8|16|32|64)m(r|i)", - "(ADC|SBB)(16|32|64)mi8", - "(ADC|SBB)64mi32")>; - -// INC DEC NOT NEG. -// m. -def : InstRW<[WriteALULd], - (instregex "(INC|DEC|NOT|NEG)(8|16|32|64)m")>; - -// MUL IMUL. -// r16. -def ZnWriteMul16 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMul16], (instrs IMUL16r, MUL16r)>; -def : InstRW<[ZnWriteMul16], (instrs IMUL16rr, IMUL16rri, IMUL16rri8)>; // TODO: is this right? -def : InstRW<[ZnWriteMul16], (instrs IMUL16rm, IMUL16rmi, IMUL16rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m16. -def ZnWriteMul16Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMul16Ld, ReadAfterLd], (instrs IMUL16m, MUL16m)>; - -// r32. -def ZnWriteMul32 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMul32], (instrs IMUL32r, MUL32r)>; -def : InstRW<[ZnWriteMul32], (instrs IMUL32rr, IMUL32rri, IMUL32rri8)>; // TODO: is this right? -def : InstRW<[ZnWriteMul32], (instrs IMUL32rm, IMUL32rmi, IMUL32rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m32. -def ZnWriteMul32Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMul32Ld, ReadAfterLd], (instrs IMUL32m, MUL32m)>; - -// r64. -def ZnWriteMul64 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 4; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteMul64], (instrs IMUL64r, MUL64r)>; -def : InstRW<[ZnWriteMul64], (instrs IMUL64rr, IMUL64rri8, IMUL64rri32)>; // TODO: is this right? -def : InstRW<[ZnWriteMul64], (instrs IMUL64rm, IMUL64rmi32, IMUL64rmi8)>; // TODO: this is definitely wrong but matches what the instregex did. - -// m64. -def ZnWriteMul64Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 9; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteMul64Ld, ReadAfterLd], (instrs IMUL64m, MUL64m)>; - -// MULX. -// r32,r32,r32. -def ZnWriteMulX32 : SchedWriteRes<[ZnALU1, ZnMultiplier]> { - let Latency = 3; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteMulX32], (instrs MULX32rr)>; - -// r32,r32,m32. -def ZnWriteMulX32Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; - let ResourceCycles = [1, 2, 2]; -} -def : InstRW<[ZnWriteMulX32Ld, ReadAfterLd], (instrs MULX32rm)>; - -// r64,r64,r64. -def ZnWriteMulX64 : SchedWriteRes<[ZnALU1]> { - let Latency = 3; -} -def : InstRW<[ZnWriteMulX64], (instrs MULX64rr)>; - -// r64,r64,m64. -def ZnWriteMulX64Ld : SchedWriteRes<[ZnAGU, ZnALU1, ZnMultiplier]> { - let Latency = 8; -} -def : InstRW<[ZnWriteMulX64Ld, ReadAfterLd], (instrs MULX64rm)>; - -//-- Control transfer instructions --// - -// J(E|R)CXZ. -def ZnWriteJCXZ : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteJCXZ], (instrs JCXZ, JECXZ, JRCXZ)>; - -// INTO -def : InstRW<[WriteMicrocoded], (instrs INTO)>; - -// LOOP. -def ZnWriteLOOP : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteLOOP], (instrs LOOP)>; - -// LOOP(N)E, LOOP(N)Z -def ZnWriteLOOPE : SchedWriteRes<[ZnALU03]>; -def : InstRW<[ZnWriteLOOPE], (instrs LOOPE, LOOPNE)>; - -// CALL. -// r. -def ZnWriteCALLr : SchedWriteRes<[ZnAGU, ZnALU03]>; -def : InstRW<[ZnWriteCALLr], (instregex "CALL(16|32)r")>; - -def : InstRW<[WriteMicrocoded], (instregex "CALL(16|32)m")>; - -// RET. -def ZnWriteRET : SchedWriteRes<[ZnALU03]> { - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteRET], (instregex "RET(L|Q|W)", "LRET(L|Q|W)", - "IRET(16|32|64)")>; - -//-- Logic instructions --// - -// AND OR XOR. -// m,r/i. -def : InstRW<[WriteALULd], - (instregex "(AND|OR|XOR)(8|16|32|64)m(r|i)", - "(AND|OR|XOR)(8|16|32|64)mi8", "(AND|OR|XOR)64mi32")>; - -// Define ALU latency variants -def ZnWriteALULat2 : SchedWriteRes<[ZnALU]> { - let Latency = 2; -} -def ZnWriteALULat2Ld : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 6; -} - -// BT. -// m,i. -def : InstRW<[WriteShiftLd], (instregex "BT(16|32|64)mi8")>; - -// BTR BTS BTC. -// r,r,i. -def ZnWriteBTRSC : SchedWriteRes<[ZnALU]> { - let Latency = 2; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteBTRSC], (instregex "BT(R|S|C)(16|32|64)r(r|i8)")>; - -// m,r,i. -def ZnWriteBTRSCm : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 6; - let NumMicroOps = 2; -} -// m,r,i. -def : InstRW<[ZnWriteBTRSCm], (instregex "BT(R|S|C)(16|32|64)m(r|i8)")>; - -// BLSI BLSMSK BLSR. -// r,r. -def : InstRW<[ZnWriteALULat2], (instregex "BLS(I|MSK|R)(32|64)rr")>; -// r,m. -def : InstRW<[ZnWriteALULat2Ld], (instregex "BLS(I|MSK|R)(32|64)rm")>; - -// CLD STD. -def : InstRW<[WriteALU], (instrs STD, CLD)>; - -// PDEP PEXT. -// r,r,r. -def : InstRW<[WriteMicrocoded], (instregex "PDEP(32|64)rr", "PEXT(32|64)rr")>; -// r,r,m. -def : InstRW<[WriteMicrocoded], (instregex "PDEP(32|64)rm", "PEXT(32|64)rm")>; - -// RCR RCL. -// m,i. -def : InstRW<[WriteMicrocoded], (instregex "RC(R|L)(8|16|32|64)m(1|i|CL)")>; - -// SHR SHL SAR. -// m,i. -def : InstRW<[WriteShiftLd], (instregex "S(A|H)(R|L)(8|16|32|64)m(i|1)")>; - -// SHRD SHLD. -// m,r -def : InstRW<[WriteShiftLd], (instregex "SH(R|L)D(16|32|64)mri8")>; - -// r,r,cl. -def : InstRW<[WriteMicrocoded], (instregex "SH(R|L)D(16|32|64)rrCL")>; - -// m,r,cl. -def : InstRW<[WriteMicrocoded], (instregex "SH(R|L)D(16|32|64)mrCL")>; - -//-- Misc instructions --// -// CMPXCHG. -def ZnWriteCMPXCHG : SchedWriteRes<[ZnAGU, ZnALU]> { - let Latency = 8; - let NumMicroOps = 5; -} -def : InstRW<[ZnWriteCMPXCHG], (instregex "CMPXCHG(8|16|32|64)rm")>; - -// CMPXCHG8B. -def ZnWriteCMPXCHG8B : SchedWriteRes<[ZnAGU, ZnALU]> { - let NumMicroOps = 18; -} -def : InstRW<[ZnWriteCMPXCHG8B], (instrs CMPXCHG8B)>; - -def : InstRW<[WriteMicrocoded], (instrs CMPXCHG16B)>; - -// LEAVE -def ZnWriteLEAVE : SchedWriteRes<[ZnALU, ZnAGU]> { - let Latency = 8; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteLEAVE], (instregex "LEAVE")>; - -// PAUSE. -def : InstRW<[WriteMicrocoded], (instrs PAUSE)>; - -// RDTSC. -def : InstRW<[WriteMicrocoded], (instregex "RDTSC")>; - -// RDPMC. -def : InstRW<[WriteMicrocoded], (instrs RDPMC)>; - -// RDRAND. -def : InstRW<[WriteMicrocoded], (instregex "RDRAND(16|32|64)r")>; - -// XGETBV. -def : InstRW<[WriteMicrocoded], (instregex "XGETBV")>; - -//-- String instructions --// -// CMPS. -def : InstRW<[WriteMicrocoded], (instregex "CMPS(B|L|Q|W)")>; - -// LODSB/W. -def : InstRW<[WriteMicrocoded], (instregex "LODS(B|W)")>; - -// LODSD/Q. -def : InstRW<[WriteMicrocoded], (instregex "LODS(L|Q)")>; - -// MOVS. -def : InstRW<[WriteMicrocoded], (instregex "MOVS(B|L|Q|W)")>; - -// SCAS. -def : InstRW<[WriteMicrocoded], (instregex "SCAS(B|W|L|Q)")>; - -// STOS -def : InstRW<[WriteMicrocoded], (instregex "STOS(B|L|Q|W)")>; - -// XADD. -def : InstRW<[WriteMicrocoded], (instregex "XADD(8|16|32|64)rm")>; - -//=== Floating Point x87 Instructions ===// -//-- Move instructions --// - -def ZnWriteFLDr : SchedWriteRes<[ZnFPU13]> ; - -def ZnWriteSTr: SchedWriteRes<[ZnFPU23]> { - let Latency = 5; - let NumMicroOps = 2; -} - -// LD_F. -// r. -def : InstRW<[ZnWriteFLDr], (instregex "LD_Frr")>; - -// m. -def ZnWriteLD_F80m : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteLD_F80m], (instregex "LD_F80m")>; - -// FBLD. -def : InstRW<[WriteMicrocoded], (instregex "FBLDm")>; - -// FST(P). -// r. -def : InstRW<[ZnWriteSTr], (instregex "ST_(F|FP)rr")>; - -// m80. -def ZnWriteST_FP80m : SchedWriteRes<[ZnAGU, ZnFPU23]> { - let Latency = 5; -} -def : InstRW<[ZnWriteST_FP80m], (instregex "ST_FP80m")>; - -// FBSTP. -// m80. -def : InstRW<[WriteMicrocoded], (instregex "FBSTPm")>; - -def ZnWriteFXCH : SchedWriteRes<[ZnFPU]>; - -// FXCHG. -def : InstRW<[ZnWriteFXCH], (instrs XCH_F)>; - -// FILD. -def ZnWriteFILD : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; - let NumMicroOps = 2; -} -def : InstRW<[ZnWriteFILD], (instregex "ILD_F(16|32|64)m")>; - -// FIST(P) FISTTP. -def ZnWriteFIST : SchedWriteRes<[ZnAGU, ZnFPU23]> { - let Latency = 12; -} -def : InstRW<[ZnWriteFIST], (instregex "IS(T|TT)_(F|FP)(16|32|64)m")>; - -def ZnWriteFPU13 : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let Latency = 8; -} - -def ZnWriteFPU3 : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; -} - -// FLDZ. -def : SchedAlias; - -// FLD1. -def : SchedAlias; - -// FLDPI FLDL2E etc. -def : SchedAlias; - -// FNSTSW. -// AX. -def : InstRW<[WriteMicrocoded], (instrs FNSTSW16r)>; - -// m16. -def : InstRW<[WriteMicrocoded], (instrs FNSTSWm)>; - -// FLDCW. -def : InstRW<[WriteMicrocoded], (instrs FLDCW16m)>; - -// FNSTCW. -def : InstRW<[WriteMicrocoded], (instrs FNSTCW16m)>; - -// FINCSTP FDECSTP. -def : InstRW<[ZnWriteFPU3], (instrs FINCSTP, FDECSTP)>; - -// FFREE. -def : InstRW<[ZnWriteFPU3], (instregex "FFREE")>; - -// FNSAVE. -def : InstRW<[WriteMicrocoded], (instregex "FSAVEm")>; - -// FRSTOR. -def : InstRW<[WriteMicrocoded], (instregex "FRSTORm")>; - -//-- Arithmetic instructions --// - -def ZnWriteFPU3Lat1 : SchedWriteRes<[ZnFPU3]> ; - -def ZnWriteFPU0Lat1 : SchedWriteRes<[ZnFPU0]> ; - -def ZnWriteFPU0Lat1Ld : SchedWriteRes<[ZnAGU, ZnFPU0]> { - let Latency = 8; -} - -// FCHS. -def : InstRW<[ZnWriteFPU3Lat1], (instregex "CHS_F")>; - -// FCOM(P) FUCOM(P). -// r. -def : InstRW<[ZnWriteFPU0Lat1], (instregex "COM(P?)_FST0r", "UCOM_F(P?)r")>; -// m. -def : InstRW<[ZnWriteFPU0Lat1Ld], (instregex "FCOM(P?)(32|64)m")>; - -// FCOMPP FUCOMPP. -// r. -def : InstRW<[ZnWriteFPU0Lat1], (instrs FCOMPP, UCOM_FPPr)>; - -def ZnWriteFPU02 : SchedWriteRes<[ZnAGU, ZnFPU02]> -{ - let Latency = 9; -} - -// FCOMI(P) FUCOMI(P). -// m. -def : InstRW<[ZnWriteFPU02], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; - -def ZnWriteFPU03 : SchedWriteRes<[ZnAGU, ZnFPU03]> -{ - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,3]; -} - -// FICOM(P). -def : InstRW<[ZnWriteFPU03], (instregex "FICOM(P?)(16|32)m")>; - -// FTST. -def : InstRW<[ZnWriteFPU0Lat1], (instregex "TST_F")>; - -// FXAM. -def : InstRW<[ZnWriteFPU3Lat1], (instrs FXAM)>; - -// FPREM. -def : InstRW<[WriteMicrocoded], (instrs FPREM)>; - -// FPREM1. -def : InstRW<[WriteMicrocoded], (instrs FPREM1)>; - -// FRNDINT. -def : InstRW<[WriteMicrocoded], (instrs FRNDINT)>; - -// FSCALE. -def : InstRW<[WriteMicrocoded], (instrs FSCALE)>; - -// FXTRACT. -def : InstRW<[WriteMicrocoded], (instrs FXTRACT)>; - -// FNOP. -def : InstRW<[ZnWriteFPU0Lat1], (instrs FNOP)>; - -// WAIT. -def : InstRW<[ZnWriteFPU0Lat1], (instrs WAIT)>; - -// FNCLEX. -def : InstRW<[WriteMicrocoded], (instrs FNCLEX)>; - -// FNINIT. -def : InstRW<[WriteMicrocoded], (instrs FNINIT)>; - -//=== Integer MMX and XMM Instructions ===// - -// PACKSSWB/DW. -// mm <- mm. -def ZnWriteFPU12 : SchedWriteRes<[ZnFPU12]> ; -def ZnWriteFPU12Y : SchedWriteRes<[ZnFPU12]> { - let NumMicroOps = 2; -} -def ZnWriteFPU12m : SchedWriteRes<[ZnAGU, ZnFPU12]> ; -def ZnWriteFPU12Ym : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; - let NumMicroOps = 2; -} - -def : InstRW<[ZnWriteFPU12], (instrs MMX_PACKSSDWirr, - MMX_PACKSSWBirr, - MMX_PACKUSWBirr)>; -def : InstRW<[ZnWriteFPU12m], (instrs MMX_PACKSSDWirm, - MMX_PACKSSWBirm, - MMX_PACKUSWBirm)>; - -// VPMOVSX/ZX BW BD BQ WD WQ DQ. -// y <- x. -def : InstRW<[ZnWriteFPU12Y], (instregex "VPMOV(SX|ZX)(BW|BD|BQ|WD|WQ|DQ)Yrr")>; -def : InstRW<[ZnWriteFPU12Ym], (instregex "VPMOV(SX|ZX)(BW|BD|BQ|WD|WQ|DQ)Yrm")>; - -def ZnWriteFPU013 : SchedWriteRes<[ZnFPU013]> ; -def ZnWriteFPU013Y : SchedWriteRes<[ZnFPU013]> { - let Latency = 2; -} -def ZnWriteFPU013m : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 8; - let NumMicroOps = 2; -} -def ZnWriteFPU013Ld : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 8; - let NumMicroOps = 2; -} -def ZnWriteFPU013LdY : SchedWriteRes<[ZnAGU, ZnFPU013]> { - let Latency = 9; - let NumMicroOps = 2; -} - -// PBLENDW. -// x,x,i / v,v,v,i -def : InstRW<[ZnWriteFPU013], (instregex "(V?)PBLENDWrri")>; -// ymm -def : InstRW<[ZnWriteFPU013Y], (instrs VPBLENDWYrri)>; - -// x,m,i / v,v,m,i -def : InstRW<[ZnWriteFPU013Ld], (instregex "(V?)PBLENDWrmi")>; -// y,m,i -def : InstRW<[ZnWriteFPU013LdY], (instrs VPBLENDWYrmi)>; - -def ZnWriteFPU01 : SchedWriteRes<[ZnFPU01]> ; -def ZnWriteFPU01Y : SchedWriteRes<[ZnFPU01]> { - let NumMicroOps = 2; -} - -// VPBLENDD. -// v,v,v,i. -def : InstRW<[ZnWriteFPU01], (instrs VPBLENDDrri)>; -// ymm -def : InstRW<[ZnWriteFPU01Y], (instrs VPBLENDDYrri)>; - -// v,v,m,i -def ZnWriteFPU01Op2 : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let NumMicroOps = 2; - let Latency = 8; - let ResourceCycles = [1, 2]; -} -def ZnWriteFPU01Op2Y : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let NumMicroOps = 2; - let Latency = 9; - let ResourceCycles = [1, 3]; -} -def : InstRW<[ZnWriteFPU01Op2], (instrs VPBLENDDrmi)>; -def : InstRW<[ZnWriteFPU01Op2Y], (instrs VPBLENDDYrmi)>; - -// MASKMOVQ. -def : InstRW<[WriteMicrocoded], (instregex "MMX_MASKMOVQ(64)?")>; - -// MASKMOVDQU. -def : InstRW<[WriteMicrocoded], (instregex "(V?)MASKMOVDQU(64)?")>; - -// VPMASKMOVD. -// ymm -def : InstRW<[WriteMicrocoded], - (instregex "VPMASKMOVD(Y?)rm")>; -// m, v,v. -def : InstRW<[WriteMicrocoded], (instregex "VPMASKMOV(D|Q)(Y?)mr")>; - -// VPBROADCAST B/W. -// x, m8/16. -def ZnWriteVPBROADCAST128Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteVPBROADCAST128Ld], - (instregex "VPBROADCAST(B|W)rm")>; - -// y, m8/16 -def ZnWriteVPBROADCAST256Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteVPBROADCAST256Ld], - (instregex "VPBROADCAST(B|W)Yrm")>; - -// VPGATHER. -def : InstRW<[WriteMicrocoded], (instregex "VPGATHER(Q|D)(Q|D)(Y?)rm")>; - -//-- Arithmetic instructions --// - -// HADD, HSUB PS/PD -// PHADD|PHSUB (S) W/D. -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -// PCMPGTQ. -def ZnWritePCMPGTQr : SchedWriteRes<[ZnFPU03]>; -def : InstRW<[ZnWritePCMPGTQr], (instregex "(V?)PCMPGTQ(Y?)rr")>; - -// x <- x,m. -def ZnWritePCMPGTQm : SchedWriteRes<[ZnAGU, ZnFPU03]> { - let Latency = 8; -} -// ymm. -def ZnWritePCMPGTQYm : SchedWriteRes<[ZnAGU, ZnFPU03]> { - let Latency = 8; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; -} -def : InstRW<[ZnWritePCMPGTQm], (instregex "(V?)PCMPGTQrm")>; -def : InstRW<[ZnWritePCMPGTQYm], (instrs VPCMPGTQYrm)>; - -//-- Logic instructions --// - -// PSLL,PSRL,PSRA W/D/Q. -// x,x / v,v,x. -def ZnWritePShift : SchedWriteRes<[ZnFPU2]> ; -def ZnWritePShiftY : SchedWriteRes<[ZnFPU2]> { - let Latency = 2; -} - -// PSLL,PSRL DQ. -def : InstRW<[ZnWritePShift], (instregex "(V?)PS(R|L)LDQri")>; -def : InstRW<[ZnWritePShiftY], (instregex "(V?)PS(R|L)LDQYri")>; - -//=== Floating Point XMM and YMM Instructions ===// -//-- Move instructions --// - -// VPERM2F128. -def : InstRW<[WriteMicrocoded], (instrs VPERM2F128rr)>; -def : InstRW<[WriteMicrocoded], (instrs VPERM2F128rm)>; - -def ZnWriteBROADCAST : SchedWriteRes<[ZnAGU, ZnFPU13]> { - let NumMicroOps = 2; - let Latency = 8; -} -// VBROADCASTF128. -def : InstRW<[ZnWriteBROADCAST], (instrs VBROADCASTF128)>; - -// EXTRACTPS. -// r32,x,i. -def ZnWriteEXTRACTPSr : SchedWriteRes<[ZnFPU12, ZnFPU2]> { - let Latency = 2; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : InstRW<[ZnWriteEXTRACTPSr], (instregex "(V?)EXTRACTPSrr")>; - -def ZnWriteEXTRACTPSm : SchedWriteRes<[ZnAGU,ZnFPU12, ZnFPU2]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [5, 1, 2]; -} -// m32,x,i. -def : InstRW<[ZnWriteEXTRACTPSm], (instregex "(V?)EXTRACTPSmr")>; - -// VEXTRACTF128. -// x,y,i. -def : InstRW<[ZnWriteFPU013], (instrs VEXTRACTF128rr)>; - -// m128,y,i. -def : InstRW<[ZnWriteFPU013m], (instrs VEXTRACTF128mr)>; - -def ZnWriteVINSERT128r: SchedWriteRes<[ZnFPU013]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def ZnWriteVINSERT128Ld: SchedWriteRes<[ZnAGU,ZnFPU013]> { - let Latency = 9; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -// VINSERTF128. -// y,y,x,i. -def : InstRW<[ZnWriteVINSERT128r], (instrs VINSERTF128rr)>; -def : InstRW<[ZnWriteVINSERT128Ld], (instrs VINSERTF128rm)>; - -// VGATHER. -def : InstRW<[WriteMicrocoded], (instregex "VGATHER(Q|D)(PD|PS)(Y?)rm")>; - -//-- Conversion instructions --// -def ZnWriteCVTPD2PSr: SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -def ZnWriteCVTPD2PSYr: SchedWriteRes<[ZnFPU3]> { - let Latency = 5; -} - -// CVTPD2PS. -// x,x. -def : SchedAlias; -// y,y. -def : SchedAlias; -// z,z. -defm : X86WriteResUnsupported; - -def ZnWriteCVTPD2PSLd: SchedWriteRes<[ZnAGU,ZnFPU03]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; -} -// x,m128. -def : SchedAlias; - -// x,m256. -def ZnWriteCVTPD2PSYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; -} -def : SchedAlias; -// z,m512 -defm : X86WriteResUnsupported; - -// CVTSD2SS. -// x,x. -// Same as WriteCVTPD2PSr -def : SchedAlias; - -// x,m64. -def : SchedAlias; - -// CVTPS2PD. -// x,x. -def ZnWriteCVTPS2PDr : SchedWriteRes<[ZnFPU3]> { - let Latency = 3; -} -def : SchedAlias; - -// x,m64. -// y,m128. -def ZnWriteCVTPS2PDLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 10; - let NumMicroOps = 2; -} -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -// y,x. -def ZnWriteVCVTPS2PDY : SchedWriteRes<[ZnFPU3]> { - let Latency = 3; -} -def : SchedAlias; -defm : X86WriteResUnsupported; - -// CVTSS2SD. -// x,x. -def ZnWriteCVTSS2SDr : SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -def : SchedAlias; - -// x,m32. -def ZnWriteCVTSS2SDLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 11; - let NumMicroOps = 2; - let ResourceCycles = [1, 2]; -} -def : SchedAlias; - -def ZnWriteCVTDQ2PDr: SchedWriteRes<[ZnFPU12,ZnFPU3]> { - let Latency = 5; -} -// CVTDQ2PD. -// x,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instregex "(V)?CVTDQ2PDrr")>; - -// Same as xmm -// y,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instrs VCVTDQ2PDYrr)>; - -def ZnWriteCVTPD2DQr: SchedWriteRes<[ZnFPU12, ZnFPU3]> { - let Latency = 5; -} -// CVT(T)PD2DQ. -// x,x. -def : InstRW<[ZnWriteCVTDQ2PDr], (instregex "(V?)CVT(T?)PD2DQrr")>; - -def ZnWriteCVTPD2DQLd: SchedWriteRes<[ZnAGU,ZnFPU12,ZnFPU3]> { - let Latency = 12; - let NumMicroOps = 2; -} -// x,m128. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "(V?)CVT(T?)PD2DQrm")>; -// same as xmm handling -// x,y. -def : InstRW<[ZnWriteCVTPD2DQr], (instregex "VCVT(T?)PD2DQYrr")>; -// x,m256. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "VCVT(T?)PD2DQYrm")>; - -def ZnWriteCVTPS2PIr: SchedWriteRes<[ZnFPU3]> { - let Latency = 4; -} -// CVT(T)PS2PI. -// mm,x. -def : InstRW<[ZnWriteCVTPS2PIr], (instregex "MMX_CVT(T?)PS2PIirr")>; - -// CVTPI2PD. -// x,mm. -def : InstRW<[ZnWriteCVTPS2PDr], (instrs MMX_CVTPI2PDirr)>; - -// CVT(T)PD2PI. -// mm,x. -def : InstRW<[ZnWriteCVTPS2PIr], (instregex "MMX_CVT(T?)PD2PIirr")>; - -def ZnWriteCVSTSI2SSr: SchedWriteRes<[ZnFPU3]> { - let Latency = 5; -} - -// same as CVTPD2DQr -// CVT(T)SS2SI. -// r32,x. -def : InstRW<[ZnWriteCVTPD2DQr], (instregex "(V?)CVT(T?)SS2SI(64)?rr")>; -// same as CVTPD2DQm -// r32,m32. -def : InstRW<[ZnWriteCVTPD2DQLd], (instregex "(V?)CVT(T?)SS2SI(64)?rm")>; - -def ZnWriteCVSTSI2SDr: SchedWriteRes<[ZnFPU013, ZnFPU3]> { - let Latency = 5; -} -// CVTSI2SD. -// x,r32/64. -def : InstRW<[ZnWriteCVSTSI2SDr], (instregex "(V?)CVTSI(64)?2SDrr")>; - - -def ZnWriteCVSTSI2SIr: SchedWriteRes<[ZnFPU3, ZnFPU2]> { - let Latency = 5; -} -def ZnWriteCVSTSI2SILd: SchedWriteRes<[ZnAGU, ZnFPU3, ZnFPU2]> { - let Latency = 12; -} -// CVTSD2SI. -// r32/64 -def : InstRW<[ZnWriteCVSTSI2SIr], (instregex "(V?)CVT(T?)SD2SI(64)?rr")>; -// r32,m32. -def : InstRW<[ZnWriteCVSTSI2SILd], (instregex "(V?)CVT(T?)SD2SI(64)?rm")>; - -// VCVTPS2PH. -// x,v,i. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; -// m,v,i. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -// VCVTPH2PS. -// v,x. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; -// v,m. -def : SchedAlias; -def : SchedAlias; -defm : X86WriteResUnsupported; - -//-- SSE4A instructions --// -// EXTRQ -def ZnWriteEXTRQ: SchedWriteRes<[ZnFPU12, ZnFPU2]> { - let Latency = 2; -} -def : InstRW<[ZnWriteEXTRQ], (instregex "EXTRQ")>; - -// INSERTQ -def ZnWriteINSERTQ: SchedWriteRes<[ZnFPU03,ZnFPU1]> { - let Latency = 4; -} -def : InstRW<[ZnWriteINSERTQ], (instregex "INSERTQ")>; - -//-- SHA instructions --// -// SHA256MSG2 -def : InstRW<[WriteMicrocoded], (instregex "SHA256MSG2(Y?)r(r|m)")>; - -// SHA1MSG1, SHA256MSG1 -// x,x. -def ZnWriteSHA1MSG1r : SchedWriteRes<[ZnFPU12]> { - let Latency = 2; - let ResourceCycles = [2]; -} -def : InstRW<[ZnWriteSHA1MSG1r], (instregex "SHA(1|256)MSG1rr")>; -// x,m. -def ZnWriteSHA1MSG1Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 9; - let ResourceCycles = [1,2]; -} -def : InstRW<[ZnWriteSHA1MSG1Ld], (instregex "SHA(1|256)MSG1rm")>; - -// SHA1MSG2 -// x,x. -def ZnWriteSHA1MSG2r : SchedWriteRes<[ZnFPU12]> ; -def : InstRW<[ZnWriteSHA1MSG2r], (instregex "SHA1MSG2rr")>; -// x,m. -def ZnWriteSHA1MSG2Ld : SchedWriteRes<[ZnAGU, ZnFPU12]> { - let Latency = 8; -} -def : InstRW<[ZnWriteSHA1MSG2Ld], (instregex "SHA1MSG2rm")>; - -// SHA1NEXTE -// x,x. -def ZnWriteSHA1NEXTEr : SchedWriteRes<[ZnFPU1]> ; -def : InstRW<[ZnWriteSHA1NEXTEr], (instregex "SHA1NEXTErr")>; -// x,m. -def ZnWriteSHA1NEXTELd : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 8; -} -def : InstRW<[ZnWriteSHA1NEXTELd], (instregex "SHA1NEXTErm")>; - -// SHA1RNDS4 -// x,x. -def ZnWriteSHA1RNDS4r : SchedWriteRes<[ZnFPU1]> { - let Latency = 6; -} -def : InstRW<[ZnWriteSHA1RNDS4r], (instregex "SHA1RNDS4rr")>; -// x,m. -def ZnWriteSHA1RNDS4Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 13; -} -def : InstRW<[ZnWriteSHA1RNDS4Ld], (instregex "SHA1RNDS4rm")>; - -// SHA256RNDS2 -// x,x. -def ZnWriteSHA256RNDS2r : SchedWriteRes<[ZnFPU1]> { - let Latency = 4; -} -def : InstRW<[ZnWriteSHA256RNDS2r], (instregex "SHA256RNDS2rr")>; -// x,m. -def ZnWriteSHA256RNDS2Ld : SchedWriteRes<[ZnAGU, ZnFPU1]> { - let Latency = 11; -} -def : InstRW<[ZnWriteSHA256RNDS2Ld], (instregex "SHA256RNDS2rm")>; - -//-- Arithmetic instructions --// - -// HADD, HSUB PS/PD -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; -def : SchedAlias; - -// VDIVPS. -// TODO - convert to ZnWriteResFpuPair -// y,y,y. -def ZnWriteVDIVPSYr : SchedWriteRes<[ZnFPU3]> { - let Latency = 12; - let ResourceCycles = [12]; -} -def : SchedAlias; - -// y,y,m256. -def ZnWriteVDIVPSYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 19; - let NumMicroOps = 2; - let ResourceCycles = [1, 19]; -} -def : SchedAlias; - -// VDIVPD. -// TODO - convert to ZnWriteResFpuPair -// y,y,y. -def ZnWriteVDIVPDY : SchedWriteRes<[ZnFPU3]> { - let Latency = 15; - let ResourceCycles = [15]; -} -def : SchedAlias; - -// y,y,m256. -def ZnWriteVDIVPDYLd : SchedWriteRes<[ZnAGU, ZnFPU3]> { - let Latency = 22; - let NumMicroOps = 2; - let ResourceCycles = [1,22]; -} -def : SchedAlias; - -// DPPS. -// x,x,i / v,v,v,i. -def : SchedAlias; -def : SchedAlias; - -// x,m,i / v,v,m,i. -def : SchedAlias; -def : SchedAlias; - -// DPPD. -// x,x,i. -def : SchedAlias; - -// x,m,i. -def : SchedAlias; - -// RSQRTSS -// TODO - convert to ZnWriteResFpuPair -// x,x. -def ZnWriteRSQRTSSr : SchedWriteRes<[ZnFPU02]> { - let Latency = 5; -} -def : SchedAlias; - -// x,m128. -def ZnWriteRSQRTSSLd: SchedWriteRes<[ZnAGU, ZnFPU02]> { - let Latency = 12; - let NumMicroOps = 2; - let ResourceCycles = [1,2]; // FIXME: Is this right? -} -def : SchedAlias; - -// RSQRTPS -// TODO - convert to ZnWriteResFpuPair -// y,y. -def ZnWriteRSQRTPSYr : SchedWriteRes<[ZnFPU01]> { - let Latency = 5; - let NumMicroOps = 2; - let ResourceCycles = [2]; -} -def : SchedAlias; - -// y,m256. -def ZnWriteRSQRTPSYLd : SchedWriteRes<[ZnAGU, ZnFPU01]> { - let Latency = 12; - let NumMicroOps = 2; -} -def : SchedAlias; - -//-- Other instructions --// - -// VZEROUPPER. -def : InstRW<[WriteMicrocoded], (instrs VZEROUPPER)>; - -// VZEROALL. -def : InstRW<[WriteMicrocoded], (instrs VZEROALL)>; - -} // SchedModel diff --git a/suite/synctools/tablegen/X86/back/X86_reduce.td b/suite/synctools/tablegen/X86/back/X86_reduce.td deleted file mode 100644 index cf2ce68908..0000000000 --- a/suite/synctools/tablegen/X86/back/X86_reduce.td +++ /dev/null @@ -1,459 +0,0 @@ -//===-- X86.td - Target definition file for the Intel X86 --*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a target description file for the Intel i386 architecture, referred -// to here as the "X86" architecture. -// -//===----------------------------------------------------------------------===// - -// Get the target-independent interfaces which we are implementing... -// -include "llvm/Target/Target.td" - -//===----------------------------------------------------------------------===// -// X86 Subtarget state -// - -def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", - "64-bit mode (x86_64)">; -def Mode32Bit : SubtargetFeature<"32bit-mode", "In32BitMode", "true", - "32-bit mode (80386)">; -def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true", - "16-bit mode (i8086)">; - -//===----------------------------------------------------------------------===// -// X86 Subtarget features -//===----------------------------------------------------------------------===// - -def FeatureX87 : SubtargetFeature<"x87","HasX87", "true", - "Enable X87 float instructions">; - -def FeatureNOPL : SubtargetFeature<"nopl", "HasNOPL", "true", - "Enable NOPL instruction">; - -def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", - "Enable conditional move instructions">; - -def FeaturePOPCNT : SubtargetFeature<"popcnt", "HasPOPCNT", "true", - "Support POPCNT instruction">; - -def FeatureFXSR : SubtargetFeature<"fxsr", "HasFXSR", "true", - "Support fxsave/fxrestore instructions">; - -def FeatureXSAVE : SubtargetFeature<"xsave", "HasXSAVE", "true", - "Support xsave instructions">; - -def FeatureXSAVEOPT: SubtargetFeature<"xsaveopt", "HasXSAVEOPT", "true", - "Support xsaveopt instructions">; - -def FeatureXSAVEC : SubtargetFeature<"xsavec", "HasXSAVEC", "true", - "Support xsavec instructions">; - -def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true", - "Support xsaves instructions">; - -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions", - // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. - [FeatureCMOV]>; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions", - [FeatureSSE1]>; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions", - [FeatureSSE2]>; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions", - [FeatureSSE3]>; -def FeatureSSE41 : SubtargetFeature<"sse4.1", "X86SSELevel", "SSE41", - "Enable SSE 4.1 instructions", - [FeatureSSSE3]>; -def FeatureSSE42 : SubtargetFeature<"sse4.2", "X86SSELevel", "SSE42", - "Enable SSE 4.2 instructions", - [FeatureSSE41]>; -// The MMX subtarget feature is separate from the rest of the SSE features -// because it's important (for odd compatibility reasons) to be able to -// turn it off explicitly while allowing SSE+ to be on. -def FeatureMMX : SubtargetFeature<"mmx","X863DNowLevel", "MMX", - "Enable MMX instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions", - [FeatureMMX]>; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions", - [Feature3DNow]>; -// All x86-64 hardware has SSE2, but we don't mark SSE2 as an implied -// feature, because SSE2 can be disabled (e.g. for compiling OS kernels) -// without disabling 64-bit mode. -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions", - [FeatureCMOV]>; -def FeatureCMPXCHG16B : SubtargetFeature<"cx16", "HasCmpxchg16b", "true", - "64-bit with cmpxchg16b", - [Feature64Bit]>; -def FeatureSlowSHLD : SubtargetFeature<"slow-shld", "IsSHLDSlow", "true", - "SHLD instruction is slow">; -def FeatureSlowPMULLD : SubtargetFeature<"slow-pmulld", "IsPMULLDSlow", "true", - "PMULLD instruction is slow">; -// FIXME: This should not apply to CPUs that do not have SSE. -def FeatureSlowUAMem16 : SubtargetFeature<"slow-unaligned-mem-16", - "IsUAMem16Slow", "true", - "Slow unaligned 16-byte memory access">; -def FeatureSlowUAMem32 : SubtargetFeature<"slow-unaligned-mem-32", - "IsUAMem32Slow", "true", - "Slow unaligned 32-byte memory access">; -def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true", - "Support SSE 4a instructions", - [FeatureSSE3]>; - -def FeatureAVX : SubtargetFeature<"avx", "X86SSELevel", "AVX", - "Enable AVX instructions", - [FeatureSSE42]>; -def FeatureAVX2 : SubtargetFeature<"avx2", "X86SSELevel", "AVX2", - "Enable AVX2 instructions", - [FeatureAVX]>; -def FeatureFMA : SubtargetFeature<"fma", "HasFMA", "true", - "Enable three-operand fused multiple-add", - [FeatureAVX]>; -def FeatureF16C : SubtargetFeature<"f16c", "HasF16C", "true", - "Support 16-bit floating point conversion instructions", - [FeatureAVX]>; -def FeatureAVX512 : SubtargetFeature<"avx512f", "X86SSELevel", "AVX512F", - "Enable AVX-512 instructions", - [FeatureAVX2, FeatureFMA, FeatureF16C]>; -def FeatureERI : SubtargetFeature<"avx512er", "HasERI", "true", - "Enable AVX-512 Exponential and Reciprocal Instructions", - [FeatureAVX512]>; -def FeatureCDI : SubtargetFeature<"avx512cd", "HasCDI", "true", - "Enable AVX-512 Conflict Detection Instructions", - [FeatureAVX512]>; -def FeatureVPOPCNTDQ : SubtargetFeature<"avx512vpopcntdq", "HasVPOPCNTDQ", - "true", "Enable AVX-512 Population Count Instructions", - [FeatureAVX512]>; -def FeaturePFI : SubtargetFeature<"avx512pf", "HasPFI", "true", - "Enable AVX-512 PreFetch Instructions", - [FeatureAVX512]>; -def FeaturePREFETCHWT1 : SubtargetFeature<"prefetchwt1", "HasPREFETCHWT1", - "true", - "Prefetch with Intent to Write and T1 Hint">; -def FeatureDQI : SubtargetFeature<"avx512dq", "HasDQI", "true", - "Enable AVX-512 Doubleword and Quadword Instructions", - [FeatureAVX512]>; -def FeatureBWI : SubtargetFeature<"avx512bw", "HasBWI", "true", - "Enable AVX-512 Byte and Word Instructions", - [FeatureAVX512]>; -def FeatureVLX : SubtargetFeature<"avx512vl", "HasVLX", "true", - "Enable AVX-512 Vector Length eXtensions", - [FeatureAVX512]>; -def FeatureVBMI : SubtargetFeature<"avx512vbmi", "HasVBMI", "true", - "Enable AVX-512 Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureVBMI2 : SubtargetFeature<"avx512vbmi2", "HasVBMI2", "true", - "Enable AVX-512 further Vector Byte Manipulation Instructions", - [FeatureBWI]>; -def FeatureIFMA : SubtargetFeature<"avx512ifma", "HasIFMA", "true", - "Enable AVX-512 Integer Fused Multiple-Add", - [FeatureAVX512]>; -def FeaturePKU : SubtargetFeature<"pku", "HasPKU", "true", - "Enable protection keys">; -def FeatureVNNI : SubtargetFeature<"avx512vnni", "HasVNNI", "true", - "Enable AVX-512 Vector Neural Network Instructions", - [FeatureAVX512]>; -def FeatureBITALG : SubtargetFeature<"avx512bitalg", "HasBITALG", "true", - "Enable AVX-512 Bit Algorithms", - [FeatureBWI]>; -def FeaturePCLMUL : SubtargetFeature<"pclmul", "HasPCLMUL", "true", - "Enable packed carry-less multiplication instructions", - [FeatureSSE2]>; -def FeatureGFNI : SubtargetFeature<"gfni", "HasGFNI", "true", - "Enable Galois Field Arithmetic Instructions", - [FeatureSSE2]>; -def FeatureVPCLMULQDQ : SubtargetFeature<"vpclmulqdq", "HasVPCLMULQDQ", "true", - "Enable vpclmulqdq instructions", - [FeatureAVX, FeaturePCLMUL]>; -def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", - "Enable four-operand fused multiple-add", - [FeatureAVX, FeatureSSE4A]>; -def FeatureXOP : SubtargetFeature<"xop", "HasXOP", "true", - "Enable XOP instructions", - [FeatureFMA4]>; -def FeatureSSEUnalignedMem : SubtargetFeature<"sse-unaligned-mem", - "HasSSEUnalignedMem", "true", - "Allow unaligned memory operands with SSE instructions">; -def FeatureAES : SubtargetFeature<"aes", "HasAES", "true", - "Enable AES instructions", - [FeatureSSE2]>; -def FeatureVAES : SubtargetFeature<"vaes", "HasVAES", "true", - "Promote selected AES instructions to AVX512/AVX registers", - [FeatureAVX, FeatureAES]>; -def FeatureTBM : SubtargetFeature<"tbm", "HasTBM", "true", - "Enable TBM instructions">; -def FeatureLWP : SubtargetFeature<"lwp", "HasLWP", "true", - "Enable LWP instructions">; -def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true", - "Support MOVBE instruction">; -def FeatureRDRAND : SubtargetFeature<"rdrnd", "HasRDRAND", "true", - "Support RDRAND instruction">; -def FeatureFSGSBase : SubtargetFeature<"fsgsbase", "HasFSGSBase", "true", - "Support FS/GS Base instructions">; -def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true", - "Support LZCNT instruction">; -def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true", - "Support BMI instructions">; -def FeatureBMI2 : SubtargetFeature<"bmi2", "HasBMI2", "true", - "Support BMI2 instructions">; -def FeatureRTM : SubtargetFeature<"rtm", "HasRTM", "true", - "Support RTM instructions">; -def FeatureADX : SubtargetFeature<"adx", "HasADX", "true", - "Support ADX instructions">; -def FeatureSHA : SubtargetFeature<"sha", "HasSHA", "true", - "Enable SHA instructions", - [FeatureSSE2]>; -def FeatureSHSTK : SubtargetFeature<"shstk", "HasSHSTK", "true", - "Support CET Shadow-Stack instructions">; -def FeaturePRFCHW : SubtargetFeature<"prfchw", "HasPRFCHW", "true", - "Support PRFCHW instructions">; -def FeatureRDSEED : SubtargetFeature<"rdseed", "HasRDSEED", "true", - "Support RDSEED instruction">; -def FeatureLAHFSAHF : SubtargetFeature<"sahf", "HasLAHFSAHF", "true", - "Support LAHF and SAHF instructions">; -def FeatureMWAITX : SubtargetFeature<"mwaitx", "HasMWAITX", "true", - "Enable MONITORX/MWAITX timer functionality">; -def FeatureCLZERO : SubtargetFeature<"clzero", "HasCLZERO", "true", - "Enable Cache Line Zero">; -def FeatureCLDEMOTE : SubtargetFeature<"cldemote", "HasCLDEMOTE", "true", - "Enable Cache Demote">; -def FeaturePTWRITE : SubtargetFeature<"ptwrite", "HasPTWRITE", "true", - "Support ptwrite instruction">; -def FeatureMPX : SubtargetFeature<"mpx", "HasMPX", "true", - "Support MPX instructions">; -def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true", - "Use LEA for adjusting the stack pointer">; -def FeatureSlowDivide32 : SubtargetFeature<"idivl-to-divb", - "HasSlowDivide32", "true", - "Use 8-bit divide for positive values less than 256">; -def FeatureSlowDivide64 : SubtargetFeature<"idivq-to-divl", - "HasSlowDivide64", "true", - "Use 32-bit divide for positive values less than 2^32">; -def FeaturePadShortFunctions : SubtargetFeature<"pad-short-functions", - "PadShortFunctions", "true", - "Pad short functions">; -def FeatureINVPCID : SubtargetFeature<"invpcid", "HasINVPCID", "true", - "Invalidate Process-Context Identifier">; -def FeatureSGX : SubtargetFeature<"sgx", "HasSGX", "true", - "Enable Software Guard Extensions">; -def FeatureCLFLUSHOPT : SubtargetFeature<"clflushopt", "HasCLFLUSHOPT", "true", - "Flush A Cache Line Optimized">; -def FeatureCLWB : SubtargetFeature<"clwb", "HasCLWB", "true", - "Cache Line Write Back">; -def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", - "Write Back No Invalidate">; -def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", - "Support RDPID instructions">; -def FeatureWAITPKG : SubtargetFeature<"waitpkg", "HasWAITPKG", "true", - "Wait and pause enhancements">; -// On some processors, instructions that implicitly take two memory operands are -// slow. In practice, this means that CALL, PUSH, and POP with memory operands -// should be avoided in favor of a MOV + register CALL/PUSH/POP. -def FeatureSlowTwoMemOps : SubtargetFeature<"slow-two-mem-ops", - "SlowTwoMemOps", "true", - "Two memory operand instructions are slow">; -def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true", - "LEA instruction needs inputs at AG stage">; -def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true", - "LEA instruction with certain arguments is slow">; -def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true", - "LEA instruction with 3 ops or certain registers is slow">; -def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true", - "INC and DEC instructions are slower than ADD and SUB">; -def FeatureSoftFloat - : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software floating point features.">; -def FeaturePOPCNTFalseDeps : SubtargetFeature<"false-deps-popcnt", - "HasPOPCNTFalseDeps", "true", - "POPCNT has a false dependency on dest register">; -def FeatureLZCNTFalseDeps : SubtargetFeature<"false-deps-lzcnt-tzcnt", - "HasLZCNTFalseDeps", "true", - "LZCNT/TZCNT have a false dependency on dest register">; -def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true", - "platform configuration instruction">; -// On recent X86 (port bound) processors, its preferable to combine to a single shuffle -// using a variable mask over multiple fixed shuffles. -def FeatureFastVariableShuffle - : SubtargetFeature<"fast-variable-shuffle", - "HasFastVariableShuffle", - "true", "Shuffles with variable masks are fast">; -// On some X86 processors, there is no performance hazard to writing only the -// lower parts of a YMM or ZMM register without clearing the upper part. -def FeatureFastPartialYMMorZMMWrite - : SubtargetFeature<"fast-partial-ymm-or-zmm-write", - "HasFastPartialYMMorZMMWrite", - "true", "Partial writes to YMM/ZMM registers are fast">; -// FeatureFastScalarFSQRT should be enabled if scalar FSQRT has shorter latency -// than the corresponding NR code. FeatureFastVectorFSQRT should be enabled if -// vector FSQRT has higher throughput than the corresponding NR code. -// The idea is that throughput bound code is likely to be vectorized, so for -// vectorized code we should care about the throughput of SQRT operations. -// But if the code is scalar that probably means that the code has some kind of -// dependency and we should care more about reducing the latency. -def FeatureFastScalarFSQRT - : SubtargetFeature<"fast-scalar-fsqrt", "HasFastScalarFSQRT", - "true", "Scalar SQRT is fast (disable Newton-Raphson)">; -def FeatureFastVectorFSQRT - : SubtargetFeature<"fast-vector-fsqrt", "HasFastVectorFSQRT", - "true", "Vector SQRT is fast (disable Newton-Raphson)">; -// If lzcnt has equivalent latency/throughput to most simple integer ops, it can -// be used to replace test/set sequences. -def FeatureFastLZCNT - : SubtargetFeature< - "fast-lzcnt", "HasFastLZCNT", "true", - "LZCNT instructions are as fast as most simple integer ops">; -// If the target can efficiently decode NOPs upto 11-bytes in length. -def FeatureFast11ByteNOP - : SubtargetFeature< - "fast-11bytenop", "HasFast11ByteNOP", "true", - "Target can quickly decode up to 11 byte NOPs">; -// If the target can efficiently decode NOPs upto 15-bytes in length. -def FeatureFast15ByteNOP - : SubtargetFeature< - "fast-15bytenop", "HasFast15ByteNOP", "true", - "Target can quickly decode up to 15 byte NOPs">; -// Sandy Bridge and newer processors can use SHLD with the same source on both -// inputs to implement rotate to avoid the partial flag update of the normal -// rotate instructions. -def FeatureFastSHLDRotate - : SubtargetFeature< - "fast-shld-rotate", "HasFastSHLDRotate", "true", - "SHLD can be used as a faster rotate">; - -// Ivy Bridge and newer processors have enhanced REP MOVSB and STOSB (aka -// "string operations"). See "REP String Enhancement" in the Intel Software -// Development Manual. This feature essentially means that REP MOVSB will copy -// using the largest available size instead of copying bytes one by one, making -// it at least as fast as REPMOVS{W,D,Q}. -def FeatureERMSB - : SubtargetFeature< - "ermsb", "HasERMSB", "true", - "REP MOVS/STOS are fast">; - -// Sandy Bridge and newer processors have many instructions that can be -// fused with conditional branches and pass through the CPU as a single -// operation. -def FeatureMacroFusion - : SubtargetFeature<"macrofusion", "HasMacroFusion", "true", - "Various instructions can be fused with conditional branches">; - -// Gather is available since Haswell (AVX2 set). So technically, we can -// generate Gathers on all AVX2 processors. But the overhead on HSW is high. -// Skylake Client processor has faster Gathers than HSW and performance is -// similar to Skylake Server (AVX-512). -def FeatureHasFastGather - : SubtargetFeature<"fast-gather", "HasFastGather", "true", - "Indicates if gather is reasonably fast.">; - -def FeaturePrefer256Bit - : SubtargetFeature<"prefer-256-bit", "Prefer256Bit", "true", - "Prefer 256-bit AVX instructions">; - -// Enable mitigation of some aspects of speculative execution related -// vulnerabilities by removing speculatable indirect branches. This disables -// jump-table formation, rewrites explicit `indirectbr` instructions into -// `switch` instructions, and uses a special construct called a "retpoline" to -// prevent speculation of the remaining indirect branches (indirect calls and -// tail calls). -def FeatureRetpoline - : SubtargetFeature<"retpoline", "UseRetpoline", "true", - "Remove speculation of indirect branches from the " - "generated code, either by avoiding them entirely or " - "lowering them with a speculation blocking construct.">; - -// Rely on external thunks for the emitted retpoline calls. This allows users -// to provide their own custom thunk definitions in highly specialized -// environments such as a kernel that does boot-time hot patching. -def FeatureRetpolineExternalThunk - : SubtargetFeature< - "retpoline-external-thunk", "UseRetpolineExternalThunk", "true", - "Enable retpoline, but with an externally provided thunk.", - [FeatureRetpoline]>; - -// Direct Move instructions. -def FeatureMOVDIRI : SubtargetFeature<"movdiri", "HasMOVDIRI", "true", - "Support movdiri instruction">; -def FeatureMOVDIR64B : SubtargetFeature<"movdir64b", "HasMOVDIR64B", "true", - "Support movdir64b instruction">; - -//===----------------------------------------------------------------------===// -// Register File Description -//===----------------------------------------------------------------------===// - -include "X86RegisterInfo.td" -include "X86RegisterBanks.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "X86Schedule.td" -include "X86InstrInfo_reduce.td" - -def X86InstrInfo : InstrInfo; - -//===----------------------------------------------------------------------===// -// Assembly Parser -//===----------------------------------------------------------------------===// - -def ATTAsmParserVariant : AsmParserVariant { - int Variant = 0; - - // Variant name. - string Name = "att"; - - // Discard comments in assembly strings. - string CommentDelimiter = "#"; - - // Recognize hard coded registers. - string RegisterPrefix = "%"; -} - -def IntelAsmParserVariant : AsmParserVariant { - int Variant = 1; - - // Variant name. - string Name = "intel"; - - // Discard comments in assembly strings. - string CommentDelimiter = ";"; - - // Recognize hard coded registers. - string RegisterPrefix = ""; -} - -//===----------------------------------------------------------------------===// -// Assembly Printers -//===----------------------------------------------------------------------===// - -// The X86 target supports two different syntaxes for emitting machine code. -// This is controlled by the -x86-asm-syntax={att|intel} -def ATTAsmWriter : AsmWriter { - string AsmWriterClassName = "ATTInstPrinter"; - int Variant = 0; -} -def IntelAsmWriter : AsmWriter { - string AsmWriterClassName = "IntelInstPrinter"; - int Variant = 1; -} - -def X86 : Target { - // Information about the instructions... - let InstructionSet = X86InstrInfo; - let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant]; - let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; - let AllowRegisterRenaming = 1; -} diff --git a/suite/synctools/tablegen/gen-tablegen-arch.sh b/suite/synctools/tablegen/gen-tablegen-arch.sh deleted file mode 100755 index a2a9559657..0000000000 --- a/suite/synctools/tablegen/gen-tablegen-arch.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# Generate raw .inc files for non-x86 architectures of Capstone, by Nguyen Anh Quynh - -# Syntax: gen-tablegen-arch.sh - -# Example: ./gen-tablegen-arch.sh ~/projects/llvm/7.0.1/build/bin ARM - -TBLGEN_PATH=$1 -DIR_TD=$2 -ARCH=$2 - -echo "Using llvm-tblgen from ${TBLGEN_PATH}" - -echo "Generating ${ARCH}GenInstrInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-instr-info -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenInstrInfo.inc - -echo "Generating ${ARCH}GenRegisterInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-register-info -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenRegisterInfo.inc - -echo "Generating ${ARCH}GenAsmMatcher.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-matcher -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenAsmMatcher.inc - -echo "Generating ${ARCH}GenDisassemblerTables.inc" -$TBLGEN_PATH/llvm-tblgen -gen-disassembler -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenDisassemblerTables.inc - -echo "Generating ${ARCH}GenAsmWriter.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenAsmWriter.inc - -echo "Generating ${ARCH}GenSubtargetInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-subtarget -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenSubtargetInfo.inc - -case $2 in - ARM) - # for ARM only - echo "Generating ${ARCH}GenAsmWriter-digit.inc" - $TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}-digit.td -o ${ARCH}GenAsmWriter-digit.inc - echo "Generating ${ARCH}GenSystemRegister.inc" - $TBLGEN_PATH/llvm-tblgen -gen-searchable-tables -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenSystemRegister.inc - ;; - AArch64) - echo "Generating ${ARCH}GenSystemOperands.inc" - $TBLGEN_PATH/llvm-tblgen -gen-searchable-tables -I include -I ${DIR_TD} ${DIR_TD}/${ARCH}.td -o ${ARCH}GenSystemOperands.inc - ;; -esac - diff --git a/suite/synctools/tablegen/gen-tablegen-full.sh b/suite/synctools/tablegen/gen-tablegen-full.sh deleted file mode 100755 index deebe2fc31..0000000000 --- a/suite/synctools/tablegen/gen-tablegen-full.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Generate raw X86*.inc files for Capstone, by Nguyen Anh Quynh - -# Syntax: gen-tablegen-full.sh - -# Example: ./gen-tablegen-full.sh ~/projects/llvm/7.0.1/build/bin X86 - -#TBLGEN_PATH=~/projects/llvm/7.0.1/build/bin -TBLGEN_PATH=$1 -#DIR_TD="X86" -DIR_TD=$2 - -echo "Using llvm-tblgen from ${TBLGEN_PATH}" - -echo "Generating X86GenInstrInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-instr-info -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenInstrInfo.inc - -echo "Generating X86GenRegisterInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-register-info -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenRegisterInfo.inc - -echo "Generating X86GenAsmMatcher.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-matcher -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenAsmMatcher.inc - -echo "Generating X86GenDisassemblerTables.inc" -$TBLGEN_PATH/llvm-tblgen -gen-disassembler -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenDisassemblerTables.inc - -echo "Generating X86GenAsmWriter1.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -asmwriternum=1 -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenAsmWriter1.inc - -echo "Generating X86GenAsmWriter.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I ${DIR_TD} ${DIR_TD}/X86.td -o X86GenAsmWriter.inc - diff --git a/suite/synctools/tablegen/gen-tablegen-reduce.sh b/suite/synctools/tablegen/gen-tablegen-reduce.sh deleted file mode 100755 index 0c8fcbd3b9..0000000000 --- a/suite/synctools/tablegen/gen-tablegen-reduce.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# Generate raw X86*reduce.inc files for Capstone, by Nguyen Anh Quynh - -# Syntax: gen-tablegen-reduce.sh X86 -# Example: ./gen-tablegen-reduce.sh ~/projects/llvm/7.0.1/build/bin X86 - -#TBLGEN_PATH=~/projects/llvm/7.0.1/build/bin -TBLGEN_PATH=$1 -#DIR_TD="X86" -DIR_TD=$2 - -echo "Using llvm-tblgen from ${TBLGEN_PATH}" - -echo "Generating X86GenAsmMatcher_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-matcher -I include -I ${DIR_TD} ${DIR_TD}/X86_reduce.td -o X86GenAsmMatcher_reduce.inc - -echo "Generating GenInstrInfo_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-instr-info -I include -I ${DIR_TD} ${DIR_TD}/X86_reduce.td -o X86GenInstrInfo_reduce.inc - -echo "Generating X86GenDisassemblerTables_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-disassembler -I include -I ${DIR_TD} ${DIR_TD}/X86_reduce.td -o X86GenDisassemblerTables_reduce.inc - -echo "Generating X86GenAsmWriter1_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -asmwriternum=1 -I include -I ${DIR_TD} ${DIR_TD}/X86_reduce.td -o X86GenAsmWriter1_reduce.inc - -echo "Generating X86GenAsmWriter_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I ${DIR_TD} ${DIR_TD}/X86_reduce.td -o X86GenAsmWriter_reduce.inc - diff --git a/suite/synctools/tablegen/gen-tablegen.sh b/suite/synctools/tablegen/gen-tablegen.sh deleted file mode 100755 index 1504d6e1ec..0000000000 --- a/suite/synctools/tablegen/gen-tablegen.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# Generate raw X86*.inc files for Capstone, by Nguyen Anh Quynh -# This combines both -full & -reduce scripts, so we keep it here for reference only. - -# Syntax: gen-tablegen.sh -# Example: ./gen-tablegen.sh ~/projects/llvm/7.0.1/build/bin - -#TBLGEN_PATH=~/projects/llvm/7.0.1/build/bin -TBLGEN_PATH=$1 - -echo "Using llvm-tblgen from ${TBLGEN_PATH}" - -echo "Generating X86GenInstrInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-instr-info -I include -I X86 X86/X86.td -o X86GenInstrInfo.inc - -echo "Generating X86GenRegisterInfo.inc" -$TBLGEN_PATH/llvm-tblgen -gen-register-info -I include -I X86 X86/X86.td -o X86GenRegisterInfo.inc - -echo "Generating X86GenAsmMatcher.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-matcher -I include -I X86 X86/X86.td -o X86GenAsmMatcher.inc - -echo "Generating X86GenDisassemblerTables.inc" -$TBLGEN_PATH/llvm-tblgen -gen-disassembler -I include -I X86 X86/X86.td -o X86GenDisassemblerTables.inc - -echo "Generating X86GenAsmWriter1.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -asmwriternum=1 -I include -I X86 X86/X86.td -o X86GenAsmWriter1.inc - -echo "Generating X86GenAsmWriter.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I X86 X86/X86.td -o X86GenAsmWriter.inc - - -echo "Generating X86GenAsmMatcher_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-matcher -I include -I X86 X86/X86_reduce.td -o X86GenAsmMatcher_reduce.inc - -echo "Generating GenInstrInfo_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-instr-info -I include -I X86 X86/X86_reduce.td -o X86GenInstrInfo_reduce.inc - -echo "Generating X86GenDisassemblerTables_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-disassembler -I include -I X86 X86/X86_reduce.td -o X86GenDisassemblerTables_reduce.inc - -echo "Generating X86GenAsmWriter1_reduce.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -asmwriternum=1 -I include -I X86 X86/X86_reduce.td -o X86GenAsmWriter1_reduce.inc - -echo "Generating X86GenAsmWriter.inc" -$TBLGEN_PATH/llvm-tblgen -gen-asm-writer -I include -I X86 X86/X86_reduce.td -o X86GenAsmWriter_reduce.inc - - diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/AccelTable.h b/suite/synctools/tablegen/include/llvm/CodeGen/AccelTable.h deleted file mode 100644 index e49ac1b6c1..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/AccelTable.h +++ /dev/null @@ -1,408 +0,0 @@ -//==- include/llvm/CodeGen/AccelTable.h - Accelerator Tables -----*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file contains support for writing accelerator tables. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ACCELTABLE_H -#define LLVM_CODEGEN_ACCELTABLE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/CodeGen/DIE.h" -#include "llvm/CodeGen/DwarfStringPoolEntry.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/DJB.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -/// \file -/// The DWARF and Apple accelerator tables are an indirect hash table optimized -/// for null lookup rather than access to known data. The Apple accelerator -/// tables are a precursor of the newer DWARF v5 accelerator tables. Both -/// formats share common design ideas. -/// -/// The Apple accelerator table are output into an on-disk format that looks -/// like this: -/// -/// .------------------. -/// | HEADER | -/// |------------------| -/// | BUCKETS | -/// |------------------| -/// | HASHES | -/// |------------------| -/// | OFFSETS | -/// |------------------| -/// | DATA | -/// `------------------' -/// -/// The header contains a magic number, version, type of hash function, -/// the number of buckets, total number of hashes, and room for a special struct -/// of data and the length of that struct. -/// -/// The buckets contain an index (e.g. 6) into the hashes array. The hashes -/// section contains all of the 32-bit hash values in contiguous memory, and the -/// offsets contain the offset into the data area for the particular hash. -/// -/// For a lookup example, we could hash a function name and take it modulo the -/// number of buckets giving us our bucket. From there we take the bucket value -/// as an index into the hashes table and look at each successive hash as long -/// as the hash value is still the same modulo result (bucket value) as earlier. -/// If we have a match we look at that same entry in the offsets table and grab -/// the offset in the data for our final match. -/// -/// The DWARF v5 accelerator table consists of zero or more name indices that -/// are output into an on-disk format that looks like this: -/// -/// .------------------. -/// | HEADER | -/// |------------------| -/// | CU LIST | -/// |------------------| -/// | LOCAL TU LIST | -/// |------------------| -/// | FOREIGN TU LIST | -/// |------------------| -/// | HASH TABLE | -/// |------------------| -/// | NAME TABLE | -/// |------------------| -/// | ABBREV TABLE | -/// |------------------| -/// | ENTRY POOL | -/// `------------------' -/// -/// For the full documentation please refer to the DWARF 5 standard. -/// -/// -/// This file defines the class template AccelTable, which is represents an -/// abstract view of an Accelerator table, without any notion of an on-disk -/// layout. This class is parameterized by an entry type, which should derive -/// from AccelTableData. This is the type of individual entries in the table, -/// and it should store the data necessary to emit them. AppleAccelTableData is -/// the base class for Apple Accelerator Table entries, which have a uniform -/// structure based on a sequence of Atoms. There are different sub-classes -/// derived from AppleAccelTable, which differ in the set of Atoms and how they -/// obtain their values. -/// -/// An Apple Accelerator Table can be serialized by calling emitAppleAccelTable -/// function. - -namespace llvm { - -class AsmPrinter; -class DwarfCompileUnit; -class DwarfDebug; - -/// Interface which the different types of accelerator table data have to -/// conform. It serves as a base class for different values of the template -/// argument of the AccelTable class template. -class AccelTableData { -public: - virtual ~AccelTableData() = default; - - bool operator<(const AccelTableData &Other) const { - return order() < Other.order(); - } - - // Subclasses should implement: - // static uint32_t hash(StringRef Name); - -#ifndef NDEBUG - virtual void print(raw_ostream &OS) const = 0; -#endif -protected: - virtual uint64_t order() const = 0; -}; - -/// A base class holding non-template-dependant functionality of the AccelTable -/// class. Clients should not use this class directly but rather instantiate -/// AccelTable with a type derived from AccelTableData. -class AccelTableBase { -public: - using HashFn = uint32_t(StringRef); - - /// Represents a group of entries with identical name (and hence, hash value). - struct HashData { - DwarfStringPoolEntryRef Name; - uint32_t HashValue; - std::vector Values; - MCSymbol *Sym; - - HashData(DwarfStringPoolEntryRef Name, HashFn *Hash) - : Name(Name), HashValue(Hash(Name.getString())) {} - -#ifndef NDEBUG - void print(raw_ostream &OS) const; - void dump() const { print(dbgs()); } -#endif - }; - using HashList = std::vector; - using BucketList = std::vector; - -protected: - /// Allocator for HashData and Values. - BumpPtrAllocator Allocator; - - using StringEntries = StringMap; - StringEntries Entries; - - HashFn *Hash; - uint32_t BucketCount; - uint32_t UniqueHashCount; - - HashList Hashes; - BucketList Buckets; - - void computeBucketCount(); - - AccelTableBase(HashFn *Hash) : Entries(Allocator), Hash(Hash) {} - -public: - void finalize(AsmPrinter *Asm, StringRef Prefix); - ArrayRef getBuckets() const { return Buckets; } - uint32_t getBucketCount() const { return BucketCount; } - uint32_t getUniqueHashCount() const { return UniqueHashCount; } - uint32_t getUniqueNameCount() const { return Entries.size(); } - -#ifndef NDEBUG - void print(raw_ostream &OS) const; - void dump() const { print(dbgs()); } -#endif - - AccelTableBase(const AccelTableBase &) = delete; - void operator=(const AccelTableBase &) = delete; -}; - -/// This class holds an abstract representation of an Accelerator Table, -/// consisting of a sequence of buckets, each bucket containing a sequence of -/// HashData entries. The class is parameterized by the type of entries it -/// holds. The type template parameter also defines the hash function to use for -/// hashing names. -template class AccelTable : public AccelTableBase { -public: - AccelTable() : AccelTableBase(DataT::hash) {} - - template - void addName(DwarfStringPoolEntryRef Name, Types &&... Args); -}; - -template -template -void AccelTable::addName(DwarfStringPoolEntryRef Name, - Types &&... Args) { - assert(Buckets.empty() && "Already finalized!"); - // If the string is in the list already then add this die to the list - // otherwise add a new one. - auto Iter = Entries.try_emplace(Name.getString(), Name, Hash).first; - assert(Iter->second.Name == Name); - Iter->second.Values.push_back( - new (Allocator) AccelTableDataT(std::forward(Args)...)); -} - -/// A base class for different implementations of Data classes for Apple -/// Accelerator Tables. The columns in the table are defined by the static Atoms -/// variable defined on the subclasses. -class AppleAccelTableData : public AccelTableData { -public: - /// An Atom defines the form of the data in an Apple accelerator table. - /// Conceptually it is a column in the accelerator consisting of a type and a - /// specification of the form of its data. - struct Atom { - /// Atom Type. - const uint16_t Type; - /// DWARF Form. - const uint16_t Form; - - constexpr Atom(uint16_t Type, uint16_t Form) : Type(Type), Form(Form) {} - -#ifndef NDEBUG - void print(raw_ostream &OS) const; - void dump() const { print(dbgs()); } -#endif - }; - // Subclasses should define: - // static constexpr Atom Atoms[]; - - virtual void emit(AsmPrinter *Asm) const = 0; - - static uint32_t hash(StringRef Buffer) { return djbHash(Buffer); } -}; - -/// The Data class implementation for DWARF v5 accelerator table. Unlike the -/// Apple Data classes, this class is just a DIE wrapper, and does not know to -/// serialize itself. The complete serialization logic is in the -/// emitDWARF5AccelTable function. -class DWARF5AccelTableData : public AccelTableData { -public: - static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); } - - DWARF5AccelTableData(const DIE &Die) : Die(Die) {} - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif - - const DIE &getDie() const { return Die; } - uint64_t getDieOffset() const { return Die.getOffset(); } - unsigned getDieTag() const { return Die.getTag(); } - -protected: - const DIE &Die; - - uint64_t order() const override { return Die.getOffset(); } -}; - -class DWARF5AccelTableStaticData : public AccelTableData { -public: - static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); } - - DWARF5AccelTableStaticData(uint64_t DieOffset, unsigned DieTag, - unsigned CUIndex) - : DieOffset(DieOffset), DieTag(DieTag), CUIndex(CUIndex) {} - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif - - uint64_t getDieOffset() const { return DieOffset; } - unsigned getDieTag() const { return DieTag; } - unsigned getCUIndex() const { return CUIndex; } - -protected: - uint64_t DieOffset; - unsigned DieTag; - unsigned CUIndex; - - uint64_t order() const override { return DieOffset; } -}; - -void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, - StringRef Prefix, const MCSymbol *SecBegin, - ArrayRef Atoms); - -/// Emit an Apple Accelerator Table consisting of entries in the specified -/// AccelTable. The DataT template parameter should be derived from -/// AppleAccelTableData. -template -void emitAppleAccelTable(AsmPrinter *Asm, AccelTable &Contents, - StringRef Prefix, const MCSymbol *SecBegin) { - static_assert(std::is_convertible::value, ""); - emitAppleAccelTableImpl(Asm, Contents, Prefix, SecBegin, DataT::Atoms); -} - -void emitDWARF5AccelTable(AsmPrinter *Asm, - AccelTable &Contents, - const DwarfDebug &DD, - ArrayRef> CUs); - -void emitDWARF5AccelTable( - AsmPrinter *Asm, AccelTable &Contents, - ArrayRef CUs, - llvm::function_ref - getCUIndexForEntry); - -/// Accelerator table data implementation for simple Apple accelerator tables -/// with just a DIE reference. -class AppleAccelTableOffsetData : public AppleAccelTableData { -public: - AppleAccelTableOffsetData(const DIE &D) : Die(D) {} - - void emit(AsmPrinter *Asm) const override; - - static constexpr Atom Atoms[] = { - Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif -protected: - uint64_t order() const override { return Die.getOffset(); } - - const DIE &Die; -}; - -/// Accelerator table data implementation for Apple type accelerator tables. -class AppleAccelTableTypeData : public AppleAccelTableOffsetData { -public: - AppleAccelTableTypeData(const DIE &D) : AppleAccelTableOffsetData(D) {} - - void emit(AsmPrinter *Asm) const override; - - static constexpr Atom Atoms[] = { - Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), - Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), - Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif -}; - -/// Accelerator table data implementation for simple Apple accelerator tables -/// with a DIE offset but no actual DIE pointer. -class AppleAccelTableStaticOffsetData : public AppleAccelTableData { -public: - AppleAccelTableStaticOffsetData(uint32_t Offset) : Offset(Offset) {} - - void emit(AsmPrinter *Asm) const override; - - static constexpr Atom Atoms[] = { - Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif -protected: - uint64_t order() const override { return Offset; } - - uint32_t Offset; -}; - -/// Accelerator table data implementation for type accelerator tables with -/// a DIE offset but no actual DIE pointer. -class AppleAccelTableStaticTypeData : public AppleAccelTableStaticOffsetData { -public: - AppleAccelTableStaticTypeData(uint32_t Offset, uint16_t Tag, - bool ObjCClassIsImplementation, - uint32_t QualifiedNameHash) - : AppleAccelTableStaticOffsetData(Offset), - QualifiedNameHash(QualifiedNameHash), Tag(Tag), - ObjCClassIsImplementation(ObjCClassIsImplementation) {} - - void emit(AsmPrinter *Asm) const override; - - static constexpr Atom Atoms[] = { - Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), - Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), - Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; - -#ifndef NDEBUG - void print(raw_ostream &OS) const override; -#endif -protected: - uint64_t order() const override { return Offset; } - - uint32_t QualifiedNameHash; - uint16_t Tag; - bool ObjCClassIsImplementation; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_ACCELTABLE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/Analysis.h b/suite/synctools/tablegen/include/llvm/CodeGen/Analysis.h deleted file mode 100644 index 60442326d6..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/Analysis.h +++ /dev/null @@ -1,144 +0,0 @@ -//===- CodeGen/Analysis.h - CodeGen LLVM IR Analysis Utilities --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares several CodeGen-specific LLVM IR analysis utilities. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ANALYSIS_H -#define LLVM_CODEGEN_ANALYSIS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Support/CodeGen.h" - -namespace llvm { -class GlobalValue; -class LLT; -class MachineBasicBlock; -class MachineFunction; -class TargetLoweringBase; -class TargetLowering; -class TargetMachine; -struct EVT; - -/// Compute the linearized index of a member in a nested -/// aggregate/struct/array. -/// -/// Given an LLVM IR aggregate type and a sequence of insertvalue or -/// extractvalue indices that identify a member, return the linearized index of -/// the start of the member, i.e the number of element in memory before the -/// sought one. This is disconnected from the number of bytes. -/// -/// \param Ty is the type indexed by \p Indices. -/// \param Indices is an optional pointer in the indices list to the current -/// index. -/// \param IndicesEnd is the end of the indices list. -/// \param CurIndex is the current index in the recursion. -/// -/// \returns \p CurIndex plus the linear index in \p Ty the indices list. -unsigned ComputeLinearIndex(Type *Ty, - const unsigned *Indices, - const unsigned *IndicesEnd, - unsigned CurIndex = 0); - -inline unsigned ComputeLinearIndex(Type *Ty, - ArrayRef Indices, - unsigned CurIndex = 0) { - return ComputeLinearIndex(Ty, Indices.begin(), Indices.end(), CurIndex); -} - -/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of -/// EVTs that represent all the individual underlying -/// non-aggregate types that comprise it. -/// -/// If Offsets is non-null, it points to a vector to be filled in -/// with the in-memory offsets of each of the individual values. -/// -void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, - SmallVectorImpl &ValueVTs, - SmallVectorImpl *Offsets = nullptr, - uint64_t StartingOffset = 0); - -/// Variant of ComputeValueVTs that also produces the memory VTs. -void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, - SmallVectorImpl &ValueVTs, - SmallVectorImpl *MemVTs, - SmallVectorImpl *Offsets = nullptr, - uint64_t StartingOffset = 0); - -/// computeValueLLTs - Given an LLVM IR type, compute a sequence of -/// LLTs that represent all the individual underlying -/// non-aggregate types that comprise it. -/// -/// If Offsets is non-null, it points to a vector to be filled in -/// with the in-memory offsets of each of the individual values. -/// -void computeValueLLTs(const DataLayout &DL, Type &Ty, - SmallVectorImpl &ValueTys, - SmallVectorImpl *Offsets = nullptr, - uint64_t StartingOffset = 0); - -/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. -GlobalValue *ExtractTypeInfo(Value *V); - -/// getFCmpCondCode - Return the ISD condition code corresponding to -/// the given LLVM IR floating-point condition code. This includes -/// consideration of global floating-point math flags. -/// -ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred); - -/// getFCmpCodeWithoutNaN - Given an ISD condition code comparing floats, -/// return the equivalent code if we're allowed to assume that NaNs won't occur. -ISD::CondCode getFCmpCodeWithoutNaN(ISD::CondCode CC); - -/// getICmpCondCode - Return the ISD condition code corresponding to -/// the given LLVM IR integer condition code. -ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); - -/// getICmpCondCode - Return the LLVM IR integer condition code -/// corresponding to the given ISD integer condition code. -ICmpInst::Predicate getICmpCondCode(ISD::CondCode Pred); - -/// Test if the given instruction is in a position to be optimized -/// with a tail-call. This roughly means that it's in a block with -/// a return and there's nothing that needs to be scheduled -/// between it and the return. -/// -/// This function only tests target-independent requirements. -bool isInTailCallPosition(const CallBase &Call, const TargetMachine &TM); - -/// Test if given that the input instruction is in the tail call position, if -/// there is an attribute mismatch between the caller and the callee that will -/// inhibit tail call optimizations. -/// \p AllowDifferingSizes is an output parameter which, if forming a tail call -/// is permitted, determines whether it's permitted only if the size of the -/// caller's and callee's return types match exactly. -bool attributesPermitTailCall(const Function *F, const Instruction *I, - const ReturnInst *Ret, - const TargetLoweringBase &TLI, - bool *AllowDifferingSizes = nullptr); - -/// Test if given that the input instruction is in the tail call position if the -/// return type or any attributes of the function will inhibit tail call -/// optimization. -bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I, - const ReturnInst *Ret, - const TargetLoweringBase &TLI); - -DenseMap -getEHScopeMembership(const MachineFunction &MF); - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/AntiDepBreaker.h b/suite/synctools/tablegen/include/llvm/CodeGen/AntiDepBreaker.h deleted file mode 100644 index 7c7cb04ca9..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/AntiDepBreaker.h +++ /dev/null @@ -1,103 +0,0 @@ -//===- llvm/CodeGen/AntiDepBreaker.h - Anti-Dependence Breaking -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the AntiDepBreaker class, which implements -// anti-dependence breaking heuristics for post-register-allocation scheduling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ANTIDEPBREAKER_H -#define LLVM_CODEGEN_ANTIDEPBREAKER_H - -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/Support/Compiler.h" -#include -#include -#include - -namespace llvm { - -class RegisterClassInfo; - -/// This class works in conjunction with the post-RA scheduler to rename -/// registers to break register anti-dependencies (WAR hazards). -class AntiDepBreaker { -public: - using DbgValueVector = - std::vector>; - - virtual ~AntiDepBreaker(); - - /// Initialize anti-dep breaking for a new basic block. - virtual void StartBlock(MachineBasicBlock *BB) = 0; - - /// Identify anti-dependencies within a basic-block region and break them by - /// renaming registers. Return the number of anti-dependencies broken. - virtual unsigned BreakAntiDependencies(const std::vector &SUnits, - MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - unsigned InsertPosIndex, - DbgValueVector &DbgValues) = 0; - - /// Update liveness information to account for the current - /// instruction, which will not be scheduled. - virtual void Observe(MachineInstr &MI, unsigned Count, - unsigned InsertPosIndex) = 0; - - /// Finish anti-dep breaking for a basic block. - virtual void FinishBlock() = 0; - - /// Update DBG_VALUE or DBG_PHI if dependency breaker is updating - /// other machine instruction to use NewReg. - void UpdateDbgValue(MachineInstr &MI, unsigned OldReg, unsigned NewReg) { - if (MI.isDebugValue()) { - if (MI.getDebugOperand(0).isReg() && - MI.getDebugOperand(0).getReg() == OldReg) - MI.getDebugOperand(0).setReg(NewReg); - } else if (MI.isDebugPHI()) { - if (MI.getOperand(0).isReg() && - MI.getOperand(0).getReg() == OldReg) - MI.getOperand(0).setReg(NewReg); - } else { - llvm_unreachable("MI is not DBG_VALUE / DBG_PHI!"); - } - } - - /// Update all DBG_VALUE instructions that may be affected by the dependency - /// breaker's update of ParentMI to use NewReg. - void UpdateDbgValues(const DbgValueVector &DbgValues, MachineInstr *ParentMI, - unsigned OldReg, unsigned NewReg) { - // The following code is dependent on the order in which the DbgValues are - // constructed in ScheduleDAGInstrs::buildSchedGraph. - MachineInstr *PrevDbgMI = nullptr; - for (const auto &DV : make_range(DbgValues.crbegin(), DbgValues.crend())) { - MachineInstr *PrevMI = DV.second; - if ((PrevMI == ParentMI) || (PrevMI == PrevDbgMI)) { - MachineInstr *DbgMI = DV.first; - UpdateDbgValue(*DbgMI, OldReg, NewReg); - PrevDbgMI = DbgMI; - } else if (PrevDbgMI) { - break; // If no match and already found a DBG_VALUE, we're done. - } - } - } -}; - -AntiDepBreaker *createAggressiveAntiDepBreaker( - MachineFunction &MFi, const RegisterClassInfo &RCI, - TargetSubtargetInfo::RegClassVector &CriticalPathRCs); - -AntiDepBreaker *createCriticalAntiDepBreaker(MachineFunction &MFi, - const RegisterClassInfo &RCI); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_ANTIDEPBREAKER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinter.h b/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinter.h deleted file mode 100644 index 40898d8a81..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinter.h +++ /dev/null @@ -1,816 +0,0 @@ -//===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains a class to be used as the base class for target specific -// asm writers. This class primarily handles common functionality used by -// all asm writers. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ASMPRINTER_H -#define LLVM_CODEGEN_ASMPRINTER_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/CodeGen/AsmPrinterHandler.h" -#include "llvm/CodeGen/DwarfStringPoolEntry.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SourceMgr.h" -#include -#include -#include -#include - -namespace llvm { - -class BasicBlock; -class BlockAddress; -class Constant; -class ConstantArray; -class DataLayout; -class DIE; -class DIEAbbrev; -class DwarfDebug; -class GCMetadataPrinter; -class GCStrategy; -class GlobalObject; -class GlobalValue; -class GlobalVariable; -class MachineBasicBlock; -class MachineConstantPoolValue; -class MachineDominatorTree; -class MachineFunction; -class MachineInstr; -class MachineJumpTableInfo; -class MachineLoopInfo; -class MachineModuleInfo; -class MachineOptimizationRemarkEmitter; -class MCAsmInfo; -class MCCFIInstruction; -class MCContext; -class MCExpr; -class MCInst; -class MCSection; -class MCStreamer; -class MCSubtargetInfo; -class MCSymbol; -class MCTargetOptions; -class MDNode; -class Module; -class PseudoProbeHandler; -class raw_ostream; -class StackMaps; -class StringRef; -class TargetLoweringObjectFile; -class TargetMachine; -class Twine; - -namespace remarks { -class RemarkStreamer; -} - -/// This class is intended to be used as a driving class for all asm writers. -class AsmPrinter : public MachineFunctionPass { -public: - /// Target machine description. - TargetMachine &TM; - - /// Target Asm Printer information. - const MCAsmInfo *MAI; - - /// This is the context for the output file that we are streaming. This owns - /// all of the global MC-related objects for the generated translation unit. - MCContext &OutContext; - - /// This is the MCStreamer object for the file we are generating. This - /// contains the transient state for the current translation unit that we are - /// generating (such as the current section etc). - std::unique_ptr OutStreamer; - - /// The current machine function. - MachineFunction *MF = nullptr; - - /// This is a pointer to the current MachineModuleInfo. - MachineModuleInfo *MMI = nullptr; - - /// This is a pointer to the current MachineDominatorTree. - MachineDominatorTree *MDT = nullptr; - - /// This is a pointer to the current MachineLoopInfo. - MachineLoopInfo *MLI = nullptr; - - /// Optimization remark emitter. - MachineOptimizationRemarkEmitter *ORE; - - /// The symbol for the entry in __patchable_function_entires. - MCSymbol *CurrentPatchableFunctionEntrySym = nullptr; - - /// The symbol for the current function. This is recalculated at the beginning - /// of each call to runOnMachineFunction(). - MCSymbol *CurrentFnSym = nullptr; - - /// The symbol for the current function descriptor on AIX. This is created - /// at the beginning of each call to SetupMachineFunction(). - MCSymbol *CurrentFnDescSym = nullptr; - - /// The symbol used to represent the start of the current function for the - /// purpose of calculating its size (e.g. using the .size directive). By - /// default, this is equal to CurrentFnSym. - MCSymbol *CurrentFnSymForSize = nullptr; - - /// Map a basic block section ID to the begin and end symbols of that section - /// which determine the section's range. - struct MBBSectionRange { - MCSymbol *BeginLabel, *EndLabel; - }; - - MapVector MBBSectionRanges; - - /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of - /// its number of uses by other globals. - using GOTEquivUsePair = std::pair; - MapVector GlobalGOTEquivs; - - /// struct HandlerInfo and Handlers permit users or target extended - /// AsmPrinter to add their own handlers. - struct HandlerInfo { - std::unique_ptr Handler; - StringRef TimerName; - StringRef TimerDescription; - StringRef TimerGroupName; - StringRef TimerGroupDescription; - - HandlerInfo(std::unique_ptr Handler, StringRef TimerName, - StringRef TimerDescription, StringRef TimerGroupName, - StringRef TimerGroupDescription) - : Handler(std::move(Handler)), TimerName(TimerName), - TimerDescription(TimerDescription), TimerGroupName(TimerGroupName), - TimerGroupDescription(TimerGroupDescription) {} - }; - - // Flags representing which CFI section is required for a function/module. - enum class CFISection : unsigned { - None = 0, ///< Do not emit either .eh_frame or .debug_frame - EH = 1, ///< Emit .eh_frame - Debug = 2 ///< Emit .debug_frame - }; - -private: - MCSymbol *CurrentFnEnd = nullptr; - - /// Map a basic block section ID to the exception symbol associated with that - /// section. Map entries are assigned and looked up via - /// AsmPrinter::getMBBExceptionSym. - DenseMap MBBSectionExceptionSyms; - - // The symbol used to represent the start of the current BB section of the - // function. This is used to calculate the size of the BB section. - MCSymbol *CurrentSectionBeginSym = nullptr; - - // The garbage collection metadata printer table. - void *GCMetadataPrinters = nullptr; // Really a DenseMap. - - /// Emit comments in assembly output if this is true. - bool VerboseAsm; - - /// Output stream for the stack usage file (i.e., .su file). - std::unique_ptr StackUsageStream; - - static char ID; - -protected: - MCSymbol *CurrentFnBegin = nullptr; - - /// A vector of all debug/EH info emitters we should use. This vector - /// maintains ownership of the emitters. - std::vector Handlers; - size_t NumUserHandlers = 0; - -private: - /// If generated on the fly this own the instance. - std::unique_ptr OwnedMDT; - - /// If generated on the fly this own the instance. - std::unique_ptr OwnedMLI; - - /// If the target supports dwarf debug info, this pointer is non-null. - DwarfDebug *DD = nullptr; - - /// A handler that supports pseudo probe emission with embedded inline - /// context. - PseudoProbeHandler *PP = nullptr; - - /// CFISection type the module needs i.e. either .eh_frame or .debug_frame. - CFISection ModuleCFISection = CFISection::None; - -protected: - explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); - -public: - ~AsmPrinter() override; - - DwarfDebug *getDwarfDebug() { return DD; } - DwarfDebug *getDwarfDebug() const { return DD; } - - uint16_t getDwarfVersion() const; - void setDwarfVersion(uint16_t Version); - - bool isDwarf64() const; - - /// Returns 4 for DWARF32 and 8 for DWARF64. - unsigned int getDwarfOffsetByteSize() const; - - /// Returns 4 for DWARF32 and 12 for DWARF64. - unsigned int getUnitLengthFieldByteSize() const; - - /// Returns information about the byte size of DW_FORM values. - dwarf::FormParams getDwarfFormParams() const; - - bool isPositionIndependent() const; - - /// Return true if assembly output should contain comments. - bool isVerbose() const { return VerboseAsm; } - - /// Return a unique ID for the current function. - unsigned getFunctionNumber() const; - - /// Return symbol for the function pseudo stack if the stack frame is not a - /// register based. - virtual const MCSymbol *getFunctionFrameSymbol() const { return nullptr; } - - MCSymbol *getFunctionBegin() const { return CurrentFnBegin; } - MCSymbol *getFunctionEnd() const { return CurrentFnEnd; } - - // Return the exception symbol associated with the MBB section containing a - // given basic block. - MCSymbol *getMBBExceptionSym(const MachineBasicBlock &MBB); - - /// Return information about object file lowering. - const TargetLoweringObjectFile &getObjFileLowering() const; - - /// Return information about data layout. - const DataLayout &getDataLayout() const; - - /// Return the pointer size from the TargetMachine - unsigned getPointerSize() const; - - /// Return information about subtarget. - const MCSubtargetInfo &getSubtargetInfo() const; - - void EmitToStreamer(MCStreamer &S, const MCInst &Inst); - - /// Emits initial debug location directive. - void emitInitialRawDwarfLocDirective(const MachineFunction &MF); - - /// Return the current section we are emitting to. - const MCSection *getCurrentSection() const; - - void getNameWithPrefix(SmallVectorImpl &Name, - const GlobalValue *GV) const; - - MCSymbol *getSymbol(const GlobalValue *GV) const; - - /// Similar to getSymbol() but preferred for references. On ELF, this uses a - /// local symbol if a reference to GV is guaranteed to be resolved to the - /// definition in the same module. - MCSymbol *getSymbolPreferLocal(const GlobalValue &GV) const; - - //===------------------------------------------------------------------===// - // XRay instrumentation implementation. - //===------------------------------------------------------------------===// -public: - // This describes the kind of sled we're storing in the XRay table. - enum class SledKind : uint8_t { - FUNCTION_ENTER = 0, - FUNCTION_EXIT = 1, - TAIL_CALL = 2, - LOG_ARGS_ENTER = 3, - CUSTOM_EVENT = 4, - TYPED_EVENT = 5, - }; - - // The table will contain these structs that point to the sled, the function - // containing the sled, and what kind of sled (and whether they should always - // be instrumented). We also use a version identifier that the runtime can use - // to decide what to do with the sled, depending on the version of the sled. - struct XRayFunctionEntry { - const MCSymbol *Sled; - const MCSymbol *Function; - SledKind Kind; - bool AlwaysInstrument; - const class Function *Fn; - uint8_t Version; - - void emit(int, MCStreamer *) const; - }; - - // All the sleds to be emitted. - SmallVector Sleds; - - // Helper function to record a given XRay sled. - void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind, - uint8_t Version = 0); - - /// Emit a table with all XRay instrumentation points. - void emitXRayTable(); - - void emitPatchableFunctionEntries(); - - //===------------------------------------------------------------------===// - // MachineFunctionPass Implementation. - //===------------------------------------------------------------------===// - - /// Record analysis usage. - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// Set up the AsmPrinter when we are working on a new module. If your pass - /// overrides this, it must make sure to explicitly call this implementation. - bool doInitialization(Module &M) override; - - /// Shut down the asmprinter. If you override this in your pass, you must make - /// sure to call it explicitly. - bool doFinalization(Module &M) override; - - /// Emit the specified function out to the OutStreamer. - bool runOnMachineFunction(MachineFunction &MF) override { - SetupMachineFunction(MF); - emitFunctionBody(); - return false; - } - - //===------------------------------------------------------------------===// - // Coarse grained IR lowering routines. - //===------------------------------------------------------------------===// - - /// This should be called when a new MachineFunction is being processed from - /// runOnMachineFunction. - virtual void SetupMachineFunction(MachineFunction &MF); - - /// This method emits the body and trailer for a function. - void emitFunctionBody(); - - void emitCFIInstruction(const MachineInstr &MI); - - void emitFrameAlloc(const MachineInstr &MI); - - void emitStackSizeSection(const MachineFunction &MF); - - void emitStackUsage(const MachineFunction &MF); - - void emitBBAddrMapSection(const MachineFunction &MF); - - void emitPseudoProbe(const MachineInstr &MI); - - void emitRemarksSection(remarks::RemarkStreamer &RS); - - /// Get the CFISection type for a function. - CFISection getFunctionCFISectionType(const Function &F) const; - - /// Get the CFISection type for a function. - CFISection getFunctionCFISectionType(const MachineFunction &MF) const; - - /// Get the CFISection type for the module. - CFISection getModuleCFISectionType() const { return ModuleCFISection; } - - bool needsSEHMoves(); - - /// Since emitting CFI unwind information is entangled with supporting the - /// exceptions, this returns true for platforms which use CFI unwind - /// information for debugging purpose when - /// `MCAsmInfo::ExceptionsType == ExceptionHandling::None`. - bool needsCFIForDebug() const; - - /// Print to the current output stream assembly representations of the - /// constants in the constant pool MCP. This is used to print out constants - /// which have been "spilled to memory" by the code generator. - virtual void emitConstantPool(); - - /// Print assembly representations of the jump tables used by the current - /// function to the current output stream. - virtual void emitJumpTableInfo(); - - /// Emit the specified global variable to the .s file. - virtual void emitGlobalVariable(const GlobalVariable *GV); - - /// Check to see if the specified global is a special global used by LLVM. If - /// so, emit it and return true, otherwise do nothing and return false. - bool emitSpecialLLVMGlobal(const GlobalVariable *GV); - - /// `llvm.global_ctors` and `llvm.global_dtors` are arrays of Structor - /// structs. - /// - /// Priority - init priority - /// Func - global initialization or global clean-up function - /// ComdatKey - associated data - struct Structor { - int Priority = 0; - Constant *Func = nullptr; - GlobalValue *ComdatKey = nullptr; - - Structor() = default; - }; - - /// This method gathers an array of Structors and then sorts them out by - /// Priority. - /// @param List The initializer of `llvm.global_ctors` or `llvm.global_dtors` - /// array. - /// @param[out] Structors Sorted Structor structs by Priority. - void preprocessXXStructorList(const DataLayout &DL, const Constant *List, - SmallVector &Structors); - - /// This method emits `llvm.global_ctors` or `llvm.global_dtors` list. - virtual void emitXXStructorList(const DataLayout &DL, const Constant *List, - bool IsCtor); - - /// Emit an alignment directive to the specified power of two boundary. If a - /// global value is specified, and if that global has an explicit alignment - /// requested, it will override the alignment request if required for - /// correctness. - void emitAlignment(Align Alignment, const GlobalObject *GV = nullptr, - unsigned MaxBytesToEmit = 0) const; - - /// Lower the specified LLVM Constant to an MCExpr. - virtual const MCExpr *lowerConstant(const Constant *CV); - - /// Print a general LLVM constant to the .s file. - void emitGlobalConstant(const DataLayout &DL, const Constant *CV); - - /// Unnamed constant global variables solely containing a pointer to - /// another globals variable act like a global variable "proxy", or GOT - /// equivalents, i.e., it's only used to hold the address of the latter. One - /// optimization is to replace accesses to these proxies by using the GOT - /// entry for the final global instead. Hence, we select GOT equivalent - /// candidates among all the module global variables, avoid emitting them - /// unnecessarily and finally replace references to them by pc relative - /// accesses to GOT entries. - void computeGlobalGOTEquivs(Module &M); - - /// Constant expressions using GOT equivalent globals may not be - /// eligible for PC relative GOT entry conversion, in such cases we need to - /// emit the proxies we previously omitted in EmitGlobalVariable. - void emitGlobalGOTEquivs(); - - /// Emit the stack maps. - void emitStackMaps(StackMaps &SM); - - //===------------------------------------------------------------------===// - // Overridable Hooks - //===------------------------------------------------------------------===// - - void addAsmPrinterHandler(HandlerInfo Handler) { - Handlers.insert(Handlers.begin(), std::move(Handler)); - NumUserHandlers++; - } - - // Targets can, or in the case of EmitInstruction, must implement these to - // customize output. - - /// This virtual method can be overridden by targets that want to emit - /// something at the start of their file. - virtual void emitStartOfAsmFile(Module &) {} - - /// This virtual method can be overridden by targets that want to emit - /// something at the end of their file. - virtual void emitEndOfAsmFile(Module &) {} - - /// Targets can override this to emit stuff before the first basic block in - /// the function. - virtual void emitFunctionBodyStart() {} - - /// Targets can override this to emit stuff after the last basic block in the - /// function. - virtual void emitFunctionBodyEnd() {} - - /// Targets can override this to emit stuff at the start of a basic block. - /// By default, this method prints the label for the specified - /// MachineBasicBlock, an alignment (if present) and a comment describing it - /// if appropriate. - virtual void emitBasicBlockStart(const MachineBasicBlock &MBB); - - /// Targets can override this to emit stuff at the end of a basic block. - virtual void emitBasicBlockEnd(const MachineBasicBlock &MBB); - - /// Targets should implement this to emit instructions. - virtual void emitInstruction(const MachineInstr *) { - llvm_unreachable("EmitInstruction not implemented"); - } - - /// Return the symbol for the specified constant pool entry. - virtual MCSymbol *GetCPISymbol(unsigned CPID) const; - - virtual void emitFunctionEntryLabel(); - - virtual void emitFunctionDescriptor() { - llvm_unreachable("Function descriptor is target-specific."); - } - - virtual void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); - - /// Targets can override this to change how global constants that are part of - /// a C++ static/global constructor list are emitted. - virtual void emitXXStructor(const DataLayout &DL, const Constant *CV) { - emitGlobalConstant(DL, CV); - } - - /// Return true if the basic block has exactly one predecessor and the control - /// transfer mechanism between the predecessor and this block is a - /// fall-through. - virtual bool - isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; - - /// Targets can override this to customize the output of IMPLICIT_DEF - /// instructions in verbose mode. - virtual void emitImplicitDef(const MachineInstr *MI) const; - - /// Emit N NOP instructions. - void emitNops(unsigned N); - - //===------------------------------------------------------------------===// - // Symbol Lowering Routines. - //===------------------------------------------------------------------===// - - MCSymbol *createTempSymbol(const Twine &Name) const; - - /// Return the MCSymbol for a private symbol with global value name as its - /// base, with the specified suffix. - MCSymbol *getSymbolWithGlobalValueBase(const GlobalValue *GV, - StringRef Suffix) const; - - /// Return the MCSymbol for the specified ExternalSymbol. - MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const; - - /// Return the symbol for the specified jump table entry. - MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const; - - /// Return the symbol for the specified jump table .set - /// FIXME: privatize to AsmPrinter. - MCSymbol *GetJTSetSymbol(unsigned UID, unsigned MBBID) const; - - /// Return the MCSymbol used to satisfy BlockAddress uses of the specified - /// basic block. - MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; - MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const; - - //===------------------------------------------------------------------===// - // Emission Helper Routines. - //===------------------------------------------------------------------===// - - /// This is just convenient handler for printing offsets. - void printOffset(int64_t Offset, raw_ostream &OS) const; - - /// Emit a byte directive and value. - void emitInt8(int Value) const; - - /// Emit a short directive and value. - void emitInt16(int Value) const; - - /// Emit a long directive and value. - void emitInt32(int Value) const; - - /// Emit a long long directive and value. - void emitInt64(uint64_t Value) const; - - /// Emit something like ".long Hi-Lo" where the size in bytes of the directive - /// is specified by Size and Hi/Lo specify the labels. This implicitly uses - /// .set if it is available. - void emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, - unsigned Size) const; - - /// Emit something like ".uleb128 Hi-Lo". - void emitLabelDifferenceAsULEB128(const MCSymbol *Hi, - const MCSymbol *Lo) const; - - /// Emit something like ".long Label+Offset" where the size in bytes of the - /// directive is specified by Size and Label specifies the label. This - /// implicitly uses .set if it is available. - void emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size, bool IsSectionRelative = false) const; - - /// Emit something like ".long Label" where the size in bytes of the directive - /// is specified by Size and Label specifies the label. - void emitLabelReference(const MCSymbol *Label, unsigned Size, - bool IsSectionRelative = false) const { - emitLabelPlusOffset(Label, 0, Size, IsSectionRelative); - } - - //===------------------------------------------------------------------===// - // Dwarf Emission Helper Routines - //===------------------------------------------------------------------===// - - /// Emit the specified signed leb128 value. - void emitSLEB128(int64_t Value, const char *Desc = nullptr) const; - - /// Emit the specified unsigned leb128 value. - void emitULEB128(uint64_t Value, const char *Desc = nullptr, - unsigned PadTo = 0) const; - - /// Emit a .byte 42 directive that corresponds to an encoding. If verbose - /// assembly output is enabled, we output comments describing the encoding. - /// Desc is a string saying what the encoding is specifying (e.g. "LSDA"). - void emitEncodingByte(unsigned Val, const char *Desc = nullptr) const; - - /// Return the size of the encoding in bytes. - unsigned GetSizeOfEncodedValue(unsigned Encoding) const; - - /// Emit reference to a ttype global with a specified encoding. - virtual void emitTTypeReference(const GlobalValue *GV, unsigned Encoding); - - /// Emit a reference to a symbol for use in dwarf. Different object formats - /// represent this in different ways. Some use a relocation others encode - /// the label offset in its section. - void emitDwarfSymbolReference(const MCSymbol *Label, - bool ForceOffset = false) const; - - /// Emit the 4- or 8-byte offset of a string from the start of its section. - /// - /// When possible, emit a DwarfStringPool section offset without any - /// relocations, and without using the symbol. Otherwise, defers to \a - /// emitDwarfSymbolReference(). - /// - /// The length of the emitted value depends on the DWARF format. - void emitDwarfStringOffset(DwarfStringPoolEntry S) const; - - /// Emit the 4-or 8-byte offset of a string from the start of its section. - void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const { - emitDwarfStringOffset(S.getEntry()); - } - - /// Emit something like ".long Label + Offset" or ".quad Label + Offset" - /// depending on the DWARF format. - void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const; - - /// Emit 32- or 64-bit value depending on the DWARF format. - void emitDwarfLengthOrOffset(uint64_t Value) const; - - /// Emit a unit length field. The actual format, DWARF32 or DWARF64, is chosen - /// according to the settings. - void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) const; - - /// Emit a unit length field. The actual format, DWARF32 or DWARF64, is chosen - /// according to the settings. - /// Return the end symbol generated inside, the caller needs to emit it. - MCSymbol *emitDwarfUnitLength(const Twine &Prefix, - const Twine &Comment) const; - - /// Emit reference to a call site with a specified encoding - void emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, - unsigned Encoding) const; - /// Emit an integer value corresponding to the call site encoding - void emitCallSiteValue(uint64_t Value, unsigned Encoding) const; - - /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. - virtual unsigned getISAEncoding() { return 0; } - - /// Emit the directive and value for debug thread local expression - /// - /// \p Value - The value to emit. - /// \p Size - The size of the integer (in bytes) to emit. - virtual void emitDebugValue(const MCExpr *Value, unsigned Size) const; - - //===------------------------------------------------------------------===// - // Dwarf Lowering Routines - //===------------------------------------------------------------------===// - - /// Emit frame instruction to describe the layout of the frame. - void emitCFIInstruction(const MCCFIInstruction &Inst) const; - - /// Emit Dwarf abbreviation table. - template void emitDwarfAbbrevs(const T &Abbrevs) const { - // For each abbreviation. - for (const auto &Abbrev : Abbrevs) - emitDwarfAbbrev(*Abbrev); - - // Mark end of abbreviations. - emitULEB128(0, "EOM(3)"); - } - - void emitDwarfAbbrev(const DIEAbbrev &Abbrev) const; - - /// Recursively emit Dwarf DIE tree. - void emitDwarfDIE(const DIE &Die) const; - - //===------------------------------------------------------------------===// - // Inline Asm Support - //===------------------------------------------------------------------===// - - // These are hooks that targets can override to implement inline asm - // support. These should probably be moved out of AsmPrinter someday. - - /// Print information related to the specified machine instr that is - /// independent of the operand, and may be independent of the instr itself. - /// This can be useful for portably encoding the comment character or other - /// bits of target-specific knowledge into the asmstrings. The syntax used is - /// ${:comment}. Targets can override this to add support for their own - /// strange codes. - virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, - StringRef Code) const; - - /// Print the MachineOperand as a symbol. Targets with complex handling of - /// symbol references should override the base implementation. - virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS); - - /// Print the specified operand of MI, an INLINEASM instruction, using the - /// specified assembler variant. Targets should override this to format as - /// appropriate. This method can return true if the operand is erroneous. - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, raw_ostream &OS); - - /// Print the specified operand of MI, an INLINEASM instruction, using the - /// specified assembler variant as an address. Targets should override this to - /// format as appropriate. This method can return true if the operand is - /// erroneous. - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, raw_ostream &OS); - - /// Let the target do anything it needs to do before emitting inlineasm. - /// \p StartInfo - the subtarget info before parsing inline asm - virtual void emitInlineAsmStart() const; - - /// Let the target do anything it needs to do after emitting inlineasm. - /// This callback can be used restore the original mode in case the - /// inlineasm contains directives to switch modes. - /// \p StartInfo - the original subtarget info before inline asm - /// \p EndInfo - the final subtarget info after parsing the inline asm, - /// or NULL if the value is unknown. - virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, - const MCSubtargetInfo *EndInfo) const; - - /// This emits visibility information about symbol, if this is supported by - /// the target. - void emitVisibility(MCSymbol *Sym, unsigned Visibility, - bool IsDefinition = true) const; - - /// This emits linkage information about \p GVSym based on \p GV, if this is - /// supported by the target. - virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; - - /// Return the alignment for the specified \p GV. - static Align getGVAlignment(const GlobalObject *GV, const DataLayout &DL, - Align InAlign = Align(1)); - -private: - /// Private state for PrintSpecial() - // Assign a unique ID to this machine instruction. - mutable const MachineInstr *LastMI = nullptr; - mutable unsigned LastFn = 0; - mutable unsigned Counter = ~0U; - - /// This method emits the header for the current function. - virtual void emitFunctionHeader(); - - /// This method emits a comment next to header for the current function. - virtual void emitFunctionHeaderComment(); - - /// Emit a blob of inline asm to the output streamer. - void - emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, - const MCTargetOptions &MCOptions, - const MDNode *LocMDNode = nullptr, - InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; - - /// This method formats and emits the specified machine instruction that is an - /// inline asm. - void emitInlineAsm(const MachineInstr *MI) const; - - /// Add inline assembly info to the diagnostics machinery, so we can - /// emit file and position info. Returns SrcMgr memory buffer position. - unsigned addInlineAsmDiagBuffer(StringRef AsmStr, - const MDNode *LocMDNode) const; - - //===------------------------------------------------------------------===// - // Internal Implementation Details - //===------------------------------------------------------------------===// - - void emitJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, unsigned uid) const; - void emitLLVMUsedList(const ConstantArray *InitList); - /// Emit llvm.ident metadata in an '.ident' directive. - void emitModuleIdents(Module &M); - /// Emit bytes for llvm.commandline metadata. - void emitModuleCommandLines(Module &M); - - GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &S); - void emitGlobalAlias(Module &M, const GlobalAlias &GA); - void emitGlobalIFunc(Module &M, const GlobalIFunc &GI); - - /// This method decides whether the specified basic block requires a label. - bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const; - -protected: - virtual bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const { - return false; - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_ASMPRINTER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinterHandler.h b/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinterHandler.h deleted file mode 100644 index dc81a30400..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/AsmPrinterHandler.h +++ /dev/null @@ -1,84 +0,0 @@ -//===-- llvm/CodeGen/AsmPrinterHandler.h -----------------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains a generic interface for AsmPrinter handlers, -// like debug and EH info emitters. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ASMPRINTERHANDLER_H -#define LLVM_CODEGEN_ASMPRINTERHANDLER_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class AsmPrinter; -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MCSymbol; -class Module; - -typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm, - const MachineBasicBlock *MBB); - -/// Collects and handles AsmPrinter objects required to build debug -/// or EH information. -class AsmPrinterHandler { -public: - virtual ~AsmPrinterHandler(); - - /// For symbols that have a size designated (e.g. common symbols), - /// this tracks that size. - virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0; - - virtual void beginModule(Module *M) {} - - /// Emit all sections that should come after the content. - virtual void endModule() = 0; - - /// Gather pre-function debug information. - /// Every beginFunction(MF) call should be followed by an endFunction(MF) - /// call. - virtual void beginFunction(const MachineFunction *MF) = 0; - - // Emit any of function marker (like .cfi_endproc). This is called - // before endFunction and cannot switch sections. - virtual void markFunctionEnd(); - - /// Gather post-function debug information. - /// Please note that some AsmPrinter implementations may not call - /// beginFunction at all. - virtual void endFunction(const MachineFunction *MF) = 0; - - virtual void beginFragment(const MachineBasicBlock *MBB, - ExceptionSymbolProvider ESP) {} - virtual void endFragment() {} - - /// Emit target-specific EH funclet machinery. - virtual void beginFunclet(const MachineBasicBlock &MBB, - MCSymbol *Sym = nullptr) {} - virtual void endFunclet() {} - - /// Process beginning of an instruction. - virtual void beginInstruction(const MachineInstr *MI) = 0; - - /// Process end of an instruction. - virtual void endInstruction() = 0; - - /// Process beginning of a basic block during basic block sections. - virtual void beginBasicBlock(const MachineBasicBlock &MBB) {} - - /// Process end of a basic block during basic block sections. - virtual void endBasicBlock(const MachineBasicBlock &MBB) {} -}; - -} // End of namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/AtomicExpandUtils.h b/suite/synctools/tablegen/include/llvm/CodeGen/AtomicExpandUtils.h deleted file mode 100644 index 7615ddb0ab..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/AtomicExpandUtils.h +++ /dev/null @@ -1,64 +0,0 @@ -//===- AtomicExpandUtils.h - Utilities for expanding atomic instructions --===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ATOMICEXPANDUTILS_H -#define LLVM_CODEGEN_ATOMICEXPANDUTILS_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/Support/AtomicOrdering.h" - -namespace llvm { - -class AtomicRMWInst; -class Value; - -/// Parameters (see the expansion example below): -/// (the builder, %addr, %loaded, %new_val, ordering, -/// /* OUT */ %success, /* OUT */ %new_loaded) -using CreateCmpXchgInstFun = - function_ref &, Value *, Value *, Value *, Align, - AtomicOrdering, SyncScope::ID, Value *&, Value *&)>; - -/// Expand an atomic RMW instruction into a loop utilizing -/// cmpxchg. You'll want to make sure your target machine likes cmpxchg -/// instructions in the first place and that there isn't another, better, -/// transformation available (for example AArch32/AArch64 have linked loads). -/// -/// This is useful in passes which can't rewrite the more exotic RMW -/// instructions directly into a platform specific intrinsics (because, say, -/// those intrinsics don't exist). If such a pass is able to expand cmpxchg -/// instructions directly however, then, with this function, it could avoid two -/// extra module passes (avoiding passes by `-atomic-expand` and itself). A -/// specific example would be PNaCl's `RewriteAtomics` pass. -/// -/// Given: atomicrmw some_op iN* %addr, iN %incr ordering -/// -/// The standard expansion we produce is: -/// [...] -/// %init_loaded = load atomic iN* %addr -/// br label %loop -/// loop: -/// %loaded = phi iN [ %init_loaded, %entry ], [ %new_loaded, %loop ] -/// %new = some_op iN %loaded, %incr -/// ; This is what -atomic-expand will produce using this function on i686 -/// targets: -/// %pair = cmpxchg iN* %addr, iN %loaded, iN %new_val -/// %new_loaded = extractvalue { iN, i1 } %pair, 0 -/// %success = extractvalue { iN, i1 } %pair, 1 -/// ; End callback produced IR -/// br i1 %success, label %atomicrmw.end, label %loop -/// atomicrmw.end: -/// [...] -/// -/// Returns true if the containing function was modified. -bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_ATOMICEXPANDUTILS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/BasicBlockSectionUtils.h b/suite/synctools/tablegen/include/llvm/CodeGen/BasicBlockSectionUtils.h deleted file mode 100644 index d8da3be0cd..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/BasicBlockSectionUtils.h +++ /dev/null @@ -1,30 +0,0 @@ -//===- BasicBlockSectionUtils.h - Utilities for basic block sections --===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H -#define LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/CommandLine.h" - -namespace llvm { - -extern cl::opt BBSectionsColdTextPrefix; - -class MachineFunction; -class MachineBasicBlock; - -using MachineBasicBlockComparator = - function_ref; - -void sortBasicBlocksAndUpdateBranches(MachineFunction &MF, - MachineBasicBlockComparator MBBCmp); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/BasicTTIImpl.h b/suite/synctools/tablegen/include/llvm/CodeGen/BasicTTIImpl.h deleted file mode 100644 index 83e09115e5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/BasicTTIImpl.h +++ /dev/null @@ -1,2262 +0,0 @@ -//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file provides a helper that implements much of the TTI interface in -/// terms of the target-independent code generator and TargetLowering -/// interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_BASICTTIIMPL_H -#define LLVM_CODEGEN_BASICTTIIMPL_H - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Analysis/TargetTransformInfoImpl.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetMachine.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class Function; -class GlobalValue; -class LLVMContext; -class ScalarEvolution; -class SCEV; -class TargetMachine; - -extern cl::opt PartialUnrollingThreshold; - -/// Base class which can be used to help build a TTI implementation. -/// -/// This class provides as much implementation of the TTI interface as is -/// possible using the target independent parts of the code generator. -/// -/// In order to subclass it, your class must implement a getST() method to -/// return the subtarget, and a getTLI() method to return the target lowering. -/// We need these methods implemented in the derived class so that this class -/// doesn't have to duplicate storage for them. -template -class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { -private: - using BaseT = TargetTransformInfoImplCRTPBase; - using TTI = TargetTransformInfo; - - /// Helper function to access this as a T. - T *thisT() { return static_cast(this); } - - /// Estimate a cost of Broadcast as an extract and sequence of insert - /// operations. - InstructionCost getBroadcastShuffleOverhead(FixedVectorType *VTy) { - InstructionCost Cost = 0; - // Broadcast cost is equal to the cost of extracting the zero'th element - // plus the cost of inserting it into every element of the result vector. - Cost += thisT()->getVectorInstrCost(Instruction::ExtractElement, VTy, 0); - - for (int i = 0, e = VTy->getNumElements(); i < e; ++i) { - Cost += thisT()->getVectorInstrCost(Instruction::InsertElement, VTy, i); - } - return Cost; - } - - /// Estimate a cost of shuffle as a sequence of extract and insert - /// operations. - InstructionCost getPermuteShuffleOverhead(FixedVectorType *VTy) { - InstructionCost Cost = 0; - // Shuffle cost is equal to the cost of extracting element from its argument - // plus the cost of inserting them onto the result vector. - - // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from - // index 0 of first vector, index 1 of second vector,index 2 of first - // vector and finally index 3 of second vector and insert them at index - // <0,1,2,3> of result vector. - for (int i = 0, e = VTy->getNumElements(); i < e; ++i) { - Cost += thisT()->getVectorInstrCost(Instruction::InsertElement, VTy, i); - Cost += thisT()->getVectorInstrCost(Instruction::ExtractElement, VTy, i); - } - return Cost; - } - - /// Estimate a cost of subvector extraction as a sequence of extract and - /// insert operations. - InstructionCost getExtractSubvectorOverhead(VectorType *VTy, int Index, - FixedVectorType *SubVTy) { - assert(VTy && SubVTy && - "Can only extract subvectors from vectors"); - int NumSubElts = SubVTy->getNumElements(); - assert((!isa(VTy) || - (Index + NumSubElts) <= - (int)cast(VTy)->getNumElements()) && - "SK_ExtractSubvector index out of range"); - - InstructionCost Cost = 0; - // Subvector extraction cost is equal to the cost of extracting element from - // the source type plus the cost of inserting them into the result vector - // type. - for (int i = 0; i != NumSubElts; ++i) { - Cost += thisT()->getVectorInstrCost(Instruction::ExtractElement, VTy, - i + Index); - Cost += - thisT()->getVectorInstrCost(Instruction::InsertElement, SubVTy, i); - } - return Cost; - } - - /// Estimate a cost of subvector insertion as a sequence of extract and - /// insert operations. - InstructionCost getInsertSubvectorOverhead(VectorType *VTy, int Index, - FixedVectorType *SubVTy) { - assert(VTy && SubVTy && - "Can only insert subvectors into vectors"); - int NumSubElts = SubVTy->getNumElements(); - assert((!isa(VTy) || - (Index + NumSubElts) <= - (int)cast(VTy)->getNumElements()) && - "SK_InsertSubvector index out of range"); - - InstructionCost Cost = 0; - // Subvector insertion cost is equal to the cost of extracting element from - // the source type plus the cost of inserting them into the result vector - // type. - for (int i = 0; i != NumSubElts; ++i) { - Cost += - thisT()->getVectorInstrCost(Instruction::ExtractElement, SubVTy, i); - Cost += thisT()->getVectorInstrCost(Instruction::InsertElement, VTy, - i + Index); - } - return Cost; - } - - /// Local query method delegates up to T which *must* implement this! - const TargetSubtargetInfo *getST() const { - return static_cast(this)->getST(); - } - - /// Local query method delegates up to T which *must* implement this! - const TargetLoweringBase *getTLI() const { - return static_cast(this)->getTLI(); - } - - static ISD::MemIndexedMode getISDIndexedMode(TTI::MemIndexedMode M) { - switch (M) { - case TTI::MIM_Unindexed: - return ISD::UNINDEXED; - case TTI::MIM_PreInc: - return ISD::PRE_INC; - case TTI::MIM_PreDec: - return ISD::PRE_DEC; - case TTI::MIM_PostInc: - return ISD::POST_INC; - case TTI::MIM_PostDec: - return ISD::POST_DEC; - } - llvm_unreachable("Unexpected MemIndexedMode"); - } - - InstructionCost getCommonMaskedMemoryOpCost(unsigned Opcode, Type *DataTy, - Align Alignment, - bool VariableMask, - bool IsGatherScatter, - TTI::TargetCostKind CostKind) { - auto *VT = cast(DataTy); - // Assume the target does not have support for gather/scatter operations - // and provide a rough estimate. - // - // First, compute the cost of the individual memory operations. - InstructionCost AddrExtractCost = - IsGatherScatter - ? getVectorInstrCost(Instruction::ExtractElement, - FixedVectorType::get( - PointerType::get(VT->getElementType(), 0), - VT->getNumElements()), - -1) - : 0; - InstructionCost LoadCost = - VT->getNumElements() * - (AddrExtractCost + - getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind)); - - // Next, compute the cost of packing the result in a vector. - InstructionCost PackingCost = getScalarizationOverhead( - VT, Opcode != Instruction::Store, Opcode == Instruction::Store); - - InstructionCost ConditionalCost = 0; - if (VariableMask) { - // Compute the cost of conditionally executing the memory operations with - // variable masks. This includes extracting the individual conditions, a - // branches and PHIs to combine the results. - // NOTE: Estimating the cost of conditionally executing the memory - // operations accurately is quite difficult and the current solution - // provides a very rough estimate only. - ConditionalCost = - VT->getNumElements() * - (getVectorInstrCost( - Instruction::ExtractElement, - FixedVectorType::get(Type::getInt1Ty(DataTy->getContext()), - VT->getNumElements()), - -1) + - getCFInstrCost(Instruction::Br, CostKind) + - getCFInstrCost(Instruction::PHI, CostKind)); - } - - return LoadCost + PackingCost + ConditionalCost; - } - -protected: - explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL) - : BaseT(DL) {} - virtual ~BasicTTIImplBase() = default; - - using TargetTransformInfoImplBase::DL; - -public: - /// \name Scalar TTI Implementations - /// @{ - bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, - unsigned AddressSpace, Align Alignment, - bool *Fast) const { - EVT E = EVT::getIntegerVT(Context, BitWidth); - return getTLI()->allowsMisalignedMemoryAccesses( - E, AddressSpace, Alignment, MachineMemOperand::MONone, Fast); - } - - bool hasBranchDivergence() { return false; } - - bool useGPUDivergenceAnalysis() { return false; } - - bool isSourceOfDivergence(const Value *V) { return false; } - - bool isAlwaysUniform(const Value *V) { return false; } - - unsigned getFlatAddressSpace() { - // Return an invalid address space. - return -1; - } - - bool collectFlatAddressOperands(SmallVectorImpl &OpIndexes, - Intrinsic::ID IID) const { - return false; - } - - bool isNoopAddrSpaceCast(unsigned FromAS, unsigned ToAS) const { - return getTLI()->getTargetMachine().isNoopAddrSpaceCast(FromAS, ToAS); - } - - unsigned getAssumedAddrSpace(const Value *V) const { - return getTLI()->getTargetMachine().getAssumedAddrSpace(V); - } - - std::pair - getPredicatedAddrSpace(const Value *V) const { - return getTLI()->getTargetMachine().getPredicatedAddrSpace(V); - } - - Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, - Value *NewV) const { - return nullptr; - } - - bool isLegalAddImmediate(int64_t imm) { - return getTLI()->isLegalAddImmediate(imm); - } - - bool isLegalICmpImmediate(int64_t imm) { - return getTLI()->isLegalICmpImmediate(imm); - } - - bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, - bool HasBaseReg, int64_t Scale, - unsigned AddrSpace, Instruction *I = nullptr) { - TargetLoweringBase::AddrMode AM; - AM.BaseGV = BaseGV; - AM.BaseOffs = BaseOffset; - AM.HasBaseReg = HasBaseReg; - AM.Scale = Scale; - return getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace, I); - } - - bool isIndexedLoadLegal(TTI::MemIndexedMode M, Type *Ty, - const DataLayout &DL) const { - EVT VT = getTLI()->getValueType(DL, Ty); - return getTLI()->isIndexedLoadLegal(getISDIndexedMode(M), VT); - } - - bool isIndexedStoreLegal(TTI::MemIndexedMode M, Type *Ty, - const DataLayout &DL) const { - EVT VT = getTLI()->getValueType(DL, Ty); - return getTLI()->isIndexedStoreLegal(getISDIndexedMode(M), VT); - } - - bool isLSRCostLess(TTI::LSRCost C1, TTI::LSRCost C2) { - return TargetTransformInfoImplBase::isLSRCostLess(C1, C2); - } - - bool isNumRegsMajorCostOfLSR() { - return TargetTransformInfoImplBase::isNumRegsMajorCostOfLSR(); - } - - bool isProfitableLSRChainElement(Instruction *I) { - return TargetTransformInfoImplBase::isProfitableLSRChainElement(I); - } - - InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale, unsigned AddrSpace) { - TargetLoweringBase::AddrMode AM; - AM.BaseGV = BaseGV; - AM.BaseOffs = BaseOffset; - AM.HasBaseReg = HasBaseReg; - AM.Scale = Scale; - return getTLI()->getScalingFactorCost(DL, AM, Ty, AddrSpace); - } - - bool isTruncateFree(Type *Ty1, Type *Ty2) { - return getTLI()->isTruncateFree(Ty1, Ty2); - } - - bool isProfitableToHoist(Instruction *I) { - return getTLI()->isProfitableToHoist(I); - } - - bool useAA() const { return getST()->useAA(); } - - bool isTypeLegal(Type *Ty) { - EVT VT = getTLI()->getValueType(DL, Ty); - return getTLI()->isTypeLegal(VT); - } - - InstructionCost getRegUsageForType(Type *Ty) { - InstructionCost Val = getTLI()->getTypeLegalizationCost(DL, Ty).first; - assert(Val >= 0 && "Negative cost!"); - return Val; - } - - InstructionCost getGEPCost(Type *PointeeType, const Value *Ptr, - ArrayRef Operands, - TTI::TargetCostKind CostKind) { - return BaseT::getGEPCost(PointeeType, Ptr, Operands, CostKind); - } - - unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, - unsigned &JumpTableSize, - ProfileSummaryInfo *PSI, - BlockFrequencyInfo *BFI) { - /// Try to find the estimated number of clusters. Note that the number of - /// clusters identified in this function could be different from the actual - /// numbers found in lowering. This function ignore switches that are - /// lowered with a mix of jump table / bit test / BTree. This function was - /// initially intended to be used when estimating the cost of switch in - /// inline cost heuristic, but it's a generic cost model to be used in other - /// places (e.g., in loop unrolling). - unsigned N = SI.getNumCases(); - const TargetLoweringBase *TLI = getTLI(); - const DataLayout &DL = this->getDataLayout(); - - JumpTableSize = 0; - bool IsJTAllowed = TLI->areJTsAllowed(SI.getParent()->getParent()); - - // Early exit if both a jump table and bit test are not allowed. - if (N < 1 || (!IsJTAllowed && DL.getIndexSizeInBits(0u) < N)) - return N; - - APInt MaxCaseVal = SI.case_begin()->getCaseValue()->getValue(); - APInt MinCaseVal = MaxCaseVal; - for (auto CI : SI.cases()) { - const APInt &CaseVal = CI.getCaseValue()->getValue(); - if (CaseVal.sgt(MaxCaseVal)) - MaxCaseVal = CaseVal; - if (CaseVal.slt(MinCaseVal)) - MinCaseVal = CaseVal; - } - - // Check if suitable for a bit test - if (N <= DL.getIndexSizeInBits(0u)) { - SmallPtrSet Dests; - for (auto I : SI.cases()) - Dests.insert(I.getCaseSuccessor()); - - if (TLI->isSuitableForBitTests(Dests.size(), N, MinCaseVal, MaxCaseVal, - DL)) - return 1; - } - - // Check if suitable for a jump table. - if (IsJTAllowed) { - if (N < 2 || N < TLI->getMinimumJumpTableEntries()) - return N; - uint64_t Range = - (MaxCaseVal - MinCaseVal) - .getLimitedValue(std::numeric_limits::max() - 1) + 1; - // Check whether a range of clusters is dense enough for a jump table - if (TLI->isSuitableForJumpTable(&SI, N, Range, PSI, BFI)) { - JumpTableSize = Range; - return 1; - } - } - return N; - } - - bool shouldBuildLookupTables() { - const TargetLoweringBase *TLI = getTLI(); - return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || - TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other); - } - - bool shouldBuildRelLookupTables() const { - const TargetMachine &TM = getTLI()->getTargetMachine(); - // If non-PIC mode, do not generate a relative lookup table. - if (!TM.isPositionIndependent()) - return false; - - /// Relative lookup table entries consist of 32-bit offsets. - /// Do not generate relative lookup tables for large code models - /// in 64-bit architectures where 32-bit offsets might not be enough. - if (TM.getCodeModel() == CodeModel::Medium || - TM.getCodeModel() == CodeModel::Large) - return false; - - Triple TargetTriple = TM.getTargetTriple(); - if (!TargetTriple.isArch64Bit()) - return false; - - // TODO: Triggers issues on aarch64 on darwin, so temporarily disable it - // there. - if (TargetTriple.getArch() == Triple::aarch64 && TargetTriple.isOSDarwin()) - return false; - - return true; - } - - bool haveFastSqrt(Type *Ty) { - const TargetLoweringBase *TLI = getTLI(); - EVT VT = TLI->getValueType(DL, Ty); - return TLI->isTypeLegal(VT) && - TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); - } - - bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) { - return true; - } - - InstructionCost getFPOpCost(Type *Ty) { - // Check whether FADD is available, as a proxy for floating-point in - // general. - const TargetLoweringBase *TLI = getTLI(); - EVT VT = TLI->getValueType(DL, Ty); - if (TLI->isOperationLegalOrCustomOrPromote(ISD::FADD, VT)) - return TargetTransformInfo::TCC_Basic; - return TargetTransformInfo::TCC_Expensive; - } - - unsigned getInliningThresholdMultiplier() { return 1; } - unsigned adjustInliningThreshold(const CallBase *CB) { return 0; } - - int getInlinerVectorBonusPercent() { return 150; } - - void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, - TTI::UnrollingPreferences &UP, - OptimizationRemarkEmitter *ORE) { - // This unrolling functionality is target independent, but to provide some - // motivation for its intended use, for x86: - - // According to the Intel 64 and IA-32 Architectures Optimization Reference - // Manual, Intel Core models and later have a loop stream detector (and - // associated uop queue) that can benefit from partial unrolling. - // The relevant requirements are: - // - The loop must have no more than 4 (8 for Nehalem and later) branches - // taken, and none of them may be calls. - // - The loop can have no more than 18 (28 for Nehalem and later) uops. - - // According to the Software Optimization Guide for AMD Family 15h - // Processors, models 30h-4fh (Steamroller and later) have a loop predictor - // and loop buffer which can benefit from partial unrolling. - // The relevant requirements are: - // - The loop must have fewer than 16 branches - // - The loop must have less than 40 uops in all executed loop branches - - // The number of taken branches in a loop is hard to estimate here, and - // benchmarking has revealed that it is better not to be conservative when - // estimating the branch count. As a result, we'll ignore the branch limits - // until someone finds a case where it matters in practice. - - unsigned MaxOps; - const TargetSubtargetInfo *ST = getST(); - if (PartialUnrollingThreshold.getNumOccurrences() > 0) - MaxOps = PartialUnrollingThreshold; - else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) - MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; - else - return; - - // Scan the loop: don't unroll loops with calls. - for (BasicBlock *BB : L->blocks()) { - for (Instruction &I : *BB) { - if (isa(I) || isa(I)) { - if (const Function *F = cast(I).getCalledFunction()) { - if (!thisT()->isLoweredToCall(F)) - continue; - } - - if (ORE) { - ORE->emit([&]() { - return OptimizationRemark("TTI", "DontUnroll", L->getStartLoc(), - L->getHeader()) - << "advising against unrolling the loop because it " - "contains a " - << ore::NV("Call", &I); - }); - } - return; - } - } - } - - // Enable runtime and partial unrolling up to the specified size. - // Enable using trip count upper bound to unroll loops. - UP.Partial = UP.Runtime = UP.UpperBound = true; - UP.PartialThreshold = MaxOps; - - // Avoid unrolling when optimizing for size. - UP.OptSizeThreshold = 0; - UP.PartialOptSizeThreshold = 0; - - // Set number of instructions optimized when "back edge" - // becomes "fall through" to default value of 2. - UP.BEInsns = 2; - } - - void getPeelingPreferences(Loop *L, ScalarEvolution &SE, - TTI::PeelingPreferences &PP) { - PP.PeelCount = 0; - PP.AllowPeeling = true; - PP.AllowLoopNestsPeeling = false; - PP.PeelProfiledIterations = true; - } - - bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, - AssumptionCache &AC, - TargetLibraryInfo *LibInfo, - HardwareLoopInfo &HWLoopInfo) { - return BaseT::isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo); - } - - bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE, - AssumptionCache &AC, TargetLibraryInfo *TLI, - DominatorTree *DT, - const LoopAccessInfo *LAI) { - return BaseT::preferPredicateOverEpilogue(L, LI, SE, AC, TLI, DT, LAI); - } - - bool emitGetActiveLaneMask() { - return BaseT::emitGetActiveLaneMask(); - } - - Optional instCombineIntrinsic(InstCombiner &IC, - IntrinsicInst &II) { - return BaseT::instCombineIntrinsic(IC, II); - } - - Optional simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, - IntrinsicInst &II, - APInt DemandedMask, - KnownBits &Known, - bool &KnownBitsComputed) { - return BaseT::simplifyDemandedUseBitsIntrinsic(IC, II, DemandedMask, Known, - KnownBitsComputed); - } - - Optional simplifyDemandedVectorEltsIntrinsic( - InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, - APInt &UndefElts2, APInt &UndefElts3, - std::function - SimplifyAndSetOp) { - return BaseT::simplifyDemandedVectorEltsIntrinsic( - IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3, - SimplifyAndSetOp); - } - - InstructionCost getInstructionLatency(const Instruction *I) { - if (isa(I)) - return getST()->getSchedModel().DefaultLoadLatency; - - return BaseT::getInstructionLatency(I); - } - - virtual Optional - getCacheSize(TargetTransformInfo::CacheLevel Level) const { - return Optional( - getST()->getCacheSize(static_cast(Level))); - } - - virtual Optional - getCacheAssociativity(TargetTransformInfo::CacheLevel Level) const { - Optional TargetResult = - getST()->getCacheAssociativity(static_cast(Level)); - - if (TargetResult) - return TargetResult; - - return BaseT::getCacheAssociativity(Level); - } - - virtual unsigned getCacheLineSize() const { - return getST()->getCacheLineSize(); - } - - virtual unsigned getPrefetchDistance() const { - return getST()->getPrefetchDistance(); - } - - virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses, - unsigned NumStridedMemAccesses, - unsigned NumPrefetches, - bool HasCall) const { - return getST()->getMinPrefetchStride(NumMemAccesses, NumStridedMemAccesses, - NumPrefetches, HasCall); - } - - virtual unsigned getMaxPrefetchIterationsAhead() const { - return getST()->getMaxPrefetchIterationsAhead(); - } - - virtual bool enableWritePrefetching() const { - return getST()->enableWritePrefetching(); - } - - /// @} - - /// \name Vector TTI Implementations - /// @{ - - TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const { - return TypeSize::getFixed(32); - } - - Optional getMaxVScale() const { return None; } - Optional getVScaleForTuning() const { return None; } - - /// Estimate the overhead of scalarizing an instruction. Insert and Extract - /// are set if the demanded result elements need to be inserted and/or - /// extracted from vectors. - InstructionCost getScalarizationOverhead(VectorType *InTy, - const APInt &DemandedElts, - bool Insert, bool Extract) { - /// FIXME: a bitfield is not a reasonable abstraction for talking about - /// which elements are needed from a scalable vector - auto *Ty = cast(InTy); - - assert(DemandedElts.getBitWidth() == Ty->getNumElements() && - "Vector size mismatch"); - - InstructionCost Cost = 0; - - for (int i = 0, e = Ty->getNumElements(); i < e; ++i) { - if (!DemandedElts[i]) - continue; - if (Insert) - Cost += thisT()->getVectorInstrCost(Instruction::InsertElement, Ty, i); - if (Extract) - Cost += thisT()->getVectorInstrCost(Instruction::ExtractElement, Ty, i); - } - - return Cost; - } - - /// Helper wrapper for the DemandedElts variant of getScalarizationOverhead. - InstructionCost getScalarizationOverhead(VectorType *InTy, bool Insert, - bool Extract) { - auto *Ty = cast(InTy); - - APInt DemandedElts = APInt::getAllOnes(Ty->getNumElements()); - return thisT()->getScalarizationOverhead(Ty, DemandedElts, Insert, Extract); - } - - /// Estimate the overhead of scalarizing an instructions unique - /// non-constant operands. The (potentially vector) types to use for each of - /// argument are passes via Tys. - InstructionCost getOperandsScalarizationOverhead(ArrayRef Args, - ArrayRef Tys) { - assert(Args.size() == Tys.size() && "Expected matching Args and Tys"); - - InstructionCost Cost = 0; - SmallPtrSet UniqueOperands; - for (int I = 0, E = Args.size(); I != E; I++) { - // Disregard things like metadata arguments. - const Value *A = Args[I]; - Type *Ty = Tys[I]; - if (!Ty->isIntOrIntVectorTy() && !Ty->isFPOrFPVectorTy() && - !Ty->isPtrOrPtrVectorTy()) - continue; - - if (!isa(A) && UniqueOperands.insert(A).second) { - if (auto *VecTy = dyn_cast(Ty)) - Cost += getScalarizationOverhead(VecTy, false, true); - } - } - - return Cost; - } - - /// Estimate the overhead of scalarizing the inputs and outputs of an - /// instruction, with return type RetTy and arguments Args of type Tys. If - /// Args are unknown (empty), then the cost associated with one argument is - /// added as a heuristic. - InstructionCost getScalarizationOverhead(VectorType *RetTy, - ArrayRef Args, - ArrayRef Tys) { - InstructionCost Cost = getScalarizationOverhead(RetTy, true, false); - if (!Args.empty()) - Cost += getOperandsScalarizationOverhead(Args, Tys); - else - // When no information on arguments is provided, we add the cost - // associated with one argument as a heuristic. - Cost += getScalarizationOverhead(RetTy, false, true); - - return Cost; - } - - unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } - - InstructionCost getArithmeticInstrCost( - unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, - TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, - TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, - TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, - TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, - ArrayRef Args = ArrayRef(), - const Instruction *CxtI = nullptr) { - // Check if any of the operands are vector operands. - const TargetLoweringBase *TLI = getTLI(); - int ISD = TLI->InstructionOpcodeToISD(Opcode); - assert(ISD && "Invalid opcode"); - - // TODO: Handle more cost kinds. - if (CostKind != TTI::TCK_RecipThroughput) - return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, - Opd1Info, Opd2Info, - Opd1PropInfo, Opd2PropInfo, - Args, CxtI); - - std::pair LT = TLI->getTypeLegalizationCost(DL, Ty); - - bool IsFloat = Ty->isFPOrFPVectorTy(); - // Assume that floating point arithmetic operations cost twice as much as - // integer operations. - InstructionCost OpCost = (IsFloat ? 2 : 1); - - if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { - // The operation is legal. Assume it costs 1. - // TODO: Once we have extract/insert subvector cost we need to use them. - return LT.first * OpCost; - } - - if (!TLI->isOperationExpand(ISD, LT.second)) { - // If the operation is custom lowered, then assume that the code is twice - // as expensive. - return LT.first * 2 * OpCost; - } - - // An 'Expand' of URem and SRem is special because it may default - // to expanding the operation into a sequence of sub-operations - // i.e. X % Y -> X-(X/Y)*Y. - if (ISD == ISD::UREM || ISD == ISD::SREM) { - bool IsSigned = ISD == ISD::SREM; - if (TLI->isOperationLegalOrCustom(IsSigned ? ISD::SDIVREM : ISD::UDIVREM, - LT.second) || - TLI->isOperationLegalOrCustom(IsSigned ? ISD::SDIV : ISD::UDIV, - LT.second)) { - unsigned DivOpc = IsSigned ? Instruction::SDiv : Instruction::UDiv; - InstructionCost DivCost = thisT()->getArithmeticInstrCost( - DivOpc, Ty, CostKind, Opd1Info, Opd2Info, Opd1PropInfo, - Opd2PropInfo); - InstructionCost MulCost = - thisT()->getArithmeticInstrCost(Instruction::Mul, Ty, CostKind); - InstructionCost SubCost = - thisT()->getArithmeticInstrCost(Instruction::Sub, Ty, CostKind); - return DivCost + MulCost + SubCost; - } - } - - // We cannot scalarize scalable vectors, so return Invalid. - if (isa(Ty)) - return InstructionCost::getInvalid(); - - // Else, assume that we need to scalarize this op. - // TODO: If one of the types get legalized by splitting, handle this - // similarly to what getCastInstrCost() does. - if (auto *VTy = dyn_cast(Ty)) { - InstructionCost Cost = thisT()->getArithmeticInstrCost( - Opcode, VTy->getScalarType(), CostKind, Opd1Info, Opd2Info, - Opd1PropInfo, Opd2PropInfo, Args, CxtI); - // Return the cost of multiple scalar invocation plus the cost of - // inserting and extracting the values. - SmallVector Tys(Args.size(), Ty); - return getScalarizationOverhead(VTy, Args, Tys) + - VTy->getNumElements() * Cost; - } - - // We don't know anything about this scalar instruction. - return OpCost; - } - - TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, - ArrayRef Mask) const { - int Limit = Mask.size() * 2; - if (Mask.empty() || - // Extra check required by isSingleSourceMaskImpl function (called by - // ShuffleVectorInst::isSingleSourceMask). - any_of(Mask, [Limit](int I) { return I >= Limit; })) - return Kind; - switch (Kind) { - case TTI::SK_PermuteSingleSrc: - if (ShuffleVectorInst::isReverseMask(Mask)) - return TTI::SK_Reverse; - if (ShuffleVectorInst::isZeroEltSplatMask(Mask)) - return TTI::SK_Broadcast; - break; - case TTI::SK_PermuteTwoSrc: - if (ShuffleVectorInst::isSelectMask(Mask)) - return TTI::SK_Select; - if (ShuffleVectorInst::isTransposeMask(Mask)) - return TTI::SK_Transpose; - break; - case TTI::SK_Select: - case TTI::SK_Reverse: - case TTI::SK_Broadcast: - case TTI::SK_Transpose: - case TTI::SK_InsertSubvector: - case TTI::SK_ExtractSubvector: - case TTI::SK_Splice: - break; - } - return Kind; - } - - InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *Tp, - ArrayRef Mask, int Index, - VectorType *SubTp) { - - switch (improveShuffleKindFromMask(Kind, Mask)) { - case TTI::SK_Broadcast: - if (auto *FVT = dyn_cast(Tp)) - return getBroadcastShuffleOverhead(FVT); - return InstructionCost::getInvalid(); - case TTI::SK_Select: - case TTI::SK_Splice: - case TTI::SK_Reverse: - case TTI::SK_Transpose: - case TTI::SK_PermuteSingleSrc: - case TTI::SK_PermuteTwoSrc: - if (auto *FVT = dyn_cast(Tp)) - return getPermuteShuffleOverhead(FVT); - return InstructionCost::getInvalid(); - case TTI::SK_ExtractSubvector: - return getExtractSubvectorOverhead(Tp, Index, - cast(SubTp)); - case TTI::SK_InsertSubvector: - return getInsertSubvectorOverhead(Tp, Index, - cast(SubTp)); - } - llvm_unreachable("Unknown TTI::ShuffleKind"); - } - - InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, - TTI::CastContextHint CCH, - TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { - if (BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I) == 0) - return 0; - - const TargetLoweringBase *TLI = getTLI(); - int ISD = TLI->InstructionOpcodeToISD(Opcode); - assert(ISD && "Invalid opcode"); - std::pair SrcLT = - TLI->getTypeLegalizationCost(DL, Src); - std::pair DstLT = - TLI->getTypeLegalizationCost(DL, Dst); - - TypeSize SrcSize = SrcLT.second.getSizeInBits(); - TypeSize DstSize = DstLT.second.getSizeInBits(); - bool IntOrPtrSrc = Src->isIntegerTy() || Src->isPointerTy(); - bool IntOrPtrDst = Dst->isIntegerTy() || Dst->isPointerTy(); - - switch (Opcode) { - default: - break; - case Instruction::Trunc: - // Check for NOOP conversions. - if (TLI->isTruncateFree(SrcLT.second, DstLT.second)) - return 0; - LLVM_FALLTHROUGH; - case Instruction::BitCast: - // Bitcast between types that are legalized to the same type are free and - // assume int to/from ptr of the same size is also free. - if (SrcLT.first == DstLT.first && IntOrPtrSrc == IntOrPtrDst && - SrcSize == DstSize) - return 0; - break; - case Instruction::FPExt: - if (I && getTLI()->isExtFree(I)) - return 0; - break; - case Instruction::ZExt: - if (TLI->isZExtFree(SrcLT.second, DstLT.second)) - return 0; - LLVM_FALLTHROUGH; - case Instruction::SExt: - if (I && getTLI()->isExtFree(I)) - return 0; - - // If this is a zext/sext of a load, return 0 if the corresponding - // extending load exists on target and the result type is legal. - if (CCH == TTI::CastContextHint::Normal) { - EVT ExtVT = EVT::getEVT(Dst); - EVT LoadVT = EVT::getEVT(Src); - unsigned LType = - ((Opcode == Instruction::ZExt) ? ISD::ZEXTLOAD : ISD::SEXTLOAD); - if (DstLT.first == SrcLT.first && - TLI->isLoadExtLegal(LType, ExtVT, LoadVT)) - return 0; - } - break; - case Instruction::AddrSpaceCast: - if (TLI->isFreeAddrSpaceCast(Src->getPointerAddressSpace(), - Dst->getPointerAddressSpace())) - return 0; - break; - } - - auto *SrcVTy = dyn_cast(Src); - auto *DstVTy = dyn_cast(Dst); - - // If the cast is marked as legal (or promote) then assume low cost. - if (SrcLT.first == DstLT.first && - TLI->isOperationLegalOrPromote(ISD, DstLT.second)) - return SrcLT.first; - - // Handle scalar conversions. - if (!SrcVTy && !DstVTy) { - // Just check the op cost. If the operation is legal then assume it costs - // 1. - if (!TLI->isOperationExpand(ISD, DstLT.second)) - return 1; - - // Assume that illegal scalar instruction are expensive. - return 4; - } - - // Check vector-to-vector casts. - if (DstVTy && SrcVTy) { - // If the cast is between same-sized registers, then the check is simple. - if (SrcLT.first == DstLT.first && SrcSize == DstSize) { - - // Assume that Zext is done using AND. - if (Opcode == Instruction::ZExt) - return SrcLT.first; - - // Assume that sext is done using SHL and SRA. - if (Opcode == Instruction::SExt) - return SrcLT.first * 2; - - // Just check the op cost. If the operation is legal then assume it - // costs - // 1 and multiply by the type-legalization overhead. - if (!TLI->isOperationExpand(ISD, DstLT.second)) - return SrcLT.first * 1; - } - - // If we are legalizing by splitting, query the concrete TTI for the cost - // of casting the original vector twice. We also need to factor in the - // cost of the split itself. Count that as 1, to be consistent with - // TLI->getTypeLegalizationCost(). - bool SplitSrc = - TLI->getTypeAction(Src->getContext(), TLI->getValueType(DL, Src)) == - TargetLowering::TypeSplitVector; - bool SplitDst = - TLI->getTypeAction(Dst->getContext(), TLI->getValueType(DL, Dst)) == - TargetLowering::TypeSplitVector; - if ((SplitSrc || SplitDst) && SrcVTy->getElementCount().isVector() && - DstVTy->getElementCount().isVector()) { - Type *SplitDstTy = VectorType::getHalfElementsVectorType(DstVTy); - Type *SplitSrcTy = VectorType::getHalfElementsVectorType(SrcVTy); - T *TTI = static_cast(this); - // If both types need to be split then the split is free. - InstructionCost SplitCost = - (!SplitSrc || !SplitDst) ? TTI->getVectorSplitCost() : 0; - return SplitCost + - (2 * TTI->getCastInstrCost(Opcode, SplitDstTy, SplitSrcTy, CCH, - CostKind, I)); - } - - // Scalarization cost is Invalid, can't assume any num elements. - if (isa(DstVTy)) - return InstructionCost::getInvalid(); - - // In other cases where the source or destination are illegal, assume - // the operation will get scalarized. - unsigned Num = cast(DstVTy)->getNumElements(); - InstructionCost Cost = thisT()->getCastInstrCost( - Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind, I); - - // Return the cost of multiple scalar invocation plus the cost of - // inserting and extracting the values. - return getScalarizationOverhead(DstVTy, true, true) + Num * Cost; - } - - // We already handled vector-to-vector and scalar-to-scalar conversions. - // This - // is where we handle bitcast between vectors and scalars. We need to assume - // that the conversion is scalarized in one way or another. - if (Opcode == Instruction::BitCast) { - // Illegal bitcasts are done by storing and loading from a stack slot. - return (SrcVTy ? getScalarizationOverhead(SrcVTy, false, true) : 0) + - (DstVTy ? getScalarizationOverhead(DstVTy, true, false) : 0); - } - - llvm_unreachable("Unhandled cast"); - } - - InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, - VectorType *VecTy, unsigned Index) { - return thisT()->getVectorInstrCost(Instruction::ExtractElement, VecTy, - Index) + - thisT()->getCastInstrCost(Opcode, Dst, VecTy->getElementType(), - TTI::CastContextHint::None, - TTI::TCK_RecipThroughput); - } - - InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { - return BaseT::getCFInstrCost(Opcode, CostKind, I); - } - - InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, - CmpInst::Predicate VecPred, - TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { - const TargetLoweringBase *TLI = getTLI(); - int ISD = TLI->InstructionOpcodeToISD(Opcode); - assert(ISD && "Invalid opcode"); - - // TODO: Handle other cost kinds. - if (CostKind != TTI::TCK_RecipThroughput) - return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, - I); - - // Selects on vectors are actually vector selects. - if (ISD == ISD::SELECT) { - assert(CondTy && "CondTy must exist"); - if (CondTy->isVectorTy()) - ISD = ISD::VSELECT; - } - std::pair LT = - TLI->getTypeLegalizationCost(DL, ValTy); - - if (!(ValTy->isVectorTy() && !LT.second.isVector()) && - !TLI->isOperationExpand(ISD, LT.second)) { - // The operation is legal. Assume it costs 1. Multiply - // by the type-legalization overhead. - return LT.first * 1; - } - - // Otherwise, assume that the cast is scalarized. - // TODO: If one of the types get legalized by splitting, handle this - // similarly to what getCastInstrCost() does. - if (auto *ValVTy = dyn_cast(ValTy)) { - unsigned Num = cast(ValVTy)->getNumElements(); - if (CondTy) - CondTy = CondTy->getScalarType(); - InstructionCost Cost = thisT()->getCmpSelInstrCost( - Opcode, ValVTy->getScalarType(), CondTy, VecPred, CostKind, I); - - // Return the cost of multiple scalar invocation plus the cost of - // inserting and extracting the values. - return getScalarizationOverhead(ValVTy, true, false) + Num * Cost; - } - - // Unknown scalar opcode. - return 1; - } - - InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index) { - std::pair LT = - getTLI()->getTypeLegalizationCost(DL, Val->getScalarType()); - - return LT.first; - } - - InstructionCost getReplicationShuffleCost(Type *EltTy, int ReplicationFactor, - int VF, - const APInt &DemandedDstElts, - TTI::TargetCostKind CostKind) { - assert(DemandedDstElts.getBitWidth() == (unsigned)VF * ReplicationFactor && - "Unexpected size of DemandedDstElts."); - - InstructionCost Cost; - - auto *SrcVT = FixedVectorType::get(EltTy, VF); - auto *ReplicatedVT = FixedVectorType::get(EltTy, VF * ReplicationFactor); - - // The Mask shuffling cost is extract all the elements of the Mask - // and insert each of them Factor times into the wide vector: - // - // E.g. an interleaved group with factor 3: - // %mask = icmp ult <8 x i32> %vec1, %vec2 - // %interleaved.mask = shufflevector <8 x i1> %mask, <8 x i1> undef, - // <24 x i32> <0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7> - // The cost is estimated as extract all mask elements from the <8xi1> mask - // vector and insert them factor times into the <24xi1> shuffled mask - // vector. - APInt DemandedSrcElts = APIntOps::ScaleBitMask(DemandedDstElts, VF); - Cost += thisT()->getScalarizationOverhead(SrcVT, DemandedSrcElts, - /*Insert*/ false, - /*Extract*/ true); - Cost += - thisT()->getScalarizationOverhead(ReplicatedVT, DemandedDstElts, - /*Insert*/ true, /*Extract*/ false); - - return Cost; - } - - InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, - MaybeAlign Alignment, unsigned AddressSpace, - TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { - assert(!Src->isVoidTy() && "Invalid type"); - // Assume types, such as structs, are expensive. - if (getTLI()->getValueType(DL, Src, true) == MVT::Other) - return 4; - std::pair LT = - getTLI()->getTypeLegalizationCost(DL, Src); - - // Assuming that all loads of legal types cost 1. - InstructionCost Cost = LT.first; - if (CostKind != TTI::TCK_RecipThroughput) - return Cost; - - if (Src->isVectorTy() && - // In practice it's not currently possible to have a change in lane - // length for extending loads or truncating stores so both types should - // have the same scalable property. - TypeSize::isKnownLT(Src->getPrimitiveSizeInBits(), - LT.second.getSizeInBits())) { - // This is a vector load that legalizes to a larger type than the vector - // itself. Unless the corresponding extending load or truncating store is - // legal, then this will scalarize. - TargetLowering::LegalizeAction LA = TargetLowering::Expand; - EVT MemVT = getTLI()->getValueType(DL, Src); - if (Opcode == Instruction::Store) - LA = getTLI()->getTruncStoreAction(LT.second, MemVT); - else - LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT); - - if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { - // This is a vector load/store for some illegal type that is scalarized. - // We must account for the cost of building or decomposing the vector. - Cost += getScalarizationOverhead(cast(Src), - Opcode != Instruction::Store, - Opcode == Instruction::Store); - } - } - - return Cost; - } - - InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *DataTy, - Align Alignment, unsigned AddressSpace, - TTI::TargetCostKind CostKind) { - return getCommonMaskedMemoryOpCost(Opcode, DataTy, Alignment, true, false, - CostKind); - } - - InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy, - const Value *Ptr, bool VariableMask, - Align Alignment, - TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { - return getCommonMaskedMemoryOpCost(Opcode, DataTy, Alignment, VariableMask, - true, CostKind); - } - - InstructionCost getInterleavedMemoryOpCost( - unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, - Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, - bool UseMaskForCond = false, bool UseMaskForGaps = false) { - auto *VT = cast(VecTy); - - unsigned NumElts = VT->getNumElements(); - assert(Factor > 1 && NumElts % Factor == 0 && "Invalid interleave factor"); - - unsigned NumSubElts = NumElts / Factor; - auto *SubVT = FixedVectorType::get(VT->getElementType(), NumSubElts); - - // Firstly, the cost of load/store operation. - InstructionCost Cost; - if (UseMaskForCond || UseMaskForGaps) - Cost = thisT()->getMaskedMemoryOpCost(Opcode, VecTy, Alignment, - AddressSpace, CostKind); - else - Cost = thisT()->getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, - CostKind); - - // Legalize the vector type, and get the legalized and unlegalized type - // sizes. - MVT VecTyLT = getTLI()->getTypeLegalizationCost(DL, VecTy).second; - unsigned VecTySize = thisT()->getDataLayout().getTypeStoreSize(VecTy); - unsigned VecTyLTSize = VecTyLT.getStoreSize(); - - // Scale the cost of the memory operation by the fraction of legalized - // instructions that will actually be used. We shouldn't account for the - // cost of dead instructions since they will be removed. - // - // E.g., An interleaved load of factor 8: - // %vec = load <16 x i64>, <16 x i64>* %ptr - // %v0 = shufflevector %vec, undef, <0, 8> - // - // If <16 x i64> is legalized to 8 v2i64 loads, only 2 of the loads will be - // used (those corresponding to elements [0:1] and [8:9] of the unlegalized - // type). The other loads are unused. - // - // TODO: Note that legalization can turn masked loads/stores into unmasked - // (legalized) loads/stores. This can be reflected in the cost. - if (Cost.isValid() && VecTySize > VecTyLTSize) { - // The number of loads of a legal type it will take to represent a load - // of the unlegalized vector type. - unsigned NumLegalInsts = divideCeil(VecTySize, VecTyLTSize); - - // The number of elements of the unlegalized type that correspond to a - // single legal instruction. - unsigned NumEltsPerLegalInst = divideCeil(NumElts, NumLegalInsts); - - // Determine which legal instructions will be used. - BitVector UsedInsts(NumLegalInsts, false); - for (unsigned Index : Indices) - for (unsigned Elt = 0; Elt < NumSubElts; ++Elt) - UsedInsts.set((Index + Elt * Factor) / NumEltsPerLegalInst); - - // Scale the cost of the load by the fraction of legal instructions that - // will be used. - Cost = divideCeil(UsedInsts.count() * Cost.getValue().getValue(), - NumLegalInsts); - } - - // Then plus the cost of interleave operation. - assert(Indices.size() <= Factor && - "Interleaved memory op has too many members"); - - const APInt DemandedAllSubElts = APInt::getAllOnes(NumSubElts); - const APInt DemandedAllResultElts = APInt::getAllOnes(NumElts); - - APInt DemandedLoadStoreElts = APInt::getZero(NumElts); - for (unsigned Index : Indices) { - assert(Index < Factor && "Invalid index for interleaved memory op"); - for (unsigned Elm = 0; Elm < NumSubElts; Elm++) - DemandedLoadStoreElts.setBit(Index + Elm * Factor); - } - - if (Opcode == Instruction::Load) { - // The interleave cost is similar to extract sub vectors' elements - // from the wide vector, and insert them into sub vectors. - // - // E.g. An interleaved load of factor 2 (with one member of index 0): - // %vec = load <8 x i32>, <8 x i32>* %ptr - // %v0 = shuffle %vec, undef, <0, 2, 4, 6> ; Index 0 - // The cost is estimated as extract elements at 0, 2, 4, 6 from the - // <8 x i32> vector and insert them into a <4 x i32> vector. - InstructionCost InsSubCost = - thisT()->getScalarizationOverhead(SubVT, DemandedAllSubElts, - /*Insert*/ true, /*Extract*/ false); - Cost += Indices.size() * InsSubCost; - Cost += - thisT()->getScalarizationOverhead(VT, DemandedLoadStoreElts, - /*Insert*/ false, /*Extract*/ true); - } else { - // The interleave cost is extract elements from sub vectors, and - // insert them into the wide vector. - // - // E.g. An interleaved store of factor 3 with 2 members at indices 0,1: - // (using VF=4): - // %v0_v1 = shuffle %v0, %v1, <0,4,undef,1,5,undef,2,6,undef,3,7,undef> - // %gaps.mask = - // call llvm.masked.store <12 x i32> %v0_v1, <12 x i32>* %ptr, - // i32 Align, <12 x i1> %gaps.mask - // The cost is estimated as extract all elements (of actual members, - // excluding gaps) from both <4 x i32> vectors and insert into the <12 x - // i32> vector. - InstructionCost ExtSubCost = - thisT()->getScalarizationOverhead(SubVT, DemandedAllSubElts, - /*Insert*/ false, /*Extract*/ true); - Cost += ExtSubCost * Indices.size(); - Cost += thisT()->getScalarizationOverhead(VT, DemandedLoadStoreElts, - /*Insert*/ true, - /*Extract*/ false); - } - - if (!UseMaskForCond) - return Cost; - - Type *I8Type = Type::getInt8Ty(VT->getContext()); - - Cost += thisT()->getReplicationShuffleCost( - I8Type, Factor, NumSubElts, - UseMaskForGaps ? DemandedLoadStoreElts : DemandedAllResultElts, - CostKind); - - // The Gaps mask is invariant and created outside the loop, therefore the - // cost of creating it is not accounted for here. However if we have both - // a MaskForGaps and some other mask that guards the execution of the - // memory access, we need to account for the cost of And-ing the two masks - // inside the loop. - if (UseMaskForGaps) { - auto *MaskVT = FixedVectorType::get(I8Type, NumElts); - Cost += thisT()->getArithmeticInstrCost(BinaryOperator::And, MaskVT, - CostKind); - } - - return Cost; - } - - /// Get intrinsic cost based on arguments. - InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, - TTI::TargetCostKind CostKind) { - // Check for generically free intrinsics. - if (BaseT::getIntrinsicInstrCost(ICA, CostKind) == 0) - return 0; - - // Assume that target intrinsics are cheap. - Intrinsic::ID IID = ICA.getID(); - if (Function::isTargetIntrinsic(IID)) - return TargetTransformInfo::TCC_Basic; - - if (ICA.isTypeBasedOnly()) - return getTypeBasedIntrinsicInstrCost(ICA, CostKind); - - Type *RetTy = ICA.getReturnType(); - - ElementCount RetVF = - (RetTy->isVectorTy() ? cast(RetTy)->getElementCount() - : ElementCount::getFixed(1)); - const IntrinsicInst *I = ICA.getInst(); - const SmallVectorImpl &Args = ICA.getArgs(); - FastMathFlags FMF = ICA.getFlags(); - switch (IID) { - default: - break; - - case Intrinsic::cttz: - // FIXME: If necessary, this should go in target-specific overrides. - if (RetVF.isScalar() && getTLI()->isCheapToSpeculateCttz()) - return TargetTransformInfo::TCC_Basic; - break; - - case Intrinsic::ctlz: - // FIXME: If necessary, this should go in target-specific overrides. - if (RetVF.isScalar() && getTLI()->isCheapToSpeculateCtlz()) - return TargetTransformInfo::TCC_Basic; - break; - - case Intrinsic::memcpy: - return thisT()->getMemcpyCost(ICA.getInst()); - - case Intrinsic::masked_scatter: { - const Value *Mask = Args[3]; - bool VarMask = !isa(Mask); - Align Alignment = cast(Args[2])->getAlignValue(); - return thisT()->getGatherScatterOpCost(Instruction::Store, - ICA.getArgTypes()[0], Args[1], - VarMask, Alignment, CostKind, I); - } - case Intrinsic::masked_gather: { - const Value *Mask = Args[2]; - bool VarMask = !isa(Mask); - Align Alignment = cast(Args[1])->getAlignValue(); - return thisT()->getGatherScatterOpCost(Instruction::Load, RetTy, Args[0], - VarMask, Alignment, CostKind, I); - } - case Intrinsic::experimental_stepvector: { - if (isa(RetTy)) - return BaseT::getIntrinsicInstrCost(ICA, CostKind); - // The cost of materialising a constant integer vector. - return TargetTransformInfo::TCC_Basic; - } - case Intrinsic::experimental_vector_extract: { - // FIXME: Handle case where a scalable vector is extracted from a scalable - // vector - if (isa(RetTy)) - return BaseT::getIntrinsicInstrCost(ICA, CostKind); - unsigned Index = cast(Args[1])->getZExtValue(); - return thisT()->getShuffleCost(TTI::SK_ExtractSubvector, - cast(Args[0]->getType()), None, - Index, cast(RetTy)); - } - case Intrinsic::experimental_vector_insert: { - // FIXME: Handle case where a scalable vector is inserted into a scalable - // vector - if (isa(Args[1]->getType())) - return BaseT::getIntrinsicInstrCost(ICA, CostKind); - unsigned Index = cast(Args[2])->getZExtValue(); - return thisT()->getShuffleCost( - TTI::SK_InsertSubvector, cast(Args[0]->getType()), None, - Index, cast(Args[1]->getType())); - } - case Intrinsic::experimental_vector_reverse: { - return thisT()->getShuffleCost(TTI::SK_Reverse, - cast(Args[0]->getType()), None, - 0, cast(RetTy)); - } - case Intrinsic::experimental_vector_splice: { - unsigned Index = cast(Args[2])->getZExtValue(); - return thisT()->getShuffleCost(TTI::SK_Splice, - cast(Args[0]->getType()), None, - Index, cast(RetTy)); - } - case Intrinsic::vector_reduce_add: - case Intrinsic::vector_reduce_mul: - case Intrinsic::vector_reduce_and: - case Intrinsic::vector_reduce_or: - case Intrinsic::vector_reduce_xor: - case Intrinsic::vector_reduce_smax: - case Intrinsic::vector_reduce_smin: - case Intrinsic::vector_reduce_fmax: - case Intrinsic::vector_reduce_fmin: - case Intrinsic::vector_reduce_umax: - case Intrinsic::vector_reduce_umin: { - IntrinsicCostAttributes Attrs(IID, RetTy, Args[0]->getType(), FMF, I, 1); - return getTypeBasedIntrinsicInstrCost(Attrs, CostKind); - } - case Intrinsic::vector_reduce_fadd: - case Intrinsic::vector_reduce_fmul: { - IntrinsicCostAttributes Attrs( - IID, RetTy, {Args[0]->getType(), Args[1]->getType()}, FMF, I, 1); - return getTypeBasedIntrinsicInstrCost(Attrs, CostKind); - } - case Intrinsic::fshl: - case Intrinsic::fshr: { - if (isa(RetTy)) - return BaseT::getIntrinsicInstrCost(ICA, CostKind); - const Value *X = Args[0]; - const Value *Y = Args[1]; - const Value *Z = Args[2]; - TTI::OperandValueProperties OpPropsX, OpPropsY, OpPropsZ, OpPropsBW; - TTI::OperandValueKind OpKindX = TTI::getOperandInfo(X, OpPropsX); - TTI::OperandValueKind OpKindY = TTI::getOperandInfo(Y, OpPropsY); - TTI::OperandValueKind OpKindZ = TTI::getOperandInfo(Z, OpPropsZ); - TTI::OperandValueKind OpKindBW = TTI::OK_UniformConstantValue; - OpPropsBW = isPowerOf2_32(RetTy->getScalarSizeInBits()) ? TTI::OP_PowerOf2 - : TTI::OP_None; - // fshl: (X << (Z % BW)) | (Y >> (BW - (Z % BW))) - // fshr: (X << (BW - (Z % BW))) | (Y >> (Z % BW)) - InstructionCost Cost = 0; - Cost += - thisT()->getArithmeticInstrCost(BinaryOperator::Or, RetTy, CostKind); - Cost += - thisT()->getArithmeticInstrCost(BinaryOperator::Sub, RetTy, CostKind); - Cost += thisT()->getArithmeticInstrCost( - BinaryOperator::Shl, RetTy, CostKind, OpKindX, OpKindZ, OpPropsX); - Cost += thisT()->getArithmeticInstrCost( - BinaryOperator::LShr, RetTy, CostKind, OpKindY, OpKindZ, OpPropsY); - // Non-constant shift amounts requires a modulo. - if (OpKindZ != TTI::OK_UniformConstantValue && - OpKindZ != TTI::OK_NonUniformConstantValue) - Cost += thisT()->getArithmeticInstrCost(BinaryOperator::URem, RetTy, - CostKind, OpKindZ, OpKindBW, - OpPropsZ, OpPropsBW); - // For non-rotates (X != Y) we must add shift-by-zero handling costs. - if (X != Y) { - Type *CondTy = RetTy->getWithNewBitWidth(1); - Cost += - thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - CmpInst::ICMP_EQ, CostKind); - Cost += - thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, - CmpInst::ICMP_EQ, CostKind); - } - return Cost; - } - } - - // Assume that we need to scalarize this intrinsic. - // Compute the scalarization overhead based on Args for a vector - // intrinsic. - InstructionCost ScalarizationCost = InstructionCost::getInvalid(); - if (RetVF.isVector() && !RetVF.isScalable()) { - ScalarizationCost = 0; - if (!RetTy->isVoidTy()) - ScalarizationCost += - getScalarizationOverhead(cast(RetTy), true, false); - ScalarizationCost += - getOperandsScalarizationOverhead(Args, ICA.getArgTypes()); - } - - IntrinsicCostAttributes Attrs(IID, RetTy, ICA.getArgTypes(), FMF, I, - ScalarizationCost); - return thisT()->getTypeBasedIntrinsicInstrCost(Attrs, CostKind); - } - - /// Get intrinsic cost based on argument types. - /// If ScalarizationCostPassed is std::numeric_limits::max(), the - /// cost of scalarizing the arguments and the return value will be computed - /// based on types. - InstructionCost - getTypeBasedIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, - TTI::TargetCostKind CostKind) { - Intrinsic::ID IID = ICA.getID(); - Type *RetTy = ICA.getReturnType(); - const SmallVectorImpl &Tys = ICA.getArgTypes(); - FastMathFlags FMF = ICA.getFlags(); - InstructionCost ScalarizationCostPassed = ICA.getScalarizationCost(); - bool SkipScalarizationCost = ICA.skipScalarizationCost(); - - VectorType *VecOpTy = nullptr; - if (!Tys.empty()) { - // The vector reduction operand is operand 0 except for fadd/fmul. - // Their operand 0 is a scalar start value, so the vector op is operand 1. - unsigned VecTyIndex = 0; - if (IID == Intrinsic::vector_reduce_fadd || - IID == Intrinsic::vector_reduce_fmul) - VecTyIndex = 1; - assert(Tys.size() > VecTyIndex && "Unexpected IntrinsicCostAttributes"); - VecOpTy = dyn_cast(Tys[VecTyIndex]); - } - - // Library call cost - other than size, make it expensive. - unsigned SingleCallCost = CostKind == TTI::TCK_CodeSize ? 1 : 10; - SmallVector ISDs; - switch (IID) { - default: { - // Scalable vectors cannot be scalarized, so return Invalid. - if (isa(RetTy) || any_of(Tys, [](const Type *Ty) { - return isa(Ty); - })) - return InstructionCost::getInvalid(); - - // Assume that we need to scalarize this intrinsic. - InstructionCost ScalarizationCost = - SkipScalarizationCost ? ScalarizationCostPassed : 0; - unsigned ScalarCalls = 1; - Type *ScalarRetTy = RetTy; - if (auto *RetVTy = dyn_cast(RetTy)) { - if (!SkipScalarizationCost) - ScalarizationCost = getScalarizationOverhead(RetVTy, true, false); - ScalarCalls = std::max(ScalarCalls, - cast(RetVTy)->getNumElements()); - ScalarRetTy = RetTy->getScalarType(); - } - SmallVector ScalarTys; - for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { - Type *Ty = Tys[i]; - if (auto *VTy = dyn_cast(Ty)) { - if (!SkipScalarizationCost) - ScalarizationCost += getScalarizationOverhead(VTy, false, true); - ScalarCalls = std::max(ScalarCalls, - cast(VTy)->getNumElements()); - Ty = Ty->getScalarType(); - } - ScalarTys.push_back(Ty); - } - if (ScalarCalls == 1) - return 1; // Return cost of a scalar intrinsic. Assume it to be cheap. - - IntrinsicCostAttributes ScalarAttrs(IID, ScalarRetTy, ScalarTys, FMF); - InstructionCost ScalarCost = - thisT()->getIntrinsicInstrCost(ScalarAttrs, CostKind); - - return ScalarCalls * ScalarCost + ScalarizationCost; - } - // Look for intrinsics that can be lowered directly or turned into a scalar - // intrinsic call. - case Intrinsic::sqrt: - ISDs.push_back(ISD::FSQRT); - break; - case Intrinsic::sin: - ISDs.push_back(ISD::FSIN); - break; - case Intrinsic::cos: - ISDs.push_back(ISD::FCOS); - break; - case Intrinsic::exp: - ISDs.push_back(ISD::FEXP); - break; - case Intrinsic::exp2: - ISDs.push_back(ISD::FEXP2); - break; - case Intrinsic::log: - ISDs.push_back(ISD::FLOG); - break; - case Intrinsic::log10: - ISDs.push_back(ISD::FLOG10); - break; - case Intrinsic::log2: - ISDs.push_back(ISD::FLOG2); - break; - case Intrinsic::fabs: - ISDs.push_back(ISD::FABS); - break; - case Intrinsic::canonicalize: - ISDs.push_back(ISD::FCANONICALIZE); - break; - case Intrinsic::minnum: - ISDs.push_back(ISD::FMINNUM); - break; - case Intrinsic::maxnum: - ISDs.push_back(ISD::FMAXNUM); - break; - case Intrinsic::minimum: - ISDs.push_back(ISD::FMINIMUM); - break; - case Intrinsic::maximum: - ISDs.push_back(ISD::FMAXIMUM); - break; - case Intrinsic::copysign: - ISDs.push_back(ISD::FCOPYSIGN); - break; - case Intrinsic::floor: - ISDs.push_back(ISD::FFLOOR); - break; - case Intrinsic::ceil: - ISDs.push_back(ISD::FCEIL); - break; - case Intrinsic::trunc: - ISDs.push_back(ISD::FTRUNC); - break; - case Intrinsic::nearbyint: - ISDs.push_back(ISD::FNEARBYINT); - break; - case Intrinsic::rint: - ISDs.push_back(ISD::FRINT); - break; - case Intrinsic::round: - ISDs.push_back(ISD::FROUND); - break; - case Intrinsic::roundeven: - ISDs.push_back(ISD::FROUNDEVEN); - break; - case Intrinsic::pow: - ISDs.push_back(ISD::FPOW); - break; - case Intrinsic::fma: - ISDs.push_back(ISD::FMA); - break; - case Intrinsic::fmuladd: - ISDs.push_back(ISD::FMA); - break; - case Intrinsic::experimental_constrained_fmuladd: - ISDs.push_back(ISD::STRICT_FMA); - break; - // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free. - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::sideeffect: - case Intrinsic::pseudoprobe: - case Intrinsic::arithmetic_fence: - return 0; - case Intrinsic::masked_store: { - Type *Ty = Tys[0]; - Align TyAlign = thisT()->DL.getABITypeAlign(Ty); - return thisT()->getMaskedMemoryOpCost(Instruction::Store, Ty, TyAlign, 0, - CostKind); - } - case Intrinsic::masked_load: { - Type *Ty = RetTy; - Align TyAlign = thisT()->DL.getABITypeAlign(Ty); - return thisT()->getMaskedMemoryOpCost(Instruction::Load, Ty, TyAlign, 0, - CostKind); - } - case Intrinsic::vector_reduce_add: - return thisT()->getArithmeticReductionCost(Instruction::Add, VecOpTy, - None, CostKind); - case Intrinsic::vector_reduce_mul: - return thisT()->getArithmeticReductionCost(Instruction::Mul, VecOpTy, - None, CostKind); - case Intrinsic::vector_reduce_and: - return thisT()->getArithmeticReductionCost(Instruction::And, VecOpTy, - None, CostKind); - case Intrinsic::vector_reduce_or: - return thisT()->getArithmeticReductionCost(Instruction::Or, VecOpTy, None, - CostKind); - case Intrinsic::vector_reduce_xor: - return thisT()->getArithmeticReductionCost(Instruction::Xor, VecOpTy, - None, CostKind); - case Intrinsic::vector_reduce_fadd: - return thisT()->getArithmeticReductionCost(Instruction::FAdd, VecOpTy, - FMF, CostKind); - case Intrinsic::vector_reduce_fmul: - return thisT()->getArithmeticReductionCost(Instruction::FMul, VecOpTy, - FMF, CostKind); - case Intrinsic::vector_reduce_smax: - case Intrinsic::vector_reduce_smin: - case Intrinsic::vector_reduce_fmax: - case Intrinsic::vector_reduce_fmin: - return thisT()->getMinMaxReductionCost( - VecOpTy, cast(CmpInst::makeCmpResultType(VecOpTy)), - /*IsUnsigned=*/false, CostKind); - case Intrinsic::vector_reduce_umax: - case Intrinsic::vector_reduce_umin: - return thisT()->getMinMaxReductionCost( - VecOpTy, cast(CmpInst::makeCmpResultType(VecOpTy)), - /*IsUnsigned=*/true, CostKind); - case Intrinsic::abs: { - // abs(X) = select(icmp(X,0),X,sub(0,X)) - Type *CondTy = RetTy->getWithNewBitWidth(1); - CmpInst::Predicate Pred = CmpInst::ICMP_SGT; - InstructionCost Cost = 0; - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - Pred, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, - Pred, CostKind); - // TODO: Should we add an OperandValueProperties::OP_Zero property? - Cost += thisT()->getArithmeticInstrCost( - BinaryOperator::Sub, RetTy, CostKind, TTI::OK_UniformConstantValue); - return Cost; - } - case Intrinsic::smax: - case Intrinsic::smin: - case Intrinsic::umax: - case Intrinsic::umin: { - // minmax(X,Y) = select(icmp(X,Y),X,Y) - Type *CondTy = RetTy->getWithNewBitWidth(1); - bool IsUnsigned = IID == Intrinsic::umax || IID == Intrinsic::umin; - CmpInst::Predicate Pred = - IsUnsigned ? CmpInst::ICMP_UGT : CmpInst::ICMP_SGT; - InstructionCost Cost = 0; - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - Pred, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, - Pred, CostKind); - return Cost; - } - case Intrinsic::sadd_sat: - case Intrinsic::ssub_sat: { - Type *CondTy = RetTy->getWithNewBitWidth(1); - - Type *OpTy = StructType::create({RetTy, CondTy}); - Intrinsic::ID OverflowOp = IID == Intrinsic::sadd_sat - ? Intrinsic::sadd_with_overflow - : Intrinsic::ssub_with_overflow; - CmpInst::Predicate Pred = CmpInst::ICMP_SGT; - - // SatMax -> Overflow && SumDiff < 0 - // SatMin -> Overflow && SumDiff >= 0 - InstructionCost Cost = 0; - IntrinsicCostAttributes Attrs(OverflowOp, OpTy, {RetTy, RetTy}, FMF, - nullptr, ScalarizationCostPassed); - Cost += thisT()->getIntrinsicInstrCost(Attrs, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - Pred, CostKind); - Cost += 2 * thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, - CondTy, Pred, CostKind); - return Cost; - } - case Intrinsic::uadd_sat: - case Intrinsic::usub_sat: { - Type *CondTy = RetTy->getWithNewBitWidth(1); - - Type *OpTy = StructType::create({RetTy, CondTy}); - Intrinsic::ID OverflowOp = IID == Intrinsic::uadd_sat - ? Intrinsic::uadd_with_overflow - : Intrinsic::usub_with_overflow; - - InstructionCost Cost = 0; - IntrinsicCostAttributes Attrs(OverflowOp, OpTy, {RetTy, RetTy}, FMF, - nullptr, ScalarizationCostPassed); - Cost += thisT()->getIntrinsicInstrCost(Attrs, CostKind); - Cost += - thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, - CmpInst::BAD_ICMP_PREDICATE, CostKind); - return Cost; - } - case Intrinsic::smul_fix: - case Intrinsic::umul_fix: { - unsigned ExtSize = RetTy->getScalarSizeInBits() * 2; - Type *ExtTy = RetTy->getWithNewBitWidth(ExtSize); - - unsigned ExtOp = - IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; - TTI::CastContextHint CCH = TTI::CastContextHint::None; - - InstructionCost Cost = 0; - Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, RetTy, CCH, CostKind); - Cost += - thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); - Cost += 2 * thisT()->getCastInstrCost(Instruction::Trunc, RetTy, ExtTy, - CCH, CostKind); - Cost += thisT()->getArithmeticInstrCost(Instruction::LShr, RetTy, - CostKind, TTI::OK_AnyValue, - TTI::OK_UniformConstantValue); - Cost += thisT()->getArithmeticInstrCost(Instruction::Shl, RetTy, CostKind, - TTI::OK_AnyValue, - TTI::OK_UniformConstantValue); - Cost += thisT()->getArithmeticInstrCost(Instruction::Or, RetTy, CostKind); - return Cost; - } - case Intrinsic::sadd_with_overflow: - case Intrinsic::ssub_with_overflow: { - Type *SumTy = RetTy->getContainedType(0); - Type *OverflowTy = RetTy->getContainedType(1); - unsigned Opcode = IID == Intrinsic::sadd_with_overflow - ? BinaryOperator::Add - : BinaryOperator::Sub; - - // Add: - // Overflow -> (Result < LHS) ^ (RHS < 0) - // Sub: - // Overflow -> (Result < LHS) ^ (RHS > 0) - InstructionCost Cost = 0; - Cost += thisT()->getArithmeticInstrCost(Opcode, SumTy, CostKind); - Cost += 2 * thisT()->getCmpSelInstrCost( - Instruction::ICmp, SumTy, OverflowTy, - CmpInst::ICMP_SGT, CostKind); - Cost += thisT()->getArithmeticInstrCost(BinaryOperator::Xor, OverflowTy, - CostKind); - return Cost; - } - case Intrinsic::uadd_with_overflow: - case Intrinsic::usub_with_overflow: { - Type *SumTy = RetTy->getContainedType(0); - Type *OverflowTy = RetTy->getContainedType(1); - unsigned Opcode = IID == Intrinsic::uadd_with_overflow - ? BinaryOperator::Add - : BinaryOperator::Sub; - CmpInst::Predicate Pred = IID == Intrinsic::uadd_with_overflow - ? CmpInst::ICMP_ULT - : CmpInst::ICMP_UGT; - - InstructionCost Cost = 0; - Cost += thisT()->getArithmeticInstrCost(Opcode, SumTy, CostKind); - Cost += - thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, OverflowTy, - Pred, CostKind); - return Cost; - } - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: { - Type *MulTy = RetTy->getContainedType(0); - Type *OverflowTy = RetTy->getContainedType(1); - unsigned ExtSize = MulTy->getScalarSizeInBits() * 2; - Type *ExtTy = MulTy->getWithNewBitWidth(ExtSize); - bool IsSigned = IID == Intrinsic::smul_with_overflow; - - unsigned ExtOp = IsSigned ? Instruction::SExt : Instruction::ZExt; - TTI::CastContextHint CCH = TTI::CastContextHint::None; - - InstructionCost Cost = 0; - Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, MulTy, CCH, CostKind); - Cost += - thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); - Cost += 2 * thisT()->getCastInstrCost(Instruction::Trunc, MulTy, ExtTy, - CCH, CostKind); - Cost += thisT()->getArithmeticInstrCost(Instruction::LShr, ExtTy, - CostKind, TTI::OK_AnyValue, - TTI::OK_UniformConstantValue); - - if (IsSigned) - Cost += thisT()->getArithmeticInstrCost(Instruction::AShr, MulTy, - CostKind, TTI::OK_AnyValue, - TTI::OK_UniformConstantValue); - - Cost += thisT()->getCmpSelInstrCost( - BinaryOperator::ICmp, MulTy, OverflowTy, CmpInst::ICMP_NE, CostKind); - return Cost; - } - case Intrinsic::ctpop: - ISDs.push_back(ISD::CTPOP); - // In case of legalization use TCC_Expensive. This is cheaper than a - // library call but still not a cheap instruction. - SingleCallCost = TargetTransformInfo::TCC_Expensive; - break; - case Intrinsic::ctlz: - ISDs.push_back(ISD::CTLZ); - break; - case Intrinsic::cttz: - ISDs.push_back(ISD::CTTZ); - break; - case Intrinsic::bswap: - ISDs.push_back(ISD::BSWAP); - break; - case Intrinsic::bitreverse: - ISDs.push_back(ISD::BITREVERSE); - break; - } - - const TargetLoweringBase *TLI = getTLI(); - std::pair LT = - TLI->getTypeLegalizationCost(DL, RetTy); - - SmallVector LegalCost; - SmallVector CustomCost; - for (unsigned ISD : ISDs) { - if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { - if (IID == Intrinsic::fabs && LT.second.isFloatingPoint() && - TLI->isFAbsFree(LT.second)) { - return 0; - } - - // The operation is legal. Assume it costs 1. - // If the type is split to multiple registers, assume that there is some - // overhead to this. - // TODO: Once we have extract/insert subvector cost we need to use them. - if (LT.first > 1) - LegalCost.push_back(LT.first * 2); - else - LegalCost.push_back(LT.first * 1); - } else if (!TLI->isOperationExpand(ISD, LT.second)) { - // If the operation is custom lowered then assume - // that the code is twice as expensive. - CustomCost.push_back(LT.first * 2); - } - } - - auto *MinLegalCostI = std::min_element(LegalCost.begin(), LegalCost.end()); - if (MinLegalCostI != LegalCost.end()) - return *MinLegalCostI; - - auto MinCustomCostI = - std::min_element(CustomCost.begin(), CustomCost.end()); - if (MinCustomCostI != CustomCost.end()) - return *MinCustomCostI; - - // If we can't lower fmuladd into an FMA estimate the cost as a floating - // point mul followed by an add. - if (IID == Intrinsic::fmuladd) - return thisT()->getArithmeticInstrCost(BinaryOperator::FMul, RetTy, - CostKind) + - thisT()->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy, - CostKind); - if (IID == Intrinsic::experimental_constrained_fmuladd) { - IntrinsicCostAttributes FMulAttrs( - Intrinsic::experimental_constrained_fmul, RetTy, Tys); - IntrinsicCostAttributes FAddAttrs( - Intrinsic::experimental_constrained_fadd, RetTy, Tys); - return thisT()->getIntrinsicInstrCost(FMulAttrs, CostKind) + - thisT()->getIntrinsicInstrCost(FAddAttrs, CostKind); - } - - // Else, assume that we need to scalarize this intrinsic. For math builtins - // this will emit a costly libcall, adding call overhead and spills. Make it - // very expensive. - if (auto *RetVTy = dyn_cast(RetTy)) { - // Scalable vectors cannot be scalarized, so return Invalid. - if (isa(RetTy) || any_of(Tys, [](const Type *Ty) { - return isa(Ty); - })) - return InstructionCost::getInvalid(); - - InstructionCost ScalarizationCost = - SkipScalarizationCost ? ScalarizationCostPassed - : getScalarizationOverhead(RetVTy, true, false); - - unsigned ScalarCalls = cast(RetVTy)->getNumElements(); - SmallVector ScalarTys; - for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { - Type *Ty = Tys[i]; - if (Ty->isVectorTy()) - Ty = Ty->getScalarType(); - ScalarTys.push_back(Ty); - } - IntrinsicCostAttributes Attrs(IID, RetTy->getScalarType(), ScalarTys, FMF); - InstructionCost ScalarCost = - thisT()->getIntrinsicInstrCost(Attrs, CostKind); - for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { - if (auto *VTy = dyn_cast(Tys[i])) { - if (!ICA.skipScalarizationCost()) - ScalarizationCost += getScalarizationOverhead(VTy, false, true); - ScalarCalls = std::max(ScalarCalls, - cast(VTy)->getNumElements()); - } - } - return ScalarCalls * ScalarCost + ScalarizationCost; - } - - // This is going to be turned into a library call, make it expensive. - return SingleCallCost; - } - - /// Compute a cost of the given call instruction. - /// - /// Compute the cost of calling function F with return type RetTy and - /// argument types Tys. F might be nullptr, in this case the cost of an - /// arbitrary call with the specified signature will be returned. - /// This is used, for instance, when we estimate call of a vector - /// counterpart of the given function. - /// \param F Called function, might be nullptr. - /// \param RetTy Return value types. - /// \param Tys Argument types. - /// \returns The cost of Call instruction. - InstructionCost getCallInstrCost(Function *F, Type *RetTy, - ArrayRef Tys, - TTI::TargetCostKind CostKind) { - return 10; - } - - unsigned getNumberOfParts(Type *Tp) { - std::pair LT = - getTLI()->getTypeLegalizationCost(DL, Tp); - return LT.first.isValid() ? *LT.first.getValue() : 0; - } - - InstructionCost getAddressComputationCost(Type *Ty, ScalarEvolution *, - const SCEV *) { - return 0; - } - - /// Try to calculate arithmetic and shuffle op costs for reduction intrinsics. - /// We're assuming that reduction operation are performing the following way: - /// - /// %val1 = shufflevector %val, %undef, - /// - /// \----------------v-------------/ \----------v------------/ - /// n/2 elements n/2 elements - /// %red1 = op %val, val1 - /// After this operation we have a vector %red1 where only the first n/2 - /// elements are meaningful, the second n/2 elements are undefined and can be - /// dropped. All other operations are actually working with the vector of - /// length n/2, not n, though the real vector length is still n. - /// %val2 = shufflevector %red1, %undef, - /// - /// \----------------v-------------/ \----------v------------/ - /// n/4 elements 3*n/4 elements - /// %red2 = op %red1, val2 - working with the vector of - /// length n/2, the resulting vector has length n/4 etc. - /// - /// The cost model should take into account that the actual length of the - /// vector is reduced on each iteration. - InstructionCost getTreeReductionCost(unsigned Opcode, VectorType *Ty, - TTI::TargetCostKind CostKind) { - Type *ScalarTy = Ty->getElementType(); - unsigned NumVecElts = cast(Ty)->getNumElements(); - if ((Opcode == Instruction::Or || Opcode == Instruction::And) && - ScalarTy == IntegerType::getInt1Ty(Ty->getContext()) && - NumVecElts >= 2) { - // Or reduction for i1 is represented as: - // %val = bitcast to iReduxWidth - // %res = cmp ne iReduxWidth %val, 0 - // And reduction for i1 is represented as: - // %val = bitcast to iReduxWidth - // %res = cmp eq iReduxWidth %val, 11111 - Type *ValTy = IntegerType::get(Ty->getContext(), NumVecElts); - return thisT()->getCastInstrCost(Instruction::BitCast, ValTy, Ty, - TTI::CastContextHint::None, CostKind) + - thisT()->getCmpSelInstrCost(Instruction::ICmp, ValTy, - CmpInst::makeCmpResultType(ValTy), - CmpInst::BAD_ICMP_PREDICATE, CostKind); - } - unsigned NumReduxLevels = Log2_32(NumVecElts); - InstructionCost ArithCost = 0; - InstructionCost ShuffleCost = 0; - std::pair LT = - thisT()->getTLI()->getTypeLegalizationCost(DL, Ty); - unsigned LongVectorCount = 0; - unsigned MVTLen = - LT.second.isVector() ? LT.second.getVectorNumElements() : 1; - while (NumVecElts > MVTLen) { - NumVecElts /= 2; - VectorType *SubTy = FixedVectorType::get(ScalarTy, NumVecElts); - ShuffleCost += thisT()->getShuffleCost(TTI::SK_ExtractSubvector, Ty, None, - NumVecElts, SubTy); - ArithCost += thisT()->getArithmeticInstrCost(Opcode, SubTy, CostKind); - Ty = SubTy; - ++LongVectorCount; - } - - NumReduxLevels -= LongVectorCount; - - // The minimal length of the vector is limited by the real length of vector - // operations performed on the current platform. That's why several final - // reduction operations are performed on the vectors with the same - // architecture-dependent length. - - // By default reductions need one shuffle per reduction level. - ShuffleCost += NumReduxLevels * thisT()->getShuffleCost( - TTI::SK_PermuteSingleSrc, Ty, None, 0, Ty); - ArithCost += - NumReduxLevels * thisT()->getArithmeticInstrCost(Opcode, Ty, CostKind); - return ShuffleCost + ArithCost + - thisT()->getVectorInstrCost(Instruction::ExtractElement, Ty, 0); - } - - /// Try to calculate the cost of performing strict (in-order) reductions, - /// which involves doing a sequence of floating point additions in lane - /// order, starting with an initial value. For example, consider a scalar - /// initial value 'InitVal' of type float and a vector of type <4 x float>: - /// - /// Vector = - /// - /// %add1 = %InitVal + %v0 - /// %add2 = %add1 + %v1 - /// %add3 = %add2 + %v2 - /// %add4 = %add3 + %v3 - /// - /// As a simple estimate we can say the cost of such a reduction is 4 times - /// the cost of a scalar FP addition. We can only estimate the costs for - /// fixed-width vectors here because for scalable vectors we do not know the - /// runtime number of operations. - InstructionCost getOrderedReductionCost(unsigned Opcode, VectorType *Ty, - TTI::TargetCostKind CostKind) { - // Targets must implement a default value for the scalable case, since - // we don't know how many lanes the vector has. - if (isa(Ty)) - return InstructionCost::getInvalid(); - - auto *VTy = cast(Ty); - InstructionCost ExtractCost = - getScalarizationOverhead(VTy, /*Insert=*/false, /*Extract=*/true); - InstructionCost ArithCost = thisT()->getArithmeticInstrCost( - Opcode, VTy->getElementType(), CostKind); - ArithCost *= VTy->getNumElements(); - - return ExtractCost + ArithCost; - } - - InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, - Optional FMF, - TTI::TargetCostKind CostKind) { - if (TTI::requiresOrderedReduction(FMF)) - return getOrderedReductionCost(Opcode, Ty, CostKind); - return getTreeReductionCost(Opcode, Ty, CostKind); - } - - /// Try to calculate op costs for min/max reduction operations. - /// \param CondTy Conditional type for the Select instruction. - InstructionCost getMinMaxReductionCost(VectorType *Ty, VectorType *CondTy, - bool IsUnsigned, - TTI::TargetCostKind CostKind) { - Type *ScalarTy = Ty->getElementType(); - Type *ScalarCondTy = CondTy->getElementType(); - unsigned NumVecElts = cast(Ty)->getNumElements(); - unsigned NumReduxLevels = Log2_32(NumVecElts); - unsigned CmpOpcode; - if (Ty->isFPOrFPVectorTy()) { - CmpOpcode = Instruction::FCmp; - } else { - assert(Ty->isIntOrIntVectorTy() && - "expecting floating point or integer type for min/max reduction"); - CmpOpcode = Instruction::ICmp; - } - InstructionCost MinMaxCost = 0; - InstructionCost ShuffleCost = 0; - std::pair LT = - thisT()->getTLI()->getTypeLegalizationCost(DL, Ty); - unsigned LongVectorCount = 0; - unsigned MVTLen = - LT.second.isVector() ? LT.second.getVectorNumElements() : 1; - while (NumVecElts > MVTLen) { - NumVecElts /= 2; - auto *SubTy = FixedVectorType::get(ScalarTy, NumVecElts); - CondTy = FixedVectorType::get(ScalarCondTy, NumVecElts); - - ShuffleCost += thisT()->getShuffleCost(TTI::SK_ExtractSubvector, Ty, None, - NumVecElts, SubTy); - MinMaxCost += - thisT()->getCmpSelInstrCost(CmpOpcode, SubTy, CondTy, - CmpInst::BAD_ICMP_PREDICATE, CostKind) + - thisT()->getCmpSelInstrCost(Instruction::Select, SubTy, CondTy, - CmpInst::BAD_ICMP_PREDICATE, CostKind); - Ty = SubTy; - ++LongVectorCount; - } - - NumReduxLevels -= LongVectorCount; - - // The minimal length of the vector is limited by the real length of vector - // operations performed on the current platform. That's why several final - // reduction operations are performed on the vectors with the same - // architecture-dependent length. - ShuffleCost += NumReduxLevels * thisT()->getShuffleCost( - TTI::SK_PermuteSingleSrc, Ty, None, 0, Ty); - MinMaxCost += - NumReduxLevels * - (thisT()->getCmpSelInstrCost(CmpOpcode, Ty, CondTy, - CmpInst::BAD_ICMP_PREDICATE, CostKind) + - thisT()->getCmpSelInstrCost(Instruction::Select, Ty, CondTy, - CmpInst::BAD_ICMP_PREDICATE, CostKind)); - // The last min/max should be in vector registers and we counted it above. - // So just need a single extractelement. - return ShuffleCost + MinMaxCost + - thisT()->getVectorInstrCost(Instruction::ExtractElement, Ty, 0); - } - - InstructionCost getExtendedAddReductionCost(bool IsMLA, bool IsUnsigned, - Type *ResTy, VectorType *Ty, - TTI::TargetCostKind CostKind) { - // Without any native support, this is equivalent to the cost of - // vecreduce.add(ext) or if IsMLA vecreduce.add(mul(ext, ext)) - VectorType *ExtTy = VectorType::get(ResTy, Ty); - InstructionCost RedCost = thisT()->getArithmeticReductionCost( - Instruction::Add, ExtTy, None, CostKind); - InstructionCost MulCost = 0; - InstructionCost ExtCost = thisT()->getCastInstrCost( - IsUnsigned ? Instruction::ZExt : Instruction::SExt, ExtTy, Ty, - TTI::CastContextHint::None, CostKind); - if (IsMLA) { - MulCost = - thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); - ExtCost *= 2; - } - - return RedCost + MulCost + ExtCost; - } - - InstructionCost getVectorSplitCost() { return 1; } - - /// @} -}; - -/// Concrete BasicTTIImpl that can be used if no further customization -/// is needed. -class BasicTTIImpl : public BasicTTIImplBase { - using BaseT = BasicTTIImplBase; - - friend class BasicTTIImplBase; - - const TargetSubtargetInfo *ST; - const TargetLoweringBase *TLI; - - const TargetSubtargetInfo *getST() const { return ST; } - const TargetLoweringBase *getTLI() const { return TLI; } - -public: - explicit BasicTTIImpl(const TargetMachine *TM, const Function &F); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_BASICTTIIMPL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CSEConfigBase.h b/suite/synctools/tablegen/include/llvm/CodeGen/CSEConfigBase.h deleted file mode 100644 index d3637099c4..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CSEConfigBase.h +++ /dev/null @@ -1,28 +0,0 @@ -//===- CSEConfigBase.h - A CSEConfig interface ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_CSECONFIGBASE_H -#define LLVM_CODEGEN_CSECONFIGBASE_H - -namespace llvm { -// Class representing some configuration that can be done during GlobalISel's -// CSEInfo analysis. We define it here because TargetPassConfig can't depend on -// the GlobalISel library, and so we use this in the interface between them -// so that the derived classes in GISel can reference generic opcodes. -class CSEConfigBase { -public: - virtual ~CSEConfigBase() = default; - // Hook for defining which Generic instructions should be CSEd. - // GISelCSEInfo currently only calls this hook when dealing with generic - // opcodes. - virtual bool shouldCSEOpc(unsigned Opc) { return false; } -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_CSECONFIGBASE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CalcSpillWeights.h b/suite/synctools/tablegen/include/llvm/CodeGen/CalcSpillWeights.h deleted file mode 100644 index bfd5bab3d1..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CalcSpillWeights.h +++ /dev/null @@ -1,119 +0,0 @@ -//===- lib/CodeGen/CalcSpillWeights.h ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H -#define LLVM_CODEGEN_CALCSPILLWEIGHTS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/SlotIndexes.h" - -namespace llvm { - -class LiveInterval; -class LiveIntervals; -class MachineBlockFrequencyInfo; -class MachineFunction; -class MachineLoopInfo; -class VirtRegMap; - - /// Normalize the spill weight of a live interval - /// - /// The spill weight of a live interval is computed as: - /// - /// (sum(use freq) + sum(def freq)) / (K + size) - /// - /// @param UseDefFreq Expected number of executed use and def instructions - /// per function call. Derived from block frequencies. - /// @param Size Size of live interval as returnexd by getSize() - /// @param NumInstr Number of instructions using this live interval - static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size, - unsigned NumInstr) { - // The constant 25 instructions is added to avoid depending too much on - // accidental SlotIndex gaps for small intervals. The effect is that small - // intervals have a spill weight that is mostly proportional to the number - // of uses, while large intervals get a spill weight that is closer to a use - // density. - return UseDefFreq / (Size + 25*SlotIndex::InstrDist); - } - - /// Calculate auxiliary information for a virtual register such as its - /// spill weight and allocation hint. - class VirtRegAuxInfo { - MachineFunction &MF; - LiveIntervals &LIS; - const VirtRegMap &VRM; - const MachineLoopInfo &Loops; - const MachineBlockFrequencyInfo &MBFI; - - /// Returns true if Reg of live interval LI is used in instruction with many - /// operands like STATEPOINT. - bool isLiveAtStatepointVarArg(LiveInterval &LI); - - public: - VirtRegAuxInfo(MachineFunction &MF, LiveIntervals &LIS, - const VirtRegMap &VRM, const MachineLoopInfo &Loops, - const MachineBlockFrequencyInfo &MBFI) - : MF(MF), LIS(LIS), VRM(VRM), Loops(Loops), MBFI(MBFI) {} - - virtual ~VirtRegAuxInfo() = default; - - /// (re)compute li's spill weight and allocation hint. - void calculateSpillWeightAndHint(LiveInterval &LI); - - /// Compute future expected spill weight of a split artifact of LI - /// that will span between start and end slot indexes. - /// \param LI The live interval to be split. - /// \param Start The expected beginning of the split artifact. Instructions - /// before start will not affect the weight. - /// \param End The expected end of the split artifact. Instructions - /// after end will not affect the weight. - /// \return The expected spill weight of the split artifact. Returns - /// negative weight for unspillable LI. - float futureWeight(LiveInterval &LI, SlotIndex Start, SlotIndex End); - - /// Compute spill weights and allocation hints for all virtual register - /// live intervals. - void calculateSpillWeightsAndHints(); - - /// Return the preferred allocation register for reg, given a COPY - /// instruction. - static Register copyHint(const MachineInstr *MI, unsigned Reg, - const TargetRegisterInfo &TRI, - const MachineRegisterInfo &MRI); - - /// Determine if all values in LI are rematerializable. - static bool isRematerializable(const LiveInterval &LI, - const LiveIntervals &LIS, - const VirtRegMap &VRM, - const TargetInstrInfo &TII); - - protected: - /// Helper function for weight calculations. - /// (Re)compute LI's spill weight and allocation hint, or, for non null - /// start and end - compute future expected spill weight of a split - /// artifact of LI that will span between start and end slot indexes. - /// \param LI The live interval for which to compute the weight. - /// \param Start The expected beginning of the split artifact. Instructions - /// before start will not affect the weight. Relevant for - /// weight calculation of future split artifact. - /// \param End The expected end of the split artifact. Instructions - /// after end will not affect the weight. Relevant for - /// weight calculation of future split artifact. - /// \return The spill weight. Returns negative weight for unspillable LI. - float weightCalcHelper(LiveInterval &LI, SlotIndex *Start = nullptr, - SlotIndex *End = nullptr); - - /// Weight normalization function. - virtual float normalize(float UseDefFreq, unsigned Size, - unsigned NumInstr) { - return normalizeSpillWeight(UseDefFreq, Size, NumInstr); - } - }; -} // end namespace llvm - -#endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CallingConvLower.h b/suite/synctools/tablegen/include/llvm/CodeGen/CallingConvLower.h deleted file mode 100644 index 8dbcd6b8ab..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CallingConvLower.h +++ /dev/null @@ -1,568 +0,0 @@ -//===- llvm/CallingConvLower.h - Calling Conventions ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the CCState and CCValAssign classes, used for lowering -// and implementing calling conventions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H -#define LLVM_CODEGEN_CALLINGCONVLOWER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/CodeGen/TargetCallingConv.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Alignment.h" - -namespace llvm { - -class CCState; -class MachineFunction; -class MVT; -class TargetRegisterInfo; - -/// CCValAssign - Represent assignment of one arg/retval to a location. -class CCValAssign { -public: - enum LocInfo { - Full, // The value fills the full location. - SExt, // The value is sign extended in the location. - ZExt, // The value is zero extended in the location. - AExt, // The value is extended with undefined upper bits. - SExtUpper, // The value is in the upper bits of the location and should be - // sign extended when retrieved. - ZExtUpper, // The value is in the upper bits of the location and should be - // zero extended when retrieved. - AExtUpper, // The value is in the upper bits of the location and should be - // extended with undefined upper bits when retrieved. - BCvt, // The value is bit-converted in the location. - Trunc, // The value is truncated in the location. - VExt, // The value is vector-widened in the location. - // FIXME: Not implemented yet. Code that uses AExt to mean - // vector-widen should be fixed to use VExt instead. - FPExt, // The floating-point value is fp-extended in the location. - Indirect // The location contains pointer to the value. - // TODO: a subset of the value is in the location. - }; - -private: - /// ValNo - This is the value number being assigned (e.g. an argument number). - unsigned ValNo; - - /// Loc is either a stack offset or a register number. - unsigned Loc; - - /// isMem - True if this is a memory loc, false if it is a register loc. - unsigned isMem : 1; - - /// isCustom - True if this arg/retval requires special handling. - unsigned isCustom : 1; - - /// Information about how the value is assigned. - LocInfo HTP : 6; - - /// ValVT - The type of the value being assigned. - MVT ValVT; - - /// LocVT - The type of the location being assigned to. - MVT LocVT; -public: - - static CCValAssign getReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret.ValNo = ValNo; - Ret.Loc = RegNo; - Ret.isMem = false; - Ret.isCustom = false; - Ret.HTP = HTP; - Ret.ValVT = ValVT; - Ret.LocVT = LocVT; - return Ret; - } - - static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); - Ret.isCustom = true; - return Ret; - } - - static CCValAssign getMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret.ValNo = ValNo; - Ret.Loc = Offset; - Ret.isMem = true; - Ret.isCustom = false; - Ret.HTP = HTP; - Ret.ValVT = ValVT; - Ret.LocVT = LocVT; - return Ret; - } - - static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); - Ret.isCustom = true; - return Ret; - } - - // There is no need to differentiate between a pending CCValAssign and other - // kinds, as they are stored in a different list. - static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, - LocInfo HTP, unsigned ExtraInfo = 0) { - return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); - } - - void convertToReg(unsigned RegNo) { - Loc = RegNo; - isMem = false; - } - - void convertToMem(unsigned Offset) { - Loc = Offset; - isMem = true; - } - - unsigned getValNo() const { return ValNo; } - MVT getValVT() const { return ValVT; } - - bool isRegLoc() const { return !isMem; } - bool isMemLoc() const { return isMem; } - - bool needsCustom() const { return isCustom; } - - Register getLocReg() const { assert(isRegLoc()); return Loc; } - unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } - unsigned getExtraInfo() const { return Loc; } - MVT getLocVT() const { return LocVT; } - - LocInfo getLocInfo() const { return HTP; } - bool isExtInLoc() const { - return (HTP == AExt || HTP == SExt || HTP == ZExt); - } - - bool isUpperBitsInLoc() const { - return HTP == AExtUpper || HTP == SExtUpper || HTP == ZExtUpper; - } -}; - -/// Describes a register that needs to be forwarded from the prologue to a -/// musttail call. -struct ForwardedRegister { - ForwardedRegister(Register VReg, MCPhysReg PReg, MVT VT) - : VReg(VReg), PReg(PReg), VT(VT) {} - Register VReg; - MCPhysReg PReg; - MVT VT; -}; - -/// CCAssignFn - This function assigns a location for Val, updating State to -/// reflect the change. It returns 'true' if it failed to handle Val. -typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State); - -/// CCCustomFn - This function assigns a location for Val, possibly updating -/// all args to reflect changes and indicates if it handled it. It must set -/// isCustom if it handles the arg and returns true. -typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State); - -/// CCState - This class holds information needed while lowering arguments and -/// return values. It captures which registers are already assigned and which -/// stack slots are used. It provides accessors to allocate these values. -class CCState { -private: - CallingConv::ID CallingConv; - bool IsVarArg; - bool AnalyzingMustTailForwardedRegs = false; - MachineFunction &MF; - const TargetRegisterInfo &TRI; - SmallVectorImpl &Locs; - LLVMContext &Context; - - unsigned StackOffset; - Align MaxStackArgAlign; - SmallVector UsedRegs; - SmallVector PendingLocs; - SmallVector PendingArgFlags; - - // ByValInfo and SmallVector ByValRegs: - // - // Vector of ByValInfo instances (ByValRegs) is introduced for byval registers - // tracking. - // Or, in another words it tracks byval parameters that are stored in - // general purpose registers. - // - // For 4 byte stack alignment, - // instance index means byval parameter number in formal - // arguments set. Assume, we have some "struct_type" with size = 4 bytes, - // then, for function "foo": - // - // i32 foo(i32 %p, %struct_type* %r, i32 %s, %struct_type* %t) - // - // ByValRegs[0] describes how "%r" is stored (Begin == r1, End == r2) - // ByValRegs[1] describes how "%t" is stored (Begin == r3, End == r4). - // - // In case of 8 bytes stack alignment, - // In function shown above, r3 would be wasted according to AAPCS rules. - // ByValRegs vector size still would be 2, - // while "%t" goes to the stack: it wouldn't be described in ByValRegs. - // - // Supposed use-case for this collection: - // 1. Initially ByValRegs is empty, InRegsParamsProcessed is 0. - // 2. HandleByVal fills up ByValRegs. - // 3. Argument analysis (LowerFormatArguments, for example). After - // some byval argument was analyzed, InRegsParamsProcessed is increased. - struct ByValInfo { - ByValInfo(unsigned B, unsigned E) : Begin(B), End(E) {} - - // First register allocated for current parameter. - unsigned Begin; - - // First after last register allocated for current parameter. - unsigned End; - }; - SmallVector ByValRegs; - - // InRegsParamsProcessed - shows how many instances of ByValRegs was proceed - // during argument analysis. - unsigned InRegsParamsProcessed; - -public: - CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - SmallVectorImpl &locs, LLVMContext &C); - - void addLoc(const CCValAssign &V) { - Locs.push_back(V); - } - - LLVMContext &getContext() const { return Context; } - MachineFunction &getMachineFunction() const { return MF; } - CallingConv::ID getCallingConv() const { return CallingConv; } - bool isVarArg() const { return IsVarArg; } - - /// getNextStackOffset - Return the next stack offset such that all stack - /// slots satisfy their alignment requirements. - unsigned getNextStackOffset() const { - return StackOffset; - } - - /// getAlignedCallFrameSize - Return the size of the call frame needed to - /// be able to store all arguments and such that the alignment requirement - /// of each of the arguments is satisfied. - unsigned getAlignedCallFrameSize() const { - return alignTo(StackOffset, MaxStackArgAlign); - } - - /// isAllocated - Return true if the specified register (or an alias) is - /// allocated. - bool isAllocated(MCRegister Reg) const { - return UsedRegs[Reg / 32] & (1 << (Reg & 31)); - } - - /// AnalyzeFormalArguments - Analyze an array of argument values, - /// incorporating info about the formals into this state. - void AnalyzeFormalArguments(const SmallVectorImpl &Ins, - CCAssignFn Fn); - - /// The function will invoke AnalyzeFormalArguments. - void AnalyzeArguments(const SmallVectorImpl &Ins, - CCAssignFn Fn) { - AnalyzeFormalArguments(Ins, Fn); - } - - /// AnalyzeReturn - Analyze the returned values of a return, - /// incorporating info about the result values into this state. - void AnalyzeReturn(const SmallVectorImpl &Outs, - CCAssignFn Fn); - - /// CheckReturn - Analyze the return values of a function, returning - /// true if the return can be performed without sret-demotion, and - /// false otherwise. - bool CheckReturn(const SmallVectorImpl &Outs, - CCAssignFn Fn); - - /// AnalyzeCallOperands - Analyze the outgoing arguments to a call, - /// incorporating info about the passed values into this state. - void AnalyzeCallOperands(const SmallVectorImpl &Outs, - CCAssignFn Fn); - - /// AnalyzeCallOperands - Same as above except it takes vectors of types - /// and argument flags. - void AnalyzeCallOperands(SmallVectorImpl &ArgVTs, - SmallVectorImpl &Flags, - CCAssignFn Fn); - - /// The function will invoke AnalyzeCallOperands. - void AnalyzeArguments(const SmallVectorImpl &Outs, - CCAssignFn Fn) { - AnalyzeCallOperands(Outs, Fn); - } - - /// AnalyzeCallResult - Analyze the return values of a call, - /// incorporating info about the passed values into this state. - void AnalyzeCallResult(const SmallVectorImpl &Ins, - CCAssignFn Fn); - - /// A shadow allocated register is a register that was allocated - /// but wasn't added to the location list (Locs). - /// \returns true if the register was allocated as shadow or false otherwise. - bool IsShadowAllocatedReg(MCRegister Reg) const; - - /// AnalyzeCallResult - Same as above except it's specialized for calls which - /// produce a single value. - void AnalyzeCallResult(MVT VT, CCAssignFn Fn); - - /// getFirstUnallocated - Return the index of the first unallocated register - /// in the set, or Regs.size() if they are all allocated. - unsigned getFirstUnallocated(ArrayRef Regs) const { - for (unsigned i = 0; i < Regs.size(); ++i) - if (!isAllocated(Regs[i])) - return i; - return Regs.size(); - } - - void DeallocateReg(MCPhysReg Reg) { - assert(isAllocated(Reg) && "Trying to deallocate an unallocated register"); - MarkUnallocated(Reg); - } - - /// AllocateReg - Attempt to allocate one register. If it is not available, - /// return zero. Otherwise, return the register, marking it and any aliases - /// as allocated. - MCRegister AllocateReg(MCPhysReg Reg) { - if (isAllocated(Reg)) - return MCRegister(); - MarkAllocated(Reg); - return Reg; - } - - /// Version of AllocateReg with extra register to be shadowed. - MCRegister AllocateReg(MCPhysReg Reg, MCPhysReg ShadowReg) { - if (isAllocated(Reg)) - return MCRegister(); - MarkAllocated(Reg); - MarkAllocated(ShadowReg); - return Reg; - } - - /// AllocateReg - Attempt to allocate one of the specified registers. If none - /// are available, return zero. Otherwise, return the first one available, - /// marking it and any aliases as allocated. - MCPhysReg AllocateReg(ArrayRef Regs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs); - if (FirstUnalloc == Regs.size()) - return MCRegister(); // Didn't find the reg. - - // Mark the register and any aliases as allocated. - MCPhysReg Reg = Regs[FirstUnalloc]; - MarkAllocated(Reg); - return Reg; - } - - /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive - /// registers. If this is not possible, return zero. Otherwise, return the first - /// register of the block that were allocated, marking the entire block as allocated. - MCPhysReg AllocateRegBlock(ArrayRef Regs, unsigned RegsRequired) { - if (RegsRequired > Regs.size()) - return 0; - - for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; - ++StartIdx) { - bool BlockAvailable = true; - // Check for already-allocated regs in this block - for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { - if (isAllocated(Regs[StartIdx + BlockIdx])) { - BlockAvailable = false; - break; - } - } - if (BlockAvailable) { - // Mark the entire block as allocated - for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { - MarkAllocated(Regs[StartIdx + BlockIdx]); - } - return Regs[StartIdx]; - } - } - // No block was available - return 0; - } - - /// Version of AllocateReg with list of registers to be shadowed. - MCRegister AllocateReg(ArrayRef Regs, const MCPhysReg *ShadowRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs); - if (FirstUnalloc == Regs.size()) - return MCRegister(); // Didn't find the reg. - - // Mark the register and any aliases as allocated. - MCRegister Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc]; - MarkAllocated(Reg); - MarkAllocated(ShadowReg); - return Reg; - } - - /// AllocateStack - Allocate a chunk of stack space with the specified size - /// and alignment. - unsigned AllocateStack(unsigned Size, Align Alignment) { - StackOffset = alignTo(StackOffset, Alignment); - unsigned Result = StackOffset; - StackOffset += Size; - MaxStackArgAlign = std::max(Alignment, MaxStackArgAlign); - ensureMaxAlignment(Alignment); - return Result; - } - - void ensureMaxAlignment(Align Alignment); - - /// Version of AllocateStack with list of extra registers to be shadowed. - /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. - unsigned AllocateStack(unsigned Size, Align Alignment, - ArrayRef ShadowRegs) { - for (unsigned i = 0; i < ShadowRegs.size(); ++i) - MarkAllocated(ShadowRegs[i]); - return AllocateStack(Size, Alignment); - } - - // HandleByVal - Allocate a stack slot large enough to pass an argument by - // value. The size and alignment information of the argument is encoded in its - // parameter attribute. - void HandleByVal(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, int MinSize, Align MinAlign, - ISD::ArgFlagsTy ArgFlags); - - // Returns count of byval arguments that are to be stored (even partly) - // in registers. - unsigned getInRegsParamsCount() const { return ByValRegs.size(); } - - // Returns count of byval in-regs arguments processed. - unsigned getInRegsParamsProcessed() const { return InRegsParamsProcessed; } - - // Get information about N-th byval parameter that is stored in registers. - // Here "ByValParamIndex" is N. - void getInRegsParamInfo(unsigned InRegsParamRecordIndex, - unsigned& BeginReg, unsigned& EndReg) const { - assert(InRegsParamRecordIndex < ByValRegs.size() && - "Wrong ByVal parameter index"); - - const ByValInfo& info = ByValRegs[InRegsParamRecordIndex]; - BeginReg = info.Begin; - EndReg = info.End; - } - - // Add information about parameter that is kept in registers. - void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd) { - ByValRegs.push_back(ByValInfo(RegBegin, RegEnd)); - } - - // Goes either to next byval parameter (excluding "waste" record), or - // to the end of collection. - // Returns false, if end is reached. - bool nextInRegsParam() { - unsigned e = ByValRegs.size(); - if (InRegsParamsProcessed < e) - ++InRegsParamsProcessed; - return InRegsParamsProcessed < e; - } - - // Clear byval registers tracking info. - void clearByValRegsInfo() { - InRegsParamsProcessed = 0; - ByValRegs.clear(); - } - - // Rewind byval registers tracking info. - void rewindByValRegsInfo() { - InRegsParamsProcessed = 0; - } - - // Get list of pending assignments - SmallVectorImpl &getPendingLocs() { - return PendingLocs; - } - - // Get a list of argflags for pending assignments. - SmallVectorImpl &getPendingArgFlags() { - return PendingArgFlags; - } - - /// Compute the remaining unused register parameters that would be used for - /// the given value type. This is useful when varargs are passed in the - /// registers that normal prototyped parameters would be passed in, or for - /// implementing perfect forwarding. - void getRemainingRegParmsForType(SmallVectorImpl &Regs, MVT VT, - CCAssignFn Fn); - - /// Compute the set of registers that need to be preserved and forwarded to - /// any musttail calls. - void analyzeMustTailForwardedRegisters( - SmallVectorImpl &Forwards, ArrayRef RegParmTypes, - CCAssignFn Fn); - - /// Returns true if the results of the two calling conventions are compatible. - /// This is usually part of the check for tailcall eligibility. - static bool resultsCompatible(CallingConv::ID CalleeCC, - CallingConv::ID CallerCC, MachineFunction &MF, - LLVMContext &C, - const SmallVectorImpl &Ins, - CCAssignFn CalleeFn, CCAssignFn CallerFn); - - /// The function runs an additional analysis pass over function arguments. - /// It will mark each argument with the attribute flag SecArgPass. - /// After running, it will sort the locs list. - template - void AnalyzeArgumentsSecondPass(const SmallVectorImpl &Args, - CCAssignFn Fn) { - unsigned NumFirstPassLocs = Locs.size(); - - /// Creates similar argument list to \p Args in which each argument is - /// marked using SecArgPass flag. - SmallVector SecPassArg; - // SmallVector SecPassArg; - for (auto Arg : Args) { - Arg.Flags.setSecArgPass(); - SecPassArg.push_back(Arg); - } - - // Run the second argument pass - AnalyzeArguments(SecPassArg, Fn); - - // Sort the locations of the arguments according to their original position. - SmallVector TmpArgLocs; - TmpArgLocs.swap(Locs); - auto B = TmpArgLocs.begin(), E = TmpArgLocs.end(); - std::merge(B, B + NumFirstPassLocs, B + NumFirstPassLocs, E, - std::back_inserter(Locs), - [](const CCValAssign &A, const CCValAssign &B) -> bool { - return A.getValNo() < B.getValNo(); - }); - } - -private: - /// MarkAllocated - Mark a register and all of its aliases as allocated. - void MarkAllocated(MCPhysReg Reg); - - void MarkUnallocated(MCPhysReg Reg); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_CALLINGCONVLOWER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenCommonISel.h b/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenCommonISel.h deleted file mode 100644 index 270f935b67..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenCommonISel.h +++ /dev/null @@ -1,219 +0,0 @@ -//===- CodeGenCommonISel.h - Common code between ISels ---------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares common utilities that are shared between SelectionDAG and -// GlobalISel frameworks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_CODEGENCOMMONISEL_H -#define LLVM_CODEGEN_CODEGENCOMMONISEL_H - -#include "llvm/CodeGen/MachineBasicBlock.h" -#include -namespace llvm { - -class BasicBlock; -class MachineBasicBlock; -/// Encapsulates all of the information needed to generate a stack protector -/// check, and signals to isel when initialized that one needs to be generated. -/// -/// *NOTE* The following is a high level documentation of SelectionDAG Stack -/// Protector Generation. This is now also ported be shared with GlobalISel, -/// but without any significant changes. -/// -/// High Level Overview of ISel Stack Protector Generation: -/// -/// Previously, the "stack protector" IR pass handled stack protector -/// generation. This necessitated splitting basic blocks at the IR level to -/// create the success/failure basic blocks in the tail of the basic block in -/// question. As a result of this, calls that would have qualified for the -/// sibling call optimization were no longer eligible for optimization since -/// said calls were no longer right in the "tail position" (i.e. the immediate -/// predecessor of a ReturnInst instruction). -/// -/// Since the sibling call optimization causes the callee to reuse the caller's -/// stack, if we could delay the generation of the stack protector check until -/// later in CodeGen after the sibling call decision was made, we get both the -/// tail call optimization and the stack protector check! -/// -/// A few goals in solving this problem were: -/// -/// 1. Preserve the architecture independence of stack protector generation. -/// -/// 2. Preserve the normal IR level stack protector check for platforms like -/// OpenBSD for which we support platform-specific stack protector -/// generation. -/// -/// The main problem that guided the present solution is that one can not -/// solve this problem in an architecture independent manner at the IR level -/// only. This is because: -/// -/// 1. The decision on whether or not to perform a sibling call on certain -/// platforms (for instance i386) requires lower level information -/// related to available registers that can not be known at the IR level. -/// -/// 2. Even if the previous point were not true, the decision on whether to -/// perform a tail call is done in LowerCallTo in SelectionDAG (or -/// CallLowering in GlobalISel) which occurs after the Stack Protector -/// Pass. As a result, one would need to put the relevant callinst into the -/// stack protector check success basic block (where the return inst is -/// placed) and then move it back later at ISel/MI time before the -/// stack protector check if the tail call optimization failed. The MI -/// level option was nixed immediately since it would require -/// platform-specific pattern matching. The ISel level option was -/// nixed because SelectionDAG only processes one IR level basic block at a -/// time implying one could not create a DAG Combine to move the callinst. -/// -/// To get around this problem: -/// -/// 1. SelectionDAG can only process one block at a time, we can generate -/// multiple machine basic blocks for one IR level basic block. -/// This is how we handle bit tests and switches. -/// -/// 2. At the MI level, tail calls are represented via a special return -/// MIInst called "tcreturn". Thus if we know the basic block in which we -/// wish to insert the stack protector check, we get the correct behavior -/// by always inserting the stack protector check right before the return -/// statement. This is a "magical transformation" since no matter where -/// the stack protector check intrinsic is, we always insert the stack -/// protector check code at the end of the BB. -/// -/// Given the aforementioned constraints, the following solution was devised: -/// -/// 1. On platforms that do not support ISel stack protector check -/// generation, allow for the normal IR level stack protector check -/// generation to continue. -/// -/// 2. On platforms that do support ISel stack protector check -/// generation: -/// -/// a. Use the IR level stack protector pass to decide if a stack -/// protector is required/which BB we insert the stack protector check -/// in by reusing the logic already therein. -/// -/// b. After we finish selecting the basic block, we produce the validation -/// code with one of these techniques: -/// 1) with a call to a guard check function -/// 2) with inlined instrumentation -/// -/// 1) We insert a call to the check function before the terminator. -/// -/// 2) We first find a splice point in the parent basic block -/// before the terminator and then splice the terminator of said basic -/// block into the success basic block. Then we code-gen a new tail for -/// the parent basic block consisting of the two loads, the comparison, -/// and finally two branches to the success/failure basic blocks. We -/// conclude by code-gening the failure basic block if we have not -/// code-gened it already (all stack protector checks we generate in -/// the same function, use the same failure basic block). -class StackProtectorDescriptor { -public: - StackProtectorDescriptor() = default; - - /// Returns true if all fields of the stack protector descriptor are - /// initialized implying that we should/are ready to emit a stack protector. - bool shouldEmitStackProtector() const { - return ParentMBB && SuccessMBB && FailureMBB; - } - - bool shouldEmitFunctionBasedCheckStackProtector() const { - return ParentMBB && !SuccessMBB && !FailureMBB; - } - - /// Initialize the stack protector descriptor structure for a new basic - /// block. - void initialize(const BasicBlock *BB, MachineBasicBlock *MBB, - bool FunctionBasedInstrumentation) { - // Make sure we are not initialized yet. - assert(!shouldEmitStackProtector() && "Stack Protector Descriptor is " - "already initialized!"); - ParentMBB = MBB; - if (!FunctionBasedInstrumentation) { - SuccessMBB = addSuccessorMBB(BB, MBB, /* IsLikely */ true); - FailureMBB = addSuccessorMBB(BB, MBB, /* IsLikely */ false, FailureMBB); - } - } - - /// Reset state that changes when we handle different basic blocks. - /// - /// This currently includes: - /// - /// 1. The specific basic block we are generating a - /// stack protector for (ParentMBB). - /// - /// 2. The successor machine basic block that will contain the tail of - /// parent mbb after we create the stack protector check (SuccessMBB). This - /// BB is visited only on stack protector check success. - void resetPerBBState() { - ParentMBB = nullptr; - SuccessMBB = nullptr; - } - - /// Reset state that only changes when we switch functions. - /// - /// This currently includes: - /// - /// 1. FailureMBB since we reuse the failure code path for all stack - /// protector checks created in an individual function. - /// - /// 2.The guard variable since the guard variable we are checking against is - /// always the same. - void resetPerFunctionState() { FailureMBB = nullptr; } - - MachineBasicBlock *getParentMBB() { return ParentMBB; } - MachineBasicBlock *getSuccessMBB() { return SuccessMBB; } - MachineBasicBlock *getFailureMBB() { return FailureMBB; } - -private: - /// The basic block for which we are generating the stack protector. - /// - /// As a result of stack protector generation, we will splice the - /// terminators of this basic block into the successor mbb SuccessMBB and - /// replace it with a compare/branch to the successor mbbs - /// SuccessMBB/FailureMBB depending on whether or not the stack protector - /// was violated. - MachineBasicBlock *ParentMBB = nullptr; - - /// A basic block visited on stack protector check success that contains the - /// terminators of ParentMBB. - MachineBasicBlock *SuccessMBB = nullptr; - - /// This basic block visited on stack protector check failure that will - /// contain a call to __stack_chk_fail(). - MachineBasicBlock *FailureMBB = nullptr; - - /// Add a successor machine basic block to ParentMBB. If the successor mbb - /// has not been created yet (i.e. if SuccMBB = 0), then the machine basic - /// block will be created. Assign a large weight if IsLikely is true. - MachineBasicBlock *addSuccessorMBB(const BasicBlock *BB, - MachineBasicBlock *ParentMBB, - bool IsLikely, - MachineBasicBlock *SuccMBB = nullptr); -}; - -/// Find the split point at which to splice the end of BB into its success stack -/// protector check machine basic block. -/// -/// On many platforms, due to ABI constraints, terminators, even before register -/// allocation, use physical registers. This creates an issue for us since -/// physical registers at this point can not travel across basic -/// blocks. Luckily, selectiondag always moves physical registers into vregs -/// when they enter functions and moves them through a sequence of copies back -/// into the physical registers right before the terminator creating a -/// ``Terminator Sequence''. This function is searching for the beginning of the -/// terminator sequence so that we can ensure that we splice off not just the -/// terminator, but additionally the copies that move the vregs into the -/// physical registers. -MachineBasicBlock::iterator -findSplitPointForStackProtector(MachineBasicBlock *BB, - const TargetInstrInfo &TII); - -} // namespace llvm - -#endif // LLVM_CODEGEN_CODEGENCOMMONISEL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenPassBuilder.h b/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenPassBuilder.h deleted file mode 100644 index 5fc32cd9a5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CodeGenPassBuilder.h +++ /dev/null @@ -1,1150 +0,0 @@ -//===- Construction of codegen pass pipelines ------------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// Interfaces for registering analysis passes, producing common pass manager -/// configurations, and parsing of pass pipelines. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_CODEGENPASSBUILDER_H -#define LLVM_CODEGEN_CODEGENPASSBUILDER_H - -#include "llvm/ADT/FunctionExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/BasicAliasAnalysis.h" -#include "llvm/Analysis/CFLAndersAliasAnalysis.h" -#include "llvm/Analysis/CFLSteensAliasAnalysis.h" -#include "llvm/Analysis/ScopedNoAliasAA.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Analysis/TypeBasedAliasAnalysis.h" -#include "llvm/CodeGen/ExpandReductions.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachinePassManager.h" -#include "llvm/CodeGen/PreISelIntrinsicLowering.h" -#include "llvm/CodeGen/ReplaceWithVeclib.h" -#include "llvm/CodeGen/UnreachableBlockElim.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCTargetOptions.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/CGPassBuilderOption.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Scalar/ConstantHoisting.h" -#include "llvm/Transforms/Scalar/LoopPassManager.h" -#include "llvm/Transforms/Scalar/LoopStrengthReduce.h" -#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" -#include "llvm/Transforms/Scalar/MergeICmps.h" -#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" -#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h" -#include "llvm/Transforms/Utils.h" -#include "llvm/Transforms/Utils/EntryExitInstrumenter.h" -#include "llvm/Transforms/Utils/LowerInvoke.h" -#include -#include -#include - -namespace llvm { - -// FIXME: Dummy target independent passes definitions that have not yet been -// ported to new pass manager. Once they do, remove these. -#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - struct PASS_NAME : public PassInfoMixin { \ - template PASS_NAME(Ts &&...) {} \ - PreservedAnalyses run(Function &, FunctionAnalysisManager &) { \ - return PreservedAnalyses::all(); \ - } \ - }; -#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - struct PASS_NAME : public PassInfoMixin { \ - template PASS_NAME(Ts &&...) {} \ - PreservedAnalyses run(Module &, ModuleAnalysisManager &) { \ - return PreservedAnalyses::all(); \ - } \ - }; -#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - struct PASS_NAME : public PassInfoMixin { \ - template PASS_NAME(Ts &&...) {} \ - Error run(Module &, MachineFunctionAnalysisManager &) { \ - return Error::success(); \ - } \ - PreservedAnalyses run(MachineFunction &, \ - MachineFunctionAnalysisManager &) { \ - llvm_unreachable("this api is to make new PM api happy"); \ - } \ - static AnalysisKey Key; \ - }; -#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - struct PASS_NAME : public PassInfoMixin { \ - template PASS_NAME(Ts &&...) {} \ - PreservedAnalyses run(MachineFunction &, \ - MachineFunctionAnalysisManager &) { \ - return PreservedAnalyses::all(); \ - } \ - static AnalysisKey Key; \ - }; -#include "MachinePassRegistry.def" - -/// This class provides access to building LLVM's passes. -/// -/// Its members provide the baseline state available to passes during their -/// construction. The \c MachinePassRegistry.def file specifies how to construct -/// all of the built-in passes, and those may reference these members during -/// construction. -template class CodeGenPassBuilder { -public: - explicit CodeGenPassBuilder(LLVMTargetMachine &TM, CGPassBuilderOption Opts, - PassInstrumentationCallbacks *PIC) - : TM(TM), Opt(Opts), PIC(PIC) { - // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve - // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID) - - // Target should override TM.Options.EnableIPRA in their target-specific - // LLVMTM ctor. See TargetMachine::setGlobalISel for example. - if (Opt.EnableIPRA) - TM.Options.EnableIPRA = *Opt.EnableIPRA; - - if (Opt.EnableGlobalISelAbort) - TM.Options.GlobalISelAbort = *Opt.EnableGlobalISelAbort; - - if (!Opt.OptimizeRegAlloc) - Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOpt::None; - } - - Error buildPipeline(ModulePassManager &MPM, MachineFunctionPassManager &MFPM, - raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType) const; - - void registerModuleAnalyses(ModuleAnalysisManager &) const; - void registerFunctionAnalyses(FunctionAnalysisManager &) const; - void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &) const; - std::pair getPassNameFromLegacyName(StringRef) const; - - void registerAnalyses(MachineFunctionAnalysisManager &MFAM) const { - registerModuleAnalyses(*MFAM.MAM); - registerFunctionAnalyses(*MFAM.FAM); - registerMachineFunctionAnalyses(MFAM); - } - - PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const { - return PIC; - } - -protected: - template using has_key_t = decltype(PassT::Key); - - template - using is_module_pass_t = decltype(std::declval().run( - std::declval(), std::declval())); - - template - using is_function_pass_t = decltype(std::declval().run( - std::declval(), std::declval())); - - // Function object to maintain state while adding codegen IR passes. - class AddIRPass { - public: - AddIRPass(ModulePassManager &MPM, bool DebugPM, bool Check = true) - : MPM(MPM) { - if (Check) - AddingFunctionPasses = false; - } - ~AddIRPass() { - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - } - - // Add Function Pass - template - std::enable_if_t::value> - operator()(PassT &&Pass) { - if (AddingFunctionPasses && !*AddingFunctionPasses) - AddingFunctionPasses = true; - FPM.addPass(std::forward(Pass)); - } - - // Add Module Pass - template - std::enable_if_t::value && - !is_detected::value> - operator()(PassT &&Pass) { - assert((!AddingFunctionPasses || !*AddingFunctionPasses) && - "could not add module pass after adding function pass"); - MPM.addPass(std::forward(Pass)); - } - - private: - ModulePassManager &MPM; - FunctionPassManager FPM; - // The codegen IR pipeline are mostly function passes with the exceptions of - // a few loop and module passes. `AddingFunctionPasses` make sures that - // we could only add module passes at the beginning of the pipeline. Once - // we begin adding function passes, we could no longer add module passes. - // This special-casing introduces less adaptor passes. If we have the need - // of adding module passes after function passes, we could change the - // implementation to accommodate that. - Optional AddingFunctionPasses; - }; - - // Function object to maintain state while adding codegen machine passes. - class AddMachinePass { - public: - AddMachinePass(MachineFunctionPassManager &PM) : PM(PM) {} - - template void operator()(PassT &&Pass) { - static_assert( - is_detected::value, - "Machine function pass must define a static member variable `Key`."); - for (auto &C : BeforeCallbacks) - if (!C(&PassT::Key)) - return; - PM.addPass(std::forward(Pass)); - for (auto &C : AfterCallbacks) - C(&PassT::Key); - } - - template void insertPass(AnalysisKey *ID, PassT Pass) { - AfterCallbacks.emplace_back( - [this, ID, Pass = std::move(Pass)](AnalysisKey *PassID) { - if (PassID == ID) - this->PM.addPass(std::move(Pass)); - }); - } - - void disablePass(AnalysisKey *ID) { - BeforeCallbacks.emplace_back( - [ID](AnalysisKey *PassID) { return PassID != ID; }); - } - - MachineFunctionPassManager releasePM() { return std::move(PM); } - - private: - MachineFunctionPassManager &PM; - SmallVector, 4> BeforeCallbacks; - SmallVector, 4> AfterCallbacks; - }; - - LLVMTargetMachine &TM; - CGPassBuilderOption Opt; - PassInstrumentationCallbacks *PIC; - - /// Target override these hooks to parse target-specific analyses. - void registerTargetAnalysis(ModuleAnalysisManager &) const {} - void registerTargetAnalysis(FunctionAnalysisManager &) const {} - void registerTargetAnalysis(MachineFunctionAnalysisManager &) const {} - std::pair getTargetPassNameFromLegacyName(StringRef) const { - return {"", false}; - } - - template TMC &getTM() const { return static_cast(TM); } - CodeGenOpt::Level getOptLevel() const { return TM.getOptLevel(); } - - /// Check whether or not GlobalISel should abort on error. - /// When this is disabled, GlobalISel will fall back on SDISel instead of - /// erroring out. - bool isGlobalISelAbortEnabled() const { - return TM.Options.GlobalISelAbort == GlobalISelAbortMode::Enable; - } - - /// Check whether or not a diagnostic should be emitted when GlobalISel - /// uses the fallback path. In other words, it will emit a diagnostic - /// when GlobalISel failed and isGlobalISelAbortEnabled is false. - bool reportDiagnosticWhenGlobalISelFallback() const { - return TM.Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag; - } - - /// addInstSelector - This method should install an instruction selector pass, - /// which converts from LLVM code to machine instructions. - Error addInstSelector(AddMachinePass &) const { - return make_error("addInstSelector is not overridden", - inconvertibleErrorCode()); - } - - /// Add passes that optimize instruction level parallelism for out-of-order - /// targets. These passes are run while the machine code is still in SSA - /// form, so they can use MachineTraceMetrics to control their heuristics. - /// - /// All passes added here should preserve the MachineDominatorTree, - /// MachineLoopInfo, and MachineTraceMetrics analyses. - void addILPOpts(AddMachinePass &) const {} - - /// This method may be implemented by targets that want to run passes - /// immediately before register allocation. - void addPreRegAlloc(AddMachinePass &) const {} - - /// addPreRewrite - Add passes to the optimized register allocation pipeline - /// after register allocation is complete, but before virtual registers are - /// rewritten to physical registers. - /// - /// These passes must preserve VirtRegMap and LiveIntervals, and when running - /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. - /// When these passes run, VirtRegMap contains legal physreg assignments for - /// all virtual registers. - /// - /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not - /// be honored. This is also not generally used for the fast variant, - /// where the allocation and rewriting are done in one pass. - void addPreRewrite(AddMachinePass &) const {} - - /// Add passes to be run immediately after virtual registers are rewritten - /// to physical registers. - void addPostRewrite(AddMachinePass &) const {} - - /// This method may be implemented by targets that want to run passes after - /// register allocation pass pipeline but before prolog-epilog insertion. - void addPostRegAlloc(AddMachinePass &) const {} - - /// This method may be implemented by targets that want to run passes after - /// prolog-epilog insertion and before the second instruction scheduling pass. - void addPreSched2(AddMachinePass &) const {} - - /// This pass may be implemented by targets that want to run passes - /// immediately before machine code is emitted. - void addPreEmitPass(AddMachinePass &) const {} - - /// Targets may add passes immediately before machine code is emitted in this - /// callback. This is called even later than `addPreEmitPass`. - // FIXME: Rename `addPreEmitPass` to something more sensible given its actual - // position and remove the `2` suffix here as this callback is what - // `addPreEmitPass` *should* be but in reality isn't. - void addPreEmitPass2(AddMachinePass &) const {} - - /// {{@ For GlobalISel - /// - - /// addPreISel - This method should add any "last minute" LLVM->LLVM - /// passes (which are run just before instruction selector). - void addPreISel(AddIRPass &) const { - llvm_unreachable("addPreISel is not overridden"); - } - - /// This method should install an IR translator pass, which converts from - /// LLVM code to machine instructions with possibly generic opcodes. - Error addIRTranslator(AddMachinePass &) const { - return make_error("addIRTranslator is not overridden", - inconvertibleErrorCode()); - } - - /// This method may be implemented by targets that want to run passes - /// immediately before legalization. - void addPreLegalizeMachineIR(AddMachinePass &) const {} - - /// This method should install a legalize pass, which converts the instruction - /// sequence into one that can be selected by the target. - Error addLegalizeMachineIR(AddMachinePass &) const { - return make_error("addLegalizeMachineIR is not overridden", - inconvertibleErrorCode()); - } - - /// This method may be implemented by targets that want to run passes - /// immediately before the register bank selection. - void addPreRegBankSelect(AddMachinePass &) const {} - - /// This method should install a register bank selector pass, which - /// assigns register banks to virtual registers without a register - /// class or register banks. - Error addRegBankSelect(AddMachinePass &) const { - return make_error("addRegBankSelect is not overridden", - inconvertibleErrorCode()); - } - - /// This method may be implemented by targets that want to run passes - /// immediately before the (global) instruction selection. - void addPreGlobalInstructionSelect(AddMachinePass &) const {} - - /// This method should install a (global) instruction selector pass, which - /// converts possibly generic instructions to fully target-specific - /// instructions, thereby constraining all generic virtual registers to - /// register classes. - Error addGlobalInstructionSelect(AddMachinePass &) const { - return make_error( - "addGlobalInstructionSelect is not overridden", - inconvertibleErrorCode()); - } - /// @}} - - /// High level function that adds all passes necessary to go from llvm IR - /// representation to the MI representation. - /// Adds IR based lowering and target specific optimization passes and finally - /// the core instruction selection passes. - void addISelPasses(AddIRPass &) const; - - /// Add the actual instruction selection passes. This does not include - /// preparation passes on IR. - Error addCoreISelPasses(AddMachinePass &) const; - - /// Add the complete, standard set of LLVM CodeGen passes. - /// Fully developed targets will not generally override this. - Error addMachinePasses(AddMachinePass &) const; - - /// Add passes to lower exception handling for the code generator. - void addPassesToHandleExceptions(AddIRPass &) const; - - /// Add common target configurable passes that perform LLVM IR to IR - /// transforms following machine independent optimization. - void addIRPasses(AddIRPass &) const; - - /// Add pass to prepare the LLVM IR for code generation. This should be done - /// before exception handling preparation passes. - void addCodeGenPrepare(AddIRPass &) const; - - /// Add common passes that perform LLVM IR to IR transforms in preparation for - /// instruction selection. - void addISelPrepare(AddIRPass &) const; - - /// Methods with trivial inline returns are convenient points in the common - /// codegen pass pipeline where targets may insert passes. Methods with - /// out-of-line standard implementations are major CodeGen stages called by - /// addMachinePasses. Some targets may override major stages when inserting - /// passes is insufficient, but maintaining overridden stages is more work. - /// - - /// addMachineSSAOptimization - Add standard passes that optimize machine - /// instructions in SSA form. - void addMachineSSAOptimization(AddMachinePass &) const; - - /// addFastRegAlloc - Add the minimum set of target-independent passes that - /// are required for fast register allocation. - Error addFastRegAlloc(AddMachinePass &) const; - - /// addOptimizedRegAlloc - Add passes related to register allocation. - /// LLVMTargetMachine provides standard regalloc passes for most targets. - void addOptimizedRegAlloc(AddMachinePass &) const; - - /// Add passes that optimize machine instructions after register allocation. - void addMachineLateOptimization(AddMachinePass &) const; - - /// addGCPasses - Add late codegen passes that analyze code for garbage - /// collection. This should return true if GC info should be printed after - /// these passes. - void addGCPasses(AddMachinePass &) const {} - - /// Add standard basic block placement passes. - void addBlockPlacement(AddMachinePass &) const; - - using CreateMCStreamer = - std::function>(MCContext &)>; - void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const { - llvm_unreachable("addAsmPrinter is not overridden"); - } - - /// Utilities for targets to add passes to the pass manager. - /// - - /// createTargetRegisterAllocator - Create the register allocator pass for - /// this target at the current optimization level. - void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const; - - /// addMachinePasses helper to create the target-selected or overridden - /// regalloc pass. - void addRegAllocPass(AddMachinePass &, bool Optimized) const; - - /// Add core register allocator passes which do the actual register assignment - /// and rewriting. \returns true if any passes were added. - Error addRegAssignmentFast(AddMachinePass &) const; - Error addRegAssignmentOptimized(AddMachinePass &) const; - -private: - DerivedT &derived() { return static_cast(*this); } - const DerivedT &derived() const { - return static_cast(*this); - } -}; - -template -Error CodeGenPassBuilder::buildPipeline( - ModulePassManager &MPM, MachineFunctionPassManager &MFPM, - raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType) const { - AddIRPass addIRPass(MPM, Opt.DebugPM); - addISelPasses(addIRPass); - - AddMachinePass addPass(MFPM); - if (auto Err = addCoreISelPasses(addPass)) - return std::move(Err); - - if (auto Err = derived().addMachinePasses(addPass)) - return std::move(Err); - - derived().addAsmPrinter( - addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) { - return this->TM.createMCStreamer(Out, DwoOut, FileType, Ctx); - }); - - addPass(FreeMachineFunctionPass()); - return Error::success(); -} - -static inline AAManager registerAAAnalyses(CFLAAType UseCFLAA) { - AAManager AA; - - // The order in which these are registered determines their priority when - // being queried. - - switch (UseCFLAA) { - case CFLAAType::Steensgaard: - AA.registerFunctionAnalysis(); - break; - case CFLAAType::Andersen: - AA.registerFunctionAnalysis(); - break; - case CFLAAType::Both: - AA.registerFunctionAnalysis(); - AA.registerFunctionAnalysis(); - break; - default: - break; - } - - // Basic AliasAnalysis support. - // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that - // BasicAliasAnalysis wins if they disagree. This is intended to help - // support "obvious" type-punning idioms. - AA.registerFunctionAnalysis(); - AA.registerFunctionAnalysis(); - AA.registerFunctionAnalysis(); - - return AA; -} - -template -void CodeGenPassBuilder::registerModuleAnalyses( - ModuleAnalysisManager &MAM) const { -#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ - MAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); -#include "MachinePassRegistry.def" - derived().registerTargetAnalysis(MAM); -} - -template -void CodeGenPassBuilder::registerFunctionAnalyses( - FunctionAnalysisManager &FAM) const { - FAM.registerPass([this] { return registerAAAnalyses(this->Opt.UseCFLAA); }); - -#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ - FAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); -#include "MachinePassRegistry.def" - derived().registerTargetAnalysis(FAM); -} - -template -void CodeGenPassBuilder::registerMachineFunctionAnalyses( - MachineFunctionAnalysisManager &MFAM) const { -#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ - MFAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); -#include "MachinePassRegistry.def" - derived().registerTargetAnalysis(MFAM); -} - -// FIXME: For new PM, use pass name directly in commandline seems good. -// Translate stringfied pass name to its old commandline name. Returns the -// matching legacy name and a boolean value indicating if the pass is a machine -// pass. -template -std::pair -CodeGenPassBuilder::getPassNameFromLegacyName(StringRef Name) const { - std::pair Ret; - if (Name.empty()) - return Ret; - -#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, false}; -#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, false}; -#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, false}; -#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, false}; -#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, true}; -#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, true}; -#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, true}; -#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ - if (Name == NAME) \ - Ret = {#PASS_NAME, true}; -#include "llvm/CodeGen/MachinePassRegistry.def" - - if (Ret.first.empty()) - Ret = derived().getTargetPassNameFromLegacyName(Name); - - if (Ret.first.empty()) - report_fatal_error(Twine('\"') + Twine(Name) + - Twine("\" pass could not be found.")); - - return Ret; -} - -template -void CodeGenPassBuilder::addISelPasses(AddIRPass &addPass) const { - if (TM.useEmulatedTLS()) - addPass(LowerEmuTLSPass()); - - addPass(PreISelIntrinsicLoweringPass()); - - derived().addIRPasses(addPass); - derived().addCodeGenPrepare(addPass); - addPassesToHandleExceptions(addPass); - derived().addISelPrepare(addPass); -} - -/// Add common target configurable passes that perform LLVM IR to IR transforms -/// following machine independent optimization. -template -void CodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const { - // Before running any passes, run the verifier to determine if the input - // coming from the front-end and/or optimizer is valid. - if (!Opt.DisableVerify) - addPass(VerifierPass()); - - // Run loop strength reduction before anything else. - if (getOptLevel() != CodeGenOpt::None && !Opt.DisableLSR) { - addPass(createFunctionToLoopPassAdaptor( - LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM)); - // FIXME: use -stop-after so we could remove PrintLSR - if (Opt.PrintLSR) - addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n")); - } - - if (getOptLevel() != CodeGenOpt::None) { - // The MergeICmpsPass tries to create memcmp calls by grouping sequences of - // loads and compares. ExpandMemCmpPass then tries to expand those calls - // into optimally-sized loads and compares. The transforms are enabled by a - // target lowering hook. - if (!Opt.DisableMergeICmps) - addPass(MergeICmpsPass()); - addPass(ExpandMemCmpPass()); - } - - // Run GC lowering passes for builtin collectors - // TODO: add a pass insertion point here - addPass(GCLoweringPass()); - addPass(ShadowStackGCLoweringPass()); - addPass(LowerConstantIntrinsicsPass()); - - // Make sure that no unreachable blocks are instruction selected. - addPass(UnreachableBlockElimPass()); - - // Prepare expensive constants for SelectionDAG. - if (getOptLevel() != CodeGenOpt::None && !Opt.DisableConstantHoisting) - addPass(ConstantHoistingPass()); - - // Replace calls to LLVM intrinsics (e.g., exp, log) operating on vector - // operands with calls to the corresponding functions in a vector library. - if (getOptLevel() != CodeGenOpt::None) - addPass(ReplaceWithVeclib()); - - if (getOptLevel() != CodeGenOpt::None && !Opt.DisablePartialLibcallInlining) - addPass(PartiallyInlineLibCallsPass()); - - // Instrument function entry and exit, e.g. with calls to mcount(). - addPass(EntryExitInstrumenterPass(/*PostInlining=*/true)); - - // Add scalarization of target's unsupported masked memory intrinsics pass. - // the unsupported intrinsic will be replaced with a chain of basic blocks, - // that stores/loads element one-by-one if the appropriate mask bit is set. - addPass(ScalarizeMaskedMemIntrinPass()); - - // Expand reduction intrinsics into shuffle sequences if the target wants to. - addPass(ExpandReductionsPass()); -} - -/// Turn exception handling constructs into something the code generators can -/// handle. -template -void CodeGenPassBuilder::addPassesToHandleExceptions( - AddIRPass &addPass) const { - const MCAsmInfo *MCAI = TM.getMCAsmInfo(); - assert(MCAI && "No MCAsmInfo"); - switch (MCAI->getExceptionHandlingType()) { - case ExceptionHandling::SjLj: - // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both - // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, - // catch info can get misplaced when a selector ends up more than one block - // removed from the parent invoke(s). This could happen when a landing - // pad is shared by multiple invokes and is also a target of a normal - // edge from elsewhere. - addPass(SjLjEHPreparePass()); - LLVM_FALLTHROUGH; - case ExceptionHandling::DwarfCFI: - case ExceptionHandling::ARM: - case ExceptionHandling::AIX: - addPass(DwarfEHPass(getOptLevel())); - break; - case ExceptionHandling::WinEH: - // We support using both GCC-style and MSVC-style exceptions on Windows, so - // add both preparation passes. Each pass will only actually run if it - // recognizes the personality function. - addPass(WinEHPass()); - addPass(DwarfEHPass(getOptLevel())); - break; - case ExceptionHandling::Wasm: - // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs - // on catchpads and cleanuppads because it does not outline them into - // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we - // should remove PHIs there. - addPass(WinEHPass(/*DemoteCatchSwitchPHIOnly=*/false)); - addPass(WasmEHPass()); - break; - case ExceptionHandling::None: - addPass(LowerInvokePass()); - - // The lower invoke pass may create unreachable code. Remove it. - addPass(UnreachableBlockElimPass()); - break; - } -} - -/// Add pass to prepare the LLVM IR for code generation. This should be done -/// before exception handling preparation passes. -template -void CodeGenPassBuilder::addCodeGenPrepare(AddIRPass &addPass) const { - if (getOptLevel() != CodeGenOpt::None && !Opt.DisableCGP) - addPass(CodeGenPreparePass()); - // TODO: Default ctor'd RewriteSymbolPass is no-op. - // addPass(RewriteSymbolPass()); -} - -/// Add common passes that perform LLVM IR to IR transforms in preparation for -/// instruction selection. -template -void CodeGenPassBuilder::addISelPrepare(AddIRPass &addPass) const { - derived().addPreISel(addPass); - - // Add both the safe stack and the stack protection passes: each of them will - // only protect functions that have corresponding attributes. - addPass(SafeStackPass()); - addPass(StackProtectorPass()); - - if (Opt.PrintISelInput) - addPass(PrintFunctionPass(dbgs(), - "\n\n*** Final LLVM Code input to ISel ***\n")); - - // All passes which modify the LLVM IR are now complete; run the verifier - // to ensure that the IR is valid. - if (!Opt.DisableVerify) - addPass(VerifierPass()); -} - -template -Error CodeGenPassBuilder::addCoreISelPasses( - AddMachinePass &addPass) const { - // Enable FastISel with -fast-isel, but allow that to be overridden. - TM.setO0WantsFastISel(Opt.EnableFastISelOption.getValueOr(true)); - - // Determine an instruction selector. - enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; - SelectorType Selector; - - if (Opt.EnableFastISelOption && *Opt.EnableFastISelOption == true) - Selector = SelectorType::FastISel; - else if ((Opt.EnableGlobalISelOption && - *Opt.EnableGlobalISelOption == true) || - (TM.Options.EnableGlobalISel && - (!Opt.EnableGlobalISelOption || - *Opt.EnableGlobalISelOption == false))) - Selector = SelectorType::GlobalISel; - else if (TM.getOptLevel() == CodeGenOpt::None && TM.getO0WantsFastISel()) - Selector = SelectorType::FastISel; - else - Selector = SelectorType::SelectionDAG; - - // Set consistently TM.Options.EnableFastISel and EnableGlobalISel. - if (Selector == SelectorType::FastISel) { - TM.setFastISel(true); - TM.setGlobalISel(false); - } else if (Selector == SelectorType::GlobalISel) { - TM.setFastISel(false); - TM.setGlobalISel(true); - } - - // Add instruction selector passes. - if (Selector == SelectorType::GlobalISel) { - if (auto Err = derived().addIRTranslator(addPass)) - return std::move(Err); - - derived().addPreLegalizeMachineIR(addPass); - - if (auto Err = derived().addLegalizeMachineIR(addPass)) - return std::move(Err); - - // Before running the register bank selector, ask the target if it - // wants to run some passes. - derived().addPreRegBankSelect(addPass); - - if (auto Err = derived().addRegBankSelect(addPass)) - return std::move(Err); - - derived().addPreGlobalInstructionSelect(addPass); - - if (auto Err = derived().addGlobalInstructionSelect(addPass)) - return std::move(Err); - - // Pass to reset the MachineFunction if the ISel failed. - addPass(ResetMachineFunctionPass(reportDiagnosticWhenGlobalISelFallback(), - isGlobalISelAbortEnabled())); - - // Provide a fallback path when we do not want to abort on - // not-yet-supported input. - if (!isGlobalISelAbortEnabled()) - if (auto Err = derived().addInstSelector(addPass)) - return std::move(Err); - - } else if (auto Err = derived().addInstSelector(addPass)) - return std::move(Err); - - // Expand pseudo-instructions emitted by ISel. Don't run the verifier before - // FinalizeISel. - addPass(FinalizeISelPass()); - - // // Print the instruction selected machine code... - // printAndVerify("After Instruction Selection"); - - return Error::success(); -} - -/// Add the complete set of target-independent postISel code generator passes. -/// -/// This can be read as the standard order of major LLVM CodeGen stages. Stages -/// with nontrivial configuration or multiple passes are broken out below in -/// add%Stage routines. -/// -/// Any CodeGenPassBuilder::addXX routine may be overridden by the -/// Target. The addPre/Post methods with empty header implementations allow -/// injecting target-specific fixups just before or after major stages. -/// Additionally, targets have the flexibility to change pass order within a -/// stage by overriding default implementation of add%Stage routines below. Each -/// technique has maintainability tradeoffs because alternate pass orders are -/// not well supported. addPre/Post works better if the target pass is easily -/// tied to a common pass. But if it has subtle dependencies on multiple passes, -/// the target should override the stage instead. -template -Error CodeGenPassBuilder::addMachinePasses( - AddMachinePass &addPass) const { - // Add passes that optimize machine instructions in SSA form. - if (getOptLevel() != CodeGenOpt::None) { - derived().addMachineSSAOptimization(addPass); - } else { - // If the target requests it, assign local variables to stack slots relative - // to one another and simplify frame index references where possible. - addPass(LocalStackSlotPass()); - } - - if (TM.Options.EnableIPRA) - addPass(RegUsageInfoPropagationPass()); - - // Run pre-ra passes. - derived().addPreRegAlloc(addPass); - - // Run register allocation and passes that are tightly coupled with it, - // including phi elimination and scheduling. - if (*Opt.OptimizeRegAlloc) { - derived().addOptimizedRegAlloc(addPass); - } else { - if (auto Err = derived().addFastRegAlloc(addPass)) - return Err; - } - - // Run post-ra passes. - derived().addPostRegAlloc(addPass); - - addPass(RemoveRedundantDebugValuesPass()); - - // Insert prolog/epilog code. Eliminate abstract frame index references... - if (getOptLevel() != CodeGenOpt::None) { - addPass(PostRAMachineSinkingPass()); - addPass(ShrinkWrapPass()); - } - - addPass(PrologEpilogInserterPass()); - - /// Add passes that optimize machine instructions after register allocation. - if (getOptLevel() != CodeGenOpt::None) - derived().addMachineLateOptimization(addPass); - - // Expand pseudo instructions before second scheduling pass. - addPass(ExpandPostRAPseudosPass()); - - // Run pre-sched2 passes. - derived().addPreSched2(addPass); - - if (Opt.EnableImplicitNullChecks) - addPass(ImplicitNullChecksPass()); - - // Second pass scheduler. - // Let Target optionally insert this pass by itself at some other - // point. - if (getOptLevel() != CodeGenOpt::None && - !TM.targetSchedulesPostRAScheduling()) { - if (Opt.MISchedPostRA) - addPass(PostMachineSchedulerPass()); - else - addPass(PostRASchedulerPass()); - } - - // GC - derived().addGCPasses(addPass); - - // Basic block placement. - if (getOptLevel() != CodeGenOpt::None) - derived().addBlockPlacement(addPass); - - // Insert before XRay Instrumentation. - addPass(FEntryInserterPass()); - - addPass(XRayInstrumentationPass()); - addPass(PatchableFunctionPass()); - - derived().addPreEmitPass(addPass); - - if (TM.Options.EnableIPRA) - // Collect register usage information and produce a register mask of - // clobbered registers, to be used to optimize call sites. - addPass(RegUsageInfoCollectorPass()); - - addPass(FuncletLayoutPass()); - - addPass(StackMapLivenessPass()); - addPass(LiveDebugValuesPass()); - - if (TM.Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None && - Opt.EnableMachineOutliner != RunOutliner::NeverOutline) { - bool RunOnAllFunctions = - (Opt.EnableMachineOutliner == RunOutliner::AlwaysOutline); - bool AddOutliner = RunOnAllFunctions || TM.Options.SupportsDefaultOutlining; - if (AddOutliner) - addPass(MachineOutlinerPass(RunOnAllFunctions)); - } - - // Add passes that directly emit MI after all other MI passes. - derived().addPreEmitPass2(addPass); - - return Error::success(); -} - -/// Add passes that optimize machine instructions in SSA form. -template -void CodeGenPassBuilder::addMachineSSAOptimization( - AddMachinePass &addPass) const { - // Pre-ra tail duplication. - addPass(EarlyTailDuplicatePass()); - - // Optimize PHIs before DCE: removing dead PHI cycles may make more - // instructions dead. - addPass(OptimizePHIsPass()); - - // This pass merges large allocas. StackSlotColoring is a different pass - // which merges spill slots. - addPass(StackColoringPass()); - - // If the target requests it, assign local variables to stack slots relative - // to one another and simplify frame index references where possible. - addPass(LocalStackSlotPass()); - - // With optimization, dead code should already be eliminated. However - // there is one known exception: lowered code for arguments that are only - // used by tail calls, where the tail calls reuse the incoming stack - // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). - addPass(DeadMachineInstructionElimPass()); - - // Allow targets to insert passes that improve instruction level parallelism, - // like if-conversion. Such passes will typically need dominator trees and - // loop info, just like LICM and CSE below. - derived().addILPOpts(addPass); - - addPass(EarlyMachineLICMPass()); - addPass(MachineCSEPass()); - - addPass(MachineSinkingPass()); - - addPass(PeepholeOptimizerPass()); - // Clean-up the dead code that may have been generated by peephole - // rewriting. - addPass(DeadMachineInstructionElimPass()); -} - -//===---------------------------------------------------------------------===// -/// Register Allocation Pass Configuration -//===---------------------------------------------------------------------===// - -/// Instantiate the default register allocator pass for this target for either -/// the optimized or unoptimized allocation path. This will be added to the pass -/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc -/// in the optimized case. -/// -/// A target that uses the standard regalloc pass order for fast or optimized -/// allocation may still override this for per-target regalloc -/// selection. But -regalloc=... always takes precedence. -template -void CodeGenPassBuilder::addTargetRegisterAllocator( - AddMachinePass &addPass, bool Optimized) const { - if (Optimized) - addPass(RAGreedyPass()); - else - addPass(RAFastPass()); -} - -/// Find and instantiate the register allocation pass requested by this target -/// at the current optimization level. Different register allocators are -/// defined as separate passes because they may require different analysis. -template -void CodeGenPassBuilder::addRegAllocPass(AddMachinePass &addPass, - bool Optimized) const { - if (Opt.RegAlloc == RegAllocType::Default) - // With no -regalloc= override, ask the target for a regalloc pass. - derived().addTargetRegisterAllocator(addPass, Optimized); - else if (Opt.RegAlloc == RegAllocType::Basic) - addPass(RABasicPass()); - else if (Opt.RegAlloc == RegAllocType::Fast) - addPass(RAFastPass()); - else if (Opt.RegAlloc == RegAllocType::Greedy) - addPass(RAGreedyPass()); - else if (Opt.RegAlloc == RegAllocType::PBQP) - addPass(RAPBQPPass()); - else - llvm_unreachable("unknown register allocator type"); -} - -template -Error CodeGenPassBuilder::addRegAssignmentFast( - AddMachinePass &addPass) const { - if (Opt.RegAlloc != RegAllocType::Default && - Opt.RegAlloc != RegAllocType::Fast) - return make_error( - "Must use fast (default) register allocator for unoptimized regalloc.", - inconvertibleErrorCode()); - - addRegAllocPass(addPass, false); - return Error::success(); -} - -template -Error CodeGenPassBuilder::addRegAssignmentOptimized( - AddMachinePass &addPass) const { - // Add the selected register allocation pass. - addRegAllocPass(addPass, true); - - // Allow targets to change the register assignments before rewriting. - derived().addPreRewrite(addPass); - - // Finally rewrite virtual registers. - addPass(VirtRegRewriterPass()); - // Perform stack slot coloring and post-ra machine LICM. - // - // FIXME: Re-enable coloring with register when it's capable of adding - // kill markers. - addPass(StackSlotColoringPass()); - - return Error::success(); -} - -/// Add the minimum set of target-independent passes that are required for -/// register allocation. No coalescing or scheduling. -template -Error CodeGenPassBuilder::addFastRegAlloc( - AddMachinePass &addPass) const { - addPass(PHIEliminationPass()); - addPass(TwoAddressInstructionPass()); - return derived().addRegAssignmentFast(addPass); -} - -/// Add standard target-independent passes that are tightly coupled with -/// optimized register allocation, including coalescing, machine instruction -/// scheduling, and register allocation itself. -template -void CodeGenPassBuilder::addOptimizedRegAlloc( - AddMachinePass &addPass) const { - addPass(DetectDeadLanesPass()); - - addPass(ProcessImplicitDefsPass()); - - // Edge splitting is smarter with machine loop info. - addPass(PHIEliminationPass()); - - // Eventually, we want to run LiveIntervals before PHI elimination. - if (Opt.EarlyLiveIntervals) - addPass(LiveIntervalsPass()); - - addPass(TwoAddressInstructionPass()); - addPass(RegisterCoalescerPass()); - - // The machine scheduler may accidentally create disconnected components - // when moving subregister definitions around, avoid this by splitting them to - // separate vregs before. Splitting can also improve reg. allocation quality. - addPass(RenameIndependentSubregsPass()); - - // PreRA instruction scheduling. - addPass(MachineSchedulerPass()); - - if (derived().addRegAssignmentOptimized(addPass)) { - // Allow targets to expand pseudo instructions depending on the choice of - // registers before MachineCopyPropagation. - derived().addPostRewrite(addPass); - - // Copy propagate to forward register uses and try to eliminate COPYs that - // were not coalesced. - addPass(MachineCopyPropagationPass()); - - // Run post-ra machine LICM to hoist reloads / remats. - // - // FIXME: can this move into MachineLateOptimization? - addPass(MachineLICMPass()); - } -} - -//===---------------------------------------------------------------------===// -/// Post RegAlloc Pass Configuration -//===---------------------------------------------------------------------===// - -/// Add passes that optimize machine instructions after register allocation. -template -void CodeGenPassBuilder::addMachineLateOptimization( - AddMachinePass &addPass) const { - // Branch folding must be run after regalloc and prolog/epilog insertion. - addPass(BranchFolderPass()); - - // Tail duplication. - // Note that duplicating tail just increases code size and degrades - // performance for targets that require Structured Control Flow. - // In addition it can also make CFG irreducible. Thus we disable it. - if (!TM.requiresStructuredCFG()) - addPass(TailDuplicatePass()); - - // Copy propagation. - addPass(MachineCopyPropagationPass()); -} - -/// Add standard basic block placement passes. -template -void CodeGenPassBuilder::addBlockPlacement( - AddMachinePass &addPass) const { - addPass(MachineBlockPlacementPass()); - // Run a separate pass to collect block placement statistics. - if (Opt.EnableBlockPlacementStats) - addPass(MachineBlockPlacementStatsPass()); -} - -} // namespace llvm - -#endif // LLVM_CODEGEN_CODEGENPASSBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CommandFlags.h b/suite/synctools/tablegen/include/llvm/CodeGen/CommandFlags.h deleted file mode 100644 index 73d39fecc2..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CommandFlags.h +++ /dev/null @@ -1,181 +0,0 @@ -//===-- CommandFlags.h - Command Line Flags Interface -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains codegen-specific flags that are shared between different -// command line tools. The tools "llc" and "opt" both use this file to prevent -// flag duplication. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_COMMANDFLAGS_H -#define LLVM_CODEGEN_COMMANDFLAGS_H - -#include "llvm/ADT/FloatingPointMode.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Triple.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/MC/MCTargetOptionsCommandFlags.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Target/TargetOptions.h" -#include -#include - -namespace llvm { - -class Module; - -namespace codegen { - -std::string getMArch(); - -std::string getMCPU(); - -std::vector getMAttrs(); - -Reloc::Model getRelocModel(); -Optional getExplicitRelocModel(); - -ThreadModel::Model getThreadModel(); - -CodeModel::Model getCodeModel(); -Optional getExplicitCodeModel(); - -llvm::ExceptionHandling getExceptionModel(); - -Optional getExplicitFileType(); - -CodeGenFileType getFileType(); - -FramePointerKind getFramePointerUsage(); - -bool getEnableUnsafeFPMath(); - -bool getEnableNoInfsFPMath(); - -bool getEnableNoNaNsFPMath(); - -bool getEnableNoSignedZerosFPMath(); - -bool getEnableNoTrappingFPMath(); - -DenormalMode::DenormalModeKind getDenormalFPMath(); -DenormalMode::DenormalModeKind getDenormalFP32Math(); - -bool getEnableHonorSignDependentRoundingFPMath(); - -llvm::FloatABI::ABIType getFloatABIForCalls(); - -llvm::FPOpFusion::FPOpFusionMode getFuseFPOps(); - -SwiftAsyncFramePointerMode getSwiftAsyncFramePointer(); - -bool getDontPlaceZerosInBSS(); - -bool getEnableGuaranteedTailCallOpt(); - -bool getEnableAIXExtendedAltivecABI(); - -bool getDisableTailCalls(); - -bool getStackSymbolOrdering(); - -unsigned getOverrideStackAlignment(); - -bool getStackRealign(); - -std::string getTrapFuncName(); - -bool getUseCtors(); - -bool getRelaxELFRelocations(); - -bool getDataSections(); -Optional getExplicitDataSections(); - -bool getFunctionSections(); -Optional getExplicitFunctionSections(); - -bool getIgnoreXCOFFVisibility(); - -bool getXCOFFTracebackTable(); - -std::string getBBSections(); - -unsigned getTLSSize(); - -bool getEmulatedTLS(); - -bool getUniqueSectionNames(); - -bool getUniqueBasicBlockSectionNames(); - -llvm::EABI getEABIVersion(); - -llvm::DebuggerKind getDebuggerTuningOpt(); - -bool getEnableStackSizeSection(); - -bool getEnableAddrsig(); - -bool getEmitCallSiteInfo(); - -bool getEnableMachineFunctionSplitter(); - -bool getEnableDebugEntryValues(); - -bool getValueTrackingVariableLocations(); -Optional getExplicitValueTrackingVariableLocations(); - -bool getForceDwarfFrameSection(); - -bool getXRayOmitFunctionIndex(); - -bool getDebugStrictDwarf(); - -unsigned getAlignLoops(); - -/// Create this object with static storage to register codegen-related command -/// line options. -struct RegisterCodeGenFlags { - RegisterCodeGenFlags(); -}; - -llvm::BasicBlockSection getBBSectionsMode(llvm::TargetOptions &Options); - -/// Common utility function tightly tied to the options listed here. Initializes -/// a TargetOptions object with CodeGen flags and returns it. -/// \p TheTriple is used to determine the default value for options if -/// options are not explicitly specified. If those triple dependant options -/// value do not have effect for your component, a default Triple() could be -/// passed in. -TargetOptions InitTargetOptionsFromCodeGenFlags(const llvm::Triple &TheTriple); - -std::string getCPUStr(); - -std::string getFeaturesStr(); - -std::vector getFeatureList(); - -void renderBoolStringAttr(AttrBuilder &B, StringRef Name, bool Val); - -/// Set function attributes of function \p F based on CPU, Features, and command -/// line flags. -void setFunctionAttributes(StringRef CPU, StringRef Features, Function &F); - -/// Set function attributes of functions in Module M based on CPU, -/// Features, and command line flags. -void setFunctionAttributes(StringRef CPU, StringRef Features, Module &M); - -/// Should value-tracking variable locations / instruction referencing be -/// enabled by default for this triple? -bool getDefaultValueTrackingVariableLocations(const llvm::Triple &T); -} // namespace codegen -} // namespace llvm - -#endif // LLVM_CODEGEN_COMMANDFLAGS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/CostTable.h b/suite/synctools/tablegen/include/llvm/CodeGen/CostTable.h deleted file mode 100644 index fc4648c252..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/CostTable.h +++ /dev/null @@ -1,89 +0,0 @@ -//===-- CostTable.h - Instruction Cost Table handling -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Cost tables and simple lookup functions -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_COSTTABLE_H_ -#define LLVM_CODEGEN_COSTTABLE_H_ - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/MachineValueType.h" - -namespace llvm { - -/// Cost Table Entry -template -struct CostTblEntryT { - int ISD; - MVT::SimpleValueType Type; - CostType Cost; -}; -using CostTblEntry = CostTblEntryT; - -/// Find in cost table. -template -inline const CostTblEntryT * -CostTableLookup(ArrayRef> Tbl, int ISD, MVT Ty) { - auto I = find_if(Tbl, [=](const CostTblEntryT &Entry) { - return ISD == Entry.ISD && Ty == Entry.Type; - }); - if (I != Tbl.end()) - return I; - - // Could not find an entry. - return nullptr; -} - -template -inline const CostTblEntryT * -CostTableLookup(const CostTblEntryT (&Table)[N], int ISD, MVT Ty) { - // Wrapper to fix template argument deduction failures. - return CostTableLookup(makeArrayRef(Table), ISD, Ty); -} - -/// Type Conversion Cost Table -template -struct TypeConversionCostTblEntryT { - int ISD; - MVT::SimpleValueType Dst; - MVT::SimpleValueType Src; - CostType Cost; -}; -using TypeConversionCostTblEntry = TypeConversionCostTblEntryT; - -/// Find in type conversion cost table. -template -inline const TypeConversionCostTblEntryT * -ConvertCostTableLookup(ArrayRef> Tbl, - int ISD, MVT Dst, MVT Src) { - auto I = - find_if(Tbl, [=](const TypeConversionCostTblEntryT &Entry) { - return ISD == Entry.ISD && Src == Entry.Src && Dst == Entry.Dst; - }); - if (I != Tbl.end()) - return I; - - // Could not find an entry. - return nullptr; -} - -template -inline const TypeConversionCostTblEntryT * -ConvertCostTableLookup(const TypeConversionCostTblEntryT (&Table)[N], - int ISD, MVT Dst, MVT Src) { - // Wrapper to fix template argument deduction failures. - return ConvertCostTableLookup(makeArrayRef(Table), ISD, Dst, Src); -} - -} // namespace llvm - -#endif /* LLVM_CODEGEN_COSTTABLE_H_ */ diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DAGCombine.h b/suite/synctools/tablegen/include/llvm/CodeGen/DAGCombine.h deleted file mode 100644 index 9441873414..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DAGCombine.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- llvm/CodeGen/DAGCombine.h ------- SelectionDAG Nodes ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// - -#ifndef LLVM_CODEGEN_DAGCOMBINE_H -#define LLVM_CODEGEN_DAGCOMBINE_H - -namespace llvm { - -enum CombineLevel { - BeforeLegalizeTypes, - AfterLegalizeTypes, - AfterLegalizeVectorOps, - AfterLegalizeDAG -}; - -} // end llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DFAPacketizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/DFAPacketizer.h deleted file mode 100644 index 7668d76f80..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DFAPacketizer.h +++ /dev/null @@ -1,200 +0,0 @@ -//===- llvm/CodeGen/DFAPacketizer.h - DFA Packetizer for VLIW ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This class implements a deterministic finite automaton (DFA) based -// packetizing mechanism for VLIW architectures. It provides APIs to -// determine whether there exists a legal mapping of instructions to -// functional unit assignments in a packet. The DFA is auto-generated from -// the target's Schedule.td file. -// -// A DFA consists of 3 major elements: states, inputs, and transitions. For -// the packetizing mechanism, the input is the set of instruction classes for -// a target. The state models all possible combinations of functional unit -// consumption for a given set of instructions in a packet. A transition -// models the addition of an instruction to a packet. In the DFA constructed -// by this class, if an instruction can be added to a packet, then a valid -// transition exists from the corresponding state. Invalid transitions -// indicate that the instruction cannot be added to the current packet. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DFAPACKETIZER_H -#define LLVM_CODEGEN_DFAPACKETIZER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ScheduleDAGMutation.h" -#include "llvm/Support/Automaton.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class DefaultVLIWScheduler; -class InstrItineraryData; -class MachineFunction; -class MachineInstr; -class MachineLoopInfo; -class MCInstrDesc; -class SUnit; -class TargetInstrInfo; - -class DFAPacketizer { -private: - const InstrItineraryData *InstrItins; - Automaton A; - /// For every itinerary, an "action" to apply to the automaton. This removes - /// the redundancy in actions between itinerary classes. - ArrayRef ItinActions; - -public: - DFAPacketizer(const InstrItineraryData *InstrItins, Automaton a, - ArrayRef ItinActions) - : InstrItins(InstrItins), A(std::move(a)), ItinActions(ItinActions) { - // Start off with resource tracking disabled. - A.enableTranscription(false); - } - - // Reset the current state to make all resources available. - void clearResources() { - A.reset(); - } - - // Set whether this packetizer should track not just whether instructions - // can be packetized, but also which functional units each instruction ends up - // using after packetization. - void setTrackResources(bool Track) { - A.enableTranscription(Track); - } - - // Check if the resources occupied by a MCInstrDesc are available in - // the current state. - bool canReserveResources(const MCInstrDesc *MID); - - // Reserve the resources occupied by a MCInstrDesc and change the current - // state to reflect that change. - void reserveResources(const MCInstrDesc *MID); - - // Check if the resources occupied by a machine instruction are available - // in the current state. - bool canReserveResources(MachineInstr &MI); - - // Reserve the resources occupied by a machine instruction and change the - // current state to reflect that change. - void reserveResources(MachineInstr &MI); - - // Return the resources used by the InstIdx'th instruction added to this - // packet. The resources are returned as a bitvector of functional units. - // - // Note that a bundle may be packed in multiple valid ways. This function - // returns one arbitrary valid packing. - // - // Requires setTrackResources(true) to have been called. - unsigned getUsedResources(unsigned InstIdx); - - const InstrItineraryData *getInstrItins() const { return InstrItins; } -}; - -// VLIWPacketizerList implements a simple VLIW packetizer using DFA. The -// packetizer works on machine basic blocks. For each instruction I in BB, -// the packetizer consults the DFA to see if machine resources are available -// to execute I. If so, the packetizer checks if I depends on any instruction -// in the current packet. If no dependency is found, I is added to current -// packet and the machine resource is marked as taken. If any dependency is -// found, a target API call is made to prune the dependence. -class VLIWPacketizerList { -protected: - MachineFunction &MF; - const TargetInstrInfo *TII; - AAResults *AA; - - // The VLIW Scheduler. - DefaultVLIWScheduler *VLIWScheduler; - // Vector of instructions assigned to the current packet. - std::vector CurrentPacketMIs; - // DFA resource tracker. - DFAPacketizer *ResourceTracker; - // Map: MI -> SU. - std::map MIToSUnit; - -public: - // The AAResults parameter can be nullptr. - VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, - AAResults *AA); - - virtual ~VLIWPacketizerList(); - - // Implement this API in the backend to bundle instructions. - void PacketizeMIs(MachineBasicBlock *MBB, - MachineBasicBlock::iterator BeginItr, - MachineBasicBlock::iterator EndItr); - - // Return the ResourceTracker. - DFAPacketizer *getResourceTracker() {return ResourceTracker;} - - // addToPacket - Add MI to the current packet. - virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI) { - CurrentPacketMIs.push_back(&MI); - ResourceTracker->reserveResources(MI); - return MI; - } - - // End the current packet and reset the state of the packetizer. - // Overriding this function allows the target-specific packetizer - // to perform custom finalization. - virtual void endPacket(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MI); - - // Perform initialization before packetizing an instruction. This - // function is supposed to be overrided by the target dependent packetizer. - virtual void initPacketizerState() {} - - // Check if the given instruction I should be ignored by the packetizer. - virtual bool ignorePseudoInstruction(const MachineInstr &I, - const MachineBasicBlock *MBB) { - return false; - } - - // Return true if instruction MI can not be packetized with any other - // instruction, which means that MI itself is a packet. - virtual bool isSoloInstruction(const MachineInstr &MI) { return true; } - - // Check if the packetizer should try to add the given instruction to - // the current packet. One reasons for which it may not be desirable - // to include an instruction in the current packet could be that it - // would cause a stall. - // If this function returns "false", the current packet will be ended, - // and the instruction will be added to the next packet. - virtual bool shouldAddToPacket(const MachineInstr &MI) { return true; } - - // Check if it is legal to packetize SUI and SUJ together. - virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { - return false; - } - - // Check if it is legal to prune dependence between SUI and SUJ. - virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) { - return false; - } - - // Add a DAG mutation to be done before the packetization begins. - void addMutation(std::unique_ptr Mutation); - - bool alias(const MachineInstr &MI1, const MachineInstr &MI2, - bool UseTBAA = true) const; - -private: - bool alias(const MachineMemOperand &Op1, const MachineMemOperand &Op2, - bool UseTBAA = true) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_DFAPACKETIZER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DIE.h b/suite/synctools/tablegen/include/llvm/CodeGen/DIE.h deleted file mode 100644 index 7f7372630d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DIE.h +++ /dev/null @@ -1,998 +0,0 @@ -//===- lib/CodeGen/DIE.h - DWARF Info Entries -------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Data structures for DWARF info entries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DIE_H -#define LLVM_CODEGEN_DIE_H - -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/CodeGen/DwarfStringPoolEntry.h" -#include "llvm/Support/AlignOf.h" -#include "llvm/Support/Allocator.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class AsmPrinter; -class DIE; -class DIEUnit; -class DwarfCompileUnit; -class MCExpr; -class MCSection; -class MCSymbol; -class raw_ostream; - -//===--------------------------------------------------------------------===// -/// Dwarf abbreviation data, describes one attribute of a Dwarf abbreviation. -class DIEAbbrevData { - /// Dwarf attribute code. - dwarf::Attribute Attribute; - - /// Dwarf form code. - dwarf::Form Form; - - /// Dwarf attribute value for DW_FORM_implicit_const - int64_t Value = 0; - -public: - DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) - : Attribute(A), Form(F) {} - DIEAbbrevData(dwarf::Attribute A, int64_t V) - : Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {} - - /// Accessors. - /// @{ - dwarf::Attribute getAttribute() const { return Attribute; } - dwarf::Form getForm() const { return Form; } - int64_t getValue() const { return Value; } - /// @} - - /// Used to gather unique data for the abbreviation folding set. - void Profile(FoldingSetNodeID &ID) const; -}; - -//===--------------------------------------------------------------------===// -/// Dwarf abbreviation, describes the organization of a debug information -/// object. -class DIEAbbrev : public FoldingSetNode { - /// Unique number for node. - unsigned Number = 0; - - /// Dwarf tag code. - dwarf::Tag Tag; - - /// Whether or not this node has children. - /// - /// This cheats a bit in all of the uses since the values in the standard - /// are 0 and 1 for no children and children respectively. - bool Children; - - /// Raw data bytes for abbreviation. - SmallVector Data; - -public: - DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C) {} - - /// Accessors. - /// @{ - dwarf::Tag getTag() const { return Tag; } - unsigned getNumber() const { return Number; } - bool hasChildren() const { return Children; } - const SmallVectorImpl &getData() const { return Data; } - void setChildrenFlag(bool hasChild) { Children = hasChild; } - void setNumber(unsigned N) { Number = N; } - /// @} - - /// Adds another set of attribute information to the abbreviation. - void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { - Data.push_back(DIEAbbrevData(Attribute, Form)); - } - - /// Adds attribute with DW_FORM_implicit_const value - void AddImplicitConstAttribute(dwarf::Attribute Attribute, int64_t Value) { - Data.push_back(DIEAbbrevData(Attribute, Value)); - } - - /// Used to gather unique data for the abbreviation folding set. - void Profile(FoldingSetNodeID &ID) const; - - /// Print the abbreviation using the specified asm printer. - void Emit(const AsmPrinter *AP) const; - - void print(raw_ostream &O) const; - void dump() const; -}; - -//===--------------------------------------------------------------------===// -/// Helps unique DIEAbbrev objects and assigns abbreviation numbers. -/// -/// This class will unique the DIE abbreviations for a llvm::DIE object and -/// assign a unique abbreviation number to each unique DIEAbbrev object it -/// finds. The resulting collection of DIEAbbrev objects can then be emitted -/// into the .debug_abbrev section. -class DIEAbbrevSet { - /// The bump allocator to use when creating DIEAbbrev objects in the uniqued - /// storage container. - BumpPtrAllocator &Alloc; - /// FoldingSet that uniques the abbreviations. - FoldingSet AbbreviationsSet; - /// A list of all the unique abbreviations in use. - std::vector Abbreviations; - -public: - DIEAbbrevSet(BumpPtrAllocator &A) : Alloc(A) {} - ~DIEAbbrevSet(); - - /// Generate the abbreviation declaration for a DIE and return a pointer to - /// the generated abbreviation. - /// - /// \param Die the debug info entry to generate the abbreviation for. - /// \returns A reference to the uniqued abbreviation declaration that is - /// owned by this class. - DIEAbbrev &uniqueAbbreviation(DIE &Die); - - /// Print all abbreviations using the specified asm printer. - void Emit(const AsmPrinter *AP, MCSection *Section) const; -}; - -//===--------------------------------------------------------------------===// -/// An integer value DIE. -/// -class DIEInteger { - uint64_t Integer; - -public: - explicit DIEInteger(uint64_t I) : Integer(I) {} - - /// Choose the best form for integer. - static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { - if (IsSigned) { - const int64_t SignedInt = Int; - if ((char)Int == SignedInt) - return dwarf::DW_FORM_data1; - if ((short)Int == SignedInt) - return dwarf::DW_FORM_data2; - if ((int)Int == SignedInt) - return dwarf::DW_FORM_data4; - } else { - if ((unsigned char)Int == Int) - return dwarf::DW_FORM_data1; - if ((unsigned short)Int == Int) - return dwarf::DW_FORM_data2; - if ((unsigned int)Int == Int) - return dwarf::DW_FORM_data4; - } - return dwarf::DW_FORM_data8; - } - - uint64_t getValue() const { return Integer; } - void setValue(uint64_t Val) { Integer = Val; } - - void emitValue(const AsmPrinter *Asm, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// An expression DIE. -class DIEExpr { - const MCExpr *Expr; - -public: - explicit DIEExpr(const MCExpr *E) : Expr(E) {} - - /// Get MCExpr. - const MCExpr *getValue() const { return Expr; } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A label DIE. -class DIELabel { - const MCSymbol *Label; - -public: - explicit DIELabel(const MCSymbol *L) : Label(L) {} - - /// Get MCSymbol. - const MCSymbol *getValue() const { return Label; } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A BaseTypeRef DIE. -class DIEBaseTypeRef { - const DwarfCompileUnit *CU; - const uint64_t Index; - static constexpr unsigned ULEB128PadSize = 4; - -public: - explicit DIEBaseTypeRef(const DwarfCompileUnit *TheCU, uint64_t Idx) - : CU(TheCU), Index(Idx) {} - - /// EmitValue - Emit base type reference. - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - /// sizeOf - Determine size of the base type reference in bytes. - unsigned sizeOf(const dwarf::FormParams &, dwarf::Form) const; - - void print(raw_ostream &O) const; - uint64_t getIndex() const { return Index; } -}; - -//===--------------------------------------------------------------------===// -/// A simple label difference DIE. -/// -class DIEDelta { - const MCSymbol *LabelHi; - const MCSymbol *LabelLo; - -public: - DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : LabelHi(Hi), LabelLo(Lo) {} - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A container for string pool string values. -/// -/// This class is used with the DW_FORM_strp and DW_FORM_GNU_str_index forms. -class DIEString { - DwarfStringPoolEntryRef S; - -public: - DIEString(DwarfStringPoolEntryRef S) : S(S) {} - - /// Grab the string out of the object. - StringRef getString() const { return S.getString(); } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A container for inline string values. -/// -/// This class is used with the DW_FORM_string form. -class DIEInlineString { - StringRef S; - -public: - template - explicit DIEInlineString(StringRef Str, Allocator &A) : S(Str.copy(A)) {} - - ~DIEInlineString() = default; - - /// Grab the string out of the object. - StringRef getString() const { return S; } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &, dwarf::Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A pointer to another debug information entry. An instance of this class can -/// also be used as a proxy for a debug information entry not yet defined -/// (ie. types.) -class DIEEntry { - DIE *Entry; - -public: - DIEEntry() = delete; - explicit DIEEntry(DIE &E) : Entry(&E) {} - - DIE &getEntry() const { return *Entry; } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// Represents a pointer to a location list in the debug_loc -/// section. -class DIELocList { - /// Index into the .debug_loc vector. - size_t Index; - -public: - DIELocList(size_t I) : Index(I) {} - - /// Grab the current index out. - size_t getValue() const { return Index; } - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A BaseTypeRef DIE. -class DIEAddrOffset { - DIEInteger Addr; - DIEDelta Offset; - -public: - explicit DIEAddrOffset(uint64_t Idx, const MCSymbol *Hi, const MCSymbol *Lo) - : Addr(Idx), Offset(Hi, Lo) {} - - void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &FormParams, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// A debug information entry value. Some of these roughly correlate -/// to DWARF attribute classes. -class DIEBlock; -class DIELoc; -class DIEValue { -public: - enum Type { - isNone, -#define HANDLE_DIEVALUE(T) is##T, -#include "llvm/CodeGen/DIEValue.def" - }; - -private: - /// Type of data stored in the value. - Type Ty = isNone; - dwarf::Attribute Attribute = (dwarf::Attribute)0; - dwarf::Form Form = (dwarf::Form)0; - - /// Storage for the value. - /// - /// All values that aren't standard layout (or are larger than 8 bytes) - /// should be stored by reference instead of by value. - using ValTy = - AlignedCharArrayUnion; - - static_assert(sizeof(ValTy) <= sizeof(uint64_t) || - sizeof(ValTy) <= sizeof(void *), - "Expected all large types to be stored via pointer"); - - /// Underlying stored value. - ValTy Val; - - template void construct(T V) { - static_assert(std::is_standard_layout::value || - std::is_pointer::value, - "Expected standard layout or pointer"); - new (reinterpret_cast(&Val)) T(V); - } - - template T *get() { return reinterpret_cast(&Val); } - template const T *get() const { - return reinterpret_cast(&Val); - } - template void destruct() { get()->~T(); } - - /// Destroy the underlying value. - /// - /// This should get optimized down to a no-op. We could skip it if we could - /// add a static assert on \a std::is_trivially_copyable(), but we currently - /// support versions of GCC that don't understand that. - void destroyVal() { - switch (Ty) { - case isNone: - return; -#define HANDLE_DIEVALUE_SMALL(T) \ - case is##T: \ - destruct(); \ - return; -#define HANDLE_DIEVALUE_LARGE(T) \ - case is##T: \ - destruct(); \ - return; -#include "llvm/CodeGen/DIEValue.def" - } - } - - /// Copy the underlying value. - /// - /// This should get optimized down to a simple copy. We need to actually - /// construct the value, rather than calling memcpy, to satisfy strict - /// aliasing rules. - void copyVal(const DIEValue &X) { - switch (Ty) { - case isNone: - return; -#define HANDLE_DIEVALUE_SMALL(T) \ - case is##T: \ - construct(*X.get()); \ - return; -#define HANDLE_DIEVALUE_LARGE(T) \ - case is##T: \ - construct(*X.get()); \ - return; -#include "llvm/CodeGen/DIEValue.def" - } - } - -public: - DIEValue() = default; - - DIEValue(const DIEValue &X) : Ty(X.Ty), Attribute(X.Attribute), Form(X.Form) { - copyVal(X); - } - - DIEValue &operator=(const DIEValue &X) { - destroyVal(); - Ty = X.Ty; - Attribute = X.Attribute; - Form = X.Form; - copyVal(X); - return *this; - } - - ~DIEValue() { destroyVal(); } - -#define HANDLE_DIEVALUE_SMALL(T) \ - DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T &V) \ - : Ty(is##T), Attribute(Attribute), Form(Form) { \ - construct(V); \ - } -#define HANDLE_DIEVALUE_LARGE(T) \ - DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T *V) \ - : Ty(is##T), Attribute(Attribute), Form(Form) { \ - assert(V && "Expected valid value"); \ - construct(V); \ - } -#include "llvm/CodeGen/DIEValue.def" - - /// Accessors. - /// @{ - Type getType() const { return Ty; } - dwarf::Attribute getAttribute() const { return Attribute; } - dwarf::Form getForm() const { return Form; } - explicit operator bool() const { return Ty; } - /// @} - -#define HANDLE_DIEVALUE_SMALL(T) \ - const DIE##T &getDIE##T() const { \ - assert(getType() == is##T && "Expected " #T); \ - return *get(); \ - } -#define HANDLE_DIEVALUE_LARGE(T) \ - const DIE##T &getDIE##T() const { \ - assert(getType() == is##T && "Expected " #T); \ - return **get(); \ - } -#include "llvm/CodeGen/DIEValue.def" - - /// Emit value via the Dwarf writer. - void emitValue(const AsmPrinter *AP) const; - - /// Return the size of a value in bytes. - unsigned sizeOf(const dwarf::FormParams &FormParams) const; - - void print(raw_ostream &O) const; - void dump() const; -}; - -struct IntrusiveBackListNode { - PointerIntPair Next; - - IntrusiveBackListNode() : Next(this, true) {} - - IntrusiveBackListNode *getNext() const { - return Next.getInt() ? nullptr : Next.getPointer(); - } -}; - -struct IntrusiveBackListBase { - using Node = IntrusiveBackListNode; - - Node *Last = nullptr; - - bool empty() const { return !Last; } - - void push_back(Node &N) { - assert(N.Next.getPointer() == &N && "Expected unlinked node"); - assert(N.Next.getInt() == true && "Expected unlinked node"); - - if (Last) { - N.Next = Last->Next; - Last->Next.setPointerAndInt(&N, false); - } - Last = &N; - } - - void push_front(Node &N) { - assert(N.Next.getPointer() == &N && "Expected unlinked node"); - assert(N.Next.getInt() == true && "Expected unlinked node"); - - if (Last) { - N.Next.setPointerAndInt(Last->Next.getPointer(), false); - Last->Next.setPointerAndInt(&N, true); - } else { - Last = &N; - } - } -}; - -template class IntrusiveBackList : IntrusiveBackListBase { -public: - using IntrusiveBackListBase::empty; - - void push_back(T &N) { IntrusiveBackListBase::push_back(N); } - void push_front(T &N) { IntrusiveBackListBase::push_front(N); } - T &back() { return *static_cast(Last); } - const T &back() const { return *static_cast(Last); } - T &front() { - return *static_cast(Last ? Last->Next.getPointer() : nullptr); - } - const T &front() const { - return *static_cast(Last ? Last->Next.getPointer() : nullptr); - } - - void takeNodes(IntrusiveBackList &Other) { - if (Other.empty()) - return; - - T *FirstNode = static_cast(Other.Last->Next.getPointer()); - T *IterNode = FirstNode; - do { - // Keep a pointer to the node and increment the iterator. - T *TmpNode = IterNode; - IterNode = static_cast(IterNode->Next.getPointer()); - - // Unlink the node and push it back to this list. - TmpNode->Next.setPointerAndInt(TmpNode, true); - push_back(*TmpNode); - } while (IterNode != FirstNode); - - Other.Last = nullptr; - } - - class const_iterator; - class iterator - : public iterator_facade_base { - friend class const_iterator; - - Node *N = nullptr; - - public: - iterator() = default; - explicit iterator(T *N) : N(N) {} - - iterator &operator++() { - N = N->getNext(); - return *this; - } - - explicit operator bool() const { return N; } - T &operator*() const { return *static_cast(N); } - - bool operator==(const iterator &X) const { return N == X.N; } - }; - - class const_iterator - : public iterator_facade_base { - const Node *N = nullptr; - - public: - const_iterator() = default; - // Placate MSVC by explicitly scoping 'iterator'. - const_iterator(typename IntrusiveBackList::iterator X) : N(X.N) {} - explicit const_iterator(const T *N) : N(N) {} - - const_iterator &operator++() { - N = N->getNext(); - return *this; - } - - explicit operator bool() const { return N; } - const T &operator*() const { return *static_cast(N); } - - bool operator==(const const_iterator &X) const { return N == X.N; } - }; - - iterator begin() { - return Last ? iterator(static_cast(Last->Next.getPointer())) : end(); - } - const_iterator begin() const { - return const_cast(this)->begin(); - } - iterator end() { return iterator(); } - const_iterator end() const { return const_iterator(); } - - static iterator toIterator(T &N) { return iterator(&N); } - static const_iterator toIterator(const T &N) { return const_iterator(&N); } -}; - -/// A list of DIE values. -/// -/// This is a singly-linked list, but instead of reversing the order of -/// insertion, we keep a pointer to the back of the list so we can push in -/// order. -/// -/// There are two main reasons to choose a linked list over a customized -/// vector-like data structure. -/// -/// 1. For teardown efficiency, we want DIEs to be BumpPtrAllocated. Using a -/// linked list here makes this way easier to accomplish. -/// 2. Carrying an extra pointer per \a DIEValue isn't expensive. 45% of DIEs -/// have 2 or fewer values, and 90% have 5 or fewer. A vector would be -/// over-allocated by 50% on average anyway, the same cost as the -/// linked-list node. -class DIEValueList { - struct Node : IntrusiveBackListNode { - DIEValue V; - - explicit Node(DIEValue V) : V(V) {} - }; - - using ListTy = IntrusiveBackList; - - ListTy List; - -public: - class const_value_iterator; - class value_iterator - : public iterator_adaptor_base { - friend class const_value_iterator; - - using iterator_adaptor = - iterator_adaptor_base; - - public: - value_iterator() = default; - explicit value_iterator(ListTy::iterator X) : iterator_adaptor(X) {} - - explicit operator bool() const { return bool(wrapped()); } - DIEValue &operator*() const { return wrapped()->V; } - }; - - class const_value_iterator : public iterator_adaptor_base< - const_value_iterator, ListTy::const_iterator, - std::forward_iterator_tag, const DIEValue> { - using iterator_adaptor = - iterator_adaptor_base; - - public: - const_value_iterator() = default; - const_value_iterator(DIEValueList::value_iterator X) - : iterator_adaptor(X.wrapped()) {} - explicit const_value_iterator(ListTy::const_iterator X) - : iterator_adaptor(X) {} - - explicit operator bool() const { return bool(wrapped()); } - const DIEValue &operator*() const { return wrapped()->V; } - }; - - using value_range = iterator_range; - using const_value_range = iterator_range; - - value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V) { - List.push_back(*new (Alloc) Node(V)); - return value_iterator(ListTy::toIterator(List.back())); - } - template - value_iterator addValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute, - dwarf::Form Form, T &&Value) { - return addValue(Alloc, DIEValue(Attribute, Form, std::forward(Value))); - } - - /// Take ownership of the nodes in \p Other, and append them to the back of - /// the list. - void takeValues(DIEValueList &Other) { List.takeNodes(Other.List); } - - value_range values() { - return make_range(value_iterator(List.begin()), value_iterator(List.end())); - } - const_value_range values() const { - return make_range(const_value_iterator(List.begin()), - const_value_iterator(List.end())); - } -}; - -//===--------------------------------------------------------------------===// -/// A structured debug information entry. Has an abbreviation which -/// describes its organization. -class DIE : IntrusiveBackListNode, public DIEValueList { - friend class IntrusiveBackList; - friend class DIEUnit; - - /// Dwarf unit relative offset. - unsigned Offset = 0; - /// Size of instance + children. - unsigned Size = 0; - unsigned AbbrevNumber = ~0u; - /// Dwarf tag code. - dwarf::Tag Tag = (dwarf::Tag)0; - /// Set to true to force a DIE to emit an abbreviation that says it has - /// children even when it doesn't. This is used for unit testing purposes. - bool ForceChildren = false; - /// Children DIEs. - IntrusiveBackList Children; - - /// The owner is either the parent DIE for children of other DIEs, or a - /// DIEUnit which contains this DIE as its unit DIE. - PointerUnion Owner; - - explicit DIE(dwarf::Tag Tag) : Tag(Tag) {} - -public: - DIE() = delete; - DIE(const DIE &RHS) = delete; - DIE(DIE &&RHS) = delete; - DIE &operator=(const DIE &RHS) = delete; - DIE &operator=(const DIE &&RHS) = delete; - - static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) { - return new (Alloc) DIE(Tag); - } - - // Accessors. - unsigned getAbbrevNumber() const { return AbbrevNumber; } - dwarf::Tag getTag() const { return Tag; } - /// Get the compile/type unit relative offset of this DIE. - unsigned getOffset() const { - // A real Offset can't be zero because the unit headers are at offset zero. - assert(Offset && "Offset being queried before it's been computed."); - return Offset; - } - unsigned getSize() const { - // A real Size can't be zero because it includes the non-empty abbrev code. - assert(Size && "Size being queried before it's been ocmputed."); - return Size; - } - bool hasChildren() const { return ForceChildren || !Children.empty(); } - void setForceChildren(bool B) { ForceChildren = B; } - - using child_iterator = IntrusiveBackList::iterator; - using const_child_iterator = IntrusiveBackList::const_iterator; - using child_range = iterator_range; - using const_child_range = iterator_range; - - child_range children() { - return make_range(Children.begin(), Children.end()); - } - const_child_range children() const { - return make_range(Children.begin(), Children.end()); - } - - DIE *getParent() const; - - /// Generate the abbreviation for this DIE. - /// - /// Calculate the abbreviation for this, which should be uniqued and - /// eventually used to call \a setAbbrevNumber(). - DIEAbbrev generateAbbrev() const; - - /// Set the abbreviation number for this DIE. - void setAbbrevNumber(unsigned I) { AbbrevNumber = I; } - - /// Get the absolute offset within the .debug_info or .debug_types section - /// for this DIE. - uint64_t getDebugSectionOffset() const; - - /// Compute the offset of this DIE and all its children. - /// - /// This function gets called just before we are going to generate the debug - /// information and gives each DIE a chance to figure out its CU relative DIE - /// offset, unique its abbreviation and fill in the abbreviation code, and - /// return the unit offset that points to where the next DIE will be emitted - /// within the debug unit section. After this function has been called for all - /// DIE objects, the DWARF can be generated since all DIEs will be able to - /// properly refer to other DIE objects since all DIEs have calculated their - /// offsets. - /// - /// \param FormParams Used when calculating sizes. - /// \param AbbrevSet the abbreviation used to unique DIE abbreviations. - /// \param CUOffset the compile/type unit relative offset in bytes. - /// \returns the offset for the DIE that follows this DIE within the - /// current compile/type unit. - unsigned computeOffsetsAndAbbrevs(const dwarf::FormParams &FormParams, - DIEAbbrevSet &AbbrevSet, unsigned CUOffset); - - /// Climb up the parent chain to get the compile unit or type unit DIE that - /// this DIE belongs to. - /// - /// \returns the compile or type unit DIE that owns this DIE, or NULL if - /// this DIE hasn't been added to a unit DIE. - const DIE *getUnitDie() const; - - /// Climb up the parent chain to get the compile unit or type unit that this - /// DIE belongs to. - /// - /// \returns the DIEUnit that represents the compile or type unit that owns - /// this DIE, or NULL if this DIE hasn't been added to a unit DIE. - DIEUnit *getUnit() const; - - void setOffset(unsigned O) { Offset = O; } - void setSize(unsigned S) { Size = S; } - - /// Add a child to the DIE. - DIE &addChild(DIE *Child) { - assert(!Child->getParent() && "Child should be orphaned"); - Child->Owner = this; - Children.push_back(*Child); - return Children.back(); - } - - DIE &addChildFront(DIE *Child) { - assert(!Child->getParent() && "Child should be orphaned"); - Child->Owner = this; - Children.push_front(*Child); - return Children.front(); - } - - /// Find a value in the DIE with the attribute given. - /// - /// Returns a default-constructed DIEValue (where \a DIEValue::getType() - /// gives \a DIEValue::isNone) if no such attribute exists. - DIEValue findAttribute(dwarf::Attribute Attribute) const; - - void print(raw_ostream &O, unsigned IndentCount = 0) const; - void dump() const; -}; - -//===--------------------------------------------------------------------===// -/// Represents a compile or type unit. -class DIEUnit { - /// The compile unit or type unit DIE. This variable must be an instance of - /// DIE so that we can calculate the DIEUnit from any DIE by traversing the - /// parent backchain and getting the Unit DIE, and then casting itself to a - /// DIEUnit. This allows us to be able to find the DIEUnit for any DIE without - /// having to store a pointer to the DIEUnit in each DIE instance. - DIE Die; - /// The section this unit will be emitted in. This may or may not be set to - /// a valid section depending on the client that is emitting DWARF. - MCSection *Section = nullptr; - uint64_t Offset = 0; /// .debug_info or .debug_types absolute section offset. -protected: - virtual ~DIEUnit() = default; - -public: - explicit DIEUnit(dwarf::Tag UnitTag); - DIEUnit(const DIEUnit &RHS) = delete; - DIEUnit(DIEUnit &&RHS) = delete; - void operator=(const DIEUnit &RHS) = delete; - void operator=(const DIEUnit &&RHS) = delete; - /// Set the section that this DIEUnit will be emitted into. - /// - /// This function is used by some clients to set the section. Not all clients - /// that emit DWARF use this section variable. - void setSection(MCSection *Section) { - assert(!this->Section); - this->Section = Section; - } - - virtual const MCSymbol *getCrossSectionRelativeBaseAddress() const { - return nullptr; - } - - /// Return the section that this DIEUnit will be emitted into. - /// - /// \returns Section pointer which can be NULL. - MCSection *getSection() const { return Section; } - void setDebugSectionOffset(uint64_t O) { Offset = O; } - uint64_t getDebugSectionOffset() const { return Offset; } - DIE &getUnitDie() { return Die; } - const DIE &getUnitDie() const { return Die; } -}; - -struct BasicDIEUnit final : DIEUnit { - explicit BasicDIEUnit(dwarf::Tag UnitTag) : DIEUnit(UnitTag) {} -}; - -//===--------------------------------------------------------------------===// -/// DIELoc - Represents an expression location. -// -class DIELoc : public DIEValueList { - mutable unsigned Size = 0; // Size in bytes excluding size header. - -public: - DIELoc() = default; - - /// Calculate the size of the location expression. - unsigned computeSize(const dwarf::FormParams &FormParams) const; - - // TODO: move setSize() and Size to DIEValueList. - void setSize(unsigned size) { Size = size; } - - /// BestForm - Choose the best form for data. - /// - dwarf::Form BestForm(unsigned DwarfVersion) const { - if (DwarfVersion > 3) - return dwarf::DW_FORM_exprloc; - // Pre-DWARF4 location expressions were blocks and not exprloc. - if ((unsigned char)Size == Size) - return dwarf::DW_FORM_block1; - if ((unsigned short)Size == Size) - return dwarf::DW_FORM_block2; - if ((unsigned int)Size == Size) - return dwarf::DW_FORM_block4; - return dwarf::DW_FORM_block; - } - - void emitValue(const AsmPrinter *Asm, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -//===--------------------------------------------------------------------===// -/// DIEBlock - Represents a block of values. -// -class DIEBlock : public DIEValueList { - mutable unsigned Size = 0; // Size in bytes excluding size header. - -public: - DIEBlock() = default; - - /// Calculate the size of the location expression. - unsigned computeSize(const dwarf::FormParams &FormParams) const; - - // TODO: move setSize() and Size to DIEValueList. - void setSize(unsigned size) { Size = size; } - - /// BestForm - Choose the best form for data. - /// - dwarf::Form BestForm() const { - if ((unsigned char)Size == Size) - return dwarf::DW_FORM_block1; - if ((unsigned short)Size == Size) - return dwarf::DW_FORM_block2; - if ((unsigned int)Size == Size) - return dwarf::DW_FORM_block4; - return dwarf::DW_FORM_block; - } - - void emitValue(const AsmPrinter *Asm, dwarf::Form Form) const; - unsigned sizeOf(const dwarf::FormParams &, dwarf::Form Form) const; - - void print(raw_ostream &O) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_DIE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DIEValue.def b/suite/synctools/tablegen/include/llvm/CodeGen/DIEValue.def deleted file mode 100644 index 8f95a814eb..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DIEValue.def +++ /dev/null @@ -1,48 +0,0 @@ -//===- llvm/CodeGen/DIEValue.def - DIEValue types ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Macros for running through all types of DIEValue. -// -//===----------------------------------------------------------------------===// - -#if !(defined HANDLE_DIEVALUE || defined HANDLE_DIEVALUE_SMALL || \ - defined HANDLE_DIEVALUE_LARGE) -#error "Missing macro definition of HANDLE_DIEVALUE" -#endif - -// Handler for all values. -#ifndef HANDLE_DIEVALUE -#define HANDLE_DIEVALUE(T) -#endif - -// Handler for small values. -#ifndef HANDLE_DIEVALUE_SMALL -#define HANDLE_DIEVALUE_SMALL(T) HANDLE_DIEVALUE(T) -#endif - -// Handler for large values. -#ifndef HANDLE_DIEVALUE_LARGE -#define HANDLE_DIEVALUE_LARGE(T) HANDLE_DIEVALUE(T) -#endif - -HANDLE_DIEVALUE_SMALL(Integer) -HANDLE_DIEVALUE_SMALL(String) -HANDLE_DIEVALUE_SMALL(Expr) -HANDLE_DIEVALUE_SMALL(Label) -HANDLE_DIEVALUE_LARGE(BaseTypeRef) -HANDLE_DIEVALUE_LARGE(Delta) -HANDLE_DIEVALUE_SMALL(Entry) -HANDLE_DIEVALUE_LARGE(Block) -HANDLE_DIEVALUE_LARGE(Loc) -HANDLE_DIEVALUE_SMALL(LocList) -HANDLE_DIEVALUE_LARGE(InlineString) -HANDLE_DIEVALUE_LARGE(AddrOffset) - -#undef HANDLE_DIEVALUE -#undef HANDLE_DIEVALUE_SMALL -#undef HANDLE_DIEVALUE_LARGE diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DbgEntityHistoryCalculator.h b/suite/synctools/tablegen/include/llvm/CodeGen/DbgEntityHistoryCalculator.h deleted file mode 100644 index 2ac9d938d2..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DbgEntityHistoryCalculator.h +++ /dev/null @@ -1,156 +0,0 @@ -//===- llvm/CodeGen/DbgEntityHistoryCalculator.h ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H -#define LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LexicalScopes.h" -#include - -namespace llvm { - -class DILocation; -class DINode; -class MachineFunction; -class MachineInstr; -class TargetRegisterInfo; - -/// Record instruction ordering so we can query their relative positions within -/// a function. Meta instructions are given the same ordinal as the preceding -/// non-meta instruction. Class state is invalid if MF is modified after -/// calling initialize. -class InstructionOrdering { -public: - void initialize(const MachineFunction &MF); - void clear() { InstNumberMap.clear(); } - - /// Check if instruction \p A comes before \p B, where \p A and \p B both - /// belong to the MachineFunction passed to initialize(). - bool isBefore(const MachineInstr *A, const MachineInstr *B) const; - -private: - /// Each instruction is assigned an order number. - DenseMap InstNumberMap; -}; - -/// For each user variable, keep a list of instruction ranges where this -/// variable is accessible. The variables are listed in order of appearance. -class DbgValueHistoryMap { -public: - /// Index in the entry vector. - typedef size_t EntryIndex; - - /// Special value to indicate that an entry is valid until the end of the - /// function. - static const EntryIndex NoEntry = std::numeric_limits::max(); - - /// Specifies a change in a variable's debug value history. - /// - /// There exist two types of entries: - /// - /// * Debug value entry: - /// - /// A new debug value becomes live. If the entry's \p EndIndex is \p NoEntry, - /// the value is valid until the end of the function. For other values, the - /// index points to the entry in the entry vector that ends this debug - /// value. The ending entry can either be an overlapping debug value, or - /// an instruction that clobbers the value. - /// - /// * Clobbering entry: - /// - /// This entry's instruction clobbers one or more preceding - /// register-described debug values that have their end index - /// set to this entry's position in the entry vector. - class Entry { - friend DbgValueHistoryMap; - - public: - enum EntryKind { DbgValue, Clobber }; - - Entry(const MachineInstr *Instr, EntryKind Kind) - : Instr(Instr, Kind), EndIndex(NoEntry) {} - - const MachineInstr *getInstr() const { return Instr.getPointer(); } - EntryIndex getEndIndex() const { return EndIndex; } - EntryKind getEntryKind() const { return Instr.getInt(); } - - bool isClobber() const { return getEntryKind() == Clobber; } - bool isDbgValue() const { return getEntryKind() == DbgValue; } - bool isClosed() const { return EndIndex != NoEntry; } - - void endEntry(EntryIndex EndIndex); - - private: - PointerIntPair Instr; - EntryIndex EndIndex; - }; - using Entries = SmallVector; - using InlinedEntity = std::pair; - using EntriesMap = MapVector; - -private: - EntriesMap VarEntries; - -public: - bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, - EntryIndex &NewIndex); - EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI); - - Entry &getEntry(InlinedEntity Var, EntryIndex Index) { - auto &Entries = VarEntries[Var]; - return Entries[Index]; - } - - /// Test whether a vector of entries features any non-empty locations. It - /// could have no entries, or only DBG_VALUE $noreg entries. - bool hasNonEmptyLocation(const Entries &Entries) const; - - /// Drop location ranges which exist entirely outside each variable's scope. - void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, - const InstructionOrdering &Ordering); - bool empty() const { return VarEntries.empty(); } - void clear() { VarEntries.clear(); } - EntriesMap::const_iterator begin() const { return VarEntries.begin(); } - EntriesMap::const_iterator end() const { return VarEntries.end(); } - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const; -#endif -}; - -/// For each inlined instance of a source-level label, keep the corresponding -/// DBG_LABEL instruction. The DBG_LABEL instruction could be used to generate -/// a temporary (assembler) label before it. -class DbgLabelInstrMap { -public: - using InlinedEntity = std::pair; - using InstrMap = MapVector; - -private: - InstrMap LabelInstr; - -public: - void addInstr(InlinedEntity Label, const MachineInstr &MI); - - bool empty() const { return LabelInstr.empty(); } - void clear() { LabelInstr.clear(); } - InstrMap::const_iterator begin() const { return LabelInstr.begin(); } - InstrMap::const_iterator end() const { return LabelInstr.end(); } -}; - -void calculateDbgEntityHistory(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - DbgValueHistoryMap &DbgValues, - DbgLabelInstrMap &DbgLabels); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DebugHandlerBase.h b/suite/synctools/tablegen/include/llvm/CodeGen/DebugHandlerBase.h deleted file mode 100644 index c0305b834a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DebugHandlerBase.h +++ /dev/null @@ -1,146 +0,0 @@ -//===-- llvm/CodeGen/DebugHandlerBase.h -----------------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Common functionality for different debug information format backends. -// LLVM currently supports DWARF and CodeView. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DEBUGHANDLERBASE_H -#define LLVM_CODEGEN_DEBUGHANDLERBASE_H - -#include "llvm/ADT/Optional.h" -#include "llvm/CodeGen/AsmPrinterHandler.h" -#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" -#include "llvm/CodeGen/LexicalScopes.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DebugLoc.h" - -namespace llvm { - -class AsmPrinter; -class MachineInstr; -class MachineModuleInfo; - -/// Represents the location at which a variable is stored. -struct DbgVariableLocation { - /// Base register. - unsigned Register; - - /// Chain of offsetted loads necessary to load the value if it lives in - /// memory. Every load except for the last is pointer-sized. - SmallVector LoadChain; - - /// Present if the location is part of a larger variable. - llvm::Optional FragmentInfo; - - /// Extract a VariableLocation from a MachineInstr. - /// This will only work if Instruction is a debug value instruction - /// and the associated DIExpression is in one of the supported forms. - /// If these requirements are not met, the returned Optional will not - /// have a value. - static Optional - extractFromMachineInstruction(const MachineInstr &Instruction); -}; - -/// Base class for debug information backends. Common functionality related to -/// tracking which variables and scopes are alive at a given PC live here. -class DebugHandlerBase : public AsmPrinterHandler { -protected: - DebugHandlerBase(AsmPrinter *A); - - /// Target of debug info emission. - AsmPrinter *Asm; - - /// Collected machine module information. - MachineModuleInfo *MMI; - - /// Previous instruction's location information. This is used to - /// determine label location to indicate scope boundaries in debug info. - /// We track the previous instruction's source location (if not line 0), - /// whether it was a label, and its parent BB. - DebugLoc PrevInstLoc; - MCSymbol *PrevLabel = nullptr; - const MachineBasicBlock *PrevInstBB = nullptr; - - /// This location indicates end of function prologue and beginning of - /// function body. - DebugLoc PrologEndLoc; - - /// If nonnull, stores the current machine instruction we're processing. - const MachineInstr *CurMI = nullptr; - - LexicalScopes LScopes; - - /// History of DBG_VALUE and clobber instructions for each user - /// variable. Variables are listed in order of appearance. - DbgValueHistoryMap DbgValues; - - /// Mapping of inlined labels and DBG_LABEL machine instruction. - DbgLabelInstrMap DbgLabels; - - /// Maps instruction with label emitted before instruction. - /// FIXME: Make this private from DwarfDebug, we have the necessary accessors - /// for it. - DenseMap LabelsBeforeInsn; - - /// Maps instruction with label emitted after instruction. - DenseMap LabelsAfterInsn; - - /// Identify instructions that are marking the beginning of or - /// ending of a scope. - void identifyScopeMarkers(); - - /// Ensure that a label will be emitted before MI. - void requestLabelBeforeInsn(const MachineInstr *MI) { - LabelsBeforeInsn.insert(std::make_pair(MI, nullptr)); - } - - /// Ensure that a label will be emitted after MI. - void requestLabelAfterInsn(const MachineInstr *MI) { - LabelsAfterInsn.insert(std::make_pair(MI, nullptr)); - } - - virtual void beginFunctionImpl(const MachineFunction *MF) = 0; - virtual void endFunctionImpl(const MachineFunction *MF) = 0; - virtual void skippedNonDebugFunction() {} - -private: - InstructionOrdering InstOrdering; - - // AsmPrinterHandler overrides. -public: - void beginModule(Module *M) override; - - void beginInstruction(const MachineInstr *MI) override; - void endInstruction() override; - - void beginFunction(const MachineFunction *MF) override; - void endFunction(const MachineFunction *MF) override; - - void beginBasicBlock(const MachineBasicBlock &MBB) override; - void endBasicBlock(const MachineBasicBlock &MBB) override; - - /// Return Label preceding the instruction. - MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - - /// Return Label immediately following the instruction. - MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - - /// If this type is derived from a base type then return base type size. - static uint64_t getBaseTypeSize(const DIType *Ty); - - /// Return true if type encoding is unsigned. - static bool isUnsignedDIType(const DIType *Ty); - - const InstructionOrdering &getInstOrdering() const { return InstOrdering; } -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/DwarfStringPoolEntry.h b/suite/synctools/tablegen/include/llvm/CodeGen/DwarfStringPoolEntry.h deleted file mode 100644 index abeba62707..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ /dev/null @@ -1,71 +0,0 @@ -//===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H -#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H - -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/StringMap.h" - -namespace llvm { - -class MCSymbol; - -/// Data for a string pool entry. -struct DwarfStringPoolEntry { - static constexpr unsigned NotIndexed = -1; - - MCSymbol *Symbol; - uint64_t Offset; - unsigned Index; - - bool isIndexed() const { return Index != NotIndexed; } -}; - -/// String pool entry reference. -class DwarfStringPoolEntryRef { - PointerIntPair *, 1, bool> - MapEntryAndIndexed; - - const StringMapEntry *getMapEntry() const { - return MapEntryAndIndexed.getPointer(); - } - -public: - DwarfStringPoolEntryRef() = default; - DwarfStringPoolEntryRef(const StringMapEntry &Entry, - bool Indexed) - : MapEntryAndIndexed(&Entry, Indexed) {} - - explicit operator bool() const { return getMapEntry(); } - MCSymbol *getSymbol() const { - assert(getMapEntry()->second.Symbol && "No symbol available!"); - return getMapEntry()->second.Symbol; - } - uint64_t getOffset() const { return getMapEntry()->second.Offset; } - bool isIndexed() const { return MapEntryAndIndexed.getInt(); } - unsigned getIndex() const { - assert(isIndexed()); - assert(getMapEntry()->getValue().isIndexed()); - return getMapEntry()->second.Index; - } - StringRef getString() const { return getMapEntry()->first(); } - /// Return the entire string pool entry for convenience. - DwarfStringPoolEntry getEntry() const { return getMapEntry()->getValue(); } - - bool operator==(const DwarfStringPoolEntryRef &X) const { - return getMapEntry() == X.getMapEntry(); - } - bool operator!=(const DwarfStringPoolEntryRef &X) const { - return getMapEntry() != X.getMapEntry(); - } -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/EdgeBundles.h b/suite/synctools/tablegen/include/llvm/CodeGen/EdgeBundles.h deleted file mode 100644 index b6187fc6dc..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/EdgeBundles.h +++ /dev/null @@ -1,62 +0,0 @@ -//===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The EdgeBundles analysis forms equivalence classes of CFG edges such that all -// edges leaving a machine basic block are in the same bundle, and all edges -// entering a machine basic block are in the same bundle. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EDGEBUNDLES_H -#define LLVM_CODEGEN_EDGEBUNDLES_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IntEqClasses.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { - -class EdgeBundles : public MachineFunctionPass { - const MachineFunction *MF; - - /// EC - Each edge bundle is an equivalence class. The keys are: - /// 2*BB->getNumber() -> Ingoing bundle. - /// 2*BB->getNumber()+1 -> Outgoing bundle. - IntEqClasses EC; - - /// Blocks - Map each bundle to a list of basic block numbers. - SmallVector, 4> Blocks; - -public: - static char ID; - EdgeBundles() : MachineFunctionPass(ID) {} - - /// getBundle - Return the ingoing (Out = false) or outgoing (Out = true) - /// bundle number for basic block #N - unsigned getBundle(unsigned N, bool Out) const { return EC[2 * N + Out]; } - - /// getNumBundles - Return the total number of bundles in the CFG. - unsigned getNumBundles() const { return EC.getNumClasses(); } - - /// getBlocks - Return an array of blocks that are connected to Bundle. - ArrayRef getBlocks(unsigned Bundle) const { return Blocks[Bundle]; } - - /// getMachineFunction - Return the last machine function computed. - const MachineFunction *getMachineFunction() const { return MF; } - - /// view - Visualize the annotated bipartite CFG with Graphviz. - void view() const; - -private: - bool runOnMachineFunction(MachineFunction&) override; - void getAnalysisUsage(AnalysisUsage&) const override; -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ExecutionDomainFix.h b/suite/synctools/tablegen/include/llvm/CodeGen/ExecutionDomainFix.h deleted file mode 100644 index c87d4f993e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ExecutionDomainFix.h +++ /dev/null @@ -1,221 +0,0 @@ -//==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Execution Domain Fix pass. -/// -/// Some X86 SSE instructions like mov, and, or, xor are available in different -/// variants for different operand types. These variant instructions are -/// equivalent, but on Nehalem and newer cpus there is extra latency -/// transferring data between integer and floating point domains. ARM cores -/// have similar issues when they are configured with both VFP and NEON -/// pipelines. -/// -/// This pass changes the variant instructions to minimize domain crossings. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXECUTIONDOMAINFIX_H -#define LLVM_CODEGEN_EXECUTIONDOMAINFIX_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LoopTraversal.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/ReachingDefAnalysis.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" - -namespace llvm { - -class MachineInstr; -class TargetInstrInfo; - -/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track -/// of execution domains. -/// -/// An open DomainValue represents a set of instructions that can still switch -/// execution domain. Multiple registers may refer to the same open -/// DomainValue - they will eventually be collapsed to the same execution -/// domain. -/// -/// A collapsed DomainValue represents a single register that has been forced -/// into one of more execution domains. There is a separate collapsed -/// DomainValue for each register, but it may contain multiple execution -/// domains. A register value is initially created in a single execution -/// domain, but if we were forced to pay the penalty of a domain crossing, we -/// keep track of the fact that the register is now available in multiple -/// domains. -struct DomainValue { - /// Basic reference counting. - unsigned Refs = 0; - - /// Bitmask of available domains. For an open DomainValue, it is the still - /// possible domains for collapsing. For a collapsed DomainValue it is the - /// domains where the register is available for free. - unsigned AvailableDomains; - - /// Pointer to the next DomainValue in a chain. When two DomainValues are - /// merged, Victim.Next is set to point to Victor, so old DomainValue - /// references can be updated by following the chain. - DomainValue *Next; - - /// Twiddleable instructions using or defining these registers. - SmallVector Instrs; - - DomainValue() { clear(); } - - /// A collapsed DomainValue has no instructions to twiddle - it simply keeps - /// track of the domains where the registers are already available. - bool isCollapsed() const { return Instrs.empty(); } - - /// Is domain available? - bool hasDomain(unsigned domain) const { - assert(domain < - static_cast(std::numeric_limits::digits) && - "undefined behavior"); - return AvailableDomains & (1u << domain); - } - - /// Mark domain as available. - void addDomain(unsigned domain) { - assert(domain < - static_cast(std::numeric_limits::digits) && - "undefined behavior"); - AvailableDomains |= 1u << domain; - } - - // Restrict to a single domain available. - void setSingleDomain(unsigned domain) { - assert(domain < - static_cast(std::numeric_limits::digits) && - "undefined behavior"); - AvailableDomains = 1u << domain; - } - - /// Return bitmask of domains that are available and in mask. - unsigned getCommonDomains(unsigned mask) const { - return AvailableDomains & mask; - } - - /// First domain available. - unsigned getFirstDomain() const { - return countTrailingZeros(AvailableDomains); - } - - /// Clear this DomainValue and point to next which has all its data. - void clear() { - AvailableDomains = 0; - Next = nullptr; - Instrs.clear(); - } -}; - -class ExecutionDomainFix : public MachineFunctionPass { - SpecificBumpPtrAllocator Allocator; - SmallVector Avail; - - const TargetRegisterClass *const RC; - MachineFunction *MF; - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - std::vector> AliasMap; - const unsigned NumRegs; - /// Value currently in each register, or NULL when no value is being tracked. - /// This counts as a DomainValue reference. - using LiveRegsDVInfo = std::vector; - LiveRegsDVInfo LiveRegs; - /// Keeps domain information for all registers. Note that this - /// is different from the usual definition notion of liveness. The CPU - /// doesn't care whether or not we consider a register killed. - using OutRegsInfoMap = SmallVector; - OutRegsInfoMap MBBOutRegsInfos; - - ReachingDefAnalysis *RDA; - -public: - ExecutionDomainFix(char &PassID, const TargetRegisterClass &RC) - : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - -private: - /// Translate TRI register number to a list of indices into our smaller tables - /// of interesting registers. - iterator_range::const_iterator> - regIndices(unsigned Reg) const; - - /// DomainValue allocation. - DomainValue *alloc(int domain = -1); - - /// Add reference to DV. - DomainValue *retain(DomainValue *DV) { - if (DV) - ++DV->Refs; - return DV; - } - - /// Release a reference to DV. When the last reference is released, - /// collapse if needed. - void release(DomainValue *); - - /// Follow the chain of dead DomainValues until a live DomainValue is reached. - /// Update the referenced pointer when necessary. - DomainValue *resolve(DomainValue *&); - - /// Set LiveRegs[rx] = dv, updating reference counts. - void setLiveReg(int rx, DomainValue *DV); - - /// Kill register rx, recycle or collapse any DomainValue. - void kill(int rx); - - /// Force register rx into domain. - void force(int rx, unsigned domain); - - /// Collapse open DomainValue into given domain. If there are multiple - /// registers using dv, they each get a unique collapsed DomainValue. - void collapse(DomainValue *dv, unsigned domain); - - /// All instructions and registers in B are moved to A, and B is released. - bool merge(DomainValue *A, DomainValue *B); - - /// Set up LiveRegs by merging predecessor live-out values. - void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); - - /// Update live-out values. - void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); - - /// Process he given basic block. - void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); - - /// Visit given insturcion. - bool visitInstr(MachineInstr *); - - /// Update def-ages for registers defined by MI. - /// If Kill is set, also kill off DomainValues clobbered by the defs. - void processDefs(MachineInstr *, bool Kill); - - /// A soft instruction can be changed to work in other domains given by mask. - void visitSoftInstr(MachineInstr *, unsigned mask); - - /// A hard instruction only works in one domain. All input registers will be - /// forced into that domain. - void visitHardInstr(MachineInstr *, unsigned domain); -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_EXECUTIONDOMAINFIX_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ExpandReductions.h b/suite/synctools/tablegen/include/llvm/CodeGen/ExpandReductions.h deleted file mode 100644 index 5dbed07873..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ExpandReductions.h +++ /dev/null @@ -1,23 +0,0 @@ -//===----- ExpandReductions.h - Expand experimental reduction intrinsics --===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXPANDREDUCTIONS_H -#define LLVM_CODEGEN_EXPANDREDUCTIONS_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class ExpandReductionsPass - : public PassInfoMixin { -public: - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; -} // end namespace llvm - -#endif // LLVM_CODEGEN_EXPANDREDUCTIONS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ExpandVectorPredication.h b/suite/synctools/tablegen/include/llvm/CodeGen/ExpandVectorPredication.h deleted file mode 100644 index b69adb9db2..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ExpandVectorPredication.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- ExpandVectorPredication.h - Expand vector predication ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXPANDVECTORPREDICATION_H -#define LLVM_CODEGEN_EXPANDVECTORPREDICATION_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class ExpandVectorPredicationPass - : public PassInfoMixin { -public: - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; -} // end namespace llvm - -#endif // LLVM_CODEGEN_EXPANDVECTORPREDICATION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/FastISel.h b/suite/synctools/tablegen/include/llvm/CodeGen/FastISel.h deleted file mode 100644 index 6de8ac4273..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/FastISel.h +++ /dev/null @@ -1,568 +0,0 @@ -//===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines the FastISel class. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_FASTISEL_H -#define LLVM_CODEGEN_FASTISEL_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/MachineValueType.h" -#include -#include -#include - -namespace llvm { - -class AllocaInst; -class BasicBlock; -class CallInst; -class Constant; -class ConstantFP; -class DataLayout; -class FunctionLoweringInfo; -class LoadInst; -class MachineConstantPool; -class MachineFrameInfo; -class MachineFunction; -class MachineInstr; -class MachineMemOperand; -class MachineOperand; -class MachineRegisterInfo; -class MCContext; -class MCInstrDesc; -class MCSymbol; -class TargetInstrInfo; -class TargetLibraryInfo; -class TargetMachine; -class TargetRegisterClass; -class TargetRegisterInfo; -class Type; -class User; -class Value; - -/// This is a fast-path instruction selection class that generates poor -/// code and doesn't support illegal types or non-trivial lowering, but runs -/// quickly. -class FastISel { -public: - using ArgListEntry = TargetLoweringBase::ArgListEntry; - using ArgListTy = TargetLoweringBase::ArgListTy; - struct CallLoweringInfo { - Type *RetTy = nullptr; - bool RetSExt : 1; - bool RetZExt : 1; - bool IsVarArg : 1; - bool IsInReg : 1; - bool DoesNotReturn : 1; - bool IsReturnValueUsed : 1; - bool IsPatchPoint : 1; - - // IsTailCall Should be modified by implementations of FastLowerCall - // that perform tail call conversions. - bool IsTailCall = false; - - unsigned NumFixedArgs = -1; - CallingConv::ID CallConv = CallingConv::C; - const Value *Callee = nullptr; - MCSymbol *Symbol = nullptr; - ArgListTy Args; - const CallBase *CB = nullptr; - MachineInstr *Call = nullptr; - Register ResultReg; - unsigned NumResultRegs = 0; - - SmallVector OutVals; - SmallVector OutFlags; - SmallVector OutRegs; - SmallVector Ins; - SmallVector InRegs; - - CallLoweringInfo() - : RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), - DoesNotReturn(false), IsReturnValueUsed(true), IsPatchPoint(false) {} - - CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, - const Value *Target, ArgListTy &&ArgsList, - const CallBase &Call) { - RetTy = ResultTy; - Callee = Target; - - IsInReg = Call.hasRetAttr(Attribute::InReg); - DoesNotReturn = Call.doesNotReturn(); - IsVarArg = FuncTy->isVarArg(); - IsReturnValueUsed = !Call.use_empty(); - RetSExt = Call.hasRetAttr(Attribute::SExt); - RetZExt = Call.hasRetAttr(Attribute::ZExt); - - CallConv = Call.getCallingConv(); - Args = std::move(ArgsList); - NumFixedArgs = FuncTy->getNumParams(); - - CB = &Call; - - return *this; - } - - CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, - MCSymbol *Target, ArgListTy &&ArgsList, - const CallBase &Call, - unsigned FixedArgs = ~0U) { - RetTy = ResultTy; - Callee = Call.getCalledOperand(); - Symbol = Target; - - IsInReg = Call.hasRetAttr(Attribute::InReg); - DoesNotReturn = Call.doesNotReturn(); - IsVarArg = FuncTy->isVarArg(); - IsReturnValueUsed = !Call.use_empty(); - RetSExt = Call.hasRetAttr(Attribute::SExt); - RetZExt = Call.hasRetAttr(Attribute::ZExt); - - CallConv = Call.getCallingConv(); - Args = std::move(ArgsList); - NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; - - CB = &Call; - - return *this; - } - - CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, - const Value *Target, ArgListTy &&ArgsList, - unsigned FixedArgs = ~0U) { - RetTy = ResultTy; - Callee = Target; - CallConv = CC; - Args = std::move(ArgsList); - NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; - return *this; - } - - CallLoweringInfo &setCallee(const DataLayout &DL, MCContext &Ctx, - CallingConv::ID CC, Type *ResultTy, - StringRef Target, ArgListTy &&ArgsList, - unsigned FixedArgs = ~0U); - - CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, - MCSymbol *Target, ArgListTy &&ArgsList, - unsigned FixedArgs = ~0U) { - RetTy = ResultTy; - Symbol = Target; - CallConv = CC; - Args = std::move(ArgsList); - NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; - return *this; - } - - CallLoweringInfo &setTailCall(bool Value = true) { - IsTailCall = Value; - return *this; - } - - CallLoweringInfo &setIsPatchPoint(bool Value = true) { - IsPatchPoint = Value; - return *this; - } - - ArgListTy &getArgs() { return Args; } - - void clearOuts() { - OutVals.clear(); - OutFlags.clear(); - OutRegs.clear(); - } - - void clearIns() { - Ins.clear(); - InRegs.clear(); - } - }; - -protected: - DenseMap LocalValueMap; - FunctionLoweringInfo &FuncInfo; - MachineFunction *MF; - MachineRegisterInfo &MRI; - MachineFrameInfo &MFI; - MachineConstantPool &MCP; - DebugLoc DbgLoc; - const TargetMachine &TM; - const DataLayout &DL; - const TargetInstrInfo &TII; - const TargetLowering &TLI; - const TargetRegisterInfo &TRI; - const TargetLibraryInfo *LibInfo; - bool SkipTargetIndependentISel; - bool UseInstrRefDebugInfo = false; - - /// The position of the last instruction for materializing constants - /// for use in the current block. It resets to EmitStartPt when it makes sense - /// (for example, it's usually profitable to avoid function calls between the - /// definition and the use) - MachineInstr *LastLocalValue = nullptr; - - /// The top most instruction in the current block that is allowed for - /// emitting local variables. LastLocalValue resets to EmitStartPt when it - /// makes sense (for example, on function calls) - MachineInstr *EmitStartPt = nullptr; - -public: - virtual ~FastISel(); - - /// Return the position of the last instruction emitted for - /// materializing constants for use in the current block. - MachineInstr *getLastLocalValue() { return LastLocalValue; } - - /// Update the position of the last instruction emitted for - /// materializing constants for use in the current block. - void setLastLocalValue(MachineInstr *I) { - EmitStartPt = I; - LastLocalValue = I; - } - - /// Set the current block to which generated machine instructions will - /// be appended. - void startNewBlock(); - - /// Flush the local value map. - void finishBasicBlock(); - - /// Return current debug location information. - DebugLoc getCurDebugLoc() const { return DbgLoc; } - - /// Do "fast" instruction selection for function arguments and append - /// the machine instructions to the current block. Returns true when - /// successful. - bool lowerArguments(); - - /// Do "fast" instruction selection for the given LLVM IR instruction - /// and append the generated machine instructions to the current block. - /// Returns true if selection was successful. - bool selectInstruction(const Instruction *I); - - /// Do "fast" instruction selection for the given LLVM IR operator - /// (Instruction or ConstantExpr), and append generated machine instructions - /// to the current block. Return true if selection was successful. - bool selectOperator(const User *I, unsigned Opcode); - - /// Create a virtual register and arrange for it to be assigned the - /// value for the given LLVM value. - Register getRegForValue(const Value *V); - - /// Look up the value to see if its value is already cached in a - /// register. It may be defined by instructions across blocks or defined - /// locally. - Register lookUpRegForValue(const Value *V); - - /// This is a wrapper around getRegForValue that also takes care of - /// truncating or sign-extending the given getelementptr index value. - Register getRegForGEPIndex(const Value *Idx); - - /// We're checking to see if we can fold \p LI into \p FoldInst. Note - /// that we could have a sequence where multiple LLVM IR instructions are - /// folded into the same machineinstr. For example we could have: - /// - /// A: x = load i32 *P - /// B: y = icmp A, 42 - /// C: br y, ... - /// - /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know about "B" - /// (and any other folded instructions) because it is between A and C. - /// - /// If we succeed folding, return true. - bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); - - /// The specified machine instr operand is a vreg, and that vreg is - /// being provided by the specified load instruction. If possible, try to - /// fold the load as an operand to the instruction, returning true if - /// possible. - /// - /// This method should be implemented by targets. - virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/, - const LoadInst * /*LI*/) { - return false; - } - - /// Reset InsertPt to prepare for inserting instructions into the - /// current block. - void recomputeInsertPt(); - - /// Remove all dead instructions between the I and E. - void removeDeadCode(MachineBasicBlock::iterator I, - MachineBasicBlock::iterator E); - - using SavePoint = MachineBasicBlock::iterator; - - /// Prepare InsertPt to begin inserting instructions into the local - /// value area and return the old insert position. - SavePoint enterLocalValueArea(); - - /// Reset InsertPt to the given old insert position. - void leaveLocalValueArea(SavePoint Old); - - /// Signal whether instruction referencing variable locations are desired for - /// this function's debug-info. - void useInstrRefDebugInfo(bool Flag) { - UseInstrRefDebugInfo = Flag; - } - -protected: - explicit FastISel(FunctionLoweringInfo &FuncInfo, - const TargetLibraryInfo *LibInfo, - bool SkipTargetIndependentISel = false); - - /// This method is called by target-independent code when the normal - /// FastISel process fails to select an instruction. This gives targets a - /// chance to emit code for anything that doesn't fit into FastISel's - /// framework. It returns true if it was successful. - virtual bool fastSelectInstruction(const Instruction *I) = 0; - - /// This method is called by target-independent code to do target- - /// specific argument lowering. It returns true if it was successful. - virtual bool fastLowerArguments(); - - /// This method is called by target-independent code to do target- - /// specific call lowering. It returns true if it was successful. - virtual bool fastLowerCall(CallLoweringInfo &CLI); - - /// This method is called by target-independent code to do target- - /// specific intrinsic lowering. It returns true if it was successful. - virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II); - - /// This method is called by target-independent code to request that an - /// instruction with the given type and opcode be emitted. - virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - - /// This method is called by target-independent code to request that an - /// instruction with the given type, opcode, and register operand be emitted. - virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0); - - /// This method is called by target-independent code to request that an - /// instruction with the given type, opcode, and register operands be emitted. - virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, - unsigned Op1); - - /// This method is called by target-independent code to request that an - /// instruction with the given type, opcode, and register and immediate - /// operands be emitted. - virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, - uint64_t Imm); - - /// This method is a wrapper of fastEmit_ri. - /// - /// It first tries to emit an instruction with an immediate operand using - /// fastEmit_ri. If that fails, it materializes the immediate into a register - /// and try fastEmit_rr instead. - Register fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, uint64_t Imm, - MVT ImmType); - - /// This method is called by target-independent code to request that an - /// instruction with the given type, opcode, and immediate operand be emitted. - virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - - /// This method is called by target-independent code to request that an - /// instruction with the given type, opcode, and floating-point immediate - /// operand be emitted. - virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, - const ConstantFP *FPImm); - - /// Emit a MachineInstr with no operands and a result register in the - /// given register class. - Register fastEmitInst_(unsigned MachineInstOpcode, - const TargetRegisterClass *RC); - - /// Emit a MachineInstr with one register operand and a result register - /// in the given register class. - Register fastEmitInst_r(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0); - - /// Emit a MachineInstr with two register operands and a result - /// register in the given register class. - Register fastEmitInst_rr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0, - unsigned Op1); - - /// Emit a MachineInstr with three register operands and a result - /// register in the given register class. - Register fastEmitInst_rrr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0, - unsigned Op1, unsigned Op2); - - /// Emit a MachineInstr with a register operand, an immediate, and a - /// result register in the given register class. - Register fastEmitInst_ri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0, - uint64_t Imm); - - /// Emit a MachineInstr with one register operand and two immediate - /// operands. - Register fastEmitInst_rii(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0, - uint64_t Imm1, uint64_t Imm2); - - /// Emit a MachineInstr with a floating point immediate, and a result - /// register in the given register class. - Register fastEmitInst_f(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - const ConstantFP *FPImm); - - /// Emit a MachineInstr with two register operands, an immediate, and a - /// result register in the given register class. - Register fastEmitInst_rri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, unsigned Op0, - unsigned Op1, uint64_t Imm); - - /// Emit a MachineInstr with a single immediate operand, and a result - /// register in the given register class. - Register fastEmitInst_i(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, uint64_t Imm); - - /// Emit a MachineInstr for an extract_subreg from a specified index of - /// a superregister to a specified type. - Register fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, uint32_t Idx); - - /// Emit MachineInstrs to compute the value of Op with all but the - /// least significant bit set to zero. - Register fastEmitZExtFromI1(MVT VT, unsigned Op0); - - /// Emit an unconditional branch to the given block, unless it is the - /// immediate (fall-through) successor, and update the CFG. - void fastEmitBranch(MachineBasicBlock *MSucc, const DebugLoc &DbgLoc); - - /// Emit an unconditional branch to \p FalseMBB, obtains the branch weight - /// and adds TrueMBB and FalseMBB to the successor list. - void finishCondBranch(const BasicBlock *BranchBB, MachineBasicBlock *TrueMBB, - MachineBasicBlock *FalseMBB); - - /// Update the value map to include the new mapping for this - /// instruction, or insert an extra copy to get the result in a previous - /// determined register. - /// - /// NOTE: This is only necessary because we might select a block that uses a - /// value before we select the block that defines the value. It might be - /// possible to fix this by selecting blocks in reverse postorder. - void updateValueMap(const Value *I, Register Reg, unsigned NumRegs = 1); - - Register createResultReg(const TargetRegisterClass *RC); - - /// Try to constrain Op so that it is usable by argument OpNum of the - /// provided MCInstrDesc. If this fails, create a new virtual register in the - /// correct class and COPY the value there. - Register constrainOperandRegClass(const MCInstrDesc &II, Register Op, - unsigned OpNum); - - /// Emit a constant in a register using target-specific logic, such as - /// constant pool loads. - virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; } - - /// Emit an alloca address in a register using target-specific logic. - virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; } - - /// Emit the floating-point constant +0.0 in a register using target- - /// specific logic. - virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) { - return 0; - } - - /// Check if \c Add is an add that can be safely folded into \c GEP. - /// - /// \c Add can be folded into \c GEP if: - /// - \c Add is an add, - /// - \c Add's size matches \c GEP's, - /// - \c Add is in the same basic block as \c GEP, and - /// - \c Add has a constant operand. - bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - - /// Create a machine mem operand from the given instruction. - MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; - - CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const; - - bool lowerCallTo(const CallInst *CI, MCSymbol *Symbol, unsigned NumArgs); - bool lowerCallTo(const CallInst *CI, const char *SymName, - unsigned NumArgs); - bool lowerCallTo(CallLoweringInfo &CLI); - - bool lowerCall(const CallInst *I); - /// Select and emit code for a binary operator instruction, which has - /// an opcode which directly corresponds to the given ISD opcode. - bool selectBinaryOp(const User *I, unsigned ISDOpcode); - bool selectFNeg(const User *I, const Value *In); - bool selectGetElementPtr(const User *I); - bool selectStackmap(const CallInst *I); - bool selectPatchpoint(const CallInst *I); - bool selectCall(const User *I); - bool selectIntrinsicCall(const IntrinsicInst *II); - bool selectBitCast(const User *I); - bool selectFreeze(const User *I); - bool selectCast(const User *I, unsigned Opcode); - bool selectExtractValue(const User *U); - bool selectXRayCustomEvent(const CallInst *II); - bool selectXRayTypedEvent(const CallInst *II); - - bool shouldOptForSize(const MachineFunction *MF) const { - // TODO: Implement PGSO. - return MF->getFunction().hasOptSize(); - } - -private: - /// Handle PHI nodes in successor blocks. - /// - /// Emit code to ensure constants are copied into registers when needed. - /// Remember the virtual registers that need to be added to the Machine PHI - /// nodes as input. We cannot just directly add them, because expansion might - /// result in multiple MBB's for one BB. As such, the start of the BB might - /// correspond to a different MBB than the end. - bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); - - /// Helper for materializeRegForValue to materialize a constant in a - /// target-independent way. - Register materializeConstant(const Value *V, MVT VT); - - /// Helper for getRegForVale. This function is called when the value - /// isn't already available in a register and must be materialized with new - /// instructions. - Register materializeRegForValue(const Value *V, MVT VT); - - /// Clears LocalValueMap and moves the area for the new local variables - /// to the beginning of the block. It helps to avoid spilling cached variables - /// across heavy instructions like calls. - void flushLocalValueMap(); - - /// Removes dead local value instructions after SavedLastLocalvalue. - void removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue); - - /// Insertion point before trying to select the current instruction. - MachineBasicBlock::iterator SavedInsertPt; - - /// Add a stackmap or patchpoint intrinsic call's live variable - /// operands to a stackmap or patchpoint machine instruction. - bool addStackMapLiveVars(SmallVectorImpl &Ops, - const CallInst *CI, unsigned StartIdx); - bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs, - const Value *Callee, bool ForceRetVoidTy, - CallLoweringInfo &CLI); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_FASTISEL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/FaultMaps.h b/suite/synctools/tablegen/include/llvm/CodeGen/FaultMaps.h deleted file mode 100644 index 8a8b1d2e60..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/FaultMaps.h +++ /dev/null @@ -1,77 +0,0 @@ -//===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_FAULTMAPS_H -#define LLVM_CODEGEN_FAULTMAPS_H - -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Endian.h" -#include -#include - -namespace llvm { - -class AsmPrinter; -class MCExpr; - -class FaultMaps { -public: - enum FaultKind { - FaultingLoad = 1, - FaultingLoadStore, - FaultingStore, - FaultKindMax - }; - - explicit FaultMaps(AsmPrinter &AP); - - static const char *faultTypeToString(FaultKind); - - void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, - const MCSymbol *HandlerLabel); - void serializeToFaultMapSection(); - void reset() { - FunctionInfos.clear(); - } - -private: - static const char *WFMP; - - struct FaultInfo { - FaultKind Kind = FaultKindMax; - const MCExpr *FaultingOffsetExpr = nullptr; - const MCExpr *HandlerOffsetExpr = nullptr; - - FaultInfo() = default; - - explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset, - const MCExpr *HandlerOffset) - : Kind(Kind), FaultingOffsetExpr(FaultingOffset), - HandlerOffsetExpr(HandlerOffset) {} - }; - - using FunctionFaultInfos = std::vector; - - // We'd like to keep a stable iteration order for FunctionInfos to help - // FileCheck based testing. - struct MCSymbolComparator { - bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const { - return LHS->getName() < RHS->getName(); - } - }; - - std::map - FunctionInfos; - AsmPrinter &AP; - - void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_FAULTMAPS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/FunctionLoweringInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/FunctionLoweringInfo.h deleted file mode 100644 index 524730d536..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/FunctionLoweringInfo.h +++ /dev/null @@ -1,285 +0,0 @@ -//===- FunctionLoweringInfo.h - Lower functions from LLVM IR ---*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This implements routines for translating functions from LLVM IR into -// Machine IR. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H -#define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/KnownBits.h" -#include -#include -#include - -namespace llvm { - -class Argument; -class BasicBlock; -class BranchProbabilityInfo; -class LegacyDivergenceAnalysis; -class Function; -class Instruction; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class MVT; -class SelectionDAG; -class TargetLowering; - -//===--------------------------------------------------------------------===// -/// FunctionLoweringInfo - This contains information that is global to a -/// function that is used when lowering a region of the function. -/// -class FunctionLoweringInfo { -public: - const Function *Fn; - MachineFunction *MF; - const TargetLowering *TLI; - MachineRegisterInfo *RegInfo; - BranchProbabilityInfo *BPI; - const LegacyDivergenceAnalysis *DA; - /// CanLowerReturn - true iff the function's return value can be lowered to - /// registers. - bool CanLowerReturn; - - /// True if part of the CSRs will be handled via explicit copies. - bool SplitCSR; - - /// DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg - /// allocated to hold a pointer to the hidden sret parameter. - Register DemoteRegister; - - /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. - DenseMap MBBMap; - - /// ValueMap - Since we emit code for the function a basic block at a time, - /// we must remember which virtual registers hold the values for - /// cross-basic-block values. - DenseMap ValueMap; - - /// VirtReg2Value map is needed by the Divergence Analysis driven - /// instruction selection. It is reverted ValueMap. It is computed - /// in lazy style - on demand. It is used to get the Value corresponding - /// to the live in virtual register and is called from the - /// TargetLowerinInfo::isSDNodeSourceOfDivergence. - DenseMap VirtReg2Value; - - /// This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence - /// to get the Value corresponding to the live-in virtual register. - const Value *getValueFromVirtualReg(Register Vreg); - - /// Track virtual registers created for exception pointers. - DenseMap CatchPadExceptionPointers; - - /// Helper object to track which of three possible relocation mechanisms are - /// used for a particular value being relocated over a statepoint. - struct StatepointRelocationRecord { - enum RelocType { - // Value did not need to be relocated and can be used directly. - NoRelocate, - // Value was spilled to stack and needs filled at the gc.relocate. - Spill, - // Value was lowered to tied def and gc.relocate should be replaced with - // copy from vreg. - VReg, - } type = NoRelocate; - // Payload contains either frame index of the stack slot in which the value - // was spilled, or virtual register which contains the re-definition. - union payload_t { - payload_t() : FI(-1) {} - int FI; - Register Reg; - } payload; - }; - - /// Keep track of each value which was relocated and the strategy used to - /// relocate that value. This information is required when visiting - /// gc.relocates which may appear in following blocks. - using StatepointSpillMapTy = - DenseMap; - DenseMap StatepointRelocationMaps; - - /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in - /// the entry block. This allows the allocas to be efficiently referenced - /// anywhere in the function. - DenseMap StaticAllocaMap; - - /// ByValArgFrameIndexMap - Keep track of frame indices for byval arguments. - DenseMap ByValArgFrameIndexMap; - - /// ArgDbgValues - A list of DBG_VALUE instructions created during isel for - /// function arguments that are inserted after scheduling is completed. - SmallVector ArgDbgValues; - - /// Bitvector with a bit set if corresponding argument is described in - /// ArgDbgValues. Using arg numbers according to Argument numbering. - BitVector DescribedArgs; - - /// RegFixups - Registers which need to be replaced after isel is done. - DenseMap RegFixups; - - DenseSet RegsWithFixups; - - /// StatepointStackSlots - A list of temporary stack slots (frame indices) - /// used to spill values at a statepoint. We store them here to enable - /// reuse of the same stack slots across different statepoints in different - /// basic blocks. - SmallVector StatepointStackSlots; - - /// MBB - The current block. - MachineBasicBlock *MBB; - - /// MBB - The current insert position inside the current block. - MachineBasicBlock::iterator InsertPt; - - struct LiveOutInfo { - unsigned NumSignBits : 31; - unsigned IsValid : 1; - KnownBits Known = 1; - - LiveOutInfo() : NumSignBits(0), IsValid(true) {} - }; - - /// Record the preferred extend type (ISD::SIGN_EXTEND or ISD::ZERO_EXTEND) - /// for a value. - DenseMap PreferredExtendType; - - /// VisitedBBs - The set of basic blocks visited thus far by instruction - /// selection. - SmallPtrSet VisitedBBs; - - /// PHINodesToUpdate - A list of phi instructions whose operand list will - /// be updated after processing the current basic block. - /// TODO: This isn't per-function state, it's per-basic-block state. But - /// there's no other convenient place for it to live right now. - std::vector > PHINodesToUpdate; - unsigned OrigNumPHINodesToUpdate; - - /// If the current MBB is a landing pad, the exception pointer and exception - /// selector registers are copied into these virtual registers by - /// SelectionDAGISel::PrepareEHLandingPad(). - unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; - - /// set - Initialize this FunctionLoweringInfo with the given Function - /// and its associated MachineFunction. - /// - void set(const Function &Fn, MachineFunction &MF, SelectionDAG *DAG); - - /// clear - Clear out all the function-specific state. This returns this - /// FunctionLoweringInfo to an empty state, ready to be used for a - /// different function. - void clear(); - - /// isExportedInst - Return true if the specified value is an instruction - /// exported from its block. - bool isExportedInst(const Value *V) const { - return ValueMap.count(V); - } - - Register CreateReg(MVT VT, bool isDivergent = false); - - Register CreateRegs(const Value *V); - - Register CreateRegs(Type *Ty, bool isDivergent = false); - - Register InitializeRegForValue(const Value *V) { - // Tokens never live in vregs. - if (V->getType()->isTokenTy()) - return 0; - Register &R = ValueMap[V]; - assert(R == 0 && "Already initialized this value register!"); - assert(VirtReg2Value.empty()); - return R = CreateRegs(V); - } - - /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the - /// register is a PHI destination and the PHI's LiveOutInfo is not valid. - const LiveOutInfo *GetLiveOutRegInfo(Register Reg) { - if (!LiveOutRegInfo.inBounds(Reg)) - return nullptr; - - const LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; - if (!LOI->IsValid) - return nullptr; - - return LOI; - } - - /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the - /// register is a PHI destination and the PHI's LiveOutInfo is not valid. If - /// the register's LiveOutInfo is for a smaller bit width, it is extended to - /// the larger bit width by zero extension. The bit width must be no smaller - /// than the LiveOutInfo's existing bit width. - const LiveOutInfo *GetLiveOutRegInfo(Register Reg, unsigned BitWidth); - - /// AddLiveOutRegInfo - Adds LiveOutInfo for a register. - void AddLiveOutRegInfo(Register Reg, unsigned NumSignBits, - const KnownBits &Known) { - // Only install this information if it tells us something. - if (NumSignBits == 1 && Known.isUnknown()) - return; - - LiveOutRegInfo.grow(Reg); - LiveOutInfo &LOI = LiveOutRegInfo[Reg]; - LOI.NumSignBits = NumSignBits; - LOI.Known.One = Known.One; - LOI.Known.Zero = Known.Zero; - } - - /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination - /// register based on the LiveOutInfo of its operands. - void ComputePHILiveOutRegInfo(const PHINode*); - - /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be - /// called when a block is visited before all of its predecessors. - void InvalidatePHILiveOutRegInfo(const PHINode *PN) { - // PHIs with no uses have no ValueMap entry. - DenseMap::const_iterator It = ValueMap.find(PN); - if (It == ValueMap.end()) - return; - - Register Reg = It->second; - if (Reg == 0) - return; - - LiveOutRegInfo.grow(Reg); - LiveOutRegInfo[Reg].IsValid = false; - } - - /// setArgumentFrameIndex - Record frame index for the byval - /// argument. - void setArgumentFrameIndex(const Argument *A, int FI); - - /// getArgumentFrameIndex - Get frame index for the byval argument. - int getArgumentFrameIndex(const Argument *A); - - Register getCatchPadExceptionPointerVReg(const Value *CPI, - const TargetRegisterClass *RC); - -private: - /// LiveOutRegInfo - Information about live out vregs. - IndexedMap LiveOutRegInfo; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadata.h b/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadata.h deleted file mode 100644 index 334c5c23b8..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadata.h +++ /dev/null @@ -1,205 +0,0 @@ -//===- GCMetadata.h - Garbage collector metadata ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the GCFunctionInfo and GCModuleInfo classes, which are -// used as a communication channel from the target code generator to the target -// garbage collectors. This interface allows code generators and garbage -// collectors to be developed independently. -// -// The GCFunctionInfo class logs the data necessary to build a type accurate -// stack map. The code generator outputs: -// -// - Safe points as specified by the GCStrategy's NeededSafePoints. -// - Stack offsets for GC roots, as specified by calls to llvm.gcroot -// -// As a refinement, liveness analysis calculates the set of live roots at each -// safe point. Liveness analysis is not presently performed by the code -// generator, so all roots are assumed live. -// -// GCModuleInfo simply collects GCFunctionInfo instances for each Function as -// they are compiled. This accretion is necessary for collectors which must emit -// a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo -// outlives the MachineFunction from which it is derived and must not refer to -// any code generator data structures. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GCMETADATA_H -#define LLVM_CODEGEN_GCMETADATA_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/GCStrategy.h" -#include "llvm/Pass.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class Constant; -class Function; -class MCSymbol; - -/// GCPoint - Metadata for a collector-safe point in machine code. -/// -struct GCPoint { - MCSymbol *Label; ///< A label. - DebugLoc Loc; - - GCPoint(MCSymbol *L, DebugLoc DL) - : Label(L), Loc(std::move(DL)) {} -}; - -/// GCRoot - Metadata for a pointer to an object managed by the garbage -/// collector. -struct GCRoot { - int Num; ///< Usually a frame index. - int StackOffset = -1; ///< Offset from the stack pointer. - const Constant *Metadata; ///< Metadata straight from the call - ///< to llvm.gcroot. - - GCRoot(int N, const Constant *MD) : Num(N), Metadata(MD) {} -}; - -/// Garbage collection metadata for a single function. Currently, this -/// information only applies to GCStrategies which use GCRoot. -class GCFunctionInfo { -public: - using iterator = std::vector::iterator; - using roots_iterator = std::vector::iterator; - using live_iterator = std::vector::const_iterator; - -private: - const Function &F; - GCStrategy &S; - uint64_t FrameSize; - std::vector Roots; - std::vector SafePoints; - - // FIXME: Liveness. A 2D BitVector, perhaps? - // - // BitVector Liveness; - // - // bool islive(int point, int root) = - // Liveness[point * SafePoints.size() + root] - // - // The bit vector is the more compact representation where >3.2% of roots - // are live per safe point (1.5% on 64-bit hosts). - -public: - GCFunctionInfo(const Function &F, GCStrategy &S); - ~GCFunctionInfo(); - - /// getFunction - Return the function to which this metadata applies. - const Function &getFunction() const { return F; } - - /// getStrategy - Return the GC strategy for the function. - GCStrategy &getStrategy() { return S; } - - /// addStackRoot - Registers a root that lives on the stack. Num is the - /// stack object ID for the alloca (if the code generator is - // using MachineFrameInfo). - void addStackRoot(int Num, const Constant *Metadata) { - Roots.push_back(GCRoot(Num, Metadata)); - } - - /// removeStackRoot - Removes a root. - roots_iterator removeStackRoot(roots_iterator position) { - return Roots.erase(position); - } - - /// addSafePoint - Notes the existence of a safe point. Num is the ID of the - /// label just prior to the safe point (if the code generator is using - /// MachineModuleInfo). - void addSafePoint(MCSymbol *Label, const DebugLoc &DL) { - SafePoints.emplace_back(Label, DL); - } - - /// getFrameSize/setFrameSize - Records the function's frame size. - uint64_t getFrameSize() const { return FrameSize; } - void setFrameSize(uint64_t S) { FrameSize = S; } - - /// begin/end - Iterators for safe points. - iterator begin() { return SafePoints.begin(); } - iterator end() { return SafePoints.end(); } - size_t size() const { return SafePoints.size(); } - - /// roots_begin/roots_end - Iterators for all roots in the function. - roots_iterator roots_begin() { return Roots.begin(); } - roots_iterator roots_end() { return Roots.end(); } - size_t roots_size() const { return Roots.size(); } - - /// live_begin/live_end - Iterators for live roots at a given safe point. - live_iterator live_begin(const iterator &p) { return roots_begin(); } - live_iterator live_end(const iterator &p) { return roots_end(); } - size_t live_size(const iterator &p) const { return roots_size(); } -}; - -/// An analysis pass which caches information about the entire Module. -/// Records both the function level information used by GCRoots and a -/// cache of the 'active' gc strategy objects for the current Module. -class GCModuleInfo : public ImmutablePass { - /// An owning list of all GCStrategies which have been created - SmallVector, 1> GCStrategyList; - /// A helper map to speedup lookups into the above list - StringMap GCStrategyMap; - -public: - /// Lookup the GCStrategy object associated with the given gc name. - /// Objects are owned internally; No caller should attempt to delete the - /// returned objects. - GCStrategy *getGCStrategy(const StringRef Name); - - /// List of per function info objects. In theory, Each of these - /// may be associated with a different GC. - using FuncInfoVec = std::vector>; - - FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } - FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } - -private: - /// Owning list of all GCFunctionInfos associated with this Module - FuncInfoVec Functions; - - /// Non-owning map to bypass linear search when finding the GCFunctionInfo - /// associated with a particular Function. - using finfo_map_type = DenseMap; - finfo_map_type FInfoMap; - -public: - using iterator = SmallVector, 1>::const_iterator; - - static char ID; - - GCModuleInfo(); - - /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should - /// call it in doFinalization(). - /// - void clear(); - - /// begin/end - Iterators for used strategies. - /// - iterator begin() const { return GCStrategyList.begin(); } - iterator end() const { return GCStrategyList.end(); } - - /// get - Look up function metadata. This is currently assumed - /// have the side effect of initializing the associated GCStrategy. That - /// will soon change. - GCFunctionInfo &getFunctionInfo(const Function &F); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GCMETADATA_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadataPrinter.h b/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadataPrinter.h deleted file mode 100644 index f9527c9f87..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GCMetadataPrinter.h +++ /dev/null @@ -1,72 +0,0 @@ -//===- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The abstract base class GCMetadataPrinter supports writing GC metadata tables -// as assembly code. This is a separate class from GCStrategy in order to allow -// users of the LLVM JIT to avoid linking with the AsmWriter. -// -// Subclasses of GCMetadataPrinter must be registered using the -// GCMetadataPrinterRegistry. This is separate from the GCStrategy itself -// because these subclasses are logically plugins for the AsmWriter. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GCMETADATAPRINTER_H -#define LLVM_CODEGEN_GCMETADATAPRINTER_H - -#include "llvm/Support/Registry.h" - -namespace llvm { - -class AsmPrinter; -class GCMetadataPrinter; -class GCModuleInfo; -class GCStrategy; -class Module; -class StackMaps; - -/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the -/// defaults from Registry. -using GCMetadataPrinterRegistry = Registry; - -/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are -/// created, managed, and owned by the AsmPrinter. -class GCMetadataPrinter { -private: - friend class AsmPrinter; - - GCStrategy *S; - -protected: - // May only be subclassed. - GCMetadataPrinter(); - -public: - GCMetadataPrinter(const GCMetadataPrinter &) = delete; - GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete; - virtual ~GCMetadataPrinter(); - - GCStrategy &getStrategy() { return *S; } - - /// Called before the assembly for the module is generated by - /// the AsmPrinter (but after target specific hooks.) - virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} - - /// Called after the assembly for the module is generated by - /// the AsmPrinter (but before target specific hooks) - virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} - - /// Called when the stack maps are generated. Return true if - /// stack maps with a custom format are generated. Otherwise - /// returns false and the default format will be used. - virtual bool emitStackMaps(StackMaps &SM, AsmPrinter &AP) { return false; } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GCMETADATAPRINTER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEInfo.h deleted file mode 100644 index dd213bf68e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ /dev/null @@ -1,242 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Provides analysis for continuously CSEing during GISel passes. -/// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GLOBALISEL_CSEINFO_H -#define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H - -#include "llvm/ADT/FoldingSet.h" -#include "llvm/CodeGen/CSEConfigBase.h" -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" -#include "llvm/CodeGen/GlobalISel/GISelWorkList.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CodeGen.h" - -namespace llvm { -class MachineBasicBlock; - -/// A class that wraps MachineInstrs and derives from FoldingSetNode in order to -/// be uniqued in a CSEMap. The tradeoff here is extra memory allocations for -/// UniqueMachineInstr vs making MachineInstr bigger. -class UniqueMachineInstr : public FoldingSetNode { - friend class GISelCSEInfo; - const MachineInstr *MI; - explicit UniqueMachineInstr(const MachineInstr *MI) : MI(MI) {} - -public: - void Profile(FoldingSetNodeID &ID); -}; - -// A CSE config for fully optimized builds. -class CSEConfigFull : public CSEConfigBase { -public: - virtual ~CSEConfigFull() = default; - virtual bool shouldCSEOpc(unsigned Opc) override; -}; - -// Commonly used for O0 config. -class CSEConfigConstantOnly : public CSEConfigBase { -public: - virtual ~CSEConfigConstantOnly() = default; - virtual bool shouldCSEOpc(unsigned Opc) override; -}; - -// Returns the standard expected CSEConfig for the given optimization level. -// We have this logic here so targets can make use of it from their derived -// TargetPassConfig, but can't put this logic into TargetPassConfig directly -// because the CodeGen library can't depend on GlobalISel. -std::unique_ptr -getStandardCSEConfigForOpt(CodeGenOpt::Level Level); - -/// The CSE Analysis object. -/// This installs itself as a delegate to the MachineFunction to track -/// new instructions as well as deletions. It however will not be able to -/// track instruction mutations. In such cases, recordNewInstruction should be -/// called (for eg inside MachineIRBuilder::recordInsertion). -/// Also because of how just the instruction can be inserted without adding any -/// operands to the instruction, instructions are uniqued and inserted lazily. -/// CSEInfo should assert when trying to enter an incomplete instruction into -/// the CSEMap. There is Opcode level granularity on which instructions can be -/// CSE'd and for now, only Generic instructions are CSEable. -class GISelCSEInfo : public GISelChangeObserver { - // Make it accessible only to CSEMIRBuilder. - friend class CSEMIRBuilder; - - BumpPtrAllocator UniqueInstrAllocator; - FoldingSet CSEMap; - MachineRegisterInfo *MRI = nullptr; - MachineFunction *MF = nullptr; - std::unique_ptr CSEOpt; - /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel, - /// often instructions are mutated (while their ID has completely changed). - /// Whenever mutation happens, invalidate the UniqueMachineInstr for the - /// MachineInstr - DenseMap InstrMapping; - - /// Store instructions that are not fully formed in TemporaryInsts. - /// Also because CSE insertion happens lazily, we can remove insts from this - /// list and avoid inserting and then removing from the CSEMap. - GISelWorkList<8> TemporaryInsts; - - // Only used in asserts. - DenseMap OpcodeHitTable; - - bool isUniqueMachineInstValid(const UniqueMachineInstr &UMI) const; - - void invalidateUniqueMachineInstr(UniqueMachineInstr *UMI); - - UniqueMachineInstr *getNodeIfExists(FoldingSetNodeID &ID, - MachineBasicBlock *MBB, void *&InsertPos); - - /// Allocate and construct a new UniqueMachineInstr for MI and return. - UniqueMachineInstr *getUniqueInstrForMI(const MachineInstr *MI); - - void insertNode(UniqueMachineInstr *UMI, void *InsertPos = nullptr); - - /// Get the MachineInstr(Unique) if it exists already in the CSEMap and the - /// same MachineBasicBlock. - MachineInstr *getMachineInstrIfExists(FoldingSetNodeID &ID, - MachineBasicBlock *MBB, - void *&InsertPos); - - /// Use this method to allocate a new UniqueMachineInstr for MI and insert it - /// into the CSEMap. MI should return true for shouldCSE(MI->getOpcode()) - void insertInstr(MachineInstr *MI, void *InsertPos = nullptr); - -public: - GISelCSEInfo() = default; - - virtual ~GISelCSEInfo(); - - void setMF(MachineFunction &MF); - - Error verify(); - - /// Records a newly created inst in a list and lazily insert it to the CSEMap. - /// Sometimes, this method might be called with a partially constructed - /// MachineInstr, - // (right after BuildMI without adding any operands) - and in such cases, - // defer the hashing of the instruction to a later stage. - void recordNewInstruction(MachineInstr *MI); - - /// Use this callback to inform CSE about a newly fully created instruction. - void handleRecordedInst(MachineInstr *MI); - - /// Use this callback to insert all the recorded instructions. At this point, - /// all of these insts need to be fully constructed and should not be missing - /// any operands. - void handleRecordedInsts(); - - /// Remove this inst from the CSE map. If this inst has not been inserted yet, - /// it will be removed from the Tempinsts list if it exists. - void handleRemoveInst(MachineInstr *MI); - - void releaseMemory(); - - void setCSEConfig(std::unique_ptr Opt) { - CSEOpt = std::move(Opt); - } - - bool shouldCSE(unsigned Opc) const; - - void analyze(MachineFunction &MF); - - void countOpcodeHit(unsigned Opc); - - void print(); - - // Observer API - void erasingInstr(MachineInstr &MI) override; - void createdInstr(MachineInstr &MI) override; - void changingInstr(MachineInstr &MI) override; - void changedInstr(MachineInstr &MI) override; -}; - -class TargetRegisterClass; -class RegisterBank; - -// Simple builder class to easily profile properties about MIs. -class GISelInstProfileBuilder { - FoldingSetNodeID &ID; - const MachineRegisterInfo &MRI; - -public: - GISelInstProfileBuilder(FoldingSetNodeID &ID, const MachineRegisterInfo &MRI) - : ID(ID), MRI(MRI) {} - // Profiling methods. - const GISelInstProfileBuilder &addNodeIDOpcode(unsigned Opc) const; - const GISelInstProfileBuilder &addNodeIDRegType(const LLT Ty) const; - const GISelInstProfileBuilder &addNodeIDRegType(const Register) const; - - const GISelInstProfileBuilder & - addNodeIDRegType(const TargetRegisterClass *RC) const; - const GISelInstProfileBuilder &addNodeIDRegType(const RegisterBank *RB) const; - - const GISelInstProfileBuilder &addNodeIDRegNum(Register Reg) const; - - const GISelInstProfileBuilder &addNodeIDReg(Register Reg) const; - - const GISelInstProfileBuilder &addNodeIDImmediate(int64_t Imm) const; - const GISelInstProfileBuilder & - addNodeIDMBB(const MachineBasicBlock *MBB) const; - - const GISelInstProfileBuilder & - addNodeIDMachineOperand(const MachineOperand &MO) const; - - const GISelInstProfileBuilder &addNodeIDFlag(unsigned Flag) const; - const GISelInstProfileBuilder &addNodeID(const MachineInstr *MI) const; -}; - -/// Simple wrapper that does the following. -/// 1) Lazily evaluate the MachineFunction to compute CSEable instructions. -/// 2) Allows configuration of which instructions are CSEd through CSEConfig -/// object. Provides a method called get which takes a CSEConfig object. -class GISelCSEAnalysisWrapper { - GISelCSEInfo Info; - MachineFunction *MF = nullptr; - bool AlreadyComputed = false; - -public: - /// Takes a CSEConfigBase object that defines what opcodes get CSEd. - /// If CSEConfig is already set, and the CSE Analysis has been preserved, - /// it will not use the new CSEOpt(use Recompute to force using the new - /// CSEOpt). - GISelCSEInfo &get(std::unique_ptr CSEOpt, - bool ReCompute = false); - void setMF(MachineFunction &MFunc) { MF = &MFunc; } - void setComputed(bool Computed) { AlreadyComputed = Computed; } - void releaseMemory() { Info.releaseMemory(); } -}; - -/// The actual analysis pass wrapper. -class GISelCSEAnalysisWrapperPass : public MachineFunctionPass { - GISelCSEAnalysisWrapper Wrapper; - -public: - static char ID; - GISelCSEAnalysisWrapperPass(); - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - const GISelCSEAnalysisWrapper &getCSEWrapper() const { return Wrapper; } - GISelCSEAnalysisWrapper &getCSEWrapper() { return Wrapper; } - - bool runOnMachineFunction(MachineFunction &MF) override; - - void releaseMemory() override { - Wrapper.releaseMemory(); - Wrapper.setComputed(false); - } -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h deleted file mode 100644 index 4f95335db7..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h +++ /dev/null @@ -1,109 +0,0 @@ -//===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file implements a version of MachineIRBuilder which CSEs insts within -/// a MachineBasicBlock. -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H -#define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H - -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" - -namespace llvm { - -/// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo. -/// Eg usage. -/// -/// -/// GISelCSEInfo *Info = -/// &getAnalysis().getCSEInfo(); CSEMIRBuilder -/// CB(Builder.getState()); CB.setCSEInfo(Info); auto A = CB.buildConstant(s32, -/// 42); auto B = CB.buildConstant(s32, 42); assert(A == B); unsigned CReg = -/// MRI.createGenericVirtualRegister(s32); auto C = CB.buildConstant(CReg, 42); -/// assert(C->getOpcode() == TargetOpcode::COPY); -/// Explicitly passing in a register would materialize a copy if possible. -/// CSEMIRBuilder also does trivial constant folding for binary ops. -class CSEMIRBuilder : public MachineIRBuilder { - - /// Returns true if A dominates B (within the same basic block). - /// Both iterators must be in the same basic block. - // - // TODO: Another approach for checking dominance is having two iterators and - // making them go towards each other until they meet or reach begin/end. Which - // approach is better? Should this even change dynamically? For G_CONSTANTS - // most of which will be at the top of the BB, the top down approach would be - // a better choice. Does IRTranslator placing constants at the beginning still - // make sense? Should this change based on Opcode? - bool dominates(MachineBasicBlock::const_iterator A, - MachineBasicBlock::const_iterator B) const; - - /// For given ID, find a machineinstr in the CSE Map. If found, check if it - /// dominates the current insertion point and if not, move it just before the - /// current insertion point and return it. If not found, return Null - /// MachineInstrBuilder. - MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID, - void *&NodeInsertPos); - /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is - /// safe to CSE. - bool canPerformCSEForOpc(unsigned Opc) const; - - void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const; - - void profileDstOps(ArrayRef Ops, GISelInstProfileBuilder &B) const { - for (const DstOp &Op : Ops) - profileDstOp(Op, B); - } - - void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const; - - void profileSrcOps(ArrayRef Ops, GISelInstProfileBuilder &B) const { - for (const SrcOp &Op : Ops) - profileSrcOp(Op, B); - } - - void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const; - - void profileEverything(unsigned Opc, ArrayRef DstOps, - ArrayRef SrcOps, Optional Flags, - GISelInstProfileBuilder &B) const; - - // Takes a MachineInstrBuilder and inserts it into the CSEMap using the - // NodeInsertPos. - MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos); - - // If we have can CSE an instruction, but still need to materialize to a VReg, - // we emit a copy from the CSE'd inst to the VReg. - MachineInstrBuilder generateCopiesIfRequired(ArrayRef DstOps, - MachineInstrBuilder &MIB); - - // If we have can CSE an instruction, but still need to materialize to a VReg, - // check if we can generate copies. It's not possible to return a single MIB, - // while emitting copies to multiple vregs. - bool checkCopyToDefsPossible(ArrayRef DstOps); - -public: - // Pull in base class constructors. - using MachineIRBuilder::MachineIRBuilder; - // Unhide buildInstr - MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, - ArrayRef SrcOps, - Optional Flag = None) override; - // Bring in the other overload from the base class. - using MachineIRBuilder::buildConstant; - - MachineInstrBuilder buildConstant(const DstOp &Res, - const ConstantInt &Val) override; - - // Bring in the other overload from the base class. - using MachineIRBuilder::buildFConstant; - MachineInstrBuilder buildFConstant(const DstOp &Res, - const ConstantFP &Val) override; -}; -} // namespace llvm -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CallLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CallLowering.h deleted file mode 100644 index f9663fadb8..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ /dev/null @@ -1,591 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file describes how to lower LLVM calls to machine code calls. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H -#define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetCallingConv.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include -#include - -namespace llvm { - -class CallBase; -class DataLayout; -class Function; -class FunctionLoweringInfo; -class MachineIRBuilder; -struct MachinePointerInfo; -class MachineRegisterInfo; -class TargetLowering; - -class CallLowering { - const TargetLowering *TLI; - - virtual void anchor(); -public: - struct BaseArgInfo { - Type *Ty; - SmallVector Flags; - bool IsFixed; - - BaseArgInfo(Type *Ty, - ArrayRef Flags = ArrayRef(), - bool IsFixed = true) - : Ty(Ty), Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) {} - - BaseArgInfo() : Ty(nullptr), IsFixed(false) {} - }; - - struct ArgInfo : public BaseArgInfo { - SmallVector Regs; - // If the argument had to be split into multiple parts according to the - // target calling convention, then this contains the original vregs - // if the argument was an incoming arg. - SmallVector OrigRegs; - - /// Optionally track the original IR value for the argument. This may not be - /// meaningful in all contexts. This should only be used on for forwarding - /// through to use for aliasing information in MachinePointerInfo for memory - /// arguments. - const Value *OrigValue = nullptr; - - /// Index original Function's argument. - unsigned OrigArgIndex; - - /// Sentinel value for implicit machine-level input arguments. - static const unsigned NoArgIndex = UINT_MAX; - - ArgInfo(ArrayRef Regs, Type *Ty, unsigned OrigIndex, - ArrayRef Flags = ArrayRef(), - bool IsFixed = true, const Value *OrigValue = nullptr) - : BaseArgInfo(Ty, Flags, IsFixed), Regs(Regs.begin(), Regs.end()), - OrigValue(OrigValue), OrigArgIndex(OrigIndex) { - if (!Regs.empty() && Flags.empty()) - this->Flags.push_back(ISD::ArgFlagsTy()); - // FIXME: We should have just one way of saying "no register". - assert(((Ty->isVoidTy() || Ty->isEmptyTy()) == - (Regs.empty() || Regs[0] == 0)) && - "only void types should have no register"); - } - - ArgInfo(ArrayRef Regs, const Value &OrigValue, unsigned OrigIndex, - ArrayRef Flags = ArrayRef(), - bool IsFixed = true) - : ArgInfo(Regs, OrigValue.getType(), OrigIndex, Flags, IsFixed, &OrigValue) {} - - ArgInfo() = default; - }; - - struct CallLoweringInfo { - /// Calling convention to be used for the call. - CallingConv::ID CallConv = CallingConv::C; - - /// Destination of the call. It should be either a register, globaladdress, - /// or externalsymbol. - MachineOperand Callee = MachineOperand::CreateImm(0); - - /// Descriptor for the return type of the function. - ArgInfo OrigRet; - - /// List of descriptors of the arguments passed to the function. - SmallVector OrigArgs; - - /// Valid if the call has a swifterror inout parameter, and contains the - /// vreg that the swifterror should be copied into after the call. - Register SwiftErrorVReg; - - /// Original IR callsite corresponding to this call, if available. - const CallBase *CB = nullptr; - - MDNode *KnownCallees = nullptr; - - /// True if the call must be tail call optimized. - bool IsMustTailCall = false; - - /// True if the call passes all target-independent checks for tail call - /// optimization. - bool IsTailCall = false; - - /// True if the call was lowered as a tail call. This is consumed by the - /// legalizer. This allows the legalizer to lower libcalls as tail calls. - bool LoweredTailCall = false; - - /// True if the call is to a vararg function. - bool IsVarArg = false; - - /// True if the function's return value can be lowered to registers. - bool CanLowerReturn = true; - - /// VReg to hold the hidden sret parameter. - Register DemoteRegister; - - /// The stack index for sret demotion. - int DemoteStackIndex; - }; - - /// Argument handling is mostly uniform between the four places that - /// make these decisions: function formal arguments, call - /// instruction args, call instruction returns and function - /// returns. However, once a decision has been made on where an - /// argument should go, exactly what happens can vary slightly. This - /// class abstracts the differences. - /// - /// ValueAssigner should not depend on any specific function state, and - /// only determine the types and locations for arguments. - struct ValueAssigner { - ValueAssigner(bool IsIncoming, CCAssignFn *AssignFn_, - CCAssignFn *AssignFnVarArg_ = nullptr) - : AssignFn(AssignFn_), AssignFnVarArg(AssignFnVarArg_), - IsIncomingArgumentHandler(IsIncoming) { - - // Some targets change the handler depending on whether the call is - // varargs or not. If - if (!AssignFnVarArg) - AssignFnVarArg = AssignFn; - } - - virtual ~ValueAssigner() = default; - - /// Returns true if the handler is dealing with incoming arguments, - /// i.e. those that move values from some physical location to vregs. - bool isIncomingArgumentHandler() const { - return IsIncomingArgumentHandler; - } - - /// Wrap call to (typically tablegenerated CCAssignFn). This may be - /// overridden to track additional state information as arguments are - /// assigned or apply target specific hacks around the legacy - /// infrastructure. - virtual bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, const ArgInfo &Info, - ISD::ArgFlagsTy Flags, CCState &State) { - if (getAssignFn(State.isVarArg())(ValNo, ValVT, LocVT, LocInfo, Flags, - State)) - return true; - StackOffset = State.getNextStackOffset(); - return false; - } - - /// Assignment function to use for a general call. - CCAssignFn *AssignFn; - - /// Assignment function to use for a variadic call. This is usually the same - /// as AssignFn on most targets. - CCAssignFn *AssignFnVarArg; - - /// Stack offset for next argument. At the end of argument evaluation, this - /// is typically the total stack size. - uint64_t StackOffset = 0; - - /// Select the appropriate assignment function depending on whether this is - /// a variadic call. - CCAssignFn *getAssignFn(bool IsVarArg) const { - return IsVarArg ? AssignFnVarArg : AssignFn; - } - - private: - const bool IsIncomingArgumentHandler; - virtual void anchor(); - }; - - struct IncomingValueAssigner : public ValueAssigner { - IncomingValueAssigner(CCAssignFn *AssignFn_, - CCAssignFn *AssignFnVarArg_ = nullptr) - : ValueAssigner(true, AssignFn_, AssignFnVarArg_) {} - }; - - struct OutgoingValueAssigner : public ValueAssigner { - OutgoingValueAssigner(CCAssignFn *AssignFn_, - CCAssignFn *AssignFnVarArg_ = nullptr) - : ValueAssigner(false, AssignFn_, AssignFnVarArg_) {} - }; - - struct ValueHandler { - MachineIRBuilder &MIRBuilder; - MachineRegisterInfo &MRI; - const bool IsIncomingArgumentHandler; - - ValueHandler(bool IsIncoming, MachineIRBuilder &MIRBuilder, - MachineRegisterInfo &MRI) - : MIRBuilder(MIRBuilder), MRI(MRI), - IsIncomingArgumentHandler(IsIncoming) {} - - virtual ~ValueHandler() = default; - - /// Returns true if the handler is dealing with incoming arguments, - /// i.e. those that move values from some physical location to vregs. - bool isIncomingArgumentHandler() const { - return IsIncomingArgumentHandler; - } - - /// Materialize a VReg containing the address of the specified - /// stack-based object. This is either based on a FrameIndex or - /// direct SP manipulation, depending on the context. \p MPO - /// should be initialized to an appropriate description of the - /// address created. - virtual Register getStackAddress(uint64_t MemSize, int64_t Offset, - MachinePointerInfo &MPO, - ISD::ArgFlagsTy Flags) = 0; - - /// Return the in-memory size to write for the argument at \p VA. This may - /// be smaller than the allocated stack slot size. - /// - /// This is overridable primarily for targets to maintain compatibility with - /// hacks around the existing DAG call lowering infrastructure. - virtual LLT getStackValueStoreType(const DataLayout &DL, - const CCValAssign &VA, - ISD::ArgFlagsTy Flags) const; - - /// The specified value has been assigned to a physical register, - /// handle the appropriate COPY (either to or from) and mark any - /// relevant uses/defines as needed. - virtual void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) = 0; - - /// The specified value has been assigned to a stack - /// location. Load or store it there, with appropriate extension - /// if necessary. - virtual void assignValueToAddress(Register ValVReg, Register Addr, - LLT MemTy, MachinePointerInfo &MPO, - CCValAssign &VA) = 0; - - /// An overload which takes an ArgInfo if additional information about the - /// arg is needed. \p ValRegIndex is the index in \p Arg.Regs for the value - /// to store. - virtual void assignValueToAddress(const ArgInfo &Arg, unsigned ValRegIndex, - Register Addr, LLT MemTy, - MachinePointerInfo &MPO, - CCValAssign &VA) { - assignValueToAddress(Arg.Regs[ValRegIndex], Addr, MemTy, MPO, VA); - } - - /// Handle custom values, which may be passed into one or more of \p VAs. - /// \p If the handler wants the assignments to be delayed until after - /// mem loc assignments, then it sets \p Thunk to the thunk to do the - /// assignment. - /// \return The number of \p VAs that have been assigned after the first - /// one, and which should therefore be skipped from further - /// processing. - virtual unsigned assignCustomValue(ArgInfo &Arg, ArrayRef VAs, - std::function *Thunk = nullptr) { - // This is not a pure virtual method because not all targets need to worry - // about custom values. - llvm_unreachable("Custom values not supported"); - } - - /// Do a memory copy of \p MemSize bytes from \p SrcPtr to \p DstPtr. This - /// is necessary for outgoing stack-passed byval arguments. - void - copyArgumentMemory(const ArgInfo &Arg, Register DstPtr, Register SrcPtr, - const MachinePointerInfo &DstPtrInfo, Align DstAlign, - const MachinePointerInfo &SrcPtrInfo, Align SrcAlign, - uint64_t MemSize, CCValAssign &VA) const; - - /// Extend a register to the location type given in VA, capped at extending - /// to at most MaxSize bits. If MaxSizeBits is 0 then no maximum is set. - Register extendRegister(Register ValReg, CCValAssign &VA, - unsigned MaxSizeBits = 0); - }; - - /// Base class for ValueHandlers used for arguments coming into the current - /// function, or for return values received from a call. - struct IncomingValueHandler : public ValueHandler { - IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : ValueHandler(/*IsIncoming*/ true, MIRBuilder, MRI) {} - - /// Insert G_ASSERT_ZEXT/G_ASSERT_SEXT or other hint instruction based on \p - /// VA, returning the new register if a hint was inserted. - Register buildExtensionHint(CCValAssign &VA, Register SrcReg, LLT NarrowTy); - - /// Provides a default implementation for argument handling. - void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) override; - }; - - /// Base class for ValueHandlers used for arguments passed to a function call, - /// or for return values. - struct OutgoingValueHandler : public ValueHandler { - OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : ValueHandler(/*IsIncoming*/ false, MIRBuilder, MRI) {} - }; - -protected: - /// Getter for generic TargetLowering class. - const TargetLowering *getTLI() const { - return TLI; - } - - /// Getter for target specific TargetLowering class. - template - const XXXTargetLowering *getTLI() const { - return static_cast(TLI); - } - - /// \returns Flags corresponding to the attributes on the \p ArgIdx-th - /// parameter of \p Call. - ISD::ArgFlagsTy getAttributesForArgIdx(const CallBase &Call, - unsigned ArgIdx) const; - - /// Adds flags to \p Flags based off of the attributes in \p Attrs. - /// \p OpIdx is the index in \p Attrs to add flags from. - void addArgFlagsFromAttributes(ISD::ArgFlagsTy &Flags, - const AttributeList &Attrs, - unsigned OpIdx) const; - - template - void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, - const FuncInfoTy &FuncInfo) const; - - /// Break \p OrigArgInfo into one or more pieces the calling convention can - /// process, returned in \p SplitArgs. For example, this should break structs - /// down into individual fields. - /// - /// If \p Offsets is non-null, it points to a vector to be filled in - /// with the in-memory offsets of each of the individual values. - void splitToValueTypes(const ArgInfo &OrigArgInfo, - SmallVectorImpl &SplitArgs, - const DataLayout &DL, CallingConv::ID CallConv, - SmallVectorImpl *Offsets = nullptr) const; - - /// Analyze the argument list in \p Args, using \p Assigner to populate \p - /// CCInfo. This will determine the types and locations to use for passed or - /// returned values. This may resize fields in \p Args if the value is split - /// across multiple registers or stack slots. - /// - /// This is independent of the function state and can be used - /// to determine how a call would pass arguments without needing to change the - /// function. This can be used to check if arguments are suitable for tail - /// call lowering. - /// - /// \return True if everything has succeeded, false otherwise. - bool determineAssignments(ValueAssigner &Assigner, - SmallVectorImpl &Args, - CCState &CCInfo) const; - - /// Invoke ValueAssigner::assignArg on each of the given \p Args and then use - /// \p Handler to move them to the assigned locations. - /// - /// \return True if everything has succeeded, false otherwise. - bool - determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, - SmallVectorImpl &Args, - MachineIRBuilder &MIRBuilder, - CallingConv::ID CallConv, bool IsVarArg, - ArrayRef ThisReturnRegs = None) const; - - /// Use \p Handler to insert code to handle the argument/return values - /// represented by \p Args. It's expected determineAssignments previously - /// processed these arguments to populate \p CCState and \p ArgLocs. - bool handleAssignments(ValueHandler &Handler, SmallVectorImpl &Args, - CCState &CCState, - SmallVectorImpl &ArgLocs, - MachineIRBuilder &MIRBuilder, - ArrayRef ThisReturnRegs = None) const; - - /// Check whether parameters to a call that are passed in callee saved - /// registers are the same as from the calling function. This needs to be - /// checked for tail call eligibility. - bool parametersInCSRMatch(const MachineRegisterInfo &MRI, - const uint32_t *CallerPreservedMask, - const SmallVectorImpl &ArgLocs, - const SmallVectorImpl &OutVals) const; - - /// \returns True if the calling convention for a callee and its caller pass - /// results in the same way. Typically used for tail call eligibility checks. - /// - /// \p Info is the CallLoweringInfo for the call. - /// \p MF is the MachineFunction for the caller. - /// \p InArgs contains the results of the call. - /// \p CalleeAssigner specifies the target's handling of the argument types - /// for the callee. - /// \p CallerAssigner specifies the target's handling of the - /// argument types for the caller. - bool resultsCompatible(CallLoweringInfo &Info, MachineFunction &MF, - SmallVectorImpl &InArgs, - ValueAssigner &CalleeAssigner, - ValueAssigner &CallerAssigner) const; - -public: - CallLowering(const TargetLowering *TLI) : TLI(TLI) {} - virtual ~CallLowering() = default; - - /// \return true if the target is capable of handling swifterror values that - /// have been promoted to a specified register. The extended versions of - /// lowerReturn and lowerCall should be implemented. - virtual bool supportSwiftError() const { - return false; - } - - /// Load the returned value from the stack into virtual registers in \p VRegs. - /// It uses the frame index \p FI and the start offset from \p DemoteReg. - /// The loaded data size will be determined from \p RetTy. - void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy, - ArrayRef VRegs, Register DemoteReg, - int FI) const; - - /// Store the return value given by \p VRegs into stack starting at the offset - /// specified in \p DemoteReg. - void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, - ArrayRef VRegs, Register DemoteReg) const; - - /// Insert the hidden sret ArgInfo to the beginning of \p SplitArgs. - /// This function should be called from the target specific - /// lowerFormalArguments when \p F requires the sret demotion. - void insertSRetIncomingArgument(const Function &F, - SmallVectorImpl &SplitArgs, - Register &DemoteReg, MachineRegisterInfo &MRI, - const DataLayout &DL) const; - - /// For the call-base described by \p CB, insert the hidden sret ArgInfo to - /// the OrigArgs field of \p Info. - void insertSRetOutgoingArgument(MachineIRBuilder &MIRBuilder, - const CallBase &CB, - CallLoweringInfo &Info) const; - - /// \return True if the return type described by \p Outs can be returned - /// without performing sret demotion. - bool checkReturn(CCState &CCInfo, SmallVectorImpl &Outs, - CCAssignFn *Fn) const; - - /// Get the type and the ArgFlags for the split components of \p RetTy as - /// returned by \c ComputeValueVTs. - void getReturnInfo(CallingConv::ID CallConv, Type *RetTy, AttributeList Attrs, - SmallVectorImpl &Outs, - const DataLayout &DL) const; - - /// Toplevel function to check the return type based on the target calling - /// convention. \return True if the return value of \p MF can be returned - /// without performing sret demotion. - bool checkReturnTypeForCallConv(MachineFunction &MF) const; - - /// This hook must be implemented to check whether the return values - /// described by \p Outs can fit into the return registers. If false - /// is returned, an sret-demotion is performed. - virtual bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, - SmallVectorImpl &Outs, - bool IsVarArg) const { - return true; - } - - /// This hook must be implemented to lower outgoing return values, described - /// by \p Val, into the specified virtual registers \p VRegs. - /// This hook is used by GlobalISel. - /// - /// \p FLI is required for sret demotion. - /// - /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter - /// that needs to be implicitly returned. - /// - /// \return True if the lowering succeeds, false otherwise. - virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs, FunctionLoweringInfo &FLI, - Register SwiftErrorVReg) const { - if (!supportSwiftError()) { - assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); - return lowerReturn(MIRBuilder, Val, VRegs, FLI); - } - return false; - } - - /// This hook behaves as the extended lowerReturn function, but for targets - /// that do not support swifterror value promotion. - virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs, - FunctionLoweringInfo &FLI) const { - return false; - } - - virtual bool fallBackToDAGISel(const MachineFunction &MF) const { - return false; - } - - /// This hook must be implemented to lower the incoming (formal) - /// arguments, described by \p VRegs, for GlobalISel. Each argument - /// must end up in the related virtual registers described by \p VRegs. - /// In other words, the first argument should end up in \c VRegs[0], - /// the second in \c VRegs[1], and so on. For each argument, there will be one - /// register for each non-aggregate type, as returned by \c computeValueLLTs. - /// \p MIRBuilder is set to the proper insertion for the argument - /// lowering. \p FLI is required for sret demotion. - /// - /// \return True if the lowering succeeded, false otherwise. - virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, - const Function &F, - ArrayRef> VRegs, - FunctionLoweringInfo &FLI) const { - return false; - } - - /// This hook must be implemented to lower the given call instruction, - /// including argument and return value marshalling. - /// - /// - /// \return true if the lowering succeeded, false otherwise. - virtual bool lowerCall(MachineIRBuilder &MIRBuilder, - CallLoweringInfo &Info) const { - return false; - } - - /// Lower the given call instruction, including argument and return value - /// marshalling. - /// - /// \p CI is the call/invoke instruction. - /// - /// \p ResRegs are the registers where the call's return value should be - /// stored (or 0 if there is no return value). There will be one register for - /// each non-aggregate type, as returned by \c computeValueLLTs. - /// - /// \p ArgRegs is a list of lists of virtual registers containing each - /// argument that needs to be passed (argument \c i should be placed in \c - /// ArgRegs[i]). For each argument, there will be one register for each - /// non-aggregate type, as returned by \c computeValueLLTs. - /// - /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout - /// parameter, and contains the vreg that the swifterror should be copied into - /// after the call. - /// - /// \p GetCalleeReg is a callback to materialize a register for the callee if - /// the target determines it cannot jump to the destination based purely on \p - /// CI. This might be because \p CI is indirect, or because of the limited - /// range of an immediate jump. - /// - /// \return true if the lowering succeeded, false otherwise. - bool lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &Call, - ArrayRef ResRegs, - ArrayRef> ArgRegs, Register SwiftErrorVReg, - std::function GetCalleeReg) const; - - /// For targets which want to use big-endian can enable it with - /// enableBigEndian() hook - virtual bool enableBigEndian() const { return false; } - - /// For targets which support the "returned" parameter attribute, returns - /// true if the given type is a valid one to use with "returned". - virtual bool isTypeIsValidForThisReturn(EVT Ty) const { return false; } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Combiner.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Combiner.h deleted file mode 100644 index 7956869808..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Combiner.h +++ /dev/null @@ -1,46 +0,0 @@ -//== ----- llvm/CodeGen/GlobalISel/Combiner.h -------------------*- C++ -*-== // -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This contains common code to drive combines. Combiner Passes will need to -/// setup a CombinerInfo and call combineMachineFunction. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H -#define LLVM_CODEGEN_GLOBALISEL_COMBINER_H - -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { -class MachineRegisterInfo; -class CombinerInfo; -class GISelCSEInfo; -class TargetPassConfig; -class MachineFunction; - -class Combiner { -public: - Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC); - - /// If CSEInfo is not null, then the Combiner will setup observer for - /// CSEInfo and instantiate a CSEMIRBuilder. Pass nullptr if CSE is not - /// needed. - bool combineMachineInstrs(MachineFunction &MF, GISelCSEInfo *CSEInfo); - -protected: - CombinerInfo &CInfo; - - MachineRegisterInfo *MRI = nullptr; - const TargetPassConfig *TPC; - std::unique_ptr Builder; -}; - -} // End namespace llvm. - -#endif // LLVM_CODEGEN_GLOBALISEL_COMBINER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerHelper.h deleted file mode 100644 index 45c27c25ae..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ /dev/null @@ -1,753 +0,0 @@ -//===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===--------------------------------------------------------------------===// -/// \file -/// This contains common combine transformations that may be used in a combine -/// pass,or by the target elsewhere. -/// Targets can pick individual opcode transformations from the helper or use -/// tryCombine which invokes all transformations. All of the transformations -/// return true if the MachineInstruction changed and false otherwise. -/// -//===--------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H -#define LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" -#include "llvm/CodeGen/LowLevelType.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/Alignment.h" - -namespace llvm { - -class GISelChangeObserver; -class MachineIRBuilder; -class MachineInstrBuilder; -class MachineRegisterInfo; -class MachineInstr; -class MachineOperand; -class GISelKnownBits; -class MachineDominatorTree; -class LegalizerInfo; -struct LegalityQuery; -class RegisterBank; -class RegisterBankInfo; -class TargetLowering; -class TargetRegisterInfo; - -struct PreferredTuple { - LLT Ty; // The result type of the extend. - unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT - MachineInstr *MI; -}; - -struct IndexedLoadStoreMatchInfo { - Register Addr; - Register Base; - Register Offset; - bool IsPre; -}; - -struct PtrAddChain { - int64_t Imm; - Register Base; - const RegisterBank *Bank; -}; - -struct RegisterImmPair { - Register Reg; - int64_t Imm; -}; - -struct ShiftOfShiftedLogic { - MachineInstr *Logic; - MachineInstr *Shift2; - Register LogicNonShiftReg; - uint64_t ValSum; -}; - -using BuildFnTy = std::function; - -struct MergeTruncStoresInfo { - SmallVector FoundStores; - GStore *LowestIdxStore = nullptr; - Register WideSrcVal; - bool NeedBSwap = false; - bool NeedRotate = false; -}; - -using OperandBuildSteps = - SmallVector, 4>; -struct InstructionBuildSteps { - unsigned Opcode = 0; /// The opcode for the produced instruction. - OperandBuildSteps OperandFns; /// Operands to be added to the instruction. - InstructionBuildSteps() = default; - InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns) - : Opcode(Opcode), OperandFns(OperandFns) {} -}; - -struct InstructionStepsMatchInfo { - /// Describes instructions to be built during a combine. - SmallVector InstrsToBuild; - InstructionStepsMatchInfo() = default; - InstructionStepsMatchInfo( - std::initializer_list InstrsToBuild) - : InstrsToBuild(InstrsToBuild) {} -}; - -class CombinerHelper { -protected: - MachineIRBuilder &Builder; - MachineRegisterInfo &MRI; - GISelChangeObserver &Observer; - GISelKnownBits *KB; - MachineDominatorTree *MDT; - const LegalizerInfo *LI; - const RegisterBankInfo *RBI; - const TargetRegisterInfo *TRI; - -public: - CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, - GISelKnownBits *KB = nullptr, - MachineDominatorTree *MDT = nullptr, - const LegalizerInfo *LI = nullptr); - - GISelKnownBits *getKnownBits() const { - return KB; - } - - const TargetLowering &getTargetLowering() const; - - /// \return true if the combine is running prior to legalization, or if \p - /// Query is legal on the target. - bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const; - - /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes - void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const; - - /// Replace a single register operand with a new register and inform the - /// observer of the changes. - void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, - Register ToReg) const; - - /// Replace the opcode in instruction with a new opcode and inform the - /// observer of the changes. - void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const; - - /// Get the register bank of \p Reg. - /// If Reg has not been assigned a register, a register class, - /// or a register bank, then this returns nullptr. - /// - /// \pre Reg.isValid() - const RegisterBank *getRegBank(Register Reg) const; - - /// Set the register bank of \p Reg. - /// Does nothing if the RegBank is null. - /// This is the counterpart to getRegBank. - void setRegBank(Register Reg, const RegisterBank *RegBank); - - /// If \p MI is COPY, try to combine it. - /// Returns true if MI changed. - bool tryCombineCopy(MachineInstr &MI); - bool matchCombineCopy(MachineInstr &MI); - void applyCombineCopy(MachineInstr &MI); - - /// Returns true if \p DefMI precedes \p UseMI or they are the same - /// instruction. Both must be in the same basic block. - bool isPredecessor(const MachineInstr &DefMI, const MachineInstr &UseMI); - - /// Returns true if \p DefMI dominates \p UseMI. By definition an - /// instruction dominates itself. - /// - /// If we haven't been provided with a MachineDominatorTree during - /// construction, this function returns a conservative result that tracks just - /// a single basic block. - bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI); - - /// If \p MI is extend that consumes the result of a load, try to combine it. - /// Returns true if MI changed. - bool tryCombineExtendingLoads(MachineInstr &MI); - bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); - void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); - - /// Match (and (load x), mask) -> zextload x - bool matchCombineLoadWithAndMask(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Combine \p MI into a pre-indexed or post-indexed load/store operation if - /// legal and the surrounding code makes it useful. - bool tryCombineIndexedLoadStore(MachineInstr &MI); - bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); - void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); - - bool matchSextTruncSextLoad(MachineInstr &MI); - void applySextTruncSextLoad(MachineInstr &MI); - - /// Match sext_inreg(load p), imm -> sextload p - bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple &MatchInfo); - void applySextInRegOfLoad(MachineInstr &MI, std::tuple &MatchInfo); - - /// Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM - /// when their source operands are identical. - bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI); - void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI); - - /// If a brcond's true block is not the fallthrough, make it so by inverting - /// the condition and swapping operands. - bool matchOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond); - void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond); - - /// If \p MI is G_CONCAT_VECTORS, try to combine it. - /// Returns true if MI changed. - /// Right now, we support: - /// - concat_vector(undef, undef) => undef - /// - concat_vector(build_vector(A, B), build_vector(C, D)) => - /// build_vector(A, B, C, D) - /// - /// \pre MI.getOpcode() == G_CONCAT_VECTORS. - bool tryCombineConcatVectors(MachineInstr &MI); - /// Check if the G_CONCAT_VECTORS \p MI is undef or if it - /// can be flattened into a build_vector. - /// In the first case \p IsUndef will be true. - /// In the second case \p Ops will contain the operands needed - /// to produce the flattened build_vector. - /// - /// \pre MI.getOpcode() == G_CONCAT_VECTORS. - bool matchCombineConcatVectors(MachineInstr &MI, bool &IsUndef, - SmallVectorImpl &Ops); - /// Replace \p MI with a flattened build_vector with \p Ops or an - /// implicit_def if IsUndef is true. - void applyCombineConcatVectors(MachineInstr &MI, bool IsUndef, - const ArrayRef Ops); - - /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS. - /// Returns true if MI changed. - /// - /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR. - bool tryCombineShuffleVector(MachineInstr &MI); - /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a - /// concat_vectors. - /// \p Ops will contain the operands needed to produce the flattened - /// concat_vectors. - /// - /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR. - bool matchCombineShuffleVector(MachineInstr &MI, - SmallVectorImpl &Ops); - /// Replace \p MI with a concat_vectors with \p Ops. - void applyCombineShuffleVector(MachineInstr &MI, - const ArrayRef Ops); - - /// Optimize memcpy intrinsics et al, e.g. constant len calls. - /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline. - /// - /// For example (pre-indexed): - /// - /// $addr = G_PTR_ADD $base, $offset - /// [...] - /// $val = G_LOAD $addr - /// [...] - /// $whatever = COPY $addr - /// - /// --> - /// - /// $val, $addr = G_INDEXED_LOAD $base, $offset, 1 (IsPre) - /// [...] - /// $whatever = COPY $addr - /// - /// or (post-indexed): - /// - /// G_STORE $val, $base - /// [...] - /// $addr = G_PTR_ADD $base, $offset - /// [...] - /// $whatever = COPY $addr - /// - /// --> - /// - /// $addr = G_INDEXED_STORE $val, $base, $offset - /// [...] - /// $whatever = COPY $addr - bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0); - - bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); - void applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); - - /// Fold (shift (shift base, x), y) -> (shift base (x+y)) - bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); - void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); - - /// If we have a shift-by-constant of a bitwise logic op that itself has a - /// shift-by-constant operand with identical opcode, we may be able to convert - /// that into 2 independent shifts followed by the logic op. - bool matchShiftOfShiftedLogic(MachineInstr &MI, - ShiftOfShiftedLogic &MatchInfo); - void applyShiftOfShiftedLogic(MachineInstr &MI, - ShiftOfShiftedLogic &MatchInfo); - - /// Transform a multiply by a power-of-2 value to a left shift. - bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); - void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); - - // Transform a G_SHL with an extended source into a narrower shift if - // possible. - bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData); - void applyCombineShlOfExtend(MachineInstr &MI, - const RegisterImmPair &MatchData); - - /// Fold away a merge of an unmerge of the corresponding values. - bool matchCombineMergeUnmerge(MachineInstr &MI, Register &MatchInfo); - - /// Reduce a shift by a constant to an unmerge and a shift on a half sized - /// type. This will not produce a shift smaller than \p TargetShiftSize. - bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, - unsigned &ShiftVal); - void applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal); - bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount); - - /// Transform G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z. - bool - matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, - SmallVectorImpl &Operands); - void - applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, - SmallVectorImpl &Operands); - - /// Transform G_UNMERGE Constant -> Constant1, Constant2, ... - bool matchCombineUnmergeConstant(MachineInstr &MI, - SmallVectorImpl &Csts); - void applyCombineUnmergeConstant(MachineInstr &MI, - SmallVectorImpl &Csts); - - /// Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ... - bool - matchCombineUnmergeUndef(MachineInstr &MI, - std::function &MatchInfo); - - /// Transform X, Y = G_UNMERGE Z -> X = G_TRUNC Z. - bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); - void applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); - - /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0 - bool matchCombineUnmergeZExtToZExt(MachineInstr &MI); - void applyCombineUnmergeZExtToZExt(MachineInstr &MI); - - /// Transform fp_instr(cst) to constant result of the fp operation. - bool matchCombineConstantFoldFpUnary(MachineInstr &MI, - Optional &Cst); - void applyCombineConstantFoldFpUnary(MachineInstr &MI, - Optional &Cst); - - /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space. - bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg); - void applyCombineI2PToP2I(MachineInstr &MI, Register &Reg); - - /// Transform PtrToInt(IntToPtr(x)) to x. - bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg); - void applyCombineP2IToI2P(MachineInstr &MI, Register &Reg); - - /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y) - /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y) - bool matchCombineAddP2IToPtrAdd(MachineInstr &MI, - std::pair &PtrRegAndCommute); - void applyCombineAddP2IToPtrAdd(MachineInstr &MI, - std::pair &PtrRegAndCommute); - - // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2 - bool matchCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst); - void applyCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst); - - /// Transform anyext(trunc(x)) to x. - bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); - void applyCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); - - /// Transform zext(trunc(x)) to x. - bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg); - - /// Transform [asz]ext([asz]ext(x)) to [asz]ext x. - bool matchCombineExtOfExt(MachineInstr &MI, - std::tuple &MatchInfo); - void applyCombineExtOfExt(MachineInstr &MI, - std::tuple &MatchInfo); - - /// Transform fneg(fneg(x)) to x. - bool matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg); - - /// Match fabs(fabs(x)) to fabs(x). - bool matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); - void applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); - - /// Transform fabs(fneg(x)) to fabs(x). - bool matchCombineFAbsOfFNeg(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x). - bool matchCombineTruncOfExt(MachineInstr &MI, - std::pair &MatchInfo); - void applyCombineTruncOfExt(MachineInstr &MI, - std::pair &MatchInfo); - - /// Transform trunc (shl x, K) to shl (trunc x), - /// K => K < VT.getScalarSizeInBits(). - bool matchCombineTruncOfShl(MachineInstr &MI, - std::pair &MatchInfo); - void applyCombineTruncOfShl(MachineInstr &MI, - std::pair &MatchInfo); - - /// Transform G_MUL(x, -1) to G_SUB(0, x) - void applyCombineMulByNegativeOne(MachineInstr &MI); - - /// Return true if any explicit use operand on \p MI is defined by a - /// G_IMPLICIT_DEF. - bool matchAnyExplicitUseIsUndef(MachineInstr &MI); - - /// Return true if all register explicit use operands on \p MI are defined by - /// a G_IMPLICIT_DEF. - bool matchAllExplicitUsesAreUndef(MachineInstr &MI); - - /// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask. - bool matchUndefShuffleVectorMask(MachineInstr &MI); - - /// Return true if a G_STORE instruction \p MI is storing an undef value. - bool matchUndefStore(MachineInstr &MI); - - /// Return true if a G_SELECT instruction \p MI has an undef comparison. - bool matchUndefSelectCmp(MachineInstr &MI); - - /// Return true if a G_SELECT instruction \p MI has a constant comparison. If - /// true, \p OpIdx will store the operand index of the known selected value. - bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx); - - /// Replace an instruction with a G_FCONSTANT with value \p C. - bool replaceInstWithFConstant(MachineInstr &MI, double C); - - /// Replace an instruction with a G_CONSTANT with value \p C. - bool replaceInstWithConstant(MachineInstr &MI, int64_t C); - - /// Replace an instruction with a G_CONSTANT with value \p C. - bool replaceInstWithConstant(MachineInstr &MI, APInt C); - - /// Replace an instruction with a G_IMPLICIT_DEF. - bool replaceInstWithUndef(MachineInstr &MI); - - /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand. - bool replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx); - - /// Delete \p MI and replace all of its uses with \p Replacement. - bool replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement); - - /// Return true if \p MOP1 and \p MOP2 are register operands are defined by - /// equivalent instructions. - bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2); - - /// Return true if \p MOP is defined by a G_CONSTANT with a value equal to - /// \p C. - bool matchConstantOp(const MachineOperand &MOP, int64_t C); - - /// Optimize (cond ? x : x) -> x - bool matchSelectSameVal(MachineInstr &MI); - - /// Optimize (x op x) -> x - bool matchBinOpSameVal(MachineInstr &MI); - - /// Check if operand \p OpIdx is zero. - bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx); - - /// Check if operand \p OpIdx is undef. - bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx); - - /// Check if operand \p OpIdx is known to be a power of 2. - bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, unsigned OpIdx); - - /// Erase \p MI - bool eraseInst(MachineInstr &MI); - - /// Return true if MI is a G_ADD which can be simplified to a G_SUB. - bool matchSimplifyAddToSub(MachineInstr &MI, - std::tuple &MatchInfo); - void applySimplifyAddToSub(MachineInstr &MI, - std::tuple &MatchInfo); - - /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) - bool - matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, - InstructionStepsMatchInfo &MatchInfo); - - /// Replace \p MI with a series of instructions described in \p MatchInfo. - void applyBuildInstructionSteps(MachineInstr &MI, - InstructionStepsMatchInfo &MatchInfo); - - /// Match ashr (shl x, C), C -> sext_inreg (C) - bool matchAshrShlToSextInreg(MachineInstr &MI, - std::tuple &MatchInfo); - void applyAshShlToSextInreg(MachineInstr &MI, - std::tuple &MatchInfo); - - /// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0 - bool matchOverlappingAnd(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// \return true if \p MI is a G_AND instruction whose operands are x and y - /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.) - /// - /// \param [in] MI - The G_AND instruction. - /// \param [out] Replacement - A register the G_AND should be replaced with on - /// success. - bool matchRedundantAnd(MachineInstr &MI, Register &Replacement); - - /// \return true if \p MI is a G_OR instruction whose operands are x and y - /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros - /// value.) - /// - /// \param [in] MI - The G_OR instruction. - /// \param [out] Replacement - A register the G_OR should be replaced with on - /// success. - bool matchRedundantOr(MachineInstr &MI, Register &Replacement); - - /// \return true if \p MI is a G_SEXT_INREG that can be erased. - bool matchRedundantSExtInReg(MachineInstr &MI); - - /// Combine inverting a result of a compare into the opposite cond code. - bool matchNotCmp(MachineInstr &MI, SmallVectorImpl &RegsToNegate); - void applyNotCmp(MachineInstr &MI, SmallVectorImpl &RegsToNegate); - - /// Fold (xor (and x, y), y) -> (and (not x), y) - ///{ - bool matchXorOfAndWithSameReg(MachineInstr &MI, - std::pair &MatchInfo); - void applyXorOfAndWithSameReg(MachineInstr &MI, - std::pair &MatchInfo); - ///} - - /// Combine G_PTR_ADD with nullptr to G_INTTOPTR - bool matchPtrAddZero(MachineInstr &MI); - void applyPtrAddZero(MachineInstr &MI); - - /// Combine G_UREM x, (known power of 2) to an add and bitmasking. - void applySimplifyURemByPow2(MachineInstr &MI); - - bool matchCombineInsertVecElts(MachineInstr &MI, - SmallVectorImpl &MatchInfo); - - void applyCombineInsertVecElts(MachineInstr &MI, - SmallVectorImpl &MatchInfo); - - /// Match expression trees of the form - /// - /// \code - /// sN *a = ... - /// sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ... - /// \endcode - /// - /// And check if the tree can be replaced with a M-bit load + possibly a - /// bswap. - bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo); - - bool matchTruncStoreMerge(MachineInstr &MI, MergeTruncStoresInfo &MatchInfo); - void applyTruncStoreMerge(MachineInstr &MI, MergeTruncStoresInfo &MatchInfo); - - bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI); - void applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI); - - bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg); - void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg); - - bool matchExtractAllEltsFromBuildVector( - MachineInstr &MI, - SmallVectorImpl> &MatchInfo); - void applyExtractAllEltsFromBuildVector( - MachineInstr &MI, - SmallVectorImpl> &MatchInfo); - - /// Use a function which takes in a MachineIRBuilder to perform a combine. - /// By default, it erases the instruction \p MI from the function. - void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Use a function which takes in a MachineIRBuilder to perform a combine. - /// This variant does not erase \p MI after calling the build function. - void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo); - - bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo); - bool matchFunnelShiftToRotate(MachineInstr &MI); - void applyFunnelShiftToRotate(MachineInstr &MI); - bool matchRotateOutOfRange(MachineInstr &MI); - void applyRotateOutOfRange(MachineInstr &MI); - - /// \returns true if a G_ICMP instruction \p MI can be replaced with a true - /// or false constant based off of KnownBits information. - bool matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo); - - /// \returns true if a G_ICMP \p MI can be replaced with its LHS based off of - /// KnownBits information. - bool - matchICmpToLHSKnownBits(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// \returns true if (and (or x, c1), c2) can be replaced with (and x, c2) - bool matchAndOrDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo); - - bool matchBitfieldExtractFromSExtInReg(MachineInstr &MI, - BuildFnTy &MatchInfo); - /// Match: and (lshr x, cst), mask -> ubfx x, cst, width - bool matchBitfieldExtractFromAnd(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width - bool matchBitfieldExtractFromShr(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Match: shr (and x, n), k -> ubfx x, pos, width - bool matchBitfieldExtractFromShrAnd(MachineInstr &MI, BuildFnTy &MatchInfo); - - // Helpers for reassociation: - bool matchReassocConstantInnerRHS(GPtrAdd &MI, MachineInstr *RHS, - BuildFnTy &MatchInfo); - bool matchReassocFoldConstantsInSubTree(GPtrAdd &MI, MachineInstr *LHS, - MachineInstr *RHS, - BuildFnTy &MatchInfo); - bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS, - MachineInstr *RHS, BuildFnTy &MatchInfo); - /// Reassociate pointer calculations with G_ADD involved, to allow better - /// addressing mode usage. - bool matchReassocPtrAdd(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Do constant folding when opportunities are exposed after MIR building. - bool matchConstantFold(MachineInstr &MI, APInt &MatchInfo); - - /// \returns true if it is possible to narrow the width of a scalar binop - /// feeding a G_AND instruction \p MI. - bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Given an G_UDIV \p MI expressing a divide by constant, return an - /// expression that implements it by multiplying by a magic number. - /// Ref: "Hacker's Delight" or "The PowerPC Compiler Writer's Guide". - MachineInstr *buildUDivUsingMul(MachineInstr &MI); - /// Combine G_UDIV by constant into a multiply by magic constant. - bool matchUDivByConst(MachineInstr &MI); - void applyUDivByConst(MachineInstr &MI); - - // G_UMULH x, (1 << c)) -> x >> (bitwidth - c) - bool matchUMulHToLShr(MachineInstr &MI); - void applyUMulHToLShr(MachineInstr &MI); - - /// Try to transform \p MI by using all of the above - /// combine functions. Returns true if changed. - bool tryCombine(MachineInstr &MI); - - /// Emit loads and stores that perform the given memcpy. - /// Assumes \p MI is a G_MEMCPY_INLINE - /// TODO: implement dynamically sized inline memcpy, - /// and rename: s/bool tryEmit/void emit/ - bool tryEmitMemcpyInline(MachineInstr &MI); - - /// Match: - /// (G_UMULO x, 2) -> (G_UADDO x, x) - /// (G_SMULO x, 2) -> (G_SADDO x, x) - bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Transform (fadd x, fneg(y)) -> (fsub x, y) - /// (fadd fneg(x), y) -> (fsub y, x) - /// (fsub x, fneg(y)) -> (fadd x, y) - /// (fmul fneg(x), fneg(y)) -> (fmul x, y) - /// (fdiv fneg(x), fneg(y)) -> (fdiv x, y) - /// (fmad fneg(x), fneg(y), z) -> (fmad x, y, z) - /// (fma fneg(x), fneg(y), z) -> (fma x, y, z) - bool matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo); - - bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally, - bool &HasFMAD, bool &Aggressive, - bool CanReassociate = false); - - /// Transform (fadd (fmul x, y), z) -> (fma x, y, z) - /// (fadd (fmul x, y), z) -> (fmad x, y, z) - bool matchCombineFAddFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) - /// (fadd (fpext (fmul x, y)), z) -> (fmad (fpext x), (fpext y), z) - bool matchCombineFAddFpExtFMulToFMadOrFMA(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// Transform (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z)) - /// (fadd (fmad x, y, (fmul u, v)), z) -> (fmad x, y, (fmad u, v, z)) - bool matchCombineFAddFMAFMulToFMadOrFMA(MachineInstr &MI, - BuildFnTy &MatchInfo); - - // Transform (fadd (fma x, y, (fpext (fmul u, v))), z) - // -> (fma x, y, (fma (fpext u), (fpext v), z)) - // (fadd (fmad x, y, (fpext (fmul u, v))), z) - // -> (fmad x, y, (fmad (fpext u), (fpext v), z)) - bool matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// Transform (fsub (fmul x, y), z) -> (fma x, y, -z) - /// (fsub (fmul x, y), z) -> (fmad x, y, -z) - bool matchCombineFSubFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo); - - /// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) - /// (fsub (fneg (fmul, x, y)), z) -> (fmad (fneg x), y, (fneg z)) - bool matchCombineFSubFNegFMulToFMadOrFMA(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// Transform (fsub (fpext (fmul x, y)), z) - /// -> (fma (fpext x), (fpext y), (fneg z)) - /// (fsub (fpext (fmul x, y)), z) - /// -> (fmad (fpext x), (fpext y), (fneg z)) - bool matchCombineFSubFpExtFMulToFMadOrFMA(MachineInstr &MI, - BuildFnTy &MatchInfo); - - /// Transform (fsub (fpext (fneg (fmul x, y))), z) - /// -> (fneg (fma (fpext x), (fpext y), z)) - /// (fsub (fpext (fneg (fmul x, y))), z) - /// -> (fneg (fmad (fpext x), (fpext y), z)) - bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI, - BuildFnTy &MatchInfo); - -private: - /// Given a non-indexed load or store instruction \p MI, find an offset that - /// can be usefully and legally folded into it as a post-indexing operation. - /// - /// \returns true if a candidate is found. - bool findPostIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base, - Register &Offset); - - /// Given a non-indexed load or store instruction \p MI, find an offset that - /// can be usefully and legally folded into it as a pre-indexing operation. - /// - /// \returns true if a candidate is found. - bool findPreIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base, - Register &Offset); - - /// Helper function for matchLoadOrCombine. Searches for Registers - /// which may have been produced by a load instruction + some arithmetic. - /// - /// \param [in] Root - The search root. - /// - /// \returns The Registers found during the search. - Optional> - findCandidatesForLoadOrCombine(const MachineInstr *Root) const; - - /// Helper function for matchLoadOrCombine. - /// - /// Checks if every register in \p RegsToVisit is defined by a load - /// instruction + some arithmetic. - /// - /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up - /// at to the index of the load. - /// \param [in] MemSizeInBits - The number of bits each load should produce. - /// - /// \returns On success, a 3-tuple containing lowest-index load found, the - /// lowest index, and the last load in the sequence. - Optional> - findLoadOffsetsForLoadOrCombine( - SmallDenseMap &MemOffset2Idx, - const SmallVector &RegsToVisit, - const unsigned MemSizeInBits); - - /// Examines the G_PTR_ADD instruction \p PtrAdd and determines if performing - /// a re-association of its operands would break an existing legal addressing - /// mode that the address computation currently represents. - bool reassociationCanBreakAddressingModePattern(MachineInstr &PtrAdd); -}; -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerInfo.h deleted file mode 100644 index e73f848949..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/CombinerInfo.h +++ /dev/null @@ -1,71 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Interface for Targets to specify which operations are combined how and when. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINERINFO_H -#define LLVM_CODEGEN_GLOBALISEL_COMBINERINFO_H - -#include -namespace llvm { - -class GISelChangeObserver; -class LegalizerInfo; -class MachineInstr; -class MachineIRBuilder; - -// Contains information relevant to enabling/disabling various combines for a -// pass. -class CombinerInfo { -public: - CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal, - const LegalizerInfo *LInfo, bool OptEnabled, bool OptSize, - bool MinSize) - : IllegalOpsAllowed(AllowIllegalOps), - LegalizeIllegalOps(ShouldLegalizeIllegal), LInfo(LInfo), - EnableOpt(OptEnabled), EnableOptSize(OptSize), EnableMinSize(MinSize) { - assert(((AllowIllegalOps || !LegalizeIllegalOps) || LInfo) && - "Expecting legalizerInfo when illegalops not allowed"); - } - virtual ~CombinerInfo() = default; - /// If \p IllegalOpsAllowed is false, the CombinerHelper will make use of - /// the legalizerInfo to check for legality before each transformation. - bool IllegalOpsAllowed; // TODO: Make use of this. - - /// If \p LegalizeIllegalOps is true, the Combiner will also legalize the - /// illegal ops that are created. - bool LegalizeIllegalOps; // TODO: Make use of this. - const LegalizerInfo *LInfo; - - /// Whether optimizations should be enabled. This is to distinguish between - /// uses of the combiner unconditionally and only when optimizations are - /// specifically enabled/ - bool EnableOpt; - /// Whether we're optimizing for size. - bool EnableOptSize; - /// Whether we're optimizing for minsize (-Oz). - bool EnableMinSize; - - /// Attempt to combine instructions using MI as the root. - /// - /// Use Observer to report the creation, modification, and erasure of - /// instructions. GISelChangeObserver will automatically report certain - /// kinds of operations. These operations are: - /// * Instructions that are newly inserted into the MachineFunction - /// * Instructions that are erased from the MachineFunction. - /// - /// However, it is important to report instruction modification and this is - /// not automatic. - virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const = 0; -}; -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h deleted file mode 100644 index 70945fcecf..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h +++ /dev/null @@ -1,140 +0,0 @@ -//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This contains common code to allow clients to notify changes to machine -/// instr. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H -#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/CodeGen/MachineFunction.h" - -namespace llvm { -class MachineInstr; -class MachineRegisterInfo; - -/// Abstract class that contains various methods for clients to notify about -/// changes. This should be the preferred way for APIs to notify changes. -/// Typically calling erasingInstr/createdInstr multiple times should not affect -/// the result. The observer would likely need to check if it was already -/// notified earlier (consider using GISelWorkList). -class GISelChangeObserver { - SmallPtrSet ChangingAllUsesOfReg; - -public: - virtual ~GISelChangeObserver() = default; - - /// An instruction is about to be erased. - virtual void erasingInstr(MachineInstr &MI) = 0; - - /// An instruction has been created and inserted into the function. - /// Note that the instruction might not be a fully fledged instruction at this - /// point and won't be if the MachineFunction::Delegate is calling it. This is - /// because the delegate only sees the construction of the MachineInstr before - /// operands have been added. - virtual void createdInstr(MachineInstr &MI) = 0; - - /// This instruction is about to be mutated in some way. - virtual void changingInstr(MachineInstr &MI) = 0; - - /// This instruction was mutated in some way. - virtual void changedInstr(MachineInstr &MI) = 0; - - /// All the instructions using the given register are being changed. - /// For convenience, finishedChangingAllUsesOfReg() will report the completion - /// of the changes. The use list may change between this call and - /// finishedChangingAllUsesOfReg(). - void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg); - /// All instructions reported as changing by changingAllUsesOfReg() have - /// finished being changed. - void finishedChangingAllUsesOfReg(); - -}; - -/// Simple wrapper observer that takes several observers, and calls -/// each one for each event. If there are multiple observers (say CSE, -/// Legalizer, Combiner), it's sufficient to register this to the machine -/// function as the delegate. -class GISelObserverWrapper : public MachineFunction::Delegate, - public GISelChangeObserver { - SmallVector Observers; - -public: - GISelObserverWrapper() = default; - GISelObserverWrapper(ArrayRef Obs) - : Observers(Obs.begin(), Obs.end()) {} - // Adds an observer. - void addObserver(GISelChangeObserver *O) { Observers.push_back(O); } - // Removes an observer from the list and does nothing if observer is not - // present. - void removeObserver(GISelChangeObserver *O) { - auto It = std::find(Observers.begin(), Observers.end(), O); - if (It != Observers.end()) - Observers.erase(It); - } - // API for Observer. - void erasingInstr(MachineInstr &MI) override { - for (auto &O : Observers) - O->erasingInstr(MI); - } - void createdInstr(MachineInstr &MI) override { - for (auto &O : Observers) - O->createdInstr(MI); - } - void changingInstr(MachineInstr &MI) override { - for (auto &O : Observers) - O->changingInstr(MI); - } - void changedInstr(MachineInstr &MI) override { - for (auto &O : Observers) - O->changedInstr(MI); - } - // API for MachineFunction::Delegate - void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); } - void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); } -}; - -/// A simple RAII based Delegate installer. -/// Use this in a scope to install a delegate to the MachineFunction and reset -/// it at the end of the scope. -class RAIIDelegateInstaller { - MachineFunction &MF; - MachineFunction::Delegate *Delegate; - -public: - RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del); - ~RAIIDelegateInstaller(); -}; - -/// A simple RAII based Observer installer. -/// Use this in a scope to install the Observer to the MachineFunction and reset -/// it at the end of the scope. -class RAIIMFObserverInstaller { - MachineFunction &MF; - -public: - RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer); - ~RAIIMFObserverInstaller(); -}; - -/// Class to install both of the above. -class RAIIMFObsDelInstaller { - RAIIDelegateInstaller DelI; - RAIIMFObserverInstaller ObsI; - -public: - RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper) - : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {} - ~RAIIMFObsDelInstaller() = default; -}; - -} // namespace llvm -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h deleted file mode 100644 index 035c5a08fe..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h +++ /dev/null @@ -1,132 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/GISelKnownBits.h ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Provides analysis for querying information about KnownBits during GISel -/// passes. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H -#define LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/InitializePasses.h" -#include "llvm/Support/KnownBits.h" - -namespace llvm { - -class TargetLowering; -class DataLayout; - -class GISelKnownBits : public GISelChangeObserver { - MachineFunction &MF; - MachineRegisterInfo &MRI; - const TargetLowering &TL; - const DataLayout &DL; - unsigned MaxDepth; - /// Cache maintained during a computeKnownBits request. - SmallDenseMap ComputeKnownBitsCache; - - void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known, - const APInt &DemandedElts, - unsigned Depth = 0); - - unsigned computeNumSignBitsMin(Register Src0, Register Src1, - const APInt &DemandedElts, unsigned Depth = 0); - -public: - GISelKnownBits(MachineFunction &MF, unsigned MaxDepth = 6); - virtual ~GISelKnownBits() = default; - - const MachineFunction &getMachineFunction() const { - return MF; - } - - const DataLayout &getDataLayout() const { - return DL; - } - - virtual void computeKnownBitsImpl(Register R, KnownBits &Known, - const APInt &DemandedElts, - unsigned Depth = 0); - - unsigned computeNumSignBits(Register R, const APInt &DemandedElts, - unsigned Depth = 0); - unsigned computeNumSignBits(Register R, unsigned Depth = 0); - - // KnownBitsAPI - KnownBits getKnownBits(Register R); - KnownBits getKnownBits(Register R, const APInt &DemandedElts, - unsigned Depth = 0); - - // Calls getKnownBits for first operand def of MI. - KnownBits getKnownBits(MachineInstr &MI); - APInt getKnownZeroes(Register R); - APInt getKnownOnes(Register R); - - /// \return true if 'V & Mask' is known to be zero in DemandedElts. We use - /// this predicate to simplify operations downstream. - /// Mask is known to be zero for bits that V cannot have. - bool maskedValueIsZero(Register Val, const APInt &Mask) { - return Mask.isSubsetOf(getKnownBits(Val).Zero); - } - - /// \return true if the sign bit of Op is known to be zero. We use this - /// predicate to simplify operations downstream. - bool signBitIsZero(Register Op); - - static void computeKnownBitsForAlignment(KnownBits &Known, - Align Alignment) { - // The low bits are known zero if the pointer is aligned. - Known.Zero.setLowBits(Log2(Alignment)); - } - - /// \return The known alignment for the pointer-like value \p R. - Align computeKnownAlignment(Register R, unsigned Depth = 0); - - // Observer API. No-op for non-caching implementation. - void erasingInstr(MachineInstr &MI) override{}; - void createdInstr(MachineInstr &MI) override{}; - void changingInstr(MachineInstr &MI) override{}; - void changedInstr(MachineInstr &MI) override{}; - -protected: - unsigned getMaxDepth() const { return MaxDepth; } -}; - -/// To use KnownBitsInfo analysis in a pass, -/// KnownBitsInfo &Info = getAnalysis().get(MF); -/// Add to observer if the Info is caching. -/// WrapperObserver.addObserver(Info); - -/// Eventually add other features such as caching/ser/deserializing -/// to MIR etc. Those implementations can derive from GISelKnownBits -/// and override computeKnownBitsImpl. -class GISelKnownBitsAnalysis : public MachineFunctionPass { - std::unique_ptr Info; - -public: - static char ID; - GISelKnownBitsAnalysis() : MachineFunctionPass(ID) { - initializeGISelKnownBitsAnalysisPass(*PassRegistry::getPassRegistry()); - } - GISelKnownBits &get(MachineFunction &MF) { - if (!Info) - Info = std::make_unique(MF); - return *Info.get(); - } - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnMachineFunction(MachineFunction &MF) override; - void releaseMemory() override { Info.reset(); } -}; -} // namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelWorkList.h deleted file mode 100644 index 5306557de0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GISelWorkList.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- GISelWorkList.h - Worklist for GISel passes ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_GISELWORKLIST_H -#define LLVM_CODEGEN_GLOBALISEL_GISELWORKLIST_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" - -namespace llvm { - -class MachineInstr; - -// Worklist which mostly works similar to InstCombineWorkList, but on -// MachineInstrs. The main difference with something like a SetVector is that -// erasing an element doesn't move all elements over one place - instead just -// nulls out the element of the vector. -// -// FIXME: Does it make sense to factor out common code with the -// instcombinerWorkList? -template -class GISelWorkList { - SmallVector Worklist; - DenseMap WorklistMap; - -#ifndef NDEBUG - bool Finalized = true; -#endif - -public: - GISelWorkList() : WorklistMap(N) {} - - bool empty() const { return WorklistMap.empty(); } - - unsigned size() const { return WorklistMap.size(); } - - // Since we don't know ahead of time how many instructions we're going to add - // to the worklist, and migrating densemap's elements is quite expensive - // every time we resize, only insert to the smallvector (typically during the - // initial phase of populating lists). Before the worklist can be used, - // finalize should be called. Also assert with NDEBUG if list is ever used - // without finalizing. Note that unlike insert, we won't check for duplicates - // - so the ideal place to use this is during the initial prepopulating phase - // of most passes. - void deferred_insert(MachineInstr *I) { - Worklist.push_back(I); -#ifndef NDEBUG - Finalized = false; -#endif - } - - // This should only be called when using deferred_insert. - // This asserts that the WorklistMap is empty, and then - // inserts all the elements in the Worklist into the map. - // It also asserts if there are any duplicate elements found. - void finalize() { - assert(WorklistMap.empty() && "Expecting empty worklistmap"); - if (Worklist.size() > N) - WorklistMap.reserve(Worklist.size()); - for (unsigned i = 0; i < Worklist.size(); ++i) - if (!WorklistMap.try_emplace(Worklist[i], i).second) - llvm_unreachable("Duplicate elements in the list"); -#ifndef NDEBUG - Finalized = true; -#endif - } - - /// Add the specified instruction to the worklist if it isn't already in it. - void insert(MachineInstr *I) { - assert(Finalized && "GISelWorkList used without finalizing"); - if (WorklistMap.try_emplace(I, Worklist.size()).second) - Worklist.push_back(I); - } - - /// Remove I from the worklist if it exists. - void remove(const MachineInstr *I) { - assert((Finalized || WorklistMap.empty()) && "Neither finalized nor empty"); - auto It = WorklistMap.find(I); - if (It == WorklistMap.end()) - return; // Not in worklist. - - // Don't bother moving everything down, just null out the slot. - Worklist[It->second] = nullptr; - - WorklistMap.erase(It); - } - - void clear() { - Worklist.clear(); - WorklistMap.clear(); - } - - MachineInstr *pop_back_val() { - assert(Finalized && "GISelWorkList used without finalizing"); - MachineInstr *I; - do { - I = Worklist.pop_back_val(); - } while(!I); - assert(I && "Pop back on empty worklist"); - WorklistMap.erase(I); - return I; - } -}; - -} // end namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h deleted file mode 100644 index 7103656365..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h +++ /dev/null @@ -1,231 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Declares convenience wrapper classes for interpreting MachineInstr instances -/// as specific generic operations. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H -#define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H - -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/Support/Casting.h" - -namespace llvm { - -/// A base class for all GenericMachineInstrs. -class GenericMachineInstr : public MachineInstr { -public: - GenericMachineInstr() = delete; - - /// Access the Idx'th operand as a register and return it. - /// This assumes that the Idx'th operand is a Register type. - Register getReg(unsigned Idx) const { return getOperand(Idx).getReg(); } - - static bool classof(const MachineInstr *MI) { - return isPreISelGenericOpcode(MI->getOpcode()); - } -}; - -/// Represents any type of generic load or store. -/// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD. -class GLoadStore : public GenericMachineInstr { -public: - /// Get the source register of the pointer value. - Register getPointerReg() const { return getOperand(1).getReg(); } - - /// Get the MachineMemOperand on this instruction. - MachineMemOperand &getMMO() const { return **memoperands_begin(); } - - /// Returns true if the attached MachineMemOperand has the atomic flag set. - bool isAtomic() const { return getMMO().isAtomic(); } - /// Returns true if the attached MachineMemOpeand as the volatile flag set. - bool isVolatile() const { return getMMO().isVolatile(); } - /// Returns true if the memory operation is neither atomic or volatile. - bool isSimple() const { return !isAtomic() && !isVolatile(); } - /// Returns true if this memory operation doesn't have any ordering - /// constraints other than normal aliasing. Volatile and (ordered) atomic - /// memory operations can't be reordered. - bool isUnordered() const { return getMMO().isUnordered(); } - - /// Returns the size in bytes of the memory access. - uint64_t getMemSize() const { return getMMO().getSize(); - } /// Returns the size in bits of the memory access. - uint64_t getMemSizeInBits() const { return getMMO().getSizeInBits(); } - - static bool classof(const MachineInstr *MI) { - switch (MI->getOpcode()) { - case TargetOpcode::G_LOAD: - case TargetOpcode::G_STORE: - case TargetOpcode::G_ZEXTLOAD: - case TargetOpcode::G_SEXTLOAD: - return true; - default: - return false; - } - } -}; - -/// Represents any generic load, including sign/zero extending variants. -class GAnyLoad : public GLoadStore { -public: - /// Get the definition register of the loaded value. - Register getDstReg() const { return getOperand(0).getReg(); } - - static bool classof(const MachineInstr *MI) { - switch (MI->getOpcode()) { - case TargetOpcode::G_LOAD: - case TargetOpcode::G_ZEXTLOAD: - case TargetOpcode::G_SEXTLOAD: - return true; - default: - return false; - } - } -}; - -/// Represents a G_LOAD. -class GLoad : public GAnyLoad { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_LOAD; - } -}; - -/// Represents either a G_SEXTLOAD or G_ZEXTLOAD. -class GExtLoad : public GAnyLoad { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_SEXTLOAD || - MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; - } -}; - -/// Represents a G_SEXTLOAD. -class GSExtLoad : public GExtLoad { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_SEXTLOAD; - } -}; - -/// Represents a G_ZEXTLOAD. -class GZExtLoad : public GExtLoad { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; - } -}; - -/// Represents a G_STORE. -class GStore : public GLoadStore { -public: - /// Get the stored value register. - Register getValueReg() const { return getOperand(0).getReg(); } - - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_STORE; - } -}; - -/// Represents a G_UNMERGE_VALUES. -class GUnmerge : public GenericMachineInstr { -public: - /// Returns the number of def registers. - unsigned getNumDefs() const { return getNumOperands() - 1; } - /// Get the unmerge source register. - Register getSourceReg() const { return getOperand(getNumDefs()).getReg(); } - - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES; - } -}; - -/// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES. -/// All these have the common property of generating a single value from -/// multiple sources. -class GMergeLikeOp : public GenericMachineInstr { -public: - /// Returns the number of source registers. - unsigned getNumSources() const { return getNumOperands() - 1; } - /// Returns the I'th source register. - Register getSourceReg(unsigned I) const { return getReg(I + 1); } - - static bool classof(const MachineInstr *MI) { - switch (MI->getOpcode()) { - case TargetOpcode::G_MERGE_VALUES: - case TargetOpcode::G_CONCAT_VECTORS: - case TargetOpcode::G_BUILD_VECTOR: - return true; - default: - return false; - } - } -}; - -/// Represents a G_MERGE_VALUES. -class GMerge : public GMergeLikeOp { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES; - } -}; - -/// Represents a G_CONCAT_VECTORS. -class GConcatVectors : public GMergeLikeOp { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS; - } -}; - -/// Represents a G_BUILD_VECTOR. -class GBuildVector : public GMergeLikeOp { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR; - } -}; - -/// Represents a G_PTR_ADD. -class GPtrAdd : public GenericMachineInstr { -public: - Register getBaseReg() const { return getReg(1); } - Register getOffsetReg() const { return getReg(2); } - - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_PTR_ADD; - } -}; - -/// Represents a G_IMPLICIT_DEF. -class GImplicitDef : public GenericMachineInstr { -public: - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF; - } -}; - -/// Represents a G_SELECT. -class GSelect : public GenericMachineInstr { -public: - Register getCondReg() const { return getReg(1); } - Register getTrueReg() const { return getReg(2); } - Register getFalseReg() const { return getReg(3); } - - static bool classof(const MachineInstr *MI) { - return MI->getOpcode() == TargetOpcode::G_SELECT; - } -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/IRTranslator.h deleted file mode 100644 index ebe16cd4f5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ /dev/null @@ -1,731 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file declares the IRTranslator pass. -/// This pass is responsible for translating LLVM IR into MachineInstr. -/// It uses target hooks to lower the ABI but aside from that, the pass -/// generated code is generic. This is the default translator used for -/// GlobalISel. -/// -/// \todo Replace the comments with actual doxygen comments. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H -#define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/CodeGenCommonISel.h" -#include "llvm/CodeGen/FunctionLoweringInfo.h" -#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/SwiftErrorValueTracking.h" -#include "llvm/CodeGen/SwitchLoweringUtils.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CodeGen.h" -#include -#include - -namespace llvm { - -class AllocaInst; -class BasicBlock; -class CallInst; -class CallLowering; -class Constant; -class ConstrainedFPIntrinsic; -class DataLayout; -class Instruction; -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class OptimizationRemarkEmitter; -class PHINode; -class TargetPassConfig; -class User; -class Value; - -// Technically the pass should run on an hypothetical MachineModule, -// since it should translate Global into some sort of MachineGlobal. -// The MachineGlobal should ultimately just be a transfer of ownership of -// the interesting bits that are relevant to represent a global value. -// That being said, we could investigate what would it cost to just duplicate -// the information from the LLVM IR. -// The idea is that ultimately we would be able to free up the memory used -// by the LLVM IR as soon as the translation is over. -class IRTranslator : public MachineFunctionPass { -public: - static char ID; - -private: - /// Interface used to lower the everything related to calls. - const CallLowering *CLI; - - /// This class contains the mapping between the Values to vreg related data. - class ValueToVRegInfo { - public: - ValueToVRegInfo() = default; - - using VRegListT = SmallVector; - using OffsetListT = SmallVector; - - using const_vreg_iterator = - DenseMap::const_iterator; - using const_offset_iterator = - DenseMap::const_iterator; - - inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); } - - VRegListT *getVRegs(const Value &V) { - auto It = ValToVRegs.find(&V); - if (It != ValToVRegs.end()) - return It->second; - - return insertVRegs(V); - } - - OffsetListT *getOffsets(const Value &V) { - auto It = TypeToOffsets.find(V.getType()); - if (It != TypeToOffsets.end()) - return It->second; - - return insertOffsets(V); - } - - const_vreg_iterator findVRegs(const Value &V) const { - return ValToVRegs.find(&V); - } - - bool contains(const Value &V) const { - return ValToVRegs.find(&V) != ValToVRegs.end(); - } - - void reset() { - ValToVRegs.clear(); - TypeToOffsets.clear(); - VRegAlloc.DestroyAll(); - OffsetAlloc.DestroyAll(); - } - - private: - VRegListT *insertVRegs(const Value &V) { - assert(ValToVRegs.find(&V) == ValToVRegs.end() && "Value already exists"); - - // We placement new using our fast allocator since we never try to free - // the vectors until translation is finished. - auto *VRegList = new (VRegAlloc.Allocate()) VRegListT(); - ValToVRegs[&V] = VRegList; - return VRegList; - } - - OffsetListT *insertOffsets(const Value &V) { - assert(TypeToOffsets.find(V.getType()) == TypeToOffsets.end() && - "Type already exists"); - - auto *OffsetList = new (OffsetAlloc.Allocate()) OffsetListT(); - TypeToOffsets[V.getType()] = OffsetList; - return OffsetList; - } - SpecificBumpPtrAllocator VRegAlloc; - SpecificBumpPtrAllocator OffsetAlloc; - - // We store pointers to vectors here since references may be invalidated - // while we hold them if we stored the vectors directly. - DenseMap ValToVRegs; - DenseMap TypeToOffsets; - }; - - /// Mapping of the values of the current LLVM IR function to the related - /// virtual registers and offsets. - ValueToVRegInfo VMap; - - // N.b. it's not completely obvious that this will be sufficient for every - // LLVM IR construct (with "invoke" being the obvious candidate to mess up our - // lives. - DenseMap BBToMBB; - - // One BasicBlock can be translated to multiple MachineBasicBlocks. For such - // BasicBlocks translated to multiple MachineBasicBlocks, MachinePreds retains - // a mapping between the edges arriving at the BasicBlock to the corresponding - // created MachineBasicBlocks. Some BasicBlocks that get translated to a - // single MachineBasicBlock may also end up in this Map. - using CFGEdge = std::pair; - DenseMap> MachinePreds; - - // List of stubbed PHI instructions, for values and basic blocks to be filled - // in once all MachineBasicBlocks have been created. - SmallVector>, 4> - PendingPHIs; - - /// Record of what frame index has been allocated to specified allocas for - /// this function. - DenseMap FrameIndices; - - SwiftErrorValueTracking SwiftError; - - /// \name Methods for translating form LLVM IR to MachineInstr. - /// \see ::translate for general information on the translate methods. - /// @{ - - /// Translate \p Inst into its corresponding MachineInstr instruction(s). - /// Insert the newly translated instruction(s) right where the CurBuilder - /// is set. - /// - /// The general algorithm is: - /// 1. Look for a virtual register for each operand or - /// create one. - /// 2 Update the VMap accordingly. - /// 2.alt. For constant arguments, if they are compile time constants, - /// produce an immediate in the right operand and do not touch - /// ValToReg. Actually we will go with a virtual register for each - /// constants because it may be expensive to actually materialize the - /// constant. Moreover, if the constant spans on several instructions, - /// CSE may not catch them. - /// => Update ValToVReg and remember that we saw a constant in Constants. - /// We will materialize all the constants in finalize. - /// Note: we would need to do something so that we can recognize such operand - /// as constants. - /// 3. Create the generic instruction. - /// - /// \return true if the translation succeeded. - bool translate(const Instruction &Inst); - - /// Materialize \p C into virtual-register \p Reg. The generic instructions - /// performing this materialization will be inserted into the entry block of - /// the function. - /// - /// \return true if the materialization succeeded. - bool translate(const Constant &C, Register Reg); - - // Translate U as a copy of V. - bool translateCopy(const User &U, const Value &V, - MachineIRBuilder &MIRBuilder); - - /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is - /// emitted. - bool translateBitCast(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate an LLVM load instruction into generic IR. - bool translateLoad(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate an LLVM store instruction into generic IR. - bool translateStore(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate an LLVM string intrinsic (memcpy, memset, ...). - bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, - unsigned Opcode); - - void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); - - bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, - MachineIRBuilder &MIRBuilder); - bool translateFixedPointIntrinsic(unsigned Op, const CallInst &CI, - MachineIRBuilder &MIRBuilder); - - /// Helper function for translateSimpleIntrinsic. - /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a - /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns - /// Intrinsic::not_intrinsic. - unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID); - - /// Translates the intrinsics defined in getSimpleIntrinsicOpcode. - /// \return true if the translation succeeded. - bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID, - MachineIRBuilder &MIRBuilder); - - bool translateConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI, - MachineIRBuilder &MIRBuilder); - - bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, - MachineIRBuilder &MIRBuilder); - - bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder); - - /// Returns true if the value should be split into multiple LLTs. - /// If \p Offsets is given then the split type's offsets will be stored in it. - /// If \p Offsets is not empty it will be cleared first. - bool valueIsSplit(const Value &V, - SmallVectorImpl *Offsets = nullptr); - - /// Common code for translating normal calls or invokes. - bool translateCallBase(const CallBase &CB, MachineIRBuilder &MIRBuilder); - - /// Translate call instruction. - /// \pre \p U is a call instruction. - bool translateCall(const User &U, MachineIRBuilder &MIRBuilder); - - /// When an invoke or a cleanupret unwinds to the next EH pad, there are - /// many places it could ultimately go. In the IR, we have a single unwind - /// destination, but in the machine CFG, we enumerate all the possible blocks. - /// This function skips over imaginary basic blocks that hold catchswitch - /// instructions, and finds all the "real" machine - /// basic block destinations. As those destinations may not be successors of - /// EHPadBB, here we also calculate the edge probability to those - /// destinations. The passed-in Prob is the edge probability to EHPadBB. - bool findUnwindDestinations( - const BasicBlock *EHPadBB, BranchProbability Prob, - SmallVectorImpl> - &UnwindDests); - - bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate one of LLVM's cast instructions into MachineInstrs, with the - /// given generic Opcode. - bool translateCast(unsigned Opcode, const User &U, - MachineIRBuilder &MIRBuilder); - - /// Translate a phi instruction. - bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate a comparison (icmp or fcmp) instruction or constant. - bool translateCompare(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate an integer compare instruction (or constant). - bool translateICmp(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCompare(U, MIRBuilder); - } - - /// Translate a floating-point compare instruction (or constant). - bool translateFCmp(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCompare(U, MIRBuilder); - } - - /// Add remaining operands onto phis we've translated. Executed after all - /// MachineBasicBlocks for the function have been created. - void finishPendingPhis(); - - /// Translate \p Inst into a unary operation \p Opcode. - /// \pre \p U is a unary operation. - bool translateUnaryOp(unsigned Opcode, const User &U, - MachineIRBuilder &MIRBuilder); - - /// Translate \p Inst into a binary operation \p Opcode. - /// \pre \p U is a binary operation. - bool translateBinaryOp(unsigned Opcode, const User &U, - MachineIRBuilder &MIRBuilder); - - /// If the set of cases should be emitted as a series of branches, return - /// true. If we should emit this as a bunch of and/or'd together conditions, - /// return false. - bool shouldEmitAsBranches(const std::vector &Cases); - /// Helper method for findMergedConditions. - /// This function emits a branch and is used at the leaves of an OR or an - /// AND operator tree. - void emitBranchForMergedCondition(const Value *Cond, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - MachineBasicBlock *CurBB, - MachineBasicBlock *SwitchBB, - BranchProbability TProb, - BranchProbability FProb, bool InvertCond); - /// Used during condbr translation to find trees of conditions that can be - /// optimized. - void findMergedConditions(const Value *Cond, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, MachineBasicBlock *CurBB, - MachineBasicBlock *SwitchBB, - Instruction::BinaryOps Opc, BranchProbability TProb, - BranchProbability FProb, bool InvertCond); - - /// Translate branch (br) instruction. - /// \pre \p U is a branch instruction. - bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); - - // Begin switch lowering functions. - bool emitJumpTableHeader(SwitchCG::JumpTable &JT, - SwitchCG::JumpTableHeader &JTH, - MachineBasicBlock *HeaderBB); - void emitJumpTable(SwitchCG::JumpTable &JT, MachineBasicBlock *MBB); - - void emitSwitchCase(SwitchCG::CaseBlock &CB, MachineBasicBlock *SwitchBB, - MachineIRBuilder &MIB); - - /// Generate for for the BitTest header block, which precedes each sequence of - /// BitTestCases. - void emitBitTestHeader(SwitchCG::BitTestBlock &BTB, - MachineBasicBlock *SwitchMBB); - /// Generate code to produces one "bit test" for a given BitTestCase \p B. - void emitBitTestCase(SwitchCG::BitTestBlock &BB, MachineBasicBlock *NextMBB, - BranchProbability BranchProbToNext, Register Reg, - SwitchCG::BitTestCase &B, MachineBasicBlock *SwitchBB); - - bool lowerJumpTableWorkItem( - SwitchCG::SwitchWorkListItem W, MachineBasicBlock *SwitchMBB, - MachineBasicBlock *CurMBB, MachineBasicBlock *DefaultMBB, - MachineIRBuilder &MIB, MachineFunction::iterator BBI, - BranchProbability UnhandledProbs, SwitchCG::CaseClusterIt I, - MachineBasicBlock *Fallthrough, bool FallthroughUnreachable); - - bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, Value *Cond, - MachineBasicBlock *Fallthrough, - bool FallthroughUnreachable, - BranchProbability UnhandledProbs, - MachineBasicBlock *CurMBB, - MachineIRBuilder &MIB, - MachineBasicBlock *SwitchMBB); - - bool lowerBitTestWorkItem( - SwitchCG::SwitchWorkListItem W, MachineBasicBlock *SwitchMBB, - MachineBasicBlock *CurMBB, MachineBasicBlock *DefaultMBB, - MachineIRBuilder &MIB, MachineFunction::iterator BBI, - BranchProbability DefaultProb, BranchProbability UnhandledProbs, - SwitchCG::CaseClusterIt I, MachineBasicBlock *Fallthrough, - bool FallthroughUnreachable); - - bool lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W, Value *Cond, - MachineBasicBlock *SwitchMBB, - MachineBasicBlock *DefaultMBB, - MachineIRBuilder &MIB); - - bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); - // End switch lowering section. - - bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateSelect(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder); - - /// Translate return (ret) instruction. - /// The target needs to implement CallLowering::lowerReturn for - /// this to succeed. - /// \pre \p U is a return instruction. - bool translateRet(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder); - } - bool translateSub(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_SUB, U, MIRBuilder); - } - bool translateAnd(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_AND, U, MIRBuilder); - } - bool translateMul(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_MUL, U, MIRBuilder); - } - bool translateOr(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_OR, U, MIRBuilder); - } - bool translateXor(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_XOR, U, MIRBuilder); - } - - bool translateUDiv(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_UDIV, U, MIRBuilder); - } - bool translateSDiv(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_SDIV, U, MIRBuilder); - } - bool translateURem(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_UREM, U, MIRBuilder); - } - bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder); - } - bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder); - } - bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder); - } - bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder); - } - bool translateFPTrunc(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_FPTRUNC, U, MIRBuilder); - } - bool translateFPExt(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_FPEXT, U, MIRBuilder); - } - bool translateFPToUI(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_FPTOUI, U, MIRBuilder); - } - bool translateFPToSI(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_FPTOSI, U, MIRBuilder); - } - bool translateUIToFP(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_UITOFP, U, MIRBuilder); - } - bool translateSIToFP(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_SITOFP, U, MIRBuilder); - } - bool translateUnreachable(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateSExt(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_SEXT, U, MIRBuilder); - } - - bool translateZExt(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_ZEXT, U, MIRBuilder); - } - - bool translateShl(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_SHL, U, MIRBuilder); - } - bool translateLShr(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_LSHR, U, MIRBuilder); - } - bool translateAShr(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_ASHR, U, MIRBuilder); - } - - bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder); - } - bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder); - } - bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder); - } - bool translateFDiv(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FDIV, U, MIRBuilder); - } - bool translateFRem(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder); - } - - bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder); - - bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder); - bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder); - bool translateFence(const User &U, MachineIRBuilder &MIRBuilder); - bool translateFreeze(const User &U, MachineIRBuilder &MIRBuilder); - - // Stubs to keep the compiler happy while we implement the rest of the - // translation. - bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateCleanupRet(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateCatchRet(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateCatchSwitch(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) { - return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder); - } - bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateCatchPad(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateUserOp1(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - - /// @} - - // Builder for machine instruction a la IRBuilder. - // I.e., compared to regular MIBuilder, this one also inserts the instruction - // in the current block, it can creates block, etc., basically a kind of - // IRBuilder, but for Machine IR. - // CSEMIRBuilder CurBuilder; - std::unique_ptr CurBuilder; - - // Builder set to the entry block (just after ABI lowering instructions). Used - // as a convenient location for Constants. - // CSEMIRBuilder EntryBuilder; - std::unique_ptr EntryBuilder; - - // The MachineFunction currently being translated. - MachineFunction *MF; - - /// MachineRegisterInfo used to create virtual registers. - MachineRegisterInfo *MRI = nullptr; - - const DataLayout *DL; - - /// Current target configuration. Controls how the pass handles errors. - const TargetPassConfig *TPC; - - CodeGenOpt::Level OptLevel; - - /// Current optimization remark emitter. Used to report failures. - std::unique_ptr ORE; - - FunctionLoweringInfo FuncInfo; - - // True when either the Target Machine specifies no optimizations or the - // function has the optnone attribute. - bool EnableOpts = false; - - /// True when the block contains a tail call. This allows the IRTranslator to - /// stop translating such blocks early. - bool HasTailCall = false; - - StackProtectorDescriptor SPDescriptor; - - /// Switch analysis and optimization. - class GISelSwitchLowering : public SwitchCG::SwitchLowering { - public: - GISelSwitchLowering(IRTranslator *irt, FunctionLoweringInfo &funcinfo) - : SwitchLowering(funcinfo), IRT(irt) { - assert(irt && "irt is null!"); - } - - virtual void addSuccessorWithProb( - MachineBasicBlock *Src, MachineBasicBlock *Dst, - BranchProbability Prob = BranchProbability::getUnknown()) override { - IRT->addSuccessorWithProb(Src, Dst, Prob); - } - - virtual ~GISelSwitchLowering() = default; - - private: - IRTranslator *IRT; - }; - - std::unique_ptr SL; - - // * Insert all the code needed to materialize the constants - // at the proper place. E.g., Entry block or dominator block - // of each constant depending on how fancy we want to be. - // * Clear the different maps. - void finalizeFunction(); - - // Processing steps done per block. E.g. emitting jump tables, stack - // protectors etc. Returns true if no errors, false if there was a problem - // that caused an abort. - bool finalizeBasicBlock(const BasicBlock &BB, MachineBasicBlock &MBB); - - /// Codegen a new tail for a stack protector check ParentMBB which has had its - /// tail spliced into a stack protector check success bb. - /// - /// For a high level explanation of how this fits into the stack protector - /// generation see the comment on the declaration of class - /// StackProtectorDescriptor. - /// - /// \return true if there were no problems. - bool emitSPDescriptorParent(StackProtectorDescriptor &SPD, - MachineBasicBlock *ParentBB); - - /// Codegen the failure basic block for a stack protector check. - /// - /// A failure stack protector machine basic block consists simply of a call to - /// __stack_chk_fail(). - /// - /// For a high level explanation of how this fits into the stack protector - /// generation see the comment on the declaration of class - /// StackProtectorDescriptor. - /// - /// \return true if there were no problems. - bool emitSPDescriptorFailure(StackProtectorDescriptor &SPD, - MachineBasicBlock *FailureBB); - - /// Get the VRegs that represent \p Val. - /// Non-aggregate types have just one corresponding VReg and the list can be - /// used as a single "unsigned". Aggregates get flattened. If such VRegs do - /// not exist, they are created. - ArrayRef getOrCreateVRegs(const Value &Val); - - Register getOrCreateVReg(const Value &Val) { - auto Regs = getOrCreateVRegs(Val); - if (Regs.empty()) - return 0; - assert(Regs.size() == 1 && - "attempt to get single VReg for aggregate or void"); - return Regs[0]; - } - - /// Allocate some vregs and offsets in the VMap. Then populate just the - /// offsets while leaving the vregs empty. - ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val); - - /// Get the frame index that represents \p Val. - /// If such VReg does not exist, it is created. - int getOrCreateFrameIndex(const AllocaInst &AI); - - /// Get the alignment of the given memory operation instruction. This will - /// either be the explicitly specified value or the ABI-required alignment for - /// the type being accessed (according to the Module's DataLayout). - Align getMemOpAlign(const Instruction &I); - - /// Get the MachineBasicBlock that represents \p BB. Specifically, the block - /// returned will be the head of the translated block (suitable for branch - /// destinations). - MachineBasicBlock &getMBB(const BasicBlock &BB); - - /// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding - /// to `Edge.first` at the IR level. This is used when IRTranslation creates - /// multiple MachineBasicBlocks for a given IR block and the CFG is no longer - /// represented simply by the IR-level CFG. - void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred); - - /// Returns the Machine IR predecessors for the given IR CFG edge. Usually - /// this is just the single MachineBasicBlock corresponding to the predecessor - /// in the IR. More complex lowering can result in multiple MachineBasicBlocks - /// preceding the original though (e.g. switch instructions). - SmallVector getMachinePredBBs(CFGEdge Edge) { - auto RemappedEdge = MachinePreds.find(Edge); - if (RemappedEdge != MachinePreds.end()) - return RemappedEdge->second; - return SmallVector(1, &getMBB(*Edge.first)); - } - - /// Return branch probability calculated by BranchProbabilityInfo for IR - /// blocks. - BranchProbability getEdgeProbability(const MachineBasicBlock *Src, - const MachineBasicBlock *Dst) const; - - void addSuccessorWithProb( - MachineBasicBlock *Src, MachineBasicBlock *Dst, - BranchProbability Prob = BranchProbability::getUnknown()); - -public: - IRTranslator(CodeGenOpt::Level OptLevel = CodeGenOpt::None); - - StringRef getPassName() const override { return "IRTranslator"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - // Algo: - // CallLowering = MF.subtarget.getCallLowering() - // F = MF.getParent() - // MIRBuilder.reset(MF) - // getMBB(F.getEntryBB()) - // CallLowering->translateArguments(MIRBuilder, F, ValToVReg) - // for each bb in F - // getMBB(bb) - // for each inst in bb - // if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence)) - // report_fatal_error("Don't know how to translate input"); - // finalize() - bool runOnMachineFunction(MachineFunction &MF) override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h deleted file mode 100644 index ac6184877b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/InlineAsmLowering.h --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file describes how to lower LLVM inline asm to machine code INLINEASM. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H -#define LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H - -#include "llvm/ADT/ArrayRef.h" -#include - -namespace llvm { -class CallBase; -class MachineIRBuilder; -class MachineOperand; -class Register; -class TargetLowering; -class Value; - -class InlineAsmLowering { - const TargetLowering *TLI; - - virtual void anchor(); - -public: - /// Lower the given inline asm call instruction - /// \p GetOrCreateVRegs is a callback to materialize a register for the - /// input and output operands of the inline asm - /// \return True if the lowering succeeds, false otherwise. - bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB, - std::function(const Value &Val)> - GetOrCreateVRegs) const; - - /// Lower the specified operand into the Ops vector. - /// \p Val is the IR input value to be lowered - /// \p Constraint is the user supplied constraint string - /// \p Ops is the vector to be filled with the lowered operands - /// \return True if the lowering succeeds, false otherwise. - virtual bool lowerAsmOperandForConstraint(Value *Val, StringRef Constraint, - std::vector &Ops, - MachineIRBuilder &MIRBuilder) const; - -protected: - /// Getter for generic TargetLowering class. - const TargetLowering *getTLI() const { return TLI; } - - /// Getter for target specific TargetLowering class. - template const XXXTargetLowering *getTLI() const { - return static_cast(TLI); - } - -public: - InlineAsmLowering(const TargetLowering *TLI) : TLI(TLI) {} - virtual ~InlineAsmLowering() = default; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelect.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelect.h deleted file mode 100644 index 4a72621ec6..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelect.h +++ /dev/null @@ -1,63 +0,0 @@ -//== llvm/CodeGen/GlobalISel/InstructionSelect.h -----------------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file This file describes the interface of the MachineFunctionPass -/// responsible for selecting (possibly generic) machine instructions to -/// target-specific instructions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECT_H -#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECT_H - -#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { - -class BlockFrequencyInfo; -class ProfileSummaryInfo; - -/// This pass is responsible for selecting generic machine instructions to -/// target-specific instructions. It relies on the InstructionSelector provided -/// by the target. -/// Selection is done by examining blocks in post-order, and instructions in -/// reverse order. -/// -/// \post for all inst in MF: not isPreISelGenericOpcode(inst.opcode) -class InstructionSelect : public MachineFunctionPass { -public: - static char ID; - StringRef getPassName() const override { return "InstructionSelect"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA) - .set(MachineFunctionProperties::Property::Legalized) - .set(MachineFunctionProperties::Property::RegBankSelected); - } - - MachineFunctionProperties getSetProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::Selected); - } - - InstructionSelect(CodeGenOpt::Level OL); - InstructionSelect(); - - bool runOnMachineFunction(MachineFunction &MF) override; - -protected: - BlockFrequencyInfo *BFI = nullptr; - ProfileSummaryInfo *PSI = nullptr; - - CodeGenOpt::Level OptLevel = CodeGenOpt::None; -}; -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelector.h deleted file mode 100644 index 3e69831c75..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ /dev/null @@ -1,569 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/InstructionSelector.h ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file declares the API for the instruction selector. -/// This class is responsible for selecting machine instructions. -/// It's implemented by the target. It's used by the InstructionSelect pass. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H -#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/BlockFrequencyInfo.h" -#include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/Support/CodeGenCoverage.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class APInt; -class APFloat; -class GISelKnownBits; -class MachineInstr; -class MachineInstrBuilder; -class MachineFunction; -class MachineOperand; -class MachineRegisterInfo; -class RegisterBankInfo; -class TargetInstrInfo; -class TargetRegisterInfo; - -/// Container class for CodeGen predicate results. -/// This is convenient because std::bitset does not have a constructor -/// with an initializer list of set bits. -/// -/// Each InstructionSelector subclass should define a PredicateBitset class -/// with: -/// const unsigned MAX_SUBTARGET_PREDICATES = 192; -/// using PredicateBitset = PredicateBitsetImpl; -/// and updating the constant to suit the target. Tablegen provides a suitable -/// definition for the predicates in use in GenGlobalISel.inc when -/// GET_GLOBALISEL_PREDICATE_BITSET is defined. -template -class PredicateBitsetImpl : public std::bitset { -public: - // Cannot inherit constructors because it's not supported by VC++.. - PredicateBitsetImpl() = default; - - PredicateBitsetImpl(const std::bitset &B) - : std::bitset(B) {} - - PredicateBitsetImpl(std::initializer_list Init) { - for (auto I : Init) - std::bitset::set(I); - } -}; - -enum { - /// Begin a try-block to attempt a match and jump to OnFail if it is - /// unsuccessful. - /// - OnFail - The MatchTable entry at which to resume if the match fails. - /// - /// FIXME: This ought to take an argument indicating the number of try-blocks - /// to exit on failure. It's usually one but the last match attempt of - /// a block will need more. The (implemented) alternative is to tack a - /// GIM_Reject on the end of each try-block which is simpler but - /// requires an extra opcode and iteration in the interpreter on each - /// failed match. - GIM_Try, - - /// Switch over the opcode on the specified instruction - /// - InsnID - Instruction ID - /// - LowerBound - numerically minimum opcode supported - /// - UpperBound - numerically maximum + 1 opcode supported - /// - Default - failure jump target - /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets - GIM_SwitchOpcode, - - /// Switch over the LLT on the specified instruction operand - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - LowerBound - numerically minimum Type ID supported - /// - UpperBound - numerically maximum + 1 Type ID supported - /// - Default - failure jump target - /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets - GIM_SwitchType, - - /// Record the specified instruction - /// - NewInsnID - Instruction ID to define - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - GIM_RecordInsn, - - /// Check the feature bits - /// - Expected features - GIM_CheckFeatures, - - /// Check the opcode on the specified instruction - /// - InsnID - Instruction ID - /// - Expected opcode - GIM_CheckOpcode, - - /// Check the opcode on the specified instruction, checking 2 acceptable - /// alternatives. - /// - InsnID - Instruction ID - /// - Expected opcode - /// - Alternative expected opcode - GIM_CheckOpcodeIsEither, - - /// Check the instruction has the right number of operands - /// - InsnID - Instruction ID - /// - Expected number of operands - GIM_CheckNumOperands, - /// Check an immediate predicate on the specified instruction - /// - InsnID - Instruction ID - /// - The predicate to test - GIM_CheckI64ImmPredicate, - /// Check an immediate predicate on the specified instruction via an APInt. - /// - InsnID - Instruction ID - /// - The predicate to test - GIM_CheckAPIntImmPredicate, - /// Check a floating point immediate predicate on the specified instruction. - /// - InsnID - Instruction ID - /// - The predicate to test - GIM_CheckAPFloatImmPredicate, - /// Check an immediate predicate on the specified instruction - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - The predicate to test - GIM_CheckImmOperandPredicate, - /// Check a memory operation has the specified atomic ordering. - /// - InsnID - Instruction ID - /// - Ordering - The AtomicOrdering value - GIM_CheckAtomicOrdering, - GIM_CheckAtomicOrderingOrStrongerThan, - GIM_CheckAtomicOrderingWeakerThan, - /// Check the size of the memory access for the given machine memory operand. - /// - InsnID - Instruction ID - /// - MMOIdx - MMO index - /// - Size - The size in bytes of the memory access - GIM_CheckMemorySizeEqualTo, - - /// Check the address space of the memory access for the given machine memory - /// operand. - /// - InsnID - Instruction ID - /// - MMOIdx - MMO index - /// - NumAddrSpace - Number of valid address spaces - /// - AddrSpaceN - An allowed space of the memory access - /// - AddrSpaceN+1 ... - GIM_CheckMemoryAddressSpace, - - /// Check the minimum alignment of the memory access for the given machine - /// memory operand. - /// - InsnID - Instruction ID - /// - MMOIdx - MMO index - /// - MinAlign - Minimum acceptable alignment - GIM_CheckMemoryAlignment, - - /// Check the size of the memory access for the given machine memory operand - /// against the size of an operand. - /// - InsnID - Instruction ID - /// - MMOIdx - MMO index - /// - OpIdx - The operand index to compare the MMO against - GIM_CheckMemorySizeEqualToLLT, - GIM_CheckMemorySizeLessThanLLT, - GIM_CheckMemorySizeGreaterThanLLT, - - /// Check if this is a vector that can be treated as a vector splat - /// constant. This is valid for both G_BUILD_VECTOR as well as - /// G_BUILD_VECTOR_TRUNC. For AllOnes refers to individual bits, so a -1 - /// element. - /// - InsnID - Instruction ID - GIM_CheckIsBuildVectorAllOnes, - GIM_CheckIsBuildVectorAllZeros, - - /// Check a generic C++ instruction predicate - /// - InsnID - Instruction ID - /// - PredicateID - The ID of the predicate function to call - GIM_CheckCxxInsnPredicate, - - /// Check the type for the specified operand - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected type - GIM_CheckType, - /// Check the type of a pointer to any address space. - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - SizeInBits - The size of the pointer value in bits. - GIM_CheckPointerToAny, - /// Check the register bank for the specified operand - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected register bank (specified as a register class) - GIM_CheckRegBankForClass, - - /// Check the operand matches a complex predicate - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - RendererID - The renderer to hold the result - /// - Complex predicate ID - GIM_CheckComplexPattern, - - /// Check the operand is a specific integer - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected integer - GIM_CheckConstantInt, - /// Check the operand is a specific literal integer (i.e. MO.isImm() or - /// MO.isCImm() is true). - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected integer - GIM_CheckLiteralInt, - /// Check the operand is a specific intrinsic ID - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected Intrinsic ID - GIM_CheckIntrinsicID, - - /// Check the operand is a specific predicate - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - Expected predicate - GIM_CheckCmpPredicate, - - /// Check the specified operand is an MBB - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - GIM_CheckIsMBB, - - /// Check the specified operand is an Imm - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - GIM_CheckIsImm, - - /// Check if the specified operand is safe to fold into the current - /// instruction. - /// - InsnID - Instruction ID - GIM_CheckIsSafeToFold, - - /// Check the specified operands are identical. - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - OtherInsnID - Other instruction ID - /// - OtherOpIdx - Other operand index - GIM_CheckIsSameOperand, - - /// Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some - /// named operands that will be recorded in RecordedOperands. Names of these - /// operands are referenced in predicate argument list. Emitter determines - /// StoreIdx(corresponds to the order in which names appear in argument list). - /// - InsnID - Instruction ID - /// - OpIdx - Operand index - /// - StoreIdx - Store location in RecordedOperands. - GIM_RecordNamedOperand, - - /// Fail the current try-block, or completely fail to match if there is no - /// current try-block. - GIM_Reject, - - //=== Renderers === - - /// Mutate an instruction - /// - NewInsnID - Instruction ID to define - /// - OldInsnID - Instruction ID to mutate - /// - NewOpcode - The new opcode to use - GIR_MutateOpcode, - - /// Build a new instruction - /// - InsnID - Instruction ID to define - /// - Opcode - The new opcode to use - GIR_BuildMI, - - /// Copy an operand to the specified instruction - /// - NewInsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to copy from - /// - OpIdx - The operand to copy - GIR_Copy, - - /// Copy an operand to the specified instruction or add a zero register if the - /// operand is a zero immediate. - /// - NewInsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to copy from - /// - OpIdx - The operand to copy - /// - ZeroReg - The zero register to use - GIR_CopyOrAddZeroReg, - /// Copy an operand to the specified instruction - /// - NewInsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to copy from - /// - OpIdx - The operand to copy - /// - SubRegIdx - The subregister to copy - GIR_CopySubReg, - - /// Add an implicit register def to the specified instruction - /// - InsnID - Instruction ID to modify - /// - RegNum - The register to add - GIR_AddImplicitDef, - /// Add an implicit register use to the specified instruction - /// - InsnID - Instruction ID to modify - /// - RegNum - The register to add - GIR_AddImplicitUse, - /// Add an register to the specified instruction - /// - InsnID - Instruction ID to modify - /// - RegNum - The register to add - GIR_AddRegister, - - /// Add a temporary register to the specified instruction - /// - InsnID - Instruction ID to modify - /// - TempRegID - The temporary register ID to add - /// - TempRegFlags - The register flags to set - GIR_AddTempRegister, - - /// Add a temporary register to the specified instruction - /// - InsnID - Instruction ID to modify - /// - TempRegID - The temporary register ID to add - /// - TempRegFlags - The register flags to set - /// - SubRegIndex - The subregister index to set - GIR_AddTempSubRegister, - - /// Add an immediate to the specified instruction - /// - InsnID - Instruction ID to modify - /// - Imm - The immediate to add - GIR_AddImm, - /// Render complex operands to the specified instruction - /// - InsnID - Instruction ID to modify - /// - RendererID - The renderer to call - GIR_ComplexRenderer, - - /// Render sub-operands of complex operands to the specified instruction - /// - InsnID - Instruction ID to modify - /// - RendererID - The renderer to call - /// - RenderOpID - The suboperand to render. - GIR_ComplexSubOperandRenderer, - /// Render operands to the specified instruction using a custom function - /// - InsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to get the matched operand from - /// - RendererFnID - Custom renderer function to call - GIR_CustomRenderer, - - /// Render operands to the specified instruction using a custom function, - /// reading from a specific operand. - /// - InsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to get the matched operand from - /// - OpIdx - Operand index in OldInsnID the render function should read from.. - /// - RendererFnID - Custom renderer function to call - GIR_CustomOperandRenderer, - - /// Render a G_CONSTANT operator as a sign-extended immediate. - /// - NewInsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to copy from - /// The operand index is implicitly 1. - GIR_CopyConstantAsSImm, - - /// Render a G_FCONSTANT operator as a sign-extended immediate. - /// - NewInsnID - Instruction ID to modify - /// - OldInsnID - Instruction ID to copy from - /// The operand index is implicitly 1. - GIR_CopyFConstantAsFPImm, - - /// Constrain an instruction operand to a register class. - /// - InsnID - Instruction ID to modify - /// - OpIdx - Operand index - /// - RCEnum - Register class enumeration value - GIR_ConstrainOperandRC, - - /// Constrain an instructions operands according to the instruction - /// description. - /// - InsnID - Instruction ID to modify - GIR_ConstrainSelectedInstOperands, - - /// Merge all memory operands into instruction. - /// - InsnID - Instruction ID to modify - /// - MergeInsnID... - One or more Instruction ID to merge into the result. - /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to - /// merge. - GIR_MergeMemOperands, - - /// Erase from parent. - /// - InsnID - Instruction ID to erase - GIR_EraseFromParent, - - /// Create a new temporary register that's not constrained. - /// - TempRegID - The temporary register ID to initialize. - /// - Expected type - GIR_MakeTempReg, - - /// A successful emission - GIR_Done, - - /// Increment the rule coverage counter. - /// - RuleID - The ID of the rule that was covered. - GIR_Coverage, - - /// Keeping track of the number of the GI opcodes. Must be the last entry. - GIU_NumOpcodes, -}; - -enum { - /// Indicates the end of the variable-length MergeInsnID list in a - /// GIR_MergeMemOperands opcode. - GIU_MergeMemOperands_EndOfList = -1, -}; - -/// Provides the logic to select generic machine instructions. -class InstructionSelector { -public: - virtual ~InstructionSelector() = default; - - /// Select the (possibly generic) instruction \p I to only use target-specific - /// opcodes. It is OK to insert multiple instructions, but they cannot be - /// generic pre-isel instructions. - /// - /// \returns whether selection succeeded. - /// \pre I.getParent() && I.getParent()->getParent() - /// \post - /// if returns true: - /// for I in all mutated/inserted instructions: - /// !isPreISelGenericOpcode(I.getOpcode()) - virtual bool select(MachineInstr &I) = 0; - - CodeGenCoverage *CoverageInfo = nullptr; - GISelKnownBits *KnownBits = nullptr; - MachineFunction *MF = nullptr; - ProfileSummaryInfo *PSI = nullptr; - BlockFrequencyInfo *BFI = nullptr; - // For some predicates, we need to track the current MBB. - MachineBasicBlock *CurMBB = nullptr; - - virtual void setupGeneratedPerFunctionState(MachineFunction &MF) { - llvm_unreachable("TableGen should have emitted implementation"); - } - - /// Setup per-MF selector state. - virtual void setupMF(MachineFunction &mf, GISelKnownBits *KB, - CodeGenCoverage &covinfo, ProfileSummaryInfo *psi, - BlockFrequencyInfo *bfi) { - CoverageInfo = &covinfo; - KnownBits = KB; - MF = &mf; - PSI = psi; - BFI = bfi; - CurMBB = nullptr; - setupGeneratedPerFunctionState(mf); - } - -protected: - using ComplexRendererFns = - Optional, 4>>; - using RecordedMIVector = SmallVector; - using NewMIVector = SmallVector; - - struct MatcherState { - std::vector Renderers; - RecordedMIVector MIs; - DenseMap TempRegisters; - /// Named operands that predicate with 'let PredicateCodeUsesOperands = 1' - /// referenced in its argument list. Operands are inserted at index set by - /// emitter, it corresponds to the order in which names appear in argument - /// list. Currently such predicates don't have more than 3 arguments. - std::array RecordedOperands; - - MatcherState(unsigned MaxRenderers); - }; - - bool shouldOptForSize(const MachineFunction *MF) const { - const auto &F = MF->getFunction(); - return F.hasOptSize() || F.hasMinSize() || - (PSI && BFI && CurMBB && llvm::shouldOptForSize(*CurMBB, PSI, BFI)); - } - -public: - template - struct ISelInfoTy { - ISelInfoTy(const LLT *TypeObjects, size_t NumTypeObjects, - const PredicateBitset *FeatureBitsets, - const ComplexMatcherMemFn *ComplexPredicates, - const CustomRendererFn *CustomRenderers) - : TypeObjects(TypeObjects), - FeatureBitsets(FeatureBitsets), - ComplexPredicates(ComplexPredicates), - CustomRenderers(CustomRenderers) { - - for (size_t I = 0; I < NumTypeObjects; ++I) - TypeIDMap[TypeObjects[I]] = I; - } - const LLT *TypeObjects; - const PredicateBitset *FeatureBitsets; - const ComplexMatcherMemFn *ComplexPredicates; - const CustomRendererFn *CustomRenderers; - - SmallDenseMap TypeIDMap; - }; - -protected: - InstructionSelector(); - - /// Execute a given matcher table and return true if the match was successful - /// and false otherwise. - template - bool executeMatchTable( - TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, - const ISelInfoTy - &ISelInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage &CoverageInfo) const; - - virtual const int64_t *getMatchTable() const { - llvm_unreachable("Should have been overridden by tablegen if used"); - } - - virtual bool testImmPredicate_I64(unsigned, int64_t) const { - llvm_unreachable( - "Subclasses must override this with a tablegen-erated function"); - } - virtual bool testImmPredicate_APInt(unsigned, const APInt &) const { - llvm_unreachable( - "Subclasses must override this with a tablegen-erated function"); - } - virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const { - llvm_unreachable( - "Subclasses must override this with a tablegen-erated function"); - } - virtual bool testMIPredicate_MI( - unsigned, const MachineInstr &, - const std::array &Operands) const { - llvm_unreachable( - "Subclasses must override this with a tablegen-erated function"); - } - - bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, - const MachineRegisterInfo &MRI) const; - - /// Return true if the specified operand is a G_PTR_ADD with a G_CONSTANT on the - /// right-hand side. GlobalISel's separation of pointer and integer types - /// means that we don't need to worry about G_OR with equivalent semantics. - bool isBaseWithConstantOffset(const MachineOperand &Root, - const MachineRegisterInfo &MRI) const; - - /// Return true if MI can obviously be folded into IntoMI. - /// MI and IntoMI do not need to be in the same basic blocks, but MI must - /// precede IntoMI. - bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h deleted file mode 100644 index bc9f952146..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ /dev/null @@ -1,1157 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file declares the API for the instruction selector. -/// This class is responsible for selecting machine instructions. -/// It's implemented by the target. It's used by the InstructionSelect pass. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H -#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" -#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -namespace llvm { - -/// GlobalISel PatFrag Predicates -enum { - GIPFP_I64_Invalid = 0, - GIPFP_APInt_Invalid = 0, - GIPFP_APFloat_Invalid = 0, - GIPFP_MI_Invalid = 0, -}; - -template -bool InstructionSelector::executeMatchTable( - TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, - const ISelInfoTy - &ISelInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage &CoverageInfo) const { - - uint64_t CurrentIdx = 0; - SmallVector OnFailResumeAt; - - // Bypass the flag check on the instruction, and only look at the MCInstrDesc. - bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException(); - - const uint16_t Flags = State.MIs[0]->getFlags(); - - enum RejectAction { RejectAndGiveUp, RejectAndResume }; - auto handleReject = [&]() -> RejectAction { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Rejected\n"); - if (OnFailResumeAt.empty()) - return RejectAndGiveUp; - CurrentIdx = OnFailResumeAt.pop_back_val(); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " (" - << OnFailResumeAt.size() << " try-blocks remain)\n"); - return RejectAndResume; - }; - - auto propagateFlags = [=](NewMIVector &OutMIs) { - for (auto MIB : OutMIs) { - // Set the NoFPExcept flag when no original matched instruction could - // raise an FP exception, but the new instruction potentially might. - uint16_t MIBFlags = Flags; - if (NoFPException && MIB->mayRaiseFPException()) - MIBFlags |= MachineInstr::NoFPExcept; - MIB.setMIFlags(MIBFlags); - } - - return true; - }; - - while (true) { - assert(CurrentIdx != ~0u && "Invalid MatchTable index"); - int64_t MatcherOpcode = MatchTable[CurrentIdx++]; - switch (MatcherOpcode) { - case GIM_Try: { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Begin try-block\n"); - OnFailResumeAt.push_back(MatchTable[CurrentIdx++]); - break; - } - - case GIM_RecordInsn: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - - // As an optimisation we require that MIs[0] is always the root. Refuse - // any attempt to modify it. - assert(NewInsnID != 0 && "Refusing to modify MIs[0]"); - - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isReg()) { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Not a register\n"); - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - if (Register::isPhysicalRegister(MO.getReg())) { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Is a physical register\n"); - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - MachineInstr *NewMI = MRI.getVRegDef(MO.getReg()); - if ((size_t)NewInsnID < State.MIs.size()) - State.MIs[NewInsnID] = NewMI; - else { - assert((size_t)NewInsnID == State.MIs.size() && - "Expected to store MIs in order"); - State.MIs.push_back(NewMI); - } - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": MIs[" << NewInsnID - << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx - << ")\n"); - break; - } - - case GIM_CheckFeatures: { - int64_t ExpectedBitsetID = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIM_CheckFeatures(ExpectedBitsetID=" - << ExpectedBitsetID << ")\n"); - if ((AvailableFeatures & ISelInfo.FeatureBitsets[ExpectedBitsetID]) != - ISelInfo.FeatureBitsets[ExpectedBitsetID]) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - - case GIM_CheckOpcode: - case GIM_CheckOpcodeIsEither: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Expected0 = MatchTable[CurrentIdx++]; - int64_t Expected1 = -1; - if (MatcherOpcode == GIM_CheckOpcodeIsEither) - Expected1 = MatchTable[CurrentIdx++]; - - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - unsigned Opcode = State.MIs[InsnID]->getOpcode(); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID - << "], ExpectedOpcode=" << Expected0; - if (MatcherOpcode == GIM_CheckOpcodeIsEither) - dbgs() << " || " << Expected1; - dbgs() << ") // Got=" << Opcode << "\n"; - ); - - if (Opcode != Expected0 && Opcode != Expected1) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_SwitchOpcode: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t LowerBound = MatchTable[CurrentIdx++]; - int64_t UpperBound = MatchTable[CurrentIdx++]; - int64_t Default = MatchTable[CurrentIdx++]; - - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - const int64_t Opcode = State.MIs[InsnID]->getOpcode(); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { - dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], [" - << LowerBound << ", " << UpperBound << "), Default=" << Default - << ", JumpTable...) // Got=" << Opcode << "\n"; - }); - if (Opcode < LowerBound || UpperBound <= Opcode) { - CurrentIdx = Default; - break; - } - CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)]; - if (!CurrentIdx) { - CurrentIdx = Default; - break; - } - OnFailResumeAt.push_back(Default); - break; - } - - case GIM_SwitchType: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t LowerBound = MatchTable[CurrentIdx++]; - int64_t UpperBound = MatchTable[CurrentIdx++]; - int64_t Default = MatchTable[CurrentIdx++]; - - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { - dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID - << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", " - << UpperBound << "), Default=" << Default - << ", JumpTable...) // Got="; - if (!MO.isReg()) - dbgs() << "Not a VReg\n"; - else - dbgs() << MRI.getType(MO.getReg()) << "\n"; - }); - if (!MO.isReg()) { - CurrentIdx = Default; - break; - } - const LLT Ty = MRI.getType(MO.getReg()); - const auto TyI = ISelInfo.TypeIDMap.find(Ty); - if (TyI == ISelInfo.TypeIDMap.end()) { - CurrentIdx = Default; - break; - } - const int64_t TypeID = TyI->second; - if (TypeID < LowerBound || UpperBound <= TypeID) { - CurrentIdx = Default; - break; - } - CurrentIdx = MatchTable[CurrentIdx + (TypeID - LowerBound)]; - if (!CurrentIdx) { - CurrentIdx = Default; - break; - } - OnFailResumeAt.push_back(Default); - break; - } - - case GIM_CheckNumOperands: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Expected = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs[" - << InsnID << "], Expected=" << Expected << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (State.MIs[InsnID]->getNumOperands() != Expected) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_CheckI64ImmPredicate: - case GIM_CheckImmOperandPredicate: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatcherOpcode == GIM_CheckImmOperandPredicate - ? MatchTable[CurrentIdx++] - : 1; - int64_t Predicate = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), Predicate=" << Predicate << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() || - State.MIs[InsnID]->getOperand(OpIdx).isCImm()) && - "Expected immediate operand"); - assert(Predicate > GIPFP_I64_Invalid && "Expected a valid predicate"); - int64_t Value = 0; - if (State.MIs[InsnID]->getOperand(OpIdx).isCImm()) - Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue(); - else if (State.MIs[InsnID]->getOperand(OpIdx).isImm()) - Value = State.MIs[InsnID]->getOperand(OpIdx).getImm(); - else - llvm_unreachable("Expected Imm or CImm operand"); - - if (!testImmPredicate_I64(Predicate, Value)) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckAPIntImmPredicate: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Predicate = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() - << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs[" - << InsnID << "], Predicate=" << Predicate << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT && - "Expected G_CONSTANT"); - assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate"); - APInt Value; - if (State.MIs[InsnID]->getOperand(1).isCImm()) - Value = State.MIs[InsnID]->getOperand(1).getCImm()->getValue(); - else - llvm_unreachable("Expected Imm or CImm operand"); - - if (!testImmPredicate_APInt(Predicate, Value)) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckAPFloatImmPredicate: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Predicate = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() - << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs[" - << InsnID << "], Predicate=" << Predicate << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && - "Expected G_FCONSTANT"); - assert(State.MIs[InsnID]->getOperand(1).isFPImm() && "Expected FPImm operand"); - assert(Predicate > GIPFP_APFloat_Invalid && "Expected a valid predicate"); - APFloat Value = State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF(); - - if (!testImmPredicate_APFloat(Predicate, Value)) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckIsBuildVectorAllOnes: - case GIM_CheckIsBuildVectorAllZeros: { - int64_t InsnID = MatchTable[CurrentIdx++]; - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs[" - << InsnID << "])\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - - const MachineInstr *MI = State.MIs[InsnID]; - assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR || - MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) && - "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC"); - - if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) { - if (!isBuildVectorAllOnes(*MI, MRI)) { - if (handleReject() == RejectAndGiveUp) - return false; - } - } else { - if (!isBuildVectorAllZeros(*MI, MRI)) { - if (handleReject() == RejectAndGiveUp) - return false; - } - } - - break; - } - case GIM_CheckCxxInsnPredicate: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Predicate = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() - << CurrentIdx << ": GIM_CheckCxxPredicate(MIs[" - << InsnID << "], Predicate=" << Predicate << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate"); - - if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], - State.RecordedOperands)) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckAtomicOrdering: { - int64_t InsnID = MatchTable[CurrentIdx++]; - AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs[" - << InsnID << "], " << (uint64_t)Ordering << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) - if (handleReject() == RejectAndGiveUp) - return false; - - for (const auto &MMO : State.MIs[InsnID]->memoperands()) - if (MMO->getMergedOrdering() != Ordering) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckAtomicOrderingOrStrongerThan: { - int64_t InsnID = MatchTable[CurrentIdx++]; - AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs[" - << InsnID << "], " << (uint64_t)Ordering << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) - if (handleReject() == RejectAndGiveUp) - return false; - - for (const auto &MMO : State.MIs[InsnID]->memoperands()) - if (!isAtLeastOrStrongerThan(MMO->getMergedOrdering(), Ordering)) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckAtomicOrderingWeakerThan: { - int64_t InsnID = MatchTable[CurrentIdx++]; - AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIM_CheckAtomicOrderingWeakerThan(MIs[" - << InsnID << "], " << (uint64_t)Ordering << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) - if (handleReject() == RejectAndGiveUp) - return false; - - for (const auto &MMO : State.MIs[InsnID]->memoperands()) - if (!isStrongerThan(Ordering, MMO->getMergedOrdering())) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckMemoryAddressSpace: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t MMOIdx = MatchTable[CurrentIdx++]; - // This accepts a list of possible address spaces. - const int NumAddrSpace = MatchTable[CurrentIdx++]; - - if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - // Need to still jump to the end of the list of address spaces if we find - // a match earlier. - const uint64_t LastIdx = CurrentIdx + NumAddrSpace; - - const MachineMemOperand *MMO - = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); - const unsigned MMOAddrSpace = MMO->getAddrSpace(); - - bool Success = false; - for (int I = 0; I != NumAddrSpace; ++I) { - unsigned AddrSpace = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE( - TgtInstructionSelector::getName(), - dbgs() << "addrspace(" << MMOAddrSpace << ") vs " - << AddrSpace << '\n'); - - if (AddrSpace == MMOAddrSpace) { - Success = true; - break; - } - } - - CurrentIdx = LastIdx; - if (!Success && handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckMemoryAlignment: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t MMOIdx = MatchTable[CurrentIdx++]; - unsigned MinAlign = MatchTable[CurrentIdx++]; - - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - - if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - MachineMemOperand *MMO - = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment" - << "(MIs[" << InsnID << "]->memoperands() + " << MMOIdx - << ")->getAlignment() >= " << MinAlign << ")\n"); - if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp) - return false; - - break; - } - case GIM_CheckMemorySizeEqualTo: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t MMOIdx = MatchTable[CurrentIdx++]; - uint64_t Size = MatchTable[CurrentIdx++]; - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIM_CheckMemorySizeEqual(MIs[" << InsnID - << "]->memoperands() + " << MMOIdx - << ", Size=" << Size << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - - if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << MMO->getSize() << " bytes vs " << Size - << " bytes\n"); - if (MMO->getSize() != Size) - if (handleReject() == RejectAndGiveUp) - return false; - - break; - } - case GIM_CheckMemorySizeEqualToLLT: - case GIM_CheckMemorySizeLessThanLLT: - case GIM_CheckMemorySizeGreaterThanLLT: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t MMOIdx = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - - DEBUG_WITH_TYPE( - TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckMemorySize" - << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT - ? "EqualTo" - : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT - ? "GreaterThan" - : "LessThan") - << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx - << ", OpIdx=" << OpIdx << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isReg()) { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": Not a register\n"); - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); - - unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); - if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && - MMO->getSizeInBits() != Size) { - if (handleReject() == RejectAndGiveUp) - return false; - } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && - MMO->getSizeInBits() >= Size) { - if (handleReject() == RejectAndGiveUp) - return false; - } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && - MMO->getSizeInBits() <= Size) - if (handleReject() == RejectAndGiveUp) - return false; - - break; - } - case GIM_CheckType: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t TypeID = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID - << "]->getOperand(" << OpIdx - << "), TypeID=" << TypeID << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isReg() || - MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_CheckPointerToAny: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - uint64_t SizeInBits = MatchTable[CurrentIdx++]; - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), SizeInBits=" << SizeInBits << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - const LLT Ty = MRI.getType(MO.getReg()); - - // iPTR must be looked up in the target. - if (SizeInBits == 0) { - MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent(); - const unsigned AddrSpace = Ty.getAddressSpace(); - SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace); - } - - assert(SizeInBits != 0 && "Pointer size must be known"); - - if (MO.isReg()) { - if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) - if (handleReject() == RejectAndGiveUp) - return false; - } else if (handleReject() == RejectAndGiveUp) - return false; - - break; - } - case GIM_RecordNamedOperand: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - uint64_t StoreIdx = MatchTable[CurrentIdx++]; - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), StoreIdx=" << StoreIdx << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(StoreIdx < State.RecordedOperands.size() && "Index out of range"); - State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx); - break; - } - case GIM_CheckRegBankForClass: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t RCEnum = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), RCEnum=" << RCEnum << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isReg() || - &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum), - MRI.getType(MO.getReg())) != - RBI.getRegBank(MO.getReg(), MRI, TRI)) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - - case GIM_CheckComplexPattern: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t RendererID = MatchTable[CurrentIdx++]; - int64_t ComplexPredicateID = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": State.Renderers[" << RendererID - << "] = GIM_CheckComplexPattern(MIs[" << InsnID - << "]->getOperand(" << OpIdx - << "), ComplexPredicateID=" << ComplexPredicateID - << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - // FIXME: Use std::invoke() when it's available. - ComplexRendererFns Renderer = - (ISel.*ISelInfo.ComplexPredicates[ComplexPredicateID])( - State.MIs[InsnID]->getOperand(OpIdx)); - if (Renderer.hasValue()) - State.Renderers[RendererID] = Renderer.getValue(); - else - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - - case GIM_CheckConstantInt: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t Value = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), Value=" << Value << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (MO.isReg()) { - // isOperandImmEqual() will sign-extend to 64-bits, so should we. - LLT Ty = MRI.getType(MO.getReg()); - Value = SignExtend64(Value, Ty.getSizeInBits()); - - if (!isOperandImmEqual(MO, Value, MRI)) { - if (handleReject() == RejectAndGiveUp) - return false; - } - } else if (handleReject() == RejectAndGiveUp) - return false; - - break; - } - - case GIM_CheckLiteralInt: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t Value = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), Value=" << Value << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (MO.isImm() && MO.getImm() == Value) - break; - - if (MO.isCImm() && MO.getCImm()->equalsInt(Value)) - break; - - if (handleReject() == RejectAndGiveUp) - return false; - - break; - } - - case GIM_CheckIntrinsicID: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t Value = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), Value=" << Value << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckCmpPredicate: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t Value = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs[" - << InsnID << "]->getOperand(" << OpIdx - << "), Value=" << Value << ")\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); - if (!MO.isPredicate() || MO.getPredicate() != Value) - if (handleReject() == RejectAndGiveUp) - return false; - break; - } - case GIM_CheckIsMBB: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID - << "]->getOperand(" << OpIdx << "))\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_CheckIsImm: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID - << "]->getOperand(" << OpIdx << "))\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_CheckIsSafeToFold: { - int64_t InsnID = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(MIs[" - << InsnID << "])\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!isObviouslySafeToFold(*State.MIs[InsnID], *State.MIs[0])) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_CheckIsSameOperand: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t OtherInsnID = MatchTable[CurrentIdx++]; - int64_t OtherOpIdx = MatchTable[CurrentIdx++]; - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs[" - << InsnID << "][" << OpIdx << "], MIs[" - << OtherInsnID << "][" << OtherOpIdx << "])\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->getOperand(OpIdx).isIdenticalTo( - State.MIs[OtherInsnID]->getOperand(OtherOpIdx))) { - if (handleReject() == RejectAndGiveUp) - return false; - } - break; - } - case GIM_Reject: - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_Reject\n"); - if (handleReject() == RejectAndGiveUp) - return false; - break; - - case GIR_MutateOpcode: { - int64_t OldInsnID = MatchTable[CurrentIdx++]; - uint64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t NewOpcode = MatchTable[CurrentIdx++]; - if (NewInsnID >= OutMIs.size()) - OutMIs.resize(NewInsnID + 1); - - OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(), - State.MIs[OldInsnID]); - OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode)); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" - << NewInsnID << "], MIs[" << OldInsnID << "], " - << NewOpcode << ")\n"); - break; - } - - case GIR_BuildMI: { - uint64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t Opcode = MatchTable[CurrentIdx++]; - if (NewInsnID >= OutMIs.size()) - OutMIs.resize(NewInsnID + 1); - - OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0], - State.MIs[0]->getDebugLoc(), TII.get(Opcode)); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" - << NewInsnID << "], " << Opcode << ")\n"); - break; - } - - case GIR_Copy: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); - OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx)); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() - << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID - << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n"); - break; - } - - case GIR_CopyOrAddZeroReg: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t ZeroReg = MatchTable[CurrentIdx++]; - assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); - MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx); - if (isOperandImmEqual(MO, 0, MRI)) - OutMIs[NewInsnID].addReg(ZeroReg); - else - OutMIs[NewInsnID].add(MO); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs[" - << NewInsnID << "], MIs[" << OldInsnID << "], " - << OpIdx << ", " << ZeroReg << ")\n"); - break; - } - - case GIR_CopySubReg: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t SubRegIdx = MatchTable[CurrentIdx++]; - assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); - OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(), - 0, SubRegIdx); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs[" - << NewInsnID << "], MIs[" << OldInsnID << "], " - << OpIdx << ", " << SubRegIdx << ")\n"); - break; - } - - case GIR_AddImplicitDef: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t RegNum = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - OutMIs[InsnID].addDef(RegNum, RegState::Implicit); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs[" - << InsnID << "], " << RegNum << ")\n"); - break; - } - - case GIR_AddImplicitUse: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t RegNum = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - OutMIs[InsnID].addUse(RegNum, RegState::Implicit); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs[" - << InsnID << "], " << RegNum << ")\n"); - break; - } - - case GIR_AddRegister: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t RegNum = MatchTable[CurrentIdx++]; - uint64_t RegFlags = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - OutMIs[InsnID].addReg(RegNum, RegFlags); - DEBUG_WITH_TYPE( - TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs[" - << InsnID << "], " << RegNum << ", " << RegFlags << ")\n"); - break; - } - - case GIR_AddTempRegister: - case GIR_AddTempSubRegister: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t TempRegID = MatchTable[CurrentIdx++]; - uint64_t TempRegFlags = MatchTable[CurrentIdx++]; - unsigned SubReg = 0; - if (MatcherOpcode == GIR_AddTempSubRegister) - SubReg = MatchTable[CurrentIdx++]; - - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - - OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags, SubReg); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" - << InsnID << "], TempRegisters[" << TempRegID - << "]"; - if (SubReg) - dbgs() << '.' << TRI.getSubRegIndexName(SubReg); - dbgs() << ", " << TempRegFlags << ")\n"); - break; - } - - case GIR_AddImm: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Imm = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - OutMIs[InsnID].addImm(Imm); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID - << "], " << Imm << ")\n"); - break; - } - - case GIR_ComplexRenderer: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t RendererID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - for (const auto &RenderOpFn : State.Renderers[RendererID]) - RenderOpFn(OutMIs[InsnID]); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs[" - << InsnID << "], " << RendererID << ")\n"); - break; - } - case GIR_ComplexSubOperandRenderer: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t RendererID = MatchTable[CurrentIdx++]; - int64_t RenderOpID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIR_ComplexSubOperandRenderer(OutMIs[" - << InsnID << "], " << RendererID << ", " - << RenderOpID << ")\n"); - break; - } - - case GIR_CopyConstantAsSImm: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); - assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT"); - if (State.MIs[OldInsnID]->getOperand(1).isCImm()) { - OutMIs[NewInsnID].addImm( - State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue()); - } else if (State.MIs[OldInsnID]->getOperand(1).isImm()) - OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1)); - else - llvm_unreachable("Expected Imm or CImm operand"); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs[" - << NewInsnID << "], MIs[" << OldInsnID << "])\n"); - break; - } - - // TODO: Needs a test case once we have a pattern that uses this. - case GIR_CopyFConstantAsFPImm: { - int64_t NewInsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); - assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && "Expected G_FCONSTANT"); - if (State.MIs[OldInsnID]->getOperand(1).isFPImm()) - OutMIs[NewInsnID].addFPImm( - State.MIs[OldInsnID]->getOperand(1).getFPImm()); - else - llvm_unreachable("Expected FPImm operand"); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs[" - << NewInsnID << "], MIs[" << OldInsnID << "])\n"); - break; - } - - case GIR_CustomRenderer: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - int64_t RendererFnID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs[" - << InsnID << "], MIs[" << OldInsnID << "], " - << RendererFnID << ")\n"); - (ISel.*ISelInfo.CustomRenderers[RendererFnID])( - OutMIs[InsnID], *State.MIs[OldInsnID], - -1); // Not a source operand of the old instruction. - break; - } - case GIR_CustomOperandRenderer: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OldInsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t RendererFnID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - - DEBUG_WITH_TYPE( - TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_CustomOperandRenderer(OutMIs[" - << InsnID << "], MIs[" << OldInsnID << "]->getOperand(" - << OpIdx << "), " - << RendererFnID << ")\n"); - (ISel.*ISelInfo.CustomRenderers[RendererFnID])(OutMIs[InsnID], - *State.MIs[OldInsnID], - OpIdx); - break; - } - case GIR_ConstrainOperandRC: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t OpIdx = MatchTable[CurrentIdx++]; - int64_t RCEnum = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - MachineInstr &I = *OutMIs[InsnID].getInstr(); - MachineFunction &MF = *I.getParent()->getParent(); - MachineRegisterInfo &MRI = MF.getRegInfo(); - const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum); - MachineOperand &MO = I.getOperand(OpIdx); - constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs[" - << InsnID << "], " << OpIdx << ", " << RCEnum - << ")\n"); - break; - } - - case GIR_ConstrainSelectedInstOperands: { - int64_t InsnID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI, - RBI); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx - << ": GIR_ConstrainSelectedInstOperands(OutMIs[" - << InsnID << "])\n"); - break; - } - - case GIR_MergeMemOperands: { - int64_t InsnID = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs[" - << InsnID << "]"); - int64_t MergeInsnID = GIU_MergeMemOperands_EndOfList; - while ((MergeInsnID = MatchTable[CurrentIdx++]) != - GIU_MergeMemOperands_EndOfList) { - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << ", MIs[" << MergeInsnID << "]"); - for (const auto &MMO : State.MIs[MergeInsnID]->memoperands()) - OutMIs[InsnID].addMemOperand(MMO); - } - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << ")\n"); - break; - } - - case GIR_EraseFromParent: { - int64_t InsnID = MatchTable[CurrentIdx++]; - assert(State.MIs[InsnID] && - "Attempted to erase an undefined instruction"); - State.MIs[InsnID]->eraseFromParent(); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" - << InsnID << "])\n"); - break; - } - - case GIR_MakeTempReg: { - int64_t TempRegID = MatchTable[CurrentIdx++]; - int64_t TypeID = MatchTable[CurrentIdx++]; - - State.TempRegisters[TempRegID] = - MRI.createGenericVirtualRegister(ISelInfo.TypeObjects[TypeID]); - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": TempRegs[" << TempRegID - << "] = GIR_MakeTempReg(" << TypeID << ")\n"); - break; - } - - case GIR_Coverage: { - int64_t RuleID = MatchTable[CurrentIdx++]; - CoverageInfo.setCovered(RuleID); - - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() - << CurrentIdx << ": GIR_Coverage(" << RuleID << ")"); - break; - } - - case GIR_Done: - DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_Done\n"); - propagateFlags(OutMIs); - return true; - - default: - llvm_unreachable("Unexpected command"); - } - } -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h deleted file mode 100644 index 281ca39ccd..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h +++ /dev/null @@ -1,481 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Interface for Targets to specify which operations they can successfully -/// select and how the others should be expanded most efficiently. -/// This implementation has been deprecated for a long time but it still in use -/// in a few places. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H -#define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include - -namespace llvm { -struct LegalityQuery; - -namespace LegacyLegalizeActions { -enum LegacyLegalizeAction : std::uint8_t { - /// The operation is expected to be selectable directly by the target, and - /// no transformation is necessary. - Legal, - - /// The operation should be synthesized from multiple instructions acting on - /// a narrower scalar base-type. For example a 64-bit add might be - /// implemented in terms of 32-bit add-with-carry. - NarrowScalar, - - /// The operation should be implemented in terms of a wider scalar - /// base-type. For example a <2 x s8> add could be implemented as a <2 - /// x s32> add (ignoring the high bits). - WidenScalar, - - /// The (vector) operation should be implemented by splitting it into - /// sub-vectors where the operation is legal. For example a <8 x s64> add - /// might be implemented as 4 separate <2 x s64> adds. - FewerElements, - - /// The (vector) operation should be implemented by widening the input - /// vector and ignoring the lanes added by doing so. For example <2 x i8> is - /// rarely legal, but you might perform an <8 x i8> and then only look at - /// the first two results. - MoreElements, - - /// Perform the operation on a different, but equivalently sized type. - Bitcast, - - /// The operation itself must be expressed in terms of simpler actions on - /// this target. E.g. a SREM replaced by an SDIV and subtraction. - Lower, - - /// The operation should be implemented as a call to some kind of runtime - /// support library. For example this usually happens on machines that don't - /// support floating-point operations natively. - Libcall, - - /// The target wants to do something special with this combination of - /// operand and type. A callback will be issued when it is needed. - Custom, - - /// This operation is completely unsupported on the target. A programming - /// error has occurred. - Unsupported, - - /// Sentinel value for when no action was found in the specified table. - NotFound, -}; -} // end namespace LegacyLegalizeActions -raw_ostream &operator<<(raw_ostream &OS, - LegacyLegalizeActions::LegacyLegalizeAction Action); - -/// Legalization is decided based on an instruction's opcode, which type slot -/// we're considering, and what the existing type is. These aspects are gathered -/// together for convenience in the InstrAspect class. -struct InstrAspect { - unsigned Opcode; - unsigned Idx = 0; - LLT Type; - - InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {} - InstrAspect(unsigned Opcode, unsigned Idx, LLT Type) - : Opcode(Opcode), Idx(Idx), Type(Type) {} - - bool operator==(const InstrAspect &RHS) const { - return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type; - } -}; - -/// The result of a query. It either indicates a final answer of Legal or -/// Unsupported or describes an action that must be taken to make an operation -/// more legal. -struct LegacyLegalizeActionStep { - /// The action to take or the final answer. - LegacyLegalizeActions::LegacyLegalizeAction Action; - /// If describing an action, the type index to change. Otherwise zero. - unsigned TypeIdx; - /// If describing an action, the new type for TypeIdx. Otherwise LLT{}. - LLT NewType; - - LegacyLegalizeActionStep(LegacyLegalizeActions::LegacyLegalizeAction Action, - unsigned TypeIdx, const LLT NewType) - : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {} - - bool operator==(const LegacyLegalizeActionStep &RHS) const { - return std::tie(Action, TypeIdx, NewType) == - std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType); - } -}; - - -class LegacyLegalizerInfo { -public: - using SizeAndAction = - std::pair; - using SizeAndActionsVec = std::vector; - using SizeChangeStrategy = - std::function; - - LegacyLegalizerInfo(); - - static bool needsLegalizingToDifferentSize( - const LegacyLegalizeActions::LegacyLegalizeAction Action) { - using namespace LegacyLegalizeActions; - switch (Action) { - case NarrowScalar: - case WidenScalar: - case FewerElements: - case MoreElements: - case Unsupported: - return true; - default: - return false; - } - } - - /// Compute any ancillary tables needed to quickly decide how an operation - /// should be handled. This must be called after all "set*Action"methods but - /// before any query is made or incorrect results may be returned. - void computeTables(); - - /// More friendly way to set an action for common types that have an LLT - /// representation. - /// The LegacyLegalizeAction must be one for which - /// NeedsLegalizingToDifferentSize returns false. - void setAction(const InstrAspect &Aspect, - LegacyLegalizeActions::LegacyLegalizeAction Action) { - assert(!needsLegalizingToDifferentSize(Action)); - TablesInitialized = false; - const unsigned OpcodeIdx = Aspect.Opcode - FirstOp; - if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx) - SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1); - SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action; - } - - /// The setAction calls record the non-size-changing legalization actions - /// to take on specifically-sized types. The SizeChangeStrategy defines what - /// to do when the size of the type needs to be changed to reach a legally - /// sized type (i.e., one that was defined through a setAction call). - /// e.g. - /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal); - /// setLegalizeScalarToDifferentSizeStrategy( - /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest); - /// will end up defining getAction({G_ADD, 0, T}) to return the following - /// actions for different scalar types T: - /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)} - /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)} - /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)} - /// - /// If no SizeChangeAction gets defined, through this function, - /// the default is unsupportedForDifferentSizes. - void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, - const unsigned TypeIdx, - SizeChangeStrategy S) { - const unsigned OpcodeIdx = Opcode - FirstOp; - if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx) - ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1); - ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S; - } - - /// See also setLegalizeScalarToDifferentSizeStrategy. - /// This function allows to set the SizeChangeStrategy for vector elements. - void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode, - const unsigned TypeIdx, - SizeChangeStrategy S) { - const unsigned OpcodeIdx = Opcode - FirstOp; - if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx) - VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1); - VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S; - } - - /// A SizeChangeStrategy for the common case where legalization for a - /// particular operation consists of only supporting a specific set of type - /// sizes. E.g. - /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal); - /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal); - /// setLegalizeScalarToDifferentSizeStrategy( - /// G_DIV, 0, unsupportedForDifferentSizes); - /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64, - /// and Unsupported for all other scalar types T. - static SizeAndActionsVec - unsupportedForDifferentSizes(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported, - Unsupported); - } - - /// A SizeChangeStrategy for the common case where legalization for a - /// particular operation consists of widening the type to a large legal type, - /// unless there is no such type and then instead it should be narrowed to the - /// largest legal type. - static SizeAndActionsVec - widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - assert(v.size() > 0 && - "At least one size that can be legalized towards is needed" - " for this SizeChangeStrategy"); - return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, - NarrowScalar); - } - - static SizeAndActionsVec - widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, - Unsupported); - } - - static SizeAndActionsVec - narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, - Unsupported); - } - - static SizeAndActionsVec - narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - assert(v.size() > 0 && - "At least one size that can be legalized towards is needed" - " for this SizeChangeStrategy"); - return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, - WidenScalar); - } - - /// A SizeChangeStrategy for the common case where legalization for a - /// particular vector operation consists of having more elements in the - /// vector, to a type that is legal. Unless there is no such type and then - /// instead it should be legalized towards the widest vector that's still - /// legal. E.g. - /// setAction({G_ADD, LLT::vector(8, 8)}, Legal); - /// setAction({G_ADD, LLT::vector(16, 8)}, Legal); - /// setAction({G_ADD, LLT::vector(2, 32)}, Legal); - /// setAction({G_ADD, LLT::vector(4, 32)}, Legal); - /// setLegalizeVectorElementToDifferentSizeStrategy( - /// G_ADD, 0, moreToWiderTypesAndLessToWidest); - /// will result in the following getAction results: - /// * getAction({G_ADD, LLT::vector(8,8)}) returns - /// (Legal, vector(8,8)). - /// * getAction({G_ADD, LLT::vector(9,8)}) returns - /// (MoreElements, vector(16,8)). - /// * getAction({G_ADD, LLT::vector(8,32)}) returns - /// (FewerElements, vector(4,32)). - static SizeAndActionsVec - moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) { - using namespace LegacyLegalizeActions; - return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements, - FewerElements); - } - - /// Helper function to implement many typical SizeChangeStrategy functions. - static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest( - const SizeAndActionsVec &v, - LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction, - LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction); - /// Helper function to implement many typical SizeChangeStrategy functions. - static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest( - const SizeAndActionsVec &v, - LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction, - LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction); - - LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const; - - unsigned getOpcodeIdxForOpcode(unsigned Opcode) const; - -private: - /// Determine what action should be taken to legalize the given generic - /// instruction opcode, type-index and type. Requires computeTables to have - /// been called. - /// - /// \returns a pair consisting of the kind of legalization that should be - /// performed and the destination type. - std::pair - getAspectAction(const InstrAspect &Aspect) const; - - /// The SizeAndActionsVec is a representation mapping between all natural - /// numbers and an Action. The natural number represents the bit size of - /// the InstrAspect. For example, for a target with native support for 32-bit - /// and 64-bit additions, you'd express that as: - /// setScalarAction(G_ADD, 0, - /// {{1, WidenScalar}, // bit sizes [ 1, 31[ - /// {32, Legal}, // bit sizes [32, 33[ - /// {33, WidenScalar}, // bit sizes [33, 64[ - /// {64, Legal}, // bit sizes [64, 65[ - /// {65, NarrowScalar} // bit sizes [65, +inf[ - /// }); - /// It may be that only 64-bit pointers are supported on your target: - /// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1), - /// {{1, Unsupported}, // bit sizes [ 1, 63[ - /// {64, Legal}, // bit sizes [64, 65[ - /// {65, Unsupported}, // bit sizes [65, +inf[ - /// }); - void setScalarAction(const unsigned Opcode, const unsigned TypeIndex, - const SizeAndActionsVec &SizeAndActions) { - const unsigned OpcodeIdx = Opcode - FirstOp; - SmallVector &Actions = ScalarActions[OpcodeIdx]; - setActions(TypeIndex, Actions, SizeAndActions); - } - void setPointerAction(const unsigned Opcode, const unsigned TypeIndex, - const unsigned AddressSpace, - const SizeAndActionsVec &SizeAndActions) { - const unsigned OpcodeIdx = Opcode - FirstOp; - if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) == - AddrSpace2PointerActions[OpcodeIdx].end()) - AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}}; - SmallVector &Actions = - AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second; - setActions(TypeIndex, Actions, SizeAndActions); - } - - /// If an operation on a given vector type (say ) isn't explicitly - /// specified, we proceed in 2 stages. First we legalize the underlying scalar - /// (so that there's at least one legal vector with that scalar), then we - /// adjust the number of elements in the vector so that it is legal. The - /// desired action in the first step is controlled by this function. - void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex, - const SizeAndActionsVec &SizeAndActions) { - unsigned OpcodeIdx = Opcode - FirstOp; - SmallVector &Actions = - ScalarInVectorActions[OpcodeIdx]; - setActions(TypeIndex, Actions, SizeAndActions); - } - - /// See also setScalarInVectorAction. - /// This function let's you specify the number of elements in a vector that - /// are legal for a legal element size. - void setVectorNumElementAction(const unsigned Opcode, - const unsigned TypeIndex, - const unsigned ElementSize, - const SizeAndActionsVec &SizeAndActions) { - const unsigned OpcodeIdx = Opcode - FirstOp; - if (NumElements2Actions[OpcodeIdx].find(ElementSize) == - NumElements2Actions[OpcodeIdx].end()) - NumElements2Actions[OpcodeIdx][ElementSize] = {{}}; - SmallVector &Actions = - NumElements2Actions[OpcodeIdx].find(ElementSize)->second; - setActions(TypeIndex, Actions, SizeAndActions); - } - - /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes, - /// i.e. it's OK if it doesn't start from size 1. - static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) { - using namespace LegacyLegalizeActions; -#ifndef NDEBUG - // The sizes should be in increasing order - int prev_size = -1; - for(auto SizeAndAction: v) { - assert(SizeAndAction.first > prev_size); - prev_size = SizeAndAction.first; - } - // - for every Widen action, there should be a larger bitsize that - // can be legalized towards (e.g. Legal, Lower, Libcall or Custom - // action). - // - for every Narrow action, there should be a smaller bitsize that - // can be legalized towards. - int SmallestNarrowIdx = -1; - int LargestWidenIdx = -1; - int SmallestLegalizableToSameSizeIdx = -1; - int LargestLegalizableToSameSizeIdx = -1; - for(size_t i=0; i SmallestLegalizableToSameSizeIdx); - } - if (LargestWidenIdx != -1) - assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx); -#endif - } - - /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with - /// from size 1. - static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) { -#ifndef NDEBUG - // Data structure invariant: The first bit size must be size 1. - assert(v.size() >= 1); - assert(v[0].first == 1); - checkPartialSizeAndActionsVector(v); -#endif - } - - /// Sets actions for all bit sizes on a particular generic opcode, type - /// index and scalar or pointer type. - void setActions(unsigned TypeIndex, - SmallVector &Actions, - const SizeAndActionsVec &SizeAndActions) { - checkFullSizeAndActionsVector(SizeAndActions); - if (Actions.size() <= TypeIndex) - Actions.resize(TypeIndex + 1); - Actions[TypeIndex] = SizeAndActions; - } - - static SizeAndAction findAction(const SizeAndActionsVec &Vec, - const uint32_t Size); - - /// Returns the next action needed to get the scalar or pointer type closer - /// to being legal - /// E.g. findLegalAction({G_REM, 13}) should return - /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will - /// probably be called, which should return (Lower, 32). - /// This is assuming the setScalarAction on G_REM was something like: - /// setScalarAction(G_REM, 0, - /// {{1, WidenScalar}, // bit sizes [ 1, 31[ - /// {32, Lower}, // bit sizes [32, 33[ - /// {33, NarrowScalar} // bit sizes [65, +inf[ - /// }); - std::pair - findScalarLegalAction(const InstrAspect &Aspect) const; - - /// Returns the next action needed towards legalizing the vector type. - std::pair - findVectorLegalAction(const InstrAspect &Aspect) const; - - static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; - static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; - - // Data structures used temporarily during construction of legality data: - using TypeMap = DenseMap; - SmallVector SpecifiedActions[LastOp - FirstOp + 1]; - SmallVector - ScalarSizeChangeStrategies[LastOp - FirstOp + 1]; - SmallVector - VectorElementSizeChangeStrategies[LastOp - FirstOp + 1]; - bool TablesInitialized = false; - - // Data structures used by getAction: - SmallVector ScalarActions[LastOp - FirstOp + 1]; - SmallVector ScalarInVectorActions[LastOp - FirstOp + 1]; - std::unordered_map> - AddrSpace2PointerActions[LastOp - FirstOp + 1]; - std::unordered_map> - NumElements2Actions[LastOp - FirstOp + 1]; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h deleted file mode 100644 index 38d2fe2806..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ /dev/null @@ -1,1297 +0,0 @@ -//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This file contains some helper functions which try to cleanup artifacts -// such as G_TRUNCs/G_[ZSA]EXTENDS that were created during legalization to make -// the types match. This file also contains some combines of merges that happens -// at the end of the legalization. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H -#define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H - -#include "llvm/ADT/SmallBitVector.h" -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" -#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" -#include "llvm/CodeGen/GlobalISel/Legalizer.h" -#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" -#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/Debug.h" - -#define DEBUG_TYPE "legalizer" -using namespace llvm::MIPatternMatch; - -namespace llvm { -class LegalizationArtifactCombiner { - MachineIRBuilder &Builder; - MachineRegisterInfo &MRI; - const LegalizerInfo &LI; - - static bool isArtifactCast(unsigned Opc) { - switch (Opc) { - case TargetOpcode::G_TRUNC: - case TargetOpcode::G_SEXT: - case TargetOpcode::G_ZEXT: - case TargetOpcode::G_ANYEXT: - return true; - default: - return false; - } - } - -public: - LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, - const LegalizerInfo &LI) - : Builder(B), MRI(MRI), LI(LI) {} - - bool tryCombineAnyExt(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs, - GISelObserverWrapper &Observer) { - assert(MI.getOpcode() == TargetOpcode::G_ANYEXT); - - Builder.setInstrAndDebugLoc(MI); - Register DstReg = MI.getOperand(0).getReg(); - Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); - - // aext(trunc x) - > aext/copy/trunc x - Register TruncSrc; - if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { - LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - if (MRI.getType(DstReg) == MRI.getType(TruncSrc)) - replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs, - Observer); - else - Builder.buildAnyExtOrTrunc(DstReg, TruncSrc); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); - return true; - } - - // aext([asz]ext x) -> [asz]ext x - Register ExtSrc; - MachineInstr *ExtMI; - if (mi_match(SrcReg, MRI, - m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)), - m_GSExt(m_Reg(ExtSrc)), - m_GZExt(m_Reg(ExtSrc)))))) { - Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc}); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *ExtMI, DeadInsts); - return true; - } - - // Try to fold aext(g_constant) when the larger constant type is legal. - auto *SrcMI = MRI.getVRegDef(SrcReg); - if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { - const LLT DstTy = MRI.getType(DstReg); - if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { - auto &CstVal = SrcMI->getOperand(1); - Builder.buildConstant( - DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits())); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *SrcMI, DeadInsts); - return true; - } - } - return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs); - } - - bool tryCombineZExt(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs, - GISelObserverWrapper &Observer) { - assert(MI.getOpcode() == TargetOpcode::G_ZEXT); - - Builder.setInstrAndDebugLoc(MI); - Register DstReg = MI.getOperand(0).getReg(); - Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); - - // zext(trunc x) - > and (aext/copy/trunc x), mask - // zext(sext x) -> and (sext x), mask - Register TruncSrc; - Register SextSrc; - if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) || - mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) { - LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || - isConstantUnsupported(DstTy)) - return false; - LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - LLT SrcTy = MRI.getType(SrcReg); - APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits()); - auto Mask = Builder.buildConstant( - DstTy, MaskVal.zext(DstTy.getScalarSizeInBits())); - if (SextSrc && (DstTy != MRI.getType(SextSrc))) - SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0); - if (TruncSrc && (DstTy != MRI.getType(TruncSrc))) - TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0); - Builder.buildAnd(DstReg, SextSrc ? SextSrc : TruncSrc, Mask); - markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); - return true; - } - - // zext(zext x) -> (zext x) - Register ZextSrc; - if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) { - LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI); - Observer.changingInstr(MI); - MI.getOperand(1).setReg(ZextSrc); - Observer.changedInstr(MI); - UpdatedDefs.push_back(DstReg); - markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); - return true; - } - - // Try to fold zext(g_constant) when the larger constant type is legal. - auto *SrcMI = MRI.getVRegDef(SrcReg); - if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { - const LLT DstTy = MRI.getType(DstReg); - if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { - auto &CstVal = SrcMI->getOperand(1); - Builder.buildConstant( - DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits())); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *SrcMI, DeadInsts); - return true; - } - } - return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs); - } - - bool tryCombineSExt(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs) { - assert(MI.getOpcode() == TargetOpcode::G_SEXT); - - Builder.setInstrAndDebugLoc(MI); - Register DstReg = MI.getOperand(0).getReg(); - Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); - - // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c) - Register TruncSrc; - if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { - LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}})) - return false; - LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - LLT SrcTy = MRI.getType(SrcReg); - uint64_t SizeInBits = SrcTy.getScalarSizeInBits(); - if (DstTy != MRI.getType(TruncSrc)) - TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0); - Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits); - markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); - return true; - } - - // sext(zext x) -> (zext x) - // sext(sext x) -> (sext x) - Register ExtSrc; - MachineInstr *ExtMI; - if (mi_match(SrcReg, MRI, - m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)), - m_GSExt(m_Reg(ExtSrc)))))) { - LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI); - Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc}); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); - return true; - } - - // Try to fold sext(g_constant) when the larger constant type is legal. - auto *SrcMI = MRI.getVRegDef(SrcReg); - if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { - const LLT DstTy = MRI.getType(DstReg); - if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { - auto &CstVal = SrcMI->getOperand(1); - Builder.buildConstant( - DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits())); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *SrcMI, DeadInsts); - return true; - } - } - - return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs); - } - - bool tryCombineTrunc(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs, - GISelObserverWrapper &Observer) { - assert(MI.getOpcode() == TargetOpcode::G_TRUNC); - - Builder.setInstr(MI); - Register DstReg = MI.getOperand(0).getReg(); - Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); - - // Try to fold trunc(g_constant) when the smaller constant type is legal. - auto *SrcMI = MRI.getVRegDef(SrcReg); - if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { - const LLT DstTy = MRI.getType(DstReg); - if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { - auto &CstVal = SrcMI->getOperand(1); - Builder.buildConstant( - DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits())); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *SrcMI, DeadInsts); - return true; - } - } - - // Try to fold trunc(merge) to directly use the source of the merge. - // This gets rid of large, difficult to legalize, merges - if (auto *SrcMerge = dyn_cast(SrcMI)) { - const Register MergeSrcReg = SrcMerge->getSourceReg(0); - const LLT MergeSrcTy = MRI.getType(MergeSrcReg); - const LLT DstTy = MRI.getType(DstReg); - - // We can only fold if the types are scalar - const unsigned DstSize = DstTy.getSizeInBits(); - const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits(); - if (!DstTy.isScalar() || !MergeSrcTy.isScalar()) - return false; - - if (DstSize < MergeSrcSize) { - // When the merge source is larger than the destination, we can just - // truncate the merge source directly - if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}})) - return false; - - LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: " - << MI); - - Builder.buildTrunc(DstReg, MergeSrcReg); - UpdatedDefs.push_back(DstReg); - } else if (DstSize == MergeSrcSize) { - // If the sizes match we can simply try to replace the register - LLVM_DEBUG( - dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: " - << MI); - replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs, - Observer); - } else if (DstSize % MergeSrcSize == 0) { - // If the trunc size is a multiple of the merge source size we can use - // a smaller merge instead - if (isInstUnsupported( - {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}})) - return false; - - LLVM_DEBUG( - dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: " - << MI); - - const unsigned NumSrcs = DstSize / MergeSrcSize; - assert(NumSrcs < SrcMI->getNumOperands() - 1 && - "trunc(merge) should require less inputs than merge"); - SmallVector SrcRegs(NumSrcs); - for (unsigned i = 0; i < NumSrcs; ++i) - SrcRegs[i] = SrcMerge->getSourceReg(i); - - Builder.buildMerge(DstReg, SrcRegs); - UpdatedDefs.push_back(DstReg); - } else { - // Unable to combine - return false; - } - - markInstAndDefDead(MI, *SrcMerge, DeadInsts); - return true; - } - - // trunc(trunc) -> trunc - Register TruncSrc; - if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { - // Always combine trunc(trunc) since the eventual resulting trunc must be - // legal anyway as it must be legal for all outputs of the consumer type - // set. - LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI); - - Builder.buildTrunc(DstReg, TruncSrc); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts); - return true; - } - - return false; - } - - /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF). - bool tryFoldImplicitDef(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs) { - unsigned Opcode = MI.getOpcode(); - assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT || - Opcode == TargetOpcode::G_SEXT); - - if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, - MI.getOperand(1).getReg(), MRI)) { - Builder.setInstr(MI); - Register DstReg = MI.getOperand(0).getReg(); - LLT DstTy = MRI.getType(DstReg); - - if (Opcode == TargetOpcode::G_ANYEXT) { - // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF - if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) - return false; - LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;); - Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {}); - UpdatedDefs.push_back(DstReg); - } else { - // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top - // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT. - if (isConstantUnsupported(DstTy)) - return false; - LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;); - Builder.buildConstant(DstReg, 0); - UpdatedDefs.push_back(DstReg); - } - - markInstAndDefDead(MI, *DefMI, DeadInsts); - return true; - } - return false; - } - - bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs) { - - assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES); - - const unsigned CastOpc = CastMI.getOpcode(); - - if (!isArtifactCast(CastOpc)) - return false; - - const unsigned NumDefs = MI.getNumOperands() - 1; - - const Register CastSrcReg = CastMI.getOperand(1).getReg(); - const LLT CastSrcTy = MRI.getType(CastSrcReg); - const LLT DestTy = MRI.getType(MI.getOperand(0).getReg()); - const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg()); - - const unsigned CastSrcSize = CastSrcTy.getSizeInBits(); - const unsigned DestSize = DestTy.getSizeInBits(); - - if (CastOpc == TargetOpcode::G_TRUNC) { - if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) { - // %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>) - // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1 - // => - // %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0 - // %2:_(s8) = G_TRUNC %6 - // %3:_(s8) = G_TRUNC %7 - // %4:_(s8) = G_TRUNC %8 - // %5:_(s8) = G_TRUNC %9 - - unsigned UnmergeNumElts = - DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1; - LLT UnmergeTy = CastSrcTy.changeElementCount( - ElementCount::getFixed(UnmergeNumElts)); - - if (isInstUnsupported( - {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}})) - return false; - - Builder.setInstr(MI); - auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg); - - for (unsigned I = 0; I != NumDefs; ++I) { - Register DefReg = MI.getOperand(I).getReg(); - UpdatedDefs.push_back(DefReg); - Builder.buildTrunc(DefReg, NewUnmerge.getReg(I)); - } - - markInstAndDefDead(MI, CastMI, DeadInsts); - return true; - } - - if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) { - // %1:_(s16) = G_TRUNC %0(s32) - // %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1 - // => - // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0 - - // Unmerge(trunc) can be combined if the trunc source size is a multiple - // of the unmerge destination size - if (CastSrcSize % DestSize != 0) - return false; - - // Check if the new unmerge is supported - if (isInstUnsupported( - {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}})) - return false; - - // Gather the original destination registers and create new ones for the - // unused bits - const unsigned NewNumDefs = CastSrcSize / DestSize; - SmallVector DstRegs(NewNumDefs); - for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) { - if (Idx < NumDefs) - DstRegs[Idx] = MI.getOperand(Idx).getReg(); - else - DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy); - } - - // Build new unmerge - Builder.setInstr(MI); - Builder.buildUnmerge(DstRegs, CastSrcReg); - UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs); - markInstAndDefDead(MI, CastMI, DeadInsts); - return true; - } - } - - // TODO: support combines with other casts as well - return false; - } - - static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp, - LLT OpTy, LLT DestTy) { - // Check if we found a definition that is like G_MERGE_VALUES. - switch (MergeOp) { - default: - return false; - case TargetOpcode::G_BUILD_VECTOR: - case TargetOpcode::G_MERGE_VALUES: - // The convert operation that we will need to insert is - // going to convert the input of that type of instruction (scalar) - // to the destination type (DestTy). - // The conversion needs to stay in the same domain (scalar to scalar - // and vector to vector), so if we were to allow to fold the merge - // we would need to insert some bitcasts. - // E.g., - // <2 x s16> = build_vector s16, s16 - // <2 x s32> = zext <2 x s16> - // <2 x s16>, <2 x s16> = unmerge <2 x s32> - // - // As is the folding would produce: - // <2 x s16> = zext s16 <-- scalar to vector - // <2 x s16> = zext s16 <-- scalar to vector - // Which is invalid. - // Instead we would want to generate: - // s32 = zext s16 - // <2 x s16> = bitcast s32 - // s32 = zext s16 - // <2 x s16> = bitcast s32 - // - // That is not done yet. - if (ConvertOp == 0) - return true; - return !DestTy.isVector() && OpTy.isVector() && - DestTy == OpTy.getElementType(); - case TargetOpcode::G_CONCAT_VECTORS: { - if (ConvertOp == 0) - return true; - if (!DestTy.isVector()) - return false; - - const unsigned OpEltSize = OpTy.getElementType().getSizeInBits(); - - // Don't handle scalarization with a cast that isn't in the same - // direction as the vector cast. This could be handled, but it would - // require more intermediate unmerges. - if (ConvertOp == TargetOpcode::G_TRUNC) - return DestTy.getSizeInBits() <= OpEltSize; - return DestTy.getSizeInBits() >= OpEltSize; - } - } - } - - /// Try to replace DstReg with SrcReg or build a COPY instruction - /// depending on the register constraints. - static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg, - MachineRegisterInfo &MRI, - MachineIRBuilder &Builder, - SmallVectorImpl &UpdatedDefs, - GISelChangeObserver &Observer) { - if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) { - Builder.buildCopy(DstReg, SrcReg); - UpdatedDefs.push_back(DstReg); - return; - } - SmallVector UseMIs; - // Get the users and notify the observer before replacing. - for (auto &UseMI : MRI.use_instructions(DstReg)) { - UseMIs.push_back(&UseMI); - Observer.changingInstr(UseMI); - } - // Replace the registers. - MRI.replaceRegWith(DstReg, SrcReg); - UpdatedDefs.push_back(SrcReg); - // Notify the observer that we changed the instructions. - for (auto *UseMI : UseMIs) - Observer.changedInstr(*UseMI); - } - - /// Return the operand index in \p MI that defines \p Def - static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) { - unsigned DefIdx = 0; - for (const MachineOperand &Def : MI.defs()) { - if (Def.getReg() == SearchDef) - break; - ++DefIdx; - } - - return DefIdx; - } - - /// This class provides utilities for finding source registers of specific - /// bit ranges in an artifact. The routines can look through the source - /// registers if they're other artifacts to try to find a non-artifact source - /// of a value. - class ArtifactValueFinder { - MachineRegisterInfo &MRI; - MachineIRBuilder &MIB; - const LegalizerInfo &LI; - - // Stores the best register found in the current query so far. - Register CurrentBest = Register(); - - /// Given an concat_vector op \p Concat and a start bit and size, try to - /// find the origin of the value defined by that start position and size. - /// - /// \returns a register with the requested size, or the current best - /// register found during the current query. - Register findValueFromConcat(GConcatVectors &Concat, unsigned StartBit, - unsigned Size) { - assert(Size > 0); - - // Find the source operand that provides the bits requested. - Register Src1Reg = Concat.getSourceReg(0); - unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits(); - - // Operand index of the source that provides the start of the bit range. - unsigned StartSrcIdx = (StartBit / SrcSize) + 1; - // Offset into the source at which the bit range starts. - unsigned InRegOffset = StartBit % SrcSize; - // Check that the bits don't span multiple sources. - // FIXME: we might be able return multiple sources? Or create an - // appropriate concat to make it fit. - if (InRegOffset + Size > SrcSize) - return CurrentBest; - - Register SrcReg = Concat.getReg(StartSrcIdx); - if (InRegOffset == 0 && Size == SrcSize) { - CurrentBest = SrcReg; - return findValueFromDefImpl(SrcReg, 0, Size); - } - - return findValueFromDefImpl(SrcReg, InRegOffset, Size); - } - - /// Given an build_vector op \p BV and a start bit and size, try to find - /// the origin of the value defined by that start position and size. - /// - /// \returns a register with the requested size, or the current best - /// register found during the current query. - Register findValueFromBuildVector(GBuildVector &BV, unsigned StartBit, - unsigned Size) { - assert(Size > 0); - - // Find the source operand that provides the bits requested. - Register Src1Reg = BV.getSourceReg(0); - unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits(); - - // Operand index of the source that provides the start of the bit range. - unsigned StartSrcIdx = (StartBit / SrcSize) + 1; - // Offset into the source at which the bit range starts. - unsigned InRegOffset = StartBit % SrcSize; - - if (InRegOffset != 0) - return CurrentBest; // Give up, bits don't start at a scalar source. - if (Size < SrcSize) - return CurrentBest; // Scalar source is too large for requested bits. - - // If the bits cover multiple sources evenly, then create a new - // build_vector to synthesize the required size, if that's been requested. - if (Size > SrcSize) { - if (Size % SrcSize > 0) - return CurrentBest; // Isn't covered exactly by sources. - - unsigned NumSrcsUsed = Size / SrcSize; - // If we're requesting all of the sources, just return this def. - if (NumSrcsUsed == BV.getNumSources()) - return BV.getReg(0); - - LLT SrcTy = MRI.getType(Src1Reg); - LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy); - - // Check if the resulting build vector would be legal. - LegalizeActionStep ActionStep = - LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}}); - if (ActionStep.Action != LegalizeActions::Legal) - return CurrentBest; - - SmallVector NewSrcs; - for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed; - ++SrcIdx) - NewSrcs.push_back(BV.getReg(SrcIdx)); - MIB.setInstrAndDebugLoc(BV); - return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0); - } - // A single source is requested, just return it. - return BV.getReg(StartSrcIdx); - } - - /// Given an G_INSERT op \p MI and a start bit and size, try to find - /// the origin of the value defined by that start position and size. - /// - /// \returns a register with the requested size, or the current best - /// register found during the current query. - Register findValueFromInsert(MachineInstr &MI, unsigned StartBit, - unsigned Size) { - assert(MI.getOpcode() == TargetOpcode::G_INSERT); - assert(Size > 0); - - Register ContainerSrcReg = MI.getOperand(1).getReg(); - Register InsertedReg = MI.getOperand(2).getReg(); - LLT InsertedRegTy = MRI.getType(InsertedReg); - unsigned InsertOffset = MI.getOperand(3).getImm(); - - // There are 4 possible container/insertreg + requested bit-range layouts - // that the instruction and query could be representing. - // For: %_ = G_INSERT %CONTAINER, %INS, InsOff (abbrev. to 'IO') - // and a start bit 'SB', with size S, giving an end bit 'EB', we could - // have... - // Scenario A: - // -------------------------- - // | INS | CONTAINER | - // -------------------------- - // | | - // SB EB - // - // Scenario B: - // -------------------------- - // | INS | CONTAINER | - // -------------------------- - // | | - // SB EB - // - // Scenario C: - // -------------------------- - // | CONTAINER | INS | - // -------------------------- - // | | - // SB EB - // - // Scenario D: - // -------------------------- - // | CONTAINER | INS | - // -------------------------- - // | | - // SB EB - // - // So therefore, A and D are requesting data from the INS operand, while - // B and C are requesting from the container operand. - - unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits(); - unsigned EndBit = StartBit + Size; - unsigned NewStartBit; - Register SrcRegToUse; - if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) { - SrcRegToUse = ContainerSrcReg; - NewStartBit = StartBit; - return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size); - } - if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) { - SrcRegToUse = InsertedReg; - NewStartBit = StartBit - InsertOffset; - if (NewStartBit == 0 && - Size == MRI.getType(SrcRegToUse).getSizeInBits()) - CurrentBest = SrcRegToUse; - return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size); - } - // The bit range spans both the inserted and container regions. - return Register(); - } - - /// Internal implementation for findValueFromDef(). findValueFromDef() - /// initializes some data like the CurrentBest register, which this method - /// and its callees rely upon. - Register findValueFromDefImpl(Register DefReg, unsigned StartBit, - unsigned Size) { - MachineInstr *Def = getDefIgnoringCopies(DefReg, MRI); - // If the instruction has a single def, then simply delegate the search. - // For unmerge however with multiple defs, we need to compute the offset - // into the source of the unmerge. - switch (Def->getOpcode()) { - case TargetOpcode::G_CONCAT_VECTORS: - return findValueFromConcat(cast(*Def), StartBit, Size); - case TargetOpcode::G_UNMERGE_VALUES: { - unsigned DefStartBit = 0; - unsigned DefSize = MRI.getType(DefReg).getSizeInBits(); - for (const auto &MO : Def->defs()) { - if (MO.getReg() == DefReg) - break; - DefStartBit += DefSize; - } - Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg(); - Register SrcOriginReg = - findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size); - if (SrcOriginReg) - return SrcOriginReg; - // Failed to find a further value. If the StartBit and Size perfectly - // covered the requested DefReg, return that since it's better than - // nothing. - if (StartBit == 0 && Size == DefSize) - return DefReg; - return CurrentBest; - } - case TargetOpcode::G_BUILD_VECTOR: - return findValueFromBuildVector(cast(*Def), StartBit, - Size); - case TargetOpcode::G_INSERT: - return findValueFromInsert(*Def, StartBit, Size); - default: - return CurrentBest; - } - } - - public: - ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder, - const LegalizerInfo &Info) - : MRI(Mri), MIB(Builder), LI(Info) {} - - /// Try to find a source of the value defined in the def \p DefReg, starting - /// at position \p StartBit with size \p Size. - /// \returns a register with the requested size, or an empty Register if no - /// better value could be found. - Register findValueFromDef(Register DefReg, unsigned StartBit, - unsigned Size) { - CurrentBest = Register(); - Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size); - return FoundReg != DefReg ? FoundReg : Register(); - } - - /// Try to combine the defs of an unmerge \p MI by attempting to find - /// values that provides the bits for each def reg. - /// \returns true if all the defs of the unmerge have been made dead. - bool tryCombineUnmergeDefs(GUnmerge &MI, GISelChangeObserver &Observer, - SmallVectorImpl &UpdatedDefs) { - unsigned NumDefs = MI.getNumDefs(); - LLT DestTy = MRI.getType(MI.getReg(0)); - - SmallBitVector DeadDefs(NumDefs); - for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) { - Register DefReg = MI.getReg(DefIdx); - if (MRI.use_nodbg_empty(DefReg)) { - DeadDefs[DefIdx] = true; - continue; - } - Register FoundVal = findValueFromDef(DefReg, 0, DestTy.getSizeInBits()); - if (!FoundVal) - continue; - if (MRI.getType(FoundVal) != DestTy) - continue; - - replaceRegOrBuildCopy(DefReg, FoundVal, MRI, MIB, UpdatedDefs, - Observer); - // We only want to replace the uses, not the def of the old reg. - Observer.changingInstr(MI); - MI.getOperand(DefIdx).setReg(DefReg); - Observer.changedInstr(MI); - DeadDefs[DefIdx] = true; - } - return DeadDefs.all(); - } - }; - - bool tryCombineUnmergeValues(GUnmerge &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs, - GISelChangeObserver &Observer) { - unsigned NumDefs = MI.getNumDefs(); - Register SrcReg = MI.getSourceReg(); - MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI); - if (!SrcDef) - return false; - - LLT OpTy = MRI.getType(SrcReg); - LLT DestTy = MRI.getType(MI.getReg(0)); - unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg); - - Builder.setInstrAndDebugLoc(MI); - - ArtifactValueFinder Finder(MRI, Builder, LI); - if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) { - markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx); - return true; - } - - if (auto *SrcUnmerge = dyn_cast(SrcDef)) { - // %0:_(<4 x s16>) = G_FOO - // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0 - // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1 - // - // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0 - Register SrcUnmergeSrc = SrcUnmerge->getSourceReg(); - LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc); - - // If we need to decrease the number of vector elements in the result type - // of an unmerge, this would involve the creation of an equivalent unmerge - // to copy back to the original result registers. - LegalizeActionStep ActionStep = LI.getAction( - {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}}); - switch (ActionStep.Action) { - case LegalizeActions::Lower: - case LegalizeActions::Unsupported: - break; - case LegalizeActions::FewerElements: - case LegalizeActions::NarrowScalar: - if (ActionStep.TypeIdx == 1) - return false; - break; - default: - return false; - } - - auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc); - - // TODO: Should we try to process out the other defs now? If the other - // defs of the source unmerge are also unmerged, we end up with a separate - // unmerge for each one. - for (unsigned I = 0; I != NumDefs; ++I) { - Register Def = MI.getReg(I); - replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I), - MRI, Builder, UpdatedDefs, Observer); - } - - markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx); - return true; - } - - MachineInstr *MergeI = SrcDef; - unsigned ConvertOp = 0; - - // Handle intermediate conversions - unsigned SrcOp = SrcDef->getOpcode(); - if (isArtifactCast(SrcOp)) { - ConvertOp = SrcOp; - MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI); - } - - if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(), - ConvertOp, OpTy, DestTy)) { - // We might have a chance to combine later by trying to combine - // unmerge(cast) first - return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs); - } - - const unsigned NumMergeRegs = MergeI->getNumOperands() - 1; - - if (NumMergeRegs < NumDefs) { - if (NumDefs % NumMergeRegs != 0) - return false; - - Builder.setInstr(MI); - // Transform to UNMERGEs, for example - // %1 = G_MERGE_VALUES %4, %5 - // %9, %10, %11, %12 = G_UNMERGE_VALUES %1 - // to - // %9, %10 = G_UNMERGE_VALUES %4 - // %11, %12 = G_UNMERGE_VALUES %5 - - const unsigned NewNumDefs = NumDefs / NumMergeRegs; - for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) { - SmallVector DstRegs; - for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs; - ++j, ++DefIdx) - DstRegs.push_back(MI.getReg(DefIdx)); - - if (ConvertOp) { - LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg()); - - // This is a vector that is being split and casted. Extract to the - // element type, and do the conversion on the scalars (or smaller - // vectors). - LLT MergeEltTy = MergeSrcTy.divide(NewNumDefs); - - // Handle split to smaller vectors, with conversions. - // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>) - // %3(<8 x s16>) = G_SEXT %2 - // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %3 - // - // => - // - // %8(<2 x s8>), %9(<2 x s8>) = G_UNMERGE_VALUES %0 - // %10(<2 x s8>), %11(<2 x s8>) = G_UNMERGE_VALUES %1 - // %4(<2 x s16>) = G_SEXT %8 - // %5(<2 x s16>) = G_SEXT %9 - // %6(<2 x s16>) = G_SEXT %10 - // %7(<2 x s16>)= G_SEXT %11 - - SmallVector TmpRegs(NewNumDefs); - for (unsigned k = 0; k < NewNumDefs; ++k) - TmpRegs[k] = MRI.createGenericVirtualRegister(MergeEltTy); - - Builder.buildUnmerge(TmpRegs, MergeI->getOperand(Idx + 1).getReg()); - - for (unsigned k = 0; k < NewNumDefs; ++k) - Builder.buildInstr(ConvertOp, {DstRegs[k]}, {TmpRegs[k]}); - } else { - Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg()); - } - UpdatedDefs.append(DstRegs.begin(), DstRegs.end()); - } - - } else if (NumMergeRegs > NumDefs) { - if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0) - return false; - - Builder.setInstr(MI); - // Transform to MERGEs - // %6 = G_MERGE_VALUES %17, %18, %19, %20 - // %7, %8 = G_UNMERGE_VALUES %6 - // to - // %7 = G_MERGE_VALUES %17, %18 - // %8 = G_MERGE_VALUES %19, %20 - - const unsigned NumRegs = NumMergeRegs / NumDefs; - for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) { - SmallVector Regs; - for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs; - ++j, ++Idx) - Regs.push_back(MergeI->getOperand(Idx).getReg()); - - Register DefReg = MI.getReg(DefIdx); - Builder.buildMerge(DefReg, Regs); - UpdatedDefs.push_back(DefReg); - } - - } else { - LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg()); - - if (!ConvertOp && DestTy != MergeSrcTy) - ConvertOp = TargetOpcode::G_BITCAST; - - if (ConvertOp) { - Builder.setInstr(MI); - - for (unsigned Idx = 0; Idx < NumDefs; ++Idx) { - Register DefReg = MI.getOperand(Idx).getReg(); - Register MergeSrc = MergeI->getOperand(Idx + 1).getReg(); - - if (!MRI.use_empty(DefReg)) { - Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc}); - UpdatedDefs.push_back(DefReg); - } - } - - markInstAndDefDead(MI, *MergeI, DeadInsts); - return true; - } - - assert(DestTy == MergeSrcTy && - "Bitcast and the other kinds of conversions should " - "have happened earlier"); - - Builder.setInstr(MI); - for (unsigned Idx = 0; Idx < NumDefs; ++Idx) { - Register DstReg = MI.getOperand(Idx).getReg(); - Register SrcReg = MergeI->getOperand(Idx + 1).getReg(); - replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs, - Observer); - } - } - - markInstAndDefDead(MI, *MergeI, DeadInsts); - return true; - } - - bool tryCombineExtract(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs) { - assert(MI.getOpcode() == TargetOpcode::G_EXTRACT); - - // Try to use the source registers from a G_MERGE_VALUES - // - // %2 = G_MERGE_VALUES %0, %1 - // %3 = G_EXTRACT %2, N - // => - // - // for N < %2.getSizeInBits() / 2 - // %3 = G_EXTRACT %0, N - // - // for N >= %2.getSizeInBits() / 2 - // %3 = G_EXTRACT %1, (N - %0.getSizeInBits() - - Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); - MachineInstr *MergeI = MRI.getVRegDef(SrcReg); - if (!MergeI || !isa(MergeI)) - return false; - - Register DstReg = MI.getOperand(0).getReg(); - LLT DstTy = MRI.getType(DstReg); - LLT SrcTy = MRI.getType(SrcReg); - - // TODO: Do we need to check if the resulting extract is supported? - unsigned ExtractDstSize = DstTy.getSizeInBits(); - unsigned Offset = MI.getOperand(2).getImm(); - unsigned NumMergeSrcs = MergeI->getNumOperands() - 1; - unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs; - unsigned MergeSrcIdx = Offset / MergeSrcSize; - - // Compute the offset of the last bit the extract needs. - unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize; - - // Can't handle the case where the extract spans multiple inputs. - if (MergeSrcIdx != EndMergeSrcIdx) - return false; - - // TODO: We could modify MI in place in most cases. - Builder.setInstr(MI); - Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(), - Offset - MergeSrcIdx * MergeSrcSize); - UpdatedDefs.push_back(DstReg); - markInstAndDefDead(MI, *MergeI, DeadInsts); - return true; - } - - /// Try to combine away MI. - /// Returns true if it combined away the MI. - /// Adds instructions that are dead as a result of the combine - /// into DeadInsts, which can include MI. - bool tryCombineInstruction(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - GISelObserverWrapper &WrapperObserver) { - // This might be a recursive call, and we might have DeadInsts already - // populated. To avoid bad things happening later with multiple vreg defs - // etc, process the dead instructions now if any. - if (!DeadInsts.empty()) - deleteMarkedDeadInsts(DeadInsts, WrapperObserver); - - // Put here every vreg that was redefined in such a way that it's at least - // possible that one (or more) of its users (immediate or COPY-separated) - // could become artifact combinable with the new definition (or the - // instruction reachable from it through a chain of copies if any). - SmallVector UpdatedDefs; - bool Changed = false; - switch (MI.getOpcode()) { - default: - return false; - case TargetOpcode::G_ANYEXT: - Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver); - break; - case TargetOpcode::G_ZEXT: - Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver); - break; - case TargetOpcode::G_SEXT: - Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs); - break; - case TargetOpcode::G_UNMERGE_VALUES: - Changed = tryCombineUnmergeValues(cast(MI), DeadInsts, - UpdatedDefs, WrapperObserver); - break; - case TargetOpcode::G_MERGE_VALUES: - case TargetOpcode::G_BUILD_VECTOR: - case TargetOpcode::G_CONCAT_VECTORS: - // If any of the users of this merge are an unmerge, then add them to the - // artifact worklist in case there's folding that can be done looking up. - for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) { - if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES || - U.getOpcode() == TargetOpcode::G_TRUNC) { - UpdatedDefs.push_back(MI.getOperand(0).getReg()); - break; - } - } - break; - case TargetOpcode::G_EXTRACT: - Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs); - break; - case TargetOpcode::G_TRUNC: - Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver); - if (!Changed) { - // Try to combine truncates away even if they are legal. As all artifact - // combines at the moment look only "up" the def-use chains, we achieve - // that by throwing truncates' users (with look through copies) into the - // ArtifactList again. - UpdatedDefs.push_back(MI.getOperand(0).getReg()); - } - break; - } - // If the main loop through the ArtifactList found at least one combinable - // pair of artifacts, not only combine it away (as done above), but also - // follow the def-use chain from there to combine everything that can be - // combined within this def-use chain of artifacts. - while (!UpdatedDefs.empty()) { - Register NewDef = UpdatedDefs.pop_back_val(); - assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg"); - for (MachineInstr &Use : MRI.use_instructions(NewDef)) { - switch (Use.getOpcode()) { - // Keep this list in sync with the list of all artifact combines. - case TargetOpcode::G_ANYEXT: - case TargetOpcode::G_ZEXT: - case TargetOpcode::G_SEXT: - case TargetOpcode::G_UNMERGE_VALUES: - case TargetOpcode::G_EXTRACT: - case TargetOpcode::G_TRUNC: - // Adding Use to ArtifactList. - WrapperObserver.changedInstr(Use); - break; - case TargetOpcode::COPY: { - Register Copy = Use.getOperand(0).getReg(); - if (Copy.isVirtual()) - UpdatedDefs.push_back(Copy); - break; - } - default: - // If we do not have an artifact combine for the opcode, there is no - // point in adding it to the ArtifactList as nothing interesting will - // be done to it anyway. - break; - } - } - } - return Changed; - } - -private: - static Register getArtifactSrcReg(const MachineInstr &MI) { - switch (MI.getOpcode()) { - case TargetOpcode::COPY: - case TargetOpcode::G_TRUNC: - case TargetOpcode::G_ZEXT: - case TargetOpcode::G_ANYEXT: - case TargetOpcode::G_SEXT: - case TargetOpcode::G_EXTRACT: - return MI.getOperand(1).getReg(); - case TargetOpcode::G_UNMERGE_VALUES: - return MI.getOperand(MI.getNumOperands() - 1).getReg(); - default: - llvm_unreachable("Not a legalization artifact happen"); - } - } - - /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI - /// (either by killing it or changing operands) results in DefMI being dead - /// too. In-between COPYs or artifact-casts are also collected if they are - /// dead. - /// MI is not marked dead. - void markDefDead(MachineInstr &MI, MachineInstr &DefMI, - SmallVectorImpl &DeadInsts, - unsigned DefIdx = 0) { - // Collect all the copy instructions that are made dead, due to deleting - // this instruction. Collect all of them until the Trunc(DefMI). - // Eg, - // %1(s1) = G_TRUNC %0(s32) - // %2(s1) = COPY %1(s1) - // %3(s1) = COPY %2(s1) - // %4(s32) = G_ANYEXT %3(s1) - // In this case, we would have replaced %4 with a copy of %0, - // and as a result, %3, %2, %1 are dead. - MachineInstr *PrevMI = &MI; - while (PrevMI != &DefMI) { - Register PrevRegSrc = getArtifactSrcReg(*PrevMI); - - MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc); - if (MRI.hasOneUse(PrevRegSrc)) { - if (TmpDef != &DefMI) { - assert((TmpDef->getOpcode() == TargetOpcode::COPY || - isArtifactCast(TmpDef->getOpcode())) && - "Expecting copy or artifact cast here"); - - DeadInsts.push_back(TmpDef); - } - } else - break; - PrevMI = TmpDef; - } - - if (PrevMI == &DefMI) { - unsigned I = 0; - bool IsDead = true; - for (MachineOperand &Def : DefMI.defs()) { - if (I != DefIdx) { - if (!MRI.use_empty(Def.getReg())) { - IsDead = false; - break; - } - } else { - if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg())) - break; - } - - ++I; - } - - if (IsDead) - DeadInsts.push_back(&DefMI); - } - } - - /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be - /// dead due to MI being killed, then mark DefMI as dead too. - /// Some of the combines (extends(trunc)), try to walk through redundant - /// copies in between the extends and the truncs, and this attempts to collect - /// the in between copies if they're dead. - void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI, - SmallVectorImpl &DeadInsts, - unsigned DefIdx = 0) { - DeadInsts.push_back(&MI); - markDefDead(MI, DefMI, DeadInsts, DefIdx); - } - - /// Erase the dead instructions in the list and call the observer hooks. - /// Normally the Legalizer will deal with erasing instructions that have been - /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to - /// process instructions which have been marked dead, but otherwise break the - /// MIR by introducing multiple vreg defs. For those cases, allow the combines - /// to explicitly delete the instructions before we run into trouble. - void deleteMarkedDeadInsts(SmallVectorImpl &DeadInsts, - GISelObserverWrapper &WrapperObserver) { - for (auto *DeadMI : DeadInsts) { - LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n"); - WrapperObserver.erasingInstr(*DeadMI); - DeadMI->eraseFromParent(); - } - DeadInsts.clear(); - } - - /// Checks if the target legalizer info has specified anything about the - /// instruction, or if unsupported. - bool isInstUnsupported(const LegalityQuery &Query) const { - using namespace LegalizeActions; - auto Step = LI.getAction(Query); - return Step.Action == Unsupported || Step.Action == NotFound; - } - - bool isInstLegal(const LegalityQuery &Query) const { - return LI.getAction(Query).Action == LegalizeActions::Legal; - } - - bool isConstantUnsupported(LLT Ty) const { - if (!Ty.isVector()) - return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}}); - - LLT EltTy = Ty.getElementType(); - return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) || - isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}); - } - - /// Looks through copy instructions and returns the actual - /// source register. - Register lookThroughCopyInstrs(Register Reg) { - Register TmpReg; - while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) { - if (MRI.getType(TmpReg).isValid()) - Reg = TmpReg; - else - break; - } - return Reg; - } -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Legalizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Legalizer.h deleted file mode 100644 index c19f1d5330..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Legalizer.h +++ /dev/null @@ -1,76 +0,0 @@ -//== llvm/CodeGen/GlobalISel/Legalizer.h ---------------- -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file A pass to convert the target-illegal operations created by IR -> MIR -/// translation into ones the target expects to be able to select. This may -/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> -> -/// G_ADD <4 x i16>. -/// -/// The LegalizeHelper class is where most of the work happens, and is designed -/// to be callable from other passes that find themselves with an illegal -/// instruction. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZER_H -#define LLVM_CODEGEN_GLOBALISEL_LEGALIZER_H - -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { - -class LostDebugLocObserver; - -class Legalizer : public MachineFunctionPass { -public: - static char ID; - - struct MFResult { - bool Changed; - const MachineInstr *FailedOn; - }; - -private: - /// Initialize the field members using \p MF. - void init(MachineFunction &MF); - -public: - // Ctor, nothing fancy. - Legalizer(); - - StringRef getPassName() const override { return "Legalizer"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::IsSSA); - } - - MachineFunctionProperties getSetProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::Legalized); - } - - MachineFunctionProperties getClearedProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoPHIs); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - static MFResult - legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI, - ArrayRef AuxObservers, - LostDebugLocObserver &LocObserver, - MachineIRBuilder &MIRBuilder); -}; -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h deleted file mode 100644 index cf4c649b9c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ /dev/null @@ -1,431 +0,0 @@ -//== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file A pass to convert the target-illegal operations created by IR -> MIR -/// translation into ones the target expects to be able to select. This may -/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> -> -/// G_ADD <4 x i16>. -/// -/// The LegalizerHelper class is where most of the work happens, and is -/// designed to be callable from other passes that find themselves with an -/// illegal instruction. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H -#define LLVM_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H - -#include "llvm/CodeGen/GlobalISel/CallLowering.h" -#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/LowLevelType.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" - -namespace llvm { -// Forward declarations. -class LegalizerInfo; -class MachineRegisterInfo; -class GISelChangeObserver; -class LostDebugLocObserver; -class TargetLowering; - -class LegalizerHelper { -public: - /// Expose MIRBuilder so clients can set their own RecordInsertInstruction - /// functions - MachineIRBuilder &MIRBuilder; - - /// To keep track of changes made by the LegalizerHelper. - GISelChangeObserver &Observer; - -private: - MachineRegisterInfo &MRI; - const LegalizerInfo &LI; - const TargetLowering &TLI; - -public: - enum LegalizeResult { - /// Instruction was already legal and no change was made to the - /// MachineFunction. - AlreadyLegal, - - /// Instruction has been legalized and the MachineFunction changed. - Legalized, - - /// Some kind of error has occurred and we could not legalize this - /// instruction. - UnableToLegalize, - }; - - /// Expose LegalizerInfo so the clients can re-use. - const LegalizerInfo &getLegalizerInfo() const { return LI; } - const TargetLowering &getTargetLowering() const { return TLI; } - - LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, - MachineIRBuilder &B); - LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, - GISelChangeObserver &Observer, MachineIRBuilder &B); - - /// Replace \p MI by a sequence of legal instructions that can implement the - /// same operation. Note that this means \p MI may be deleted, so any iterator - /// steps should be performed before calling this function. \p Helper should - /// be initialized to the MachineFunction containing \p MI. - /// - /// Considered as an opaque blob, the legal code will use and define the same - /// registers as \p MI. - LegalizeResult legalizeInstrStep(MachineInstr &MI, - LostDebugLocObserver &LocObserver); - - /// Legalize an instruction by emitting a runtime library call instead. - LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver); - - /// Legalize an instruction by reducing the width of the underlying scalar - /// type. - LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); - - /// Legalize an instruction by performing the operation on a wider scalar type - /// (for example a 16-bit addition can be safely performed at 32-bits - /// precision, ignoring the unused bits). - LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - - /// Legalize an instruction by replacing the value type - LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - - /// Legalize an instruction by splitting it into simpler parts, hopefully - /// understood by the target. - LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - - /// Legalize a vector instruction by splitting into multiple components, each - /// acting on the same scalar type as the original but with fewer elements. - LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, - LLT NarrowTy); - - /// Legalize a vector instruction by increasing the number of vector elements - /// involved and ignoring the added elements later. - LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, - LLT MoreTy); - - /// Cast the given value to an LLT::scalar with an equivalent size. Returns - /// the register to use if an instruction was inserted. Returns the original - /// register if no coercion was necessary. - // - // This may also fail and return Register() if there is no legal way to cast. - Register coerceToScalar(Register Val); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// Use by extending the operand's type to \p WideTy using the specified \p - /// ExtOpcode for the extension instruction, and replacing the vreg of the - /// operand in place. - void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, - unsigned ExtOpcode); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and - /// replacing the vreg of the operand in place. - void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// Def by extending the operand's type to \p WideTy and truncating it back - /// with the \p TruncOpcode, and replacing the vreg of the operand in place. - void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0, - unsigned TruncOpcode = TargetOpcode::G_TRUNC); - - // Legalize a single operand \p OpIdx of the machine instruction \p MI as a - // Def by truncating the operand's type to \p NarrowTy, replacing in place and - // extending back with \p ExtOpcode. - void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, - unsigned ExtOpcode); - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// Def by performing it with additional vector elements and extracting the - /// result elements, and replacing the vreg of the operand in place. - void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// Use by producing a vector with undefined high elements, extracting the - /// original vector type, and replacing the vreg of the operand in place. - void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// use by inserting a G_BITCAST to \p CastTy - void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx); - - /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a - /// def by inserting a G_BITCAST from \p CastTy - void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx); - - /// Widen \p OrigReg to \p WideTy by merging to a wider type, padding with - /// G_IMPLICIT_DEF, and producing dead results. - Register widenWithUnmerge(LLT WideTy, Register OrigReg); - -private: - LegalizeResult - widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult - widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult - widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult - widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); - LegalizeResult widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); - LegalizeResult widenScalarMulo(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); - - /// Helper function to split a wide generic register into bitwise blocks with - /// the given Type (which implies the number of blocks needed). The generic - /// registers created are appended to Ops, starting at bit 0 of Reg. - void extractParts(Register Reg, LLT Ty, int NumParts, - SmallVectorImpl &VRegs); - - /// Version which handles irregular splits. - bool extractParts(Register Reg, LLT RegTy, LLT MainTy, - LLT &LeftoverTy, - SmallVectorImpl &VRegs, - SmallVectorImpl &LeftoverVRegs); - - /// Version which handles irregular sub-vector splits. - void extractVectorParts(Register Reg, unsigned NumElst, - SmallVectorImpl &VRegs); - - /// Helper function to build a wide generic register \p DstReg of type \p - /// RegTy from smaller parts. This will produce a G_MERGE_VALUES, - /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate - /// for the types. - /// - /// \p PartRegs must be registers of type \p PartTy. - /// - /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the - /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy. - void insertParts(Register DstReg, LLT ResultTy, - LLT PartTy, ArrayRef PartRegs, - LLT LeftoverTy = LLT(), ArrayRef LeftoverRegs = {}); - - /// Merge \p PartRegs with different types into \p DstReg. - void mergeMixedSubvectors(Register DstReg, ArrayRef PartRegs); - - void appendVectorElts(SmallVectorImpl &Elts, Register Reg); - - /// Unmerge \p SrcReg into smaller sized values, and append them to \p - /// Parts. The elements of \p Parts will be the greatest common divisor type - /// of \p DstTy, \p NarrowTy and the type of \p SrcReg. This will compute and - /// return the GCD type. - LLT extractGCDType(SmallVectorImpl &Parts, LLT DstTy, - LLT NarrowTy, Register SrcReg); - - /// Unmerge \p SrcReg into \p GCDTy typed registers. This will append all of - /// the unpacked registers to \p Parts. This version is if the common unmerge - /// type is already known. - void extractGCDType(SmallVectorImpl &Parts, LLT GCDTy, - Register SrcReg); - - /// Produce a merge of values in \p VRegs to define \p DstReg. Perform a merge - /// from the least common multiple type, and convert as appropriate to \p - /// DstReg. - /// - /// \p VRegs should each have type \p GCDTy. This type should be greatest - /// common divisor type of \p DstReg, \p NarrowTy, and an undetermined source - /// type. - /// - /// \p NarrowTy is the desired result merge source type. If the source value - /// needs to be widened to evenly cover \p DstReg, inserts high bits - /// corresponding to the extension opcode \p PadStrategy. - /// - /// \p VRegs will be cleared, and the result \p NarrowTy register pieces - /// will replace it. Returns The complete LCMTy that \p VRegs will cover when - /// merged. - LLT buildLCMMergePieces(LLT DstTy, LLT NarrowTy, LLT GCDTy, - SmallVectorImpl &VRegs, - unsigned PadStrategy = TargetOpcode::G_ANYEXT); - - /// Merge the values in \p RemergeRegs to an \p LCMTy typed value. Extract the - /// low bits into \p DstReg. This is intended to use the outputs from - /// buildLCMMergePieces after processing. - void buildWidenedRemergeToDst(Register DstReg, LLT LCMTy, - ArrayRef RemergeRegs); - - /// Perform generic multiplication of values held in multiple registers. - /// Generated instructions use only types NarrowTy and i1. - /// Destination can be same or two times size of the source. - void multiplyRegisters(SmallVectorImpl &DstRegs, - ArrayRef Src1Regs, - ArrayRef Src2Regs, LLT NarrowTy); - - void changeOpcode(MachineInstr &MI, unsigned NewOpcode); - - LegalizeResult tryNarrowPow2Reduction(MachineInstr &MI, Register SrcReg, - LLT SrcTy, LLT NarrowTy, - unsigned ScalarOpc); - - // Memcpy family legalization helpers. - LegalizeResult lowerMemset(MachineInstr &MI, Register Dst, Register Val, - uint64_t KnownLen, Align Alignment, - bool IsVolatile); - LegalizeResult lowerMemcpyInline(MachineInstr &MI, Register Dst, Register Src, - uint64_t KnownLen, Align DstAlign, - Align SrcAlign, bool IsVolatile); - LegalizeResult lowerMemcpy(MachineInstr &MI, Register Dst, Register Src, - uint64_t KnownLen, uint64_t Limit, Align DstAlign, - Align SrcAlign, bool IsVolatile); - LegalizeResult lowerMemmove(MachineInstr &MI, Register Dst, Register Src, - uint64_t KnownLen, Align DstAlign, Align SrcAlign, - bool IsVolatile); - -public: - /// Return the alignment to use for a stack temporary object with the given - /// type. - Align getStackTemporaryAlignment(LLT Type, Align MinAlign = Align()) const; - - /// Create a stack temporary based on the size in bytes and the alignment - MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, - MachinePointerInfo &PtrInfo); - - /// Get a pointer to vector element \p Index located in memory for a vector of - /// type \p VecTy starting at a base address of \p VecPtr. If \p Index is out - /// of bounds the returned pointer is unspecified, but will be within the - /// vector bounds. - Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index); - - /// Handles most opcodes. Split \p MI into same instruction on sub-vectors or - /// scalars with \p NumElts elements (1 for scalar). Supports uneven splits: - /// there can be leftover sub-vector with fewer then \p NumElts or a leftover - /// scalar. To avoid this use moreElements first and set MI number of elements - /// to multiple of \p NumElts. Non-vector operands that should be used on all - /// sub-instructions without split are listed in \p NonVecOpIndices. - LegalizeResult fewerElementsVectorMultiEltType( - GenericMachineInstr &MI, unsigned NumElts, - std::initializer_list NonVecOpIndices = {}); - - LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, - unsigned NumElts); - - LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, - LLT MoreTy); - LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, - LLT MoreTy); - - LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, - unsigned TypeIdx, - LLT NarrowTy); - LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, - LLT NarrowTy); - LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, - unsigned TypeIdx, - LLT NarrowTy); - - LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, - LLT NarrowTy); - - LegalizeResult fewerElementsVectorSextInReg(MachineInstr &MI, unsigned TypeIdx, - LLT NarrowTy); - - LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, - LLT HalfTy, LLT ShiftAmtTy); - - LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, - unsigned TypeIdx, LLT NarrowTy); - - LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, - LLT NarrowTy); - - LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, - LLT NarrowTy); - LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); - LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - - LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - - /// Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT. - LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, - LLT CastTy); - - /// Perform Bitcast legalize action on G_INSERT_VECTOR_ELT. - LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, - LLT CastTy); - - LegalizeResult lowerBitcast(MachineInstr &MI); - LegalizeResult lowerLoad(GAnyLoad &MI); - LegalizeResult lowerStore(GStore &MI); - LegalizeResult lowerBitCount(MachineInstr &MI); - LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI); - LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI); - LegalizeResult lowerFunnelShift(MachineInstr &MI); - LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI); - LegalizeResult lowerRotate(MachineInstr &MI); - - LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); - LegalizeResult lowerUITOFP(MachineInstr &MI); - LegalizeResult lowerSITOFP(MachineInstr &MI); - LegalizeResult lowerFPTOUI(MachineInstr &MI); - LegalizeResult lowerFPTOSI(MachineInstr &MI); - - LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI); - LegalizeResult lowerFPTRUNC(MachineInstr &MI); - LegalizeResult lowerFPOWI(MachineInstr &MI); - - LegalizeResult lowerMinMax(MachineInstr &MI); - LegalizeResult lowerFCopySign(MachineInstr &MI); - LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); - LegalizeResult lowerFMad(MachineInstr &MI); - LegalizeResult lowerIntrinsicRound(MachineInstr &MI); - LegalizeResult lowerFFloor(MachineInstr &MI); - LegalizeResult lowerMergeValues(MachineInstr &MI); - LegalizeResult lowerUnmergeValues(MachineInstr &MI); - LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI); - LegalizeResult lowerShuffleVector(MachineInstr &MI); - LegalizeResult lowerDynStackAlloc(MachineInstr &MI); - LegalizeResult lowerExtract(MachineInstr &MI); - LegalizeResult lowerInsert(MachineInstr &MI); - LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); - LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI); - LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI); - LegalizeResult lowerShlSat(MachineInstr &MI); - LegalizeResult lowerBswap(MachineInstr &MI); - LegalizeResult lowerBitreverse(MachineInstr &MI); - LegalizeResult lowerReadWriteRegister(MachineInstr &MI); - LegalizeResult lowerSMULH_UMULH(MachineInstr &MI); - LegalizeResult lowerSelect(MachineInstr &MI); - LegalizeResult lowerDIVREM(MachineInstr &MI); - LegalizeResult lowerAbsToAddXor(MachineInstr &MI); - LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI); - LegalizeResult lowerVectorReduction(MachineInstr &MI); - LegalizeResult lowerMemcpyInline(MachineInstr &MI); - LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0); -}; - -/// Helper function that creates a libcall to the given \p Name using the given -/// calling convention \p CC. -LegalizerHelper::LegalizeResult -createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, - const CallLowering::ArgInfo &Result, - ArrayRef Args, CallingConv::ID CC); - -/// Helper function that creates the given libcall. -LegalizerHelper::LegalizeResult -createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, - const CallLowering::ArgInfo &Result, - ArrayRef Args); - -/// Create a libcall to memcpy et al. -LegalizerHelper::LegalizeResult -createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - MachineInstr &MI, LostDebugLocObserver &LocObserver); - -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h deleted file mode 100644 index 17cb53dd2d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ /dev/null @@ -1,1261 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Interface for Targets to specify which operations they can successfully -/// select and how the others should be expanded most efficiently. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H -#define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallBitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include - -namespace llvm { - -extern cl::opt DisableGISelLegalityCheck; - -class LegalizerHelper; -class MachineInstr; -class MachineRegisterInfo; -class MCInstrInfo; - -namespace LegalizeActions { -enum LegalizeAction : std::uint8_t { - /// The operation is expected to be selectable directly by the target, and - /// no transformation is necessary. - Legal, - - /// The operation should be synthesized from multiple instructions acting on - /// a narrower scalar base-type. For example a 64-bit add might be - /// implemented in terms of 32-bit add-with-carry. - NarrowScalar, - - /// The operation should be implemented in terms of a wider scalar - /// base-type. For example a <2 x s8> add could be implemented as a <2 - /// x s32> add (ignoring the high bits). - WidenScalar, - - /// The (vector) operation should be implemented by splitting it into - /// sub-vectors where the operation is legal. For example a <8 x s64> add - /// might be implemented as 4 separate <2 x s64> adds. There can be a leftover - /// if there are not enough elements for last sub-vector e.g. <7 x s64> add - /// will be implemented as 3 separate <2 x s64> adds and one s64 add. Leftover - /// types can be avoided by doing MoreElements first. - FewerElements, - - /// The (vector) operation should be implemented by widening the input - /// vector and ignoring the lanes added by doing so. For example <2 x i8> is - /// rarely legal, but you might perform an <8 x i8> and then only look at - /// the first two results. - MoreElements, - - /// Perform the operation on a different, but equivalently sized type. - Bitcast, - - /// The operation itself must be expressed in terms of simpler actions on - /// this target. E.g. a SREM replaced by an SDIV and subtraction. - Lower, - - /// The operation should be implemented as a call to some kind of runtime - /// support library. For example this usually happens on machines that don't - /// support floating-point operations natively. - Libcall, - - /// The target wants to do something special with this combination of - /// operand and type. A callback will be issued when it is needed. - Custom, - - /// This operation is completely unsupported on the target. A programming - /// error has occurred. - Unsupported, - - /// Sentinel value for when no action was found in the specified table. - NotFound, - - /// Fall back onto the old rules. - /// TODO: Remove this once we've migrated - UseLegacyRules, -}; -} // end namespace LegalizeActions -raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action); - -using LegalizeActions::LegalizeAction; - -/// The LegalityQuery object bundles together all the information that's needed -/// to decide whether a given operation is legal or not. -/// For efficiency, it doesn't make a copy of Types so care must be taken not -/// to free it before using the query. -struct LegalityQuery { - unsigned Opcode; - ArrayRef Types; - - struct MemDesc { - LLT MemoryTy; - uint64_t AlignInBits; - AtomicOrdering Ordering; - - MemDesc() = default; - MemDesc(LLT MemoryTy, uint64_t AlignInBits, AtomicOrdering Ordering) - : MemoryTy(MemoryTy), AlignInBits(AlignInBits), Ordering(Ordering) {} - MemDesc(const MachineMemOperand &MMO) - : MemoryTy(MMO.getMemoryType()), - AlignInBits(MMO.getAlign().value() * 8), - Ordering(MMO.getSuccessOrdering()) {} - }; - - /// Operations which require memory can use this to place requirements on the - /// memory type for each MMO. - ArrayRef MMODescrs; - - constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types, - const ArrayRef MMODescrs) - : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} - constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types) - : LegalityQuery(Opcode, Types, {}) {} - - raw_ostream &print(raw_ostream &OS) const; -}; - -/// The result of a query. It either indicates a final answer of Legal or -/// Unsupported or describes an action that must be taken to make an operation -/// more legal. -struct LegalizeActionStep { - /// The action to take or the final answer. - LegalizeAction Action; - /// If describing an action, the type index to change. Otherwise zero. - unsigned TypeIdx; - /// If describing an action, the new type for TypeIdx. Otherwise LLT{}. - LLT NewType; - - LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx, - const LLT NewType) - : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {} - - LegalizeActionStep(LegacyLegalizeActionStep Step) - : TypeIdx(Step.TypeIdx), NewType(Step.NewType) { - switch (Step.Action) { - case LegacyLegalizeActions::Legal: - Action = LegalizeActions::Legal; - break; - case LegacyLegalizeActions::NarrowScalar: - Action = LegalizeActions::NarrowScalar; - break; - case LegacyLegalizeActions::WidenScalar: - Action = LegalizeActions::WidenScalar; - break; - case LegacyLegalizeActions::FewerElements: - Action = LegalizeActions::FewerElements; - break; - case LegacyLegalizeActions::MoreElements: - Action = LegalizeActions::MoreElements; - break; - case LegacyLegalizeActions::Bitcast: - Action = LegalizeActions::Bitcast; - break; - case LegacyLegalizeActions::Lower: - Action = LegalizeActions::Lower; - break; - case LegacyLegalizeActions::Libcall: - Action = LegalizeActions::Libcall; - break; - case LegacyLegalizeActions::Custom: - Action = LegalizeActions::Custom; - break; - case LegacyLegalizeActions::Unsupported: - Action = LegalizeActions::Unsupported; - break; - case LegacyLegalizeActions::NotFound: - Action = LegalizeActions::NotFound; - break; - } - } - - bool operator==(const LegalizeActionStep &RHS) const { - return std::tie(Action, TypeIdx, NewType) == - std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType); - } -}; - -using LegalityPredicate = std::function; -using LegalizeMutation = - std::function(const LegalityQuery &)>; - -namespace LegalityPredicates { -struct TypePairAndMemDesc { - LLT Type0; - LLT Type1; - LLT MemTy; - uint64_t Align; - - bool operator==(const TypePairAndMemDesc &Other) const { - return Type0 == Other.Type0 && Type1 == Other.Type1 && - Align == Other.Align && MemTy == Other.MemTy; - } - - /// \returns true if this memory access is legal with for the access described - /// by \p Other (The alignment is sufficient for the size and result type). - bool isCompatible(const TypePairAndMemDesc &Other) const { - return Type0 == Other.Type0 && Type1 == Other.Type1 && - Align >= Other.Align && - // FIXME: This perhaps should be stricter, but the current legality - // rules are written only considering the size. - MemTy.getSizeInBits() == Other.MemTy.getSizeInBits(); - } -}; - -/// True iff P0 and P1 are true. -template -Predicate all(Predicate P0, Predicate P1) { - return [=](const LegalityQuery &Query) { - return P0(Query) && P1(Query); - }; -} -/// True iff all given predicates are true. -template -Predicate all(Predicate P0, Predicate P1, Args... args) { - return all(all(P0, P1), args...); -} - -/// True iff P0 or P1 are true. -template -Predicate any(Predicate P0, Predicate P1) { - return [=](const LegalityQuery &Query) { - return P0(Query) || P1(Query); - }; -} -/// True iff any given predicates are true. -template -Predicate any(Predicate P0, Predicate P1, Args... args) { - return any(any(P0, P1), args...); -} - -/// True iff the given type index is the specified type. -LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit); -/// True iff the given type index is one of the specified types. -LegalityPredicate typeInSet(unsigned TypeIdx, - std::initializer_list TypesInit); - -/// True iff the given type index is not the specified type. -inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) { - return [=](const LegalityQuery &Query) { - return Query.Types[TypeIdx] != Type; - }; -} - -/// True iff the given types for the given pair of type indexes is one of the -/// specified type pairs. -LegalityPredicate -typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, - std::initializer_list> TypesInit); -/// True iff the given types for the given pair of type indexes is one of the -/// specified type pairs. -LegalityPredicate typePairAndMemDescInSet( - unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, - std::initializer_list TypesAndMemDescInit); -/// True iff the specified type index is a scalar. -LegalityPredicate isScalar(unsigned TypeIdx); -/// True iff the specified type index is a vector. -LegalityPredicate isVector(unsigned TypeIdx); -/// True iff the specified type index is a pointer (with any address space). -LegalityPredicate isPointer(unsigned TypeIdx); -/// True iff the specified type index is a pointer with the specified address -/// space. -LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace); - -/// True if the type index is a vector with element type \p EltTy -LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy); - -/// True iff the specified type index is a scalar that's narrower than the given -/// size. -LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type index is a scalar that's wider than the given -/// size. -LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type index is a scalar or vector with an element type -/// that's narrower than the given size. -LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type index is a scalar or a vector with an element -/// type that's wider than the given size. -LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type index is a scalar whose size is not a multiple -/// of Size. -LegalityPredicate sizeNotMultipleOf(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type index is a scalar whose size is not a power of -/// 2. -LegalityPredicate sizeNotPow2(unsigned TypeIdx); - -/// True iff the specified type index is a scalar or vector whose element size -/// is not a power of 2. -LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx); - -/// True if the total bitwidth of the specified type index is \p Size bits. -LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size); - -/// True iff the specified type indices are both the same bit size. -LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1); - -/// True iff the first type index has a larger total bit size than second type -/// index. -LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1); - -/// True iff the first type index has a smaller total bit size than second type -/// index. -LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1); - -/// True iff the specified MMO index has a size that is not a power of 2 -LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); -/// True iff the specified type index is a vector whose element count is not a -/// power of 2. -LegalityPredicate numElementsNotPow2(unsigned TypeIdx); -/// True iff the specified MMO index has at an atomic ordering of at Ordering or -/// stronger. -LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, - AtomicOrdering Ordering); -} // end namespace LegalityPredicates - -namespace LegalizeMutations { -/// Select this specific type for the given type index. -LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); - -/// Keep the same type as the given type index. -LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); - -/// Keep the same scalar or element type as the given type index. -LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); - -/// Keep the same scalar or element type as the given type. -LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); - -/// Change the scalar size or element size to have the same scalar size as type -/// index \p FromIndex. Unlike changeElementTo, this discards pointer types and -/// only changes the size. -LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx); - -/// Widen the scalar type or vector element type for the given type index to the -/// next power of 2. -LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); - -/// Widen the scalar type or vector element type for the given type index to -/// next multiple of \p Size. -LegalizeMutation widenScalarOrEltToNextMultipleOf(unsigned TypeIdx, - unsigned Size); - -/// Add more elements to the type for the given type index to the next power of -/// 2. -LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); -/// Break up the vector type for the given type index into the element type. -LegalizeMutation scalarize(unsigned TypeIdx); -} // end namespace LegalizeMutations - -/// A single rule in a legalizer info ruleset. -/// The specified action is chosen when the predicate is true. Where appropriate -/// for the action (e.g. for WidenScalar) the new type is selected using the -/// given mutator. -class LegalizeRule { - LegalityPredicate Predicate; - LegalizeAction Action; - LegalizeMutation Mutation; - -public: - LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action, - LegalizeMutation Mutation = nullptr) - : Predicate(Predicate), Action(Action), Mutation(Mutation) {} - - /// Test whether the LegalityQuery matches. - bool match(const LegalityQuery &Query) const { - return Predicate(Query); - } - - LegalizeAction getAction() const { return Action; } - - /// Determine the change to make. - std::pair determineMutation(const LegalityQuery &Query) const { - if (Mutation) - return Mutation(Query); - return std::make_pair(0, LLT{}); - } -}; - -class LegalizeRuleSet { - /// When non-zero, the opcode we are an alias of - unsigned AliasOf = 0; - /// If true, there is another opcode that aliases this one - bool IsAliasedByAnother = false; - SmallVector Rules; - -#ifndef NDEBUG - /// If bit I is set, this rule set contains a rule that may handle (predicate - /// or perform an action upon (or both)) the type index I. The uncertainty - /// comes from free-form rules executing user-provided lambda functions. We - /// conservatively assume such rules do the right thing and cover all type - /// indices. The bitset is intentionally 1 bit wider than it absolutely needs - /// to be to distinguish such cases from the cases where all type indices are - /// individually handled. - SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC - - MCOI::OPERAND_FIRST_GENERIC + 2}; - SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM - - MCOI::OPERAND_FIRST_GENERIC_IMM + 2}; -#endif - - unsigned typeIdx(unsigned TypeIdx) { - assert(TypeIdx <= - (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) && - "Type Index is out of bounds"); -#ifndef NDEBUG - TypeIdxsCovered.set(TypeIdx); -#endif - return TypeIdx; - } - - void markAllIdxsAsCovered() { -#ifndef NDEBUG - TypeIdxsCovered.set(); - ImmIdxsCovered.set(); -#endif - } - - void add(const LegalizeRule &Rule) { - assert(AliasOf == 0 && - "RuleSet is aliased, change the representative opcode instead"); - Rules.push_back(Rule); - } - - static bool always(const LegalityQuery &) { return true; } - - /// Use the given action when the predicate is true. - /// Action should not be an action that requires mutation. - LegalizeRuleSet &actionIf(LegalizeAction Action, - LegalityPredicate Predicate) { - add({Predicate, Action}); - return *this; - } - /// Use the given action when the predicate is true. - /// Action should be an action that requires mutation. - LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate, - LegalizeMutation Mutation) { - add({Predicate, Action, Mutation}); - return *this; - } - /// Use the given action when type index 0 is any type in the given list. - /// Action should not be an action that requires mutation. - LegalizeRuleSet &actionFor(LegalizeAction Action, - std::initializer_list Types) { - using namespace LegalityPredicates; - return actionIf(Action, typeInSet(typeIdx(0), Types)); - } - /// Use the given action when type index 0 is any type in the given list. - /// Action should be an action that requires mutation. - LegalizeRuleSet &actionFor(LegalizeAction Action, - std::initializer_list Types, - LegalizeMutation Mutation) { - using namespace LegalityPredicates; - return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation); - } - /// Use the given action when type indexes 0 and 1 is any type pair in the - /// given list. - /// Action should not be an action that requires mutation. - LegalizeRuleSet &actionFor(LegalizeAction Action, - std::initializer_list> Types) { - using namespace LegalityPredicates; - return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); - } - /// Use the given action when type indexes 0 and 1 is any type pair in the - /// given list. - /// Action should be an action that requires mutation. - LegalizeRuleSet &actionFor(LegalizeAction Action, - std::initializer_list> Types, - LegalizeMutation Mutation) { - using namespace LegalityPredicates; - return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types), - Mutation); - } - /// Use the given action when type index 0 is any type in the given list and - /// imm index 0 is anything. Action should not be an action that requires - /// mutation. - LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action, - std::initializer_list Types) { - using namespace LegalityPredicates; - immIdx(0); // Inform verifier imm idx 0 is handled. - return actionIf(Action, typeInSet(typeIdx(0), Types)); - } - - LegalizeRuleSet &actionForTypeWithAnyImm( - LegalizeAction Action, std::initializer_list> Types) { - using namespace LegalityPredicates; - immIdx(0); // Inform verifier imm idx 0 is handled. - return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); - } - - /// Use the given action when type indexes 0 and 1 are both in the given list. - /// That is, the type pair is in the cartesian product of the list. - /// Action should not be an action that requires mutation. - LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action, - std::initializer_list Types) { - using namespace LegalityPredicates; - return actionIf(Action, all(typeInSet(typeIdx(0), Types), - typeInSet(typeIdx(1), Types))); - } - /// Use the given action when type indexes 0 and 1 are both in their - /// respective lists. - /// That is, the type pair is in the cartesian product of the lists - /// Action should not be an action that requires mutation. - LegalizeRuleSet & - actionForCartesianProduct(LegalizeAction Action, - std::initializer_list Types0, - std::initializer_list Types1) { - using namespace LegalityPredicates; - return actionIf(Action, all(typeInSet(typeIdx(0), Types0), - typeInSet(typeIdx(1), Types1))); - } - /// Use the given action when type indexes 0, 1, and 2 are all in their - /// respective lists. - /// That is, the type triple is in the cartesian product of the lists - /// Action should not be an action that requires mutation. - LegalizeRuleSet &actionForCartesianProduct( - LegalizeAction Action, std::initializer_list Types0, - std::initializer_list Types1, std::initializer_list Types2) { - using namespace LegalityPredicates; - return actionIf(Action, all(typeInSet(typeIdx(0), Types0), - all(typeInSet(typeIdx(1), Types1), - typeInSet(typeIdx(2), Types2)))); - } - -public: - LegalizeRuleSet() = default; - - bool isAliasedByAnother() { return IsAliasedByAnother; } - void setIsAliasedByAnother() { IsAliasedByAnother = true; } - void aliasTo(unsigned Opcode) { - assert((AliasOf == 0 || AliasOf == Opcode) && - "Opcode is already aliased to another opcode"); - assert(Rules.empty() && "Aliasing will discard rules"); - AliasOf = Opcode; - } - unsigned getAlias() const { return AliasOf; } - - unsigned immIdx(unsigned ImmIdx) { - assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM - - MCOI::OPERAND_FIRST_GENERIC_IMM) && - "Imm Index is out of bounds"); -#ifndef NDEBUG - ImmIdxsCovered.set(ImmIdx); -#endif - return ImmIdx; - } - - /// The instruction is legal if predicate is true. - LegalizeRuleSet &legalIf(LegalityPredicate Predicate) { - // We have no choice but conservatively assume that the free-form - // user-provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Legal, Predicate); - } - /// The instruction is legal when type index 0 is any type in the given list. - LegalizeRuleSet &legalFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Legal, Types); - } - /// The instruction is legal when type indexes 0 and 1 is any type pair in the - /// given list. - LegalizeRuleSet &legalFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Legal, Types); - } - /// The instruction is legal when type index 0 is any type in the given list - /// and imm index 0 is anything. - LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list Types) { - markAllIdxsAsCovered(); - return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); - } - - LegalizeRuleSet &legalForTypeWithAnyImm( - std::initializer_list> Types) { - markAllIdxsAsCovered(); - return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); - } - - /// The instruction is legal when type indexes 0 and 1 along with the memory - /// size and minimum alignment is any type and size tuple in the given list. - LegalizeRuleSet &legalForTypesWithMemDesc( - std::initializer_list - TypesAndMemDesc) { - return actionIf(LegalizeAction::Legal, - LegalityPredicates::typePairAndMemDescInSet( - typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); - } - /// The instruction is legal when type indexes 0 and 1 are both in the given - /// list. That is, the type pair is in the cartesian product of the list. - LegalizeRuleSet &legalForCartesianProduct(std::initializer_list Types) { - return actionForCartesianProduct(LegalizeAction::Legal, Types); - } - /// The instruction is legal when type indexes 0 and 1 are both their - /// respective lists. - LegalizeRuleSet &legalForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1) { - return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); - } - /// The instruction is legal when type indexes 0, 1, and 2 are both their - /// respective lists. - LegalizeRuleSet &legalForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1, - std::initializer_list Types2) { - return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, - Types2); - } - - LegalizeRuleSet &alwaysLegal() { - using namespace LegalizeMutations; - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Legal, always); - } - - /// The specified type index is coerced if predicate is true. - LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that lowering with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Bitcast, Predicate, Mutation); - } - - /// The instruction is lowered. - LegalizeRuleSet &lower() { - using namespace LegalizeMutations; - // We have no choice but conservatively assume that predicate-less lowering - // properly handles all type indices by design: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Lower, always); - } - /// The instruction is lowered if predicate is true. Keep type index 0 as the - /// same type. - LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) { - using namespace LegalizeMutations; - // We have no choice but conservatively assume that lowering with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Lower, Predicate); - } - /// The instruction is lowered if predicate is true. - LegalizeRuleSet &lowerIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that lowering with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Lower, Predicate, Mutation); - } - /// The instruction is lowered when type index 0 is any type in the given - /// list. Keep type index 0 as the same type. - LegalizeRuleSet &lowerFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Lower, Types); - } - /// The instruction is lowered when type index 0 is any type in the given - /// list. - LegalizeRuleSet &lowerFor(std::initializer_list Types, - LegalizeMutation Mutation) { - return actionFor(LegalizeAction::Lower, Types, Mutation); - } - /// The instruction is lowered when type indexes 0 and 1 is any type pair in - /// the given list. Keep type index 0 as the same type. - LegalizeRuleSet &lowerFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Lower, Types); - } - /// The instruction is lowered when type indexes 0 and 1 is any type pair in - /// the given list. - LegalizeRuleSet &lowerFor(std::initializer_list> Types, - LegalizeMutation Mutation) { - return actionFor(LegalizeAction::Lower, Types, Mutation); - } - /// The instruction is lowered when type indexes 0 and 1 are both in their - /// respective lists. - LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1) { - using namespace LegalityPredicates; - return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1); - } - /// The instruction is lowered when when type indexes 0, 1, and 2 are all in - /// their respective lists. - LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1, - std::initializer_list Types2) { - using namespace LegalityPredicates; - return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1, - Types2); - } - - /// The instruction is emitted as a library call. - LegalizeRuleSet &libcall() { - using namespace LegalizeMutations; - // We have no choice but conservatively assume that predicate-less lowering - // properly handles all type indices by design: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Libcall, always); - } - - /// Like legalIf, but for the Libcall action. - LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) { - // We have no choice but conservatively assume that a libcall with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Libcall, Predicate); - } - LegalizeRuleSet &libcallFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Libcall, Types); - } - LegalizeRuleSet & - libcallFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Libcall, Types); - } - LegalizeRuleSet & - libcallForCartesianProduct(std::initializer_list Types) { - return actionForCartesianProduct(LegalizeAction::Libcall, Types); - } - LegalizeRuleSet & - libcallForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1) { - return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1); - } - - /// Widen the scalar to the one selected by the mutation if the predicate is - /// true. - LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that an action with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation); - } - /// Narrow the scalar to the one selected by the mutation if the predicate is - /// true. - LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that an action with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation); - } - /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any - /// type pair in the given list. - LegalizeRuleSet & - narrowScalarFor(std::initializer_list> Types, - LegalizeMutation Mutation) { - return actionFor(LegalizeAction::NarrowScalar, Types, Mutation); - } - - /// Add more elements to reach the type selected by the mutation if the - /// predicate is true. - LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that an action with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::MoreElements, Predicate, Mutation); - } - /// Remove elements to reach the type selected by the mutation if the - /// predicate is true. - LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate, - LegalizeMutation Mutation) { - // We have no choice but conservatively assume that an action with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::FewerElements, Predicate, Mutation); - } - - /// The instruction is unsupported. - LegalizeRuleSet &unsupported() { - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Unsupported, always); - } - LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) { - return actionIf(LegalizeAction::Unsupported, Predicate); - } - - LegalizeRuleSet &unsupportedFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Unsupported, Types); - } - - LegalizeRuleSet &unsupportedIfMemSizeNotPow2() { - return actionIf(LegalizeAction::Unsupported, - LegalityPredicates::memSizeInBytesNotPow2(0)); - } - LegalizeRuleSet &lowerIfMemSizeNotPow2() { - return actionIf(LegalizeAction::Lower, - LegalityPredicates::memSizeInBytesNotPow2(0)); - } - - LegalizeRuleSet &customIf(LegalityPredicate Predicate) { - // We have no choice but conservatively assume that a custom action with a - // free-form user provided Predicate properly handles all type indices: - markAllIdxsAsCovered(); - return actionIf(LegalizeAction::Custom, Predicate); - } - LegalizeRuleSet &customFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Custom, Types); - } - - /// The instruction is custom when type indexes 0 and 1 is any type pair in the - /// given list. - LegalizeRuleSet &customFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Custom, Types); - } - - LegalizeRuleSet &customForCartesianProduct(std::initializer_list Types) { - return actionForCartesianProduct(LegalizeAction::Custom, Types); - } - /// The instruction is custom when type indexes 0 and 1 are both in their - /// respective lists. - LegalizeRuleSet & - customForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1) { - return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); - } - /// The instruction is custom when when type indexes 0, 1, and 2 are all in - /// their respective lists. - LegalizeRuleSet & - customForCartesianProduct(std::initializer_list Types0, - std::initializer_list Types1, - std::initializer_list Types2) { - return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1, - Types2); - } - - /// Unconditionally custom lower. - LegalizeRuleSet &custom() { - return customIf(always); - } - - /// Widen the scalar to the next power of two that is at least MinSize. - /// No effect if the type is not a scalar or is a power of two. - LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, - unsigned MinSize = 0) { - using namespace LegalityPredicates; - return actionIf( - LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), - LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); - } - - /// Widen the scalar to the next multiple of Size. No effect if the - /// type is not a scalar or is a multiple of Size. - LegalizeRuleSet &widenScalarToNextMultipleOf(unsigned TypeIdx, - unsigned Size) { - using namespace LegalityPredicates; - return actionIf( - LegalizeAction::WidenScalar, sizeNotMultipleOf(typeIdx(TypeIdx), Size), - LegalizeMutations::widenScalarOrEltToNextMultipleOf(TypeIdx, Size)); - } - - /// Widen the scalar or vector element type to the next power of two that is - /// at least MinSize. No effect if the scalar size is a power of two. - LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx, - unsigned MinSize = 0) { - using namespace LegalityPredicates; - return actionIf( - LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)), - LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); - } - - LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { - using namespace LegalityPredicates; - return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)), - Mutation); - } - - LegalizeRuleSet &scalarize(unsigned TypeIdx) { - using namespace LegalityPredicates; - return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)), - LegalizeMutations::scalarize(TypeIdx)); - } - - LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) { - using namespace LegalityPredicates; - return actionIf(LegalizeAction::FewerElements, - all(Predicate, isVector(typeIdx(TypeIdx))), - LegalizeMutations::scalarize(TypeIdx)); - } - - /// Ensure the scalar or element is at least as wide as Ty. - LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf(LegalizeAction::WidenScalar, - scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()), - changeElementTo(typeIdx(TypeIdx), Ty)); - } - - /// Ensure the scalar or element is at least as wide as Ty. - LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate, - unsigned TypeIdx, const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf(LegalizeAction::WidenScalar, - all(Predicate, scalarOrEltNarrowerThan( - TypeIdx, Ty.getScalarSizeInBits())), - changeElementTo(typeIdx(TypeIdx), Ty)); - } - - /// Ensure the scalar is at least as wide as Ty. - LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf(LegalizeAction::WidenScalar, - scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()), - changeTo(typeIdx(TypeIdx), Ty)); - } - - /// Ensure the scalar is at most as wide as Ty. - LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf(LegalizeAction::NarrowScalar, - scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()), - changeElementTo(typeIdx(TypeIdx), Ty)); - } - - /// Ensure the scalar is at most as wide as Ty. - LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf(LegalizeAction::NarrowScalar, - scalarWiderThan(TypeIdx, Ty.getSizeInBits()), - changeTo(typeIdx(TypeIdx), Ty)); - } - - /// Conditionally limit the maximum size of the scalar. - /// For example, when the maximum size of one type depends on the size of - /// another such as extracting N bits from an M bit container. - LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, - const LLT Ty) { - using namespace LegalityPredicates; - using namespace LegalizeMutations; - return actionIf( - LegalizeAction::NarrowScalar, - [=](const LegalityQuery &Query) { - const LLT QueryTy = Query.Types[TypeIdx]; - return QueryTy.isScalar() && - QueryTy.getSizeInBits() > Ty.getSizeInBits() && - Predicate(Query); - }, - changeElementTo(typeIdx(TypeIdx), Ty)); - } - - /// Limit the range of scalar sizes to MinTy and MaxTy. - LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy, - const LLT MaxTy) { - assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types"); - return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); - } - - /// Limit the range of scalar sizes to MinTy and MaxTy. - LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, - const LLT MaxTy) { - return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy); - } - - /// Widen the scalar to match the size of another. - LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { - typeIdx(TypeIdx); - return widenScalarIf( - [=](const LegalityQuery &Query) { - return Query.Types[LargeTypeIdx].getScalarSizeInBits() > - Query.Types[TypeIdx].getSizeInBits(); - }, - LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx)); - } - - /// Narrow the scalar to match the size of another. - LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) { - typeIdx(TypeIdx); - return narrowScalarIf( - [=](const LegalityQuery &Query) { - return Query.Types[NarrowTypeIdx].getScalarSizeInBits() < - Query.Types[TypeIdx].getSizeInBits(); - }, - LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx)); - } - - /// Change the type \p TypeIdx to have the same scalar size as type \p - /// SameSizeIdx. - LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) { - return minScalarSameAs(TypeIdx, SameSizeIdx) - .maxScalarSameAs(TypeIdx, SameSizeIdx); - } - - /// Conditionally widen the scalar or elt to match the size of another. - LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate, - unsigned TypeIdx, unsigned LargeTypeIdx) { - typeIdx(TypeIdx); - return widenScalarIf( - [=](const LegalityQuery &Query) { - return Query.Types[LargeTypeIdx].getScalarSizeInBits() > - Query.Types[TypeIdx].getScalarSizeInBits() && - Predicate(Query); - }, - [=](const LegalityQuery &Query) { - LLT T = Query.Types[LargeTypeIdx]; - return std::make_pair(TypeIdx, T); - }); - } - - /// Conditionally narrow the scalar or elt to match the size of another. - LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate, - unsigned TypeIdx, - unsigned SmallTypeIdx) { - typeIdx(TypeIdx); - return narrowScalarIf( - [=](const LegalityQuery &Query) { - return Query.Types[SmallTypeIdx].getScalarSizeInBits() < - Query.Types[TypeIdx].getScalarSizeInBits() && - Predicate(Query); - }, - [=](const LegalityQuery &Query) { - LLT T = Query.Types[SmallTypeIdx]; - return std::make_pair(TypeIdx, T); - }); - } - - /// Add more elements to the vector to reach the next power of two. - /// No effect if the type is not a vector or the element count is a power of - /// two. - LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) { - using namespace LegalityPredicates; - return actionIf(LegalizeAction::MoreElements, - numElementsNotPow2(typeIdx(TypeIdx)), - LegalizeMutations::moreElementsToNextPow2(TypeIdx)); - } - - /// Limit the number of elements in EltTy vectors to at least MinElements. - LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy, - unsigned MinElements) { - // Mark the type index as covered: - typeIdx(TypeIdx); - return actionIf( - LegalizeAction::MoreElements, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - return VecTy.isVector() && VecTy.getElementType() == EltTy && - VecTy.getNumElements() < MinElements; - }, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - return std::make_pair( - TypeIdx, LLT::fixed_vector(MinElements, VecTy.getElementType())); - }); - } - - /// Set number of elements to nearest larger multiple of NumElts. - LegalizeRuleSet &alignNumElementsTo(unsigned TypeIdx, const LLT EltTy, - unsigned NumElts) { - typeIdx(TypeIdx); - return actionIf( - LegalizeAction::MoreElements, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - return VecTy.isVector() && VecTy.getElementType() == EltTy && - (VecTy.getNumElements() % NumElts != 0); - }, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - unsigned NewSize = alignTo(VecTy.getNumElements(), NumElts); - return std::make_pair( - TypeIdx, LLT::fixed_vector(NewSize, VecTy.getElementType())); - }); - } - - /// Limit the number of elements in EltTy vectors to at most MaxElements. - LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, - unsigned MaxElements) { - // Mark the type index as covered: - typeIdx(TypeIdx); - return actionIf( - LegalizeAction::FewerElements, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - return VecTy.isVector() && VecTy.getElementType() == EltTy && - VecTy.getNumElements() > MaxElements; - }, - [=](const LegalityQuery &Query) { - LLT VecTy = Query.Types[TypeIdx]; - LLT NewTy = LLT::scalarOrVector(ElementCount::getFixed(MaxElements), - VecTy.getElementType()); - return std::make_pair(TypeIdx, NewTy); - }); - } - /// Limit the number of elements for the given vectors to at least MinTy's - /// number of elements and at most MaxTy's number of elements. - /// - /// No effect if the type is not a vector or does not have the same element - /// type as the constraints. - /// The element type of MinTy and MaxTy must match. - LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy, - const LLT MaxTy) { - assert(MinTy.getElementType() == MaxTy.getElementType() && - "Expected element types to agree"); - - const LLT EltTy = MinTy.getElementType(); - return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements()) - .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements()); - } - - /// Express \p EltTy vectors strictly using vectors with \p NumElts elements - /// (or scalars when \p NumElts equals 1). - /// First pad with undef elements to nearest larger multiple of \p NumElts. - /// Then perform split with all sub-instructions having the same type. - /// Using clampMaxNumElements (non-strict) can result in leftover instruction - /// with different type (fewer elements then \p NumElts or scalar). - /// No effect if the type is not a vector. - LegalizeRuleSet &clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, - unsigned NumElts) { - return alignNumElementsTo(TypeIdx, EltTy, NumElts) - .clampMaxNumElements(TypeIdx, EltTy, NumElts); - } - - /// Fallback on the previous implementation. This should only be used while - /// porting a rule. - LegalizeRuleSet &fallback() { - add({always, LegalizeAction::UseLegacyRules}); - return *this; - } - - /// Check if there is no type index which is obviously not handled by the - /// LegalizeRuleSet in any way at all. - /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. - bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const; - /// Check if there is no imm index which is obviously not handled by the - /// LegalizeRuleSet in any way at all. - /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. - bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const; - - /// Apply the ruleset to the given LegalityQuery. - LegalizeActionStep apply(const LegalityQuery &Query) const; -}; - -class LegalizerInfo { -public: - virtual ~LegalizerInfo() = default; - - const LegacyLegalizerInfo &getLegacyLegalizerInfo() const { - return LegacyInfo; - } - LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; } - - unsigned getOpcodeIdxForOpcode(unsigned Opcode) const; - unsigned getActionDefinitionsIdx(unsigned Opcode) const; - - /// Perform simple self-diagnostic and assert if there is anything obviously - /// wrong with the actions set up. - void verify(const MCInstrInfo &MII) const; - - /// Get the action definitions for the given opcode. Use this to run a - /// LegalityQuery through the definitions. - const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const; - - /// Get the action definition builder for the given opcode. Use this to define - /// the action definitions. - /// - /// It is an error to request an opcode that has already been requested by the - /// multiple-opcode variant. - LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode); - - /// Get the action definition builder for the given set of opcodes. Use this - /// to define the action definitions for multiple opcodes at once. The first - /// opcode given will be considered the representative opcode and will hold - /// the definitions whereas the other opcodes will be configured to refer to - /// the representative opcode. This lowers memory requirements and very - /// slightly improves performance. - /// - /// It would be very easy to introduce unexpected side-effects as a result of - /// this aliasing if it were permitted to request different but intersecting - /// sets of opcodes but that is difficult to keep track of. It is therefore an - /// error to request the same opcode twice using this API, to request an - /// opcode that already has definitions, or to use the single-opcode API on an - /// opcode that has already been requested by this API. - LegalizeRuleSet & - getActionDefinitionsBuilder(std::initializer_list Opcodes); - void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom); - - /// Determine what action should be taken to legalize the described - /// instruction. Requires computeTables to have been called. - /// - /// \returns a description of the next legalization step to perform. - LegalizeActionStep getAction(const LegalityQuery &Query) const; - - /// Determine what action should be taken to legalize the given generic - /// instruction. - /// - /// \returns a description of the next legalization step to perform. - LegalizeActionStep getAction(const MachineInstr &MI, - const MachineRegisterInfo &MRI) const; - - bool isLegal(const LegalityQuery &Query) const { - return getAction(Query).Action == LegalizeAction::Legal; - } - - bool isLegalOrCustom(const LegalityQuery &Query) const { - auto Action = getAction(Query).Action; - return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom; - } - - bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; - bool isLegalOrCustom(const MachineInstr &MI, - const MachineRegisterInfo &MRI) const; - - /// Called for instructions with the Custom LegalizationAction. - virtual bool legalizeCustom(LegalizerHelper &Helper, - MachineInstr &MI) const { - llvm_unreachable("must implement this if custom action is used"); - } - - /// \returns true if MI is either legal or has been legalized and false if not - /// legal. - /// Return true if MI is either legal or has been legalized and false - /// if not legal. - virtual bool legalizeIntrinsic(LegalizerHelper &Helper, - MachineInstr &MI) const { - return true; - } - - /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while - /// widening a constant of type SmallTy which targets can override. - /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which - /// will be the default. - virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const; - -private: - static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; - static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; - - LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1]; - LegacyLegalizerInfo LegacyInfo; -}; - -#ifndef NDEBUG -/// Checks that MIR is fully legal, returns an illegal instruction if it's not, -/// nullptr otherwise -const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF); -#endif - -} // end namespace llvm. - -#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h deleted file mode 100644 index 0845c001ab..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h +++ /dev/null @@ -1,164 +0,0 @@ -//== llvm/CodeGen/GlobalISel/LoadStoreOpt.h - LoadStoreOpt -------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// This is an optimization pass for GlobalISel generic memory operations. -/// Specifically, it focuses on merging stores and loads to consecutive -/// addresses. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H -#define LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" -#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" - -namespace llvm { -// Forward declarations. -class MachineRegisterInfo; -namespace GISelAddressing { -/// Helper struct to store a base, index and offset that forms an address -struct BaseIndexOffset { - Register BaseReg; - Register IndexReg; - int64_t Offset = 0; - bool IsIndexSignExt = false; -}; - -/// Returns a BaseIndexOffset which describes the pointer in \p Ptr. -BaseIndexOffset getPointerInfo(Register Ptr, MachineRegisterInfo &MRI); - -/// Compute whether or not a memory access at \p MI1 aliases with an access at -/// \p MI2 \returns true if either alias/no-alias is known. Sets \p IsAlias -/// accordingly. -bool aliasIsKnownForLoadStore(const MachineInstr &MI1, const MachineInstr &MI2, - bool &IsAlias, MachineRegisterInfo &MRI); - -/// Returns true if the instruction \p MI may alias \p Other. -/// This function uses multiple strategies to detect aliasing, whereas -/// aliasIsKnownForLoadStore just looks at the addresses of load/stores and is -/// tries to reason about base/index/offsets. -bool instMayAlias(const MachineInstr &MI, const MachineInstr &Other, - MachineRegisterInfo &MRI, AliasAnalysis *AA); -} // namespace GISelAddressing - -using namespace GISelAddressing; - -class LoadStoreOpt : public MachineFunctionPass { -public: - static char ID; - -private: - /// An input function to decide if the pass should run or not - /// on the given MachineFunction. - std::function DoNotRunPass; - - MachineRegisterInfo *MRI; - const TargetLowering *TLI; - MachineFunction *MF; - AliasAnalysis *AA; - const LegalizerInfo *LI; - - MachineIRBuilder Builder; - - /// Initialize the field members using \p MF. - void init(MachineFunction &MF); - - class StoreMergeCandidate { - public: - // The base pointer used as the base for all stores in this candidate. - Register BasePtr; - // Our algorithm is very simple at the moment. We assume that in instruction - // order stores are writing to incremeneting consecutive addresses. So when - // we walk the block in reverse order, the next eligible store must write to - // an offset one store width lower than CurrentLowestOffset. - uint64_t CurrentLowestOffset; - SmallVector Stores; - // A vector of MachineInstr/unsigned pairs to denote potential aliases that - // need to be checked before the candidate is considered safe to merge. The - // unsigned value is an index into the Stores vector. The indexed store is - // the highest-indexed store that has already been checked to not have an - // alias with the instruction. We record this so we don't have to repeat - // alias checks that have been already done, only those with stores added - // after the potential alias is recorded. - SmallVector> PotentialAliases; - - void addPotentialAlias(MachineInstr &MI); - - /// Reset this candidate back to an empty one. - void reset() { - Stores.clear(); - PotentialAliases.clear(); - CurrentLowestOffset = 0; - BasePtr = Register(); - } - }; - - bool isLegalOrBeforeLegalizer(const LegalityQuery &Query, - MachineFunction &MF) const; - /// If the given store is valid to be a member of the candidate, add it and - /// return true. Otherwise, returns false. - bool addStoreToCandidate(GStore &MI, StoreMergeCandidate &C); - /// Returns true if the instruction \p MI would potentially alias with any - /// stores in the candidate \p C. - bool operationAliasesWithCandidate(MachineInstr &MI, StoreMergeCandidate &C); - /// Merges the stores in the given vector into a wide store. - /// \p returns true if at least some of the stores were merged. - /// This may decide not to merge stores if heuristics predict it will not be - /// worth it. - bool mergeStores(SmallVectorImpl &StoresToMerge); - /// Perform a merge of all the stores in \p Stores into a single store. - /// Erases the old stores from the block when finished. - /// \returns true if merging was done. It may fail to perform a merge if - /// there are issues with materializing legal wide values. - bool doSingleStoreMerge(SmallVectorImpl &Stores); - bool processMergeCandidate(StoreMergeCandidate &C); - bool mergeBlockStores(MachineBasicBlock &MBB); - bool mergeFunctionStores(MachineFunction &MF); - - /// Initialize some target-specific data structures for the store merging - /// optimization. \p AddrSpace indicates which address space to use when - /// probing the legalizer info for legal stores. - void initializeStoreMergeTargetInfo(unsigned AddrSpace = 0); - /// A map between address space numbers and a bitvector of supported stores - /// sizes. Each bit in the bitvector represents whether a store size of - /// that bit's value is legal. E.g. if bit 64 is set, then 64 bit scalar - /// stores are legal. - DenseMap LegalStoreSizes; - bool IsPreLegalizer; - /// Contains instructions to be erased at the end of a block scan. - SmallSet InstsToErase; - -public: - LoadStoreOpt(); - LoadStoreOpt(std::function); - - StringRef getPassName() const override { return "LoadStoreOpt"; } - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &MF) override; -}; - -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Localizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Localizer.h deleted file mode 100644 index 1d1afff7f9..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Localizer.h +++ /dev/null @@ -1,97 +0,0 @@ -//== llvm/CodeGen/GlobalISel/Localizer.h - Localizer -------------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file describes the interface of the Localizer pass. -/// This pass moves/duplicates constant-like instructions close to their uses. -/// Its primarily goal is to workaround the deficiencies of the fast register -/// allocator. -/// With GlobalISel constants are all materialized in the entry block of -/// a function. However, the fast allocator cannot rematerialize constants and -/// has a lot more live-ranges to deal with and will most likely end up -/// spilling a lot. -/// By pushing the constants close to their use, we only create small -/// live-ranges. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H -#define LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { -// Forward declarations. -class MachineRegisterInfo; -class TargetTransformInfo; - -/// This pass implements the localization mechanism described at the -/// top of this file. One specificity of the implementation is that -/// it will materialize one and only one instance of a constant per -/// basic block, thus enabling reuse of that constant within that block. -/// Moreover, it only materializes constants in blocks where they -/// are used. PHI uses are considered happening at the end of the -/// related predecessor. -class Localizer : public MachineFunctionPass { -public: - static char ID; - -private: - /// An input function to decide if the pass should run or not - /// on the given MachineFunction. - std::function DoNotRunPass; - - /// MRI contains all the register class/bank information that this - /// pass uses and updates. - MachineRegisterInfo *MRI; - /// TTI used for getting remat costs for instructions. - TargetTransformInfo *TTI; - - /// Check if \p MOUse is used in the same basic block as \p Def. - /// If the use is in the same block, we say it is local. - /// When the use is not local, \p InsertMBB will contain the basic - /// block when to insert \p Def to have a local use. - static bool isLocalUse(MachineOperand &MOUse, const MachineInstr &Def, - MachineBasicBlock *&InsertMBB); - - /// Initialize the field members using \p MF. - void init(MachineFunction &MF); - - typedef SmallSetVector LocalizedSetVecT; - - /// If \p Op is a phi operand and not unique in that phi, that is, - /// there are other operands in the phi with the same register, - /// return true. - bool isNonUniquePhiValue(MachineOperand &Op) const; - - /// Do inter-block localization from the entry block. - bool localizeInterBlock(MachineFunction &MF, - LocalizedSetVecT &LocalizedInstrs); - - /// Do intra-block localization of already localized instructions. - bool localizeIntraBlock(LocalizedSetVecT &LocalizedInstrs); - -public: - Localizer(); - Localizer(std::function); - - StringRef getPassName() const override { return "Localizer"; } - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &MF) override; -}; - -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LostDebugLocObserver.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LostDebugLocObserver.h deleted file mode 100644 index 1667d0145b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/LostDebugLocObserver.h +++ /dev/null @@ -1,50 +0,0 @@ -//===----- llvm/CodeGen/GlobalISel/LostDebugLocObserver.h -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Tracks DebugLocs between checkpoints and verifies that they are transferred. -/// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GLOBALISEL_LOSTDEBUGLOCOBSERVER_H -#define LLVM_CODEGEN_GLOBALISEL_LOSTDEBUGLOCOBSERVER_H - -#include "llvm/ADT/SmallSet.h" -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" - -namespace llvm { -class LostDebugLocObserver : public GISelChangeObserver { - StringRef DebugType; - SmallSet LostDebugLocs; - SmallPtrSet PotentialMIsForDebugLocs; - unsigned NumLostDebugLocs = 0; - -public: - LostDebugLocObserver(StringRef DebugType) : DebugType(DebugType) {} - - unsigned getNumLostDebugLocs() const { return NumLostDebugLocs; } - - /// Call this to indicate that it's a good point to assess whether locations - /// have been lost. Typically this will be when a logical change has been - /// completed such as the caller has finished replacing some instructions with - /// alternatives. When CheckDebugLocs is true, the locations will be checked - /// to see if any have been lost since the last checkpoint. When - /// CheckDebugLocs is false, it will just reset ready for the next checkpoint - /// without checking anything. This can be helpful to limit the detection to - /// easy-to-fix portions of an algorithm before allowing more difficult ones. - void checkpoint(bool CheckDebugLocs = true); - - void createdInstr(MachineInstr &MI) override; - void erasingInstr(MachineInstr &MI) override; - void changingInstr(MachineInstr &MI) override; - void changedInstr(MachineInstr &MI) override; - -private: - void analyzeDebugLocations(); -}; - -} // namespace llvm -#endif // LLVM_CODEGEN_GLOBALISEL_LOSTDEBUGLOCOBSERVER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h deleted file mode 100644 index daf1ff0529..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ /dev/null @@ -1,661 +0,0 @@ -//==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Contains matchers for matching SSA Machine Instructions. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H -#define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H - -#include "llvm/ADT/APInt.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/IR/InstrTypes.h" - -namespace llvm { -namespace MIPatternMatch { - -template -bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P) { - return P.match(MRI, R); -} - -template -bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI, Pattern &&P) { - return P.match(MRI, &MI); -} - -// TODO: Extend for N use. -template struct OneUse_match { - SubPatternT SubPat; - OneUse_match(const SubPatternT &SP) : SubPat(SP) {} - - bool match(const MachineRegisterInfo &MRI, Register Reg) { - return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg); - } -}; - -template -inline OneUse_match m_OneUse(const SubPat &SP) { - return SP; -} - -template struct OneNonDBGUse_match { - SubPatternT SubPat; - OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {} - - bool match(const MachineRegisterInfo &MRI, Register Reg) { - return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg); - } -}; - -template -inline OneNonDBGUse_match m_OneNonDBGUse(const SubPat &SP) { - return SP; -} - -template -inline Optional matchConstant(Register, const MachineRegisterInfo &); - -template <> -inline Optional matchConstant(Register Reg, - const MachineRegisterInfo &MRI) { - return getIConstantVRegVal(Reg, MRI); -} - -template <> -inline Optional matchConstant(Register Reg, - const MachineRegisterInfo &MRI) { - return getIConstantVRegSExtVal(Reg, MRI); -} - -template struct ConstantMatch { - ConstT &CR; - ConstantMatch(ConstT &C) : CR(C) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - if (auto MaybeCst = matchConstant(Reg, MRI)) { - CR = *MaybeCst; - return true; - } - return false; - } -}; - -inline ConstantMatch m_ICst(APInt &Cst) { - return ConstantMatch(Cst); -} -inline ConstantMatch m_ICst(int64_t &Cst) { - return ConstantMatch(Cst); -} - -struct GCstAndRegMatch { - Optional &ValReg; - GCstAndRegMatch(Optional &ValReg) : ValReg(ValReg) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - ValReg = getIConstantVRegValWithLookThrough(Reg, MRI); - return ValReg ? true : false; - } -}; - -inline GCstAndRegMatch m_GCst(Optional &ValReg) { - return GCstAndRegMatch(ValReg); -} - -struct GFCstAndRegMatch { - Optional &FPValReg; - GFCstAndRegMatch(Optional &FPValReg) : FPValReg(FPValReg) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI); - return FPValReg ? true : false; - } -}; - -inline GFCstAndRegMatch m_GFCst(Optional &FPValReg) { - return GFCstAndRegMatch(FPValReg); -} - -struct GFCstOrSplatGFCstMatch { - Optional &FPValReg; - GFCstOrSplatGFCstMatch(Optional &FPValReg) - : FPValReg(FPValReg) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - return (FPValReg = getFConstantSplat(Reg, MRI)) || - (FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI)); - }; -}; - -inline GFCstOrSplatGFCstMatch -m_GFCstOrSplat(Optional &FPValReg) { - return GFCstOrSplatGFCstMatch(FPValReg); -} - -/// Matcher for a specific constant value. -struct SpecificConstantMatch { - int64_t RequestedVal; - SpecificConstantMatch(int64_t RequestedVal) : RequestedVal(RequestedVal) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - int64_t MatchedVal; - return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal; - } -}; - -/// Matches a constant equal to \p RequestedValue. -inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) { - return SpecificConstantMatch(RequestedValue); -} - -/// Matcher for a specific constant splat. -struct SpecificConstantSplatMatch { - int64_t RequestedVal; - SpecificConstantSplatMatch(int64_t RequestedVal) - : RequestedVal(RequestedVal) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - return isBuildVectorConstantSplat(Reg, MRI, RequestedVal, - /* AllowUndef */ false); - } -}; - -/// Matches a constant splat of \p RequestedValue. -inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) { - return SpecificConstantSplatMatch(RequestedValue); -} - -/// Matcher for a specific constant or constant splat. -struct SpecificConstantOrSplatMatch { - int64_t RequestedVal; - SpecificConstantOrSplatMatch(int64_t RequestedVal) - : RequestedVal(RequestedVal) {} - bool match(const MachineRegisterInfo &MRI, Register Reg) { - int64_t MatchedVal; - if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal) - return true; - return isBuildVectorConstantSplat(Reg, MRI, RequestedVal, - /* AllowUndef */ false); - } -}; - -/// Matches a \p RequestedValue constant or a constant splat of \p -/// RequestedValue. -inline SpecificConstantOrSplatMatch -m_SpecificICstOrSplat(int64_t RequestedValue) { - return SpecificConstantOrSplatMatch(RequestedValue); -} - -///{ -/// Convenience matchers for specific integer values. -inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); } -inline SpecificConstantMatch m_AllOnesInt() { - return SpecificConstantMatch(-1); -} -///} - -// TODO: Rework this for different kinds of MachineOperand. -// Currently assumes the Src for a match is a register. -// We might want to support taking in some MachineOperands and call getReg on -// that. - -struct operand_type_match { - bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; } - bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) { - return MO->isReg(); - } -}; - -inline operand_type_match m_Reg() { return operand_type_match(); } - -/// Matching combinators. -template struct And { - template - bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) { - return true; - } -}; - -template -struct And : And { - Pred P; - And(Pred &&p, Preds &&... preds) - : And(std::forward(preds)...), P(std::forward(p)) { - } - template - bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) { - return P.match(MRI, src) && And::match(MRI, src); - } -}; - -template struct Or { - template - bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) { - return false; - } -}; - -template -struct Or : Or { - Pred P; - Or(Pred &&p, Preds &&... preds) - : Or(std::forward(preds)...), P(std::forward(p)) {} - template - bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) { - return P.match(MRI, src) || Or::match(MRI, src); - } -}; - -template And m_all_of(Preds &&... preds) { - return And(std::forward(preds)...); -} - -template Or m_any_of(Preds &&... preds) { - return Or(std::forward(preds)...); -} - -template struct bind_helper { - static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) { - VR = V; - return true; - } -}; - -template <> struct bind_helper { - static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI, - Register Reg) { - MI = MRI.getVRegDef(Reg); - if (MI) - return true; - return false; - } - static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI, - MachineInstr *Inst) { - MI = Inst; - return MI; - } -}; - -template <> struct bind_helper { - static bool bind(const MachineRegisterInfo &MRI, LLT Ty, Register Reg) { - Ty = MRI.getType(Reg); - if (Ty.isValid()) - return true; - return false; - } -}; - -template <> struct bind_helper { - static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F, - Register Reg) { - F = getConstantFPVRegVal(Reg, MRI); - if (F) - return true; - return false; - } -}; - -template struct bind_ty { - Class &VR; - - bind_ty(Class &V) : VR(V) {} - - template bool match(const MachineRegisterInfo &MRI, ITy &&V) { - return bind_helper::bind(MRI, VR, V); - } -}; - -inline bind_ty m_Reg(Register &R) { return R; } -inline bind_ty m_MInstr(MachineInstr *&MI) { return MI; } -inline bind_ty m_Type(LLT Ty) { return Ty; } -inline bind_ty m_Pred(CmpInst::Predicate &P) { return P; } -inline operand_type_match m_Pred() { return operand_type_match(); } - -// Helper for matching G_FCONSTANT -inline bind_ty m_GFCst(const ConstantFP *&C) { return C; } - -// General helper for all the binary generic MI such as G_ADD/G_SUB etc -template -struct BinaryOp_match { - LHS_P L; - RHS_P R; - - BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {} - template - bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { - MachineInstr *TmpMI; - if (mi_match(Op, MRI, m_MInstr(TmpMI))) { - if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) { - return (L.match(MRI, TmpMI->getOperand(1).getReg()) && - R.match(MRI, TmpMI->getOperand(2).getReg())) || - (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) && - L.match(MRI, TmpMI->getOperand(2).getReg()))); - } - } - return false; - } -}; - -// Helper for (commutative) binary generic MI that checks Opcode. -template -struct BinaryOpc_match { - unsigned Opc; - LHS_P L; - RHS_P R; - - BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS) - : Opc(Opcode), L(LHS), R(RHS) {} - template - bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { - MachineInstr *TmpMI; - if (mi_match(Op, MRI, m_MInstr(TmpMI))) { - if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 && - TmpMI->getNumOperands() == 3) { - return (L.match(MRI, TmpMI->getOperand(1).getReg()) && - R.match(MRI, TmpMI->getOperand(2).getReg())) || - (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) && - L.match(MRI, TmpMI->getOperand(2).getReg()))); - } - } - return false; - } -}; - -template -inline BinaryOpc_match m_BinOp(unsigned Opcode, const LHS &L, - const RHS &R) { - return BinaryOpc_match(Opcode, L, R); -} - -template -inline BinaryOpc_match -m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) { - return BinaryOpc_match(Opcode, L, R); -} - -template -inline BinaryOp_match -m_GAdd(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GPtrAdd(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_GSub(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GMul(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GFAdd(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GFMul(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GFSub(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GAnd(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GXor(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_GOr(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GShl(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GLShr(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GAShr(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GSMax(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match -m_GSMin(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc -template struct UnaryOp_match { - SrcTy L; - - UnaryOp_match(const SrcTy &LHS) : L(LHS) {} - template - bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { - MachineInstr *TmpMI; - if (mi_match(Op, MRI, m_MInstr(TmpMI))) { - if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) { - return L.match(MRI, TmpMI->getOperand(1).getReg()); - } - } - return false; - } -}; - -template -inline UnaryOp_match -m_GAnyExt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GSExt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GZExt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GFPExt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GTrunc(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match -m_GBitcast(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match -m_GPtrToInt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match -m_GIntToPtr(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match -m_GFPTrunc(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GFabs(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_GFNeg(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -template -inline UnaryOp_match m_Copy(SrcTy &&Src) { - return UnaryOp_match(std::forward(Src)); -} - -template -inline UnaryOp_match m_GFSqrt(const SrcTy &Src) { - return UnaryOp_match(Src); -} - -// General helper for generic MI compares, i.e. G_ICMP and G_FCMP -// TODO: Allow checking a specific predicate. -template -struct CompareOp_match { - Pred_P P; - LHS_P L; - RHS_P R; - - CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS) - : P(Pred), L(LHS), R(RHS) {} - - template - bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { - MachineInstr *TmpMI; - if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode) - return false; - - auto TmpPred = - static_cast(TmpMI->getOperand(1).getPredicate()); - if (!P.match(MRI, TmpPred)) - return false; - - return L.match(MRI, TmpMI->getOperand(2).getReg()) && - R.match(MRI, TmpMI->getOperand(3).getReg()); - } -}; - -template -inline CompareOp_match -m_GICmp(const Pred &P, const LHS &L, const RHS &R) { - return CompareOp_match(P, L, R); -} - -template -inline CompareOp_match -m_GFCmp(const Pred &P, const LHS &L, const RHS &R) { - return CompareOp_match(P, L, R); -} - -// Helper for checking if a Reg is of specific type. -struct CheckType { - LLT Ty; - CheckType(const LLT Ty) : Ty(Ty) {} - - bool match(const MachineRegisterInfo &MRI, Register Reg) { - return MRI.getType(Reg) == Ty; - } -}; - -inline CheckType m_SpecificType(LLT Ty) { return Ty; } - -template -struct TernaryOp_match { - Src0Ty Src0; - Src1Ty Src1; - Src2Ty Src2; - - TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) - : Src0(Src0), Src1(Src1), Src2(Src2) {} - template - bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { - MachineInstr *TmpMI; - if (mi_match(Op, MRI, m_MInstr(TmpMI))) { - if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) { - return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) && - Src1.match(MRI, TmpMI->getOperand(2).getReg()) && - Src2.match(MRI, TmpMI->getOperand(3).getReg())); - } - } - return false; - } -}; -template -inline TernaryOp_match -m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) { - return TernaryOp_match(Src0, Src1, Src2); -} - -template -inline TernaryOp_match -m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) { - return TernaryOp_match( - Src0, Src1, Src2); -} - -/// Matches a register negated by a G_SUB. -/// G_SUB 0, %negated_reg -template -inline BinaryOp_match -m_Neg(const SrcTy &&Src) { - return m_GSub(m_ZeroInt(), Src); -} - -/// Matches a register not-ed by a G_XOR. -/// G_XOR %not_reg, -1 -template -inline BinaryOp_match -m_Not(const SrcTy &&Src) { - return m_GXor(Src, m_AllOnesInt()); -} - -} // namespace MIPatternMatch -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h deleted file mode 100644 index 1e7111cd23..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ /dev/null @@ -1,1931 +0,0 @@ -//===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file declares the MachineIRBuilder class. -/// This is a helper class to build MachineInstr. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H -#define LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H - -#include "llvm/CodeGen/GlobalISel/CSEInfo.h" -#include "llvm/CodeGen/LowLevelType.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Module.h" - -namespace llvm { - -// Forward declarations. -class MachineFunction; -class MachineInstr; -class TargetInstrInfo; -class GISelChangeObserver; - -/// Class which stores all the state required in a MachineIRBuilder. -/// Since MachineIRBuilders will only store state in this object, it allows -/// to transfer BuilderState between different kinds of MachineIRBuilders. -struct MachineIRBuilderState { - /// MachineFunction under construction. - MachineFunction *MF = nullptr; - /// Information used to access the description of the opcodes. - const TargetInstrInfo *TII = nullptr; - /// Information used to verify types are consistent and to create virtual registers. - MachineRegisterInfo *MRI = nullptr; - /// Debug location to be set to any instruction we create. - DebugLoc DL; - - /// \name Fields describing the insertion point. - /// @{ - MachineBasicBlock *MBB = nullptr; - MachineBasicBlock::iterator II; - /// @} - - GISelChangeObserver *Observer = nullptr; - - GISelCSEInfo *CSEInfo = nullptr; -}; - -class DstOp { - union { - LLT LLTTy; - Register Reg; - const TargetRegisterClass *RC; - }; - -public: - enum class DstType { Ty_LLT, Ty_Reg, Ty_RC }; - DstOp(unsigned R) : Reg(R), Ty(DstType::Ty_Reg) {} - DstOp(Register R) : Reg(R), Ty(DstType::Ty_Reg) {} - DstOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(DstType::Ty_Reg) {} - DstOp(const LLT T) : LLTTy(T), Ty(DstType::Ty_LLT) {} - DstOp(const TargetRegisterClass *TRC) : RC(TRC), Ty(DstType::Ty_RC) {} - - void addDefToMIB(MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) const { - switch (Ty) { - case DstType::Ty_Reg: - MIB.addDef(Reg); - break; - case DstType::Ty_LLT: - MIB.addDef(MRI.createGenericVirtualRegister(LLTTy)); - break; - case DstType::Ty_RC: - MIB.addDef(MRI.createVirtualRegister(RC)); - break; - } - } - - LLT getLLTTy(const MachineRegisterInfo &MRI) const { - switch (Ty) { - case DstType::Ty_RC: - return LLT{}; - case DstType::Ty_LLT: - return LLTTy; - case DstType::Ty_Reg: - return MRI.getType(Reg); - } - llvm_unreachable("Unrecognised DstOp::DstType enum"); - } - - Register getReg() const { - assert(Ty == DstType::Ty_Reg && "Not a register"); - return Reg; - } - - const TargetRegisterClass *getRegClass() const { - switch (Ty) { - case DstType::Ty_RC: - return RC; - default: - llvm_unreachable("Not a RC Operand"); - } - } - - DstType getDstOpKind() const { return Ty; } - -private: - DstType Ty; -}; - -class SrcOp { - union { - MachineInstrBuilder SrcMIB; - Register Reg; - CmpInst::Predicate Pred; - int64_t Imm; - }; - -public: - enum class SrcType { Ty_Reg, Ty_MIB, Ty_Predicate, Ty_Imm }; - SrcOp(Register R) : Reg(R), Ty(SrcType::Ty_Reg) {} - SrcOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(SrcType::Ty_Reg) {} - SrcOp(const MachineInstrBuilder &MIB) : SrcMIB(MIB), Ty(SrcType::Ty_MIB) {} - SrcOp(const CmpInst::Predicate P) : Pred(P), Ty(SrcType::Ty_Predicate) {} - /// Use of registers held in unsigned integer variables (or more rarely signed - /// integers) is no longer permitted to avoid ambiguity with upcoming support - /// for immediates. - SrcOp(unsigned) = delete; - SrcOp(int) = delete; - SrcOp(uint64_t V) : Imm(V), Ty(SrcType::Ty_Imm) {} - SrcOp(int64_t V) : Imm(V), Ty(SrcType::Ty_Imm) {} - - void addSrcToMIB(MachineInstrBuilder &MIB) const { - switch (Ty) { - case SrcType::Ty_Predicate: - MIB.addPredicate(Pred); - break; - case SrcType::Ty_Reg: - MIB.addUse(Reg); - break; - case SrcType::Ty_MIB: - MIB.addUse(SrcMIB->getOperand(0).getReg()); - break; - case SrcType::Ty_Imm: - MIB.addImm(Imm); - break; - } - } - - LLT getLLTTy(const MachineRegisterInfo &MRI) const { - switch (Ty) { - case SrcType::Ty_Predicate: - case SrcType::Ty_Imm: - llvm_unreachable("Not a register operand"); - case SrcType::Ty_Reg: - return MRI.getType(Reg); - case SrcType::Ty_MIB: - return MRI.getType(SrcMIB->getOperand(0).getReg()); - } - llvm_unreachable("Unrecognised SrcOp::SrcType enum"); - } - - Register getReg() const { - switch (Ty) { - case SrcType::Ty_Predicate: - case SrcType::Ty_Imm: - llvm_unreachable("Not a register operand"); - case SrcType::Ty_Reg: - return Reg; - case SrcType::Ty_MIB: - return SrcMIB->getOperand(0).getReg(); - } - llvm_unreachable("Unrecognised SrcOp::SrcType enum"); - } - - CmpInst::Predicate getPredicate() const { - switch (Ty) { - case SrcType::Ty_Predicate: - return Pred; - default: - llvm_unreachable("Not a register operand"); - } - } - - int64_t getImm() const { - switch (Ty) { - case SrcType::Ty_Imm: - return Imm; - default: - llvm_unreachable("Not an immediate"); - } - } - - SrcType getSrcOpKind() const { return Ty; } - -private: - SrcType Ty; -}; - -/// Helper class to build MachineInstr. -/// It keeps internally the insertion point and debug location for all -/// the new instructions we want to create. -/// This information can be modify via the related setters. -class MachineIRBuilder { - - MachineIRBuilderState State; - -protected: - void validateTruncExt(const LLT Dst, const LLT Src, bool IsExtend); - - void validateUnaryOp(const LLT Res, const LLT Op0); - void validateBinaryOp(const LLT Res, const LLT Op0, const LLT Op1); - void validateShiftOp(const LLT Res, const LLT Op0, const LLT Op1); - - void validateSelectOp(const LLT ResTy, const LLT TstTy, const LLT Op0Ty, - const LLT Op1Ty); - - void recordInsertion(MachineInstr *InsertedInstr) const { - if (State.Observer) - State.Observer->createdInstr(*InsertedInstr); - } - -public: - /// Some constructors for easy use. - MachineIRBuilder() = default; - MachineIRBuilder(MachineFunction &MF) { setMF(MF); } - - MachineIRBuilder(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt) { - setMF(*MBB.getParent()); - setInsertPt(MBB, InsPt); - } - - MachineIRBuilder(MachineInstr &MI) : - MachineIRBuilder(*MI.getParent(), MI.getIterator()) { - setInstr(MI); - setDebugLoc(MI.getDebugLoc()); - } - - MachineIRBuilder(MachineInstr &MI, GISelChangeObserver &Observer) : - MachineIRBuilder(MI) { - setChangeObserver(Observer); - } - - virtual ~MachineIRBuilder() = default; - - MachineIRBuilder(const MachineIRBuilderState &BState) : State(BState) {} - - const TargetInstrInfo &getTII() { - assert(State.TII && "TargetInstrInfo is not set"); - return *State.TII; - } - - /// Getter for the function we currently build. - MachineFunction &getMF() { - assert(State.MF && "MachineFunction is not set"); - return *State.MF; - } - - const MachineFunction &getMF() const { - assert(State.MF && "MachineFunction is not set"); - return *State.MF; - } - - const DataLayout &getDataLayout() const { - return getMF().getFunction().getParent()->getDataLayout(); - } - - /// Getter for DebugLoc - const DebugLoc &getDL() { return State.DL; } - - /// Getter for MRI - MachineRegisterInfo *getMRI() { return State.MRI; } - const MachineRegisterInfo *getMRI() const { return State.MRI; } - - /// Getter for the State - MachineIRBuilderState &getState() { return State; } - - /// Getter for the basic block we currently build. - const MachineBasicBlock &getMBB() const { - assert(State.MBB && "MachineBasicBlock is not set"); - return *State.MBB; - } - - MachineBasicBlock &getMBB() { - return const_cast( - const_cast(this)->getMBB()); - } - - GISelCSEInfo *getCSEInfo() { return State.CSEInfo; } - const GISelCSEInfo *getCSEInfo() const { return State.CSEInfo; } - - /// Current insertion point for new instructions. - MachineBasicBlock::iterator getInsertPt() { return State.II; } - - /// Set the insertion point before the specified position. - /// \pre MBB must be in getMF(). - /// \pre II must be a valid iterator in MBB. - void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II) { - assert(MBB.getParent() == &getMF() && - "Basic block is in a different function"); - State.MBB = &MBB; - State.II = II; - } - - /// @} - - void setCSEInfo(GISelCSEInfo *Info) { State.CSEInfo = Info; } - - /// \name Setters for the insertion point. - /// @{ - /// Set the MachineFunction where to build instructions. - void setMF(MachineFunction &MF); - - /// Set the insertion point to the end of \p MBB. - /// \pre \p MBB must be contained by getMF(). - void setMBB(MachineBasicBlock &MBB) { - State.MBB = &MBB; - State.II = MBB.end(); - assert(&getMF() == MBB.getParent() && - "Basic block is in a different function"); - } - - /// Set the insertion point to before MI. - /// \pre MI must be in getMF(). - void setInstr(MachineInstr &MI) { - assert(MI.getParent() && "Instruction is not part of a basic block"); - setMBB(*MI.getParent()); - State.II = MI.getIterator(); - } - /// @} - - /// Set the insertion point to before MI, and set the debug loc to MI's loc. - /// \pre MI must be in getMF(). - void setInstrAndDebugLoc(MachineInstr &MI) { - setInstr(MI); - setDebugLoc(MI.getDebugLoc()); - } - - void setChangeObserver(GISelChangeObserver &Observer) { - State.Observer = &Observer; - } - - void stopObservingChanges() { State.Observer = nullptr; } - /// @} - - /// Set the debug location to \p DL for all the next build instructions. - void setDebugLoc(const DebugLoc &DL) { this->State.DL = DL; } - - /// Get the current instruction's debug location. - const DebugLoc &getDebugLoc() { return State.DL; } - - /// Build and insert = \p Opcode . - /// The insertion point is the one set by the last call of either - /// setBasicBlock or setMI. - /// - /// \pre setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildInstr(unsigned Opcode) { - return insertInstr(buildInstrNoInsert(Opcode)); - } - - /// Build but don't insert = \p Opcode . - /// - /// \pre setMF, setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildInstrNoInsert(unsigned Opcode); - - /// Insert an existing instruction at the insertion point. - MachineInstrBuilder insertInstr(MachineInstrBuilder MIB); - - /// Build and insert a DBG_VALUE instruction expressing the fact that the - /// associated \p Variable lives in \p Reg (suitably modified by \p Expr). - MachineInstrBuilder buildDirectDbgValue(Register Reg, const MDNode *Variable, - const MDNode *Expr); - - /// Build and insert a DBG_VALUE instruction expressing the fact that the - /// associated \p Variable lives in memory at \p Reg (suitably modified by \p - /// Expr). - MachineInstrBuilder buildIndirectDbgValue(Register Reg, - const MDNode *Variable, - const MDNode *Expr); - - /// Build and insert a DBG_VALUE instruction expressing the fact that the - /// associated \p Variable lives in the stack slot specified by \p FI - /// (suitably modified by \p Expr). - MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable, - const MDNode *Expr); - - /// Build and insert a DBG_VALUE instructions specifying that \p Variable is - /// given by \p C (suitably modified by \p Expr). - MachineInstrBuilder buildConstDbgValue(const Constant &C, - const MDNode *Variable, - const MDNode *Expr); - - /// Build and insert a DBG_LABEL instructions specifying that \p Label is - /// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label". - MachineInstrBuilder buildDbgLabel(const MDNode *Label); - - /// Build and insert \p Res = G_DYN_STACKALLOC \p Size, \p Align - /// - /// G_DYN_STACKALLOC does a dynamic stack allocation and writes the address of - /// the allocated memory into \p Res. - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildDynStackAlloc(const DstOp &Res, const SrcOp &Size, - Align Alignment); - - /// Build and insert \p Res = G_FRAME_INDEX \p Idx - /// - /// G_FRAME_INDEX materializes the address of an alloca value or other - /// stack-based object. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx); - - /// Build and insert \p Res = G_GLOBAL_VALUE \p GV - /// - /// G_GLOBAL_VALUE materializes the address of the specified global - /// into \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with pointer type - /// in the same address space as \p GV. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV); - - /// Build and insert \p Res = G_PTR_ADD \p Op0, \p Op1 - /// - /// G_PTR_ADD adds \p Op1 addressible units to the pointer specified by \p Op0, - /// storing the resulting pointer in \p Res. Addressible units are typically - /// bytes but this can vary between targets. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Op0 must be generic virtual registers with pointer - /// type. - /// \pre \p Op1 must be a generic virtual register with scalar type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, - const SrcOp &Op1); - - /// Materialize and insert \p Res = G_PTR_ADD \p Op0, (G_CONSTANT \p Value) - /// - /// G_PTR_ADD adds \p Value bytes to the pointer specified by \p Op0, - /// storing the resulting pointer in \p Res. If \p Value is zero then no - /// G_PTR_ADD or G_CONSTANT will be created and \pre Op0 will be assigned to - /// \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Op0 must be a generic virtual register with pointer type. - /// \pre \p ValueTy must be a scalar type. - /// \pre \p Res must be 0. This is to detect confusion between - /// materializePtrAdd() and buildPtrAdd(). - /// \post \p Res will either be a new generic virtual register of the same - /// type as \p Op0 or \p Op0 itself. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - Optional materializePtrAdd(Register &Res, Register Op0, - const LLT ValueTy, - uint64_t Value); - - /// Build and insert \p Res = G_PTRMASK \p Op0, \p Op1 - MachineInstrBuilder buildPtrMask(const DstOp &Res, const SrcOp &Op0, - const SrcOp &Op1) { - return buildInstr(TargetOpcode::G_PTRMASK, {Res}, {Op0, Op1}); - } - - /// Build and insert \p Res = G_PTRMASK \p Op0, \p G_CONSTANT (1 << NumBits) - 1 - /// - /// This clears the low bits of a pointer operand without destroying its - /// pointer properties. This has the effect of rounding the address *down* to - /// a specified alignment in bits. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Op0 must be generic virtual registers with pointer - /// type. - /// \pre \p NumBits must be an integer representing the number of low bits to - /// be cleared in \p Op0. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMaskLowPtrBits(const DstOp &Res, const SrcOp &Op0, - uint32_t NumBits); - - /// Build and insert - /// a, b, ..., x = G_UNMERGE_VALUES \p Op0 - /// \p Res = G_BUILD_VECTOR a, b, ..., x, undef, ..., undef - /// - /// Pad \p Op0 with undef elements to match number of elements in \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Op0 must be generic virtual registers with vector type, - /// same vector element type and Op0 must have fewer elements then Res. - /// - /// \return a MachineInstrBuilder for the newly created build vector instr. - MachineInstrBuilder buildPadVectorWithUndefElements(const DstOp &Res, - const SrcOp &Op0); - - /// Build and insert - /// a, b, ..., x, y, z = G_UNMERGE_VALUES \p Op0 - /// \p Res = G_BUILD_VECTOR a, b, ..., x - /// - /// Delete trailing elements in \p Op0 to match number of elements in \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Op0 must be generic virtual registers with vector type, - /// same vector element type and Op0 must have more elements then Res. - /// - /// \return a MachineInstrBuilder for the newly created build vector instr. - MachineInstrBuilder buildDeleteTrailingVectorElements(const DstOp &Res, - const SrcOp &Op0); - - /// Build and insert \p Res, \p CarryOut = G_UADDO \p Op0, \p Op1 - /// - /// G_UADDO sets \p Res to \p Op0 + \p Op1 (truncated to the bit width) and - /// sets \p CarryOut to 1 if the result overflowed in unsigned arithmetic. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers with the - /// same scalar type. - ////\pre \p CarryOut must be generic virtual register with scalar type - ///(typically s1) - /// - /// \return The newly created instruction. - MachineInstrBuilder buildUAddo(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1) { - return buildInstr(TargetOpcode::G_UADDO, {Res, CarryOut}, {Op0, Op1}); - } - - /// Build and insert \p Res, \p CarryOut = G_USUBO \p Op0, \p Op1 - MachineInstrBuilder buildUSubo(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1) { - return buildInstr(TargetOpcode::G_USUBO, {Res, CarryOut}, {Op0, Op1}); - } - - /// Build and insert \p Res, \p CarryOut = G_SADDO \p Op0, \p Op1 - MachineInstrBuilder buildSAddo(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1) { - return buildInstr(TargetOpcode::G_SADDO, {Res, CarryOut}, {Op0, Op1}); - } - - /// Build and insert \p Res, \p CarryOut = G_SUBO \p Op0, \p Op1 - MachineInstrBuilder buildSSubo(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1) { - return buildInstr(TargetOpcode::G_SSUBO, {Res, CarryOut}, {Op0, Op1}); - } - - /// Build and insert \p Res, \p CarryOut = G_UADDE \p Op0, - /// \p Op1, \p CarryIn - /// - /// G_UADDE sets \p Res to \p Op0 + \p Op1 + \p CarryIn (truncated to the bit - /// width) and sets \p CarryOut to 1 if the result overflowed in unsigned - /// arithmetic. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same scalar type. - /// \pre \p CarryOut and \p CarryIn must be generic virtual - /// registers with the same scalar type (typically s1) - /// - /// \return The newly created instruction. - MachineInstrBuilder buildUAdde(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1, - const SrcOp &CarryIn) { - return buildInstr(TargetOpcode::G_UADDE, {Res, CarryOut}, - {Op0, Op1, CarryIn}); - } - - /// Build and insert \p Res, \p CarryOut = G_USUBE \p Op0, \p Op1, \p CarryInp - MachineInstrBuilder buildUSube(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1, - const SrcOp &CarryIn) { - return buildInstr(TargetOpcode::G_USUBE, {Res, CarryOut}, - {Op0, Op1, CarryIn}); - } - - /// Build and insert \p Res, \p CarryOut = G_SADDE \p Op0, \p Op1, \p CarryInp - MachineInstrBuilder buildSAdde(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1, - const SrcOp &CarryIn) { - return buildInstr(TargetOpcode::G_SADDE, {Res, CarryOut}, - {Op0, Op1, CarryIn}); - } - - /// Build and insert \p Res, \p CarryOut = G_SSUBE \p Op0, \p Op1, \p CarryInp - MachineInstrBuilder buildSSube(const DstOp &Res, const DstOp &CarryOut, - const SrcOp &Op0, const SrcOp &Op1, - const SrcOp &CarryIn) { - return buildInstr(TargetOpcode::G_SSUBE, {Res, CarryOut}, - {Op0, Op1, CarryIn}); - } - - /// Build and insert \p Res = G_ANYEXT \p Op0 - /// - /// G_ANYEXT produces a register of the specified width, with bits 0 to - /// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are unspecified - /// (i.e. this is neither zero nor sign-extension). For a vector register, - /// each element is extended individually. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be smaller than \p Res - /// - /// \return The newly created instruction. - - MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op); - - /// Build and insert \p Res = G_SEXT \p Op - /// - /// G_SEXT produces a register of the specified width, with bits 0 to - /// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are duplicated from the - /// high bit of \p Op (i.e. 2s-complement sign extended). - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be smaller than \p Res - /// - /// \return The newly created instruction. - MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op); - - /// Build and insert \p Res = G_SEXT_INREG \p Op, ImmOp - MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp) { - return buildInstr(TargetOpcode::G_SEXT_INREG, {Res}, {Op, SrcOp(ImmOp)}); - } - - /// Build and insert \p Res = G_FPEXT \p Op - MachineInstrBuilder buildFPExt(const DstOp &Res, const SrcOp &Op, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FPEXT, {Res}, {Op}, Flags); - } - - - /// Build and insert a G_PTRTOINT instruction. - MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_PTRTOINT, {Dst}, {Src}); - } - - /// Build and insert a G_INTTOPTR instruction. - MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_INTTOPTR, {Dst}, {Src}); - } - - /// Build and insert \p Dst = G_BITCAST \p Src - MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_BITCAST, {Dst}, {Src}); - } - - /// Build and insert \p Dst = G_ADDRSPACE_CAST \p Src - MachineInstrBuilder buildAddrSpaceCast(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_ADDRSPACE_CAST, {Dst}, {Src}); - } - - /// \return The opcode of the extension the target wants to use for boolean - /// values. - unsigned getBoolExtOp(bool IsVec, bool IsFP) const; - - // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_SEXT \p Op, or \p Res - // = G_ZEXT \p Op depending on how the target wants to extend boolean values. - MachineInstrBuilder buildBoolExt(const DstOp &Res, const SrcOp &Op, - bool IsFP); - - /// Build and insert \p Res = G_ZEXT \p Op - /// - /// G_ZEXT produces a register of the specified width, with bits 0 to - /// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are 0. For a vector - /// register, each element is extended individually. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be smaller than \p Res - /// - /// \return The newly created instruction. - MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op); - - /// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or - /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. - /// /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op); - - /// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or - /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. - /// /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op); - - // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or - /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. - /// /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op); - - /// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p - /// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and - /// \p Op. - /// /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, const DstOp &Res, - const SrcOp &Op); - - /// Build and inserts \p Res = \p G_AND \p Op, \p LowBitsSet(ImmOp) - /// Since there is no G_ZEXT_INREG like G_SEXT_INREG, the instruction is - /// emulated using G_AND. - MachineInstrBuilder buildZExtInReg(const DstOp &Res, const SrcOp &Op, - int64_t ImmOp); - - /// Build and insert an appropriate cast between two registers of equal size. - MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src); - - /// Build and insert G_BR \p Dest - /// - /// G_BR is an unconditional branch to \p Dest. - /// - /// \pre setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBr(MachineBasicBlock &Dest); - - /// Build and insert G_BRCOND \p Tst, \p Dest - /// - /// G_BRCOND is a conditional branch to \p Dest. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Tst must be a generic virtual register with scalar - /// type. At the beginning of legalization, this will be a single - /// bit (s1). Targets with interesting flags registers may change - /// this. For a wider type, whether the branch is taken must only - /// depend on bit 0 (for now). - /// - /// \return The newly created instruction. - MachineInstrBuilder buildBrCond(const SrcOp &Tst, MachineBasicBlock &Dest); - - /// Build and insert G_BRINDIRECT \p Tgt - /// - /// G_BRINDIRECT is an indirect branch to \p Tgt. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Tgt must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBrIndirect(Register Tgt); - - /// Build and insert G_BRJT \p TablePtr, \p JTI, \p IndexReg - /// - /// G_BRJT is a jump table branch using a table base pointer \p TablePtr, - /// jump table index \p JTI and index \p IndexReg - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p TablePtr must be a generic virtual register with pointer type. - /// \pre \p JTI must be a jump table index. - /// \pre \p IndexReg must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBrJT(Register TablePtr, unsigned JTI, - Register IndexReg); - - /// Build and insert \p Res = G_CONSTANT \p Val - /// - /// G_CONSTANT is an integer constant with the specified size and value. \p - /// Val will be extended or truncated to the size of \p Reg. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or pointer - /// type. - /// - /// \return The newly created instruction. - virtual MachineInstrBuilder buildConstant(const DstOp &Res, - const ConstantInt &Val); - - /// Build and insert \p Res = G_CONSTANT \p Val - /// - /// G_CONSTANT is an integer constant with the specified size and value. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val); - MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val); - - /// Build and insert \p Res = G_FCONSTANT \p Val - /// - /// G_FCONSTANT is a floating-point constant with the specified size and - /// value. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar type. - /// - /// \return The newly created instruction. - virtual MachineInstrBuilder buildFConstant(const DstOp &Res, - const ConstantFP &Val); - - MachineInstrBuilder buildFConstant(const DstOp &Res, double Val); - MachineInstrBuilder buildFConstant(const DstOp &Res, const APFloat &Val); - - /// Build and insert \p Res = COPY Op - /// - /// Register-to-register COPY sets \p Res to \p Op. - /// - /// \pre setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op); - - - /// Build and insert G_ASSERT_SEXT, G_ASSERT_ZEXT, or G_ASSERT_ALIGN - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAssertOp(unsigned Opc, const DstOp &Res, const SrcOp &Op, - unsigned Val) { - return buildInstr(Opc, Res, Op).addImm(Val); - } - - /// Build and insert \p Res = G_ASSERT_ZEXT Op, Size - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAssertZExt(const DstOp &Res, const SrcOp &Op, - unsigned Size) { - return buildAssertOp(TargetOpcode::G_ASSERT_ZEXT, Res, Op, Size); - } - - /// Build and insert \p Res = G_ASSERT_SEXT Op, Size - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAssertSExt(const DstOp &Res, const SrcOp &Op, - unsigned Size) { - return buildAssertOp(TargetOpcode::G_ASSERT_SEXT, Res, Op, Size); - } - - /// Build and insert \p Res = G_ASSERT_ALIGN Op, AlignVal - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAssertAlign(const DstOp &Res, const SrcOp &Op, - Align AlignVal) { - return buildAssertOp(TargetOpcode::G_ASSERT_ALIGN, Res, Op, AlignVal.value()); - } - - /// Build and insert `Res = G_LOAD Addr, MMO`. - /// - /// Loads the value stored at \p Addr. Puts the result in \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, - MachineMemOperand &MMO) { - return buildLoadInstr(TargetOpcode::G_LOAD, Res, Addr, MMO); - } - - /// Build and insert a G_LOAD instruction, while constructing the - /// MachineMemOperand. - MachineInstrBuilder - buildLoad(const DstOp &Res, const SrcOp &Addr, MachinePointerInfo PtrInfo, - Align Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()); - - /// Build and insert `Res = Addr, MMO`. - /// - /// Loads the value stored at \p Addr. Puts the result in \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, - const SrcOp &Addr, MachineMemOperand &MMO); - - /// Helper to create a load from a constant offset given a base address. Load - /// the type of \p Dst from \p Offset from the given base address and memory - /// operand. - MachineInstrBuilder buildLoadFromOffset(const DstOp &Dst, - const SrcOp &BasePtr, - MachineMemOperand &BaseMMO, - int64_t Offset); - - /// Build and insert `G_STORE Val, Addr, MMO`. - /// - /// Stores the value \p Val to \p Addr. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Val must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, - MachineMemOperand &MMO); - - /// Build and insert a G_STORE instruction, while constructing the - /// MachineMemOperand. - MachineInstrBuilder - buildStore(const SrcOp &Val, const SrcOp &Addr, MachinePointerInfo PtrInfo, - Align Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()); - - /// Build and insert `Res0, ... = G_EXTRACT Src, Idx0`. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Src must be generic virtual registers. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index); - - /// Build and insert \p Res = IMPLICIT_DEF. - MachineInstrBuilder buildUndef(const DstOp &Res); - - /// Build and insert instructions to put \p Ops together at the specified p - /// Indices to form a larger register. - /// - /// If the types of the input registers are uniform and cover the entirety of - /// \p Res then a G_MERGE_VALUES will be produced. Otherwise an IMPLICIT_DEF - /// followed by a sequence of G_INSERT instructions. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre The final element of the sequence must not extend past the end of the - /// destination register. - /// \pre The bits defined by each Op (derived from index and scalar size) must - /// not overlap. - /// \pre \p Indices must be in ascending order of bit position. - void buildSequence(Register Res, ArrayRef Ops, - ArrayRef Indices); - - /// Build and insert \p Res = G_MERGE_VALUES \p Op0, ... - /// - /// G_MERGE_VALUES combines the input elements contiguously into a larger - /// register. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre The entire register \p Res (and no more) must be covered by the input - /// registers. - /// \pre The type of all \p Ops registers must be identical. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef Ops); - MachineInstrBuilder buildMerge(const DstOp &Res, - std::initializer_list Ops); - - /// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op - /// - /// G_UNMERGE_VALUES splits contiguous bits of the input into multiple - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre The entire register \p Res (and no more) must be covered by the input - /// registers. - /// \pre The type of all \p Res registers must be identical. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildUnmerge(ArrayRef Res, const SrcOp &Op); - MachineInstrBuilder buildUnmerge(ArrayRef Res, const SrcOp &Op); - - /// Build and insert an unmerge of \p Res sized pieces to cover \p Op - MachineInstrBuilder buildUnmerge(LLT Res, const SrcOp &Op); - - /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ... - /// - /// G_BUILD_VECTOR creates a vector value from multiple scalar registers. - /// \pre setBasicBlock or setMI must have been called. - /// \pre The entire register \p Res (and no more) must be covered by the - /// input scalar registers. - /// \pre The type of all \p Ops registers must be identical. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBuildVector(const DstOp &Res, - ArrayRef Ops); - - /// Build and insert \p Res = G_BUILD_VECTOR with \p Src replicated to fill - /// the number of elements - MachineInstrBuilder buildSplatVector(const DstOp &Res, - const SrcOp &Src); - - /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ... - /// - /// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers - /// which have types larger than the destination vector element type, and - /// truncates the values to fit. - /// - /// If the operands given are already the same size as the vector elt type, - /// then this method will instead create a G_BUILD_VECTOR instruction. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre The type of all \p Ops registers must be identical. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, - ArrayRef Ops); - - /// Build and insert a vector splat of a scalar \p Src using a - /// G_INSERT_VECTOR_ELT and G_SHUFFLE_VECTOR idiom. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Src must have the same type as the element type of \p Dst - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildShuffleSplat(const DstOp &Res, const SrcOp &Src); - - /// Build and insert \p Res = G_SHUFFLE_VECTOR \p Src1, \p Src2, \p Mask - /// - /// \pre setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildShuffleVector(const DstOp &Res, const SrcOp &Src1, - const SrcOp &Src2, ArrayRef Mask); - - /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ... - /// - /// G_CONCAT_VECTORS creates a vector from the concatenation of 2 or more - /// vectors. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre The entire register \p Res (and no more) must be covered by the input - /// registers. - /// \pre The type of all source operands must be identical. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildConcatVectors(const DstOp &Res, - ArrayRef Ops); - - MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, - const SrcOp &Op, unsigned Index); - - /// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or - /// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the - /// result register definition unless \p Reg is NoReg (== 0). The second - /// operand will be the intrinsic's ID. - /// - /// Callers are expected to add the required definitions and uses afterwards. - /// - /// \pre setBasicBlock or setMI must have been called. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef Res, - bool HasSideEffects); - MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef Res, - bool HasSideEffects); - - /// Build and insert \p Res = G_FPTRUNC \p Op - /// - /// G_FPTRUNC converts a floating-point value into one with a smaller type. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// \pre \p Res must be smaller than \p Op - /// - /// \return The newly created instruction. - MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, - Optional Flags = None); - - /// Build and insert \p Res = G_TRUNC \p Op - /// - /// G_TRUNC extracts the low bits of a type. For a vector type each element is - /// truncated independently before being packed into the destination. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar or vector type. - /// \pre \p Op must be a generic virtual register with scalar or vector type. - /// \pre \p Res must be smaller than \p Op - /// - /// \return The newly created instruction. - MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op); - - /// Build and insert a \p Res = G_ICMP \p Pred, \p Op0, \p Op1 - /// - /// \pre setBasicBlock or setMI must have been called. - - /// \pre \p Res must be a generic virtual register with scalar or - /// vector type. Typically this starts as s1 or . - /// \pre \p Op0 and Op1 must be generic virtual registers with the - /// same number of elements as \p Res. If \p Res is a scalar, - /// \p Op0 must be either a scalar or pointer. - /// \pre \p Pred must be an integer predicate. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, - const SrcOp &Op0, const SrcOp &Op1); - - /// Build and insert a \p Res = G_FCMP \p Pred\p Op0, \p Op1 - /// - /// \pre setBasicBlock or setMI must have been called. - - /// \pre \p Res must be a generic virtual register with scalar or - /// vector type. Typically this starts as s1 or . - /// \pre \p Op0 and Op1 must be generic virtual registers with the - /// same number of elements as \p Res (or scalar, if \p Res is - /// scalar). - /// \pre \p Pred must be a floating-point predicate. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res, - const SrcOp &Op0, const SrcOp &Op1, - Optional Flags = None); - - /// Build and insert a \p Res = G_SELECT \p Tst, \p Op0, \p Op1 - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same type. - /// \pre \p Tst must be a generic virtual register with scalar, pointer or - /// vector type. If vector then it must have the same number of - /// elements as the other parameters. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, - const SrcOp &Op0, const SrcOp &Op1, - Optional Flags = None); - - /// Build and insert \p Res = G_INSERT_VECTOR_ELT \p Val, - /// \p Elt, \p Idx - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res and \p Val must be a generic virtual register - // with the same vector type. - /// \pre \p Elt and \p Idx must be a generic virtual register - /// with scalar type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildInsertVectorElement(const DstOp &Res, - const SrcOp &Val, - const SrcOp &Elt, - const SrcOp &Idx); - - /// Build and insert \p Res = G_EXTRACT_VECTOR_ELT \p Val, \p Idx - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register with scalar type. - /// \pre \p Val must be a generic virtual register with vector type. - /// \pre \p Idx must be a generic virtual register with scalar type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildExtractVectorElement(const DstOp &Res, - const SrcOp &Val, - const SrcOp &Idx); - - /// Build and insert `OldValRes, SuccessRes = - /// G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr, CmpVal, NewVal, MMO`. - /// - /// Atomically replace the value at \p Addr with \p NewVal if it is currently - /// \p CmpVal otherwise leaves it unchanged. Puts the original value from \p - /// Addr in \p Res, along with an s1 indicating whether it was replaced. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register of scalar type. - /// \pre \p SuccessRes must be a generic virtual register of scalar type. It - /// will be assigned 0 on failure and 1 on success. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, \p CmpVal, and \p NewVal must be generic virtual - /// registers of the same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder - buildAtomicCmpXchgWithSuccess(Register OldValRes, Register SuccessRes, - Register Addr, Register CmpVal, Register NewVal, - MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, - /// MMO`. - /// - /// Atomically replace the value at \p Addr with \p NewVal if it is currently - /// \p CmpVal otherwise leaves it unchanged. Puts the original value from \p - /// Addr in \p Res. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register of scalar type. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, \p CmpVal, and \p NewVal must be generic virtual - /// registers of the same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicCmpXchg(Register OldValRes, Register Addr, - Register CmpVal, Register NewVal, - MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_ Addr, Val, MMO`. - /// - /// Atomically read-modify-update the value at \p Addr with \p Val. Puts the - /// original value from \p Addr in \p OldValRes. The modification is - /// determined by the opcode. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMW(unsigned Opcode, const DstOp &OldValRes, - const SrcOp &Addr, const SrcOp &Val, - MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_XCHG Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with \p Val. Puts the original - /// value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXchg(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_ADD Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the addition of \p Val and - /// the original value. Puts the original value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAdd(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_SUB Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the subtraction of \p Val and - /// the original value. Puts the original value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWSub(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_AND Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the bitwise and of \p Val and - /// the original value. Puts the original value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAnd(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_NAND Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the bitwise nand of \p Val - /// and the original value. Puts the original value from \p Addr in \p - /// OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWNand(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_OR Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the bitwise or of \p Val and - /// the original value. Puts the original value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWOr(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_XOR Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the bitwise xor of \p Val and - /// the original value. Puts the original value from \p Addr in \p OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXor(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_MAX Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the signed maximum of \p - /// Val and the original value. Puts the original value from \p Addr in \p - /// OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMax(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_MIN Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the signed minimum of \p - /// Val and the original value. Puts the original value from \p Addr in \p - /// OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMin(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_UMAX Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the unsigned maximum of \p - /// Val and the original value. Puts the original value from \p Addr in \p - /// OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmax(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_UMIN Addr, Val, MMO`. - /// - /// Atomically replace the value at \p Addr with the unsigned minimum of \p - /// Val and the original value. Puts the original value from \p Addr in \p - /// OldValRes. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p OldValRes must be a generic virtual register. - /// \pre \p Addr must be a generic virtual register with pointer type. - /// \pre \p OldValRes, and \p Val must be generic virtual registers of the - /// same type. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmin(Register OldValRes, Register Addr, - Register Val, MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_FADD Addr, Val, MMO`. - MachineInstrBuilder buildAtomicRMWFAdd( - const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, - MachineMemOperand &MMO); - - /// Build and insert `OldValRes = G_ATOMICRMW_FSUB Addr, Val, MMO`. - MachineInstrBuilder buildAtomicRMWFSub( - const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, - MachineMemOperand &MMO); - - /// Build and insert `G_FENCE Ordering, Scope`. - MachineInstrBuilder buildFence(unsigned Ordering, unsigned Scope); - - /// Build and insert \p Dst = G_FREEZE \p Src - MachineInstrBuilder buildFreeze(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_FREEZE, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_BLOCK_ADDR \p BA - /// - /// G_BLOCK_ADDR computes the address of a basic block. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res must be a generic virtual register of a pointer type. - /// - /// \return The newly created instruction. - MachineInstrBuilder buildBlockAddress(Register Res, const BlockAddress *BA); - - /// Build and insert \p Res = G_ADD \p Op0, \p Op1 - /// - /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - - MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_ADD, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_SUB \p Op0, \p Op1 - /// - /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - - MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_SUB, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_MUL \p Op0, \p Op1 - /// - /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildUMulH(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_UMULH, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildSMulH(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_SMULH, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_UREM \p Op0, \p Op1 - MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_UREM, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildFMul(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMUL, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildFMinNum(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMINNUM, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildFMaxNum(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMAXNUM, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildFMinNumIEEE(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMINNUM_IEEE, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildFMaxNumIEEE(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMAXNUM_IEEE, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_SHL, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_LSHR, {Dst}, {Src0, Src1}, Flags); - } - - MachineInstrBuilder buildAShr(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_ASHR, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_AND \p Op0, \p Op1 - /// - /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p - /// Op1. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - - MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_AND, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Res = G_OR \p Op0, \p Op1 - /// - /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p - /// Op1. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_OR, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_XOR \p Op0, \p Op1 - MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, Src1}); - } - - /// Build and insert a bitwise not, - /// \p NegOne = G_CONSTANT -1 - /// \p Res = G_OR \p Op0, NegOne - MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0) { - auto NegOne = buildConstant(Dst.getLLTTy(*getMRI()), -1); - return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, NegOne}); - } - - /// Build and insert integer negation - /// \p Zero = G_CONSTANT 0 - /// \p Res = G_SUB Zero, \p Op0 - MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0) { - auto Zero = buildConstant(Dst.getLLTTy(*getMRI()), 0); - return buildInstr(TargetOpcode::G_SUB, {Dst}, {Zero, Src0}); - } - - /// Build and insert \p Res = G_CTPOP \p Op0, \p Src0 - MachineInstrBuilder buildCTPOP(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_CTPOP, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_CTLZ \p Op0, \p Src0 - MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_CTLZ, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_CTLZ_ZERO_UNDEF \p Op0, \p Src0 - MachineInstrBuilder buildCTLZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_CTTZ \p Op0, \p Src0 - MachineInstrBuilder buildCTTZ(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_CTTZ, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_CTTZ_ZERO_UNDEF \p Op0, \p Src0 - MachineInstrBuilder buildCTTZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {Dst}, {Src0}); - } - - /// Build and insert \p Dst = G_BSWAP \p Src0 - MachineInstrBuilder buildBSwap(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_BSWAP, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_FADD \p Op0, \p Op1 - MachineInstrBuilder buildFAdd(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FADD, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_FSUB \p Op0, \p Op1 - MachineInstrBuilder buildFSub(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FSUB, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_FDIV \p Op0, \p Op1 - MachineInstrBuilder buildFDiv(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FDIV, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_FMA \p Op0, \p Op1, \p Op2 - MachineInstrBuilder buildFMA(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, const SrcOp &Src2, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMA, {Dst}, {Src0, Src1, Src2}, Flags); - } - - /// Build and insert \p Res = G_FMAD \p Op0, \p Op1, \p Op2 - MachineInstrBuilder buildFMAD(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, const SrcOp &Src2, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FMAD, {Dst}, {Src0, Src1, Src2}, Flags); - } - - /// Build and insert \p Res = G_FNEG \p Op0 - MachineInstrBuilder buildFNeg(const DstOp &Dst, const SrcOp &Src0, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}, Flags); - } - - /// Build and insert \p Res = G_FABS \p Op0 - MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FABS, {Dst}, {Src0}, Flags); - } - - /// Build and insert \p Dst = G_FCANONICALIZE \p Src0 - MachineInstrBuilder buildFCanonicalize(const DstOp &Dst, const SrcOp &Src0, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FCANONICALIZE, {Dst}, {Src0}, Flags); - } - - /// Build and insert \p Dst = G_INTRINSIC_TRUNC \p Src0 - MachineInstrBuilder buildIntrinsicTrunc(const DstOp &Dst, const SrcOp &Src0, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_INTRINSIC_TRUNC, {Dst}, {Src0}, Flags); - } - - /// Build and insert \p Res = GFFLOOR \p Op0, \p Op1 - MachineInstrBuilder buildFFloor(const DstOp &Dst, const SrcOp &Src0, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FFLOOR, {Dst}, {Src0}, Flags); - } - - /// Build and insert \p Dst = G_FLOG \p Src - MachineInstrBuilder buildFLog(const DstOp &Dst, const SrcOp &Src, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FLOG, {Dst}, {Src}, Flags); - } - - /// Build and insert \p Dst = G_FLOG2 \p Src - MachineInstrBuilder buildFLog2(const DstOp &Dst, const SrcOp &Src, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FLOG2, {Dst}, {Src}, Flags); - } - - /// Build and insert \p Dst = G_FEXP2 \p Src - MachineInstrBuilder buildFExp2(const DstOp &Dst, const SrcOp &Src, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FEXP2, {Dst}, {Src}, Flags); - } - - /// Build and insert \p Dst = G_FPOW \p Src0, \p Src1 - MachineInstrBuilder buildFPow(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1, - Optional Flags = None) { - return buildInstr(TargetOpcode::G_FPOW, {Dst}, {Src0, Src1}, Flags); - } - - /// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1 - MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Res = G_UITOFP \p Src0 - MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_UITOFP, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_SITOFP \p Src0 - MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_SITOFP, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_FPTOUI \p Src0 - MachineInstrBuilder buildFPTOUI(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_FPTOUI, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_FPTOSI \p Src0 - MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0) { - return buildInstr(TargetOpcode::G_FPTOSI, {Dst}, {Src0}); - } - - /// Build and insert \p Res = G_SMIN \p Op0, \p Op1 - MachineInstrBuilder buildSMin(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_SMIN, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Res = G_SMAX \p Op0, \p Op1 - MachineInstrBuilder buildSMax(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_SMAX, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Res = G_UMIN \p Op0, \p Op1 - MachineInstrBuilder buildUMin(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_UMIN, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Res = G_UMAX \p Op0, \p Op1 - MachineInstrBuilder buildUMax(const DstOp &Dst, const SrcOp &Src0, - const SrcOp &Src1) { - return buildInstr(TargetOpcode::G_UMAX, {Dst}, {Src0, Src1}); - } - - /// Build and insert \p Dst = G_ABS \p Src - MachineInstrBuilder buildAbs(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_ABS, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_JUMP_TABLE \p JTI - /// - /// G_JUMP_TABLE sets \p Res to the address of the jump table specified by - /// the jump table index \p JTI. - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildJumpTable(const LLT PtrTy, unsigned JTI); - - /// Build and insert \p Res = G_VECREDUCE_SEQ_FADD \p ScalarIn, \p VecIn - /// - /// \p ScalarIn is the scalar accumulator input to start the sequential - /// reduction operation of \p VecIn. - MachineInstrBuilder buildVecReduceSeqFAdd(const DstOp &Dst, - const SrcOp &ScalarIn, - const SrcOp &VecIn) { - return buildInstr(TargetOpcode::G_VECREDUCE_SEQ_FADD, {Dst}, - {ScalarIn, {VecIn}}); - } - - /// Build and insert \p Res = G_VECREDUCE_SEQ_FMUL \p ScalarIn, \p VecIn - /// - /// \p ScalarIn is the scalar accumulator input to start the sequential - /// reduction operation of \p VecIn. - MachineInstrBuilder buildVecReduceSeqFMul(const DstOp &Dst, - const SrcOp &ScalarIn, - const SrcOp &VecIn) { - return buildInstr(TargetOpcode::G_VECREDUCE_SEQ_FMUL, {Dst}, - {ScalarIn, {VecIn}}); - } - - /// Build and insert \p Res = G_VECREDUCE_FADD \p Src - /// - /// \p ScalarIn is the scalar accumulator input to the reduction operation of - /// \p VecIn. - MachineInstrBuilder buildVecReduceFAdd(const DstOp &Dst, - const SrcOp &ScalarIn, - const SrcOp &VecIn) { - return buildInstr(TargetOpcode::G_VECREDUCE_FADD, {Dst}, {ScalarIn, VecIn}); - } - - /// Build and insert \p Res = G_VECREDUCE_FMUL \p Src - /// - /// \p ScalarIn is the scalar accumulator input to the reduction operation of - /// \p VecIn. - MachineInstrBuilder buildVecReduceFMul(const DstOp &Dst, - const SrcOp &ScalarIn, - const SrcOp &VecIn) { - return buildInstr(TargetOpcode::G_VECREDUCE_FMUL, {Dst}, {ScalarIn, VecIn}); - } - - /// Build and insert \p Res = G_VECREDUCE_FMAX \p Src - MachineInstrBuilder buildVecReduceFMax(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_FMAX, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_FMIN \p Src - MachineInstrBuilder buildVecReduceFMin(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_FMIN, {Dst}, {Src}); - } - /// Build and insert \p Res = G_VECREDUCE_ADD \p Src - MachineInstrBuilder buildVecReduceAdd(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_ADD, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_MUL \p Src - MachineInstrBuilder buildVecReduceMul(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_MUL, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_AND \p Src - MachineInstrBuilder buildVecReduceAnd(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_AND, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_OR \p Src - MachineInstrBuilder buildVecReduceOr(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_OR, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_XOR \p Src - MachineInstrBuilder buildVecReduceXor(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_XOR, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_SMAX \p Src - MachineInstrBuilder buildVecReduceSMax(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_SMAX, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_SMIN \p Src - MachineInstrBuilder buildVecReduceSMin(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_SMIN, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_UMAX \p Src - MachineInstrBuilder buildVecReduceUMax(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_UMAX, {Dst}, {Src}); - } - - /// Build and insert \p Res = G_VECREDUCE_UMIN \p Src - MachineInstrBuilder buildVecReduceUMin(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_VECREDUCE_UMIN, {Dst}, {Src}); - } - - /// Build and insert G_MEMCPY or G_MEMMOVE - MachineInstrBuilder buildMemTransferInst(unsigned Opcode, const SrcOp &DstPtr, - const SrcOp &SrcPtr, - const SrcOp &Size, - MachineMemOperand &DstMMO, - MachineMemOperand &SrcMMO) { - auto MIB = buildInstr( - Opcode, {}, {DstPtr, SrcPtr, Size, SrcOp(INT64_C(0) /*isTailCall*/)}); - MIB.addMemOperand(&DstMMO); - MIB.addMemOperand(&SrcMMO); - return MIB; - } - - MachineInstrBuilder buildMemCpy(const SrcOp &DstPtr, const SrcOp &SrcPtr, - const SrcOp &Size, MachineMemOperand &DstMMO, - MachineMemOperand &SrcMMO) { - return buildMemTransferInst(TargetOpcode::G_MEMCPY, DstPtr, SrcPtr, Size, - DstMMO, SrcMMO); - } - - /// Build and insert \p Dst = G_SBFX \p Src, \p LSB, \p Width. - MachineInstrBuilder buildSbfx(const DstOp &Dst, const SrcOp &Src, - const SrcOp &LSB, const SrcOp &Width) { - return buildInstr(TargetOpcode::G_SBFX, {Dst}, {Src, LSB, Width}); - } - - /// Build and insert \p Dst = G_UBFX \p Src, \p LSB, \p Width. - MachineInstrBuilder buildUbfx(const DstOp &Dst, const SrcOp &Src, - const SrcOp &LSB, const SrcOp &Width) { - return buildInstr(TargetOpcode::G_UBFX, {Dst}, {Src, LSB, Width}); - } - - /// Build and insert \p Dst = G_ROTR \p Src, \p Amt - MachineInstrBuilder buildRotateRight(const DstOp &Dst, const SrcOp &Src, - const SrcOp &Amt) { - return buildInstr(TargetOpcode::G_ROTR, {Dst}, {Src, Amt}); - } - - /// Build and insert \p Dst = G_ROTL \p Src, \p Amt - MachineInstrBuilder buildRotateLeft(const DstOp &Dst, const SrcOp &Src, - const SrcOp &Amt) { - return buildInstr(TargetOpcode::G_ROTL, {Dst}, {Src, Amt}); - } - - /// Build and insert \p Dst = G_BITREVERSE \p Src - MachineInstrBuilder buildBitReverse(const DstOp &Dst, const SrcOp &Src) { - return buildInstr(TargetOpcode::G_BITREVERSE, {Dst}, {Src}); - } - - virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, - ArrayRef SrcOps, - Optional Flags = None); -}; - -} // End namespace llvm. -#endif // LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegBankSelect.h deleted file mode 100644 index 421aa555dc..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ /dev/null @@ -1,670 +0,0 @@ -//=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file describes the interface of the MachineFunctionPass -/// responsible for assigning the generic virtual registers to register bank. -/// -/// By default, the reg bank selector relies on local decisions to -/// assign the register bank. In other words, it looks at one instruction -/// at a time to decide where the operand of that instruction should live. -/// -/// At higher optimization level, we could imagine that the reg bank selector -/// would use more global analysis and do crazier thing like duplicating -/// instructions and so on. This is future work. -/// -/// For now, the pass uses a greedy algorithm to decide where the operand -/// of an instruction should live. It asks the target which banks may be -/// used for each operand of the instruction and what is the cost. Then, -/// it chooses the solution which minimize the cost of the instruction plus -/// the cost of any move that may be needed to the values into the right -/// register bank. -/// In other words, the cost for an instruction on a register bank RegBank -/// is: Cost of I on RegBank plus the sum of the cost for bringing the -/// input operands from their current register bank to RegBank. -/// Thus, the following formula: -/// cost(I, RegBank) = cost(I.Opcode, RegBank) + -/// sum(for each arg in I.arguments: costCrossCopy(arg.RegBank, RegBank)) -/// -/// E.g., Let say we are assigning the register bank for the instruction -/// defining v2. -/// v0(A_REGBANK) = ... -/// v1(A_REGBANK) = ... -/// v2 = G_ADD i32 v0, v1 <-- MI -/// -/// The target may say it can generate G_ADD i32 on register bank A and B -/// with a cost of respectively 5 and 1. -/// Then, let say the cost of a cross register bank copies from A to B is 1. -/// The reg bank selector would compare the following two costs: -/// cost(MI, A_REGBANK) = cost(G_ADD, A_REGBANK) + cost(v0.RegBank, A_REGBANK) + -/// cost(v1.RegBank, A_REGBANK) -/// = 5 + cost(A_REGBANK, A_REGBANK) + cost(A_REGBANK, -/// A_REGBANK) -/// = 5 + 0 + 0 = 5 -/// cost(MI, B_REGBANK) = cost(G_ADD, B_REGBANK) + cost(v0.RegBank, B_REGBANK) + -/// cost(v1.RegBank, B_REGBANK) -/// = 1 + cost(A_REGBANK, B_REGBANK) + cost(A_REGBANK, -/// B_REGBANK) -/// = 1 + 1 + 1 = 3 -/// Therefore, in this specific example, the reg bank selector would choose -/// bank B for MI. -/// v0(A_REGBANK) = ... -/// v1(A_REGBANK) = ... -/// tmp0(B_REGBANK) = COPY v0 -/// tmp1(B_REGBANK) = COPY v1 -/// v2(B_REGBANK) = G_ADD i32 tmp0, tmp1 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H -#define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" -#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include -#include -#include - -namespace llvm { - -class BlockFrequency; -class MachineBlockFrequencyInfo; -class MachineBranchProbabilityInfo; -class MachineOperand; -class MachineRegisterInfo; -class Pass; -class raw_ostream; -class TargetPassConfig; -class TargetRegisterInfo; - -/// This pass implements the reg bank selector pass used in the GlobalISel -/// pipeline. At the end of this pass, all register operands have been assigned -class RegBankSelect : public MachineFunctionPass { -public: - static char ID; - - /// List of the modes supported by the RegBankSelect pass. - enum Mode { - /// Assign the register banks as fast as possible (default). - Fast, - /// Greedily minimize the cost of assigning register banks. - /// This should produce code of greater quality, but will - /// require more compile time. - Greedy - }; - - /// Abstract class used to represent an insertion point in a CFG. - /// This class records an insertion point and materializes it on - /// demand. - /// It allows to reason about the frequency of this insertion point, - /// without having to logically materialize it (e.g., on an edge), - /// before we actually need to insert something. - class InsertPoint { - protected: - /// Tell if the insert point has already been materialized. - bool WasMaterialized = false; - - /// Materialize the insertion point. - /// - /// If isSplit() is true, this involves actually splitting - /// the block or edge. - /// - /// \post getPointImpl() returns a valid iterator. - /// \post getInsertMBBImpl() returns a valid basic block. - /// \post isSplit() == false ; no more splitting should be required. - virtual void materialize() = 0; - - /// Return the materialized insertion basic block. - /// Code will be inserted into that basic block. - /// - /// \pre ::materialize has been called. - virtual MachineBasicBlock &getInsertMBBImpl() = 0; - - /// Return the materialized insertion point. - /// Code will be inserted before that point. - /// - /// \pre ::materialize has been called. - virtual MachineBasicBlock::iterator getPointImpl() = 0; - - public: - virtual ~InsertPoint() = default; - - /// The first call to this method will cause the splitting to - /// happen if need be, then sub sequent calls just return - /// the iterator to that point. I.e., no more splitting will - /// occur. - /// - /// \return The iterator that should be used with - /// MachineBasicBlock::insert. I.e., additional code happens - /// before that point. - MachineBasicBlock::iterator getPoint() { - if (!WasMaterialized) { - WasMaterialized = true; - assert(canMaterialize() && "Impossible to materialize this point"); - materialize(); - } - // When we materialized the point we should have done the splitting. - assert(!isSplit() && "Wrong pre-condition"); - return getPointImpl(); - } - - /// The first call to this method will cause the splitting to - /// happen if need be, then sub sequent calls just return - /// the basic block that contains the insertion point. - /// I.e., no more splitting will occur. - /// - /// \return The basic block should be used with - /// MachineBasicBlock::insert and ::getPoint. The new code should - /// happen before that point. - MachineBasicBlock &getInsertMBB() { - if (!WasMaterialized) { - WasMaterialized = true; - assert(canMaterialize() && "Impossible to materialize this point"); - materialize(); - } - // When we materialized the point we should have done the splitting. - assert(!isSplit() && "Wrong pre-condition"); - return getInsertMBBImpl(); - } - - /// Insert \p MI in the just before ::getPoint() - MachineBasicBlock::iterator insert(MachineInstr &MI) { - return getInsertMBB().insert(getPoint(), &MI); - } - - /// Does this point involve splitting an edge or block? - /// As soon as ::getPoint is called and thus, the point - /// materialized, the point will not require splitting anymore, - /// i.e., this will return false. - virtual bool isSplit() const { return false; } - - /// Frequency of the insertion point. - /// \p P is used to access the various analysis that will help to - /// get that information, like MachineBlockFrequencyInfo. If \p P - /// does not contain enough enough to return the actual frequency, - /// this returns 1. - virtual uint64_t frequency(const Pass &P) const { return 1; } - - /// Check whether this insertion point can be materialized. - /// As soon as ::getPoint is called and thus, the point materialized - /// calling this method does not make sense. - virtual bool canMaterialize() const { return false; } - }; - - /// Insertion point before or after an instruction. - class InstrInsertPoint : public InsertPoint { - private: - /// Insertion point. - MachineInstr &Instr; - - /// Does the insertion point is before or after Instr. - bool Before; - - void materialize() override; - - MachineBasicBlock::iterator getPointImpl() override { - if (Before) - return Instr; - return Instr.getNextNode() ? *Instr.getNextNode() - : Instr.getParent()->end(); - } - - MachineBasicBlock &getInsertMBBImpl() override { - return *Instr.getParent(); - } - - public: - /// Create an insertion point before (\p Before=true) or after \p Instr. - InstrInsertPoint(MachineInstr &Instr, bool Before = true); - - bool isSplit() const override; - uint64_t frequency(const Pass &P) const override; - - // Worst case, we need to slice the basic block, but that is still doable. - bool canMaterialize() const override { return true; } - }; - - /// Insertion point at the beginning or end of a basic block. - class MBBInsertPoint : public InsertPoint { - private: - /// Insertion point. - MachineBasicBlock &MBB; - - /// Does the insertion point is at the beginning or end of MBB. - bool Beginning; - - void materialize() override { /*Nothing to do to materialize*/ - } - - MachineBasicBlock::iterator getPointImpl() override { - return Beginning ? MBB.begin() : MBB.end(); - } - - MachineBasicBlock &getInsertMBBImpl() override { return MBB; } - - public: - MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true) - : MBB(MBB), Beginning(Beginning) { - // If we try to insert before phis, we should use the insertion - // points on the incoming edges. - assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) && - "Invalid beginning point"); - // If we try to insert after the terminators, we should use the - // points on the outcoming edges. - assert((Beginning || MBB.getFirstTerminator() == MBB.end()) && - "Invalid end point"); - } - - bool isSplit() const override { return false; } - uint64_t frequency(const Pass &P) const override; - bool canMaterialize() const override { return true; }; - }; - - /// Insertion point on an edge. - class EdgeInsertPoint : public InsertPoint { - private: - /// Source of the edge. - MachineBasicBlock &Src; - - /// Destination of the edge. - /// After the materialization is done, this hold the basic block - /// that resulted from the splitting. - MachineBasicBlock *DstOrSplit; - - /// P is used to update the analysis passes as applicable. - Pass &P; - - void materialize() override; - - MachineBasicBlock::iterator getPointImpl() override { - // DstOrSplit should be the Split block at this point. - // I.e., it should have one predecessor, Src, and one successor, - // the original Dst. - assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) && - DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 && - "Did not split?!"); - return DstOrSplit->begin(); - } - - MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; } - - public: - EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P) - : Src(Src), DstOrSplit(&Dst), P(P) {} - - bool isSplit() const override { - return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1; - } - - uint64_t frequency(const Pass &P) const override; - bool canMaterialize() const override; - }; - - /// Struct used to represent the placement of a repairing point for - /// a given operand. - class RepairingPlacement { - public: - /// Define the kind of action this repairing needs. - enum RepairingKind { - /// Nothing to repair, just drop this action. - None, - /// Reparing code needs to happen before InsertPoints. - Insert, - /// (Re)assign the register bank of the operand. - Reassign, - /// Mark this repairing placement as impossible. - Impossible - }; - - /// \name Convenient types for a list of insertion points. - /// @{ - using InsertionPoints = SmallVector, 2>; - using insertpt_iterator = InsertionPoints::iterator; - using const_insertpt_iterator = InsertionPoints::const_iterator; - /// @} - - private: - /// Kind of repairing. - RepairingKind Kind; - /// Index of the operand that will be repaired. - unsigned OpIdx; - /// Are all the insert points materializeable? - bool CanMaterialize; - /// Is there any of the insert points needing splitting? - bool HasSplit = false; - /// Insertion point for the repair code. - /// The repairing code needs to happen just before these points. - InsertionPoints InsertPoints; - /// Some insertion points may need to update the liveness and such. - Pass &P; - - public: - /// Create a repairing placement for the \p OpIdx-th operand of - /// \p MI. \p TRI is used to make some checks on the register aliases - /// if the machine operand is a physical register. \p P is used to - /// to update liveness information and such when materializing the - /// points. - RepairingPlacement(MachineInstr &MI, unsigned OpIdx, - const TargetRegisterInfo &TRI, Pass &P, - RepairingKind Kind = RepairingKind::Insert); - - /// \name Getters. - /// @{ - RepairingKind getKind() const { return Kind; } - unsigned getOpIdx() const { return OpIdx; } - bool canMaterialize() const { return CanMaterialize; } - bool hasSplit() { return HasSplit; } - /// @} - - /// \name Overloaded methods to add an insertion point. - /// @{ - /// Add a MBBInsertionPoint to the list of InsertPoints. - void addInsertPoint(MachineBasicBlock &MBB, bool Beginning); - /// Add a InstrInsertionPoint to the list of InsertPoints. - void addInsertPoint(MachineInstr &MI, bool Before); - /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints. - void addInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst); - /// Add an InsertPoint to the list of insert points. - /// This method takes the ownership of &\p Point. - void addInsertPoint(InsertPoint &Point); - /// @} - - /// \name Accessors related to the insertion points. - /// @{ - insertpt_iterator begin() { return InsertPoints.begin(); } - insertpt_iterator end() { return InsertPoints.end(); } - - const_insertpt_iterator begin() const { return InsertPoints.begin(); } - const_insertpt_iterator end() const { return InsertPoints.end(); } - - unsigned getNumInsertPoints() const { return InsertPoints.size(); } - /// @} - - /// Change the type of this repairing placement to \p NewKind. - /// It is not possible to switch a repairing placement to the - /// RepairingKind::Insert. There is no fundamental problem with - /// that, but no uses as well, so do not support it for now. - /// - /// \pre NewKind != RepairingKind::Insert - /// \post getKind() == NewKind - void switchTo(RepairingKind NewKind) { - assert(NewKind != Kind && "Already of the right Kind"); - Kind = NewKind; - InsertPoints.clear(); - CanMaterialize = NewKind != RepairingKind::Impossible; - HasSplit = false; - assert(NewKind != RepairingKind::Insert && - "We would need more MI to switch to Insert"); - } - }; - -private: - /// Helper class used to represent the cost for mapping an instruction. - /// When mapping an instruction, we may introduce some repairing code. - /// In most cases, the repairing code is local to the instruction, - /// thus, we can omit the basic block frequency from the cost. - /// However, some alternatives may produce non-local cost, e.g., when - /// repairing a phi, and thus we then need to scale the local cost - /// to the non-local cost. This class does this for us. - /// \note: We could simply always scale the cost. The problem is that - /// there are higher chances that we saturate the cost easier and end - /// up having the same cost for actually different alternatives. - /// Another option would be to use APInt everywhere. - class MappingCost { - private: - /// Cost of the local instructions. - /// This cost is free of basic block frequency. - uint64_t LocalCost = 0; - /// Cost of the non-local instructions. - /// This cost should include the frequency of the related blocks. - uint64_t NonLocalCost = 0; - /// Frequency of the block where the local instructions live. - uint64_t LocalFreq; - - MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq) - : LocalCost(LocalCost), NonLocalCost(NonLocalCost), - LocalFreq(LocalFreq) {} - - /// Check if this cost is saturated. - bool isSaturated() const; - - public: - /// Create a MappingCost assuming that most of the instructions - /// will occur in a basic block with \p LocalFreq frequency. - MappingCost(const BlockFrequency &LocalFreq); - - /// Add \p Cost to the local cost. - /// \return true if this cost is saturated, false otherwise. - bool addLocalCost(uint64_t Cost); - - /// Add \p Cost to the non-local cost. - /// Non-local cost should reflect the frequency of their placement. - /// \return true if this cost is saturated, false otherwise. - bool addNonLocalCost(uint64_t Cost); - - /// Saturate the cost to the maximal representable value. - void saturate(); - - /// Return an instance of MappingCost that represents an - /// impossible mapping. - static MappingCost ImpossibleCost(); - - /// Check if this is less than \p Cost. - bool operator<(const MappingCost &Cost) const; - /// Check if this is equal to \p Cost. - bool operator==(const MappingCost &Cost) const; - /// Check if this is not equal to \p Cost. - bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); } - /// Check if this is greater than \p Cost. - bool operator>(const MappingCost &Cost) const { - return *this != Cost && Cost < *this; - } - - /// Print this on dbgs() stream. - void dump() const; - - /// Print this on \p OS; - void print(raw_ostream &OS) const; - - /// Overload the stream operator for easy debug printing. - friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) { - Cost.print(OS); - return OS; - } - }; - - /// Interface to the target lowering info related - /// to register banks. - const RegisterBankInfo *RBI = nullptr; - - /// MRI contains all the register class/bank information that this - /// pass uses and updates. - MachineRegisterInfo *MRI = nullptr; - - /// Information on the register classes for the current function. - const TargetRegisterInfo *TRI = nullptr; - - /// Get the frequency of blocks. - /// This is required for non-fast mode. - MachineBlockFrequencyInfo *MBFI = nullptr; - - /// Get the frequency of the edges. - /// This is required for non-fast mode. - MachineBranchProbabilityInfo *MBPI = nullptr; - - /// Current optimization remark emitter. Used to report failures. - std::unique_ptr MORE; - - /// Helper class used for every code morphing. - MachineIRBuilder MIRBuilder; - - /// Optimization mode of the pass. - Mode OptMode; - - /// Current target configuration. Controls how the pass handles errors. - const TargetPassConfig *TPC; - - /// Assign the register bank of each operand of \p MI. - /// \return True on success, false otherwise. - bool assignInstr(MachineInstr &MI); - - /// Initialize the field members using \p MF. - void init(MachineFunction &MF); - - /// Check if \p Reg is already assigned what is described by \p ValMapping. - /// \p OnlyAssign == true means that \p Reg just needs to be assigned a - /// register bank. I.e., no repairing is necessary to have the - /// assignment match. - bool assignmentMatch(Register Reg, - const RegisterBankInfo::ValueMapping &ValMapping, - bool &OnlyAssign) const; - - /// Insert repairing code for \p Reg as specified by \p ValMapping. - /// The repairing placement is specified by \p RepairPt. - /// \p NewVRegs contains all the registers required to remap \p Reg. - /// In other words, the number of registers in NewVRegs must be equal - /// to ValMapping.BreakDown.size(). - /// - /// The transformation could be sketched as: - /// \code - /// ... = op Reg - /// \endcode - /// Becomes - /// \code - /// = COPY or extract Reg - /// ... = op Reg - /// \endcode - /// - /// and - /// \code - /// Reg = op ... - /// \endcode - /// Becomes - /// \code - /// Reg = op ... - /// Reg = COPY or build_sequence - /// \endcode - /// - /// \pre NewVRegs.size() == ValMapping.BreakDown.size() - /// - /// \note The caller is supposed to do the rewriting of op if need be. - /// I.e., Reg = op ... => = NewOp ... - /// - /// \return True if the repairing worked, false otherwise. - bool repairReg(MachineOperand &MO, - const RegisterBankInfo::ValueMapping &ValMapping, - RegBankSelect::RepairingPlacement &RepairPt, - const iterator_range::const_iterator> - &NewVRegs); - - /// Return the cost of the instruction needed to map \p MO to \p ValMapping. - /// The cost is free of basic block frequencies. - /// \pre MO.isReg() - /// \pre MO is assigned to a register bank. - /// \pre ValMapping is a valid mapping for MO. - uint64_t - getRepairCost(const MachineOperand &MO, - const RegisterBankInfo::ValueMapping &ValMapping) const; - - /// Find the best mapping for \p MI from \p PossibleMappings. - /// \return a reference on the best mapping in \p PossibleMappings. - const RegisterBankInfo::InstructionMapping & - findBestMapping(MachineInstr &MI, - RegisterBankInfo::InstructionMappings &PossibleMappings, - SmallVectorImpl &RepairPts); - - /// Compute the cost of mapping \p MI with \p InstrMapping and - /// compute the repairing placement for such mapping in \p - /// RepairPts. - /// \p BestCost is used to specify when the cost becomes too high - /// and thus it is not worth computing the RepairPts. Moreover if - /// \p BestCost == nullptr, the mapping cost is actually not - /// computed. - MappingCost - computeMapping(MachineInstr &MI, - const RegisterBankInfo::InstructionMapping &InstrMapping, - SmallVectorImpl &RepairPts, - const MappingCost *BestCost = nullptr); - - /// When \p RepairPt involves splitting to repair \p MO for the - /// given \p ValMapping, try to change the way we repair such that - /// the splitting is not required anymore. - /// - /// \pre \p RepairPt.hasSplit() - /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx()) - /// \pre \p ValMapping is the mapping of \p MO for MO.getParent() - /// that implied \p RepairPt. - void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt, - const MachineOperand &MO, - const RegisterBankInfo::ValueMapping &ValMapping) const; - - /// Apply \p Mapping to \p MI. \p RepairPts represents the different - /// mapping action that need to happen for the mapping to be - /// applied. - /// \return True if the mapping was applied successfully, false otherwise. - bool applyMapping(MachineInstr &MI, - const RegisterBankInfo::InstructionMapping &InstrMapping, - SmallVectorImpl &RepairPts); - -public: - /// Create a RegBankSelect pass with the specified \p RunningMode. - RegBankSelect(Mode RunningMode = Fast); - - StringRef getPassName() const override { return "RegBankSelect"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA) - .set(MachineFunctionProperties::Property::Legalized); - } - - MachineFunctionProperties getSetProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::RegBankSelected); - } - - MachineFunctionProperties getClearedProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::NoPHIs); - } - - /// Walk through \p MF and assign a register bank to every virtual register - /// that are still mapped to nothing. - /// The target needs to provide a RegisterBankInfo and in particular - /// override RegisterBankInfo::getInstrMapping. - /// - /// Simplified algo: - /// \code - /// RBI = MF.subtarget.getRegBankInfo() - /// MIRBuilder.setMF(MF) - /// for each bb in MF - /// for each inst in bb - /// MIRBuilder.setInstr(inst) - /// MappingCosts = RBI.getMapping(inst); - /// Idx = findIdxOfMinCost(MappingCosts) - /// CurRegBank = MappingCosts[Idx].RegBank - /// MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank) - /// for each argument in inst - /// if (CurRegBank != argument.RegBank) - /// ArgReg = argument.getReg() - /// Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank) - /// MIRBuilder.buildInstr(COPY, Tmp, ArgReg) - /// inst.getOperand(argument.getOperandNo()).setReg(Tmp) - /// \endcode - bool runOnMachineFunction(MachineFunction &MF) override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBank.h deleted file mode 100644 index 5440d97728..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ /dev/null @@ -1,98 +0,0 @@ -//==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file declares the API of register banks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_REGISTERBANK_H -#define LLVM_CODEGEN_GLOBALISEL_REGISTERBANK_H - -#include "llvm/ADT/BitVector.h" - -namespace llvm { -// Forward declarations. -class RegisterBankInfo; -class raw_ostream; -class TargetRegisterClass; -class TargetRegisterInfo; - -/// This class implements the register bank concept. -/// Two instances of RegisterBank must have different ID. -/// This property is enforced by the RegisterBankInfo class. -class RegisterBank { -private: - unsigned ID; - const char *Name; - unsigned Size; - BitVector ContainedRegClasses; - - /// Sentinel value used to recognize register bank not properly - /// initialized yet. - static const unsigned InvalidID; - - /// Only the RegisterBankInfo can initialize RegisterBank properly. - friend RegisterBankInfo; - -public: - RegisterBank(unsigned ID, const char *Name, unsigned Size, - const uint32_t *CoveredClasses, unsigned NumRegClasses); - - /// Get the identifier of this register bank. - unsigned getID() const { return ID; } - - /// Get a user friendly name of this register bank. - /// Should be used only for debugging purposes. - const char *getName() const { return Name; } - - /// Get the maximal size in bits that fits in this register bank. - unsigned getSize() const { return Size; } - - /// Check whether this instance is ready to be used. - bool isValid() const; - - /// Check if this register bank is valid. In other words, - /// if it has been properly constructed. - /// - /// \note This method does not check anything when assertions are disabled. - /// - /// \return True is the check was successful. - bool verify(const TargetRegisterInfo &TRI) const; - - /// Check whether this register bank covers \p RC. - /// In other words, check if this register bank fully covers - /// the registers that \p RC contains. - /// \pre isValid() - bool covers(const TargetRegisterClass &RC) const; - - /// Check whether \p OtherRB is the same as this. - bool operator==(const RegisterBank &OtherRB) const; - bool operator!=(const RegisterBank &OtherRB) const { - return !this->operator==(OtherRB); - } - - /// Dump the register mask on dbgs() stream. - /// The dump is verbose. - void dump(const TargetRegisterInfo *TRI = nullptr) const; - - /// Print the register mask on OS. - /// If IsForDebug is false, then only the name of the register bank - /// is printed. Otherwise, all the fields are printing. - /// TRI is then used to print the name of the register classes that - /// this register bank covers. - void print(raw_ostream &OS, bool IsForDebug = false, - const TargetRegisterInfo *TRI = nullptr) const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const RegisterBank &RegBank) { - RegBank.print(OS); - return OS; -} -} // End namespace llvm. - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h deleted file mode 100644 index 906819bb2c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ /dev/null @@ -1,775 +0,0 @@ -//===- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file declares the API for the register bank info. -/// This API is responsible for handling the register banks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H -#define LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include -#include -#include - -namespace llvm { - -class MachineInstr; -class MachineRegisterInfo; -class raw_ostream; -class RegisterBank; -class TargetInstrInfo; -class TargetRegisterClass; -class TargetRegisterInfo; - -/// Holds all the information related to register banks. -class RegisterBankInfo { -public: - /// Helper struct that represents how a value is partially mapped - /// into a register. - /// The StartIdx and Length represent what region of the original - /// value this partial mapping covers. - /// This can be represented as a Mask of contiguous bit starting - /// at StartIdx bit and spanning Length bits. - /// StartIdx is the number of bits from the less significant bits. - struct PartialMapping { - /// Number of bits at which this partial mapping starts in the - /// original value. The bits are counted from less significant - /// bits to most significant bits. - unsigned StartIdx; - - /// Length of this mapping in bits. This is how many bits this - /// partial mapping covers in the original value: - /// from StartIdx to StartIdx + Length -1. - unsigned Length; - - /// Register bank where the partial value lives. - const RegisterBank *RegBank; - - PartialMapping() = default; - - /// Provide a shortcut for quickly building PartialMapping. - PartialMapping(unsigned StartIdx, unsigned Length, - const RegisterBank &RegBank) - : StartIdx(StartIdx), Length(Length), RegBank(&RegBank) {} - - /// \return the index of in the original value of the most - /// significant bit that this partial mapping covers. - unsigned getHighBitIdx() const { return StartIdx + Length - 1; } - - /// Print this partial mapping on dbgs() stream. - void dump() const; - - /// Print this partial mapping on \p OS; - void print(raw_ostream &OS) const; - - /// Check that the Mask is compatible with the RegBank. - /// Indeed, if the RegBank cannot accommodate the "active bits" of the mask, - /// there is no way this mapping is valid. - /// - /// \note This method does not check anything when assertions are disabled. - /// - /// \return True is the check was successful. - bool verify() const; - }; - - /// Helper struct that represents how a value is mapped through - /// different register banks. - /// - /// \note: So far we do not have any users of the complex mappings - /// (mappings with more than one partial mapping), but when we do, - /// we would have needed to duplicate partial mappings. - /// The alternative could be to use an array of pointers of partial - /// mapping (i.e., PartialMapping **BreakDown) and duplicate the - /// pointers instead. - /// - /// E.g., - /// Let say we have a 32-bit add and a <2 x 32-bit> vadd. We - /// can expand the - /// <2 x 32-bit> add into 2 x 32-bit add. - /// - /// Currently the TableGen-like file would look like: - /// \code - /// PartialMapping[] = { - /// /*32-bit add*/ {0, 32, GPR}, // Scalar entry repeated for first - /// // vec elt. - /// /*2x32-bit add*/ {0, 32, GPR}, {32, 32, GPR}, - /// /*<2x32-bit> vadd*/ {0, 64, VPR} - /// }; // PartialMapping duplicated. - /// - /// ValueMapping[] { - /// /*plain 32-bit add*/ {&PartialMapping[0], 1}, - /// /*expanded vadd on 2xadd*/ {&PartialMapping[1], 2}, - /// /*plain <2x32-bit> vadd*/ {&PartialMapping[3], 1} - /// }; - /// \endcode - /// - /// With the array of pointer, we would have: - /// \code - /// PartialMapping[] = { - /// /*32-bit add lower */ { 0, 32, GPR}, - /// /*32-bit add upper */ {32, 32, GPR}, - /// /*<2x32-bit> vadd */ { 0, 64, VPR} - /// }; // No more duplication. - /// - /// BreakDowns[] = { - /// /*AddBreakDown*/ &PartialMapping[0], - /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[1], - /// /*VAddBreakDown*/ &PartialMapping[2] - /// }; // Addresses of PartialMapping duplicated (smaller). - /// - /// ValueMapping[] { - /// /*plain 32-bit add*/ {&BreakDowns[0], 1}, - /// /*expanded vadd on 2xadd*/ {&BreakDowns[1], 2}, - /// /*plain <2x32-bit> vadd*/ {&BreakDowns[3], 1} - /// }; - /// \endcode - /// - /// Given that a PartialMapping is actually small, the code size - /// impact is actually a degradation. Moreover the compile time will - /// be hit by the additional indirection. - /// If PartialMapping gets bigger we may reconsider. - struct ValueMapping { - /// How the value is broken down between the different register banks. - const PartialMapping *BreakDown; - - /// Number of partial mapping to break down this value. - unsigned NumBreakDowns; - - /// The default constructor creates an invalid (isValid() == false) - /// instance. - ValueMapping() : ValueMapping(nullptr, 0) {} - - /// Initialize a ValueMapping with the given parameter. - /// \p BreakDown needs to have a life time at least as long - /// as this instance. - ValueMapping(const PartialMapping *BreakDown, unsigned NumBreakDowns) - : BreakDown(BreakDown), NumBreakDowns(NumBreakDowns) {} - - /// Iterators through the PartialMappings. - const PartialMapping *begin() const { return BreakDown; } - const PartialMapping *end() const { return BreakDown + NumBreakDowns; } - - /// \return true if all partial mappings are the same size and register - /// bank. - bool partsAllUniform() const; - - /// Check if this ValueMapping is valid. - bool isValid() const { return BreakDown && NumBreakDowns; } - - /// Verify that this mapping makes sense for a value of - /// \p MeaningfulBitWidth. - /// \note This method does not check anything when assertions are disabled. - /// - /// \return True is the check was successful. - bool verify(unsigned MeaningfulBitWidth) const; - - /// Print this on dbgs() stream. - void dump() const; - - /// Print this on \p OS; - void print(raw_ostream &OS) const; - }; - - /// Helper class that represents how the value of an instruction may be - /// mapped and what is the related cost of such mapping. - class InstructionMapping { - /// Identifier of the mapping. - /// This is used to communicate between the target and the optimizers - /// which mapping should be realized. - unsigned ID = InvalidMappingID; - - /// Cost of this mapping. - unsigned Cost = 0; - - /// Mapping of all the operands. - const ValueMapping *OperandsMapping = nullptr; - - /// Number of operands. - unsigned NumOperands = 0; - - const ValueMapping &getOperandMapping(unsigned i) { - assert(i < getNumOperands() && "Out of bound operand"); - return OperandsMapping[i]; - } - - public: - /// Constructor for the mapping of an instruction. - /// \p NumOperands must be equal to number of all the operands of - /// the related instruction. - /// The rationale is that it is more efficient for the optimizers - /// to be able to assume that the mapping of the ith operand is - /// at the index i. - InstructionMapping(unsigned ID, unsigned Cost, - const ValueMapping *OperandsMapping, - unsigned NumOperands) - : ID(ID), Cost(Cost), OperandsMapping(OperandsMapping), - NumOperands(NumOperands) { - } - - /// Default constructor. - /// Use this constructor to express that the mapping is invalid. - InstructionMapping() = default; - - /// Get the cost. - unsigned getCost() const { return Cost; } - - /// Get the ID. - unsigned getID() const { return ID; } - - /// Get the number of operands. - unsigned getNumOperands() const { return NumOperands; } - - /// Get the value mapping of the ith operand. - /// \pre The mapping for the ith operand has been set. - /// \pre The ith operand is a register. - const ValueMapping &getOperandMapping(unsigned i) const { - const ValueMapping &ValMapping = - const_cast(this)->getOperandMapping(i); - return ValMapping; - } - - /// Set the mapping for all the operands. - /// In other words, OpdsMapping should hold at least getNumOperands - /// ValueMapping. - void setOperandsMapping(const ValueMapping *OpdsMapping) { - OperandsMapping = OpdsMapping; - } - - /// Check whether this object is valid. - /// This is a lightweight check for obvious wrong instance. - bool isValid() const { - return getID() != InvalidMappingID && OperandsMapping; - } - - /// Verify that this mapping makes sense for \p MI. - /// \pre \p MI must be connected to a MachineFunction. - /// - /// \note This method does not check anything when assertions are disabled. - /// - /// \return True is the check was successful. - bool verify(const MachineInstr &MI) const; - - /// Print this on dbgs() stream. - void dump() const; - - /// Print this on \p OS; - void print(raw_ostream &OS) const; - }; - - /// Convenient type to represent the alternatives for mapping an - /// instruction. - /// \todo When we move to TableGen this should be an array ref. - using InstructionMappings = SmallVector; - - /// Helper class used to get/create the virtual registers that will be used - /// to replace the MachineOperand when applying a mapping. - class OperandsMapper { - /// The OpIdx-th cell contains the index in NewVRegs where the VRegs of the - /// OpIdx-th operand starts. -1 means we do not have such mapping yet. - /// Note: We use a SmallVector to avoid heap allocation for most cases. - SmallVector OpToNewVRegIdx; - - /// Hold the registers that will be used to map MI with InstrMapping. - SmallVector NewVRegs; - - /// Current MachineRegisterInfo, used to create new virtual registers. - MachineRegisterInfo &MRI; - - /// Instruction being remapped. - MachineInstr &MI; - - /// New mapping of the instruction. - const InstructionMapping &InstrMapping; - - /// Constant value identifying that the index in OpToNewVRegIdx - /// for an operand has not been set yet. - static const int DontKnowIdx; - - /// Get the range in NewVRegs to store all the partial - /// values for the \p OpIdx-th operand. - /// - /// \return The iterator range for the space created. - // - /// \pre getMI().getOperand(OpIdx).isReg() - iterator_range::iterator> - getVRegsMem(unsigned OpIdx); - - /// Get the end iterator for a range starting at \p StartIdx and - /// spannig \p NumVal in NewVRegs. - /// \pre StartIdx + NumVal <= NewVRegs.size() - SmallVectorImpl::const_iterator - getNewVRegsEnd(unsigned StartIdx, unsigned NumVal) const; - SmallVectorImpl::iterator getNewVRegsEnd(unsigned StartIdx, - unsigned NumVal); - - public: - /// Create an OperandsMapper that will hold the information to apply \p - /// InstrMapping to \p MI. - /// \pre InstrMapping.verify(MI) - OperandsMapper(MachineInstr &MI, const InstructionMapping &InstrMapping, - MachineRegisterInfo &MRI); - - /// \name Getters. - /// @{ - /// The MachineInstr being remapped. - MachineInstr &getMI() const { return MI; } - - /// The final mapping of the instruction. - const InstructionMapping &getInstrMapping() const { return InstrMapping; } - - /// The MachineRegisterInfo we used to realize the mapping. - MachineRegisterInfo &getMRI() const { return MRI; } - /// @} - - /// Create as many new virtual registers as needed for the mapping of the \p - /// OpIdx-th operand. - /// The number of registers is determined by the number of breakdown for the - /// related operand in the instruction mapping. - /// The type of the new registers is a plain scalar of the right size. - /// The proper type is expected to be set when the mapping is applied to - /// the instruction(s) that realizes the mapping. - /// - /// \pre getMI().getOperand(OpIdx).isReg() - /// - /// \post All the partial mapping of the \p OpIdx-th operand have been - /// assigned a new virtual register. - void createVRegs(unsigned OpIdx); - - /// Set the virtual register of the \p PartialMapIdx-th partial mapping of - /// the OpIdx-th operand to \p NewVReg. - /// - /// \pre getMI().getOperand(OpIdx).isReg() - /// \pre getInstrMapping().getOperandMapping(OpIdx).BreakDown.size() > - /// PartialMapIdx - /// \pre NewReg != 0 - /// - /// \post the \p PartialMapIdx-th register of the value mapping of the \p - /// OpIdx-th operand has been set. - void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, Register NewVReg); - - /// Get all the virtual registers required to map the \p OpIdx-th operand of - /// the instruction. - /// - /// This return an empty range when createVRegs or setVRegs has not been - /// called. - /// The iterator may be invalidated by a call to setVRegs or createVRegs. - /// - /// When \p ForDebug is true, we will not check that the list of new virtual - /// registers does not contain uninitialized values. - /// - /// \pre getMI().getOperand(OpIdx).isReg() - /// \pre ForDebug || All partial mappings have been set a register - iterator_range::const_iterator> - getVRegs(unsigned OpIdx, bool ForDebug = false) const; - - /// Print this operands mapper on dbgs() stream. - void dump() const; - - /// Print this operands mapper on \p OS stream. - void print(raw_ostream &OS, bool ForDebug = false) const; - }; - -protected: - /// Hold the set of supported register banks. - RegisterBank **RegBanks; - - /// Total number of register banks. - unsigned NumRegBanks; - - /// Keep dynamically allocated PartialMapping in a separate map. - /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap> - MapOfPartialMappings; - - /// Keep dynamically allocated ValueMapping in a separate map. - /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap> - MapOfValueMappings; - - /// Keep dynamically allocated array of ValueMapping in a separate map. - /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap> - MapOfOperandsMappings; - - /// Keep dynamically allocated InstructionMapping in a separate map. - /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap> - MapOfInstructionMappings; - - /// Getting the minimal register class of a physreg is expensive. - /// Cache this information as we get it. - mutable DenseMap PhysRegMinimalRCs; - - /// Create a RegisterBankInfo that can accommodate up to \p NumRegBanks - /// RegisterBank instances. - RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks); - - /// This constructor is meaningless. - /// It just provides a default constructor that can be used at link time - /// when GlobalISel is not built. - /// That way, targets can still inherit from this class without doing - /// crazy gymnastic to avoid link time failures. - /// \note That works because the constructor is inlined. - RegisterBankInfo() { - llvm_unreachable("This constructor should not be executed"); - } - - /// Get the register bank identified by \p ID. - RegisterBank &getRegBank(unsigned ID) { - assert(ID < getNumRegBanks() && "Accessing an unknown register bank"); - return *RegBanks[ID]; - } - - /// Get the MinimalPhysRegClass for Reg. - /// \pre Reg is a physical register. - const TargetRegisterClass & - getMinimalPhysRegClass(Register Reg, const TargetRegisterInfo &TRI) const; - - /// Try to get the mapping of \p MI. - /// See getInstrMapping for more details on what a mapping represents. - /// - /// Unlike getInstrMapping the returned InstructionMapping may be invalid - /// (isValid() == false). - /// This means that the target independent code is not smart enough - /// to get the mapping of \p MI and thus, the target has to provide the - /// information for \p MI. - /// - /// This implementation is able to get the mapping of: - /// - Target specific instructions by looking at the encoding constraints. - /// - Any instruction if all the register operands have already been assigned - /// a register, a register class, or a register bank. - /// - Copies and phis if at least one of the operands has been assigned a - /// register, a register class, or a register bank. - /// In other words, this method will likely fail to find a mapping for - /// any generic opcode that has not been lowered by target specific code. - const InstructionMapping &getInstrMappingImpl(const MachineInstr &MI) const; - - /// Get the uniquely generated PartialMapping for the - /// given arguments. - const PartialMapping &getPartialMapping(unsigned StartIdx, unsigned Length, - const RegisterBank &RegBank) const; - - /// \name Methods to get a uniquely generated ValueMapping. - /// @{ - - /// The most common ValueMapping consists of a single PartialMapping. - /// Feature a method for that. - const ValueMapping &getValueMapping(unsigned StartIdx, unsigned Length, - const RegisterBank &RegBank) const; - - /// Get the ValueMapping for the given arguments. - const ValueMapping &getValueMapping(const PartialMapping *BreakDown, - unsigned NumBreakDowns) const; - /// @} - - /// \name Methods to get a uniquely generated array of ValueMapping. - /// @{ - - /// Get the uniquely generated array of ValueMapping for the - /// elements of between \p Begin and \p End. - /// - /// Elements that are nullptr will be replaced by - /// invalid ValueMapping (ValueMapping::isValid == false). - /// - /// \pre The pointers on ValueMapping between \p Begin and \p End - /// must uniquely identify a ValueMapping. Otherwise, there is no - /// guarantee that the return instance will be unique, i.e., another - /// OperandsMapping could have the same content. - template - const ValueMapping *getOperandsMapping(Iterator Begin, Iterator End) const; - - /// Get the uniquely generated array of ValueMapping for the - /// elements of \p OpdsMapping. - /// - /// Elements of \p OpdsMapping that are nullptr will be replaced by - /// invalid ValueMapping (ValueMapping::isValid == false). - const ValueMapping *getOperandsMapping( - const SmallVectorImpl &OpdsMapping) const; - - /// Get the uniquely generated array of ValueMapping for the - /// given arguments. - /// - /// Arguments that are nullptr will be replaced by invalid - /// ValueMapping (ValueMapping::isValid == false). - const ValueMapping *getOperandsMapping( - std::initializer_list OpdsMapping) const; - /// @} - - /// \name Methods to get a uniquely generated InstructionMapping. - /// @{ - -private: - /// Method to get a uniquely generated InstructionMapping. - const InstructionMapping & - getInstructionMappingImpl(bool IsInvalid, unsigned ID = InvalidMappingID, - unsigned Cost = 0, - const ValueMapping *OperandsMapping = nullptr, - unsigned NumOperands = 0) const; - -public: - /// Method to get a uniquely generated InstructionMapping. - const InstructionMapping & - getInstructionMapping(unsigned ID, unsigned Cost, - const ValueMapping *OperandsMapping, - unsigned NumOperands) const { - return getInstructionMappingImpl(/*IsInvalid*/ false, ID, Cost, - OperandsMapping, NumOperands); - } - - /// Method to get a uniquely generated invalid InstructionMapping. - const InstructionMapping &getInvalidInstructionMapping() const { - return getInstructionMappingImpl(/*IsInvalid*/ true); - } - /// @} - - /// Get the register bank for the \p OpIdx-th operand of \p MI form - /// the encoding constraints, if any. - /// - /// \return A register bank that covers the register class of the - /// related encoding constraints or nullptr if \p MI did not provide - /// enough information to deduce it. - const RegisterBank * - getRegBankFromConstraints(const MachineInstr &MI, unsigned OpIdx, - const TargetInstrInfo &TII, - const MachineRegisterInfo &MRI) const; - - /// Helper method to apply something that is like the default mapping. - /// Basically, that means that \p OpdMapper.getMI() is left untouched - /// aside from the reassignment of the register operand that have been - /// remapped. - /// - /// The type of all the new registers that have been created by the - /// mapper are properly remapped to the type of the original registers - /// they replace. In other words, the semantic of the instruction does - /// not change, only the register banks. - /// - /// If the mapping of one of the operand spans several registers, this - /// method will abort as this is not like a default mapping anymore. - /// - /// \pre For OpIdx in {0..\p OpdMapper.getMI().getNumOperands()) - /// the range OpdMapper.getVRegs(OpIdx) is empty or of size 1. - static void applyDefaultMapping(const OperandsMapper &OpdMapper); - - /// See ::applyMapping. - virtual void applyMappingImpl(const OperandsMapper &OpdMapper) const { - llvm_unreachable("The target has to implement that part"); - } - -public: - virtual ~RegisterBankInfo() = default; - - /// Get the register bank identified by \p ID. - const RegisterBank &getRegBank(unsigned ID) const { - return const_cast(this)->getRegBank(ID); - } - - /// Get the register bank of \p Reg. - /// If Reg has not been assigned a register, a register class, - /// or a register bank, then this returns nullptr. - /// - /// \pre Reg != 0 (NoRegister) - const RegisterBank *getRegBank(Register Reg, const MachineRegisterInfo &MRI, - const TargetRegisterInfo &TRI) const; - - /// Get the total number of register banks. - unsigned getNumRegBanks() const { return NumRegBanks; } - - /// Get a register bank that covers \p RC. - /// - /// \pre \p RC is a user-defined register class (as opposed as one - /// generated by TableGen). - /// - /// \note The mapping RC -> RegBank could be built while adding the - /// coverage for the register banks. However, we do not do it, because, - /// at least for now, we only need this information for register classes - /// that are used in the description of instruction. In other words, - /// there are just a handful of them and we do not want to waste space. - /// - /// \todo This should be TableGen'ed. - virtual const RegisterBank & - getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const { - llvm_unreachable("The target must override this method"); - } - - /// Get the cost of a copy from \p B to \p A, or put differently, - /// get the cost of A = COPY B. Since register banks may cover - /// different size, \p Size specifies what will be the size in bits - /// that will be copied around. - /// - /// \note Since this is a copy, both registers have the same size. - virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B, - unsigned Size) const { - // Optimistically assume that copies are coalesced. I.e., when - // they are on the same bank, they are free. - // Otherwise assume a non-zero cost of 1. The targets are supposed - // to override that properly anyway if they care. - return &A != &B; - } - - /// \returns true if emitting a copy from \p Src to \p Dst is impossible. - bool cannotCopy(const RegisterBank &Dst, const RegisterBank &Src, - unsigned Size) const { - return copyCost(Dst, Src, Size) == std::numeric_limits::max(); - } - - /// Get the cost of using \p ValMapping to decompose a register. This is - /// similar to ::copyCost, except for cases where multiple copy-like - /// operations need to be inserted. If the register is used as a source - /// operand and already has a bank assigned, \p CurBank is non-null. - virtual unsigned getBreakDownCost(const ValueMapping &ValMapping, - const RegisterBank *CurBank = nullptr) const { - return std::numeric_limits::max(); - } - - /// Constrain the (possibly generic) virtual register \p Reg to \p RC. - /// - /// \pre \p Reg is a virtual register that either has a bank or a class. - /// \returns The constrained register class, or nullptr if there is none. - /// \note This is a generic variant of MachineRegisterInfo::constrainRegClass - /// \note Use MachineRegisterInfo::constrainRegAttrs instead for any non-isel - /// purpose, including non-select passes of GlobalISel - static const TargetRegisterClass * - constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, - MachineRegisterInfo &MRI); - - /// Identifier used when the related instruction mapping instance - /// is generated by target independent code. - /// Make sure not to use that identifier to avoid possible collision. - static const unsigned DefaultMappingID; - - /// Identifier used when the related instruction mapping instance - /// is generated by the default constructor. - /// Make sure not to use that identifier. - static const unsigned InvalidMappingID; - - /// Get the mapping of the different operands of \p MI - /// on the register bank. - /// This mapping should be the direct translation of \p MI. - /// In other words, when \p MI is mapped with the returned mapping, - /// only the register banks of the operands of \p MI need to be updated. - /// In particular, neither the opcode nor the type of \p MI needs to be - /// updated for this direct mapping. - /// - /// The target independent implementation gives a mapping based on - /// the register classes for the target specific opcode. - /// It uses the ID RegisterBankInfo::DefaultMappingID for that mapping. - /// Make sure you do not use that ID for the alternative mapping - /// for MI. See getInstrAlternativeMappings for the alternative - /// mappings. - /// - /// For instance, if \p MI is a vector add, the mapping should - /// not be a scalarization of the add. - /// - /// \post returnedVal.verify(MI). - /// - /// \note If returnedVal does not verify MI, this would probably mean - /// that the target does not support that instruction. - virtual const InstructionMapping & - getInstrMapping(const MachineInstr &MI) const; - - /// Get the alternative mappings for \p MI. - /// Alternative in the sense different from getInstrMapping. - virtual InstructionMappings - getInstrAlternativeMappings(const MachineInstr &MI) const; - - /// Get the possible mapping for \p MI. - /// A mapping defines where the different operands may live and at what cost. - /// For instance, let us consider: - /// v0(16) = G_ADD <2 x i8> v1, v2 - /// The possible mapping could be: - /// - /// {/*ID*/VectorAdd, /*Cost*/1, /*v0*/{(0xFFFF, VPR)}, /*v1*/{(0xFFFF, VPR)}, - /// /*v2*/{(0xFFFF, VPR)}} - /// {/*ID*/ScalarAddx2, /*Cost*/2, /*v0*/{(0x00FF, GPR),(0xFF00, GPR)}, - /// /*v1*/{(0x00FF, GPR),(0xFF00, GPR)}, - /// /*v2*/{(0x00FF, GPR),(0xFF00, GPR)}} - /// - /// \note The first alternative of the returned mapping should be the - /// direct translation of \p MI current form. - /// - /// \post !returnedVal.empty(). - InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const; - - /// Apply \p OpdMapper.getInstrMapping() to \p OpdMapper.getMI(). - /// After this call \p OpdMapper.getMI() may not be valid anymore. - /// \p OpdMapper.getInstrMapping().getID() carries the information of - /// what has been chosen to map \p OpdMapper.getMI(). This ID is set - /// by the various getInstrXXXMapping method. - /// - /// Therefore, getting the mapping and applying it should be kept in - /// sync. - void applyMapping(const OperandsMapper &OpdMapper) const { - // The only mapping we know how to handle is the default mapping. - if (OpdMapper.getInstrMapping().getID() == DefaultMappingID) - return applyDefaultMapping(OpdMapper); - // For other mapping, the target needs to do the right thing. - // If that means calling applyDefaultMapping, fine, but this - // must be explicitly stated. - applyMappingImpl(OpdMapper); - } - - /// Get the size in bits of \p Reg. - /// Utility method to get the size of any registers. Unlike - /// MachineRegisterInfo::getSize, the register does not need to be a - /// virtual register. - /// - /// \pre \p Reg != 0 (NoRegister). - unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, - const TargetRegisterInfo &TRI) const; - - /// Check that information hold by this instance make sense for the - /// given \p TRI. - /// - /// \note This method does not check anything when assertions are disabled. - /// - /// \return True is the check was successful. - bool verify(const TargetRegisterInfo &TRI) const; -}; - -inline raw_ostream & -operator<<(raw_ostream &OS, - const RegisterBankInfo::PartialMapping &PartMapping) { - PartMapping.print(OS); - return OS; -} - -inline raw_ostream & -operator<<(raw_ostream &OS, const RegisterBankInfo::ValueMapping &ValMapping) { - ValMapping.print(OS); - return OS; -} - -inline raw_ostream & -operator<<(raw_ostream &OS, - const RegisterBankInfo::InstructionMapping &InstrMapping) { - InstrMapping.print(OS); - return OS; -} - -inline raw_ostream & -operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) { - OpdMapper.print(OS, /*ForDebug*/ false); - return OS; -} - -/// Hashing function for PartialMapping. -/// It is required for the hashing of ValueMapping. -hash_code hash_value(const RegisterBankInfo::PartialMapping &PartMapping); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Utils.h b/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Utils.h deleted file mode 100644 index aed915d2cc..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/GlobalISel/Utils.h +++ /dev/null @@ -1,474 +0,0 @@ -//==-- llvm/CodeGen/GlobalISel/Utils.h ---------------------------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file declares the API of helper functions used throughout the -/// GlobalISel pipeline. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H -#define LLVM_CODEGEN_GLOBALISEL_UTILS_H - -#include "GISelWorkList.h" -#include "LostDebugLocObserver.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include - -namespace llvm { - -class AnalysisUsage; -class BlockFrequencyInfo; -class GISelKnownBits; -class MachineFunction; -class MachineInstr; -class MachineOperand; -class MachineOptimizationRemarkEmitter; -class MachineOptimizationRemarkMissed; -struct MachinePointerInfo; -class MachineRegisterInfo; -class MCInstrDesc; -class ProfileSummaryInfo; -class RegisterBankInfo; -class TargetInstrInfo; -class TargetLowering; -class TargetPassConfig; -class TargetRegisterInfo; -class TargetRegisterClass; -class ConstantFP; -class APFloat; -class MachineIRBuilder; - -// Convenience macros for dealing with vector reduction opcodes. -#define GISEL_VECREDUCE_CASES_ALL \ - case TargetOpcode::G_VECREDUCE_SEQ_FADD: \ - case TargetOpcode::G_VECREDUCE_SEQ_FMUL: \ - case TargetOpcode::G_VECREDUCE_FADD: \ - case TargetOpcode::G_VECREDUCE_FMUL: \ - case TargetOpcode::G_VECREDUCE_FMAX: \ - case TargetOpcode::G_VECREDUCE_FMIN: \ - case TargetOpcode::G_VECREDUCE_ADD: \ - case TargetOpcode::G_VECREDUCE_MUL: \ - case TargetOpcode::G_VECREDUCE_AND: \ - case TargetOpcode::G_VECREDUCE_OR: \ - case TargetOpcode::G_VECREDUCE_XOR: \ - case TargetOpcode::G_VECREDUCE_SMAX: \ - case TargetOpcode::G_VECREDUCE_SMIN: \ - case TargetOpcode::G_VECREDUCE_UMAX: \ - case TargetOpcode::G_VECREDUCE_UMIN: - -#define GISEL_VECREDUCE_CASES_NONSEQ \ - case TargetOpcode::G_VECREDUCE_FADD: \ - case TargetOpcode::G_VECREDUCE_FMUL: \ - case TargetOpcode::G_VECREDUCE_FMAX: \ - case TargetOpcode::G_VECREDUCE_FMIN: \ - case TargetOpcode::G_VECREDUCE_ADD: \ - case TargetOpcode::G_VECREDUCE_MUL: \ - case TargetOpcode::G_VECREDUCE_AND: \ - case TargetOpcode::G_VECREDUCE_OR: \ - case TargetOpcode::G_VECREDUCE_XOR: \ - case TargetOpcode::G_VECREDUCE_SMAX: \ - case TargetOpcode::G_VECREDUCE_SMIN: \ - case TargetOpcode::G_VECREDUCE_UMAX: \ - case TargetOpcode::G_VECREDUCE_UMIN: - -/// Try to constrain Reg to the specified register class. If this fails, -/// create a new virtual register in the correct class. -/// -/// \return The virtual register constrained to the right register class. -Register constrainRegToClass(MachineRegisterInfo &MRI, - const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, Register Reg, - const TargetRegisterClass &RegClass); - -/// Constrain the Register operand OpIdx, so that it is now constrained to the -/// TargetRegisterClass passed as an argument (RegClass). -/// If this fails, create a new virtual register in the correct class and insert -/// a COPY before \p InsertPt if it is a use or after if it is a definition. -/// In both cases, the function also updates the register of RegMo. The debug -/// location of \p InsertPt is used for the new copy. -/// -/// \return The virtual register constrained to the right register class. -Register constrainOperandRegClass(const MachineFunction &MF, - const TargetRegisterInfo &TRI, - MachineRegisterInfo &MRI, - const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, - const TargetRegisterClass &RegClass, - MachineOperand &RegMO); - -/// Try to constrain Reg so that it is usable by argument OpIdx of the provided -/// MCInstrDesc \p II. If this fails, create a new virtual register in the -/// correct class and insert a COPY before \p InsertPt if it is a use or after -/// if it is a definition. In both cases, the function also updates the register -/// of RegMo. -/// This is equivalent to constrainOperandRegClass(..., RegClass, ...) -/// with RegClass obtained from the MCInstrDesc. The debug location of \p -/// InsertPt is used for the new copy. -/// -/// \return The virtual register constrained to the right register class. -Register constrainOperandRegClass(const MachineFunction &MF, - const TargetRegisterInfo &TRI, - MachineRegisterInfo &MRI, - const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, const MCInstrDesc &II, - MachineOperand &RegMO, unsigned OpIdx); - -/// Mutate the newly-selected instruction \p I to constrain its (possibly -/// generic) virtual register operands to the instruction's register class. -/// This could involve inserting COPYs before (for uses) or after (for defs). -/// This requires the number of operands to match the instruction description. -/// \returns whether operand regclass constraining succeeded. -/// -// FIXME: Not all instructions have the same number of operands. We should -// probably expose a constrain helper per operand and let the target selector -// constrain individual registers, like fast-isel. -bool constrainSelectedInstRegOperands(MachineInstr &I, - const TargetInstrInfo &TII, - const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI); - -/// Check if DstReg can be replaced with SrcReg depending on the register -/// constraints. -bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI); - -/// Check whether an instruction \p MI is dead: it only defines dead virtual -/// registers, and doesn't have other side effects. -bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI); - -/// Report an ISel error as a missed optimization remark to the LLVMContext's -/// diagnostic stream. Set the FailedISel MachineFunction property. -void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, - MachineOptimizationRemarkEmitter &MORE, - MachineOptimizationRemarkMissed &R); - -void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, - MachineOptimizationRemarkEmitter &MORE, - const char *PassName, StringRef Msg, - const MachineInstr &MI); - -/// Report an ISel warning as a missed optimization remark to the LLVMContext's -/// diagnostic stream. -void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC, - MachineOptimizationRemarkEmitter &MORE, - MachineOptimizationRemarkMissed &R); - -/// If \p VReg is defined by a G_CONSTANT, return the corresponding value. -Optional getIConstantVRegVal(Register VReg, - const MachineRegisterInfo &MRI); - -/// If \p VReg is defined by a G_CONSTANT fits in int64_t returns it. -Optional getIConstantVRegSExtVal(Register VReg, - const MachineRegisterInfo &MRI); - -/// Simple struct used to hold a constant integer value and a virtual -/// register. -struct ValueAndVReg { - APInt Value; - Register VReg; -}; - -/// If \p VReg is defined by a statically evaluable chain of instructions rooted -/// on a G_CONSTANT returns its APInt value and def register. -Optional -getIConstantVRegValWithLookThrough(Register VReg, - const MachineRegisterInfo &MRI, - bool LookThroughInstrs = true); - -/// If \p VReg is defined by a statically evaluable chain of instructions rooted -/// on a G_CONSTANT or G_FCONSTANT returns its value as APInt and def register. -Optional getAnyConstantVRegValWithLookThrough( - Register VReg, const MachineRegisterInfo &MRI, - bool LookThroughInstrs = true, bool LookThroughAnyExt = false); - -struct FPValueAndVReg { - APFloat Value; - Register VReg; -}; - -/// If \p VReg is defined by a statically evaluable chain of instructions rooted -/// on a G_FCONSTANT returns its APFloat value and def register. -Optional -getFConstantVRegValWithLookThrough(Register VReg, - const MachineRegisterInfo &MRI, - bool LookThroughInstrs = true); - -const ConstantFP* getConstantFPVRegVal(Register VReg, - const MachineRegisterInfo &MRI); - -/// See if Reg is defined by an single def instruction that is -/// Opcode. Also try to do trivial folding if it's a COPY with -/// same types. Returns null otherwise. -MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg, - const MachineRegisterInfo &MRI); - -/// Simple struct used to hold a Register value and the instruction which -/// defines it. -struct DefinitionAndSourceRegister { - MachineInstr *MI; - Register Reg; -}; - -/// Find the def instruction for \p Reg, and underlying value Register folding -/// away any copies. -/// -/// Also walks through hints such as G_ASSERT_ZEXT. -Optional -getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); - -/// Find the def instruction for \p Reg, folding away any trivial copies. May -/// return nullptr if \p Reg is not a generic virtual register. -/// -/// Also walks through hints such as G_ASSERT_ZEXT. -MachineInstr *getDefIgnoringCopies(Register Reg, - const MachineRegisterInfo &MRI); - -/// Find the source register for \p Reg, folding away any trivial copies. It -/// will be an output register of the instruction that getDefIgnoringCopies -/// returns. May return an invalid register if \p Reg is not a generic virtual -/// register. -/// -/// Also walks through hints such as G_ASSERT_ZEXT. -Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); - -// Templated variant of getOpcodeDef returning a MachineInstr derived T. -/// See if Reg is defined by an single def instruction of type T -/// Also try to do trivial folding if it's a COPY with -/// same types. Returns null otherwise. -template -T *getOpcodeDef(Register Reg, const MachineRegisterInfo &MRI) { - MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI); - return dyn_cast_or_null(DefMI); -} - -/// Returns an APFloat from Val converted to the appropriate size. -APFloat getAPFloatFromSize(double Val, unsigned Size); - -/// Modify analysis usage so it preserves passes required for the SelectionDAG -/// fallback. -void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); - -Optional ConstantFoldBinOp(unsigned Opcode, const Register Op1, - const Register Op2, - const MachineRegisterInfo &MRI); -Optional ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, - const Register Op2, - const MachineRegisterInfo &MRI); - -/// Tries to constant fold a vector binop with sources \p Op1 and \p Op2. -/// If successful, returns the G_BUILD_VECTOR representing the folded vector -/// constant. \p MIB should have an insertion point already set to create new -/// G_CONSTANT instructions as needed. -Register ConstantFoldVectorBinop(unsigned Opcode, const Register Op1, - const Register Op2, - const MachineRegisterInfo &MRI, - MachineIRBuilder &MIB); - -Optional ConstantFoldExtOp(unsigned Opcode, const Register Op1, - uint64_t Imm, const MachineRegisterInfo &MRI); - -Optional ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, - Register Src, - const MachineRegisterInfo &MRI); - -/// Tries to constant fold a G_CTLZ operation on \p Src. If \p Src is a vector -/// then it tries to do an element-wise constant fold. -Optional> -ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI); - -/// Test if the given value is known to have exactly one bit set. This differs -/// from computeKnownBits in that it doesn't necessarily determine which bit is -/// set. -bool isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI, - GISelKnownBits *KnownBits = nullptr); - -/// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true, -/// this returns if \p Val can be assumed to never be a signaling NaN. -bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, - bool SNaN = false); - -/// Returns true if \p Val can be assumed to never be a signaling NaN. -inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) { - return isKnownNeverNaN(Val, MRI, true); -} - -Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO); - -/// Return a virtual register corresponding to the incoming argument register \p -/// PhysReg. This register is expected to have class \p RC, and optional type \p -/// RegTy. This assumes all references to the register will use the same type. -/// -/// If there is an existing live-in argument register, it will be returned. -/// This will also ensure there is a valid copy -Register getFunctionLiveInPhysReg(MachineFunction &MF, - const TargetInstrInfo &TII, - MCRegister PhysReg, - const TargetRegisterClass &RC, - const DebugLoc &DL, LLT RegTy = LLT()); - -/// Return the least common multiple type of \p OrigTy and \p TargetTy, by changing the -/// number of vector elements or scalar bitwidth. The intent is a -/// G_MERGE_VALUES, G_BUILD_VECTOR, or G_CONCAT_VECTORS can be constructed from -/// \p OrigTy elements, and unmerged into \p TargetTy -LLVM_READNONE -LLT getLCMType(LLT OrigTy, LLT TargetTy); - -LLVM_READNONE -/// Return smallest type that covers both \p OrigTy and \p TargetTy and is -/// multiple of TargetTy. -LLT getCoverTy(LLT OrigTy, LLT TargetTy); - -/// Return a type where the total size is the greatest common divisor of \p -/// OrigTy and \p TargetTy. This will try to either change the number of vector -/// elements, or bitwidth of scalars. The intent is the result type can be used -/// as the result of a G_UNMERGE_VALUES from \p OrigTy, and then some -/// combination of G_MERGE_VALUES, G_BUILD_VECTOR and G_CONCAT_VECTORS (possibly -/// with intermediate casts) can re-form \p TargetTy. -/// -/// If these are vectors with different element types, this will try to produce -/// a vector with a compatible total size, but the element type of \p OrigTy. If -/// this can't be satisfied, this will produce a scalar smaller than the -/// original vector elements. -/// -/// In the worst case, this returns LLT::scalar(1) -LLVM_READNONE -LLT getGCDType(LLT OrigTy, LLT TargetTy); - -/// Represents a value which can be a Register or a constant. -/// -/// This is useful in situations where an instruction may have an interesting -/// register operand or interesting constant operand. For a concrete example, -/// \see getVectorSplat. -class RegOrConstant { - int64_t Cst; - Register Reg; - bool IsReg; - -public: - explicit RegOrConstant(Register Reg) : Reg(Reg), IsReg(true) {} - explicit RegOrConstant(int64_t Cst) : Cst(Cst), IsReg(false) {} - bool isReg() const { return IsReg; } - bool isCst() const { return !IsReg; } - Register getReg() const { - assert(isReg() && "Expected a register!"); - return Reg; - } - int64_t getCst() const { - assert(isCst() && "Expected a constant!"); - return Cst; - } -}; - -/// \returns The splat index of a G_SHUFFLE_VECTOR \p MI when \p MI is a splat. -/// If \p MI is not a splat, returns None. -Optional getSplatIndex(MachineInstr &MI); - -/// Returns a scalar constant of a G_BUILD_VECTOR splat if it exists. -Optional getBuildVectorConstantSplat(const MachineInstr &MI, - const MachineRegisterInfo &MRI); - -/// Returns a floating point scalar constant of a build vector splat if it -/// exists. When \p AllowUndef == true some elements can be undef but not all. -Optional getFConstantSplat(Register VReg, - const MachineRegisterInfo &MRI, - bool AllowUndef = true); - -/// Return true if the specified register is defined by G_BUILD_VECTOR or -/// G_BUILD_VECTOR_TRUNC where all of the elements are \p SplatValue or undef. -bool isBuildVectorConstantSplat(const Register Reg, - const MachineRegisterInfo &MRI, - int64_t SplatValue, bool AllowUndef); - -/// Return true if the specified instruction is a G_BUILD_VECTOR or -/// G_BUILD_VECTOR_TRUNC where all of the elements are \p SplatValue or undef. -bool isBuildVectorConstantSplat(const MachineInstr &MI, - const MachineRegisterInfo &MRI, - int64_t SplatValue, bool AllowUndef); - -/// Return true if the specified instruction is a G_BUILD_VECTOR or -/// G_BUILD_VECTOR_TRUNC where all of the elements are 0 or undef. -bool isBuildVectorAllZeros(const MachineInstr &MI, - const MachineRegisterInfo &MRI, - bool AllowUndef = false); - -/// Return true if the specified instruction is a G_BUILD_VECTOR or -/// G_BUILD_VECTOR_TRUNC where all of the elements are ~0 or undef. -bool isBuildVectorAllOnes(const MachineInstr &MI, - const MachineRegisterInfo &MRI, - bool AllowUndef = false); - -/// \returns a value when \p MI is a vector splat. The splat can be either a -/// Register or a constant. -/// -/// Examples: -/// -/// \code -/// %reg = COPY $physreg -/// %reg_splat = G_BUILD_VECTOR %reg, %reg, ..., %reg -/// \endcode -/// -/// If called on the G_BUILD_VECTOR above, this will return a RegOrConstant -/// containing %reg. -/// -/// \code -/// %cst = G_CONSTANT iN 4 -/// %constant_splat = G_BUILD_VECTOR %cst, %cst, ..., %cst -/// \endcode -/// -/// In the above case, this will return a RegOrConstant containing 4. -Optional getVectorSplat(const MachineInstr &MI, - const MachineRegisterInfo &MRI); - -/// Determines if \p MI defines a constant integer or a build vector of -/// constant integers. Treats undef values as constants. -bool isConstantOrConstantVector(MachineInstr &MI, - const MachineRegisterInfo &MRI); - -/// Determines if \p MI defines a constant integer or a splat vector of -/// constant integers. -/// \returns the scalar constant or None. -Optional isConstantOrConstantSplatVector(MachineInstr &MI, - const MachineRegisterInfo &MRI); - -/// Attempt to match a unary predicate against a scalar/splat constant or every -/// element of a constant G_BUILD_VECTOR. If \p ConstVal is null, the source -/// value was undef. -bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, - std::function Match, - bool AllowUndefs = false); - -/// Returns true if given the TargetLowering's boolean contents information, -/// the value \p Val contains a true value. -bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, - bool IsFP); - -/// Returns an integer representing true, as defined by the -/// TargetBooleanContents. -int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP); - -/// Returns true if the given block should be optimized for size. -bool shouldOptForSize(const MachineBasicBlock &MBB, ProfileSummaryInfo *PSI, - BlockFrequencyInfo *BFI); - -using SmallInstListTy = GISelWorkList<4>; -void saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI, - LostDebugLocObserver *LocObserver, - SmallInstListTy &DeadInstChain); -void eraseInstrs(ArrayRef DeadInstrs, MachineRegisterInfo &MRI, - LostDebugLocObserver *LocObserver = nullptr); -void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, - LostDebugLocObserver *LocObserver = nullptr); - -} // End namespace llvm. -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ISDOpcodes.h b/suite/synctools/tablegen/include/llvm/CodeGen/ISDOpcodes.h deleted file mode 100644 index f343f2dd72..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ISDOpcodes.h +++ /dev/null @@ -1,1463 +0,0 @@ -//===-- llvm/CodeGen/ISDOpcodes.h - CodeGen opcodes -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares codegen opcodes and related utilities. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ISDOPCODES_H -#define LLVM_CODEGEN_ISDOPCODES_H - -#include "llvm/CodeGen/ValueTypes.h" - -namespace llvm { - -/// ISD namespace - This namespace contains an enum which represents all of the -/// SelectionDAG node types and value types. -/// -namespace ISD { - -//===--------------------------------------------------------------------===// -/// ISD::NodeType enum - This enum defines the target-independent operators -/// for a SelectionDAG. -/// -/// Targets may also define target-dependent operator codes for SDNodes. For -/// example, on x86, these are the enum values in the X86ISD namespace. -/// Targets should aim to use target-independent operators to model their -/// instruction sets as much as possible, and only use target-dependent -/// operators when they have special requirements. -/// -/// Finally, during and after selection proper, SNodes may use special -/// operator codes that correspond directly with MachineInstr opcodes. These -/// are used to represent selected instructions. See the isMachineOpcode() -/// and getMachineOpcode() member functions of SDNode. -/// -enum NodeType { - - /// DELETED_NODE - This is an illegal value that is used to catch - /// errors. This opcode is not a legal opcode for any node. - DELETED_NODE, - - /// EntryToken - This is the marker used to indicate the start of a region. - EntryToken, - - /// TokenFactor - This node takes multiple tokens as input and produces a - /// single token result. This is used to represent the fact that the operand - /// operators are independent of each other. - TokenFactor, - - /// AssertSext, AssertZext - These nodes record if a register contains a - /// value that has already been zero or sign extended from a narrower type. - /// These nodes take two operands. The first is the node that has already - /// been extended, and the second is a value type node indicating the width - /// of the extension. - /// NOTE: In case of the source value (or any vector element value) is - /// poisoned the assertion will not be true for that value. - AssertSext, - AssertZext, - - /// AssertAlign - These nodes record if a register contains a value that - /// has a known alignment and the trailing bits are known to be zero. - /// NOTE: In case of the source value (or any vector element value) is - /// poisoned the assertion will not be true for that value. - AssertAlign, - - /// Various leaf nodes. - BasicBlock, - VALUETYPE, - CONDCODE, - Register, - RegisterMask, - Constant, - ConstantFP, - GlobalAddress, - GlobalTLSAddress, - FrameIndex, - JumpTable, - ConstantPool, - ExternalSymbol, - BlockAddress, - - /// The address of the GOT - GLOBAL_OFFSET_TABLE, - - /// FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and - /// llvm.returnaddress on the DAG. These nodes take one operand, the index - /// of the frame or return address to return. An index of zero corresponds - /// to the current function's frame or return address, an index of one to - /// the parent's frame or return address, and so on. - FRAMEADDR, - RETURNADDR, - - /// ADDROFRETURNADDR - Represents the llvm.addressofreturnaddress intrinsic. - /// This node takes no operand, returns a target-specific pointer to the - /// place in the stack frame where the return address of the current - /// function is stored. - ADDROFRETURNADDR, - - /// SPONENTRY - Represents the llvm.sponentry intrinsic. Takes no argument - /// and returns the stack pointer value at the entry of the current - /// function calling this intrinsic. - SPONENTRY, - - /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. - /// Materializes the offset from the local object pointer of another - /// function to a particular local object passed to llvm.localescape. The - /// operand is the MCSymbol label used to represent this offset, since - /// typically the offset is not known until after code generation of the - /// parent. - LOCAL_RECOVER, - - /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on - /// the DAG, which implements the named register global variables extension. - READ_REGISTER, - WRITE_REGISTER, - - /// FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to - /// first (possible) on-stack argument. This is needed for correct stack - /// adjustment during unwind. - FRAME_TO_ARGS_OFFSET, - - /// EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical - /// Frame Address (CFA), generally the value of the stack pointer at the - /// call site in the previous frame. - EH_DWARF_CFA, - - /// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents - /// 'eh_return' gcc dwarf builtin, which is used to return from - /// exception. The general meaning is: adjust stack by OFFSET and pass - /// execution to HANDLER. Many platform-related details also :) - EH_RETURN, - - /// RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) - /// This corresponds to the eh.sjlj.setjmp intrinsic. - /// It takes an input chain and a pointer to the jump buffer as inputs - /// and returns an outchain. - EH_SJLJ_SETJMP, - - /// OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) - /// This corresponds to the eh.sjlj.longjmp intrinsic. - /// It takes an input chain and a pointer to the jump buffer as inputs - /// and returns an outchain. - EH_SJLJ_LONGJMP, - - /// OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) - /// The target initializes the dispatch table here. - EH_SJLJ_SETUP_DISPATCH, - - /// TargetConstant* - Like Constant*, but the DAG does not do any folding, - /// simplification, or lowering of the constant. They are used for constants - /// which are known to fit in the immediate fields of their users, or for - /// carrying magic numbers which are not values which need to be - /// materialized in registers. - TargetConstant, - TargetConstantFP, - - /// TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or - /// anything else with this node, and this is valid in the target-specific - /// dag, turning into a GlobalAddress operand. - TargetGlobalAddress, - TargetGlobalTLSAddress, - TargetFrameIndex, - TargetJumpTable, - TargetConstantPool, - TargetExternalSymbol, - TargetBlockAddress, - - MCSymbol, - - /// TargetIndex - Like a constant pool entry, but with completely - /// target-dependent semantics. Holds target flags, a 32-bit index, and a - /// 64-bit index. Targets can use this however they like. - TargetIndex, - - /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) - /// This node represents a target intrinsic function with no side effects. - /// The first operand is the ID number of the intrinsic from the - /// llvm::Intrinsic namespace. The operands to the intrinsic follow. The - /// node returns the result of the intrinsic. - INTRINSIC_WO_CHAIN, - - /// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) - /// This node represents a target intrinsic function with side effects that - /// returns a result. The first operand is a chain pointer. The second is - /// the ID number of the intrinsic from the llvm::Intrinsic namespace. The - /// operands to the intrinsic follow. The node has two results, the result - /// of the intrinsic and an output chain. - INTRINSIC_W_CHAIN, - - /// OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) - /// This node represents a target intrinsic function with side effects that - /// does not return a result. The first operand is a chain pointer. The - /// second is the ID number of the intrinsic from the llvm::Intrinsic - /// namespace. The operands to the intrinsic follow. - INTRINSIC_VOID, - - /// CopyToReg - This node has three operands: a chain, a register number to - /// set to this value, and a value. - CopyToReg, - - /// CopyFromReg - This node indicates that the input value is a virtual or - /// physical register that is defined outside of the scope of this - /// SelectionDAG. The register is available from the RegisterSDNode object. - CopyFromReg, - - /// UNDEF - An undefined node. - UNDEF, - - // FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or - // is evaluated to UNDEF), or returns VAL otherwise. Note that each - // read of UNDEF can yield different value, but FREEZE(UNDEF) cannot. - FREEZE, - - /// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by - /// a Constant, which is required to be operand #1) half of the integer or - /// float value specified as operand #0. This is only for use before - /// legalization, for values that will be broken into multiple registers. - EXTRACT_ELEMENT, - - /// BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. - /// Given two values of the same integer value type, this produces a value - /// twice as big. Like EXTRACT_ELEMENT, this can only be used before - /// legalization. The lower part of the composite value should be in - /// element 0 and the upper part should be in element 1. - BUILD_PAIR, - - /// MERGE_VALUES - This node takes multiple discrete operands and returns - /// them all as its individual results. This nodes has exactly the same - /// number of inputs and outputs. This node is useful for some pieces of the - /// code generator that want to think about a single node with multiple - /// results, not multiple nodes. - MERGE_VALUES, - - /// Simple integer binary arithmetic operators. - ADD, - SUB, - MUL, - SDIV, - UDIV, - SREM, - UREM, - - /// SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing - /// a signed/unsigned value of type i[2*N], and return the full value as - /// two results, each of type iN. - SMUL_LOHI, - UMUL_LOHI, - - /// SDIVREM/UDIVREM - Divide two integers and produce both a quotient and - /// remainder result. - SDIVREM, - UDIVREM, - - /// CARRY_FALSE - This node is used when folding other nodes, - /// like ADDC/SUBC, which indicate the carry result is always false. - CARRY_FALSE, - - /// Carry-setting nodes for multiple precision addition and subtraction. - /// These nodes take two operands of the same value type, and produce two - /// results. The first result is the normal add or sub result, the second - /// result is the carry flag result. - /// FIXME: These nodes are deprecated in favor of ADDCARRY and SUBCARRY. - /// They are kept around for now to provide a smooth transition path - /// toward the use of ADDCARRY/SUBCARRY and will eventually be removed. - ADDC, - SUBC, - - /// Carry-using nodes for multiple precision addition and subtraction. These - /// nodes take three operands: The first two are the normal lhs and rhs to - /// the add or sub, and the third is the input carry flag. These nodes - /// produce two results; the normal result of the add or sub, and the output - /// carry flag. These nodes both read and write a carry flag to allow them - /// to them to be chained together for add and sub of arbitrarily large - /// values. - ADDE, - SUBE, - - /// Carry-using nodes for multiple precision addition and subtraction. - /// These nodes take three operands: The first two are the normal lhs and - /// rhs to the add or sub, and the third is a boolean indicating if there - /// is an incoming carry. These nodes produce two results: the normal - /// result of the add or sub, and the output carry so they can be chained - /// together. The use of this opcode is preferable to adde/sube if the - /// target supports it, as the carry is a regular value rather than a - /// glue, which allows further optimisation. - ADDCARRY, - SUBCARRY, - - /// Carry-using overflow-aware nodes for multiple precision addition and - /// subtraction. These nodes take three operands: The first two are normal lhs - /// and rhs to the add or sub, and the third is a boolean indicating if there - /// is an incoming carry. They produce two results: the normal result of the - /// add or sub, and a boolean that indicates if an overflow occurred (*not* - /// flag, because it may be a store to memory, etc.). If the type of the - /// boolean is not i1 then the high bits conform to getBooleanContents. - SADDO_CARRY, - SSUBO_CARRY, - - /// RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. - /// These nodes take two operands: the normal LHS and RHS to the add. They - /// produce two results: the normal result of the add, and a boolean that - /// indicates if an overflow occurred (*not* a flag, because it may be store - /// to memory, etc.). If the type of the boolean is not i1 then the high - /// bits conform to getBooleanContents. - /// These nodes are generated from llvm.[su]add.with.overflow intrinsics. - SADDO, - UADDO, - - /// Same for subtraction. - SSUBO, - USUBO, - - /// Same for multiplication. - SMULO, - UMULO, - - /// RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 - /// integers with the same bit width (W). If the true value of LHS + RHS - /// exceeds the largest value that can be represented by W bits, the - /// resulting value is this maximum value. Otherwise, if this value is less - /// than the smallest value that can be represented by W bits, the - /// resulting value is this minimum value. - SADDSAT, - UADDSAT, - - /// RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 - /// integers with the same bit width (W). If the true value of LHS - RHS - /// exceeds the largest value that can be represented by W bits, the - /// resulting value is this maximum value. Otherwise, if this value is less - /// than the smallest value that can be represented by W bits, the - /// resulting value is this minimum value. - SSUBSAT, - USUBSAT, - - /// RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift. The first - /// operand is the value to be shifted, and the second argument is the amount - /// to shift by. Both must be integers of the same bit width (W). If the true - /// value of LHS << RHS exceeds the largest value that can be represented by - /// W bits, the resulting value is this maximum value, Otherwise, if this - /// value is less than the smallest value that can be represented by W bits, - /// the resulting value is this minimum value. - SSHLSAT, - USHLSAT, - - /// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication - /// on 2 integers with the same width and scale. SCALE represents the scale - /// of both operands as fixed point numbers. This SCALE parameter must be a - /// constant integer. A scale of zero is effectively performing - /// multiplication on 2 integers. - SMULFIX, - UMULFIX, - - /// Same as the corresponding unsaturated fixed point instructions, but the - /// result is clamped between the min and max values representable by the - /// bits of the first 2 operands. - SMULFIXSAT, - UMULFIXSAT, - - /// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on - /// 2 integers with the same width and scale. SCALE represents the scale - /// of both operands as fixed point numbers. This SCALE parameter must be a - /// constant integer. - SDIVFIX, - UDIVFIX, - - /// Same as the corresponding unsaturated fixed point instructions, but the - /// result is clamped between the min and max values representable by the - /// bits of the first 2 operands. - SDIVFIXSAT, - UDIVFIXSAT, - - /// Simple binary floating point operators. - FADD, - FSUB, - FMUL, - FDIV, - FREM, - - /// Constrained versions of the binary floating point operators. - /// These will be lowered to the simple operators before final selection. - /// They are used to limit optimizations while the DAG is being - /// optimized. - STRICT_FADD, - STRICT_FSUB, - STRICT_FMUL, - STRICT_FDIV, - STRICT_FREM, - STRICT_FMA, - - /// Constrained versions of libm-equivalent floating point intrinsics. - /// These will be lowered to the equivalent non-constrained pseudo-op - /// (or expanded to the equivalent library call) before final selection. - /// They are used to limit optimizations while the DAG is being optimized. - STRICT_FSQRT, - STRICT_FPOW, - STRICT_FPOWI, - STRICT_FSIN, - STRICT_FCOS, - STRICT_FEXP, - STRICT_FEXP2, - STRICT_FLOG, - STRICT_FLOG10, - STRICT_FLOG2, - STRICT_FRINT, - STRICT_FNEARBYINT, - STRICT_FMAXNUM, - STRICT_FMINNUM, - STRICT_FCEIL, - STRICT_FFLOOR, - STRICT_FROUND, - STRICT_FROUNDEVEN, - STRICT_FTRUNC, - STRICT_LROUND, - STRICT_LLROUND, - STRICT_LRINT, - STRICT_LLRINT, - STRICT_FMAXIMUM, - STRICT_FMINIMUM, - - /// STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or - /// unsigned integer. These have the same semantics as fptosi and fptoui - /// in IR. - /// They are used to limit optimizations while the DAG is being optimized. - STRICT_FP_TO_SINT, - STRICT_FP_TO_UINT, - - /// STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to - /// a floating point value. These have the same semantics as sitofp and - /// uitofp in IR. - /// They are used to limit optimizations while the DAG is being optimized. - STRICT_SINT_TO_FP, - STRICT_UINT_TO_FP, - - /// X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating - /// point type down to the precision of the destination VT. TRUNC is a - /// flag, which is always an integer that is zero or one. If TRUNC is 0, - /// this is a normal rounding, if it is 1, this FP_ROUND is known to not - /// change the value of Y. - /// - /// The TRUNC = 1 case is used in cases where we know that the value will - /// not be modified by the node, because Y is not using any of the extra - /// precision of source type. This allows certain transformations like - /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,1)) -> X which are not safe for - /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,0)) because the extra bits aren't - /// removed. - /// It is used to limit optimizations while the DAG is being optimized. - STRICT_FP_ROUND, - - /// X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP - /// type. - /// It is used to limit optimizations while the DAG is being optimized. - STRICT_FP_EXTEND, - - /// STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used - /// for floating-point operands only. STRICT_FSETCC performs a quiet - /// comparison operation, while STRICT_FSETCCS performs a signaling - /// comparison operation. - STRICT_FSETCC, - STRICT_FSETCCS, - - /// FMA - Perform a * b + c with no intermediate rounding step. - FMA, - - /// FMAD - Perform a * b + c, while getting the same result as the - /// separately rounded operations. - FMAD, - - /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This - /// DAG node does not require that X and Y have the same type, just that - /// they are both floating point. X and the result must have the same type. - /// FCOPYSIGN(f32, f64) is allowed. - FCOPYSIGN, - - /// INT = FGETSIGN(FP) - Return the sign bit of the specified floating point - /// value as an integer 0/1 value. - FGETSIGN, - - /// Returns platform specific canonical encoding of a floating point number. - FCANONICALIZE, - - /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector - /// with the specified, possibly variable, elements. The types of the - /// operands must match the vector element type, except that integer types - /// are allowed to be larger than the element type, in which case the - /// operands are implicitly truncated. The types of the operands must all - /// be the same. - BUILD_VECTOR, - - /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element - /// at IDX replaced with VAL. If the type of VAL is larger than the vector - /// element type then VAL is truncated before replacement. - /// - /// If VECTOR is a scalable vector, then IDX may be larger than the minimum - /// vector width. IDX is not first scaled by the runtime scaling factor of - /// VECTOR. - INSERT_VECTOR_ELT, - - /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR - /// identified by the (potentially variable) element number IDX. If the return - /// type is an integer type larger than the element type of the vector, the - /// result is extended to the width of the return type. In that case, the high - /// bits are undefined. - /// - /// If VECTOR is a scalable vector, then IDX may be larger than the minimum - /// vector width. IDX is not first scaled by the runtime scaling factor of - /// VECTOR. - EXTRACT_VECTOR_ELT, - - /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of - /// vector type with the same length and element type, this produces a - /// concatenated vector result value, with length equal to the sum of the - /// lengths of the input vectors. If VECTOR0 is a fixed-width vector, then - /// VECTOR1..VECTORN must all be fixed-width vectors. Similarly, if VECTOR0 - /// is a scalable vector, then VECTOR1..VECTORN must all be scalable vectors. - CONCAT_VECTORS, - - /// INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 - /// inserted into VECTOR1. IDX represents the starting element number at which - /// VECTOR2 will be inserted. IDX must be a constant multiple of T's known - /// minimum vector length. Let the type of VECTOR2 be T, then if T is a - /// scalable vector, IDX is first scaled by the runtime scaling factor of T. - /// The elements of VECTOR1 starting at IDX are overwritten with VECTOR2. - /// Elements IDX through (IDX + num_elements(T) - 1) must be valid VECTOR1 - /// indices. If this condition cannot be determined statically but is false at - /// runtime, then the result vector is undefined. The IDX parameter must be a - /// vector index constant type, which for most targets will be an integer - /// pointer type. - /// - /// This operation supports inserting a fixed-width vector into a scalable - /// vector, but not the other way around. - INSERT_SUBVECTOR, - - /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR. - /// Let the result type be T, then IDX represents the starting element number - /// from which a subvector of type T is extracted. IDX must be a constant - /// multiple of T's known minimum vector length. If T is a scalable vector, - /// IDX is first scaled by the runtime scaling factor of T. Elements IDX - /// through (IDX + num_elements(T) - 1) must be valid VECTOR indices. If this - /// condition cannot be determined statically but is false at runtime, then - /// the result vector is undefined. The IDX parameter must be a vector index - /// constant type, which for most targets will be an integer pointer type. - /// - /// This operation supports extracting a fixed-width vector from a scalable - /// vector, but not the other way around. - EXTRACT_SUBVECTOR, - - /// VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, - /// whose elements are shuffled using the following algorithm: - /// RESULT[i] = VECTOR[VECTOR.ElementCount - 1 - i] - VECTOR_REVERSE, - - /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as - /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int - /// values that indicate which value (or undef) each result element will - /// get. These constant ints are accessible through the - /// ShuffleVectorSDNode class. This is quite similar to the Altivec - /// 'vperm' instruction, except that the indices must be constants and are - /// in terms of the element size of VEC1/VEC2, not in terms of bytes. - VECTOR_SHUFFLE, - - /// VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as - /// VEC1/VEC2 from CONCAT_VECTORS(VEC1, VEC2), based on the IMM in two ways. - /// Let the result type be T, if IMM is positive it represents the starting - /// element number (an index) from which a subvector of type T is extracted - /// from CONCAT_VECTORS(VEC1, VEC2). If IMM is negative it represents a count - /// specifying the number of trailing elements to extract from VEC1, where the - /// elements of T are selected using the following algorithm: - /// RESULT[i] = CONCAT_VECTORS(VEC1,VEC2)[VEC1.ElementCount - ABS(IMM) + i] - /// If IMM is not in the range [-VL, VL-1] the result vector is undefined. IMM - /// is a constant integer. - VECTOR_SPLICE, - - /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a - /// scalar value into element 0 of the resultant vector type. The top - /// elements 1 to N-1 of the N-element vector are undefined. The type - /// of the operand must match the vector element type, except when they - /// are integer types. In this case the operand is allowed to be wider - /// than the vector element type, and is implicitly truncated to it. - SCALAR_TO_VECTOR, - - /// SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL - /// duplicated in all lanes. The type of the operand must match the vector - /// element type, except when they are integer types. In this case the - /// operand is allowed to be wider than the vector element type, and is - /// implicitly truncated to it. - SPLAT_VECTOR, - - /// SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the - /// scalar values joined together and then duplicated in all lanes. This - /// represents a SPLAT_VECTOR that has had its scalar operand expanded. This - /// allows representing a 64-bit splat on a target with 32-bit integers. The - /// total width of the scalars must cover the element width. SCALAR1 contains - /// the least significant bits of the value regardless of endianness and all - /// scalars should have the same type. - SPLAT_VECTOR_PARTS, - - /// STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised - /// of a linear sequence of unsigned values starting from 0 with a step of - /// IMM, where IMM must be a TargetConstant with type equal to the vector - /// element type. The arithmetic is performed modulo the bitwidth of the - /// element. - /// - /// The operation does not support returning fixed-width vectors or - /// non-constant operands. - STEP_VECTOR, - - /// MULHU/MULHS - Multiply high - Multiply two integers of type iN, - /// producing an unsigned/signed value of type i[2*N], then return the top - /// part. - MULHU, - MULHS, - - // ABDS/ABDU - Absolute difference - Return the absolute difference between - // two numbers interpreted as signed/unsigned. - // i.e trunc(abs(sext(Op0) - sext(Op1))) becomes abds(Op0, Op1) - // or trunc(abs(zext(Op0) - zext(Op1))) becomes abdu(Op0, Op1) - ABDS, - ABDU, - - /// [US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned - /// integers. - SMIN, - SMAX, - UMIN, - UMAX, - - /// Bitwise operators - logical and, logical or, logical xor. - AND, - OR, - XOR, - - /// ABS - Determine the unsigned absolute value of a signed integer value of - /// the same bitwidth. - /// Note: A value of INT_MIN will return INT_MIN, no saturation or overflow - /// is performed. - ABS, - - /// Shift and rotation operations. After legalization, the type of the - /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization - /// the shift amount can be any type, but care must be taken to ensure it is - /// large enough. TLI.getShiftAmountTy() is i8 on some targets, but before - /// legalization, types like i1024 can occur and i8 doesn't have enough bits - /// to represent the shift amount. - /// When the 1st operand is a vector, the shift amount must be in the same - /// type. (TLI.getShiftAmountTy() will return the same type when the input - /// type is a vector.) - /// For rotates and funnel shifts, the shift amount is treated as an unsigned - /// amount modulo the element size of the first operand. - /// - /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. - /// fshl(X,Y,Z): (X << (Z % BW)) | (Y >> (BW - (Z % BW))) - /// fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW)) - SHL, - SRA, - SRL, - ROTL, - ROTR, - FSHL, - FSHR, - - /// Byte Swap and Counting operators. - BSWAP, - CTTZ, - CTLZ, - CTPOP, - BITREVERSE, - PARITY, - - /// Bit counting operators with an undefined result for zero inputs. - CTTZ_ZERO_UNDEF, - CTLZ_ZERO_UNDEF, - - /// Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not - /// i1 then the high bits must conform to getBooleanContents. - SELECT, - - /// Select with a vector condition (op #0) and two vector operands (ops #1 - /// and #2), returning a vector result. All vectors have the same length. - /// Much like the scalar select and setcc, each bit in the condition selects - /// whether the corresponding result element is taken from op #1 or op #2. - /// At first, the VSELECT condition is of vXi1 type. Later, targets may - /// change the condition type in order to match the VSELECT node using a - /// pattern. The condition follows the BooleanContent format of the target. - VSELECT, - - /// Select with condition operator - This selects between a true value and - /// a false value (ops #2 and #3) based on the boolean result of comparing - /// the lhs and rhs (ops #0 and #1) of a conditional expression with the - /// condition code in op #4, a CondCodeSDNode. - SELECT_CC, - - /// SetCC operator - This evaluates to a true value iff the condition is - /// true. If the result value type is not i1 then the high bits conform - /// to getBooleanContents. The operands to this are the left and right - /// operands to compare (ops #0, and #1) and the condition code to compare - /// them with (op #2) as a CondCodeSDNode. If the operands are vector types - /// then the result type must also be a vector type. - SETCC, - - /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but - /// op #2 is a boolean indicating if there is an incoming carry. This - /// operator checks the result of "LHS - RHS - Carry", and can be used to - /// compare two wide integers: - /// (setcccarry lhshi rhshi (subcarry lhslo rhslo) cc). - /// Only valid for integers. - SETCCCARRY, - - /// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded - /// integer shift operations. The operation ordering is: - /// [Lo,Hi] = op [LoLHS,HiLHS], Amt - SHL_PARTS, - SRA_PARTS, - SRL_PARTS, - - /// Conversion operators. These are all single input single output - /// operations. For all of these, the result type must be strictly - /// wider or narrower (depending on the operation) than the source - /// type. - - /// SIGN_EXTEND - Used for integer types, replicating the sign bit - /// into new bits. - SIGN_EXTEND, - - /// ZERO_EXTEND - Used for integer types, zeroing the new bits. - ZERO_EXTEND, - - /// ANY_EXTEND - Used for integer types. The high bits are undefined. - ANY_EXTEND, - - /// TRUNCATE - Completely drop the high bits. - TRUNCATE, - - /// [SU]INT_TO_FP - These operators convert integers (whose interpreted sign - /// depends on the first letter) to floating point. - SINT_TO_FP, - UINT_TO_FP, - - /// SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to - /// sign extend a small value in a large integer register (e.g. sign - /// extending the low 8 bits of a 32-bit register to fill the top 24 bits - /// with the 7th bit). The size of the smaller type is indicated by the 1th - /// operand, a ValueType node. - SIGN_EXTEND_INREG, - - /// ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an - /// in-register any-extension of the low lanes of an integer vector. The - /// result type must have fewer elements than the operand type, and those - /// elements must be larger integer types such that the total size of the - /// operand type is less than or equal to the size of the result type. Each - /// of the low operand elements is any-extended into the corresponding, - /// wider result elements with the high bits becoming undef. - /// NOTE: The type legalizer prefers to make the operand and result size - /// the same to allow expansion to shuffle vector during op legalization. - ANY_EXTEND_VECTOR_INREG, - - /// SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an - /// in-register sign-extension of the low lanes of an integer vector. The - /// result type must have fewer elements than the operand type, and those - /// elements must be larger integer types such that the total size of the - /// operand type is less than or equal to the size of the result type. Each - /// of the low operand elements is sign-extended into the corresponding, - /// wider result elements. - /// NOTE: The type legalizer prefers to make the operand and result size - /// the same to allow expansion to shuffle vector during op legalization. - SIGN_EXTEND_VECTOR_INREG, - - /// ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an - /// in-register zero-extension of the low lanes of an integer vector. The - /// result type must have fewer elements than the operand type, and those - /// elements must be larger integer types such that the total size of the - /// operand type is less than or equal to the size of the result type. Each - /// of the low operand elements is zero-extended into the corresponding, - /// wider result elements. - /// NOTE: The type legalizer prefers to make the operand and result size - /// the same to allow expansion to shuffle vector during op legalization. - ZERO_EXTEND_VECTOR_INREG, - - /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned - /// integer. These have the same semantics as fptosi and fptoui in IR. If - /// the FP value cannot fit in the integer type, the results are undefined. - FP_TO_SINT, - FP_TO_UINT, - - /// FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a - /// signed or unsigned scalar integer type given in operand 1 with the - /// following semantics: - /// - /// * If the value is NaN, zero is returned. - /// * If the value is larger/smaller than the largest/smallest integer, - /// the largest/smallest integer is returned (saturation). - /// * Otherwise the result of rounding the value towards zero is returned. - /// - /// The scalar width of the type given in operand 1 must be equal to, or - /// smaller than, the scalar result type width. It may end up being smaller - /// than the result width as a result of integer type legalization. - /// - /// After converting to the scalar integer type in operand 1, the value is - /// extended to the result VT. FP_TO_SINT_SAT sign extends and FP_TO_UINT_SAT - /// zero extends. - FP_TO_SINT_SAT, - FP_TO_UINT_SAT, - - /// X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type - /// down to the precision of the destination VT. TRUNC is a flag, which is - /// always an integer that is zero or one. If TRUNC is 0, this is a - /// normal rounding, if it is 1, this FP_ROUND is known to not change the - /// value of Y. - /// - /// The TRUNC = 1 case is used in cases where we know that the value will - /// not be modified by the node, because Y is not using any of the extra - /// precision of source type. This allows certain transformations like - /// FP_EXTEND(FP_ROUND(X,1)) -> X which are not safe for - /// FP_EXTEND(FP_ROUND(X,0)) because the extra bits aren't removed. - FP_ROUND, - - /// Returns current rounding mode: - /// -1 Undefined - /// 0 Round to 0 - /// 1 Round to nearest, ties to even - /// 2 Round to +inf - /// 3 Round to -inf - /// 4 Round to nearest, ties to zero - /// Result is rounding mode and chain. Input is a chain. - /// TODO: Rename this node to GET_ROUNDING. - FLT_ROUNDS_, - - /// Set rounding mode. - /// The first operand is a chain pointer. The second specifies the required - /// rounding mode, encoded in the same way as used in '``FLT_ROUNDS_``'. - SET_ROUNDING, - - /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. - FP_EXTEND, - - /// BITCAST - This operator converts between integer, vector and FP - /// values, as if the value was stored to memory with one type and loaded - /// from the same address with the other type (or equivalently for vector - /// format conversions, etc). The source and result are required to have - /// the same bit size (e.g. f32 <-> i32). This can also be used for - /// int-to-int or fp-to-fp conversions, but that is a noop, deleted by - /// getNode(). - /// - /// This operator is subtly different from the bitcast instruction from - /// LLVM-IR since this node may change the bits in the register. For - /// example, this occurs on big-endian NEON and big-endian MSA where the - /// layout of the bits in the register depends on the vector type and this - /// operator acts as a shuffle operation for some vector type combinations. - BITCAST, - - /// ADDRSPACECAST - This operator converts between pointers of different - /// address spaces. - ADDRSPACECAST, - - /// FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions - /// and truncation for half-precision (16 bit) floating numbers. These nodes - /// form a semi-softened interface for dealing with f16 (as an i16), which - /// is often a storage-only type but has native conversions. - FP16_TO_FP, - FP_TO_FP16, - STRICT_FP16_TO_FP, - STRICT_FP_TO_FP16, - - /// Perform various unary floating-point operations inspired by libm. For - /// FPOWI, the result is undefined if the integer operand doesn't fit into - /// sizeof(int). - FNEG, - FABS, - FSQRT, - FCBRT, - FSIN, - FCOS, - FPOWI, - FPOW, - FLOG, - FLOG2, - FLOG10, - FEXP, - FEXP2, - FCEIL, - FTRUNC, - FRINT, - FNEARBYINT, - FROUND, - FROUNDEVEN, - FFLOOR, - LROUND, - LLROUND, - LRINT, - LLRINT, - - /// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two - /// values. - // - /// In the case where a single input is a NaN (either signaling or quiet), - /// the non-NaN input is returned. - /// - /// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. - FMINNUM, - FMAXNUM, - - /// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on - /// two values, following the IEEE-754 2008 definition. This differs from - /// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a - /// signaling NaN, returns a quiet NaN. - FMINNUM_IEEE, - FMAXNUM_IEEE, - - /// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 - /// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 - /// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. - FMINIMUM, - FMAXIMUM, - - /// FSINCOS - Compute both fsin and fcos as a single operation. - FSINCOS, - - /// LOAD and STORE have token chains as their first operand, then the same - /// operands as an LLVM load/store instruction, then an offset node that - /// is added / subtracted from the base pointer to form the address (for - /// indexed memory ops). - LOAD, - STORE, - - /// DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned - /// to a specified boundary. This node always has two return values: a new - /// stack pointer value and a chain. The first operand is the token chain, - /// the second is the number of bytes to allocate, and the third is the - /// alignment boundary. The size is guaranteed to be a multiple of the - /// stack alignment, and the alignment is guaranteed to be bigger than the - /// stack alignment (if required) or 0 to get standard stack alignment. - DYNAMIC_STACKALLOC, - - /// Control flow instructions. These all have token chains. - - /// BR - Unconditional branch. The first operand is the chain - /// operand, the second is the MBB to branch to. - BR, - - /// BRIND - Indirect branch. The first operand is the chain, the second - /// is the value to branch to, which must be of the same type as the - /// target's pointer type. - BRIND, - - /// BR_JT - Jumptable branch. The first operand is the chain, the second - /// is the jumptable index, the last one is the jumptable entry index. - BR_JT, - - /// BRCOND - Conditional branch. The first operand is the chain, the - /// second is the condition, the third is the block to branch to if the - /// condition is true. If the type of the condition is not i1, then the - /// high bits must conform to getBooleanContents. If the condition is undef, - /// it nondeterministically jumps to the block. - /// TODO: Its semantics w.r.t undef requires further discussion; we need to - /// make it sure that it is consistent with optimizations in MIR & the - /// meaning of IMPLICIT_DEF. See https://reviews.llvm.org/D92015 - BRCOND, - - /// BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in - /// that the condition is represented as condition code, and two nodes to - /// compare, rather than as a combined SetCC node. The operands in order - /// are chain, cc, lhs, rhs, block to branch to if condition is true. If - /// condition is undef, it nondeterministically jumps to the block. - BR_CC, - - /// INLINEASM - Represents an inline asm block. This node always has two - /// return values: a chain and a flag result. The inputs are as follows: - /// Operand #0 : Input chain. - /// Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. - /// Operand #2 : a MDNodeSDNode with the !srcloc metadata. - /// Operand #3 : HasSideEffect, IsAlignStack bits. - /// After this, it is followed by a list of operands with this format: - /// ConstantSDNode: Flags that encode whether it is a mem or not, the - /// of operands that follow, etc. See InlineAsm.h. - /// ... however many operands ... - /// Operand #last: Optional, an incoming flag. - /// - /// The variable width operands are required to represent target addressing - /// modes as a single "operand", even though they may have multiple - /// SDOperands. - INLINEASM, - - /// INLINEASM_BR - Branching version of inline asm. Used by asm-goto. - INLINEASM_BR, - - /// EH_LABEL - Represents a label in mid basic block used to track - /// locations needed for debug and exception handling tables. These nodes - /// take a chain as input and return a chain. - EH_LABEL, - - /// ANNOTATION_LABEL - Represents a mid basic block label used by - /// annotations. This should remain within the basic block and be ordered - /// with respect to other call instructions, but loads and stores may float - /// past it. - ANNOTATION_LABEL, - - /// CATCHRET - Represents a return from a catch block funclet. Used for - /// MSVC compatible exception handling. Takes a chain operand and a - /// destination basic block operand. - CATCHRET, - - /// CLEANUPRET - Represents a return from a cleanup block funclet. Used for - /// MSVC compatible exception handling. Takes only a chain operand. - CLEANUPRET, - - /// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a - /// value, the same type as the pointer type for the system, and an output - /// chain. - STACKSAVE, - - /// STACKRESTORE has two operands, an input chain and a pointer to restore - /// to it returns an output chain. - STACKRESTORE, - - /// CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end - /// of a call sequence, and carry arbitrary information that target might - /// want to know. The first operand is a chain, the rest are specified by - /// the target and not touched by the DAG optimizers. - /// Targets that may use stack to pass call arguments define additional - /// operands: - /// - size of the call frame part that must be set up within the - /// CALLSEQ_START..CALLSEQ_END pair, - /// - part of the call frame prepared prior to CALLSEQ_START. - /// Both these parameters must be constants, their sum is the total call - /// frame size. - /// CALLSEQ_START..CALLSEQ_END pairs may not be nested. - CALLSEQ_START, // Beginning of a call sequence - CALLSEQ_END, // End of a call sequence - - /// VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, - /// and the alignment. It returns a pair of values: the vaarg value and a - /// new chain. - VAARG, - - /// VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, - /// a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the - /// source. - VACOPY, - - /// VAEND, VASTART - VAEND and VASTART have three operands: an input chain, - /// pointer, and a SRCVALUE. - VAEND, - VASTART, - - // PREALLOCATED_SETUP - This has 2 operands: an input chain and a SRCVALUE - // with the preallocated call Value. - PREALLOCATED_SETUP, - // PREALLOCATED_ARG - This has 3 operands: an input chain, a SRCVALUE - // with the preallocated call Value, and a constant int. - PREALLOCATED_ARG, - - /// SRCVALUE - This is a node type that holds a Value* that is used to - /// make reference to a value in the LLVM IR. - SRCVALUE, - - /// MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to - /// reference metadata in the IR. - MDNODE_SDNODE, - - /// PCMARKER - This corresponds to the pcmarker intrinsic. - PCMARKER, - - /// READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. - /// It produces a chain and one i64 value. The only operand is a chain. - /// If i64 is not legal, the result will be expanded into smaller values. - /// Still, it returns an i64, so targets should set legality for i64. - /// The result is the content of the architecture-specific cycle - /// counter-like register (or other high accuracy low latency clock source). - READCYCLECOUNTER, - - /// HANDLENODE node - Used as a handle for various purposes. - HANDLENODE, - - /// INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic. It - /// takes as input a token chain, the pointer to the trampoline, the pointer - /// to the nested function, the pointer to pass for the 'nest' parameter, a - /// SRCVALUE for the trampoline and another for the nested function - /// (allowing targets to access the original Function*). - /// It produces a token chain as output. - INIT_TRAMPOLINE, - - /// ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic. - /// It takes a pointer to the trampoline and produces a (possibly) new - /// pointer to the same trampoline with platform-specific adjustments - /// applied. The pointer it returns points to an executable block of code. - ADJUST_TRAMPOLINE, - - /// TRAP - Trapping instruction - TRAP, - - /// DEBUGTRAP - Trap intended to get the attention of a debugger. - DEBUGTRAP, - - /// UBSANTRAP - Trap with an immediate describing the kind of sanitizer - /// failure. - UBSANTRAP, - - /// PREFETCH - This corresponds to a prefetch intrinsic. The first operand - /// is the chain. The other operands are the address to prefetch, - /// read / write specifier, locality specifier and instruction / data cache - /// specifier. - PREFETCH, - - /// ARITH_FENCE - This corresponds to a arithmetic fence intrinsic. Both its - /// operand and output are the same floating type. - ARITH_FENCE, - - /// OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) - /// This corresponds to the fence instruction. It takes an input chain, and - /// two integer constants: an AtomicOrdering and a SynchronizationScope. - ATOMIC_FENCE, - - /// Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) - /// This corresponds to "load atomic" instruction. - ATOMIC_LOAD, - - /// OUTCHAIN = ATOMIC_STORE(INCHAIN, ptr, val) - /// This corresponds to "store atomic" instruction. - ATOMIC_STORE, - - /// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) - /// For double-word atomic operations: - /// ValLo, ValHi, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmpLo, cmpHi, - /// swapLo, swapHi) - /// This corresponds to the cmpxchg instruction. - ATOMIC_CMP_SWAP, - - /// Val, Success, OUTCHAIN - /// = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) - /// N.b. this is still a strong cmpxchg operation, so - /// Success == "Val == cmp". - ATOMIC_CMP_SWAP_WITH_SUCCESS, - - /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) - /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) - /// For double-word atomic operations: - /// ValLo, ValHi, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amtLo, amtHi) - /// ValLo, ValHi, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amtLo, amtHi) - /// These correspond to the atomicrmw instruction. - ATOMIC_SWAP, - ATOMIC_LOAD_ADD, - ATOMIC_LOAD_SUB, - ATOMIC_LOAD_AND, - ATOMIC_LOAD_CLR, - ATOMIC_LOAD_OR, - ATOMIC_LOAD_XOR, - ATOMIC_LOAD_NAND, - ATOMIC_LOAD_MIN, - ATOMIC_LOAD_MAX, - ATOMIC_LOAD_UMIN, - ATOMIC_LOAD_UMAX, - ATOMIC_LOAD_FADD, - ATOMIC_LOAD_FSUB, - - // Masked load and store - consecutive vector load and store operations - // with additional mask operand that prevents memory accesses to the - // masked-off lanes. - // - // Val, OutChain = MLOAD(BasePtr, Mask, PassThru) - // OutChain = MSTORE(Value, BasePtr, Mask) - MLOAD, - MSTORE, - - // Masked gather and scatter - load and store operations for a vector of - // random addresses with additional mask operand that prevents memory - // accesses to the masked-off lanes. - // - // Val, OutChain = GATHER(InChain, PassThru, Mask, BasePtr, Index, Scale) - // OutChain = SCATTER(InChain, Value, Mask, BasePtr, Index, Scale) - // - // The Index operand can have more vector elements than the other operands - // due to type legalization. The extra elements are ignored. - MGATHER, - MSCATTER, - - /// This corresponds to the llvm.lifetime.* intrinsics. The first operand - /// is the chain and the second operand is the alloca pointer. - LIFETIME_START, - LIFETIME_END, - - /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the - /// beginning and end of GC transition sequence, and carry arbitrary - /// information that target might need for lowering. The first operand is - /// a chain, the rest are specified by the target and not touched by the DAG - /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be - /// nested. - GC_TRANSITION_START, - GC_TRANSITION_END, - - /// GET_DYNAMIC_AREA_OFFSET - get offset from native SP to the address of - /// the most recent dynamic alloca. For most targets that would be 0, but - /// for some others (e.g. PowerPC, PowerPC64) that would be compile-time - /// known nonzero constant. The only operand here is the chain. - GET_DYNAMIC_AREA_OFFSET, - - /// Pseudo probe for AutoFDO, as a place holder in a basic block to improve - /// the sample counts quality. - PSEUDO_PROBE, - - /// VSCALE(IMM) - Returns the runtime scaling factor used to calculate the - /// number of elements within a scalable vector. IMM is a constant integer - /// multiplier that is applied to the runtime value. - VSCALE, - - /// Generic reduction nodes. These nodes represent horizontal vector - /// reduction operations, producing a scalar result. - /// The SEQ variants perform reductions in sequential order. The first - /// operand is an initial scalar accumulator value, and the second operand - /// is the vector to reduce. - /// E.g. RES = VECREDUCE_SEQ_FADD f32 ACC, <4 x f32> SRC_VEC - /// ... is equivalent to - /// RES = (((ACC + SRC_VEC[0]) + SRC_VEC[1]) + SRC_VEC[2]) + SRC_VEC[3] - VECREDUCE_SEQ_FADD, - VECREDUCE_SEQ_FMUL, - - /// These reductions have relaxed evaluation order semantics, and have a - /// single vector operand. The order of evaluation is unspecified. For - /// pow-of-2 vectors, one valid legalizer expansion is to use a tree - /// reduction, i.e.: - /// For RES = VECREDUCE_FADD <8 x f16> SRC_VEC - /// PART_RDX = FADD SRC_VEC[0:3], SRC_VEC[4:7] - /// PART_RDX2 = FADD PART_RDX[0:1], PART_RDX[2:3] - /// RES = FADD PART_RDX2[0], PART_RDX2[1] - /// For non-pow-2 vectors, this can be computed by extracting each element - /// and performing the operation as if it were scalarized. - VECREDUCE_FADD, - VECREDUCE_FMUL, - /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. - VECREDUCE_FMAX, - VECREDUCE_FMIN, - /// Integer reductions may have a result type larger than the vector element - /// type. However, the reduction is performed using the vector element type - /// and the value in the top bits is unspecified. - VECREDUCE_ADD, - VECREDUCE_MUL, - VECREDUCE_AND, - VECREDUCE_OR, - VECREDUCE_XOR, - VECREDUCE_SMAX, - VECREDUCE_SMIN, - VECREDUCE_UMAX, - VECREDUCE_UMIN, - -// Vector Predication -#define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID, -#include "llvm/IR/VPIntrinsics.def" - - /// BUILTIN_OP_END - This must be the last enum value in this list. - /// The target-specific pre-isel opcode values start here. - BUILTIN_OP_END -}; - -/// FIRST_TARGET_STRICTFP_OPCODE - Target-specific pre-isel operations -/// which cannot raise FP exceptions should be less than this value. -/// Those that do must not be less than this value. -static const int FIRST_TARGET_STRICTFP_OPCODE = BUILTIN_OP_END + 400; - -/// FIRST_TARGET_MEMORY_OPCODE - Target-specific pre-isel operations -/// which do not reference a specific memory location should be less than -/// this value. Those that do must not be less than this value, and can -/// be used with SelectionDAG::getMemIntrinsicNode. -static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END + 500; - -/// Whether this is bitwise logic opcode. -inline bool isBitwiseLogicOp(unsigned Opcode) { - return Opcode == ISD::AND || Opcode == ISD::OR || Opcode == ISD::XOR; -} - -/// Get underlying scalar opcode for VECREDUCE opcode. -/// For example ISD::AND for ISD::VECREDUCE_AND. -NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode); - -/// Whether this is a vector-predicated Opcode. -bool isVPOpcode(unsigned Opcode); - -/// Whether this is a vector-predicated binary operation opcode. -bool isVPBinaryOp(unsigned Opcode); - -/// Whether this is a vector-predicated reduction opcode. -bool isVPReduction(unsigned Opcode); - -/// The operand position of the vector mask. -Optional getVPMaskIdx(unsigned Opcode); - -/// The operand position of the explicit vector length parameter. -Optional getVPExplicitVectorLengthIdx(unsigned Opcode); - -//===--------------------------------------------------------------------===// -/// MemIndexedMode enum - This enum defines the load / store indexed -/// addressing modes. -/// -/// UNINDEXED "Normal" load / store. The effective address is already -/// computed and is available in the base pointer. The offset -/// operand is always undefined. In addition to producing a -/// chain, an unindexed load produces one value (result of the -/// load); an unindexed store does not produce a value. -/// -/// PRE_INC Similar to the unindexed mode where the effective address is -/// PRE_DEC the value of the base pointer add / subtract the offset. -/// It considers the computation as being folded into the load / -/// store operation (i.e. the load / store does the address -/// computation as well as performing the memory transaction). -/// The base operand is always undefined. In addition to -/// producing a chain, pre-indexed load produces two values -/// (result of the load and the result of the address -/// computation); a pre-indexed store produces one value (result -/// of the address computation). -/// -/// POST_INC The effective address is the value of the base pointer. The -/// POST_DEC value of the offset operand is then added to / subtracted -/// from the base after memory transaction. In addition to -/// producing a chain, post-indexed load produces two values -/// (the result of the load and the result of the base +/- offset -/// computation); a post-indexed store produces one value (the -/// the result of the base +/- offset computation). -enum MemIndexedMode { UNINDEXED = 0, PRE_INC, PRE_DEC, POST_INC, POST_DEC }; - -static const int LAST_INDEXED_MODE = POST_DEC + 1; - -//===--------------------------------------------------------------------===// -/// MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's -/// index parameter when calculating addresses. -/// -/// SIGNED_SCALED Addr = Base + ((signed)Index * sizeof(element)) -/// SIGNED_UNSCALED Addr = Base + (signed)Index -/// UNSIGNED_SCALED Addr = Base + ((unsigned)Index * sizeof(element)) -/// UNSIGNED_UNSCALED Addr = Base + (unsigned)Index -enum MemIndexType { - SIGNED_SCALED = 0, - SIGNED_UNSCALED, - UNSIGNED_SCALED, - UNSIGNED_UNSCALED -}; - -static const int LAST_MEM_INDEX_TYPE = UNSIGNED_UNSCALED + 1; - -//===--------------------------------------------------------------------===// -/// LoadExtType enum - This enum defines the three variants of LOADEXT -/// (load with extension). -/// -/// SEXTLOAD loads the integer operand and sign extends it to a larger -/// integer result type. -/// ZEXTLOAD loads the integer operand and zero extends it to a larger -/// integer result type. -/// EXTLOAD is used for two things: floating point extending loads and -/// integer extending loads [the top bits are undefined]. -enum LoadExtType { NON_EXTLOAD = 0, EXTLOAD, SEXTLOAD, ZEXTLOAD }; - -static const int LAST_LOADEXT_TYPE = ZEXTLOAD + 1; - -NodeType getExtForLoadExtType(bool IsFP, LoadExtType); - -//===--------------------------------------------------------------------===// -/// ISD::CondCode enum - These are ordered carefully to make the bitfields -/// below work out, when considering SETFALSE (something that never exists -/// dynamically) as 0. "U" -> Unsigned (for integer operands) or Unordered -/// (for floating point), "L" -> Less than, "G" -> Greater than, "E" -> Equal -/// to. If the "N" column is 1, the result of the comparison is undefined if -/// the input is a NAN. -/// -/// All of these (except for the 'always folded ops') should be handled for -/// floating point. For integer, only the SETEQ,SETNE,SETLT,SETLE,SETGT, -/// SETGE,SETULT,SETULE,SETUGT, and SETUGE opcodes are used. -/// -/// Note that these are laid out in a specific order to allow bit-twiddling -/// to transform conditions. -enum CondCode { - // Opcode N U L G E Intuitive operation - SETFALSE, // 0 0 0 0 Always false (always folded) - SETOEQ, // 0 0 0 1 True if ordered and equal - SETOGT, // 0 0 1 0 True if ordered and greater than - SETOGE, // 0 0 1 1 True if ordered and greater than or equal - SETOLT, // 0 1 0 0 True if ordered and less than - SETOLE, // 0 1 0 1 True if ordered and less than or equal - SETONE, // 0 1 1 0 True if ordered and operands are unequal - SETO, // 0 1 1 1 True if ordered (no nans) - SETUO, // 1 0 0 0 True if unordered: isnan(X) | isnan(Y) - SETUEQ, // 1 0 0 1 True if unordered or equal - SETUGT, // 1 0 1 0 True if unordered or greater than - SETUGE, // 1 0 1 1 True if unordered, greater than, or equal - SETULT, // 1 1 0 0 True if unordered or less than - SETULE, // 1 1 0 1 True if unordered, less than, or equal - SETUNE, // 1 1 1 0 True if unordered or not equal - SETTRUE, // 1 1 1 1 Always true (always folded) - // Don't care operations: undefined if the input is a nan. - SETFALSE2, // 1 X 0 0 0 Always false (always folded) - SETEQ, // 1 X 0 0 1 True if equal - SETGT, // 1 X 0 1 0 True if greater than - SETGE, // 1 X 0 1 1 True if greater than or equal - SETLT, // 1 X 1 0 0 True if less than - SETLE, // 1 X 1 0 1 True if less than or equal - SETNE, // 1 X 1 1 0 True if not equal - SETTRUE2, // 1 X 1 1 1 Always true (always folded) - - SETCC_INVALID // Marker value. -}; - -/// Return true if this is a setcc instruction that performs a signed -/// comparison when used with integer operands. -inline bool isSignedIntSetCC(CondCode Code) { - return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE; -} - -/// Return true if this is a setcc instruction that performs an unsigned -/// comparison when used with integer operands. -inline bool isUnsignedIntSetCC(CondCode Code) { - return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; -} - -/// Return true if this is a setcc instruction that performs an equality -/// comparison when used with integer operands. -inline bool isIntEqualitySetCC(CondCode Code) { - return Code == SETEQ || Code == SETNE; -} - -/// Return true if the specified condition returns true if the two operands to -/// the condition are equal. Note that if one of the two operands is a NaN, -/// this value is meaningless. -inline bool isTrueWhenEqual(CondCode Cond) { return ((int)Cond & 1) != 0; } - -/// This function returns 0 if the condition is always false if an operand is -/// a NaN, 1 if the condition is always true if the operand is a NaN, and 2 if -/// the condition is undefined if the operand is a NaN. -inline unsigned getUnorderedFlavor(CondCode Cond) { - return ((int)Cond >> 3) & 3; -} - -/// Return the operation corresponding to !(X op Y), where 'op' is a valid -/// SetCC operation. -CondCode getSetCCInverse(CondCode Operation, EVT Type); - -namespace GlobalISel { -/// Return the operation corresponding to !(X op Y), where 'op' is a valid -/// SetCC operation. The U bit of the condition code has different meanings -/// between floating point and integer comparisons and LLT's don't provide -/// this distinction. As such we need to be told whether the comparison is -/// floating point or integer-like. Pointers should use integer-like -/// comparisons. -CondCode getSetCCInverse(CondCode Operation, bool isIntegerLike); -} // end namespace GlobalISel - -/// Return the operation corresponding to (Y op X) when given the operation -/// for (X op Y). -CondCode getSetCCSwappedOperands(CondCode Operation); - -/// Return the result of a logical OR between different comparisons of -/// identical values: ((X op1 Y) | (X op2 Y)). This function returns -/// SETCC_INVALID if it is not possible to represent the resultant comparison. -CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, EVT Type); - -/// Return the result of a logical AND between different comparisons of -/// identical values: ((X op1 Y) & (X op2 Y)). This function returns -/// SETCC_INVALID if it is not possible to represent the resultant comparison. -CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, EVT Type); - -} // namespace ISD - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/IndirectThunks.h b/suite/synctools/tablegen/include/llvm/CodeGen/IndirectThunks.h deleted file mode 100644 index a2cdd0a9e9..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/IndirectThunks.h +++ /dev/null @@ -1,115 +0,0 @@ -//===---- IndirectThunks.h - Indirect Thunk Base Class ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Contains a base class for Passes that inject an MI thunk. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_INDIRECTTHUNKS_H -#define LLVM_CODEGEN_INDIRECTTHUNKS_H - -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" - -namespace llvm { - -template class ThunkInserter { - Derived &getDerived() { return *static_cast(this); } - -protected: - bool InsertedThunks; - void doInitialization(Module &M) {} - void createThunkFunction(MachineModuleInfo &MMI, StringRef Name, - bool Comdat = true); - -public: - void init(Module &M) { - InsertedThunks = false; - getDerived().doInitialization(M); - } - // return `true` if `MMI` or `MF` was modified - bool run(MachineModuleInfo &MMI, MachineFunction &MF); -}; - -template -void ThunkInserter::createThunkFunction(MachineModuleInfo &MMI, - StringRef Name, bool Comdat) { - assert(Name.startswith(getDerived().getThunkPrefix()) && - "Created a thunk with an unexpected prefix!"); - - Module &M = const_cast(*MMI.getModule()); - LLVMContext &Ctx = M.getContext(); - auto Type = FunctionType::get(Type::getVoidTy(Ctx), false); - Function *F = Function::Create(Type, - Comdat ? GlobalValue::LinkOnceODRLinkage - : GlobalValue::InternalLinkage, - Name, &M); - if (Comdat) { - F->setVisibility(GlobalValue::HiddenVisibility); - F->setComdat(M.getOrInsertComdat(Name)); - } - - // Add Attributes so that we don't create a frame, unwind information, or - // inline. - AttrBuilder B(Ctx); - B.addAttribute(llvm::Attribute::NoUnwind); - B.addAttribute(llvm::Attribute::Naked); - F->addFnAttrs(B); - - // Populate our function a bit so that we can verify. - BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F); - IRBuilder<> Builder(Entry); - - Builder.CreateRetVoid(); - - // MachineFunctions aren't created automatically for the IR-level constructs - // we already made. Create them and insert them into the module. - MachineFunction &MF = MMI.getOrCreateMachineFunction(*F); - // A MachineBasicBlock must not be created for the Entry block; code - // generation from an empty naked function in C source code also does not - // generate one. At least GlobalISel asserts if this invariant isn't - // respected. - - // Set MF properties. We never use vregs... - MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); -} - -template -bool ThunkInserter::run(MachineModuleInfo &MMI, MachineFunction &MF) { - // If MF is not a thunk, check to see if we need to insert a thunk. - if (!MF.getName().startswith(getDerived().getThunkPrefix())) { - // If we've already inserted a thunk, nothing else to do. - if (InsertedThunks) - return false; - - // Only add a thunk if one of the functions has the corresponding feature - // enabled in its subtarget, and doesn't enable external thunks. - // FIXME: Conditionalize on indirect calls so we don't emit a thunk when - // nothing will end up calling it. - // FIXME: It's a little silly to look at every function just to enumerate - // the subtargets, but eventually we'll want to look at them for indirect - // calls, so maybe this is OK. - if (!getDerived().mayUseThunk(MF)) - return false; - - getDerived().insertThunks(MMI); - InsertedThunks = true; - return true; - } - - // If this *is* a thunk function, we need to populate it with the correct MI. - getDerived().populateThunk(MF); - return true; -} - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/IntrinsicLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/IntrinsicLowering.h deleted file mode 100644 index 06512f2dc5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/IntrinsicLowering.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the IntrinsicLowering interface. This interface allows -// addition of domain-specific or front-end specific intrinsics to LLVM without -// having to modify all of the C backend or interpreter. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_INTRINSICLOWERING_H -#define LLVM_CODEGEN_INTRINSICLOWERING_H - -#include "llvm/IR/Intrinsics.h" - -namespace llvm { -class CallInst; -class DataLayout; - -class IntrinsicLowering { - const DataLayout &DL; - - bool Warned = false; - -public: - explicit IntrinsicLowering(const DataLayout &DL) : DL(DL) {} - - /// Replace a call to the specified intrinsic function. - /// If an intrinsic function must be implemented by the code generator - /// (such as va_start), this function should print a message and abort. - /// - /// Otherwise, if an intrinsic function call can be lowered, the code to - /// implement it (often a call to a non-intrinsic function) is inserted - /// _after_ the call instruction and the call is deleted. The caller must - /// be capable of handling this kind of change. - void LowerIntrinsicCall(CallInst *CI); - - /// Try to replace a call instruction with a call to a bswap intrinsic. Return - /// false if the call is not a simple integer bswap. - static bool LowerToByteSwap(CallInst *CI); -}; -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LatencyPriorityQueue.h b/suite/synctools/tablegen/include/llvm/CodeGen/LatencyPriorityQueue.h deleted file mode 100644 index 95f4c64735..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LatencyPriorityQueue.h +++ /dev/null @@ -1,102 +0,0 @@ -//===---- LatencyPriorityQueue.h - A latency-oriented priority queue ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the LatencyPriorityQueue class, which is a -// SchedulingPriorityQueue that schedules using latency information to -// reduce the length of the critical path through the basic block. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H -#define LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H - -#include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/Config/llvm-config.h" - -namespace llvm { - class LatencyPriorityQueue; - - /// Sorting functions for the Available queue. - struct latency_sort { - LatencyPriorityQueue *PQ; - explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} - - bool operator()(const SUnit* LHS, const SUnit* RHS) const; - }; - - class LatencyPriorityQueue : public SchedulingPriorityQueue { - // SUnits - The SUnits for the current graph. - std::vector *SUnits; - - /// NumNodesSolelyBlocking - This vector contains, for every node in the - /// Queue, the number of nodes that the node is the sole unscheduled - /// predecessor for. This is used as a tie-breaker heuristic for better - /// mobility. - std::vector NumNodesSolelyBlocking; - - /// Queue - The queue. - std::vector Queue; - latency_sort Picker; - - public: - LatencyPriorityQueue() : Picker(this) { - } - - bool isBottomUp() const override { return false; } - - void initNodes(std::vector &sunits) override { - SUnits = &sunits; - NumNodesSolelyBlocking.resize(SUnits->size(), 0); - } - - void addNode(const SUnit *SU) override { - NumNodesSolelyBlocking.resize(SUnits->size(), 0); - } - - void updateNode(const SUnit *SU) override { - } - - void releaseState() override { - SUnits = nullptr; - } - - unsigned getLatency(unsigned NodeNum) const { - assert(NodeNum < (*SUnits).size()); - return (*SUnits)[NodeNum].getHeight(); - } - - unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { - assert(NodeNum < NumNodesSolelyBlocking.size()); - return NumNodesSolelyBlocking[NodeNum]; - } - - bool empty() const override { return Queue.empty(); } - - void push(SUnit *U) override; - - SUnit *pop() override; - - void remove(SUnit *SU) override; - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override; -#endif - - // scheduledNode - As nodes are scheduled, we look to see if there are any - // successor nodes that have a single unscheduled predecessor. If so, that - // single predecessor has a higher priority, since scheduling it will make - // the node available. - void scheduledNode(SUnit *SU) override; - -private: - void AdjustPriorityOfUnscheduledPreds(SUnit *SU); - SUnit *getSingleUnscheduledPred(SUnit *SU); - }; -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h deleted file mode 100644 index c692dbc219..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h +++ /dev/null @@ -1,75 +0,0 @@ -///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===// -/// -/// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -/// See https://llvm.org/LICENSE.txt for license information. -/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -/// -///===---------------------------------------------------------------------===// -/// \file -/// This is an alternative analysis pass to MachineBlockFrequencyInfo. The -/// difference is that with this pass the block frequencies are not computed -/// when the analysis pass is executed but rather when the BFI result is -/// explicitly requested by the analysis client. -/// -///===---------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LAZYMACHINEBLOCKFREQUENCYINFO_H -#define LLVM_CODEGEN_LAZYMACHINEBLOCKFREQUENCYINFO_H - -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineLoopInfo.h" - -namespace llvm { -/// This is an alternative analysis pass to MachineBlockFrequencyInfo. -/// The difference is that with this pass, the block frequencies are not -/// computed when the analysis pass is executed but rather when the BFI result -/// is explicitly requested by the analysis client. -/// -/// This works by checking querying if MBFI is available and otherwise -/// generating MBFI on the fly. In this case the passes required for (LI, DT) -/// are also queried before being computed on the fly. -/// -/// Note that it is expected that we wouldn't need this functionality for the -/// new PM since with the new PM, analyses are executed on demand. - -class LazyMachineBlockFrequencyInfoPass : public MachineFunctionPass { -private: - /// If generated on the fly this own the instance. - mutable std::unique_ptr OwnedMBFI; - - /// If generated on the fly this own the instance. - mutable std::unique_ptr OwnedMLI; - - /// If generated on the fly this own the instance. - mutable std::unique_ptr OwnedMDT; - - /// The function. - MachineFunction *MF = nullptr; - - /// Calculate MBFI and all other analyses that's not available and - /// required by BFI. - MachineBlockFrequencyInfo &calculateIfNotAvailable() const; - -public: - static char ID; - - LazyMachineBlockFrequencyInfoPass(); - - /// Compute and return the block frequencies. - MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); } - - /// Compute and return the block frequencies. - const MachineBlockFrequencyInfo &getBFI() const { - return calculateIfNotAvailable(); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &F) override; - void releaseMemory() override; - void print(raw_ostream &OS, const Module *M) const override; -}; -} -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LexicalScopes.h b/suite/synctools/tablegen/include/llvm/CodeGen/LexicalScopes.h deleted file mode 100644 index 0366de8ecb..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LexicalScopes.h +++ /dev/null @@ -1,259 +0,0 @@ -//===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements LexicalScopes analysis. -// -// This pass collects lexical scope information and maps machine instructions -// to respective lexical scopes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LEXICALSCOPES_H -#define LLVM_CODEGEN_LEXICALSCOPES_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include -#include -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MDNode; - -//===----------------------------------------------------------------------===// -/// InsnRange - This is used to track range of instructions with identical -/// lexical scope. -/// -using InsnRange = std::pair; - -//===----------------------------------------------------------------------===// -/// LexicalScope - This class is used to track scope information. -/// -class LexicalScope { -public: - LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, - bool A) - : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) { - assert(D); - assert(D->getSubprogram()->getUnit()->getEmissionKind() != - DICompileUnit::NoDebug && - "Don't build lexical scopes for non-debug locations"); - assert(D->isResolved() && "Expected resolved node"); - assert((!I || I->isResolved()) && "Expected resolved node"); - if (Parent) - Parent->addChild(this); - } - - // Accessors. - LexicalScope *getParent() const { return Parent; } - const MDNode *getDesc() const { return Desc; } - const DILocation *getInlinedAt() const { return InlinedAtLocation; } - const DILocalScope *getScopeNode() const { return Desc; } - bool isAbstractScope() const { return AbstractScope; } - SmallVectorImpl &getChildren() { return Children; } - SmallVectorImpl &getRanges() { return Ranges; } - - /// addChild - Add a child scope. - void addChild(LexicalScope *S) { Children.push_back(S); } - - /// openInsnRange - This scope covers instruction range starting from MI. - void openInsnRange(const MachineInstr *MI) { - if (!FirstInsn) - FirstInsn = MI; - - if (Parent) - Parent->openInsnRange(MI); - } - - /// extendInsnRange - Extend the current instruction range covered by - /// this scope. - void extendInsnRange(const MachineInstr *MI) { - assert(FirstInsn && "MI Range is not open!"); - LastInsn = MI; - if (Parent) - Parent->extendInsnRange(MI); - } - - /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected - /// until now. This is used when a new scope is encountered while walking - /// machine instructions. - void closeInsnRange(LexicalScope *NewScope = nullptr) { - assert(LastInsn && "Last insn missing!"); - Ranges.push_back(InsnRange(FirstInsn, LastInsn)); - FirstInsn = nullptr; - LastInsn = nullptr; - // If Parent dominates NewScope then do not close Parent's instruction - // range. - if (Parent && (!NewScope || !Parent->dominates(NewScope))) - Parent->closeInsnRange(NewScope); - } - - /// dominates - Return true if current scope dominates given lexical scope. - bool dominates(const LexicalScope *S) const { - if (S == this) - return true; - if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) - return true; - return false; - } - - // Depth First Search support to walk and manipulate LexicalScope hierarchy. - unsigned getDFSOut() const { return DFSOut; } - void setDFSOut(unsigned O) { DFSOut = O; } - unsigned getDFSIn() const { return DFSIn; } - void setDFSIn(unsigned I) { DFSIn = I; } - - /// dump - print lexical scope. - void dump(unsigned Indent = 0) const; - -private: - LexicalScope *Parent; // Parent to this scope. - const DILocalScope *Desc; // Debug info descriptor. - const DILocation *InlinedAtLocation; // Location at which this - // scope is inlined. - bool AbstractScope; // Abstract Scope - SmallVector Children; // Scopes defined in scope. - // Contents not owned. - SmallVector Ranges; - - const MachineInstr *LastInsn = nullptr; // Last instruction of this scope. - const MachineInstr *FirstInsn = nullptr; // First instruction of this scope. - unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting. - unsigned DFSOut = 0; -}; - -//===----------------------------------------------------------------------===// -/// LexicalScopes - This class provides interface to collect and use lexical -/// scoping information from machine instruction. -/// -class LexicalScopes { -public: - LexicalScopes() = default; - - /// initialize - Scan machine function and construct lexical scope nest, resets - /// the instance if necessary. - void initialize(const MachineFunction &); - - /// releaseMemory - release memory. - void reset(); - - /// empty - Return true if there is any lexical scope information available. - bool empty() { return CurrentFnLexicalScope == nullptr; } - - /// getCurrentFunctionScope - Return lexical scope for the current function. - LexicalScope *getCurrentFunctionScope() const { - return CurrentFnLexicalScope; - } - - /// getMachineBasicBlocks - Populate given set using machine basic blocks - /// which have machine instructions that belong to lexical scope identified by - /// DebugLoc. - void getMachineBasicBlocks(const DILocation *DL, - SmallPtrSetImpl &MBBs); - - /// Return true if DebugLoc's lexical scope dominates at least one machine - /// instruction's lexical scope in a given machine basic block. - bool dominates(const DILocation *DL, MachineBasicBlock *MBB); - - /// findLexicalScope - Find lexical scope, either regular or inlined, for the - /// given DebugLoc. Return NULL if not found. - LexicalScope *findLexicalScope(const DILocation *DL); - - /// getAbstractScopesList - Return a reference to list of abstract scopes. - ArrayRef getAbstractScopesList() const { - return AbstractScopesList; - } - - /// findAbstractScope - Find an abstract scope or return null. - LexicalScope *findAbstractScope(const DILocalScope *N) { - auto I = AbstractScopeMap.find(N); - return I != AbstractScopeMap.end() ? &I->second : nullptr; - } - - /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. - LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) { - auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); - return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; - } - - /// findLexicalScope - Find regular lexical scope or return null. - LexicalScope *findLexicalScope(const DILocalScope *N) { - auto I = LexicalScopeMap.find(N); - return I != LexicalScopeMap.end() ? &I->second : nullptr; - } - - /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope); - -private: - /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If - /// not available then create new lexical scope. - LexicalScope *getOrCreateLexicalScope(const DILocalScope *Scope, - const DILocation *IA = nullptr); - LexicalScope *getOrCreateLexicalScope(const DILocation *DL) { - return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt()) - : nullptr; - } - - /// getOrCreateRegularScope - Find or create a regular lexical scope. - LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope); - - /// getOrCreateInlinedScope - Find or create an inlined lexical scope. - LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope, - const DILocation *InlinedAt); - - /// extractLexicalScopes - Extract instruction ranges for each lexical scopes - /// for the given machine function. - void extractLexicalScopes(SmallVectorImpl &MIRanges, - DenseMap &M); - void constructScopeNest(LexicalScope *Scope); - void - assignInstructionRanges(SmallVectorImpl &MIRanges, - DenseMap &M); - - const MachineFunction *MF = nullptr; - - /// LexicalScopeMap - Tracks the scopes in the current function. - // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map LexicalScopeMap; - - /// InlinedLexicalScopeMap - Tracks inlined function scopes in current - /// function. - std::unordered_map, - LexicalScope, - pair_hash> - InlinedLexicalScopeMap; - - /// AbstractScopeMap - These scopes are not included LexicalScopeMap. - // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map AbstractScopeMap; - - /// AbstractScopesList - Tracks abstract scopes constructed while processing - /// a function. - SmallVector AbstractScopesList; - - /// CurrentFnLexicalScope - Top level scope for the current function. - /// - LexicalScope *CurrentFnLexicalScope = nullptr; - - /// Map a location to the set of basic blocks it dominates. This is a cache - /// for \ref LexicalScopes::getMachineBasicBlocks results. - using BlockSetT = SmallPtrSet; - DenseMap> DominatedBlocks; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LEXICALSCOPES_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllAsmWriterComponents.h deleted file mode 100644 index c22f9d49f3..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ /dev/null @@ -1,40 +0,0 @@ -//===- llvm/Codegen/LinkAllAsmWriterComponents.h ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header file pulls in all assembler writer related passes for tools like -// llc that need this functionality. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H -#define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H - -#include "llvm/IR/BuiltinGCs.h" -#include - -namespace { - struct ForceAsmWriterLinking { - ForceAsmWriterLinking() { - // We must reference the plug-ins in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char*) -1) - return; - - llvm::linkOcamlGCPrinter(); - llvm::linkErlangGCPrinter(); - - } - } ForceAsmWriterLinking; // Force link by creating a global definition. -} - -#endif // LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllCodegenComponents.h b/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllCodegenComponents.h deleted file mode 100644 index d615a5db45..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ /dev/null @@ -1,57 +0,0 @@ -//===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header file pulls in all codegen related passes for tools like lli and -// llc that need this functionality. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H -#define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H - -#include "llvm/IR/BuiltinGCs.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Target/TargetMachine.h" -#include - -namespace { - struct ForceCodegenLinking { - ForceCodegenLinking() { - // We must reference the passes in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char*) -1) - return; - - (void) llvm::createFastRegisterAllocator(); - (void) llvm::createBasicRegisterAllocator(); - (void) llvm::createGreedyRegisterAllocator(); - (void) llvm::createDefaultPBQPRegisterAllocator(); - - llvm::linkAllBuiltinGCs(); - - (void) llvm::createBURRListDAGScheduler(nullptr, - llvm::CodeGenOpt::Default); - (void) llvm::createSourceListDAGScheduler(nullptr, - llvm::CodeGenOpt::Default); - (void) llvm::createHybridListDAGScheduler(nullptr, - llvm::CodeGenOpt::Default); - (void) llvm::createFastDAGScheduler(nullptr, llvm::CodeGenOpt::Default); - (void) llvm::createDefaultScheduler(nullptr, llvm::CodeGenOpt::Default); - (void) llvm::createVLIWDAGScheduler(nullptr, llvm::CodeGenOpt::Default); - - } - } ForceCodegenLinking; // Force link by creating a global definition. -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveInterval.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveInterval.h deleted file mode 100644 index 7de2e42f26..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveInterval.h +++ /dev/null @@ -1,1017 +0,0 @@ -//===- llvm/CodeGen/LiveInterval.h - Interval representation ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the LiveRange and LiveInterval classes. Given some -// numbering of each the machine instructions an interval [i, j) is said to be a -// live range for register v if there is no instruction with number j' >= j -// such that v is live at j' and there is no instruction with number i' < i such -// that v is live at i'. In this implementation ranges can have holes, -// i.e. a range might look like [1,20), [50,65), [1000,1001). Each -// individual segment is represented as an instance of LiveRange::Segment, -// and the whole range is represented as an instance of LiveRange. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEINTERVAL_H -#define LLVM_CODEGEN_LIVEINTERVAL_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IntEqClasses.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/MathExtras.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - - class CoalescerPair; - class LiveIntervals; - class MachineRegisterInfo; - class raw_ostream; - - /// VNInfo - Value Number Information. - /// This class holds information about a machine level values, including - /// definition and use points. - /// - class VNInfo { - public: - using Allocator = BumpPtrAllocator; - - /// The ID number of this value. - unsigned id; - - /// The index of the defining instruction. - SlotIndex def; - - /// VNInfo constructor. - VNInfo(unsigned i, SlotIndex d) : id(i), def(d) {} - - /// VNInfo constructor, copies values from orig, except for the value number. - VNInfo(unsigned i, const VNInfo &orig) : id(i), def(orig.def) {} - - /// Copy from the parameter into this VNInfo. - void copyFrom(VNInfo &src) { - def = src.def; - } - - /// Returns true if this value is defined by a PHI instruction (or was, - /// PHI instructions may have been eliminated). - /// PHI-defs begin at a block boundary, all other defs begin at register or - /// EC slots. - bool isPHIDef() const { return def.isBlock(); } - - /// Returns true if this value is unused. - bool isUnused() const { return !def.isValid(); } - - /// Mark this value as unused. - void markUnused() { def = SlotIndex(); } - }; - - /// Result of a LiveRange query. This class hides the implementation details - /// of live ranges, and it should be used as the primary interface for - /// examining live ranges around instructions. - class LiveQueryResult { - VNInfo *const EarlyVal; - VNInfo *const LateVal; - const SlotIndex EndPoint; - const bool Kill; - - public: - LiveQueryResult(VNInfo *EarlyVal, VNInfo *LateVal, SlotIndex EndPoint, - bool Kill) - : EarlyVal(EarlyVal), LateVal(LateVal), EndPoint(EndPoint), Kill(Kill) - {} - - /// Return the value that is live-in to the instruction. This is the value - /// that will be read by the instruction's use operands. Return NULL if no - /// value is live-in. - VNInfo *valueIn() const { - return EarlyVal; - } - - /// Return true if the live-in value is killed by this instruction. This - /// means that either the live range ends at the instruction, or it changes - /// value. - bool isKill() const { - return Kill; - } - - /// Return true if this instruction has a dead def. - bool isDeadDef() const { - return EndPoint.isDead(); - } - - /// Return the value leaving the instruction, if any. This can be a - /// live-through value, or a live def. A dead def returns NULL. - VNInfo *valueOut() const { - return isDeadDef() ? nullptr : LateVal; - } - - /// Returns the value alive at the end of the instruction, if any. This can - /// be a live-through value, a live def or a dead def. - VNInfo *valueOutOrDead() const { - return LateVal; - } - - /// Return the value defined by this instruction, if any. This includes - /// dead defs, it is the value created by the instruction's def operands. - VNInfo *valueDefined() const { - return EarlyVal == LateVal ? nullptr : LateVal; - } - - /// Return the end point of the last live range segment to interact with - /// the instruction, if any. - /// - /// The end point is an invalid SlotIndex only if the live range doesn't - /// intersect the instruction at all. - /// - /// The end point may be at or past the end of the instruction's basic - /// block. That means the value was live out of the block. - SlotIndex endPoint() const { - return EndPoint; - } - }; - - /// This class represents the liveness of a register, stack slot, etc. - /// It manages an ordered list of Segment objects. - /// The Segments are organized in a static single assignment form: At places - /// where a new value is defined or different values reach a CFG join a new - /// segment with a new value number is used. - class LiveRange { - public: - /// This represents a simple continuous liveness interval for a value. - /// The start point is inclusive, the end point exclusive. These intervals - /// are rendered as [start,end). - struct Segment { - SlotIndex start; // Start point of the interval (inclusive) - SlotIndex end; // End point of the interval (exclusive) - VNInfo *valno = nullptr; // identifier for the value contained in this - // segment. - - Segment() = default; - - Segment(SlotIndex S, SlotIndex E, VNInfo *V) - : start(S), end(E), valno(V) { - assert(S < E && "Cannot create empty or backwards segment"); - } - - /// Return true if the index is covered by this segment. - bool contains(SlotIndex I) const { - return start <= I && I < end; - } - - /// Return true if the given interval, [S, E), is covered by this segment. - bool containsInterval(SlotIndex S, SlotIndex E) const { - assert((S < E) && "Backwards interval?"); - return (start <= S && S < end) && (start < E && E <= end); - } - - bool operator<(const Segment &Other) const { - return std::tie(start, end) < std::tie(Other.start, Other.end); - } - bool operator==(const Segment &Other) const { - return start == Other.start && end == Other.end; - } - - bool operator!=(const Segment &Other) const { - return !(*this == Other); - } - - void dump() const; - }; - - using Segments = SmallVector; - using VNInfoList = SmallVector; - - Segments segments; // the liveness segments - VNInfoList valnos; // value#'s - - // The segment set is used temporarily to accelerate initial computation - // of live ranges of physical registers in computeRegUnitRange. - // After that the set is flushed to the segment vector and deleted. - using SegmentSet = std::set; - std::unique_ptr segmentSet; - - using iterator = Segments::iterator; - using const_iterator = Segments::const_iterator; - - iterator begin() { return segments.begin(); } - iterator end() { return segments.end(); } - - const_iterator begin() const { return segments.begin(); } - const_iterator end() const { return segments.end(); } - - using vni_iterator = VNInfoList::iterator; - using const_vni_iterator = VNInfoList::const_iterator; - - vni_iterator vni_begin() { return valnos.begin(); } - vni_iterator vni_end() { return valnos.end(); } - - const_vni_iterator vni_begin() const { return valnos.begin(); } - const_vni_iterator vni_end() const { return valnos.end(); } - - /// Constructs a new LiveRange object. - LiveRange(bool UseSegmentSet = false) - : segmentSet(UseSegmentSet ? std::make_unique() - : nullptr) {} - - /// Constructs a new LiveRange object by copying segments and valnos from - /// another LiveRange. - LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) { - assert(Other.segmentSet == nullptr && - "Copying of LiveRanges with active SegmentSets is not supported"); - assign(Other, Allocator); - } - - /// Copies values numbers and live segments from \p Other into this range. - void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) { - if (this == &Other) - return; - - assert(Other.segmentSet == nullptr && - "Copying of LiveRanges with active SegmentSets is not supported"); - // Duplicate valnos. - for (const VNInfo *VNI : Other.valnos) - createValueCopy(VNI, Allocator); - // Now we can copy segments and remap their valnos. - for (const Segment &S : Other.segments) - segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); - } - - /// advanceTo - Advance the specified iterator to point to the Segment - /// containing the specified position, or end() if the position is past the - /// end of the range. If no Segment contains this position, but the - /// position is in a hole, this method returns an iterator pointing to the - /// Segment immediately after the hole. - iterator advanceTo(iterator I, SlotIndex Pos) { - assert(I != end()); - if (Pos >= endIndex()) - return end(); - while (I->end <= Pos) ++I; - return I; - } - - const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { - assert(I != end()); - if (Pos >= endIndex()) - return end(); - while (I->end <= Pos) ++I; - return I; - } - - /// find - Return an iterator pointing to the first segment that ends after - /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster - /// when searching large ranges. - /// - /// If Pos is contained in a Segment, that segment is returned. - /// If Pos is in a hole, the following Segment is returned. - /// If Pos is beyond endIndex, end() is returned. - iterator find(SlotIndex Pos); - - const_iterator find(SlotIndex Pos) const { - return const_cast(this)->find(Pos); - } - - void clear() { - valnos.clear(); - segments.clear(); - } - - size_t size() const { - return segments.size(); - } - - bool hasAtLeastOneValue() const { return !valnos.empty(); } - - bool containsOneValue() const { return valnos.size() == 1; } - - unsigned getNumValNums() const { return (unsigned)valnos.size(); } - - /// getValNumInfo - Returns pointer to the specified val#. - /// - inline VNInfo *getValNumInfo(unsigned ValNo) { - return valnos[ValNo]; - } - inline const VNInfo *getValNumInfo(unsigned ValNo) const { - return valnos[ValNo]; - } - - /// containsValue - Returns true if VNI belongs to this range. - bool containsValue(const VNInfo *VNI) const { - return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id); - } - - /// getNextValue - Create a new value number and return it. MIIdx specifies - /// the instruction that defines the value number. - VNInfo *getNextValue(SlotIndex def, VNInfo::Allocator &VNInfoAllocator) { - VNInfo *VNI = - new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), def); - valnos.push_back(VNI); - return VNI; - } - - /// createDeadDef - Make sure the range has a value defined at Def. - /// If one already exists, return it. Otherwise allocate a new value and - /// add liveness for a dead def. - VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNIAlloc); - - /// Create a def of value @p VNI. Return @p VNI. If there already exists - /// a definition at VNI->def, the value defined there must be @p VNI. - VNInfo *createDeadDef(VNInfo *VNI); - - /// Create a copy of the given value. The new value will be identical except - /// for the Value number. - VNInfo *createValueCopy(const VNInfo *orig, - VNInfo::Allocator &VNInfoAllocator) { - VNInfo *VNI = - new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), *orig); - valnos.push_back(VNI); - return VNI; - } - - /// RenumberValues - Renumber all values in order of appearance and remove - /// unused values. - void RenumberValues(); - - /// MergeValueNumberInto - This method is called when two value numbers - /// are found to be equivalent. This eliminates V1, replacing all - /// segments with the V1 value number with the V2 value number. This can - /// cause merging of V1/V2 values numbers and compaction of the value space. - VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); - - /// Merge all of the live segments of a specific val# in RHS into this live - /// range as the specified value number. The segments in RHS are allowed - /// to overlap with segments in the current range, it will replace the - /// value numbers of the overlapped live segments with the specified value - /// number. - void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo); - - /// MergeValueInAsValue - Merge all of the segments of a specific val# - /// in RHS into this live range as the specified value number. - /// The segments in RHS are allowed to overlap with segments in the - /// current range, but only if the overlapping segments have the - /// specified value number. - void MergeValueInAsValue(const LiveRange &RHS, - const VNInfo *RHSValNo, VNInfo *LHSValNo); - - bool empty() const { return segments.empty(); } - - /// beginIndex - Return the lowest numbered slot covered. - SlotIndex beginIndex() const { - assert(!empty() && "Call to beginIndex() on empty range."); - return segments.front().start; - } - - /// endNumber - return the maximum point of the range of the whole, - /// exclusive. - SlotIndex endIndex() const { - assert(!empty() && "Call to endIndex() on empty range."); - return segments.back().end; - } - - bool expiredAt(SlotIndex index) const { - return index >= endIndex(); - } - - bool liveAt(SlotIndex index) const { - const_iterator r = find(index); - return r != end() && r->start <= index; - } - - /// Return the segment that contains the specified index, or null if there - /// is none. - const Segment *getSegmentContaining(SlotIndex Idx) const { - const_iterator I = FindSegmentContaining(Idx); - return I == end() ? nullptr : &*I; - } - - /// Return the live segment that contains the specified index, or null if - /// there is none. - Segment *getSegmentContaining(SlotIndex Idx) { - iterator I = FindSegmentContaining(Idx); - return I == end() ? nullptr : &*I; - } - - /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. - VNInfo *getVNInfoAt(SlotIndex Idx) const { - const_iterator I = FindSegmentContaining(Idx); - return I == end() ? nullptr : I->valno; - } - - /// getVNInfoBefore - Return the VNInfo that is live up to but not - /// necessarily including Idx, or NULL. Use this to find the reaching def - /// used by an instruction at this SlotIndex position. - VNInfo *getVNInfoBefore(SlotIndex Idx) const { - const_iterator I = FindSegmentContaining(Idx.getPrevSlot()); - return I == end() ? nullptr : I->valno; - } - - /// Return an iterator to the segment that contains the specified index, or - /// end() if there is none. - iterator FindSegmentContaining(SlotIndex Idx) { - iterator I = find(Idx); - return I != end() && I->start <= Idx ? I : end(); - } - - const_iterator FindSegmentContaining(SlotIndex Idx) const { - const_iterator I = find(Idx); - return I != end() && I->start <= Idx ? I : end(); - } - - /// overlaps - Return true if the intersection of the two live ranges is - /// not empty. - bool overlaps(const LiveRange &other) const { - if (other.empty()) - return false; - return overlapsFrom(other, other.begin()); - } - - /// overlaps - Return true if the two ranges have overlapping segments - /// that are not coalescable according to CP. - /// - /// Overlapping segments where one range is defined by a coalescable - /// copy are allowed. - bool overlaps(const LiveRange &Other, const CoalescerPair &CP, - const SlotIndexes&) const; - - /// overlaps - Return true if the live range overlaps an interval specified - /// by [Start, End). - bool overlaps(SlotIndex Start, SlotIndex End) const; - - /// overlapsFrom - Return true if the intersection of the two live ranges - /// is not empty. The specified iterator is a hint that we can begin - /// scanning the Other range starting at I. - bool overlapsFrom(const LiveRange &Other, const_iterator StartPos) const; - - /// Returns true if all segments of the @p Other live range are completely - /// covered by this live range. - /// Adjacent live ranges do not affect the covering:the liverange - /// [1,5](5,10] covers (3,7]. - bool covers(const LiveRange &Other) const; - - /// Add the specified Segment to this range, merging segments as - /// appropriate. This returns an iterator to the inserted segment (which - /// may have grown since it was inserted). - iterator addSegment(Segment S); - - /// Attempt to extend a value defined after @p StartIdx to include @p Use. - /// Both @p StartIdx and @p Use should be in the same basic block. In case - /// of subranges, an extension could be prevented by an explicit "undef" - /// caused by a on a non-overlapping lane. The list of - /// location of such "undefs" should be provided in @p Undefs. - /// The return value is a pair: the first element is VNInfo of the value - /// that was extended (possibly nullptr), the second is a boolean value - /// indicating whether an "undef" was encountered. - /// If this range is live before @p Use in the basic block that starts at - /// @p StartIdx, and there is no intervening "undef", extend it to be live - /// up to @p Use, and return the pair {value, false}. If there is no - /// segment before @p Use and there is no "undef" between @p StartIdx and - /// @p Use, return {nullptr, false}. If there is an "undef" before @p Use, - /// return {nullptr, true}. - std::pair extendInBlock(ArrayRef Undefs, - SlotIndex StartIdx, SlotIndex Kill); - - /// Simplified version of the above "extendInBlock", which assumes that - /// no register lanes are undefined by operands. - /// If this range is live before @p Use in the basic block that starts - /// at @p StartIdx, extend it to be live up to @p Use, and return the - /// value. If there is no segment before @p Use, return nullptr. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); - - /// join - Join two live ranges (this, and other) together. This applies - /// mappings to the value numbers in the LHS/RHS ranges as specified. If - /// the ranges are not joinable, this aborts. - void join(LiveRange &Other, - const int *ValNoAssignments, - const int *RHSValNoAssignments, - SmallVectorImpl &NewVNInfo); - - /// True iff this segment is a single segment that lies between the - /// specified boundaries, exclusively. Vregs live across a backedge are not - /// considered local. The boundaries are expected to lie within an extended - /// basic block, so vregs that are not live out should contain no holes. - bool isLocal(SlotIndex Start, SlotIndex End) const { - return beginIndex() > Start.getBaseIndex() && - endIndex() < End.getBoundaryIndex(); - } - - /// Remove the specified segment from this range. Note that the segment - /// must be a single Segment in its entirety. - void removeSegment(SlotIndex Start, SlotIndex End, - bool RemoveDeadValNo = false); - - void removeSegment(Segment S, bool RemoveDeadValNo = false) { - removeSegment(S.start, S.end, RemoveDeadValNo); - } - - /// Remove segment pointed to by iterator @p I from this range. - iterator removeSegment(iterator I, bool RemoveDeadValNo = false); - - /// Mark \p ValNo for deletion if no segments in this range use it. - void removeValNoIfDead(VNInfo *ValNo); - - /// Query Liveness at Idx. - /// The sub-instruction slot of Idx doesn't matter, only the instruction - /// it refers to is considered. - LiveQueryResult Query(SlotIndex Idx) const { - // Find the segment that enters the instruction. - const_iterator I = find(Idx.getBaseIndex()); - const_iterator E = end(); - if (I == E) - return LiveQueryResult(nullptr, nullptr, SlotIndex(), false); - - // Is this an instruction live-in segment? - // If Idx is the start index of a basic block, include live-in segments - // that start at Idx.getBaseIndex(). - VNInfo *EarlyVal = nullptr; - VNInfo *LateVal = nullptr; - SlotIndex EndPoint; - bool Kill = false; - if (I->start <= Idx.getBaseIndex()) { - EarlyVal = I->valno; - EndPoint = I->end; - // Move to the potentially live-out segment. - if (SlotIndex::isSameInstr(Idx, I->end)) { - Kill = true; - if (++I == E) - return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); - } - // Special case: A PHIDef value can have its def in the middle of a - // segment if the value happens to be live out of the layout - // predecessor. - // Such a value is not live-in. - if (EarlyVal->def == Idx.getBaseIndex()) - EarlyVal = nullptr; - } - // I now points to the segment that may be live-through, or defined by - // this instr. Ignore segments starting after the current instr. - if (!SlotIndex::isEarlierInstr(Idx, I->start)) { - LateVal = I->valno; - EndPoint = I->end; - } - return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); - } - - /// removeValNo - Remove all the segments defined by the specified value#. - /// Also remove the value# from value# list. - void removeValNo(VNInfo *ValNo); - - /// Returns true if the live range is zero length, i.e. no live segments - /// span instructions. It doesn't pay to spill such a range. - bool isZeroLength(SlotIndexes *Indexes) const { - for (const Segment &S : segments) - if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < - S.end.getBaseIndex()) - return false; - return true; - } - - // Returns true if any segment in the live range contains any of the - // provided slot indexes. Slots which occur in holes between - // segments will not cause the function to return true. - bool isLiveAtIndexes(ArrayRef Slots) const; - - bool operator<(const LiveRange& other) const { - const SlotIndex &thisIndex = beginIndex(); - const SlotIndex &otherIndex = other.beginIndex(); - return thisIndex < otherIndex; - } - - /// Returns true if there is an explicit "undef" between @p Begin - /// @p End. - bool isUndefIn(ArrayRef Undefs, SlotIndex Begin, - SlotIndex End) const { - return llvm::any_of(Undefs, [Begin, End](SlotIndex Idx) -> bool { - return Begin <= Idx && Idx < End; - }); - } - - /// Flush segment set into the regular segment vector. - /// The method is to be called after the live range - /// has been created, if use of the segment set was - /// activated in the constructor of the live range. - void flushSegmentSet(); - - /// Stores indexes from the input index sequence R at which this LiveRange - /// is live to the output O iterator. - /// R is a range of _ascending sorted_ _random_ access iterators - /// to the input indexes. Indexes stored at O are ascending sorted so it - /// can be used directly in the subsequent search (for example for - /// subranges). Returns true if found at least one index. - template - bool findIndexesLiveAt(Range &&R, OutputIt O) const { - assert(llvm::is_sorted(R)); - auto Idx = R.begin(), EndIdx = R.end(); - auto Seg = segments.begin(), EndSeg = segments.end(); - bool Found = false; - while (Idx != EndIdx && Seg != EndSeg) { - // if the Seg is lower find first segment that is above Idx using binary - // search - if (Seg->end <= *Idx) { - Seg = std::upper_bound( - ++Seg, EndSeg, *Idx, - [=](std::remove_reference_t V, - const std::remove_reference_t &S) { - return V < S.end; - }); - if (Seg == EndSeg) - break; - } - auto NotLessStart = std::lower_bound(Idx, EndIdx, Seg->start); - if (NotLessStart == EndIdx) - break; - auto NotLessEnd = std::lower_bound(NotLessStart, EndIdx, Seg->end); - if (NotLessEnd != NotLessStart) { - Found = true; - O = std::copy(NotLessStart, NotLessEnd, O); - } - Idx = NotLessEnd; - ++Seg; - } - return Found; - } - - void print(raw_ostream &OS) const; - void dump() const; - - /// Walk the range and assert if any invariants fail to hold. - /// - /// Note that this is a no-op when asserts are disabled. -#ifdef NDEBUG - void verify() const {} -#else - void verify() const; -#endif - - protected: - /// Append a segment to the list of segments. - void append(const LiveRange::Segment S); - - private: - friend class LiveRangeUpdater; - void addSegmentToSet(Segment S); - void markValNoForDeletion(VNInfo *V); - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const LiveRange &LR) { - LR.print(OS); - return OS; - } - - /// LiveInterval - This class represents the liveness of a register, - /// or stack slot. - class LiveInterval : public LiveRange { - public: - using super = LiveRange; - - /// A live range for subregisters. The LaneMask specifies which parts of the - /// super register are covered by the interval. - /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). - class SubRange : public LiveRange { - public: - SubRange *Next = nullptr; - LaneBitmask LaneMask; - - /// Constructs a new SubRange object. - SubRange(LaneBitmask LaneMask) : LaneMask(LaneMask) {} - - /// Constructs a new SubRange object by copying liveness from @p Other. - SubRange(LaneBitmask LaneMask, const LiveRange &Other, - BumpPtrAllocator &Allocator) - : LiveRange(Other, Allocator), LaneMask(LaneMask) {} - - void print(raw_ostream &OS) const; - void dump() const; - }; - - private: - SubRange *SubRanges = nullptr; ///< Single linked list of subregister live - /// ranges. - const Register Reg; // the register or stack slot of this interval. - float Weight = 0.0; // weight of this interval - - public: - Register reg() const { return Reg; } - float weight() const { return Weight; } - void incrementWeight(float Inc) { Weight += Inc; } - void setWeight(float Value) { Weight = Value; } - - LiveInterval(unsigned Reg, float Weight) : Reg(Reg), Weight(Weight) {} - - ~LiveInterval() { - clearSubRanges(); - } - - template - class SingleLinkedListIterator { - T *P; - - public: - SingleLinkedListIterator(T *P) : P(P) {} - - SingleLinkedListIterator &operator++() { - P = P->Next; - return *this; - } - SingleLinkedListIterator operator++(int) { - SingleLinkedListIterator res = *this; - ++*this; - return res; - } - bool operator!=(const SingleLinkedListIterator &Other) const { - return P != Other.operator->(); - } - bool operator==(const SingleLinkedListIterator &Other) const { - return P == Other.operator->(); - } - T &operator*() const { - return *P; - } - T *operator->() const { - return P; - } - }; - - using subrange_iterator = SingleLinkedListIterator; - using const_subrange_iterator = SingleLinkedListIterator; - - subrange_iterator subrange_begin() { - return subrange_iterator(SubRanges); - } - subrange_iterator subrange_end() { - return subrange_iterator(nullptr); - } - - const_subrange_iterator subrange_begin() const { - return const_subrange_iterator(SubRanges); - } - const_subrange_iterator subrange_end() const { - return const_subrange_iterator(nullptr); - } - - iterator_range subranges() { - return make_range(subrange_begin(), subrange_end()); - } - - iterator_range subranges() const { - return make_range(subrange_begin(), subrange_end()); - } - - /// Creates a new empty subregister live range. The range is added at the - /// beginning of the subrange list; subrange iterators stay valid. - SubRange *createSubRange(BumpPtrAllocator &Allocator, - LaneBitmask LaneMask) { - SubRange *Range = new (Allocator) SubRange(LaneMask); - appendSubRange(Range); - return Range; - } - - /// Like createSubRange() but the new range is filled with a copy of the - /// liveness information in @p CopyFrom. - SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, - LaneBitmask LaneMask, - const LiveRange &CopyFrom) { - SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); - appendSubRange(Range); - return Range; - } - - /// Returns true if subregister liveness information is available. - bool hasSubRanges() const { - return SubRanges != nullptr; - } - - /// Removes all subregister liveness information. - void clearSubRanges(); - - /// Removes all subranges without any segments (subranges without segments - /// are not considered valid and should only exist temporarily). - void removeEmptySubRanges(); - - /// getSize - Returns the sum of sizes of all the LiveRange's. - /// - unsigned getSize() const; - - /// isSpillable - Can this interval be spilled? - bool isSpillable() const { return Weight != huge_valf; } - - /// markNotSpillable - Mark interval as not spillable - void markNotSpillable() { Weight = huge_valf; } - - /// For a given lane mask @p LaneMask, compute indexes at which the - /// lane is marked undefined by subregister definitions. - void computeSubRangeUndefs(SmallVectorImpl &Undefs, - LaneBitmask LaneMask, - const MachineRegisterInfo &MRI, - const SlotIndexes &Indexes) const; - - /// Refines the subranges to support \p LaneMask. This may only be called - /// for LI.hasSubrange()==true. Subregister ranges are split or created - /// until \p LaneMask can be matched exactly. \p Mod is executed on the - /// matching subranges. - /// - /// Example: - /// Given an interval with subranges with lanemasks L0F00, L00F0 and - /// L000F, refining for mask L0018. Will split the L00F0 lane into - /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod - /// function will be applied to the L0010 and L0008 subranges. - /// - /// \p Indexes and \p TRI are required to clean up the VNIs that - /// don't define the related lane masks after they get shrunk. E.g., - /// when L000F gets split into L0007 and L0008 maybe only a subset - /// of the VNIs that defined L000F defines L0007. - /// - /// The clean up of the VNIs need to look at the actual instructions - /// to decide what is or is not live at a definition point. If the - /// update of the subranges occurs while the IR does not reflect these - /// changes, \p ComposeSubRegIdx can be used to specify how the - /// definition are going to be rewritten. - /// E.g., let say we want to merge: - /// V1.sub1:<2 x s32> = COPY V2.sub3:<4 x s32> - /// We do that by choosing a class where sub1:<2 x s32> and sub3:<4 x s32> - /// overlap, i.e., by choosing a class where we can find "offset + 1 == 3". - /// Put differently we align V2's sub3 with V1's sub1: - /// V2: sub0 sub1 sub2 sub3 - /// V1: sub0 sub1 - /// - /// This offset will look like a composed subregidx in the class: - /// V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32> - /// => V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32> - /// - /// Now if we didn't rewrite the uses and def of V1, all the checks for V1 - /// need to account for this offset. - /// This happens during coalescing where we update the live-ranges while - /// still having the old IR around because updating the IR on-the-fly - /// would actually clobber some information on how the live-ranges that - /// are being updated look like. - void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, - std::function Apply, - const SlotIndexes &Indexes, - const TargetRegisterInfo &TRI, - unsigned ComposeSubRegIdx = 0); - - bool operator<(const LiveInterval& other) const { - const SlotIndex &thisIndex = beginIndex(); - const SlotIndex &otherIndex = other.beginIndex(); - return std::tie(thisIndex, Reg) < std::tie(otherIndex, other.Reg); - } - - void print(raw_ostream &OS) const; - void dump() const; - - /// Walks the interval and assert if any invariants fail to hold. - /// - /// Note that this is a no-op when asserts are disabled. -#ifdef NDEBUG - void verify(const MachineRegisterInfo *MRI = nullptr) const {} -#else - void verify(const MachineRegisterInfo *MRI = nullptr) const; -#endif - - private: - /// Appends @p Range to SubRanges list. - void appendSubRange(SubRange *Range) { - Range->Next = SubRanges; - SubRanges = Range; - } - - /// Free memory held by SubRange. - void freeSubRange(SubRange *S); - }; - - inline raw_ostream &operator<<(raw_ostream &OS, - const LiveInterval::SubRange &SR) { - SR.print(OS); - return OS; - } - - inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { - LI.print(OS); - return OS; - } - - raw_ostream &operator<<(raw_ostream &OS, const LiveRange::Segment &S); - - inline bool operator<(SlotIndex V, const LiveRange::Segment &S) { - return V < S.start; - } - - inline bool operator<(const LiveRange::Segment &S, SlotIndex V) { - return S.start < V; - } - - /// Helper class for performant LiveRange bulk updates. - /// - /// Calling LiveRange::addSegment() repeatedly can be expensive on large - /// live ranges because segments after the insertion point may need to be - /// shifted. The LiveRangeUpdater class can defer the shifting when adding - /// many segments in order. - /// - /// The LiveRange will be in an invalid state until flush() is called. - class LiveRangeUpdater { - LiveRange *LR; - SlotIndex LastStart; - LiveRange::iterator WriteI; - LiveRange::iterator ReadI; - SmallVector Spills; - void mergeSpills(); - - public: - /// Create a LiveRangeUpdater for adding segments to LR. - /// LR will temporarily be in an invalid state until flush() is called. - LiveRangeUpdater(LiveRange *lr = nullptr) : LR(lr) {} - - ~LiveRangeUpdater() { flush(); } - - /// Add a segment to LR and coalesce when possible, just like - /// LR.addSegment(). Segments should be added in increasing start order for - /// best performance. - void add(LiveRange::Segment); - - void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) { - add(LiveRange::Segment(Start, End, VNI)); - } - - /// Return true if the LR is currently in an invalid state, and flush() - /// needs to be called. - bool isDirty() const { return LastStart.isValid(); } - - /// Flush the updater state to LR so it is valid and contains all added - /// segments. - void flush(); - - /// Select a different destination live range. - void setDest(LiveRange *lr) { - if (LR != lr && isDirty()) - flush(); - LR = lr; - } - - /// Get the current destination live range. - LiveRange *getDest() const { return LR; } - - void dump() const; - void print(raw_ostream&) const; - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const LiveRangeUpdater &X) { - X.print(OS); - return OS; - } - - /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a - /// LiveInterval into equivalence classes of connected components. A - /// LiveInterval that has multiple connected components can be broken into - /// multiple LiveIntervals. - /// - /// Given a LiveInterval that may have multiple connected components, run: - /// - /// unsigned numComps = ConEQ.Classify(LI); - /// if (numComps > 1) { - /// // allocate numComps-1 new LiveIntervals into LIS[1..] - /// ConEQ.Distribute(LIS); - /// } - - class ConnectedVNInfoEqClasses { - LiveIntervals &LIS; - IntEqClasses EqClass; - - public: - explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : LIS(lis) {} - - /// Classify the values in \p LR into connected components. - /// Returns the number of connected components. - unsigned Classify(const LiveRange &LR); - - /// getEqClass - Classify creates equivalence classes numbered 0..N. Return - /// the equivalence class assigned the VNI. - unsigned getEqClass(const VNInfo *VNI) const { return EqClass[VNI->id]; } - - /// Distribute values in \p LI into a separate LiveIntervals - /// for each connected component. LIV must have an empty LiveInterval for - /// each additional connected component. The first connected component is - /// left in \p LI. - void Distribute(LiveInterval &LI, LiveInterval *LIV[], - MachineRegisterInfo &MRI); - }; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEINTERVAL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalCalc.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalCalc.h deleted file mode 100644 index b8d67ef8f4..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalCalc.h +++ /dev/null @@ -1,71 +0,0 @@ -//===- LiveIntervalCalc.h - Calculate live intervals -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The LiveIntervalCalc class is an extension of LiveRangeCalc targeted to the -// computation and modification of the LiveInterval variants of LiveRanges. -// LiveIntervals are meant to track liveness of registers and stack slots and -// LiveIntervalCalc adds to LiveRangeCalc all the machinery required to -// construct the liveness of virtual registers tracked by a LiveInterval. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEINTERVALCALC_H -#define LLVM_CODEGEN_LIVEINTERVALCALC_H - -#include "llvm/CodeGen/LiveRangeCalc.h" - -namespace llvm { - -template class DomTreeNodeBase; - -using MachineDomTreeNode = DomTreeNodeBase; - -class LiveIntervalCalc : public LiveRangeCalc { - /// Extend the live range of @p LR to reach all uses of Reg. - /// - /// If @p LR is a main range, or if @p LI is null, then all uses must be - /// jointly dominated by the definitions from @p LR. If @p LR is a subrange - /// of the live interval @p LI, corresponding to lane mask @p LaneMask, - /// all uses must be jointly dominated by the definitions from @p LR - /// together with definitions of other lanes where @p LR becomes undefined - /// (via operands). - /// If @p LR is a main range, the @p LaneMask should be set to ~0, i.e. - /// LaneBitmask::getAll(). - void extendToUses(LiveRange &LR, Register Reg, LaneBitmask LaneMask, - LiveInterval *LI = nullptr); - -public: - LiveIntervalCalc() = default; - - /// createDeadDefs - Create a dead def in LI for every def operand of Reg. - /// Each instruction defining Reg gets a new VNInfo with a corresponding - /// minimal live range. - void createDeadDefs(LiveRange &LR, Register Reg); - - /// Extend the live range of @p LR to reach all uses of Reg. - /// - /// All uses must be jointly dominated by existing liveness. PHI-defs are - /// inserted as needed to preserve SSA form. - void extendToUses(LiveRange &LR, MCRegister PhysReg) { - extendToUses(LR, PhysReg, LaneBitmask::getAll()); - } - - /// Calculates liveness for the register specified in live interval @p LI. - /// Creates subregister live ranges as needed if subreg liveness tracking is - /// enabled. - void calculate(LiveInterval &LI, bool TrackSubRegs); - - /// For live interval \p LI with correct SubRanges construct matching - /// information for the main live range. Expects the main live range to not - /// have any segments or value numbers. - void constructMainRangeFromSubranges(LiveInterval &LI); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEINTERVALCALC_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalUnion.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalUnion.h deleted file mode 100644 index 3b6a4a379d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervalUnion.h +++ /dev/null @@ -1,201 +0,0 @@ -//===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// LiveIntervalUnion is a union of live segments across multiple live virtual -// registers. This may be used during coalescing to represent a congruence -// class, or during register allocation to model liveness of a physical -// register. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEINTERVALUNION_H -#define LLVM_CODEGEN_LIVEINTERVALUNION_H - -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include -#include - -namespace llvm { - -class raw_ostream; -class TargetRegisterInfo; - -#ifndef NDEBUG -// forward declaration -template class SparseBitVector; - -using LiveVirtRegBitSet = SparseBitVector<128>; -#endif - -/// Union of live intervals that are strong candidates for coalescing into a -/// single register (either physical or virtual depending on the context). We -/// expect the constituent live intervals to be disjoint, although we may -/// eventually make exceptions to handle value-based interference. -class LiveIntervalUnion { - // A set of live virtual register segments that supports fast insertion, - // intersection, and removal. - // Mapping SlotIndex intervals to virtual register numbers. - using LiveSegments = IntervalMap; - -public: - // SegmentIter can advance to the next segment ordered by starting position - // which may belong to a different live virtual register. We also must be able - // to reach the current segment's containing virtual register. - using SegmentIter = LiveSegments::iterator; - - /// Const version of SegmentIter. - using ConstSegmentIter = LiveSegments::const_iterator; - - // LiveIntervalUnions share an external allocator. - using Allocator = LiveSegments::Allocator; - -private: - unsigned Tag = 0; // unique tag for current contents. - LiveSegments Segments; // union of virtual reg segments - -public: - explicit LiveIntervalUnion(Allocator &a) : Segments(a) {} - - // Iterate over all segments in the union of live virtual registers ordered - // by their starting position. - SegmentIter begin() { return Segments.begin(); } - SegmentIter end() { return Segments.end(); } - SegmentIter find(SlotIndex x) { return Segments.find(x); } - ConstSegmentIter begin() const { return Segments.begin(); } - ConstSegmentIter end() const { return Segments.end(); } - ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); } - - bool empty() const { return Segments.empty(); } - SlotIndex startIndex() const { return Segments.start(); } - SlotIndex endIndex() const { return Segments.stop(); } - - // Provide public access to the underlying map to allow overlap iteration. - using Map = LiveSegments; - const Map &getMap() const { return Segments; } - - /// getTag - Return an opaque tag representing the current state of the union. - unsigned getTag() const { return Tag; } - - /// changedSince - Return true if the union change since getTag returned tag. - bool changedSince(unsigned tag) const { return tag != Tag; } - - // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg, const LiveRange &Range); - - // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg, const LiveRange &Range); - - // Remove all inserted virtual registers. - void clear() { Segments.clear(); ++Tag; } - - // Print union, using TRI to translate register names - void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; - -#ifndef NDEBUG - // Verify the live intervals in this union and add them to the visited set. - void verify(LiveVirtRegBitSet& VisitedVRegs); -#endif - - // Get any virtual register that is assign to this physical unit - LiveInterval *getOneVReg() const; - - /// Query interferences between a single live virtual register and a live - /// interval union. - class Query { - const LiveIntervalUnion *LiveUnion = nullptr; - const LiveRange *LR = nullptr; - LiveRange::const_iterator LRI; ///< current position in LR - ConstSegmentIter LiveUnionI; ///< current position in LiveUnion - SmallVector InterferingVRegs; - bool CheckedFirstInterference = false; - bool SeenAllInterferences = false; - unsigned Tag = 0; - unsigned UserTag = 0; - - // Count the virtual registers in this union that interfere with this - // query's live virtual register, up to maxInterferingRegs. - unsigned collectInterferingVRegs(unsigned MaxInterferingRegs); - - // Was this virtual register visited during collectInterferingVRegs? - bool isSeenInterference(LiveInterval *VirtReg) const; - - public: - Query() = default; - Query(const LiveRange &LR, const LiveIntervalUnion &LIU) - : LiveUnion(&LIU), LR(&LR) {} - Query(const Query &) = delete; - Query &operator=(const Query &) = delete; - - void reset(unsigned NewUserTag, const LiveRange &NewLR, - const LiveIntervalUnion &NewLiveUnion) { - LiveUnion = &NewLiveUnion; - LR = &NewLR; - InterferingVRegs.clear(); - CheckedFirstInterference = false; - SeenAllInterferences = false; - Tag = NewLiveUnion.getTag(); - UserTag = NewUserTag; - } - - void init(unsigned NewUserTag, const LiveRange &NewLR, - const LiveIntervalUnion &NewLiveUnion) { - if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion && - !NewLiveUnion.changedSince(Tag)) { - // Retain cached results, e.g. firstInterference. - return; - } - reset(NewUserTag, NewLR, NewLiveUnion); - } - - // Does this live virtual register interfere with the union? - bool checkInterference() { return collectInterferingVRegs(1); } - - // Vector generated by collectInterferingVRegs. - const SmallVectorImpl &interferingVRegs( - unsigned MaxInterferingRegs = std::numeric_limits::max()) { - if (!SeenAllInterferences || MaxInterferingRegs < InterferingVRegs.size()) - collectInterferingVRegs(MaxInterferingRegs); - return InterferingVRegs; - } - }; - - // Array of LiveIntervalUnions. - class Array { - unsigned Size = 0; - LiveIntervalUnion *LIUs = nullptr; - - public: - Array() = default; - ~Array() { clear(); } - - // Initialize the array to have Size entries. - // Reuse an existing allocation if the size matches. - void init(LiveIntervalUnion::Allocator&, unsigned Size); - - unsigned size() const { return Size; } - - void clear(); - - LiveIntervalUnion& operator[](unsigned idx) { - assert(idx < Size && "idx out of bounds"); - return LIUs[idx]; - } - - const LiveIntervalUnion& operator[](unsigned Idx) const { - assert(Idx < Size && "Idx out of bounds"); - return LIUs[Idx]; - } - }; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEINTERVALUNION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervals.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervals.h deleted file mode 100644 index 22d10bb93a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveIntervals.h +++ /dev/null @@ -1,494 +0,0 @@ -//===- LiveIntervals.h - Live Interval Analysis -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file implements the LiveInterval analysis pass. Given some -/// numbering of each the machine instructions (in this implementation depth-first -/// order) an interval [i, j) is said to be a live interval for register v if -/// there is no instruction with number j' > j such that v is live at j' and -/// there is no instruction with number i' < i such that v is live at i'. In -/// this implementation intervals can have holes, i.e. an interval might look -/// like [1,20), [50,65), [1000,1001). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEINTERVALS_H -#define LLVM_CODEGEN_LIVEINTERVALS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include - -namespace llvm { - -extern cl::opt UseSegmentSetForPhysRegs; - -class AAResults; -class BitVector; -class LiveIntervalCalc; -class MachineBlockFrequencyInfo; -class MachineDominatorTree; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class raw_ostream; -class TargetInstrInfo; -class VirtRegMap; - - class LiveIntervals : public MachineFunctionPass { - MachineFunction* MF; - MachineRegisterInfo* MRI; - const TargetRegisterInfo* TRI; - const TargetInstrInfo* TII; - AAResults *AA; - SlotIndexes* Indexes; - MachineDominatorTree *DomTree = nullptr; - LiveIntervalCalc *LICalc = nullptr; - - /// Special pool allocator for VNInfo's (LiveInterval val#). - VNInfo::Allocator VNInfoAllocator; - - /// Live interval pointers for all the virtual registers. - IndexedMap VirtRegIntervals; - - /// Sorted list of instructions with register mask operands. Always use the - /// 'r' slot, RegMasks are normal clobbers, not early clobbers. - SmallVector RegMaskSlots; - - /// This vector is parallel to RegMaskSlots, it holds a pointer to the - /// corresponding register mask. This pointer can be recomputed as: - /// - /// MI = Indexes->getInstructionFromIndex(RegMaskSlot[N]); - /// unsigned OpNum = findRegMaskOperand(MI); - /// RegMaskBits[N] = MI->getOperand(OpNum).getRegMask(); - /// - /// This is kept in a separate vector partly because some standard - /// libraries don't support lower_bound() with mixed objects, partly to - /// improve locality when searching in RegMaskSlots. - /// Also see the comment in LiveInterval::find(). - SmallVector RegMaskBits; - - /// For each basic block number, keep (begin, size) pairs indexing into the - /// RegMaskSlots and RegMaskBits arrays. - /// Note that basic block numbers may not be layout contiguous, that's why - /// we can't just keep track of the first register mask in each basic - /// block. - SmallVector, 8> RegMaskBlocks; - - /// Keeps a live range set for each register unit to track fixed physreg - /// interference. - SmallVector RegUnitRanges; - - public: - static char ID; - - LiveIntervals(); - ~LiveIntervals() override; - - /// Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, - const MachineBlockFrequencyInfo *MBFI, - const MachineInstr &MI); - - /// Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, - const MachineBlockFrequencyInfo *MBFI, - const MachineBasicBlock *MBB); - - LiveInterval &getInterval(Register Reg) { - if (hasInterval(Reg)) - return *VirtRegIntervals[Reg.id()]; - - return createAndComputeVirtRegInterval(Reg); - } - - const LiveInterval &getInterval(Register Reg) const { - return const_cast(this)->getInterval(Reg); - } - - bool hasInterval(Register Reg) const { - return VirtRegIntervals.inBounds(Reg.id()) && - VirtRegIntervals[Reg.id()]; - } - - /// Interval creation. - LiveInterval &createEmptyInterval(Register Reg) { - assert(!hasInterval(Reg) && "Interval already exists!"); - VirtRegIntervals.grow(Reg.id()); - VirtRegIntervals[Reg.id()] = createInterval(Reg); - return *VirtRegIntervals[Reg.id()]; - } - - LiveInterval &createAndComputeVirtRegInterval(Register Reg) { - LiveInterval &LI = createEmptyInterval(Reg); - computeVirtRegInterval(LI); - return LI; - } - - /// Interval removal. - void removeInterval(Register Reg) { - delete VirtRegIntervals[Reg]; - VirtRegIntervals[Reg] = nullptr; - } - - /// Given a register and an instruction, adds a live segment from that - /// instruction to the end of its MBB. - LiveInterval::Segment addSegmentToEndOfBlock(Register Reg, - MachineInstr &startInst); - - /// After removing some uses of a register, shrink its live range to just - /// the remaining uses. This method does not compute reaching defs for new - /// uses, and it doesn't remove dead defs. - /// Dead PHIDef values are marked as unused. New dead machine instructions - /// are added to the dead vector. Returns true if the interval may have been - /// separated into multiple connected components. - bool shrinkToUses(LiveInterval *li, - SmallVectorImpl *dead = nullptr); - - /// Specialized version of - /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) - /// that works on a subregister live range and only looks at uses matching - /// the lane mask of the subregister range. - /// This may leave the subrange empty which needs to be cleaned up with - /// LiveInterval::removeEmptySubranges() afterwards. - void shrinkToUses(LiveInterval::SubRange &SR, Register Reg); - - /// Extend the live range \p LR to reach all points in \p Indices. The - /// points in the \p Indices array must be jointly dominated by the union - /// of the existing defs in \p LR and points in \p Undefs. - /// - /// PHI-defs are added as needed to maintain SSA form. - /// - /// If a SlotIndex in \p Indices is the end index of a basic block, \p LR - /// will be extended to be live out of the basic block. - /// If a SlotIndex in \p Indices is jointy dominated only by points in - /// \p Undefs, the live range will not be extended to that point. - /// - /// See also LiveRangeCalc::extend(). - void extendToIndices(LiveRange &LR, ArrayRef Indices, - ArrayRef Undefs); - - void extendToIndices(LiveRange &LR, ArrayRef Indices) { - extendToIndices(LR, Indices, /*Undefs=*/{}); - } - - /// If \p LR has a live value at \p Kill, prune its live range by removing - /// any liveness reachable from Kill. Add live range end points to - /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the - /// value's live range. - /// - /// Calling pruneValue() and extendToIndices() can be used to reconstruct - /// SSA form after adding defs to a virtual register. - void pruneValue(LiveRange &LR, SlotIndex Kill, - SmallVectorImpl *EndPoints); - - /// This function should not be used. Its intent is to tell you that you are - /// doing something wrong if you call pruneValue directly on a - /// LiveInterval. Indeed, you are supposed to call pruneValue on the main - /// LiveRange and all the LiveRanges of the subranges if any. - LLVM_ATTRIBUTE_UNUSED void pruneValue(LiveInterval &, SlotIndex, - SmallVectorImpl *) { - llvm_unreachable( - "Use pruneValue on the main LiveRange and on each subrange"); - } - - SlotIndexes *getSlotIndexes() const { - return Indexes; - } - - AAResults *getAliasAnalysis() const { - return AA; - } - - /// Returns true if the specified machine instr has been removed or was - /// never entered in the map. - bool isNotInMIMap(const MachineInstr &Instr) const { - return !Indexes->hasIndex(Instr); - } - - /// Returns the base index of the given instruction. - SlotIndex getInstructionIndex(const MachineInstr &Instr) const { - return Indexes->getInstructionIndex(Instr); - } - - /// Returns the instruction associated with the given index. - MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return Indexes->getInstructionFromIndex(index); - } - - /// Return the first index in the given basic block. - SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { - return Indexes->getMBBStartIdx(mbb); - } - - /// Return the last index in the given basic block. - SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { - return Indexes->getMBBEndIdx(mbb); - } - - bool isLiveInToMBB(const LiveRange &LR, - const MachineBasicBlock *mbb) const { - return LR.liveAt(getMBBStartIdx(mbb)); - } - - bool isLiveOutOfMBB(const LiveRange &LR, - const MachineBasicBlock *mbb) const { - return LR.liveAt(getMBBEndIdx(mbb).getPrevSlot()); - } - - MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { - return Indexes->getMBBFromIndex(index); - } - - void insertMBBInMaps(MachineBasicBlock *MBB) { - Indexes->insertMBBInMaps(MBB); - assert(unsigned(MBB->getNumber()) == RegMaskBlocks.size() && - "Blocks must be added in order."); - RegMaskBlocks.push_back(std::make_pair(RegMaskSlots.size(), 0)); - } - - SlotIndex InsertMachineInstrInMaps(MachineInstr &MI) { - return Indexes->insertMachineInstrInMaps(MI); - } - - void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B, - MachineBasicBlock::iterator E) { - for (MachineBasicBlock::iterator I = B; I != E; ++I) - Indexes->insertMachineInstrInMaps(*I); - } - - void RemoveMachineInstrFromMaps(MachineInstr &MI) { - Indexes->removeMachineInstrFromMaps(MI); - } - - SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) { - return Indexes->replaceMachineInstrInMaps(MI, NewMI); - } - - VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - - /// Pass entry point; Calculates LiveIntervals. - bool runOnMachineFunction(MachineFunction&) override; - - /// Implement the dump method. - void print(raw_ostream &O, const Module* = nullptr) const override; - - /// If LI is confined to a single basic block, return a pointer to that - /// block. If LI is live in to or out of any block, return NULL. - MachineBasicBlock *intervalIsInOneMBB(const LiveInterval &LI) const; - - /// Returns true if VNI is killed by any PHI-def values in LI. - /// This may conservatively return true to avoid expensive computations. - bool hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const; - - /// Add kill flags to any instruction that kills a virtual register. - void addKillFlags(const VirtRegMap*); - - /// Call this method to notify LiveIntervals that instruction \p MI has been - /// moved within a basic block. This will update the live intervals for all - /// operands of \p MI. Moves between basic blocks are not supported. - /// - /// \param UpdateFlags Update live intervals for nonallocatable physregs. - void handleMove(MachineInstr &MI, bool UpdateFlags = false); - - /// Update intervals of operands of all instructions in the newly - /// created bundle specified by \p BundleStart. - /// - /// \param UpdateFlags Update live intervals for nonallocatable physregs. - /// - /// Assumes existing liveness is accurate. - /// \pre BundleStart should be the first instruction in the Bundle. - /// \pre BundleStart should not have a have SlotIndex as one will be assigned. - void handleMoveIntoNewBundle(MachineInstr &BundleStart, - bool UpdateFlags = false); - - /// Update live intervals for instructions in a range of iterators. It is - /// intended for use after target hooks that may insert or remove - /// instructions, and is only efficient for a small number of instructions. - /// - /// OrigRegs is a vector of registers that were originally used by the - /// instructions in the range between the two iterators. - /// - /// Currently, the only only changes that are supported are simple removal - /// and addition of uses. - void repairIntervalsInRange(MachineBasicBlock *MBB, - MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - ArrayRef OrigRegs); - - // Register mask functions. - // - // Machine instructions may use a register mask operand to indicate that a - // large number of registers are clobbered by the instruction. This is - // typically used for calls. - // - // For compile time performance reasons, these clobbers are not recorded in - // the live intervals for individual physical registers. Instead, - // LiveIntervalAnalysis maintains a sorted list of instructions with - // register mask operands. - - /// Returns a sorted array of slot indices of all instructions with - /// register mask operands. - ArrayRef getRegMaskSlots() const { return RegMaskSlots; } - - /// Returns a sorted array of slot indices of all instructions with register - /// mask operands in the basic block numbered \p MBBNum. - ArrayRef getRegMaskSlotsInBlock(unsigned MBBNum) const { - std::pair P = RegMaskBlocks[MBBNum]; - return getRegMaskSlots().slice(P.first, P.second); - } - - /// Returns an array of register mask pointers corresponding to - /// getRegMaskSlots(). - ArrayRef getRegMaskBits() const { return RegMaskBits; } - - /// Returns an array of mask pointers corresponding to - /// getRegMaskSlotsInBlock(MBBNum). - ArrayRef getRegMaskBitsInBlock(unsigned MBBNum) const { - std::pair P = RegMaskBlocks[MBBNum]; - return getRegMaskBits().slice(P.first, P.second); - } - - /// Test if \p LI is live across any register mask instructions, and - /// compute a bit mask of physical registers that are not clobbered by any - /// of them. - /// - /// Returns false if \p LI doesn't cross any register mask instructions. In - /// that case, the bit vector is not filled in. - bool checkRegMaskInterference(LiveInterval &LI, - BitVector &UsableRegs); - - // Register unit functions. - // - // Fixed interference occurs when MachineInstrs use physregs directly - // instead of virtual registers. This typically happens when passing - // arguments to a function call, or when instructions require operands in - // fixed registers. - // - // Each physreg has one or more register units, see MCRegisterInfo. We - // track liveness per register unit to handle aliasing registers more - // efficiently. - - /// Return the live range for register unit \p Unit. It will be computed if - /// it doesn't exist. - LiveRange &getRegUnit(unsigned Unit) { - LiveRange *LR = RegUnitRanges[Unit]; - if (!LR) { - // Compute missing ranges on demand. - // Use segment set to speed-up initial computation of the live range. - RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs); - computeRegUnitRange(*LR, Unit); - } - return *LR; - } - - /// Return the live range for register unit \p Unit if it has already been - /// computed, or nullptr if it hasn't been computed yet. - LiveRange *getCachedRegUnit(unsigned Unit) { - return RegUnitRanges[Unit]; - } - - const LiveRange *getCachedRegUnit(unsigned Unit) const { - return RegUnitRanges[Unit]; - } - - /// Remove computed live range for register unit \p Unit. Subsequent uses - /// should rely on on-demand recomputation. - void removeRegUnit(unsigned Unit) { - delete RegUnitRanges[Unit]; - RegUnitRanges[Unit] = nullptr; - } - - /// Remove associated live ranges for the register units associated with \p - /// Reg. Subsequent uses should rely on on-demand recomputation. \note This - /// method can result in inconsistent liveness tracking if multiple phyical - /// registers share a regunit, and should be used cautiously. - void removeAllRegUnitsForPhysReg(MCRegister Reg) { - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) - removeRegUnit(*Units); - } - - /// Remove value numbers and related live segments starting at position - /// \p Pos that are part of any liverange of physical register \p Reg or one - /// of its subregisters. - void removePhysRegDefAt(MCRegister Reg, SlotIndex Pos); - - /// Remove value number and related live segments of \p LI and its subranges - /// that start at position \p Pos. - void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos); - - /// Split separate components in LiveInterval \p LI into separate intervals. - void splitSeparateComponents(LiveInterval &LI, - SmallVectorImpl &SplitLIs); - - /// For live interval \p LI with correct SubRanges construct matching - /// information for the main live range. Expects the main live range to not - /// have any segments or value numbers. - void constructMainRangeFromSubranges(LiveInterval &LI); - - private: - /// Compute live intervals for all virtual registers. - void computeVirtRegs(); - - /// Compute RegMaskSlots and RegMaskBits. - void computeRegMasks(); - - /// Walk the values in \p LI and check for dead values: - /// - Dead PHIDef values are marked as unused. - /// - Dead operands are marked as such. - /// - Completely dead machine instructions are added to the \p dead vector - /// if it is not nullptr. - /// Returns true if any PHI value numbers have been removed which may - /// have separated the interval into multiple connected components. - bool computeDeadValues(LiveInterval &LI, - SmallVectorImpl *dead); - - static LiveInterval *createInterval(Register Reg); - - void printInstrs(raw_ostream &O) const; - void dumpInstrs() const; - - void computeLiveInRegUnits(); - void computeRegUnitRange(LiveRange&, unsigned Unit); - bool computeVirtRegInterval(LiveInterval&); - - using ShrinkToUsesWorkList = SmallVector, 16>; - void extendSegmentsToUses(LiveRange &Segments, - ShrinkToUsesWorkList &WorkList, Register Reg, - LaneBitmask LaneMask); - - /// Helper function for repairIntervalsInRange(), walks backwards and - /// creates/modifies live segments in \p LR to match the operands found. - /// Only full operands or operands with subregisters matching \p LaneMask - /// are considered. - void repairOldRegInRange(MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - const SlotIndex endIdx, LiveRange &LR, - Register Reg, - LaneBitmask LaneMask = LaneBitmask::getAll()); - - class HMEditor; - }; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LivePhysRegs.h b/suite/synctools/tablegen/include/llvm/CodeGen/LivePhysRegs.h deleted file mode 100644 index 710737feff..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LivePhysRegs.h +++ /dev/null @@ -1,204 +0,0 @@ -//===- llvm/CodeGen/LivePhysRegs.h - Live Physical Register Set -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file implements the LivePhysRegs utility for tracking liveness of -/// physical registers. This can be used for ad-hoc liveness tracking after -/// register allocation. You can start with the live-ins/live-outs at the -/// beginning/end of a block and update the information while walking the -/// instructions inside the block. This implementation tracks the liveness on a -/// sub-register granularity. -/// -/// We assume that the high bits of a physical super-register are not preserved -/// unless the instruction has an implicit-use operand reading the super- -/// register. -/// -/// X86 Example: -/// %ymm0 = ... -/// %xmm0 = ... (Kills %xmm0, all %xmm0s sub-registers, and %ymm0) -/// -/// %ymm0 = ... -/// %xmm0 = ..., implicit %ymm0 (%ymm0 and all its sub-registers are alive) -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H -#define LLVM_CODEGEN_LIVEPHYSREGS_H - -#include "llvm/ADT/SparseSet.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include -#include - -namespace llvm { - -class MachineInstr; -class MachineOperand; -class MachineRegisterInfo; -class raw_ostream; - -/// A set of physical registers with utility functions to track liveness -/// when walking backward/forward through a basic block. -class LivePhysRegs { - const TargetRegisterInfo *TRI = nullptr; - using RegisterSet = SparseSet>; - RegisterSet LiveRegs; - -public: - /// Constructs an uninitialized set. init() needs to be called to initialize it. - LivePhysRegs() = default; - - /// Constructs and initializes an empty set. - LivePhysRegs(const TargetRegisterInfo &TRI) : TRI(&TRI) { - LiveRegs.setUniverse(TRI.getNumRegs()); - } - - LivePhysRegs(const LivePhysRegs&) = delete; - LivePhysRegs &operator=(const LivePhysRegs&) = delete; - - /// (re-)initializes and clears the set. - void init(const TargetRegisterInfo &TRI) { - this->TRI = &TRI; - LiveRegs.clear(); - LiveRegs.setUniverse(TRI.getNumRegs()); - } - - /// Clears the set. - void clear() { LiveRegs.clear(); } - - /// Returns true if the set is empty. - bool empty() const { return LiveRegs.empty(); } - - /// Adds a physical register and all its sub-registers to the set. - void addReg(MCPhysReg Reg) { - assert(TRI && "LivePhysRegs is not initialized."); - assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); - for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); - SubRegs.isValid(); ++SubRegs) - LiveRegs.insert(*SubRegs); - } - - /// Removes a physical register, all its sub-registers, and all its - /// super-registers from the set. - void removeReg(MCPhysReg Reg) { - assert(TRI && "LivePhysRegs is not initialized."); - assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); - for (MCRegAliasIterator R(Reg, TRI, true); R.isValid(); ++R) - LiveRegs.erase(*R); - } - - /// Removes physical registers clobbered by the regmask operand \p MO. - void removeRegsInMask(const MachineOperand &MO, - SmallVectorImpl> *Clobbers = - nullptr); - - /// Returns true if register \p Reg is contained in the set. This also - /// works if only the super register of \p Reg has been defined, because - /// addReg() always adds all sub-registers to the set as well. - /// Note: Returns false if just some sub registers are live, use available() - /// when searching a free register. - bool contains(MCPhysReg Reg) const { return LiveRegs.count(Reg); } - - /// Returns true if register \p Reg and no aliasing register is in the set. - bool available(const MachineRegisterInfo &MRI, MCPhysReg Reg) const; - - /// Remove defined registers and regmask kills from the set. - void removeDefs(const MachineInstr &MI); - - /// Add uses to the set. - void addUses(const MachineInstr &MI); - - /// Simulates liveness when stepping backwards over an instruction(bundle). - /// Remove Defs, add uses. This is the recommended way of calculating - /// liveness. - void stepBackward(const MachineInstr &MI); - - /// Simulates liveness when stepping forward over an instruction(bundle). - /// Remove killed-uses, add defs. This is the not recommended way, because it - /// depends on accurate kill flags. If possible use stepBackward() instead of - /// this function. The clobbers set will be the list of registers either - /// defined or clobbered by a regmask. The operand will identify whether this - /// is a regmask or register operand. - void stepForward(const MachineInstr &MI, - SmallVectorImpl> &Clobbers); - - /// Adds all live-in registers of basic block \p MBB. - /// Live in registers are the registers in the blocks live-in list and the - /// pristine registers. - void addLiveIns(const MachineBasicBlock &MBB); - - /// Adds all live-in registers of basic block \p MBB but skips pristine - /// registers. - void addLiveInsNoPristines(const MachineBasicBlock &MBB); - - /// Adds all live-out registers of basic block \p MBB. - /// Live out registers are the union of the live-in registers of the successor - /// blocks and pristine registers. Live out registers of the end block are the - /// callee saved registers. - /// If a register is not added by this method, it is guaranteed to not be - /// live out from MBB, although a sub-register may be. This is true - /// both before and after regalloc. - void addLiveOuts(const MachineBasicBlock &MBB); - - /// Adds all live-out registers of basic block \p MBB but skips pristine - /// registers. - void addLiveOutsNoPristines(const MachineBasicBlock &MBB); - - using const_iterator = RegisterSet::const_iterator; - - const_iterator begin() const { return LiveRegs.begin(); } - const_iterator end() const { return LiveRegs.end(); } - - /// Prints the currently live registers to \p OS. - void print(raw_ostream &OS) const; - - /// Dumps the currently live registers to the debug output. - void dump() const; - -private: - /// Adds live-in registers from basic block \p MBB, taking associated - /// lane masks into consideration. - void addBlockLiveIns(const MachineBasicBlock &MBB); - - /// Adds pristine registers. Pristine registers are callee saved registers - /// that are unused in the function. - void addPristines(const MachineFunction &MF); -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) { - LR.print(OS); - return OS; -} - -/// Computes registers live-in to \p MBB assuming all of its successors -/// live-in lists are up-to-date. Puts the result into the given LivePhysReg -/// instance \p LiveRegs. -void computeLiveIns(LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB); - -/// Recomputes dead and kill flags in \p MBB. -void recomputeLivenessFlags(MachineBasicBlock &MBB); - -/// Adds registers contained in \p LiveRegs to the block live-in list of \p MBB. -/// Does not add reserved registers. -void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs); - -/// Convenience function combining computeLiveIns() and addLiveIns(). -void computeAndAddLiveIns(LivePhysRegs &LiveRegs, - MachineBasicBlock &MBB); - -/// Convenience function for recomputing live-in's for \p MBB. -static inline void recomputeLiveIns(MachineBasicBlock &MBB) { - LivePhysRegs LPR; - MBB.clearLiveIns(); - computeAndAddLiveIns(LPR, MBB); -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEPHYSREGS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeCalc.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeCalc.h deleted file mode 100644 index 31efd6e37e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeCalc.h +++ /dev/null @@ -1,270 +0,0 @@ -//===- LiveRangeCalc.h - Calculate live ranges -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The LiveRangeCalc class can be used to implement the computation of -// live ranges from scratch. -// It caches information about values in the CFG to speed up repeated -// operations on the same live range. The cache can be shared by -// non-overlapping live ranges. SplitKit uses that when computing the live -// range of split products. -// -// A low-level interface is available to clients that know where a variable is -// live, but don't know which value it has as every point. LiveRangeCalc will -// propagate values down the dominator tree, and even insert PHI-defs where -// needed. SplitKit uses this faster interface when possible. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVERANGECALC_H -#define LLVM_CODEGEN_LIVERANGECALC_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/MC/LaneBitmask.h" -#include - -namespace llvm { - -template class DomTreeNodeBase; -class MachineDominatorTree; -class MachineFunction; -class MachineRegisterInfo; - -using MachineDomTreeNode = DomTreeNodeBase; - -class LiveRangeCalc { - const MachineFunction *MF = nullptr; - const MachineRegisterInfo *MRI = nullptr; - SlotIndexes *Indexes = nullptr; - MachineDominatorTree *DomTree = nullptr; - VNInfo::Allocator *Alloc = nullptr; - - /// LiveOutPair - A value and the block that defined it. The domtree node is - /// redundant, it can be computed as: MDT[Indexes.getMBBFromIndex(VNI->def)]. - using LiveOutPair = std::pair; - - /// LiveOutMap - Map basic blocks to the value leaving the block. - using LiveOutMap = IndexedMap; - - /// Bit vector of active entries in LiveOut, also used as a visited set by - /// findReachingDefs. One entry per basic block, indexed by block number. - /// This is kept as a separate bit vector because it can be cleared quickly - /// when switching live ranges. - BitVector Seen; - - /// Map LiveRange to sets of blocks (represented by bit vectors) that - /// in the live range are defined on entry and undefined on entry. - /// A block is defined on entry if there is a path from at least one of - /// the defs in the live range to the entry of the block, and conversely, - /// a block is undefined on entry, if there is no such path (i.e. no - /// definition reaches the entry of the block). A single LiveRangeCalc - /// object is used to track live-out information for multiple registers - /// in live range splitting (which is ok, since the live ranges of these - /// registers do not overlap), but the defined/undefined information must - /// be kept separate for each individual range. - /// By convention, EntryInfoMap[&LR] = { Defined, Undefined }. - using EntryInfoMap = DenseMap>; - EntryInfoMap EntryInfos; - - /// Map each basic block where a live range is live out to the live-out value - /// and its defining block. - /// - /// For every basic block, MBB, one of these conditions shall be true: - /// - /// 1. !Seen.count(MBB->getNumber()) - /// Blocks without a Seen bit are ignored. - /// 2. LiveOut[MBB].second.getNode() == MBB - /// The live-out value is defined in MBB. - /// 3. forall P in preds(MBB): LiveOut[P] == LiveOut[MBB] - /// The live-out value passses through MBB. All predecessors must carry - /// the same value. - /// - /// The domtree node may be null, it can be computed. - /// - /// The map can be shared by multiple live ranges as long as no two are - /// live-out of the same block. - LiveOutMap Map; - - /// LiveInBlock - Information about a basic block where a live range is known - /// to be live-in, but the value has not yet been determined. - struct LiveInBlock { - // The live range set that is live-in to this block. The algorithms can - // handle multiple non-overlapping live ranges simultaneously. - LiveRange &LR; - - // DomNode - Dominator tree node for the block. - // Cleared when the final value has been determined and LI has been updated. - MachineDomTreeNode *DomNode; - - // Position in block where the live-in range ends, or SlotIndex() if the - // range passes through the block. When the final value has been - // determined, the range from the block start to Kill will be added to LI. - SlotIndex Kill; - - // Live-in value filled in by updateSSA once it is known. - VNInfo *Value = nullptr; - - LiveInBlock(LiveRange &LR, MachineDomTreeNode *node, SlotIndex kill) - : LR(LR), DomNode(node), Kill(kill) {} - }; - - /// LiveIn - Work list of blocks where the live-in value has yet to be - /// determined. This list is typically computed by findReachingDefs() and - /// used as a work list by updateSSA(). The low-level interface may also be - /// used to add entries directly. - SmallVector LiveIn; - - /// Check if the entry to block @p MBB can be reached by any of the defs - /// in @p LR. Return true if none of the defs reach the entry to @p MBB. - bool isDefOnEntry(LiveRange &LR, ArrayRef Undefs, - MachineBasicBlock &MBB, BitVector &DefOnEntry, - BitVector &UndefOnEntry); - - /// Find the set of defs that can reach @p Kill. @p Kill must belong to - /// @p UseMBB. - /// - /// If exactly one def can reach @p UseMBB, and the def dominates @p Kill, - /// all paths from the def to @p UseMBB are added to @p LR, and the function - /// returns true. - /// - /// If multiple values can reach @p UseMBB, the blocks that need @p LR to be - /// live in are added to the LiveIn array, and the function returns false. - /// - /// The array @p Undef provides the locations where the range @p LR becomes - /// undefined by operands on other subranges. If @p Undef - /// is non-empty and @p Kill is jointly dominated only by the entries of - /// @p Undef, the function returns false. - /// - /// PhysReg, when set, is used to verify live-in lists on basic blocks. - bool findReachingDefs(LiveRange &LR, MachineBasicBlock &UseMBB, SlotIndex Use, - unsigned PhysReg, ArrayRef Undefs); - - /// updateSSA - Compute the values that will be live in to all requested - /// blocks in LiveIn. Create PHI-def values as required to preserve SSA form. - /// - /// Every live-in block must be jointly dominated by the added live-out - /// blocks. No values are read from the live ranges. - void updateSSA(); - - /// Transfer information from the LiveIn vector to the live ranges and update - /// the given @p LiveOuts. - void updateFromLiveIns(); - -protected: - /// Some getters to expose in a read-only way some private fields to - /// subclasses. - const MachineFunction *getMachineFunction() { return MF; } - const MachineRegisterInfo *getRegInfo() const { return MRI; } - SlotIndexes *getIndexes() { return Indexes; } - MachineDominatorTree *getDomTree() { return DomTree; } - VNInfo::Allocator *getVNAlloc() { return Alloc; } - - /// Reset Map and Seen fields. - void resetLiveOutMap(); - -public: - LiveRangeCalc() = default; - - //===--------------------------------------------------------------------===// - // High-level interface. - //===--------------------------------------------------------------------===// - // - // Calculate live ranges from scratch. - // - - /// reset - Prepare caches for a new set of non-overlapping live ranges. The - /// caches must be reset before attempting calculations with a live range - /// that may overlap a previously computed live range, and before the first - /// live range in a function. If live ranges are not known to be - /// non-overlapping, call reset before each. - void reset(const MachineFunction *mf, SlotIndexes *SI, - MachineDominatorTree *MDT, VNInfo::Allocator *VNIA); - - //===--------------------------------------------------------------------===// - // Mid-level interface. - //===--------------------------------------------------------------------===// - // - // Modify existing live ranges. - // - - /// Extend the live range of @p LR to reach @p Use. - /// - /// The existing values in @p LR must be live so they jointly dominate @p Use. - /// If @p Use is not dominated by a single existing value, PHI-defs are - /// inserted as required to preserve SSA form. - /// - /// PhysReg, when set, is used to verify live-in lists on basic blocks. - void extend(LiveRange &LR, SlotIndex Use, unsigned PhysReg, - ArrayRef Undefs); - - //===--------------------------------------------------------------------===// - // Low-level interface. - //===--------------------------------------------------------------------===// - // - // These functions can be used to compute live ranges where the live-in and - // live-out blocks are already known, but the SSA value in each block is - // unknown. - // - // After calling reset(), add known live-out values and known live-in blocks. - // Then call calculateValues() to compute the actual value that is - // live-in to each block, and add liveness to the live ranges. - // - - /// setLiveOutValue - Indicate that VNI is live out from MBB. The - /// calculateValues() function will not add liveness for MBB, the caller - /// should take care of that. - /// - /// VNI may be null only if MBB is a live-through block also passed to - /// addLiveInBlock(). - void setLiveOutValue(MachineBasicBlock *MBB, VNInfo *VNI) { - Seen.set(MBB->getNumber()); - Map[MBB] = LiveOutPair(VNI, nullptr); - } - - /// addLiveInBlock - Add a block with an unknown live-in value. This - /// function can only be called once per basic block. Once the live-in value - /// has been determined, calculateValues() will add liveness to LI. - /// - /// @param LR The live range that is live-in to the block. - /// @param DomNode The domtree node for the block. - /// @param Kill Index in block where LI is killed. If the value is - /// live-through, set Kill = SLotIndex() and also call - /// setLiveOutValue(MBB, 0). - void addLiveInBlock(LiveRange &LR, MachineDomTreeNode *DomNode, - SlotIndex Kill = SlotIndex()) { - LiveIn.push_back(LiveInBlock(LR, DomNode, Kill)); - } - - /// calculateValues - Calculate the value that will be live-in to each block - /// added with addLiveInBlock. Add PHI-def values as needed to preserve SSA - /// form. Add liveness to all live-in blocks up to the Kill point, or the - /// whole block for live-through blocks. - /// - /// Every predecessor of a live-in block must have been given a value with - /// setLiveOutValue, the value may be null for live-trough blocks. - void calculateValues(); - - /// A diagnostic function to check if the end of the block @p MBB is - /// jointly dominated by the blocks corresponding to the slot indices - /// in @p Defs. This function is mainly for use in self-verification - /// checks. - LLVM_ATTRIBUTE_UNUSED - static bool isJointlyDominated(const MachineBasicBlock *MBB, - ArrayRef Defs, - const SlotIndexes &Indexes); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVERANGECALC_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeEdit.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeEdit.h deleted file mode 100644 index 7000bfac7d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRangeEdit.h +++ /dev/null @@ -1,255 +0,0 @@ -//===- LiveRangeEdit.h - Basic tools for split and spill --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The LiveRangeEdit class represents changes done to a virtual register when it -// is spilled or split. -// -// The parent register is never changed. Instead, a number of new virtual -// registers are created and added to the newRegs vector. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVERANGEEDIT_H -#define LLVM_CODEGEN_LIVERANGEEDIT_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include - -namespace llvm { - -class AAResults; -class LiveIntervals; -class MachineInstr; -class MachineOperand; -class TargetInstrInfo; -class TargetRegisterInfo; -class VirtRegMap; -class VirtRegAuxInfo; - -class LiveRangeEdit : private MachineRegisterInfo::Delegate { -public: - /// Callback methods for LiveRangeEdit owners. - class Delegate { - virtual void anchor(); - - public: - virtual ~Delegate() = default; - - /// Called immediately before erasing a dead machine instruction. - virtual void LRE_WillEraseInstruction(MachineInstr *MI) {} - - /// Called when a virtual register is no longer used. Return false to defer - /// its deletion from LiveIntervals. - virtual bool LRE_CanEraseVirtReg(Register) { return true; } - - /// Called before shrinking the live range of a virtual register. - virtual void LRE_WillShrinkVirtReg(Register) {} - - /// Called after cloning a virtual register. - /// This is used for new registers representing connected components of Old. - virtual void LRE_DidCloneVirtReg(Register New, Register Old) {} - }; - -private: - LiveInterval *Parent; - SmallVectorImpl &NewRegs; - MachineRegisterInfo &MRI; - LiveIntervals &LIS; - VirtRegMap *VRM; - const TargetInstrInfo &TII; - Delegate *const TheDelegate; - - /// FirstNew - Index of the first register added to NewRegs. - const unsigned FirstNew; - - /// ScannedRemattable - true when remattable values have been identified. - bool ScannedRemattable = false; - - /// DeadRemats - The saved instructions which have already been dead after - /// rematerialization but not deleted yet -- to be done in postOptimization. - SmallPtrSet *DeadRemats; - - /// Remattable - Values defined by remattable instructions as identified by - /// tii.isTriviallyReMaterializable(). - SmallPtrSet Remattable; - - /// Rematted - Values that were actually rematted, and so need to have their - /// live range trimmed or entirely removed. - SmallPtrSet Rematted; - - /// scanRemattable - Identify the Parent values that may rematerialize. - void scanRemattable(AAResults *aa); - - /// foldAsLoad - If LI has a single use and a single def that can be folded as - /// a load, eliminate the register by folding the def into the use. - bool foldAsLoad(LiveInterval *LI, SmallVectorImpl &Dead); - - using ToShrinkSet = SetVector, - SmallPtrSet>; - - /// Helper for eliminateDeadDefs. - void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink, - AAResults *AA); - - /// MachineRegisterInfo callback to notify when new virtual - /// registers are created. - void MRI_NoteNewVirtualRegister(Register VReg) override; - - /// Check if MachineOperand \p MO is a last use/kill either in the - /// main live range of \p LI or in one of the matching subregister ranges. - bool useIsKill(const LiveInterval &LI, const MachineOperand &MO) const; - - /// Create a new empty interval based on OldReg. - LiveInterval &createEmptyIntervalFrom(Register OldReg, bool createSubRanges); - -public: - /// Create a LiveRangeEdit for breaking down parent into smaller pieces. - /// @param parent The register being spilled or split. - /// @param newRegs List to receive any new registers created. This needn't be - /// empty initially, any existing registers are ignored. - /// @param MF The MachineFunction the live range edit is taking place in. - /// @param lis The collection of all live intervals in this function. - /// @param vrm Map of virtual registers to physical registers for this - /// function. If NULL, no virtual register map updates will - /// be done. This could be the case if called before Regalloc. - /// @param deadRemats The collection of all the instructions defining an - /// original reg and are dead after remat. - LiveRangeEdit(LiveInterval *parent, SmallVectorImpl &newRegs, - MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, - Delegate *delegate = nullptr, - SmallPtrSet *deadRemats = nullptr) - : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis), - VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), TheDelegate(delegate), - FirstNew(newRegs.size()), DeadRemats(deadRemats) { - MRI.setDelegate(this); - } - - ~LiveRangeEdit() override { MRI.resetDelegate(this); } - - LiveInterval &getParent() const { - assert(Parent && "No parent LiveInterval"); - return *Parent; - } - - Register getReg() const { return getParent().reg(); } - - /// Iterator for accessing the new registers added by this edit. - using iterator = SmallVectorImpl::const_iterator; - iterator begin() const { return NewRegs.begin() + FirstNew; } - iterator end() const { return NewRegs.end(); } - unsigned size() const { return NewRegs.size() - FirstNew; } - bool empty() const { return size() == 0; } - Register get(unsigned idx) const { return NewRegs[idx + FirstNew]; } - - /// pop_back - It allows LiveRangeEdit users to drop new registers. - /// The context is when an original def instruction of a register is - /// dead after rematerialization, we still want to keep it for following - /// rematerializations. We save the def instruction in DeadRemats, - /// and replace the original dst register with a new dummy register so - /// the live range of original dst register can be shrunk normally. - /// We don't want to allocate phys register for the dummy register, so - /// we want to drop it from the NewRegs set. - void pop_back() { NewRegs.pop_back(); } - - ArrayRef regs() const { - return makeArrayRef(NewRegs).slice(FirstNew); - } - - /// createFrom - Create a new virtual register based on OldReg. - Register createFrom(Register OldReg); - - /// create - Create a new register with the same class and original slot as - /// parent. - LiveInterval &createEmptyInterval() { - return createEmptyIntervalFrom(getReg(), true); - } - - Register create() { return createFrom(getReg()); } - - /// anyRematerializable - Return true if any parent values may be - /// rematerializable. - /// This function must be called before any rematerialization is attempted. - bool anyRematerializable(AAResults *); - - /// checkRematerializable - Manually add VNI to the list of rematerializable - /// values if DefMI may be rematerializable. - bool checkRematerializable(VNInfo *VNI, const MachineInstr *DefMI, - AAResults *); - - /// Remat - Information needed to rematerialize at a specific location. - struct Remat { - VNInfo *ParentVNI; // parent_'s value at the remat location. - MachineInstr *OrigMI = nullptr; // Instruction defining OrigVNI. It contains - // the real expr for remat. - - explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI) {} - }; - - /// allUsesAvailableAt - Return true if all registers used by OrigMI at - /// OrigIdx are also available with the same value at UseIdx. - bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx, - SlotIndex UseIdx) const; - - /// canRematerializeAt - Determine if ParentVNI can be rematerialized at - /// UseIdx. It is assumed that parent_.getVNINfoAt(UseIdx) == ParentVNI. - /// When cheapAsAMove is set, only cheap remats are allowed. - bool canRematerializeAt(Remat &RM, VNInfo *OrigVNI, SlotIndex UseIdx, - bool cheapAsAMove); - - /// rematerializeAt - Rematerialize RM.ParentVNI into DestReg by inserting an - /// instruction into MBB before MI. The new instruction is mapped, but - /// liveness is not updated. - /// Return the SlotIndex of the new instruction. - SlotIndex rematerializeAt(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, unsigned DestReg, - const Remat &RM, const TargetRegisterInfo &, - bool Late = false); - - /// markRematerialized - explicitly mark a value as rematerialized after doing - /// it manually. - void markRematerialized(const VNInfo *ParentVNI) { - Rematted.insert(ParentVNI); - } - - /// didRematerialize - Return true if ParentVNI was rematerialized anywhere. - bool didRematerialize(const VNInfo *ParentVNI) const { - return Rematted.count(ParentVNI); - } - - /// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try - /// to erase it from LIS. - void eraseVirtReg(Register Reg); - - /// eliminateDeadDefs - Try to delete machine instructions that are now dead - /// (allDefsAreDead returns true). This may cause live intervals to be trimmed - /// and further dead efs to be eliminated. - /// RegsBeingSpilled lists registers currently being spilled by the register - /// allocator. These registers should not be split into new intervals - /// as currently those new intervals are not guaranteed to spill. - void eliminateDeadDefs(SmallVectorImpl &Dead, - ArrayRef RegsBeingSpilled = None, - AAResults *AA = nullptr); - - /// calculateRegClassAndHint - Recompute register class and hint for each new - /// register. - void calculateRegClassAndHint(MachineFunction &, VirtRegAuxInfo &); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVERANGEEDIT_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegMatrix.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegMatrix.h deleted file mode 100644 index fc67bce329..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegMatrix.h +++ /dev/null @@ -1,162 +0,0 @@ -//===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The LiveRegMatrix analysis pass keeps track of virtual register interference -// along two dimensions: Slot indexes and register units. The matrix is used by -// register allocators to ensure that no interfering virtual registers get -// assigned to overlapping physical registers. -// -// Register units are defined in MCRegisterInfo.h, they represent the smallest -// unit of interference when dealing with overlapping physical registers. The -// LiveRegMatrix is represented as a LiveIntervalUnion per register unit. When -// a virtual register is assigned to a physical register, the live range for -// the virtual register is inserted into the LiveIntervalUnion for each regunit -// in the physreg. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEREGMATRIX_H -#define LLVM_CODEGEN_LIVEREGMATRIX_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/CodeGen/LiveIntervalUnion.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include - -namespace llvm { - -class AnalysisUsage; -class LiveInterval; -class LiveIntervals; -class MachineFunction; -class TargetRegisterInfo; -class VirtRegMap; - -class LiveRegMatrix : public MachineFunctionPass { - const TargetRegisterInfo *TRI; - LiveIntervals *LIS; - VirtRegMap *VRM; - - // UserTag changes whenever virtual registers have been modified. - unsigned UserTag = 0; - - // The matrix is represented as a LiveIntervalUnion per register unit. - LiveIntervalUnion::Allocator LIUAlloc; - LiveIntervalUnion::Array Matrix; - - // Cached queries per register unit. - std::unique_ptr Queries; - - // Cached register mask interference info. - unsigned RegMaskTag = 0; - unsigned RegMaskVirtReg = 0; - BitVector RegMaskUsable; - - // MachineFunctionPass boilerplate. - void getAnalysisUsage(AnalysisUsage &) const override; - bool runOnMachineFunction(MachineFunction &) override; - void releaseMemory() override; - -public: - static char ID; - - LiveRegMatrix(); - - //===--------------------------------------------------------------------===// - // High-level interface. - //===--------------------------------------------------------------------===// - // - // Check for interference before assigning virtual registers to physical - // registers. - // - - /// Invalidate cached interference queries after modifying virtual register - /// live ranges. Interference checks may return stale information unless - /// caches are invalidated. - void invalidateVirtRegs() { ++UserTag; } - - enum InterferenceKind { - /// No interference, go ahead and assign. - IK_Free = 0, - - /// Virtual register interference. There are interfering virtual registers - /// assigned to PhysReg or its aliases. This interference could be resolved - /// by unassigning those other virtual registers. - IK_VirtReg, - - /// Register unit interference. A fixed live range is in the way, typically - /// argument registers for a call. This can't be resolved by unassigning - /// other virtual registers. - IK_RegUnit, - - /// RegMask interference. The live range is crossing an instruction with a - /// regmask operand that doesn't preserve PhysReg. This typically means - /// VirtReg is live across a call, and PhysReg isn't call-preserved. - IK_RegMask - }; - - /// Check for interference before assigning VirtReg to PhysReg. - /// If this function returns IK_Free, it is legal to assign(VirtReg, PhysReg). - /// When there is more than one kind of interference, the InterferenceKind - /// with the highest enum value is returned. - InterferenceKind checkInterference(LiveInterval &VirtReg, MCRegister PhysReg); - - /// Check for interference in the segment [Start, End) that may prevent - /// assignment to PhysReg. If this function returns true, there is - /// interference in the segment [Start, End) of some other interval already - /// assigned to PhysReg. If this function returns false, PhysReg is free at - /// the segment [Start, End). - bool checkInterference(SlotIndex Start, SlotIndex End, MCRegister PhysReg); - - /// Assign VirtReg to PhysReg. - /// This will mark VirtReg's live range as occupied in the LiveRegMatrix and - /// update VirtRegMap. The live range is expected to be available in PhysReg. - void assign(LiveInterval &VirtReg, MCRegister PhysReg); - - /// Unassign VirtReg from its PhysReg. - /// Assuming that VirtReg was previously assigned to a PhysReg, this undoes - /// the assignment and updates VirtRegMap accordingly. - void unassign(LiveInterval &VirtReg); - - /// Returns true if the given \p PhysReg has any live intervals assigned. - bool isPhysRegUsed(MCRegister PhysReg) const; - - //===--------------------------------------------------------------------===// - // Low-level interface. - //===--------------------------------------------------------------------===// - // - // Provide access to the underlying LiveIntervalUnions. - // - - /// Check for regmask interference only. - /// Return true if VirtReg crosses a regmask operand that clobbers PhysReg. - /// If PhysReg is null, check if VirtReg crosses any regmask operands. - bool checkRegMaskInterference(LiveInterval &VirtReg, - MCRegister PhysReg = MCRegister::NoRegister); - - /// Check for regunit interference only. - /// Return true if VirtReg overlaps a fixed assignment of one of PhysRegs's - /// register units. - bool checkRegUnitInterference(LiveInterval &VirtReg, MCRegister PhysReg); - - /// Query a line of the assigned virtual register matrix directly. - /// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg. - /// This returns a reference to an internal Query data structure that is only - /// valid until the next query() call. - LiveIntervalUnion::Query &query(const LiveRange &LR, MCRegister RegUnit); - - /// Directly access the live interval unions per regunit. - /// This returns an array indexed by the regunit number. - LiveIntervalUnion *getLiveUnions() { return &Matrix[0]; } - - Register getOneVReg(unsigned PhysReg) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEREGMATRIX_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegUnits.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegUnits.h deleted file mode 100644 index 3ef3e6bab4..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveRegUnits.h +++ /dev/null @@ -1,177 +0,0 @@ -//===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// A set of register units. It is intended for register liveness tracking. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEREGUNITS_H -#define LLVM_CODEGEN_LIVEREGUNITS_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/MC/MCRegisterInfo.h" -#include - -namespace llvm { - -class MachineInstr; -class MachineBasicBlock; - -/// A set of register units used to track register liveness. -class LiveRegUnits { - const TargetRegisterInfo *TRI = nullptr; - BitVector Units; - -public: - /// Constructs a new empty LiveRegUnits set. - LiveRegUnits() = default; - - /// Constructs and initialize an empty LiveRegUnits set. - LiveRegUnits(const TargetRegisterInfo &TRI) { - init(TRI); - } - - /// For a machine instruction \p MI, adds all register units used in - /// \p UsedRegUnits and defined or clobbered in \p ModifiedRegUnits. This is - /// useful when walking over a range of instructions to track registers - /// used or defined separately. - static void accumulateUsedDefed(const MachineInstr &MI, - LiveRegUnits &ModifiedRegUnits, - LiveRegUnits &UsedRegUnits, - const TargetRegisterInfo *TRI) { - for (ConstMIBundleOperands O(MI); O.isValid(); ++O) { - if (O->isRegMask()) - ModifiedRegUnits.addRegsInMask(O->getRegMask()); - if (!O->isReg()) - continue; - Register Reg = O->getReg(); - if (!Reg.isPhysical()) - continue; - if (O->isDef()) { - // Some architectures (e.g. AArch64 XZR/WZR) have registers that are - // constant and may be used as destinations to indicate the generated - // value is discarded. No need to track such case as a def. - if (!TRI->isConstantPhysReg(Reg)) - ModifiedRegUnits.addReg(Reg); - } else { - assert(O->isUse() && "Reg operand not a def and not a use"); - UsedRegUnits.addReg(Reg); - } - } - } - - /// Initialize and clear the set. - void init(const TargetRegisterInfo &TRI) { - this->TRI = &TRI; - Units.reset(); - Units.resize(TRI.getNumRegUnits()); - } - - /// Clears the set. - void clear() { Units.reset(); } - - /// Returns true if the set is empty. - bool empty() const { return Units.none(); } - - /// Adds register units covered by physical register \p Reg. - void addReg(MCPhysReg Reg) { - for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) - Units.set(*Unit); - } - - /// Adds register units covered by physical register \p Reg that are - /// part of the lanemask \p Mask. - void addRegMasked(MCPhysReg Reg, LaneBitmask Mask) { - for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { - LaneBitmask UnitMask = (*Unit).second; - if (UnitMask.none() || (UnitMask & Mask).any()) - Units.set((*Unit).first); - } - } - - /// Removes all register units covered by physical register \p Reg. - void removeReg(MCPhysReg Reg) { - for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) - Units.reset(*Unit); - } - - /// Removes register units not preserved by the regmask \p RegMask. - /// The regmask has the same format as the one in the RegMask machine operand. - void removeRegsNotPreserved(const uint32_t *RegMask); - - /// Adds register units not preserved by the regmask \p RegMask. - /// The regmask has the same format as the one in the RegMask machine operand. - void addRegsInMask(const uint32_t *RegMask); - - /// Returns true if no part of physical register \p Reg is live. - bool available(MCPhysReg Reg) const { - for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { - if (Units.test(*Unit)) - return false; - } - return true; - } - - /// Updates liveness when stepping backwards over the instruction \p MI. - /// This removes all register units defined or clobbered in \p MI and then - /// adds the units used (as in use operands) in \p MI. - void stepBackward(const MachineInstr &MI); - - /// Adds all register units used, defined or clobbered in \p MI. - /// This is useful when walking over a range of instruction to find registers - /// unused over the whole range. - void accumulate(const MachineInstr &MI); - - /// Adds registers living out of block \p MBB. - /// Live out registers are the union of the live-in registers of the successor - /// blocks and pristine registers. Live out registers of the end block are the - /// callee saved registers. - void addLiveOuts(const MachineBasicBlock &MBB); - - /// Adds registers living into block \p MBB. - void addLiveIns(const MachineBasicBlock &MBB); - - /// Adds all register units marked in the bitvector \p RegUnits. - void addUnits(const BitVector &RegUnits) { - Units |= RegUnits; - } - /// Removes all register units marked in the bitvector \p RegUnits. - void removeUnits(const BitVector &RegUnits) { - Units.reset(RegUnits); - } - /// Return the internal bitvector representation of the set. - const BitVector &getBitVector() const { - return Units; - } - -private: - /// Adds pristine registers. Pristine registers are callee saved registers - /// that are unused in the function. - void addPristines(const MachineFunction &MF); -}; - -/// Returns an iterator range over all physical register and mask operands for -/// \p MI and bundled instructions. This also skips any debug operands. -inline iterator_range>> -phys_regs_and_masks(const MachineInstr &MI) { - std::function Pred = - [](const MachineOperand &MOP) { - return MOP.isRegMask() || (MOP.isReg() && !MOP.isDebug() && - Register::isPhysicalRegister(MOP.getReg())); - }; - return make_filter_range(const_mi_bundle_ops(MI), Pred); -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_LIVEREGUNITS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveStacks.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveStacks.h deleted file mode 100644 index 1cbdb8bd86..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveStacks.h +++ /dev/null @@ -1,103 +0,0 @@ -//===- LiveStacks.h - Live Stack Slot Analysis ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the live stack slot analysis pass. It is analogous to -// live interval analysis except it's analyzing liveness of stack slots rather -// than registers. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVESTACKS_H -#define LLVM_CODEGEN_LIVESTACKS_H - -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" -#include -#include -#include - -namespace llvm { - -class TargetRegisterClass; -class TargetRegisterInfo; - -class LiveStacks : public MachineFunctionPass { - const TargetRegisterInfo *TRI; - - /// Special pool allocator for VNInfo's (LiveInterval val#). - /// - VNInfo::Allocator VNInfoAllocator; - - /// S2IMap - Stack slot indices to live interval mapping. - using SS2IntervalMap = std::unordered_map; - SS2IntervalMap S2IMap; - - /// S2RCMap - Stack slot indices to register class mapping. - std::map S2RCMap; - -public: - static char ID; // Pass identification, replacement for typeid - - LiveStacks() : MachineFunctionPass(ID) { - initializeLiveStacksPass(*PassRegistry::getPassRegistry()); - } - - using iterator = SS2IntervalMap::iterator; - using const_iterator = SS2IntervalMap::const_iterator; - - const_iterator begin() const { return S2IMap.begin(); } - const_iterator end() const { return S2IMap.end(); } - iterator begin() { return S2IMap.begin(); } - iterator end() { return S2IMap.end(); } - - unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } - - LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC); - - LiveInterval &getInterval(int Slot) { - assert(Slot >= 0 && "Spill slot indice must be >= 0"); - SS2IntervalMap::iterator I = S2IMap.find(Slot); - assert(I != S2IMap.end() && "Interval does not exist for stack slot"); - return I->second; - } - - const LiveInterval &getInterval(int Slot) const { - assert(Slot >= 0 && "Spill slot indice must be >= 0"); - SS2IntervalMap::const_iterator I = S2IMap.find(Slot); - assert(I != S2IMap.end() && "Interval does not exist for stack slot"); - return I->second; - } - - bool hasInterval(int Slot) const { return S2IMap.count(Slot); } - - const TargetRegisterClass *getIntervalRegClass(int Slot) const { - assert(Slot >= 0 && "Spill slot indice must be >= 0"); - std::map::const_iterator I = - S2RCMap.find(Slot); - assert(I != S2RCMap.end() && - "Register class info does not exist for stack slot"); - return I->second; - } - - VNInfo::Allocator &getVNInfoAllocator() { return VNInfoAllocator; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - - /// runOnMachineFunction - pass entry point - bool runOnMachineFunction(MachineFunction &) override; - - /// print - Implement the dump method. - void print(raw_ostream &O, const Module * = nullptr) const override; -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LiveVariables.h b/suite/synctools/tablegen/include/llvm/CodeGen/LiveVariables.h deleted file mode 100644 index dee316677b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LiveVariables.h +++ /dev/null @@ -1,320 +0,0 @@ -//===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the LiveVariables analysis pass. For each machine -// instruction in the function, this pass calculates the set of registers that -// are immediately dead after the instruction (i.e., the instruction calculates -// the value, but it is never used) and the set of registers that are used by -// the instruction, but are never used after the instruction (i.e., they are -// killed). -// -// This class computes live variables using a sparse implementation based on -// the machine code SSA form. This class computes live variable information for -// each virtual and _register allocatable_ physical register in a function. It -// uses the dominance properties of SSA form to efficiently compute live -// variables for virtual registers, and assumes that physical registers are only -// live within a single basic block (allowing it to do a single local analysis -// to resolve physical register lifetimes in each basic block). If a physical -// register is not register allocatable, it is not tracked. This is useful for -// things like the stack pointer and condition codes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEVARIABLES_H -#define LLVM_CODEGEN_LIVEVARIABLES_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SparseBitVector.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/InitializePasses.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineRegisterInfo; - -class LiveVariables : public MachineFunctionPass { -public: - static char ID; // Pass identification, replacement for typeid - LiveVariables() : MachineFunctionPass(ID) { - initializeLiveVariablesPass(*PassRegistry::getPassRegistry()); - } - - /// VarInfo - This represents the regions where a virtual register is live in - /// the program. We represent this with three different pieces of - /// information: the set of blocks in which the instruction is live - /// throughout, the set of blocks in which the instruction is actually used, - /// and the set of non-phi instructions that are the last users of the value. - /// - /// In the common case where a value is defined and killed in the same block, - /// There is one killing instruction, and AliveBlocks is empty. - /// - /// Otherwise, the value is live out of the block. If the value is live - /// throughout any blocks, these blocks are listed in AliveBlocks. Blocks - /// where the liveness range ends are not included in AliveBlocks, instead - /// being captured by the Kills set. In these blocks, the value is live into - /// the block (unless the value is defined and killed in the same block) and - /// lives until the specified instruction. Note that there cannot ever be a - /// value whose Kills set contains two instructions from the same basic block. - /// - /// PHI nodes complicate things a bit. If a PHI node is the last user of a - /// value in one of its predecessor blocks, it is not listed in the kills set, - /// but does include the predecessor block in the AliveBlocks set (unless that - /// block also defines the value). This leads to the (perfectly sensical) - /// situation where a value is defined in a block, and the last use is a phi - /// node in the successor. In this case, AliveBlocks is empty (the value is - /// not live across any blocks) and Kills is empty (phi nodes are not - /// included). This is sensical because the value must be live to the end of - /// the block, but is not live in any successor blocks. - struct VarInfo { - /// AliveBlocks - Set of blocks in which this value is alive completely - /// through. This is a bit set which uses the basic block number as an - /// index. - /// - SparseBitVector<> AliveBlocks; - - /// Kills - List of MachineInstruction's which are the last use of this - /// virtual register (kill it) in their basic block. - /// - std::vector Kills; - - /// removeKill - Delete a kill corresponding to the specified - /// machine instruction. Returns true if there was a kill - /// corresponding to this instruction, false otherwise. - bool removeKill(MachineInstr &MI) { - std::vector::iterator I = find(Kills, &MI); - if (I == Kills.end()) - return false; - Kills.erase(I); - return true; - } - - /// findKill - Find a kill instruction in MBB. Return NULL if none is found. - MachineInstr *findKill(const MachineBasicBlock *MBB) const; - - /// isLiveIn - Is Reg live in to MBB? This means that Reg is live through - /// MBB, or it is killed in MBB. If Reg is only used by PHI instructions in - /// MBB, it is not considered live in. - bool isLiveIn(const MachineBasicBlock &MBB, Register Reg, - MachineRegisterInfo &MRI); - - void dump() const; - }; - -private: - /// VirtRegInfo - This list is a mapping from virtual register number to - /// variable information. - /// - IndexedMap VirtRegInfo; - - /// PHIJoins - list of virtual registers that are PHI joins. These registers - /// may have multiple definitions, and they require special handling when - /// building live intervals. - SparseBitVector<> PHIJoins; - -private: // Intermediate data structures - MachineFunction *MF; - - MachineRegisterInfo* MRI; - - const TargetRegisterInfo *TRI; - - // PhysRegInfo - Keep track of which instruction was the last def of a - // physical register. This is a purely local property, because all physical - // register references are presumed dead across basic blocks. - std::vector PhysRegDef; - - // PhysRegInfo - Keep track of which instruction was the last use of a - // physical register. This is a purely local property, because all physical - // register references are presumed dead across basic blocks. - std::vector PhysRegUse; - - std::vector> PHIVarInfo; - - // DistanceMap - Keep track the distance of a MI from the start of the - // current basic block. - DenseMap DistanceMap; - - /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the - /// uses. Pay special attention to the sub-register uses which may come below - /// the last use of the whole register. - bool HandlePhysRegKill(Register Reg, MachineInstr *MI); - - /// HandleRegMask - Call HandlePhysRegKill for all registers clobbered by Mask. - void HandleRegMask(const MachineOperand&); - - void HandlePhysRegUse(Register Reg, MachineInstr &MI); - void HandlePhysRegDef(Register Reg, MachineInstr *MI, - SmallVectorImpl &Defs); - void UpdatePhysRegDefs(MachineInstr &MI, SmallVectorImpl &Defs); - - /// FindLastRefOrPartRef - Return the last reference or partial reference of - /// the specified register. - MachineInstr *FindLastRefOrPartRef(Register Reg); - - /// FindLastPartialDef - Return the last partial def of the specified - /// register. Also returns the sub-registers that're defined by the - /// instruction. - MachineInstr *FindLastPartialDef(Register Reg, - SmallSet &PartDefRegs); - - /// analyzePHINodes - Gather information about the PHI nodes in here. In - /// particular, we want to map the variable information of a virtual - /// register which is used in a PHI node. We map that to the BB the vreg - /// is coming from. - void analyzePHINodes(const MachineFunction& Fn); - - void runOnInstr(MachineInstr &MI, SmallVectorImpl &Defs); - - void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs); -public: - - bool runOnMachineFunction(MachineFunction &MF) override; - - /// RegisterDefIsDead - Return true if the specified instruction defines the - /// specified register, but that definition is dead. - bool RegisterDefIsDead(MachineInstr &MI, Register Reg) const; - - //===--------------------------------------------------------------------===// - // API to update live variable information - - /// Recompute liveness from scratch for a virtual register \p Reg that is - /// known to have a single def that dominates all uses. This can be useful - /// after removing some uses of \p Reg. It is not necessary for the whole - /// machine function to be in SSA form. - void recomputeForSingleDefVirtReg(Register Reg); - - /// replaceKillInstruction - Update register kill info by replacing a kill - /// instruction with a new one. - void replaceKillInstruction(Register Reg, MachineInstr &OldMI, - MachineInstr &NewMI); - - /// addVirtualRegisterKilled - Add information about the fact that the - /// specified register is killed after being used by the specified - /// instruction. If AddIfNotFound is true, add a implicit operand if it's - /// not found. - void addVirtualRegisterKilled(Register IncomingReg, MachineInstr &MI, - bool AddIfNotFound = false) { - if (MI.addRegisterKilled(IncomingReg, TRI, AddIfNotFound)) - getVarInfo(IncomingReg).Kills.push_back(&MI); - } - - /// removeVirtualRegisterKilled - Remove the specified kill of the virtual - /// register from the live variable information. Returns true if the - /// variable was marked as killed by the specified instruction, - /// false otherwise. - bool removeVirtualRegisterKilled(Register Reg, MachineInstr &MI) { - if (!getVarInfo(Reg).removeKill(MI)) - return false; - - bool Removed = false; - for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI.getOperand(i); - if (MO.isReg() && MO.isKill() && MO.getReg() == Reg) { - MO.setIsKill(false); - Removed = true; - break; - } - } - - assert(Removed && "Register is not used by this instruction!"); - (void)Removed; - return true; - } - - /// removeVirtualRegistersKilled - Remove all killed info for the specified - /// instruction. - void removeVirtualRegistersKilled(MachineInstr &MI); - - /// addVirtualRegisterDead - Add information about the fact that the specified - /// register is dead after being used by the specified instruction. If - /// AddIfNotFound is true, add a implicit operand if it's not found. - void addVirtualRegisterDead(Register IncomingReg, MachineInstr &MI, - bool AddIfNotFound = false) { - if (MI.addRegisterDead(IncomingReg, TRI, AddIfNotFound)) - getVarInfo(IncomingReg).Kills.push_back(&MI); - } - - /// removeVirtualRegisterDead - Remove the specified kill of the virtual - /// register from the live variable information. Returns true if the - /// variable was marked dead at the specified instruction, false - /// otherwise. - bool removeVirtualRegisterDead(Register Reg, MachineInstr &MI) { - if (!getVarInfo(Reg).removeKill(MI)) - return false; - - bool Removed = false; - for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI.getOperand(i); - if (MO.isReg() && MO.isDef() && MO.getReg() == Reg) { - MO.setIsDead(false); - Removed = true; - break; - } - } - assert(Removed && "Register is not defined by this instruction!"); - (void)Removed; - return true; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - void releaseMemory() override { - VirtRegInfo.clear(); - } - - /// getVarInfo - Return the VarInfo structure for the specified VIRTUAL - /// register. - VarInfo &getVarInfo(Register Reg); - - void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, - MachineBasicBlock *BB); - void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *DefBlock, - MachineBasicBlock *BB, - SmallVectorImpl &WorkList); - - void HandleVirtRegDef(Register reg, MachineInstr &MI); - void HandleVirtRegUse(Register reg, MachineBasicBlock *MBB, MachineInstr &MI); - - bool isLiveIn(Register Reg, const MachineBasicBlock &MBB) { - return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI); - } - - /// isLiveOut - Determine if Reg is live out from MBB, when not considering - /// PHI nodes. This means that Reg is either killed by a successor block or - /// passed through one. - bool isLiveOut(Register Reg, const MachineBasicBlock &MBB); - - /// addNewBlock - Add a new basic block BB between DomBB and SuccBB. All - /// variables that are live out of DomBB and live into SuccBB will be marked - /// as passing live through BB. This method assumes that the machine code is - /// still in SSA form. - void addNewBlock(MachineBasicBlock *BB, - MachineBasicBlock *DomBB, - MachineBasicBlock *SuccBB); - - void addNewBlock(MachineBasicBlock *BB, - MachineBasicBlock *DomBB, - MachineBasicBlock *SuccBB, - std::vector> &LiveInSets); - - /// isPHIJoin - Return true if Reg is a phi join register. - bool isPHIJoin(Register Reg) { return PHIJoins.test(Reg.id()); } - - /// setPHIJoin - Mark Reg as a phi join register. - void setPHIJoin(Register Reg) { PHIJoins.set(Reg.id()); } -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LoopTraversal.h b/suite/synctools/tablegen/include/llvm/CodeGen/LoopTraversal.h deleted file mode 100644 index eaa4594d92..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LoopTraversal.h +++ /dev/null @@ -1,115 +0,0 @@ -//==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Loop Traversal logic. -/// -/// This class provides the basic blocks traversal order used by passes like -/// ReachingDefAnalysis and ExecutionDomainFix. -/// It identifies basic blocks that are part of loops and should to be visited -/// twice and returns efficient traversal order for all the blocks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LOOPTRAVERSAL_H -#define LLVM_CODEGEN_LOOPTRAVERSAL_H - -#include "llvm/ADT/SmallVector.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; - -/// This class provides the basic blocks traversal order used by passes like -/// ReachingDefAnalysis and ExecutionDomainFix. -/// It identifies basic blocks that are part of loops and should to be visited -/// twice and returns efficient traversal order for all the blocks. -/// -/// We want to visit every instruction in every basic block in order to update -/// it's execution domain or collect clearance information. However, for the -/// clearance calculation, we need to know clearances from all predecessors -/// (including any backedges), therefore we need to visit some blocks twice. -/// As an example, consider the following loop. -/// -/// -/// PH -> A -> B (xmm -> xmm) -> C -> D -> EXIT -/// ^ | -/// +----------------------------------+ -/// -/// The iteration order this pass will return is as follows: -/// Optimized: PH A B C A' B' C' D -/// -/// The basic block order is constructed as follows: -/// Once we finish processing some block, we update the counters in MBBInfos -/// and re-process any successors that are now 'done'. -/// We call a block that is ready for its final round of processing `done` -/// (isBlockDone), e.g. when all predecessor information is known. -/// -/// Note that a naive traversal order would be to do two complete passes over -/// all basic blocks/instructions, the first for recording clearances, the -/// second for updating clearance based on backedges. -/// However, for functions without backedges, or functions with a lot of -/// straight-line code, and a small loop, that would be a lot of unnecessary -/// work (since only the BBs that are part of the loop require two passes). -/// -/// E.g., the naive iteration order for the above example is as follows: -/// Naive: PH A B C D A' B' C' D' -/// -/// In the optimized approach we avoid processing D twice, because we -/// can entirely process the predecessors before getting to D. -class LoopTraversal { -private: - struct MBBInfo { - /// Whether we have gotten to this block in primary processing yet. - bool PrimaryCompleted = false; - - /// The number of predecessors for which primary processing has completed - unsigned IncomingProcessed = 0; - - /// The value of `IncomingProcessed` at the start of primary processing - unsigned PrimaryIncoming = 0; - - /// The number of predecessors for which all processing steps are done. - unsigned IncomingCompleted = 0; - - MBBInfo() = default; - }; - using MBBInfoMap = SmallVector; - /// Helps keep track if we processed this block and all its predecessors. - MBBInfoMap MBBInfos; - -public: - struct TraversedMBBInfo { - /// The basic block. - MachineBasicBlock *MBB = nullptr; - - /// True if this is the first time we process the basic block. - bool PrimaryPass = true; - - /// True if the block that is ready for its final round of processing. - bool IsDone = true; - - TraversedMBBInfo(MachineBasicBlock *BB = nullptr, bool Primary = true, - bool Done = true) - : MBB(BB), PrimaryPass(Primary), IsDone(Done) {} - }; - LoopTraversal() = default; - - /// Identifies basic blocks that are part of loops and should to be - /// visited twice and returns efficient traversal order for all the blocks. - typedef SmallVector TraversalOrder; - TraversalOrder traverse(MachineFunction &MF); - -private: - /// Returens true if the block is ready for its final round of processing. - bool isBlockDone(MachineBasicBlock *MBB); -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_LOOPTRAVERSAL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/LowLevelType.h b/suite/synctools/tablegen/include/llvm/CodeGen/LowLevelType.h deleted file mode 100644 index 922f93d2e5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/LowLevelType.h +++ /dev/null @@ -1,45 +0,0 @@ -//== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Implement a low-level type suitable for MachineInstr level instruction -/// selection. -/// -/// This provides the CodeGen aspects of LowLevelType, such as Type conversion. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H -#define LLVM_CODEGEN_LOWLEVELTYPE_H - -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/LowLevelTypeImpl.h" - -namespace llvm { - -class DataLayout; -class Type; -struct fltSemantics; - -/// Construct a low-level type based on an LLVM type. -LLT getLLTForType(Type &Ty, const DataLayout &DL); - -/// Get a rough equivalent of an MVT for a given LLT. MVT can't distinguish -/// pointers, so these will convert to a plain integer. -MVT getMVTForLLT(LLT Ty); -EVT getApproximateEVTForLLT(LLT Ty, const DataLayout &DL, LLVMContext &Ctx); - -/// Get a rough equivalent of an LLT for a given MVT. LLT does not yet support -/// scalarable vector types, and will assert if used. -LLT getLLTForMVT(MVT Ty); - -/// Get the appropriate floating point arithmetic semantic based on the bit size -/// of the given scalar LLT. -const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty); -} - -#endif // LLVM_CODEGEN_LOWLEVELTYPE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MBFIWrapper.h b/suite/synctools/tablegen/include/llvm/CodeGen/MBFIWrapper.h deleted file mode 100644 index 7c0a4c6e02..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MBFIWrapper.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- llvm/CodeGen/MBFIWrapper.h -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class keeps track of branch frequencies of newly created blocks and -// tail-merged blocks. Used by the TailDuplication and MachineBlockPlacement. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MBFIWRAPPER_H -#define LLVM_CODEGEN_MBFIWRAPPER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/BlockFrequency.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineBlockFrequencyInfo; - -class MBFIWrapper { - public: - MBFIWrapper(const MachineBlockFrequencyInfo &I) : MBFI(I) {} - - BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const; - void setBlockFreq(const MachineBasicBlock *MBB, BlockFrequency F); - Optional getBlockProfileCount(const MachineBasicBlock *MBB) const; - - raw_ostream &printBlockFreq(raw_ostream &OS, - const MachineBasicBlock *MBB) const; - raw_ostream &printBlockFreq(raw_ostream &OS, - const BlockFrequency Freq) const; - void view(const Twine &Name, bool isSimple = true); - uint64_t getEntryFreq() const; - const MachineBlockFrequencyInfo &getMBFI() { return MBFI; } - - private: - const MachineBlockFrequencyInfo &MBFI; - DenseMap MergedBBFreq; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MBFIWRAPPER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRFSDiscriminator.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRFSDiscriminator.h deleted file mode 100644 index deb6b37a9b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRFSDiscriminator.h +++ /dev/null @@ -1,80 +0,0 @@ -//===----- MIRFSDiscriminator.h: MIR FS Discriminator Support --0-- c++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the supporting functions for adding Machine level IR -// Flow Sensitive discriminators to the instruction debug information. With -// this, a cloned machine instruction in a different MachineBasicBlock will -// have its own discriminator value. This is done in a MIRAddFSDiscriminators -// pass. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRFSDISCRIMINATOR_H -#define LLVM_CODEGEN_MIRFSDISCRIMINATOR_H - -#include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachinePostDominators.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/ProfileData/SampleProfReader.h" - -#include - -namespace llvm { - -using namespace sampleprof; -class MIRAddFSDiscriminators : public MachineFunctionPass { - MachineFunction *MF; - unsigned LowBit; - unsigned HighBit; - -public: - static char ID; - /// PassNum is the sequence number this pass is called, start from 1. - MIRAddFSDiscriminators(FSDiscriminatorPass P = FSDiscriminatorPass::Pass1) - : MachineFunctionPass(ID) { - LowBit = getFSPassBitBegin(P); - HighBit = getFSPassBitEnd(P); - assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit"); - } - - StringRef getPassName() const override { - return "Add FS discriminators in MIR"; - } - - /// getNumFSBBs() - Return the number of machine BBs that have FS samples. - unsigned getNumFSBBs(); - - /// getNumFSSamples() - Return the number of samples that have flow sensitive - /// values. - uint64_t getNumFSSamples(); - - /// getMachineFunction - Return the current machine function. - const MachineFunction *getMachineFunction() const { return MF; } - -private: - bool runOnMachineFunction(MachineFunction &) override; -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_MIRFSDISCRIMINATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRFormatter.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRFormatter.h deleted file mode 100644 index 12be5ede28..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRFormatter.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- llvm/CodeGen/MIRFormatter.h -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MIRFormatter class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRFORMATTER_H -#define LLVM_CODEGEN_MIRFORMATTER_H - -#include "llvm/ADT/Optional.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { - -class MachineFunction; -class MachineInstr; -struct PerFunctionMIParsingState; - -/// MIRFormater - Interface to format MIR operand based on target -class MIRFormatter { -public: - typedef function_ref - ErrorCallbackType; - - MIRFormatter() = default; - virtual ~MIRFormatter() = default; - - /// Implement target specific printing for machine operand immediate value, so - /// that we can have more meaningful mnemonic than a 64-bit integer. Passing - /// None to OpIdx means the index is unknown. - virtual void printImm(raw_ostream &OS, const MachineInstr &MI, - Optional OpIdx, int64_t Imm) const { - OS << Imm; - } - - /// Implement target specific parsing of immediate mnemonics. The mnemonic is - /// dot separated strings. - virtual bool parseImmMnemonic(const unsigned OpCode, const unsigned OpIdx, - StringRef Src, int64_t &Imm, - ErrorCallbackType ErrorCallback) const { - llvm_unreachable("target did not implement parsing MIR immediate mnemonic"); - } - - /// Implement target specific printing of target custom pseudo source value. - /// Default implementation is not necessarily the correct MIR serialization - /// format. - virtual void - printCustomPseudoSourceValue(raw_ostream &OS, ModuleSlotTracker &MST, - const PseudoSourceValue &PSV) const { - PSV.printCustom(OS); - } - - /// Implement target specific parsing of target custom pseudo source value. - virtual bool parseCustomPseudoSourceValue( - StringRef Src, MachineFunction &MF, PerFunctionMIParsingState &PFS, - const PseudoSourceValue *&PSV, ErrorCallbackType ErrorCallback) const { - llvm_unreachable( - "target did not implement parsing MIR custom pseudo source value"); - } - - /// Helper functions to print IR value as MIR serialization format which will - /// be useful for target specific printer, e.g. for printing IR value in - /// custom pseudo source value. - static void printIRValue(raw_ostream &OS, const Value &V, - ModuleSlotTracker &MST); - - /// Helper functions to parse IR value from MIR serialization format which - /// will be useful for target specific parser, e.g. for parsing IR value for - /// custom pseudo source value. - static bool parseIRValue(StringRef Src, MachineFunction &MF, - PerFunctionMIParsingState &PFS, const Value *&V, - ErrorCallbackType ErrorCallback); -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIParser.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIParser.h deleted file mode 100644 index b01a0c7aa0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIParser.h +++ /dev/null @@ -1,246 +0,0 @@ -//===- MIParser.h - Machine Instructions Parser -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the function that parses the machine instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRPARSER_MIPARSER_H -#define LLVM_CODEGEN_MIRPARSER_MIPARSER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/SMLoc.h" -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; -class MDNode; -class RegisterBank; -struct SlotMapping; -class SMDiagnostic; -class SourceMgr; -class StringRef; -class TargetRegisterClass; -class TargetSubtargetInfo; - -struct VRegInfo { - enum uint8_t { - UNKNOWN, NORMAL, GENERIC, REGBANK - } Kind = UNKNOWN; - bool Explicit = false; ///< VReg was explicitly specified in the .mir file. - union { - const TargetRegisterClass *RC; - const RegisterBank *RegBank; - } D; - Register VReg; - Register PreferredReg; -}; - -using Name2RegClassMap = StringMap; -using Name2RegBankMap = StringMap; - -struct PerTargetMIParsingState { -private: - const TargetSubtargetInfo &Subtarget; - - /// Maps from instruction names to op codes. - StringMap Names2InstrOpCodes; - - /// Maps from register names to registers. - StringMap Names2Regs; - - /// Maps from register mask names to register masks. - StringMap Names2RegMasks; - - /// Maps from subregister names to subregister indices. - StringMap Names2SubRegIndices; - - /// Maps from target index names to target indices. - StringMap Names2TargetIndices; - - /// Maps from direct target flag names to the direct target flag values. - StringMap Names2DirectTargetFlags; - - /// Maps from direct target flag names to the bitmask target flag values. - StringMap Names2BitmaskTargetFlags; - - /// Maps from MMO target flag names to MMO target flag values. - StringMap Names2MMOTargetFlags; - - /// Maps from register class names to register classes. - Name2RegClassMap Names2RegClasses; - - /// Maps from register bank names to register banks. - Name2RegBankMap Names2RegBanks; - - void initNames2InstrOpCodes(); - void initNames2Regs(); - void initNames2RegMasks(); - void initNames2SubRegIndices(); - void initNames2TargetIndices(); - void initNames2DirectTargetFlags(); - void initNames2BitmaskTargetFlags(); - void initNames2MMOTargetFlags(); - - void initNames2RegClasses(); - void initNames2RegBanks(); - -public: - /// Try to convert an instruction name to an opcode. Return true if the - /// instruction name is invalid. - bool parseInstrName(StringRef InstrName, unsigned &OpCode); - - /// Try to convert a register name to a register number. Return true if the - /// register name is invalid. - bool getRegisterByName(StringRef RegName, Register &Reg); - - /// Check if the given identifier is a name of a register mask. - /// - /// Return null if the identifier isn't a register mask. - const uint32_t *getRegMask(StringRef Identifier); - - /// Check if the given identifier is a name of a subregister index. - /// - /// Return 0 if the name isn't a subregister index class. - unsigned getSubRegIndex(StringRef Name); - - /// Try to convert a name of target index to the corresponding target index. - /// - /// Return true if the name isn't a name of a target index. - bool getTargetIndex(StringRef Name, int &Index); - - /// Try to convert a name of a direct target flag to the corresponding - /// target flag. - /// - /// Return true if the name isn't a name of a direct flag. - bool getDirectTargetFlag(StringRef Name, unsigned &Flag); - - /// Try to convert a name of a bitmask target flag to the corresponding - /// target flag. - /// - /// Return true if the name isn't a name of a bitmask target flag. - bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag); - - /// Try to convert a name of a MachineMemOperand target flag to the - /// corresponding target flag. - /// - /// Return true if the name isn't a name of a target MMO flag. - bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag); - - /// Check if the given identifier is a name of a register class. - /// - /// Return null if the name isn't a register class. - const TargetRegisterClass *getRegClass(StringRef Name); - - /// Check if the given identifier is a name of a register bank. - /// - /// Return null if the name isn't a register bank. - const RegisterBank *getRegBank(StringRef Name); - - PerTargetMIParsingState(const TargetSubtargetInfo &STI) - : Subtarget(STI) { - initNames2RegClasses(); - initNames2RegBanks(); - } - - ~PerTargetMIParsingState() = default; - - void setTarget(const TargetSubtargetInfo &NewSubtarget); -}; - -struct PerFunctionMIParsingState { - BumpPtrAllocator Allocator; - MachineFunction &MF; - SourceMgr *SM; - const SlotMapping &IRSlots; - PerTargetMIParsingState &Target; - - std::map MachineMetadataNodes; - std::map> MachineForwardRefMDNodes; - - DenseMap MBBSlots; - DenseMap VRegInfos; - StringMap VRegInfosNamed; - DenseMap FixedStackObjectSlots; - DenseMap StackObjectSlots; - DenseMap ConstantPoolSlots; - DenseMap JumpTableSlots; - - /// Maps from slot numbers to function's unnamed values. - DenseMap Slots2Values; - - PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, - const SlotMapping &IRSlots, - PerTargetMIParsingState &Target); - - VRegInfo &getVRegInfo(Register Num); - VRegInfo &getVRegInfoNamed(StringRef RegName); - const Value *getIRValue(unsigned Slot); -}; - -/// Parse the machine basic block definitions, and skip the machine -/// instructions. -/// -/// This function runs the first parsing pass on the machine function's body. -/// It parses only the machine basic block definitions and creates the machine -/// basic blocks in the given machine function. -/// -/// The machine instructions aren't parsed during the first pass because all -/// the machine basic blocks aren't defined yet - this makes it impossible to -/// resolve the machine basic block references. -/// -/// Return true if an error occurred. -bool parseMachineBasicBlockDefinitions(PerFunctionMIParsingState &PFS, - StringRef Src, SMDiagnostic &Error); - -/// Parse the machine instructions. -/// -/// This function runs the second parsing pass on the machine function's body. -/// It skips the machine basic block definitions and parses only the machine -/// instructions and basic block attributes like liveins and successors. -/// -/// The second parsing pass assumes that the first parsing pass already ran -/// on the given source string. -/// -/// Return true if an error occurred. -bool parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src, - SMDiagnostic &Error); - -bool parseMBBReference(PerFunctionMIParsingState &PFS, - MachineBasicBlock *&MBB, StringRef Src, - SMDiagnostic &Error); - -bool parseRegisterReference(PerFunctionMIParsingState &PFS, - Register &Reg, StringRef Src, - SMDiagnostic &Error); - -bool parseNamedRegisterReference(PerFunctionMIParsingState &PFS, Register &Reg, - StringRef Src, SMDiagnostic &Error); - -bool parseVirtualRegisterReference(PerFunctionMIParsingState &PFS, - VRegInfo *&Info, StringRef Src, - SMDiagnostic &Error); - -bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI, - StringRef Src, SMDiagnostic &Error); - -bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, - SMDiagnostic &Error); - -bool parseMachineMetadata(PerFunctionMIParsingState &PFS, StringRef Src, - SMRange SourceRange, SMDiagnostic &Error); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MIRPARSER_MIPARSER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIRParser.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIRParser.h deleted file mode 100644 index a7c69e2d43..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRParser/MIRParser.h +++ /dev/null @@ -1,88 +0,0 @@ -//===- MIRParser.h - MIR serialization format parser ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This MIR serialization library is currently a work in progress. It can't -// serialize machine functions at this time. -// -// This file declares the functions that parse the MIR serialization format -// files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H -#define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H - -#include "llvm/IR/Module.h" -#include "llvm/Support/MemoryBuffer.h" -#include - -namespace llvm { - -class Function; -class MIRParserImpl; -class MachineModuleInfo; -class SMDiagnostic; -class StringRef; - -typedef llvm::function_ref(StringRef)> - DataLayoutCallbackTy; - -/// This class initializes machine functions by applying the state loaded from -/// a MIR file. -class MIRParser { - std::unique_ptr Impl; - -public: - MIRParser(std::unique_ptr Impl); - MIRParser(const MIRParser &) = delete; - ~MIRParser(); - - /// Parses the optional LLVM IR module in the MIR file. - /// - /// A new, empty module is created if the LLVM IR isn't present. - /// \returns nullptr if a parsing error occurred. - std::unique_ptr parseIRModule( - DataLayoutCallbackTy DataLayoutCallback = [](StringRef) { return None; }); - - /// Parses MachineFunctions in the MIR file and add them to the given - /// MachineModuleInfo \p MMI. - /// - /// \returns true if an error occurred. - bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI); -}; - -/// This function is the main interface to the MIR serialization format parser. -/// -/// It reads in a MIR file and returns a MIR parser that can parse the embedded -/// LLVM IR module and initialize the machine functions by parsing the machine -/// function's state. -/// -/// \param Filename - The name of the file to parse. -/// \param Error - Error result info. -/// \param Context - Context which will be used for the parsed LLVM IR module. -/// \param ProcessIRFunction - function to run on every IR function or stub -/// loaded from the MIR file. -std::unique_ptr createMIRParserFromFile( - StringRef Filename, SMDiagnostic &Error, LLVMContext &Context, - std::function ProcessIRFunction = nullptr); - -/// This function is another interface to the MIR serialization format parser. -/// -/// It returns a MIR parser that works with the given memory buffer and that can -/// parse the embedded LLVM IR module and initialize the machine functions by -/// parsing the machine function's state. -/// -/// \param Contents - The MemoryBuffer containing the machine level IR. -/// \param Context - Context which will be used for the parsed LLVM IR module. -std::unique_ptr -createMIRParser(std::unique_ptr Contents, LLVMContext &Context, - std::function ProcessIRFunction = nullptr); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MIRPARSER_MIRPARSER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRPrinter.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRPrinter.h deleted file mode 100644 index 5e94418d5f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRPrinter.h +++ /dev/null @@ -1,45 +0,0 @@ -//===- MIRPrinter.h - MIR serialization format printer ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the functions that print out the LLVM IR and the machine -// functions using the MIR serialization format. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRPRINTER_H -#define LLVM_CODEGEN_MIRPRINTER_H - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; -class Module; -class raw_ostream; -template class SmallVectorImpl; - -/// Print LLVM IR using the MIR serialization format to the given output stream. -void printMIR(raw_ostream &OS, const Module &M); - -/// Print a machine function using the MIR serialization format to the given -/// output stream. -void printMIR(raw_ostream &OS, const MachineFunction &MF); - -/// Determine a possible list of successors of a basic block based on the -/// basic block machine operand being used inside the block. This should give -/// you the correct list of successor blocks in most cases except for things -/// like jump tables where the basic block references can't easily be found. -/// The MIRPRinter will skip printing successors if they match the result of -/// this function and the parser will use this function to construct a list if -/// it is missing. -void guessSuccessors(const MachineBasicBlock &MBB, - SmallVectorImpl &Result, - bool &IsFallthrough); - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRSampleProfile.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRSampleProfile.h deleted file mode 100644 index a9638fc3fd..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRSampleProfile.h +++ /dev/null @@ -1,76 +0,0 @@ -//===----- MIRSampleProfile.h: SampleFDO Support in MIR ---*- c++ -*-------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the supporting functions for machine level Sample FDO -// loader. This is used in Flow Sensitive SampelFDO. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRSAMPLEPROFILE_H -#define LLVM_CODEGEN_MIRSAMPLEPROFILE_H - -#include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachinePostDominators.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/ProfileData/SampleProfReader.h" - -#include - -namespace llvm { - -using namespace sampleprof; - -class MIRProfileLoader; -class MIRProfileLoaderPass : public MachineFunctionPass { - MachineFunction *MF; - std::string ProfileFileName; - FSDiscriminatorPass P; - unsigned LowBit; - unsigned HighBit; - -public: - static char ID; - /// FS bits will only use the '1' bits in the Mask. - MIRProfileLoaderPass(std::string FileName = "", - std::string RemappingFileName = "", - FSDiscriminatorPass P = FSDiscriminatorPass::Pass1); - - /// getMachineFunction - Return the last machine function computed. - const MachineFunction *getMachineFunction() const { return MF; } - - StringRef getPassName() const override { return "SampleFDO loader in MIR"; } - -private: - void init(MachineFunction &MF); - bool runOnMachineFunction(MachineFunction &) override; - bool doInitialization(Module &M) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - - std::unique_ptr MIRSampleLoader; - /// Hold the information of the basic block frequency. - MachineBlockFrequencyInfo *MBFI; -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_MIRSAMPLEPROFILE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MIRYamlMapping.h b/suite/synctools/tablegen/include/llvm/CodeGen/MIRYamlMapping.h deleted file mode 100644 index 02eb5d2427..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MIRYamlMapping.h +++ /dev/null @@ -1,760 +0,0 @@ -//===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the mapping between various MIR data structures and -// their corresponding YAML representation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MIRYAMLMAPPING_H -#define LLVM_CODEGEN_MIRYAMLMAPPING_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include - -namespace llvm { -namespace yaml { - -/// A wrapper around std::string which contains a source range that's being -/// set during parsing. -struct StringValue { - std::string Value; - SMRange SourceRange; - - StringValue() = default; - StringValue(std::string Value) : Value(std::move(Value)) {} - StringValue(const char Val[]) : Value(Val) {} - - bool operator==(const StringValue &Other) const { - return Value == Other.Value; - } -}; - -template <> struct ScalarTraits { - static void output(const StringValue &S, void *, raw_ostream &OS) { - OS << S.Value; - } - - static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) { - S.Value = Scalar.str(); - if (const auto *Node = - reinterpret_cast(Ctx)->getCurrentNode()) - S.SourceRange = Node->getSourceRange(); - return ""; - } - - static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } -}; - -struct FlowStringValue : StringValue { - FlowStringValue() = default; - FlowStringValue(std::string Value) : StringValue(std::move(Value)) {} -}; - -template <> struct ScalarTraits { - static void output(const FlowStringValue &S, void *, raw_ostream &OS) { - return ScalarTraits::output(S, nullptr, OS); - } - - static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) { - return ScalarTraits::input(Scalar, Ctx, S); - } - - static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } -}; - -struct BlockStringValue { - StringValue Value; - - bool operator==(const BlockStringValue &Other) const { - return Value == Other.Value; - } -}; - -template <> struct BlockScalarTraits { - static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) { - return ScalarTraits::output(S.Value, Ctx, OS); - } - - static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) { - return ScalarTraits::input(Scalar, Ctx, S.Value); - } -}; - -/// A wrapper around unsigned which contains a source range that's being set -/// during parsing. -struct UnsignedValue { - unsigned Value = 0; - SMRange SourceRange; - - UnsignedValue() = default; - UnsignedValue(unsigned Value) : Value(Value) {} - - bool operator==(const UnsignedValue &Other) const { - return Value == Other.Value; - } -}; - -template <> struct ScalarTraits { - static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) { - return ScalarTraits::output(Value.Value, Ctx, OS); - } - - static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) { - if (const auto *Node = - reinterpret_cast(Ctx)->getCurrentNode()) - Value.SourceRange = Node->getSourceRange(); - return ScalarTraits::input(Scalar, Ctx, Value.Value); - } - - static QuotingType mustQuote(StringRef Scalar) { - return ScalarTraits::mustQuote(Scalar); - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(yaml::IO &IO, - MachineJumpTableInfo::JTEntryKind &EntryKind) { - IO.enumCase(EntryKind, "block-address", - MachineJumpTableInfo::EK_BlockAddress); - IO.enumCase(EntryKind, "gp-rel64-block-address", - MachineJumpTableInfo::EK_GPRel64BlockAddress); - IO.enumCase(EntryKind, "gp-rel32-block-address", - MachineJumpTableInfo::EK_GPRel32BlockAddress); - IO.enumCase(EntryKind, "label-difference32", - MachineJumpTableInfo::EK_LabelDifference32); - IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline); - IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32); - } -}; - -template <> struct ScalarTraits { - static void output(const MaybeAlign &Alignment, void *, - llvm::raw_ostream &out) { - out << uint64_t(Alignment ? Alignment->value() : 0U); - } - static StringRef input(StringRef Scalar, void *, MaybeAlign &Alignment) { - unsigned long long n; - if (getAsUnsignedInteger(Scalar, 10, n)) - return "invalid number"; - if (n > 0 && !isPowerOf2_64(n)) - return "must be 0 or a power of two"; - Alignment = MaybeAlign(n); - return StringRef(); - } - static QuotingType mustQuote(StringRef) { return QuotingType::None; } -}; - -template <> struct ScalarTraits { - static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) { - OS << Alignment.value(); - } - static StringRef input(StringRef Scalar, void *, Align &Alignment) { - unsigned long long N; - if (getAsUnsignedInteger(Scalar, 10, N)) - return "invalid number"; - if (!isPowerOf2_64(N)) - return "must be a power of two"; - Alignment = Align(N); - return StringRef(); - } - static QuotingType mustQuote(StringRef) { return QuotingType::None; } -}; - -} // end namespace yaml -} // end namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue) - -namespace llvm { -namespace yaml { - -struct VirtualRegisterDefinition { - UnsignedValue ID; - StringValue Class; - StringValue PreferredRegister; - - // TODO: Serialize the target specific register hints. - - bool operator==(const VirtualRegisterDefinition &Other) const { - return ID == Other.ID && Class == Other.Class && - PreferredRegister == Other.PreferredRegister; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { - YamlIO.mapRequired("id", Reg.ID); - YamlIO.mapRequired("class", Reg.Class); - YamlIO.mapOptional("preferred-register", Reg.PreferredRegister, - StringValue()); // Don't print out when it's empty. - } - - static const bool flow = true; -}; - -struct MachineFunctionLiveIn { - StringValue Register; - StringValue VirtualRegister; - - bool operator==(const MachineFunctionLiveIn &Other) const { - return Register == Other.Register && - VirtualRegister == Other.VirtualRegister; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { - YamlIO.mapRequired("reg", LiveIn.Register); - YamlIO.mapOptional( - "virtual-reg", LiveIn.VirtualRegister, - StringValue()); // Don't print the virtual register when it's empty. - } - - static const bool flow = true; -}; - -/// Serializable representation of stack object from the MachineFrameInfo class. -/// -/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are -/// determined by the object's type and frame information flags. -/// Dead stack objects aren't serialized. -/// -/// The 'isPreallocated' flag is determined by the local offset. -struct MachineStackObject { - enum ObjectType { DefaultType, SpillSlot, VariableSized }; - UnsignedValue ID; - StringValue Name; - // TODO: Serialize unnamed LLVM alloca reference. - ObjectType Type = DefaultType; - int64_t Offset = 0; - uint64_t Size = 0; - MaybeAlign Alignment = None; - TargetStackID::Value StackID; - StringValue CalleeSavedRegister; - bool CalleeSavedRestored = true; - Optional LocalOffset; - StringValue DebugVar; - StringValue DebugExpr; - StringValue DebugLoc; - - bool operator==(const MachineStackObject &Other) const { - return ID == Other.ID && Name == Other.Name && Type == Other.Type && - Offset == Other.Offset && Size == Other.Size && - Alignment == Other.Alignment && - StackID == Other.StackID && - CalleeSavedRegister == Other.CalleeSavedRegister && - CalleeSavedRestored == Other.CalleeSavedRestored && - LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar && - DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc; - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { - IO.enumCase(Type, "default", MachineStackObject::DefaultType); - IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); - IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); - } -}; - -template <> struct MappingTraits { - static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { - YamlIO.mapRequired("id", Object.ID); - YamlIO.mapOptional("name", Object.Name, - StringValue()); // Don't print out an empty name. - YamlIO.mapOptional( - "type", Object.Type, - MachineStackObject::DefaultType); // Don't print the default type. - YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); - if (Object.Type != MachineStackObject::VariableSized) - YamlIO.mapRequired("size", Object.Size); - YamlIO.mapOptional("alignment", Object.Alignment, None); - YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); - YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, - true); - YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional()); - YamlIO.mapOptional("debug-info-variable", Object.DebugVar, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("debug-info-location", Object.DebugLoc, - StringValue()); // Don't print it out when it's empty. - } - - static const bool flow = true; -}; - -/// Serializable representation of the fixed stack object from the -/// MachineFrameInfo class. -struct FixedMachineStackObject { - enum ObjectType { DefaultType, SpillSlot }; - UnsignedValue ID; - ObjectType Type = DefaultType; - int64_t Offset = 0; - uint64_t Size = 0; - MaybeAlign Alignment = None; - TargetStackID::Value StackID; - bool IsImmutable = false; - bool IsAliased = false; - StringValue CalleeSavedRegister; - bool CalleeSavedRestored = true; - StringValue DebugVar; - StringValue DebugExpr; - StringValue DebugLoc; - - bool operator==(const FixedMachineStackObject &Other) const { - return ID == Other.ID && Type == Other.Type && Offset == Other.Offset && - Size == Other.Size && Alignment == Other.Alignment && - StackID == Other.StackID && - IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased && - CalleeSavedRegister == Other.CalleeSavedRegister && - CalleeSavedRestored == Other.CalleeSavedRestored && - DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr - && DebugLoc == Other.DebugLoc; - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(yaml::IO &IO, - FixedMachineStackObject::ObjectType &Type) { - IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); - IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { - IO.enumCase(ID, "default", TargetStackID::Default); - IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); - IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector); - IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal); - IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); - } -}; - -template <> struct MappingTraits { - static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { - YamlIO.mapRequired("id", Object.ID); - YamlIO.mapOptional( - "type", Object.Type, - FixedMachineStackObject::DefaultType); // Don't print the default type. - YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); - YamlIO.mapOptional("size", Object.Size, (uint64_t)0); - YamlIO.mapOptional("alignment", Object.Alignment, None); - YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); - if (Object.Type != FixedMachineStackObject::SpillSlot) { - YamlIO.mapOptional("isImmutable", Object.IsImmutable, false); - YamlIO.mapOptional("isAliased", Object.IsAliased, false); - } - YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, - true); - YamlIO.mapOptional("debug-info-variable", Object.DebugVar, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("debug-info-location", Object.DebugLoc, - StringValue()); // Don't print it out when it's empty. - } - - static const bool flow = true; -}; - -/// A serializaable representation of a reference to a stack object or fixed -/// stack object. -struct FrameIndex { - // The frame index as printed. This is always a positive number, even for - // fixed objects. To obtain the real index, - // MachineFrameInfo::getObjectIndexBegin has to be added. - int FI; - bool IsFixed; - SMRange SourceRange; - - FrameIndex() = default; - FrameIndex(int FI, const llvm::MachineFrameInfo &MFI); - - Expected getFI(const llvm::MachineFrameInfo &MFI) const; -}; - -template <> struct ScalarTraits { - static void output(const FrameIndex &FI, void *, raw_ostream &OS) { - MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, ""); - } - - static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) { - FI.IsFixed = false; - StringRef Num; - if (Scalar.startswith("%stack.")) { - Num = Scalar.substr(7); - } else if (Scalar.startswith("%fixed-stack.")) { - Num = Scalar.substr(13); - FI.IsFixed = true; - } else { - return "Invalid frame index, needs to start with %stack. or " - "%fixed-stack."; - } - if (Num.consumeInteger(10, FI.FI)) - return "Invalid frame index, not a valid number"; - - if (const auto *Node = - reinterpret_cast(Ctx)->getCurrentNode()) - FI.SourceRange = Node->getSourceRange(); - return StringRef(); - } - - static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } -}; - -/// Serializable representation of CallSiteInfo. -struct CallSiteInfo { - // Representation of call argument and register which is used to - // transfer it. - struct ArgRegPair { - StringValue Reg; - uint16_t ArgNo; - - bool operator==(const ArgRegPair &Other) const { - return Reg == Other.Reg && ArgNo == Other.ArgNo; - } - }; - - /// Identifies call instruction location in machine function. - struct MachineInstrLoc { - unsigned BlockNum; - unsigned Offset; - - bool operator==(const MachineInstrLoc &Other) const { - return BlockNum == Other.BlockNum && Offset == Other.Offset; - } - }; - - MachineInstrLoc CallLocation; - std::vector ArgForwardingRegs; - - bool operator==(const CallSiteInfo &Other) const { - return CallLocation.BlockNum == Other.CallLocation.BlockNum && - CallLocation.Offset == Other.CallLocation.Offset; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) { - YamlIO.mapRequired("arg", ArgReg.ArgNo); - YamlIO.mapRequired("reg", ArgReg.Reg); - } - - static const bool flow = true; -}; -} -} - -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair) - -namespace llvm { -namespace yaml { - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) { - YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum); - YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); - YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, - std::vector()); - } - - static const bool flow = true; -}; - -/// Serializable representation of debug value substitutions. -struct DebugValueSubstitution { - unsigned SrcInst; - unsigned SrcOp; - unsigned DstInst; - unsigned DstOp; - unsigned Subreg; - - bool operator==(const DebugValueSubstitution &Other) const { - return std::tie(SrcInst, SrcOp, DstInst, DstOp) == - std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) { - YamlIO.mapRequired("srcinst", Sub.SrcInst); - YamlIO.mapRequired("srcop", Sub.SrcOp); - YamlIO.mapRequired("dstinst", Sub.DstInst); - YamlIO.mapRequired("dstop", Sub.DstOp); - YamlIO.mapRequired("subreg", Sub.Subreg); - } - - static const bool flow = true; -}; -} // namespace yaml -} // namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution) - -namespace llvm { -namespace yaml { -struct MachineConstantPoolValue { - UnsignedValue ID; - StringValue Value; - MaybeAlign Alignment = None; - bool IsTargetSpecific = false; - - bool operator==(const MachineConstantPoolValue &Other) const { - return ID == Other.ID && Value == Other.Value && - Alignment == Other.Alignment && - IsTargetSpecific == Other.IsTargetSpecific; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { - YamlIO.mapRequired("id", Constant.ID); - YamlIO.mapOptional("value", Constant.Value, StringValue()); - YamlIO.mapOptional("alignment", Constant.Alignment, None); - YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false); - } -}; - -struct MachineJumpTable { - struct Entry { - UnsignedValue ID; - std::vector Blocks; - - bool operator==(const Entry &Other) const { - return ID == Other.ID && Blocks == Other.Blocks; - } - }; - - MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32; - std::vector Entries; - - bool operator==(const MachineJumpTable &Other) const { - return Kind == Other.Kind && Entries == Other.Entries; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) { - YamlIO.mapRequired("id", Entry.ID); - YamlIO.mapOptional("blocks", Entry.Blocks, std::vector()); - } -}; - -} // end namespace yaml -} // end namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) - -namespace llvm { -namespace yaml { - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineJumpTable &JT) { - YamlIO.mapRequired("kind", JT.Kind); - YamlIO.mapOptional("entries", JT.Entries, - std::vector()); - } -}; - -/// Serializable representation of MachineFrameInfo. -/// -/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and -/// 'RealignOption' as they are determined by the target and LLVM function -/// attributes. -/// It also doesn't serialize attributes like 'NumFixedObject' and -/// 'HasVarSizedObjects' as they are determined by the frame objects themselves. -struct MachineFrameInfo { - bool IsFrameAddressTaken = false; - bool IsReturnAddressTaken = false; - bool HasStackMap = false; - bool HasPatchPoint = false; - uint64_t StackSize = 0; - int OffsetAdjustment = 0; - unsigned MaxAlignment = 0; - bool AdjustsStack = false; - bool HasCalls = false; - StringValue StackProtector; - // TODO: Serialize FunctionContextIdx - unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet. - unsigned CVBytesOfCalleeSavedRegisters = 0; - bool HasOpaqueSPAdjustment = false; - bool HasVAStart = false; - bool HasMustTailInVarArgFunc = false; - bool HasTailCall = false; - unsigned LocalFrameSize = 0; - StringValue SavePoint; - StringValue RestorePoint; - - bool operator==(const MachineFrameInfo &Other) const { - return IsFrameAddressTaken == Other.IsFrameAddressTaken && - IsReturnAddressTaken == Other.IsReturnAddressTaken && - HasStackMap == Other.HasStackMap && - HasPatchPoint == Other.HasPatchPoint && - StackSize == Other.StackSize && - OffsetAdjustment == Other.OffsetAdjustment && - MaxAlignment == Other.MaxAlignment && - AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls && - StackProtector == Other.StackProtector && - MaxCallFrameSize == Other.MaxCallFrameSize && - CVBytesOfCalleeSavedRegisters == - Other.CVBytesOfCalleeSavedRegisters && - HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment && - HasVAStart == Other.HasVAStart && - HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && - HasTailCall == Other.HasTailCall && - LocalFrameSize == Other.LocalFrameSize && - SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint; - } -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { - YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false); - YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false); - YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false); - YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false); - YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0); - YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0); - YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0); - YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false); - YamlIO.mapOptional("hasCalls", MFI.HasCalls, false); - YamlIO.mapOptional("stackProtector", MFI.StackProtector, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0); - YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters", - MFI.CVBytesOfCalleeSavedRegisters, 0U); - YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment, - false); - YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); - YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc, - false); - YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false); - YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0); - YamlIO.mapOptional("savePoint", MFI.SavePoint, - StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("restorePoint", MFI.RestorePoint, - StringValue()); // Don't print it out when it's empty. - } -}; - -/// Targets should override this in a way that mirrors the implementation of -/// llvm::MachineFunctionInfo. -struct MachineFunctionInfo { - virtual ~MachineFunctionInfo() = default; - virtual void mappingImpl(IO &YamlIO) {} -}; - -template <> struct MappingTraits> { - static void mapping(IO &YamlIO, std::unique_ptr &MFI) { - if (MFI) - MFI->mappingImpl(YamlIO); - } -}; - -struct MachineFunction { - StringRef Name; - MaybeAlign Alignment = None; - bool ExposesReturnsTwice = false; - // GISel MachineFunctionProperties. - bool Legalized = false; - bool RegBankSelected = false; - bool Selected = false; - bool FailedISel = false; - // Register information - bool TracksRegLiveness = false; - bool HasWinCFI = false; - bool FailsVerification = false; - bool TracksDebugUserValues = false; - std::vector VirtualRegisters; - std::vector LiveIns; - Optional> CalleeSavedRegisters; - // TODO: Serialize the various register masks. - // Frame information - MachineFrameInfo FrameInfo; - std::vector FixedStackObjects; - std::vector StackObjects; - std::vector Constants; /// Constant pool. - std::unique_ptr MachineFuncInfo; - std::vector CallSitesInfo; - std::vector DebugValueSubstitutions; - MachineJumpTable JumpTableInfo; - std::vector MachineMetadataNodes; - BlockStringValue Body; -}; - -template <> struct MappingTraits { - static void mapping(IO &YamlIO, MachineFunction &MF) { - YamlIO.mapRequired("name", MF.Name); - YamlIO.mapOptional("alignment", MF.Alignment, None); - YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false); - YamlIO.mapOptional("legalized", MF.Legalized, false); - YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false); - YamlIO.mapOptional("selected", MF.Selected, false); - YamlIO.mapOptional("failedISel", MF.FailedISel, false); - YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); - YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false); - YamlIO.mapOptional("failsVerification", MF.FailsVerification, false); - YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues, - false); - YamlIO.mapOptional("registers", MF.VirtualRegisters, - std::vector()); - YamlIO.mapOptional("liveins", MF.LiveIns, - std::vector()); - YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters, - Optional>()); - YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo()); - YamlIO.mapOptional("fixedStack", MF.FixedStackObjects, - std::vector()); - YamlIO.mapOptional("stack", MF.StackObjects, - std::vector()); - YamlIO.mapOptional("callSites", MF.CallSitesInfo, - std::vector()); - YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions, - std::vector()); - YamlIO.mapOptional("constants", MF.Constants, - std::vector()); - YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); - if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) - YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable()); - if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty()) - YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes, - std::vector()); - YamlIO.mapOptional("body", MF.Body, BlockStringValue()); - } -}; - -} // end namespace yaml -} // end namespace llvm - -#endif // LLVM_CODEGEN_MIRYAMLMAPPING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachORelocation.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachORelocation.h deleted file mode 100644 index 0185c7cbe0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachORelocation.h +++ /dev/null @@ -1,55 +0,0 @@ -//=== MachORelocation.h - Mach-O Relocation Info ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachORelocation class. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CODEGEN_MACHORELOCATION_H -#define LLVM_CODEGEN_MACHORELOCATION_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - - /// MachORelocation - This struct contains information about each relocation - /// that needs to be emitted to the file. - /// see - class MachORelocation { - uint32_t r_address; // offset in the section to what is being relocated - uint32_t r_symbolnum; // symbol index if r_extern == 1 else section index - bool r_pcrel; // was relocated pc-relative already - uint8_t r_length; // length = 2 ^ r_length - bool r_extern; // - uint8_t r_type; // if not 0, machine-specific relocation type. - bool r_scattered; // 1 = scattered, 0 = non-scattered - int32_t r_value; // the value the item to be relocated is referring - // to. - public: - uint32_t getPackedFields() const { - if (r_scattered) - return (1 << 31) | (r_pcrel << 30) | ((r_length & 3) << 28) | - ((r_type & 15) << 24) | (r_address & 0x00FFFFFF); - else - return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | - (r_extern << 4) | (r_type & 15); - } - uint32_t getAddress() const { return r_scattered ? r_value : r_address; } - uint32_t getRawAddress() const { return r_address; } - - MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len, - bool ext, uint8_t type, bool scattered = false, - int32_t value = 0) : - r_address(addr), r_symbolnum(index), r_pcrel(pcrel), r_length(len), - r_extern(ext), r_type(type), r_scattered(scattered), r_value(value) {} - }; - -} // end llvm namespace - -#endif // LLVM_CODEGEN_MACHORELOCATION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBasicBlock.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineBasicBlock.h deleted file mode 100644 index 28132d16b7..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBasicBlock.h +++ /dev/null @@ -1,1270 +0,0 @@ -//===- llvm/CodeGen/MachineBasicBlock.h -------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Collect the sequence of machine instructions for a basic block. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H -#define LLVM_CODEGEN_MACHINEBASICBLOCK_H - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/ADT/SparseBitVector.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBundleIterator.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/Support/BranchProbability.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class BasicBlock; -class MachineFunction; -class MCSymbol; -class ModuleSlotTracker; -class Pass; -class Printable; -class SlotIndexes; -class StringRef; -class raw_ostream; -class LiveIntervals; -class TargetRegisterClass; -class TargetRegisterInfo; - -// This structure uniquely identifies a basic block section. -// Possible values are -// {Type: Default, Number: (unsigned)} (These are regular section IDs) -// {Type: Exception, Number: 0} (ExceptionSectionID) -// {Type: Cold, Number: 0} (ColdSectionID) -struct MBBSectionID { - enum SectionType { - Default = 0, // Regular section (these sections are distinguished by the - // Number field). - Exception, // Special section type for exception handling blocks - Cold, // Special section type for cold blocks - } Type; - unsigned Number; - - MBBSectionID(unsigned N) : Type(Default), Number(N) {} - - // Special unique sections for cold and exception blocks. - const static MBBSectionID ColdSectionID; - const static MBBSectionID ExceptionSectionID; - - bool operator==(const MBBSectionID &Other) const { - return Type == Other.Type && Number == Other.Number; - } - - bool operator!=(const MBBSectionID &Other) const { return !(*this == Other); } - -private: - // This is only used to construct the special cold and exception sections. - MBBSectionID(SectionType T) : Type(T), Number(0) {} -}; - -template <> struct ilist_traits { -private: - friend class MachineBasicBlock; // Set by the owning MachineBasicBlock. - - MachineBasicBlock *Parent; - - using instr_iterator = - simple_ilist>::iterator; - -public: - void addNodeToList(MachineInstr *N); - void removeNodeFromList(MachineInstr *N); - void transferNodesFromList(ilist_traits &FromList, instr_iterator First, - instr_iterator Last); - void deleteNode(MachineInstr *MI); -}; - -class MachineBasicBlock - : public ilist_node_with_parent { -public: - /// Pair of physical register and lane mask. - /// This is not simply a std::pair typedef because the members should be named - /// clearly as they both have an integer type. - struct RegisterMaskPair { - public: - MCPhysReg PhysReg; - LaneBitmask LaneMask; - - RegisterMaskPair(MCPhysReg PhysReg, LaneBitmask LaneMask) - : PhysReg(PhysReg), LaneMask(LaneMask) {} - }; - -private: - using Instructions = ilist>; - - Instructions Insts; - const BasicBlock *BB; - int Number; - MachineFunction *xParent; - - /// Keep track of the predecessor / successor basic blocks. - std::vector Predecessors; - std::vector Successors; - - /// Keep track of the probabilities to the successors. This vector has the - /// same order as Successors, or it is empty if we don't use it (disable - /// optimization). - std::vector Probs; - using probability_iterator = std::vector::iterator; - using const_probability_iterator = - std::vector::const_iterator; - - Optional IrrLoopHeaderWeight; - - /// Keep track of the physical registers that are livein of the basicblock. - using LiveInVector = std::vector; - LiveInVector LiveIns; - - /// Alignment of the basic block. One if the basic block does not need to be - /// aligned. - Align Alignment; - /// Maximum amount of bytes that can be added to align the basic block. If the - /// alignment cannot be reached in this many bytes, no bytes are emitted. - /// Zero to represent no maximum. - unsigned MaxBytesForAlignment = 0; - - /// Indicate that this basic block is entered via an exception handler. - bool IsEHPad = false; - - /// Indicate that this basic block is potentially the target of an indirect - /// branch. - bool AddressTaken = false; - - /// Indicate that this basic block needs its symbol be emitted regardless of - /// whether the flow just falls-through to it. - bool LabelMustBeEmitted = false; - - /// Indicate that this basic block is the entry block of an EH scope, i.e., - /// the block that used to have a catchpad or cleanuppad instruction in the - /// LLVM IR. - bool IsEHScopeEntry = false; - - /// Indicates if this is a target block of a catchret. - bool IsEHCatchretTarget = false; - - /// Indicate that this basic block is the entry block of an EH funclet. - bool IsEHFuncletEntry = false; - - /// Indicate that this basic block is the entry block of a cleanup funclet. - bool IsCleanupFuncletEntry = false; - - /// With basic block sections, this stores the Section ID of the basic block. - MBBSectionID SectionID{0}; - - // Indicate that this basic block begins a section. - bool IsBeginSection = false; - - // Indicate that this basic block ends a section. - bool IsEndSection = false; - - /// Indicate that this basic block is the indirect dest of an INLINEASM_BR. - bool IsInlineAsmBrIndirectTarget = false; - - /// since getSymbol is a relatively heavy-weight operation, the symbol - /// is only computed once and is cached. - mutable MCSymbol *CachedMCSymbol = nullptr; - - /// Cached MCSymbol for this block (used if IsEHCatchRetTarget). - mutable MCSymbol *CachedEHCatchretMCSymbol = nullptr; - - /// Marks the end of the basic block. Used during basic block sections to - /// calculate the size of the basic block, or the BB section ending with it. - mutable MCSymbol *CachedEndMCSymbol = nullptr; - - // Intrusive list support - MachineBasicBlock() = default; - - explicit MachineBasicBlock(MachineFunction &MF, const BasicBlock *BB); - - ~MachineBasicBlock(); - - // MachineBasicBlocks are allocated and owned by MachineFunction. - friend class MachineFunction; - -public: - /// Return the LLVM basic block that this instance corresponded to originally. - /// Note that this may be NULL if this instance does not correspond directly - /// to an LLVM basic block. - const BasicBlock *getBasicBlock() const { return BB; } - - /// Return the name of the corresponding LLVM basic block, or an empty string. - StringRef getName() const; - - /// Return a formatted string to identify this block and its parent function. - std::string getFullName() const; - - /// Test whether this block is potentially the target of an indirect branch. - bool hasAddressTaken() const { return AddressTaken; } - - /// Set this block to reflect that it potentially is the target of an indirect - /// branch. - void setHasAddressTaken() { AddressTaken = true; } - - /// Test whether this block must have its label emitted. - bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; } - - /// Set this block to reflect that, regardless how we flow to it, we need - /// its label be emitted. - void setLabelMustBeEmitted() { LabelMustBeEmitted = true; } - - /// Return the MachineFunction containing this basic block. - const MachineFunction *getParent() const { return xParent; } - MachineFunction *getParent() { return xParent; } - - using instr_iterator = Instructions::iterator; - using const_instr_iterator = Instructions::const_iterator; - using reverse_instr_iterator = Instructions::reverse_iterator; - using const_reverse_instr_iterator = Instructions::const_reverse_iterator; - - using iterator = MachineInstrBundleIterator; - using const_iterator = MachineInstrBundleIterator; - using reverse_iterator = MachineInstrBundleIterator; - using const_reverse_iterator = - MachineInstrBundleIterator; - - unsigned size() const { return (unsigned)Insts.size(); } - bool empty() const { return Insts.empty(); } - - MachineInstr &instr_front() { return Insts.front(); } - MachineInstr &instr_back() { return Insts.back(); } - const MachineInstr &instr_front() const { return Insts.front(); } - const MachineInstr &instr_back() const { return Insts.back(); } - - MachineInstr &front() { return Insts.front(); } - MachineInstr &back() { return *--end(); } - const MachineInstr &front() const { return Insts.front(); } - const MachineInstr &back() const { return *--end(); } - - instr_iterator instr_begin() { return Insts.begin(); } - const_instr_iterator instr_begin() const { return Insts.begin(); } - instr_iterator instr_end() { return Insts.end(); } - const_instr_iterator instr_end() const { return Insts.end(); } - reverse_instr_iterator instr_rbegin() { return Insts.rbegin(); } - const_reverse_instr_iterator instr_rbegin() const { return Insts.rbegin(); } - reverse_instr_iterator instr_rend () { return Insts.rend(); } - const_reverse_instr_iterator instr_rend () const { return Insts.rend(); } - - using instr_range = iterator_range; - using const_instr_range = iterator_range; - instr_range instrs() { return instr_range(instr_begin(), instr_end()); } - const_instr_range instrs() const { - return const_instr_range(instr_begin(), instr_end()); - } - - iterator begin() { return instr_begin(); } - const_iterator begin() const { return instr_begin(); } - iterator end () { return instr_end(); } - const_iterator end () const { return instr_end(); } - reverse_iterator rbegin() { - return reverse_iterator::getAtBundleBegin(instr_rbegin()); - } - const_reverse_iterator rbegin() const { - return const_reverse_iterator::getAtBundleBegin(instr_rbegin()); - } - reverse_iterator rend() { return reverse_iterator(instr_rend()); } - const_reverse_iterator rend() const { - return const_reverse_iterator(instr_rend()); - } - - /// Support for MachineInstr::getNextNode(). - static Instructions MachineBasicBlock::*getSublistAccess(MachineInstr *) { - return &MachineBasicBlock::Insts; - } - - inline iterator_range terminators() { - return make_range(getFirstTerminator(), end()); - } - inline iterator_range terminators() const { - return make_range(getFirstTerminator(), end()); - } - - /// Returns a range that iterates over the phis in the basic block. - inline iterator_range phis() { - return make_range(begin(), getFirstNonPHI()); - } - inline iterator_range phis() const { - return const_cast(this)->phis(); - } - - // Machine-CFG iterators - using pred_iterator = std::vector::iterator; - using const_pred_iterator = std::vector::const_iterator; - using succ_iterator = std::vector::iterator; - using const_succ_iterator = std::vector::const_iterator; - using pred_reverse_iterator = - std::vector::reverse_iterator; - using const_pred_reverse_iterator = - std::vector::const_reverse_iterator; - using succ_reverse_iterator = - std::vector::reverse_iterator; - using const_succ_reverse_iterator = - std::vector::const_reverse_iterator; - pred_iterator pred_begin() { return Predecessors.begin(); } - const_pred_iterator pred_begin() const { return Predecessors.begin(); } - pred_iterator pred_end() { return Predecessors.end(); } - const_pred_iterator pred_end() const { return Predecessors.end(); } - pred_reverse_iterator pred_rbegin() - { return Predecessors.rbegin();} - const_pred_reverse_iterator pred_rbegin() const - { return Predecessors.rbegin();} - pred_reverse_iterator pred_rend() - { return Predecessors.rend(); } - const_pred_reverse_iterator pred_rend() const - { return Predecessors.rend(); } - unsigned pred_size() const { - return (unsigned)Predecessors.size(); - } - bool pred_empty() const { return Predecessors.empty(); } - succ_iterator succ_begin() { return Successors.begin(); } - const_succ_iterator succ_begin() const { return Successors.begin(); } - succ_iterator succ_end() { return Successors.end(); } - const_succ_iterator succ_end() const { return Successors.end(); } - succ_reverse_iterator succ_rbegin() - { return Successors.rbegin(); } - const_succ_reverse_iterator succ_rbegin() const - { return Successors.rbegin(); } - succ_reverse_iterator succ_rend() - { return Successors.rend(); } - const_succ_reverse_iterator succ_rend() const - { return Successors.rend(); } - unsigned succ_size() const { - return (unsigned)Successors.size(); - } - bool succ_empty() const { return Successors.empty(); } - - inline iterator_range predecessors() { - return make_range(pred_begin(), pred_end()); - } - inline iterator_range predecessors() const { - return make_range(pred_begin(), pred_end()); - } - inline iterator_range successors() { - return make_range(succ_begin(), succ_end()); - } - inline iterator_range successors() const { - return make_range(succ_begin(), succ_end()); - } - - // LiveIn management methods. - - /// Adds the specified register as a live in. Note that it is an error to add - /// the same register to the same set more than once unless the intention is - /// to call sortUniqueLiveIns after all registers are added. - void addLiveIn(MCRegister PhysReg, - LaneBitmask LaneMask = LaneBitmask::getAll()) { - LiveIns.push_back(RegisterMaskPair(PhysReg, LaneMask)); - } - void addLiveIn(const RegisterMaskPair &RegMaskPair) { - LiveIns.push_back(RegMaskPair); - } - - /// Sorts and uniques the LiveIns vector. It can be significantly faster to do - /// this than repeatedly calling isLiveIn before calling addLiveIn for every - /// LiveIn insertion. - void sortUniqueLiveIns(); - - /// Clear live in list. - void clearLiveIns(); - - /// Add PhysReg as live in to this block, and ensure that there is a copy of - /// PhysReg to a virtual register of class RC. Return the virtual register - /// that is a copy of the live in PhysReg. - Register addLiveIn(MCRegister PhysReg, const TargetRegisterClass *RC); - - /// Remove the specified register from the live in set. - void removeLiveIn(MCPhysReg Reg, - LaneBitmask LaneMask = LaneBitmask::getAll()); - - /// Return true if the specified register is in the live in set. - bool isLiveIn(MCPhysReg Reg, - LaneBitmask LaneMask = LaneBitmask::getAll()) const; - - // Iteration support for live in sets. These sets are kept in sorted - // order by their register number. - using livein_iterator = LiveInVector::const_iterator; -#ifndef NDEBUG - /// Unlike livein_begin, this method does not check that the liveness - /// information is accurate. Still for debug purposes it may be useful - /// to have iterators that won't assert if the liveness information - /// is not current. - livein_iterator livein_begin_dbg() const { return LiveIns.begin(); } - iterator_range liveins_dbg() const { - return make_range(livein_begin_dbg(), livein_end()); - } -#endif - livein_iterator livein_begin() const; - livein_iterator livein_end() const { return LiveIns.end(); } - bool livein_empty() const { return LiveIns.empty(); } - iterator_range liveins() const { - return make_range(livein_begin(), livein_end()); - } - - /// Remove entry from the livein set and return iterator to the next. - livein_iterator removeLiveIn(livein_iterator I); - - class liveout_iterator { - public: - using iterator_category = std::input_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = RegisterMaskPair; - using pointer = const RegisterMaskPair *; - using reference = const RegisterMaskPair &; - - liveout_iterator(const MachineBasicBlock &MBB, MCPhysReg ExceptionPointer, - MCPhysReg ExceptionSelector, bool End) - : ExceptionPointer(ExceptionPointer), - ExceptionSelector(ExceptionSelector), BlockI(MBB.succ_begin()), - BlockEnd(MBB.succ_end()) { - if (End) - BlockI = BlockEnd; - else if (BlockI != BlockEnd) { - LiveRegI = (*BlockI)->livein_begin(); - if (!advanceToValidPosition()) - return; - if (LiveRegI->PhysReg == ExceptionPointer || - LiveRegI->PhysReg == ExceptionSelector) - ++(*this); - } - } - - liveout_iterator &operator++() { - do { - ++LiveRegI; - if (!advanceToValidPosition()) - return *this; - } while ((*BlockI)->isEHPad() && - (LiveRegI->PhysReg == ExceptionPointer || - LiveRegI->PhysReg == ExceptionSelector)); - return *this; - } - - liveout_iterator operator++(int) { - liveout_iterator Tmp = *this; - ++(*this); - return Tmp; - } - - reference operator*() const { - return *LiveRegI; - } - - pointer operator->() const { - return &*LiveRegI; - } - - bool operator==(const liveout_iterator &RHS) const { - if (BlockI != BlockEnd) - return BlockI == RHS.BlockI && LiveRegI == RHS.LiveRegI; - return RHS.BlockI == BlockEnd; - } - - bool operator!=(const liveout_iterator &RHS) const { - return !(*this == RHS); - } - private: - bool advanceToValidPosition() { - if (LiveRegI != (*BlockI)->livein_end()) - return true; - - do { - ++BlockI; - } while (BlockI != BlockEnd && (*BlockI)->livein_empty()); - if (BlockI == BlockEnd) - return false; - - LiveRegI = (*BlockI)->livein_begin(); - return true; - } - - MCPhysReg ExceptionPointer, ExceptionSelector; - const_succ_iterator BlockI; - const_succ_iterator BlockEnd; - livein_iterator LiveRegI; - }; - - /// Iterator scanning successor basic blocks' liveins to determine the - /// registers potentially live at the end of this block. There may be - /// duplicates or overlapping registers in the list returned. - liveout_iterator liveout_begin() const; - liveout_iterator liveout_end() const { - return liveout_iterator(*this, 0, 0, true); - } - iterator_range liveouts() const { - return make_range(liveout_begin(), liveout_end()); - } - - /// Get the clobber mask for the start of this basic block. Funclets use this - /// to prevent register allocation across funclet transitions. - const uint32_t *getBeginClobberMask(const TargetRegisterInfo *TRI) const; - - /// Get the clobber mask for the end of the basic block. - /// \see getBeginClobberMask() - const uint32_t *getEndClobberMask(const TargetRegisterInfo *TRI) const; - - /// Return alignment of the basic block. - Align getAlignment() const { return Alignment; } - - /// Set alignment of the basic block. - void setAlignment(Align A) { Alignment = A; } - - void setAlignment(Align A, unsigned MaxBytes) { - setAlignment(A); - setMaxBytesForAlignment(MaxBytes); - } - - /// Return the maximum amount of padding allowed for aligning the basic block. - unsigned getMaxBytesForAlignment() const { return MaxBytesForAlignment; } - - /// Set the maximum amount of padding allowed for aligning the basic block - void setMaxBytesForAlignment(unsigned MaxBytes) { - MaxBytesForAlignment = MaxBytes; - } - - /// Returns true if the block is a landing pad. That is this basic block is - /// entered via an exception handler. - bool isEHPad() const { return IsEHPad; } - - /// Indicates the block is a landing pad. That is this basic block is entered - /// via an exception handler. - void setIsEHPad(bool V = true) { IsEHPad = V; } - - bool hasEHPadSuccessor() const; - - /// Returns true if this is the entry block of the function. - bool isEntryBlock() const; - - /// Returns true if this is the entry block of an EH scope, i.e., the block - /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. - bool isEHScopeEntry() const { return IsEHScopeEntry; } - - /// Indicates if this is the entry block of an EH scope, i.e., the block that - /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. - void setIsEHScopeEntry(bool V = true) { IsEHScopeEntry = V; } - - /// Returns true if this is a target block of a catchret. - bool isEHCatchretTarget() const { return IsEHCatchretTarget; } - - /// Indicates if this is a target block of a catchret. - void setIsEHCatchretTarget(bool V = true) { IsEHCatchretTarget = V; } - - /// Returns true if this is the entry block of an EH funclet. - bool isEHFuncletEntry() const { return IsEHFuncletEntry; } - - /// Indicates if this is the entry block of an EH funclet. - void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; } - - /// Returns true if this is the entry block of a cleanup funclet. - bool isCleanupFuncletEntry() const { return IsCleanupFuncletEntry; } - - /// Indicates if this is the entry block of a cleanup funclet. - void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; } - - /// Returns true if this block begins any section. - bool isBeginSection() const { return IsBeginSection; } - - /// Returns true if this block ends any section. - bool isEndSection() const { return IsEndSection; } - - void setIsBeginSection(bool V = true) { IsBeginSection = V; } - - void setIsEndSection(bool V = true) { IsEndSection = V; } - - /// Returns the section ID of this basic block. - MBBSectionID getSectionID() const { return SectionID; } - - /// Returns the unique section ID number of this basic block. - unsigned getSectionIDNum() const { - return ((unsigned)MBBSectionID::SectionType::Cold) - - ((unsigned)SectionID.Type) + SectionID.Number; - } - - /// Sets the section ID for this basic block. - void setSectionID(MBBSectionID V) { SectionID = V; } - - /// Returns the MCSymbol marking the end of this basic block. - MCSymbol *getEndSymbol() const; - - /// Returns true if this block may have an INLINEASM_BR (overestimate, by - /// checking if any of the successors are indirect targets of any inlineasm_br - /// in the function). - bool mayHaveInlineAsmBr() const; - - /// Returns true if this is the indirect dest of an INLINEASM_BR. - bool isInlineAsmBrIndirectTarget() const { - return IsInlineAsmBrIndirectTarget; - } - - /// Indicates if this is the indirect dest of an INLINEASM_BR. - void setIsInlineAsmBrIndirectTarget(bool V = true) { - IsInlineAsmBrIndirectTarget = V; - } - - /// Returns true if it is legal to hoist instructions into this block. - bool isLegalToHoistInto() const; - - // Code Layout methods. - - /// Move 'this' block before or after the specified block. This only moves - /// the block, it does not modify the CFG or adjust potential fall-throughs at - /// the end of the block. - void moveBefore(MachineBasicBlock *NewAfter); - void moveAfter(MachineBasicBlock *NewBefore); - - /// Returns true if this and MBB belong to the same section. - bool sameSection(const MachineBasicBlock *MBB) const { - return getSectionID() == MBB->getSectionID(); - } - - /// Update the terminator instructions in block to account for changes to - /// block layout which may have been made. PreviousLayoutSuccessor should be - /// set to the block which may have been used as fallthrough before the block - /// layout was modified. If the block previously fell through to that block, - /// it may now need a branch. If it previously branched to another block, it - /// may now be able to fallthrough to the current layout successor. - void updateTerminator(MachineBasicBlock *PreviousLayoutSuccessor); - - // Machine-CFG mutators - - /// Add Succ as a successor of this MachineBasicBlock. The Predecessors list - /// of Succ is automatically updated. PROB parameter is stored in - /// Probabilities list. The default probability is set as unknown. Mixing - /// known and unknown probabilities in successor list is not allowed. When all - /// successors have unknown probabilities, 1 / N is returned as the - /// probability for each successor, where N is the number of successors. - /// - /// Note that duplicate Machine CFG edges are not allowed. - void addSuccessor(MachineBasicBlock *Succ, - BranchProbability Prob = BranchProbability::getUnknown()); - - /// Add Succ as a successor of this MachineBasicBlock. The Predecessors list - /// of Succ is automatically updated. The probability is not provided because - /// BPI is not available (e.g. -O0 is used), in which case edge probabilities - /// won't be used. Using this interface can save some space. - void addSuccessorWithoutProb(MachineBasicBlock *Succ); - - /// Set successor probability of a given iterator. - void setSuccProbability(succ_iterator I, BranchProbability Prob); - - /// Normalize probabilities of all successors so that the sum of them becomes - /// one. This is usually done when the current update on this MBB is done, and - /// the sum of its successors' probabilities is not guaranteed to be one. The - /// user is responsible for the correct use of this function. - /// MBB::removeSuccessor() has an option to do this automatically. - void normalizeSuccProbs() { - BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end()); - } - - /// Validate successors' probabilities and check if the sum of them is - /// approximate one. This only works in DEBUG mode. - void validateSuccProbs() const; - - /// Remove successor from the successors list of this MachineBasicBlock. The - /// Predecessors list of Succ is automatically updated. - /// If NormalizeSuccProbs is true, then normalize successors' probabilities - /// after the successor is removed. - void removeSuccessor(MachineBasicBlock *Succ, - bool NormalizeSuccProbs = false); - - /// Remove specified successor from the successors list of this - /// MachineBasicBlock. The Predecessors list of Succ is automatically updated. - /// If NormalizeSuccProbs is true, then normalize successors' probabilities - /// after the successor is removed. - /// Return the iterator to the element after the one removed. - succ_iterator removeSuccessor(succ_iterator I, - bool NormalizeSuccProbs = false); - - /// Replace successor OLD with NEW and update probability info. - void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New); - - /// Copy a successor (and any probability info) from original block to this - /// block's. Uses an iterator into the original blocks successors. - /// - /// This is useful when doing a partial clone of successors. Afterward, the - /// probabilities may need to be normalized. - void copySuccessor(MachineBasicBlock *Orig, succ_iterator I); - - /// Split the old successor into old plus new and updates the probability - /// info. - void splitSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New, - bool NormalizeSuccProbs = false); - - /// Transfers all the successors from MBB to this machine basic block (i.e., - /// copies all the successors FromMBB and remove all the successors from - /// FromMBB). - void transferSuccessors(MachineBasicBlock *FromMBB); - - /// Transfers all the successors, as in transferSuccessors, and update PHI - /// operands in the successor blocks which refer to FromMBB to refer to this. - void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB); - - /// Return true if any of the successors have probabilities attached to them. - bool hasSuccessorProbabilities() const { return !Probs.empty(); } - - /// Return true if the specified MBB is a predecessor of this block. - bool isPredecessor(const MachineBasicBlock *MBB) const; - - /// Return true if the specified MBB is a successor of this block. - bool isSuccessor(const MachineBasicBlock *MBB) const; - - /// Return true if the specified MBB will be emitted immediately after this - /// block, such that if this block exits by falling through, control will - /// transfer to the specified MBB. Note that MBB need not be a successor at - /// all, for example if this block ends with an unconditional branch to some - /// other block. - bool isLayoutSuccessor(const MachineBasicBlock *MBB) const; - - /// Return the fallthrough block if the block can implicitly - /// transfer control to the block after it by falling off the end of - /// it. This should return null if it can reach the block after - /// it, but it uses an explicit branch to do so (e.g., a table - /// jump). Non-null return is a conservative answer. - MachineBasicBlock *getFallThrough(); - - /// Return true if the block can implicitly transfer control to the - /// block after it by falling off the end of it. This should return - /// false if it can reach the block after it, but it uses an - /// explicit branch to do so (e.g., a table jump). True is a - /// conservative answer. - bool canFallThrough(); - - /// Returns a pointer to the first instruction in this block that is not a - /// PHINode instruction. When adding instructions to the beginning of the - /// basic block, they should be added before the returned value, not before - /// the first instruction, which might be PHI. - /// Returns end() is there's no non-PHI instruction. - iterator getFirstNonPHI(); - - /// Return the first instruction in MBB after I that is not a PHI or a label. - /// This is the correct point to insert lowered copies at the beginning of a - /// basic block that must be before any debugging information. - iterator SkipPHIsAndLabels(iterator I); - - /// Return the first instruction in MBB after I that is not a PHI, label or - /// debug. This is the correct point to insert copies at the beginning of a - /// basic block. - iterator SkipPHIsLabelsAndDebug(iterator I, bool SkipPseudoOp = true); - - /// Returns an iterator to the first terminator instruction of this basic - /// block. If a terminator does not exist, it returns end(). - iterator getFirstTerminator(); - const_iterator getFirstTerminator() const { - return const_cast(this)->getFirstTerminator(); - } - - /// Same getFirstTerminator but it ignores bundles and return an - /// instr_iterator instead. - instr_iterator getFirstInstrTerminator(); - - /// Returns an iterator to the first non-debug instruction in the basic block, - /// or end(). Skip any pseudo probe operation if \c SkipPseudoOp is true. - /// Pseudo probes are like debug instructions which do not turn into real - /// machine code. We try to use the function to skip both debug instructions - /// and pseudo probe operations to avoid API proliferation. This should work - /// most of the time when considering optimizing the rest of code in the - /// block, except for certain cases where pseudo probes are designed to block - /// the optimizations. For example, code merge like optimizations are supposed - /// to be blocked by pseudo probes for better AutoFDO profile quality. - /// Therefore, they should be considered as a valid instruction when this - /// function is called in a context of such optimizations. On the other hand, - /// \c SkipPseudoOp should be true when it's used in optimizations that - /// unlikely hurt profile quality, e.g., without block merging. The default - /// value of \c SkipPseudoOp is set to true to maximize code quality in - /// general, with an explicit false value passed in a few places like branch - /// folding and if-conversion to favor profile quality. - iterator getFirstNonDebugInstr(bool SkipPseudoOp = true); - const_iterator getFirstNonDebugInstr(bool SkipPseudoOp = true) const { - return const_cast(this)->getFirstNonDebugInstr( - SkipPseudoOp); - } - - /// Returns an iterator to the last non-debug instruction in the basic block, - /// or end(). Skip any pseudo operation if \c SkipPseudoOp is true. - /// Pseudo probes are like debug instructions which do not turn into real - /// machine code. We try to use the function to skip both debug instructions - /// and pseudo probe operations to avoid API proliferation. This should work - /// most of the time when considering optimizing the rest of code in the - /// block, except for certain cases where pseudo probes are designed to block - /// the optimizations. For example, code merge like optimizations are supposed - /// to be blocked by pseudo probes for better AutoFDO profile quality. - /// Therefore, they should be considered as a valid instruction when this - /// function is called in a context of such optimizations. On the other hand, - /// \c SkipPseudoOp should be true when it's used in optimizations that - /// unlikely hurt profile quality, e.g., without block merging. The default - /// value of \c SkipPseudoOp is set to true to maximize code quality in - /// general, with an explicit false value passed in a few places like branch - /// folding and if-conversion to favor profile quality. - iterator getLastNonDebugInstr(bool SkipPseudoOp = true); - const_iterator getLastNonDebugInstr(bool SkipPseudoOp = true) const { - return const_cast(this)->getLastNonDebugInstr( - SkipPseudoOp); - } - - /// Convenience function that returns true if the block ends in a return - /// instruction. - bool isReturnBlock() const { - return !empty() && back().isReturn(); - } - - /// Convenience function that returns true if the bock ends in a EH scope - /// return instruction. - bool isEHScopeReturnBlock() const { - return !empty() && back().isEHScopeReturn(); - } - - /// Split a basic block into 2 pieces at \p SplitPoint. A new block will be - /// inserted after this block, and all instructions after \p SplitInst moved - /// to it (\p SplitInst will be in the original block). If \p LIS is provided, - /// LiveIntervals will be appropriately updated. \return the newly inserted - /// block. - /// - /// If \p UpdateLiveIns is true, this will ensure the live ins list is - /// accurate, including for physreg uses/defs in the original block. - MachineBasicBlock *splitAt(MachineInstr &SplitInst, bool UpdateLiveIns = true, - LiveIntervals *LIS = nullptr); - - /// Split the critical edge from this block to the given successor block, and - /// return the newly created block, or null if splitting is not possible. - /// - /// This function updates LiveVariables, MachineDominatorTree, and - /// MachineLoopInfo, as applicable. - MachineBasicBlock * - SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P, - std::vector> *LiveInSets = nullptr); - - /// Check if the edge between this block and the given successor \p - /// Succ, can be split. If this returns true a subsequent call to - /// SplitCriticalEdge is guaranteed to return a valid basic block if - /// no changes occurred in the meantime. - bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const; - - void pop_front() { Insts.pop_front(); } - void pop_back() { Insts.pop_back(); } - void push_back(MachineInstr *MI) { Insts.push_back(MI); } - - /// Insert MI into the instruction list before I, possibly inside a bundle. - /// - /// If the insertion point is inside a bundle, MI will be added to the bundle, - /// otherwise MI will not be added to any bundle. That means this function - /// alone can't be used to prepend or append instructions to bundles. See - /// MIBundleBuilder::insert() for a more reliable way of doing that. - instr_iterator insert(instr_iterator I, MachineInstr *M); - - /// Insert a range of instructions into the instruction list before I. - template - void insert(iterator I, IT S, IT E) { - assert((I == end() || I->getParent() == this) && - "iterator points outside of basic block"); - Insts.insert(I.getInstrIterator(), S, E); - } - - /// Insert MI into the instruction list before I. - iterator insert(iterator I, MachineInstr *MI) { - assert((I == end() || I->getParent() == this) && - "iterator points outside of basic block"); - assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && - "Cannot insert instruction with bundle flags"); - return Insts.insert(I.getInstrIterator(), MI); - } - - /// Insert MI into the instruction list after I. - iterator insertAfter(iterator I, MachineInstr *MI) { - assert((I == end() || I->getParent() == this) && - "iterator points outside of basic block"); - assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && - "Cannot insert instruction with bundle flags"); - return Insts.insertAfter(I.getInstrIterator(), MI); - } - - /// If I is bundled then insert MI into the instruction list after the end of - /// the bundle, otherwise insert MI immediately after I. - instr_iterator insertAfterBundle(instr_iterator I, MachineInstr *MI) { - assert((I == instr_end() || I->getParent() == this) && - "iterator points outside of basic block"); - assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && - "Cannot insert instruction with bundle flags"); - while (I->isBundledWithSucc()) - ++I; - return Insts.insertAfter(I, MI); - } - - /// Remove an instruction from the instruction list and delete it. - /// - /// If the instruction is part of a bundle, the other instructions in the - /// bundle will still be bundled after removing the single instruction. - instr_iterator erase(instr_iterator I); - - /// Remove an instruction from the instruction list and delete it. - /// - /// If the instruction is part of a bundle, the other instructions in the - /// bundle will still be bundled after removing the single instruction. - instr_iterator erase_instr(MachineInstr *I) { - return erase(instr_iterator(I)); - } - - /// Remove a range of instructions from the instruction list and delete them. - iterator erase(iterator I, iterator E) { - return Insts.erase(I.getInstrIterator(), E.getInstrIterator()); - } - - /// Remove an instruction or bundle from the instruction list and delete it. - /// - /// If I points to a bundle of instructions, they are all erased. - iterator erase(iterator I) { - return erase(I, std::next(I)); - } - - /// Remove an instruction from the instruction list and delete it. - /// - /// If I is the head of a bundle of instructions, the whole bundle will be - /// erased. - iterator erase(MachineInstr *I) { - return erase(iterator(I)); - } - - /// Remove the unbundled instruction from the instruction list without - /// deleting it. - /// - /// This function can not be used to remove bundled instructions, use - /// remove_instr to remove individual instructions from a bundle. - MachineInstr *remove(MachineInstr *I) { - assert(!I->isBundled() && "Cannot remove bundled instructions"); - return Insts.remove(instr_iterator(I)); - } - - /// Remove the possibly bundled instruction from the instruction list - /// without deleting it. - /// - /// If the instruction is part of a bundle, the other instructions in the - /// bundle will still be bundled after removing the single instruction. - MachineInstr *remove_instr(MachineInstr *I); - - void clear() { - Insts.clear(); - } - - /// Take an instruction from MBB 'Other' at the position From, and insert it - /// into this MBB right before 'Where'. - /// - /// If From points to a bundle of instructions, the whole bundle is moved. - void splice(iterator Where, MachineBasicBlock *Other, iterator From) { - // The range splice() doesn't allow noop moves, but this one does. - if (Where != From) - splice(Where, Other, From, std::next(From)); - } - - /// Take a block of instructions from MBB 'Other' in the range [From, To), - /// and insert them into this MBB right before 'Where'. - /// - /// The instruction at 'Where' must not be included in the range of - /// instructions to move. - void splice(iterator Where, MachineBasicBlock *Other, - iterator From, iterator To) { - Insts.splice(Where.getInstrIterator(), Other->Insts, - From.getInstrIterator(), To.getInstrIterator()); - } - - /// This method unlinks 'this' from the containing function, and returns it, - /// but does not delete it. - MachineBasicBlock *removeFromParent(); - - /// This method unlinks 'this' from the containing function and deletes it. - void eraseFromParent(); - - /// Given a machine basic block that branched to 'Old', change the code and - /// CFG so that it branches to 'New' instead. - void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); - - /// Update all phi nodes in this basic block to refer to basic block \p New - /// instead of basic block \p Old. - void replacePhiUsesWith(MachineBasicBlock *Old, MachineBasicBlock *New); - - /// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE - /// and DBG_LABEL instructions. Return UnknownLoc if there is none. - DebugLoc findDebugLoc(instr_iterator MBBI); - DebugLoc findDebugLoc(iterator MBBI) { - return findDebugLoc(MBBI.getInstrIterator()); - } - - /// Has exact same behavior as @ref findDebugLoc (it also - /// searches from the first to the last MI of this MBB) except - /// that this takes reverse iterator. - DebugLoc rfindDebugLoc(reverse_instr_iterator MBBI); - DebugLoc rfindDebugLoc(reverse_iterator MBBI) { - return rfindDebugLoc(MBBI.getInstrIterator()); - } - - /// Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE - /// instructions. Return UnknownLoc if there is none. - DebugLoc findPrevDebugLoc(instr_iterator MBBI); - DebugLoc findPrevDebugLoc(iterator MBBI) { - return findPrevDebugLoc(MBBI.getInstrIterator()); - } - - /// Has exact same behavior as @ref findPrevDebugLoc (it also - /// searches from the last to the first MI of this MBB) except - /// that this takes reverse iterator. - DebugLoc rfindPrevDebugLoc(reverse_instr_iterator MBBI); - DebugLoc rfindPrevDebugLoc(reverse_iterator MBBI) { - return rfindPrevDebugLoc(MBBI.getInstrIterator()); - } - - /// Find and return the merged DebugLoc of the branch instructions of the - /// block. Return UnknownLoc if there is none. - DebugLoc findBranchDebugLoc(); - - /// Possible outcome of a register liveness query to computeRegisterLiveness() - enum LivenessQueryResult { - LQR_Live, ///< Register is known to be (at least partially) live. - LQR_Dead, ///< Register is known to be fully dead. - LQR_Unknown ///< Register liveness not decidable from local neighborhood. - }; - - /// Return whether (physical) register \p Reg has been defined and not - /// killed as of just before \p Before. - /// - /// Search is localised to a neighborhood of \p Neighborhood instructions - /// before (searching for defs or kills) and \p Neighborhood instructions - /// after (searching just for defs) \p Before. - /// - /// \p Reg must be a physical register. - LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, - MCRegister Reg, - const_iterator Before, - unsigned Neighborhood = 10) const; - - // Debugging methods. - void dump() const; - void print(raw_ostream &OS, const SlotIndexes * = nullptr, - bool IsStandalone = true) const; - void print(raw_ostream &OS, ModuleSlotTracker &MST, - const SlotIndexes * = nullptr, bool IsStandalone = true) const; - - enum PrintNameFlag { - PrintNameIr = (1 << 0), ///< Add IR name where available - PrintNameAttributes = (1 << 1), ///< Print attributes - }; - - void printName(raw_ostream &os, unsigned printNameFlags = PrintNameIr, - ModuleSlotTracker *moduleSlotTracker = nullptr) const; - - // Printing method used by LoopInfo. - void printAsOperand(raw_ostream &OS, bool PrintType = true) const; - - /// MachineBasicBlocks are uniquely numbered at the function level, unless - /// they're not in a MachineFunction yet, in which case this will return -1. - int getNumber() const { return Number; } - void setNumber(int N) { Number = N; } - - /// Return the MCSymbol for this basic block. - MCSymbol *getSymbol() const; - - /// Return the EHCatchret Symbol for this basic block. - MCSymbol *getEHCatchretSymbol() const; - - Optional getIrrLoopHeaderWeight() const { - return IrrLoopHeaderWeight; - } - - void setIrrLoopHeaderWeight(uint64_t Weight) { - IrrLoopHeaderWeight = Weight; - } - -private: - /// Return probability iterator corresponding to the I successor iterator. - probability_iterator getProbabilityIterator(succ_iterator I); - const_probability_iterator - getProbabilityIterator(const_succ_iterator I) const; - - friend class MachineBranchProbabilityInfo; - friend class MIPrinter; - - /// Return probability of the edge from this block to MBB. This method should - /// NOT be called directly, but by using getEdgeProbability method from - /// MachineBranchProbabilityInfo class. - BranchProbability getSuccProbability(const_succ_iterator Succ) const; - - // Methods used to maintain doubly linked list of blocks... - friend struct ilist_callback_traits; - - // Machine-CFG mutators - - /// Add Pred as a predecessor of this MachineBasicBlock. Don't do this - /// unless you know what you're doing, because it doesn't update Pred's - /// successors list. Use Pred->addSuccessor instead. - void addPredecessor(MachineBasicBlock *Pred); - - /// Remove Pred as a predecessor of this MachineBasicBlock. Don't do this - /// unless you know what you're doing, because it doesn't update Pred's - /// successors list. Use Pred->removeSuccessor instead. - void removePredecessor(MachineBasicBlock *Pred); -}; - -raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); - -/// Prints a machine basic block reference. -/// -/// The format is: -/// %bb.5 - a machine basic block with MBB.getNumber() == 5. -/// -/// Usage: OS << printMBBReference(MBB) << '\n'; -Printable printMBBReference(const MachineBasicBlock &MBB); - -// This is useful when building IndexedMaps keyed on basic block pointers. -struct MBB2NumberFunctor { - using argument_type = const MachineBasicBlock *; - unsigned operator()(const MachineBasicBlock *MBB) const { - return MBB->getNumber(); - } -}; - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for machine basic block graphs (machine-CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a -// MachineFunction as a graph of MachineBasicBlocks. -// - -template <> struct GraphTraits { - using NodeRef = MachineBasicBlock *; - using ChildIteratorType = MachineBasicBlock::succ_iterator; - - static NodeRef getEntryNode(MachineBasicBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } -}; - -template <> struct GraphTraits { - using NodeRef = const MachineBasicBlock *; - using ChildIteratorType = MachineBasicBlock::const_succ_iterator; - - static NodeRef getEntryNode(const MachineBasicBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } -}; - -// Provide specializations of GraphTraits to be able to treat a -// MachineFunction as a graph of MachineBasicBlocks and to walk it -// in inverse order. Inverse order for a function is considered -// to be when traversing the predecessor edges of a MBB -// instead of the successor edges. -// -template <> struct GraphTraits> { - using NodeRef = MachineBasicBlock *; - using ChildIteratorType = MachineBasicBlock::pred_iterator; - - static NodeRef getEntryNode(Inverse G) { - return G.Graph; - } - - static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } -}; - -template <> struct GraphTraits> { - using NodeRef = const MachineBasicBlock *; - using ChildIteratorType = MachineBasicBlock::const_pred_iterator; - - static NodeRef getEntryNode(Inverse G) { - return G.Graph; - } - - static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } -}; - -/// MachineInstrSpan provides an interface to get an iteration range -/// containing the instruction it was initialized with, along with all -/// those instructions inserted prior to or following that instruction -/// at some point after the MachineInstrSpan is constructed. -class MachineInstrSpan { - MachineBasicBlock &MBB; - MachineBasicBlock::iterator I, B, E; - -public: - MachineInstrSpan(MachineBasicBlock::iterator I, MachineBasicBlock *BB) - : MBB(*BB), I(I), B(I == MBB.begin() ? MBB.end() : std::prev(I)), - E(std::next(I)) { - assert(I == BB->end() || I->getParent() == BB); - } - - MachineBasicBlock::iterator begin() { - return B == MBB.end() ? MBB.begin() : std::next(B); - } - MachineBasicBlock::iterator end() { return E; } - bool empty() { return begin() == end(); } - - MachineBasicBlock::iterator getInitial() { return I; } -}; - -/// Increment \p It until it points to a non-debug instruction or to \p End -/// and return the resulting iterator. This function should only be used -/// MachineBasicBlock::{iterator, const_iterator, instr_iterator, -/// const_instr_iterator} and the respective reverse iterators. -template -inline IterT skipDebugInstructionsForward(IterT It, IterT End, - bool SkipPseudoOp = true) { - while (It != End && - (It->isDebugInstr() || (SkipPseudoOp && It->isPseudoProbe()))) - ++It; - return It; -} - -/// Decrement \p It until it points to a non-debug instruction or to \p Begin -/// and return the resulting iterator. This function should only be used -/// MachineBasicBlock::{iterator, const_iterator, instr_iterator, -/// const_instr_iterator} and the respective reverse iterators. -template -inline IterT skipDebugInstructionsBackward(IterT It, IterT Begin, - bool SkipPseudoOp = true) { - while (It != Begin && - (It->isDebugInstr() || (SkipPseudoOp && It->isPseudoProbe()))) - --It; - return It; -} - -/// Increment \p It, then continue incrementing it while it points to a debug -/// instruction. A replacement for std::next. -template -inline IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp = true) { - return skipDebugInstructionsForward(std::next(It), End, SkipPseudoOp); -} - -/// Decrement \p It, then continue decrementing it while it points to a debug -/// instruction. A replacement for std::prev. -template -inline IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp = true) { - return skipDebugInstructionsBackward(std::prev(It), Begin, SkipPseudoOp); -} - -/// Construct a range iterator which begins at \p It and moves forwards until -/// \p End is reached, skipping any debug instructions. -template -inline auto instructionsWithoutDebug(IterT It, IterT End, - bool SkipPseudoOp = true) { - return make_filter_range(make_range(It, End), [=](const MachineInstr &MI) { - return !MI.isDebugInstr() && !(SkipPseudoOp && MI.isPseudoProbe()); - }); -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEBASICBLOCK_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineBlockFrequencyInfo.h deleted file mode 100644 index 6c442d3d07..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ /dev/null @@ -1,106 +0,0 @@ -//===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Loops should be simplified before this analysis. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H -#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H - -#include "llvm/ADT/Optional.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/BlockFrequency.h" -#include -#include - -namespace llvm { - -template class BlockFrequencyInfoImpl; -class MachineBasicBlock; -class MachineBranchProbabilityInfo; -class MachineFunction; -class MachineLoopInfo; -class raw_ostream; - -/// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation -/// to estimate machine basic block frequencies. -class MachineBlockFrequencyInfo : public MachineFunctionPass { - using ImplType = BlockFrequencyInfoImpl; - std::unique_ptr MBFI; - -public: - static char ID; - - MachineBlockFrequencyInfo(); - explicit MachineBlockFrequencyInfo(MachineFunction &F, - MachineBranchProbabilityInfo &MBPI, - MachineLoopInfo &MLI); - ~MachineBlockFrequencyInfo() override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &F) override; - - /// calculate - compute block frequency info for the given function. - void calculate(const MachineFunction &F, - const MachineBranchProbabilityInfo &MBPI, - const MachineLoopInfo &MLI); - - void releaseMemory() override; - - /// getblockFreq - Return block frequency. Return 0 if we don't have the - /// information. Please note that initial frequency is equal to 1024. It means - /// that we should not rely on the value itself, but only on the comparison to - /// the other block frequencies. We do this to avoid using of floating points. - /// For example, to get the frequency of a block relative to the entry block, - /// divide the integral value returned by this function (the - /// BlockFrequency::getFrequency() value) by getEntryFreq(). - BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const; - - /// Compute the frequency of the block, relative to the entry block. - /// This API assumes getEntryFreq() is non-zero. - float getBlockFreqRelativeToEntryBlock(const MachineBasicBlock *MBB) const { - return getBlockFreq(MBB).getFrequency() * (1.0f / getEntryFreq()); - } - - Optional getBlockProfileCount(const MachineBasicBlock *MBB) const; - Optional getProfileCountFromFreq(uint64_t Freq) const; - - bool isIrrLoopHeader(const MachineBasicBlock *MBB) const; - - /// incrementally calculate block frequencies when we split edges, to avoid - /// full CFG traversal. - void onEdgeSplit(const MachineBasicBlock &NewPredecessor, - const MachineBasicBlock &NewSuccessor, - const MachineBranchProbabilityInfo &MBPI); - - const MachineFunction *getFunction() const; - const MachineBranchProbabilityInfo *getMBPI() const; - - /// Pop up a ghostview window with the current block frequency propagation - /// rendered using dot. - void view(const Twine &Name, bool isSimple = true) const; - - // Print the block frequency Freq to OS using the current functions entry - // frequency to convert freq into a relative decimal form. - raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; - - // Convenience method that attempts to look up the frequency associated with - // BB and print it to OS. - raw_ostream &printBlockFreq(raw_ostream &OS, - const MachineBasicBlock *MBB) const; - - /// Divide a block's BlockFrequency::getFrequency() value by this value to - /// obtain the entry block - relative frequency of said block. - uint64_t getEntryFreq() const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineBranchProbabilityInfo.h deleted file mode 100644 index 06f9ee3abb..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ /dev/null @@ -1,69 +0,0 @@ -//=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass is used to evaluate branch probabilities on machine basic blocks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEBRANCHPROBABILITYINFO_H -#define LLVM_CODEGEN_MACHINEBRANCHPROBABILITYINFO_H - -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Pass.h" -#include "llvm/Support/BranchProbability.h" -#include -#include - -namespace llvm { - -class MachineBranchProbabilityInfo : public ImmutablePass { - virtual void anchor(); - - // Default weight value. Used when we don't have information about the edge. - // TODO: DEFAULT_WEIGHT makes sense during static predication, when none of - // the successors have a weight yet. But it doesn't make sense when providing - // weight to an edge that may have siblings with non-zero weights. This can - // be handled various ways, but it's probably fine for an edge with unknown - // weight to just "inherit" the non-zero weight of an adjacent successor. - static const uint32_t DEFAULT_WEIGHT = 16; - -public: - static char ID; - - MachineBranchProbabilityInfo(); - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - // Return edge probability. - BranchProbability getEdgeProbability(const MachineBasicBlock *Src, - const MachineBasicBlock *Dst) const; - - // Same as above, but using a const_succ_iterator from Src. This is faster - // when the iterator is already available. - BranchProbability - getEdgeProbability(const MachineBasicBlock *Src, - MachineBasicBlock::const_succ_iterator Dst) const; - - // A 'Hot' edge is an edge which probability is >= 80%. - bool isEdgeHot(const MachineBasicBlock *Src, - const MachineBasicBlock *Dst) const; - - // Print value between 0 (0% probability) and 1 (100% probability), - // however the value is never equal to 0, and can be 1 only iff SRC block - // has only one successor. - raw_ostream &printEdgeProbability(raw_ostream &OS, - const MachineBasicBlock *Src, - const MachineBasicBlock *Dst) const; -}; - -} - - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineCombinerPattern.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineCombinerPattern.h deleted file mode 100644 index 67544779f3..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineCombinerPattern.h +++ /dev/null @@ -1,172 +0,0 @@ -//===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by -// combiner ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines instruction pattern supported by combiner -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECOMBINERPATTERN_H -#define LLVM_CODEGEN_MACHINECOMBINERPATTERN_H - -namespace llvm { - -/// These are instruction patterns matched by the machine combiner pass. -enum class MachineCombinerPattern { - // These are commutative variants for reassociating a computation chain. See - // the comments before getMachineCombinerPatterns() in TargetInstrInfo.cpp. - REASSOC_AX_BY, - REASSOC_AX_YB, - REASSOC_XA_BY, - REASSOC_XA_YB, - - // These are patterns matched by the PowerPC to reassociate FMA chains. - REASSOC_XY_AMM_BMM, - REASSOC_XMM_AMM_BMM, - - // These are patterns matched by the PowerPC to reassociate FMA and FSUB to - // reduce register pressure. - REASSOC_XY_BCA, - REASSOC_XY_BAC, - - // These are multiply-add patterns matched by the AArch64 machine combiner. - MULADDW_OP1, - MULADDW_OP2, - MULSUBW_OP1, - MULSUBW_OP2, - MULADDWI_OP1, - MULSUBWI_OP1, - MULADDX_OP1, - MULADDX_OP2, - MULSUBX_OP1, - MULSUBX_OP2, - MULADDXI_OP1, - MULSUBXI_OP1, - // NEON integers vectors - MULADDv8i8_OP1, - MULADDv8i8_OP2, - MULADDv16i8_OP1, - MULADDv16i8_OP2, - MULADDv4i16_OP1, - MULADDv4i16_OP2, - MULADDv8i16_OP1, - MULADDv8i16_OP2, - MULADDv2i32_OP1, - MULADDv2i32_OP2, - MULADDv4i32_OP1, - MULADDv4i32_OP2, - - MULSUBv8i8_OP1, - MULSUBv8i8_OP2, - MULSUBv16i8_OP1, - MULSUBv16i8_OP2, - MULSUBv4i16_OP1, - MULSUBv4i16_OP2, - MULSUBv8i16_OP1, - MULSUBv8i16_OP2, - MULSUBv2i32_OP1, - MULSUBv2i32_OP2, - MULSUBv4i32_OP1, - MULSUBv4i32_OP2, - - MULADDv4i16_indexed_OP1, - MULADDv4i16_indexed_OP2, - MULADDv8i16_indexed_OP1, - MULADDv8i16_indexed_OP2, - MULADDv2i32_indexed_OP1, - MULADDv2i32_indexed_OP2, - MULADDv4i32_indexed_OP1, - MULADDv4i32_indexed_OP2, - - MULSUBv4i16_indexed_OP1, - MULSUBv4i16_indexed_OP2, - MULSUBv8i16_indexed_OP1, - MULSUBv8i16_indexed_OP2, - MULSUBv2i32_indexed_OP1, - MULSUBv2i32_indexed_OP2, - MULSUBv4i32_indexed_OP1, - MULSUBv4i32_indexed_OP2, - - // Floating Point - FMULADDH_OP1, - FMULADDH_OP2, - FMULSUBH_OP1, - FMULSUBH_OP2, - FMULADDS_OP1, - FMULADDS_OP2, - FMULSUBS_OP1, - FMULSUBS_OP2, - FMULADDD_OP1, - FMULADDD_OP2, - FMULSUBD_OP1, - FMULSUBD_OP2, - FNMULSUBH_OP1, - FNMULSUBS_OP1, - FNMULSUBD_OP1, - FMLAv1i32_indexed_OP1, - FMLAv1i32_indexed_OP2, - FMLAv1i64_indexed_OP1, - FMLAv1i64_indexed_OP2, - FMLAv4f16_OP1, - FMLAv4f16_OP2, - FMLAv8f16_OP1, - FMLAv8f16_OP2, - FMLAv2f32_OP2, - FMLAv2f32_OP1, - FMLAv2f64_OP1, - FMLAv2f64_OP2, - FMLAv4i16_indexed_OP1, - FMLAv4i16_indexed_OP2, - FMLAv8i16_indexed_OP1, - FMLAv8i16_indexed_OP2, - FMLAv2i32_indexed_OP1, - FMLAv2i32_indexed_OP2, - FMLAv2i64_indexed_OP1, - FMLAv2i64_indexed_OP2, - FMLAv4f32_OP1, - FMLAv4f32_OP2, - FMLAv4i32_indexed_OP1, - FMLAv4i32_indexed_OP2, - FMLSv1i32_indexed_OP2, - FMLSv1i64_indexed_OP2, - FMLSv4f16_OP1, - FMLSv4f16_OP2, - FMLSv8f16_OP1, - FMLSv8f16_OP2, - FMLSv2f32_OP1, - FMLSv2f32_OP2, - FMLSv2f64_OP1, - FMLSv2f64_OP2, - FMLSv4i16_indexed_OP1, - FMLSv4i16_indexed_OP2, - FMLSv8i16_indexed_OP1, - FMLSv8i16_indexed_OP2, - FMLSv2i32_indexed_OP1, - FMLSv2i32_indexed_OP2, - FMLSv2i64_indexed_OP1, - FMLSv2i64_indexed_OP2, - FMLSv4f32_OP1, - FMLSv4f32_OP2, - FMLSv4i32_indexed_OP1, - FMLSv4i32_indexed_OP2, - - FMULv2i32_indexed_OP1, - FMULv2i32_indexed_OP2, - FMULv2i64_indexed_OP1, - FMULv2i64_indexed_OP2, - FMULv4i16_indexed_OP1, - FMULv4i16_indexed_OP2, - FMULv4i32_indexed_OP1, - FMULv4i32_indexed_OP2, - FMULv8i16_indexed_OP1, - FMULv8i16_indexed_OP2, -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineConstantPool.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineConstantPool.h deleted file mode 100644 index a9bc0ce300..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineConstantPool.h +++ /dev/null @@ -1,159 +0,0 @@ -//===- CodeGen/MachineConstantPool.h - Abstract Constant Pool ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file declares the MachineConstantPool class which is an abstract -/// constant pool to keep track of constants referenced by a function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H -#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/Alignment.h" -#include -#include - -namespace llvm { - -class Constant; -class DataLayout; -class FoldingSetNodeID; -class MachineConstantPool; -class raw_ostream; -class Type; - -/// Abstract base class for all machine specific constantpool value subclasses. -/// -class MachineConstantPoolValue { - virtual void anchor(); - - Type *Ty; - -public: - explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {} - virtual ~MachineConstantPoolValue() = default; - - Type *getType() const { return Ty; } - - virtual unsigned getSizeInBytes(const DataLayout &DL) const; - - virtual int getExistingMachineCPValue(MachineConstantPool *CP, - Align Alignment) = 0; - - virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; - - /// print - Implement operator<< - virtual void print(raw_ostream &O) const = 0; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, - const MachineConstantPoolValue &V) { - V.print(OS); - return OS; -} - -/// This class is a data container for one entry in a MachineConstantPool. -/// It contains a pointer to the value and an offset from the start of -/// the constant pool. -/// An entry in a MachineConstantPool -class MachineConstantPoolEntry { -public: - /// The constant itself. - union { - const Constant *ConstVal; - MachineConstantPoolValue *MachineCPVal; - } Val; - - /// The required alignment for this entry. - Align Alignment; - - bool IsMachineConstantPoolEntry; - - MachineConstantPoolEntry(const Constant *V, Align A) - : Alignment(A), IsMachineConstantPoolEntry(false) { - Val.ConstVal = V; - } - - MachineConstantPoolEntry(MachineConstantPoolValue *V, Align A) - : Alignment(A), IsMachineConstantPoolEntry(true) { - Val.MachineCPVal = V; - } - - /// isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry - /// is indeed a target specific constantpool entry, not a wrapper over a - /// Constant. - bool isMachineConstantPoolEntry() const { return IsMachineConstantPoolEntry; } - - Align getAlign() const { return Alignment; } - - unsigned getSizeInBytes(const DataLayout &DL) const; - - /// This method classifies the entry according to whether or not it may - /// generate a relocation entry. This must be conservative, so if it might - /// codegen to a relocatable entry, it should say so. - bool needsRelocation() const; - - SectionKind getSectionKind(const DataLayout *DL) const; -}; - -/// The MachineConstantPool class keeps track of constants referenced by a -/// function which must be spilled to memory. This is used for constants which -/// are unable to be used directly as operands to instructions, which typically -/// include floating point and large integer constants. -/// -/// Instructions reference the address of these constant pool constants through -/// the use of MO_ConstantPoolIndex values. When emitting assembly or machine -/// code, these virtual address references are converted to refer to the -/// address of the function constant pool values. -/// The machine constant pool. -class MachineConstantPool { - Align PoolAlignment; ///< The alignment for the pool. - std::vector Constants; ///< The pool of constants. - /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. - DenseSet MachineCPVsSharingEntries; - const DataLayout &DL; - - const DataLayout &getDataLayout() const { return DL; } - -public: - /// The only constructor. - explicit MachineConstantPool(const DataLayout &DL) - : PoolAlignment(1), DL(DL) {} - ~MachineConstantPool(); - - /// Return the alignment required by the whole constant pool, of which the - /// first element must be aligned. - Align getConstantPoolAlign() const { return PoolAlignment; } - - /// getConstantPoolIndex - Create a new entry in the constant pool or return - /// an existing one. User must specify the minimum required alignment for - /// the object. - unsigned getConstantPoolIndex(const Constant *C, Align Alignment); - unsigned getConstantPoolIndex(MachineConstantPoolValue *V, Align Alignment); - - /// isEmpty - Return true if this constant pool contains no constants. - bool isEmpty() const { return Constants.empty(); } - - const std::vector &getConstants() const { - return Constants; - } - - /// print - Used by the MachineFunction printer to print information about - /// constant pool objects. Implemented in MachineFunction.cpp - void print(raw_ostream &OS) const; - - /// dump - Call print(cerr) to be called from the debugger. - void dump() const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINECONSTANTPOOL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineCycleAnalysis.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineCycleAnalysis.h deleted file mode 100644 index d3816bbc07..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineCycleAnalysis.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- MachineCycleAnalysis.h - Cycle Info for Machine IR -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachineCycleInfo class, which is a thin wrapper over -// the Machine IR instance of GenericCycleInfo. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECYCLEANALYSIS_H -#define LLVM_CODEGEN_MACHINECYCLEANALYSIS_H - -#include "llvm/ADT/GenericCycleInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineSSAContext.h" - -namespace llvm { - -extern template class GenericCycleInfo; -extern template class GenericCycle; - -using MachineCycleInfo = GenericCycleInfo; -using MachineCycle = MachineCycleInfo::CycleT; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINECYCLEANALYSIS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominanceFrontier.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominanceFrontier.h deleted file mode 100644 index e3e6796087..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominanceFrontier.h +++ /dev/null @@ -1,109 +0,0 @@ -//===- llvm/CodeGen/MachineDominanceFrontier.h ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H -#define LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H - -#include "llvm/Analysis/DominanceFrontier.h" -#include "llvm/Analysis/DominanceFrontierImpl.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/GenericDomTree.h" - -namespace llvm { - -class MachineDominanceFrontier : public MachineFunctionPass { - ForwardDominanceFrontierBase Base; - -public: - using DomTreeT = DomTreeBase; - using DomTreeNodeT = DomTreeNodeBase; - using DomSetType = DominanceFrontierBase::DomSetType; - using iterator = DominanceFrontierBase::iterator; - using const_iterator = - DominanceFrontierBase::const_iterator; - - MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; - MachineDominanceFrontier &operator=(const MachineDominanceFrontier &) = delete; - - static char ID; - - MachineDominanceFrontier(); - - ForwardDominanceFrontierBase &getBase() { return Base; } - - const SmallVectorImpl &getRoots() const { - return Base.getRoots(); - } - - MachineBasicBlock *getRoot() const { - return Base.getRoot(); - } - - bool isPostDominator() const { - return Base.isPostDominator(); - } - - iterator begin() { - return Base.begin(); - } - - const_iterator begin() const { - return Base.begin(); - } - - iterator end() { - return Base.end(); - } - - const_iterator end() const { - return Base.end(); - } - - iterator find(MachineBasicBlock *B) { - return Base.find(B); - } - - const_iterator find(MachineBasicBlock *B) const { - return Base.find(B); - } - - iterator addBasicBlock(MachineBasicBlock *BB, const DomSetType &frontier) { - return Base.addBasicBlock(BB, frontier); - } - - void removeBlock(MachineBasicBlock *BB) { - return Base.removeBlock(BB); - } - - void addToFrontier(iterator I, MachineBasicBlock *Node) { - return Base.addToFrontier(I, Node); - } - - void removeFromFrontier(iterator I, MachineBasicBlock *Node) { - return Base.removeFromFrontier(I, Node); - } - - bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { - return Base.compareDomSet(DS1, DS2); - } - - bool compare(DominanceFrontierBase &Other) const { - return Base.compare(Other); - } - - bool runOnMachineFunction(MachineFunction &F) override; - - void releaseMemory() override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominators.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominators.h deleted file mode 100644 index f749e9ff7e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineDominators.h +++ /dev/null @@ -1,287 +0,0 @@ -//==- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines classes mirroring those in llvm/Analysis/Dominators.h, -// but for target-specific code rather than target-independent IR. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H -#define LLVM_CODEGEN_MACHINEDOMINATORS_H - -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Support/GenericDomTree.h" -#include "llvm/Support/GenericDomTreeConstruction.h" -#include -#include - -namespace llvm { - -template <> -inline void DominatorTreeBase::addRoot( - MachineBasicBlock *MBB) { - this->Roots.push_back(MBB); -} - -extern template class DomTreeNodeBase; -extern template class DominatorTreeBase; // DomTree -extern template class DominatorTreeBase; // PostDomTree - -using MachineDomTree = DomTreeBase; -using MachineDomTreeNode = DomTreeNodeBase; - -//===------------------------------------- -/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to -/// compute a normal dominator tree. -/// -class MachineDominatorTree : public MachineFunctionPass { - /// Helper structure used to hold all the basic blocks - /// involved in the split of a critical edge. - struct CriticalEdge { - MachineBasicBlock *FromBB; - MachineBasicBlock *ToBB; - MachineBasicBlock *NewBB; - }; - - /// Pile up all the critical edges to be split. - /// The splitting of a critical edge is local and thus, it is possible - /// to apply several of those changes at the same time. - mutable SmallVector CriticalEdgesToSplit; - - /// Remember all the basic blocks that are inserted during - /// edge splitting. - /// Invariant: NewBBs == all the basic blocks contained in the NewBB - /// field of all the elements of CriticalEdgesToSplit. - /// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs - /// such as BB == elt.NewBB. - mutable SmallSet NewBBs; - - /// The DominatorTreeBase that is used to compute a normal dominator tree. - std::unique_ptr DT; - - /// Apply all the recorded critical edges to the DT. - /// This updates the underlying DT information in a way that uses - /// the fast query path of DT as much as possible. - /// - /// \post CriticalEdgesToSplit.empty(). - void applySplitCriticalEdges() const; - -public: - static char ID; // Pass ID, replacement for typeid - - MachineDominatorTree(); - explicit MachineDominatorTree(MachineFunction &MF) : MachineFunctionPass(ID) { - calculate(MF); - } - - MachineDomTree &getBase() { - if (!DT) - DT.reset(new MachineDomTree()); - applySplitCriticalEdges(); - return *DT; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineBasicBlock *getRoot() const { - applySplitCriticalEdges(); - return DT->getRoot(); - } - - MachineDomTreeNode *getRootNode() const { - applySplitCriticalEdges(); - return DT->getRootNode(); - } - - bool runOnMachineFunction(MachineFunction &F) override; - - void calculate(MachineFunction &F); - - bool dominates(const MachineDomTreeNode *A, - const MachineDomTreeNode *B) const { - applySplitCriticalEdges(); - return DT->dominates(A, B); - } - - void getDescendants(MachineBasicBlock *A, - SmallVectorImpl &Result) { - applySplitCriticalEdges(); - DT->getDescendants(A, Result); - } - - bool dominates(const MachineBasicBlock *A, const MachineBasicBlock *B) const { - applySplitCriticalEdges(); - return DT->dominates(A, B); - } - - // dominates - Return true if A dominates B. This performs the - // special checks necessary if A and B are in the same basic block. - bool dominates(const MachineInstr *A, const MachineInstr *B) const { - applySplitCriticalEdges(); - const MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); - if (BBA != BBB) return DT->dominates(BBA, BBB); - - // Loop through the basic block until we find A or B. - MachineBasicBlock::const_iterator I = BBA->begin(); - for (; &*I != A && &*I != B; ++I) - /*empty*/ ; - - return &*I == A; - } - - bool properlyDominates(const MachineDomTreeNode *A, - const MachineDomTreeNode *B) const { - applySplitCriticalEdges(); - return DT->properlyDominates(A, B); - } - - bool properlyDominates(const MachineBasicBlock *A, - const MachineBasicBlock *B) const { - applySplitCriticalEdges(); - return DT->properlyDominates(A, B); - } - - /// findNearestCommonDominator - Find nearest common dominator basic block - /// for basic block A and B. If there is no such block then return NULL. - MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, - MachineBasicBlock *B) { - applySplitCriticalEdges(); - return DT->findNearestCommonDominator(A, B); - } - - MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { - applySplitCriticalEdges(); - return DT->getNode(BB); - } - - /// getNode - return the (Post)DominatorTree node for the specified basic - /// block. This is the same as using operator[] on this class. - /// - MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { - applySplitCriticalEdges(); - return DT->getNode(BB); - } - - /// addNewBlock - Add a new node to the dominator tree information. This - /// creates a new node as a child of DomBB dominator node,linking it into - /// the children list of the immediate dominator. - MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, - MachineBasicBlock *DomBB) { - applySplitCriticalEdges(); - return DT->addNewBlock(BB, DomBB); - } - - /// changeImmediateDominator - This method is used to update the dominator - /// tree information when a node's immediate dominator changes. - /// - void changeImmediateDominator(MachineBasicBlock *N, - MachineBasicBlock *NewIDom) { - applySplitCriticalEdges(); - DT->changeImmediateDominator(N, NewIDom); - } - - void changeImmediateDominator(MachineDomTreeNode *N, - MachineDomTreeNode *NewIDom) { - applySplitCriticalEdges(); - DT->changeImmediateDominator(N, NewIDom); - } - - /// eraseNode - Removes a node from the dominator tree. Block must not - /// dominate any other blocks. Removes node from its immediate dominator's - /// children list. Deletes dominator node associated with basic block BB. - void eraseNode(MachineBasicBlock *BB) { - applySplitCriticalEdges(); - DT->eraseNode(BB); - } - - /// splitBlock - BB is split and now it has one successor. Update dominator - /// tree to reflect this change. - void splitBlock(MachineBasicBlock* NewBB) { - applySplitCriticalEdges(); - DT->splitBlock(NewBB); - } - - /// isReachableFromEntry - Return true if A is dominated by the entry - /// block of the function containing it. - bool isReachableFromEntry(const MachineBasicBlock *A) { - applySplitCriticalEdges(); - return DT->isReachableFromEntry(A); - } - - void releaseMemory() override; - - void verifyAnalysis() const override; - - void print(raw_ostream &OS, const Module*) const override; - - /// Record that the critical edge (FromBB, ToBB) has been - /// split with NewBB. - /// This is best to use this method instead of directly update the - /// underlying information, because this helps mitigating the - /// number of time the DT information is invalidated. - /// - /// \note Do not use this method with regular edges. - /// - /// \note To benefit from the compile time improvement incurred by this - /// method, the users of this method have to limit the queries to the DT - /// interface between two edges splitting. In other words, they have to - /// pack the splitting of critical edges as much as possible. - void recordSplitCriticalEdge(MachineBasicBlock *FromBB, - MachineBasicBlock *ToBB, - MachineBasicBlock *NewBB) { - bool Inserted = NewBBs.insert(NewBB).second; - (void)Inserted; - assert(Inserted && - "A basic block inserted via edge splitting cannot appear twice"); - CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB}); - } -}; - -//===------------------------------------- -/// DominatorTree GraphTraits specialization so the DominatorTree can be -/// iterable by generic graph iterators. -/// - -template -struct MachineDomTreeGraphTraitsBase { - using NodeRef = Node *; - using ChildIteratorType = ChildIterator; - - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->end(); } -}; - -template struct GraphTraits; - -template <> -struct GraphTraits - : public MachineDomTreeGraphTraitsBase { -}; - -template <> -struct GraphTraits - : public MachineDomTreeGraphTraitsBase { -}; - -template <> struct GraphTraits - : public GraphTraits { - static NodeRef getEntryNode(MachineDominatorTree *DT) { - return DT->getRootNode(); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEDOMINATORS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFrameInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineFrameInfo.h deleted file mode 100644 index 0105c14101..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFrameInfo.h +++ /dev/null @@ -1,796 +0,0 @@ -//===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The file defines the MachineFrameInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H -#define LLVM_CODEGEN_MACHINEFRAMEINFO_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/DataTypes.h" -#include -#include - -namespace llvm { -class raw_ostream; -class MachineFunction; -class MachineBasicBlock; -class BitVector; -class AllocaInst; - -/// The CalleeSavedInfo class tracks the information need to locate where a -/// callee saved register is in the current frame. -/// Callee saved reg can also be saved to a different register rather than -/// on the stack by setting DstReg instead of FrameIdx. -class CalleeSavedInfo { - Register Reg; - union { - int FrameIdx; - unsigned DstReg; - }; - /// Flag indicating whether the register is actually restored in the epilog. - /// In most cases, if a register is saved, it is also restored. There are - /// some situations, though, when this is not the case. For example, the - /// LR register on ARM is usually saved, but on exit from the function its - /// saved value may be loaded directly into PC. Since liveness tracking of - /// physical registers treats callee-saved registers are live outside of - /// the function, LR would be treated as live-on-exit, even though in these - /// scenarios it is not. This flag is added to indicate that the saved - /// register described by this object is not restored in the epilog. - /// The long-term solution is to model the liveness of callee-saved registers - /// by implicit uses on the return instructions, however, the required - /// changes in the ARM backend would be quite extensive. - bool Restored = true; - /// Flag indicating whether the register is spilled to stack or another - /// register. - bool SpilledToReg = false; - -public: - explicit CalleeSavedInfo(unsigned R, int FI = 0) : Reg(R), FrameIdx(FI) {} - - // Accessors. - Register getReg() const { return Reg; } - int getFrameIdx() const { return FrameIdx; } - unsigned getDstReg() const { return DstReg; } - void setFrameIdx(int FI) { - FrameIdx = FI; - SpilledToReg = false; - } - void setDstReg(Register SpillReg) { - DstReg = SpillReg; - SpilledToReg = true; - } - bool isRestored() const { return Restored; } - void setRestored(bool R) { Restored = R; } - bool isSpilledToReg() const { return SpilledToReg; } -}; - -/// The MachineFrameInfo class represents an abstract stack frame until -/// prolog/epilog code is inserted. This class is key to allowing stack frame -/// representation optimizations, such as frame pointer elimination. It also -/// allows more mundane (but still important) optimizations, such as reordering -/// of abstract objects on the stack frame. -/// -/// To support this, the class assigns unique integer identifiers to stack -/// objects requested clients. These identifiers are negative integers for -/// fixed stack objects (such as arguments passed on the stack) or nonnegative -/// for objects that may be reordered. Instructions which refer to stack -/// objects use a special MO_FrameIndex operand to represent these frame -/// indexes. -/// -/// Because this class keeps track of all references to the stack frame, it -/// knows when a variable sized object is allocated on the stack. This is the -/// sole condition which prevents frame pointer elimination, which is an -/// important optimization on register-poor architectures. Because original -/// variable sized alloca's in the source program are the only source of -/// variable sized stack objects, it is safe to decide whether there will be -/// any variable sized objects before all stack objects are known (for -/// example, register allocator spill code never needs variable sized -/// objects). -/// -/// When prolog/epilog code emission is performed, the final stack frame is -/// built and the machine instructions are modified to refer to the actual -/// stack offsets of the object, eliminating all MO_FrameIndex operands from -/// the program. -/// -/// Abstract Stack Frame Information -class MachineFrameInfo { -public: - /// Stack Smashing Protection (SSP) rules require that vulnerable stack - /// allocations are located close the stack protector. - enum SSPLayoutKind { - SSPLK_None, ///< Did not trigger a stack protector. No effect on data - ///< layout. - SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest - ///< to the stack protector. - SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest - ///< to the stack protector. - SSPLK_AddrOf ///< The address of this allocation is exposed and - ///< triggered protection. 3rd closest to the protector. - }; - -private: - // Represent a single object allocated on the stack. - struct StackObject { - // The offset of this object from the stack pointer on entry to - // the function. This field has no meaning for a variable sized element. - int64_t SPOffset; - - // The size of this object on the stack. 0 means a variable sized object, - // ~0ULL means a dead object. - uint64_t Size; - - // The required alignment of this stack slot. - Align Alignment; - - // If true, the value of the stack object is set before - // entering the function and is not modified inside the function. By - // default, fixed objects are immutable unless marked otherwise. - bool isImmutable; - - // If true the stack object is used as spill slot. It - // cannot alias any other memory objects. - bool isSpillSlot; - - /// If true, this stack slot is used to spill a value (could be deopt - /// and/or GC related) over a statepoint. We know that the address of the - /// slot can't alias any LLVM IR value. This is very similar to a Spill - /// Slot, but is created by statepoint lowering is SelectionDAG, not the - /// register allocator. - bool isStatepointSpillSlot = false; - - /// Identifier for stack memory type analogous to address space. If this is - /// non-0, the meaning is target defined. Offsets cannot be directly - /// compared between objects with different stack IDs. The object may not - /// necessarily reside in the same contiguous memory block as other stack - /// objects. Objects with differing stack IDs should not be merged or - /// replaced substituted for each other. - // - /// It is assumed a target uses consecutive, increasing stack IDs starting - /// from 1. - uint8_t StackID; - - /// If this stack object is originated from an Alloca instruction - /// this value saves the original IR allocation. Can be NULL. - const AllocaInst *Alloca; - - // If true, the object was mapped into the local frame - // block and doesn't need additional handling for allocation beyond that. - bool PreAllocated = false; - - // If true, an LLVM IR value might point to this object. - // Normally, spill slots and fixed-offset objects don't alias IR-accessible - // objects, but there are exceptions (on PowerPC, for example, some byval - // arguments have ABI-prescribed offsets). - bool isAliased; - - /// If true, the object has been zero-extended. - bool isZExt = false; - - /// If true, the object has been sign-extended. - bool isSExt = false; - - uint8_t SSPLayout = SSPLK_None; - - StackObject(uint64_t Size, Align Alignment, int64_t SPOffset, - bool IsImmutable, bool IsSpillSlot, const AllocaInst *Alloca, - bool IsAliased, uint8_t StackID = 0) - : SPOffset(SPOffset), Size(Size), Alignment(Alignment), - isImmutable(IsImmutable), isSpillSlot(IsSpillSlot), StackID(StackID), - Alloca(Alloca), isAliased(IsAliased) {} - }; - - /// The alignment of the stack. - Align StackAlignment; - - /// Can the stack be realigned. This can be false if the target does not - /// support stack realignment, or if the user asks us not to realign the - /// stack. In this situation, overaligned allocas are all treated as dynamic - /// allocations and the target must handle them as part of DYNAMIC_STACKALLOC - /// lowering. All non-alloca stack objects have their alignment clamped to the - /// base ABI stack alignment. - /// FIXME: There is room for improvement in this case, in terms of - /// grouping overaligned allocas into a "secondary stack frame" and - /// then only use a single alloca to allocate this frame and only a - /// single virtual register to access it. Currently, without such an - /// optimization, each such alloca gets its own dynamic realignment. - bool StackRealignable; - - /// Whether the function has the \c alignstack attribute. - bool ForcedRealign; - - /// The list of stack objects allocated. - std::vector Objects; - - /// This contains the number of fixed objects contained on - /// the stack. Because fixed objects are stored at a negative index in the - /// Objects list, this is also the index to the 0th object in the list. - unsigned NumFixedObjects = 0; - - /// This boolean keeps track of whether any variable - /// sized objects have been allocated yet. - bool HasVarSizedObjects = false; - - /// This boolean keeps track of whether there is a call - /// to builtin \@llvm.frameaddress. - bool FrameAddressTaken = false; - - /// This boolean keeps track of whether there is a call - /// to builtin \@llvm.returnaddress. - bool ReturnAddressTaken = false; - - /// This boolean keeps track of whether there is a call - /// to builtin \@llvm.experimental.stackmap. - bool HasStackMap = false; - - /// This boolean keeps track of whether there is a call - /// to builtin \@llvm.experimental.patchpoint. - bool HasPatchPoint = false; - - /// The prolog/epilog code inserter calculates the final stack - /// offsets for all of the fixed size objects, updating the Objects list - /// above. It then updates StackSize to contain the number of bytes that need - /// to be allocated on entry to the function. - uint64_t StackSize = 0; - - /// The amount that a frame offset needs to be adjusted to - /// have the actual offset from the stack/frame pointer. The exact usage of - /// this is target-dependent, but it is typically used to adjust between - /// SP-relative and FP-relative offsets. E.G., if objects are accessed via - /// SP then OffsetAdjustment is zero; if FP is used, OffsetAdjustment is set - /// to the distance between the initial SP and the value in FP. For many - /// targets, this value is only used when generating debug info (via - /// TargetRegisterInfo::getFrameIndexReference); when generating code, the - /// corresponding adjustments are performed directly. - int OffsetAdjustment = 0; - - /// The prolog/epilog code inserter may process objects that require greater - /// alignment than the default alignment the target provides. - /// To handle this, MaxAlignment is set to the maximum alignment - /// needed by the objects on the current frame. If this is greater than the - /// native alignment maintained by the compiler, dynamic alignment code will - /// be needed. - /// - Align MaxAlignment; - - /// Set to true if this function adjusts the stack -- e.g., - /// when calling another function. This is only valid during and after - /// prolog/epilog code insertion. - bool AdjustsStack = false; - - /// Set to true if this function has any function calls. - bool HasCalls = false; - - /// The frame index for the stack protector. - int StackProtectorIdx = -1; - - /// The frame index for the function context. Used for SjLj exceptions. - int FunctionContextIdx = -1; - - /// This contains the size of the largest call frame if the target uses frame - /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo - /// class). This information is important for frame pointer elimination. - /// It is only valid during and after prolog/epilog code insertion. - unsigned MaxCallFrameSize = ~0u; - - /// The number of bytes of callee saved registers that the target wants to - /// report for the current function in the CodeView S_FRAMEPROC record. - unsigned CVBytesOfCalleeSavedRegisters = 0; - - /// The prolog/epilog code inserter fills in this vector with each - /// callee saved register saved in either the frame or a different - /// register. Beyond its use by the prolog/ epilog code inserter, - /// this data is used for debug info and exception handling. - std::vector CSInfo; - - /// Has CSInfo been set yet? - bool CSIValid = false; - - /// References to frame indices which are mapped - /// into the local frame allocation block. - SmallVector, 32> LocalFrameObjects; - - /// Size of the pre-allocated local frame block. - int64_t LocalFrameSize = 0; - - /// Required alignment of the local object blob, which is the strictest - /// alignment of any object in it. - Align LocalFrameMaxAlign; - - /// Whether the local object blob needs to be allocated together. If not, - /// PEI should ignore the isPreAllocated flags on the stack objects and - /// just allocate them normally. - bool UseLocalStackAllocationBlock = false; - - /// True if the function dynamically adjusts the stack pointer through some - /// opaque mechanism like inline assembly or Win32 EH. - bool HasOpaqueSPAdjustment = false; - - /// True if the function contains operations which will lower down to - /// instructions which manipulate the stack pointer. - bool HasCopyImplyingStackAdjustment = false; - - /// True if the function contains a call to the llvm.vastart intrinsic. - bool HasVAStart = false; - - /// True if this is a varargs function that contains a musttail call. - bool HasMustTailInVarArgFunc = false; - - /// True if this function contains a tail call. If so immutable objects like - /// function arguments are no longer so. A tail call *can* override fixed - /// stack objects like arguments so we can't treat them as immutable. - bool HasTailCall = false; - - /// Not null, if shrink-wrapping found a better place for the prologue. - MachineBasicBlock *Save = nullptr; - /// Not null, if shrink-wrapping found a better place for the epilogue. - MachineBasicBlock *Restore = nullptr; - -public: - explicit MachineFrameInfo(unsigned StackAlignment, bool StackRealignable, - bool ForcedRealign) - : StackAlignment(assumeAligned(StackAlignment)), - StackRealignable(StackRealignable), ForcedRealign(ForcedRealign) {} - - MachineFrameInfo(const MachineFrameInfo &) = delete; - - /// Return true if there are any stack objects in this function. - bool hasStackObjects() const { return !Objects.empty(); } - - /// This method may be called any time after instruction - /// selection is complete to determine if the stack frame for this function - /// contains any variable sized objects. - bool hasVarSizedObjects() const { return HasVarSizedObjects; } - - /// Return the index for the stack protector object. - int getStackProtectorIndex() const { return StackProtectorIdx; } - void setStackProtectorIndex(int I) { StackProtectorIdx = I; } - bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; } - - /// Return the index for the function context object. - /// This object is used for SjLj exceptions. - int getFunctionContextIndex() const { return FunctionContextIdx; } - void setFunctionContextIndex(int I) { FunctionContextIdx = I; } - - /// This method may be called any time after instruction - /// selection is complete to determine if there is a call to - /// \@llvm.frameaddress in this function. - bool isFrameAddressTaken() const { return FrameAddressTaken; } - void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } - - /// This method may be called any time after - /// instruction selection is complete to determine if there is a call to - /// \@llvm.returnaddress in this function. - bool isReturnAddressTaken() const { return ReturnAddressTaken; } - void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } - - /// This method may be called any time after instruction - /// selection is complete to determine if there is a call to builtin - /// \@llvm.experimental.stackmap. - bool hasStackMap() const { return HasStackMap; } - void setHasStackMap(bool s = true) { HasStackMap = s; } - - /// This method may be called any time after instruction - /// selection is complete to determine if there is a call to builtin - /// \@llvm.experimental.patchpoint. - bool hasPatchPoint() const { return HasPatchPoint; } - void setHasPatchPoint(bool s = true) { HasPatchPoint = s; } - - /// Return the minimum frame object index. - int getObjectIndexBegin() const { return -NumFixedObjects; } - - /// Return one past the maximum frame object index. - int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; } - - /// Return the number of fixed objects. - unsigned getNumFixedObjects() const { return NumFixedObjects; } - - /// Return the number of objects. - unsigned getNumObjects() const { return Objects.size(); } - - /// Map a frame index into the local object block - void mapLocalFrameObject(int ObjectIndex, int64_t Offset) { - LocalFrameObjects.push_back(std::pair(ObjectIndex, Offset)); - Objects[ObjectIndex + NumFixedObjects].PreAllocated = true; - } - - /// Get the local offset mapping for a for an object. - std::pair getLocalFrameObjectMap(int i) const { - assert (i >= 0 && (unsigned)i < LocalFrameObjects.size() && - "Invalid local object reference!"); - return LocalFrameObjects[i]; - } - - /// Return the number of objects allocated into the local object block. - int64_t getLocalFrameObjectCount() const { return LocalFrameObjects.size(); } - - /// Set the size of the local object blob. - void setLocalFrameSize(int64_t sz) { LocalFrameSize = sz; } - - /// Get the size of the local object blob. - int64_t getLocalFrameSize() const { return LocalFrameSize; } - - /// Required alignment of the local object blob, - /// which is the strictest alignment of any object in it. - void setLocalFrameMaxAlign(Align Alignment) { - LocalFrameMaxAlign = Alignment; - } - - /// Return the required alignment of the local object blob. - Align getLocalFrameMaxAlign() const { return LocalFrameMaxAlign; } - - /// Get whether the local allocation blob should be allocated together or - /// let PEI allocate the locals in it directly. - bool getUseLocalStackAllocationBlock() const { - return UseLocalStackAllocationBlock; - } - - /// setUseLocalStackAllocationBlock - Set whether the local allocation blob - /// should be allocated together or let PEI allocate the locals in it - /// directly. - void setUseLocalStackAllocationBlock(bool v) { - UseLocalStackAllocationBlock = v; - } - - /// Return true if the object was pre-allocated into the local block. - bool isObjectPreAllocated(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].PreAllocated; - } - - /// Return the size of the specified object. - int64_t getObjectSize(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].Size; - } - - /// Change the size of the specified stack object. - void setObjectSize(int ObjectIdx, int64_t Size) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].Size = Size; - } - - /// Return the alignment of the specified stack object. - Align getObjectAlign(int ObjectIdx) const { - assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx + NumFixedObjects].Alignment; - } - - /// setObjectAlignment - Change the alignment of the specified stack object. - void setObjectAlignment(int ObjectIdx, Align Alignment) { - assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx + NumFixedObjects].Alignment = Alignment; - - // Only ensure max alignment for the default stack. - if (getStackID(ObjectIdx) == 0) - ensureMaxAlignment(Alignment); - } - - /// Return the underlying Alloca of the specified - /// stack object if it exists. Returns 0 if none exists. - const AllocaInst* getObjectAllocation(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].Alloca; - } - - /// Return the assigned stack offset of the specified object - /// from the incoming stack pointer. - int64_t getObjectOffset(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - assert(!isDeadObjectIndex(ObjectIdx) && - "Getting frame offset for a dead object?"); - return Objects[ObjectIdx+NumFixedObjects].SPOffset; - } - - bool isObjectZExt(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isZExt; - } - - void setObjectZExt(int ObjectIdx, bool IsZExt) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isZExt = IsZExt; - } - - bool isObjectSExt(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isSExt; - } - - void setObjectSExt(int ObjectIdx, bool IsSExt) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isSExt = IsSExt; - } - - /// Set the stack frame offset of the specified object. The - /// offset is relative to the stack pointer on entry to the function. - void setObjectOffset(int ObjectIdx, int64_t SPOffset) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - assert(!isDeadObjectIndex(ObjectIdx) && - "Setting frame offset for a dead object?"); - Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; - } - - SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return (SSPLayoutKind)Objects[ObjectIdx+NumFixedObjects].SSPLayout; - } - - void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - assert(!isDeadObjectIndex(ObjectIdx) && - "Setting SSP layout for a dead object?"); - Objects[ObjectIdx+NumFixedObjects].SSPLayout = Kind; - } - - /// Return the number of bytes that must be allocated to hold - /// all of the fixed size frame objects. This is only valid after - /// Prolog/Epilog code insertion has finalized the stack frame layout. - uint64_t getStackSize() const { return StackSize; } - - /// Set the size of the stack. - void setStackSize(uint64_t Size) { StackSize = Size; } - - /// Estimate and return the size of the stack frame. - uint64_t estimateStackSize(const MachineFunction &MF) const; - - /// Return the correction for frame offsets. - int getOffsetAdjustment() const { return OffsetAdjustment; } - - /// Set the correction for frame offsets. - void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } - - /// Return the alignment in bytes that this function must be aligned to, - /// which is greater than the default stack alignment provided by the target. - Align getMaxAlign() const { return MaxAlignment; } - - /// Make sure the function is at least Align bytes aligned. - void ensureMaxAlignment(Align Alignment); - - /// Return true if this function adjusts the stack -- e.g., - /// when calling another function. This is only valid during and after - /// prolog/epilog code insertion. - bool adjustsStack() const { return AdjustsStack; } - void setAdjustsStack(bool V) { AdjustsStack = V; } - - /// Return true if the current function has any function calls. - bool hasCalls() const { return HasCalls; } - void setHasCalls(bool V) { HasCalls = V; } - - /// Returns true if the function contains opaque dynamic stack adjustments. - bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; } - void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; } - - /// Returns true if the function contains operations which will lower down to - /// instructions which manipulate the stack pointer. - bool hasCopyImplyingStackAdjustment() const { - return HasCopyImplyingStackAdjustment; - } - void setHasCopyImplyingStackAdjustment(bool B) { - HasCopyImplyingStackAdjustment = B; - } - - /// Returns true if the function calls the llvm.va_start intrinsic. - bool hasVAStart() const { return HasVAStart; } - void setHasVAStart(bool B) { HasVAStart = B; } - - /// Returns true if the function is variadic and contains a musttail call. - bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } - void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } - - /// Returns true if the function contains a tail call. - bool hasTailCall() const { return HasTailCall; } - void setHasTailCall(bool V = true) { HasTailCall = V; } - - /// Computes the maximum size of a callframe and the AdjustsStack property. - /// This only works for targets defining - /// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(), - /// and getFrameSize(). - /// This is usually computed by the prologue epilogue inserter but some - /// targets may call this to compute it earlier. - void computeMaxCallFrameSize(const MachineFunction &MF); - - /// Return the maximum size of a call frame that must be - /// allocated for an outgoing function call. This is only available if - /// CallFrameSetup/Destroy pseudo instructions are used by the target, and - /// then only during or after prolog/epilog code insertion. - /// - unsigned getMaxCallFrameSize() const { - // TODO: Enable this assert when targets are fixed. - //assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet"); - if (!isMaxCallFrameSizeComputed()) - return 0; - return MaxCallFrameSize; - } - bool isMaxCallFrameSizeComputed() const { - return MaxCallFrameSize != ~0u; - } - void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } - - /// Returns how many bytes of callee-saved registers the target pushed in the - /// prologue. Only used for debug info. - unsigned getCVBytesOfCalleeSavedRegisters() const { - return CVBytesOfCalleeSavedRegisters; - } - void setCVBytesOfCalleeSavedRegisters(unsigned S) { - CVBytesOfCalleeSavedRegisters = S; - } - - /// Create a new object at a fixed location on the stack. - /// All fixed objects should be created before other objects are created for - /// efficiency. By default, fixed objects are not pointed to by LLVM IR - /// values. This returns an index with a negative value. - int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, - bool isAliased = false); - - /// Create a spill slot at a fixed location on the stack. - /// Returns an index with a negative value. - int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, - bool IsImmutable = false); - - /// Returns true if the specified index corresponds to a fixed stack object. - bool isFixedObjectIndex(int ObjectIdx) const { - return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); - } - - /// Returns true if the specified index corresponds - /// to an object that might be pointed to by an LLVM IR value. - bool isAliasedObjectIndex(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isAliased; - } - - /// Returns true if the specified index corresponds to an immutable object. - bool isImmutableObjectIndex(int ObjectIdx) const { - // Tail calling functions can clobber their function arguments. - if (HasTailCall) - return false; - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isImmutable; - } - - /// Marks the immutability of an object. - void setIsImmutableObjectIndex(int ObjectIdx, bool IsImmutable) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isImmutable = IsImmutable; - } - - /// Returns true if the specified index corresponds to a spill slot. - bool isSpillSlotObjectIndex(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isSpillSlot; - } - - bool isStatepointSpillSlotObjectIndex(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isStatepointSpillSlot; - } - - /// \see StackID - uint8_t getStackID(int ObjectIdx) const { - return Objects[ObjectIdx+NumFixedObjects].StackID; - } - - /// \see StackID - void setStackID(int ObjectIdx, uint8_t ID) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].StackID = ID; - // If ID > 0, MaxAlignment may now be overly conservative. - // If ID == 0, MaxAlignment will need to be updated separately. - } - - /// Returns true if the specified index corresponds to a dead object. - bool isDeadObjectIndex(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; - } - - /// Returns true if the specified index corresponds to a variable sized - /// object. - bool isVariableSizedObjectIndex(int ObjectIdx) const { - assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx + NumFixedObjects].Size == 0; - } - - void markAsStatepointSpillSlotObjectIndex(int ObjectIdx) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isStatepointSpillSlot = true; - assert(isStatepointSpillSlotObjectIndex(ObjectIdx) && "inconsistent"); - } - - /// Create a new statically sized stack object, returning - /// a nonnegative identifier to represent it. - int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, - const AllocaInst *Alloca = nullptr, uint8_t ID = 0); - - /// Create a new statically sized stack object that represents a spill slot, - /// returning a nonnegative identifier to represent it. - int CreateSpillStackObject(uint64_t Size, Align Alignment); - - /// Remove or mark dead a statically sized stack object. - void RemoveStackObject(int ObjectIdx) { - // Mark it dead. - Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL; - } - - /// Notify the MachineFrameInfo object that a variable sized object has been - /// created. This must be created whenever a variable sized object is - /// created, whether or not the index returned is actually used. - int CreateVariableSizedObject(Align Alignment, const AllocaInst *Alloca); - - /// Returns a reference to call saved info vector for the current function. - const std::vector &getCalleeSavedInfo() const { - return CSInfo; - } - /// \copydoc getCalleeSavedInfo() - std::vector &getCalleeSavedInfo() { return CSInfo; } - - /// Used by prolog/epilog inserter to set the function's callee saved - /// information. - void setCalleeSavedInfo(std::vector CSI) { - CSInfo = std::move(CSI); - } - - /// Has the callee saved info been calculated yet? - bool isCalleeSavedInfoValid() const { return CSIValid; } - - void setCalleeSavedInfoValid(bool v) { CSIValid = v; } - - MachineBasicBlock *getSavePoint() const { return Save; } - void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; } - MachineBasicBlock *getRestorePoint() const { return Restore; } - void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; } - - /// Return a set of physical registers that are pristine. - /// - /// Pristine registers hold a value that is useless to the current function, - /// but that must be preserved - they are callee saved registers that are not - /// saved. - /// - /// Before the PrologueEpilogueInserter has placed the CSR spill code, this - /// method always returns an empty set. - BitVector getPristineRegs(const MachineFunction &MF) const; - - /// Used by the MachineFunction printer to print information about - /// stack objects. Implemented in MachineFunction.cpp. - void print(const MachineFunction &MF, raw_ostream &OS) const; - - /// dump - Print the function to stderr. - void dump(const MachineFunction &MF) const; -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunction.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunction.h deleted file mode 100644 index a41fcb4072..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunction.h +++ /dev/null @@ -1,1309 +0,0 @@ -//===- llvm/CodeGen/MachineFunction.h ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Collect native machine code for a function. This class contains a list of -// MachineBasicBlock instances that make up the current compiled function. -// -// This class also contains pointers to various classes which hold -// target-specific information about the generated code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H -#define LLVM_CODEGEN_MACHINEFUNCTION_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/iterator.h" -#include "llvm/Analysis/EHPersonalities.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/ArrayRecycler.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Recycler.h" -#include "llvm/Target/TargetOptions.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class BasicBlock; -class BlockAddress; -class DataLayout; -class DebugLoc; -struct DenormalMode; -class DIExpression; -class DILocalVariable; -class DILocation; -class Function; -class GISelChangeObserver; -class GlobalValue; -class LLVMTargetMachine; -class MachineConstantPool; -class MachineFrameInfo; -class MachineFunction; -class MachineJumpTableInfo; -class MachineModuleInfo; -class MachineRegisterInfo; -class MCContext; -class MCInstrDesc; -class MCSymbol; -class MCSection; -class Pass; -class PseudoSourceValueManager; -class raw_ostream; -class SlotIndexes; -class StringRef; -class TargetRegisterClass; -class TargetSubtargetInfo; -struct WasmEHFuncInfo; -struct WinEHFuncInfo; - -template <> struct ilist_alloc_traits { - void deleteNode(MachineBasicBlock *MBB); -}; - -template <> struct ilist_callback_traits { - void addNodeToList(MachineBasicBlock* N); - void removeNodeFromList(MachineBasicBlock* N); - - template - void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) { - assert(this == &OldList && "never transfer MBBs between functions"); - } -}; - -/// MachineFunctionInfo - This class can be derived from and used by targets to -/// hold private target-specific information for each MachineFunction. Objects -/// of type are accessed/created with MF::getInfo and destroyed when the -/// MachineFunction is destroyed. -struct MachineFunctionInfo { - virtual ~MachineFunctionInfo(); - - /// Factory function: default behavior is to call new using the - /// supplied allocator. - /// - /// This function can be overridden in a derive class. - template - static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { - return new (Allocator.Allocate()) Ty(MF); - } -}; - -/// Properties which a MachineFunction may have at a given point in time. -/// Each of these has checking code in the MachineVerifier, and passes can -/// require that a property be set. -class MachineFunctionProperties { - // Possible TODO: Allow targets to extend this (perhaps by allowing the - // constructor to specify the size of the bit vector) - // Possible TODO: Allow requiring the negative (e.g. VRegsAllocated could be - // stated as the negative of "has vregs" - -public: - // The properties are stated in "positive" form; i.e. a pass could require - // that the property hold, but not that it does not hold. - - // Property descriptions: - // IsSSA: True when the machine function is in SSA form and virtual registers - // have a single def. - // NoPHIs: The machine function does not contain any PHI instruction. - // TracksLiveness: True when tracking register liveness accurately. - // While this property is set, register liveness information in basic block - // live-in lists and machine instruction operands (e.g. implicit defs) is - // accurate, kill flags are conservatively accurate (kill flag correctly - // indicates the last use of a register, an operand without kill flag may or - // may not be the last use of a register). This means it can be used to - // change the code in ways that affect the values in registers, for example - // by the register scavenger. - // When this property is cleared at a very late time, liveness is no longer - // reliable. - // NoVRegs: The machine function does not use any virtual registers. - // Legalized: In GlobalISel: the MachineLegalizer ran and all pre-isel generic - // instructions have been legalized; i.e., all instructions are now one of: - // - generic and always legal (e.g., COPY) - // - target-specific - // - legal pre-isel generic instructions. - // RegBankSelected: In GlobalISel: the RegBankSelect pass ran and all generic - // virtual registers have been assigned to a register bank. - // Selected: In GlobalISel: the InstructionSelect pass ran and all pre-isel - // generic instructions have been eliminated; i.e., all instructions are now - // target-specific or non-pre-isel generic instructions (e.g., COPY). - // Since only pre-isel generic instructions can have generic virtual register - // operands, this also means that all generic virtual registers have been - // constrained to virtual registers (assigned to register classes) and that - // all sizes attached to them have been eliminated. - // TiedOpsRewritten: The twoaddressinstruction pass will set this flag, it - // means that tied-def have been rewritten to meet the RegConstraint. - // FailsVerification: Means that the function is not expected to pass machine - // verification. This can be set by passes that introduce known problems that - // have not been fixed yet. - // TracksDebugUserValues: Without this property enabled, debug instructions - // such as DBG_VALUE are allowed to reference virtual registers even if those - // registers do not have a definition. With the property enabled virtual - // registers must only be used if they have a definition. This property - // allows earlier passes in the pipeline to skip updates of `DBG_VALUE` - // instructions to save compile time. - enum class Property : unsigned { - IsSSA, - NoPHIs, - TracksLiveness, - NoVRegs, - FailedISel, - Legalized, - RegBankSelected, - Selected, - TiedOpsRewritten, - FailsVerification, - TracksDebugUserValues, - LastProperty = TracksDebugUserValues, - }; - - bool hasProperty(Property P) const { - return Properties[static_cast(P)]; - } - - MachineFunctionProperties &set(Property P) { - Properties.set(static_cast(P)); - return *this; - } - - MachineFunctionProperties &reset(Property P) { - Properties.reset(static_cast(P)); - return *this; - } - - /// Reset all the properties. - MachineFunctionProperties &reset() { - Properties.reset(); - return *this; - } - - MachineFunctionProperties &set(const MachineFunctionProperties &MFP) { - Properties |= MFP.Properties; - return *this; - } - - MachineFunctionProperties &reset(const MachineFunctionProperties &MFP) { - Properties.reset(MFP.Properties); - return *this; - } - - // Returns true if all properties set in V (i.e. required by a pass) are set - // in this. - bool verifyRequiredProperties(const MachineFunctionProperties &V) const { - return !V.Properties.test(Properties); - } - - /// Print the MachineFunctionProperties in human-readable form. - void print(raw_ostream &OS) const; - -private: - BitVector Properties = - BitVector(static_cast(Property::LastProperty)+1); -}; - -struct SEHHandler { - /// Filter or finally function. Null indicates a catch-all. - const Function *FilterOrFinally; - - /// Address of block to recover at. Null for a finally handler. - const BlockAddress *RecoverBA; -}; - -/// This structure is used to retain landing pad info for the current function. -struct LandingPadInfo { - MachineBasicBlock *LandingPadBlock; // Landing pad block. - SmallVector BeginLabels; // Labels prior to invoke. - SmallVector EndLabels; // Labels after invoke. - SmallVector SEHHandlers; // SEH handlers active at this lpad. - MCSymbol *LandingPadLabel = nullptr; // Label at beginning of landing pad. - std::vector TypeIds; // List of type ids (filters negative). - - explicit LandingPadInfo(MachineBasicBlock *MBB) - : LandingPadBlock(MBB) {} -}; - -class LLVM_EXTERNAL_VISIBILITY MachineFunction { - Function &F; - const LLVMTargetMachine &Target; - const TargetSubtargetInfo *STI; - MCContext &Ctx; - MachineModuleInfo &MMI; - - // RegInfo - Information about each register in use in the function. - MachineRegisterInfo *RegInfo; - - // Used to keep track of target-specific per-machine function information for - // the target implementation. - MachineFunctionInfo *MFInfo; - - // Keep track of objects allocated on the stack. - MachineFrameInfo *FrameInfo; - - // Keep track of constants which are spilled to memory - MachineConstantPool *ConstantPool; - - // Keep track of jump tables for switch instructions - MachineJumpTableInfo *JumpTableInfo; - - // Keep track of the function section. - MCSection *Section = nullptr; - - // Keeps track of Wasm exception handling related data. This will be null for - // functions that aren't using a wasm EH personality. - WasmEHFuncInfo *WasmEHInfo = nullptr; - - // Keeps track of Windows exception handling related data. This will be null - // for functions that aren't using a funclet-based EH personality. - WinEHFuncInfo *WinEHInfo = nullptr; - - // Function-level unique numbering for MachineBasicBlocks. When a - // MachineBasicBlock is inserted into a MachineFunction is it automatically - // numbered and this vector keeps track of the mapping from ID's to MBB's. - std::vector MBBNumbering; - - // Unary encoding of basic block symbols is used to reduce size of ".strtab". - // Basic block number 'i' gets a prefix of length 'i'. The ith character also - // denotes the type of basic block number 'i'. Return blocks are marked with - // 'r', landing pads with 'l' and regular blocks with 'a'. - std::vector BBSectionsSymbolPrefix; - - // Pool-allocate MachineFunction-lifetime and IR objects. - BumpPtrAllocator Allocator; - - // Allocation management for instructions in function. - Recycler InstructionRecycler; - - // Allocation management for operand arrays on instructions. - ArrayRecycler OperandRecycler; - - // Allocation management for basic blocks in function. - Recycler BasicBlockRecycler; - - // List of machine basic blocks in function - using BasicBlockListType = ilist; - BasicBlockListType BasicBlocks; - - /// FunctionNumber - This provides a unique ID for each function emitted in - /// this translation unit. - /// - unsigned FunctionNumber; - - /// Alignment - The alignment of the function. - Align Alignment; - - /// ExposesReturnsTwice - True if the function calls setjmp or related - /// functions with attribute "returns twice", but doesn't have - /// the attribute itself. - /// This is used to limit optimizations which cannot reason - /// about the control flow of such functions. - bool ExposesReturnsTwice = false; - - /// True if the function includes any inline assembly. - bool HasInlineAsm = false; - - /// True if any WinCFI instruction have been emitted in this function. - bool HasWinCFI = false; - - /// Current high-level properties of the IR of the function (e.g. is in SSA - /// form or whether registers have been allocated) - MachineFunctionProperties Properties; - - // Allocation management for pseudo source values. - std::unique_ptr PSVManager; - - /// List of moves done by a function's prolog. Used to construct frame maps - /// by debug and exception handling consumers. - std::vector FrameInstructions; - - /// List of basic blocks immediately following calls to _setjmp. Used to - /// construct a table of valid longjmp targets for Windows Control Flow Guard. - std::vector LongjmpTargets; - - /// List of basic blocks that are the target of catchrets. Used to construct - /// a table of valid targets for Windows EHCont Guard. - std::vector CatchretTargets; - - /// \name Exception Handling - /// \{ - - /// List of LandingPadInfo describing the landing pad information. - std::vector LandingPads; - - /// Map a landing pad's EH symbol to the call site indexes. - DenseMap> LPadToCallSiteMap; - - /// Map a landing pad to its index. - DenseMap WasmLPadToIndexMap; - - /// Map of invoke call site index values to associated begin EH_LABEL. - DenseMap CallSiteMap; - - /// CodeView label annotations. - std::vector> CodeViewAnnotations; - - bool CallsEHReturn = false; - bool CallsUnwindInit = false; - bool HasEHCatchret = false; - bool HasEHScopes = false; - bool HasEHFunclets = false; - - /// Section Type for basic blocks, only relevant with basic block sections. - BasicBlockSection BBSectionsType = BasicBlockSection::None; - - /// List of C++ TypeInfo used. - std::vector TypeInfos; - - /// List of typeids encoding filters used. - std::vector FilterIds; - - /// List of the indices in FilterIds corresponding to filter terminators. - std::vector FilterEnds; - - EHPersonality PersonalityTypeCache = EHPersonality::Unknown; - - /// \} - - /// Clear all the members of this MachineFunction, but the ones used - /// to initialize again the MachineFunction. - /// More specifically, this deallocates all the dynamically allocated - /// objects and get rid of all the XXXInfo data structure, but keep - /// unchanged the references to Fn, Target, MMI, and FunctionNumber. - void clear(); - /// Allocate and initialize the different members. - /// In particular, the XXXInfo data structure. - /// \pre Fn, Target, MMI, and FunctionNumber are properly set. - void init(); - -public: - struct VariableDbgInfo { - const DILocalVariable *Var; - const DIExpression *Expr; - // The Slot can be negative for fixed stack objects. - int Slot; - const DILocation *Loc; - - VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, - int Slot, const DILocation *Loc) - : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} - }; - - class Delegate { - virtual void anchor(); - - public: - virtual ~Delegate() = default; - /// Callback after an insertion. This should not modify the MI directly. - virtual void MF_HandleInsertion(MachineInstr &MI) = 0; - /// Callback before a removal. This should not modify the MI directly. - virtual void MF_HandleRemoval(MachineInstr &MI) = 0; - }; - - /// Structure used to represent pair of argument number after call lowering - /// and register used to transfer that argument. - /// For now we support only cases when argument is transferred through one - /// register. - struct ArgRegPair { - Register Reg; - uint16_t ArgNo; - ArgRegPair(Register R, unsigned Arg) : Reg(R), ArgNo(Arg) { - assert(Arg < (1 << 16) && "Arg out of range"); - } - }; - /// Vector of call argument and its forwarding register. - using CallSiteInfo = SmallVector; - using CallSiteInfoImpl = SmallVectorImpl; - -private: - Delegate *TheDelegate = nullptr; - GISelChangeObserver *Observer = nullptr; - - using CallSiteInfoMap = DenseMap; - /// Map a call instruction to call site arguments forwarding info. - CallSiteInfoMap CallSitesInfo; - - /// A helper function that returns call site info for a give call - /// instruction if debug entry value support is enabled. - CallSiteInfoMap::iterator getCallSiteInfo(const MachineInstr *MI); - - // Callbacks for insertion and removal. - void handleInsertion(MachineInstr &MI); - void handleRemoval(MachineInstr &MI); - friend struct ilist_traits; - -public: - using VariableDbgInfoMapTy = SmallVector; - VariableDbgInfoMapTy VariableDbgInfos; - - /// A count of how many instructions in the function have had numbers - /// assigned to them. Used for debug value tracking, to determine the - /// next instruction number. - unsigned DebugInstrNumberingCount = 0; - - /// Set value of DebugInstrNumberingCount field. Avoid using this unless - /// you're deserializing this data. - void setDebugInstrNumberingCount(unsigned Num); - - /// Pair of instruction number and operand number. - using DebugInstrOperandPair = std::pair; - - /// Replacement definition for a debug instruction reference. Made up of a - /// source instruction / operand pair, destination pair, and a qualifying - /// subregister indicating what bits in the operand make up the substitution. - // For example, a debug user - /// of %1: - /// %0:gr32 = someinst, debug-instr-number 1 - /// %1:gr16 = %0.some_16_bit_subreg, debug-instr-number 2 - /// Would receive the substitution {{2, 0}, {1, 0}, $subreg}, where $subreg is - /// the subregister number for some_16_bit_subreg. - class DebugSubstitution { - public: - DebugInstrOperandPair Src; ///< Source instruction / operand pair. - DebugInstrOperandPair Dest; ///< Replacement instruction / operand pair. - unsigned Subreg; ///< Qualifier for which part of Dest is read. - - DebugSubstitution(const DebugInstrOperandPair &Src, - const DebugInstrOperandPair &Dest, unsigned Subreg) - : Src(Src), Dest(Dest), Subreg(Subreg) {} - - /// Order only by source instruction / operand pair: there should never - /// be duplicate entries for the same source in any collection. - bool operator<(const DebugSubstitution &Other) const { - return Src < Other.Src; - } - }; - - /// Debug value substitutions: a collection of DebugSubstitution objects, - /// recording changes in where a value is defined. For example, when one - /// instruction is substituted for another. Keeping a record allows recovery - /// of variable locations after compilation finishes. - SmallVector DebugValueSubstitutions; - - /// Location of a PHI instruction that is also a debug-info variable value, - /// for the duration of register allocation. Loaded by the PHI-elimination - /// pass, and emitted as DBG_PHI instructions during VirtRegRewriter, with - /// maintenance applied by intermediate passes that edit registers (such as - /// coalescing and the allocator passes). - class DebugPHIRegallocPos { - public: - MachineBasicBlock *MBB; ///< Block where this PHI was originally located. - Register Reg; ///< VReg where the control-flow-merge happens. - unsigned SubReg; ///< Optional subreg qualifier within Reg. - DebugPHIRegallocPos(MachineBasicBlock *MBB, Register Reg, unsigned SubReg) - : MBB(MBB), Reg(Reg), SubReg(SubReg) {} - }; - - /// Map of debug instruction numbers to the position of their PHI instructions - /// during register allocation. See DebugPHIRegallocPos. - DenseMap DebugPHIPositions; - - /// Create a substitution between one value to a different, - /// new value. - void makeDebugValueSubstitution(DebugInstrOperandPair, DebugInstrOperandPair, - unsigned SubReg = 0); - - /// Create substitutions for any tracked values in \p Old, to point at - /// \p New. Needed when we re-create an instruction during optimization, - /// which has the same signature (i.e., def operands in the same place) but - /// a modified instruction type, flags, or otherwise. An example: X86 moves - /// are sometimes transformed into equivalent LEAs. - /// If the two instructions are not the same opcode, limit which operands to - /// examine for substitutions to the first N operands by setting - /// \p MaxOperand. - void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, - unsigned MaxOperand = UINT_MAX); - - /// Find the underlying defining instruction / operand for a COPY instruction - /// while in SSA form. Copies do not actually define values -- they move them - /// between registers. Labelling a COPY-like instruction with an instruction - /// number is to be avoided as it makes value numbers non-unique later in - /// compilation. This method follows the definition chain for any sequence of - /// COPY-like instructions to find whatever non-COPY-like instruction defines - /// the copied value; or for parameters, creates a DBG_PHI on entry. - /// May insert instructions into the entry block! - /// \p MI The copy-like instruction to salvage. - /// \returns An instruction/operand pair identifying the defining value. - DebugInstrOperandPair salvageCopySSA(MachineInstr &MI); - - /// Finalise any partially emitted debug instructions. These are DBG_INSTR_REF - /// instructions where we only knew the vreg of the value they use, not the - /// instruction that defines that vreg. Once isel finishes, we should have - /// enough information for every DBG_INSTR_REF to point at an instruction - /// (or DBG_PHI). - void finalizeDebugInstrRefs(); - - /// Returns true if the function's variable locations should be tracked with - /// instruction referencing. - bool useDebugInstrRef() const; - - /// A reserved operand number representing the instructions memory operand, - /// for instructions that have a stack spill fused into them. - const static unsigned int DebugOperandMemNumber; - - MachineFunction(Function &F, const LLVMTargetMachine &Target, - const TargetSubtargetInfo &STI, unsigned FunctionNum, - MachineModuleInfo &MMI); - MachineFunction(const MachineFunction &) = delete; - MachineFunction &operator=(const MachineFunction &) = delete; - ~MachineFunction(); - - /// Reset the instance as if it was just created. - void reset() { - clear(); - init(); - } - - /// Reset the currently registered delegate - otherwise assert. - void resetDelegate(Delegate *delegate) { - assert(TheDelegate == delegate && - "Only the current delegate can perform reset!"); - TheDelegate = nullptr; - } - - /// Set the delegate. resetDelegate must be called before attempting - /// to set. - void setDelegate(Delegate *delegate) { - assert(delegate && !TheDelegate && - "Attempted to set delegate to null, or to change it without " - "first resetting it!"); - - TheDelegate = delegate; - } - - void setObserver(GISelChangeObserver *O) { Observer = O; } - - GISelChangeObserver *getObserver() const { return Observer; } - - MachineModuleInfo &getMMI() const { return MMI; } - MCContext &getContext() const { return Ctx; } - - /// Returns the Section this function belongs to. - MCSection *getSection() const { return Section; } - - /// Indicates the Section this function belongs to. - void setSection(MCSection *S) { Section = S; } - - PseudoSourceValueManager &getPSVManager() const { return *PSVManager; } - - /// Return the DataLayout attached to the Module associated to this MF. - const DataLayout &getDataLayout() const; - - /// Return the LLVM function that this machine code represents - Function &getFunction() { return F; } - - /// Return the LLVM function that this machine code represents - const Function &getFunction() const { return F; } - - /// getName - Return the name of the corresponding LLVM function. - StringRef getName() const; - - /// getFunctionNumber - Return a unique ID for the current function. - unsigned getFunctionNumber() const { return FunctionNumber; } - - /// Returns true if this function has basic block sections enabled. - bool hasBBSections() const { - return (BBSectionsType == BasicBlockSection::All || - BBSectionsType == BasicBlockSection::List || - BBSectionsType == BasicBlockSection::Preset); - } - - /// Returns true if basic block labels are to be generated for this function. - bool hasBBLabels() const { - return BBSectionsType == BasicBlockSection::Labels; - } - - void setBBSectionsType(BasicBlockSection V) { BBSectionsType = V; } - - /// Assign IsBeginSection IsEndSection fields for basic blocks in this - /// function. - void assignBeginEndSections(); - - /// getTarget - Return the target machine this machine code is compiled with - const LLVMTargetMachine &getTarget() const { return Target; } - - /// getSubtarget - Return the subtarget for which this machine code is being - /// compiled. - const TargetSubtargetInfo &getSubtarget() const { return *STI; } - - /// getSubtarget - This method returns a pointer to the specified type of - /// TargetSubtargetInfo. In debug builds, it verifies that the object being - /// returned is of the correct type. - template const STC &getSubtarget() const { - return *static_cast(STI); - } - - /// getRegInfo - Return information about the registers currently in use. - MachineRegisterInfo &getRegInfo() { return *RegInfo; } - const MachineRegisterInfo &getRegInfo() const { return *RegInfo; } - - /// getFrameInfo - Return the frame info object for the current function. - /// This object contains information about objects allocated on the stack - /// frame of the current function in an abstract way. - MachineFrameInfo &getFrameInfo() { return *FrameInfo; } - const MachineFrameInfo &getFrameInfo() const { return *FrameInfo; } - - /// getJumpTableInfo - Return the jump table info object for the current - /// function. This object contains information about jump tables in the - /// current function. If the current function has no jump tables, this will - /// return null. - const MachineJumpTableInfo *getJumpTableInfo() const { return JumpTableInfo; } - MachineJumpTableInfo *getJumpTableInfo() { return JumpTableInfo; } - - /// getOrCreateJumpTableInfo - Get the JumpTableInfo for this function, if it - /// does already exist, allocate one. - MachineJumpTableInfo *getOrCreateJumpTableInfo(unsigned JTEntryKind); - - /// getConstantPool - Return the constant pool object for the current - /// function. - MachineConstantPool *getConstantPool() { return ConstantPool; } - const MachineConstantPool *getConstantPool() const { return ConstantPool; } - - /// getWasmEHFuncInfo - Return information about how the current function uses - /// Wasm exception handling. Returns null for functions that don't use wasm - /// exception handling. - const WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; } - WasmEHFuncInfo *getWasmEHFuncInfo() { return WasmEHInfo; } - - /// getWinEHFuncInfo - Return information about how the current function uses - /// Windows exception handling. Returns null for functions that don't use - /// funclets for exception handling. - const WinEHFuncInfo *getWinEHFuncInfo() const { return WinEHInfo; } - WinEHFuncInfo *getWinEHFuncInfo() { return WinEHInfo; } - - /// getAlignment - Return the alignment of the function. - Align getAlignment() const { return Alignment; } - - /// setAlignment - Set the alignment of the function. - void setAlignment(Align A) { Alignment = A; } - - /// ensureAlignment - Make sure the function is at least A bytes aligned. - void ensureAlignment(Align A) { - if (Alignment < A) - Alignment = A; - } - - /// exposesReturnsTwice - Returns true if the function calls setjmp or - /// any other similar functions with attribute "returns twice" without - /// having the attribute itself. - bool exposesReturnsTwice() const { - return ExposesReturnsTwice; - } - - /// setCallsSetJmp - Set a flag that indicates if there's a call to - /// a "returns twice" function. - void setExposesReturnsTwice(bool B) { - ExposesReturnsTwice = B; - } - - /// Returns true if the function contains any inline assembly. - bool hasInlineAsm() const { - return HasInlineAsm; - } - - /// Set a flag that indicates that the function contains inline assembly. - void setHasInlineAsm(bool B) { - HasInlineAsm = B; - } - - bool hasWinCFI() const { - return HasWinCFI; - } - void setHasWinCFI(bool v) { HasWinCFI = v; } - - /// True if this function needs frame moves for debug or exceptions. - bool needsFrameMoves() const; - - /// Get the function properties - const MachineFunctionProperties &getProperties() const { return Properties; } - MachineFunctionProperties &getProperties() { return Properties; } - - /// getInfo - Keep track of various per-function pieces of information for - /// backends that would like to do so. - /// - template - Ty *getInfo() { - if (!MFInfo) - MFInfo = Ty::template create(Allocator, *this); - return static_cast(MFInfo); - } - - template - const Ty *getInfo() const { - return const_cast(this)->getInfo(); - } - - /// Returns the denormal handling type for the default rounding mode of the - /// function. - DenormalMode getDenormalMode(const fltSemantics &FPType) const; - - /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they - /// are inserted into the machine function. The block number for a machine - /// basic block can be found by using the MBB::getNumber method, this method - /// provides the inverse mapping. - MachineBasicBlock *getBlockNumbered(unsigned N) const { - assert(N < MBBNumbering.size() && "Illegal block number"); - assert(MBBNumbering[N] && "Block was removed from the machine function!"); - return MBBNumbering[N]; - } - - /// Should we be emitting segmented stack stuff for the function - bool shouldSplitStack() const; - - /// getNumBlockIDs - Return the number of MBB ID's allocated. - unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); } - - /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and - /// recomputes them. This guarantees that the MBB numbers are sequential, - /// dense, and match the ordering of the blocks within the function. If a - /// specific MachineBasicBlock is specified, only that block and those after - /// it are renumbered. - void RenumberBlocks(MachineBasicBlock *MBBFrom = nullptr); - - /// print - Print out the MachineFunction in a format suitable for debugging - /// to the specified stream. - void print(raw_ostream &OS, const SlotIndexes* = nullptr) const; - - /// viewCFG - This function is meant for use from the debugger. You can just - /// say 'call F->viewCFG()' and a ghostview window should pop up from the - /// program, displaying the CFG of the current function with the code for each - /// basic block inside. This depends on there being a 'dot' and 'gv' program - /// in your path. - void viewCFG() const; - - /// viewCFGOnly - This function is meant for use from the debugger. It works - /// just like viewCFG, but it does not include the contents of basic blocks - /// into the nodes, just the label. If you are only interested in the CFG - /// this can make the graph smaller. - /// - void viewCFGOnly() const; - - /// dump - Print the current MachineFunction to cerr, useful for debugger use. - void dump() const; - - /// Run the current MachineFunction through the machine code verifier, useful - /// for debugger use. - /// \returns true if no problems were found. - bool verify(Pass *p = nullptr, const char *Banner = nullptr, - bool AbortOnError = true) const; - - // Provide accessors for the MachineBasicBlock list... - using iterator = BasicBlockListType::iterator; - using const_iterator = BasicBlockListType::const_iterator; - using const_reverse_iterator = BasicBlockListType::const_reverse_iterator; - using reverse_iterator = BasicBlockListType::reverse_iterator; - - /// Support for MachineBasicBlock::getNextNode(). - static BasicBlockListType MachineFunction::* - getSublistAccess(MachineBasicBlock *) { - return &MachineFunction::BasicBlocks; - } - - /// addLiveIn - Add the specified physical register as a live-in value and - /// create a corresponding virtual register for it. - Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC); - - //===--------------------------------------------------------------------===// - // BasicBlock accessor functions. - // - iterator begin() { return BasicBlocks.begin(); } - const_iterator begin() const { return BasicBlocks.begin(); } - iterator end () { return BasicBlocks.end(); } - const_iterator end () const { return BasicBlocks.end(); } - - reverse_iterator rbegin() { return BasicBlocks.rbegin(); } - const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } - reverse_iterator rend () { return BasicBlocks.rend(); } - const_reverse_iterator rend () const { return BasicBlocks.rend(); } - - unsigned size() const { return (unsigned)BasicBlocks.size();} - bool empty() const { return BasicBlocks.empty(); } - const MachineBasicBlock &front() const { return BasicBlocks.front(); } - MachineBasicBlock &front() { return BasicBlocks.front(); } - const MachineBasicBlock & back() const { return BasicBlocks.back(); } - MachineBasicBlock & back() { return BasicBlocks.back(); } - - void push_back (MachineBasicBlock *MBB) { BasicBlocks.push_back (MBB); } - void push_front(MachineBasicBlock *MBB) { BasicBlocks.push_front(MBB); } - void insert(iterator MBBI, MachineBasicBlock *MBB) { - BasicBlocks.insert(MBBI, MBB); - } - void splice(iterator InsertPt, iterator MBBI) { - BasicBlocks.splice(InsertPt, BasicBlocks, MBBI); - } - void splice(iterator InsertPt, MachineBasicBlock *MBB) { - BasicBlocks.splice(InsertPt, BasicBlocks, MBB); - } - void splice(iterator InsertPt, iterator MBBI, iterator MBBE) { - BasicBlocks.splice(InsertPt, BasicBlocks, MBBI, MBBE); - } - - void remove(iterator MBBI) { BasicBlocks.remove(MBBI); } - void remove(MachineBasicBlock *MBBI) { BasicBlocks.remove(MBBI); } - void erase(iterator MBBI) { BasicBlocks.erase(MBBI); } - void erase(MachineBasicBlock *MBBI) { BasicBlocks.erase(MBBI); } - - template - void sort(Comp comp) { - BasicBlocks.sort(comp); - } - - /// Return the number of \p MachineInstrs in this \p MachineFunction. - unsigned getInstructionCount() const { - unsigned InstrCount = 0; - for (const MachineBasicBlock &MBB : BasicBlocks) - InstrCount += MBB.size(); - return InstrCount; - } - - //===--------------------------------------------------------------------===// - // Internal functions used to automatically number MachineBasicBlocks - - /// Adds the MBB to the internal numbering. Returns the unique number - /// assigned to the MBB. - unsigned addToMBBNumbering(MachineBasicBlock *MBB) { - MBBNumbering.push_back(MBB); - return (unsigned)MBBNumbering.size()-1; - } - - /// removeFromMBBNumbering - Remove the specific machine basic block from our - /// tracker, this is only really to be used by the MachineBasicBlock - /// implementation. - void removeFromMBBNumbering(unsigned N) { - assert(N < MBBNumbering.size() && "Illegal basic block #"); - MBBNumbering[N] = nullptr; - } - - /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead - /// of `new MachineInstr'. - MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, - bool NoImplicit = false); - - /// Create a new MachineInstr which is a copy of \p Orig, identical in all - /// ways except the instruction has no parent, prev, or next. Bundling flags - /// are reset. - /// - /// Note: Clones a single instruction, not whole instruction bundles. - /// Does not perform target specific adjustments; consider using - /// TargetInstrInfo::duplicate() instead. - MachineInstr *CloneMachineInstr(const MachineInstr *Orig); - - /// Clones instruction or the whole instruction bundle \p Orig and insert - /// into \p MBB before \p InsertBefore. - /// - /// Note: Does not perform target specific adjustments; consider using - /// TargetInstrInfo::duplicate() instead. - MachineInstr & - cloneMachineInstrBundle(MachineBasicBlock &MBB, - MachineBasicBlock::iterator InsertBefore, - const MachineInstr &Orig); - - /// DeleteMachineInstr - Delete the given MachineInstr. - void deleteMachineInstr(MachineInstr *MI); - - /// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this - /// instead of `new MachineBasicBlock'. - MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = nullptr); - - /// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. - void deleteMachineBasicBlock(MachineBasicBlock *MBB); - - /// getMachineMemOperand - Allocate a new MachineMemOperand. - /// MachineMemOperands are owned by the MachineFunction and need not be - /// explicitly deallocated. - MachineMemOperand *getMachineMemOperand( - MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, - Align base_alignment, const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, - AtomicOrdering Ordering = AtomicOrdering::NotAtomic, - AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); - - MachineMemOperand *getMachineMemOperand( - MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, - Align base_alignment, const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, - AtomicOrdering Ordering = AtomicOrdering::NotAtomic, - AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); - - /// getMachineMemOperand - Allocate a new MachineMemOperand by copying - /// an existing one, adjusting by an offset and using the given size. - /// MachineMemOperands are owned by the MachineFunction and need not be - /// explicitly deallocated. - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - int64_t Offset, LLT Ty); - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - int64_t Offset, uint64_t Size) { - return getMachineMemOperand( - MMO, Offset, Size == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * Size)); - } - - /// getMachineMemOperand - Allocate a new MachineMemOperand by copying - /// an existing one, replacing only the MachinePointerInfo and size. - /// MachineMemOperands are owned by the MachineFunction and need not be - /// explicitly deallocated. - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - const MachinePointerInfo &PtrInfo, - uint64_t Size); - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - const MachinePointerInfo &PtrInfo, - LLT Ty); - - /// Allocate a new MachineMemOperand by copying an existing one, - /// replacing only AliasAnalysis information. MachineMemOperands are owned - /// by the MachineFunction and need not be explicitly deallocated. - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - const AAMDNodes &AAInfo); - - /// Allocate a new MachineMemOperand by copying an existing one, - /// replacing the flags. MachineMemOperands are owned - /// by the MachineFunction and need not be explicitly deallocated. - MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - MachineMemOperand::Flags Flags); - - using OperandCapacity = ArrayRecycler::Capacity; - - /// Allocate an array of MachineOperands. This is only intended for use by - /// internal MachineInstr functions. - MachineOperand *allocateOperandArray(OperandCapacity Cap) { - return OperandRecycler.allocate(Cap, Allocator); - } - - /// Dellocate an array of MachineOperands and recycle the memory. This is - /// only intended for use by internal MachineInstr functions. - /// Cap must be the same capacity that was used to allocate the array. - void deallocateOperandArray(OperandCapacity Cap, MachineOperand *Array) { - OperandRecycler.deallocate(Cap, Array); - } - - /// Allocate and initialize a register mask with @p NumRegister bits. - uint32_t *allocateRegMask(); - - ArrayRef allocateShuffleMask(ArrayRef Mask); - - /// Allocate and construct an extra info structure for a `MachineInstr`. - /// - /// This is allocated on the function's allocator and so lives the life of - /// the function. - MachineInstr::ExtraInfo *createMIExtraInfo( - ArrayRef MMOs, MCSymbol *PreInstrSymbol = nullptr, - MCSymbol *PostInstrSymbol = nullptr, MDNode *HeapAllocMarker = nullptr); - - /// Allocate a string and populate it with the given external symbol name. - const char *createExternalSymbolName(StringRef Name); - - //===--------------------------------------------------------------------===// - // Label Manipulation. - - /// getJTISymbol - Return the MCSymbol for the specified non-empty jump table. - /// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a - /// normal 'L' label is returned. - MCSymbol *getJTISymbol(unsigned JTI, MCContext &Ctx, - bool isLinkerPrivate = false) const; - - /// getPICBaseSymbol - Return a function-local symbol to represent the PIC - /// base. - MCSymbol *getPICBaseSymbol() const; - - /// Returns a reference to a list of cfi instructions in the function's - /// prologue. Used to construct frame maps for debug and exception handling - /// consumers. - const std::vector &getFrameInstructions() const { - return FrameInstructions; - } - - LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst); - - /// Returns a reference to a list of symbols immediately following calls to - /// _setjmp in the function. Used to construct the longjmp target table used - /// by Windows Control Flow Guard. - const std::vector &getLongjmpTargets() const { - return LongjmpTargets; - } - - /// Add the specified symbol to the list of valid longjmp targets for Windows - /// Control Flow Guard. - void addLongjmpTarget(MCSymbol *Target) { LongjmpTargets.push_back(Target); } - - /// Returns a reference to a list of symbols that we have catchrets. - /// Used to construct the catchret target table used by Windows EHCont Guard. - const std::vector &getCatchretTargets() const { - return CatchretTargets; - } - - /// Add the specified symbol to the list of valid catchret targets for Windows - /// EHCont Guard. - void addCatchretTarget(MCSymbol *Target) { - CatchretTargets.push_back(Target); - } - - /// \name Exception Handling - /// \{ - - bool callsEHReturn() const { return CallsEHReturn; } - void setCallsEHReturn(bool b) { CallsEHReturn = b; } - - bool callsUnwindInit() const { return CallsUnwindInit; } - void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } - - bool hasEHCatchret() const { return HasEHCatchret; } - void setHasEHCatchret(bool V) { HasEHCatchret = V; } - - bool hasEHScopes() const { return HasEHScopes; } - void setHasEHScopes(bool V) { HasEHScopes = V; } - - bool hasEHFunclets() const { return HasEHFunclets; } - void setHasEHFunclets(bool V) { HasEHFunclets = V; } - - /// Find or create an LandingPadInfo for the specified MachineBasicBlock. - LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); - - /// Remap landing pad labels and remove any deleted landing pads. - void tidyLandingPads(DenseMap *LPMap = nullptr, - bool TidyIfNoBeginLabels = true); - - /// Return a reference to the landing pad info for the current function. - const std::vector &getLandingPads() const { - return LandingPads; - } - - /// Provide the begin and end labels of an invoke style call and associate it - /// with a try landing pad block. - void addInvoke(MachineBasicBlock *LandingPad, - MCSymbol *BeginLabel, MCSymbol *EndLabel); - - /// Add a new panding pad, and extract the exception handling information from - /// the landingpad instruction. Returns the label ID for the landing pad - /// entry. - MCSymbol *addLandingPad(MachineBasicBlock *LandingPad); - - /// Provide the catch typeinfo for a landing pad. - void addCatchTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef TyInfo); - - /// Provide the filter typeinfo for a landing pad. - void addFilterTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef TyInfo); - - /// Add a cleanup action for a landing pad. - void addCleanup(MachineBasicBlock *LandingPad); - - void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter, - const BlockAddress *RecoverBA); - - void addSEHCleanupHandler(MachineBasicBlock *LandingPad, - const Function *Cleanup); - - /// Return the type id for the specified typeinfo. This is function wide. - unsigned getTypeIDFor(const GlobalValue *TI); - - /// Return the id of the filter encoded by TyIds. This is function wide. - int getFilterIDFor(std::vector &TyIds); - - /// Map the landing pad's EH symbol to the call site indexes. - void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef Sites); - - /// Map the landing pad to its index. Used for Wasm exception handling. - void setWasmLandingPadIndex(const MachineBasicBlock *LPad, unsigned Index) { - WasmLPadToIndexMap[LPad] = Index; - } - - /// Returns true if the landing pad has an associate index in wasm EH. - bool hasWasmLandingPadIndex(const MachineBasicBlock *LPad) const { - return WasmLPadToIndexMap.count(LPad); - } - - /// Get the index in wasm EH for a given landing pad. - unsigned getWasmLandingPadIndex(const MachineBasicBlock *LPad) const { - assert(hasWasmLandingPadIndex(LPad)); - return WasmLPadToIndexMap.lookup(LPad); - } - - /// Get the call site indexes for a landing pad EH symbol. - SmallVectorImpl &getCallSiteLandingPad(MCSymbol *Sym) { - assert(hasCallSiteLandingPad(Sym) && - "missing call site number for landing pad!"); - return LPadToCallSiteMap[Sym]; - } - - /// Return true if the landing pad Eh symbol has an associated call site. - bool hasCallSiteLandingPad(MCSymbol *Sym) { - return !LPadToCallSiteMap[Sym].empty(); - } - - /// Map the begin label for a call site. - void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) { - CallSiteMap[BeginLabel] = Site; - } - - /// Get the call site number for a begin label. - unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) const { - assert(hasCallSiteBeginLabel(BeginLabel) && - "Missing call site number for EH_LABEL!"); - return CallSiteMap.lookup(BeginLabel); - } - - /// Return true if the begin label has a call site number associated with it. - bool hasCallSiteBeginLabel(MCSymbol *BeginLabel) const { - return CallSiteMap.count(BeginLabel); - } - - /// Record annotations associated with a particular label. - void addCodeViewAnnotation(MCSymbol *Label, MDNode *MD) { - CodeViewAnnotations.push_back({Label, MD}); - } - - ArrayRef> getCodeViewAnnotations() const { - return CodeViewAnnotations; - } - - /// Return a reference to the C++ typeinfo for the current function. - const std::vector &getTypeInfos() const { - return TypeInfos; - } - - /// Return a reference to the typeids encoding filters used in the current - /// function. - const std::vector &getFilterIds() const { - return FilterIds; - } - - /// \} - - /// Collect information used to emit debugging information of a variable. - void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, - int Slot, const DILocation *Loc) { - VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); - } - - VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } - const VariableDbgInfoMapTy &getVariableDbgInfo() const { - return VariableDbgInfos; - } - - /// Start tracking the arguments passed to the call \p CallI. - void addCallArgsForwardingRegs(const MachineInstr *CallI, - CallSiteInfoImpl &&CallInfo) { - assert(CallI->isCandidateForCallSiteEntry()); - bool Inserted = - CallSitesInfo.try_emplace(CallI, std::move(CallInfo)).second; - (void)Inserted; - assert(Inserted && "Call site info not unique"); - } - - const CallSiteInfoMap &getCallSitesInfo() const { - return CallSitesInfo; - } - - /// Following functions update call site info. They should be called before - /// removing, replacing or copying call instruction. - - /// Erase the call site info for \p MI. It is used to remove a call - /// instruction from the instruction stream. - void eraseCallSiteInfo(const MachineInstr *MI); - /// Copy the call site info from \p Old to \ New. Its usage is when we are - /// making a copy of the instruction that will be inserted at different point - /// of the instruction stream. - void copyCallSiteInfo(const MachineInstr *Old, - const MachineInstr *New); - - const std::vector &getBBSectionsSymbolPrefix() const { - return BBSectionsSymbolPrefix; - } - - /// Move the call site info from \p Old to \New call site info. This function - /// is used when we are replacing one call instruction with another one to - /// the same callee. - void moveCallSiteInfo(const MachineInstr *Old, - const MachineInstr *New); - - unsigned getNewDebugInstrNum() { - return ++DebugInstrNumberingCount; - } -}; - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for function basic block graphs (CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a -// machine function as a graph of machine basic blocks... these are -// the same as the machine basic block iterators, except that the root -// node is implicitly the first node of the function. -// -template <> struct GraphTraits : - public GraphTraits { - static NodeRef getEntryNode(MachineFunction *F) { return &F->front(); } - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - using nodes_iterator = pointer_iterator; - - static nodes_iterator nodes_begin(MachineFunction *F) { - return nodes_iterator(F->begin()); - } - - static nodes_iterator nodes_end(MachineFunction *F) { - return nodes_iterator(F->end()); - } - - static unsigned size (MachineFunction *F) { return F->size(); } -}; -template <> struct GraphTraits : - public GraphTraits { - static NodeRef getEntryNode(const MachineFunction *F) { return &F->front(); } - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - using nodes_iterator = pointer_iterator; - - static nodes_iterator nodes_begin(const MachineFunction *F) { - return nodes_iterator(F->begin()); - } - - static nodes_iterator nodes_end (const MachineFunction *F) { - return nodes_iterator(F->end()); - } - - static unsigned size (const MachineFunction *F) { - return F->size(); - } -}; - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... and to walk it in inverse order. Inverse order for -// a function is considered to be when traversing the predecessor edges of a BB -// instead of the successor edges. -// -template <> struct GraphTraits> : - public GraphTraits> { - static NodeRef getEntryNode(Inverse G) { - return &G.Graph->front(); - } -}; -template <> struct GraphTraits> : - public GraphTraits> { - static NodeRef getEntryNode(Inverse G) { - return &G.Graph->front(); - } -}; - -class MachineFunctionAnalysisManager; -void verifyMachineFunction(MachineFunctionAnalysisManager *, - const std::string &Banner, - const MachineFunction &MF); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEFUNCTION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunctionPass.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunctionPass.h deleted file mode 100644 index caaf22c213..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineFunctionPass.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachineFunctionPass class. MachineFunctionPass's are -// just FunctionPass's, except they operate on machine code as part of a code -// generator. Because they operate on machine code, not the LLVM -// representation, MachineFunctionPass's are not allowed to modify the LLVM -// representation. Due to this limitation, the MachineFunctionPass class takes -// care of declaring that no LLVM passes are invalidated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEFUNCTIONPASS_H -#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H - -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/Pass.h" - -namespace llvm { - -/// MachineFunctionPass - This class adapts the FunctionPass interface to -/// allow convenient creation of passes that operate on the MachineFunction -/// representation. Instead of overriding runOnFunction, subclasses -/// override runOnMachineFunction. -class MachineFunctionPass : public FunctionPass { -public: - bool doInitialization(Module&) override { - // Cache the properties info at module-init time so we don't have to - // construct them for every function. - RequiredProperties = getRequiredProperties(); - SetProperties = getSetProperties(); - ClearedProperties = getClearedProperties(); - return false; - } -protected: - explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {} - - /// runOnMachineFunction - This method must be overloaded to perform the - /// desired machine code transformation or analysis. - /// - virtual bool runOnMachineFunction(MachineFunction &MF) = 0; - - /// getAnalysisUsage - Subclasses that override getAnalysisUsage - /// must call this. - /// - /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that - /// the pass does not modify the MachineBasicBlock CFG. - /// - void getAnalysisUsage(AnalysisUsage &AU) const override; - - virtual MachineFunctionProperties getRequiredProperties() const { - return MachineFunctionProperties(); - } - virtual MachineFunctionProperties getSetProperties() const { - return MachineFunctionProperties(); - } - virtual MachineFunctionProperties getClearedProperties() const { - return MachineFunctionProperties(); - } - -private: - MachineFunctionProperties RequiredProperties; - MachineFunctionProperties SetProperties; - MachineFunctionProperties ClearedProperties; - - /// createPrinterPass - Get a machine function printer pass. - Pass *createPrinterPass(raw_ostream &O, - const std::string &Banner) const override; - - bool runOnFunction(Function &F) override; -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstr.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstr.h deleted file mode 100644 index 357dba79f4..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstr.h +++ /dev/null @@ -1,1924 +0,0 @@ -//===- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MachineInstr class, which is the -// basic representation for all target dependent machine instructions used by -// the back end. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEINSTR_H -#define LLVM_CODEGEN_MACHINEINSTR_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/PointerSumType.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/PseudoProbe.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/ArrayRecycler.h" -#include "llvm/Support/TrailingObjects.h" -#include -#include -#include -#include - -namespace llvm { - -class AAResults; -template class ArrayRef; -class DIExpression; -class DILocalVariable; -class MachineBasicBlock; -class MachineFunction; -class MachineRegisterInfo; -class ModuleSlotTracker; -class raw_ostream; -template class SmallVectorImpl; -class SmallBitVector; -class StringRef; -class TargetInstrInfo; -class TargetRegisterClass; -class TargetRegisterInfo; - -//===----------------------------------------------------------------------===// -/// Representation of each machine instruction. -/// -/// This class isn't a POD type, but it must have a trivial destructor. When a -/// MachineFunction is deleted, all the contained MachineInstrs are deallocated -/// without having their destructor called. -/// -class MachineInstr - : public ilist_node_with_parent> { -public: - using mmo_iterator = ArrayRef::iterator; - - /// Flags to specify different kinds of comments to output in - /// assembly code. These flags carry semantic information not - /// otherwise easily derivable from the IR text. - /// - enum CommentFlag { - ReloadReuse = 0x1, // higher bits are reserved for target dep comments. - NoSchedComment = 0x2, - TAsmComments = 0x4 // Target Asm comments should start from this value. - }; - - enum MIFlag { - NoFlags = 0, - FrameSetup = 1 << 0, // Instruction is used as a part of - // function frame setup code. - FrameDestroy = 1 << 1, // Instruction is used as a part of - // function frame destruction code. - BundledPred = 1 << 2, // Instruction has bundled predecessors. - BundledSucc = 1 << 3, // Instruction has bundled successors. - FmNoNans = 1 << 4, // Instruction does not support Fast - // math nan values. - FmNoInfs = 1 << 5, // Instruction does not support Fast - // math infinity values. - FmNsz = 1 << 6, // Instruction is not required to retain - // signed zero values. - FmArcp = 1 << 7, // Instruction supports Fast math - // reciprocal approximations. - FmContract = 1 << 8, // Instruction supports Fast math - // contraction operations like fma. - FmAfn = 1 << 9, // Instruction may map to Fast math - // intrinsic approximation. - FmReassoc = 1 << 10, // Instruction supports Fast math - // reassociation of operand order. - NoUWrap = 1 << 11, // Instruction supports binary operator - // no unsigned wrap. - NoSWrap = 1 << 12, // Instruction supports binary operator - // no signed wrap. - IsExact = 1 << 13, // Instruction supports division is - // known to be exact. - NoFPExcept = 1 << 14, // Instruction does not raise - // floatint-point exceptions. - NoMerge = 1 << 15, // Passes that drop source location info - // (e.g. branch folding) should skip - // this instruction. - }; - -private: - const MCInstrDesc *MCID; // Instruction descriptor. - MachineBasicBlock *Parent = nullptr; // Pointer to the owning basic block. - - // Operands are allocated by an ArrayRecycler. - MachineOperand *Operands = nullptr; // Pointer to the first operand. - unsigned NumOperands = 0; // Number of operands on instruction. - - uint16_t Flags = 0; // Various bits of additional - // information about machine - // instruction. - - uint8_t AsmPrinterFlags = 0; // Various bits of information used by - // the AsmPrinter to emit helpful - // comments. This is *not* semantic - // information. Do not use this for - // anything other than to convey comment - // information to AsmPrinter. - - // OperandCapacity has uint8_t size, so it should be next to AsmPrinterFlags - // to properly pack. - using OperandCapacity = ArrayRecycler::Capacity; - OperandCapacity CapOperands; // Capacity of the Operands array. - - /// Internal implementation detail class that provides out-of-line storage for - /// extra info used by the machine instruction when this info cannot be stored - /// in-line within the instruction itself. - /// - /// This has to be defined eagerly due to the implementation constraints of - /// `PointerSumType` where it is used. - class ExtraInfo final - : TrailingObjects { - public: - static ExtraInfo *create(BumpPtrAllocator &Allocator, - ArrayRef MMOs, - MCSymbol *PreInstrSymbol = nullptr, - MCSymbol *PostInstrSymbol = nullptr, - MDNode *HeapAllocMarker = nullptr) { - bool HasPreInstrSymbol = PreInstrSymbol != nullptr; - bool HasPostInstrSymbol = PostInstrSymbol != nullptr; - bool HasHeapAllocMarker = HeapAllocMarker != nullptr; - auto *Result = new (Allocator.Allocate( - totalSizeToAlloc( - MMOs.size(), HasPreInstrSymbol + HasPostInstrSymbol, - HasHeapAllocMarker), - alignof(ExtraInfo))) - ExtraInfo(MMOs.size(), HasPreInstrSymbol, HasPostInstrSymbol, - HasHeapAllocMarker); - - // Copy the actual data into the trailing objects. - std::copy(MMOs.begin(), MMOs.end(), - Result->getTrailingObjects()); - - if (HasPreInstrSymbol) - Result->getTrailingObjects()[0] = PreInstrSymbol; - if (HasPostInstrSymbol) - Result->getTrailingObjects()[HasPreInstrSymbol] = - PostInstrSymbol; - if (HasHeapAllocMarker) - Result->getTrailingObjects()[0] = HeapAllocMarker; - - return Result; - } - - ArrayRef getMMOs() const { - return makeArrayRef(getTrailingObjects(), NumMMOs); - } - - MCSymbol *getPreInstrSymbol() const { - return HasPreInstrSymbol ? getTrailingObjects()[0] : nullptr; - } - - MCSymbol *getPostInstrSymbol() const { - return HasPostInstrSymbol - ? getTrailingObjects()[HasPreInstrSymbol] - : nullptr; - } - - MDNode *getHeapAllocMarker() const { - return HasHeapAllocMarker ? getTrailingObjects()[0] : nullptr; - } - - private: - friend TrailingObjects; - - // Description of the extra info, used to interpret the actual optional - // data appended. - // - // Note that this is not terribly space optimized. This leaves a great deal - // of flexibility to fit more in here later. - const int NumMMOs; - const bool HasPreInstrSymbol; - const bool HasPostInstrSymbol; - const bool HasHeapAllocMarker; - - // Implement the `TrailingObjects` internal API. - size_t numTrailingObjects(OverloadToken) const { - return NumMMOs; - } - size_t numTrailingObjects(OverloadToken) const { - return HasPreInstrSymbol + HasPostInstrSymbol; - } - size_t numTrailingObjects(OverloadToken) const { - return HasHeapAllocMarker; - } - - // Just a boring constructor to allow us to initialize the sizes. Always use - // the `create` routine above. - ExtraInfo(int NumMMOs, bool HasPreInstrSymbol, bool HasPostInstrSymbol, - bool HasHeapAllocMarker) - : NumMMOs(NumMMOs), HasPreInstrSymbol(HasPreInstrSymbol), - HasPostInstrSymbol(HasPostInstrSymbol), - HasHeapAllocMarker(HasHeapAllocMarker) {} - }; - - /// Enumeration of the kinds of inline extra info available. It is important - /// that the `MachineMemOperand` inline kind has a tag value of zero to make - /// it accessible as an `ArrayRef`. - enum ExtraInfoInlineKinds { - EIIK_MMO = 0, - EIIK_PreInstrSymbol, - EIIK_PostInstrSymbol, - EIIK_OutOfLine - }; - - // We store extra information about the instruction here. The common case is - // expected to be nothing or a single pointer (typically a MMO or a symbol). - // We work to optimize this common case by storing it inline here rather than - // requiring a separate allocation, but we fall back to an allocation when - // multiple pointers are needed. - PointerSumType, - PointerSumTypeMember, - PointerSumTypeMember, - PointerSumTypeMember> - Info; - - DebugLoc DbgLoc; // Source line information. - - /// Unique instruction number. Used by DBG_INSTR_REFs to refer to the values - /// defined by this instruction. - unsigned DebugInstrNum; - - // Intrusive list support - friend struct ilist_traits; - friend struct ilist_callback_traits; - void setParent(MachineBasicBlock *P) { Parent = P; } - - /// This constructor creates a copy of the given - /// MachineInstr in the given MachineFunction. - MachineInstr(MachineFunction &, const MachineInstr &); - - /// This constructor create a MachineInstr and add the implicit operands. - /// It reserves space for number of operands specified by - /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction &, const MCInstrDesc &TID, DebugLoc DL, - bool NoImp = false); - - // MachineInstrs are pool-allocated and owned by MachineFunction. - friend class MachineFunction; - - void - dumprImpl(const MachineRegisterInfo &MRI, unsigned Depth, unsigned MaxDepth, - SmallPtrSetImpl &AlreadySeenInstrs) const; - -public: - MachineInstr(const MachineInstr &) = delete; - MachineInstr &operator=(const MachineInstr &) = delete; - // Use MachineFunction::DeleteMachineInstr() instead. - ~MachineInstr() = delete; - - const MachineBasicBlock* getParent() const { return Parent; } - MachineBasicBlock* getParent() { return Parent; } - - /// Move the instruction before \p MovePos. - void moveBefore(MachineInstr *MovePos); - - /// Return the function that contains the basic block that this instruction - /// belongs to. - /// - /// Note: this is undefined behaviour if the instruction does not have a - /// parent. - const MachineFunction *getMF() const; - MachineFunction *getMF() { - return const_cast( - static_cast(this)->getMF()); - } - - /// Return the asm printer flags bitvector. - uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } - - /// Clear the AsmPrinter bitvector. - void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } - - /// Return whether an AsmPrinter flag is set. - bool getAsmPrinterFlag(CommentFlag Flag) const { - return AsmPrinterFlags & Flag; - } - - /// Set a flag for the AsmPrinter. - void setAsmPrinterFlag(uint8_t Flag) { - AsmPrinterFlags |= Flag; - } - - /// Clear specific AsmPrinter flags. - void clearAsmPrinterFlag(CommentFlag Flag) { - AsmPrinterFlags &= ~Flag; - } - - /// Return the MI flags bitvector. - uint16_t getFlags() const { - return Flags; - } - - /// Return whether an MI flag is set. - bool getFlag(MIFlag Flag) const { - return Flags & Flag; - } - - /// Set a MI flag. - void setFlag(MIFlag Flag) { - Flags |= (uint16_t)Flag; - } - - void setFlags(unsigned flags) { - // Filter out the automatically maintained flags. - unsigned Mask = BundledPred | BundledSucc; - Flags = (Flags & Mask) | (flags & ~Mask); - } - - /// clearFlag - Clear a MI flag. - void clearFlag(MIFlag Flag) { - Flags &= ~((uint16_t)Flag); - } - - /// Return true if MI is in a bundle (but not the first MI in a bundle). - /// - /// A bundle looks like this before it's finalized: - /// ---------------- - /// | MI | - /// ---------------- - /// | - /// ---------------- - /// | MI * | - /// ---------------- - /// | - /// ---------------- - /// | MI * | - /// ---------------- - /// In this case, the first MI starts a bundle but is not inside a bundle, the - /// next 2 MIs are considered "inside" the bundle. - /// - /// After a bundle is finalized, it looks like this: - /// ---------------- - /// | Bundle | - /// ---------------- - /// | - /// ---------------- - /// | MI * | - /// ---------------- - /// | - /// ---------------- - /// | MI * | - /// ---------------- - /// | - /// ---------------- - /// | MI * | - /// ---------------- - /// The first instruction has the special opcode "BUNDLE". It's not "inside" - /// a bundle, but the next three MIs are. - bool isInsideBundle() const { - return getFlag(BundledPred); - } - - /// Return true if this instruction part of a bundle. This is true - /// if either itself or its following instruction is marked "InsideBundle". - bool isBundled() const { - return isBundledWithPred() || isBundledWithSucc(); - } - - /// Return true if this instruction is part of a bundle, and it is not the - /// first instruction in the bundle. - bool isBundledWithPred() const { return getFlag(BundledPred); } - - /// Return true if this instruction is part of a bundle, and it is not the - /// last instruction in the bundle. - bool isBundledWithSucc() const { return getFlag(BundledSucc); } - - /// Bundle this instruction with its predecessor. This can be an unbundled - /// instruction, or it can be the first instruction in a bundle. - void bundleWithPred(); - - /// Bundle this instruction with its successor. This can be an unbundled - /// instruction, or it can be the last instruction in a bundle. - void bundleWithSucc(); - - /// Break bundle above this instruction. - void unbundleFromPred(); - - /// Break bundle below this instruction. - void unbundleFromSucc(); - - /// Returns the debug location id of this MachineInstr. - const DebugLoc &getDebugLoc() const { return DbgLoc; } - - /// Return the operand containing the offset to be used if this DBG_VALUE - /// instruction is indirect; will be an invalid register if this value is - /// not indirect, and an immediate with value 0 otherwise. - const MachineOperand &getDebugOffset() const { - assert(isNonListDebugValue() && "not a DBG_VALUE"); - return getOperand(1); - } - MachineOperand &getDebugOffset() { - assert(isNonListDebugValue() && "not a DBG_VALUE"); - return getOperand(1); - } - - /// Return the operand for the debug variable referenced by - /// this DBG_VALUE instruction. - const MachineOperand &getDebugVariableOp() const; - MachineOperand &getDebugVariableOp(); - - /// Return the debug variable referenced by - /// this DBG_VALUE instruction. - const DILocalVariable *getDebugVariable() const; - - /// Return the operand for the complex address expression referenced by - /// this DBG_VALUE instruction. - const MachineOperand &getDebugExpressionOp() const; - MachineOperand &getDebugExpressionOp(); - - /// Return the complex address expression referenced by - /// this DBG_VALUE instruction. - const DIExpression *getDebugExpression() const; - - /// Return the debug label referenced by - /// this DBG_LABEL instruction. - const DILabel *getDebugLabel() const; - - /// Fetch the instruction number of this MachineInstr. If it does not have - /// one already, a new and unique number will be assigned. - unsigned getDebugInstrNum(); - - /// Fetch instruction number of this MachineInstr -- but before it's inserted - /// into \p MF. Needed for transformations that create an instruction but - /// don't immediately insert them. - unsigned getDebugInstrNum(MachineFunction &MF); - - /// Examine the instruction number of this MachineInstr. May be zero if - /// it hasn't been assigned a number yet. - unsigned peekDebugInstrNum() const { return DebugInstrNum; } - - /// Set instruction number of this MachineInstr. Avoid using unless you're - /// deserializing this information. - void setDebugInstrNum(unsigned Num) { DebugInstrNum = Num; } - - /// Drop any variable location debugging information associated with this - /// instruction. Use when an instruction is modified in such a way that it no - /// longer defines the value it used to. Variable locations using that value - /// will be dropped. - void dropDebugNumber() { DebugInstrNum = 0; } - - /// Emit an error referring to the source location of this instruction. - /// This should only be used for inline assembly that is somehow - /// impossible to compile. Other errors should have been handled much - /// earlier. - /// - /// If this method returns, the caller should try to recover from the error. - void emitError(StringRef Msg) const; - - /// Returns the target instruction descriptor of this MachineInstr. - const MCInstrDesc &getDesc() const { return *MCID; } - - /// Returns the opcode of this MachineInstr. - unsigned getOpcode() const { return MCID->Opcode; } - - /// Returns the total number of operands. - unsigned getNumOperands() const { return NumOperands; } - - /// Returns the total number of operands which are debug locations. - unsigned getNumDebugOperands() const { - return std::distance(debug_operands().begin(), debug_operands().end()); - } - - const MachineOperand& getOperand(unsigned i) const { - assert(i < getNumOperands() && "getOperand() out of range!"); - return Operands[i]; - } - MachineOperand& getOperand(unsigned i) { - assert(i < getNumOperands() && "getOperand() out of range!"); - return Operands[i]; - } - - MachineOperand &getDebugOperand(unsigned Index) { - assert(Index < getNumDebugOperands() && "getDebugOperand() out of range!"); - return *(debug_operands().begin() + Index); - } - const MachineOperand &getDebugOperand(unsigned Index) const { - assert(Index < getNumDebugOperands() && "getDebugOperand() out of range!"); - return *(debug_operands().begin() + Index); - } - - SmallSet getUsedDebugRegs() const { - assert(isDebugValue() && "not a DBG_VALUE*"); - SmallSet UsedRegs; - for (const auto &MO : debug_operands()) - if (MO.isReg() && MO.getReg()) - UsedRegs.insert(MO.getReg()); - return UsedRegs; - } - - /// Returns whether this debug value has at least one debug operand with the - /// register \p Reg. - bool hasDebugOperandForReg(Register Reg) const { - return any_of(debug_operands(), [Reg](const MachineOperand &Op) { - return Op.isReg() && Op.getReg() == Reg; - }); - } - - /// Returns a range of all of the operands that correspond to a debug use of - /// \p Reg. - template - static iterator_range< - filter_iterator>> - getDebugOperandsForReg(Instruction *MI, Register Reg) { - std::function OpUsesReg( - [Reg](Operand &Op) { return Op.isReg() && Op.getReg() == Reg; }); - return make_filter_range(MI->debug_operands(), OpUsesReg); - } - iterator_range>> - getDebugOperandsForReg(Register Reg) const { - return MachineInstr::getDebugOperandsForReg(this, Reg); - } - iterator_range>> - getDebugOperandsForReg(Register Reg) { - return MachineInstr::getDebugOperandsForReg( - this, Reg); - } - - bool isDebugOperand(const MachineOperand *Op) const { - return Op >= adl_begin(debug_operands()) && Op <= adl_end(debug_operands()); - } - - unsigned getDebugOperandIndex(const MachineOperand *Op) const { - assert(isDebugOperand(Op) && "Expected a debug operand."); - return std::distance(adl_begin(debug_operands()), Op); - } - - /// Returns the total number of definitions. - unsigned getNumDefs() const { - return getNumExplicitDefs() + MCID->getNumImplicitDefs(); - } - - /// Returns true if the instruction has implicit definition. - bool hasImplicitDef() const { - for (unsigned I = getNumExplicitOperands(), E = getNumOperands(); - I != E; ++I) { - const MachineOperand &MO = getOperand(I); - if (MO.isDef() && MO.isImplicit()) - return true; - } - return false; - } - - /// Returns the implicit operands number. - unsigned getNumImplicitOperands() const { - return getNumOperands() - getNumExplicitOperands(); - } - - /// Return true if operand \p OpIdx is a subregister index. - bool isOperandSubregIdx(unsigned OpIdx) const { - assert(getOperand(OpIdx).getType() == MachineOperand::MO_Immediate && - "Expected MO_Immediate operand type."); - if (isExtractSubreg() && OpIdx == 2) - return true; - if (isInsertSubreg() && OpIdx == 3) - return true; - if (isRegSequence() && OpIdx > 1 && (OpIdx % 2) == 0) - return true; - if (isSubregToReg() && OpIdx == 3) - return true; - return false; - } - - /// Returns the number of non-implicit operands. - unsigned getNumExplicitOperands() const; - - /// Returns the number of non-implicit definitions. - unsigned getNumExplicitDefs() const; - - /// iterator/begin/end - Iterate over all operands of a machine instruction. - using mop_iterator = MachineOperand *; - using const_mop_iterator = const MachineOperand *; - - mop_iterator operands_begin() { return Operands; } - mop_iterator operands_end() { return Operands + NumOperands; } - - const_mop_iterator operands_begin() const { return Operands; } - const_mop_iterator operands_end() const { return Operands + NumOperands; } - - iterator_range operands() { - return make_range(operands_begin(), operands_end()); - } - iterator_range operands() const { - return make_range(operands_begin(), operands_end()); - } - iterator_range explicit_operands() { - return make_range(operands_begin(), - operands_begin() + getNumExplicitOperands()); - } - iterator_range explicit_operands() const { - return make_range(operands_begin(), - operands_begin() + getNumExplicitOperands()); - } - iterator_range implicit_operands() { - return make_range(explicit_operands().end(), operands_end()); - } - iterator_range implicit_operands() const { - return make_range(explicit_operands().end(), operands_end()); - } - /// Returns a range over all operands that are used to determine the variable - /// location for this DBG_VALUE instruction. - iterator_range debug_operands() { - assert(isDebugValue() && "Must be a debug value instruction."); - return isDebugValueList() - ? make_range(operands_begin() + 2, operands_end()) - : make_range(operands_begin(), operands_begin() + 1); - } - /// \copydoc debug_operands() - iterator_range debug_operands() const { - assert(isDebugValue() && "Must be a debug value instruction."); - return isDebugValueList() - ? make_range(operands_begin() + 2, operands_end()) - : make_range(operands_begin(), operands_begin() + 1); - } - /// Returns a range over all explicit operands that are register definitions. - /// Implicit definition are not included! - iterator_range defs() { - return make_range(operands_begin(), - operands_begin() + getNumExplicitDefs()); - } - /// \copydoc defs() - iterator_range defs() const { - return make_range(operands_begin(), - operands_begin() + getNumExplicitDefs()); - } - /// Returns a range that includes all operands that are register uses. - /// This may include unrelated operands which are not register uses. - iterator_range uses() { - return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); - } - /// \copydoc uses() - iterator_range uses() const { - return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); - } - iterator_range explicit_uses() { - return make_range(operands_begin() + getNumExplicitDefs(), - operands_begin() + getNumExplicitOperands()); - } - iterator_range explicit_uses() const { - return make_range(operands_begin() + getNumExplicitDefs(), - operands_begin() + getNumExplicitOperands()); - } - - /// Returns the number of the operand iterator \p I points to. - unsigned getOperandNo(const_mop_iterator I) const { - return I - operands_begin(); - } - - /// Access to memory operands of the instruction. If there are none, that does - /// not imply anything about whether the function accesses memory. Instead, - /// the caller must behave conservatively. - ArrayRef memoperands() const { - if (!Info) - return {}; - - if (Info.is()) - return makeArrayRef(Info.getAddrOfZeroTagPointer(), 1); - - if (ExtraInfo *EI = Info.get()) - return EI->getMMOs(); - - return {}; - } - - /// Access to memory operands of the instruction. - /// - /// If `memoperands_begin() == memoperands_end()`, that does not imply - /// anything about whether the function accesses memory. Instead, the caller - /// must behave conservatively. - mmo_iterator memoperands_begin() const { return memoperands().begin(); } - - /// Access to memory operands of the instruction. - /// - /// If `memoperands_begin() == memoperands_end()`, that does not imply - /// anything about whether the function accesses memory. Instead, the caller - /// must behave conservatively. - mmo_iterator memoperands_end() const { return memoperands().end(); } - - /// Return true if we don't have any memory operands which described the - /// memory access done by this instruction. If this is true, calling code - /// must be conservative. - bool memoperands_empty() const { return memoperands().empty(); } - - /// Return true if this instruction has exactly one MachineMemOperand. - bool hasOneMemOperand() const { return memoperands().size() == 1; } - - /// Return the number of memory operands. - unsigned getNumMemOperands() const { return memoperands().size(); } - - /// Helper to extract a pre-instruction symbol if one has been added. - MCSymbol *getPreInstrSymbol() const { - if (!Info) - return nullptr; - if (MCSymbol *S = Info.get()) - return S; - if (ExtraInfo *EI = Info.get()) - return EI->getPreInstrSymbol(); - - return nullptr; - } - - /// Helper to extract a post-instruction symbol if one has been added. - MCSymbol *getPostInstrSymbol() const { - if (!Info) - return nullptr; - if (MCSymbol *S = Info.get()) - return S; - if (ExtraInfo *EI = Info.get()) - return EI->getPostInstrSymbol(); - - return nullptr; - } - - /// Helper to extract a heap alloc marker if one has been added. - MDNode *getHeapAllocMarker() const { - if (!Info) - return nullptr; - if (ExtraInfo *EI = Info.get()) - return EI->getHeapAllocMarker(); - - return nullptr; - } - - /// API for querying MachineInstr properties. They are the same as MCInstrDesc - /// queries but they are bundle aware. - - enum QueryType { - IgnoreBundle, // Ignore bundles - AnyInBundle, // Return true if any instruction in bundle has property - AllInBundle // Return true if all instructions in bundle have property - }; - - /// Return true if the instruction (or in the case of a bundle, - /// the instructions inside the bundle) has the specified property. - /// The first argument is the property being queried. - /// The second argument indicates whether the query should look inside - /// instruction bundles. - bool hasProperty(unsigned MCFlag, QueryType Type = AnyInBundle) const { - assert(MCFlag < 64 && - "MCFlag out of range for bit mask in getFlags/hasPropertyInBundle."); - // Inline the fast path for unbundled or bundle-internal instructions. - if (Type == IgnoreBundle || !isBundled() || isBundledWithPred()) - return getDesc().getFlags() & (1ULL << MCFlag); - - // If this is the first instruction in a bundle, take the slow path. - return hasPropertyInBundle(1ULL << MCFlag, Type); - } - - /// Return true if this is an instruction that should go through the usual - /// legalization steps. - bool isPreISelOpcode(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::PreISelOpcode, Type); - } - - /// Return true if this instruction can have a variable number of operands. - /// In this case, the variable operands will be after the normal - /// operands but before the implicit definitions and uses (if any are - /// present). - bool isVariadic(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Variadic, Type); - } - - /// Set if this instruction has an optional definition, e.g. - /// ARM instructions which can set condition code if 's' bit is set. - bool hasOptionalDef(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::HasOptionalDef, Type); - } - - /// Return true if this is a pseudo instruction that doesn't - /// correspond to a real machine instruction. - bool isPseudo(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Pseudo, Type); - } - - bool isReturn(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::Return, Type); - } - - /// Return true if this is an instruction that marks the end of an EH scope, - /// i.e., a catchpad or a cleanuppad instruction. - bool isEHScopeReturn(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::EHScopeReturn, Type); - } - - bool isCall(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::Call, Type); - } - - /// Return true if this is a call instruction that may have an associated - /// call site entry in the debug info. - bool isCandidateForCallSiteEntry(QueryType Type = IgnoreBundle) const; - /// Return true if copying, moving, or erasing this instruction requires - /// updating Call Site Info (see \ref copyCallSiteInfo, \ref moveCallSiteInfo, - /// \ref eraseCallSiteInfo). - bool shouldUpdateCallSiteInfo() const; - - /// Returns true if the specified instruction stops control flow - /// from executing the instruction immediately following it. Examples include - /// unconditional branches and return instructions. - bool isBarrier(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::Barrier, Type); - } - - /// Returns true if this instruction part of the terminator for a basic block. - /// Typically this is things like return and branch instructions. - /// - /// Various passes use this to insert code into the bottom of a basic block, - /// but before control flow occurs. - bool isTerminator(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::Terminator, Type); - } - - /// Returns true if this is a conditional, unconditional, or indirect branch. - /// Predicates below can be used to discriminate between - /// these cases, and the TargetInstrInfo::analyzeBranch method can be used to - /// get more information. - bool isBranch(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::Branch, Type); - } - - /// Return true if this is an indirect branch, such as a - /// branch through a register. - bool isIndirectBranch(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::IndirectBranch, Type); - } - - /// Return true if this is a branch which may fall - /// through to the next instruction or may transfer control flow to some other - /// block. The TargetInstrInfo::analyzeBranch method can be used to get more - /// information about this branch. - bool isConditionalBranch(QueryType Type = AnyInBundle) const { - return isBranch(Type) && !isBarrier(Type) && !isIndirectBranch(Type); - } - - /// Return true if this is a branch which always - /// transfers control flow to some other block. The - /// TargetInstrInfo::analyzeBranch method can be used to get more information - /// about this branch. - bool isUnconditionalBranch(QueryType Type = AnyInBundle) const { - return isBranch(Type) && isBarrier(Type) && !isIndirectBranch(Type); - } - - /// Return true if this instruction has a predicate operand that - /// controls execution. It may be set to 'always', or may be set to other - /// values. There are various methods in TargetInstrInfo that can be used to - /// control and modify the predicate in this instruction. - bool isPredicable(QueryType Type = AllInBundle) const { - // If it's a bundle than all bundled instructions must be predicable for this - // to return true. - return hasProperty(MCID::Predicable, Type); - } - - /// Return true if this instruction is a comparison. - bool isCompare(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Compare, Type); - } - - /// Return true if this instruction is a move immediate - /// (including conditional moves) instruction. - bool isMoveImmediate(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::MoveImm, Type); - } - - /// Return true if this instruction is a register move. - /// (including moving values from subreg to reg) - bool isMoveReg(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::MoveReg, Type); - } - - /// Return true if this instruction is a bitcast instruction. - bool isBitcast(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Bitcast, Type); - } - - /// Return true if this instruction is a select instruction. - bool isSelect(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Select, Type); - } - - /// Return true if this instruction cannot be safely duplicated. - /// For example, if the instruction has a unique labels attached - /// to it, duplicating it would cause multiple definition errors. - bool isNotDuplicable(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::NotDuplicable, Type); - } - - /// Return true if this instruction is convergent. - /// Convergent instructions can not be made control-dependent on any - /// additional values. - bool isConvergent(QueryType Type = AnyInBundle) const { - if (isInlineAsm()) { - unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_IsConvergent) - return true; - } - return hasProperty(MCID::Convergent, Type); - } - - /// Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::DelaySlot, Type); - } - - /// Return true for instructions that can be folded as - /// memory operands in other instructions. The most common use for this - /// is instructions that are simple loads from memory that don't modify - /// the loaded value in any way, but it can also be used for instructions - /// that can be expressed as constant-pool loads, such as V_SETALLONES - /// on x86, to allow them to be folded when it is beneficial. - /// This should only be set on instructions that return a value in their - /// only virtual register definition. - bool canFoldAsLoad(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::FoldableAsLoad, Type); - } - - /// Return true if this instruction behaves - /// the same way as the generic REG_SEQUENCE instructions. - /// E.g., on ARM, - /// dX VMOVDRR rY, rZ - /// is equivalent to - /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. - /// - /// Note that for the optimizers to be able to take advantage of - /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be - /// override accordingly. - bool isRegSequenceLike(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::RegSequence, Type); - } - - /// Return true if this instruction behaves - /// the same way as the generic EXTRACT_SUBREG instructions. - /// E.g., on ARM, - /// rX, rY VMOVRRD dZ - /// is equivalent to two EXTRACT_SUBREG: - /// rX = EXTRACT_SUBREG dZ, ssub_0 - /// rY = EXTRACT_SUBREG dZ, ssub_1 - /// - /// Note that for the optimizers to be able to take advantage of - /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be - /// override accordingly. - bool isExtractSubregLike(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::ExtractSubreg, Type); - } - - /// Return true if this instruction behaves - /// the same way as the generic INSERT_SUBREG instructions. - /// E.g., on ARM, - /// dX = VSETLNi32 dY, rZ, Imm - /// is equivalent to a INSERT_SUBREG: - /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) - /// - /// Note that for the optimizers to be able to take advantage of - /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be - /// override accordingly. - bool isInsertSubregLike(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::InsertSubreg, Type); - } - - //===--------------------------------------------------------------------===// - // Side Effect Analysis - //===--------------------------------------------------------------------===// - - /// Return true if this instruction could possibly read memory. - /// Instructions with this flag set are not necessarily simple load - /// instructions, they may load a value and modify it, for example. - bool mayLoad(QueryType Type = AnyInBundle) const { - if (isInlineAsm()) { - unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_MayLoad) - return true; - } - return hasProperty(MCID::MayLoad, Type); - } - - /// Return true if this instruction could possibly modify memory. - /// Instructions with this flag set are not necessarily simple store - /// instructions, they may store a modified value based on their operands, or - /// may not actually modify anything, for example. - bool mayStore(QueryType Type = AnyInBundle) const { - if (isInlineAsm()) { - unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_MayStore) - return true; - } - return hasProperty(MCID::MayStore, Type); - } - - /// Return true if this instruction could possibly read or modify memory. - bool mayLoadOrStore(QueryType Type = AnyInBundle) const { - return mayLoad(Type) || mayStore(Type); - } - - /// Return true if this instruction could possibly raise a floating-point - /// exception. This is the case if the instruction is a floating-point - /// instruction that can in principle raise an exception, as indicated - /// by the MCID::MayRaiseFPException property, *and* at the same time, - /// the instruction is used in a context where we expect floating-point - /// exceptions are not disabled, as indicated by the NoFPExcept MI flag. - bool mayRaiseFPException() const { - return hasProperty(MCID::MayRaiseFPException) && - !getFlag(MachineInstr::MIFlag::NoFPExcept); - } - - //===--------------------------------------------------------------------===// - // Flags that indicate whether an instruction can be modified by a method. - //===--------------------------------------------------------------------===// - - /// Return true if this may be a 2- or 3-address - /// instruction (of the form "X = op Y, Z, ..."), which produces the same - /// result if Y and Z are exchanged. If this flag is set, then the - /// TargetInstrInfo::commuteInstruction method may be used to hack on the - /// instruction. - /// - /// Note that this flag may be set on instructions that are only commutable - /// sometimes. In these cases, the call to commuteInstruction will fail. - /// Also note that some instructions require non-trivial modification to - /// commute them. - bool isCommutable(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::Commutable, Type); - } - - /// Return true if this is a 2-address instruction - /// which can be changed into a 3-address instruction if needed. Doing this - /// transformation can be profitable in the register allocator, because it - /// means that the instruction can use a 2-address form if possible, but - /// degrade into a less efficient form if the source and dest register cannot - /// be assigned to the same register. For example, this allows the x86 - /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which - /// is the same speed as the shift but has bigger code size. - /// - /// If this returns true, then the target must implement the - /// TargetInstrInfo::convertToThreeAddress method for this instruction, which - /// is allowed to fail if the transformation isn't valid for this specific - /// instruction (e.g. shl reg, 4 on x86). - /// - bool isConvertibleTo3Addr(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::ConvertibleTo3Addr, Type); - } - - /// Return true if this instruction requires - /// custom insertion support when the DAG scheduler is inserting it into a - /// machine basic block. If this is true for the instruction, it basically - /// means that it is a pseudo instruction used at SelectionDAG time that is - /// expanded out into magic code by the target when MachineInstrs are formed. - /// - /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method - /// is used to insert this into the MachineBasicBlock. - bool usesCustomInsertionHook(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::UsesCustomInserter, Type); - } - - /// Return true if this instruction requires *adjustment* - /// after instruction selection by calling a target hook. For example, this - /// can be used to fill in ARM 's' optional operand depending on whether - /// the conditional flag register is used. - bool hasPostISelHook(QueryType Type = IgnoreBundle) const { - return hasProperty(MCID::HasPostISelHook, Type); - } - - /// Returns true if this instruction is a candidate for remat. - /// This flag is deprecated, please don't use it anymore. If this - /// flag is set, the isReallyTriviallyReMaterializable() method is called to - /// verify the instruction is really rematable. - bool isRematerializable(QueryType Type = AllInBundle) const { - // It's only possible to re-mat a bundle if all bundled instructions are - // re-materializable. - return hasProperty(MCID::Rematerializable, Type); - } - - /// Returns true if this instruction has the same cost (or less) than a move - /// instruction. This is useful during certain types of optimizations - /// (e.g., remat during two-address conversion or machine licm) - /// where we would like to remat or hoist the instruction, but not if it costs - /// more than moving the instruction into the appropriate register. Note, we - /// are not marking copies from and to the same register class with this flag. - bool isAsCheapAsAMove(QueryType Type = AllInBundle) const { - // Only returns true for a bundle if all bundled instructions are cheap. - return hasProperty(MCID::CheapAsAMove, Type); - } - - /// Returns true if this instruction source operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::STRD's two source registers must be an - /// even / odd pair, ARM::STM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for sources of instructions with this flag. - bool hasExtraSrcRegAllocReq(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::ExtraSrcRegAllocReq, Type); - } - - /// Returns true if this instruction def operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::LDRD's two def registers must be an - /// even / odd pair, ARM::LDM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for definitions of instructions with this flag. - bool hasExtraDefRegAllocReq(QueryType Type = AnyInBundle) const { - return hasProperty(MCID::ExtraDefRegAllocReq, Type); - } - - enum MICheckType { - CheckDefs, // Check all operands for equality - CheckKillDead, // Check all operands including kill / dead markers - IgnoreDefs, // Ignore all definitions - IgnoreVRegDefs // Ignore virtual register definitions - }; - - /// Return true if this instruction is identical to \p Other. - /// Two instructions are identical if they have the same opcode and all their - /// operands are identical (with respect to MachineOperand::isIdenticalTo()). - /// Note that this means liveness related flags (dead, undef, kill) do not - /// affect the notion of identical. - bool isIdenticalTo(const MachineInstr &Other, - MICheckType Check = CheckDefs) const; - - /// Unlink 'this' from the containing basic block, and return it without - /// deleting it. - /// - /// This function can not be used on bundled instructions, use - /// removeFromBundle() to remove individual instructions from a bundle. - MachineInstr *removeFromParent(); - - /// Unlink this instruction from its basic block and return it without - /// deleting it. - /// - /// If the instruction is part of a bundle, the other instructions in the - /// bundle remain bundled. - MachineInstr *removeFromBundle(); - - /// Unlink 'this' from the containing basic block and delete it. - /// - /// If this instruction is the header of a bundle, the whole bundle is erased. - /// This function can not be used for instructions inside a bundle, use - /// eraseFromBundle() to erase individual bundled instructions. - void eraseFromParent(); - - /// Unlink 'this' form its basic block and delete it. - /// - /// If the instruction is part of a bundle, the other instructions in the - /// bundle remain bundled. - void eraseFromBundle(); - - bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } - bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } - bool isAnnotationLabel() const { - return getOpcode() == TargetOpcode::ANNOTATION_LABEL; - } - - /// Returns true if the MachineInstr represents a label. - bool isLabel() const { - return isEHLabel() || isGCLabel() || isAnnotationLabel(); - } - - bool isCFIInstruction() const { - return getOpcode() == TargetOpcode::CFI_INSTRUCTION; - } - - bool isPseudoProbe() const { - return getOpcode() == TargetOpcode::PSEUDO_PROBE; - } - - // True if the instruction represents a position in the function. - bool isPosition() const { return isLabel() || isCFIInstruction(); } - - bool isNonListDebugValue() const { - return getOpcode() == TargetOpcode::DBG_VALUE; - } - bool isDebugValueList() const { - return getOpcode() == TargetOpcode::DBG_VALUE_LIST; - } - bool isDebugValue() const { - return isNonListDebugValue() || isDebugValueList(); - } - bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } - bool isDebugRef() const { return getOpcode() == TargetOpcode::DBG_INSTR_REF; } - bool isDebugPHI() const { return getOpcode() == TargetOpcode::DBG_PHI; } - bool isDebugInstr() const { - return isDebugValue() || isDebugLabel() || isDebugRef() || isDebugPHI(); - } - bool isDebugOrPseudoInstr() const { - return isDebugInstr() || isPseudoProbe(); - } - - bool isDebugOffsetImm() const { - return isNonListDebugValue() && getDebugOffset().isImm(); - } - - /// A DBG_VALUE is indirect iff the location operand is a register and - /// the offset operand is an immediate. - bool isIndirectDebugValue() const { - return isDebugOffsetImm() && getDebugOperand(0).isReg(); - } - - /// A DBG_VALUE is an entry value iff its debug expression contains the - /// DW_OP_LLVM_entry_value operation. - bool isDebugEntryValue() const; - - /// Return true if the instruction is a debug value which describes a part of - /// a variable as unavailable. - bool isUndefDebugValue() const { - if (!isDebugValue()) - return false; - // If any $noreg locations are given, this DV is undef. - for (const MachineOperand &Op : debug_operands()) - if (Op.isReg() && !Op.getReg().isValid()) - return true; - return false; - } - - bool isPHI() const { - return getOpcode() == TargetOpcode::PHI || - getOpcode() == TargetOpcode::G_PHI; - } - bool isKill() const { return getOpcode() == TargetOpcode::KILL; } - bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } - bool isInlineAsm() const { - return getOpcode() == TargetOpcode::INLINEASM || - getOpcode() == TargetOpcode::INLINEASM_BR; - } - - /// FIXME: Seems like a layering violation that the AsmDialect, which is X86 - /// specific, be attached to a generic MachineInstr. - bool isMSInlineAsm() const { - return isInlineAsm() && getInlineAsmDialect() == InlineAsm::AD_Intel; - } - - bool isStackAligningInlineAsm() const; - InlineAsm::AsmDialect getInlineAsmDialect() const; - - bool isInsertSubreg() const { - return getOpcode() == TargetOpcode::INSERT_SUBREG; - } - - bool isSubregToReg() const { - return getOpcode() == TargetOpcode::SUBREG_TO_REG; - } - - bool isRegSequence() const { - return getOpcode() == TargetOpcode::REG_SEQUENCE; - } - - bool isBundle() const { - return getOpcode() == TargetOpcode::BUNDLE; - } - - bool isCopy() const { - return getOpcode() == TargetOpcode::COPY; - } - - bool isFullCopy() const { - return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg(); - } - - bool isExtractSubreg() const { - return getOpcode() == TargetOpcode::EXTRACT_SUBREG; - } - - /// Return true if the instruction behaves like a copy. - /// This does not include native copy instructions. - bool isCopyLike() const { - return isCopy() || isSubregToReg(); - } - - /// Return true is the instruction is an identity copy. - bool isIdentityCopy() const { - return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() && - getOperand(0).getSubReg() == getOperand(1).getSubReg(); - } - - /// Return true if this instruction doesn't produce any output in the form of - /// executable instructions. - bool isMetaInstruction() const { - switch (getOpcode()) { - default: - return false; - case TargetOpcode::IMPLICIT_DEF: - case TargetOpcode::KILL: - case TargetOpcode::CFI_INSTRUCTION: - case TargetOpcode::EH_LABEL: - case TargetOpcode::GC_LABEL: - case TargetOpcode::DBG_VALUE: - case TargetOpcode::DBG_VALUE_LIST: - case TargetOpcode::DBG_INSTR_REF: - case TargetOpcode::DBG_PHI: - case TargetOpcode::DBG_LABEL: - case TargetOpcode::LIFETIME_START: - case TargetOpcode::LIFETIME_END: - case TargetOpcode::PSEUDO_PROBE: - case TargetOpcode::ARITH_FENCE: - return true; - } - } - - /// Return true if this is a transient instruction that is either very likely - /// to be eliminated during register allocation (such as copy-like - /// instructions), or if this instruction doesn't have an execution-time cost. - bool isTransient() const { - switch (getOpcode()) { - default: - return isMetaInstruction(); - // Copy-like instructions are usually eliminated during register allocation. - case TargetOpcode::PHI: - case TargetOpcode::G_PHI: - case TargetOpcode::COPY: - case TargetOpcode::INSERT_SUBREG: - case TargetOpcode::SUBREG_TO_REG: - case TargetOpcode::REG_SEQUENCE: - return true; - } - } - - /// Return the number of instructions inside the MI bundle, excluding the - /// bundle header. - /// - /// This is the number of instructions that MachineBasicBlock::iterator - /// skips, 0 for unbundled instructions. - unsigned getBundleSize() const; - - /// Return true if the MachineInstr reads the specified register. - /// If TargetRegisterInfo is passed, then it also checks if there - /// is a read of a super-register. - /// This does not count partial redefines of virtual registers as reads: - /// %reg1024:6 = OP. - bool readsRegister(Register Reg, - const TargetRegisterInfo *TRI = nullptr) const { - return findRegisterUseOperandIdx(Reg, false, TRI) != -1; - } - - /// Return true if the MachineInstr reads the specified virtual register. - /// Take into account that a partial define is a - /// read-modify-write operation. - bool readsVirtualRegister(Register Reg) const { - return readsWritesVirtualRegister(Reg).first; - } - - /// Return a pair of bools (reads, writes) indicating if this instruction - /// reads or writes Reg. This also considers partial defines. - /// If Ops is not null, all operand indices for Reg are added. - std::pair readsWritesVirtualRegister(Register Reg, - SmallVectorImpl *Ops = nullptr) const; - - /// Return true if the MachineInstr kills the specified register. - /// If TargetRegisterInfo is passed, then it also checks if there is - /// a kill of a super-register. - bool killsRegister(Register Reg, - const TargetRegisterInfo *TRI = nullptr) const { - return findRegisterUseOperandIdx(Reg, true, TRI) != -1; - } - - /// Return true if the MachineInstr fully defines the specified register. - /// If TargetRegisterInfo is passed, then it also checks - /// if there is a def of a super-register. - /// NOTE: It's ignoring subreg indices on virtual registers. - bool definesRegister(Register Reg, - const TargetRegisterInfo *TRI = nullptr) const { - return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; - } - - /// Return true if the MachineInstr modifies (fully define or partially - /// define) the specified register. - /// NOTE: It's ignoring subreg indices on virtual registers. - bool modifiesRegister(Register Reg, - const TargetRegisterInfo *TRI = nullptr) const { - return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; - } - - /// Returns true if the register is dead in this machine instruction. - /// If TargetRegisterInfo is passed, then it also checks - /// if there is a dead def of a super-register. - bool registerDefIsDead(Register Reg, - const TargetRegisterInfo *TRI = nullptr) const { - return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; - } - - /// Returns true if the MachineInstr has an implicit-use operand of exactly - /// the given register (not considering sub/super-registers). - bool hasRegisterImplicitUseOperand(Register Reg) const; - - /// Returns the operand index that is a use of the specific register or -1 - /// if it is not found. It further tightens the search criteria to a use - /// that kills the register if isKill is true. - int findRegisterUseOperandIdx(Register Reg, bool isKill = false, - const TargetRegisterInfo *TRI = nullptr) const; - - /// Wrapper for findRegisterUseOperandIdx, it returns - /// a pointer to the MachineOperand rather than an index. - MachineOperand *findRegisterUseOperand(Register Reg, bool isKill = false, - const TargetRegisterInfo *TRI = nullptr) { - int Idx = findRegisterUseOperandIdx(Reg, isKill, TRI); - return (Idx == -1) ? nullptr : &getOperand(Idx); - } - - const MachineOperand *findRegisterUseOperand( - Register Reg, bool isKill = false, - const TargetRegisterInfo *TRI = nullptr) const { - return const_cast(this)-> - findRegisterUseOperand(Reg, isKill, TRI); - } - - /// Returns the operand index that is a def of the specified register or - /// -1 if it is not found. If isDead is true, defs that are not dead are - /// skipped. If Overlap is true, then it also looks for defs that merely - /// overlap the specified register. If TargetRegisterInfo is non-null, - /// then it also checks if there is a def of a super-register. - /// This may also return a register mask operand when Overlap is true. - int findRegisterDefOperandIdx(Register Reg, - bool isDead = false, bool Overlap = false, - const TargetRegisterInfo *TRI = nullptr) const; - - /// Wrapper for findRegisterDefOperandIdx, it returns - /// a pointer to the MachineOperand rather than an index. - MachineOperand * - findRegisterDefOperand(Register Reg, bool isDead = false, - bool Overlap = false, - const TargetRegisterInfo *TRI = nullptr) { - int Idx = findRegisterDefOperandIdx(Reg, isDead, Overlap, TRI); - return (Idx == -1) ? nullptr : &getOperand(Idx); - } - - const MachineOperand * - findRegisterDefOperand(Register Reg, bool isDead = false, - bool Overlap = false, - const TargetRegisterInfo *TRI = nullptr) const { - return const_cast(this)->findRegisterDefOperand( - Reg, isDead, Overlap, TRI); - } - - /// Find the index of the first operand in the - /// operand list that is used to represent the predicate. It returns -1 if - /// none is found. - int findFirstPredOperandIdx() const; - - /// Find the index of the flag word operand that - /// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if - /// getOperand(OpIdx) does not belong to an inline asm operand group. - /// - /// If GroupNo is not NULL, it will receive the number of the operand group - /// containing OpIdx. - int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const; - - /// Compute the static register class constraint for operand OpIdx. - /// For normal instructions, this is derived from the MCInstrDesc. - /// For inline assembly it is derived from the flag words. - /// - /// Returns NULL if the static register class constraint cannot be - /// determined. - const TargetRegisterClass* - getRegClassConstraint(unsigned OpIdx, - const TargetInstrInfo *TII, - const TargetRegisterInfo *TRI) const; - - /// Applies the constraints (def/use) implied by this MI on \p Reg to - /// the given \p CurRC. - /// If \p ExploreBundle is set and MI is part of a bundle, all the - /// instructions inside the bundle will be taken into account. In other words, - /// this method accumulates all the constraints of the operand of this MI and - /// the related bundle if MI is a bundle or inside a bundle. - /// - /// Returns the register class that satisfies both \p CurRC and the - /// constraints set by MI. Returns NULL if such a register class does not - /// exist. - /// - /// \pre CurRC must not be NULL. - const TargetRegisterClass *getRegClassConstraintEffectForVReg( - Register Reg, const TargetRegisterClass *CurRC, - const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, - bool ExploreBundle = false) const; - - /// Applies the constraints (def/use) implied by the \p OpIdx operand - /// to the given \p CurRC. - /// - /// Returns the register class that satisfies both \p CurRC and the - /// constraints set by \p OpIdx MI. Returns NULL if such a register class - /// does not exist. - /// - /// \pre CurRC must not be NULL. - /// \pre The operand at \p OpIdx must be a register. - const TargetRegisterClass * - getRegClassConstraintEffect(unsigned OpIdx, const TargetRegisterClass *CurRC, - const TargetInstrInfo *TII, - const TargetRegisterInfo *TRI) const; - - /// Add a tie between the register operands at DefIdx and UseIdx. - /// The tie will cause the register allocator to ensure that the two - /// operands are assigned the same physical register. - /// - /// Tied operands are managed automatically for explicit operands in the - /// MCInstrDesc. This method is for exceptional cases like inline asm. - void tieOperands(unsigned DefIdx, unsigned UseIdx); - - /// Given the index of a tied register operand, find the - /// operand it is tied to. Defs are tied to uses and vice versa. Returns the - /// index of the tied operand which must exist. - unsigned findTiedOperandIdx(unsigned OpIdx) const; - - /// Given the index of a register def operand, - /// check if the register def is tied to a source operand, due to either - /// two-address elimination or inline assembly constraints. Returns the - /// first tied use operand index by reference if UseOpIdx is not null. - bool isRegTiedToUseOperand(unsigned DefOpIdx, - unsigned *UseOpIdx = nullptr) const { - const MachineOperand &MO = getOperand(DefOpIdx); - if (!MO.isReg() || !MO.isDef() || !MO.isTied()) - return false; - if (UseOpIdx) - *UseOpIdx = findTiedOperandIdx(DefOpIdx); - return true; - } - - /// Return true if the use operand of the specified index is tied to a def - /// operand. It also returns the def operand index by reference if DefOpIdx - /// is not null. - bool isRegTiedToDefOperand(unsigned UseOpIdx, - unsigned *DefOpIdx = nullptr) const { - const MachineOperand &MO = getOperand(UseOpIdx); - if (!MO.isReg() || !MO.isUse() || !MO.isTied()) - return false; - if (DefOpIdx) - *DefOpIdx = findTiedOperandIdx(UseOpIdx); - return true; - } - - /// Clears kill flags on all operands. - void clearKillInfo(); - - /// Replace all occurrences of FromReg with ToReg:SubIdx, - /// properly composing subreg indices where necessary. - void substituteRegister(Register FromReg, Register ToReg, unsigned SubIdx, - const TargetRegisterInfo &RegInfo); - - /// We have determined MI kills a register. Look for the - /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, - /// add a implicit operand if it's not found. Returns true if the operand - /// exists / is added. - bool addRegisterKilled(Register IncomingReg, - const TargetRegisterInfo *RegInfo, - bool AddIfNotFound = false); - - /// Clear all kill flags affecting Reg. If RegInfo is provided, this includes - /// all aliasing registers. - void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo); - - /// We have determined MI defined a register without a use. - /// Look for the operand that defines it and mark it as IsDead. If - /// AddIfNotFound is true, add a implicit operand if it's not found. Returns - /// true if the operand exists / is added. - bool addRegisterDead(Register Reg, const TargetRegisterInfo *RegInfo, - bool AddIfNotFound = false); - - /// Clear all dead flags on operands defining register @p Reg. - void clearRegisterDeads(Register Reg); - - /// Mark all subregister defs of register @p Reg with the undef flag. - /// This function is used when we determined to have a subregister def in an - /// otherwise undefined super register. - void setRegisterDefReadUndef(Register Reg, bool IsUndef = true); - - /// We have determined MI defines a register. Make sure there is an operand - /// defining Reg. - void addRegisterDefined(Register Reg, - const TargetRegisterInfo *RegInfo = nullptr); - - /// Mark every physreg used by this instruction as - /// dead except those in the UsedRegs list. - /// - /// On instructions with register mask operands, also add implicit-def - /// operands for all registers in UsedRegs. - void setPhysRegsDeadExcept(ArrayRef UsedRegs, - const TargetRegisterInfo &TRI); - - /// Return true if it is safe to move this instruction. If - /// SawStore is set to true, it means that there is a store (or call) between - /// the instruction's location and its intended destination. - bool isSafeToMove(AAResults *AA, bool &SawStore) const; - - /// Returns true if this instruction's memory access aliases the memory - /// access of Other. - // - /// Assumes any physical registers used to compute addresses - /// have the same value for both instructions. Returns false if neither - /// instruction writes to memory. - /// - /// @param AA Optional alias analysis, used to compare memory operands. - /// @param Other MachineInstr to check aliasing against. - /// @param UseTBAA Whether to pass TBAA information to alias analysis. - bool mayAlias(AAResults *AA, const MachineInstr &Other, bool UseTBAA) const; - - /// Return true if this instruction may have an ordered - /// or volatile memory reference, or if the information describing the memory - /// reference is not available. Return false if it is known to have no - /// ordered or volatile memory references. - bool hasOrderedMemoryRef() const; - - /// Return true if this load instruction never traps and points to a memory - /// location whose value doesn't change during the execution of this function. - /// - /// Examples include loading a value from the constant pool or from the - /// argument area of a function (if it does not change). If the instruction - /// does multiple loads, this returns true only if all of the loads are - /// dereferenceable and invariant. - bool isDereferenceableInvariantLoad(AAResults *AA) const; - - /// If the specified instruction is a PHI that always merges together the - /// same virtual register, return the register, otherwise return 0. - unsigned isConstantValuePHI() const; - - /// Return true if this instruction has side effects that are not modeled - /// by mayLoad / mayStore, etc. - /// For all instructions, the property is encoded in MCInstrDesc::Flags - /// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is - /// INLINEASM instruction, in which case the side effect property is encoded - /// in one of its operands (see InlineAsm::Extra_HasSideEffect). - /// - bool hasUnmodeledSideEffects() const; - - /// Returns true if it is illegal to fold a load across this instruction. - bool isLoadFoldBarrier() const; - - /// Return true if all the defs of this instruction are dead. - bool allDefsAreDead() const; - - /// Return a valid size if the instruction is a spill instruction. - Optional getSpillSize(const TargetInstrInfo *TII) const; - - /// Return a valid size if the instruction is a folded spill instruction. - Optional getFoldedSpillSize(const TargetInstrInfo *TII) const; - - /// Return a valid size if the instruction is a restore instruction. - Optional getRestoreSize(const TargetInstrInfo *TII) const; - - /// Return a valid size if the instruction is a folded restore instruction. - Optional - getFoldedRestoreSize(const TargetInstrInfo *TII) const; - - /// Copy implicit register operands from specified - /// instruction to this instruction. - void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI); - - /// Debugging support - /// @{ - /// Determine the generic type to be printed (if needed) on uses and defs. - LLT getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes, - const MachineRegisterInfo &MRI) const; - - /// Return true when an instruction has tied register that can't be determined - /// by the instruction's descriptor. This is useful for MIR printing, to - /// determine whether we need to print the ties or not. - bool hasComplexRegisterTies() const; - - /// Print this MI to \p OS. - /// Don't print information that can be inferred from other instructions if - /// \p IsStandalone is false. It is usually true when only a fragment of the - /// function is printed. - /// Only print the defs and the opcode if \p SkipOpers is true. - /// Otherwise, also print operands if \p SkipDebugLoc is true. - /// Otherwise, also print the debug loc, with a terminating newline. - /// \p TII is used to print the opcode name. If it's not present, but the - /// MI is in a function, the opcode will be printed using the function's TII. - void print(raw_ostream &OS, bool IsStandalone = true, bool SkipOpers = false, - bool SkipDebugLoc = false, bool AddNewLine = true, - const TargetInstrInfo *TII = nullptr) const; - void print(raw_ostream &OS, ModuleSlotTracker &MST, bool IsStandalone = true, - bool SkipOpers = false, bool SkipDebugLoc = false, - bool AddNewLine = true, - const TargetInstrInfo *TII = nullptr) const; - void dump() const; - /// Print on dbgs() the current instruction and the instructions defining its - /// operands and so on until we reach \p MaxDepth. - void dumpr(const MachineRegisterInfo &MRI, - unsigned MaxDepth = UINT_MAX) const; - /// @} - - //===--------------------------------------------------------------------===// - // Accessors used to build up machine instructions. - - /// Add the specified operand to the instruction. If it is an implicit - /// operand, it is added to the end of the operand list. If it is an - /// explicit operand it is added at the end of the explicit operand list - /// (before the first implicit operand). - /// - /// MF must be the machine function that was used to allocate this - /// instruction. - /// - /// MachineInstrBuilder provides a more convenient interface for creating - /// instructions and adding operands. - void addOperand(MachineFunction &MF, const MachineOperand &Op); - - /// Add an operand without providing an MF reference. This only works for - /// instructions that are inserted in a basic block. - /// - /// MachineInstrBuilder and the two-argument addOperand(MF, MO) should be - /// preferred. - void addOperand(const MachineOperand &Op); - - /// Replace the instruction descriptor (thus opcode) of - /// the current instruction with a new one. - void setDesc(const MCInstrDesc &TID) { MCID = &TID; } - - /// Replace current source information with new such. - /// Avoid using this, the constructor argument is preferable. - void setDebugLoc(DebugLoc DL) { - DbgLoc = std::move(DL); - assert(DbgLoc.hasTrivialDestructor() && "Expected trivial destructor"); - } - - /// Erase an operand from an instruction, leaving it with one - /// fewer operand than it started with. - void RemoveOperand(unsigned OpNo); - - /// Clear this MachineInstr's memory reference descriptor list. This resets - /// the memrefs to their most conservative state. This should be used only - /// as a last resort since it greatly pessimizes our knowledge of the memory - /// access performed by the instruction. - void dropMemRefs(MachineFunction &MF); - - /// Assign this MachineInstr's memory reference descriptor list. - /// - /// Unlike other methods, this *will* allocate them into a new array - /// associated with the provided `MachineFunction`. - void setMemRefs(MachineFunction &MF, ArrayRef MemRefs); - - /// Add a MachineMemOperand to the machine instruction. - /// This function should be used only occasionally. The setMemRefs function - /// is the primary method for setting up a MachineInstr's MemRefs list. - void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - - /// Clone another MachineInstr's memory reference descriptor list and replace - /// ours with it. - /// - /// Note that `*this` may be the incoming MI! - /// - /// Prefer this API whenever possible as it can avoid allocations in common - /// cases. - void cloneMemRefs(MachineFunction &MF, const MachineInstr &MI); - - /// Clone the merge of multiple MachineInstrs' memory reference descriptors - /// list and replace ours with it. - /// - /// Note that `*this` may be one of the incoming MIs! - /// - /// Prefer this API whenever possible as it can avoid allocations in common - /// cases. - void cloneMergedMemRefs(MachineFunction &MF, - ArrayRef MIs); - - /// Set a symbol that will be emitted just prior to the instruction itself. - /// - /// Setting this to a null pointer will remove any such symbol. - /// - /// FIXME: This is not fully implemented yet. - void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); - - /// Set a symbol that will be emitted just after the instruction itself. - /// - /// Setting this to a null pointer will remove any such symbol. - /// - /// FIXME: This is not fully implemented yet. - void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); - - /// Clone another MachineInstr's pre- and post- instruction symbols and - /// replace ours with it. - void cloneInstrSymbols(MachineFunction &MF, const MachineInstr &MI); - - /// Set a marker on instructions that denotes where we should create and emit - /// heap alloc site labels. This waits until after instruction selection and - /// optimizations to create the label, so it should still work if the - /// instruction is removed or duplicated. - void setHeapAllocMarker(MachineFunction &MF, MDNode *MD); - - /// Return the MIFlags which represent both MachineInstrs. This - /// should be used when merging two MachineInstrs into one. This routine does - /// not modify the MIFlags of this MachineInstr. - uint16_t mergeFlagsWith(const MachineInstr& Other) const; - - static uint16_t copyFlagsFromInstruction(const Instruction &I); - - /// Copy all flags to MachineInst MIFlags - void copyIRFlags(const Instruction &I); - - /// Break any tie involving OpIdx. - void untieRegOperand(unsigned OpIdx) { - MachineOperand &MO = getOperand(OpIdx); - if (MO.isReg() && MO.isTied()) { - getOperand(findTiedOperandIdx(OpIdx)).TiedTo = 0; - MO.TiedTo = 0; - } - } - - /// Add all implicit def and use operands to this instruction. - void addImplicitDefUseOperands(MachineFunction &MF); - - /// Scan instructions immediately following MI and collect any matching - /// DBG_VALUEs. - void collectDebugValues(SmallVectorImpl &DbgValues); - - /// Find all DBG_VALUEs that point to the register def in this instruction - /// and point them to \p Reg instead. - void changeDebugValuesDefReg(Register Reg); - - /// Returns the Intrinsic::ID for this instruction. - /// \pre Must have an intrinsic ID operand. - unsigned getIntrinsicID() const { - return getOperand(getNumExplicitDefs()).getIntrinsicID(); - } - - /// Sets all register debug operands in this debug value instruction to be - /// undef. - void setDebugValueUndef() { - assert(isDebugValue() && "Must be a debug value instruction."); - for (MachineOperand &MO : debug_operands()) { - if (MO.isReg()) { - MO.setReg(0); - MO.setSubReg(0); - } - } - } - -private: - /// If this instruction is embedded into a MachineFunction, return the - /// MachineRegisterInfo object for the current function, otherwise - /// return null. - MachineRegisterInfo *getRegInfo(); - - /// Unlink all of the register operands in this instruction from their - /// respective use lists. This requires that the operands already be on their - /// use lists. - void RemoveRegOperandsFromUseLists(MachineRegisterInfo&); - - /// Add all of the register operands in this instruction from their - /// respective use lists. This requires that the operands not be on their - /// use lists yet. - void AddRegOperandsToUseLists(MachineRegisterInfo&); - - /// Slow path for hasProperty when we're dealing with a bundle. - bool hasPropertyInBundle(uint64_t Mask, QueryType Type) const; - - /// Implements the logic of getRegClassConstraintEffectForVReg for the - /// this MI and the given operand index \p OpIdx. - /// If the related operand does not constrained Reg, this returns CurRC. - const TargetRegisterClass *getRegClassConstraintEffectForVRegImpl( - unsigned OpIdx, Register Reg, const TargetRegisterClass *CurRC, - const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; - - /// Stores extra instruction information inline or allocates as ExtraInfo - /// based on the number of pointers. - void setExtraInfo(MachineFunction &MF, ArrayRef MMOs, - MCSymbol *PreInstrSymbol, MCSymbol *PostInstrSymbol, - MDNode *HeapAllocMarker); -}; - -/// Special DenseMapInfo traits to compare MachineInstr* by *value* of the -/// instruction rather than by pointer value. -/// The hashing and equality testing functions ignore definitions so this is -/// useful for CSE, etc. -struct MachineInstrExpressionTrait : DenseMapInfo { - static inline MachineInstr *getEmptyKey() { - return nullptr; - } - - static inline MachineInstr *getTombstoneKey() { - return reinterpret_cast(-1); - } - - static unsigned getHashValue(const MachineInstr* const &MI); - - static bool isEqual(const MachineInstr* const &LHS, - const MachineInstr* const &RHS) { - if (RHS == getEmptyKey() || RHS == getTombstoneKey() || - LHS == getEmptyKey() || LHS == getTombstoneKey()) - return LHS == RHS; - return LHS->isIdenticalTo(*RHS, MachineInstr::IgnoreVRegDefs); - } -}; - -//===----------------------------------------------------------------------===// -// Debugging Support - -inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) { - MI.print(OS); - return OS; -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEINSTR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBuilder.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBuilder.h deleted file mode 100644 index 80f30231ae..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBuilder.h +++ /dev/null @@ -1,624 +0,0 @@ -//===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file exposes a function named BuildMI, which is useful for dramatically -// simplifying how MachineInstr's are created. It allows use of code like this: -// -// M = BuildMI(MBB, MI, DL, TII.get(X86::ADD8rr), Dst) -// .addReg(argVal1) -// .addReg(argVal2); -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H -#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include - -namespace llvm { - -class MCInstrDesc; -class MDNode; - -namespace RegState { - -enum { - /// Register definition. - Define = 0x2, - /// Not emitted register (e.g. carry, or temporary result). - Implicit = 0x4, - /// The last use of a register. - Kill = 0x8, - /// Unused definition. - Dead = 0x10, - /// Value of the register doesn't matter. - Undef = 0x20, - /// Register definition happens before uses. - EarlyClobber = 0x40, - /// Register 'use' is for debugging purpose. - Debug = 0x80, - /// Register reads a value that is defined inside the same instruction or - /// bundle. - InternalRead = 0x100, - /// Register that may be renamed. - Renamable = 0x200, - DefineNoRead = Define | Undef, - ImplicitDefine = Implicit | Define, - ImplicitKill = Implicit | Kill -}; - -} // end namespace RegState - -class MachineInstrBuilder { - MachineFunction *MF = nullptr; - MachineInstr *MI = nullptr; - -public: - MachineInstrBuilder() = default; - - /// Create a MachineInstrBuilder for manipulating an existing instruction. - /// F must be the machine function that was used to allocate I. - MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} - MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I) - : MF(&F), MI(&*I) {} - - /// Allow automatic conversion to the machine instruction we are working on. - operator MachineInstr*() const { return MI; } - MachineInstr *operator->() const { return MI; } - operator MachineBasicBlock::iterator() const { return MI; } - - /// If conversion operators fail, use this method to get the MachineInstr - /// explicitly. - MachineInstr *getInstr() const { return MI; } - - /// Get the register for the operand index. - /// The operand at the index should be a register (asserted by - /// MachineOperand). - Register getReg(unsigned Idx) const { return MI->getOperand(Idx).getReg(); } - - /// Add a new virtual register operand. - const MachineInstrBuilder &addReg(Register RegNo, unsigned flags = 0, - unsigned SubReg = 0) const { - assert((flags & 0x1) == 0 && - "Passing in 'true' to addReg is forbidden! Use enums instead."); - MI->addOperand(*MF, MachineOperand::CreateReg(RegNo, - flags & RegState::Define, - flags & RegState::Implicit, - flags & RegState::Kill, - flags & RegState::Dead, - flags & RegState::Undef, - flags & RegState::EarlyClobber, - SubReg, - flags & RegState::Debug, - flags & RegState::InternalRead, - flags & RegState::Renamable)); - return *this; - } - - /// Add a virtual register definition operand. - const MachineInstrBuilder &addDef(Register RegNo, unsigned Flags = 0, - unsigned SubReg = 0) const { - return addReg(RegNo, Flags | RegState::Define, SubReg); - } - - /// Add a virtual register use operand. It is an error for Flags to contain - /// `RegState::Define` when calling this function. - const MachineInstrBuilder &addUse(Register RegNo, unsigned Flags = 0, - unsigned SubReg = 0) const { - assert(!(Flags & RegState::Define) && - "Misleading addUse defines register, use addReg instead."); - return addReg(RegNo, Flags, SubReg); - } - - /// Add a new immediate operand. - const MachineInstrBuilder &addImm(int64_t Val) const { - MI->addOperand(*MF, MachineOperand::CreateImm(Val)); - return *this; - } - - const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { - MI->addOperand(*MF, MachineOperand::CreateCImm(Val)); - return *this; - } - - const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { - MI->addOperand(*MF, MachineOperand::CreateFPImm(Val)); - return *this; - } - - const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addFrameIndex(int Idx) const { - MI->addOperand(*MF, MachineOperand::CreateFI(Idx)); - return *this; - } - - const MachineInstrBuilder & - addConstantPoolIndex(unsigned Idx, int Offset = 0, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset, - TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, - int64_t Offset = 0, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addExternalSymbol(const char *FnName, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA, - int64_t Offset = 0, - unsigned TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateBA(BA, Offset, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { - MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask)); - return *this; - } - - const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { - MI->addMemOperand(*MF, MMO); - return *this; - } - - const MachineInstrBuilder & - setMemRefs(ArrayRef MMOs) const { - MI->setMemRefs(*MF, MMOs); - return *this; - } - - const MachineInstrBuilder &cloneMemRefs(const MachineInstr &OtherMI) const { - MI->cloneMemRefs(*MF, OtherMI); - return *this; - } - - const MachineInstrBuilder & - cloneMergedMemRefs(ArrayRef OtherMIs) const { - MI->cloneMergedMemRefs(*MF, OtherMIs); - return *this; - } - - const MachineInstrBuilder &add(const MachineOperand &MO) const { - MI->addOperand(*MF, MO); - return *this; - } - - const MachineInstrBuilder &add(ArrayRef MOs) const { - for (const MachineOperand &MO : MOs) { - MI->addOperand(*MF, MO); - } - return *this; - } - - const MachineInstrBuilder &addMetadata(const MDNode *MD) const { - MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); - assert((MI->isDebugValue() ? static_cast(MI->getDebugVariable()) - : true) && - "first MDNode argument of a DBG_VALUE not a variable"); - assert((MI->isDebugLabel() ? static_cast(MI->getDebugLabel()) - : true) && - "first MDNode argument of a DBG_LABEL not a label"); - return *this; - } - - const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { - MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); - return *this; - } - - const MachineInstrBuilder &addIntrinsicID(Intrinsic::ID ID) const { - MI->addOperand(*MF, MachineOperand::CreateIntrinsicID(ID)); - return *this; - } - - const MachineInstrBuilder &addPredicate(CmpInst::Predicate Pred) const { - MI->addOperand(*MF, MachineOperand::CreatePredicate(Pred)); - return *this; - } - - const MachineInstrBuilder &addShuffleMask(ArrayRef Val) const { - MI->addOperand(*MF, MachineOperand::CreateShuffleMask(Val)); - return *this; - } - - const MachineInstrBuilder &addSym(MCSymbol *Sym, - unsigned char TargetFlags = 0) const { - MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); - return *this; - } - - const MachineInstrBuilder &setMIFlags(unsigned Flags) const { - MI->setFlags(Flags); - return *this; - } - - const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { - MI->setFlag(Flag); - return *this; - } - - // Add a displacement from an existing MachineOperand with an added offset. - const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off, - unsigned char TargetFlags = 0) const { - // If caller specifies new TargetFlags then use it, otherwise the - // default behavior is to copy the target flags from the existing - // MachineOperand. This means if the caller wants to clear the - // target flags it needs to do so explicitly. - if (0 == TargetFlags) - TargetFlags = Disp.getTargetFlags(); - - switch (Disp.getType()) { - default: - llvm_unreachable("Unhandled operand type in addDisp()"); - case MachineOperand::MO_Immediate: - return addImm(Disp.getImm() + off); - case MachineOperand::MO_ConstantPoolIndex: - return addConstantPoolIndex(Disp.getIndex(), Disp.getOffset() + off, - TargetFlags); - case MachineOperand::MO_GlobalAddress: - return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, - TargetFlags); - case MachineOperand::MO_BlockAddress: - return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off, - TargetFlags); - case MachineOperand::MO_JumpTableIndex: - assert(off == 0 && "cannot create offset into jump tables"); - return addJumpTableIndex(Disp.getIndex(), TargetFlags); - } - } - - /// Copy all the implicit operands from OtherMI onto this one. - const MachineInstrBuilder & - copyImplicitOps(const MachineInstr &OtherMI) const { - MI->copyImplicitOps(*MF, OtherMI); - return *this; - } - - bool constrainAllUses(const TargetInstrInfo &TII, - const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI) const { - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); - } -}; - -/// Builder interface. Specify how to create the initial instruction itself. -inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID) { - return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)); -} - -/// This version of the builder sets up the first operand as a -/// destination virtual register. -inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, Register DestReg) { - return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)) - .addReg(DestReg, RegState::Define); -} - -/// This version of the builder inserts the newly-built instruction before -/// the given position in the given MachineBasicBlock, and sets up the first -/// operand as a destination virtual register. -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, const MCInstrDesc &MCID, - Register DestReg) { - MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); - BB.insert(I, MI); - return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); -} - -/// This version of the builder inserts the newly-built instruction before -/// the given position in the given MachineBasicBlock, and sets up the first -/// operand as a destination virtual register. -/// -/// If \c I is inside a bundle, then the newly inserted \a MachineInstr is -/// added to the same bundle. -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::instr_iterator I, - const DebugLoc &DL, const MCInstrDesc &MCID, - Register DestReg) { - MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); - BB.insert(I, MI); - return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); -} - -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I, - const DebugLoc &DL, const MCInstrDesc &MCID, - Register DestReg) { - // Calling the overload for instr_iterator is always correct. However, the - // definition is not available in headers, so inline the check. - if (I.isInsideBundle()) - return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID, DestReg); - return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID, DestReg); -} - -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I, - const DebugLoc &DL, const MCInstrDesc &MCID, - Register DestReg) { - return BuildMI(BB, *I, DL, MCID, DestReg); -} - -/// This version of the builder inserts the newly-built instruction before the -/// given position in the given MachineBasicBlock, and does NOT take a -/// destination register. -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, - const MCInstrDesc &MCID) { - MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); - BB.insert(I, MI); - return MachineInstrBuilder(MF, MI); -} - -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::instr_iterator I, - const DebugLoc &DL, - const MCInstrDesc &MCID) { - MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); - BB.insert(I, MI); - return MachineInstrBuilder(MF, MI); -} - -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I, - const DebugLoc &DL, - const MCInstrDesc &MCID) { - // Calling the overload for instr_iterator is always correct. However, the - // definition is not available in headers, so inline the check. - if (I.isInsideBundle()) - return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID); - return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID); -} - -inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I, - const DebugLoc &DL, - const MCInstrDesc &MCID) { - return BuildMI(BB, *I, DL, MCID); -} - -/// This version of the builder inserts the newly-built instruction at the end -/// of the given MachineBasicBlock, and does NOT take a destination register. -inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL, - const MCInstrDesc &MCID) { - return BuildMI(*BB, BB->end(), DL, MCID); -} - -/// This version of the builder inserts the newly-built instruction at the -/// end of the given MachineBasicBlock, and sets up the first operand as a -/// destination virtual register. -inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL, - const MCInstrDesc &MCID, Register DestReg) { - return BuildMI(*BB, BB->end(), DL, MCID, DestReg); -} - -/// This version of the builder builds a DBG_VALUE intrinsic -/// for either a value in a register or a register-indirect -/// address. The convention is that a DBG_VALUE is indirect iff the -/// second operand is an immediate. -MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - Register Reg, const MDNode *Variable, - const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE intrinsic -/// for a MachineOperand. -MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - const MachineOperand &MO, const MDNode *Variable, - const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE or DBG_VALUE_LIST intrinsic -/// for a MachineOperand. -MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - ArrayRef MOs, - const MDNode *Variable, const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE intrinsic -/// for either a value in a register or a register-indirect -/// address and inserts it at position I. -MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - Register Reg, const MDNode *Variable, - const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE intrinsic -/// for a machine operand and inserts it at position I. -MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - MachineOperand &MO, const MDNode *Variable, - const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE or DBG_VALUE_LIST intrinsic -/// for a machine operand and inserts it at position I. -MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - ArrayRef MOs, - const MDNode *Variable, const MDNode *Expr); - -/// Clone a DBG_VALUE whose value has been spilled to FrameIndex. -MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - const MachineInstr &Orig, int FrameIndex, - Register SpillReg); -MachineInstr * -buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I, - const MachineInstr &Orig, int FrameIndex, - SmallVectorImpl &SpilledOperands); - -/// Update a DBG_VALUE whose value has been spilled to FrameIndex. Useful when -/// modifying an instruction in place while iterating over a basic block. -void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex, Register Reg); - -inline unsigned getDefRegState(bool B) { - return B ? RegState::Define : 0; -} -inline unsigned getImplRegState(bool B) { - return B ? RegState::Implicit : 0; -} -inline unsigned getKillRegState(bool B) { - return B ? RegState::Kill : 0; -} -inline unsigned getDeadRegState(bool B) { - return B ? RegState::Dead : 0; -} -inline unsigned getUndefRegState(bool B) { - return B ? RegState::Undef : 0; -} -inline unsigned getInternalReadRegState(bool B) { - return B ? RegState::InternalRead : 0; -} -inline unsigned getDebugRegState(bool B) { - return B ? RegState::Debug : 0; -} -inline unsigned getRenamableRegState(bool B) { - return B ? RegState::Renamable : 0; -} - -/// Get all register state flags from machine operand \p RegOp. -inline unsigned getRegState(const MachineOperand &RegOp) { - assert(RegOp.isReg() && "Not a register operand"); - return getDefRegState(RegOp.isDef()) | getImplRegState(RegOp.isImplicit()) | - getKillRegState(RegOp.isKill()) | getDeadRegState(RegOp.isDead()) | - getUndefRegState(RegOp.isUndef()) | - getInternalReadRegState(RegOp.isInternalRead()) | - getDebugRegState(RegOp.isDebug()) | - getRenamableRegState(Register::isPhysicalRegister(RegOp.getReg()) && - RegOp.isRenamable()); -} - -/// Helper class for constructing bundles of MachineInstrs. -/// -/// MIBundleBuilder can create a bundle from scratch by inserting new -/// MachineInstrs one at a time, or it can create a bundle from a sequence of -/// existing MachineInstrs in a basic block. -class MIBundleBuilder { - MachineBasicBlock &MBB; - MachineBasicBlock::instr_iterator Begin; - MachineBasicBlock::instr_iterator End; - -public: - /// Create an MIBundleBuilder that inserts instructions into a new bundle in - /// BB above the bundle or instruction at Pos. - MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator Pos) - : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {} - - /// Create a bundle from the sequence of instructions between B and E. - MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator B, - MachineBasicBlock::iterator E) - : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) { - assert(B != E && "No instructions to bundle"); - ++B; - while (B != E) { - MachineInstr &MI = *B; - ++B; - MI.bundleWithPred(); - } - } - - /// Create an MIBundleBuilder representing an existing instruction or bundle - /// that has MI as its head. - explicit MIBundleBuilder(MachineInstr *MI) - : MBB(*MI->getParent()), Begin(MI), - End(getBundleEnd(MI->getIterator())) {} - - /// Return a reference to the basic block containing this bundle. - MachineBasicBlock &getMBB() const { return MBB; } - - /// Return true if no instructions have been inserted in this bundle yet. - /// Empty bundles aren't representable in a MachineBasicBlock. - bool empty() const { return Begin == End; } - - /// Return an iterator to the first bundled instruction. - MachineBasicBlock::instr_iterator begin() const { return Begin; } - - /// Return an iterator beyond the last bundled instruction. - MachineBasicBlock::instr_iterator end() const { return End; } - - /// Insert MI into this bundle before I which must point to an instruction in - /// the bundle, or end(). - MIBundleBuilder &insert(MachineBasicBlock::instr_iterator I, - MachineInstr *MI) { - MBB.insert(I, MI); - if (I == Begin) { - if (!empty()) - MI->bundleWithSucc(); - Begin = MI->getIterator(); - return *this; - } - if (I == End) { - MI->bundleWithPred(); - return *this; - } - // MI was inserted in the middle of the bundle, so its neighbors' flags are - // already fine. Update MI's bundle flags manually. - MI->setFlag(MachineInstr::BundledPred); - MI->setFlag(MachineInstr::BundledSucc); - return *this; - } - - /// Insert MI into MBB by prepending it to the instructions in the bundle. - /// MI will become the first instruction in the bundle. - MIBundleBuilder &prepend(MachineInstr *MI) { - return insert(begin(), MI); - } - - /// Insert MI into MBB by appending it to the instructions in the bundle. - /// MI will become the last instruction in the bundle. - MIBundleBuilder &append(MachineInstr *MI) { - return insert(end(), MI); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEINSTRBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundle.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundle.h deleted file mode 100644 index 8a73f9a18f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundle.h +++ /dev/null @@ -1,289 +0,0 @@ -//===- llvm/CodeGen/MachineInstrBundle.h - MI bundle utilities --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provide utility functions to manipulate machine instruction -// bundles. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLE_H -#define LLVM_CODEGEN_MACHINEINSTRBUNDLE_H - -#include "llvm/CodeGen/MachineBasicBlock.h" - -namespace llvm { - -/// finalizeBundle - Finalize a machine instruction bundle which includes -/// a sequence of instructions starting from FirstMI to LastMI (exclusive). -/// This routine adds a BUNDLE instruction to represent the bundle, it adds -/// IsInternalRead markers to MachineOperands which are defined inside the -/// bundle, and it copies externally visible defs and uses to the BUNDLE -/// instruction. -void finalizeBundle(MachineBasicBlock &MBB, - MachineBasicBlock::instr_iterator FirstMI, - MachineBasicBlock::instr_iterator LastMI); - -/// finalizeBundle - Same functionality as the previous finalizeBundle except -/// the last instruction in the bundle is not provided as an input. This is -/// used in cases where bundles are pre-determined by marking instructions -/// with 'InsideBundle' marker. It returns the MBB instruction iterator that -/// points to the end of the bundle. -MachineBasicBlock::instr_iterator finalizeBundle(MachineBasicBlock &MBB, - MachineBasicBlock::instr_iterator FirstMI); - -/// finalizeBundles - Finalize instruction bundles in the specified -/// MachineFunction. Return true if any bundles are finalized. -bool finalizeBundles(MachineFunction &MF); - -/// Returns an iterator to the first instruction in the bundle containing \p I. -inline MachineBasicBlock::instr_iterator getBundleStart( - MachineBasicBlock::instr_iterator I) { - while (I->isBundledWithPred()) - --I; - return I; -} - -/// Returns an iterator to the first instruction in the bundle containing \p I. -inline MachineBasicBlock::const_instr_iterator getBundleStart( - MachineBasicBlock::const_instr_iterator I) { - while (I->isBundledWithPred()) - --I; - return I; -} - -/// Returns an iterator pointing beyond the bundle containing \p I. -inline MachineBasicBlock::instr_iterator getBundleEnd( - MachineBasicBlock::instr_iterator I) { - while (I->isBundledWithSucc()) - ++I; - ++I; - return I; -} - -/// Returns an iterator pointing beyond the bundle containing \p I. -inline MachineBasicBlock::const_instr_iterator getBundleEnd( - MachineBasicBlock::const_instr_iterator I) { - while (I->isBundledWithSucc()) - ++I; - ++I; - return I; -} - -//===----------------------------------------------------------------------===// -// MachineBundleOperand iterator -// - -/// MIBundleOperandIteratorBase - Iterator that visits all operands in a bundle -/// of MachineInstrs. This class is not intended to be used directly, use one -/// of the sub-classes instead. -/// -/// Intended use: -/// -/// for (MIBundleOperands MIO(MI); MIO.isValid(); ++MIO) { -/// if (!MIO->isReg()) -/// continue; -/// ... -/// } -/// -template -class MIBundleOperandIteratorBase - : public iterator_facade_base, - std::forward_iterator_tag, ValueT> { - MachineBasicBlock::instr_iterator InstrI, InstrE; - MachineInstr::mop_iterator OpI, OpE; - - // If the operands on InstrI are exhausted, advance InstrI to the next - // bundled instruction with operands. - void advance() { - while (OpI == OpE) { - // Don't advance off the basic block, or into a new bundle. - if (++InstrI == InstrE || !InstrI->isInsideBundle()) { - InstrI = InstrE; - break; - } - OpI = InstrI->operands_begin(); - OpE = InstrI->operands_end(); - } - } - -protected: - /// MIBundleOperandIteratorBase - Create an iterator that visits all operands - /// on MI, or all operands on every instruction in the bundle containing MI. - /// - /// @param MI The instruction to examine. - /// - explicit MIBundleOperandIteratorBase(MachineInstr &MI) { - InstrI = getBundleStart(MI.getIterator()); - InstrE = MI.getParent()->instr_end(); - OpI = InstrI->operands_begin(); - OpE = InstrI->operands_end(); - advance(); - } - - /// Constructor for an iterator past the last iteration: both instruction - /// iterators point to the end of the BB and OpI == OpE. - explicit MIBundleOperandIteratorBase(MachineBasicBlock::instr_iterator InstrE, - MachineInstr::mop_iterator OpE) - : InstrI(InstrE), InstrE(InstrE), OpI(OpE), OpE(OpE) {} - -public: - /// isValid - Returns true until all the operands have been visited. - bool isValid() const { return OpI != OpE; } - - /// Preincrement. Move to the next operand. - void operator++() { - assert(isValid() && "Cannot advance MIOperands beyond the last operand"); - ++OpI; - advance(); - } - - ValueT &operator*() const { return *OpI; } - ValueT *operator->() const { return &*OpI; } - - bool operator==(const MIBundleOperandIteratorBase &Arg) const { - // Iterators are equal, if InstrI matches and either OpIs match or OpI == - // OpE match for both. The second condition allows us to construct an 'end' - // iterator, without finding the last instruction in a bundle up-front. - return InstrI == Arg.InstrI && - (OpI == Arg.OpI || (OpI == OpE && Arg.OpI == Arg.OpE)); - } - /// getOperandNo - Returns the number of the current operand relative to its - /// instruction. - /// - unsigned getOperandNo() const { - return OpI - InstrI->operands_begin(); - } -}; - -/// MIBundleOperands - Iterate over all operands in a bundle of machine -/// instructions. -/// -class MIBundleOperands : public MIBundleOperandIteratorBase { - /// Constructor for an iterator past the last iteration. - MIBundleOperands(MachineBasicBlock::instr_iterator InstrE, - MachineInstr::mop_iterator OpE) - : MIBundleOperandIteratorBase(InstrE, OpE) {} - -public: - MIBundleOperands(MachineInstr &MI) : MIBundleOperandIteratorBase(MI) {} - - /// Returns an iterator past the last iteration. - static MIBundleOperands end(const MachineBasicBlock &MBB) { - return {const_cast(MBB).instr_end(), - const_cast(MBB).instr_begin()->operands_end()}; - } -}; - -/// ConstMIBundleOperands - Iterate over all operands in a const bundle of -/// machine instructions. -/// -class ConstMIBundleOperands - : public MIBundleOperandIteratorBase { - - /// Constructor for an iterator past the last iteration. - ConstMIBundleOperands(MachineBasicBlock::instr_iterator InstrE, - MachineInstr::mop_iterator OpE) - : MIBundleOperandIteratorBase(InstrE, OpE) {} - -public: - ConstMIBundleOperands(const MachineInstr &MI) - : MIBundleOperandIteratorBase(const_cast(MI)) {} - - /// Returns an iterator past the last iteration. - static ConstMIBundleOperands end(const MachineBasicBlock &MBB) { - return {const_cast(MBB).instr_end(), - const_cast(MBB).instr_begin()->operands_end()}; - } -}; - -inline iterator_range -const_mi_bundle_ops(const MachineInstr &MI) { - return make_range(ConstMIBundleOperands(MI), - ConstMIBundleOperands::end(*MI.getParent())); -} - -inline iterator_range mi_bundle_ops(MachineInstr &MI) { - return make_range(MIBundleOperands(MI), - MIBundleOperands::end(*MI.getParent())); -} - -/// VirtRegInfo - Information about a virtual register used by a set of -/// operands. -/// -struct VirtRegInfo { - /// Reads - One of the operands read the virtual register. This does not - /// include undef or internal use operands, see MO::readsReg(). - bool Reads; - - /// Writes - One of the operands writes the virtual register. - bool Writes; - - /// Tied - Uses and defs must use the same register. This can be because of - /// a two-address constraint, or there may be a partial redefinition of a - /// sub-register. - bool Tied; -}; - -/// AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses -/// a virtual register. This function should not be called after operator++(), -/// it expects a fresh iterator. -/// -/// @param Reg The virtual register to analyze. -/// @param Ops When set, this vector will receive an (MI, OpNum) entry for -/// each operand referring to Reg. -/// @returns A filled-in RegInfo struct. -VirtRegInfo AnalyzeVirtRegInBundle( - MachineInstr &MI, Register Reg, - SmallVectorImpl> *Ops = nullptr); - -/// Information about how a physical register Reg is used by a set of -/// operands. -struct PhysRegInfo { - /// There is a regmask operand indicating Reg is clobbered. - /// \see MachineOperand::CreateRegMask(). - bool Clobbered; - - /// Reg or one of its aliases is defined. The definition may only cover - /// parts of the register. - bool Defined; - /// Reg or a super-register is defined. The definition covers the full - /// register. - bool FullyDefined; - - /// Reg or one of its aliases is read. The register may only be read - /// partially. - bool Read; - /// Reg or a super-register is read. The full register is read. - bool FullyRead; - - /// Either: - /// - Reg is FullyDefined and all defs of reg or an overlapping - /// register are dead, or - /// - Reg is completely dead because "defined" by a clobber. - bool DeadDef; - - /// Reg is Defined and all defs of reg or an overlapping register are - /// dead. - bool PartialDeadDef; - - /// There is a use operand of reg or a super-register with kill flag set. - bool Killed; -}; - -/// AnalyzePhysRegInBundle - Analyze how the current instruction or bundle uses -/// a physical register. This function should not be called after operator++(), -/// it expects a fresh iterator. -/// -/// @param Reg The physical register to analyze. -/// @returns A filled-in PhysRegInfo struct. -PhysRegInfo AnalyzePhysRegInBundle(const MachineInstr &MI, Register Reg, - const TargetRegisterInfo *TRI); - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundleIterator.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundleIterator.h deleted file mode 100644 index 250cb0d78a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineInstrBundleIterator.h +++ /dev/null @@ -1,288 +0,0 @@ -//===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines an iterator class that bundles MachineInstr. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H -#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H - -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/simple_ilist.h" -#include -#include -#include - -namespace llvm { - -template struct MachineInstrBundleIteratorTraits; -template struct MachineInstrBundleIteratorTraits { - using list_type = simple_ilist>; - using instr_iterator = typename list_type::iterator; - using nonconst_instr_iterator = typename list_type::iterator; - using const_instr_iterator = typename list_type::const_iterator; -}; -template struct MachineInstrBundleIteratorTraits { - using list_type = simple_ilist>; - using instr_iterator = typename list_type::reverse_iterator; - using nonconst_instr_iterator = typename list_type::reverse_iterator; - using const_instr_iterator = typename list_type::const_reverse_iterator; -}; -template struct MachineInstrBundleIteratorTraits { - using list_type = simple_ilist>; - using instr_iterator = typename list_type::const_iterator; - using nonconst_instr_iterator = typename list_type::iterator; - using const_instr_iterator = typename list_type::const_iterator; -}; -template struct MachineInstrBundleIteratorTraits { - using list_type = simple_ilist>; - using instr_iterator = typename list_type::const_reverse_iterator; - using nonconst_instr_iterator = typename list_type::reverse_iterator; - using const_instr_iterator = typename list_type::const_reverse_iterator; -}; - -template struct MachineInstrBundleIteratorHelper; -template <> struct MachineInstrBundleIteratorHelper { - /// Get the beginning of the current bundle. - template static Iterator getBundleBegin(Iterator I) { - if (!I.isEnd()) - while (I->isBundledWithPred()) - --I; - return I; - } - - /// Get the final node of the current bundle. - template static Iterator getBundleFinal(Iterator I) { - if (!I.isEnd()) - while (I->isBundledWithSucc()) - ++I; - return I; - } - - /// Increment forward ilist iterator. - template static void increment(Iterator &I) { - I = std::next(getBundleFinal(I)); - } - - /// Decrement forward ilist iterator. - template static void decrement(Iterator &I) { - I = getBundleBegin(std::prev(I)); - } -}; - -template <> struct MachineInstrBundleIteratorHelper { - /// Get the beginning of the current bundle. - template static Iterator getBundleBegin(Iterator I) { - return MachineInstrBundleIteratorHelper::getBundleBegin( - I.getReverse()) - .getReverse(); - } - - /// Get the final node of the current bundle. - template static Iterator getBundleFinal(Iterator I) { - return MachineInstrBundleIteratorHelper::getBundleFinal( - I.getReverse()) - .getReverse(); - } - - /// Increment reverse ilist iterator. - template static void increment(Iterator &I) { - I = getBundleBegin(std::next(I)); - } - - /// Decrement reverse ilist iterator. - template static void decrement(Iterator &I) { - I = std::prev(getBundleFinal(I)); - } -}; - -/// MachineBasicBlock iterator that automatically skips over MIs that are -/// inside bundles (i.e. walk top level MIs only). -template -class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper { - using Traits = MachineInstrBundleIteratorTraits; - using instr_iterator = typename Traits::instr_iterator; - - instr_iterator MII; - -public: - using value_type = typename instr_iterator::value_type; - using difference_type = typename instr_iterator::difference_type; - using pointer = typename instr_iterator::pointer; - using reference = typename instr_iterator::reference; - using const_pointer = typename instr_iterator::const_pointer; - using const_reference = typename instr_iterator::const_reference; - using iterator_category = std::bidirectional_iterator_tag; - -private: - using nonconst_instr_iterator = typename Traits::nonconst_instr_iterator; - using const_instr_iterator = typename Traits::const_instr_iterator; - using nonconst_iterator = - MachineInstrBundleIterator; - using reverse_iterator = MachineInstrBundleIterator; - -public: - MachineInstrBundleIterator(instr_iterator MI) : MII(MI) { - assert((!MI.getNodePtr() || MI.isEnd() || !MI->isBundledWithPred()) && - "It's not legal to initialize MachineInstrBundleIterator with a " - "bundled MI"); - } - - MachineInstrBundleIterator(reference MI) : MII(MI) { - assert(!MI.isBundledWithPred() && "It's not legal to initialize " - "MachineInstrBundleIterator with a " - "bundled MI"); - } - - MachineInstrBundleIterator(pointer MI) : MII(MI) { - // FIXME: This conversion should be explicit. - assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize " - "MachineInstrBundleIterator " - "with a bundled MI"); - } - - // Template allows conversion from const to nonconst. - template - MachineInstrBundleIterator( - const MachineInstrBundleIterator &I, - std::enable_if_t::value, void *> = - nullptr) - : MII(I.getInstrIterator()) {} - - MachineInstrBundleIterator() : MII(nullptr) {} - - /// Explicit conversion between forward/reverse iterators. - /// - /// Translate between forward and reverse iterators without changing range - /// boundaries. The resulting iterator will dereference (and have a handle) - /// to the previous node, which is somewhat unexpected; but converting the - /// two endpoints in a range will give the same range in reverse. - /// - /// This matches std::reverse_iterator conversions. - explicit MachineInstrBundleIterator( - const MachineInstrBundleIterator &I) - : MachineInstrBundleIterator(++I.getReverse()) {} - - /// Get the bundle iterator for the given instruction's bundle. - static MachineInstrBundleIterator getAtBundleBegin(instr_iterator MI) { - return MachineInstrBundleIteratorHelper::getBundleBegin(MI); - } - - reference operator*() const { return *MII; } - pointer operator->() const { return &operator*(); } - - /// Check for null. - bool isValid() const { return MII.getNodePtr(); } - - friend bool operator==(const MachineInstrBundleIterator &L, - const MachineInstrBundleIterator &R) { - return L.MII == R.MII; - } - friend bool operator==(const MachineInstrBundleIterator &L, - const const_instr_iterator &R) { - return L.MII == R; // Avoid assertion about validity of R. - } - friend bool operator==(const const_instr_iterator &L, - const MachineInstrBundleIterator &R) { - return L == R.MII; // Avoid assertion about validity of L. - } - friend bool operator==(const MachineInstrBundleIterator &L, - const nonconst_instr_iterator &R) { - return L.MII == R; // Avoid assertion about validity of R. - } - friend bool operator==(const nonconst_instr_iterator &L, - const MachineInstrBundleIterator &R) { - return L == R.MII; // Avoid assertion about validity of L. - } - friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) { - return L == const_instr_iterator(R); // Avoid assertion about validity of R. - } - friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) { - return const_instr_iterator(L) == R; // Avoid assertion about validity of L. - } - friend bool operator==(const MachineInstrBundleIterator &L, - const_reference R) { - return L == &R; // Avoid assertion about validity of R. - } - friend bool operator==(const_reference L, - const MachineInstrBundleIterator &R) { - return &L == R; // Avoid assertion about validity of L. - } - - friend bool operator!=(const MachineInstrBundleIterator &L, - const MachineInstrBundleIterator &R) { - return !(L == R); - } - friend bool operator!=(const MachineInstrBundleIterator &L, - const const_instr_iterator &R) { - return !(L == R); - } - friend bool operator!=(const const_instr_iterator &L, - const MachineInstrBundleIterator &R) { - return !(L == R); - } - friend bool operator!=(const MachineInstrBundleIterator &L, - const nonconst_instr_iterator &R) { - return !(L == R); - } - friend bool operator!=(const nonconst_instr_iterator &L, - const MachineInstrBundleIterator &R) { - return !(L == R); - } - friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) { - return !(L == R); - } - friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) { - return !(L == R); - } - friend bool operator!=(const MachineInstrBundleIterator &L, - const_reference R) { - return !(L == R); - } - friend bool operator!=(const_reference L, - const MachineInstrBundleIterator &R) { - return !(L == R); - } - - // Increment and decrement operators... - MachineInstrBundleIterator &operator--() { - this->decrement(MII); - return *this; - } - MachineInstrBundleIterator &operator++() { - this->increment(MII); - return *this; - } - MachineInstrBundleIterator operator--(int) { - MachineInstrBundleIterator Temp = *this; - --*this; - return Temp; - } - MachineInstrBundleIterator operator++(int) { - MachineInstrBundleIterator Temp = *this; - ++*this; - return Temp; - } - - instr_iterator getInstrIterator() const { return MII; } - - nonconst_iterator getNonConstIterator() const { return MII.getNonConst(); } - - /// Get a reverse iterator to the same node. - /// - /// Gives a reverse iterator that will dereference (and have a handle) to the - /// same node. Converting the endpoint iterators in a range will give a - /// different range; for range operations, use the explicit conversions. - reverse_iterator getReverse() const { return MII.getReverse(); } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineJumpTableInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineJumpTableInfo.h deleted file mode 100644 index 1d082bd03e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineJumpTableInfo.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The MachineJumpTableInfo class keeps track of jump tables referenced by -// lowered switch instructions in the MachineFunction. -// -// Instructions reference the address of these jump tables through the use of -// MO_JumpTableIndex values. When emitting assembly or machine code, these -// virtual address references are converted to refer to the address of the -// function jump tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H -#define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H - -#include "llvm/Support/Printable.h" -#include -#include - -namespace llvm { - -class MachineBasicBlock; -class DataLayout; -class raw_ostream; - -/// MachineJumpTableEntry - One jump table in the jump table info. -/// -struct MachineJumpTableEntry { - /// MBBs - The vector of basic blocks from which to create the jump table. - std::vector MBBs; - - explicit MachineJumpTableEntry(const std::vector &M) - : MBBs(M) {} -}; - -class MachineJumpTableInfo { -public: - /// JTEntryKind - This enum indicates how each entry of the jump table is - /// represented and emitted. - enum JTEntryKind { - /// EK_BlockAddress - Each entry is a plain address of block, e.g.: - /// .word LBB123 - EK_BlockAddress, - - /// EK_GPRel64BlockAddress - Each entry is an address of block, encoded - /// with a relocation as gp-relative, e.g.: - /// .gpdword LBB123 - EK_GPRel64BlockAddress, - - /// EK_GPRel32BlockAddress - Each entry is an address of block, encoded - /// with a relocation as gp-relative, e.g.: - /// .gprel32 LBB123 - EK_GPRel32BlockAddress, - - /// EK_LabelDifference32 - Each entry is the address of the block minus - /// the address of the jump table. This is used for PIC jump tables where - /// gprel32 is not supported. e.g.: - /// .word LBB123 - LJTI1_2 - /// If the .set directive is supported, this is emitted as: - /// .set L4_5_set_123, LBB123 - LJTI1_2 - /// .word L4_5_set_123 - EK_LabelDifference32, - - /// EK_Inline - Jump table entries are emitted inline at their point of - /// use. It is the responsibility of the target to emit the entries. - EK_Inline, - - /// EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the - /// TargetLowering::LowerCustomJumpTableEntry hook. - EK_Custom32 - }; -private: - JTEntryKind EntryKind; - std::vector JumpTables; -public: - explicit MachineJumpTableInfo(JTEntryKind Kind): EntryKind(Kind) {} - - JTEntryKind getEntryKind() const { return EntryKind; } - - /// getEntrySize - Return the size of each entry in the jump table. - unsigned getEntrySize(const DataLayout &TD) const; - /// getEntryAlignment - Return the alignment of each entry in the jump table. - unsigned getEntryAlignment(const DataLayout &TD) const; - - /// createJumpTableIndex - Create a new jump table. - /// - unsigned createJumpTableIndex(const std::vector &DestBBs); - - /// isEmpty - Return true if there are no jump tables. - /// - bool isEmpty() const { return JumpTables.empty(); } - - const std::vector &getJumpTables() const { - return JumpTables; - } - - /// RemoveJumpTable - Mark the specific index as being dead. This will - /// prevent it from being emitted. - void RemoveJumpTable(unsigned Idx) { - JumpTables[Idx].MBBs.clear(); - } - - /// RemoveMBBFromJumpTables - If MBB is present in any jump tables, remove it. - bool RemoveMBBFromJumpTables(MachineBasicBlock *MBB); - - /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update - /// the jump tables to branch to New instead. - bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New); - - /// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update - /// the jump table to branch to New instead. - bool ReplaceMBBInJumpTable(unsigned Idx, MachineBasicBlock *Old, - MachineBasicBlock *New); - - /// print - Used by the MachineFunction printer to print information about - /// jump tables. Implemented in MachineFunction.cpp - /// - void print(raw_ostream &OS) const; - - /// dump - Call to stderr. - /// - void dump() const; -}; - - -/// Prints a jump table entry reference. -/// -/// The format is: -/// %jump-table.5 - a jump table entry with index == 5. -/// -/// Usage: OS << printJumpTableEntryReference(Idx) << '\n'; -Printable printJumpTableEntryReference(unsigned Idx); - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopInfo.h deleted file mode 100644 index c90f07096d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopInfo.h +++ /dev/null @@ -1,205 +0,0 @@ -//===- llvm/CodeGen/MachineLoopInfo.h - Natural Loop Calculator -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachineLoopInfo class that is used to identify natural -// loops and determine the loop depth of various nodes of the CFG. Note that -// natural loops may actually be several loops that share the same header node. -// -// This analysis calculates the nesting structure of loops in a function. For -// each natural loop identified, this analysis identifies natural loops -// contained entirely within the loop and the basic blocks the make up the loop. -// -// It can calculate on the fly various bits of information, for example: -// -// * whether there is a preheader for the loop -// * the number of back edges to the header -// * whether or not a particular block branches out of the loop -// * the successor blocks of the loop -// * the loop depth -// * the trip count -// * etc... -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINELOOPINFO_H -#define LLVM_CODEGEN_MACHINELOOPINFO_H - -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/Pass.h" - -namespace llvm { - -class MachineDominatorTree; -// Implementation in LoopInfoImpl.h -class MachineLoop; -extern template class LoopBase; - -class MachineLoop : public LoopBase { -public: - /// Return the "top" block in the loop, which is the first block in the linear - /// layout, ignoring any parts of the loop not contiguous with the part that - /// contains the header. - MachineBasicBlock *getTopBlock(); - - /// Return the "bottom" block in the loop, which is the last block in the - /// linear layout, ignoring any parts of the loop not contiguous with the part - /// that contains the header. - MachineBasicBlock *getBottomBlock(); - - /// Find the block that contains the loop control variable and the - /// loop test. This will return the latch block if it's one of the exiting - /// blocks. Otherwise, return the exiting block. Return 'null' when - /// multiple exiting blocks are present. - MachineBasicBlock *findLoopControlBlock(); - - /// Return the debug location of the start of this loop. - /// This looks for a BB terminating instruction with a known debug - /// location by looking at the preheader and header blocks. If it - /// cannot find a terminating instruction with location information, - /// it returns an unknown location. - DebugLoc getStartLoc() const; - - /// Returns true if the instruction is loop invariant. - /// I.e., all virtual register operands are defined outside of the loop, - /// physical registers aren't accessed explicitly, and there are no side - /// effects that aren't captured by the operands or other flags. - bool isLoopInvariant(MachineInstr &I) const; - - void dump() const; - -private: - friend class LoopInfoBase; - - explicit MachineLoop(MachineBasicBlock *MBB) - : LoopBase(MBB) {} - - MachineLoop() = default; -}; - -// Implementation in LoopInfoImpl.h -extern template class LoopInfoBase; - -class MachineLoopInfo : public MachineFunctionPass { - friend class LoopBase; - - LoopInfoBase LI; - -public: - static char ID; // Pass identification, replacement for typeid - - MachineLoopInfo(); - explicit MachineLoopInfo(MachineDominatorTree &MDT) - : MachineFunctionPass(ID) { - calculate(MDT); - } - MachineLoopInfo(const MachineLoopInfo &) = delete; - MachineLoopInfo &operator=(const MachineLoopInfo &) = delete; - - LoopInfoBase& getBase() { return LI; } - - /// Find the block that either is the loop preheader, or could - /// speculatively be used as the preheader. This is e.g. useful to place - /// loop setup code. Code that cannot be speculated should not be placed - /// here. SpeculativePreheader is controlling whether it also tries to - /// find the speculative preheader if the regular preheader is not present. - /// With FindMultiLoopPreheader = false, nullptr will be returned if the found - /// preheader is the preheader of multiple loops. - MachineBasicBlock * - findLoopPreheader(MachineLoop *L, bool SpeculativePreheader = false, - bool FindMultiLoopPreheader = false) const; - - /// The iterator interface to the top-level loops in the current function. - using iterator = LoopInfoBase::iterator; - inline iterator begin() const { return LI.begin(); } - inline iterator end() const { return LI.end(); } - bool empty() const { return LI.empty(); } - - /// Return the innermost loop that BB lives in. If a basic block is in no loop - /// (for example the entry node), null is returned. - inline MachineLoop *getLoopFor(const MachineBasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// Same as getLoopFor. - inline const MachineLoop *operator[](const MachineBasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// Return the loop nesting level of the specified block. - inline unsigned getLoopDepth(const MachineBasicBlock *BB) const { - return LI.getLoopDepth(BB); - } - - /// True if the block is a loop header node. - inline bool isLoopHeader(const MachineBasicBlock *BB) const { - return LI.isLoopHeader(BB); - } - - /// Calculate the natural loop information. - bool runOnMachineFunction(MachineFunction &F) override; - void calculate(MachineDominatorTree &MDT); - - void releaseMemory() override { LI.releaseMemory(); } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// This removes the specified top-level loop from this loop info object. The - /// loop is not deleted, as it will presumably be inserted into another loop. - inline MachineLoop *removeLoop(iterator I) { return LI.removeLoop(I); } - - /// Change the top-level loop that contains BB to the specified loop. This - /// should be used by transformations that restructure the loop hierarchy - /// tree. - inline void changeLoopFor(MachineBasicBlock *BB, MachineLoop *L) { - LI.changeLoopFor(BB, L); - } - - /// Replace the specified loop in the top-level loops list with the indicated - /// loop. - inline void changeTopLevelLoop(MachineLoop *OldLoop, MachineLoop *NewLoop) { - LI.changeTopLevelLoop(OldLoop, NewLoop); - } - - /// This adds the specified loop to the collection of top-level loops. - inline void addTopLevelLoop(MachineLoop *New) { - LI.addTopLevelLoop(New); - } - - /// This method completely removes BB from all data structures, including all - /// of the Loop objects it is nested in and our mapping from - /// MachineBasicBlocks to loops. - void removeBlock(MachineBasicBlock *BB) { - LI.removeBlock(BB); - } -}; - -// Allow clients to walk the list of nested loops... -template <> struct GraphTraits { - using NodeRef = const MachineLoop *; - using ChildIteratorType = MachineLoopInfo::iterator; - - static NodeRef getEntryNode(const MachineLoop *L) { return L; } - static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->end(); } -}; - -template <> struct GraphTraits { - using NodeRef = MachineLoop *; - using ChildIteratorType = MachineLoopInfo::iterator; - - static NodeRef getEntryNode(MachineLoop *L) { return L; } - static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->end(); } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINELOOPINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopUtils.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopUtils.h deleted file mode 100644 index b9bf93b71e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineLoopUtils.h +++ /dev/null @@ -1,41 +0,0 @@ -//=- MachineLoopUtils.h - Helper functions for manipulating loops -*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINELOOPUTILS_H -#define LLVM_CODEGEN_MACHINELOOPUTILS_H - -namespace llvm { -class MachineBasicBlock; -class MachineRegisterInfo; -class TargetInstrInfo; - -enum LoopPeelDirection { - LPD_Front, ///< Peel the first iteration of the loop. - LPD_Back ///< Peel the last iteration of the loop. -}; - -/// Peels a single block loop. Loop must have two successors, one of which -/// must be itself. Similarly it must have two predecessors, one of which must -/// be itself. -/// -/// The loop block is copied and inserted into the CFG such that two copies of -/// the loop follow on from each other. The copy is inserted either before or -/// after the loop based on Direction. -/// -/// Phis are updated and an unconditional branch inserted at the end of the -/// clone so as to execute a single iteration. -/// -/// The trip count of Loop is not updated. -MachineBasicBlock *PeelSingleBlockLoop(LoopPeelDirection Direction, - MachineBasicBlock *Loop, - MachineRegisterInfo &MRI, - const TargetInstrInfo *TII); - -} // namespace llvm - -#endif // LLVM_CODEGEN_MACHINELOOPUTILS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineMemOperand.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineMemOperand.h deleted file mode 100644 index 00080b1719..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineMemOperand.h +++ /dev/null @@ -1,359 +0,0 @@ -//==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MachineMemOperand class, which is a -// description of a memory reference. It is used to help track dependencies -// in the backend. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H -#define LLVM_CODEGEN_MACHINEMEMOPERAND_H - -#include "llvm/ADT/BitmaskEnum.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Value.h" // PointerLikeTypeTraits -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/LowLevelTypeImpl.h" - -namespace llvm { - -class FoldingSetNodeID; -class MDNode; -class raw_ostream; -class MachineFunction; -class ModuleSlotTracker; - -/// This class contains a discriminated union of information about pointers in -/// memory operands, relating them back to LLVM IR or to virtual locations (such -/// as frame indices) that are exposed during codegen. -struct MachinePointerInfo { - /// This is the IR pointer value for the access, or it is null if unknown. - /// If this is null, then the access is to a pointer in the default address - /// space. - PointerUnion V; - - /// Offset - This is an offset from the base Value*. - int64_t Offset; - - unsigned AddrSpace = 0; - - uint8_t StackID; - - explicit MachinePointerInfo(const Value *v, int64_t offset = 0, - uint8_t ID = 0) - : V(v), Offset(offset), StackID(ID) { - AddrSpace = v ? v->getType()->getPointerAddressSpace() : 0; - } - - explicit MachinePointerInfo(const PseudoSourceValue *v, int64_t offset = 0, - uint8_t ID = 0) - : V(v), Offset(offset), StackID(ID) { - AddrSpace = v ? v->getAddressSpace() : 0; - } - - explicit MachinePointerInfo(unsigned AddressSpace = 0, int64_t offset = 0) - : V((const Value *)nullptr), Offset(offset), AddrSpace(AddressSpace), - StackID(0) {} - - explicit MachinePointerInfo( - PointerUnion v, - int64_t offset = 0, - uint8_t ID = 0) - : V(v), Offset(offset), StackID(ID) { - if (V) { - if (const auto *ValPtr = V.dyn_cast()) - AddrSpace = ValPtr->getType()->getPointerAddressSpace(); - else - AddrSpace = V.get()->getAddressSpace(); - } - } - - MachinePointerInfo getWithOffset(int64_t O) const { - if (V.isNull()) - return MachinePointerInfo(AddrSpace, Offset + O); - if (V.is()) - return MachinePointerInfo(V.get(), Offset + O, StackID); - return MachinePointerInfo(V.get(), Offset + O, - StackID); - } - - /// Return true if memory region [V, V+Offset+Size) is known to be - /// dereferenceable. - bool isDereferenceable(unsigned Size, LLVMContext &C, - const DataLayout &DL) const; - - /// Return the LLVM IR address space number that this pointer points into. - unsigned getAddrSpace() const; - - /// Return a MachinePointerInfo record that refers to the constant pool. - static MachinePointerInfo getConstantPool(MachineFunction &MF); - - /// Return a MachinePointerInfo record that refers to the specified - /// FrameIndex. - static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, - int64_t Offset = 0); - - /// Return a MachinePointerInfo record that refers to a jump table entry. - static MachinePointerInfo getJumpTable(MachineFunction &MF); - - /// Return a MachinePointerInfo record that refers to a GOT entry. - static MachinePointerInfo getGOT(MachineFunction &MF); - - /// Stack pointer relative access. - static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, - uint8_t ID = 0); - - /// Stack memory without other information. - static MachinePointerInfo getUnknownStack(MachineFunction &MF); -}; - - -//===----------------------------------------------------------------------===// -/// A description of a memory reference used in the backend. -/// Instead of holding a StoreInst or LoadInst, this class holds the address -/// Value of the reference along with a byte size and offset. This allows it -/// to describe lowered loads and stores. Also, the special PseudoSourceValue -/// objects can be used to represent loads and stores to memory locations -/// that aren't explicit in the regular LLVM IR. -/// -class MachineMemOperand { -public: - /// Flags values. These may be or'd together. - enum Flags : uint16_t { - // No flags set. - MONone = 0, - /// The memory access reads data. - MOLoad = 1u << 0, - /// The memory access writes data. - MOStore = 1u << 1, - /// The memory access is volatile. - MOVolatile = 1u << 2, - /// The memory access is non-temporal. - MONonTemporal = 1u << 3, - /// The memory access is dereferenceable (i.e., doesn't trap). - MODereferenceable = 1u << 4, - /// The memory access always returns the same value (or traps). - MOInvariant = 1u << 5, - - // Reserved for use by target-specific passes. - // Targets may override getSerializableMachineMemOperandTargetFlags() to - // enable MIR serialization/parsing of these flags. If more of these flags - // are added, the MIR printing/parsing code will need to be updated as well. - MOTargetFlag1 = 1u << 6, - MOTargetFlag2 = 1u << 7, - MOTargetFlag3 = 1u << 8, - - LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ MOTargetFlag3) - }; - -private: - /// Atomic information for this memory operation. - struct MachineAtomicInfo { - /// Synchronization scope ID for this memory operation. - unsigned SSID : 8; // SyncScope::ID - /// Atomic ordering requirements for this memory operation. For cmpxchg - /// atomic operations, atomic ordering requirements when store occurs. - unsigned Ordering : 4; // enum AtomicOrdering - /// For cmpxchg atomic operations, atomic ordering requirements when store - /// does not occur. - unsigned FailureOrdering : 4; // enum AtomicOrdering - }; - - MachinePointerInfo PtrInfo; - - /// Track the memory type of the access. An access size which is unknown or - /// too large to be represented by LLT should use the invalid LLT. - LLT MemoryType; - - Flags FlagVals; - Align BaseAlign; - MachineAtomicInfo AtomicInfo; - AAMDNodes AAInfo; - const MDNode *Ranges; - -public: - /// Construct a MachineMemOperand object with the specified PtrInfo, flags, - /// size, and base alignment. For atomic operations the synchronization scope - /// and atomic ordering requirements must also be specified. For cmpxchg - /// atomic operations the atomic ordering requirements when store does not - /// occur must also be specified. - MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s, - Align a, const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr, - SyncScope::ID SSID = SyncScope::System, - AtomicOrdering Ordering = AtomicOrdering::NotAtomic, - AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); - MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, LLT type, Align a, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr, - SyncScope::ID SSID = SyncScope::System, - AtomicOrdering Ordering = AtomicOrdering::NotAtomic, - AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); - - const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } - - /// Return the base address of the memory access. This may either be a normal - /// LLVM IR Value, or one of the special values used in CodeGen. - /// Special values are those obtained via - /// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and - /// other PseudoSourceValue member functions which return objects which stand - /// for frame/stack pointer relative references and other special references - /// which are not representable in the high-level IR. - const Value *getValue() const { return PtrInfo.V.dyn_cast(); } - - const PseudoSourceValue *getPseudoValue() const { - return PtrInfo.V.dyn_cast(); - } - - const void *getOpaqueValue() const { return PtrInfo.V.getOpaqueValue(); } - - /// Return the raw flags of the source value, \see Flags. - Flags getFlags() const { return FlagVals; } - - /// Bitwise OR the current flags with the given flags. - void setFlags(Flags f) { FlagVals |= f; } - - /// For normal values, this is a byte offset added to the base address. - /// For PseudoSourceValue::FPRel values, this is the FrameIndex number. - int64_t getOffset() const { return PtrInfo.Offset; } - - unsigned getAddrSpace() const { return PtrInfo.getAddrSpace(); } - - /// Return the memory type of the memory reference. This should only be relied - /// on for GlobalISel G_* operation legalization. - LLT getMemoryType() const { return MemoryType; } - - /// Return the size in bytes of the memory reference. - uint64_t getSize() const { - return MemoryType.isValid() ? MemoryType.getSizeInBytes() : ~UINT64_C(0); - } - - /// Return the size in bits of the memory reference. - uint64_t getSizeInBits() const { - return MemoryType.isValid() ? MemoryType.getSizeInBits() : ~UINT64_C(0); - } - - LLT getType() const { - return MemoryType; - } - - /// Return the minimum known alignment in bytes of the actual memory - /// reference. - Align getAlign() const; - - /// Return the minimum known alignment in bytes of the base address, without - /// the offset. - Align getBaseAlign() const { return BaseAlign; } - - /// Return the AA tags for the memory reference. - AAMDNodes getAAInfo() const { return AAInfo; } - - /// Return the range tag for the memory reference. - const MDNode *getRanges() const { return Ranges; } - - /// Returns the synchronization scope ID for this memory operation. - SyncScope::ID getSyncScopeID() const { - return static_cast(AtomicInfo.SSID); - } - - /// Return the atomic ordering requirements for this memory operation. For - /// cmpxchg atomic operations, return the atomic ordering requirements when - /// store occurs. - AtomicOrdering getSuccessOrdering() const { - return static_cast(AtomicInfo.Ordering); - } - - /// For cmpxchg atomic operations, return the atomic ordering requirements - /// when store does not occur. - AtomicOrdering getFailureOrdering() const { - return static_cast(AtomicInfo.FailureOrdering); - } - - /// Return a single atomic ordering that is at least as strong as both the - /// success and failure orderings for an atomic operation. (For operations - /// other than cmpxchg, this is equivalent to getSuccessOrdering().) - AtomicOrdering getMergedOrdering() const { - return getMergedAtomicOrdering(getSuccessOrdering(), getFailureOrdering()); - } - - bool isLoad() const { return FlagVals & MOLoad; } - bool isStore() const { return FlagVals & MOStore; } - bool isVolatile() const { return FlagVals & MOVolatile; } - bool isNonTemporal() const { return FlagVals & MONonTemporal; } - bool isDereferenceable() const { return FlagVals & MODereferenceable; } - bool isInvariant() const { return FlagVals & MOInvariant; } - - /// Returns true if this operation has an atomic ordering requirement of - /// unordered or higher, false otherwise. - bool isAtomic() const { - return getSuccessOrdering() != AtomicOrdering::NotAtomic; - } - - /// Returns true if this memory operation doesn't have any ordering - /// constraints other than normal aliasing. Volatile and (ordered) atomic - /// memory operations can't be reordered. - bool isUnordered() const { - return (getSuccessOrdering() == AtomicOrdering::NotAtomic || - getSuccessOrdering() == AtomicOrdering::Unordered) && - !isVolatile(); - } - - /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a - /// greater alignment. This must only be used when the new alignment applies - /// to all users of this MachineMemOperand. - void refineAlignment(const MachineMemOperand *MMO); - - /// Change the SourceValue for this MachineMemOperand. This should only be - /// used when an object is being relocated and all references to it are being - /// updated. - void setValue(const Value *NewSV) { PtrInfo.V = NewSV; } - void setValue(const PseudoSourceValue *NewSV) { PtrInfo.V = NewSV; } - void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; } - - /// Reset the tracked memory type. - void setType(LLT NewTy) { - MemoryType = NewTy; - } - - /// Profile - Gather unique data for the object. - /// - void Profile(FoldingSetNodeID &ID) const; - - /// Support for operator<<. - /// @{ - void print(raw_ostream &OS, ModuleSlotTracker &MST, - SmallVectorImpl &SSNs, const LLVMContext &Context, - const MachineFrameInfo *MFI, const TargetInstrInfo *TII) const; - /// @} - - friend bool operator==(const MachineMemOperand &LHS, - const MachineMemOperand &RHS) { - return LHS.getValue() == RHS.getValue() && - LHS.getPseudoValue() == RHS.getPseudoValue() && - LHS.getSize() == RHS.getSize() && - LHS.getOffset() == RHS.getOffset() && - LHS.getFlags() == RHS.getFlags() && - LHS.getAAInfo() == RHS.getAAInfo() && - LHS.getRanges() == RHS.getRanges() && - LHS.getAlign() == RHS.getAlign() && - LHS.getAddrSpace() == RHS.getAddrSpace(); - } - - friend bool operator!=(const MachineMemOperand &LHS, - const MachineMemOperand &RHS) { - return !(LHS == RHS); - } -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfo.h deleted file mode 100644 index b7569acf4d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfo.h +++ /dev/null @@ -1,315 +0,0 @@ -//===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Collect meta information for a module. This information should be in a -// neutral form that can be used by different debugging and exception handling -// schemes. -// -// The organization of information is primarily clustered around the source -// compile units. The main exception is source line correspondence where -// inlining may interleave code from various compile units. -// -// The following information can be retrieved from the MachineModuleInfo. -// -// -- Source directories - Directories are uniqued based on their canonical -// string and assigned a sequential numeric ID (base 1.) -// -- Source files - Files are also uniqued based on their name and directory -// ID. A file ID is sequential number (base 1.) -// -- Source line correspondence - A vector of file ID, line#, column# triples. -// A DEBUG_LOCATION instruction is generated by the DAG Legalizer -// corresponding to each entry in the source line list. This allows a debug -// emitter to generate labels referenced by debug information tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H -#define LLVM_CODEGEN_MACHINEMODULEINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/IR/PassManager.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Pass.h" -#include -#include -#include - -namespace llvm { - -class BasicBlock; -class Function; -class LLVMTargetMachine; -class MMIAddrLabelMap; -class MachineFunction; -class Module; - -//===----------------------------------------------------------------------===// -/// This class can be derived from and used by targets to hold private -/// target-specific information for each Module. Objects of type are -/// accessed/created with MachineModuleInfo::getObjFileInfo and destroyed when -/// the MachineModuleInfo is destroyed. -/// -class MachineModuleInfoImpl { -public: - using StubValueTy = PointerIntPair; - using SymbolListTy = std::vector>; - - virtual ~MachineModuleInfoImpl(); - -protected: - /// Return the entries from a DenseMap in a deterministic sorted order. - /// Clears the map. - static SymbolListTy getSortedStubs(DenseMap&); -}; - -//===----------------------------------------------------------------------===// -/// This class contains meta information specific to a module. Queries can be -/// made by different debugging and exception handling schemes and reformatted -/// for specific use. -/// -class MachineModuleInfo { - friend class MachineModuleInfoWrapperPass; - friend class MachineModuleAnalysis; - - const LLVMTargetMachine &TM; - - /// This is the MCContext used for the entire code generator. - MCContext Context; - // This is an external context, that if assigned, will be used instead of the - // internal context. - MCContext *ExternalContext = nullptr; - - /// This is the LLVM Module being worked on. - const Module *TheModule; - - /// This is the object-file-format-specific implementation of - /// MachineModuleInfoImpl, which lets targets accumulate whatever info they - /// want. - MachineModuleInfoImpl *ObjFileMMI; - - /// \name Exception Handling - /// \{ - - /// Vector of all personality functions ever seen. Used to emit common EH - /// frames. - std::vector Personalities; - - /// The current call site index being processed, if any. 0 if none. - unsigned CurCallSite; - - /// \} - - /// This map keeps track of which symbol is being used for the specified - /// basic block's address of label. - MMIAddrLabelMap *AddrLabelSymbols; - - // TODO: Ideally, what we'd like is to have a switch that allows emitting - // synchronous (precise at call-sites only) CFA into .eh_frame. However, - // even under this switch, we'd like .debug_frame to be precise when using - // -g. At this moment, there's no way to specify that some CFI directives - // go into .eh_frame only, while others go into .debug_frame only. - - /// True if debugging information is available in this module. - bool DbgInfoAvailable; - - /// True if this module is being built for windows/msvc, and uses floating - /// point. This is used to emit an undefined reference to _fltused. - bool UsesMSVCFloatingPoint; - - /// True if the module calls the __morestack function indirectly, as is - /// required under the large code model on x86. This is used to emit - /// a definition of a symbol, __morestack_addr, containing the address. See - /// comments in lib/Target/X86/X86FrameLowering.cpp for more details. - bool UsesMorestackAddr; - - /// True if the module contains split-stack functions. This is used to - /// emit .note.GNU-split-stack section as required by the linker for - /// special handling split-stack function calling no-split-stack function. - bool HasSplitStack; - - /// True if the module contains no-split-stack functions. This is used to - /// emit .note.GNU-no-split-stack section when it also contains split-stack - /// functions. - bool HasNosplitStack; - - /// Maps IR Functions to their corresponding MachineFunctions. - DenseMap> MachineFunctions; - /// Next unique number available for a MachineFunction. - unsigned NextFnNum = 0; - const Function *LastRequest = nullptr; ///< Used for shortcut/cache. - MachineFunction *LastResult = nullptr; ///< Used for shortcut/cache. - - MachineModuleInfo &operator=(MachineModuleInfo &&MMII) = delete; - -public: - explicit MachineModuleInfo(const LLVMTargetMachine *TM = nullptr); - - explicit MachineModuleInfo(const LLVMTargetMachine *TM, - MCContext *ExtContext); - - MachineModuleInfo(MachineModuleInfo &&MMII); - - ~MachineModuleInfo(); - - void initialize(); - void finalize(); - - const LLVMTargetMachine &getTarget() const { return TM; } - - const MCContext &getContext() const { - return ExternalContext ? *ExternalContext : Context; - } - MCContext &getContext() { - return ExternalContext ? *ExternalContext : Context; - } - - const Module *getModule() const { return TheModule; } - - /// Returns the MachineFunction constructed for the IR function \p F. - /// Creates a new MachineFunction if none exists yet. - MachineFunction &getOrCreateMachineFunction(Function &F); - - /// \brief Returns the MachineFunction associated to IR function \p F if there - /// is one, otherwise nullptr. - MachineFunction *getMachineFunction(const Function &F) const; - - /// Delete the MachineFunction \p MF and reset the link in the IR Function to - /// Machine Function map. - void deleteMachineFunctionFor(Function &F); - - /// Keep track of various per-module pieces of information for backends - /// that would like to do so. - template - Ty &getObjFileInfo() { - if (ObjFileMMI == nullptr) - ObjFileMMI = new Ty(*this); - return *static_cast(ObjFileMMI); - } - - template - const Ty &getObjFileInfo() const { - return const_cast(this)->getObjFileInfo(); - } - - /// Returns true if valid debug info is present. - bool hasDebugInfo() const { return DbgInfoAvailable; } - void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } - - bool usesMSVCFloatingPoint() const { return UsesMSVCFloatingPoint; } - - void setUsesMSVCFloatingPoint(bool b) { UsesMSVCFloatingPoint = b; } - - bool usesMorestackAddr() const { - return UsesMorestackAddr; - } - - void setUsesMorestackAddr(bool b) { - UsesMorestackAddr = b; - } - - bool hasSplitStack() const { - return HasSplitStack; - } - - void setHasSplitStack(bool b) { - HasSplitStack = b; - } - - bool hasNosplitStack() const { - return HasNosplitStack; - } - - void setHasNosplitStack(bool b) { - HasNosplitStack = b; - } - - /// Return the symbol to be used for the specified basic block when its - /// address is taken. This cannot be its normal LBB label because the block - /// may be accessed outside its containing function. - MCSymbol *getAddrLabelSymbol(const BasicBlock *BB) { - return getAddrLabelSymbolToEmit(BB).front(); - } - - /// Return the symbol to be used for the specified basic block when its - /// address is taken. If other blocks were RAUW'd to this one, we may have - /// to emit them as well, return the whole set. - ArrayRef getAddrLabelSymbolToEmit(const BasicBlock *BB); - - /// If the specified function has had any references to address-taken blocks - /// generated, but the block got deleted, return the symbol now so we can - /// emit it. This prevents emitting a reference to a symbol that has no - /// definition. - void takeDeletedSymbolsForFunction(const Function *F, - std::vector &Result); - - /// \name Exception Handling - /// \{ - - /// Set the call site currently being processed. - void setCurrentCallSite(unsigned Site) { CurCallSite = Site; } - - /// Get the call site currently being processed, if any. return zero if - /// none. - unsigned getCurrentCallSite() { return CurCallSite; } - - /// Provide the personality function for the exception information. - void addPersonality(const Function *Personality); - - /// Return array of personality functions ever seen. - const std::vector& getPersonalities() const { - return Personalities; - } - /// \} - - // MMI owes MCContext. It should never be invalidated. - bool invalidate(Module &, const PreservedAnalyses &, - ModuleAnalysisManager::Invalidator &) { - return false; - } -}; // End class MachineModuleInfo - -class MachineModuleInfoWrapperPass : public ImmutablePass { - MachineModuleInfo MMI; - -public: - static char ID; // Pass identification, replacement for typeid - explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM = nullptr); - - explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM, - MCContext *ExtContext); - - // Initialization and Finalization - bool doInitialization(Module &) override; - bool doFinalization(Module &) override; - - MachineModuleInfo &getMMI() { return MMI; } - const MachineModuleInfo &getMMI() const { return MMI; } -}; - -/// An analysis that produces \c MachineInfo for a module. -class MachineModuleAnalysis : public AnalysisInfoMixin { - friend AnalysisInfoMixin; - static AnalysisKey Key; - - const LLVMTargetMachine *TM; - -public: - /// Provide the result type for this analysis pass. - using Result = MachineModuleInfo; - - MachineModuleAnalysis(const LLVMTargetMachine *TM) : TM(TM) {} - - /// Run the analysis pass and produce machine module information. - MachineModuleInfo run(Module &M, ModuleAnalysisManager &); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEMODULEINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfoImpls.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfoImpls.h deleted file mode 100644 index 58f7163d7b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ /dev/null @@ -1,118 +0,0 @@ -//===- llvm/CodeGen/MachineModuleInfoImpls.h --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines object-file format specific implementations of -// MachineModuleInfoImpl. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H -#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include - -namespace llvm { - -class MCSymbol; - -/// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation -/// for MachO targets. -class MachineModuleInfoMachO : public MachineModuleInfoImpl { - /// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like - /// "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra bit - /// is true if this GV is external. - DenseMap GVStubs; - - /// ThreadLocalGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something - /// like "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra - /// bit is true if this GV is external. - DenseMap ThreadLocalGVStubs; - - virtual void anchor(); // Out of line virtual method. - -public: - MachineModuleInfoMachO(const MachineModuleInfo &) {} - - StubValueTy &getGVStubEntry(MCSymbol *Sym) { - assert(Sym && "Key cannot be null"); - return GVStubs[Sym]; - } - - StubValueTy &getThreadLocalGVStubEntry(MCSymbol *Sym) { - assert(Sym && "Key cannot be null"); - return ThreadLocalGVStubs[Sym]; - } - - /// Accessor methods to return the set of stubs in sorted order. - SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } - SymbolListTy GetThreadLocalGVStubList() { - return getSortedStubs(ThreadLocalGVStubs); - } -}; - -/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation -/// for ELF targets. -class MachineModuleInfoELF : public MachineModuleInfoImpl { - /// GVStubs - These stubs are used to materialize global addresses in PIC - /// mode. - DenseMap GVStubs; - - virtual void anchor(); // Out of line virtual method. - -public: - MachineModuleInfoELF(const MachineModuleInfo &) {} - - StubValueTy &getGVStubEntry(MCSymbol *Sym) { - assert(Sym && "Key cannot be null"); - return GVStubs[Sym]; - } - - /// Accessor methods to return the set of stubs in sorted order. - - SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } -}; - -/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation -/// for COFF targets. -class MachineModuleInfoCOFF : public MachineModuleInfoImpl { - /// GVStubs - These stubs are used to materialize global addresses in PIC - /// mode. - DenseMap GVStubs; - - virtual void anchor(); // Out of line virtual method. - -public: - MachineModuleInfoCOFF(const MachineModuleInfo &) {} - - StubValueTy &getGVStubEntry(MCSymbol *Sym) { - assert(Sym && "Key cannot be null"); - return GVStubs[Sym]; - } - - /// Accessor methods to return the set of stubs in sorted order. - - SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } -}; - -/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation -/// for Wasm targets. -class MachineModuleInfoWasm : public MachineModuleInfoImpl { - virtual void anchor(); // Out of line virtual method. - -public: - MachineModuleInfoWasm(const MachineModuleInfo &) {} - - StringSet<> MachineSymbolsUsed; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleSlotTracker.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleSlotTracker.h deleted file mode 100644 index fc7635edd8..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineModuleSlotTracker.h +++ /dev/null @@ -1,45 +0,0 @@ -//===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEMODULESLOTTRACKER_H -#define LLVM_CODEGEN_MACHINEMODULESLOTTRACKER_H - -#include "llvm/IR/ModuleSlotTracker.h" - -namespace llvm { - -class AbstractSlotTrackerStorage; -class Function; -class MachineModuleInfo; -class MachineFunction; -class Module; - -class MachineModuleSlotTracker : public ModuleSlotTracker { - const Function &TheFunction; - const MachineModuleInfo &TheMMI; - unsigned MDNStartSlot = 0, MDNEndSlot = 0; - - void processMachineFunctionMetadata(AbstractSlotTrackerStorage *AST, - const MachineFunction &MF); - void processMachineModule(AbstractSlotTrackerStorage *AST, const Module *M, - bool ShouldInitializeAllMetadata); - void processMachineFunction(AbstractSlotTrackerStorage *AST, - const Function *F, - bool ShouldInitializeAllMetadata); - -public: - MachineModuleSlotTracker(const MachineFunction *MF, - bool ShouldInitializeAllMetadata = true); - ~MachineModuleSlotTracker(); - - void collectMachineMDNodes(MachineMDNodeListType &L) const; -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_MACHINEMODULESLOTTRACKER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOperand.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineOperand.h deleted file mode 100644 index 9bc946a54e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOperand.h +++ /dev/null @@ -1,998 +0,0 @@ -//===-- llvm/CodeGen/MachineOperand.h - MachineOperand class ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MachineOperand class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEOPERAND_H -#define LLVM_CODEGEN_MACHINEOPERAND_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/LowLevelTypeImpl.h" -#include - -namespace llvm { - -class BlockAddress; -class Constant; -class ConstantFP; -class ConstantInt; -class GlobalValue; -class MachineBasicBlock; -class MachineInstr; -class MachineRegisterInfo; -class MCCFIInstruction; -class MDNode; -class ModuleSlotTracker; -class TargetIntrinsicInfo; -class TargetRegisterInfo; -class hash_code; -class raw_ostream; -class MCSymbol; - -/// MachineOperand class - Representation of each machine instruction operand. -/// -/// This class isn't a POD type because it has a private constructor, but its -/// destructor must be trivial. Functions like MachineInstr::addOperand(), -/// MachineRegisterInfo::moveOperands(), and MF::DeleteMachineInstr() depend on -/// not having to call the MachineOperand destructor. -/// -class MachineOperand { -public: - enum MachineOperandType : unsigned char { - MO_Register, ///< Register operand. - MO_Immediate, ///< Immediate operand - MO_CImmediate, ///< Immediate >64bit operand - MO_FPImmediate, ///< Floating-point immediate operand - MO_MachineBasicBlock, ///< MachineBasicBlock reference - MO_FrameIndex, ///< Abstract Stack Frame Index - MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool - MO_TargetIndex, ///< Target-dependent index+offset operand. - MO_JumpTableIndex, ///< Address of indexed Jump Table for switch - MO_ExternalSymbol, ///< Name of external global symbol - MO_GlobalAddress, ///< Address of a global value - MO_BlockAddress, ///< Address of a basic block - MO_RegisterMask, ///< Mask of preserved registers. - MO_RegisterLiveOut, ///< Mask of live-out registers. - MO_Metadata, ///< Metadata reference (for debug info) - MO_MCSymbol, ///< MCSymbol reference (for debug/eh info) - MO_CFIIndex, ///< MCCFIInstruction index. - MO_IntrinsicID, ///< Intrinsic ID for ISel - MO_Predicate, ///< Generic predicate for ISel - MO_ShuffleMask, ///< Other IR Constant for ISel (shuffle masks) - MO_Last = MO_ShuffleMask - }; - -private: - /// OpKind - Specify what kind of operand this is. This discriminates the - /// union. - unsigned OpKind : 8; - - /// Subregister number for MO_Register. A value of 0 indicates the - /// MO_Register has no subReg. - /// - /// For all other kinds of operands, this field holds target-specific flags. - unsigned SubReg_TargetFlags : 12; - - /// TiedTo - Non-zero when this register operand is tied to another register - /// operand. The encoding of this field is described in the block comment - /// before MachineInstr::tieOperands(). - unsigned TiedTo : 4; - - /// IsDef - True if this is a def, false if this is a use of the register. - /// This is only valid on register operands. - /// - unsigned IsDef : 1; - - /// IsImp - True if this is an implicit def or use, false if it is explicit. - /// This is only valid on register opderands. - /// - unsigned IsImp : 1; - - /// IsDeadOrKill - /// For uses: IsKill - Conservatively indicates the last use of a register - /// on this path through the function. A register operand with true value of - /// this flag must be the last use of the register, a register operand with - /// false value may or may not be the last use of the register. After regalloc - /// we can use recomputeLivenessFlags to get precise kill flags. - /// For defs: IsDead - True if this register is never used by a subsequent - /// instruction. - /// This is only valid on register operands. - unsigned IsDeadOrKill : 1; - - /// See isRenamable(). - unsigned IsRenamable : 1; - - /// IsUndef - True if this register operand reads an "undef" value, i.e. the - /// read value doesn't matter. This flag can be set on both use and def - /// operands. On a sub-register def operand, it refers to the part of the - /// register that isn't written. On a full-register def operand, it is a - /// noop. See readsReg(). - /// - /// This is only valid on registers. - /// - /// Note that an instruction may have multiple operands referring to - /// the same register. In that case, the instruction may depend on those - /// operands reading the same dont-care value. For example: - /// - /// %1 = XOR undef %2, undef %2 - /// - /// Any register can be used for %2, and its value doesn't matter, but - /// the two operands must be the same register. - /// - unsigned IsUndef : 1; - - /// IsInternalRead - True if this operand reads a value that was defined - /// inside the same instruction or bundle. This flag can be set on both use - /// and def operands. On a sub-register def operand, it refers to the part - /// of the register that isn't written. On a full-register def operand, it - /// is a noop. - /// - /// When this flag is set, the instruction bundle must contain at least one - /// other def of the register. If multiple instructions in the bundle define - /// the register, the meaning is target-defined. - unsigned IsInternalRead : 1; - - /// IsEarlyClobber - True if this MO_Register 'def' operand is written to - /// by the MachineInstr before all input registers are read. This is used to - /// model the GCC inline asm '&' constraint modifier. - unsigned IsEarlyClobber : 1; - - /// IsDebug - True if this MO_Register 'use' operand is in a debug pseudo, - /// not a real instruction. Such uses should be ignored during codegen. - unsigned IsDebug : 1; - - /// SmallContents - This really should be part of the Contents union, but - /// lives out here so we can get a better packed struct. - /// MO_Register: Register number. - /// OffsetedInfo: Low bits of offset. - union { - unsigned RegNo; // For MO_Register. - unsigned OffsetLo; // Matches Contents.OffsetedInfo.OffsetHi. - } SmallContents; - - /// ParentMI - This is the instruction that this operand is embedded into. - /// This is valid for all operand types, when the operand is in an instr. - MachineInstr *ParentMI = nullptr; - - /// Contents union - This contains the payload for the various operand types. - union ContentsUnion { - ContentsUnion() {} - MachineBasicBlock *MBB; // For MO_MachineBasicBlock. - const ConstantFP *CFP; // For MO_FPImmediate. - const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. - int64_t ImmVal; // For MO_Immediate. - const uint32_t *RegMask; // For MO_RegisterMask and MO_RegisterLiveOut. - const MDNode *MD; // For MO_Metadata. - MCSymbol *Sym; // For MO_MCSymbol. - unsigned CFIIndex; // For MO_CFI. - Intrinsic::ID IntrinsicID; // For MO_IntrinsicID. - unsigned Pred; // For MO_Predicate - ArrayRef ShuffleMask; // For MO_ShuffleMask - - struct { // For MO_Register. - // Register number is in SmallContents.RegNo. - MachineOperand *Prev; // Access list for register. See MRI. - MachineOperand *Next; - } Reg; - - /// OffsetedInfo - This struct contains the offset and an object identifier. - /// this represent the object as with an optional offset from it. - struct { - union { - int Index; // For MO_*Index - The index itself. - const char *SymbolName; // For MO_ExternalSymbol. - const GlobalValue *GV; // For MO_GlobalAddress. - const BlockAddress *BA; // For MO_BlockAddress. - } Val; - // Low bits of offset are in SmallContents.OffsetLo. - int OffsetHi; // An offset from the object, high 32 bits. - } OffsetedInfo; - } Contents; - - explicit MachineOperand(MachineOperandType K) - : OpKind(K), SubReg_TargetFlags(0) { - // Assert that the layout is what we expect. It's easy to grow this object. - static_assert(alignof(MachineOperand) <= alignof(int64_t), - "MachineOperand shouldn't be more than 8 byte aligned"); - static_assert(sizeof(Contents) <= 2 * sizeof(void *), - "Contents should be at most two pointers"); - static_assert(sizeof(MachineOperand) <= - alignTo(2 * sizeof(unsigned) + - 3 * sizeof(void *)), - "MachineOperand too big. Should be Kind, SmallContents, " - "ParentMI, and Contents"); - } - -public: - /// getType - Returns the MachineOperandType for this operand. - /// - MachineOperandType getType() const { return (MachineOperandType)OpKind; } - - unsigned getTargetFlags() const { - return isReg() ? 0 : SubReg_TargetFlags; - } - void setTargetFlags(unsigned F) { - assert(!isReg() && "Register operands can't have target flags"); - SubReg_TargetFlags = F; - assert(SubReg_TargetFlags == F && "Target flags out of range"); - } - void addTargetFlag(unsigned F) { - assert(!isReg() && "Register operands can't have target flags"); - SubReg_TargetFlags |= F; - assert((SubReg_TargetFlags & F) && "Target flags out of range"); - } - - - /// getParent - Return the instruction that this operand belongs to. - /// - MachineInstr *getParent() { return ParentMI; } - const MachineInstr *getParent() const { return ParentMI; } - - /// clearParent - Reset the parent pointer. - /// - /// The MachineOperand copy constructor also copies ParentMI, expecting the - /// original to be deleted. If a MachineOperand is ever stored outside a - /// MachineInstr, the parent pointer must be cleared. - /// - /// Never call clearParent() on an operand in a MachineInstr. - /// - void clearParent() { ParentMI = nullptr; } - - /// Print a subreg index operand. - /// MO_Immediate operands can also be subreg indices. If it's the case, the - /// subreg index name will be printed. MachineInstr::isOperandSubregIdx can be - /// called to check this. - static void printSubRegIdx(raw_ostream &OS, uint64_t Index, - const TargetRegisterInfo *TRI); - - /// Print operand target flags. - static void printTargetFlags(raw_ostream& OS, const MachineOperand &Op); - - /// Print a MCSymbol as an operand. - static void printSymbol(raw_ostream &OS, MCSymbol &Sym); - - /// Print a stack object reference. - static void printStackObjectReference(raw_ostream &OS, unsigned FrameIndex, - bool IsFixed, StringRef Name); - - /// Print the offset with explicit +/- signs. - static void printOperandOffset(raw_ostream &OS, int64_t Offset); - - /// Print an IRSlotNumber. - static void printIRSlotNumber(raw_ostream &OS, int Slot); - - /// Print the MachineOperand to \p os. - /// Providing a valid \p TRI and \p IntrinsicInfo results in a more - /// target-specific printing. If \p TRI and \p IntrinsicInfo are null, the - /// function will try to pick it up from the parent. - void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr, - const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; - - /// More complex way of printing a MachineOperand. - /// \param TypeToPrint specifies the generic type to be printed on uses and - /// defs. It can be determined using MachineInstr::getTypeToPrint. - /// \param OpIdx - specifies the index of the operand in machine instruction. - /// This will be used by target dependent MIR formatter. Could be None if the - /// index is unknown, e.g. called by dump(). - /// \param PrintDef - whether we want to print `def` on an operand which - /// isDef. Sometimes, if the operand is printed before '=', we don't print - /// `def`. - /// \param IsStandalone - whether we want a verbose output of the MO. This - /// prints extra information that can be easily inferred when printing the - /// whole function, but not when printing only a fragment of it. - /// \param ShouldPrintRegisterTies - whether we want to print register ties. - /// Sometimes they are easily determined by the instruction's descriptor - /// (MachineInstr::hasComplexRegiterTies can determine if it's needed). - /// \param TiedOperandIdx - if we need to print register ties this needs to - /// provide the index of the tied register. If not, it will be ignored. - /// \param TRI - provide more target-specific information to the printer. - /// Unlike the previous function, this one will not try to get the - /// information from its parent. - /// \param IntrinsicInfo - same as \p TRI. - void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint, - Optional OpIdx, bool PrintDef, bool IsStandalone, - bool ShouldPrintRegisterTies, unsigned TiedOperandIdx, - const TargetRegisterInfo *TRI, - const TargetIntrinsicInfo *IntrinsicInfo) const; - - /// Same as print(os, TRI, IntrinsicInfo), but allows to specify the low-level - /// type to be printed the same way the full version of print(...) does it. - void print(raw_ostream &os, LLT TypeToPrint, - const TargetRegisterInfo *TRI = nullptr, - const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; - - void dump() const; - - //===--------------------------------------------------------------------===// - // Accessors that tell you what kind of MachineOperand you're looking at. - //===--------------------------------------------------------------------===// - - /// isReg - Tests if this is a MO_Register operand. - bool isReg() const { return OpKind == MO_Register; } - /// isImm - Tests if this is a MO_Immediate operand. - bool isImm() const { return OpKind == MO_Immediate; } - /// isCImm - Test if this is a MO_CImmediate operand. - bool isCImm() const { return OpKind == MO_CImmediate; } - /// isFPImm - Tests if this is a MO_FPImmediate operand. - bool isFPImm() const { return OpKind == MO_FPImmediate; } - /// isMBB - Tests if this is a MO_MachineBasicBlock operand. - bool isMBB() const { return OpKind == MO_MachineBasicBlock; } - /// isFI - Tests if this is a MO_FrameIndex operand. - bool isFI() const { return OpKind == MO_FrameIndex; } - /// isCPI - Tests if this is a MO_ConstantPoolIndex operand. - bool isCPI() const { return OpKind == MO_ConstantPoolIndex; } - /// isTargetIndex - Tests if this is a MO_TargetIndex operand. - bool isTargetIndex() const { return OpKind == MO_TargetIndex; } - /// isJTI - Tests if this is a MO_JumpTableIndex operand. - bool isJTI() const { return OpKind == MO_JumpTableIndex; } - /// isGlobal - Tests if this is a MO_GlobalAddress operand. - bool isGlobal() const { return OpKind == MO_GlobalAddress; } - /// isSymbol - Tests if this is a MO_ExternalSymbol operand. - bool isSymbol() const { return OpKind == MO_ExternalSymbol; } - /// isBlockAddress - Tests if this is a MO_BlockAddress operand. - bool isBlockAddress() const { return OpKind == MO_BlockAddress; } - /// isRegMask - Tests if this is a MO_RegisterMask operand. - bool isRegMask() const { return OpKind == MO_RegisterMask; } - /// isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand. - bool isRegLiveOut() const { return OpKind == MO_RegisterLiveOut; } - /// isMetadata - Tests if this is a MO_Metadata operand. - bool isMetadata() const { return OpKind == MO_Metadata; } - bool isMCSymbol() const { return OpKind == MO_MCSymbol; } - bool isCFIIndex() const { return OpKind == MO_CFIIndex; } - bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; } - bool isPredicate() const { return OpKind == MO_Predicate; } - bool isShuffleMask() const { return OpKind == MO_ShuffleMask; } - //===--------------------------------------------------------------------===// - // Accessors for Register Operands - //===--------------------------------------------------------------------===// - - /// getReg - Returns the register number. - Register getReg() const { - assert(isReg() && "This is not a register operand!"); - return Register(SmallContents.RegNo); - } - - unsigned getSubReg() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return SubReg_TargetFlags; - } - - bool isUse() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return !IsDef; - } - - bool isDef() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsDef; - } - - bool isImplicit() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsImp; - } - - bool isDead() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsDeadOrKill & IsDef; - } - - bool isKill() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsDeadOrKill & !IsDef; - } - - bool isUndef() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsUndef; - } - - /// isRenamable - Returns true if this register may be renamed, i.e. it does - /// not generate a value that is somehow read in a way that is not represented - /// by the Machine IR (e.g. to meet an ABI or ISA requirement). This is only - /// valid on physical register operands. Virtual registers are assumed to - /// always be renamable regardless of the value of this field. - /// - /// Operands that are renamable can freely be changed to any other register - /// that is a member of the register class returned by - /// MI->getRegClassConstraint(). - /// - /// isRenamable can return false for several different reasons: - /// - /// - ABI constraints (since liveness is not always precisely modeled). We - /// conservatively handle these cases by setting all physical register - /// operands that didn’t start out as virtual regs to not be renamable. - /// Also any physical register operands created after register allocation or - /// whose register is changed after register allocation will not be - /// renamable. This state is tracked in the MachineOperand::IsRenamable - /// bit. - /// - /// - Opcode/target constraints: for opcodes that have complex register class - /// requirements (e.g. that depend on other operands/instructions), we set - /// hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq in the machine opcode - /// description. Operands belonging to instructions with opcodes that are - /// marked hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq return false from - /// isRenamable(). Additionally, the AllowRegisterRenaming target property - /// prevents any operands from being marked renamable for targets that don't - /// have detailed opcode hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq - /// values. - bool isRenamable() const; - - bool isInternalRead() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsInternalRead; - } - - bool isEarlyClobber() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsEarlyClobber; - } - - bool isTied() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return TiedTo; - } - - bool isDebug() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return IsDebug; - } - - /// readsReg - Returns true if this operand reads the previous value of its - /// register. A use operand with the flag set doesn't read its - /// register. A sub-register def implicitly reads the other parts of the - /// register being redefined unless the flag is set. - /// - /// This refers to reading the register value from before the current - /// instruction or bundle. Internal bundle reads are not included. - bool readsReg() const { - assert(isReg() && "Wrong MachineOperand accessor"); - return !isUndef() && !isInternalRead() && (isUse() || getSubReg()); - } - - //===--------------------------------------------------------------------===// - // Mutators for Register Operands - //===--------------------------------------------------------------------===// - - /// Change the register this operand corresponds to. - /// - void setReg(Register Reg); - - void setSubReg(unsigned subReg) { - assert(isReg() && "Wrong MachineOperand mutator"); - SubReg_TargetFlags = subReg; - assert(SubReg_TargetFlags == subReg && "SubReg out of range"); - } - - /// substVirtReg - Substitute the current register with the virtual - /// subregister Reg:SubReg. Take any existing SubReg index into account, - /// using TargetRegisterInfo to compose the subreg indices if necessary. - /// Reg must be a virtual register, SubIdx can be 0. - /// - void substVirtReg(Register Reg, unsigned SubIdx, const TargetRegisterInfo&); - - /// substPhysReg - Substitute the current register with the physical register - /// Reg, taking any existing SubReg into account. For instance, - /// substPhysReg(%eax) will change %reg1024:sub_8bit to %al. - /// - void substPhysReg(MCRegister Reg, const TargetRegisterInfo&); - - void setIsUse(bool Val = true) { setIsDef(!Val); } - - /// Change a def to a use, or a use to a def. - void setIsDef(bool Val = true); - - void setImplicit(bool Val = true) { - assert(isReg() && "Wrong MachineOperand mutator"); - IsImp = Val; - } - - void setIsKill(bool Val = true) { - assert(isReg() && !IsDef && "Wrong MachineOperand mutator"); - assert((!Val || !isDebug()) && "Marking a debug operation as kill"); - IsDeadOrKill = Val; - } - - void setIsDead(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand mutator"); - IsDeadOrKill = Val; - } - - void setIsUndef(bool Val = true) { - assert(isReg() && "Wrong MachineOperand mutator"); - IsUndef = Val; - } - - void setIsRenamable(bool Val = true); - - void setIsInternalRead(bool Val = true) { - assert(isReg() && "Wrong MachineOperand mutator"); - IsInternalRead = Val; - } - - void setIsEarlyClobber(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand mutator"); - IsEarlyClobber = Val; - } - - void setIsDebug(bool Val = true) { - assert(isReg() && !IsDef && "Wrong MachineOperand mutator"); - IsDebug = Val; - } - - //===--------------------------------------------------------------------===// - // Accessors for various operand types. - //===--------------------------------------------------------------------===// - - int64_t getImm() const { - assert(isImm() && "Wrong MachineOperand accessor"); - return Contents.ImmVal; - } - - const ConstantInt *getCImm() const { - assert(isCImm() && "Wrong MachineOperand accessor"); - return Contents.CI; - } - - const ConstantFP *getFPImm() const { - assert(isFPImm() && "Wrong MachineOperand accessor"); - return Contents.CFP; - } - - MachineBasicBlock *getMBB() const { - assert(isMBB() && "Wrong MachineOperand accessor"); - return Contents.MBB; - } - - int getIndex() const { - assert((isFI() || isCPI() || isTargetIndex() || isJTI()) && - "Wrong MachineOperand accessor"); - return Contents.OffsetedInfo.Val.Index; - } - - const GlobalValue *getGlobal() const { - assert(isGlobal() && "Wrong MachineOperand accessor"); - return Contents.OffsetedInfo.Val.GV; - } - - const BlockAddress *getBlockAddress() const { - assert(isBlockAddress() && "Wrong MachineOperand accessor"); - return Contents.OffsetedInfo.Val.BA; - } - - MCSymbol *getMCSymbol() const { - assert(isMCSymbol() && "Wrong MachineOperand accessor"); - return Contents.Sym; - } - - unsigned getCFIIndex() const { - assert(isCFIIndex() && "Wrong MachineOperand accessor"); - return Contents.CFIIndex; - } - - Intrinsic::ID getIntrinsicID() const { - assert(isIntrinsicID() && "Wrong MachineOperand accessor"); - return Contents.IntrinsicID; - } - - unsigned getPredicate() const { - assert(isPredicate() && "Wrong MachineOperand accessor"); - return Contents.Pred; - } - - ArrayRef getShuffleMask() const { - assert(isShuffleMask() && "Wrong MachineOperand accessor"); - return Contents.ShuffleMask; - } - - /// Return the offset from the symbol in this operand. This always returns 0 - /// for ExternalSymbol operands. - int64_t getOffset() const { - assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() || - isTargetIndex() || isBlockAddress()) && - "Wrong MachineOperand accessor"); - return int64_t(uint64_t(Contents.OffsetedInfo.OffsetHi) << 32) | - SmallContents.OffsetLo; - } - - const char *getSymbolName() const { - assert(isSymbol() && "Wrong MachineOperand accessor"); - return Contents.OffsetedInfo.Val.SymbolName; - } - - /// clobbersPhysReg - Returns true if this RegMask clobbers PhysReg. - /// It is sometimes necessary to detach the register mask pointer from its - /// machine operand. This static method can be used for such detached bit - /// mask pointers. - static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg) { - // See TargetRegisterInfo.h. - assert(PhysReg < (1u << 30) && "Not a physical register"); - return !(RegMask[PhysReg / 32] & (1u << PhysReg % 32)); - } - - /// clobbersPhysReg - Returns true if this RegMask operand clobbers PhysReg. - bool clobbersPhysReg(MCRegister PhysReg) const { - return clobbersPhysReg(getRegMask(), PhysReg); - } - - /// getRegMask - Returns a bit mask of registers preserved by this RegMask - /// operand. - const uint32_t *getRegMask() const { - assert(isRegMask() && "Wrong MachineOperand accessor"); - return Contents.RegMask; - } - - /// Returns number of elements needed for a regmask array. - static unsigned getRegMaskSize(unsigned NumRegs) { - return (NumRegs + 31) / 32; - } - - /// getRegLiveOut - Returns a bit mask of live-out registers. - const uint32_t *getRegLiveOut() const { - assert(isRegLiveOut() && "Wrong MachineOperand accessor"); - return Contents.RegMask; - } - - const MDNode *getMetadata() const { - assert(isMetadata() && "Wrong MachineOperand accessor"); - return Contents.MD; - } - - //===--------------------------------------------------------------------===// - // Mutators for various operand types. - //===--------------------------------------------------------------------===// - - void setImm(int64_t immVal) { - assert(isImm() && "Wrong MachineOperand mutator"); - Contents.ImmVal = immVal; - } - - void setCImm(const ConstantInt *CI) { - assert(isCImm() && "Wrong MachineOperand mutator"); - Contents.CI = CI; - } - - void setFPImm(const ConstantFP *CFP) { - assert(isFPImm() && "Wrong MachineOperand mutator"); - Contents.CFP = CFP; - } - - void setOffset(int64_t Offset) { - assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() || - isTargetIndex() || isBlockAddress()) && - "Wrong MachineOperand mutator"); - SmallContents.OffsetLo = unsigned(Offset); - Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); - } - - void setIndex(int Idx) { - assert((isFI() || isCPI() || isTargetIndex() || isJTI()) && - "Wrong MachineOperand mutator"); - Contents.OffsetedInfo.Val.Index = Idx; - } - - void setMetadata(const MDNode *MD) { - assert(isMetadata() && "Wrong MachineOperand mutator"); - Contents.MD = MD; - } - - void setMBB(MachineBasicBlock *MBB) { - assert(isMBB() && "Wrong MachineOperand mutator"); - Contents.MBB = MBB; - } - - /// Sets value of register mask operand referencing Mask. The - /// operand does not take ownership of the memory referenced by Mask, it must - /// remain valid for the lifetime of the operand. See CreateRegMask(). - /// Any physreg with a 0 bit in the mask is clobbered by the instruction. - void setRegMask(const uint32_t *RegMaskPtr) { - assert(isRegMask() && "Wrong MachineOperand mutator"); - Contents.RegMask = RegMaskPtr; - } - - void setIntrinsicID(Intrinsic::ID IID) { - assert(isIntrinsicID() && "Wrong MachineOperand mutator"); - Contents.IntrinsicID = IID; - } - - void setPredicate(unsigned Predicate) { - assert(isPredicate() && "Wrong MachineOperand mutator"); - Contents.Pred = Predicate; - } - - //===--------------------------------------------------------------------===// - // Other methods. - //===--------------------------------------------------------------------===// - - /// Returns true if this operand is identical to the specified operand except - /// for liveness related flags (isKill, isUndef and isDead). Note that this - /// should stay in sync with the hash_value overload below. - bool isIdenticalTo(const MachineOperand &Other) const; - - /// MachineOperand hash_value overload. - /// - /// Note that this includes the same information in the hash that - /// isIdenticalTo uses for comparison. It is thus suited for use in hash - /// tables which use that function for equality comparisons only. This must - /// stay exactly in sync with isIdenticalTo above. - friend hash_code hash_value(const MachineOperand &MO); - - /// ChangeToImmediate - Replace this operand with a new immediate operand of - /// the specified value. If an operand is known to be an immediate already, - /// the setImm method should be used. - void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags = 0); - - /// ChangeToFPImmediate - Replace this operand with a new FP immediate operand - /// of the specified value. If an operand is known to be an FP immediate - /// already, the setFPImm method should be used. - void ChangeToFPImmediate(const ConstantFP *FPImm, unsigned TargetFlags = 0); - - /// ChangeToES - Replace this operand with a new external symbol operand. - void ChangeToES(const char *SymName, unsigned TargetFlags = 0); - - /// ChangeToGA - Replace this operand with a new global address operand. - void ChangeToGA(const GlobalValue *GV, int64_t Offset, - unsigned TargetFlags = 0); - - /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. - void ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags = 0); - - /// Replace this operand with a frame index. - void ChangeToFrameIndex(int Idx, unsigned TargetFlags = 0); - - /// Replace this operand with a target index. - void ChangeToTargetIndex(unsigned Idx, int64_t Offset, - unsigned TargetFlags = 0); - - /// ChangeToRegister - Replace this operand with a new register operand of - /// the specified value. If an operand is known to be an register already, - /// the setReg method should be used. - void ChangeToRegister(Register Reg, bool isDef, bool isImp = false, - bool isKill = false, bool isDead = false, - bool isUndef = false, bool isDebug = false); - - /// getTargetIndexName - If this MachineOperand is a TargetIndex that has a - /// name, attempt to get the name. Returns nullptr if the TargetIndex does not - /// have a name. Asserts if MO is not a TargetIndex. - const char *getTargetIndexName() const; - - //===--------------------------------------------------------------------===// - // Construction methods. - //===--------------------------------------------------------------------===// - - static MachineOperand CreateImm(int64_t Val) { - MachineOperand Op(MachineOperand::MO_Immediate); - Op.setImm(Val); - return Op; - } - - static MachineOperand CreateCImm(const ConstantInt *CI) { - MachineOperand Op(MachineOperand::MO_CImmediate); - Op.Contents.CI = CI; - return Op; - } - - static MachineOperand CreateFPImm(const ConstantFP *CFP) { - MachineOperand Op(MachineOperand::MO_FPImmediate); - Op.Contents.CFP = CFP; - return Op; - } - - static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp = false, - bool isKill = false, bool isDead = false, - bool isUndef = false, - bool isEarlyClobber = false, - unsigned SubReg = 0, bool isDebug = false, - bool isInternalRead = false, - bool isRenamable = false) { - assert(!(isDead && !isDef) && "Dead flag on non-def"); - assert(!(isKill && isDef) && "Kill flag on def"); - MachineOperand Op(MachineOperand::MO_Register); - Op.IsDef = isDef; - Op.IsImp = isImp; - Op.IsDeadOrKill = isKill | isDead; - Op.IsRenamable = isRenamable; - Op.IsUndef = isUndef; - Op.IsInternalRead = isInternalRead; - Op.IsEarlyClobber = isEarlyClobber; - Op.TiedTo = 0; - Op.IsDebug = isDebug; - Op.SmallContents.RegNo = Reg; - Op.Contents.Reg.Prev = nullptr; - Op.Contents.Reg.Next = nullptr; - Op.setSubReg(SubReg); - return Op; - } - static MachineOperand CreateMBB(MachineBasicBlock *MBB, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_MachineBasicBlock); - Op.setMBB(MBB); - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateFI(int Idx) { - MachineOperand Op(MachineOperand::MO_FrameIndex); - Op.setIndex(Idx); - return Op; - } - static MachineOperand CreateCPI(unsigned Idx, int Offset, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_ConstantPoolIndex); - Op.setIndex(Idx); - Op.setOffset(Offset); - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateTargetIndex(unsigned Idx, int64_t Offset, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_TargetIndex); - Op.setIndex(Idx); - Op.setOffset(Offset); - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateJTI(unsigned Idx, unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_JumpTableIndex); - Op.setIndex(Idx); - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_GlobalAddress); - Op.Contents.OffsetedInfo.Val.GV = GV; - Op.setOffset(Offset); - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateES(const char *SymName, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_ExternalSymbol); - Op.Contents.OffsetedInfo.Val.SymbolName = SymName; - Op.setOffset(0); // Offset is always 0. - Op.setTargetFlags(TargetFlags); - return Op; - } - static MachineOperand CreateBA(const BlockAddress *BA, int64_t Offset, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_BlockAddress); - Op.Contents.OffsetedInfo.Val.BA = BA; - Op.setOffset(Offset); - Op.setTargetFlags(TargetFlags); - return Op; - } - /// CreateRegMask - Creates a register mask operand referencing Mask. The - /// operand does not take ownership of the memory referenced by Mask, it - /// must remain valid for the lifetime of the operand. - /// - /// A RegMask operand represents a set of non-clobbered physical registers - /// on an instruction that clobbers many registers, typically a call. The - /// bit mask has a bit set for each physreg that is preserved by this - /// instruction, as described in the documentation for - /// TargetRegisterInfo::getCallPreservedMask(). - /// - /// Any physreg with a 0 bit in the mask is clobbered by the instruction. - /// - static MachineOperand CreateRegMask(const uint32_t *Mask) { - assert(Mask && "Missing register mask"); - MachineOperand Op(MachineOperand::MO_RegisterMask); - Op.Contents.RegMask = Mask; - return Op; - } - static MachineOperand CreateRegLiveOut(const uint32_t *Mask) { - assert(Mask && "Missing live-out register mask"); - MachineOperand Op(MachineOperand::MO_RegisterLiveOut); - Op.Contents.RegMask = Mask; - return Op; - } - static MachineOperand CreateMetadata(const MDNode *Meta) { - MachineOperand Op(MachineOperand::MO_Metadata); - Op.Contents.MD = Meta; - return Op; - } - - static MachineOperand CreateMCSymbol(MCSymbol *Sym, - unsigned TargetFlags = 0) { - MachineOperand Op(MachineOperand::MO_MCSymbol); - Op.Contents.Sym = Sym; - Op.setOffset(0); - Op.setTargetFlags(TargetFlags); - return Op; - } - - static MachineOperand CreateCFIIndex(unsigned CFIIndex) { - MachineOperand Op(MachineOperand::MO_CFIIndex); - Op.Contents.CFIIndex = CFIIndex; - return Op; - } - - static MachineOperand CreateIntrinsicID(Intrinsic::ID ID) { - MachineOperand Op(MachineOperand::MO_IntrinsicID); - Op.Contents.IntrinsicID = ID; - return Op; - } - - static MachineOperand CreatePredicate(unsigned Pred) { - MachineOperand Op(MachineOperand::MO_Predicate); - Op.Contents.Pred = Pred; - return Op; - } - - static MachineOperand CreateShuffleMask(ArrayRef Mask) { - MachineOperand Op(MachineOperand::MO_ShuffleMask); - Op.Contents.ShuffleMask = Mask; - return Op; - } - - friend class MachineInstr; - friend class MachineRegisterInfo; - -private: - // If this operand is currently a register operand, and if this is in a - // function, deregister the operand from the register's use/def list. - void removeRegFromUses(); - - /// Artificial kinds for DenseMap usage. - enum : unsigned char { - MO_Empty = MO_Last + 1, - MO_Tombstone, - }; - - friend struct DenseMapInfo; - - //===--------------------------------------------------------------------===// - // Methods for handling register use/def lists. - //===--------------------------------------------------------------------===// - - /// isOnRegUseList - Return true if this operand is on a register use/def - /// list or false if not. This can only be called for register operands - /// that are part of a machine instruction. - bool isOnRegUseList() const { - assert(isReg() && "Can only add reg operand to use lists"); - return Contents.Reg.Prev != nullptr; - } -}; - -template <> struct DenseMapInfo { - static MachineOperand getEmptyKey() { - return MachineOperand(static_cast( - MachineOperand::MO_Empty)); - } - static MachineOperand getTombstoneKey() { - return MachineOperand(static_cast( - MachineOperand::MO_Tombstone)); - } - static unsigned getHashValue(const MachineOperand &MO) { - return hash_value(MO); - } - static bool isEqual(const MachineOperand &LHS, const MachineOperand &RHS) { - if (LHS.getType() == static_cast( - MachineOperand::MO_Empty) || - LHS.getType() == static_cast( - MachineOperand::MO_Tombstone)) - return LHS.getType() == RHS.getType(); - return LHS.isIdenticalTo(RHS); - } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand &MO) { - MO.print(OS); - return OS; -} - -// See friend declaration above. This additional declaration is required in -// order to compile LLVM with IBM xlC compiler. -hash_code hash_value(const MachineOperand &MO); -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h deleted file mode 100644 index 285b858c96..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ /dev/null @@ -1,237 +0,0 @@ -///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===// -/// -/// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -/// See https://llvm.org/LICENSE.txt for license information. -/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -/// -///===---------------------------------------------------------------------===// -/// \file -/// Optimization diagnostic interfaces for machine passes. It's packaged as an -/// analysis pass so that by using this service passes become dependent on MBFI -/// as well. MBFI is used to compute the "hotness" of the diagnostic message. -/// -///===---------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H -#define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H - -#include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - -namespace llvm { -class MachineBasicBlock; -class MachineBlockFrequencyInfo; -class MachineInstr; - -/// Common features for diagnostics dealing with optimization remarks -/// that are used by machine passes. -class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase { -public: - DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName, - StringRef RemarkName, - const DiagnosticLocation &Loc, - const MachineBasicBlock *MBB) - : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName, - MBB->getParent()->getFunction(), Loc), - MBB(MBB) {} - - /// MI-specific kinds of diagnostic Arguments. - struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument { - /// Print an entire MachineInstr. - MachineArgument(StringRef Key, const MachineInstr &MI); - }; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() >= DK_FirstMachineRemark && - DI->getKind() <= DK_LastMachineRemark; - } - - const MachineBasicBlock *getBlock() const { return MBB; } - -private: - const MachineBasicBlock *MBB; -}; - -/// Diagnostic information for applied optimization remarks. -class MachineOptimizationRemark : public DiagnosticInfoMIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass=, then the diagnostic will - /// be emitted. \p RemarkName is a textual identifier for the remark. \p - /// Loc is the debug location and \p MBB is the block that the optimization - /// operates in. - MachineOptimizationRemark(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const MachineBasicBlock *MBB) - : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName, - RemarkName, Loc, MBB) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_MachineOptimizationRemark; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { - const Function &Fn = getFunction(); - LLVMContext &Ctx = Fn.getContext(); - return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName()); - } -}; - -/// Diagnostic information for missed-optimization remarks. -class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-missed=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark. \p Loc is the debug location and \p MBB is the block that the - /// optimization operates in. - MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const MachineBasicBlock *MBB) - : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed, - PassName, RemarkName, Loc, MBB) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_MachineOptimizationRemarkMissed; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { - const Function &Fn = getFunction(); - LLVMContext &Ctx = Fn.getContext(); - return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName()); - } -}; - -/// Diagnostic information for optimization analysis remarks. -class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-analysis=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark. \p Loc is the debug location and \p MBB is the block that the - /// optimization operates in. - MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const MachineBasicBlock *MBB) - : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis, - PassName, RemarkName, Loc, MBB) {} - - MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, - const MachineInstr *MI) - : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis, - PassName, RemarkName, MI->getDebugLoc(), - MI->getParent()) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_MachineOptimizationRemarkAnalysis; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { - const Function &Fn = getFunction(); - LLVMContext &Ctx = Fn.getContext(); - return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()); - } -}; - -/// Extend llvm::ore:: with MI-specific helper names. -namespace ore { -using MNV = DiagnosticInfoMIROptimization::MachineArgument; -} - -/// The optimization diagnostic interface. -/// -/// It allows reporting when optimizations are performed and when they are not -/// along with the reasons for it. Hotness information of the corresponding -/// code region can be included in the remark if DiagnosticsHotnessRequested is -/// enabled in the LLVM context. -class MachineOptimizationRemarkEmitter { -public: - MachineOptimizationRemarkEmitter(MachineFunction &MF, - MachineBlockFrequencyInfo *MBFI) - : MF(MF), MBFI(MBFI) {} - - /// Emit an optimization remark. - void emit(DiagnosticInfoOptimizationBase &OptDiag); - - /// Whether we allow for extra compile-time budget to perform more - /// analysis to be more informative. - /// - /// This is useful to enable additional missed optimizations to be reported - /// that are normally too noisy. In this mode, we can use the extra analysis - /// (1) to filter trivial false positives or (2) to provide more context so - /// that non-trivial false positives can be quickly detected by the user. - bool allowExtraAnalysis(StringRef PassName) const { - return ( - MF.getFunction().getContext().getLLVMRemarkStreamer() || - MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled( - PassName)); - } - - /// Take a lambda that returns a remark which will be emitted. Second - /// argument is only used to restrict this to functions. - template - void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { - // Avoid building the remark unless we know there are at least *some* - // remarks enabled. We can't currently check whether remarks are requested - // for the calling pass since that requires actually building the remark. - - if (MF.getFunction().getContext().getLLVMRemarkStreamer() || - MF.getFunction() - .getContext() - .getDiagHandlerPtr() - ->isAnyRemarkEnabled()) { - auto R = RemarkBuilder(); - emit((DiagnosticInfoOptimizationBase &)R); - } - } - - MachineBlockFrequencyInfo *getBFI() { - return MBFI; - } - -private: - MachineFunction &MF; - - /// MBFI is only set if hotness is requested. - MachineBlockFrequencyInfo *MBFI; - - /// Compute hotness from IR value (currently assumed to be a block) if PGO is - /// available. - Optional computeHotness(const MachineBasicBlock &MBB); - - /// Similar but use value from \p OptDiag and update hotness there. - void computeHotness(DiagnosticInfoMIROptimization &Remark); - - /// Only allow verbose messages if we know we're filtering by hotness - /// (BFI is only set in this case). - bool shouldEmitVerbose() { return MBFI != nullptr; } -}; - -/// The analysis pass -/// -/// Note that this pass shouldn't generally be marked as preserved by other -/// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI -/// could be freed. -class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass { - std::unique_ptr ORE; - -public: - MachineOptimizationRemarkEmitterPass(); - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineOptimizationRemarkEmitter &getORE() { - assert(ORE && "pass not run yet"); - return *ORE; - } - - static char ID; -}; -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOutliner.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineOutliner.h deleted file mode 100644 index 08b76295db..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineOutliner.h +++ /dev/null @@ -1,226 +0,0 @@ -//===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Contains all data structures shared between the outliner implemented in -/// MachineOutliner.cpp and target implementations of the outliner. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEOUTLINER_H -#define LLVM_CODEGEN_MACHINEOUTLINER_H - -#include "llvm/CodeGen/LivePhysRegs.h" -#include "llvm/CodeGen/LiveRegUnits.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" - -namespace llvm { -namespace outliner { - -/// Represents how an instruction should be mapped by the outliner. -/// \p Legal instructions are those which are safe to outline. -/// \p LegalTerminator instructions are safe to outline, but only as the -/// last instruction in a sequence. -/// \p Illegal instructions are those which cannot be outlined. -/// \p Invisible instructions are instructions which can be outlined, but -/// shouldn't actually impact the outlining result. -enum InstrType { Legal, LegalTerminator, Illegal, Invisible }; - -/// An individual sequence of instructions to be replaced with a call to -/// an outlined function. -struct Candidate { -private: - /// The start index of this \p Candidate in the instruction list. - unsigned StartIdx = 0; - - /// The number of instructions in this \p Candidate. - unsigned Len = 0; - - // The first instruction in this \p Candidate. - MachineBasicBlock::iterator FirstInst; - - // The last instruction in this \p Candidate. - MachineBasicBlock::iterator LastInst; - - // The basic block that contains this Candidate. - MachineBasicBlock *MBB = nullptr; - - /// Cost of calling an outlined function from this point as defined by the - /// target. - unsigned CallOverhead = 0; - -public: - /// The index of this \p Candidate's \p OutlinedFunction in the list of - /// \p OutlinedFunctions. - unsigned FunctionIdx = 0; - - /// Identifier denoting the instructions to emit to call an outlined function - /// from this point. Defined by the target. - unsigned CallConstructionID = 0; - - /// Contains physical register liveness information for the MBB containing - /// this \p Candidate. - /// - /// This is optionally used by the target to calculate more fine-grained - /// cost model information. - LiveRegUnits LRU; - - /// Contains the accumulated register liveness information for the - /// instructions in this \p Candidate. - /// - /// This is optionally used by the target to determine which registers have - /// been used across the sequence. - LiveRegUnits UsedInSequence; - - /// Target-specific flags for this Candidate's MBB. - unsigned Flags = 0x0; - - /// True if initLRU has been called on this Candidate. - bool LRUWasSet = false; - - /// Return the number of instructions in this Candidate. - unsigned getLength() const { return Len; } - - /// Return the start index of this candidate. - unsigned getStartIdx() const { return StartIdx; } - - /// Return the end index of this candidate. - unsigned getEndIdx() const { return StartIdx + Len - 1; } - - /// Set the CallConstructionID and CallOverhead of this candidate to CID and - /// CO respectively. - void setCallInfo(unsigned CID, unsigned CO) { - CallConstructionID = CID; - CallOverhead = CO; - } - - /// Returns the call overhead of this candidate if it is in the list. - unsigned getCallOverhead() const { return CallOverhead; } - - MachineBasicBlock::iterator &front() { return FirstInst; } - MachineBasicBlock::iterator &back() { return LastInst; } - MachineFunction *getMF() const { return MBB->getParent(); } - MachineBasicBlock *getMBB() const { return MBB; } - - /// The number of instructions that would be saved by outlining every - /// candidate of this type. - /// - /// This is a fixed value which is not updated during the candidate pruning - /// process. It is only used for deciding which candidate to keep if two - /// candidates overlap. The true benefit is stored in the OutlinedFunction - /// for some given candidate. - unsigned Benefit = 0; - - Candidate(unsigned StartIdx, unsigned Len, - MachineBasicBlock::iterator &FirstInst, - MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB, - unsigned FunctionIdx, unsigned Flags) - : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst), - MBB(MBB), FunctionIdx(FunctionIdx), Flags(Flags) {} - Candidate() = default; - - /// Used to ensure that \p Candidates are outlined in an order that - /// preserves the start and end indices of other \p Candidates. - bool operator<(const Candidate &RHS) const { - return getStartIdx() > RHS.getStartIdx(); - } - - /// Compute the registers that are live across this Candidate. - /// Used by targets that need this information for cost model calculation. - /// If a target does not need this information, then this should not be - /// called. - void initLRU(const TargetRegisterInfo &TRI) { - assert(MBB->getParent()->getRegInfo().tracksLiveness() && - "Candidate's Machine Function must track liveness"); - // Only initialize once. - if (LRUWasSet) - return; - LRUWasSet = true; - LRU.init(TRI); - LRU.addLiveOuts(*MBB); - - // Compute liveness from the end of the block up to the beginning of the - // outlining candidate. - std::for_each(MBB->rbegin(), (MachineBasicBlock::reverse_iterator)front(), - [this](MachineInstr &MI) { LRU.stepBackward(MI); }); - - // Walk over the sequence itself and figure out which registers were used - // in the sequence. - UsedInSequence.init(TRI); - std::for_each(front(), std::next(back()), - [this](MachineInstr &MI) { UsedInSequence.accumulate(MI); }); - } -}; - -/// The information necessary to create an outlined function for some -/// class of candidate. -struct OutlinedFunction { - -public: - std::vector Candidates; - - /// The actual outlined function created. - /// This is initialized after we go through and create the actual function. - MachineFunction *MF = nullptr; - - /// Represents the size of a sequence in bytes. (Some instructions vary - /// widely in size, so just counting the instructions isn't very useful.) - unsigned SequenceSize = 0; - - /// Target-defined overhead of constructing a frame for this function. - unsigned FrameOverhead = 0; - - /// Target-defined identifier for constructing a frame for this function. - unsigned FrameConstructionID = 0; - - /// Return the number of candidates for this \p OutlinedFunction. - unsigned getOccurrenceCount() const { return Candidates.size(); } - - /// Return the number of bytes it would take to outline this - /// function. - unsigned getOutliningCost() const { - unsigned CallOverhead = 0; - for (const Candidate &C : Candidates) - CallOverhead += C.getCallOverhead(); - return CallOverhead + SequenceSize + FrameOverhead; - } - - /// Return the size in bytes of the unoutlined sequences. - unsigned getNotOutlinedCost() const { - return getOccurrenceCount() * SequenceSize; - } - - /// Return the number of instructions that would be saved by outlining - /// this function. - unsigned getBenefit() const { - unsigned NotOutlinedCost = getNotOutlinedCost(); - unsigned OutlinedCost = getOutliningCost(); - return (NotOutlinedCost < OutlinedCost) ? 0 - : NotOutlinedCost - OutlinedCost; - } - - /// Return the number of instructions in this sequence. - unsigned getNumInstrs() const { return Candidates[0].getLength(); } - - OutlinedFunction(std::vector &Candidates, unsigned SequenceSize, - unsigned FrameOverhead, unsigned FrameConstructionID) - : Candidates(Candidates), SequenceSize(SequenceSize), - FrameOverhead(FrameOverhead), FrameConstructionID(FrameConstructionID) { - const unsigned B = getBenefit(); - for (Candidate &C : Candidates) - C.Benefit = B; - } - - OutlinedFunction() = default; -}; -} // namespace outliner -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassManager.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassManager.h deleted file mode 100644 index 1f1dddba02..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassManager.h +++ /dev/null @@ -1,255 +0,0 @@ -//===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header defines the pass manager interface for codegen. The codegen -// pipeline consists of only machine function passes. There is no container -// relationship between IR module/function and machine function in terms of pass -// manager organization. So there is no need for adaptor classes (for example -// ModuleToMachineFunctionAdaptor). Since invalidation could only happen among -// machine function passes, there is no proxy classes to handle cross-IR-unit -// invalidation. IR analysis results are provided for machine function passes by -// their respective analysis managers such as ModuleAnalysisManager and -// FunctionAnalysisManager. -// -// TODO: Add MachineFunctionProperties support. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H -#define LLVM_CODEGEN_MACHINEPASSMANAGER_H - -#include "llvm/ADT/FunctionExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/IR/PassManager.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/type_traits.h" - -namespace llvm { -class Module; - -extern template class AnalysisManager; - -/// An AnalysisManager that also exposes IR analysis results. -class MachineFunctionAnalysisManager : public AnalysisManager { -public: - using Base = AnalysisManager; - - MachineFunctionAnalysisManager() : FAM(nullptr), MAM(nullptr) {} - MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM, - ModuleAnalysisManager &MAM) - : FAM(&FAM), MAM(&MAM) {} - MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default; - MachineFunctionAnalysisManager & - operator=(MachineFunctionAnalysisManager &&) = default; - - /// Get the result of an analysis pass for a Function. - /// - /// Runs the analysis if a cached result is not available. - template typename PassT::Result &getResult(Function &F) { - return FAM->getResult(F); - } - - /// Get the cached result of an analysis pass for a Function. - /// - /// This method never runs the analysis. - /// - /// \returns null if there is no cached result. - template - typename PassT::Result *getCachedResult(Function &F) { - return FAM->getCachedResult(F); - } - - /// Get the result of an analysis pass for a Module. - /// - /// Runs the analysis if a cached result is not available. - template typename PassT::Result &getResult(Module &M) { - return MAM->getResult(M); - } - - /// Get the cached result of an analysis pass for a Module. - /// - /// This method never runs the analysis. - /// - /// \returns null if there is no cached result. - template typename PassT::Result *getCachedResult(Module &M) { - return MAM->getCachedResult(M); - } - - /// Get the result of an analysis pass for a MachineFunction. - /// - /// Runs the analysis if a cached result is not available. - using Base::getResult; - - /// Get the cached result of an analysis pass for a MachineFunction. - /// - /// This method never runs the analysis. - /// - /// returns null if there is no cached result. - using Base::getCachedResult; - - // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed. - FunctionAnalysisManager *FAM; - ModuleAnalysisManager *MAM; -}; - -extern template class PassManager; - -/// MachineFunctionPassManager adds/removes below features to/from the base -/// PassManager template instantiation. -/// -/// - Support passes that implement doInitialization/doFinalization. This is for -/// machine function passes to work on module level constructs. One such pass -/// is AsmPrinter. -/// -/// - Support machine module pass which runs over the module (for example, -/// MachineOutliner). A machine module pass needs to define the method: -/// -/// ```Error run(Module &, MachineFunctionAnalysisManager &)``` -/// -/// FIXME: machine module passes still need to define the usual machine -/// function pass interface, namely, -/// `PreservedAnalyses run(MachineFunction &, -/// MachineFunctionAnalysisManager &)` -/// But this interface wouldn't be executed. It is just a placeholder -/// to satisfy the pass manager type-erased interface. This -/// special-casing of machine module pass is due to its limited use -/// cases and the unnecessary complexity it may bring to the machine -/// pass manager. -/// -/// - The base class `run` method is replaced by an alternative `run` method. -/// See details below. -/// -/// - Support codegening in the SCC order. Users include interprocedural -/// register allocation (IPRA). -class MachineFunctionPassManager - : public PassManager { - using Base = PassManager; - -public: - MachineFunctionPassManager(bool DebugLogging = false, - bool RequireCodeGenSCCOrder = false, - bool VerifyMachineFunction = false) - : RequireCodeGenSCCOrder(RequireCodeGenSCCOrder), - VerifyMachineFunction(VerifyMachineFunction) {} - MachineFunctionPassManager(MachineFunctionPassManager &&) = default; - MachineFunctionPassManager & - operator=(MachineFunctionPassManager &&) = default; - - /// Run machine passes for a Module. - /// - /// The intended use is to start the codegen pipeline for a Module. The base - /// class's `run` method is deliberately hidden by this due to the observation - /// that we don't yet have the use cases of compositing two instances of - /// machine pass managers, or compositing machine pass managers with other - /// types of pass managers. - Error run(Module &M, MachineFunctionAnalysisManager &MFAM); - - template void addPass(PassT &&Pass) { - Base::addPass(std::forward(Pass)); - PassConceptT *P = Passes.back().get(); - addDoInitialization(P); - addDoFinalization(P); - - // Add machine module pass. - addRunOnModule(P); - } - -private: - template - using has_init_t = decltype(std::declval().doInitialization( - std::declval(), - std::declval())); - - template - std::enable_if_t::value> - addDoInitialization(PassConceptT *Pass) {} - - template - std::enable_if_t::value> - addDoInitialization(PassConceptT *Pass) { - using PassModelT = - detail::PassModel; - auto *P = static_cast(Pass); - InitializationFuncs.emplace_back( - [=](Module &M, MachineFunctionAnalysisManager &MFAM) { - return P->Pass.doInitialization(M, MFAM); - }); - } - - template - using has_fini_t = decltype(std::declval().doFinalization( - std::declval(), - std::declval())); - - template - std::enable_if_t::value> - addDoFinalization(PassConceptT *Pass) {} - - template - std::enable_if_t::value> - addDoFinalization(PassConceptT *Pass) { - using PassModelT = - detail::PassModel; - auto *P = static_cast(Pass); - FinalizationFuncs.emplace_back( - [=](Module &M, MachineFunctionAnalysisManager &MFAM) { - return P->Pass.doFinalization(M, MFAM); - }); - } - - template - using is_machine_module_pass_t = decltype(std::declval().run( - std::declval(), - std::declval())); - - template - using is_machine_function_pass_t = decltype(std::declval().run( - std::declval(), - std::declval())); - - template - std::enable_if_t::value> - addRunOnModule(PassConceptT *Pass) {} - - template - std::enable_if_t::value> - addRunOnModule(PassConceptT *Pass) { - static_assert(is_detected::value, - "machine module pass needs to define machine function pass " - "api. sorry."); - - using PassModelT = - detail::PassModel; - auto *P = static_cast(Pass); - MachineModulePasses.emplace( - Passes.size() - 1, - [=](Module &M, MachineFunctionAnalysisManager &MFAM) { - return P->Pass.run(M, MFAM); - }); - } - - using FuncTy = Error(Module &, MachineFunctionAnalysisManager &); - SmallVector, 4> InitializationFuncs; - SmallVector, 4> FinalizationFuncs; - - using PassIndex = decltype(Passes)::size_type; - std::map> MachineModulePasses; - - // Run codegen in the SCC order. - bool RequireCodeGenSCCOrder; - - bool VerifyMachineFunction; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.def b/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.def deleted file mode 100644 index e6763899a0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.def +++ /dev/null @@ -1,202 +0,0 @@ -//===- MachinePassRegistry.def - Registry of passes -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is used as the registry of passes that are for target-independent -// code generator. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -#ifndef MODULE_ANALYSIS -#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) -#undef MODULE_ANALYSIS - -#ifndef MODULE_PASS -#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass, ()) -#undef MODULE_PASS - -#ifndef FUNCTION_ANALYSIS -#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) -FUNCTION_ANALYSIS("targetir", TargetIRAnalysis, (std::move(TM.getTargetIRAnalysis()))) -#undef FUNCTION_ANALYSIS - -#ifndef FUNCTION_PASS -#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -FUNCTION_PASS("mergeicmps", MergeICmpsPass, ()) -FUNCTION_PASS("lower-constant-intrinsics", LowerConstantIntrinsicsPass, ()) -FUNCTION_PASS("unreachableblockelim", UnreachableBlockElimPass, ()) -FUNCTION_PASS("consthoist", ConstantHoistingPass, ()) -FUNCTION_PASS("replace-with-veclib", ReplaceWithVeclib, ()) -FUNCTION_PASS("partially-inline-libcalls", PartiallyInlineLibCallsPass, ()) -FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass, (false)) -FUNCTION_PASS("post-inline-ee-instrument", EntryExitInstrumenterPass, (true)) -FUNCTION_PASS("expand-reductions", ExpandReductionsPass, ()) -FUNCTION_PASS("expandvp", ExpandVectorPredicationPass, ()) -FUNCTION_PASS("lowerinvoke", LowerInvokePass, ()) -FUNCTION_PASS("scalarize-masked-mem-intrin", ScalarizeMaskedMemIntrinPass, ()) -FUNCTION_PASS("verify", VerifierPass, ()) -#undef FUNCTION_PASS - -#ifndef LOOP_PASS -#define LOOP_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -LOOP_PASS("loop-reduce", LoopStrengthReducePass, ()) -#undef LOOP_PASS - -#ifndef MACHINE_MODULE_PASS -#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -#undef MACHINE_MODULE_PASS - -#ifndef MACHINE_FUNCTION_ANALYSIS -#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -MACHINE_FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) -// LiveVariables currently requires pure SSA form. -// FIXME: Once TwoAddressInstruction pass no longer uses kill flags, -// LiveVariables can be removed completely, and LiveIntervals can be directly -// computed. (We still either need to regenerate kill flags after regalloc, or -// preferably fix the scavenger to not depend on them). -// MACHINE_FUNCTION_ANALYSIS("live-vars", LiveVariablesAnalysis()) - -// MACHINE_FUNCTION_ANALYSIS("live-stacks", LiveStacksPass()) -// MACHINE_FUNCTION_ANALYSIS("slot-indexes", SlotIndexesAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("edge-bundles", EdgeBundlesAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("lazy-machine-bfi", LazyMachineBlockFrequencyInfoAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-bfi", MachineBlockFrequencyInfoAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-loops", MachineLoopInfoAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-dom-frontier", MachineDominanceFrontierAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-dom-tree", MachineDominatorTreeAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-ore", MachineOptimizationRemarkEmitterPassAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-post-dom-tree", MachinePostDominatorTreeAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-region-info", MachineRegionInfoPassAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("machine-trace-metrics", MachineTraceMetricsAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("reaching-def", ReachingDefAnalysisAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("live-reg-matrix", LiveRegMatrixAnalysis()) -// MACHINE_FUNCTION_ANALYSIS("gc-analysis", GCMachineCodeAnalysisPass()) -#undef MACHINE_FUNCTION_ANALYSIS - -#ifndef MACHINE_FUNCTION_PASS -#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -// MACHINE_FUNCTION_PASS("mir-printer", PrintMIRPass, ()) -// MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass, ()) -#undef MACHINE_FUNCTION_PASS - -// After a pass is converted to new pass manager, its entry should be moved from -// dummy table to the normal one. For example, for a machine function pass, -// DUMMY_MACHINE_FUNCTION_PASS to MACHINE_FUNCTION_PASS. - -#ifndef DUMMY_FUNCTION_PASS -#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -DUMMY_FUNCTION_PASS("expandmemcmp", ExpandMemCmpPass, ()) -DUMMY_FUNCTION_PASS("gc-lowering", GCLoweringPass, ()) -DUMMY_FUNCTION_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass, ()) -DUMMY_FUNCTION_PASS("sjljehprepare", SjLjEHPreparePass, ()) -DUMMY_FUNCTION_PASS("dwarfehprepare", DwarfEHPass, ()) -DUMMY_FUNCTION_PASS("winehprepare", WinEHPass, ()) -DUMMY_FUNCTION_PASS("wasmehprepare", WasmEHPass, ()) -DUMMY_FUNCTION_PASS("codegenprepare", CodeGenPreparePass, ()) -DUMMY_FUNCTION_PASS("safe-stack", SafeStackPass, ()) -DUMMY_FUNCTION_PASS("stack-protector", StackProtectorPass, ()) -DUMMY_FUNCTION_PASS("atomic-expand", AtomicExpandPass, ()) -DUMMY_FUNCTION_PASS("interleaved-access", InterleavedAccessPass, ()) -DUMMY_FUNCTION_PASS("indirectbr-expand", IndirectBrExpandPass, ()) -DUMMY_FUNCTION_PASS("cfguard-dispatch", CFGuardDispatchPass, ()) -DUMMY_FUNCTION_PASS("cfguard-check", CFGuardCheckPass, ()) -DUMMY_FUNCTION_PASS("gc-info-printer", GCInfoPrinterPass, ()) -#undef DUMMY_FUNCTION_PASS - -#ifndef DUMMY_MODULE_PASS -#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -DUMMY_MODULE_PASS("lower-emutls", LowerEmuTLSPass, ()) -#undef DUMMY_MODULE_PASS - -#ifndef DUMMY_MACHINE_MODULE_PASS -#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -DUMMY_MACHINE_MODULE_PASS("machine-outliner", MachineOutlinerPass, ()) -#undef DUMMY_MACHINE_MODULE_PASS - -#ifndef DUMMY_MACHINE_FUNCTION_PASS -#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) -#endif -DUMMY_MACHINE_FUNCTION_PASS("mir-printer", PrintMIRPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("finalize-isel", FinalizeISelPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("localstackalloc", LocalStackSlotPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("shrink-wrap", ShrinkWrapPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("prologepilog", PrologEpilogInserterPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("postrapseudos", ExpandPostRAPseudosPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("implicit-null-checks", ImplicitNullChecksPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("postmisched", PostMachineSchedulerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-scheduler", MachineSchedulerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("post-RA-sched", PostRASchedulerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("fentry-insert", FEntryInserterPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("xray-instrumentation", XRayInstrumentationPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("patchable-function", PatchableFunctionPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("reg-usage-propagation", RegUsageInfoPropagationPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("removeredundantdebugvalues", RemoveRedundantDebugValuesPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass, ()) -DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("stack-coloring", StackColoringPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("dead-mi-elimination", DeadMachineInstructionElimPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("early-machinelicm", EarlyMachineLICMPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machinelicm", MachineLICMPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-cse", MachineCSEPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-sink", MachineSinkingPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("postra-machine-sink", PostRAMachineSinkingPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("peephole-opt", PeepholeOptimizerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("regalloc", RegAllocPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("virtregrewriter", VirtRegRewriterPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("stack-slot-coloring", StackSlotColoringPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("phi-node-elimination", PHIEliminationPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("twoaddressinstruction", TwoAddressInstructionPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("detect-dead-lanes", DetectDeadLanesPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("processimpdefs", ProcessImplicitDefsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("liveintervals", LiveIntervalsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("simple-register-coalescing", RegisterCoalescerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("rename-independent-subregs", RenameIndependentSubregsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("branch-folder", BranchFolderPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("tailduplication", TailDuplicatePass, ()) -DUMMY_MACHINE_FUNCTION_PASS("block-placement", MachineBlockPlacementPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("block-placement-stats", MachineBlockPlacementStatsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("early-ifcvt", EarlyIfConverterPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-combiner", MachineCombinerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("lrshrink", LiveRangeShrinkPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("break-false-deps", BreakFalseDepsPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("cfi-instr-inserter", CFIInstrInserterPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("cfguard-longjmp", CFGuardLongjmpPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("ra-fast", RAFastPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("ra-greedy", RAGreedyPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("legalizer", LegalizerPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("irtranslator", IRTranslatorPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("regbankselect", RegBankSelectPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function", ResetMachineFunctionPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machineverifier", MachineVerifierPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("machine-cycles", MachineCycleInfoWrapperPass, ()) -DUMMY_MACHINE_FUNCTION_PASS("print-machine-cycles", MachineCycleInfoPrinterPass, ()) -#undef DUMMY_MACHINE_FUNCTION_PASS diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.h deleted file mode 100644 index f5b3723db0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePassRegistry.h +++ /dev/null @@ -1,171 +0,0 @@ -//===- llvm/CodeGen/MachinePassRegistry.h -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the mechanics for machine function pass registries. A -// function pass registry (MachinePassRegistry) is auto filled by the static -// constructors of MachinePassRegistryNode. Further there is a command line -// parser (RegisterPassParser) which listens to each registry for additions -// and deletions, so that the appropriate command option is updated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H -#define LLVM_CODEGEN_MACHINEPASSREGISTRY_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Support/CommandLine.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -/// -/// MachinePassRegistryListener - Listener to adds and removals of nodes in -/// registration list. -/// -//===----------------------------------------------------------------------===// -template class MachinePassRegistryListener { - virtual void anchor() {} - -public: - MachinePassRegistryListener() = default; - virtual ~MachinePassRegistryListener() = default; - - virtual void NotifyAdd(StringRef N, PassCtorTy C, StringRef D) = 0; - virtual void NotifyRemove(StringRef N) = 0; -}; - -//===----------------------------------------------------------------------===// -/// -/// MachinePassRegistryNode - Machine pass node stored in registration list. -/// -//===----------------------------------------------------------------------===// -template class MachinePassRegistryNode { -private: - MachinePassRegistryNode *Next = nullptr; // Next function pass in list. - StringRef Name; // Name of function pass. - StringRef Description; // Description string. - PassCtorTy Ctor; // Pass creator. - -public: - MachinePassRegistryNode(const char *N, const char *D, PassCtorTy C) - : Name(N), Description(D), Ctor(C) {} - - // Accessors - MachinePassRegistryNode *getNext() const { return Next; } - MachinePassRegistryNode **getNextAddress() { return &Next; } - StringRef getName() const { return Name; } - StringRef getDescription() const { return Description; } - PassCtorTy getCtor() const { return Ctor; } - void setNext(MachinePassRegistryNode *N) { Next = N; } -}; - -//===----------------------------------------------------------------------===// -/// -/// MachinePassRegistry - Track the registration of machine passes. -/// -//===----------------------------------------------------------------------===// -template class MachinePassRegistry { -private: - MachinePassRegistryNode *List; // List of registry nodes. - PassCtorTy Default; // Default function pass creator. - MachinePassRegistryListener - *Listener; // Listener for list adds are removes. - -public: - // NO CONSTRUCTOR - we don't want static constructor ordering to mess - // with the registry. - - // Accessors. - // - MachinePassRegistryNode *getList() { return List; } - PassCtorTy getDefault() { return Default; } - void setDefault(PassCtorTy C) { Default = C; } - /// setDefault - Set the default constructor by name. - void setDefault(StringRef Name) { - PassCtorTy Ctor = nullptr; - for (MachinePassRegistryNode *R = getList(); R; - R = R->getNext()) { - if (R->getName() == Name) { - Ctor = R->getCtor(); - break; - } - } - assert(Ctor && "Unregistered pass name"); - setDefault(Ctor); - } - void setListener(MachinePassRegistryListener *L) { Listener = L; } - - /// Add - Adds a function pass to the registration list. - /// - void Add(MachinePassRegistryNode *Node) { - Node->setNext(List); - List = Node; - if (Listener) - Listener->NotifyAdd(Node->getName(), Node->getCtor(), - Node->getDescription()); - } - - /// Remove - Removes a function pass from the registration list. - /// - void Remove(MachinePassRegistryNode *Node) { - for (MachinePassRegistryNode **I = &List; *I; - I = (*I)->getNextAddress()) { - if (*I == Node) { - if (Listener) - Listener->NotifyRemove(Node->getName()); - *I = (*I)->getNext(); - break; - } - } - } -}; - -//===----------------------------------------------------------------------===// -/// -/// RegisterPassParser class - Handle the addition of new machine passes. -/// -//===----------------------------------------------------------------------===// -template -class RegisterPassParser - : public MachinePassRegistryListener< - typename RegistryClass::FunctionPassCtor>, - public cl::parser { -public: - RegisterPassParser(cl::Option &O) - : cl::parser(O) {} - ~RegisterPassParser() override { RegistryClass::setListener(nullptr); } - - void initialize() { - cl::parser::initialize(); - - // Add existing passes to option. - for (RegistryClass *Node = RegistryClass::getList(); - Node; Node = Node->getNext()) { - this->addLiteralOption(Node->getName(), - (typename RegistryClass::FunctionPassCtor)Node->getCtor(), - Node->getDescription()); - } - - // Make sure we listen for list changes. - RegistryClass::setListener(this); - } - - // Implement the MachinePassRegistryListener callbacks. - void NotifyAdd(StringRef N, typename RegistryClass::FunctionPassCtor C, - StringRef D) override { - this->addLiteralOption(N, C, D); - } - void NotifyRemove(StringRef N) override { - this->removeLiteralOption(N); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEPASSREGISTRY_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePipeliner.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachinePipeliner.h deleted file mode 100644 index 1237005fa2..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePipeliner.h +++ /dev/null @@ -1,601 +0,0 @@ -//===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// An implementation of the Swing Modulo Scheduling (SMS) software pipeliner. -// -// Software pipelining (SWP) is an instruction scheduling technique for loops -// that overlap loop iterations and exploits ILP via a compiler transformation. -// -// Swing Modulo Scheduling is an implementation of software pipelining -// that generates schedules that are near optimal in terms of initiation -// interval, register requirements, and stage count. See the papers: -// -// "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa, -// A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Proceedings of the 1996 -// Conference on Parallel Architectures and Compilation Techniques. -// -// "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J. -// Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE -// Transactions on Computers, Vol. 50, No. 3, 2001. -// -// "An Implementation of Swing Modulo Scheduling With Extensions for -// Superblocks", by T. Lattner, Master's Thesis, University of Illinois at -// Urbana-Champaign, 2005. -// -// -// The SMS algorithm consists of three main steps after computing the minimal -// initiation interval (MII). -// 1) Analyze the dependence graph and compute information about each -// instruction in the graph. -// 2) Order the nodes (instructions) by priority based upon the heuristics -// described in the algorithm. -// 3) Attempt to schedule the nodes in the specified order using the MII. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINEPIPELINER_H -#define LLVM_CODEGEN_MACHINEPIPELINER_H - -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/CodeGen/RegisterClassInfo.h" -#include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/InitializePasses.h" - -namespace llvm { - -class AAResults; -class NodeSet; -class SMSchedule; - -extern cl::opt SwpEnableCopyToPhi; - -/// The main class in the implementation of the target independent -/// software pipeliner pass. -class MachinePipeliner : public MachineFunctionPass { -public: - MachineFunction *MF = nullptr; - MachineOptimizationRemarkEmitter *ORE = nullptr; - const MachineLoopInfo *MLI = nullptr; - const MachineDominatorTree *MDT = nullptr; - const InstrItineraryData *InstrItins; - const TargetInstrInfo *TII = nullptr; - RegisterClassInfo RegClassInfo; - bool disabledByPragma = false; - unsigned II_setByPragma = 0; - -#ifndef NDEBUG - static int NumTries; -#endif - - /// Cache the target analysis information about the loop. - struct LoopInfo { - MachineBasicBlock *TBB = nullptr; - MachineBasicBlock *FBB = nullptr; - SmallVector BrCond; - MachineInstr *LoopInductionVar = nullptr; - MachineInstr *LoopCompare = nullptr; - }; - LoopInfo LI; - - static char ID; - - MachinePipeliner() : MachineFunctionPass(ID) { - initializeMachinePipelinerPass(*PassRegistry::getPassRegistry()); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - -private: - void preprocessPhiNodes(MachineBasicBlock &B); - bool canPipelineLoop(MachineLoop &L); - bool scheduleLoop(MachineLoop &L); - bool swingModuloScheduler(MachineLoop &L); - void setPragmaPipelineOptions(MachineLoop &L); -}; - -/// This class builds the dependence graph for the instructions in a loop, -/// and attempts to schedule the instructions using the SMS algorithm. -class SwingSchedulerDAG : public ScheduleDAGInstrs { - MachinePipeliner &Pass; - /// The minimum initiation interval between iterations for this schedule. - unsigned MII = 0; - /// The maximum initiation interval between iterations for this schedule. - unsigned MAX_II = 0; - /// Set to true if a valid pipelined schedule is found for the loop. - bool Scheduled = false; - MachineLoop &Loop; - LiveIntervals &LIS; - const RegisterClassInfo &RegClassInfo; - unsigned II_setByPragma = 0; - - /// A toplogical ordering of the SUnits, which is needed for changing - /// dependences and iterating over the SUnits. - ScheduleDAGTopologicalSort Topo; - - struct NodeInfo { - int ASAP = 0; - int ALAP = 0; - int ZeroLatencyDepth = 0; - int ZeroLatencyHeight = 0; - - NodeInfo() = default; - }; - /// Computed properties for each node in the graph. - std::vector ScheduleInfo; - - enum OrderKind { BottomUp = 0, TopDown = 1 }; - /// Computed node ordering for scheduling. - SetVector NodeOrder; - - using NodeSetType = SmallVector; - using ValueMapTy = DenseMap; - using MBBVectorTy = SmallVectorImpl; - using InstrMapTy = DenseMap; - - /// Instructions to change when emitting the final schedule. - DenseMap> InstrChanges; - - /// We may create a new instruction, so remember it because it - /// must be deleted when the pass is finished. - DenseMap NewMIs; - - /// Ordered list of DAG postprocessing steps. - std::vector> Mutations; - - /// Helper class to implement Johnson's circuit finding algorithm. - class Circuits { - std::vector &SUnits; - SetVector Stack; - BitVector Blocked; - SmallVector, 10> B; - SmallVector, 16> AdjK; - // Node to Index from ScheduleDAGTopologicalSort - std::vector *Node2Idx; - unsigned NumPaths; - static unsigned MaxPaths; - - public: - Circuits(std::vector &SUs, ScheduleDAGTopologicalSort &Topo) - : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) { - Node2Idx = new std::vector(SUs.size()); - unsigned Idx = 0; - for (const auto &NodeNum : Topo) - Node2Idx->at(NodeNum) = Idx++; - } - - ~Circuits() { delete Node2Idx; } - - /// Reset the data structures used in the circuit algorithm. - void reset() { - Stack.clear(); - Blocked.reset(); - B.assign(SUnits.size(), SmallPtrSet()); - NumPaths = 0; - } - - void createAdjacencyStructure(SwingSchedulerDAG *DAG); - bool circuit(int V, int S, NodeSetType &NodeSets, bool HasBackedge = false); - void unblock(int U); - }; - - struct CopyToPhiMutation : public ScheduleDAGMutation { - void apply(ScheduleDAGInstrs *DAG) override; - }; - -public: - SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis, - const RegisterClassInfo &rci, unsigned II) - : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis), - RegClassInfo(rci), II_setByPragma(II), Topo(SUnits, &ExitSU) { - P.MF->getSubtarget().getSMSMutations(Mutations); - if (SwpEnableCopyToPhi) - Mutations.push_back(std::make_unique()); - } - - void schedule() override; - void finishBlock() override; - - /// Return true if the loop kernel has been scheduled. - bool hasNewSchedule() { return Scheduled; } - - /// Return the earliest time an instruction may be scheduled. - int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; } - - /// Return the latest time an instruction my be scheduled. - int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; } - - /// The mobility function, which the number of slots in which - /// an instruction may be scheduled. - int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); } - - /// The depth, in the dependence graph, for a node. - unsigned getDepth(SUnit *Node) { return Node->getDepth(); } - - /// The maximum unweighted length of a path from an arbitrary node to the - /// given node in which each edge has latency 0 - int getZeroLatencyDepth(SUnit *Node) { - return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth; - } - - /// The height, in the dependence graph, for a node. - unsigned getHeight(SUnit *Node) { return Node->getHeight(); } - - /// The maximum unweighted length of a path from the given node to an - /// arbitrary node in which each edge has latency 0 - int getZeroLatencyHeight(SUnit *Node) { - return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight; - } - - /// Return true if the dependence is a back-edge in the data dependence graph. - /// Since the DAG doesn't contain cycles, we represent a cycle in the graph - /// using an anti dependence from a Phi to an instruction. - bool isBackedge(SUnit *Source, const SDep &Dep) { - if (Dep.getKind() != SDep::Anti) - return false; - return Source->getInstr()->isPHI() || Dep.getSUnit()->getInstr()->isPHI(); - } - - bool isLoopCarriedDep(SUnit *Source, const SDep &Dep, bool isSucc = true); - - /// The distance function, which indicates that operation V of iteration I - /// depends on operations U of iteration I-distance. - unsigned getDistance(SUnit *U, SUnit *V, const SDep &Dep) { - // Instructions that feed a Phi have a distance of 1. Computing larger - // values for arrays requires data dependence information. - if (V->getInstr()->isPHI() && Dep.getKind() == SDep::Anti) - return 1; - return 0; - } - - void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule); - - void fixupRegisterOverlaps(std::deque &Instrs); - - /// Return the new base register that was stored away for the changed - /// instruction. - unsigned getInstrBaseReg(SUnit *SU) { - DenseMap>::iterator It = - InstrChanges.find(SU); - if (It != InstrChanges.end()) - return It->second.first; - return 0; - } - - void addMutation(std::unique_ptr Mutation) { - Mutations.push_back(std::move(Mutation)); - } - - static bool classof(const ScheduleDAGInstrs *DAG) { return true; } - -private: - void addLoopCarriedDependences(AAResults *AA); - void updatePhiDependences(); - void changeDependences(); - unsigned calculateResMII(); - unsigned calculateRecMII(NodeSetType &RecNodeSets); - void findCircuits(NodeSetType &NodeSets); - void fuseRecs(NodeSetType &NodeSets); - void removeDuplicateNodes(NodeSetType &NodeSets); - void computeNodeFunctions(NodeSetType &NodeSets); - void registerPressureFilter(NodeSetType &NodeSets); - void colocateNodeSets(NodeSetType &NodeSets); - void checkNodeSets(NodeSetType &NodeSets); - void groupRemainingNodes(NodeSetType &NodeSets); - void addConnectedNodes(SUnit *SU, NodeSet &NewSet, - SetVector &NodesAdded); - void computeNodeOrder(NodeSetType &NodeSets); - void checkValidNodeOrder(const NodeSetType &Circuits) const; - bool schedulePipeline(SMSchedule &Schedule); - bool computeDelta(MachineInstr &MI, unsigned &Delta); - MachineInstr *findDefInLoop(Register Reg); - bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos, - unsigned &OffsetPos, unsigned &NewBase, - int64_t &NewOffset); - void postprocessDAG(); - /// Set the Minimum Initiation Interval for this schedule attempt. - void setMII(unsigned ResMII, unsigned RecMII); - /// Set the Maximum Initiation Interval for this schedule attempt. - void setMAX_II(); -}; - -/// A NodeSet contains a set of SUnit DAG nodes with additional information -/// that assigns a priority to the set. -class NodeSet { - SetVector Nodes; - bool HasRecurrence = false; - unsigned RecMII = 0; - int MaxMOV = 0; - unsigned MaxDepth = 0; - unsigned Colocate = 0; - SUnit *ExceedPressure = nullptr; - unsigned Latency = 0; - -public: - using iterator = SetVector::const_iterator; - - NodeSet() = default; - NodeSet(iterator S, iterator E) : Nodes(S, E), HasRecurrence(true) { - Latency = 0; - for (unsigned i = 0, e = Nodes.size(); i < e; ++i) { - DenseMap SuccSUnitLatency; - for (const SDep &Succ : Nodes[i]->Succs) { - auto SuccSUnit = Succ.getSUnit(); - if (!Nodes.count(SuccSUnit)) - continue; - unsigned CurLatency = Succ.getLatency(); - unsigned MaxLatency = 0; - if (SuccSUnitLatency.count(SuccSUnit)) - MaxLatency = SuccSUnitLatency[SuccSUnit]; - if (CurLatency > MaxLatency) - SuccSUnitLatency[SuccSUnit] = CurLatency; - } - for (auto SUnitLatency : SuccSUnitLatency) - Latency += SUnitLatency.second; - } - } - - bool insert(SUnit *SU) { return Nodes.insert(SU); } - - void insert(iterator S, iterator E) { Nodes.insert(S, E); } - - template bool remove_if(UnaryPredicate P) { - return Nodes.remove_if(P); - } - - unsigned count(SUnit *SU) const { return Nodes.count(SU); } - - bool hasRecurrence() { return HasRecurrence; }; - - unsigned size() const { return Nodes.size(); } - - bool empty() const { return Nodes.empty(); } - - SUnit *getNode(unsigned i) const { return Nodes[i]; }; - - void setRecMII(unsigned mii) { RecMII = mii; }; - - void setColocate(unsigned c) { Colocate = c; }; - - void setExceedPressure(SUnit *SU) { ExceedPressure = SU; } - - bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; } - - int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; } - - int getRecMII() { return RecMII; } - - /// Summarize node functions for the entire node set. - void computeNodeSetInfo(SwingSchedulerDAG *SSD) { - for (SUnit *SU : *this) { - MaxMOV = std::max(MaxMOV, SSD->getMOV(SU)); - MaxDepth = std::max(MaxDepth, SSD->getDepth(SU)); - } - } - - unsigned getLatency() { return Latency; } - - unsigned getMaxDepth() { return MaxDepth; } - - void clear() { - Nodes.clear(); - RecMII = 0; - HasRecurrence = false; - MaxMOV = 0; - MaxDepth = 0; - Colocate = 0; - ExceedPressure = nullptr; - } - - operator SetVector &() { return Nodes; } - - /// Sort the node sets by importance. First, rank them by recurrence MII, - /// then by mobility (least mobile done first), and finally by depth. - /// Each node set may contain a colocate value which is used as the first - /// tie breaker, if it's set. - bool operator>(const NodeSet &RHS) const { - if (RecMII == RHS.RecMII) { - if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate) - return Colocate < RHS.Colocate; - if (MaxMOV == RHS.MaxMOV) - return MaxDepth > RHS.MaxDepth; - return MaxMOV < RHS.MaxMOV; - } - return RecMII > RHS.RecMII; - } - - bool operator==(const NodeSet &RHS) const { - return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV && - MaxDepth == RHS.MaxDepth; - } - - bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); } - - iterator begin() { return Nodes.begin(); } - iterator end() { return Nodes.end(); } - void print(raw_ostream &os) const; - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const; -#endif -}; - -// 16 was selected based on the number of ProcResource kinds for all -// existing Subtargets, so that SmallVector don't need to resize too often. -static const int DefaultProcResSize = 16; - -class ResourceManager { -private: - const MCSubtargetInfo *STI; - const MCSchedModel &SM; - const bool UseDFA; - std::unique_ptr DFAResources; - /// Each processor resource is associated with a so-called processor resource - /// mask. This vector allows to correlate processor resource IDs with - /// processor resource masks. There is exactly one element per each processor - /// resource declared by the scheduling model. - llvm::SmallVector ProcResourceMasks; - - llvm::SmallVector ProcResourceCount; - -public: - ResourceManager(const TargetSubtargetInfo *ST) - : STI(ST), SM(ST->getSchedModel()), UseDFA(ST->useDFAforSMS()), - ProcResourceMasks(SM.getNumProcResourceKinds(), 0), - ProcResourceCount(SM.getNumProcResourceKinds(), 0) { - if (UseDFA) - DFAResources.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST)); - initProcResourceVectors(SM, ProcResourceMasks); - } - - void initProcResourceVectors(const MCSchedModel &SM, - SmallVectorImpl &Masks); - /// Check if the resources occupied by a MCInstrDesc are available in - /// the current state. - bool canReserveResources(const MCInstrDesc *MID) const; - - /// Reserve the resources occupied by a MCInstrDesc and change the current - /// state to reflect that change. - void reserveResources(const MCInstrDesc *MID); - - /// Check if the resources occupied by a machine instruction are available - /// in the current state. - bool canReserveResources(const MachineInstr &MI) const; - - /// Reserve the resources occupied by a machine instruction and change the - /// current state to reflect that change. - void reserveResources(const MachineInstr &MI); - - /// Reset the state - void clearResources(); -}; - -/// This class represents the scheduled code. The main data structure is a -/// map from scheduled cycle to instructions. During scheduling, the -/// data structure explicitly represents all stages/iterations. When -/// the algorithm finishes, the schedule is collapsed into a single stage, -/// which represents instructions from different loop iterations. -/// -/// The SMS algorithm allows negative values for cycles, so the first cycle -/// in the schedule is the smallest cycle value. -class SMSchedule { -private: - /// Map from execution cycle to instructions. - DenseMap> ScheduledInstrs; - - /// Map from instruction to execution cycle. - std::map InstrToCycle; - - /// Keep track of the first cycle value in the schedule. It starts - /// as zero, but the algorithm allows negative values. - int FirstCycle = 0; - - /// Keep track of the last cycle value in the schedule. - int LastCycle = 0; - - /// The initiation interval (II) for the schedule. - int InitiationInterval = 0; - - /// Target machine information. - const TargetSubtargetInfo &ST; - - /// Virtual register information. - MachineRegisterInfo &MRI; - - ResourceManager ProcItinResources; - -public: - SMSchedule(MachineFunction *mf) - : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), ProcItinResources(&ST) {} - - void reset() { - ScheduledInstrs.clear(); - InstrToCycle.clear(); - FirstCycle = 0; - LastCycle = 0; - InitiationInterval = 0; - } - - /// Set the initiation interval for this schedule. - void setInitiationInterval(int ii) { InitiationInterval = ii; } - - /// Return the initiation interval for this schedule. - int getInitiationInterval() const { return InitiationInterval; } - - /// Return the first cycle in the completed schedule. This - /// can be a negative value. - int getFirstCycle() const { return FirstCycle; } - - /// Return the last cycle in the finalized schedule. - int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; } - - /// Return the cycle of the earliest scheduled instruction in the dependence - /// chain. - int earliestCycleInChain(const SDep &Dep); - - /// Return the cycle of the latest scheduled instruction in the dependence - /// chain. - int latestCycleInChain(const SDep &Dep); - - void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart, - int *MinEnd, int *MaxStart, int II, SwingSchedulerDAG *DAG); - bool insert(SUnit *SU, int StartCycle, int EndCycle, int II); - - /// Iterators for the cycle to instruction map. - using sched_iterator = DenseMap>::iterator; - using const_sched_iterator = - DenseMap>::const_iterator; - - /// Return true if the instruction is scheduled at the specified stage. - bool isScheduledAtStage(SUnit *SU, unsigned StageNum) { - return (stageScheduled(SU) == (int)StageNum); - } - - /// Return the stage for a scheduled instruction. Return -1 if - /// the instruction has not been scheduled. - int stageScheduled(SUnit *SU) const { - std::map::const_iterator it = InstrToCycle.find(SU); - if (it == InstrToCycle.end()) - return -1; - return (it->second - FirstCycle) / InitiationInterval; - } - - /// Return the cycle for a scheduled instruction. This function normalizes - /// the first cycle to be 0. - unsigned cycleScheduled(SUnit *SU) const { - std::map::const_iterator it = InstrToCycle.find(SU); - assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled."); - return (it->second - FirstCycle) % InitiationInterval; - } - - /// Return the maximum stage count needed for this schedule. - unsigned getMaxStageCount() { - return (LastCycle - FirstCycle) / InitiationInterval; - } - - /// Return the instructions that are scheduled at the specified cycle. - std::deque &getInstructions(int cycle) { - return ScheduledInstrs[cycle]; - } - - bool isValidSchedule(SwingSchedulerDAG *SSD); - void finalizeSchedule(SwingSchedulerDAG *SSD); - void orderDependence(SwingSchedulerDAG *SSD, SUnit *SU, - std::deque &Insts); - bool isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi); - bool isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD, MachineInstr *Def, - MachineOperand &MO); - void print(raw_ostream &os) const; - void dump() const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEPIPELINER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePostDominators.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachinePostDominators.h deleted file mode 100644 index cee4294f63..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachinePostDominators.h +++ /dev/null @@ -1,95 +0,0 @@ -//===- llvm/CodeGen/MachinePostDominators.h ----------------------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file exposes interfaces to post dominance information for -// target-specific code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H -#define LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H - -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include - -namespace llvm { - -/// -/// MachinePostDominatorTree - an analysis pass wrapper for DominatorTree -/// used to compute the post-dominator tree for MachineFunctions. -/// -class MachinePostDominatorTree : public MachineFunctionPass { - using PostDomTreeT = PostDomTreeBase; - std::unique_ptr PDT; - -public: - static char ID; - - MachinePostDominatorTree(); - - PostDomTreeT &getBase() { - if (!PDT) - PDT.reset(new PostDomTreeT()); - return *PDT; - } - - FunctionPass *createMachinePostDominatorTreePass(); - - MachineDomTreeNode *getRootNode() const { return PDT->getRootNode(); } - - MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { - return PDT->getNode(BB); - } - - MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { - return PDT->getNode(BB); - } - - bool dominates(const MachineDomTreeNode *A, - const MachineDomTreeNode *B) const { - return PDT->dominates(A, B); - } - - bool dominates(const MachineBasicBlock *A, const MachineBasicBlock *B) const { - return PDT->dominates(A, B); - } - - bool properlyDominates(const MachineDomTreeNode *A, - const MachineDomTreeNode *B) const { - return PDT->properlyDominates(A, B); - } - - bool properlyDominates(const MachineBasicBlock *A, - const MachineBasicBlock *B) const { - return PDT->properlyDominates(A, B); - } - - bool isVirtualRoot(const MachineDomTreeNode *Node) const { - return PDT->isVirtualRoot(Node); - } - - MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, - MachineBasicBlock *B) const { - return PDT->findNearestCommonDominator(A, B); - } - - /// Returns the nearest common dominator of the given blocks. - /// If that tree node is a virtual root, a nullptr will be returned. - MachineBasicBlock * - findNearestCommonDominator(ArrayRef Blocks) const; - - bool runOnMachineFunction(MachineFunction &MF) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override { PDT.reset(nullptr); } - void verifyAnalysis() const override; - void print(llvm::raw_ostream &OS, const Module *M = nullptr) const override; -}; -} //end of namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegionInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegionInfo.h deleted file mode 100644 index eeb69fef2c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegionInfo.h +++ /dev/null @@ -1,181 +0,0 @@ -//===- llvm/CodeGen/MachineRegionInfo.h -------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEREGIONINFO_H -#define LLVM_CODEGEN_MACHINEREGIONINFO_H - -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/Analysis/RegionInfo.h" -#include "llvm/Analysis/RegionIterator.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineDominanceFrontier.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include - -namespace llvm { - -class MachinePostDominatorTree; -class MachineRegion; -class MachineRegionNode; -class MachineRegionInfo; - -template <> struct RegionTraits { - using FuncT = MachineFunction; - using BlockT = MachineBasicBlock; - using RegionT = MachineRegion; - using RegionNodeT = MachineRegionNode; - using RegionInfoT = MachineRegionInfo; - using DomTreeT = MachineDominatorTree; - using DomTreeNodeT = MachineDomTreeNode; - using PostDomTreeT = MachinePostDominatorTree; - using DomFrontierT = MachineDominanceFrontier; - using InstT = MachineInstr; - using LoopT = MachineLoop; - using LoopInfoT = MachineLoopInfo; - - static unsigned getNumSuccessors(MachineBasicBlock *BB) { - return BB->succ_size(); - } -}; - -class MachineRegionNode : public RegionNodeBase> { -public: - inline MachineRegionNode(MachineRegion *Parent, MachineBasicBlock *Entry, - bool isSubRegion = false) - : RegionNodeBase>(Parent, Entry, - isSubRegion) {} - - bool operator==(const MachineRegion &RN) const { - return this == reinterpret_cast(&RN); - } -}; - -class MachineRegion : public RegionBase> { -public: - MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, - MachineRegionInfo *RI, MachineDominatorTree *DT, - MachineRegion *Parent = nullptr); - ~MachineRegion(); - - bool operator==(const MachineRegionNode &RN) const { - return &RN == reinterpret_cast(this); - } -}; - -class MachineRegionInfo : public RegionInfoBase> { -public: - explicit MachineRegionInfo(); - ~MachineRegionInfo() override; - - // updateStatistics - Update statistic about created regions. - void updateStatistics(MachineRegion *R) final; - - void recalculate(MachineFunction &F, MachineDominatorTree *DT, - MachinePostDominatorTree *PDT, MachineDominanceFrontier *DF); -}; - -class MachineRegionInfoPass : public MachineFunctionPass { - MachineRegionInfo RI; - -public: - static char ID; - - explicit MachineRegionInfoPass(); - ~MachineRegionInfoPass() override; - - MachineRegionInfo &getRegionInfo() { return RI; } - - const MachineRegionInfo &getRegionInfo() const { return RI; } - - /// @name MachineFunctionPass interface - //@{ - bool runOnMachineFunction(MachineFunction &F) override; - void releaseMemory() override; - void verifyAnalysis() const override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void print(raw_ostream &OS, const Module *) const override; - void dump() const; - //@} -}; - -template <> -template <> -inline MachineBasicBlock * -RegionNodeBase>::getNodeAs() - const { - assert(!isSubRegion() && "This is not a MachineBasicBlock RegionNode!"); - return getEntry(); -} - -template <> -template <> -inline MachineRegion * -RegionNodeBase>::getNodeAs() - const { - assert(isSubRegion() && "This is not a subregion RegionNode!"); - auto Unconst = - const_cast> *>(this); - return reinterpret_cast(Unconst); -} - -RegionNodeGraphTraits(MachineRegionNode, MachineBasicBlock, MachineRegion); -RegionNodeGraphTraits(const MachineRegionNode, MachineBasicBlock, - MachineRegion); - -RegionGraphTraits(MachineRegion, MachineRegionNode); -RegionGraphTraits(const MachineRegion, const MachineRegionNode); - -template <> -struct GraphTraits - : public GraphTraits> { - using nodes_iterator = df_iterator, - false, GraphTraits>>; - - static NodeRef getEntryNode(MachineRegionInfo *RI) { - return GraphTraits>::getEntryNode( - RI->getTopLevelRegion()); - } - - static nodes_iterator nodes_begin(MachineRegionInfo *RI) { - return nodes_iterator::begin(getEntryNode(RI)); - } - - static nodes_iterator nodes_end(MachineRegionInfo *RI) { - return nodes_iterator::end(getEntryNode(RI)); - } -}; - -template <> -struct GraphTraits - : public GraphTraits { - using nodes_iterator = df_iterator, - false, GraphTraits>>; - - static NodeRef getEntryNode(MachineRegionInfoPass *RI) { - return GraphTraits::getEntryNode(&RI->getRegionInfo()); - } - - static nodes_iterator nodes_begin(MachineRegionInfoPass *RI) { - return GraphTraits::nodes_begin(&RI->getRegionInfo()); - } - - static nodes_iterator nodes_end(MachineRegionInfoPass *RI) { - return GraphTraits::nodes_end(&RI->getRegionInfo()); - } -}; - -extern template class RegionBase>; -extern template class RegionNodeBase>; -extern template class RegionInfoBase>; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEREGIONINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegisterInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegisterInfo.h deleted file mode 100644 index 94ae6fe02e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineRegisterInfo.h +++ /dev/null @@ -1,1247 +0,0 @@ -//===- llvm/CodeGen/MachineRegisterInfo.h -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachineRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H -#define LLVM_CODEGEN_MACHINEREGISTERINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/GlobalISel/RegisterBank.h" -#include "llvm/CodeGen/LowLevelType.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/MC/LaneBitmask.h" -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class PSetIterator; - -/// Convenient type to represent either a register class or a register bank. -using RegClassOrRegBank = - PointerUnion; - -/// MachineRegisterInfo - Keep track of information for virtual and physical -/// registers, including vreg register classes, use/def chains for registers, -/// etc. -class MachineRegisterInfo { -public: - class Delegate { - virtual void anchor(); - - public: - virtual ~Delegate() = default; - - virtual void MRI_NoteNewVirtualRegister(Register Reg) = 0; - }; - -private: - MachineFunction *MF; - Delegate *TheDelegate = nullptr; - - /// True if subregister liveness is tracked. - const bool TracksSubRegLiveness; - - /// VRegInfo - Information we keep for each virtual register. - /// - /// Each element in this list contains the register class of the vreg and the - /// start of the use/def list for the register. - IndexedMap, - VirtReg2IndexFunctor> - VRegInfo; - - /// Map for recovering vreg name from vreg number. - /// This map is used by the MIR Printer. - IndexedMap VReg2Name; - - /// StringSet that is used to unique vreg names. - StringSet<> VRegNames; - - /// The flag is true upon \p UpdatedCSRs initialization - /// and false otherwise. - bool IsUpdatedCSRsInitialized = false; - - /// Contains the updated callee saved register list. - /// As opposed to the static list defined in register info, - /// all registers that were disabled are removed from the list. - SmallVector UpdatedCSRs; - - /// RegAllocHints - This vector records register allocation hints for - /// virtual registers. For each virtual register, it keeps a pair of hint - /// type and hints vector making up the allocation hints. Only the first - /// hint may be target specific, and in that case this is reflected by the - /// first member of the pair being non-zero. If the hinted register is - /// virtual, it means the allocator should prefer the physical register - /// allocated to it if any. - IndexedMap>, - VirtReg2IndexFunctor> RegAllocHints; - - /// PhysRegUseDefLists - This is an array of the head of the use/def list for - /// physical registers. - std::unique_ptr PhysRegUseDefLists; - - /// getRegUseDefListHead - Return the head pointer for the register use/def - /// list for the specified virtual or physical register. - MachineOperand *&getRegUseDefListHead(Register RegNo) { - if (RegNo.isVirtual()) - return VRegInfo[RegNo.id()].second; - return PhysRegUseDefLists[RegNo.id()]; - } - - MachineOperand *getRegUseDefListHead(Register RegNo) const { - if (RegNo.isVirtual()) - return VRegInfo[RegNo.id()].second; - return PhysRegUseDefLists[RegNo.id()]; - } - - /// Get the next element in the use-def chain. - static MachineOperand *getNextOperandForReg(const MachineOperand *MO) { - assert(MO && MO->isReg() && "This is not a register operand!"); - return MO->Contents.Reg.Next; - } - - /// UsedPhysRegMask - Additional used physregs including aliases. - /// This bit vector represents all the registers clobbered by function calls. - BitVector UsedPhysRegMask; - - /// ReservedRegs - This is a bit vector of reserved registers. The target - /// may change its mind about which registers should be reserved. This - /// vector is the frozen set of reserved registers when register allocation - /// started. - BitVector ReservedRegs; - - using VRegToTypeMap = IndexedMap; - /// Map generic virtual registers to their low-level type. - VRegToTypeMap VRegToType; - - /// Keep track of the physical registers that are live in to the function. - /// Live in values are typically arguments in registers. LiveIn values are - /// allowed to have virtual registers associated with them, stored in the - /// second element. - std::vector> LiveIns; - -public: - explicit MachineRegisterInfo(MachineFunction *MF); - MachineRegisterInfo(const MachineRegisterInfo &) = delete; - MachineRegisterInfo &operator=(const MachineRegisterInfo &) = delete; - - const TargetRegisterInfo *getTargetRegisterInfo() const { - return MF->getSubtarget().getRegisterInfo(); - } - - void resetDelegate(Delegate *delegate) { - // Ensure another delegate does not take over unless the current - // delegate first unattaches itself. If we ever need to multicast - // notifications, we will need to change to using a list. - assert(TheDelegate == delegate && - "Only the current delegate can perform reset!"); - TheDelegate = nullptr; - } - - void setDelegate(Delegate *delegate) { - assert(delegate && !TheDelegate && - "Attempted to set delegate to null, or to change it without " - "first resetting it!"); - - TheDelegate = delegate; - } - - //===--------------------------------------------------------------------===// - // Function State - //===--------------------------------------------------------------------===// - - // isSSA - Returns true when the machine function is in SSA form. Early - // passes require the machine function to be in SSA form where every virtual - // register has a single defining instruction. - // - // The TwoAddressInstructionPass and PHIElimination passes take the machine - // function out of SSA form when they introduce multiple defs per virtual - // register. - bool isSSA() const { - return MF->getProperties().hasProperty( - MachineFunctionProperties::Property::IsSSA); - } - - // leaveSSA - Indicates that the machine function is no longer in SSA form. - void leaveSSA() { - MF->getProperties().reset(MachineFunctionProperties::Property::IsSSA); - } - - /// tracksLiveness - Returns true when tracking register liveness accurately. - /// (see MachineFUnctionProperties::Property description for details) - bool tracksLiveness() const { - return MF->getProperties().hasProperty( - MachineFunctionProperties::Property::TracksLiveness); - } - - /// invalidateLiveness - Indicates that register liveness is no longer being - /// tracked accurately. - /// - /// This should be called by late passes that invalidate the liveness - /// information. - void invalidateLiveness() { - MF->getProperties().reset( - MachineFunctionProperties::Property::TracksLiveness); - } - - /// Returns true if liveness for register class @p RC should be tracked at - /// the subregister level. - bool shouldTrackSubRegLiveness(const TargetRegisterClass &RC) const { - return subRegLivenessEnabled() && RC.HasDisjunctSubRegs; - } - bool shouldTrackSubRegLiveness(Register VReg) const { - assert(VReg.isVirtual() && "Must pass a VReg"); - return shouldTrackSubRegLiveness(*getRegClass(VReg)); - } - bool subRegLivenessEnabled() const { - return TracksSubRegLiveness; - } - - //===--------------------------------------------------------------------===// - // Register Info - //===--------------------------------------------------------------------===// - - /// Returns true if the updated CSR list was initialized and false otherwise. - bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; } - - /// Disables the register from the list of CSRs. - /// I.e. the register will not appear as part of the CSR mask. - /// \see UpdatedCalleeSavedRegs. - void disableCalleeSavedRegister(MCRegister Reg); - - /// Returns list of callee saved registers. - /// The function returns the updated CSR list (after taking into account - /// registers that are disabled from the CSR list). - const MCPhysReg *getCalleeSavedRegs() const; - - /// Sets the updated Callee Saved Registers list. - /// Notice that it will override ant previously disabled/saved CSRs. - void setCalleeSavedRegs(ArrayRef CSRs); - - // Strictly for use by MachineInstr.cpp. - void addRegOperandToUseList(MachineOperand *MO); - - // Strictly for use by MachineInstr.cpp. - void removeRegOperandFromUseList(MachineOperand *MO); - - // Strictly for use by MachineInstr.cpp. - void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps); - - /// Verify the sanity of the use list for Reg. - void verifyUseList(Register Reg) const; - - /// Verify the use list of all registers. - void verifyUseLists() const; - - /// reg_begin/reg_end - Provide iteration support to walk over all definitions - /// and uses of a register within the MachineFunction that corresponds to this - /// MachineRegisterInfo object. - template - class defusechain_iterator; - template - class defusechain_instr_iterator; - - // Make it a friend so it can access getNextOperandForReg(). - template - friend class defusechain_iterator; - template - friend class defusechain_instr_iterator; - - /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified - /// register. - using reg_iterator = - defusechain_iterator; - reg_iterator reg_begin(Register RegNo) const { - return reg_iterator(getRegUseDefListHead(RegNo)); - } - static reg_iterator reg_end() { return reg_iterator(nullptr); } - - inline iterator_range reg_operands(Register Reg) const { - return make_range(reg_begin(Reg), reg_end()); - } - - /// reg_instr_iterator/reg_instr_begin/reg_instr_end - Walk all defs and uses - /// of the specified register, stepping by MachineInstr. - using reg_instr_iterator = - defusechain_instr_iterator; - reg_instr_iterator reg_instr_begin(Register RegNo) const { - return reg_instr_iterator(getRegUseDefListHead(RegNo)); - } - static reg_instr_iterator reg_instr_end() { - return reg_instr_iterator(nullptr); - } - - inline iterator_range - reg_instructions(Register Reg) const { - return make_range(reg_instr_begin(Reg), reg_instr_end()); - } - - /// reg_bundle_iterator/reg_bundle_begin/reg_bundle_end - Walk all defs and uses - /// of the specified register, stepping by bundle. - using reg_bundle_iterator = - defusechain_instr_iterator; - reg_bundle_iterator reg_bundle_begin(Register RegNo) const { - return reg_bundle_iterator(getRegUseDefListHead(RegNo)); - } - static reg_bundle_iterator reg_bundle_end() { - return reg_bundle_iterator(nullptr); - } - - inline iterator_range reg_bundles(Register Reg) const { - return make_range(reg_bundle_begin(Reg), reg_bundle_end()); - } - - /// reg_empty - Return true if there are no instructions using or defining the - /// specified register (it may be live-in). - bool reg_empty(Register RegNo) const { return reg_begin(RegNo) == reg_end(); } - - /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses - /// of the specified register, skipping those marked as Debug. - using reg_nodbg_iterator = - defusechain_iterator; - reg_nodbg_iterator reg_nodbg_begin(Register RegNo) const { - return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static reg_nodbg_iterator reg_nodbg_end() { - return reg_nodbg_iterator(nullptr); - } - - inline iterator_range - reg_nodbg_operands(Register Reg) const { - return make_range(reg_nodbg_begin(Reg), reg_nodbg_end()); - } - - /// reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk - /// all defs and uses of the specified register, stepping by MachineInstr, - /// skipping those marked as Debug. - using reg_instr_nodbg_iterator = - defusechain_instr_iterator; - reg_instr_nodbg_iterator reg_instr_nodbg_begin(Register RegNo) const { - return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static reg_instr_nodbg_iterator reg_instr_nodbg_end() { - return reg_instr_nodbg_iterator(nullptr); - } - - inline iterator_range - reg_nodbg_instructions(Register Reg) const { - return make_range(reg_instr_nodbg_begin(Reg), reg_instr_nodbg_end()); - } - - /// reg_bundle_nodbg_iterator/reg_bundle_nodbg_begin/reg_bundle_nodbg_end - Walk - /// all defs and uses of the specified register, stepping by bundle, - /// skipping those marked as Debug. - using reg_bundle_nodbg_iterator = - defusechain_instr_iterator; - reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(Register RegNo) const { - return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static reg_bundle_nodbg_iterator reg_bundle_nodbg_end() { - return reg_bundle_nodbg_iterator(nullptr); - } - - inline iterator_range - reg_nodbg_bundles(Register Reg) const { - return make_range(reg_bundle_nodbg_begin(Reg), reg_bundle_nodbg_end()); - } - - /// reg_nodbg_empty - Return true if the only instructions using or defining - /// Reg are Debug instructions. - bool reg_nodbg_empty(Register RegNo) const { - return reg_nodbg_begin(RegNo) == reg_nodbg_end(); - } - - /// def_iterator/def_begin/def_end - Walk all defs of the specified register. - using def_iterator = - defusechain_iterator; - def_iterator def_begin(Register RegNo) const { - return def_iterator(getRegUseDefListHead(RegNo)); - } - static def_iterator def_end() { return def_iterator(nullptr); } - - inline iterator_range def_operands(Register Reg) const { - return make_range(def_begin(Reg), def_end()); - } - - /// def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the - /// specified register, stepping by MachineInst. - using def_instr_iterator = - defusechain_instr_iterator; - def_instr_iterator def_instr_begin(Register RegNo) const { - return def_instr_iterator(getRegUseDefListHead(RegNo)); - } - static def_instr_iterator def_instr_end() { - return def_instr_iterator(nullptr); - } - - inline iterator_range - def_instructions(Register Reg) const { - return make_range(def_instr_begin(Reg), def_instr_end()); - } - - /// def_bundle_iterator/def_bundle_begin/def_bundle_end - Walk all defs of the - /// specified register, stepping by bundle. - using def_bundle_iterator = - defusechain_instr_iterator; - def_bundle_iterator def_bundle_begin(Register RegNo) const { - return def_bundle_iterator(getRegUseDefListHead(RegNo)); - } - static def_bundle_iterator def_bundle_end() { - return def_bundle_iterator(nullptr); - } - - inline iterator_range def_bundles(Register Reg) const { - return make_range(def_bundle_begin(Reg), def_bundle_end()); - } - - /// def_empty - Return true if there are no instructions defining the - /// specified register (it may be live-in). - bool def_empty(Register RegNo) const { return def_begin(RegNo) == def_end(); } - - StringRef getVRegName(Register Reg) const { - return VReg2Name.inBounds(Reg) ? StringRef(VReg2Name[Reg]) : ""; - } - - void insertVRegByName(StringRef Name, Register Reg) { - assert((Name.empty() || VRegNames.find(Name) == VRegNames.end()) && - "Named VRegs Must be Unique."); - if (!Name.empty()) { - VRegNames.insert(Name); - VReg2Name.grow(Reg); - VReg2Name[Reg] = Name.str(); - } - } - - /// Return true if there is exactly one operand defining the specified - /// register. - bool hasOneDef(Register RegNo) const { - return hasSingleElement(def_operands(RegNo)); - } - - /// Returns the defining operand if there is exactly one operand defining the - /// specified register, otherwise nullptr. - MachineOperand *getOneDef(Register Reg) const { - def_iterator DI = def_begin(Reg); - if (DI == def_end()) // No defs. - return nullptr; - - def_iterator OneDef = DI; - if (++DI == def_end()) - return &*OneDef; - return nullptr; // Multiple defs. - } - - /// use_iterator/use_begin/use_end - Walk all uses of the specified register. - using use_iterator = - defusechain_iterator; - use_iterator use_begin(Register RegNo) const { - return use_iterator(getRegUseDefListHead(RegNo)); - } - static use_iterator use_end() { return use_iterator(nullptr); } - - inline iterator_range use_operands(Register Reg) const { - return make_range(use_begin(Reg), use_end()); - } - - /// use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the - /// specified register, stepping by MachineInstr. - using use_instr_iterator = - defusechain_instr_iterator; - use_instr_iterator use_instr_begin(Register RegNo) const { - return use_instr_iterator(getRegUseDefListHead(RegNo)); - } - static use_instr_iterator use_instr_end() { - return use_instr_iterator(nullptr); - } - - inline iterator_range - use_instructions(Register Reg) const { - return make_range(use_instr_begin(Reg), use_instr_end()); - } - - /// use_bundle_iterator/use_bundle_begin/use_bundle_end - Walk all uses of the - /// specified register, stepping by bundle. - using use_bundle_iterator = - defusechain_instr_iterator; - use_bundle_iterator use_bundle_begin(Register RegNo) const { - return use_bundle_iterator(getRegUseDefListHead(RegNo)); - } - static use_bundle_iterator use_bundle_end() { - return use_bundle_iterator(nullptr); - } - - inline iterator_range use_bundles(Register Reg) const { - return make_range(use_bundle_begin(Reg), use_bundle_end()); - } - - /// use_empty - Return true if there are no instructions using the specified - /// register. - bool use_empty(Register RegNo) const { return use_begin(RegNo) == use_end(); } - - /// hasOneUse - Return true if there is exactly one instruction using the - /// specified register. - bool hasOneUse(Register RegNo) const { - return hasSingleElement(use_operands(RegNo)); - } - - /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the - /// specified register, skipping those marked as Debug. - using use_nodbg_iterator = - defusechain_iterator; - use_nodbg_iterator use_nodbg_begin(Register RegNo) const { - return use_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static use_nodbg_iterator use_nodbg_end() { - return use_nodbg_iterator(nullptr); - } - - inline iterator_range - use_nodbg_operands(Register Reg) const { - return make_range(use_nodbg_begin(Reg), use_nodbg_end()); - } - - /// use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk - /// all uses of the specified register, stepping by MachineInstr, skipping - /// those marked as Debug. - using use_instr_nodbg_iterator = - defusechain_instr_iterator; - use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const { - return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static use_instr_nodbg_iterator use_instr_nodbg_end() { - return use_instr_nodbg_iterator(nullptr); - } - - inline iterator_range - use_nodbg_instructions(Register Reg) const { - return make_range(use_instr_nodbg_begin(Reg), use_instr_nodbg_end()); - } - - /// use_bundle_nodbg_iterator/use_bundle_nodbg_begin/use_bundle_nodbg_end - Walk - /// all uses of the specified register, stepping by bundle, skipping - /// those marked as Debug. - using use_bundle_nodbg_iterator = - defusechain_instr_iterator; - use_bundle_nodbg_iterator use_bundle_nodbg_begin(Register RegNo) const { - return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); - } - static use_bundle_nodbg_iterator use_bundle_nodbg_end() { - return use_bundle_nodbg_iterator(nullptr); - } - - inline iterator_range - use_nodbg_bundles(Register Reg) const { - return make_range(use_bundle_nodbg_begin(Reg), use_bundle_nodbg_end()); - } - - /// use_nodbg_empty - Return true if there are no non-Debug instructions - /// using the specified register. - bool use_nodbg_empty(Register RegNo) const { - return use_nodbg_begin(RegNo) == use_nodbg_end(); - } - - /// hasOneNonDBGUse - Return true if there is exactly one non-Debug - /// use of the specified register. - bool hasOneNonDBGUse(Register RegNo) const; - - /// hasOneNonDBGUse - Return true if there is exactly one non-Debug - /// instruction using the specified register. Said instruction may have - /// multiple uses. - bool hasOneNonDBGUser(Register RegNo) const; - - /// replaceRegWith - Replace all instances of FromReg with ToReg in the - /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), - /// except that it also changes any definitions of the register as well. - /// - /// Note that it is usually necessary to first constrain ToReg's register - /// class and register bank to match the FromReg constraints using one of the - /// methods: - /// - /// constrainRegClass(ToReg, getRegClass(FromReg)) - /// constrainRegAttrs(ToReg, FromReg) - /// RegisterBankInfo::constrainGenericRegister(ToReg, - /// *MRI.getRegClass(FromReg), MRI) - /// - /// These functions will return a falsy result if the virtual registers have - /// incompatible constraints. - /// - /// Note that if ToReg is a physical register the function will replace and - /// apply sub registers to ToReg in order to obtain a final/proper physical - /// register. - void replaceRegWith(Register FromReg, Register ToReg); - - /// getVRegDef - Return the machine instr that defines the specified virtual - /// register or null if none is found. This assumes that the code is in SSA - /// form, so there should only be one definition. - MachineInstr *getVRegDef(Register Reg) const; - - /// getUniqueVRegDef - Return the unique machine instr that defines the - /// specified virtual register or null if none is found. If there are - /// multiple definitions or no definition, return null. - MachineInstr *getUniqueVRegDef(Register Reg) const; - - /// clearKillFlags - Iterate over all the uses of the given register and - /// clear the kill flag from the MachineOperand. This function is used by - /// optimization passes which extend register lifetimes and need only - /// preserve conservative kill flag information. - void clearKillFlags(Register Reg) const; - - void dumpUses(Register RegNo) const; - - /// Returns true if PhysReg is unallocatable and constant throughout the - /// function. Writing to a constant register has no effect. - bool isConstantPhysReg(MCRegister PhysReg) const; - - /// Get an iterator over the pressure sets affected by the given physical or - /// virtual register. If RegUnit is physical, it must be a register unit (from - /// MCRegUnitIterator). - PSetIterator getPressureSets(Register RegUnit) const; - - //===--------------------------------------------------------------------===// - // Virtual Register Info - //===--------------------------------------------------------------------===// - - /// Return the register class of the specified virtual register. - /// This shouldn't be used directly unless \p Reg has a register class. - /// \see getRegClassOrNull when this might happen. - const TargetRegisterClass *getRegClass(Register Reg) const { - assert(VRegInfo[Reg.id()].first.is() && - "Register class not set, wrong accessor"); - return VRegInfo[Reg.id()].first.get(); - } - - /// Return the register class of \p Reg, or null if Reg has not been assigned - /// a register class yet. - /// - /// \note A null register class can only happen when these two - /// conditions are met: - /// 1. Generic virtual registers are created. - /// 2. The machine function has not completely been through the - /// instruction selection process. - /// None of this condition is possible without GlobalISel for now. - /// In other words, if GlobalISel is not used or if the query happens after - /// the select pass, using getRegClass is safe. - const TargetRegisterClass *getRegClassOrNull(Register Reg) const { - const RegClassOrRegBank &Val = VRegInfo[Reg].first; - return Val.dyn_cast(); - } - - /// Return the register bank of \p Reg, or null if Reg has not been assigned - /// a register bank or has been assigned a register class. - /// \note It is possible to get the register bank from the register class via - /// RegisterBankInfo::getRegBankFromRegClass. - const RegisterBank *getRegBankOrNull(Register Reg) const { - const RegClassOrRegBank &Val = VRegInfo[Reg].first; - return Val.dyn_cast(); - } - - /// Return the register bank or register class of \p Reg. - /// \note Before the register bank gets assigned (i.e., before the - /// RegBankSelect pass) \p Reg may not have either. - const RegClassOrRegBank &getRegClassOrRegBank(Register Reg) const { - return VRegInfo[Reg].first; - } - - /// setRegClass - Set the register class of the specified virtual register. - void setRegClass(Register Reg, const TargetRegisterClass *RC); - - /// Set the register bank to \p RegBank for \p Reg. - void setRegBank(Register Reg, const RegisterBank &RegBank); - - void setRegClassOrRegBank(Register Reg, - const RegClassOrRegBank &RCOrRB){ - VRegInfo[Reg].first = RCOrRB; - } - - /// constrainRegClass - Constrain the register class of the specified virtual - /// register to be a common subclass of RC and the current register class, - /// but only if the new class has at least MinNumRegs registers. Return the - /// new register class, or NULL if no such class exists. - /// This should only be used when the constraint is known to be trivial, like - /// GR32 -> GR32_NOSP. Beware of increasing register pressure. - /// - /// \note Assumes that the register has a register class assigned. - /// Use RegisterBankInfo::constrainGenericRegister in GlobalISel's - /// InstructionSelect pass and constrainRegAttrs in every other pass, - /// including non-select passes of GlobalISel, instead. - const TargetRegisterClass *constrainRegClass(Register Reg, - const TargetRegisterClass *RC, - unsigned MinNumRegs = 0); - - /// Constrain the register class or the register bank of the virtual register - /// \p Reg (and low-level type) to be a common subclass or a common bank of - /// both registers provided respectively (and a common low-level type). Do - /// nothing if any of the attributes (classes, banks, or low-level types) of - /// the registers are deemed incompatible, or if the resulting register will - /// have a class smaller than before and of size less than \p MinNumRegs. - /// Return true if such register attributes exist, false otherwise. - /// - /// \note Use this method instead of constrainRegClass and - /// RegisterBankInfo::constrainGenericRegister everywhere but SelectionDAG - /// ISel / FastISel and GlobalISel's InstructionSelect pass respectively. - bool constrainRegAttrs(Register Reg, Register ConstrainingReg, - unsigned MinNumRegs = 0); - - /// recomputeRegClass - Try to find a legal super-class of Reg's register - /// class that still satisfies the constraints from the instructions using - /// Reg. Returns true if Reg was upgraded. - /// - /// This method can be used after constraints have been removed from a - /// virtual register, for example after removing instructions or splitting - /// the live range. - bool recomputeRegClass(Register Reg); - - /// createVirtualRegister - Create and return a new virtual register in the - /// function with the specified register class. - Register createVirtualRegister(const TargetRegisterClass *RegClass, - StringRef Name = ""); - - /// Create and return a new virtual register in the function with the same - /// attributes as the given register. - Register cloneVirtualRegister(Register VReg, StringRef Name = ""); - - /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic - /// (target independent) virtual register. - LLT getType(Register Reg) const { - if (Register::isVirtualRegister(Reg) && VRegToType.inBounds(Reg)) - return VRegToType[Reg]; - return LLT{}; - } - - /// Set the low-level type of \p VReg to \p Ty. - void setType(Register VReg, LLT Ty); - - /// Create and return a new generic virtual register with low-level - /// type \p Ty. - Register createGenericVirtualRegister(LLT Ty, StringRef Name = ""); - - /// Remove all types associated to virtual registers (after instruction - /// selection and constraining of all generic virtual registers). - void clearVirtRegTypes(); - - /// Creates a new virtual register that has no register class, register bank - /// or size assigned yet. This is only allowed to be used - /// temporarily while constructing machine instructions. Most operations are - /// undefined on an incomplete register until one of setRegClass(), - /// setRegBank() or setSize() has been called on it. - Register createIncompleteVirtualRegister(StringRef Name = ""); - - /// getNumVirtRegs - Return the number of virtual registers created. - unsigned getNumVirtRegs() const { return VRegInfo.size(); } - - /// clearVirtRegs - Remove all virtual registers (after physreg assignment). - void clearVirtRegs(); - - /// setRegAllocationHint - Specify a register allocation hint for the - /// specified virtual register. This is typically used by target, and in case - /// of an earlier hint it will be overwritten. - void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg) { - assert(VReg.isVirtual()); - RegAllocHints[VReg].first = Type; - RegAllocHints[VReg].second.clear(); - RegAllocHints[VReg].second.push_back(PrefReg); - } - - /// addRegAllocationHint - Add a register allocation hint to the hints - /// vector for VReg. - void addRegAllocationHint(Register VReg, Register PrefReg) { - assert(Register::isVirtualRegister(VReg)); - RegAllocHints[VReg].second.push_back(PrefReg); - } - - /// Specify the preferred (target independent) register allocation hint for - /// the specified virtual register. - void setSimpleHint(Register VReg, Register PrefReg) { - setRegAllocationHint(VReg, /*Type=*/0, PrefReg); - } - - void clearSimpleHint(Register VReg) { - assert (!RegAllocHints[VReg].first && - "Expected to clear a non-target hint!"); - RegAllocHints[VReg].second.clear(); - } - - /// getRegAllocationHint - Return the register allocation hint for the - /// specified virtual register. If there are many hints, this returns the - /// one with the greatest weight. - std::pair - getRegAllocationHint(Register VReg) const { - assert(VReg.isVirtual()); - Register BestHint = (RegAllocHints[VReg.id()].second.size() ? - RegAllocHints[VReg.id()].second[0] : Register()); - return std::pair(RegAllocHints[VReg.id()].first, - BestHint); - } - - /// getSimpleHint - same as getRegAllocationHint except it will only return - /// a target independent hint. - Register getSimpleHint(Register VReg) const { - assert(VReg.isVirtual()); - std::pair Hint = getRegAllocationHint(VReg); - return Hint.first ? Register() : Hint.second; - } - - /// getRegAllocationHints - Return a reference to the vector of all - /// register allocation hints for VReg. - const std::pair> - &getRegAllocationHints(Register VReg) const { - assert(VReg.isVirtual()); - return RegAllocHints[VReg]; - } - - /// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the - /// specified register as undefined which causes the DBG_VALUE to be - /// deleted during LiveDebugVariables analysis. - void markUsesInDebugValueAsUndef(Register Reg) const; - - /// updateDbgUsersToReg - Update a collection of debug instructions - /// to refer to the designated register. - void updateDbgUsersToReg(MCRegister OldReg, MCRegister NewReg, - ArrayRef Users) const { - SmallSet OldRegUnits; - for (MCRegUnitIterator RUI(OldReg, getTargetRegisterInfo()); RUI.isValid(); - ++RUI) - OldRegUnits.insert(*RUI); - - // If this operand is a register, check whether it overlaps with OldReg. - // If it does, replace with NewReg. - auto UpdateOp = [this, &NewReg, &OldReg, &OldRegUnits](MachineOperand &Op) { - if (Op.isReg()) { - for (MCRegUnitIterator RUI(OldReg, getTargetRegisterInfo()); - RUI.isValid(); ++RUI) { - if (OldRegUnits.contains(*RUI)) { - Op.setReg(NewReg); - break; - } - } - } - }; - - // Iterate through (possibly several) operands to DBG_VALUEs and update - // each. For DBG_PHIs, only one operand will be present. - for (MachineInstr *MI : Users) { - if (MI->isDebugValue()) { - for (auto &Op : MI->debug_operands()) - UpdateOp(Op); - assert(MI->hasDebugOperandForReg(NewReg) && - "Expected debug value to have some overlap with OldReg"); - } else if (MI->isDebugPHI()) { - UpdateOp(MI->getOperand(0)); - } else { - llvm_unreachable("Non-DBG_VALUE, Non-DBG_PHI debug instr updated"); - } - } - } - - /// Return true if the specified register is modified in this function. - /// This checks that no defining machine operands exist for the register or - /// any of its aliases. Definitions found on functions marked noreturn are - /// ignored, to consider them pass 'true' for optional parameter - /// SkipNoReturnDef. The register is also considered modified when it is set - /// in the UsedPhysRegMask. - bool isPhysRegModified(MCRegister PhysReg, bool SkipNoReturnDef = false) const; - - /// Return true if the specified register is modified or read in this - /// function. This checks that no machine operands exist for the register or - /// any of its aliases. If SkipRegMaskTest is false, the register is - /// considered used when it is set in the UsedPhysRegMask. - bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest = false) const; - - /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. - /// This corresponds to the bit mask attached to register mask operands. - void addPhysRegsUsedFromRegMask(const uint32_t *RegMask) { - UsedPhysRegMask.setBitsNotInMask(RegMask); - } - - const BitVector &getUsedPhysRegsMask() const { return UsedPhysRegMask; } - - //===--------------------------------------------------------------------===// - // Reserved Register Info - //===--------------------------------------------------------------------===// - // - // The set of reserved registers must be invariant during register - // allocation. For example, the target cannot suddenly decide it needs a - // frame pointer when the register allocator has already used the frame - // pointer register for something else. - // - // These methods can be used by target hooks like hasFP() to avoid changing - // the reserved register set during register allocation. - - /// freezeReservedRegs - Called by the register allocator to freeze the set - /// of reserved registers before allocation begins. - void freezeReservedRegs(const MachineFunction&); - - /// reservedRegsFrozen - Returns true after freezeReservedRegs() was called - /// to ensure the set of reserved registers stays constant. - bool reservedRegsFrozen() const { - return !ReservedRegs.empty(); - } - - /// canReserveReg - Returns true if PhysReg can be used as a reserved - /// register. Any register can be reserved before freezeReservedRegs() is - /// called. - bool canReserveReg(MCRegister PhysReg) const { - return !reservedRegsFrozen() || ReservedRegs.test(PhysReg); - } - - /// getReservedRegs - Returns a reference to the frozen set of reserved - /// registers. This method should always be preferred to calling - /// TRI::getReservedRegs() when possible. - const BitVector &getReservedRegs() const { - assert(reservedRegsFrozen() && - "Reserved registers haven't been frozen yet. " - "Use TRI::getReservedRegs()."); - return ReservedRegs; - } - - /// isReserved - Returns true when PhysReg is a reserved register. - /// - /// Reserved registers may belong to an allocatable register class, but the - /// target has explicitly requested that they are not used. - bool isReserved(MCRegister PhysReg) const { - return getReservedRegs().test(PhysReg.id()); - } - - /// Returns true when the given register unit is considered reserved. - /// - /// Register units are considered reserved when for at least one of their - /// root registers, the root register and all super registers are reserved. - /// This currently iterates the register hierarchy and may be slower than - /// expected. - bool isReservedRegUnit(unsigned Unit) const; - - /// isAllocatable - Returns true when PhysReg belongs to an allocatable - /// register class and it hasn't been reserved. - /// - /// Allocatable registers may show up in the allocation order of some virtual - /// register, so a register allocator needs to track its liveness and - /// availability. - bool isAllocatable(MCRegister PhysReg) const { - return getTargetRegisterInfo()->isInAllocatableClass(PhysReg) && - !isReserved(PhysReg); - } - - //===--------------------------------------------------------------------===// - // LiveIn Management - //===--------------------------------------------------------------------===// - - /// addLiveIn - Add the specified register as a live-in. Note that it - /// is an error to add the same register to the same set more than once. - void addLiveIn(MCRegister Reg, Register vreg = Register()) { - LiveIns.push_back(std::make_pair(Reg, vreg)); - } - - // Iteration support for the live-ins set. It's kept in sorted order - // by register number. - using livein_iterator = - std::vector>::const_iterator; - livein_iterator livein_begin() const { return LiveIns.begin(); } - livein_iterator livein_end() const { return LiveIns.end(); } - bool livein_empty() const { return LiveIns.empty(); } - - ArrayRef> liveins() const { - return LiveIns; - } - - bool isLiveIn(Register Reg) const; - - /// getLiveInPhysReg - If VReg is a live-in virtual register, return the - /// corresponding live-in physical register. - MCRegister getLiveInPhysReg(Register VReg) const; - - /// getLiveInVirtReg - If PReg is a live-in physical register, return the - /// corresponding live-in virtual register. - Register getLiveInVirtReg(MCRegister PReg) const; - - /// EmitLiveInCopies - Emit copies to initialize livein virtual registers - /// into the given entry block. - void EmitLiveInCopies(MachineBasicBlock *EntryMBB, - const TargetRegisterInfo &TRI, - const TargetInstrInfo &TII); - - /// Returns a mask covering all bits that can appear in lane masks of - /// subregisters of the virtual register @p Reg. - LaneBitmask getMaxLaneMaskForVReg(Register Reg) const; - - /// defusechain_iterator - This class provides iterator support for machine - /// operands in the function that use or define a specific register. If - /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it - /// returns defs. If neither are true then you are silly and it always - /// returns end(). If SkipDebug is true it skips uses marked Debug - /// when incrementing. - template - class defusechain_iterator { - friend class MachineRegisterInfo; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = MachineOperand; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - private: - MachineOperand *Op = nullptr; - - explicit defusechain_iterator(MachineOperand *op) : Op(op) { - // If the first node isn't one we're interested in, advance to one that - // we are interested in. - if (op) { - if ((!ReturnUses && op->isUse()) || - (!ReturnDefs && op->isDef()) || - (SkipDebug && op->isDebug())) - advance(); - } - } - - void advance() { - assert(Op && "Cannot increment end iterator!"); - Op = getNextOperandForReg(Op); - - // All defs come before the uses, so stop def_iterator early. - if (!ReturnUses) { - if (Op) { - if (Op->isUse()) - Op = nullptr; - else - assert(!Op->isDebug() && "Can't have debug defs"); - } - } else { - // If this is an operand we don't care about, skip it. - while (Op && ((!ReturnDefs && Op->isDef()) || - (SkipDebug && Op->isDebug()))) - Op = getNextOperandForReg(Op); - } - } - - public: - defusechain_iterator() = default; - - bool operator==(const defusechain_iterator &x) const { - return Op == x.Op; - } - bool operator!=(const defusechain_iterator &x) const { - return !operator==(x); - } - - /// atEnd - return true if this iterator is equal to reg_end() on the value. - bool atEnd() const { return Op == nullptr; } - - // Iterator traversal: forward iteration only - defusechain_iterator &operator++() { // Preincrement - assert(Op && "Cannot increment end iterator!"); - if (ByOperand) - advance(); - else if (ByInstr) { - MachineInstr *P = Op->getParent(); - do { - advance(); - } while (Op && Op->getParent() == P); - } else if (ByBundle) { - MachineBasicBlock::instr_iterator P = - getBundleStart(Op->getParent()->getIterator()); - do { - advance(); - } while (Op && getBundleStart(Op->getParent()->getIterator()) == P); - } - - return *this; - } - defusechain_iterator operator++(int) { // Postincrement - defusechain_iterator tmp = *this; ++*this; return tmp; - } - - /// getOperandNo - Return the operand # of this MachineOperand in its - /// MachineInstr. - unsigned getOperandNo() const { - assert(Op && "Cannot dereference end iterator!"); - return Op - &Op->getParent()->getOperand(0); - } - - // Retrieve a reference to the current operand. - MachineOperand &operator*() const { - assert(Op && "Cannot dereference end iterator!"); - return *Op; - } - - MachineOperand *operator->() const { - assert(Op && "Cannot dereference end iterator!"); - return Op; - } - }; - - /// defusechain_iterator - This class provides iterator support for machine - /// operands in the function that use or define a specific register. If - /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it - /// returns defs. If neither are true then you are silly and it always - /// returns end(). If SkipDebug is true it skips uses marked Debug - /// when incrementing. - template - class defusechain_instr_iterator { - friend class MachineRegisterInfo; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = MachineInstr; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - private: - MachineOperand *Op = nullptr; - - explicit defusechain_instr_iterator(MachineOperand *op) : Op(op) { - // If the first node isn't one we're interested in, advance to one that - // we are interested in. - if (op) { - if ((!ReturnUses && op->isUse()) || - (!ReturnDefs && op->isDef()) || - (SkipDebug && op->isDebug())) - advance(); - } - } - - void advance() { - assert(Op && "Cannot increment end iterator!"); - Op = getNextOperandForReg(Op); - - // All defs come before the uses, so stop def_iterator early. - if (!ReturnUses) { - if (Op) { - if (Op->isUse()) - Op = nullptr; - else - assert(!Op->isDebug() && "Can't have debug defs"); - } - } else { - // If this is an operand we don't care about, skip it. - while (Op && ((!ReturnDefs && Op->isDef()) || - (SkipDebug && Op->isDebug()))) - Op = getNextOperandForReg(Op); - } - } - - public: - defusechain_instr_iterator() = default; - - bool operator==(const defusechain_instr_iterator &x) const { - return Op == x.Op; - } - bool operator!=(const defusechain_instr_iterator &x) const { - return !operator==(x); - } - - /// atEnd - return true if this iterator is equal to reg_end() on the value. - bool atEnd() const { return Op == nullptr; } - - // Iterator traversal: forward iteration only - defusechain_instr_iterator &operator++() { // Preincrement - assert(Op && "Cannot increment end iterator!"); - if (ByOperand) - advance(); - else if (ByInstr) { - MachineInstr *P = Op->getParent(); - do { - advance(); - } while (Op && Op->getParent() == P); - } else if (ByBundle) { - MachineBasicBlock::instr_iterator P = - getBundleStart(Op->getParent()->getIterator()); - do { - advance(); - } while (Op && getBundleStart(Op->getParent()->getIterator()) == P); - } - - return *this; - } - defusechain_instr_iterator operator++(int) { // Postincrement - defusechain_instr_iterator tmp = *this; ++*this; return tmp; - } - - // Retrieve a reference to the current operand. - MachineInstr &operator*() const { - assert(Op && "Cannot dereference end iterator!"); - if (ByBundle) - return *getBundleStart(Op->getParent()->getIterator()); - return *Op->getParent(); - } - - MachineInstr *operator->() const { return &operator*(); } - }; -}; - -/// Iterate over the pressure sets affected by the given physical or virtual -/// register. If Reg is physical, it must be a register unit (from -/// MCRegUnitIterator). -class PSetIterator { - const int *PSet = nullptr; - unsigned Weight = 0; - -public: - PSetIterator() = default; - - PSetIterator(Register RegUnit, const MachineRegisterInfo *MRI) { - const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); - if (RegUnit.isVirtual()) { - const TargetRegisterClass *RC = MRI->getRegClass(RegUnit); - PSet = TRI->getRegClassPressureSets(RC); - Weight = TRI->getRegClassWeight(RC).RegWeight; - } else { - PSet = TRI->getRegUnitPressureSets(RegUnit); - Weight = TRI->getRegUnitWeight(RegUnit); - } - if (*PSet == -1) - PSet = nullptr; - } - - bool isValid() const { return PSet; } - - unsigned getWeight() const { return Weight; } - - unsigned operator*() const { return *PSet; } - - void operator++() { - assert(isValid() && "Invalid PSetIterator."); - ++PSet; - if (*PSet == -1) - PSet = nullptr; - } -}; - -inline PSetIterator -MachineRegisterInfo::getPressureSets(Register RegUnit) const { - return PSetIterator(RegUnit, this); -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEREGISTERINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAContext.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAContext.h deleted file mode 100644 index 6dbf321bde..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAContext.h +++ /dev/null @@ -1,58 +0,0 @@ -//===- MachineSSAContext.h --------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file declares a specialization of the GenericSSAContext -/// template class for Machine IR. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINESSACONTEXT_H -#define LLVM_CODEGEN_MACHINESSACONTEXT_H - -#include "llvm/ADT/GenericSSAContext.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/Printable.h" - -#include - -namespace llvm { -class MachineInstr; -class MachineBasicBlock; -class MachineFunction; -class Register; -template class DominatorTreeBase; - -inline auto successors(MachineBasicBlock *BB) { return BB->successors(); } -inline auto predecessors(MachineBasicBlock *BB) { return BB->predecessors(); } - -template <> class GenericSSAContext { - const MachineRegisterInfo *RegInfo = nullptr; - MachineFunction *MF; - -public: - using BlockT = MachineBasicBlock; - using FunctionT = MachineFunction; - using InstructionT = MachineInstr; - using ValueRefT = Register; - using DominatorTreeT = DominatorTreeBase; - - static MachineBasicBlock *getEntryBlock(MachineFunction &F); - - void setFunction(MachineFunction &Fn); - MachineFunction *getFunction() const { return MF; } - - Printable print(MachineBasicBlock *Block) const; - Printable print(MachineInstr *Inst) const; - Printable print(Register Value) const; -}; - -using MachineSSAContext = GenericSSAContext; -} // namespace llvm - -#endif // LLVM_CODEGEN_MACHINESSACONTEXT_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAUpdater.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAUpdater.h deleted file mode 100644 index 3f0b55e0ab..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSSAUpdater.h +++ /dev/null @@ -1,118 +0,0 @@ -//===- MachineSSAUpdater.h - Unstructured SSA Update Tool -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the MachineSSAUpdater class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H -#define LLVM_CODEGEN_MACHINESSAUPDATER_H - -#include "llvm/CodeGen/Register.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MachineOperand; -class MachineRegisterInfo; -class TargetInstrInfo; -class TargetRegisterClass; -template class SmallVectorImpl; -template class SSAUpdaterTraits; - -/// MachineSSAUpdater - This class updates SSA form for a set of virtual -/// registers defined in multiple blocks. This is used when code duplication -/// or another unstructured transformation wants to rewrite a set of uses of one -/// vreg with uses of a set of vregs. -class MachineSSAUpdater { - friend class SSAUpdaterTraits; - -private: - /// AvailableVals - This keeps track of which value to use on a per-block - /// basis. When we insert PHI nodes, we keep track of them here. - //typedef DenseMap AvailableValsTy; - void *AV = nullptr; - - /// VRC - Register class of the current virtual register. - const TargetRegisterClass *VRC; - - /// InsertedPHIs - If this is non-null, the MachineSSAUpdater adds all PHI - /// nodes that it creates to the vector. - SmallVectorImpl *InsertedPHIs; - - const TargetInstrInfo *TII; - MachineRegisterInfo *MRI; - -public: - /// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be - /// filled in with all PHI Nodes created by rewriting. - explicit MachineSSAUpdater(MachineFunction &MF, - SmallVectorImpl *NewPHI = nullptr); - MachineSSAUpdater(const MachineSSAUpdater &) = delete; - MachineSSAUpdater &operator=(const MachineSSAUpdater &) = delete; - ~MachineSSAUpdater(); - - /// Initialize - Reset this object to get ready for a new set of SSA - /// updates. - void Initialize(Register V); - void Initialize(const TargetRegisterClass *RC); - - /// AddAvailableValue - Indicate that a rewritten value is available at the - /// end of the specified block with the specified value. - void AddAvailableValue(MachineBasicBlock *BB, Register V); - - /// HasValueForBlock - Return true if the MachineSSAUpdater already has a - /// value for the specified block. - bool HasValueForBlock(MachineBasicBlock *BB) const; - - /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is - /// live at the end of the specified block. - Register GetValueAtEndOfBlock(MachineBasicBlock *BB); - - /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that - /// is live in the middle of the specified block. If ExistingValueOnly is - /// true then this will only return an existing value or $noreg; otherwise new - /// instructions may be inserted to materialize a value. - /// - /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one - /// important case: if there is a definition of the rewritten value after the - /// 'use' in BB. Consider code like this: - /// - /// X1 = ... - /// SomeBB: - /// use(X) - /// X2 = ... - /// br Cond, SomeBB, OutBB - /// - /// In this case, there are two values (X1 and X2) added to the AvailableVals - /// set by the client of the rewriter, and those values are both live out of - /// their respective blocks. However, the use of X happens in the *middle* of - /// a block. Because of this, we need to insert a new PHI node in SomeBB to - /// merge the appropriate values, and this value isn't live out of the block. - Register GetValueInMiddleOfBlock(MachineBasicBlock *BB, - bool ExistingValueOnly = false); - - /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, - /// which use their value in the corresponding predecessor. Note that this - /// will not work if the use is supposed to be rewritten to a value defined in - /// the same block as the use, but above it. Any 'AddAvailableValue's added - /// for the use's block will be considered to be below it. - void RewriteUse(MachineOperand &U); - -private: - // If ExistingValueOnly is true, will not create any new instructions. Used - // for debug values, which cannot modify Codegen. - Register GetValueAtEndOfBlockInternal(MachineBasicBlock *BB, - bool ExistingValueOnly = false); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINESSAUPDATER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineScheduler.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineScheduler.h deleted file mode 100644 index fab296c2a1..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineScheduler.h +++ /dev/null @@ -1,1106 +0,0 @@ -//===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides an interface for customizing the standard MachineScheduler -// pass. Note that the entire pass may be replaced as follows: -// -// TargetMachine::createPassConfig(PassManagerBase &PM) { -// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); -// ...} -// -// The MachineScheduler pass is only responsible for choosing the regions to be -// scheduled. Targets can override the DAG builder and scheduler without -// replacing the pass as follows: -// -// ScheduleDAGInstrs *PassConfig:: -// createMachineScheduler(MachineSchedContext *C) { -// return new CustomMachineScheduler(C); -// } -// -// The default scheduler, ScheduleDAGMILive, builds the DAG and drives list -// scheduling while updating the instruction stream, register pressure, and live -// intervals. Most targets don't need to override the DAG builder and list -// scheduler, but subtargets that require custom scheduling heuristics may -// plugin an alternate MachineSchedStrategy. The strategy is responsible for -// selecting the highest priority node from the list: -// -// ScheduleDAGInstrs *PassConfig:: -// createMachineScheduler(MachineSchedContext *C) { -// return new ScheduleDAGMILive(C, CustomStrategy(C)); -// } -// -// The DAG builder can also be customized in a sense by adding DAG mutations -// that will run after DAG building and before list scheduling. DAG mutations -// can adjust dependencies based on target-specific knowledge or add weak edges -// to aid heuristics: -// -// ScheduleDAGInstrs *PassConfig:: -// createMachineScheduler(MachineSchedContext *C) { -// ScheduleDAGMI *DAG = createGenericSchedLive(C); -// DAG->addMutation(new CustomDAGMutation(...)); -// return DAG; -// } -// -// A target that supports alternative schedulers can use the -// MachineSchedRegistry to allow command line selection. This can be done by -// implementing the following boilerplate: -// -// static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { -// return new CustomMachineScheduler(C); -// } -// static MachineSchedRegistry -// SchedCustomRegistry("custom", "Run my target's custom scheduler", -// createCustomMachineSched); -// -// -// Finally, subtargets that don't need to implement custom heuristics but would -// like to configure the GenericScheduler's policy for a given scheduler region, -// including scheduling direction and register pressure tracking policy, can do -// this: -// -// void Subtarget:: -// overrideSchedPolicy(MachineSchedPolicy &Policy, -// unsigned NumRegionInstrs) const { -// Policy. = true; -// } -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H -#define LLVM_CODEGEN_MACHINESCHEDULER_H - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachinePassRegistry.h" -#include "llvm/CodeGen/RegisterPressure.h" -#include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/CodeGen/ScheduleDAGMutation.h" -#include "llvm/CodeGen/TargetSchedule.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include - -namespace llvm { - -extern cl::opt ForceTopDown; -extern cl::opt ForceBottomUp; -extern cl::opt VerifyScheduling; -#ifndef NDEBUG -extern cl::opt ViewMISchedDAGs; -#else -extern const bool ViewMISchedDAGs; -#endif - -class AAResults; -class LiveIntervals; -class MachineDominatorTree; -class MachineFunction; -class MachineInstr; -class MachineLoopInfo; -class RegisterClassInfo; -class SchedDFSResult; -class ScheduleHazardRecognizer; -class TargetInstrInfo; -class TargetPassConfig; -class TargetRegisterInfo; - -/// MachineSchedContext provides enough context from the MachineScheduler pass -/// for the target to instantiate a scheduler. -struct MachineSchedContext { - MachineFunction *MF = nullptr; - const MachineLoopInfo *MLI = nullptr; - const MachineDominatorTree *MDT = nullptr; - const TargetPassConfig *PassConfig = nullptr; - AAResults *AA = nullptr; - LiveIntervals *LIS = nullptr; - - RegisterClassInfo *RegClassInfo; - - MachineSchedContext(); - virtual ~MachineSchedContext(); -}; - -/// MachineSchedRegistry provides a selection of available machine instruction -/// schedulers. -class MachineSchedRegistry - : public MachinePassRegistryNode< - ScheduleDAGInstrs *(*)(MachineSchedContext *)> { -public: - using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *); - - // RegisterPassParser requires a (misnamed) FunctionPassCtor type. - using FunctionPassCtor = ScheduleDAGCtor; - - static MachinePassRegistry Registry; - - MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) - : MachinePassRegistryNode(N, D, C) { - Registry.Add(this); - } - - ~MachineSchedRegistry() { Registry.Remove(this); } - - // Accessors. - // - MachineSchedRegistry *getNext() const { - return (MachineSchedRegistry *)MachinePassRegistryNode::getNext(); - } - - static MachineSchedRegistry *getList() { - return (MachineSchedRegistry *)Registry.getList(); - } - - static void setListener(MachinePassRegistryListener *L) { - Registry.setListener(L); - } -}; - -class ScheduleDAGMI; - -/// Define a generic scheduling policy for targets that don't provide their own -/// MachineSchedStrategy. This can be overridden for each scheduling region -/// before building the DAG. -struct MachineSchedPolicy { - // Allow the scheduler to disable register pressure tracking. - bool ShouldTrackPressure = false; - /// Track LaneMasks to allow reordering of independent subregister writes - /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks() - bool ShouldTrackLaneMasks = false; - - // Allow the scheduler to force top-down or bottom-up scheduling. If neither - // is true, the scheduler runs in both directions and converges. - bool OnlyTopDown = false; - bool OnlyBottomUp = false; - - // Disable heuristic that tries to fetch nodes from long dependency chains - // first. - bool DisableLatencyHeuristic = false; - - // Compute DFSResult for use in scheduling heuristics. - bool ComputeDFSResult = false; - - MachineSchedPolicy() = default; -}; - -/// MachineSchedStrategy - Interface to the scheduling algorithm used by -/// ScheduleDAGMI. -/// -/// Initialization sequence: -/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots -class MachineSchedStrategy { - virtual void anchor(); - -public: - virtual ~MachineSchedStrategy() = default; - - /// Optionally override the per-region scheduling policy. - virtual void initPolicy(MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - unsigned NumRegionInstrs) {} - - virtual void dumpPolicy() const {} - - /// Check if pressure tracking is needed before building the DAG and - /// initializing this strategy. Called after initPolicy. - virtual bool shouldTrackPressure() const { return true; } - - /// Returns true if lanemasks should be tracked. LaneMask tracking is - /// necessary to reorder independent subregister defs for the same vreg. - /// This has to be enabled in combination with shouldTrackPressure(). - virtual bool shouldTrackLaneMasks() const { return false; } - - // If this method returns true, handling of the scheduling regions - // themselves (in case of a scheduling boundary in MBB) will be done - // beginning with the topmost region of MBB. - virtual bool doMBBSchedRegionsTopDown() const { return false; } - - /// Initialize the strategy after building the DAG for a new region. - virtual void initialize(ScheduleDAGMI *DAG) = 0; - - /// Tell the strategy that MBB is about to be processed. - virtual void enterMBB(MachineBasicBlock *MBB) {}; - - /// Tell the strategy that current MBB is done. - virtual void leaveMBB() {}; - - /// Notify this strategy that all roots have been released (including those - /// that depend on EntrySU or ExitSU). - virtual void registerRoots() {} - - /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to - /// schedule the node at the top of the unscheduled region. Otherwise it will - /// be scheduled at the bottom. - virtual SUnit *pickNode(bool &IsTopNode) = 0; - - /// Scheduler callback to notify that a new subtree is scheduled. - virtual void scheduleTree(unsigned SubtreeID) {} - - /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an - /// instruction and updated scheduled/remaining flags in the DAG nodes. - virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; - - /// When all predecessor dependencies have been resolved, free this node for - /// top-down scheduling. - virtual void releaseTopNode(SUnit *SU) = 0; - - /// When all successor dependencies have been resolved, free this node for - /// bottom-up scheduling. - virtual void releaseBottomNode(SUnit *SU) = 0; -}; - -/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply -/// schedules machine instructions according to the given MachineSchedStrategy -/// without much extra book-keeping. This is the common functionality between -/// PreRA and PostRA MachineScheduler. -class ScheduleDAGMI : public ScheduleDAGInstrs { -protected: - AAResults *AA; - LiveIntervals *LIS; - std::unique_ptr SchedImpl; - - /// Ordered list of DAG postprocessing steps. - std::vector> Mutations; - - /// The top of the unscheduled zone. - MachineBasicBlock::iterator CurrentTop; - - /// The bottom of the unscheduled zone. - MachineBasicBlock::iterator CurrentBottom; - - /// Record the next node in a scheduled cluster. - const SUnit *NextClusterPred = nullptr; - const SUnit *NextClusterSucc = nullptr; - -#ifndef NDEBUG - /// The number of instructions scheduled so far. Used to cut off the - /// scheduler at the point determined by misched-cutoff. - unsigned NumInstrsScheduled = 0; -#endif - -public: - ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr S, - bool RemoveKillFlags) - : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA), - LIS(C->LIS), SchedImpl(std::move(S)) {} - - // Provide a vtable anchor - ~ScheduleDAGMI() override; - - /// If this method returns true, handling of the scheduling regions - /// themselves (in case of a scheduling boundary in MBB) will be done - /// beginning with the topmost region of MBB. - bool doMBBSchedRegionsTopDown() const override { - return SchedImpl->doMBBSchedRegionsTopDown(); - } - - // Returns LiveIntervals instance for use in DAG mutators and such. - LiveIntervals *getLIS() const { return LIS; } - - /// Return true if this DAG supports VReg liveness and RegPressure. - virtual bool hasVRegLiveness() const { return false; } - - /// Add a postprocessing step to the DAG builder. - /// Mutations are applied in the order that they are added after normal DAG - /// building and before MachineSchedStrategy initialization. - /// - /// ScheduleDAGMI takes ownership of the Mutation object. - void addMutation(std::unique_ptr Mutation) { - if (Mutation) - Mutations.push_back(std::move(Mutation)); - } - - MachineBasicBlock::iterator top() const { return CurrentTop; } - MachineBasicBlock::iterator bottom() const { return CurrentBottom; } - - /// Implement the ScheduleDAGInstrs interface for handling the next scheduling - /// region. This covers all instructions in a block, while schedule() may only - /// cover a subset. - void enterRegion(MachineBasicBlock *bb, - MachineBasicBlock::iterator begin, - MachineBasicBlock::iterator end, - unsigned regioninstrs) override; - - /// Implement ScheduleDAGInstrs interface for scheduling a sequence of - /// reorderable instructions. - void schedule() override; - - void startBlock(MachineBasicBlock *bb) override; - void finishBlock() override; - - /// Change the position of an instruction within the basic block and update - /// live ranges and region boundary iterators. - void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); - - const SUnit *getNextClusterPred() const { return NextClusterPred; } - - const SUnit *getNextClusterSucc() const { return NextClusterSucc; } - - void viewGraph(const Twine &Name, const Twine &Title) override; - void viewGraph() override; - -protected: - // Top-Level entry points for the schedule() driver... - - /// Apply each ScheduleDAGMutation step in order. This allows different - /// instances of ScheduleDAGMI to perform custom DAG postprocessing. - void postprocessDAG(); - - /// Release ExitSU predecessors and setup scheduler queues. - void initQueues(ArrayRef TopRoots, ArrayRef BotRoots); - - /// Update scheduler DAG and queues after scheduling an instruction. - void updateQueues(SUnit *SU, bool IsTopNode); - - /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. - void placeDebugValues(); - - /// dump the scheduled Sequence. - void dumpSchedule() const; - - // Lesser helpers... - bool checkSchedLimit(); - - void findRootsAndBiasEdges(SmallVectorImpl &TopRoots, - SmallVectorImpl &BotRoots); - - void releaseSucc(SUnit *SU, SDep *SuccEdge); - void releaseSuccessors(SUnit *SU); - void releasePred(SUnit *SU, SDep *PredEdge); - void releasePredecessors(SUnit *SU); -}; - -/// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules -/// machine instructions while updating LiveIntervals and tracking regpressure. -class ScheduleDAGMILive : public ScheduleDAGMI { -protected: - RegisterClassInfo *RegClassInfo; - - /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees - /// will be empty. - SchedDFSResult *DFSResult = nullptr; - BitVector ScheduledTrees; - - MachineBasicBlock::iterator LiveRegionEnd; - - /// Maps vregs to the SUnits of their uses in the current scheduling region. - VReg2SUnitMultiMap VRegUses; - - // Map each SU to its summary of pressure changes. This array is updated for - // liveness during bottom-up scheduling. Top-down scheduling may proceed but - // has no affect on the pressure diffs. - PressureDiffs SUPressureDiffs; - - /// Register pressure in this region computed by initRegPressure. - bool ShouldTrackPressure = false; - bool ShouldTrackLaneMasks = false; - IntervalPressure RegPressure; - RegPressureTracker RPTracker; - - /// List of pressure sets that exceed the target's pressure limit before - /// scheduling, listed in increasing set ID order. Each pressure set is paired - /// with its max pressure in the currently scheduled regions. - std::vector RegionCriticalPSets; - - /// The top of the unscheduled zone. - IntervalPressure TopPressure; - RegPressureTracker TopRPTracker; - - /// The bottom of the unscheduled zone. - IntervalPressure BotPressure; - RegPressureTracker BotRPTracker; - -public: - ScheduleDAGMILive(MachineSchedContext *C, - std::unique_ptr S) - : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false), - RegClassInfo(C->RegClassInfo), RPTracker(RegPressure), - TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} - - ~ScheduleDAGMILive() override; - - /// Return true if this DAG supports VReg liveness and RegPressure. - bool hasVRegLiveness() const override { return true; } - - /// Return true if register pressure tracking is enabled. - bool isTrackingPressure() const { return ShouldTrackPressure; } - - /// Get current register pressure for the top scheduled instructions. - const IntervalPressure &getTopPressure() const { return TopPressure; } - const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } - - /// Get current register pressure for the bottom scheduled instructions. - const IntervalPressure &getBotPressure() const { return BotPressure; } - const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } - - /// Get register pressure for the entire scheduling region before scheduling. - const IntervalPressure &getRegPressure() const { return RegPressure; } - - const std::vector &getRegionCriticalPSets() const { - return RegionCriticalPSets; - } - - PressureDiff &getPressureDiff(const SUnit *SU) { - return SUPressureDiffs[SU->NodeNum]; - } - const PressureDiff &getPressureDiff(const SUnit *SU) const { - return SUPressureDiffs[SU->NodeNum]; - } - - /// Compute a DFSResult after DAG building is complete, and before any - /// queue comparisons. - void computeDFSResult(); - - /// Return a non-null DFS result if the scheduling strategy initialized it. - const SchedDFSResult *getDFSResult() const { return DFSResult; } - - BitVector &getScheduledTrees() { return ScheduledTrees; } - - /// Implement the ScheduleDAGInstrs interface for handling the next scheduling - /// region. This covers all instructions in a block, while schedule() may only - /// cover a subset. - void enterRegion(MachineBasicBlock *bb, - MachineBasicBlock::iterator begin, - MachineBasicBlock::iterator end, - unsigned regioninstrs) override; - - /// Implement ScheduleDAGInstrs interface for scheduling a sequence of - /// reorderable instructions. - void schedule() override; - - /// Compute the cyclic critical path through the DAG. - unsigned computeCyclicCriticalPath(); - - void dump() const override; - -protected: - // Top-Level entry points for the schedule() driver... - - /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking - /// enabled. This sets up three trackers. RPTracker will cover the entire DAG - /// region, TopTracker and BottomTracker will be initialized to the top and - /// bottom of the DAG region without covereing any unscheduled instruction. - void buildDAGWithRegPressure(); - - /// Release ExitSU predecessors and setup scheduler queues. Re-position - /// the Top RP tracker in case the region beginning has changed. - void initQueues(ArrayRef TopRoots, ArrayRef BotRoots); - - /// Move an instruction and update register pressure. - void scheduleMI(SUnit *SU, bool IsTopNode); - - // Lesser helpers... - - void initRegPressure(); - - void updatePressureDiffs(ArrayRef LiveUses); - - void updateScheduledPressure(const SUnit *SU, - const std::vector &NewMaxPressure); - - void collectVRegUses(SUnit &SU); -}; - -//===----------------------------------------------------------------------===// -/// -/// Helpers for implementing custom MachineSchedStrategy classes. These take -/// care of the book-keeping associated with list scheduling heuristics. -/// -//===----------------------------------------------------------------------===// - -/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience -/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified -/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. -/// -/// This is a convenience class that may be used by implementations of -/// MachineSchedStrategy. -class ReadyQueue { - unsigned ID; - std::string Name; - std::vector Queue; - -public: - ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} - - unsigned getID() const { return ID; } - - StringRef getName() const { return Name; } - - // SU is in this queue if it's NodeQueueID is a superset of this ID. - bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } - - bool empty() const { return Queue.empty(); } - - void clear() { Queue.clear(); } - - unsigned size() const { return Queue.size(); } - - using iterator = std::vector::iterator; - - iterator begin() { return Queue.begin(); } - - iterator end() { return Queue.end(); } - - ArrayRef elements() { return Queue; } - - iterator find(SUnit *SU) { return llvm::find(Queue, SU); } - - void push(SUnit *SU) { - Queue.push_back(SU); - SU->NodeQueueId |= ID; - } - - iterator remove(iterator I) { - (*I)->NodeQueueId &= ~ID; - *I = Queue.back(); - unsigned idx = I - Queue.begin(); - Queue.pop_back(); - return Queue.begin() + idx; - } - - void dump() const; -}; - -/// Summarize the unscheduled region. -struct SchedRemainder { - // Critical path through the DAG in expected latency. - unsigned CriticalPath; - unsigned CyclicCritPath; - - // Scaled count of micro-ops left to schedule. - unsigned RemIssueCount; - - bool IsAcyclicLatencyLimited; - - // Unscheduled resources - SmallVector RemainingCounts; - - SchedRemainder() { reset(); } - - void reset() { - CriticalPath = 0; - CyclicCritPath = 0; - RemIssueCount = 0; - IsAcyclicLatencyLimited = false; - RemainingCounts.clear(); - } - - void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel); -}; - -/// Each Scheduling boundary is associated with ready queues. It tracks the -/// current cycle in the direction of movement, and maintains the state -/// of "hazards" and other interlocks at the current cycle. -class SchedBoundary { -public: - /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) - enum { - TopQID = 1, - BotQID = 2, - LogMaxQID = 2 - }; - - ScheduleDAGMI *DAG = nullptr; - const TargetSchedModel *SchedModel = nullptr; - SchedRemainder *Rem = nullptr; - - ReadyQueue Available; - ReadyQueue Pending; - - ScheduleHazardRecognizer *HazardRec = nullptr; - -private: - /// True if the pending Q should be checked/updated before scheduling another - /// instruction. - bool CheckPending; - - /// Number of cycles it takes to issue the instructions scheduled in this - /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls. - /// See getStalls(). - unsigned CurrCycle; - - /// Micro-ops issued in the current cycle - unsigned CurrMOps; - - /// MinReadyCycle - Cycle of the soonest available instruction. - unsigned MinReadyCycle; - - // The expected latency of the critical path in this scheduled zone. - unsigned ExpectedLatency; - - // The latency of dependence chains leading into this zone. - // For each node scheduled bottom-up: DLat = max DLat, N.Depth. - // For each cycle scheduled: DLat -= 1. - unsigned DependentLatency; - - /// Count the scheduled (issued) micro-ops that can be retired by - /// time=CurrCycle assuming the first scheduled instr is retired at time=0. - unsigned RetiredMOps; - - // Count scheduled resources that have been executed. Resources are - // considered executed if they become ready in the time that it takes to - // saturate any resource including the one in question. Counts are scaled - // for direct comparison with other resources. Counts can be compared with - // MOps * getMicroOpFactor and Latency * getLatencyFactor. - SmallVector ExecutedResCounts; - - /// Cache the max count for a single resource. - unsigned MaxExecutedResCount; - - // Cache the critical resources ID in this scheduled zone. - unsigned ZoneCritResIdx; - - // Is the scheduled region resource limited vs. latency limited. - bool IsResourceLimited; - - // Record the highest cycle at which each resource has been reserved by a - // scheduled instruction. - SmallVector ReservedCycles; - - // For each PIdx, stores first index into ReservedCycles that corresponds to - // it. - SmallVector ReservedCyclesIndex; - - // For each PIdx, stores the resource group IDs of its subunits - SmallVector ResourceGroupSubUnitMasks; - -#ifndef NDEBUG - // Remember the greatest possible stall as an upper bound on the number of - // times we should retry the pending queue because of a hazard. - unsigned MaxObservedStall; -#endif - -public: - /// Pending queues extend the ready queues with the same ID and the - /// PendingFlag set. - SchedBoundary(unsigned ID, const Twine &Name): - Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") { - reset(); - } - - ~SchedBoundary(); - - void reset(); - - void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, - SchedRemainder *rem); - - bool isTop() const { - return Available.getID() == TopQID; - } - - /// Number of cycles to issue the instructions scheduled in this zone. - unsigned getCurrCycle() const { return CurrCycle; } - - /// Micro-ops issued in the current cycle - unsigned getCurrMOps() const { return CurrMOps; } - - // The latency of dependence chains leading into this zone. - unsigned getDependentLatency() const { return DependentLatency; } - - /// Get the number of latency cycles "covered" by the scheduled - /// instructions. This is the larger of the critical path within the zone - /// and the number of cycles required to issue the instructions. - unsigned getScheduledLatency() const { - return std::max(ExpectedLatency, CurrCycle); - } - - unsigned getUnscheduledLatency(SUnit *SU) const { - return isTop() ? SU->getHeight() : SU->getDepth(); - } - - unsigned getResourceCount(unsigned ResIdx) const { - return ExecutedResCounts[ResIdx]; - } - - /// Get the scaled count of scheduled micro-ops and resources, including - /// executed resources. - unsigned getCriticalCount() const { - if (!ZoneCritResIdx) - return RetiredMOps * SchedModel->getMicroOpFactor(); - return getResourceCount(ZoneCritResIdx); - } - - /// Get a scaled count for the minimum execution time of the scheduled - /// micro-ops that are ready to execute by getExecutedCount. Notice the - /// feedback loop. - unsigned getExecutedCount() const { - return std::max(CurrCycle * SchedModel->getLatencyFactor(), - MaxExecutedResCount); - } - - unsigned getZoneCritResIdx() const { return ZoneCritResIdx; } - - // Is the scheduled region resource limited vs. latency limited. - bool isResourceLimited() const { return IsResourceLimited; } - - /// Get the difference between the given SUnit's ready time and the current - /// cycle. - unsigned getLatencyStallCycles(SUnit *SU); - - unsigned getNextResourceCycleByInstance(unsigned InstanceIndex, - unsigned Cycles); - - std::pair getNextResourceCycle(const MCSchedClassDesc *SC, - unsigned PIdx, - unsigned Cycles); - - bool isUnbufferedGroup(unsigned PIdx) const { - return SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin && - !SchedModel->getProcResource(PIdx)->BufferSize; - } - - bool checkHazard(SUnit *SU); - - unsigned findMaxLatency(ArrayRef ReadySUs); - - unsigned getOtherResourceCount(unsigned &OtherCritIdx); - - /// Release SU to make it ready. If it's not in hazard, remove it from - /// pending queue (if already in) and push into available queue. - /// Otherwise, push the SU into pending queue. - /// - /// @param SU The unit to be released. - /// @param ReadyCycle Until which cycle the unit is ready. - /// @param InPQueue Whether SU is already in pending queue. - /// @param Idx Position offset in pending queue (if in it). - void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue, - unsigned Idx = 0); - - void bumpCycle(unsigned NextCycle); - - void incExecutedResources(unsigned PIdx, unsigned Count); - - unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx, - unsigned Cycles, unsigned ReadyCycle); - - void bumpNode(SUnit *SU); - - void releasePending(); - - void removeReady(SUnit *SU); - - /// Call this before applying any other heuristics to the Available queue. - /// Updates the Available/Pending Q's if necessary and returns the single - /// available instruction, or NULL if there are multiple candidates. - SUnit *pickOnlyChoice(); - - void dumpScheduledState() const; -}; - -/// Base class for GenericScheduler. This class maintains information about -/// scheduling candidates based on TargetSchedModel making it easy to implement -/// heuristics for either preRA or postRA scheduling. -class GenericSchedulerBase : public MachineSchedStrategy { -public: - /// Represent the type of SchedCandidate found within a single queue. - /// pickNodeBidirectional depends on these listed by decreasing priority. - enum CandReason : uint8_t { - NoCand, Only1, PhysReg, RegExcess, RegCritical, Stall, Cluster, Weak, - RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce, - TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder}; - -#ifndef NDEBUG - static const char *getReasonStr(GenericSchedulerBase::CandReason Reason); -#endif - - /// Policy for scheduling the next instruction in the candidate's zone. - struct CandPolicy { - bool ReduceLatency = false; - unsigned ReduceResIdx = 0; - unsigned DemandResIdx = 0; - - CandPolicy() = default; - - bool operator==(const CandPolicy &RHS) const { - return ReduceLatency == RHS.ReduceLatency && - ReduceResIdx == RHS.ReduceResIdx && - DemandResIdx == RHS.DemandResIdx; - } - bool operator!=(const CandPolicy &RHS) const { - return !(*this == RHS); - } - }; - - /// Status of an instruction's critical resource consumption. - struct SchedResourceDelta { - // Count critical resources in the scheduled region required by SU. - unsigned CritResources = 0; - - // Count critical resources from another region consumed by SU. - unsigned DemandedResources = 0; - - SchedResourceDelta() = default; - - bool operator==(const SchedResourceDelta &RHS) const { - return CritResources == RHS.CritResources - && DemandedResources == RHS.DemandedResources; - } - bool operator!=(const SchedResourceDelta &RHS) const { - return !operator==(RHS); - } - }; - - /// Store the state used by GenericScheduler heuristics, required for the - /// lifetime of one invocation of pickNode(). - struct SchedCandidate { - CandPolicy Policy; - - // The best SUnit candidate. - SUnit *SU; - - // The reason for this candidate. - CandReason Reason; - - // Whether this candidate should be scheduled at top/bottom. - bool AtTop; - - // Register pressure values for the best candidate. - RegPressureDelta RPDelta; - - // Critical resource consumption of the best candidate. - SchedResourceDelta ResDelta; - - SchedCandidate() { reset(CandPolicy()); } - SchedCandidate(const CandPolicy &Policy) { reset(Policy); } - - void reset(const CandPolicy &NewPolicy) { - Policy = NewPolicy; - SU = nullptr; - Reason = NoCand; - AtTop = false; - RPDelta = RegPressureDelta(); - ResDelta = SchedResourceDelta(); - } - - bool isValid() const { return SU; } - - // Copy the status of another candidate without changing policy. - void setBest(SchedCandidate &Best) { - assert(Best.Reason != NoCand && "uninitialized Sched candidate"); - SU = Best.SU; - Reason = Best.Reason; - AtTop = Best.AtTop; - RPDelta = Best.RPDelta; - ResDelta = Best.ResDelta; - } - - void initResourceDelta(const ScheduleDAGMI *DAG, - const TargetSchedModel *SchedModel); - }; - -protected: - const MachineSchedContext *Context; - const TargetSchedModel *SchedModel = nullptr; - const TargetRegisterInfo *TRI = nullptr; - - SchedRemainder Rem; - - GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {} - - void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, - SchedBoundary *OtherZone); - -#ifndef NDEBUG - void traceCandidate(const SchedCandidate &Cand); -#endif - -private: - bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone, - bool ComputeRemLatency, unsigned &RemLatency) const; -}; - -// Utility functions used by heuristics in tryCandidate(). -bool tryLess(int TryVal, int CandVal, - GenericSchedulerBase::SchedCandidate &TryCand, - GenericSchedulerBase::SchedCandidate &Cand, - GenericSchedulerBase::CandReason Reason); -bool tryGreater(int TryVal, int CandVal, - GenericSchedulerBase::SchedCandidate &TryCand, - GenericSchedulerBase::SchedCandidate &Cand, - GenericSchedulerBase::CandReason Reason); -bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, - GenericSchedulerBase::SchedCandidate &Cand, - SchedBoundary &Zone); -bool tryPressure(const PressureChange &TryP, - const PressureChange &CandP, - GenericSchedulerBase::SchedCandidate &TryCand, - GenericSchedulerBase::SchedCandidate &Cand, - GenericSchedulerBase::CandReason Reason, - const TargetRegisterInfo *TRI, - const MachineFunction &MF); -unsigned getWeakLeft(const SUnit *SU, bool isTop); -int biasPhysReg(const SUnit *SU, bool isTop); - -/// GenericScheduler shrinks the unscheduled zone using heuristics to balance -/// the schedule. -class GenericScheduler : public GenericSchedulerBase { -public: - GenericScheduler(const MachineSchedContext *C): - GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"), - Bot(SchedBoundary::BotQID, "BotQ") {} - - void initPolicy(MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - unsigned NumRegionInstrs) override; - - void dumpPolicy() const override; - - bool shouldTrackPressure() const override { - return RegionPolicy.ShouldTrackPressure; - } - - bool shouldTrackLaneMasks() const override { - return RegionPolicy.ShouldTrackLaneMasks; - } - - void initialize(ScheduleDAGMI *dag) override; - - SUnit *pickNode(bool &IsTopNode) override; - - void schedNode(SUnit *SU, bool IsTopNode) override; - - void releaseTopNode(SUnit *SU) override { - if (SU->isScheduled) - return; - - Top.releaseNode(SU, SU->TopReadyCycle, false); - TopCand.SU = nullptr; - } - - void releaseBottomNode(SUnit *SU) override { - if (SU->isScheduled) - return; - - Bot.releaseNode(SU, SU->BotReadyCycle, false); - BotCand.SU = nullptr; - } - - void registerRoots() override; - -protected: - ScheduleDAGMILive *DAG = nullptr; - - MachineSchedPolicy RegionPolicy; - - // State of the top and bottom scheduled instruction boundaries. - SchedBoundary Top; - SchedBoundary Bot; - - /// Candidate last picked from Top boundary. - SchedCandidate TopCand; - /// Candidate last picked from Bot boundary. - SchedCandidate BotCand; - - void checkAcyclicLatency(); - - void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, - const RegPressureTracker &RPTracker, - RegPressureTracker &TempTracker); - - virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, - SchedBoundary *Zone) const; - - SUnit *pickNodeBidirectional(bool &IsTopNode); - - void pickNodeFromQueue(SchedBoundary &Zone, - const CandPolicy &ZonePolicy, - const RegPressureTracker &RPTracker, - SchedCandidate &Candidate); - - void reschedulePhysReg(SUnit *SU, bool isTop); -}; - -/// PostGenericScheduler - Interface to the scheduling algorithm used by -/// ScheduleDAGMI. -/// -/// Callbacks from ScheduleDAGMI: -/// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... -class PostGenericScheduler : public GenericSchedulerBase { -protected: - ScheduleDAGMI *DAG = nullptr; - SchedBoundary Top; - SmallVector BotRoots; - -public: - PostGenericScheduler(const MachineSchedContext *C): - GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} - - ~PostGenericScheduler() override = default; - - void initPolicy(MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End, - unsigned NumRegionInstrs) override { - /* no configurable policy */ - } - - /// PostRA scheduling does not track pressure. - bool shouldTrackPressure() const override { return false; } - - void initialize(ScheduleDAGMI *Dag) override; - - void registerRoots() override; - - SUnit *pickNode(bool &IsTopNode) override; - - void scheduleTree(unsigned SubtreeID) override { - llvm_unreachable("PostRA scheduler does not support subtree analysis."); - } - - void schedNode(SUnit *SU, bool IsTopNode) override; - - void releaseTopNode(SUnit *SU) override { - if (SU->isScheduled) - return; - Top.releaseNode(SU, SU->TopReadyCycle, false); - } - - // Only called for roots. - void releaseBottomNode(SUnit *SU) override { - BotRoots.push_back(SU); - } - -protected: - virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand); - - void pickNodeFromQueue(SchedCandidate &Cand); -}; - -/// Create the standard converging machine scheduler. This will be used as the -/// default scheduler if the target does not set a default. -/// Adds default DAG mutations. -ScheduleDAGMILive *createGenericSchedLive(MachineSchedContext *C); - -/// Create a generic scheduler with no vreg liveness or DAG mutation passes. -ScheduleDAGMI *createGenericSchedPostRA(MachineSchedContext *C); - -std::unique_ptr -createLoadClusterDAGMutation(const TargetInstrInfo *TII, - const TargetRegisterInfo *TRI); - -std::unique_ptr -createStoreClusterDAGMutation(const TargetInstrInfo *TII, - const TargetRegisterInfo *TRI); - -std::unique_ptr -createCopyConstrainDAGMutation(const TargetInstrInfo *TII, - const TargetRegisterInfo *TRI); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINESCHEDULER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSizeOpts.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineSizeOpts.h deleted file mode 100644 index 550508ad7a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineSizeOpts.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- MachineSizeOpts.h - machine size optimization ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains some shared machine IR code size optimization related -// code. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINESIZEOPTS_H -#define LLVM_CODEGEN_MACHINESIZEOPTS_H - -#include "llvm/Transforms/Utils/SizeOpts.h" - -namespace llvm { - -class ProfileSummaryInfo; -class MachineBasicBlock; -class MachineBlockFrequencyInfo; -class MachineFunction; -class MBFIWrapper; - -/// Returns true if machine function \p MF is suggested to be size-optimized -/// based on the profile. -bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *BFI, - PGSOQueryType QueryType = PGSOQueryType::Other); -/// Returns true if machine basic block \p MBB is suggested to be size-optimized -/// based on the profile. -bool shouldOptimizeForSize(const MachineBasicBlock *MBB, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI, - PGSOQueryType QueryType = PGSOQueryType::Other); -/// Returns true if machine basic block \p MBB is suggested to be size-optimized -/// based on the profile. -bool shouldOptimizeForSize(const MachineBasicBlock *MBB, - ProfileSummaryInfo *PSI, - MBFIWrapper *MBFIWrapper, - PGSOQueryType QueryType = PGSOQueryType::Other); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINESIZEOPTS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineStableHash.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineStableHash.h deleted file mode 100644 index 8423b2da1c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineStableHash.h +++ /dev/null @@ -1,30 +0,0 @@ -//===------------ MachineStableHash.h - MIR Stable Hashing Utilities ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Stable hashing for MachineInstr and MachineOperand. Useful or getting a -// hash across runs, modules, etc. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINESTABLEHASH_H -#define LLVM_CODEGEN_MACHINESTABLEHASH_H - -#include "llvm/CodeGen/StableHashing.h" - -namespace llvm { -class MachineInstr; -class MachineOperand; - -stable_hash stableHashValue(const MachineOperand &MO); -stable_hash stableHashValue(const MachineInstr &MI, bool HashVRegs = false, - bool HashConstantPoolIndices = false, - bool HashMemOperands = false); - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MachineTraceMetrics.h b/suite/synctools/tablegen/include/llvm/CodeGen/MachineTraceMetrics.h deleted file mode 100644 index 46b57365e6..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MachineTraceMetrics.h +++ /dev/null @@ -1,435 +0,0 @@ -//===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the interface for the MachineTraceMetrics analysis pass -// that estimates CPU resource usage and critical data dependency paths through -// preferred traces. This is useful for super-scalar CPUs where execution speed -// can be limited both by data dependencies and by limited execution resources. -// -// Out-of-order CPUs will often be executing instructions from multiple basic -// blocks at the same time. This makes it difficult to estimate the resource -// usage accurately in a single basic block. Resources can be estimated better -// by looking at a trace through the current basic block. -// -// For every block, the MachineTraceMetrics pass will pick a preferred trace -// that passes through the block. The trace is chosen based on loop structure, -// branch probabilities, and resource usage. The intention is to pick likely -// traces that would be the most affected by code transformations. -// -// It is expensive to compute a full arbitrary trace for every block, so to -// save some computations, traces are chosen to be convergent. This means that -// if the traces through basic blocks A and B ever cross when moving away from -// A and B, they never diverge again. This applies in both directions - If the -// traces meet above A and B, they won't diverge when going further back. -// -// Traces tend to align with loops. The trace through a block in an inner loop -// will begin at the loop entry block and end at a back edge. If there are -// nested loops, the trace may begin and end at those instead. -// -// For each trace, we compute the critical path length, which is the number of -// cycles required to execute the trace when execution is limited by data -// dependencies only. We also compute the resource height, which is the number -// of cycles required to execute all instructions in the trace when ignoring -// data dependencies. -// -// Every instruction in the current block has a slack - the number of cycles -// execution of the instruction can be delayed without extending the critical -// path. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H -#define LLVM_CODEGEN_MACHINETRACEMETRICS_H - -#include "llvm/ADT/SparseSet.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/TargetSchedule.h" - -namespace llvm { - -class AnalysisUsage; -class MachineFunction; -class MachineInstr; -class MachineLoop; -class MachineLoopInfo; -class MachineRegisterInfo; -struct MCSchedClassDesc; -class raw_ostream; -class TargetInstrInfo; -class TargetRegisterInfo; - -// Keep track of physreg data dependencies by recording each live register unit. -// Associate each regunit with an instruction operand. Depending on the -// direction instructions are scanned, it could be the operand that defined the -// regunit, or the highest operand to read the regunit. -struct LiveRegUnit { - unsigned RegUnit; - unsigned Cycle = 0; - const MachineInstr *MI = nullptr; - unsigned Op = 0; - - unsigned getSparseSetIndex() const { return RegUnit; } - - LiveRegUnit(unsigned RU) : RegUnit(RU) {} -}; - - -class MachineTraceMetrics : public MachineFunctionPass { - const MachineFunction *MF = nullptr; - const TargetInstrInfo *TII = nullptr; - const TargetRegisterInfo *TRI = nullptr; - const MachineRegisterInfo *MRI = nullptr; - const MachineLoopInfo *Loops = nullptr; - TargetSchedModel SchedModel; - -public: - friend class Ensemble; - friend class Trace; - - class Ensemble; - - static char ID; - - MachineTraceMetrics(); - - void getAnalysisUsage(AnalysisUsage&) const override; - bool runOnMachineFunction(MachineFunction&) override; - void releaseMemory() override; - void verifyAnalysis() const override; - - /// Per-basic block information that doesn't depend on the trace through the - /// block. - struct FixedBlockInfo { - /// The number of non-trivial instructions in the block. - /// Doesn't count PHI and COPY instructions that are likely to be removed. - unsigned InstrCount = ~0u; - - /// True when the block contains calls. - bool HasCalls = false; - - FixedBlockInfo() = default; - - /// Returns true when resource information for this block has been computed. - bool hasResources() const { return InstrCount != ~0u; } - - /// Invalidate resource information. - void invalidate() { InstrCount = ~0u; } - }; - - /// Get the fixed resource information about MBB. Compute it on demand. - const FixedBlockInfo *getResources(const MachineBasicBlock*); - - /// Get the scaled number of cycles used per processor resource in MBB. - /// This is an array with SchedModel.getNumProcResourceKinds() entries. - /// The getResources() function above must have been called first. - /// - /// These numbers have already been scaled by SchedModel.getResourceFactor(). - ArrayRef getProcResourceCycles(unsigned MBBNum) const; - - /// A virtual register or regunit required by a basic block or its trace - /// successors. - struct LiveInReg { - /// The virtual register required, or a register unit. - Register Reg; - - /// For virtual registers: Minimum height of the defining instruction. - /// For regunits: Height of the highest user in the trace. - unsigned Height; - - LiveInReg(Register Reg, unsigned Height = 0) : Reg(Reg), Height(Height) {} - }; - - /// Per-basic block information that relates to a specific trace through the - /// block. Convergent traces means that only one of these is required per - /// block in a trace ensemble. - struct TraceBlockInfo { - /// Trace predecessor, or NULL for the first block in the trace. - /// Valid when hasValidDepth(). - const MachineBasicBlock *Pred = nullptr; - - /// Trace successor, or NULL for the last block in the trace. - /// Valid when hasValidHeight(). - const MachineBasicBlock *Succ = nullptr; - - /// The block number of the head of the trace. (When hasValidDepth()). - unsigned Head; - - /// The block number of the tail of the trace. (When hasValidHeight()). - unsigned Tail; - - /// Accumulated number of instructions in the trace above this block. - /// Does not include instructions in this block. - unsigned InstrDepth = ~0u; - - /// Accumulated number of instructions in the trace below this block. - /// Includes instructions in this block. - unsigned InstrHeight = ~0u; - - TraceBlockInfo() = default; - - /// Returns true if the depth resources have been computed from the trace - /// above this block. - bool hasValidDepth() const { return InstrDepth != ~0u; } - - /// Returns true if the height resources have been computed from the trace - /// below this block. - bool hasValidHeight() const { return InstrHeight != ~0u; } - - /// Invalidate depth resources when some block above this one has changed. - void invalidateDepth() { InstrDepth = ~0u; HasValidInstrDepths = false; } - - /// Invalidate height resources when a block below this one has changed. - void invalidateHeight() { InstrHeight = ~0u; HasValidInstrHeights = false; } - - /// Assuming that this is a dominator of TBI, determine if it contains - /// useful instruction depths. A dominating block can be above the current - /// trace head, and any dependencies from such a far away dominator are not - /// expected to affect the critical path. - /// - /// Also returns true when TBI == this. - bool isUsefulDominator(const TraceBlockInfo &TBI) const { - // The trace for TBI may not even be calculated yet. - if (!hasValidDepth() || !TBI.hasValidDepth()) - return false; - // Instruction depths are only comparable if the traces share a head. - if (Head != TBI.Head) - return false; - // It is almost always the case that TBI belongs to the same trace as - // this block, but rare convoluted cases involving irreducible control - // flow, a dominator may share a trace head without actually being on the - // same trace as TBI. This is not a big problem as long as it doesn't - // increase the instruction depth. - return HasValidInstrDepths && InstrDepth <= TBI.InstrDepth; - } - - // Data-dependency-related information. Per-instruction depth and height - // are computed from data dependencies in the current trace, using - // itinerary data. - - /// Instruction depths have been computed. This implies hasValidDepth(). - bool HasValidInstrDepths = false; - - /// Instruction heights have been computed. This implies hasValidHeight(). - bool HasValidInstrHeights = false; - - /// Critical path length. This is the number of cycles in the longest data - /// dependency chain through the trace. This is only valid when both - /// HasValidInstrDepths and HasValidInstrHeights are set. - unsigned CriticalPath; - - /// Live-in registers. These registers are defined above the current block - /// and used by this block or a block below it. - /// This does not include PHI uses in the current block, but it does - /// include PHI uses in deeper blocks. - SmallVector LiveIns; - - void print(raw_ostream&) const; - }; - - /// InstrCycles represents the cycle height and depth of an instruction in a - /// trace. - struct InstrCycles { - /// Earliest issue cycle as determined by data dependencies and instruction - /// latencies from the beginning of the trace. Data dependencies from - /// before the trace are not included. - unsigned Depth; - - /// Minimum number of cycles from this instruction is issued to the of the - /// trace, as determined by data dependencies and instruction latencies. - unsigned Height; - }; - - /// A trace represents a plausible sequence of executed basic blocks that - /// passes through the current basic block one. The Trace class serves as a - /// handle to internal cached data structures. - class Trace { - Ensemble &TE; - TraceBlockInfo &TBI; - - unsigned getBlockNum() const { return &TBI - &TE.BlockInfo[0]; } - - public: - explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {} - - void print(raw_ostream&) const; - - /// Compute the total number of instructions in the trace. - unsigned getInstrCount() const { - return TBI.InstrDepth + TBI.InstrHeight; - } - - /// Return the resource depth of the top/bottom of the trace center block. - /// This is the number of cycles required to execute all instructions from - /// the trace head to the trace center block. The resource depth only - /// considers execution resources, it ignores data dependencies. - /// When Bottom is set, instructions in the trace center block are included. - unsigned getResourceDepth(bool Bottom) const; - - /// Return the resource length of the trace. This is the number of cycles - /// required to execute the instructions in the trace if they were all - /// independent, exposing the maximum instruction-level parallelism. - /// - /// Any blocks in Extrablocks are included as if they were part of the - /// trace. Likewise, extra resources required by the specified scheduling - /// classes are included. For the caller to account for extra machine - /// instructions, it must first resolve each instruction's scheduling class. - unsigned getResourceLength( - ArrayRef Extrablocks = None, - ArrayRef ExtraInstrs = None, - ArrayRef RemoveInstrs = None) const; - - /// Return the length of the (data dependency) critical path through the - /// trace. - unsigned getCriticalPath() const { return TBI.CriticalPath; } - - /// Return the depth and height of MI. The depth is only valid for - /// instructions in or above the trace center block. The height is only - /// valid for instructions in or below the trace center block. - InstrCycles getInstrCycles(const MachineInstr &MI) const { - return TE.Cycles.lookup(&MI); - } - - /// Return the slack of MI. This is the number of cycles MI can be delayed - /// before the critical path becomes longer. - /// MI must be an instruction in the trace center block. - unsigned getInstrSlack(const MachineInstr &MI) const; - - /// Return the Depth of a PHI instruction in a trace center block successor. - /// The PHI does not have to be part of the trace. - unsigned getPHIDepth(const MachineInstr &PHI) const; - - /// A dependence is useful if the basic block of the defining instruction - /// is part of the trace of the user instruction. It is assumed that DefMI - /// dominates UseMI (see also isUsefulDominator). - bool isDepInTrace(const MachineInstr &DefMI, - const MachineInstr &UseMI) const; - }; - - /// A trace ensemble is a collection of traces selected using the same - /// strategy, for example 'minimum resource height'. There is one trace for - /// every block in the function. - class Ensemble { - friend class Trace; - - SmallVector BlockInfo; - DenseMap Cycles; - SmallVector ProcResourceDepths; - SmallVector ProcResourceHeights; - - void computeTrace(const MachineBasicBlock*); - void computeDepthResources(const MachineBasicBlock*); - void computeHeightResources(const MachineBasicBlock*); - unsigned computeCrossBlockCriticalPath(const TraceBlockInfo&); - void computeInstrDepths(const MachineBasicBlock*); - void computeInstrHeights(const MachineBasicBlock*); - void addLiveIns(const MachineInstr *DefMI, unsigned DefOp, - ArrayRef Trace); - - protected: - MachineTraceMetrics &MTM; - - explicit Ensemble(MachineTraceMetrics*); - - virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0; - virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0; - const MachineLoop *getLoopFor(const MachineBasicBlock*) const; - const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const; - const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const; - ArrayRef getProcResourceDepths(unsigned MBBNum) const; - ArrayRef getProcResourceHeights(unsigned MBBNum) const; - - public: - virtual ~Ensemble(); - - virtual const char *getName() const = 0; - void print(raw_ostream&) const; - void invalidate(const MachineBasicBlock *MBB); - void verify() const; - - /// Get the trace that passes through MBB. - /// The trace is computed on demand. - Trace getTrace(const MachineBasicBlock *MBB); - - /// Updates the depth of an machine instruction, given RegUnits. - void updateDepth(TraceBlockInfo &TBI, const MachineInstr&, - SparseSet &RegUnits); - void updateDepth(const MachineBasicBlock *, const MachineInstr&, - SparseSet &RegUnits); - - /// Updates the depth of the instructions from Start to End. - void updateDepths(MachineBasicBlock::iterator Start, - MachineBasicBlock::iterator End, - SparseSet &RegUnits); - - }; - - /// Strategies for selecting traces. - enum Strategy { - /// Select the trace through a block that has the fewest instructions. - TS_MinInstrCount, - - TS_NumStrategies - }; - - /// Get the trace ensemble representing the given trace selection strategy. - /// The returned Ensemble object is owned by the MachineTraceMetrics analysis, - /// and valid for the lifetime of the analysis pass. - Ensemble *getEnsemble(Strategy); - - /// Invalidate cached information about MBB. This must be called *before* MBB - /// is erased, or the CFG is otherwise changed. - /// - /// This invalidates per-block information about resource usage for MBB only, - /// and it invalidates per-trace information for any trace that passes - /// through MBB. - /// - /// Call Ensemble::getTrace() again to update any trace handles. - void invalidate(const MachineBasicBlock *MBB); - -private: - // One entry per basic block, indexed by block number. - SmallVector BlockInfo; - - // Cycles consumed on each processor resource per block. - // The number of processor resource kinds is constant for a given subtarget, - // but it is not known at compile time. The number of cycles consumed by - // block B on processor resource R is at ProcResourceCycles[B*Kinds + R] - // where Kinds = SchedModel.getNumProcResourceKinds(). - SmallVector ProcResourceCycles; - - // One ensemble per strategy. - Ensemble* Ensembles[TS_NumStrategies]; - - // Convert scaled resource usage to a cycle count that can be compared with - // latencies. - unsigned getCycles(unsigned Scaled) { - unsigned Factor = SchedModel.getLatencyFactor(); - return (Scaled + Factor - 1) / Factor; - } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, - const MachineTraceMetrics::Trace &Tr) { - Tr.print(OS); - return OS; -} - -inline raw_ostream &operator<<(raw_ostream &OS, - const MachineTraceMetrics::Ensemble &En) { - En.print(OS); - return OS; -} - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINETRACEMETRICS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MacroFusion.h b/suite/synctools/tablegen/include/llvm/CodeGen/MacroFusion.h deleted file mode 100644 index ea2c7a5faa..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MacroFusion.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- MacroFusion.h - Macro Fusion -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file This file contains the definition of the DAG scheduling mutation to -/// pair instructions back to back. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACROFUSION_H -#define LLVM_CODEGEN_MACROFUSION_H - -#include -#include - -namespace llvm { - -class MachineInstr; -class ScheduleDAGMutation; -class TargetInstrInfo; -class TargetSubtargetInfo; -class ScheduleDAGInstrs; -class SUnit; - -/// Check if the instr pair, FirstMI and SecondMI, should be fused -/// together. Given SecondMI, when FirstMI is unspecified, then check if -/// SecondMI may be part of a fused pair at all. -using ShouldSchedulePredTy = std::function; - -/// Checks if the number of cluster edges between SU and its predecessors is -/// less than FuseLimit -bool hasLessThanNumFused(const SUnit &SU, unsigned FuseLimit); - -/// Create an artificial edge between FirstSU and SecondSU. -/// Make data dependencies from the FirstSU also dependent on the SecondSU to -/// prevent them from being scheduled between the FirstSU and the SecondSU -/// and vice-versa. -/// Fusing more than 2 instructions is not currently supported. -bool fuseInstructionPair(ScheduleDAGInstrs &DAG, SUnit &FirstSU, - SUnit &SecondSU); - -/// Create a DAG scheduling mutation to pair instructions back to back -/// for instructions that benefit according to the target-specific -/// shouldScheduleAdjacent predicate function. -std::unique_ptr -createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent); - -/// Create a DAG scheduling mutation to pair branch instructions with one -/// of their predecessors back to back for instructions that benefit according -/// to the target-specific shouldScheduleAdjacent predicate function. -std::unique_ptr -createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACROFUSION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ModuloSchedule.h b/suite/synctools/tablegen/include/llvm/CodeGen/ModuloSchedule.h deleted file mode 100644 index dfe8f0f517..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ModuloSchedule.h +++ /dev/null @@ -1,389 +0,0 @@ -//===- ModuloSchedule.h - Software pipeline schedule expansion ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Software pipelining (SWP) is an instruction scheduling technique for loops -// that overlaps loop iterations and exploits ILP via compiler transformations. -// -// There are multiple methods for analyzing a loop and creating a schedule. -// An example algorithm is Swing Modulo Scheduling (implemented by the -// MachinePipeliner). The details of how a schedule is arrived at are irrelevant -// for the task of actually rewriting a loop to adhere to the schedule, which -// is what this file does. -// -// A schedule is, for every instruction in a block, a Cycle and a Stage. Note -// that we only support single-block loops, so "block" and "loop" can be used -// interchangeably. -// -// The Cycle of an instruction defines a partial order of the instructions in -// the remapped loop. Instructions within a cycle must not consume the output -// of any instruction in the same cycle. Cycle information is assumed to have -// been calculated such that the processor will execute instructions in -// lock-step (for example in a VLIW ISA). -// -// The Stage of an instruction defines the mapping between logical loop -// iterations and pipelined loop iterations. An example (unrolled) pipeline -// may look something like: -// -// I0[0] Execute instruction I0 of iteration 0 -// I1[0], I0[1] Execute I0 of iteration 1 and I1 of iteration 1 -// I1[1], I0[2] -// I1[2], I0[3] -// -// In the schedule for this unrolled sequence we would say that I0 was scheduled -// in stage 0 and I1 in stage 1: -// -// loop: -// [stage 0] x = I0 -// [stage 1] I1 x (from stage 0) -// -// And to actually generate valid code we must insert a phi: -// -// loop: -// x' = phi(x) -// x = I0 -// I1 x' -// -// This is a simple example; the rules for how to generate correct code given -// an arbitrary schedule containing loop-carried values are complex. -// -// Note that these examples only mention the steady-state kernel of the -// generated loop; prologs and epilogs must be generated also that prime and -// flush the pipeline. Doing so is nontrivial. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MODULOSCHEDULE_H -#define LLVM_CODEGEN_MODULOSCHEDULE_H - -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineLoopUtils.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include -#include - -namespace llvm { -class MachineBasicBlock; -class MachineInstr; -class LiveIntervals; - -/// Represents a schedule for a single-block loop. For every instruction we -/// maintain a Cycle and Stage. -class ModuloSchedule { -private: - /// The block containing the loop instructions. - MachineLoop *Loop; - - /// The instructions to be generated, in total order. Cycle provides a partial - /// order; the total order within cycles has been decided by the schedule - /// producer. - std::vector ScheduledInstrs; - - /// The cycle for each instruction. - DenseMap Cycle; - - /// The stage for each instruction. - DenseMap Stage; - - /// The number of stages in this schedule (Max(Stage) + 1). - int NumStages; - -public: - /// Create a new ModuloSchedule. - /// \arg ScheduledInstrs The new loop instructions, in total resequenced - /// order. - /// \arg Cycle Cycle index for all instructions in ScheduledInstrs. Cycle does - /// not need to start at zero. ScheduledInstrs must be partially ordered by - /// Cycle. - /// \arg Stage Stage index for all instructions in ScheduleInstrs. - ModuloSchedule(MachineFunction &MF, MachineLoop *Loop, - std::vector ScheduledInstrs, - DenseMap Cycle, - DenseMap Stage) - : Loop(Loop), ScheduledInstrs(ScheduledInstrs), Cycle(std::move(Cycle)), - Stage(std::move(Stage)) { - NumStages = 0; - for (auto &KV : this->Stage) - NumStages = std::max(NumStages, KV.second); - ++NumStages; - } - - /// Return the single-block loop being scheduled. - MachineLoop *getLoop() const { return Loop; } - - /// Return the number of stages contained in this schedule, which is the - /// largest stage index + 1. - int getNumStages() const { return NumStages; } - - /// Return the first cycle in the schedule, which is the cycle index of the - /// first instruction. - int getFirstCycle() { return Cycle[ScheduledInstrs.front()]; } - - /// Return the final cycle in the schedule, which is the cycle index of the - /// last instruction. - int getFinalCycle() { return Cycle[ScheduledInstrs.back()]; } - - /// Return the stage that MI is scheduled in, or -1. - int getStage(MachineInstr *MI) { - auto I = Stage.find(MI); - return I == Stage.end() ? -1 : I->second; - } - - /// Return the cycle that MI is scheduled at, or -1. - int getCycle(MachineInstr *MI) { - auto I = Cycle.find(MI); - return I == Cycle.end() ? -1 : I->second; - } - - /// Set the stage of a newly created instruction. - void setStage(MachineInstr *MI, int MIStage) { - assert(Stage.count(MI) == 0); - Stage[MI] = MIStage; - } - - /// Return the rescheduled instructions in order. - ArrayRef getInstructions() { return ScheduledInstrs; } - - void dump() { print(dbgs()); } - void print(raw_ostream &OS); -}; - -/// The ModuloScheduleExpander takes a ModuloSchedule and expands it in-place, -/// rewriting the old loop and inserting prologs and epilogs as required. -class ModuloScheduleExpander { -public: - using InstrChangesTy = DenseMap>; - -private: - using ValueMapTy = DenseMap; - using MBBVectorTy = SmallVectorImpl; - using InstrMapTy = DenseMap; - - ModuloSchedule &Schedule; - MachineFunction &MF; - const TargetSubtargetInfo &ST; - MachineRegisterInfo &MRI; - const TargetInstrInfo *TII; - LiveIntervals &LIS; - - MachineBasicBlock *BB; - MachineBasicBlock *Preheader; - MachineBasicBlock *NewKernel = nullptr; - std::unique_ptr LoopInfo; - - /// Map for each register and the max difference between its uses and def. - /// The first element in the pair is the max difference in stages. The - /// second is true if the register defines a Phi value and loop value is - /// scheduled before the Phi. - std::map> RegToStageDiff; - - /// Instructions to change when emitting the final schedule. - InstrChangesTy InstrChanges; - - void generatePipelinedLoop(); - void generateProlog(unsigned LastStage, MachineBasicBlock *KernelBB, - ValueMapTy *VRMap, MBBVectorTy &PrologBBs); - void generateEpilog(unsigned LastStage, MachineBasicBlock *KernelBB, - ValueMapTy *VRMap, MBBVectorTy &EpilogBBs, - MBBVectorTy &PrologBBs); - void generateExistingPhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, - MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, - ValueMapTy *VRMap, InstrMapTy &InstrMap, - unsigned LastStageNum, unsigned CurStageNum, - bool IsLast); - void generatePhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, - MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, - ValueMapTy *VRMap, InstrMapTy &InstrMap, - unsigned LastStageNum, unsigned CurStageNum, bool IsLast); - void removeDeadInstructions(MachineBasicBlock *KernelBB, - MBBVectorTy &EpilogBBs); - void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs); - void addBranches(MachineBasicBlock &PreheaderBB, MBBVectorTy &PrologBBs, - MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, - ValueMapTy *VRMap); - bool computeDelta(MachineInstr &MI, unsigned &Delta); - void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI, - unsigned Num); - MachineInstr *cloneInstr(MachineInstr *OldMI, unsigned CurStageNum, - unsigned InstStageNum); - MachineInstr *cloneAndChangeInstr(MachineInstr *OldMI, unsigned CurStageNum, - unsigned InstStageNum); - void updateInstruction(MachineInstr *NewMI, bool LastDef, - unsigned CurStageNum, unsigned InstrStageNum, - ValueMapTy *VRMap); - MachineInstr *findDefInLoop(unsigned Reg); - unsigned getPrevMapVal(unsigned StageNum, unsigned PhiStage, unsigned LoopVal, - unsigned LoopStage, ValueMapTy *VRMap, - MachineBasicBlock *BB); - void rewritePhiValues(MachineBasicBlock *NewBB, unsigned StageNum, - ValueMapTy *VRMap, InstrMapTy &InstrMap); - void rewriteScheduledInstr(MachineBasicBlock *BB, InstrMapTy &InstrMap, - unsigned CurStageNum, unsigned PhiNum, - MachineInstr *Phi, unsigned OldReg, - unsigned NewReg, unsigned PrevReg = 0); - bool isLoopCarried(MachineInstr &Phi); - - /// Return the max. number of stages/iterations that can occur between a - /// register definition and its uses. - unsigned getStagesForReg(int Reg, unsigned CurStage) { - std::pair Stages = RegToStageDiff[Reg]; - if ((int)CurStage > Schedule.getNumStages() - 1 && Stages.first == 0 && - Stages.second) - return 1; - return Stages.first; - } - - /// The number of stages for a Phi is a little different than other - /// instructions. The minimum value computed in RegToStageDiff is 1 - /// because we assume the Phi is needed for at least 1 iteration. - /// This is not the case if the loop value is scheduled prior to the - /// Phi in the same stage. This function returns the number of stages - /// or iterations needed between the Phi definition and any uses. - unsigned getStagesForPhi(int Reg) { - std::pair Stages = RegToStageDiff[Reg]; - if (Stages.second) - return Stages.first; - return Stages.first - 1; - } - -public: - /// Create a new ModuloScheduleExpander. - /// \arg InstrChanges Modifications to make to instructions with memory - /// operands. - /// FIXME: InstrChanges is opaque and is an implementation detail of an - /// optimization in MachinePipeliner that crosses abstraction boundaries. - ModuloScheduleExpander(MachineFunction &MF, ModuloSchedule &S, - LiveIntervals &LIS, InstrChangesTy InstrChanges) - : Schedule(S), MF(MF), ST(MF.getSubtarget()), MRI(MF.getRegInfo()), - TII(ST.getInstrInfo()), LIS(LIS), - InstrChanges(std::move(InstrChanges)) {} - - /// Performs the actual expansion. - void expand(); - /// Performs final cleanup after expansion. - void cleanup(); - - /// Returns the newly rewritten kernel block, or nullptr if this was - /// optimized away. - MachineBasicBlock *getRewrittenKernel() { return NewKernel; } -}; - -/// A reimplementation of ModuloScheduleExpander. It works by generating a -/// standalone kernel loop and peeling out the prologs and epilogs. -class PeelingModuloScheduleExpander { -public: - PeelingModuloScheduleExpander(MachineFunction &MF, ModuloSchedule &S, - LiveIntervals *LIS) - : Schedule(S), MF(MF), ST(MF.getSubtarget()), MRI(MF.getRegInfo()), - TII(ST.getInstrInfo()), LIS(LIS) {} - - void expand(); - - /// Runs ModuloScheduleExpander and treats it as a golden input to validate - /// aspects of the code generated by PeelingModuloScheduleExpander. - void validateAgainstModuloScheduleExpander(); - -protected: - ModuloSchedule &Schedule; - MachineFunction &MF; - const TargetSubtargetInfo &ST; - MachineRegisterInfo &MRI; - const TargetInstrInfo *TII; - LiveIntervals *LIS; - - /// The original loop block that gets rewritten in-place. - MachineBasicBlock *BB; - /// The original loop preheader. - MachineBasicBlock *Preheader; - /// All prolog and epilog blocks. - SmallVector Prologs, Epilogs; - /// For every block, the stages that are produced. - DenseMap LiveStages; - /// For every block, the stages that are available. A stage can be available - /// but not produced (in the epilog) or produced but not available (in the - /// prolog). - DenseMap AvailableStages; - /// When peeling the epilogue keep track of the distance between the phi - /// nodes and the kernel. - DenseMap PhiNodeLoopIteration; - - /// CanonicalMIs and BlockMIs form a bidirectional map between any of the - /// loop kernel clones. - DenseMap CanonicalMIs; - DenseMap, MachineInstr *> - BlockMIs; - - /// State passed from peelKernel to peelPrologAndEpilogs(). - std::deque PeeledFront, PeeledBack; - /// Illegal phis that need to be deleted once we re-link stages. - SmallVector IllegalPhisToDelete; - - /// Converts BB from the original loop body to the rewritten, pipelined - /// steady-state. - void rewriteKernel(); - - /// Peels one iteration of the rewritten kernel (BB) in the specified - /// direction. - MachineBasicBlock *peelKernel(LoopPeelDirection LPD); - // Delete instructions whose stage is less than MinStage in the given basic - // block. - void filterInstructions(MachineBasicBlock *MB, int MinStage); - // Move instructions of the given stage from sourceBB to DestBB. Remap the phi - // instructions to keep a valid IR. - void moveStageBetweenBlocks(MachineBasicBlock *DestBB, - MachineBasicBlock *SourceBB, unsigned Stage); - /// Peel the kernel forwards and backwards to produce prologs and epilogs, - /// and stitch them together. - void peelPrologAndEpilogs(); - /// All prolog and epilog blocks are clones of the kernel, so any produced - /// register in one block has an corollary in all other blocks. - Register getEquivalentRegisterIn(Register Reg, MachineBasicBlock *BB); - /// Change all users of MI, if MI is predicated out - /// (LiveStages[MI->getParent()] == false). - void rewriteUsesOf(MachineInstr *MI); - /// Insert branches between prologs, kernel and epilogs. - void fixupBranches(); - /// Create a poor-man's LCSSA by cloning only the PHIs from the kernel block - /// to a block dominated by all prologs and epilogs. This allows us to treat - /// the loop exiting block as any other kernel clone. - MachineBasicBlock *CreateLCSSAExitingBlock(); - /// Helper to get the stage of an instruction in the schedule. - unsigned getStage(MachineInstr *MI) { - if (CanonicalMIs.count(MI)) - MI = CanonicalMIs[MI]; - return Schedule.getStage(MI); - } - /// Helper function to find the right canonical register for a phi instruction - /// coming from a peeled out prologue. - Register getPhiCanonicalReg(MachineInstr* CanonicalPhi, MachineInstr* Phi); - /// Target loop info before kernel peeling. - std::unique_ptr LoopInfo; -}; - -/// Expander that simply annotates each scheduled instruction with a post-instr -/// symbol that can be consumed by the ModuloScheduleTest pass. -/// -/// The post-instr symbol is a way of annotating an instruction that can be -/// roundtripped in MIR. The syntax is: -/// MYINST %0, post-instr-symbol -class ModuloScheduleTestAnnotater { - MachineFunction &MF; - ModuloSchedule &S; - -public: - ModuloScheduleTestAnnotater(MachineFunction &MF, ModuloSchedule &S) - : MF(MF), S(S) {} - - /// Performs the annotation. - void annotate(); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MODULOSCHEDULE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/MultiHazardRecognizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/MultiHazardRecognizer.h deleted file mode 100644 index 9846045ff0..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/MultiHazardRecognizer.h +++ /dev/null @@ -1,47 +0,0 @@ -//=- llvm/CodeGen/MultiHazardRecognizer.h - Scheduling Support ----*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the MultiHazardRecognizer class, which is a wrapper -// for a set of ScheduleHazardRecognizer instances -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H -#define LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" - -namespace llvm { - -class MachineInstr; -class SUnit; - -class MultiHazardRecognizer : public ScheduleHazardRecognizer { - SmallVector, 4> Recognizers; - -public: - MultiHazardRecognizer() = default; - void AddHazardRecognizer(std::unique_ptr &&); - - bool atIssueLimit() const override; - HazardType getHazardType(SUnit *, int Stalls = 0) override; - void Reset() override; - void EmitInstruction(SUnit *) override; - void EmitInstruction(MachineInstr *) override; - unsigned PreEmitNoops(SUnit *) override; - unsigned PreEmitNoops(MachineInstr *) override; - bool ShouldPreferAnother(SUnit *) override; - void AdvanceCycle() override; - void RecedeCycle() override; - void EmitNoop() override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/NonRelocatableStringpool.h b/suite/synctools/tablegen/include/llvm/CodeGen/NonRelocatableStringpool.h deleted file mode 100644 index fe07c70d85..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/NonRelocatableStringpool.h +++ /dev/null @@ -1,83 +0,0 @@ -//===- NonRelocatableStringpool.h -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_NONRELOCATABLESTRINGPOOL_H -#define LLVM_CODEGEN_NONRELOCATABLESTRINGPOOL_H - -#include "llvm/CodeGen/DwarfStringPoolEntry.h" -#include "llvm/Support/Allocator.h" -#include -#include - -namespace llvm { - -/// A string table that doesn't need relocations. -/// -/// Use this class when a string table doesn't need relocations. -/// This class provides this ability by just associating offsets with strings. -class NonRelocatableStringpool { -public: - /// Entries are stored into the StringMap and simply linked together through - /// the second element of this pair in order to keep track of insertion - /// order. - using MapTy = StringMap; - - NonRelocatableStringpool( - std::function Translator = nullptr, - bool PutEmptyString = false) - : Translator(Translator) { - if (PutEmptyString) - EmptyString = getEntry(""); - } - - DwarfStringPoolEntryRef getEntry(StringRef S); - - /// Get the offset of string \p S in the string table. This can insert a new - /// element or return the offset of a pre-existing one. - uint64_t getStringOffset(StringRef S) { return getEntry(S).getOffset(); } - - /// Get permanent storage for \p S (but do not necessarily emit \p S in the - /// output section). A latter call to getStringOffset() with the same string - /// will chain it though. - /// - /// \returns The StringRef that points to permanent storage to use - /// in place of \p S. - StringRef internString(StringRef S); - - uint64_t getSize() { return CurrentEndOffset; } - - /// Return the list of strings to be emitted. This does not contain the - /// strings which were added via internString only. - std::vector getEntriesForEmission() const; - -private: - MapTy Strings; - uint64_t CurrentEndOffset = 0; - unsigned NumEntries = 0; - DwarfStringPoolEntryRef EmptyString; - std::function Translator; -}; - -/// Helper for making strong types. -template class StrongType : public T { -public: - template - explicit StrongType(Args... A) : T(std::forward(A)...) {} -}; - -/// It's very easy to introduce bugs by passing the wrong string pool. -/// By using strong types the interface enforces that the right -/// kind of pool is used. -struct UniqueTag {}; -struct OffsetsTag {}; -using UniquingStringPool = StrongType; -using OffsetsStringPool = StrongType; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_NONRELOCATABLESTRINGPOOL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/CostAllocator.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/CostAllocator.h deleted file mode 100644 index 0d6d8a3131..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/CostAllocator.h +++ /dev/null @@ -1,134 +0,0 @@ -//===- CostAllocator.h - PBQP Cost Allocator --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines classes conforming to the PBQP cost value manager concept. -// -// Cost value managers are memory managers for PBQP cost values (vectors and -// matrices). Since PBQP graphs can grow very large (E.g. hundreds of thousands -// of edges on the largest function in SPEC2006). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_COSTALLOCATOR_H -#define LLVM_CODEGEN_PBQP_COSTALLOCATOR_H - -#include "llvm/ADT/DenseSet.h" -#include -#include -#include - -namespace llvm { -namespace PBQP { - -template class ValuePool { -public: - using PoolRef = std::shared_ptr; - -private: - class PoolEntry : public std::enable_shared_from_this { - public: - template - PoolEntry(ValuePool &Pool, ValueKeyT Value) - : Pool(Pool), Value(std::move(Value)) {} - - ~PoolEntry() { Pool.removeEntry(this); } - - const ValueT &getValue() const { return Value; } - - private: - ValuePool &Pool; - ValueT Value; - }; - - class PoolEntryDSInfo { - public: - static inline PoolEntry *getEmptyKey() { return nullptr; } - - static inline PoolEntry *getTombstoneKey() { - return reinterpret_cast(static_cast(1)); - } - - template - static unsigned getHashValue(const ValueKeyT &C) { - return hash_value(C); - } - - static unsigned getHashValue(PoolEntry *P) { - return getHashValue(P->getValue()); - } - - static unsigned getHashValue(const PoolEntry *P) { - return getHashValue(P->getValue()); - } - - template - static bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) { - return C1 == C2; - } - - template - static bool isEqual(const ValueKeyT &C, PoolEntry *P) { - if (P == getEmptyKey() || P == getTombstoneKey()) - return false; - return isEqual(C, P->getValue()); - } - - static bool isEqual(PoolEntry *P1, PoolEntry *P2) { - if (P1 == getEmptyKey() || P1 == getTombstoneKey()) - return P1 == P2; - return isEqual(P1->getValue(), P2); - } - }; - - using EntrySetT = DenseSet; - - EntrySetT EntrySet; - - void removeEntry(PoolEntry *P) { EntrySet.erase(P); } - -public: - template PoolRef getValue(ValueKeyT ValueKey) { - typename EntrySetT::iterator I = EntrySet.find_as(ValueKey); - - if (I != EntrySet.end()) - return PoolRef((*I)->shared_from_this(), &(*I)->getValue()); - - auto P = std::make_shared(*this, std::move(ValueKey)); - EntrySet.insert(P.get()); - return PoolRef(std::move(P), &P->getValue()); - } -}; - -template class PoolCostAllocator { -private: - using VectorCostPool = ValuePool; - using MatrixCostPool = ValuePool; - -public: - using Vector = VectorT; - using Matrix = MatrixT; - using VectorPtr = typename VectorCostPool::PoolRef; - using MatrixPtr = typename MatrixCostPool::PoolRef; - - template VectorPtr getVector(VectorKeyT v) { - return VectorPool.getValue(std::move(v)); - } - - template MatrixPtr getMatrix(MatrixKeyT m) { - return MatrixPool.getValue(std::move(m)); - } - -private: - VectorCostPool VectorPool; - MatrixCostPool MatrixPool; -}; - -} // end namespace PBQP -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQP_COSTALLOCATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Graph.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Graph.h deleted file mode 100644 index 5077ae8377..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Graph.h +++ /dev/null @@ -1,674 +0,0 @@ -//===- Graph.h - PBQP Graph -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// PBQP Graph class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_GRAPH_H -#define LLVM_CODEGEN_PBQP_GRAPH_H - -#include "llvm/ADT/STLExtras.h" -#include -#include -#include -#include -#include - -namespace llvm { -namespace PBQP { - - class GraphBase { - public: - using NodeId = unsigned; - using EdgeId = unsigned; - - /// Returns a value representing an invalid (non-existent) node. - static NodeId invalidNodeId() { - return std::numeric_limits::max(); - } - - /// Returns a value representing an invalid (non-existent) edge. - static EdgeId invalidEdgeId() { - return std::numeric_limits::max(); - } - }; - - /// PBQP Graph class. - /// Instances of this class describe PBQP problems. - /// - template - class Graph : public GraphBase { - private: - using CostAllocator = typename SolverT::CostAllocator; - - public: - using RawVector = typename SolverT::RawVector; - using RawMatrix = typename SolverT::RawMatrix; - using Vector = typename SolverT::Vector; - using Matrix = typename SolverT::Matrix; - using VectorPtr = typename CostAllocator::VectorPtr; - using MatrixPtr = typename CostAllocator::MatrixPtr; - using NodeMetadata = typename SolverT::NodeMetadata; - using EdgeMetadata = typename SolverT::EdgeMetadata; - using GraphMetadata = typename SolverT::GraphMetadata; - - private: - class NodeEntry { - public: - using AdjEdgeList = std::vector; - using AdjEdgeIdx = AdjEdgeList::size_type; - using AdjEdgeItr = AdjEdgeList::const_iterator; - - NodeEntry(VectorPtr Costs) : Costs(std::move(Costs)) {} - - static AdjEdgeIdx getInvalidAdjEdgeIdx() { - return std::numeric_limits::max(); - } - - AdjEdgeIdx addAdjEdgeId(EdgeId EId) { - AdjEdgeIdx Idx = AdjEdgeIds.size(); - AdjEdgeIds.push_back(EId); - return Idx; - } - - void removeAdjEdgeId(Graph &G, NodeId ThisNId, AdjEdgeIdx Idx) { - // Swap-and-pop for fast removal. - // 1) Update the adj index of the edge currently at back(). - // 2) Move last Edge down to Idx. - // 3) pop_back() - // If Idx == size() - 1 then the setAdjEdgeIdx and swap are - // redundant, but both operations are cheap. - G.getEdge(AdjEdgeIds.back()).setAdjEdgeIdx(ThisNId, Idx); - AdjEdgeIds[Idx] = AdjEdgeIds.back(); - AdjEdgeIds.pop_back(); - } - - const AdjEdgeList& getAdjEdgeIds() const { return AdjEdgeIds; } - - VectorPtr Costs; - NodeMetadata Metadata; - - private: - AdjEdgeList AdjEdgeIds; - }; - - class EdgeEntry { - public: - EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs) - : Costs(std::move(Costs)) { - NIds[0] = N1Id; - NIds[1] = N2Id; - ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx(); - ThisEdgeAdjIdxs[1] = NodeEntry::getInvalidAdjEdgeIdx(); - } - - void connectToN(Graph &G, EdgeId ThisEdgeId, unsigned NIdx) { - assert(ThisEdgeAdjIdxs[NIdx] == NodeEntry::getInvalidAdjEdgeIdx() && - "Edge already connected to NIds[NIdx]."); - NodeEntry &N = G.getNode(NIds[NIdx]); - ThisEdgeAdjIdxs[NIdx] = N.addAdjEdgeId(ThisEdgeId); - } - - void connect(Graph &G, EdgeId ThisEdgeId) { - connectToN(G, ThisEdgeId, 0); - connectToN(G, ThisEdgeId, 1); - } - - void setAdjEdgeIdx(NodeId NId, typename NodeEntry::AdjEdgeIdx NewIdx) { - if (NId == NIds[0]) - ThisEdgeAdjIdxs[0] = NewIdx; - else { - assert(NId == NIds[1] && "Edge not connected to NId"); - ThisEdgeAdjIdxs[1] = NewIdx; - } - } - - void disconnectFromN(Graph &G, unsigned NIdx) { - assert(ThisEdgeAdjIdxs[NIdx] != NodeEntry::getInvalidAdjEdgeIdx() && - "Edge not connected to NIds[NIdx]."); - NodeEntry &N = G.getNode(NIds[NIdx]); - N.removeAdjEdgeId(G, NIds[NIdx], ThisEdgeAdjIdxs[NIdx]); - ThisEdgeAdjIdxs[NIdx] = NodeEntry::getInvalidAdjEdgeIdx(); - } - - void disconnectFrom(Graph &G, NodeId NId) { - if (NId == NIds[0]) - disconnectFromN(G, 0); - else { - assert(NId == NIds[1] && "Edge does not connect NId"); - disconnectFromN(G, 1); - } - } - - NodeId getN1Id() const { return NIds[0]; } - NodeId getN2Id() const { return NIds[1]; } - - MatrixPtr Costs; - EdgeMetadata Metadata; - - private: - NodeId NIds[2]; - typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2]; - }; - - // ----- MEMBERS ----- - - GraphMetadata Metadata; - CostAllocator CostAlloc; - SolverT *Solver = nullptr; - - using NodeVector = std::vector; - using FreeNodeVector = std::vector; - NodeVector Nodes; - FreeNodeVector FreeNodeIds; - - using EdgeVector = std::vector; - using FreeEdgeVector = std::vector; - EdgeVector Edges; - FreeEdgeVector FreeEdgeIds; - - Graph(const Graph &Other) {} - - // ----- INTERNAL METHODS ----- - - NodeEntry &getNode(NodeId NId) { - assert(NId < Nodes.size() && "Out of bound NodeId"); - return Nodes[NId]; - } - const NodeEntry &getNode(NodeId NId) const { - assert(NId < Nodes.size() && "Out of bound NodeId"); - return Nodes[NId]; - } - - EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; } - const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; } - - NodeId addConstructedNode(NodeEntry N) { - NodeId NId = 0; - if (!FreeNodeIds.empty()) { - NId = FreeNodeIds.back(); - FreeNodeIds.pop_back(); - Nodes[NId] = std::move(N); - } else { - NId = Nodes.size(); - Nodes.push_back(std::move(N)); - } - return NId; - } - - EdgeId addConstructedEdge(EdgeEntry E) { - assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() && - "Attempt to add duplicate edge."); - EdgeId EId = 0; - if (!FreeEdgeIds.empty()) { - EId = FreeEdgeIds.back(); - FreeEdgeIds.pop_back(); - Edges[EId] = std::move(E); - } else { - EId = Edges.size(); - Edges.push_back(std::move(E)); - } - - EdgeEntry &NE = getEdge(EId); - - // Add the edge to the adjacency sets of its nodes. - NE.connect(*this, EId); - return EId; - } - - void operator=(const Graph &Other) {} - - public: - using AdjEdgeItr = typename NodeEntry::AdjEdgeItr; - - class NodeItr { - public: - using iterator_category = std::forward_iterator_tag; - using value_type = NodeId; - using difference_type = int; - using pointer = NodeId *; - using reference = NodeId &; - - NodeItr(NodeId CurNId, const Graph &G) - : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) { - this->CurNId = findNextInUse(CurNId); // Move to first in-use node id - } - - bool operator==(const NodeItr &O) const { return CurNId == O.CurNId; } - bool operator!=(const NodeItr &O) const { return !(*this == O); } - NodeItr& operator++() { CurNId = findNextInUse(++CurNId); return *this; } - NodeId operator*() const { return CurNId; } - - private: - NodeId findNextInUse(NodeId NId) const { - while (NId < EndNId && is_contained(FreeNodeIds, NId)) { - ++NId; - } - return NId; - } - - NodeId CurNId, EndNId; - const FreeNodeVector &FreeNodeIds; - }; - - class EdgeItr { - public: - EdgeItr(EdgeId CurEId, const Graph &G) - : CurEId(CurEId), EndEId(G.Edges.size()), FreeEdgeIds(G.FreeEdgeIds) { - this->CurEId = findNextInUse(CurEId); // Move to first in-use edge id - } - - bool operator==(const EdgeItr &O) const { return CurEId == O.CurEId; } - bool operator!=(const EdgeItr &O) const { return !(*this == O); } - EdgeItr& operator++() { CurEId = findNextInUse(++CurEId); return *this; } - EdgeId operator*() const { return CurEId; } - - private: - EdgeId findNextInUse(EdgeId EId) const { - while (EId < EndEId && is_contained(FreeEdgeIds, EId)) { - ++EId; - } - return EId; - } - - EdgeId CurEId, EndEId; - const FreeEdgeVector &FreeEdgeIds; - }; - - class NodeIdSet { - public: - NodeIdSet(const Graph &G) : G(G) {} - - NodeItr begin() const { return NodeItr(0, G); } - NodeItr end() const { return NodeItr(G.Nodes.size(), G); } - - bool empty() const { return G.Nodes.empty(); } - - typename NodeVector::size_type size() const { - return G.Nodes.size() - G.FreeNodeIds.size(); - } - - private: - const Graph& G; - }; - - class EdgeIdSet { - public: - EdgeIdSet(const Graph &G) : G(G) {} - - EdgeItr begin() const { return EdgeItr(0, G); } - EdgeItr end() const { return EdgeItr(G.Edges.size(), G); } - - bool empty() const { return G.Edges.empty(); } - - typename NodeVector::size_type size() const { - return G.Edges.size() - G.FreeEdgeIds.size(); - } - - private: - const Graph& G; - }; - - class AdjEdgeIdSet { - public: - AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) {} - - typename NodeEntry::AdjEdgeItr begin() const { - return NE.getAdjEdgeIds().begin(); - } - - typename NodeEntry::AdjEdgeItr end() const { - return NE.getAdjEdgeIds().end(); - } - - bool empty() const { return NE.getAdjEdgeIds().empty(); } - - typename NodeEntry::AdjEdgeList::size_type size() const { - return NE.getAdjEdgeIds().size(); - } - - private: - const NodeEntry &NE; - }; - - /// Construct an empty PBQP graph. - Graph() = default; - - /// Construct an empty PBQP graph with the given graph metadata. - Graph(GraphMetadata Metadata) : Metadata(std::move(Metadata)) {} - - /// Get a reference to the graph metadata. - GraphMetadata& getMetadata() { return Metadata; } - - /// Get a const-reference to the graph metadata. - const GraphMetadata& getMetadata() const { return Metadata; } - - /// Lock this graph to the given solver instance in preparation - /// for running the solver. This method will call solver.handleAddNode for - /// each node in the graph, and handleAddEdge for each edge, to give the - /// solver an opportunity to set up any required metadata. - void setSolver(SolverT &S) { - assert(!Solver && "Solver already set. Call unsetSolver()."); - Solver = &S; - for (auto NId : nodeIds()) - Solver->handleAddNode(NId); - for (auto EId : edgeIds()) - Solver->handleAddEdge(EId); - } - - /// Release from solver instance. - void unsetSolver() { - assert(Solver && "Solver not set."); - Solver = nullptr; - } - - /// Add a node with the given costs. - /// @param Costs Cost vector for the new node. - /// @return Node iterator for the added node. - template - NodeId addNode(OtherVectorT Costs) { - // Get cost vector from the problem domain - VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs)); - NodeId NId = addConstructedNode(NodeEntry(AllocatedCosts)); - if (Solver) - Solver->handleAddNode(NId); - return NId; - } - - /// Add a node bypassing the cost allocator. - /// @param Costs Cost vector ptr for the new node (must be convertible to - /// VectorPtr). - /// @return Node iterator for the added node. - /// - /// This method allows for fast addition of a node whose costs don't need - /// to be passed through the cost allocator. The most common use case for - /// this is when duplicating costs from an existing node (when using a - /// pooling allocator). These have already been uniqued, so we can avoid - /// re-constructing and re-uniquing them by attaching them directly to the - /// new node. - template - NodeId addNodeBypassingCostAllocator(OtherVectorPtrT Costs) { - NodeId NId = addConstructedNode(NodeEntry(Costs)); - if (Solver) - Solver->handleAddNode(NId); - return NId; - } - - /// Add an edge between the given nodes with the given costs. - /// @param N1Id First node. - /// @param N2Id Second node. - /// @param Costs Cost matrix for new edge. - /// @return Edge iterator for the added edge. - template - EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) { - assert(getNodeCosts(N1Id).getLength() == Costs.getRows() && - getNodeCosts(N2Id).getLength() == Costs.getCols() && - "Matrix dimensions mismatch."); - // Get cost matrix from the problem domain. - MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); - EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, AllocatedCosts)); - if (Solver) - Solver->handleAddEdge(EId); - return EId; - } - - /// Add an edge bypassing the cost allocator. - /// @param N1Id First node. - /// @param N2Id Second node. - /// @param Costs Cost matrix for new edge. - /// @return Edge iterator for the added edge. - /// - /// This method allows for fast addition of an edge whose costs don't need - /// to be passed through the cost allocator. The most common use case for - /// this is when duplicating costs from an existing edge (when using a - /// pooling allocator). These have already been uniqued, so we can avoid - /// re-constructing and re-uniquing them by attaching them directly to the - /// new edge. - template - NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id, - OtherMatrixPtrT Costs) { - assert(getNodeCosts(N1Id).getLength() == Costs->getRows() && - getNodeCosts(N2Id).getLength() == Costs->getCols() && - "Matrix dimensions mismatch."); - // Get cost matrix from the problem domain. - EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, Costs)); - if (Solver) - Solver->handleAddEdge(EId); - return EId; - } - - /// Returns true if the graph is empty. - bool empty() const { return NodeIdSet(*this).empty(); } - - NodeIdSet nodeIds() const { return NodeIdSet(*this); } - EdgeIdSet edgeIds() const { return EdgeIdSet(*this); } - - AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); } - - /// Get the number of nodes in the graph. - /// @return Number of nodes in the graph. - unsigned getNumNodes() const { return NodeIdSet(*this).size(); } - - /// Get the number of edges in the graph. - /// @return Number of edges in the graph. - unsigned getNumEdges() const { return EdgeIdSet(*this).size(); } - - /// Set a node's cost vector. - /// @param NId Node to update. - /// @param Costs New costs to set. - template - void setNodeCosts(NodeId NId, OtherVectorT Costs) { - VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs)); - if (Solver) - Solver->handleSetNodeCosts(NId, *AllocatedCosts); - getNode(NId).Costs = AllocatedCosts; - } - - /// Get a VectorPtr to a node's cost vector. Rarely useful - use - /// getNodeCosts where possible. - /// @param NId Node id. - /// @return VectorPtr to node cost vector. - /// - /// This method is primarily useful for duplicating costs quickly by - /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer - /// getNodeCosts when dealing with node cost values. - const VectorPtr& getNodeCostsPtr(NodeId NId) const { - return getNode(NId).Costs; - } - - /// Get a node's cost vector. - /// @param NId Node id. - /// @return Node cost vector. - const Vector& getNodeCosts(NodeId NId) const { - return *getNodeCostsPtr(NId); - } - - NodeMetadata& getNodeMetadata(NodeId NId) { - return getNode(NId).Metadata; - } - - const NodeMetadata& getNodeMetadata(NodeId NId) const { - return getNode(NId).Metadata; - } - - typename NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const { - return getNode(NId).getAdjEdgeIds().size(); - } - - /// Update an edge's cost matrix. - /// @param EId Edge id. - /// @param Costs New cost matrix. - template - void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) { - MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); - if (Solver) - Solver->handleUpdateCosts(EId, *AllocatedCosts); - getEdge(EId).Costs = AllocatedCosts; - } - - /// Get a MatrixPtr to a node's cost matrix. Rarely useful - use - /// getEdgeCosts where possible. - /// @param EId Edge id. - /// @return MatrixPtr to edge cost matrix. - /// - /// This method is primarily useful for duplicating costs quickly by - /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer - /// getEdgeCosts when dealing with edge cost values. - const MatrixPtr& getEdgeCostsPtr(EdgeId EId) const { - return getEdge(EId).Costs; - } - - /// Get an edge's cost matrix. - /// @param EId Edge id. - /// @return Edge cost matrix. - const Matrix& getEdgeCosts(EdgeId EId) const { - return *getEdge(EId).Costs; - } - - EdgeMetadata& getEdgeMetadata(EdgeId EId) { - return getEdge(EId).Metadata; - } - - const EdgeMetadata& getEdgeMetadata(EdgeId EId) const { - return getEdge(EId).Metadata; - } - - /// Get the first node connected to this edge. - /// @param EId Edge id. - /// @return The first node connected to the given edge. - NodeId getEdgeNode1Id(EdgeId EId) const { - return getEdge(EId).getN1Id(); - } - - /// Get the second node connected to this edge. - /// @param EId Edge id. - /// @return The second node connected to the given edge. - NodeId getEdgeNode2Id(EdgeId EId) const { - return getEdge(EId).getN2Id(); - } - - /// Get the "other" node connected to this edge. - /// @param EId Edge id. - /// @param NId Node id for the "given" node. - /// @return The iterator for the "other" node connected to this edge. - NodeId getEdgeOtherNodeId(EdgeId EId, NodeId NId) { - EdgeEntry &E = getEdge(EId); - if (E.getN1Id() == NId) { - return E.getN2Id(); - } // else - return E.getN1Id(); - } - - /// Get the edge connecting two nodes. - /// @param N1Id First node id. - /// @param N2Id Second node id. - /// @return An id for edge (N1Id, N2Id) if such an edge exists, - /// otherwise returns an invalid edge id. - EdgeId findEdge(NodeId N1Id, NodeId N2Id) { - for (auto AEId : adjEdgeIds(N1Id)) { - if ((getEdgeNode1Id(AEId) == N2Id) || - (getEdgeNode2Id(AEId) == N2Id)) { - return AEId; - } - } - return invalidEdgeId(); - } - - /// Remove a node from the graph. - /// @param NId Node id. - void removeNode(NodeId NId) { - if (Solver) - Solver->handleRemoveNode(NId); - NodeEntry &N = getNode(NId); - // TODO: Can this be for-each'd? - for (AdjEdgeItr AEItr = N.adjEdgesBegin(), - AEEnd = N.adjEdgesEnd(); - AEItr != AEEnd;) { - EdgeId EId = *AEItr; - ++AEItr; - removeEdge(EId); - } - FreeNodeIds.push_back(NId); - } - - /// Disconnect an edge from the given node. - /// - /// Removes the given edge from the adjacency list of the given node. - /// This operation leaves the edge in an 'asymmetric' state: It will no - /// longer appear in an iteration over the given node's (NId's) edges, but - /// will appear in an iteration over the 'other', unnamed node's edges. - /// - /// This does not correspond to any normal graph operation, but exists to - /// support efficient PBQP graph-reduction based solvers. It is used to - /// 'effectively' remove the unnamed node from the graph while the solver - /// is performing the reduction. The solver will later call reconnectNode - /// to restore the edge in the named node's adjacency list. - /// - /// Since the degree of a node is the number of connected edges, - /// disconnecting an edge from a node 'u' will cause the degree of 'u' to - /// drop by 1. - /// - /// A disconnected edge WILL still appear in an iteration over the graph - /// edges. - /// - /// A disconnected edge should not be removed from the graph, it should be - /// reconnected first. - /// - /// A disconnected edge can be reconnected by calling the reconnectEdge - /// method. - void disconnectEdge(EdgeId EId, NodeId NId) { - if (Solver) - Solver->handleDisconnectEdge(EId, NId); - - EdgeEntry &E = getEdge(EId); - E.disconnectFrom(*this, NId); - } - - /// Convenience method to disconnect all neighbours from the given - /// node. - void disconnectAllNeighborsFromNode(NodeId NId) { - for (auto AEId : adjEdgeIds(NId)) - disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId)); - } - - /// Re-attach an edge to its nodes. - /// - /// Adds an edge that had been previously disconnected back into the - /// adjacency set of the nodes that the edge connects. - void reconnectEdge(EdgeId EId, NodeId NId) { - EdgeEntry &E = getEdge(EId); - E.connectTo(*this, EId, NId); - if (Solver) - Solver->handleReconnectEdge(EId, NId); - } - - /// Remove an edge from the graph. - /// @param EId Edge id. - void removeEdge(EdgeId EId) { - if (Solver) - Solver->handleRemoveEdge(EId); - EdgeEntry &E = getEdge(EId); - E.disconnect(); - FreeEdgeIds.push_back(EId); - Edges[EId].invalidate(); - } - - /// Remove all nodes and edges from the graph. - void clear() { - Nodes.clear(); - FreeNodeIds.clear(); - Edges.clear(); - FreeEdgeIds.clear(); - } - }; - -} // end namespace PBQP -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQP_GRAPH_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Math.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Math.h deleted file mode 100644 index 099ba788e9..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Math.h +++ /dev/null @@ -1,291 +0,0 @@ -//===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_MATH_H -#define LLVM_CODEGEN_PBQP_MATH_H - -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/STLExtras.h" -#include -#include -#include -#include - -namespace llvm { -namespace PBQP { - -using PBQPNum = float; - -/// PBQP Vector class. -class Vector { - friend hash_code hash_value(const Vector &); - -public: - /// Construct a PBQP vector of the given size. - explicit Vector(unsigned Length) - : Length(Length), Data(std::make_unique(Length)) {} - - /// Construct a PBQP vector with initializer. - Vector(unsigned Length, PBQPNum InitVal) - : Length(Length), Data(std::make_unique(Length)) { - std::fill(Data.get(), Data.get() + Length, InitVal); - } - - /// Copy construct a PBQP vector. - Vector(const Vector &V) - : Length(V.Length), Data(std::make_unique(Length)) { - std::copy(V.Data.get(), V.Data.get() + Length, Data.get()); - } - - /// Move construct a PBQP vector. - Vector(Vector &&V) - : Length(V.Length), Data(std::move(V.Data)) { - V.Length = 0; - } - - /// Comparison operator. - bool operator==(const Vector &V) const { - assert(Length != 0 && Data && "Invalid vector"); - if (Length != V.Length) - return false; - return std::equal(Data.get(), Data.get() + Length, V.Data.get()); - } - - /// Return the length of the vector - unsigned getLength() const { - assert(Length != 0 && Data && "Invalid vector"); - return Length; - } - - /// Element access. - PBQPNum& operator[](unsigned Index) { - assert(Length != 0 && Data && "Invalid vector"); - assert(Index < Length && "Vector element access out of bounds."); - return Data[Index]; - } - - /// Const element access. - const PBQPNum& operator[](unsigned Index) const { - assert(Length != 0 && Data && "Invalid vector"); - assert(Index < Length && "Vector element access out of bounds."); - return Data[Index]; - } - - /// Add another vector to this one. - Vector& operator+=(const Vector &V) { - assert(Length != 0 && Data && "Invalid vector"); - assert(Length == V.Length && "Vector length mismatch."); - std::transform(Data.get(), Data.get() + Length, V.Data.get(), Data.get(), - std::plus()); - return *this; - } - - /// Returns the index of the minimum value in this vector - unsigned minIndex() const { - assert(Length != 0 && Data && "Invalid vector"); - return std::min_element(Data.get(), Data.get() + Length) - Data.get(); - } - -private: - unsigned Length; - std::unique_ptr Data; -}; - -/// Return a hash_value for the given vector. -inline hash_code hash_value(const Vector &V) { - unsigned *VBegin = reinterpret_cast(V.Data.get()); - unsigned *VEnd = reinterpret_cast(V.Data.get() + V.Length); - return hash_combine(V.Length, hash_combine_range(VBegin, VEnd)); -} - -/// Output a textual representation of the given vector on the given -/// output stream. -template -OStream& operator<<(OStream &OS, const Vector &V) { - assert((V.getLength() != 0) && "Zero-length vector badness."); - - OS << "[ " << V[0]; - for (unsigned i = 1; i < V.getLength(); ++i) - OS << ", " << V[i]; - OS << " ]"; - - return OS; -} - -/// PBQP Matrix class -class Matrix { -private: - friend hash_code hash_value(const Matrix &); - -public: - /// Construct a PBQP Matrix with the given dimensions. - Matrix(unsigned Rows, unsigned Cols) : - Rows(Rows), Cols(Cols), Data(std::make_unique(Rows * Cols)) { - } - - /// Construct a PBQP Matrix with the given dimensions and initial - /// value. - Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal) - : Rows(Rows), Cols(Cols), - Data(std::make_unique(Rows * Cols)) { - std::fill(Data.get(), Data.get() + (Rows * Cols), InitVal); - } - - /// Copy construct a PBQP matrix. - Matrix(const Matrix &M) - : Rows(M.Rows), Cols(M.Cols), - Data(std::make_unique(Rows * Cols)) { - std::copy(M.Data.get(), M.Data.get() + (Rows * Cols), Data.get()); - } - - /// Move construct a PBQP matrix. - Matrix(Matrix &&M) - : Rows(M.Rows), Cols(M.Cols), Data(std::move(M.Data)) { - M.Rows = M.Cols = 0; - } - - /// Comparison operator. - bool operator==(const Matrix &M) const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - if (Rows != M.Rows || Cols != M.Cols) - return false; - return std::equal(Data.get(), Data.get() + (Rows * Cols), M.Data.get()); - } - - /// Return the number of rows in this matrix. - unsigned getRows() const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - return Rows; - } - - /// Return the number of cols in this matrix. - unsigned getCols() const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - return Cols; - } - - /// Matrix element access. - PBQPNum* operator[](unsigned R) { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - assert(R < Rows && "Row out of bounds."); - return Data.get() + (R * Cols); - } - - /// Matrix element access. - const PBQPNum* operator[](unsigned R) const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - assert(R < Rows && "Row out of bounds."); - return Data.get() + (R * Cols); - } - - /// Returns the given row as a vector. - Vector getRowAsVector(unsigned R) const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - Vector V(Cols); - for (unsigned C = 0; C < Cols; ++C) - V[C] = (*this)[R][C]; - return V; - } - - /// Returns the given column as a vector. - Vector getColAsVector(unsigned C) const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - Vector V(Rows); - for (unsigned R = 0; R < Rows; ++R) - V[R] = (*this)[R][C]; - return V; - } - - /// Matrix transpose. - Matrix transpose() const { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - Matrix M(Cols, Rows); - for (unsigned r = 0; r < Rows; ++r) - for (unsigned c = 0; c < Cols; ++c) - M[c][r] = (*this)[r][c]; - return M; - } - - /// Add the given matrix to this one. - Matrix& operator+=(const Matrix &M) { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - assert(Rows == M.Rows && Cols == M.Cols && - "Matrix dimensions mismatch."); - std::transform(Data.get(), Data.get() + (Rows * Cols), M.Data.get(), - Data.get(), std::plus()); - return *this; - } - - Matrix operator+(const Matrix &M) { - assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); - Matrix Tmp(*this); - Tmp += M; - return Tmp; - } - -private: - unsigned Rows, Cols; - std::unique_ptr Data; -}; - -/// Return a hash_code for the given matrix. -inline hash_code hash_value(const Matrix &M) { - unsigned *MBegin = reinterpret_cast(M.Data.get()); - unsigned *MEnd = - reinterpret_cast(M.Data.get() + (M.Rows * M.Cols)); - return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd)); -} - -/// Output a textual representation of the given matrix on the given -/// output stream. -template -OStream& operator<<(OStream &OS, const Matrix &M) { - assert((M.getRows() != 0) && "Zero-row matrix badness."); - for (unsigned i = 0; i < M.getRows(); ++i) - OS << M.getRowAsVector(i) << "\n"; - return OS; -} - -template -class MDVector : public Vector { -public: - MDVector(const Vector &v) : Vector(v), md(*this) {} - MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { } - - const Metadata& getMetadata() const { return md; } - -private: - Metadata md; -}; - -template -inline hash_code hash_value(const MDVector &V) { - return hash_value(static_cast(V)); -} - -template -class MDMatrix : public Matrix { -public: - MDMatrix(const Matrix &m) : Matrix(m), md(*this) {} - MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { } - - const Metadata& getMetadata() const { return md; } - -private: - Metadata md; -}; - -template -inline hash_code hash_value(const MDMatrix &M) { - return hash_value(static_cast(M)); -} - -} // end namespace PBQP -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/ReductionRules.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/ReductionRules.h deleted file mode 100644 index 51822d082b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/ReductionRules.h +++ /dev/null @@ -1,222 +0,0 @@ -//===- ReductionRules.h - Reduction Rules -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Reduction Rules. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H -#define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H - -#include "Graph.h" -#include "Math.h" -#include "Solution.h" -#include -#include - -namespace llvm { -namespace PBQP { - - /// Reduce a node of degree one. - /// - /// Propagate costs from the given node, which must be of degree one, to its - /// neighbor. Notify the problem domain. - template - void applyR1(GraphT &G, typename GraphT::NodeId NId) { - using NodeId = typename GraphT::NodeId; - using EdgeId = typename GraphT::EdgeId; - using Vector = typename GraphT::Vector; - using Matrix = typename GraphT::Matrix; - using RawVector = typename GraphT::RawVector; - - assert(G.getNodeDegree(NId) == 1 && - "R1 applied to node with degree != 1."); - - EdgeId EId = *G.adjEdgeIds(NId).begin(); - NodeId MId = G.getEdgeOtherNodeId(EId, NId); - - const Matrix &ECosts = G.getEdgeCosts(EId); - const Vector &XCosts = G.getNodeCosts(NId); - RawVector YCosts = G.getNodeCosts(MId); - - // Duplicate a little to avoid transposing matrices. - if (NId == G.getEdgeNode1Id(EId)) { - for (unsigned j = 0; j < YCosts.getLength(); ++j) { - PBQPNum Min = ECosts[0][j] + XCosts[0]; - for (unsigned i = 1; i < XCosts.getLength(); ++i) { - PBQPNum C = ECosts[i][j] + XCosts[i]; - if (C < Min) - Min = C; - } - YCosts[j] += Min; - } - } else { - for (unsigned i = 0; i < YCosts.getLength(); ++i) { - PBQPNum Min = ECosts[i][0] + XCosts[0]; - for (unsigned j = 1; j < XCosts.getLength(); ++j) { - PBQPNum C = ECosts[i][j] + XCosts[j]; - if (C < Min) - Min = C; - } - YCosts[i] += Min; - } - } - G.setNodeCosts(MId, YCosts); - G.disconnectEdge(EId, MId); - } - - template - void applyR2(GraphT &G, typename GraphT::NodeId NId) { - using NodeId = typename GraphT::NodeId; - using EdgeId = typename GraphT::EdgeId; - using Vector = typename GraphT::Vector; - using Matrix = typename GraphT::Matrix; - using RawMatrix = typename GraphT::RawMatrix; - - assert(G.getNodeDegree(NId) == 2 && - "R2 applied to node with degree != 2."); - - const Vector &XCosts = G.getNodeCosts(NId); - - typename GraphT::AdjEdgeItr AEItr = G.adjEdgeIds(NId).begin(); - EdgeId YXEId = *AEItr, - ZXEId = *(++AEItr); - - NodeId YNId = G.getEdgeOtherNodeId(YXEId, NId), - ZNId = G.getEdgeOtherNodeId(ZXEId, NId); - - bool FlipEdge1 = (G.getEdgeNode1Id(YXEId) == NId), - FlipEdge2 = (G.getEdgeNode1Id(ZXEId) == NId); - - const Matrix *YXECosts = FlipEdge1 ? - new Matrix(G.getEdgeCosts(YXEId).transpose()) : - &G.getEdgeCosts(YXEId); - - const Matrix *ZXECosts = FlipEdge2 ? - new Matrix(G.getEdgeCosts(ZXEId).transpose()) : - &G.getEdgeCosts(ZXEId); - - unsigned XLen = XCosts.getLength(), - YLen = YXECosts->getRows(), - ZLen = ZXECosts->getRows(); - - RawMatrix Delta(YLen, ZLen); - - for (unsigned i = 0; i < YLen; ++i) { - for (unsigned j = 0; j < ZLen; ++j) { - PBQPNum Min = (*YXECosts)[i][0] + (*ZXECosts)[j][0] + XCosts[0]; - for (unsigned k = 1; k < XLen; ++k) { - PBQPNum C = (*YXECosts)[i][k] + (*ZXECosts)[j][k] + XCosts[k]; - if (C < Min) { - Min = C; - } - } - Delta[i][j] = Min; - } - } - - if (FlipEdge1) - delete YXECosts; - - if (FlipEdge2) - delete ZXECosts; - - EdgeId YZEId = G.findEdge(YNId, ZNId); - - if (YZEId == G.invalidEdgeId()) { - YZEId = G.addEdge(YNId, ZNId, Delta); - } else { - const Matrix &YZECosts = G.getEdgeCosts(YZEId); - if (YNId == G.getEdgeNode1Id(YZEId)) { - G.updateEdgeCosts(YZEId, Delta + YZECosts); - } else { - G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts); - } - } - - G.disconnectEdge(YXEId, YNId); - G.disconnectEdge(ZXEId, ZNId); - - // TODO: Try to normalize newly added/modified edge. - } - -#ifndef NDEBUG - // Does this Cost vector have any register options ? - template - bool hasRegisterOptions(const VectorT &V) { - unsigned VL = V.getLength(); - - // An empty or spill only cost vector does not provide any register option. - if (VL <= 1) - return false; - - // If there are registers in the cost vector, but all of them have infinite - // costs, then ... there is no available register. - for (unsigned i = 1; i < VL; ++i) - if (V[i] != std::numeric_limits::infinity()) - return true; - - return false; - } -#endif - - // Find a solution to a fully reduced graph by backpropagation. - // - // Given a graph and a reduction order, pop each node from the reduction - // order and greedily compute a minimum solution based on the node costs, and - // the dependent costs due to previously solved nodes. - // - // Note - This does not return the graph to its original (pre-reduction) - // state: the existing solvers destructively alter the node and edge - // costs. Given that, the backpropagate function doesn't attempt to - // replace the edges either, but leaves the graph in its reduced - // state. - template - Solution backpropagate(GraphT& G, StackT stack) { - using NodeId = GraphBase::NodeId; - using Matrix = typename GraphT::Matrix; - using RawVector = typename GraphT::RawVector; - - Solution s; - - while (!stack.empty()) { - NodeId NId = stack.back(); - stack.pop_back(); - - RawVector v = G.getNodeCosts(NId); - -#ifndef NDEBUG - // Although a conservatively allocatable node can be allocated to a register, - // spilling it may provide a lower cost solution. Assert here that spilling - // is done by choice, not because there were no register available. - if (G.getNodeMetadata(NId).wasConservativelyAllocatable()) - assert(hasRegisterOptions(v) && "A conservatively allocatable node " - "must have available register options"); -#endif - - for (auto EId : G.adjEdgeIds(NId)) { - const Matrix& edgeCosts = G.getEdgeCosts(EId); - if (NId == G.getEdgeNode1Id(EId)) { - NodeId mId = G.getEdgeNode2Id(EId); - v += edgeCosts.getColAsVector(s.getSelection(mId)); - } else { - NodeId mId = G.getEdgeNode1Id(EId); - v += edgeCosts.getRowAsVector(s.getSelection(mId)); - } - } - - s.setSelection(NId, v.minIndex()); - } - - return s; - } - -} // end namespace PBQP -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQP_REDUCTIONRULES_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Solution.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Solution.h deleted file mode 100644 index d5b1474f0f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQP/Solution.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- Solution.h - PBQP Solution -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// PBQP Solution class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H -#define LLVM_CODEGEN_PBQP_SOLUTION_H - -#include "llvm/CodeGen/PBQP/Graph.h" -#include -#include - -namespace llvm { -namespace PBQP { - - /// Represents a solution to a PBQP problem. - /// - /// To get the selection for each node in the problem use the getSelection method. - class Solution { - private: - using SelectionsMap = std::map; - SelectionsMap selections; - - public: - /// Initialise an empty solution. - Solution() = default; - - /// Set the selection for a given node. - /// @param nodeId Node id. - /// @param selection Selection for nodeId. - void setSelection(GraphBase::NodeId nodeId, unsigned selection) { - selections[nodeId] = selection; - } - - /// Get a node's selection. - /// @param nodeId Node id. - /// @return The selection for nodeId; - unsigned getSelection(GraphBase::NodeId nodeId) const { - SelectionsMap::const_iterator sItr = selections.find(nodeId); - assert(sItr != selections.end() && "No selection for node."); - return sItr->second; - } - }; - -} // end namespace PBQP -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PBQPRAConstraint.h b/suite/synctools/tablegen/include/llvm/CodeGen/PBQPRAConstraint.h deleted file mode 100644 index 876ab97a66..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PBQPRAConstraint.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- llvm/CodeGen/PBQPRAConstraint.h --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the PBQPBuilder interface, for classes which build PBQP -// instances to represent register allocation problems, and the RegAllocPBQP -// interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQPRACONSTRAINT_H -#define LLVM_CODEGEN_PBQPRACONSTRAINT_H - -#include -#include -#include - -namespace llvm { - -namespace PBQP { -namespace RegAlloc { - -// Forward declare PBQP graph class. -class PBQPRAGraph; - -} // end namespace RegAlloc -} // end namespace PBQP - -using PBQPRAGraph = PBQP::RegAlloc::PBQPRAGraph; - -/// Abstract base for classes implementing PBQP register allocation -/// constraints (e.g. Spill-costs, interference, coalescing). -class PBQPRAConstraint { -public: - virtual ~PBQPRAConstraint() = 0; - virtual void apply(PBQPRAGraph &G) = 0; - -private: - virtual void anchor(); -}; - -/// PBQP register allocation constraint composer. -/// -/// Constraints added to this list will be applied, in the order that they are -/// added, to the PBQP graph. -class PBQPRAConstraintList : public PBQPRAConstraint { -public: - void apply(PBQPRAGraph &G) override { - for (auto &C : Constraints) - C->apply(G); - } - - void addConstraint(std::unique_ptr C) { - if (C) - Constraints.push_back(std::move(C)); - } - -private: - std::vector> Constraints; - - void anchor() override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_PBQPRACONSTRAINT_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ParallelCG.h b/suite/synctools/tablegen/include/llvm/CodeGen/ParallelCG.h deleted file mode 100644 index 70ce2ff474..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ParallelCG.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- llvm/CodeGen/ParallelCG.h - Parallel code generation ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header declares functions that can be used for parallel code generation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PARALLELCG_H -#define LLVM_CODEGEN_PARALLELCG_H - -#include "llvm/Support/CodeGen.h" -#include -#include - -namespace llvm { - -template class ArrayRef; -class Module; -class TargetMachine; -class raw_pwrite_stream; - -/// Split M into OSs.size() partitions, and generate code for each. Takes a -/// factory function for the TargetMachine TMFactory. Writes OSs.size() output -/// files to the output streams in OSs. The resulting output files if linked -/// together are intended to be equivalent to the single output file that would -/// have been code generated from M. -/// -/// Writes bitcode for individual partitions into output streams in BCOSs, if -/// BCOSs is not empty. -void splitCodeGen( - Module &M, ArrayRef OSs, - ArrayRef BCOSs, - const std::function()> &TMFactory, - CodeGenFileType FileType = CGFT_ObjectFile, bool PreserveLocals = false); - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/Passes.h b/suite/synctools/tablegen/include/llvm/CodeGen/Passes.h deleted file mode 100644 index 616ab10341..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/Passes.h +++ /dev/null @@ -1,559 +0,0 @@ -//===-- Passes.h - Target independent code generation passes ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines interfaces to access the target independent code generation -// passes provided by the LLVM backend. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PASSES_H -#define LLVM_CODEGEN_PASSES_H - -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/Discriminator.h" -#include "llvm/CodeGen/RegAllocCommon.h" - -#include -#include - -namespace llvm { - -class FunctionPass; -class MachineFunction; -class MachineFunctionPass; -class MemoryBuffer; -class ModulePass; -class Pass; -class TargetMachine; -class raw_ostream; - -} // End llvm namespace - -// List of target independent CodeGen pass IDs. -namespace llvm { - - /// AtomicExpandPass - At IR level this pass replace atomic instructions with - /// __atomic_* library calls, or target specific instruction which implement the - /// same semantics in a way which better fits the target backend. - FunctionPass *createAtomicExpandPass(); - - /// createUnreachableBlockEliminationPass - The LLVM code generator does not - /// work well with unreachable basic blocks (what live ranges make sense for a - /// block that cannot be reached?). As such, a code generator should either - /// not instruction select unreachable blocks, or run this pass as its - /// last LLVM modifying pass to clean up blocks that are not reachable from - /// the entry block. - FunctionPass *createUnreachableBlockEliminationPass(); - - /// createBasicBlockSections Pass - This pass assigns sections to machine - /// basic blocks and is enabled with -fbasic-block-sections. Buf is a memory - /// buffer that contains the list of functions and basic block ids to - /// selectively enable basic block sections. - MachineFunctionPass *createBasicBlockSectionsPass(const MemoryBuffer *Buf); - - /// createMachineFunctionSplitterPass - This pass splits machine functions - /// using profile information. - MachineFunctionPass *createMachineFunctionSplitterPass(); - - /// MachineFunctionPrinter pass - This pass prints out the machine function to - /// the given stream as a debugging tool. - MachineFunctionPass * - createMachineFunctionPrinterPass(raw_ostream &OS, - const std::string &Banner =""); - - /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream - /// using the MIR serialization format. - MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); - - /// This pass resets a MachineFunction when it has the FailedISel property - /// as if it was just created. - /// If EmitFallbackDiag is true, the pass will emit a - /// DiagnosticInfoISelFallback for every MachineFunction it resets. - /// If AbortOnFailedISel is true, abort compilation instead of resetting. - MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag, - bool AbortOnFailedISel); - - /// createCodeGenPreparePass - Transform the code to expose more pattern - /// matching during instruction selection. - FunctionPass *createCodeGenPreparePass(); - - /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg - /// load-linked/store-conditional loops. - extern char &AtomicExpandID; - - /// MachineLoopInfo - This pass is a loop analysis pass. - extern char &MachineLoopInfoID; - - /// MachineDominators - This pass is a machine dominators analysis pass. - extern char &MachineDominatorsID; - - /// MachineDominanaceFrontier - This pass is a machine dominators analysis. - extern char &MachineDominanceFrontierID; - - /// MachineRegionInfo - This pass computes SESE regions for machine functions. - extern char &MachineRegionInfoPassID; - - /// EdgeBundles analysis - Bundle machine CFG edges. - extern char &EdgeBundlesID; - - /// LiveVariables pass - This pass computes the set of blocks in which each - /// variable is life and sets machine operand kill flags. - extern char &LiveVariablesID; - - /// PHIElimination - This pass eliminates machine instruction PHI nodes - /// by inserting copy instructions. This destroys SSA information, but is the - /// desired input for some register allocators. This pass is "required" by - /// these register allocator like this: AU.addRequiredID(PHIEliminationID); - extern char &PHIEliminationID; - - /// LiveIntervals - This analysis keeps track of the live ranges of virtual - /// and physical registers. - extern char &LiveIntervalsID; - - /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. - extern char &LiveStacksID; - - /// TwoAddressInstruction - This pass reduces two-address instructions to - /// use two operands. This destroys SSA information but it is desired by - /// register allocators. - extern char &TwoAddressInstructionPassID; - - /// ProcessImpicitDefs pass - This pass removes IMPLICIT_DEFs. - extern char &ProcessImplicitDefsID; - - /// RegisterCoalescer - This pass merges live ranges to eliminate copies. - extern char &RegisterCoalescerID; - - /// MachineScheduler - This pass schedules machine instructions. - extern char &MachineSchedulerID; - - /// PostMachineScheduler - This pass schedules machine instructions postRA. - extern char &PostMachineSchedulerID; - - /// SpillPlacement analysis. Suggest optimal placement of spill code between - /// basic blocks. - extern char &SpillPlacementID; - - /// ShrinkWrap pass. Look for the best place to insert save and restore - // instruction and update the MachineFunctionInfo with that information. - extern char &ShrinkWrapID; - - /// LiveRangeShrink pass. Move instruction close to its definition to shrink - /// the definition's live range. - extern char &LiveRangeShrinkID; - - /// Greedy register allocator. - extern char &RAGreedyID; - - /// Basic register allocator. - extern char &RABasicID; - - /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as - /// assigned in VirtRegMap. - extern char &VirtRegRewriterID; - FunctionPass *createVirtRegRewriter(bool ClearVirtRegs = true); - - /// UnreachableMachineBlockElimination - This pass removes unreachable - /// machine basic blocks. - extern char &UnreachableMachineBlockElimID; - - /// DeadMachineInstructionElim - This pass removes dead machine instructions. - extern char &DeadMachineInstructionElimID; - - /// This pass adds dead/undef flags after analyzing subregister lanes. - extern char &DetectDeadLanesID; - - /// This pass perform post-ra machine sink for COPY instructions. - extern char &PostRAMachineSinkingID; - - /// This pass adds flow sensitive discriminators. - extern char &MIRAddFSDiscriminatorsID; - - /// This pass reads flow sensitive profile. - extern char &MIRProfileLoaderPassID; - - /// FastRegisterAllocation Pass - This pass register allocates as fast as - /// possible. It is best suited for debug code where live ranges are short. - /// - FunctionPass *createFastRegisterAllocator(); - FunctionPass *createFastRegisterAllocator(RegClassFilterFunc F, - bool ClearVirtRegs); - - /// BasicRegisterAllocation Pass - This pass implements a degenerate global - /// register allocator using the basic regalloc framework. - /// - FunctionPass *createBasicRegisterAllocator(); - FunctionPass *createBasicRegisterAllocator(RegClassFilterFunc F); - - /// Greedy register allocation pass - This pass implements a global register - /// allocator for optimized builds. - /// - FunctionPass *createGreedyRegisterAllocator(); - FunctionPass *createGreedyRegisterAllocator(RegClassFilterFunc F); - - /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean - /// Quadratic Prograaming (PBQP) based register allocator. - /// - FunctionPass *createDefaultPBQPRegisterAllocator(); - - /// PrologEpilogCodeInserter - This pass inserts prolog and epilog code, - /// and eliminates abstract frame references. - extern char &PrologEpilogCodeInserterID; - MachineFunctionPass *createPrologEpilogInserterPass(); - - /// ExpandPostRAPseudos - This pass expands pseudo instructions after - /// register allocation. - extern char &ExpandPostRAPseudosID; - - /// PostRAHazardRecognizer - This pass runs the post-ra hazard - /// recognizer. - extern char &PostRAHazardRecognizerID; - - /// PostRAScheduler - This pass performs post register allocation - /// scheduling. - extern char &PostRASchedulerID; - - /// BranchFolding - This pass performs machine code CFG based - /// optimizations to delete branches to branches, eliminate branches to - /// successor blocks (creating fall throughs), and eliminating branches over - /// branches. - extern char &BranchFolderPassID; - - /// BranchRelaxation - This pass replaces branches that need to jump further - /// than is supported by a branch instruction. - extern char &BranchRelaxationPassID; - - /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. - extern char &MachineFunctionPrinterPassID; - - /// MIRPrintingPass - this pass prints out the LLVM IR using the MIR - /// serialization format. - extern char &MIRPrintingPassID; - - /// TailDuplicate - Duplicate blocks with unconditional branches - /// into tails of their predecessors. - extern char &TailDuplicateID; - - /// Duplicate blocks with unconditional branches into tails of their - /// predecessors. Variant that works before register allocation. - extern char &EarlyTailDuplicateID; - - /// MachineTraceMetrics - This pass computes critical path and CPU resource - /// usage in an ensemble of traces. - extern char &MachineTraceMetricsID; - - /// EarlyIfConverter - This pass performs if-conversion on SSA form by - /// inserting cmov instructions. - extern char &EarlyIfConverterID; - - /// EarlyIfPredicator - This pass performs if-conversion on SSA form by - /// predicating if/else block and insert select at the join point. - extern char &EarlyIfPredicatorID; - - /// This pass performs instruction combining using trace metrics to estimate - /// critical-path and resource depth. - extern char &MachineCombinerID; - - /// StackSlotColoring - This pass performs stack coloring and merging. - /// It merges disjoint allocas to reduce the stack size. - extern char &StackColoringID; - - /// IfConverter - This pass performs machine code if conversion. - extern char &IfConverterID; - - FunctionPass *createIfConverter( - std::function Ftor); - - /// MachineBlockPlacement - This pass places basic blocks based on branch - /// probabilities. - extern char &MachineBlockPlacementID; - - /// MachineBlockPlacementStats - This pass collects statistics about the - /// basic block placement using branch probabilities and block frequency - /// information. - extern char &MachineBlockPlacementStatsID; - - /// GCLowering Pass - Used by gc.root to perform its default lowering - /// operations. - FunctionPass *createGCLoweringPass(); - - /// GCLowering Pass - Used by gc.root to perform its default lowering - /// operations. - extern char &GCLoweringID; - - /// ShadowStackGCLowering - Implements the custom lowering mechanism - /// used by the shadow stack GC. Only runs on functions which opt in to - /// the shadow stack collector. - FunctionPass *createShadowStackGCLoweringPass(); - - /// ShadowStackGCLowering - Implements the custom lowering mechanism - /// used by the shadow stack GC. - extern char &ShadowStackGCLoweringID; - - /// GCMachineCodeAnalysis - Target-independent pass to mark safe points - /// in machine code. Must be added very late during code generation, just - /// prior to output, and importantly after all CFG transformations (such as - /// branch folding). - extern char &GCMachineCodeAnalysisID; - - /// Creates a pass to print GC metadata. - /// - FunctionPass *createGCInfoPrinter(raw_ostream &OS); - - /// MachineCSE - This pass performs global CSE on machine instructions. - extern char &MachineCSEID; - - /// MIRCanonicalizer - This pass canonicalizes MIR by renaming vregs - /// according to the semantics of the instruction as well as hoists - /// code. - extern char &MIRCanonicalizerID; - - /// ImplicitNullChecks - This pass folds null pointer checks into nearby - /// memory operations. - extern char &ImplicitNullChecksID; - - /// This pass performs loop invariant code motion on machine instructions. - extern char &MachineLICMID; - - /// This pass performs loop invariant code motion on machine instructions. - /// This variant works before register allocation. \see MachineLICMID. - extern char &EarlyMachineLICMID; - - /// MachineSinking - This pass performs sinking on machine instructions. - extern char &MachineSinkingID; - - /// MachineCopyPropagation - This pass performs copy propagation on - /// machine instructions. - extern char &MachineCopyPropagationID; - - /// PeepholeOptimizer - This pass performs peephole optimizations - - /// like extension and comparison eliminations. - extern char &PeepholeOptimizerID; - - /// OptimizePHIs - This pass optimizes machine instruction PHIs - /// to take advantage of opportunities created during DAG legalization. - extern char &OptimizePHIsID; - - /// StackSlotColoring - This pass performs stack slot coloring. - extern char &StackSlotColoringID; - - /// This pass lays out funclets contiguously. - extern char &FuncletLayoutID; - - /// This pass inserts the XRay instrumentation sleds if they are supported by - /// the target platform. - extern char &XRayInstrumentationID; - - /// This pass inserts FEntry calls - extern char &FEntryInserterID; - - /// This pass implements the "patchable-function" attribute. - extern char &PatchableFunctionID; - - /// createStackProtectorPass - This pass adds stack protectors to functions. - /// - FunctionPass *createStackProtectorPass(); - - /// createMachineVerifierPass - This pass verifies cenerated machine code - /// instructions for correctness. - /// - FunctionPass *createMachineVerifierPass(const std::string& Banner); - - /// createDwarfEHPass - This pass mulches exception handling code into a form - /// adapted to code generation. Required if using dwarf exception handling. - FunctionPass *createDwarfEHPass(CodeGenOpt::Level OptLevel); - - /// createWinEHPass - Prepares personality functions used by MSVC on Windows, - /// in addition to the Itanium LSDA based personalities. - FunctionPass *createWinEHPass(bool DemoteCatchSwitchPHIOnly = false); - - /// createSjLjEHPreparePass - This pass adapts exception handling code to use - /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. - /// - FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); - - /// createWasmEHPass - This pass adapts exception handling code to use - /// WebAssembly's exception handling scheme. - FunctionPass *createWasmEHPass(); - - /// LocalStackSlotAllocation - This pass assigns local frame indices to stack - /// slots relative to one another and allocates base registers to access them - /// when it is estimated by the target to be out of range of normal frame - /// pointer or stack pointer index addressing. - extern char &LocalStackSlotAllocationID; - - /// This pass expands pseudo-instructions, reserves registers and adjusts - /// machine frame information. - extern char &FinalizeISelID; - - /// UnpackMachineBundles - This pass unpack machine instruction bundles. - extern char &UnpackMachineBundlesID; - - FunctionPass * - createUnpackMachineBundles(std::function Ftor); - - /// FinalizeMachineBundles - This pass finalize machine instruction - /// bundles (created earlier, e.g. during pre-RA scheduling). - extern char &FinalizeMachineBundlesID; - - /// StackMapLiveness - This pass analyses the register live-out set of - /// stackmap/patchpoint intrinsics and attaches the calculated information to - /// the intrinsic for later emission to the StackMap. - extern char &StackMapLivenessID; - - /// RemoveRedundantDebugValues pass. - extern char &RemoveRedundantDebugValuesID; - - /// LiveDebugValues pass - extern char &LiveDebugValuesID; - - /// createJumpInstrTables - This pass creates jump-instruction tables. - ModulePass *createJumpInstrTablesPass(); - - /// InterleavedAccess Pass - This pass identifies and matches interleaved - /// memory accesses to target specific intrinsics. - /// - FunctionPass *createInterleavedAccessPass(); - - /// InterleavedLoadCombines Pass - This pass identifies interleaved loads and - /// combines them into wide loads detectable by InterleavedAccessPass - /// - FunctionPass *createInterleavedLoadCombinePass(); - - /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all - /// TLS variables for the emulated TLS model. - /// - ModulePass *createLowerEmuTLSPass(); - - /// This pass lowers the \@llvm.load.relative and \@llvm.objc.* intrinsics to - /// instructions. This is unsafe to do earlier because a pass may combine the - /// constant initializer into the load, which may result in an overflowing - /// evaluation. - ModulePass *createPreISelIntrinsicLoweringPass(); - - /// GlobalMerge - This pass merges internal (by default) globals into structs - /// to enable reuse of a base pointer by indexed addressing modes. - /// It can also be configured to focus on size optimizations only. - /// - Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, - bool OnlyOptimizeForSize = false, - bool MergeExternalByDefault = false); - - /// This pass splits the stack into a safe stack and an unsafe stack to - /// protect against stack-based overflow vulnerabilities. - FunctionPass *createSafeStackPass(); - - /// This pass detects subregister lanes in a virtual register that are used - /// independently of other lanes and splits them into separate virtual - /// registers. - extern char &RenameIndependentSubregsID; - - /// This pass is executed POST-RA to collect which physical registers are - /// preserved by given machine function. - FunctionPass *createRegUsageInfoCollector(); - - /// Return a MachineFunction pass that identifies call sites - /// and propagates register usage information of callee to caller - /// if available with PysicalRegisterUsageInfo pass. - FunctionPass *createRegUsageInfoPropPass(); - - /// This pass performs software pipelining on machine instructions. - extern char &MachinePipelinerID; - - /// This pass frees the memory occupied by the MachineFunction. - FunctionPass *createFreeMachineFunctionPass(); - - /// This pass performs outlining on machine instructions directly before - /// printing assembly. - ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions = true); - - /// This pass expands the experimental reduction intrinsics into sequences of - /// shuffles. - FunctionPass *createExpandReductionsPass(); - - // This pass replaces intrinsics operating on vector operands with calls to - // the corresponding function in a vector library (e.g., SVML, libmvec). - FunctionPass *createReplaceWithVeclibLegacyPass(); - - /// This pass expands the vector predication intrinsics into unpredicated - /// instructions with selects or just the explicit vector length into the - /// predicate mask. - FunctionPass *createExpandVectorPredicationPass(); - - // This pass expands memcmp() to load/stores. - FunctionPass *createExpandMemCmpPass(); - - /// Creates Break False Dependencies pass. \see BreakFalseDeps.cpp - FunctionPass *createBreakFalseDeps(); - - // This pass expands indirectbr instructions. - FunctionPass *createIndirectBrExpandPass(); - - /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp - FunctionPass *createCFIInstrInserter(); - - /// Creates CFGuard longjmp target identification pass. - /// \see CFGuardLongjmp.cpp - FunctionPass *createCFGuardLongjmpPass(); - - /// Creates EHContGuard catchret target identification pass. - /// \see EHContGuardCatchret.cpp - FunctionPass *createEHContGuardCatchretPass(); - - /// Create Hardware Loop pass. \see HardwareLoops.cpp - FunctionPass *createHardwareLoopsPass(); - - /// This pass inserts pseudo probe annotation for callsite profiling. - FunctionPass *createPseudoProbeInserter(); - - /// Create IR Type Promotion pass. \see TypePromotion.cpp - FunctionPass *createTypePromotionPass(); - - /// Add Flow Sensitive Discriminators. PassNum specifies the - /// sequence number of this pass (starting from 1). - FunctionPass * - createMIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass P); - - /// Read Flow Sensitive Profile. - FunctionPass *createMIRProfileLoaderPass(std::string File, - std::string RemappingFile, - sampleprof::FSDiscriminatorPass P); - - /// Creates MIR Debugify pass. \see MachineDebugify.cpp - ModulePass *createDebugifyMachineModulePass(); - - /// Creates MIR Strip Debug pass. \see MachineStripDebug.cpp - /// If OnlyDebugified is true then it will only strip debug info if it was - /// added by a Debugify pass. The module will be left unchanged if the debug - /// info was generated by another source such as clang. - ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified); - - /// Creates MIR Check Debug pass. \see MachineCheckDebugify.cpp - ModulePass *createCheckDebugMachineModulePass(); - - /// The pass fixups statepoint machine instruction to replace usage of - /// caller saved registers with stack slots. - extern char &FixupStatepointCallerSavedID; - - /// The pass transforms load/store <256 x i32> to AMX load/store intrinsics - /// or split the data to two <128 x i32>. - FunctionPass *createX86LowerAMXTypePass(); - - /// The pass insert tile config intrinsics for AMX fast register allocation. - FunctionPass *createX86PreAMXConfigPass(); - - /// The pass transforms amx intrinsics to scalar operation if the function has - /// optnone attribute or it is O0. - FunctionPass *createX86LowerAMXIntrinsicsPass(); - - /// When learning an eviction policy, extract score(reward) information, - /// otherwise this does nothing - FunctionPass *createRegAllocScoringPass(); -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/PreISelIntrinsicLowering.h deleted file mode 100644 index 73d7d779e5..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PreISelIntrinsicLowering.h +++ /dev/null @@ -1,29 +0,0 @@ -//===- PreISelIntrinsicLowering.h - Pre-ISel intrinsic lowering pass ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass implements IR lowering for the llvm.load.relative and llvm.objc.* -// intrinsics. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_PREISELINTRINSICLOWERING_H -#define LLVM_CODEGEN_PREISELINTRINSICLOWERING_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class Module; - -struct PreISelIntrinsicLoweringPass - : PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_PREISELINTRINSICLOWERING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/PseudoSourceValue.h b/suite/synctools/tablegen/include/llvm/CodeGen/PseudoSourceValue.h deleted file mode 100644 index f1487017f2..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/PseudoSourceValue.h +++ /dev/null @@ -1,197 +0,0 @@ -//===-- llvm/CodeGen/PseudoSourceValue.h ------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the PseudoSourceValue class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PSEUDOSOURCEVALUE_H -#define LLVM_CODEGEN_PSEUDOSOURCEVALUE_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/IR/ValueMap.h" -#include - -namespace llvm { - -class GlobalValue; -class MachineFrameInfo; -class MachineMemOperand; -class MIRFormatter; -class PseudoSourceValue; -class raw_ostream; -class TargetInstrInfo; - -raw_ostream &operator<<(raw_ostream &OS, const PseudoSourceValue* PSV); - -/// Special value supplied for machine level alias analysis. It indicates that -/// a memory access references the functions stack frame (e.g., a spill slot), -/// below the stack frame (e.g., argument space), or constant pool. -class PseudoSourceValue { -public: - enum PSVKind : unsigned { - Stack, - GOT, - JumpTable, - ConstantPool, - FixedStack, - GlobalValueCallEntry, - ExternalSymbolCallEntry, - TargetCustom - }; - -private: - unsigned Kind; - unsigned AddressSpace; - friend raw_ostream &llvm::operator<<(raw_ostream &OS, - const PseudoSourceValue* PSV); - - friend class MachineMemOperand; // For printCustom(). - friend class MIRFormatter; // For printCustom(). - - /// Implement printing for PseudoSourceValue. This is called from - /// Value::print or Value's operator<<. - virtual void printCustom(raw_ostream &O) const; - -public: - explicit PseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII); - - virtual ~PseudoSourceValue(); - - unsigned kind() const { return Kind; } - - bool isStack() const { return Kind == Stack; } - bool isGOT() const { return Kind == GOT; } - bool isConstantPool() const { return Kind == ConstantPool; } - bool isJumpTable() const { return Kind == JumpTable; } - - unsigned getAddressSpace() const { return AddressSpace; } - - unsigned getTargetCustom() const { - return (Kind >= TargetCustom) ? ((Kind+1) - TargetCustom) : 0; - } - - /// Test whether the memory pointed to by this PseudoSourceValue has a - /// constant value. - virtual bool isConstant(const MachineFrameInfo *) const; - - /// Test whether the memory pointed to by this PseudoSourceValue may also be - /// pointed to by an LLVM IR Value. - virtual bool isAliased(const MachineFrameInfo *) const; - - /// Return true if the memory pointed to by this PseudoSourceValue can ever - /// alias an LLVM IR Value. - virtual bool mayAlias(const MachineFrameInfo *) const; -}; - -/// A specialized PseudoSourceValue for holding FixedStack values, which must -/// include a frame index. -class FixedStackPseudoSourceValue : public PseudoSourceValue { - const int FI; - -public: - explicit FixedStackPseudoSourceValue(int FI, const TargetInstrInfo &TII) - : PseudoSourceValue(FixedStack, TII), FI(FI) {} - - static bool classof(const PseudoSourceValue *V) { - return V->kind() == FixedStack; - } - - bool isConstant(const MachineFrameInfo *MFI) const override; - - bool isAliased(const MachineFrameInfo *MFI) const override; - - bool mayAlias(const MachineFrameInfo *) const override; - - void printCustom(raw_ostream &OS) const override; - - int getFrameIndex() const { return FI; } -}; - -class CallEntryPseudoSourceValue : public PseudoSourceValue { -protected: - CallEntryPseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII); - -public: - bool isConstant(const MachineFrameInfo *) const override; - bool isAliased(const MachineFrameInfo *) const override; - bool mayAlias(const MachineFrameInfo *) const override; -}; - -/// A specialized pseudo source value for holding GlobalValue values. -class GlobalValuePseudoSourceValue : public CallEntryPseudoSourceValue { - const GlobalValue *GV; - -public: - GlobalValuePseudoSourceValue(const GlobalValue *GV, - const TargetInstrInfo &TII); - - static bool classof(const PseudoSourceValue *V) { - return V->kind() == GlobalValueCallEntry; - } - - const GlobalValue *getValue() const { return GV; } -}; - -/// A specialized pseudo source value for holding external symbol values. -class ExternalSymbolPseudoSourceValue : public CallEntryPseudoSourceValue { - const char *ES; - -public: - ExternalSymbolPseudoSourceValue(const char *ES, const TargetInstrInfo &TII); - - static bool classof(const PseudoSourceValue *V) { - return V->kind() == ExternalSymbolCallEntry; - } - - const char *getSymbol() const { return ES; } -}; - -/// Manages creation of pseudo source values. -class PseudoSourceValueManager { - const TargetInstrInfo &TII; - const PseudoSourceValue StackPSV, GOTPSV, JumpTablePSV, ConstantPoolPSV; - std::map> FSValues; - StringMap> - ExternalCallEntries; - ValueMap> - GlobalCallEntries; - -public: - PseudoSourceValueManager(const TargetInstrInfo &TII); - - /// Return a pseudo source value referencing the area below the stack frame of - /// a function, e.g., the argument space. - const PseudoSourceValue *getStack(); - - /// Return a pseudo source value referencing the global offset table - /// (or something the like). - const PseudoSourceValue *getGOT(); - - /// Return a pseudo source value referencing the constant pool. Since constant - /// pools are constant, this doesn't need to identify a specific constant - /// pool entry. - const PseudoSourceValue *getConstantPool(); - - /// Return a pseudo source value referencing a jump table. Since jump tables - /// are constant, this doesn't need to identify a specific jump table. - const PseudoSourceValue *getJumpTable(); - - /// Return a pseudo source value referencing a fixed stack frame entry, - /// e.g., a spill slot. - const PseudoSourceValue *getFixedStack(int FI); - - const PseudoSourceValue *getGlobalValueCallEntry(const GlobalValue *GV); - - const PseudoSourceValue *getExternalSymbolCallEntry(const char *ES); -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RDFGraph.h b/suite/synctools/tablegen/include/llvm/CodeGen/RDFGraph.h deleted file mode 100644 index e0205d7c92..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RDFGraph.h +++ /dev/null @@ -1,964 +0,0 @@ -//===- RDFGraph.h -----------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Target-independent, SSA-based data flow graph for register data flow (RDF) -// for a non-SSA program representation (e.g. post-RA machine code). -// -// -// *** Introduction -// -// The RDF graph is a collection of nodes, each of which denotes some element -// of the program. There are two main types of such elements: code and refe- -// rences. Conceptually, "code" is something that represents the structure -// of the program, e.g. basic block or a statement, while "reference" is an -// instance of accessing a register, e.g. a definition or a use. Nodes are -// connected with each other based on the structure of the program (such as -// blocks, instructions, etc.), and based on the data flow (e.g. reaching -// definitions, reached uses, etc.). The single-reaching-definition principle -// of SSA is generally observed, although, due to the non-SSA representation -// of the program, there are some differences between the graph and a "pure" -// SSA representation. -// -// -// *** Implementation remarks -// -// Since the graph can contain a large number of nodes, memory consumption -// was one of the major design considerations. As a result, there is a single -// base class NodeBase which defines all members used by all possible derived -// classes. The members are arranged in a union, and a derived class cannot -// add any data members of its own. Each derived class only defines the -// functional interface, i.e. member functions. NodeBase must be a POD, -// which implies that all of its members must also be PODs. -// Since nodes need to be connected with other nodes, pointers have been -// replaced with 32-bit identifiers: each node has an id of type NodeId. -// There are mapping functions in the graph that translate between actual -// memory addresses and the corresponding identifiers. -// A node id of 0 is equivalent to nullptr. -// -// -// *** Structure of the graph -// -// A code node is always a collection of other nodes. For example, a code -// node corresponding to a basic block will contain code nodes corresponding -// to instructions. In turn, a code node corresponding to an instruction will -// contain a list of reference nodes that correspond to the definitions and -// uses of registers in that instruction. The members are arranged into a -// circular list, which is yet another consequence of the effort to save -// memory: for each member node it should be possible to obtain its owner, -// and it should be possible to access all other members. There are other -// ways to accomplish that, but the circular list seemed the most natural. -// -// +- CodeNode -+ -// | | <---------------------------------------------------+ -// +-+--------+-+ | -// |FirstM |LastM | -// | +-------------------------------------+ | -// | | | -// V V | -// +----------+ Next +----------+ Next Next +----------+ Next | -// | |----->| |-----> ... ----->| |----->-+ -// +- Member -+ +- Member -+ +- Member -+ -// -// The order of members is such that related reference nodes (see below) -// should be contiguous on the member list. -// -// A reference node is a node that encapsulates an access to a register, -// in other words, data flowing into or out of a register. There are two -// major kinds of reference nodes: defs and uses. A def node will contain -// the id of the first reached use, and the id of the first reached def. -// Each def and use will contain the id of the reaching def, and also the -// id of the next reached def (for def nodes) or use (for use nodes). -// The "next node sharing the same reaching def" is denoted as "sibling". -// In summary: -// - Def node contains: reaching def, sibling, first reached def, and first -// reached use. -// - Use node contains: reaching def and sibling. -// -// +-- DefNode --+ -// | R2 = ... | <---+--------------------+ -// ++---------+--+ | | -// |Reached |Reached | | -// |Def |Use | | -// | | |Reaching |Reaching -// | V |Def |Def -// | +-- UseNode --+ Sib +-- UseNode --+ Sib Sib -// | | ... = R2 |----->| ... = R2 |----> ... ----> 0 -// | +-------------+ +-------------+ -// V -// +-- DefNode --+ Sib -// | R2 = ... |----> ... -// ++---------+--+ -// | | -// | | -// ... ... -// -// To get a full picture, the circular lists connecting blocks within a -// function, instructions within a block, etc. should be superimposed with -// the def-def, def-use links shown above. -// To illustrate this, consider a small example in a pseudo-assembly: -// foo: -// add r2, r0, r1 ; r2 = r0+r1 -// addi r0, r2, 1 ; r0 = r2+1 -// ret r0 ; return value in r0 -// -// The graph (in a format used by the debugging functions) would look like: -// -// DFG dump:[ -// f1: Function foo -// b2: === %bb.0 === preds(0), succs(0): -// p3: phi [d4(,d12,u9):] -// p5: phi [d6(,,u10):] -// s7: add [d8(,,u13):, u9(d4):, u10(d6):] -// s11: addi [d12(d4,,u15):, u13(d8):] -// s14: ret [u15(d12):] -// ] -// -// The f1, b2, p3, etc. are node ids. The letter is prepended to indicate the -// kind of the node (i.e. f - function, b - basic block, p - phi, s - state- -// ment, d - def, u - use). -// The format of a def node is: -// dN(rd,d,u):sib, -// where -// N - numeric node id, -// R - register being defined -// rd - reaching def, -// d - reached def, -// u - reached use, -// sib - sibling. -// The format of a use node is: -// uN[!](rd):sib, -// where -// N - numeric node id, -// R - register being used, -// rd - reaching def, -// sib - sibling. -// Possible annotations (usually preceding the node id): -// + - preserving def, -// ~ - clobbering def, -// " - shadow ref (follows the node id), -// ! - fixed register (appears after register name). -// -// The circular lists are not explicit in the dump. -// -// -// *** Node attributes -// -// NodeBase has a member "Attrs", which is the primary way of determining -// the node's characteristics. The fields in this member decide whether -// the node is a code node or a reference node (i.e. node's "type"), then -// within each type, the "kind" determines what specifically this node -// represents. The remaining bits, "flags", contain additional information -// that is even more detailed than the "kind". -// CodeNode's kinds are: -// - Phi: Phi node, members are reference nodes. -// - Stmt: Statement, members are reference nodes. -// - Block: Basic block, members are instruction nodes (i.e. Phi or Stmt). -// - Func: The whole function. The members are basic block nodes. -// RefNode's kinds are: -// - Use. -// - Def. -// -// Meaning of flags: -// - Preserving: applies only to defs. A preserving def is one that can -// preserve some of the original bits among those that are included in -// the register associated with that def. For example, if R0 is a 32-bit -// register, but a def can only change the lower 16 bits, then it will -// be marked as preserving. -// - Shadow: a reference that has duplicates holding additional reaching -// defs (see more below). -// - Clobbering: applied only to defs, indicates that the value generated -// by this def is unspecified. A typical example would be volatile registers -// after function calls. -// - Fixed: the register in this def/use cannot be replaced with any other -// register. A typical case would be a parameter register to a call, or -// the register with the return value from a function. -// - Undef: the register in this reference the register is assumed to have -// no pre-existing value, even if it appears to be reached by some def. -// This is typically used to prevent keeping registers artificially live -// in cases when they are defined via predicated instructions. For example: -// r0 = add-if-true cond, r10, r11 (1) -// r0 = add-if-false cond, r12, r13, implicit r0 (2) -// ... = r0 (3) -// Before (1), r0 is not intended to be live, and the use of r0 in (3) is -// not meant to be reached by any def preceding (1). However, since the -// defs in (1) and (2) are both preserving, these properties alone would -// imply that the use in (3) may indeed be reached by some prior def. -// Adding Undef flag to the def in (1) prevents that. The Undef flag -// may be applied to both defs and uses. -// - Dead: applies only to defs. The value coming out of a "dead" def is -// assumed to be unused, even if the def appears to be reaching other defs -// or uses. The motivation for this flag comes from dead defs on function -// calls: there is no way to determine if such a def is dead without -// analyzing the target's ABI. Hence the graph should contain this info, -// as it is unavailable otherwise. On the other hand, a def without any -// uses on a typical instruction is not the intended target for this flag. -// -// *** Shadow references -// -// It may happen that a super-register can have two (or more) non-overlapping -// sub-registers. When both of these sub-registers are defined and followed -// by a use of the super-register, the use of the super-register will not -// have a unique reaching def: both defs of the sub-registers need to be -// accounted for. In such cases, a duplicate use of the super-register is -// added and it points to the extra reaching def. Both uses are marked with -// a flag "shadow". Example: -// Assume t0 is a super-register of r0 and r1, r0 and r1 do not overlap: -// set r0, 1 ; r0 = 1 -// set r1, 1 ; r1 = 1 -// addi t1, t0, 1 ; t1 = t0+1 -// -// The DFG: -// s1: set [d2(,,u9):] -// s3: set [d4(,,u10):] -// s5: addi [d6(,,):, u7"(d2):, u8"(d4):] -// -// The statement s5 has two use nodes for t0: u7" and u9". The quotation -// mark " indicates that the node is a shadow. -// - -#ifndef LLVM_CODEGEN_RDFGRAPH_H -#define LLVM_CODEGEN_RDFGRAPH_H - -#include "RDFRegisters.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/MathExtras.h" -#include -#include -#include -#include -#include -#include -#include -#include - -// RDF uses uint32_t to refer to registers. This is to ensure that the type -// size remains specific. In other places, registers are often stored using -// unsigned. -static_assert(sizeof(uint32_t) == sizeof(unsigned), "Those should be equal"); - -namespace llvm { - -class MachineBasicBlock; -class MachineDominanceFrontier; -class MachineDominatorTree; -class MachineFunction; -class MachineInstr; -class MachineOperand; -class raw_ostream; -class TargetInstrInfo; -class TargetRegisterInfo; - -namespace rdf { - - using NodeId = uint32_t; - - struct DataFlowGraph; - - struct NodeAttrs { - enum : uint16_t { - None = 0x0000, // Nothing - - // Types: 2 bits - TypeMask = 0x0003, - Code = 0x0001, // 01, Container - Ref = 0x0002, // 10, Reference - - // Kind: 3 bits - KindMask = 0x0007 << 2, - Def = 0x0001 << 2, // 001 - Use = 0x0002 << 2, // 010 - Phi = 0x0003 << 2, // 011 - Stmt = 0x0004 << 2, // 100 - Block = 0x0005 << 2, // 101 - Func = 0x0006 << 2, // 110 - - // Flags: 7 bits for now - FlagMask = 0x007F << 5, - Shadow = 0x0001 << 5, // 0000001, Has extra reaching defs. - Clobbering = 0x0002 << 5, // 0000010, Produces unspecified values. - PhiRef = 0x0004 << 5, // 0000100, Member of PhiNode. - Preserving = 0x0008 << 5, // 0001000, Def can keep original bits. - Fixed = 0x0010 << 5, // 0010000, Fixed register. - Undef = 0x0020 << 5, // 0100000, Has no pre-existing value. - Dead = 0x0040 << 5, // 1000000, Does not define a value. - }; - - static uint16_t type(uint16_t T) { return T & TypeMask; } - static uint16_t kind(uint16_t T) { return T & KindMask; } - static uint16_t flags(uint16_t T) { return T & FlagMask; } - - static uint16_t set_type(uint16_t A, uint16_t T) { - return (A & ~TypeMask) | T; - } - - static uint16_t set_kind(uint16_t A, uint16_t K) { - return (A & ~KindMask) | K; - } - - static uint16_t set_flags(uint16_t A, uint16_t F) { - return (A & ~FlagMask) | F; - } - - // Test if A contains B. - static bool contains(uint16_t A, uint16_t B) { - if (type(A) != Code) - return false; - uint16_t KB = kind(B); - switch (kind(A)) { - case Func: - return KB == Block; - case Block: - return KB == Phi || KB == Stmt; - case Phi: - case Stmt: - return type(B) == Ref; - } - return false; - } - }; - - struct BuildOptions { - enum : unsigned { - None = 0x00, - KeepDeadPhis = 0x01, // Do not remove dead phis during build. - }; - }; - - template struct NodeAddr { - NodeAddr() = default; - NodeAddr(T A, NodeId I) : Addr(A), Id(I) {} - - // Type cast (casting constructor). The reason for having this class - // instead of std::pair. - template NodeAddr(const NodeAddr &NA) - : Addr(static_cast(NA.Addr)), Id(NA.Id) {} - - bool operator== (const NodeAddr &NA) const { - assert((Addr == NA.Addr) == (Id == NA.Id)); - return Addr == NA.Addr; - } - bool operator!= (const NodeAddr &NA) const { - return !operator==(NA); - } - - T Addr = nullptr; - NodeId Id = 0; - }; - - struct NodeBase; - - // Fast memory allocation and translation between node id and node address. - // This is really the same idea as the one underlying the "bump pointer - // allocator", the difference being in the translation. A node id is - // composed of two components: the index of the block in which it was - // allocated, and the index within the block. With the default settings, - // where the number of nodes per block is 4096, the node id (minus 1) is: - // - // bit position: 11 0 - // +----------------------------+--------------+ - // | Index of the block |Index in block| - // +----------------------------+--------------+ - // - // The actual node id is the above plus 1, to avoid creating a node id of 0. - // - // This method significantly improved the build time, compared to using maps - // (std::unordered_map or DenseMap) to translate between pointers and ids. - struct NodeAllocator { - // Amount of storage for a single node. - enum { NodeMemSize = 32 }; - - NodeAllocator(uint32_t NPB = 4096) - : NodesPerBlock(NPB), BitsPerIndex(Log2_32(NPB)), - IndexMask((1 << BitsPerIndex)-1) { - assert(isPowerOf2_32(NPB)); - } - - NodeBase *ptr(NodeId N) const { - uint32_t N1 = N-1; - uint32_t BlockN = N1 >> BitsPerIndex; - uint32_t Offset = (N1 & IndexMask) * NodeMemSize; - return reinterpret_cast(Blocks[BlockN]+Offset); - } - - NodeId id(const NodeBase *P) const; - NodeAddr New(); - void clear(); - - private: - void startNewBlock(); - bool needNewBlock(); - - uint32_t makeId(uint32_t Block, uint32_t Index) const { - // Add 1 to the id, to avoid the id of 0, which is treated as "null". - return ((Block << BitsPerIndex) | Index) + 1; - } - - const uint32_t NodesPerBlock; - const uint32_t BitsPerIndex; - const uint32_t IndexMask; - char *ActiveEnd = nullptr; - std::vector Blocks; - using AllocatorTy = BumpPtrAllocatorImpl; - AllocatorTy MemPool; - }; - - using RegisterSet = std::set; - - struct TargetOperandInfo { - TargetOperandInfo(const TargetInstrInfo &tii) : TII(tii) {} - virtual ~TargetOperandInfo() = default; - - virtual bool isPreserving(const MachineInstr &In, unsigned OpNum) const; - virtual bool isClobbering(const MachineInstr &In, unsigned OpNum) const; - virtual bool isFixedReg(const MachineInstr &In, unsigned OpNum) const; - - const TargetInstrInfo &TII; - }; - - // Packed register reference. Only used for storage. - struct PackedRegisterRef { - RegisterId Reg; - uint32_t MaskId; - }; - - struct LaneMaskIndex : private IndexedSet { - LaneMaskIndex() = default; - - LaneBitmask getLaneMaskForIndex(uint32_t K) const { - return K == 0 ? LaneBitmask::getAll() : get(K); - } - - uint32_t getIndexForLaneMask(LaneBitmask LM) { - assert(LM.any()); - return LM.all() ? 0 : insert(LM); - } - - uint32_t getIndexForLaneMask(LaneBitmask LM) const { - assert(LM.any()); - return LM.all() ? 0 : find(LM); - } - }; - - struct NodeBase { - public: - // Make sure this is a POD. - NodeBase() = default; - - uint16_t getType() const { return NodeAttrs::type(Attrs); } - uint16_t getKind() const { return NodeAttrs::kind(Attrs); } - uint16_t getFlags() const { return NodeAttrs::flags(Attrs); } - NodeId getNext() const { return Next; } - - uint16_t getAttrs() const { return Attrs; } - void setAttrs(uint16_t A) { Attrs = A; } - void setFlags(uint16_t F) { setAttrs(NodeAttrs::set_flags(getAttrs(), F)); } - - // Insert node NA after "this" in the circular chain. - void append(NodeAddr NA); - - // Initialize all members to 0. - void init() { memset(this, 0, sizeof *this); } - - void setNext(NodeId N) { Next = N; } - - protected: - uint16_t Attrs; - uint16_t Reserved; - NodeId Next; // Id of the next node in the circular chain. - // Definitions of nested types. Using anonymous nested structs would make - // this class definition clearer, but unnamed structs are not a part of - // the standard. - struct Def_struct { - NodeId DD, DU; // Ids of the first reached def and use. - }; - struct PhiU_struct { - NodeId PredB; // Id of the predecessor block for a phi use. - }; - struct Code_struct { - void *CP; // Pointer to the actual code. - NodeId FirstM, LastM; // Id of the first member and last. - }; - struct Ref_struct { - NodeId RD, Sib; // Ids of the reaching def and the sibling. - union { - Def_struct Def; - PhiU_struct PhiU; - }; - union { - MachineOperand *Op; // Non-phi refs point to a machine operand. - PackedRegisterRef PR; // Phi refs store register info directly. - }; - }; - - // The actual payload. - union { - Ref_struct Ref; - Code_struct Code; - }; - }; - // The allocator allocates chunks of 32 bytes for each node. The fact that - // each node takes 32 bytes in memory is used for fast translation between - // the node id and the node address. - static_assert(sizeof(NodeBase) <= NodeAllocator::NodeMemSize, - "NodeBase must be at most NodeAllocator::NodeMemSize bytes"); - - using NodeList = SmallVector, 4>; - using NodeSet = std::set; - - struct RefNode : public NodeBase { - RefNode() = default; - - RegisterRef getRegRef(const DataFlowGraph &G) const; - - MachineOperand &getOp() { - assert(!(getFlags() & NodeAttrs::PhiRef)); - return *Ref.Op; - } - - void setRegRef(RegisterRef RR, DataFlowGraph &G); - void setRegRef(MachineOperand *Op, DataFlowGraph &G); - - NodeId getReachingDef() const { - return Ref.RD; - } - void setReachingDef(NodeId RD) { - Ref.RD = RD; - } - - NodeId getSibling() const { - return Ref.Sib; - } - void setSibling(NodeId Sib) { - Ref.Sib = Sib; - } - - bool isUse() const { - assert(getType() == NodeAttrs::Ref); - return getKind() == NodeAttrs::Use; - } - - bool isDef() const { - assert(getType() == NodeAttrs::Ref); - return getKind() == NodeAttrs::Def; - } - - template - NodeAddr getNextRef(RegisterRef RR, Predicate P, bool NextOnly, - const DataFlowGraph &G); - NodeAddr getOwner(const DataFlowGraph &G); - }; - - struct DefNode : public RefNode { - NodeId getReachedDef() const { - return Ref.Def.DD; - } - void setReachedDef(NodeId D) { - Ref.Def.DD = D; - } - NodeId getReachedUse() const { - return Ref.Def.DU; - } - void setReachedUse(NodeId U) { - Ref.Def.DU = U; - } - - void linkToDef(NodeId Self, NodeAddr DA); - }; - - struct UseNode : public RefNode { - void linkToDef(NodeId Self, NodeAddr DA); - }; - - struct PhiUseNode : public UseNode { - NodeId getPredecessor() const { - assert(getFlags() & NodeAttrs::PhiRef); - return Ref.PhiU.PredB; - } - void setPredecessor(NodeId B) { - assert(getFlags() & NodeAttrs::PhiRef); - Ref.PhiU.PredB = B; - } - }; - - struct CodeNode : public NodeBase { - template T getCode() const { - return static_cast(Code.CP); - } - void setCode(void *C) { - Code.CP = C; - } - - NodeAddr getFirstMember(const DataFlowGraph &G) const; - NodeAddr getLastMember(const DataFlowGraph &G) const; - void addMember(NodeAddr NA, const DataFlowGraph &G); - void addMemberAfter(NodeAddr MA, NodeAddr NA, - const DataFlowGraph &G); - void removeMember(NodeAddr NA, const DataFlowGraph &G); - - NodeList members(const DataFlowGraph &G) const; - template - NodeList members_if(Predicate P, const DataFlowGraph &G) const; - }; - - struct InstrNode : public CodeNode { - NodeAddr getOwner(const DataFlowGraph &G); - }; - - struct PhiNode : public InstrNode { - MachineInstr *getCode() const { - return nullptr; - } - }; - - struct StmtNode : public InstrNode { - MachineInstr *getCode() const { - return CodeNode::getCode(); - } - }; - - struct BlockNode : public CodeNode { - MachineBasicBlock *getCode() const { - return CodeNode::getCode(); - } - - void addPhi(NodeAddr PA, const DataFlowGraph &G); - }; - - struct FuncNode : public CodeNode { - MachineFunction *getCode() const { - return CodeNode::getCode(); - } - - NodeAddr findBlock(const MachineBasicBlock *BB, - const DataFlowGraph &G) const; - NodeAddr getEntryBlock(const DataFlowGraph &G); - }; - - struct DataFlowGraph { - DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, - const TargetRegisterInfo &tri, const MachineDominatorTree &mdt, - const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi); - - NodeBase *ptr(NodeId N) const; - template T ptr(NodeId N) const { - return static_cast(ptr(N)); - } - - NodeId id(const NodeBase *P) const; - - template NodeAddr addr(NodeId N) const { - return { ptr(N), N }; - } - - NodeAddr getFunc() const { return Func; } - MachineFunction &getMF() const { return MF; } - const TargetInstrInfo &getTII() const { return TII; } - const TargetRegisterInfo &getTRI() const { return TRI; } - const PhysicalRegisterInfo &getPRI() const { return PRI; } - const MachineDominatorTree &getDT() const { return MDT; } - const MachineDominanceFrontier &getDF() const { return MDF; } - const RegisterAggr &getLiveIns() const { return LiveIns; } - - struct DefStack { - DefStack() = default; - - bool empty() const { return Stack.empty() || top() == bottom(); } - - private: - using value_type = NodeAddr; - struct Iterator { - using value_type = DefStack::value_type; - - Iterator &up() { Pos = DS.nextUp(Pos); return *this; } - Iterator &down() { Pos = DS.nextDown(Pos); return *this; } - - value_type operator*() const { - assert(Pos >= 1); - return DS.Stack[Pos-1]; - } - const value_type *operator->() const { - assert(Pos >= 1); - return &DS.Stack[Pos-1]; - } - bool operator==(const Iterator &It) const { return Pos == It.Pos; } - bool operator!=(const Iterator &It) const { return Pos != It.Pos; } - - private: - friend struct DefStack; - - Iterator(const DefStack &S, bool Top); - - // Pos-1 is the index in the StorageType object that corresponds to - // the top of the DefStack. - const DefStack &DS; - unsigned Pos; - }; - - public: - using iterator = Iterator; - - iterator top() const { return Iterator(*this, true); } - iterator bottom() const { return Iterator(*this, false); } - unsigned size() const; - - void push(NodeAddr DA) { Stack.push_back(DA); } - void pop(); - void start_block(NodeId N); - void clear_block(NodeId N); - - private: - friend struct Iterator; - - using StorageType = std::vector; - - bool isDelimiter(const StorageType::value_type &P, NodeId N = 0) const { - return (P.Addr == nullptr) && (N == 0 || P.Id == N); - } - - unsigned nextUp(unsigned P) const; - unsigned nextDown(unsigned P) const; - - StorageType Stack; - }; - - // Make this std::unordered_map for speed of accessing elements. - // Map: Register (physical or virtual) -> DefStack - using DefStackMap = std::unordered_map; - - void build(unsigned Options = BuildOptions::None); - void pushAllDefs(NodeAddr IA, DefStackMap &DM); - void markBlock(NodeId B, DefStackMap &DefM); - void releaseBlock(NodeId B, DefStackMap &DefM); - - PackedRegisterRef pack(RegisterRef RR) { - return { RR.Reg, LMI.getIndexForLaneMask(RR.Mask) }; - } - PackedRegisterRef pack(RegisterRef RR) const { - return { RR.Reg, LMI.getIndexForLaneMask(RR.Mask) }; - } - RegisterRef unpack(PackedRegisterRef PR) const { - return RegisterRef(PR.Reg, LMI.getLaneMaskForIndex(PR.MaskId)); - } - - RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const; - RegisterRef makeRegRef(const MachineOperand &Op) const; - RegisterRef restrictRef(RegisterRef AR, RegisterRef BR) const; - - NodeAddr getNextRelated(NodeAddr IA, - NodeAddr RA) const; - NodeAddr getNextShadow(NodeAddr IA, - NodeAddr RA, bool Create); - NodeAddr getNextShadow(NodeAddr IA, - NodeAddr RA) const; - - NodeList getRelatedRefs(NodeAddr IA, - NodeAddr RA) const; - - NodeAddr findBlock(MachineBasicBlock *BB) const { - return BlockNodes.at(BB); - } - - void unlinkUse(NodeAddr UA, bool RemoveFromOwner) { - unlinkUseDF(UA); - if (RemoveFromOwner) - removeFromOwner(UA); - } - - void unlinkDef(NodeAddr DA, bool RemoveFromOwner) { - unlinkDefDF(DA); - if (RemoveFromOwner) - removeFromOwner(DA); - } - - // Some useful filters. - template - static bool IsRef(const NodeAddr BA) { - return BA.Addr->getType() == NodeAttrs::Ref && - BA.Addr->getKind() == Kind; - } - - template - static bool IsCode(const NodeAddr BA) { - return BA.Addr->getType() == NodeAttrs::Code && - BA.Addr->getKind() == Kind; - } - - static bool IsDef(const NodeAddr BA) { - return BA.Addr->getType() == NodeAttrs::Ref && - BA.Addr->getKind() == NodeAttrs::Def; - } - - static bool IsUse(const NodeAddr BA) { - return BA.Addr->getType() == NodeAttrs::Ref && - BA.Addr->getKind() == NodeAttrs::Use; - } - - static bool IsPhi(const NodeAddr BA) { - return BA.Addr->getType() == NodeAttrs::Code && - BA.Addr->getKind() == NodeAttrs::Phi; - } - - static bool IsPreservingDef(const NodeAddr DA) { - uint16_t Flags = DA.Addr->getFlags(); - return (Flags & NodeAttrs::Preserving) && !(Flags & NodeAttrs::Undef); - } - - private: - void reset(); - - RegisterSet getLandingPadLiveIns() const; - - NodeAddr newNode(uint16_t Attrs); - NodeAddr cloneNode(const NodeAddr B); - NodeAddr newUse(NodeAddr Owner, - MachineOperand &Op, uint16_t Flags = NodeAttrs::None); - NodeAddr newPhiUse(NodeAddr Owner, - RegisterRef RR, NodeAddr PredB, - uint16_t Flags = NodeAttrs::PhiRef); - NodeAddr newDef(NodeAddr Owner, - MachineOperand &Op, uint16_t Flags = NodeAttrs::None); - NodeAddr newDef(NodeAddr Owner, - RegisterRef RR, uint16_t Flags = NodeAttrs::PhiRef); - NodeAddr newPhi(NodeAddr Owner); - NodeAddr newStmt(NodeAddr Owner, - MachineInstr *MI); - NodeAddr newBlock(NodeAddr Owner, - MachineBasicBlock *BB); - NodeAddr newFunc(MachineFunction *MF); - - template - std::pair,NodeAddr> - locateNextRef(NodeAddr IA, NodeAddr RA, - Predicate P) const; - - using BlockRefsMap = std::map; - - void buildStmt(NodeAddr BA, MachineInstr &In); - void recordDefsForDF(BlockRefsMap &PhiM, NodeAddr BA); - void buildPhis(BlockRefsMap &PhiM, RegisterSet &AllRefs, - NodeAddr BA); - void removeUnusedPhis(); - - void pushClobbers(NodeAddr IA, DefStackMap &DM); - void pushDefs(NodeAddr IA, DefStackMap &DM); - template void linkRefUp(NodeAddr IA, - NodeAddr TA, DefStack &DS); - template void linkStmtRefs(DefStackMap &DefM, - NodeAddr SA, Predicate P); - void linkBlockRefs(DefStackMap &DefM, NodeAddr BA); - - void unlinkUseDF(NodeAddr UA); - void unlinkDefDF(NodeAddr DA); - - void removeFromOwner(NodeAddr RA) { - NodeAddr IA = RA.Addr->getOwner(*this); - IA.Addr->removeMember(RA, *this); - } - - MachineFunction &MF; - const TargetInstrInfo &TII; - const TargetRegisterInfo &TRI; - const PhysicalRegisterInfo PRI; - const MachineDominatorTree &MDT; - const MachineDominanceFrontier &MDF; - const TargetOperandInfo &TOI; - - RegisterAggr LiveIns; - NodeAddr Func; - NodeAllocator Memory; - // Local map: MachineBasicBlock -> NodeAddr - std::map> BlockNodes; - // Lane mask map. - LaneMaskIndex LMI; - }; // struct DataFlowGraph - - template - NodeAddr RefNode::getNextRef(RegisterRef RR, Predicate P, - bool NextOnly, const DataFlowGraph &G) { - // Get the "Next" reference in the circular list that references RR and - // satisfies predicate "Pred". - auto NA = G.addr(getNext()); - - while (NA.Addr != this) { - if (NA.Addr->getType() == NodeAttrs::Ref) { - NodeAddr RA = NA; - if (RA.Addr->getRegRef(G) == RR && P(NA)) - return NA; - if (NextOnly) - break; - NA = G.addr(NA.Addr->getNext()); - } else { - // We've hit the beginning of the chain. - assert(NA.Addr->getType() == NodeAttrs::Code); - NodeAddr CA = NA; - NA = CA.Addr->getFirstMember(G); - } - } - // Return the equivalent of "nullptr" if such a node was not found. - return NodeAddr(); - } - - template - NodeList CodeNode::members_if(Predicate P, const DataFlowGraph &G) const { - NodeList MM; - auto M = getFirstMember(G); - if (M.Id == 0) - return MM; - - while (M.Addr != this) { - if (P(M)) - MM.push_back(M); - M = G.addr(M.Addr->getNext()); - } - return MM; - } - - template - struct Print { - Print(const T &x, const DataFlowGraph &g) : Obj(x), G(g) {} - - const T &Obj; - const DataFlowGraph &G; - }; - - template - struct PrintNode : Print> { - PrintNode(const NodeAddr &x, const DataFlowGraph &g) - : Print>(x, g) {} - }; - - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print> &P); - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - raw_ostream &operator<<(raw_ostream &OS, - const Print &P); - -} // end namespace rdf - -} // end namespace llvm - -#endif // LLVM_CODEGEN_RDFGRAPH_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RDFLiveness.h b/suite/synctools/tablegen/include/llvm/CodeGen/RDFLiveness.h deleted file mode 100644 index 45cd84a130..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RDFLiveness.h +++ /dev/null @@ -1,175 +0,0 @@ -//===- RDFLiveness.h --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Recalculate the liveness information given a data flow graph. -// This includes block live-ins and kill flags. - -#ifndef LLVM_CODEGEN_RDFLIVENESS_H -#define LLVM_CODEGEN_RDFLIVENESS_H - -#include "RDFGraph.h" -#include "RDFRegisters.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/MC/LaneBitmask.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineDominanceFrontier; -class MachineDominatorTree; -class MachineRegisterInfo; -class TargetRegisterInfo; - -} // namespace llvm - -namespace llvm { -namespace rdf { -namespace detail { - -using NodeRef = std::pair; - -} // namespace detail -} // namespace rdf -} // namespace llvm - -namespace std { - -template <> struct hash { - std::size_t operator()(llvm::rdf::detail::NodeRef R) const { - return std::hash{}(R.first) ^ - std::hash{}(R.second.getAsInteger()); - } -}; - -} // namespace std - -namespace llvm { -namespace rdf { - - struct Liveness { - public: - // This is really a std::map, except that it provides a non-trivial - // default constructor to the element accessed via []. - struct LiveMapType { - LiveMapType(const PhysicalRegisterInfo &pri) : Empty(pri) {} - - RegisterAggr &operator[] (MachineBasicBlock *B) { - return Map.emplace(B, Empty).first->second; - } - - private: - RegisterAggr Empty; - std::map Map; - }; - - using NodeRef = detail::NodeRef; - using NodeRefSet = std::unordered_set; - using RefMap = std::unordered_map; - - Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g) - : DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()), - MDF(g.getDF()), LiveMap(g.getPRI()), Empty(), NoRegs(g.getPRI()) {} - - NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr RefA, - bool TopShadows, bool FullChain, const RegisterAggr &DefRRs); - - NodeList getAllReachingDefs(NodeAddr RefA) { - return getAllReachingDefs(RefA.Addr->getRegRef(DFG), RefA, false, - false, NoRegs); - } - - NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr RefA) { - return getAllReachingDefs(RefRR, RefA, false, false, NoRegs); - } - - NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr DefA, - const RegisterAggr &DefRRs); - - NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr DefA) { - return getAllReachedUses(RefRR, DefA, NoRegs); - } - - std::pair getAllReachingDefsRec(RegisterRef RefRR, - NodeAddr RefA, NodeSet &Visited, const NodeSet &Defs); - - NodeAddr getNearestAliasedRef(RegisterRef RefRR, - NodeAddr IA); - - LiveMapType &getLiveMap() { return LiveMap; } - const LiveMapType &getLiveMap() const { return LiveMap; } - - const RefMap &getRealUses(NodeId P) const { - auto F = RealUseMap.find(P); - return F == RealUseMap.end() ? Empty : F->second; - } - - void computePhiInfo(); - void computeLiveIns(); - void resetLiveIns(); - void resetKills(); - void resetKills(MachineBasicBlock *B); - - void trace(bool T) { Trace = T; } - - private: - const DataFlowGraph &DFG; - const TargetRegisterInfo &TRI; - const PhysicalRegisterInfo &PRI; - const MachineDominatorTree &MDT; - const MachineDominanceFrontier &MDF; - LiveMapType LiveMap; - const RefMap Empty; - const RegisterAggr NoRegs; - bool Trace = false; - - // Cache of mapping from node ids (for RefNodes) to the containing - // basic blocks. Not computing it each time for each node reduces - // the liveness calculation time by a large fraction. - DenseMap NBMap; - - // Phi information: - // - // RealUseMap - // map: NodeId -> (map: RegisterId -> NodeRefSet) - // phi id -> (map: register -> set of reached non-phi uses) - DenseMap RealUseMap; - - // Inverse iterated dominance frontier. - std::map> IIDF; - - // Live on entry. - std::map PhiLON; - - // Phi uses are considered to be located at the end of the block that - // they are associated with. The reaching def of a phi use dominates the - // block that the use corresponds to, but not the block that contains - // the phi itself. To include these uses in the liveness propagation (up - // the dominator tree), create a map: block -> set of uses live on exit. - std::map PhiLOX; - - MachineBasicBlock *getBlockWithRef(NodeId RN) const; - void traverse(MachineBasicBlock *B, RefMap &LiveIn); - void emptify(RefMap &M); - - std::pair getAllReachingDefsRecImpl(RegisterRef RefRR, - NodeAddr RefA, NodeSet &Visited, const NodeSet &Defs, - unsigned Nest, unsigned MaxNest); - }; - - raw_ostream &operator<<(raw_ostream &OS, const Print &P); - -} // end namespace rdf - -} // end namespace llvm - -#endif // LLVM_CODEGEN_RDFLIVENESS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RDFRegisters.h b/suite/synctools/tablegen/include/llvm/CodeGen/RDFRegisters.h deleted file mode 100644 index b18cbba227..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RDFRegisters.h +++ /dev/null @@ -1,279 +0,0 @@ -//===- RDFRegisters.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_RDFREGISTERS_H -#define LLVM_CODEGEN_RDFREGISTERS_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/LaneBitmask.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class MachineFunction; -class raw_ostream; - -namespace rdf { - - using RegisterId = uint32_t; - - // Template class for a map translating uint32_t into arbitrary types. - // The map will act like an indexed set: upon insertion of a new object, - // it will automatically assign a new index to it. Index of 0 is treated - // as invalid and is never allocated. - template - struct IndexedSet { - IndexedSet() { Map.reserve(N); } - - T get(uint32_t Idx) const { - // Index Idx corresponds to Map[Idx-1]. - assert(Idx != 0 && !Map.empty() && Idx-1 < Map.size()); - return Map[Idx-1]; - } - - uint32_t insert(T Val) { - // Linear search. - auto F = llvm::find(Map, Val); - if (F != Map.end()) - return F - Map.begin() + 1; - Map.push_back(Val); - return Map.size(); // Return actual_index + 1. - } - - uint32_t find(T Val) const { - auto F = llvm::find(Map, Val); - assert(F != Map.end()); - return F - Map.begin() + 1; - } - - uint32_t size() const { return Map.size(); } - - using const_iterator = typename std::vector::const_iterator; - - const_iterator begin() const { return Map.begin(); } - const_iterator end() const { return Map.end(); } - - private: - std::vector Map; - }; - - struct RegisterRef { - RegisterId Reg = 0; - LaneBitmask Mask = LaneBitmask::getNone(); - - RegisterRef() = default; - explicit RegisterRef(RegisterId R, LaneBitmask M = LaneBitmask::getAll()) - : Reg(R), Mask(R != 0 ? M : LaneBitmask::getNone()) {} - - operator bool() const { - return Reg != 0 && Mask.any(); - } - - bool operator== (const RegisterRef &RR) const { - return Reg == RR.Reg && Mask == RR.Mask; - } - - bool operator!= (const RegisterRef &RR) const { - return !operator==(RR); - } - - bool operator< (const RegisterRef &RR) const { - return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask); - } - - size_t hash() const { - return std::hash{}(Reg) ^ - std::hash{}(Mask.getAsInteger()); - } - }; - - - struct PhysicalRegisterInfo { - PhysicalRegisterInfo(const TargetRegisterInfo &tri, - const MachineFunction &mf); - - static bool isRegMaskId(RegisterId R) { - return Register::isStackSlot(R); - } - - RegisterId getRegMaskId(const uint32_t *RM) const { - return Register::index2StackSlot(RegMasks.find(RM)); - } - - const uint32_t *getRegMaskBits(RegisterId R) const { - return RegMasks.get(Register::stackSlot2Index(R)); - } - - bool alias(RegisterRef RA, RegisterRef RB) const { - if (!isRegMaskId(RA.Reg)) - return !isRegMaskId(RB.Reg) ? aliasRR(RA, RB) : aliasRM(RA, RB); - return !isRegMaskId(RB.Reg) ? aliasRM(RB, RA) : aliasMM(RA, RB); - } - - std::set getAliasSet(RegisterId Reg) const; - - RegisterRef getRefForUnit(uint32_t U) const { - return RegisterRef(UnitInfos[U].Reg, UnitInfos[U].Mask); - } - - const BitVector &getMaskUnits(RegisterId MaskId) const { - return MaskInfos[Register::stackSlot2Index(MaskId)].Units; - } - - const BitVector &getUnitAliases(uint32_t U) const { - return AliasInfos[U].Regs; - } - - RegisterRef mapTo(RegisterRef RR, unsigned R) const; - const TargetRegisterInfo &getTRI() const { return TRI; } - - private: - struct RegInfo { - const TargetRegisterClass *RegClass = nullptr; - }; - struct UnitInfo { - RegisterId Reg = 0; - LaneBitmask Mask; - }; - struct MaskInfo { - BitVector Units; - }; - struct AliasInfo { - BitVector Regs; - }; - - const TargetRegisterInfo &TRI; - IndexedSet RegMasks; - std::vector RegInfos; - std::vector UnitInfos; - std::vector MaskInfos; - std::vector AliasInfos; - - bool aliasRR(RegisterRef RA, RegisterRef RB) const; - bool aliasRM(RegisterRef RR, RegisterRef RM) const; - bool aliasMM(RegisterRef RM, RegisterRef RN) const; - }; - - struct RegisterAggr { - RegisterAggr(const PhysicalRegisterInfo &pri) - : Units(pri.getTRI().getNumRegUnits()), PRI(pri) {} - RegisterAggr(const RegisterAggr &RG) = default; - - unsigned count() const { return Units.count(); } - bool empty() const { return Units.none(); } - bool hasAliasOf(RegisterRef RR) const; - bool hasCoverOf(RegisterRef RR) const; - - bool operator==(const RegisterAggr &A) const { - return DenseMapInfo::isEqual(Units, A.Units); - } - - static bool isCoverOf(RegisterRef RA, RegisterRef RB, - const PhysicalRegisterInfo &PRI) { - return RegisterAggr(PRI).insert(RA).hasCoverOf(RB); - } - - RegisterAggr &insert(RegisterRef RR); - RegisterAggr &insert(const RegisterAggr &RG); - RegisterAggr &intersect(RegisterRef RR); - RegisterAggr &intersect(const RegisterAggr &RG); - RegisterAggr &clear(RegisterRef RR); - RegisterAggr &clear(const RegisterAggr &RG); - - RegisterRef intersectWith(RegisterRef RR) const; - RegisterRef clearIn(RegisterRef RR) const; - RegisterRef makeRegRef() const; - - size_t hash() const { - return DenseMapInfo::getHashValue(Units); - } - - void print(raw_ostream &OS) const; - - struct rr_iterator { - using MapType = std::map; - - private: - MapType Masks; - MapType::iterator Pos; - unsigned Index; - const RegisterAggr *Owner; - - public: - rr_iterator(const RegisterAggr &RG, bool End); - - RegisterRef operator*() const { - return RegisterRef(Pos->first, Pos->second); - } - - rr_iterator &operator++() { - ++Pos; - ++Index; - return *this; - } - - bool operator==(const rr_iterator &I) const { - assert(Owner == I.Owner); - (void)Owner; - return Index == I.Index; - } - - bool operator!=(const rr_iterator &I) const { - return !(*this == I); - } - }; - - rr_iterator rr_begin() const { - return rr_iterator(*this, false); - } - rr_iterator rr_end() const { - return rr_iterator(*this, true); - } - - private: - BitVector Units; - const PhysicalRegisterInfo &PRI; - }; - - // Optionally print the lane mask, if it is not ~0. - struct PrintLaneMaskOpt { - PrintLaneMaskOpt(LaneBitmask M) : Mask(M) {} - LaneBitmask Mask; - }; - raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P); - - raw_ostream &operator<< (raw_ostream &OS, const RegisterAggr &A); -} // end namespace rdf - -} // end namespace llvm - -namespace std { - template <> struct hash { - size_t operator()(llvm::rdf::RegisterRef A) const { - return A.hash(); - } - }; - template <> struct hash { - size_t operator()(const llvm::rdf::RegisterAggr &A) const { - return A.hash(); - } - }; - template <> struct equal_to { - bool operator()(const llvm::rdf::RegisterAggr &A, - const llvm::rdf::RegisterAggr &B) const { - return A == B; - } - }; -} -#endif // LLVM_CODEGEN_RDFREGISTERS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ReachingDefAnalysis.h b/suite/synctools/tablegen/include/llvm/CodeGen/ReachingDefAnalysis.h deleted file mode 100644 index 68e913576c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ReachingDefAnalysis.h +++ /dev/null @@ -1,281 +0,0 @@ -//==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Reaching Defs Analysis pass. -/// -/// This pass tracks for each instruction what is the "closest" reaching def of -/// a given register. It is used by BreakFalseDeps (for clearance calculation) -/// and ExecutionDomainFix (for arbitrating conflicting domains). -/// -/// Note that this is different from the usual definition notion of liveness. -/// The CPU doesn't care whether or not we consider a register killed. -/// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REACHINGDEFANALYSIS_H -#define LLVM_CODEGEN_REACHINGDEFANALYSIS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/CodeGen/LoopTraversal.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/InitializePasses.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineInstr; - -/// Thin wrapper around "int" used to store reaching definitions, -/// using an encoding that makes it compatible with TinyPtrVector. -/// The 0th LSB is forced zero (and will be used for pointer union tagging), -/// The 1st LSB is forced one (to make sure the value is non-zero). -class ReachingDef { - uintptr_t Encoded; - friend struct PointerLikeTypeTraits; - explicit ReachingDef(uintptr_t Encoded) : Encoded(Encoded) {} - -public: - ReachingDef(std::nullptr_t) : Encoded(0) {} - ReachingDef(int Instr) : Encoded(((uintptr_t) Instr << 2) | 2) {} - operator int() const { return ((int) Encoded) >> 2; } -}; - -template<> -struct PointerLikeTypeTraits { - static constexpr int NumLowBitsAvailable = 1; - - static inline void *getAsVoidPointer(const ReachingDef &RD) { - return reinterpret_cast(RD.Encoded); - } - - static inline ReachingDef getFromVoidPointer(void *P) { - return ReachingDef(reinterpret_cast(P)); - } - - static inline ReachingDef getFromVoidPointer(const void *P) { - return ReachingDef(reinterpret_cast(P)); - } -}; - -/// This class provides the reaching def analysis. -class ReachingDefAnalysis : public MachineFunctionPass { -private: - MachineFunction *MF; - const TargetRegisterInfo *TRI; - LoopTraversal::TraversalOrder TraversedMBBOrder; - unsigned NumRegUnits; - /// Instruction that defined each register, relative to the beginning of the - /// current basic block. When a LiveRegsDefInfo is used to represent a - /// live-out register, this value is relative to the end of the basic block, - /// so it will be a negative number. - using LiveRegsDefInfo = std::vector; - LiveRegsDefInfo LiveRegs; - - /// Keeps clearance information for all registers. Note that this - /// is different from the usual definition notion of liveness. The CPU - /// doesn't care whether or not we consider a register killed. - using OutRegsInfoMap = SmallVector; - OutRegsInfoMap MBBOutRegsInfos; - - /// Current instruction number. - /// The first instruction in each basic block is 0. - int CurInstr; - - /// Maps instructions to their instruction Ids, relative to the beginning of - /// their basic blocks. - DenseMap InstIds; - - /// All reaching defs of a given RegUnit for a given MBB. - using MBBRegUnitDefs = TinyPtrVector; - /// All reaching defs of all reg units for a given MBB - using MBBDefsInfo = std::vector; - /// All reaching defs of all reg units for a all MBBs - using MBBReachingDefsInfo = SmallVector; - MBBReachingDefsInfo MBBReachingDefs; - - /// Default values are 'nothing happened a long time ago'. - const int ReachingDefDefaultVal = -(1 << 20); - - using InstSet = SmallPtrSetImpl; - using BlockSet = SmallPtrSetImpl; - -public: - static char ID; // Pass identification, replacement for typeid - - ReachingDefAnalysis() : MachineFunctionPass(ID) { - initializeReachingDefAnalysisPass(*PassRegistry::getPassRegistry()); - } - void releaseMemory() override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs).set( - MachineFunctionProperties::Property::TracksLiveness); - } - - /// Re-run the analysis. - void reset(); - - /// Initialize data structures. - void init(); - - /// Traverse the machine function, mapping definitions. - void traverse(); - - /// Provides the instruction id of the closest reaching def instruction of - /// PhysReg that reaches MI, relative to the beginning of MI's basic block. - int getReachingDef(MachineInstr *MI, MCRegister PhysReg) const; - - /// Return whether A and B use the same def of PhysReg. - bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, - MCRegister PhysReg) const; - - /// Return whether the reaching def for MI also is live out of its parent - /// block. - bool isReachingDefLiveOut(MachineInstr *MI, MCRegister PhysReg) const; - - /// Return the local MI that produces the live out value for PhysReg, or - /// nullptr for a non-live out or non-local def. - MachineInstr *getLocalLiveOutMIDef(MachineBasicBlock *MBB, - MCRegister PhysReg) const; - - /// If a single MachineInstr creates the reaching definition, then return it. - /// Otherwise return null. - MachineInstr *getUniqueReachingMIDef(MachineInstr *MI, - MCRegister PhysReg) const; - - /// If a single MachineInstr creates the reaching definition, for MIs operand - /// at Idx, then return it. Otherwise return null. - MachineInstr *getMIOperand(MachineInstr *MI, unsigned Idx) const; - - /// If a single MachineInstr creates the reaching definition, for MIs MO, - /// then return it. Otherwise return null. - MachineInstr *getMIOperand(MachineInstr *MI, MachineOperand &MO) const; - - /// Provide whether the register has been defined in the same basic block as, - /// and before, MI. - bool hasLocalDefBefore(MachineInstr *MI, MCRegister PhysReg) const; - - /// Return whether the given register is used after MI, whether it's a local - /// use or a live out. - bool isRegUsedAfter(MachineInstr *MI, MCRegister PhysReg) const; - - /// Return whether the given register is defined after MI. - bool isRegDefinedAfter(MachineInstr *MI, MCRegister PhysReg) const; - - /// Provides the clearance - the number of instructions since the closest - /// reaching def instruction of PhysReg that reaches MI. - int getClearance(MachineInstr *MI, MCRegister PhysReg) const; - - /// Provides the uses, in the same block as MI, of register that MI defines. - /// This does not consider live-outs. - void getReachingLocalUses(MachineInstr *MI, MCRegister PhysReg, - InstSet &Uses) const; - - /// Search MBB for a definition of PhysReg and insert it into Defs. If no - /// definition is found, recursively search the predecessor blocks for them. - void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, InstSet &Defs, - BlockSet &VisitedBBs) const; - void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, - InstSet &Defs) const; - - /// For the given block, collect the instructions that use the live-in - /// value of the provided register. Return whether the value is still - /// live on exit. - bool getLiveInUses(MachineBasicBlock *MBB, MCRegister PhysReg, - InstSet &Uses) const; - - /// Collect the users of the value stored in PhysReg, which is defined - /// by MI. - void getGlobalUses(MachineInstr *MI, MCRegister PhysReg, InstSet &Uses) const; - - /// Collect all possible definitions of the value stored in PhysReg, which is - /// used by MI. - void getGlobalReachingDefs(MachineInstr *MI, MCRegister PhysReg, - InstSet &Defs) const; - - /// Return whether From can be moved forwards to just before To. - bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const; - - /// Return whether From can be moved backwards to just after To. - bool isSafeToMoveBackwards(MachineInstr *From, MachineInstr *To) const; - - /// Assuming MI is dead, recursively search the incoming operands which are - /// killed by MI and collect those that would become dead. - void collectKilledOperands(MachineInstr *MI, InstSet &Dead) const; - - /// Return whether removing this instruction will have no effect on the - /// program, returning the redundant use-def chain. - bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove) const; - - /// Return whether removing this instruction will have no effect on the - /// program, ignoring the possible effects on some instructions, returning - /// the redundant use-def chain. - bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove, - InstSet &Ignore) const; - - /// Return whether a MachineInstr could be inserted at MI and safely define - /// the given register without affecting the program. - bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg) const; - - /// Return whether a MachineInstr could be inserted at MI and safely define - /// the given register without affecting the program, ignoring any effects - /// on the provided instructions. - bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg, - InstSet &Ignore) const; - -private: - /// Set up LiveRegs by merging predecessor live-out values. - void enterBasicBlock(MachineBasicBlock *MBB); - - /// Update live-out values. - void leaveBasicBlock(MachineBasicBlock *MBB); - - /// Process he given basic block. - void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); - - /// Process block that is part of a loop again. - void reprocessBasicBlock(MachineBasicBlock *MBB); - - /// Update def-ages for registers defined by MI. - /// Also break dependencies on partial defs and undef uses. - void processDefs(MachineInstr *); - - /// Utility function for isSafeToMoveForwards/Backwards. - template - bool isSafeToMove(MachineInstr *From, MachineInstr *To) const; - - /// Return whether removing this instruction will have no effect on the - /// program, ignoring the possible effects on some instructions, returning - /// the redundant use-def chain. - bool isSafeToRemove(MachineInstr *MI, InstSet &Visited, - InstSet &ToRemove, InstSet &Ignore) const; - - /// Provides the MI, from the given block, corresponding to the Id or a - /// nullptr if the id does not refer to the block. - MachineInstr *getInstFromId(MachineBasicBlock *MBB, int InstId) const; - - /// Provides the instruction of the closest reaching def instruction of - /// PhysReg that reaches MI, relative to the beginning of MI's basic block. - MachineInstr *getReachingLocalMIDef(MachineInstr *MI, - MCRegister PhysReg) const; -}; - -} // namespace llvm - -#endif // LLVM_CODEGEN_REACHINGDEFANALYSIS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocCommon.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocCommon.h deleted file mode 100644 index 757ca8e112..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocCommon.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- RegAllocCommon.h - Utilities shared between allocators ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGALLOCCOMMON_H -#define LLVM_CODEGEN_REGALLOCCOMMON_H - -#include - -namespace llvm { - -class TargetRegisterClass; -class TargetRegisterInfo; - -typedef std::function RegClassFilterFunc; - -/// Default register class filter function for register allocation. All virtual -/// registers should be allocated. -static inline bool allocateAllRegClasses(const TargetRegisterInfo &, - const TargetRegisterClass &) { - return true; -} - -} - -#endif // LLVM_CODEGEN_REGALLOCCOMMON_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocPBQP.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocPBQP.h deleted file mode 100644 index 1ed55082e3..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocPBQP.h +++ /dev/null @@ -1,537 +0,0 @@ -//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the PBQPBuilder interface, for classes which build PBQP -// instances to represent register allocation problems, and the RegAllocPBQP -// interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGALLOCPBQP_H -#define LLVM_CODEGEN_REGALLOCPBQP_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/CodeGen/PBQP/CostAllocator.h" -#include "llvm/CodeGen/PBQP/Graph.h" -#include "llvm/CodeGen/PBQP/Math.h" -#include "llvm/CodeGen/PBQP/ReductionRules.h" -#include "llvm/CodeGen/PBQP/Solution.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/MC/MCRegister.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class FunctionPass; -class LiveIntervals; -class MachineBlockFrequencyInfo; -class MachineFunction; -class raw_ostream; - -namespace PBQP { -namespace RegAlloc { - -/// Spill option index. -inline unsigned getSpillOptionIdx() { return 0; } - -/// Metadata to speed allocatability test. -/// -/// Keeps track of the number of infinities in each row and column. -class MatrixMetadata { -public: - MatrixMetadata(const Matrix& M) - : UnsafeRows(new bool[M.getRows() - 1]()), - UnsafeCols(new bool[M.getCols() - 1]()) { - unsigned* ColCounts = new unsigned[M.getCols() - 1](); - - for (unsigned i = 1; i < M.getRows(); ++i) { - unsigned RowCount = 0; - for (unsigned j = 1; j < M.getCols(); ++j) { - if (M[i][j] == std::numeric_limits::infinity()) { - ++RowCount; - ++ColCounts[j - 1]; - UnsafeRows[i - 1] = true; - UnsafeCols[j - 1] = true; - } - } - WorstRow = std::max(WorstRow, RowCount); - } - unsigned WorstColCountForCurRow = - *std::max_element(ColCounts, ColCounts + M.getCols() - 1); - WorstCol = std::max(WorstCol, WorstColCountForCurRow); - delete[] ColCounts; - } - - MatrixMetadata(const MatrixMetadata &) = delete; - MatrixMetadata &operator=(const MatrixMetadata &) = delete; - - unsigned getWorstRow() const { return WorstRow; } - unsigned getWorstCol() const { return WorstCol; } - const bool* getUnsafeRows() const { return UnsafeRows.get(); } - const bool* getUnsafeCols() const { return UnsafeCols.get(); } - -private: - unsigned WorstRow = 0; - unsigned WorstCol = 0; - std::unique_ptr UnsafeRows; - std::unique_ptr UnsafeCols; -}; - -/// Holds a vector of the allowed physical regs for a vreg. -class AllowedRegVector { - friend hash_code hash_value(const AllowedRegVector &); - -public: - AllowedRegVector() = default; - AllowedRegVector(AllowedRegVector &&) = default; - - AllowedRegVector(const std::vector &OptVec) - : NumOpts(OptVec.size()), Opts(new MCRegister[NumOpts]) { - std::copy(OptVec.begin(), OptVec.end(), Opts.get()); - } - - unsigned size() const { return NumOpts; } - MCRegister operator[](size_t I) const { return Opts[I]; } - - bool operator==(const AllowedRegVector &Other) const { - if (NumOpts != Other.NumOpts) - return false; - return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get()); - } - - bool operator!=(const AllowedRegVector &Other) const { - return !(*this == Other); - } - -private: - unsigned NumOpts = 0; - std::unique_ptr Opts; -}; - -inline hash_code hash_value(const AllowedRegVector &OptRegs) { - MCRegister *OStart = OptRegs.Opts.get(); - MCRegister *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts; - return hash_combine(OptRegs.NumOpts, - hash_combine_range(OStart, OEnd)); -} - -/// Holds graph-level metadata relevant to PBQP RA problems. -class GraphMetadata { -private: - using AllowedRegVecPool = ValuePool; - -public: - using AllowedRegVecRef = AllowedRegVecPool::PoolRef; - - GraphMetadata(MachineFunction &MF, - LiveIntervals &LIS, - MachineBlockFrequencyInfo &MBFI) - : MF(MF), LIS(LIS), MBFI(MBFI) {} - - MachineFunction &MF; - LiveIntervals &LIS; - MachineBlockFrequencyInfo &MBFI; - - void setNodeIdForVReg(Register VReg, GraphBase::NodeId NId) { - VRegToNodeId[VReg.id()] = NId; - } - - GraphBase::NodeId getNodeIdForVReg(Register VReg) const { - auto VRegItr = VRegToNodeId.find(VReg); - if (VRegItr == VRegToNodeId.end()) - return GraphBase::invalidNodeId(); - return VRegItr->second; - } - - AllowedRegVecRef getAllowedRegs(AllowedRegVector Allowed) { - return AllowedRegVecs.getValue(std::move(Allowed)); - } - -private: - DenseMap VRegToNodeId; - AllowedRegVecPool AllowedRegVecs; -}; - -/// Holds solver state and other metadata relevant to each PBQP RA node. -class NodeMetadata { -public: - using AllowedRegVector = RegAlloc::AllowedRegVector; - - // The node's reduction state. The order in this enum is important, - // as it is assumed nodes can only progress up (i.e. towards being - // optimally reducible) when reducing the graph. - using ReductionState = enum { - Unprocessed, - NotProvablyAllocatable, - ConservativelyAllocatable, - OptimallyReducible - }; - - NodeMetadata() = default; - - NodeMetadata(const NodeMetadata &Other) - : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), - OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), - AllowedRegs(Other.AllowedRegs) -#ifndef NDEBUG - , everConservativelyAllocatable(Other.everConservativelyAllocatable) -#endif - { - if (NumOpts > 0) { - std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], - &OptUnsafeEdges[0]); - } - } - - NodeMetadata(NodeMetadata &&) = default; - NodeMetadata& operator=(NodeMetadata &&) = default; - - void setVReg(Register VReg) { this->VReg = VReg; } - Register getVReg() const { return VReg; } - - void setAllowedRegs(GraphMetadata::AllowedRegVecRef AllowedRegs) { - this->AllowedRegs = std::move(AllowedRegs); - } - const AllowedRegVector& getAllowedRegs() const { return *AllowedRegs; } - - void setup(const Vector& Costs) { - NumOpts = Costs.getLength() - 1; - OptUnsafeEdges = std::unique_ptr(new unsigned[NumOpts]()); - } - - ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { - assert(RS >= this->RS && "A node's reduction state can not be downgraded"); - this->RS = RS; - -#ifndef NDEBUG - // Remember this state to assert later that a non-infinite register - // option was available. - if (RS == ConservativelyAllocatable) - everConservativelyAllocatable = true; -#endif - } - - void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] += UnsafeOpts[i]; - } - - void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstRow() : MD.getWorstCol(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] -= UnsafeOpts[i]; - } - - bool isConservativelyAllocatable() const { - return (DeniedOpts < NumOpts) || - (std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) != - &OptUnsafeEdges[NumOpts]); - } - -#ifndef NDEBUG - bool wasConservativelyAllocatable() const { - return everConservativelyAllocatable; - } -#endif - -private: - ReductionState RS = Unprocessed; - unsigned NumOpts = 0; - unsigned DeniedOpts = 0; - std::unique_ptr OptUnsafeEdges; - Register VReg; - GraphMetadata::AllowedRegVecRef AllowedRegs; - -#ifndef NDEBUG - bool everConservativelyAllocatable = false; -#endif -}; - -class RegAllocSolverImpl { -private: - using RAMatrix = MDMatrix; - -public: - using RawVector = PBQP::Vector; - using RawMatrix = PBQP::Matrix; - using Vector = PBQP::Vector; - using Matrix = RAMatrix; - using CostAllocator = PBQP::PoolCostAllocator; - - using NodeId = GraphBase::NodeId; - using EdgeId = GraphBase::EdgeId; - - using NodeMetadata = RegAlloc::NodeMetadata; - struct EdgeMetadata {}; - using GraphMetadata = RegAlloc::GraphMetadata; - - using Graph = PBQP::Graph; - - RegAllocSolverImpl(Graph &G) : G(G) {} - - Solution solve() { - G.setSolver(*this); - Solution S; - setup(); - S = backpropagate(G, reduce()); - G.unsetSolver(); - return S; - } - - void handleAddNode(NodeId NId) { - assert(G.getNodeCosts(NId).getLength() > 1 && - "PBQP Graph should not contain single or zero-option nodes"); - G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); - } - - void handleRemoveNode(NodeId NId) {} - void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} - - void handleAddEdge(EdgeId EId) { - handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); - handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); - } - - void handleDisconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - promote(NId, NMd); - } - - void handleReconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); - } - - void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) { - NodeId N1Id = G.getEdgeNode1Id(EId); - NodeId N2Id = G.getEdgeNode2Id(EId); - NodeMetadata& N1Md = G.getNodeMetadata(N1Id); - NodeMetadata& N2Md = G.getNodeMetadata(N2Id); - bool Transpose = N1Id != G.getEdgeNode1Id(EId); - - // Metadata are computed incrementally. First, update them - // by removing the old cost. - const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata(); - N1Md.handleRemoveEdge(OldMMd, Transpose); - N2Md.handleRemoveEdge(OldMMd, !Transpose); - - // And update now the metadata with the new cost. - const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, Transpose); - N2Md.handleAddEdge(MMd, !Transpose); - - // As the metadata may have changed with the update, the nodes may have - // become ConservativelyAllocatable or OptimallyReducible. - promote(N1Id, N1Md); - promote(N2Id, N2Md); - } - -private: - void promote(NodeId NId, NodeMetadata& NMd) { - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } - } - - void removeFromCurrentSet(NodeId NId) { - switch (G.getNodeMetadata(NId).getReductionState()) { - case NodeMetadata::Unprocessed: break; - case NodeMetadata::OptimallyReducible: - assert(OptimallyReducibleNodes.find(NId) != - OptimallyReducibleNodes.end() && - "Node not in optimally reducible set."); - OptimallyReducibleNodes.erase(NId); - break; - case NodeMetadata::ConservativelyAllocatable: - assert(ConservativelyAllocatableNodes.find(NId) != - ConservativelyAllocatableNodes.end() && - "Node not in conservatively allocatable set."); - ConservativelyAllocatableNodes.erase(NId); - break; - case NodeMetadata::NotProvablyAllocatable: - assert(NotProvablyAllocatableNodes.find(NId) != - NotProvablyAllocatableNodes.end() && - "Node not in not-provably-allocatable set."); - NotProvablyAllocatableNodes.erase(NId); - break; - } - } - - void moveToOptimallyReducibleNodes(NodeId NId) { - removeFromCurrentSet(NId); - OptimallyReducibleNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::OptimallyReducible); - } - - void moveToConservativelyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - ConservativelyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::ConservativelyAllocatable); - } - - void moveToNotProvablyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - NotProvablyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::NotProvablyAllocatable); - } - - void setup() { - // Set up worklists. - for (auto NId : G.nodeIds()) { - if (G.getNodeDegree(NId) < 3) - moveToOptimallyReducibleNodes(NId); - else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) - moveToConservativelyAllocatableNodes(NId); - else - moveToNotProvablyAllocatableNodes(NId); - } - } - - // Compute a reduction order for the graph by iteratively applying PBQP - // reduction rules. Locally optimal rules are applied whenever possible (R0, - // R1, R2). If no locally-optimal rules apply then any conservatively - // allocatable node is reduced. Finally, if no conservatively allocatable - // node exists then the node with the lowest spill-cost:degree ratio is - // selected. - std::vector reduce() { - assert(!G.empty() && "Cannot reduce empty graph."); - - using NodeId = GraphBase::NodeId; - std::vector NodeStack; - - // Consume worklists. - while (true) { - if (!OptimallyReducibleNodes.empty()) { - NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); - NodeId NId = *NItr; - OptimallyReducibleNodes.erase(NItr); - NodeStack.push_back(NId); - switch (G.getNodeDegree(NId)) { - case 0: - break; - case 1: - applyR1(G, NId); - break; - case 2: - applyR2(G, NId); - break; - default: llvm_unreachable("Not an optimally reducible node."); - } - } else if (!ConservativelyAllocatableNodes.empty()) { - // Conservatively allocatable nodes will never spill. For now just - // take the first node in the set and push it on the stack. When we - // start optimizing more heavily for register preferencing, it may - // would be better to push nodes with lower 'expected' or worst-case - // register costs first (since early nodes are the most - // constrained). - NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); - NodeId NId = *NItr; - ConservativelyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - } else if (!NotProvablyAllocatableNodes.empty()) { - NodeSet::iterator NItr = - std::min_element(NotProvablyAllocatableNodes.begin(), - NotProvablyAllocatableNodes.end(), - SpillCostComparator(G)); - NodeId NId = *NItr; - NotProvablyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - } else - break; - } - - return NodeStack; - } - - class SpillCostComparator { - public: - SpillCostComparator(const Graph& G) : G(G) {} - - bool operator()(NodeId N1Id, NodeId N2Id) { - PBQPNum N1SC = G.getNodeCosts(N1Id)[0]; - PBQPNum N2SC = G.getNodeCosts(N2Id)[0]; - if (N1SC == N2SC) - return G.getNodeDegree(N1Id) < G.getNodeDegree(N2Id); - return N1SC < N2SC; - } - - private: - const Graph& G; - }; - - Graph& G; - using NodeSet = std::set; - NodeSet OptimallyReducibleNodes; - NodeSet ConservativelyAllocatableNodes; - NodeSet NotProvablyAllocatableNodes; -}; - -class PBQPRAGraph : public PBQP::Graph { -private: - using BaseT = PBQP::Graph; - -public: - PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {} - - /// Dump this graph to dbgs(). - void dump() const; - - /// Dump this graph to an output stream. - /// @param OS Output stream to print on. - void dump(raw_ostream &OS) const; - - /// Print a representation of this graph in DOT format. - /// @param OS Output stream to print on. - void printDot(raw_ostream &OS) const; -}; - -inline Solution solve(PBQPRAGraph& G) { - if (G.empty()) - return Solution(); - RegAllocSolverImpl RegAllocSolver(G); - return RegAllocSolver.solve(); -} - -} // end namespace RegAlloc -} // end namespace PBQP - -/// Create a PBQP register allocator instance. -FunctionPass * -createPBQPRegisterAllocator(char *customPassID = nullptr); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGALLOCPBQP_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocRegistry.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocRegistry.h deleted file mode 100644 index e33d16c636..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegAllocRegistry.h +++ /dev/null @@ -1,74 +0,0 @@ -//===- llvm/CodeGen/RegAllocRegistry.h --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation for register allocator function -// pass registry (RegisterRegAlloc). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGALLOCREGISTRY_H -#define LLVM_CODEGEN_REGALLOCREGISTRY_H - -#include "llvm/CodeGen/RegAllocCommon.h" -#include "llvm/CodeGen/MachinePassRegistry.h" - -namespace llvm { - -class FunctionPass; - -//===----------------------------------------------------------------------===// -/// -/// RegisterRegAllocBase class - Track the registration of register allocators. -/// -//===----------------------------------------------------------------------===// -template -class RegisterRegAllocBase : public MachinePassRegistryNode { -public: - using FunctionPassCtor = FunctionPass *(*)(); - - static MachinePassRegistry Registry; - - RegisterRegAllocBase(const char *N, const char *D, FunctionPassCtor C) - : MachinePassRegistryNode(N, D, C) { - Registry.Add(this); - } - - ~RegisterRegAllocBase() { Registry.Remove(this); } - - // Accessors. - SubClass *getNext() const { - return static_cast(MachinePassRegistryNode::getNext()); - } - - static SubClass *getList() { - return static_cast(Registry.getList()); - } - - static FunctionPassCtor getDefault() { return Registry.getDefault(); } - - static void setDefault(FunctionPassCtor C) { Registry.setDefault(C); } - - static void setListener(MachinePassRegistryListener *L) { - Registry.setListener(L); - } -}; - -class RegisterRegAlloc : public RegisterRegAllocBase { -public: - RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) - : RegisterRegAllocBase(N, D, C) {} -}; - -/// RegisterRegAlloc's global Registry tracks allocator registration. -template -MachinePassRegistry -RegisterRegAllocBase::Registry; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGALLOCREGISTRY_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/Register.h b/suite/synctools/tablegen/include/llvm/CodeGen/Register.h deleted file mode 100644 index a683223b5a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/Register.h +++ /dev/null @@ -1,165 +0,0 @@ -//===-- llvm/CodeGen/Register.h ---------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGISTER_H -#define LLVM_CODEGEN_REGISTER_H - -#include "llvm/MC/MCRegister.h" -#include - -namespace llvm { - -/// Wrapper class representing virtual and physical registers. Should be passed -/// by value. -class Register { - unsigned Reg; - -public: - constexpr Register(unsigned Val = 0): Reg(Val) {} - constexpr Register(MCRegister Val): Reg(Val) {} - - // Register numbers can represent physical registers, virtual registers, and - // sometimes stack slots. The unsigned values are divided into these ranges: - // - // 0 Not a register, can be used as a sentinel. - // [1;2^30) Physical registers assigned by TableGen. - // [2^30;2^31) Stack slots. (Rarely used.) - // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. - // - // Further sentinels can be allocated from the small negative integers. - // DenseMapInfo uses -1u and -2u. - static_assert(std::numeric_limits::max() >= 0xFFFFFFFF, - "Reg isn't large enough to hold full range."); - - /// isStackSlot - Sometimes it is useful the be able to store a non-negative - /// frame index in a variable that normally holds a register. isStackSlot() - /// returns true if Reg is in the range used for stack slots. - /// - /// FIXME: remove in favor of member. - static bool isStackSlot(unsigned Reg) { - return MCRegister::isStackSlot(Reg); - } - - /// Return true if this is a stack slot. - bool isStack() const { return MCRegister::isStackSlot(Reg); } - - /// Compute the frame index from a register value representing a stack slot. - static int stackSlot2Index(Register Reg) { - assert(Reg.isStack() && "Not a stack slot"); - return int(Reg - MCRegister::FirstStackSlot); - } - - /// Convert a non-negative frame index to a stack slot register value. - static Register index2StackSlot(int FI) { - assert(FI >= 0 && "Cannot hold a negative frame index."); - return Register(FI + MCRegister::FirstStackSlot); - } - - /// Return true if the specified register number is in - /// the physical register namespace. - static bool isPhysicalRegister(unsigned Reg) { - return MCRegister::isPhysicalRegister(Reg); - } - - /// Return true if the specified register number is in - /// the virtual register namespace. - static bool isVirtualRegister(unsigned Reg) { - return Reg & MCRegister::VirtualRegFlag && !isStackSlot(Reg); - } - - /// Convert a virtual register number to a 0-based index. - /// The first virtual register in a function will get the index 0. - static unsigned virtReg2Index(Register Reg) { - assert(isVirtualRegister(Reg) && "Not a virtual register"); - return Reg & ~MCRegister::VirtualRegFlag; - } - - /// Convert a 0-based index to a virtual register number. - /// This is the inverse operation of VirtReg2IndexFunctor below. - static Register index2VirtReg(unsigned Index) { - assert(Index < (1u << 31) && "Index too large for virtual register range."); - return Index | MCRegister::VirtualRegFlag; - } - - /// Return true if the specified register number is in the virtual register - /// namespace. - bool isVirtual() const { - return isVirtualRegister(Reg); - } - - /// Return true if the specified register number is in the physical register - /// namespace. - bool isPhysical() const { - return isPhysicalRegister(Reg); - } - - /// Convert a virtual register number to a 0-based index. The first virtual - /// register in a function will get the index 0. - unsigned virtRegIndex() const { - return virtReg2Index(Reg); - } - - constexpr operator unsigned() const { - return Reg; - } - - unsigned id() const { return Reg; } - - operator MCRegister() const { - return MCRegister(Reg); - } - - /// Utility to check-convert this value to a MCRegister. The caller is - /// expected to have already validated that this Register is, indeed, - /// physical. - MCRegister asMCReg() const { - assert(Reg == MCRegister::NoRegister || - MCRegister::isPhysicalRegister(Reg)); - return MCRegister(Reg); - } - - bool isValid() const { return Reg != MCRegister::NoRegister; } - - /// Comparisons between register objects - bool operator==(const Register &Other) const { return Reg == Other.Reg; } - bool operator!=(const Register &Other) const { return Reg != Other.Reg; } - bool operator==(const MCRegister &Other) const { return Reg == Other.id(); } - bool operator!=(const MCRegister &Other) const { return Reg != Other.id(); } - - /// Comparisons against register constants. E.g. - /// * R == AArch64::WZR - /// * R == 0 - /// * R == VirtRegMap::NO_PHYS_REG - bool operator==(unsigned Other) const { return Reg == Other; } - bool operator!=(unsigned Other) const { return Reg != Other; } - bool operator==(int Other) const { return Reg == unsigned(Other); } - bool operator!=(int Other) const { return Reg != unsigned(Other); } - // MSVC requires that we explicitly declare these two as well. - bool operator==(MCPhysReg Other) const { return Reg == unsigned(Other); } - bool operator!=(MCPhysReg Other) const { return Reg != unsigned(Other); } -}; - -// Provide DenseMapInfo for Register -template<> struct DenseMapInfo { - static inline unsigned getEmptyKey() { - return DenseMapInfo::getEmptyKey(); - } - static inline unsigned getTombstoneKey() { - return DenseMapInfo::getTombstoneKey(); - } - static unsigned getHashValue(const Register &Val) { - return DenseMapInfo::getHashValue(Val.id()); - } - static bool isEqual(const Register &LHS, const Register &RHS) { - return DenseMapInfo::isEqual(LHS.id(), RHS.id()); - } -}; - -} - -#endif // LLVM_CODEGEN_REGISTER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterClassInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegisterClassInfo.h deleted file mode 100644 index d82f1db60d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterClassInfo.h +++ /dev/null @@ -1,152 +0,0 @@ -//===- RegisterClassInfo.h - Dynamic Register Class Info --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the RegisterClassInfo class which provides dynamic -// information about target register classes. Callee saved and reserved -// registers depends on calling conventions and other dynamic information, so -// some things cannot be determined statically. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGISTERCLASSINFO_H -#define LLVM_CODEGEN_REGISTERCLASSINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include -#include -#include - -namespace llvm { - -class RegisterClassInfo { - struct RCInfo { - unsigned Tag = 0; - unsigned NumRegs = 0; - bool ProperSubClass = false; - uint8_t MinCost = 0; - uint16_t LastCostChange = 0; - std::unique_ptr Order; - - RCInfo() = default; - - operator ArrayRef() const { - return makeArrayRef(Order.get(), NumRegs); - } - }; - - // Brief cached information for each register class. - std::unique_ptr RegClass; - - // Tag changes whenever cached information needs to be recomputed. An RCInfo - // entry is valid when its tag matches. - unsigned Tag = 0; - - const MachineFunction *MF = nullptr; - const TargetRegisterInfo *TRI = nullptr; - - // Callee saved registers of last MF. Assumed to be valid until the next - // runOnFunction() call. - // Used only to determine if an update was made to CalleeSavedAliases. - const MCPhysReg *CalleeSavedRegs = nullptr; - - // Map register alias to the callee saved Register. - SmallVector CalleeSavedAliases; - - // Reserved registers in the current MF. - BitVector Reserved; - - std::unique_ptr PSetLimits; - - // The register cost values. - ArrayRef RegCosts; - - // Compute all information about RC. - void compute(const TargetRegisterClass *RC) const; - - // Return an up-to-date RCInfo for RC. - const RCInfo &get(const TargetRegisterClass *RC) const { - const RCInfo &RCI = RegClass[RC->getID()]; - if (Tag != RCI.Tag) - compute(RC); - return RCI; - } - -public: - RegisterClassInfo(); - - /// runOnFunction - Prepare to answer questions about MF. This must be called - /// before any other methods are used. - void runOnMachineFunction(const MachineFunction &MF); - - /// getNumAllocatableRegs - Returns the number of actually allocatable - /// registers in RC in the current function. - unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const { - return get(RC).NumRegs; - } - - /// getOrder - Returns the preferred allocation order for RC. The order - /// contains no reserved registers, and registers that alias callee saved - /// registers come last. - ArrayRef getOrder(const TargetRegisterClass *RC) const { - return get(RC); - } - - /// isProperSubClass - Returns true if RC has a legal super-class with more - /// allocatable registers. - /// - /// Register classes like GR32_NOSP are not proper sub-classes because %esp - /// is not allocatable. Similarly, tGPR is not a proper sub-class in Thumb - /// mode because the GPR super-class is not legal. - bool isProperSubClass(const TargetRegisterClass *RC) const { - return get(RC).ProperSubClass; - } - - /// getLastCalleeSavedAlias - Returns the last callee saved register that - /// overlaps PhysReg, or NoRegister if Reg doesn't overlap a - /// CalleeSavedAliases. - MCRegister getLastCalleeSavedAlias(MCRegister PhysReg) const { - if (PhysReg.id() < CalleeSavedAliases.size()) - return CalleeSavedAliases[PhysReg]; - return MCRegister::NoRegister; - } - - /// Get the minimum register cost in RC's allocation order. - /// This is the smallest value in RegCosts[Reg] for all - /// the registers in getOrder(RC). - uint8_t getMinCost(const TargetRegisterClass *RC) const { - return get(RC).MinCost; - } - - /// Get the position of the last cost change in getOrder(RC). - /// - /// All registers in getOrder(RC).slice(getLastCostChange(RC)) will have the - /// same cost according to RegCosts[Reg]. - unsigned getLastCostChange(const TargetRegisterClass *RC) const { - return get(RC).LastCostChange; - } - - /// Get the register unit limit for the given pressure set index. - /// - /// RegisterClassInfo adjusts this limit for reserved registers. - unsigned getRegPressureSetLimit(unsigned Idx) const { - if (!PSetLimits[Idx]) - PSetLimits[Idx] = computePSetLimit(Idx); - return PSetLimits[Idx]; - } - -protected: - unsigned computePSetLimit(unsigned Idx) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGISTERCLASSINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterPressure.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegisterPressure.h deleted file mode 100644 index 32da3e032b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterPressure.h +++ /dev/null @@ -1,574 +0,0 @@ -//===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the RegisterPressure class which can be used to track -// MachineInstr level register pressure. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGISTERPRESSURE_H -#define LLVM_CODEGEN_REGISTERPRESSURE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SparseSet.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/MC/LaneBitmask.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class LiveIntervals; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class RegisterClassInfo; - -struct RegisterMaskPair { - Register RegUnit; ///< Virtual register or register unit. - LaneBitmask LaneMask; - - RegisterMaskPair(Register RegUnit, LaneBitmask LaneMask) - : RegUnit(RegUnit), LaneMask(LaneMask) {} -}; - -/// Base class for register pressure results. -struct RegisterPressure { - /// Map of max reg pressure indexed by pressure set ID, not class ID. - std::vector MaxSetPressure; - - /// List of live in virtual registers or physical register units. - SmallVector LiveInRegs; - SmallVector LiveOutRegs; - - void dump(const TargetRegisterInfo *TRI) const; -}; - -/// RegisterPressure computed within a region of instructions delimited by -/// TopIdx and BottomIdx. During pressure computation, the maximum pressure per -/// register pressure set is increased. Once pressure within a region is fully -/// computed, the live-in and live-out sets are recorded. -/// -/// This is preferable to RegionPressure when LiveIntervals are available, -/// because delimiting regions by SlotIndex is more robust and convenient than -/// holding block iterators. The block contents can change without invalidating -/// the pressure result. -struct IntervalPressure : RegisterPressure { - /// Record the boundary of the region being tracked. - SlotIndex TopIdx; - SlotIndex BottomIdx; - - void reset(); - - void openTop(SlotIndex NextTop); - - void openBottom(SlotIndex PrevBottom); -}; - -/// RegisterPressure computed within a region of instructions delimited by -/// TopPos and BottomPos. This is a less precise version of IntervalPressure for -/// use when LiveIntervals are unavailable. -struct RegionPressure : RegisterPressure { - /// Record the boundary of the region being tracked. - MachineBasicBlock::const_iterator TopPos; - MachineBasicBlock::const_iterator BottomPos; - - void reset(); - - void openTop(MachineBasicBlock::const_iterator PrevTop); - - void openBottom(MachineBasicBlock::const_iterator PrevBottom); -}; - -/// Capture a change in pressure for a single pressure set. UnitInc may be -/// expressed in terms of upward or downward pressure depending on the client -/// and will be dynamically adjusted for current liveness. -/// -/// Pressure increments are tiny, typically 1-2 units, and this is only for -/// heuristics, so we don't check UnitInc overflow. Instead, we may have a -/// higher level assert that pressure is consistent within a region. We also -/// effectively ignore dead defs which don't affect heuristics much. -class PressureChange { - uint16_t PSetID = 0; // ID+1. 0=Invalid. - int16_t UnitInc = 0; - -public: - PressureChange() = default; - PressureChange(unsigned id): PSetID(id + 1) { - assert(id < std::numeric_limits::max() && "PSetID overflow."); - } - - bool isValid() const { return PSetID > 0; } - - unsigned getPSet() const { - assert(isValid() && "invalid PressureChange"); - return PSetID - 1; - } - - // If PSetID is invalid, return UINT16_MAX to give it lowest priority. - unsigned getPSetOrMax() const { - return (PSetID - 1) & std::numeric_limits::max(); - } - - int getUnitInc() const { return UnitInc; } - - void setUnitInc(int Inc) { UnitInc = Inc; } - - bool operator==(const PressureChange &RHS) const { - return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; - } - - void dump() const; -}; - -/// List of PressureChanges in order of increasing, unique PSetID. -/// -/// Use a small fixed number, because we can fit more PressureChanges in an -/// empty SmallVector than ever need to be tracked per register class. If more -/// PSets are affected, then we only track the most constrained. -class PressureDiff { - // The initial design was for MaxPSets=4, but that requires PSet partitions, - // which are not yet implemented. (PSet partitions are equivalent PSets given - // the register classes actually in use within the scheduling region.) - enum { MaxPSets = 16 }; - - PressureChange PressureChanges[MaxPSets]; - - using iterator = PressureChange *; - - iterator nonconst_begin() { return &PressureChanges[0]; } - iterator nonconst_end() { return &PressureChanges[MaxPSets]; } - -public: - using const_iterator = const PressureChange *; - - const_iterator begin() const { return &PressureChanges[0]; } - const_iterator end() const { return &PressureChanges[MaxPSets]; } - - void addPressureChange(Register RegUnit, bool IsDec, - const MachineRegisterInfo *MRI); - - void dump(const TargetRegisterInfo &TRI) const; -}; - -/// List of registers defined and used by a machine instruction. -class RegisterOperands { -public: - /// List of virtual registers and register units read by the instruction. - SmallVector Uses; - /// List of virtual registers and register units defined by the - /// instruction which are not dead. - SmallVector Defs; - /// List of virtual registers and register units defined by the - /// instruction but dead. - SmallVector DeadDefs; - - /// Analyze the given instruction \p MI and fill in the Uses, Defs and - /// DeadDefs list based on the MachineOperand flags. - void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, - const MachineRegisterInfo &MRI, bool TrackLaneMasks, - bool IgnoreDead); - - /// Use liveness information to find dead defs not marked with a dead flag - /// and move them to the DeadDefs vector. - void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS); - - /// Use liveness information to find out which uses/defs are partially - /// undefined/dead and adjust the RegisterMaskPairs accordingly. - /// If \p AddFlagsMI is given then missing read-undef and dead flags will be - /// added to the instruction. - void adjustLaneLiveness(const LiveIntervals &LIS, - const MachineRegisterInfo &MRI, SlotIndex Pos, - MachineInstr *AddFlagsMI = nullptr); -}; - -/// Array of PressureDiffs. -class PressureDiffs { - PressureDiff *PDiffArray = nullptr; - unsigned Size = 0; - unsigned Max = 0; - -public: - PressureDiffs() = default; - ~PressureDiffs() { free(PDiffArray); } - - void clear() { Size = 0; } - - void init(unsigned N); - - PressureDiff &operator[](unsigned Idx) { - assert(Idx < Size && "PressureDiff index out of bounds"); - return PDiffArray[Idx]; - } - const PressureDiff &operator[](unsigned Idx) const { - return const_cast(this)->operator[](Idx); - } - - /// Record pressure difference induced by the given operand list to - /// node with index \p Idx. - void addInstruction(unsigned Idx, const RegisterOperands &RegOpers, - const MachineRegisterInfo &MRI); -}; - -/// Store the effects of a change in pressure on things that MI scheduler cares -/// about. -/// -/// Excess records the value of the largest difference in register units beyond -/// the target's pressure limits across the affected pressure sets, where -/// largest is defined as the absolute value of the difference. Negative -/// ExcessUnits indicates a reduction in pressure that had already exceeded the -/// target's limits. -/// -/// CriticalMax records the largest increase in the tracker's max pressure that -/// exceeds the critical limit for some pressure set determined by the client. -/// -/// CurrentMax records the largest increase in the tracker's max pressure that -/// exceeds the current limit for some pressure set determined by the client. -struct RegPressureDelta { - PressureChange Excess; - PressureChange CriticalMax; - PressureChange CurrentMax; - - RegPressureDelta() = default; - - bool operator==(const RegPressureDelta &RHS) const { - return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax - && CurrentMax == RHS.CurrentMax; - } - bool operator!=(const RegPressureDelta &RHS) const { - return !operator==(RHS); - } - void dump() const; -}; - -/// A set of live virtual registers and physical register units. -/// -/// This is a wrapper around a SparseSet which deals with mapping register unit -/// and virtual register indexes to an index usable by the sparse set. -class LiveRegSet { -private: - struct IndexMaskPair { - unsigned Index; - LaneBitmask LaneMask; - - IndexMaskPair(unsigned Index, LaneBitmask LaneMask) - : Index(Index), LaneMask(LaneMask) {} - - unsigned getSparseSetIndex() const { - return Index; - } - }; - - using RegSet = SparseSet; - RegSet Regs; - unsigned NumRegUnits; - - unsigned getSparseIndexFromReg(Register Reg) const { - if (Reg.isVirtual()) - return Register::virtReg2Index(Reg) + NumRegUnits; - assert(Reg < NumRegUnits); - return Reg; - } - - Register getRegFromSparseIndex(unsigned SparseIndex) const { - if (SparseIndex >= NumRegUnits) - return Register::index2VirtReg(SparseIndex - NumRegUnits); - return Register(SparseIndex); - } - -public: - void clear(); - void init(const MachineRegisterInfo &MRI); - - LaneBitmask contains(Register Reg) const { - unsigned SparseIndex = getSparseIndexFromReg(Reg); - RegSet::const_iterator I = Regs.find(SparseIndex); - if (I == Regs.end()) - return LaneBitmask::getNone(); - return I->LaneMask; - } - - /// Mark the \p Pair.LaneMask lanes of \p Pair.Reg as live. - /// Returns the previously live lanes of \p Pair.Reg. - LaneBitmask insert(RegisterMaskPair Pair) { - unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit); - auto InsertRes = Regs.insert(IndexMaskPair(SparseIndex, Pair.LaneMask)); - if (!InsertRes.second) { - LaneBitmask PrevMask = InsertRes.first->LaneMask; - InsertRes.first->LaneMask |= Pair.LaneMask; - return PrevMask; - } - return LaneBitmask::getNone(); - } - - /// Clears the \p Pair.LaneMask lanes of \p Pair.Reg (mark them as dead). - /// Returns the previously live lanes of \p Pair.Reg. - LaneBitmask erase(RegisterMaskPair Pair) { - unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit); - RegSet::iterator I = Regs.find(SparseIndex); - if (I == Regs.end()) - return LaneBitmask::getNone(); - LaneBitmask PrevMask = I->LaneMask; - I->LaneMask &= ~Pair.LaneMask; - return PrevMask; - } - - size_t size() const { - return Regs.size(); - } - - template - void appendTo(ContainerT &To) const { - for (const IndexMaskPair &P : Regs) { - Register Reg = getRegFromSparseIndex(P.Index); - if (P.LaneMask.any()) - To.push_back(RegisterMaskPair(Reg, P.LaneMask)); - } - } -}; - -/// Track the current register pressure at some position in the instruction -/// stream, and remember the high water mark within the region traversed. This -/// does not automatically consider live-through ranges. The client may -/// independently adjust for global liveness. -/// -/// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can -/// be tracked across a larger region by storing a RegisterPressure result at -/// each block boundary and explicitly adjusting pressure to account for block -/// live-in and live-out register sets. -/// -/// RegPressureTracker holds a reference to a RegisterPressure result that it -/// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos -/// is invalid until it reaches the end of the block or closeRegion() is -/// explicitly called. Similarly, P.TopIdx is invalid during upward -/// tracking. Changing direction has the side effect of closing region, and -/// traversing past TopIdx or BottomIdx reopens it. -class RegPressureTracker { - const MachineFunction *MF = nullptr; - const TargetRegisterInfo *TRI = nullptr; - const RegisterClassInfo *RCI = nullptr; - const MachineRegisterInfo *MRI; - const LiveIntervals *LIS = nullptr; - - /// We currently only allow pressure tracking within a block. - const MachineBasicBlock *MBB = nullptr; - - /// Track the max pressure within the region traversed so far. - RegisterPressure &P; - - /// Run in two modes dependending on whether constructed with IntervalPressure - /// or RegisterPressure. If requireIntervals is false, LIS are ignored. - bool RequireIntervals; - - /// True if UntiedDefs will be populated. - bool TrackUntiedDefs = false; - - /// True if lanemasks should be tracked. - bool TrackLaneMasks = false; - - /// Register pressure corresponds to liveness before this instruction - /// iterator. It may point to the end of the block or a DebugValue rather than - /// an instruction. - MachineBasicBlock::const_iterator CurrPos; - - /// Pressure map indexed by pressure set ID, not class ID. - std::vector CurrSetPressure; - - /// Set of live registers. - LiveRegSet LiveRegs; - - /// Set of vreg defs that start a live range. - SparseSet UntiedDefs; - /// Live-through pressure. - std::vector LiveThruPressure; - -public: - RegPressureTracker(IntervalPressure &rp) : P(rp), RequireIntervals(true) {} - RegPressureTracker(RegionPressure &rp) : P(rp), RequireIntervals(false) {} - - void reset(); - - void init(const MachineFunction *mf, const RegisterClassInfo *rci, - const LiveIntervals *lis, const MachineBasicBlock *mbb, - MachineBasicBlock::const_iterator pos, - bool TrackLaneMasks, bool TrackUntiedDefs); - - /// Force liveness of virtual registers or physical register - /// units. Particularly useful to initialize the livein/out state of the - /// tracker before the first call to advance/recede. - void addLiveRegs(ArrayRef Regs); - - /// Get the MI position corresponding to this register pressure. - MachineBasicBlock::const_iterator getPos() const { return CurrPos; } - - // Reset the MI position corresponding to the register pressure. This allows - // schedulers to move instructions above the RegPressureTracker's - // CurrPos. Since the pressure is computed before CurrPos, the iterator - // position changes while pressure does not. - void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } - - /// Recede across the previous instruction. - void recede(SmallVectorImpl *LiveUses = nullptr); - - /// Recede across the previous instruction. - /// This "low-level" variant assumes that recedeSkipDebugValues() was - /// called previously and takes precomputed RegisterOperands for the - /// instruction. - void recede(const RegisterOperands &RegOpers, - SmallVectorImpl *LiveUses = nullptr); - - /// Recede until we find an instruction which is not a DebugValue. - void recedeSkipDebugValues(); - - /// Advance across the current instruction. - void advance(); - - /// Advance across the current instruction. - /// This is a "low-level" variant of advance() which takes precomputed - /// RegisterOperands of the instruction. - void advance(const RegisterOperands &RegOpers); - - /// Finalize the region boundaries and record live ins and live outs. - void closeRegion(); - - /// Initialize the LiveThru pressure set based on the untied defs found in - /// RPTracker. - void initLiveThru(const RegPressureTracker &RPTracker); - - /// Copy an existing live thru pressure result. - void initLiveThru(ArrayRef PressureSet) { - LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); - } - - ArrayRef getLiveThru() const { return LiveThruPressure; } - - /// Get the resulting register pressure over the traversed region. - /// This result is complete if closeRegion() was explicitly invoked. - RegisterPressure &getPressure() { return P; } - const RegisterPressure &getPressure() const { return P; } - - /// Get the register set pressure at the current position, which may be less - /// than the pressure across the traversed region. - const std::vector &getRegSetPressureAtPos() const { - return CurrSetPressure; - } - - bool isTopClosed() const; - bool isBottomClosed() const; - - void closeTop(); - void closeBottom(); - - /// Consider the pressure increase caused by traversing this instruction - /// bottom-up. Find the pressure set with the most change beyond its pressure - /// limit based on the tracker's current pressure, and record the number of - /// excess register units of that pressure set introduced by this instruction. - void getMaxUpwardPressureDelta(const MachineInstr *MI, - PressureDiff *PDiff, - RegPressureDelta &Delta, - ArrayRef CriticalPSets, - ArrayRef MaxPressureLimit); - - void getUpwardPressureDelta(const MachineInstr *MI, - /*const*/ PressureDiff &PDiff, - RegPressureDelta &Delta, - ArrayRef CriticalPSets, - ArrayRef MaxPressureLimit) const; - - /// Consider the pressure increase caused by traversing this instruction - /// top-down. Find the pressure set with the most change beyond its pressure - /// limit based on the tracker's current pressure, and record the number of - /// excess register units of that pressure set introduced by this instruction. - void getMaxDownwardPressureDelta(const MachineInstr *MI, - RegPressureDelta &Delta, - ArrayRef CriticalPSets, - ArrayRef MaxPressureLimit); - - /// Find the pressure set with the most change beyond its pressure limit after - /// traversing this instruction either upward or downward depending on the - /// closed end of the current region. - void getMaxPressureDelta(const MachineInstr *MI, - RegPressureDelta &Delta, - ArrayRef CriticalPSets, - ArrayRef MaxPressureLimit) { - if (isTopClosed()) - return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, - MaxPressureLimit); - - assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getMaxUpwardPressureDelta(MI, nullptr, Delta, CriticalPSets, - MaxPressureLimit); - } - - /// Get the pressure of each PSet after traversing this instruction bottom-up. - void getUpwardPressure(const MachineInstr *MI, - std::vector &PressureResult, - std::vector &MaxPressureResult); - - /// Get the pressure of each PSet after traversing this instruction top-down. - void getDownwardPressure(const MachineInstr *MI, - std::vector &PressureResult, - std::vector &MaxPressureResult); - - void getPressureAfterInst(const MachineInstr *MI, - std::vector &PressureResult, - std::vector &MaxPressureResult) { - if (isTopClosed()) - return getUpwardPressure(MI, PressureResult, MaxPressureResult); - - assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getDownwardPressure(MI, PressureResult, MaxPressureResult); - } - - bool hasUntiedDef(Register VirtReg) const { - return UntiedDefs.count(VirtReg); - } - - void dump() const; - -protected: - /// Add Reg to the live out set and increase max pressure. - void discoverLiveOut(RegisterMaskPair Pair); - /// Add Reg to the live in set and increase max pressure. - void discoverLiveIn(RegisterMaskPair Pair); - - /// Get the SlotIndex for the first nondebug instruction including or - /// after the current position. - SlotIndex getCurrSlot() const; - - void increaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, - LaneBitmask NewMask); - void decreaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, - LaneBitmask NewMask); - - void bumpDeadDefs(ArrayRef DeadDefs); - - void bumpUpwardPressure(const MachineInstr *MI); - void bumpDownwardPressure(const MachineInstr *MI); - - void discoverLiveInOrOut(RegisterMaskPair Pair, - SmallVectorImpl &LiveInOrOut); - - LaneBitmask getLastUsedLanes(Register RegUnit, SlotIndex Pos) const; - LaneBitmask getLiveLanesAt(Register RegUnit, SlotIndex Pos) const; - LaneBitmask getLiveThroughAt(Register RegUnit, SlotIndex Pos) const; -}; - -void dumpRegSetPressure(ArrayRef SetPressure, - const TargetRegisterInfo *TRI); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGISTERPRESSURE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterScavenging.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegisterScavenging.h deleted file mode 100644 index 218e05f6eb..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterScavenging.h +++ /dev/null @@ -1,227 +0,0 @@ -//===- RegisterScavenging.h - Machine register scavenging -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file declares the machine register scavenger class. It can provide -/// information such as unused register at any point in a machine basic block. -/// It also provides a mechanism to make registers available by evicting them -/// to spill slots. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGISTERSCAVENGING_H -#define LLVM_CODEGEN_REGISTERSCAVENGING_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LiveRegUnits.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/MC/LaneBitmask.h" - -namespace llvm { - -class MachineInstr; -class TargetInstrInfo; -class TargetRegisterClass; -class TargetRegisterInfo; - -class RegScavenger { - const TargetRegisterInfo *TRI; - const TargetInstrInfo *TII; - MachineRegisterInfo* MRI; - MachineBasicBlock *MBB = nullptr; - MachineBasicBlock::iterator MBBI; - unsigned NumRegUnits = 0; - - /// True if RegScavenger is currently tracking the liveness of registers. - bool Tracking = false; - - /// Information on scavenged registers (held in a spill slot). - struct ScavengedInfo { - ScavengedInfo(int FI = -1) : FrameIndex(FI) {} - - /// A spill slot used for scavenging a register post register allocation. - int FrameIndex; - - /// If non-zero, the specific register is currently being - /// scavenged. That is, it is spilled to this scavenging stack slot. - Register Reg; - - /// The instruction that restores the scavenged register from stack. - const MachineInstr *Restore = nullptr; - }; - - /// A vector of information on scavenged registers. - SmallVector Scavenged; - - LiveRegUnits LiveUnits; - - // These BitVectors are only used internally to forward(). They are members - // to avoid frequent reallocations. - BitVector KillRegUnits, DefRegUnits; - BitVector TmpRegUnits; - -public: - RegScavenger() = default; - - /// Start tracking liveness from the begin of basic block \p MBB. - void enterBasicBlock(MachineBasicBlock &MBB); - - /// Start tracking liveness from the end of basic block \p MBB. - /// Use backward() to move towards the beginning of the block. This is - /// preferred to enterBasicBlock() and forward() because it does not depend - /// on the presence of kill flags. - void enterBasicBlockEnd(MachineBasicBlock &MBB); - - /// Move the internal MBB iterator and update register states. - void forward(); - - /// Move the internal MBB iterator and update register states until - /// it has processed the specific iterator. - void forward(MachineBasicBlock::iterator I) { - if (!Tracking && MBB->begin() != I) forward(); - while (MBBI != I) forward(); - } - - /// Update internal register state and move MBB iterator backwards. - /// Contrary to unprocess() this method gives precise results even in the - /// absence of kill flags. - void backward(); - - /// Call backward() as long as the internal iterator does not point to \p I. - void backward(MachineBasicBlock::iterator I) { - while (MBBI != I) - backward(); - } - - /// Move the internal MBB iterator but do not update register states. - void skipTo(MachineBasicBlock::iterator I) { - if (I == MachineBasicBlock::iterator(nullptr)) - Tracking = false; - MBBI = I; - } - - MachineBasicBlock::iterator getCurrentPosition() const { return MBBI; } - - /// Return if a specific register is currently used. - bool isRegUsed(Register Reg, bool includeReserved = true) const; - - /// Return all available registers in the register class in Mask. - BitVector getRegsAvailable(const TargetRegisterClass *RC); - - /// Find an unused register of the specified register class. - /// Return 0 if none is found. - Register FindUnusedReg(const TargetRegisterClass *RC) const; - - /// Add a scavenging frame index. - void addScavengingFrameIndex(int FI) { - Scavenged.push_back(ScavengedInfo(FI)); - } - - /// Query whether a frame index is a scavenging frame index. - bool isScavengingFrameIndex(int FI) const { - for (SmallVectorImpl::const_iterator I = Scavenged.begin(), - IE = Scavenged.end(); I != IE; ++I) - if (I->FrameIndex == FI) - return true; - - return false; - } - - /// Get an array of scavenging frame indices. - void getScavengingFrameIndices(SmallVectorImpl &A) const { - for (SmallVectorImpl::const_iterator I = Scavenged.begin(), - IE = Scavenged.end(); I != IE; ++I) - if (I->FrameIndex >= 0) - A.push_back(I->FrameIndex); - } - - /// Make a register of the specific register class - /// available and do the appropriate bookkeeping. SPAdj is the stack - /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). - /// Returns the scavenged register. - /// This is deprecated as it depends on the quality of the kill flags being - /// present; Use scavengeRegisterBackwards() instead! - /// - /// If \p AllowSpill is false, fail if a spill is required to make the - /// register available, and return NoRegister. - Register scavengeRegister(const TargetRegisterClass *RC, - MachineBasicBlock::iterator I, int SPAdj, - bool AllowSpill = true); - Register scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj, - bool AllowSpill = true) { - return scavengeRegister(RegClass, MBBI, SPAdj, AllowSpill); - } - - /// Make a register of the specific register class available from the current - /// position backwards to the place before \p To. If \p RestoreAfter is true - /// this includes the instruction following the current position. - /// SPAdj is the stack adjustment due to call frame, it's passed along to - /// eliminateFrameIndex(). - /// Returns the scavenged register. - /// - /// If \p AllowSpill is false, fail if a spill is required to make the - /// register available, and return NoRegister. - Register scavengeRegisterBackwards(const TargetRegisterClass &RC, - MachineBasicBlock::iterator To, - bool RestoreAfter, int SPAdj, - bool AllowSpill = true); - - /// Tell the scavenger a register is used. - void setRegUsed(Register Reg, LaneBitmask LaneMask = LaneBitmask::getAll()); - -private: - /// Returns true if a register is reserved. It is never "unused". - bool isReserved(Register Reg) const { return MRI->isReserved(Reg); } - - /// setUsed / setUnused - Mark the state of one or a number of register units. - /// - void setUsed(const BitVector &RegUnits) { - LiveUnits.addUnits(RegUnits); - } - void setUnused(const BitVector &RegUnits) { - LiveUnits.removeUnits(RegUnits); - } - - /// Processes the current instruction and fill the KillRegUnits and - /// DefRegUnits bit vectors. - void determineKillsAndDefs(); - - /// Add all Reg Units that Reg contains to BV. - void addRegUnits(BitVector &BV, MCRegister Reg); - - /// Remove all Reg Units that \p Reg contains from \p BV. - void removeRegUnits(BitVector &BV, MCRegister Reg); - - /// Return the candidate register that is unused for the longest after - /// StartMI. UseMI is set to the instruction where the search stopped. - /// - /// No more than InstrLimit instructions are inspected. - Register findSurvivorReg(MachineBasicBlock::iterator StartMI, - BitVector &Candidates, - unsigned InstrLimit, - MachineBasicBlock::iterator &UseMI); - - /// Initialize RegisterScavenger. - void init(MachineBasicBlock &MBB); - - /// Spill a register after position \p After and reload it before position - /// \p UseMI. - ScavengedInfo &spill(Register Reg, const TargetRegisterClass &RC, int SPAdj, - MachineBasicBlock::iterator Before, - MachineBasicBlock::iterator &UseMI); -}; - -/// Replaces all frame index virtual registers with physical registers. Uses the -/// register scavenger to find an appropriate register to use. -void scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGISTERSCAVENGING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterUsageInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/RegisterUsageInfo.h deleted file mode 100644 index bf347c0753..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RegisterUsageInfo.h +++ /dev/null @@ -1,71 +0,0 @@ -//==- RegisterUsageInfo.h - Register Usage Informartion Storage --*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This pass is required to take advantage of the interprocedural register -/// allocation infrastructure. -/// -/// This pass is simple immutable pass which keeps RegMasks (calculated based on -/// actual register allocation) for functions in a module and provides simple -/// API to query this information. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_REGISTERUSAGEINFO_H -#define LLVM_CODEGEN_REGISTERUSAGEINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/Instructions.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" -#include -#include - -namespace llvm { - -class Function; -class LLVMTargetMachine; - -class PhysicalRegisterUsageInfo : public ImmutablePass { -public: - static char ID; - - PhysicalRegisterUsageInfo() : ImmutablePass(ID) { - PassRegistry &Registry = *PassRegistry::getPassRegistry(); - initializePhysicalRegisterUsageInfoPass(Registry); - } - - /// Set TargetMachine which is used to print analysis. - void setTargetMachine(const LLVMTargetMachine &TM); - - bool doInitialization(Module &M) override; - - bool doFinalization(Module &M) override; - - /// To store RegMask for given Function *. - void storeUpdateRegUsageInfo(const Function &FP, - ArrayRef RegMask); - - /// To query stored RegMask for given Function *, it will returns ane empty - /// array if function is not known. - ArrayRef getRegUsageInfo(const Function &FP); - - void print(raw_ostream &OS, const Module *M = nullptr) const override; - -private: - /// A Dense map from Function * to RegMask. - /// In RegMask 0 means register used (clobbered) by function. - /// and 1 means content of register will be preserved around function call. - DenseMap> RegMasks; - - const LLVMTargetMachine *TM; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_REGISTERUSAGEINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ReplaceWithVeclib.h b/suite/synctools/tablegen/include/llvm/CodeGen/ReplaceWithVeclib.h deleted file mode 100644 index 461b57f2af..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ReplaceWithVeclib.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- ReplaceWithVeclib.h - Replace vector intrinsics with veclib calls -===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Replaces calls to LLVM vector intrinsics (i.e., calls to LLVM intrinsics -// with vector operands) with matching calls to functions from a vector -// library (e.g., libmvec, SVML) according to TargetLibraryInfo. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_REPLACEWITHVECLIB_H -#define LLVM_CODEGEN_REPLACEWITHVECLIB_H - -#include "llvm/IR/PassManager.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" - -namespace llvm { -struct ReplaceWithVeclib : public PassInfoMixin { - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; - -// Legacy pass -struct ReplaceWithVeclibLegacy : public FunctionPass { - static char ID; - ReplaceWithVeclibLegacy() : FunctionPass(ID) { - initializeReplaceWithVeclibLegacyPass(*PassRegistry::getPassRegistry()); - } - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; -}; - -} // End namespace llvm -#endif // LLVM_CODEGEN_REPLACEWITHVECLIB_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ResourcePriorityQueue.h b/suite/synctools/tablegen/include/llvm/CodeGen/ResourcePriorityQueue.h deleted file mode 100644 index bd63dd8756..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ResourcePriorityQueue.h +++ /dev/null @@ -1,134 +0,0 @@ -//===----- ResourcePriorityQueue.h - A DFA-oriented priority queue -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the ResourcePriorityQueue class, which is a -// SchedulingPriorityQueue that schedules using DFA state to -// reduce the length of the critical path through the basic block -// on VLIW platforms. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H -#define LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H - -#include "llvm/CodeGen/ScheduleDAG.h" - -namespace llvm { - class DFAPacketizer; - class InstrItineraryData; - class ResourcePriorityQueue; - class SelectionDAGISel; - class TargetInstrInfo; - class TargetRegisterInfo; - - /// Sorting functions for the Available queue. - struct resource_sort { - ResourcePriorityQueue *PQ; - explicit resource_sort(ResourcePriorityQueue *pq) : PQ(pq) {} - - bool operator()(const SUnit* LHS, const SUnit* RHS) const; - }; - - class ResourcePriorityQueue : public SchedulingPriorityQueue { - /// SUnits - The SUnits for the current graph. - std::vector *SUnits; - - /// NumNodesSolelyBlocking - This vector contains, for every node in the - /// Queue, the number of nodes that the node is the sole unscheduled - /// predecessor for. This is used as a tie-breaker heuristic for better - /// mobility. - std::vector NumNodesSolelyBlocking; - - /// Queue - The queue. - std::vector Queue; - - /// RegPressure - Tracking current reg pressure per register class. - /// - std::vector RegPressure; - - /// RegLimit - Tracking the number of allocatable registers per register - /// class. - std::vector RegLimit; - - resource_sort Picker; - const TargetRegisterInfo *TRI; - const TargetLowering *TLI; - const TargetInstrInfo *TII; - const InstrItineraryData* InstrItins; - /// ResourcesModel - Represents VLIW state. - /// Not limited to VLIW targets per say, but assumes - /// definition of DFA by a target. - std::unique_ptr ResourcesModel; - - /// Resource model - packet/bundle model. Purely - /// internal at the time. - std::vector Packet; - - /// Heuristics for estimating register pressure. - unsigned ParallelLiveRanges; - int HorizontalVerticalBalance; - - public: - ResourcePriorityQueue(SelectionDAGISel *IS); - - bool isBottomUp() const override { return false; } - - void initNodes(std::vector &sunits) override; - - void addNode(const SUnit *SU) override { - NumNodesSolelyBlocking.resize(SUnits->size(), 0); - } - - void updateNode(const SUnit *SU) override {} - - void releaseState() override { - SUnits = nullptr; - } - - unsigned getLatency(unsigned NodeNum) const { - assert(NodeNum < (*SUnits).size()); - return (*SUnits)[NodeNum].getHeight(); - } - - unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { - assert(NodeNum < NumNodesSolelyBlocking.size()); - return NumNodesSolelyBlocking[NodeNum]; - } - - /// Single cost function reflecting benefit of scheduling SU - /// in the current cycle. - int SUSchedulingCost (SUnit *SU); - - /// InitNumRegDefsLeft - Determine the # of regs defined by this node. - /// - void initNumRegDefsLeft(SUnit *SU); - int regPressureDelta(SUnit *SU, bool RawPressure = false); - int rawRegPressureDelta (SUnit *SU, unsigned RCId); - - bool empty() const override { return Queue.empty(); } - - void push(SUnit *U) override; - - SUnit *pop() override; - - void remove(SUnit *SU) override; - - /// scheduledNode - Main resource tracking point. - void scheduledNode(SUnit *SU) override; - bool isResourceAvailable(SUnit *SU); - void reserveResources(SUnit *SU); - -private: - void adjustPriorityOfUnscheduledPreds(SUnit *SU); - SUnit *getSingleUnscheduledPred(SUnit *SU); - unsigned numberRCValPredInSU (SUnit *SU, unsigned RCId); - unsigned numberRCValSuccInSU (SUnit *SU, unsigned RCId); - }; -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/RuntimeLibcalls.h b/suite/synctools/tablegen/include/llvm/CodeGen/RuntimeLibcalls.h deleted file mode 100644 index d8c631060b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/RuntimeLibcalls.h +++ /dev/null @@ -1,99 +0,0 @@ -//===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the enum representing the list of runtime library calls -// the backend may emit during code generation, and also some helper functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H -#define LLVM_CODEGEN_RUNTIMELIBCALLS_H - -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/AtomicOrdering.h" - -namespace llvm { -namespace RTLIB { - /// RTLIB::Libcall enum - This enum defines all of the runtime library calls - /// the backend can emit. The various long double types cannot be merged, - /// because 80-bit library functions use "xf" and 128-bit use "tf". - /// - /// When adding PPCF128 functions here, note that their names generally need - /// to be overridden for Darwin with the xxx$LDBL128 form. See - /// PPCISelLowering.cpp. - /// - enum Libcall { -#define HANDLE_LIBCALL(code, name) code, - #include "llvm/IR/RuntimeLibcalls.def" -#undef HANDLE_LIBCALL - }; - - /// GetFPLibCall - Helper to return the right libcall for the given floating - /// point type, or UNKNOWN_LIBCALL if there is none. - Libcall getFPLibCall(EVT VT, - Libcall Call_F32, - Libcall Call_F64, - Libcall Call_F80, - Libcall Call_F128, - Libcall Call_PPCF128); - - /// getFPEXT - Return the FPEXT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPEXT(EVT OpVT, EVT RetVT); - - /// getFPROUND - Return the FPROUND_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPROUND(EVT OpVT, EVT RetVT); - - /// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOSINT(EVT OpVT, EVT RetVT); - - /// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOUINT(EVT OpVT, EVT RetVT); - - /// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getSINTTOFP(EVT OpVT, EVT RetVT); - - /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getUINTTOFP(EVT OpVT, EVT RetVT); - - /// getPOWI - Return the POWI_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getPOWI(EVT RetVT); - - /// Return the SYNC_FETCH_AND_* value for the given opcode and type, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getSYNC(unsigned Opc, MVT VT); - - /// Return the outline atomics value for the given opcode, atomic ordering - /// and type, or UNKNOWN_LIBCALL if there is none. - Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT); - - /// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - - /// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - - /// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - -} -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SDNodeProperties.td b/suite/synctools/tablegen/include/llvm/CodeGen/SDNodeProperties.td deleted file mode 100644 index 3cb304f47f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SDNodeProperties.td +++ /dev/null @@ -1,33 +0,0 @@ -//===- SDNodeProperties.td - Common code for DAG isels -----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -class SDNodeProperty; - -// Selection DAG Pattern Operations -class SDPatternOperator { - list Properties = []; -} - -//===----------------------------------------------------------------------===// -// Selection DAG Node Properties. -// -// Note: These are hard coded into tblgen. -// -def SDNPCommutative : SDNodeProperty; // X op Y == Y op X -def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z) -def SDNPHasChain : SDNodeProperty; // R/W chain operand and result -def SDNPOutGlue : SDNodeProperty; // Write a flag result -def SDNPInGlue : SDNodeProperty; // Read a flag operand -def SDNPOptInGlue : SDNodeProperty; // Optionally read a flag operand -def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'. -def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'. -def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'. -def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand -def SDNPVariadic : SDNodeProperty; // Node has variable arguments. -def SDNPWantRoot : SDNodeProperty; // ComplexPattern gets the root of match -def SDNPWantParent : SDNodeProperty; // ComplexPattern gets the parent diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAG.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAG.h deleted file mode 100644 index c1838196e3..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAG.h +++ /dev/null @@ -1,787 +0,0 @@ -//===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Implements the ScheduleDAG class, which is used as the common base -/// class for instruction schedulers. This encapsulates the scheduling DAG, -/// which is shared between SelectionDAG and MachineInstr scheduling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULEDAG_H -#define LLVM_CODEGEN_SCHEDULEDAG_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include - -namespace llvm { - -template class GraphWriter; -class LLVMTargetMachine; -class MachineFunction; -class MachineRegisterInfo; -class MCInstrDesc; -struct MCSchedClassDesc; -class SDNode; -class SUnit; -class ScheduleDAG; -class TargetInstrInfo; -class TargetRegisterClass; -class TargetRegisterInfo; - - /// Scheduling dependency. This represents one direction of an edge in the - /// scheduling DAG. - class SDep { - public: - /// These are the different kinds of scheduling dependencies. - enum Kind { - Data, ///< Regular data dependence (aka true-dependence). - Anti, ///< A register anti-dependence (aka WAR). - Output, ///< A register output-dependence (aka WAW). - Order ///< Any other ordering dependency. - }; - - // Strong dependencies must be respected by the scheduler. Artificial - // dependencies may be removed only if they are redundant with another - // strong dependence. - // - // Weak dependencies may be violated by the scheduling strategy, but only if - // the strategy can prove it is correct to do so. - // - // Strong OrderKinds must occur before "Weak". - // Weak OrderKinds must occur after "Weak". - enum OrderKind { - Barrier, ///< An unknown scheduling barrier. - MayAliasMem, ///< Nonvolatile load/Store instructions that may alias. - MustAliasMem, ///< Nonvolatile load/Store instructions that must alias. - Artificial, ///< Arbitrary strong DAG edge (no real dependence). - Weak, ///< Arbitrary weak DAG edge. - Cluster ///< Weak DAG edge linking a chain of clustered instrs. - }; - - private: - /// A pointer to the depending/depended-on SUnit, and an enum - /// indicating the kind of the dependency. - PointerIntPair Dep; - - /// A union discriminated by the dependence kind. - union { - /// For Data, Anti, and Output dependencies, the associated register. For - /// Data dependencies that don't currently have a register/ assigned, this - /// is set to zero. - unsigned Reg; - - /// Additional information about Order dependencies. - unsigned OrdKind; // enum OrderKind - } Contents; - - /// The time associated with this edge. Often this is just the value of the - /// Latency field of the predecessor, however advanced models may provide - /// additional information about specific edges. - unsigned Latency; - - public: - /// Constructs a null SDep. This is only for use by container classes which - /// require default constructors. SUnits may not/ have null SDep edges. - SDep() : Dep(nullptr, Data) {} - - /// Constructs an SDep with the specified values. - SDep(SUnit *S, Kind kind, unsigned Reg) - : Dep(S, kind), Contents() { - switch (kind) { - default: - llvm_unreachable("Reg given for non-register dependence!"); - case Anti: - case Output: - assert(Reg != 0 && - "SDep::Anti and SDep::Output must use a non-zero Reg!"); - Contents.Reg = Reg; - Latency = 0; - break; - case Data: - Contents.Reg = Reg; - Latency = 1; - break; - } - } - - SDep(SUnit *S, OrderKind kind) - : Dep(S, Order), Contents(), Latency(0) { - Contents.OrdKind = kind; - } - - /// Returns true if the specified SDep is equivalent except for latency. - bool overlaps(const SDep &Other) const; - - bool operator==(const SDep &Other) const { - return overlaps(Other) && Latency == Other.Latency; - } - - bool operator!=(const SDep &Other) const { - return !operator==(Other); - } - - /// Returns the latency value for this edge, which roughly means the - /// minimum number of cycles that must elapse between the predecessor and - /// the successor, given that they have this edge between them. - unsigned getLatency() const { - return Latency; - } - - /// Sets the latency for this edge. - void setLatency(unsigned Lat) { - Latency = Lat; - } - - //// Returns the SUnit to which this edge points. - SUnit *getSUnit() const; - - //// Assigns the SUnit to which this edge points. - void setSUnit(SUnit *SU); - - /// Returns an enum value representing the kind of the dependence. - Kind getKind() const; - - /// Shorthand for getKind() != SDep::Data. - bool isCtrl() const { - return getKind() != Data; - } - - /// Tests if this is an Order dependence between two memory accesses - /// where both sides of the dependence access memory in non-volatile and - /// fully modeled ways. - bool isNormalMemory() const { - return getKind() == Order && (Contents.OrdKind == MayAliasMem - || Contents.OrdKind == MustAliasMem); - } - - /// Tests if this is an Order dependence that is marked as a barrier. - bool isBarrier() const { - return getKind() == Order && Contents.OrdKind == Barrier; - } - - /// Tests if this could be any kind of memory dependence. - bool isNormalMemoryOrBarrier() const { - return (isNormalMemory() || isBarrier()); - } - - /// Tests if this is an Order dependence that is marked as - /// "must alias", meaning that the SUnits at either end of the edge have a - /// memory dependence on a known memory location. - bool isMustAlias() const { - return getKind() == Order && Contents.OrdKind == MustAliasMem; - } - - /// Tests if this a weak dependence. Weak dependencies are considered DAG - /// edges for height computation and other heuristics, but do not force - /// ordering. Breaking a weak edge may require the scheduler to compensate, - /// for example by inserting a copy. - bool isWeak() const { - return getKind() == Order && Contents.OrdKind >= Weak; - } - - /// Tests if this is an Order dependence that is marked as - /// "artificial", meaning it isn't necessary for correctness. - bool isArtificial() const { - return getKind() == Order && Contents.OrdKind == Artificial; - } - - /// Tests if this is an Order dependence that is marked as "cluster", - /// meaning it is artificial and wants to be adjacent. - bool isCluster() const { - return getKind() == Order && Contents.OrdKind == Cluster; - } - - /// Tests if this is a Data dependence that is associated with a register. - bool isAssignedRegDep() const { - return getKind() == Data && Contents.Reg != 0; - } - - /// Returns the register associated with this edge. This is only valid on - /// Data, Anti, and Output edges. On Data edges, this value may be zero, - /// meaning there is no associated register. - unsigned getReg() const { - assert((getKind() == Data || getKind() == Anti || getKind() == Output) && - "getReg called on non-register dependence edge!"); - return Contents.Reg; - } - - /// Assigns the associated register for this edge. This is only valid on - /// Data, Anti, and Output edges. On Anti and Output edges, this value must - /// not be zero. On Data edges, the value may be zero, which would mean that - /// no specific register is associated with this edge. - void setReg(unsigned Reg) { - assert((getKind() == Data || getKind() == Anti || getKind() == Output) && - "setReg called on non-register dependence edge!"); - assert((getKind() != Anti || Reg != 0) && - "SDep::Anti edge cannot use the zero register!"); - assert((getKind() != Output || Reg != 0) && - "SDep::Output edge cannot use the zero register!"); - Contents.Reg = Reg; - } - - void dump(const TargetRegisterInfo *TRI = nullptr) const; - }; - - /// Scheduling unit. This is a node in the scheduling DAG. - class SUnit { - private: - enum : unsigned { BoundaryID = ~0u }; - - SDNode *Node = nullptr; ///< Representative node. - MachineInstr *Instr = nullptr; ///< Alternatively, a MachineInstr. - - public: - SUnit *OrigNode = nullptr; ///< If not this, the node from which this node - /// was cloned. (SD scheduling only) - - const MCSchedClassDesc *SchedClass = - nullptr; ///< nullptr or resolved SchedClass. - - SmallVector Preds; ///< All sunit predecessors. - SmallVector Succs; ///< All sunit successors. - - typedef SmallVectorImpl::iterator pred_iterator; - typedef SmallVectorImpl::iterator succ_iterator; - typedef SmallVectorImpl::const_iterator const_pred_iterator; - typedef SmallVectorImpl::const_iterator const_succ_iterator; - - unsigned NodeNum = BoundaryID; ///< Entry # of node in the node vector. - unsigned NodeQueueId = 0; ///< Queue id of node. - unsigned NumPreds = 0; ///< # of SDep::Data preds. - unsigned NumSuccs = 0; ///< # of SDep::Data sucss. - unsigned NumPredsLeft = 0; ///< # of preds not scheduled. - unsigned NumSuccsLeft = 0; ///< # of succs not scheduled. - unsigned WeakPredsLeft = 0; ///< # of weak preds not scheduled. - unsigned WeakSuccsLeft = 0; ///< # of weak succs not scheduled. - unsigned short NumRegDefsLeft = 0; ///< # of reg defs with no scheduled use. - unsigned short Latency = 0; ///< Node latency. - bool isVRegCycle : 1; ///< May use and def the same vreg. - bool isCall : 1; ///< Is a function call. - bool isCallOp : 1; ///< Is a function call operand. - bool isTwoAddress : 1; ///< Is a two-address instruction. - bool isCommutable : 1; ///< Is a commutable instruction. - bool hasPhysRegUses : 1; ///< Has physreg uses. - bool hasPhysRegDefs : 1; ///< Has physreg defs that are being used. - bool hasPhysRegClobbers : 1; ///< Has any physreg defs, used or not. - bool isPending : 1; ///< True once pending. - bool isAvailable : 1; ///< True once available. - bool isScheduled : 1; ///< True once scheduled. - bool isScheduleHigh : 1; ///< True if preferable to schedule high. - bool isScheduleLow : 1; ///< True if preferable to schedule low. - bool isCloned : 1; ///< True if this node has been cloned. - bool isUnbuffered : 1; ///< Uses an unbuffered resource. - bool hasReservedResource : 1; ///< Uses a reserved resource. - Sched::Preference SchedulingPref = Sched::None; ///< Scheduling preference. - - private: - bool isDepthCurrent : 1; ///< True if Depth is current. - bool isHeightCurrent : 1; ///< True if Height is current. - unsigned Depth = 0; ///< Node depth. - unsigned Height = 0; ///< Node height. - - public: - unsigned TopReadyCycle = 0; ///< Cycle relative to start when node is ready. - unsigned BotReadyCycle = 0; ///< Cycle relative to end when node is ready. - - const TargetRegisterClass *CopyDstRC = - nullptr; ///< Is a special copy node if != nullptr. - const TargetRegisterClass *CopySrcRC = nullptr; - - /// Constructs an SUnit for pre-regalloc scheduling to represent an - /// SDNode and any nodes flagged to it. - SUnit(SDNode *node, unsigned nodenum) - : Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false), - isCallOp(false), isTwoAddress(false), isCommutable(false), - hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), - isHeightCurrent(false) {} - - /// Constructs an SUnit for post-regalloc scheduling to represent a - /// MachineInstr. - SUnit(MachineInstr *instr, unsigned nodenum) - : Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false), - isCallOp(false), isTwoAddress(false), isCommutable(false), - hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), - isHeightCurrent(false) {} - - /// Constructs a placeholder SUnit. - SUnit() - : isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), - isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false), - hasPhysRegClobbers(false), isPending(false), isAvailable(false), - isScheduled(false), isScheduleHigh(false), isScheduleLow(false), - isCloned(false), isUnbuffered(false), hasReservedResource(false), - isDepthCurrent(false), isHeightCurrent(false) {} - - /// Boundary nodes are placeholders for the boundary of the - /// scheduling region. - /// - /// BoundaryNodes can have DAG edges, including Data edges, but they do not - /// correspond to schedulable entities (e.g. instructions) and do not have a - /// valid ID. Consequently, always check for boundary nodes before accessing - /// an associative data structure keyed on node ID. - bool isBoundaryNode() const { return NodeNum == BoundaryID; } - - /// Assigns the representative SDNode for this SUnit. This may be used - /// during pre-regalloc scheduling. - void setNode(SDNode *N) { - assert(!Instr && "Setting SDNode of SUnit with MachineInstr!"); - Node = N; - } - - /// Returns the representative SDNode for this SUnit. This may be used - /// during pre-regalloc scheduling. - SDNode *getNode() const { - assert(!Instr && "Reading SDNode of SUnit with MachineInstr!"); - return Node; - } - - /// Returns true if this SUnit refers to a machine instruction as - /// opposed to an SDNode. - bool isInstr() const { return Instr; } - - /// Assigns the instruction for the SUnit. This may be used during - /// post-regalloc scheduling. - void setInstr(MachineInstr *MI) { - assert(!Node && "Setting MachineInstr of SUnit with SDNode!"); - Instr = MI; - } - - /// Returns the representative MachineInstr for this SUnit. This may be used - /// during post-regalloc scheduling. - MachineInstr *getInstr() const { - assert(!Node && "Reading MachineInstr of SUnit with SDNode!"); - return Instr; - } - - /// Adds the specified edge as a pred of the current node if not already. - /// It also adds the current node as a successor of the specified node. - bool addPred(const SDep &D, bool Required = true); - - /// Adds a barrier edge to SU by calling addPred(), with latency 0 - /// generally or latency 1 for a store followed by a load. - bool addPredBarrier(SUnit *SU) { - SDep Dep(SU, SDep::Barrier); - unsigned TrueMemOrderLatency = - ((SU->getInstr()->mayStore() && this->getInstr()->mayLoad()) ? 1 : 0); - Dep.setLatency(TrueMemOrderLatency); - return addPred(Dep); - } - - /// Removes the specified edge as a pred of the current node if it exists. - /// It also removes the current node as a successor of the specified node. - void removePred(const SDep &D); - - /// Returns the depth of this node, which is the length of the maximum path - /// up to any node which has no predecessors. - unsigned getDepth() const { - if (!isDepthCurrent) - const_cast(this)->ComputeDepth(); - return Depth; - } - - /// Returns the height of this node, which is the length of the - /// maximum path down to any node which has no successors. - unsigned getHeight() const { - if (!isHeightCurrent) - const_cast(this)->ComputeHeight(); - return Height; - } - - /// If NewDepth is greater than this node's depth value, sets it to - /// be the new depth value. This also recursively marks successor nodes - /// dirty. - void setDepthToAtLeast(unsigned NewDepth); - - /// If NewHeight is greater than this node's height value, set it to be - /// the new height value. This also recursively marks predecessor nodes - /// dirty. - void setHeightToAtLeast(unsigned NewHeight); - - /// Sets a flag in this node to indicate that its stored Depth value - /// will require recomputation the next time getDepth() is called. - void setDepthDirty(); - - /// Sets a flag in this node to indicate that its stored Height value - /// will require recomputation the next time getHeight() is called. - void setHeightDirty(); - - /// Tests if node N is a predecessor of this node. - bool isPred(const SUnit *N) const { - for (const SDep &Pred : Preds) - if (Pred.getSUnit() == N) - return true; - return false; - } - - /// Tests if node N is a successor of this node. - bool isSucc(const SUnit *N) const { - for (const SDep &Succ : Succs) - if (Succ.getSUnit() == N) - return true; - return false; - } - - bool isTopReady() const { - return NumPredsLeft == 0; - } - bool isBottomReady() const { - return NumSuccsLeft == 0; - } - - /// Orders this node's predecessor edges such that the critical path - /// edge occurs first. - void biasCriticalPath(); - - void dumpAttributes() const; - - private: - void ComputeDepth(); - void ComputeHeight(); - }; - - /// Returns true if the specified SDep is equivalent except for latency. - inline bool SDep::overlaps(const SDep &Other) const { - if (Dep != Other.Dep) - return false; - switch (Dep.getInt()) { - case Data: - case Anti: - case Output: - return Contents.Reg == Other.Contents.Reg; - case Order: - return Contents.OrdKind == Other.Contents.OrdKind; - } - llvm_unreachable("Invalid dependency kind!"); - } - - //// Returns the SUnit to which this edge points. - inline SUnit *SDep::getSUnit() const { return Dep.getPointer(); } - - //// Assigns the SUnit to which this edge points. - inline void SDep::setSUnit(SUnit *SU) { Dep.setPointer(SU); } - - /// Returns an enum value representing the kind of the dependence. - inline SDep::Kind SDep::getKind() const { return Dep.getInt(); } - - //===--------------------------------------------------------------------===// - - /// This interface is used to plug different priorities computation - /// algorithms into the list scheduler. It implements the interface of a - /// standard priority queue, where nodes are inserted in arbitrary order and - /// returned in priority order. The computation of the priority and the - /// representation of the queue are totally up to the implementation to - /// decide. - class SchedulingPriorityQueue { - virtual void anchor(); - - unsigned CurCycle = 0; - bool HasReadyFilter; - - public: - SchedulingPriorityQueue(bool rf = false) : HasReadyFilter(rf) {} - - virtual ~SchedulingPriorityQueue() = default; - - virtual bool isBottomUp() const = 0; - - virtual void initNodes(std::vector &SUnits) = 0; - virtual void addNode(const SUnit *SU) = 0; - virtual void updateNode(const SUnit *SU) = 0; - virtual void releaseState() = 0; - - virtual bool empty() const = 0; - - bool hasReadyFilter() const { return HasReadyFilter; } - - virtual bool tracksRegPressure() const { return false; } - - virtual bool isReady(SUnit *) const { - assert(!HasReadyFilter && "The ready filter must override isReady()"); - return true; - } - - virtual void push(SUnit *U) = 0; - - void push_all(const std::vector &Nodes) { - for (std::vector::const_iterator I = Nodes.begin(), - E = Nodes.end(); I != E; ++I) - push(*I); - } - - virtual SUnit *pop() = 0; - - virtual void remove(SUnit *SU) = 0; - - virtual void dump(ScheduleDAG *) const {} - - /// As each node is scheduled, this method is invoked. This allows the - /// priority function to adjust the priority of related unscheduled nodes, - /// for example. - virtual void scheduledNode(SUnit *) {} - - virtual void unscheduledNode(SUnit *) {} - - void setCurCycle(unsigned Cycle) { - CurCycle = Cycle; - } - - unsigned getCurCycle() const { - return CurCycle; - } - }; - - class ScheduleDAG { - public: - const LLVMTargetMachine &TM; ///< Target processor - const TargetInstrInfo *TII; ///< Target instruction information - const TargetRegisterInfo *TRI; ///< Target processor register info - MachineFunction &MF; ///< Machine function - MachineRegisterInfo &MRI; ///< Virtual/real register map - std::vector SUnits; ///< The scheduling units. - SUnit EntrySU; ///< Special node for the region entry. - SUnit ExitSU; ///< Special node for the region exit. - -#ifdef NDEBUG - static const bool StressSched = false; -#else - bool StressSched; -#endif - - explicit ScheduleDAG(MachineFunction &mf); - - virtual ~ScheduleDAG(); - - /// Clears the DAG state (between regions). - void clearDAG(); - - /// Returns the MCInstrDesc of this SUnit. - /// Returns NULL for SDNodes without a machine opcode. - const MCInstrDesc *getInstrDesc(const SUnit *SU) const { - if (SU->isInstr()) return &SU->getInstr()->getDesc(); - return getNodeDesc(SU->getNode()); - } - - /// Pops up a GraphViz/gv window with the ScheduleDAG rendered using 'dot'. - virtual void viewGraph(const Twine &Name, const Twine &Title); - virtual void viewGraph(); - - virtual void dumpNode(const SUnit &SU) const = 0; - virtual void dump() const = 0; - void dumpNodeName(const SUnit &SU) const; - - /// Returns a label for an SUnit node in a visualization of the ScheduleDAG. - virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; - - /// Returns a label for the region of code covered by the DAG. - virtual std::string getDAGName() const = 0; - - /// Adds custom features for a visualization of the ScheduleDAG. - virtual void addCustomGraphFeatures(GraphWriter &) const {} - -#ifndef NDEBUG - /// Verifies that all SUnits were scheduled and that their state is - /// consistent. Returns the number of scheduled SUnits. - unsigned VerifyScheduledDAG(bool isBottomUp); -#endif - - protected: - void dumpNodeAll(const SUnit &SU) const; - - private: - /// Returns the MCInstrDesc of this SDNode or NULL. - const MCInstrDesc *getNodeDesc(const SDNode *Node) const; - }; - - class SUnitIterator { - SUnit *Node; - unsigned Operand; - - SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {} - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = SUnit; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - bool operator==(const SUnitIterator& x) const { - return Operand == x.Operand; - } - bool operator!=(const SUnitIterator& x) const { return !operator==(x); } - - pointer operator*() const { - return Node->Preds[Operand].getSUnit(); - } - pointer operator->() const { return operator*(); } - - SUnitIterator& operator++() { // Preincrement - ++Operand; - return *this; - } - SUnitIterator operator++(int) { // Postincrement - SUnitIterator tmp = *this; ++*this; return tmp; - } - - static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); } - static SUnitIterator end (SUnit *N) { - return SUnitIterator(N, (unsigned)N->Preds.size()); - } - - unsigned getOperand() const { return Operand; } - const SUnit *getNode() const { return Node; } - - /// Tests if this is not an SDep::Data dependence. - bool isCtrlDep() const { - return getSDep().isCtrl(); - } - bool isArtificialDep() const { - return getSDep().isArtificial(); - } - const SDep &getSDep() const { - return Node->Preds[Operand]; - } - }; - - template <> struct GraphTraits { - typedef SUnit *NodeRef; - typedef SUnitIterator ChildIteratorType; - static NodeRef getEntryNode(SUnit *N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return SUnitIterator::begin(N); - } - static ChildIteratorType child_end(NodeRef N) { - return SUnitIterator::end(N); - } - }; - - template <> struct GraphTraits : public GraphTraits { - typedef pointer_iterator::iterator> nodes_iterator; - static nodes_iterator nodes_begin(ScheduleDAG *G) { - return nodes_iterator(G->SUnits.begin()); - } - static nodes_iterator nodes_end(ScheduleDAG *G) { - return nodes_iterator(G->SUnits.end()); - } - }; - - /// This class can compute a topological ordering for SUnits and provides - /// methods for dynamically updating the ordering as new edges are added. - /// - /// This allows a very fast implementation of IsReachable, for example. - class ScheduleDAGTopologicalSort { - /// A reference to the ScheduleDAG's SUnits. - std::vector &SUnits; - SUnit *ExitSU; - - // Have any new nodes been added? - bool Dirty = false; - - // Outstanding added edges, that have not been applied to the ordering. - SmallVector, 16> Updates; - - /// Maps topological index to the node number. - std::vector Index2Node; - /// Maps the node number to its topological index. - std::vector Node2Index; - /// a set of nodes visited during a DFS traversal. - BitVector Visited; - - /// Makes a DFS traversal and mark all nodes affected by the edge insertion. - /// These nodes will later get new topological indexes by means of the Shift - /// method. - void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); - - /// Reassigns topological indexes for the nodes in the DAG to - /// preserve the topological ordering. - void Shift(BitVector& Visited, int LowerBound, int UpperBound); - - /// Assigns the topological index to the node n. - void Allocate(int n, int index); - - /// Fix the ordering, by either recomputing from scratch or by applying - /// any outstanding updates. Uses a heuristic to estimate what will be - /// cheaper. - void FixOrder(); - - public: - ScheduleDAGTopologicalSort(std::vector &SUnits, SUnit *ExitSU); - - /// Add a SUnit without predecessors to the end of the topological order. It - /// also must be the first new node added to the DAG. - void AddSUnitWithoutPredecessors(const SUnit *SU); - - /// Creates the initial topological ordering from the DAG to be scheduled. - void InitDAGTopologicalSorting(); - - /// Returns an array of SUs that are both in the successor - /// subtree of StartSU and in the predecessor subtree of TargetSU. - /// StartSU and TargetSU are not in the array. - /// Success is false if TargetSU is not in the successor subtree of - /// StartSU, else it is true. - std::vector GetSubGraph(const SUnit &StartSU, const SUnit &TargetSU, - bool &Success); - - /// Checks if \p SU is reachable from \p TargetSU. - bool IsReachable(const SUnit *SU, const SUnit *TargetSU); - - /// Returns true if addPred(TargetSU, SU) creates a cycle. - bool WillCreateCycle(SUnit *TargetSU, SUnit *SU); - - /// Updates the topological ordering to accommodate an edge to be - /// added from SUnit \p X to SUnit \p Y. - void AddPred(SUnit *Y, SUnit *X); - - /// Queues an update to the topological ordering to accommodate an edge to - /// be added from SUnit \p X to SUnit \p Y. - void AddPredQueued(SUnit *Y, SUnit *X); - - /// Updates the topological ordering to accommodate an edge to be - /// removed from the specified node \p N from the predecessors of the - /// current node \p M. - void RemovePred(SUnit *M, SUnit *N); - - /// Mark the ordering as temporarily broken, after a new node has been - /// added. - void MarkDirty() { Dirty = true; } - - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - iterator begin() { return Index2Node.begin(); } - const_iterator begin() const { return Index2Node.begin(); } - iterator end() { return Index2Node.end(); } - const_iterator end() const { return Index2Node.end(); } - - typedef std::vector::reverse_iterator reverse_iterator; - typedef std::vector::const_reverse_iterator const_reverse_iterator; - reverse_iterator rbegin() { return Index2Node.rbegin(); } - const_reverse_iterator rbegin() const { return Index2Node.rbegin(); } - reverse_iterator rend() { return Index2Node.rend(); } - const_reverse_iterator rend() const { return Index2Node.rend(); } - }; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULEDAG_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGInstrs.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGInstrs.h deleted file mode 100644 index 50b186de2b..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ /dev/null @@ -1,396 +0,0 @@ -//===- ScheduleDAGInstrs.h - MachineInstr Scheduling ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Implements the ScheduleDAGInstrs class, which implements scheduling -/// for a MachineInstr-based dependency graph. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H -#define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SparseMultiSet.h" -#include "llvm/ADT/SparseSet.h" -#include "llvm/CodeGen/LivePhysRegs.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSchedule.h" -#include "llvm/MC/LaneBitmask.h" -#include -#include -#include -#include -#include - -namespace llvm { - - class AAResults; - class LiveIntervals; - class MachineFrameInfo; - class MachineFunction; - class MachineInstr; - class MachineLoopInfo; - class MachineOperand; - struct MCSchedClassDesc; - class PressureDiffs; - class PseudoSourceValue; - class RegPressureTracker; - class UndefValue; - class Value; - - /// An individual mapping from virtual register number to SUnit. - struct VReg2SUnit { - unsigned VirtReg; - LaneBitmask LaneMask; - SUnit *SU; - - VReg2SUnit(unsigned VReg, LaneBitmask LaneMask, SUnit *SU) - : VirtReg(VReg), LaneMask(LaneMask), SU(SU) {} - - unsigned getSparseSetIndex() const { - return Register::virtReg2Index(VirtReg); - } - }; - - /// Mapping from virtual register to SUnit including an operand index. - struct VReg2SUnitOperIdx : public VReg2SUnit { - unsigned OperandIndex; - - VReg2SUnitOperIdx(unsigned VReg, LaneBitmask LaneMask, - unsigned OperandIndex, SUnit *SU) - : VReg2SUnit(VReg, LaneMask, SU), OperandIndex(OperandIndex) {} - }; - - /// Record a physical register access. - /// For non-data-dependent uses, OpIdx == -1. - struct PhysRegSUOper { - SUnit *SU; - int OpIdx; - unsigned Reg; - - PhysRegSUOper(SUnit *su, int op, unsigned R): SU(su), OpIdx(op), Reg(R) {} - - unsigned getSparseSetIndex() const { return Reg; } - }; - - /// Use a SparseMultiSet to track physical registers. Storage is only - /// allocated once for the pass. It can be cleared in constant time and reused - /// without any frees. - using Reg2SUnitsMap = - SparseMultiSet, uint16_t>; - - /// Use SparseSet as a SparseMap by relying on the fact that it never - /// compares ValueT's, only unsigned keys. This allows the set to be cleared - /// between scheduling regions in constant time as long as ValueT does not - /// require a destructor. - using VReg2SUnitMap = SparseSet; - - /// Track local uses of virtual registers. These uses are gathered by the DAG - /// builder and may be consulted by the scheduler to avoid iterating an entire - /// vreg use list. - using VReg2SUnitMultiMap = SparseMultiSet; - - using VReg2SUnitOperIdxMultiMap = - SparseMultiSet; - - using ValueType = PointerUnion; - - struct UnderlyingObject : PointerIntPair { - UnderlyingObject(ValueType V, bool MayAlias) - : PointerIntPair(V, MayAlias) {} - - ValueType getValue() const { return getPointer(); } - bool mayAlias() const { return getInt(); } - }; - - using UnderlyingObjectsVector = SmallVector; - - /// A ScheduleDAG for scheduling lists of MachineInstr. - class ScheduleDAGInstrs : public ScheduleDAG { - protected: - const MachineLoopInfo *MLI; - const MachineFrameInfo &MFI; - - /// TargetSchedModel provides an interface to the machine model. - TargetSchedModel SchedModel; - - /// True if the DAG builder should remove kill flags (in preparation for - /// rescheduling). - bool RemoveKillFlags; - - /// The standard DAG builder does not normally include terminators as DAG - /// nodes because it does not create the necessary dependencies to prevent - /// reordering. A specialized scheduler can override - /// TargetInstrInfo::isSchedulingBoundary then enable this flag to indicate - /// it has taken responsibility for scheduling the terminator correctly. - bool CanHandleTerminators = false; - - /// Whether lane masks should get tracked. - bool TrackLaneMasks = false; - - // State specific to the current scheduling region. - // ------------------------------------------------ - - /// The block in which to insert instructions - MachineBasicBlock *BB; - - /// The beginning of the range to be scheduled. - MachineBasicBlock::iterator RegionBegin; - - /// The end of the range to be scheduled. - MachineBasicBlock::iterator RegionEnd; - - /// Instructions in this region (distance(RegionBegin, RegionEnd)). - unsigned NumRegionInstrs; - - /// After calling BuildSchedGraph, each machine instruction in the current - /// scheduling region is mapped to an SUnit. - DenseMap MISUnitMap; - - // State internal to DAG building. - // ------------------------------- - - /// Defs, Uses - Remember where defs and uses of each register are as we - /// iterate upward through the instructions. This is allocated here instead - /// of inside BuildSchedGraph to avoid the need for it to be initialized and - /// destructed for each block. - Reg2SUnitsMap Defs; - Reg2SUnitsMap Uses; - - /// Tracks the last instruction(s) in this region defining each virtual - /// register. There may be multiple current definitions for a register with - /// disjunct lanemasks. - VReg2SUnitMultiMap CurrentVRegDefs; - /// Tracks the last instructions in this region using each virtual register. - VReg2SUnitOperIdxMultiMap CurrentVRegUses; - - AAResults *AAForDep = nullptr; - - /// Remember a generic side-effecting instruction as we proceed. - /// No other SU ever gets scheduled around it (except in the special - /// case of a huge region that gets reduced). - SUnit *BarrierChain = nullptr; - - public: - /// A list of SUnits, used in Value2SUsMap, during DAG construction. - /// Note: to gain speed it might be worth investigating an optimized - /// implementation of this data structure, such as a singly linked list - /// with a memory pool (SmallVector was tried but slow and SparseSet is not - /// applicable). - using SUList = std::list; - - protected: - /// A map from ValueType to SUList, used during DAG construction, as - /// a means of remembering which SUs depend on which memory locations. - class Value2SUsMap; - - /// Reduces maps in FIFO order, by N SUs. This is better than turning - /// every Nth memory SU into BarrierChain in buildSchedGraph(), since - /// it avoids unnecessary edges between seen SUs above the new BarrierChain, - /// and those below it. - void reduceHugeMemNodeMaps(Value2SUsMap &stores, - Value2SUsMap &loads, unsigned N); - - /// Adds a chain edge between SUa and SUb, but only if both - /// AAResults and Target fail to deny the dependency. - void addChainDependency(SUnit *SUa, SUnit *SUb, - unsigned Latency = 0); - - /// Adds dependencies as needed from all SUs in list to SU. - void addChainDependencies(SUnit *SU, SUList &SUs, unsigned Latency) { - for (SUnit *Entry : SUs) - addChainDependency(SU, Entry, Latency); - } - - /// Adds dependencies as needed from all SUs in map, to SU. - void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap); - - /// Adds dependencies as needed to SU, from all SUs mapped to V. - void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap, - ValueType V); - - /// Adds barrier chain edges from all SUs in map, and then clear the map. - /// This is equivalent to insertBarrierChain(), but optimized for the common - /// case where the new BarrierChain (a global memory object) has a higher - /// NodeNum than all SUs in map. It is assumed BarrierChain has been set - /// before calling this. - void addBarrierChain(Value2SUsMap &map); - - /// Inserts a barrier chain in a huge region, far below current SU. - /// Adds barrier chain edges from all SUs in map with higher NodeNums than - /// this new BarrierChain, and remove them from map. It is assumed - /// BarrierChain has been set before calling this. - void insertBarrierChain(Value2SUsMap &map); - - /// For an unanalyzable memory access, this Value is used in maps. - UndefValue *UnknownValue; - - - /// Topo - A topological ordering for SUnits which permits fast IsReachable - /// and similar queries. - ScheduleDAGTopologicalSort Topo; - - using DbgValueVector = - std::vector>; - /// Remember instruction that precedes DBG_VALUE. - /// These are generated by buildSchedGraph but persist so they can be - /// referenced when emitting the final schedule. - DbgValueVector DbgValues; - MachineInstr *FirstDbgValue = nullptr; - - /// Set of live physical registers for updating kill flags. - LivePhysRegs LiveRegs; - - public: - explicit ScheduleDAGInstrs(MachineFunction &mf, - const MachineLoopInfo *mli, - bool RemoveKillFlags = false); - - ~ScheduleDAGInstrs() override = default; - - /// Gets the machine model for instruction scheduling. - const TargetSchedModel *getSchedModel() const { return &SchedModel; } - - /// Resolves and cache a resolved scheduling class for an SUnit. - const MCSchedClassDesc *getSchedClass(SUnit *SU) const { - if (!SU->SchedClass && SchedModel.hasInstrSchedModel()) - SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); - return SU->SchedClass; - } - - /// IsReachable - Checks if SU is reachable from TargetSU. - bool IsReachable(SUnit *SU, SUnit *TargetSU) { - return Topo.IsReachable(SU, TargetSU); - } - - /// Returns an iterator to the top of the current scheduling region. - MachineBasicBlock::iterator begin() const { return RegionBegin; } - - /// Returns an iterator to the bottom of the current scheduling region. - MachineBasicBlock::iterator end() const { return RegionEnd; } - - /// Creates a new SUnit and return a ptr to it. - SUnit *newSUnit(MachineInstr *MI); - - /// Returns an existing SUnit for this MI, or nullptr. - SUnit *getSUnit(MachineInstr *MI) const; - - /// If this method returns true, handling of the scheduling regions - /// themselves (in case of a scheduling boundary in MBB) will be done - /// beginning with the topmost region of MBB. - virtual bool doMBBSchedRegionsTopDown() const { return false; } - - /// Prepares to perform scheduling in the given block. - virtual void startBlock(MachineBasicBlock *BB); - - /// Cleans up after scheduling in the given block. - virtual void finishBlock(); - - /// Initialize the DAG and common scheduler state for a new - /// scheduling region. This does not actually create the DAG, only clears - /// it. The scheduling driver may call BuildSchedGraph multiple times per - /// scheduling region. - virtual void enterRegion(MachineBasicBlock *bb, - MachineBasicBlock::iterator begin, - MachineBasicBlock::iterator end, - unsigned regioninstrs); - - /// Called when the scheduler has finished scheduling the current region. - virtual void exitRegion(); - - /// Builds SUnits for the current region. - /// If \p RPTracker is non-null, compute register pressure as a side effect. - /// The DAG builder is an efficient place to do it because it already visits - /// operands. - void buildSchedGraph(AAResults *AA, - RegPressureTracker *RPTracker = nullptr, - PressureDiffs *PDiffs = nullptr, - LiveIntervals *LIS = nullptr, - bool TrackLaneMasks = false); - - /// Adds dependencies from instructions in the current list of - /// instructions being scheduled to scheduling barrier. We want to make sure - /// instructions which define registers that are either used by the - /// terminator or are live-out are properly scheduled. This is especially - /// important when the definition latency of the return value(s) are too - /// high to be hidden by the branch or when the liveout registers used by - /// instructions in the fallthrough block. - void addSchedBarrierDeps(); - - /// Orders nodes according to selected style. - /// - /// Typically, a scheduling algorithm will implement schedule() without - /// overriding enterRegion() or exitRegion(). - virtual void schedule() = 0; - - /// Allow targets to perform final scheduling actions at the level of the - /// whole MachineFunction. By default does nothing. - virtual void finalizeSchedule() {} - - void dumpNode(const SUnit &SU) const override; - void dump() const override; - - /// Returns a label for a DAG node that points to an instruction. - std::string getGraphNodeLabel(const SUnit *SU) const override; - - /// Returns a label for the region of code covered by the DAG. - std::string getDAGName() const override; - - /// Fixes register kill flags that scheduling has made invalid. - void fixupKills(MachineBasicBlock &MBB); - - /// True if an edge can be added from PredSU to SuccSU without creating - /// a cycle. - bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); - - /// Add a DAG edge to the given SU with the given predecessor - /// dependence data. - /// - /// \returns true if the edge may be added without creating a cycle OR if an - /// equivalent edge already existed (false indicates failure). - bool addEdge(SUnit *SuccSU, const SDep &PredDep); - - protected: - void initSUnits(); - void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx); - void addPhysRegDeps(SUnit *SU, unsigned OperIdx); - void addVRegDefDeps(SUnit *SU, unsigned OperIdx); - void addVRegUseDeps(SUnit *SU, unsigned OperIdx); - - /// Returns a mask for which lanes get read/written by the given (register) - /// machine operand. - LaneBitmask getLaneMaskForMO(const MachineOperand &MO) const; - - /// Returns true if the def register in \p MO has no uses. - bool deadDefHasNoUse(const MachineOperand &MO); - }; - - /// Creates a new SUnit and return a ptr to it. - inline SUnit *ScheduleDAGInstrs::newSUnit(MachineInstr *MI) { -#ifndef NDEBUG - const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0]; -#endif - SUnits.emplace_back(MI, (unsigned)SUnits.size()); - assert((Addr == nullptr || Addr == &SUnits[0]) && - "SUnits std::vector reallocated on the fly!"); - return &SUnits.back(); - } - - /// Returns an existing SUnit for this MI, or nullptr. - inline SUnit *ScheduleDAGInstrs::getSUnit(MachineInstr *MI) const { - return MISUnitMap.lookup(MI); - } - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULEDAGINSTRS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGMutation.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGMutation.h deleted file mode 100644 index d1dd72859a..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDAGMutation.h +++ /dev/null @@ -1,33 +0,0 @@ -//===- ScheduleDAGMutation.h - MachineInstr Scheduling ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the ScheduleDAGMutation class, which represents -// a target-specific mutation of the dependency graph for scheduling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULEDAGMUTATION_H -#define LLVM_CODEGEN_SCHEDULEDAGMUTATION_H - -namespace llvm { - -class ScheduleDAGInstrs; - -/// Mutate the DAG as a postpass after normal DAG building. -class ScheduleDAGMutation { - virtual void anchor(); - -public: - virtual ~ScheduleDAGMutation() = default; - - virtual void apply(ScheduleDAGInstrs *DAG) = 0; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULEDAGMUTATION_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDFS.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDFS.h deleted file mode 100644 index 2e0a30cc56..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleDFS.h +++ /dev/null @@ -1,193 +0,0 @@ -//===- ScheduleDFS.h - ILP metric for ScheduleDAGInstrs ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Definition of an ILP metric for machine level instruction scheduling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULEDFS_H -#define LLVM_CODEGEN_SCHEDULEDFS_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ScheduleDAG.h" -#include -#include -#include - -namespace llvm { - -template class ArrayRef; -class raw_ostream; - -/// Represent the ILP of the subDAG rooted at a DAG node. -/// -/// ILPValues summarize the DAG subtree rooted at each node. ILPValues are -/// valid for all nodes regardless of their subtree membership. -/// -/// When computed using bottom-up DFS, this metric assumes that the DAG is a -/// forest of trees with roots at the bottom of the schedule branching upward. -struct ILPValue { - unsigned InstrCount; - /// Length may either correspond to depth or height, depending on direction, - /// and cycles or nodes depending on context. - unsigned Length; - - ILPValue(unsigned count, unsigned length): - InstrCount(count), Length(length) {} - - // Order by the ILP metric's value. - bool operator<(ILPValue RHS) const { - return (uint64_t)InstrCount * RHS.Length - < (uint64_t)Length * RHS.InstrCount; - } - bool operator>(ILPValue RHS) const { - return RHS < *this; - } - bool operator<=(ILPValue RHS) const { - return (uint64_t)InstrCount * RHS.Length - <= (uint64_t)Length * RHS.InstrCount; - } - bool operator>=(ILPValue RHS) const { - return RHS <= *this; - } - - void print(raw_ostream &OS) const; - - void dump() const; -}; - -/// Compute the values of each DAG node for various metrics during DFS. -class SchedDFSResult { - friend class SchedDFSImpl; - - static const unsigned InvalidSubtreeID = ~0u; - - /// Per-SUnit data computed during DFS for various metrics. - /// - /// A node's SubtreeID is set to itself when it is visited to indicate that it - /// is the root of a subtree. Later it is set to its parent to indicate an - /// interior node. Finally, it is set to a representative subtree ID during - /// finalization. - struct NodeData { - unsigned InstrCount = 0; - unsigned SubtreeID = InvalidSubtreeID; - - NodeData() = default; - }; - - /// Per-Subtree data computed during DFS. - struct TreeData { - unsigned ParentTreeID = InvalidSubtreeID; - unsigned SubInstrCount = 0; - - TreeData() = default; - }; - - /// Record a connection between subtrees and the connection level. - struct Connection { - unsigned TreeID; - unsigned Level; - - Connection(unsigned tree, unsigned level): TreeID(tree), Level(level) {} - }; - - bool IsBottomUp; - unsigned SubtreeLimit; - /// DFS results for each SUnit in this DAG. - std::vector DFSNodeData; - - // Store per-tree data indexed on tree ID, - SmallVector DFSTreeData; - - // For each subtree discovered during DFS, record its connections to other - // subtrees. - std::vector> SubtreeConnections; - - /// Cache the current connection level of each subtree. - /// This mutable array is updated during scheduling. - std::vector SubtreeConnectLevels; - -public: - SchedDFSResult(bool IsBU, unsigned lim) - : IsBottomUp(IsBU), SubtreeLimit(lim) {} - - /// Get the node cutoff before subtrees are considered significant. - unsigned getSubtreeLimit() const { return SubtreeLimit; } - - /// Return true if this DFSResult is uninitialized. - /// - /// resize() initializes DFSResult, while compute() populates it. - bool empty() const { return DFSNodeData.empty(); } - - /// Clear the results. - void clear() { - DFSNodeData.clear(); - DFSTreeData.clear(); - SubtreeConnections.clear(); - SubtreeConnectLevels.clear(); - } - - /// Initialize the result data with the size of the DAG. - void resize(unsigned NumSUnits) { - DFSNodeData.resize(NumSUnits); - } - - /// Compute various metrics for the DAG with given roots. - void compute(ArrayRef SUnits); - - /// Get the number of instructions in the given subtree and its - /// children. - unsigned getNumInstrs(const SUnit *SU) const { - return DFSNodeData[SU->NodeNum].InstrCount; - } - - /// Get the number of instructions in the given subtree not including - /// children. - unsigned getNumSubInstrs(unsigned SubtreeID) const { - return DFSTreeData[SubtreeID].SubInstrCount; - } - - /// Get the ILP value for a DAG node. - /// - /// A leaf node has an ILP of 1/1. - ILPValue getILP(const SUnit *SU) const { - return ILPValue(DFSNodeData[SU->NodeNum].InstrCount, 1 + SU->getDepth()); - } - - /// The number of subtrees detected in this DAG. - unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); } - - /// Get the ID of the subtree the given DAG node belongs to. - /// - /// For convenience, if DFSResults have not been computed yet, give everything - /// tree ID 0. - unsigned getSubtreeID(const SUnit *SU) const { - if (empty()) - return 0; - assert(SU->NodeNum < DFSNodeData.size() && "New Node"); - return DFSNodeData[SU->NodeNum].SubtreeID; - } - - /// Get the connection level of a subtree. - /// - /// For bottom-up trees, the connection level is the latency depth (in cycles) - /// of the deepest connection to another subtree. - unsigned getSubtreeLevel(unsigned SubtreeID) const { - return SubtreeConnectLevels[SubtreeID]; - } - - /// Scheduler callback to update SubtreeConnectLevels when a tree is - /// initially scheduled. - void scheduleTree(unsigned SubtreeID); -}; - -raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULEDFS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleHazardRecognizer.h deleted file mode 100644 index 9f1101b658..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ /dev/null @@ -1,129 +0,0 @@ -//=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the ScheduleHazardRecognizer class, which implements -// hazard-avoidance heuristics for scheduling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H -#define LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H - -namespace llvm { - -class MachineInstr; -class SUnit; - -/// HazardRecognizer - This determines whether or not an instruction can be -/// issued this cycle, and whether or not a noop needs to be inserted to handle -/// the hazard. -class ScheduleHazardRecognizer { -protected: - /// MaxLookAhead - Indicate the number of cycles in the scoreboard - /// state. Important to restore the state after backtracking. Additionally, - /// MaxLookAhead=0 identifies a fake recognizer, allowing the client to - /// bypass virtual calls. Currently the PostRA scheduler ignores it. - unsigned MaxLookAhead = 0; - -public: - ScheduleHazardRecognizer() = default; - virtual ~ScheduleHazardRecognizer(); - - enum HazardType { - NoHazard, // This instruction can be emitted at this cycle. - Hazard, // This instruction can't be emitted at this cycle. - NoopHazard // This instruction can't be emitted, and needs noops. - }; - - unsigned getMaxLookAhead() const { return MaxLookAhead; } - - bool isEnabled() const { return MaxLookAhead != 0; } - - /// atIssueLimit - Return true if no more instructions may be issued in this - /// cycle. - /// - /// FIXME: remove this once MachineScheduler is the only client. - virtual bool atIssueLimit() const { return false; } - - /// getHazardType - Return the hazard type of emitting this node. There are - /// three possible results. Either: - /// * NoHazard: it is legal to issue this instruction on this cycle. - /// * Hazard: issuing this instruction would stall the machine. If some - /// other instruction is available, issue it first. - /// * NoopHazard: issuing this instruction would break the program. If - /// some other instruction can be issued, do so, otherwise issue a noop. - virtual HazardType getHazardType(SUnit *, int Stalls = 0) { - return NoHazard; - } - - /// Reset - This callback is invoked when a new block of - /// instructions is about to be schedule. The hazard state should be - /// set to an initialized state. - virtual void Reset() {} - - /// EmitInstruction - This callback is invoked when an instruction is - /// emitted, to advance the hazard state. - virtual void EmitInstruction(SUnit *) {} - - /// This overload will be used when the hazard recognizer is being used - /// by a non-scheduling pass, which does not use SUnits. - virtual void EmitInstruction(MachineInstr *) {} - - /// PreEmitNoops - This callback is invoked prior to emitting an instruction. - /// It should return the number of noops to emit prior to the provided - /// instruction. - /// Note: This is only used during PostRA scheduling. EmitNoop is not called - /// for these noops. - virtual unsigned PreEmitNoops(SUnit *) { - return 0; - } - - /// This overload will be used when the hazard recognizer is being used - /// by a non-scheduling pass, which does not use SUnits. - virtual unsigned PreEmitNoops(MachineInstr *) { - return 0; - } - - /// ShouldPreferAnother - This callback may be invoked if getHazardType - /// returns NoHazard. If, even though there is no hazard, it would be better to - /// schedule another available instruction, this callback should return true. - virtual bool ShouldPreferAnother(SUnit *) { - return false; - } - - /// AdvanceCycle - This callback is invoked whenever the next top-down - /// instruction to be scheduled cannot issue in the current cycle, either - /// because of latency or resource conflicts. This should increment the - /// internal state of the hazard recognizer so that previously "Hazard" - /// instructions will now not be hazards. - virtual void AdvanceCycle() {} - - /// RecedeCycle - This callback is invoked whenever the next bottom-up - /// instruction to be scheduled cannot issue in the current cycle, either - /// because of latency or resource conflicts. - virtual void RecedeCycle() {} - - /// EmitNoop - This callback is invoked when a noop was added to the - /// instruction stream. - virtual void EmitNoop() { - // Default implementation: count it as a cycle. - AdvanceCycle(); - } - - /// EmitNoops - This callback is invoked when noops were added to the - /// instruction stream. - virtual void EmitNoops(unsigned Quantity) { - // Default implementation: count it as a cycle. - for (unsigned i = 0; i < Quantity; ++i) - EmitNoop(); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SchedulerRegistry.h b/suite/synctools/tablegen/include/llvm/CodeGen/SchedulerRegistry.h deleted file mode 100644 index 0ccfaafd9e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SchedulerRegistry.h +++ /dev/null @@ -1,107 +0,0 @@ -//===- llvm/CodeGen/SchedulerRegistry.h -------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation for instruction scheduler function -// pass registry (RegisterScheduler). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCHEDULERREGISTRY_H -#define LLVM_CODEGEN_SCHEDULERREGISTRY_H - -#include "llvm/CodeGen/MachinePassRegistry.h" -#include "llvm/Support/CodeGen.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -/// -/// RegisterScheduler class - Track the registration of instruction schedulers. -/// -//===----------------------------------------------------------------------===// - -class ScheduleDAGSDNodes; -class SelectionDAGISel; - -class RegisterScheduler - : public MachinePassRegistryNode< - ScheduleDAGSDNodes *(*)(SelectionDAGISel *, CodeGenOpt::Level)> { -public: - using FunctionPassCtor = ScheduleDAGSDNodes *(*)(SelectionDAGISel*, - CodeGenOpt::Level); - - static MachinePassRegistry Registry; - - RegisterScheduler(const char *N, const char *D, FunctionPassCtor C) - : MachinePassRegistryNode(N, D, C) { - Registry.Add(this); - } - ~RegisterScheduler() { Registry.Remove(this); } - - - // Accessors. - RegisterScheduler *getNext() const { - return (RegisterScheduler *)MachinePassRegistryNode::getNext(); - } - - static RegisterScheduler *getList() { - return (RegisterScheduler *)Registry.getList(); - } - - static void setListener(MachinePassRegistryListener *L) { - Registry.setListener(L); - } -}; - -/// createBURRListDAGScheduler - This creates a bottom up register usage -/// reduction list scheduler. -ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); - -/// createBURRListDAGScheduler - This creates a bottom up list scheduler that -/// schedules nodes in source code order when possible. -ScheduleDAGSDNodes *createSourceListDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); - -/// createHybridListDAGScheduler - This creates a bottom up register pressure -/// aware list scheduler that make use of latency information to avoid stalls -/// for long latency instructions in low register pressure mode. In high -/// register pressure mode it schedules to reduce register pressure. -ScheduleDAGSDNodes *createHybridListDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level); - -/// createILPListDAGScheduler - This creates a bottom up register pressure -/// aware list scheduler that tries to increase instruction level parallelism -/// in low register pressure mode. In high register pressure mode it schedules -/// to reduce register pressure. -ScheduleDAGSDNodes *createILPListDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level); - -/// createFastDAGScheduler - This creates a "fast" scheduler. -/// -ScheduleDAGSDNodes *createFastDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); - -/// createVLIWDAGScheduler - Scheduler for VLIW targets. This creates top down -/// DFA driven list scheduler with clustering heuristic to control -/// register pressure. -ScheduleDAGSDNodes *createVLIWDAGScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); -/// createDefaultScheduler - This creates an instruction scheduler appropriate -/// for the target. -ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); - -/// createDAGLinearizer - This creates a "no-scheduling" scheduler which -/// linearize the DAG using topological order. -ScheduleDAGSDNodes *createDAGLinearizer(SelectionDAGISel *IS, - CodeGenOpt::Level OptLevel); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCHEDULERREGISTRY_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/suite/synctools/tablegen/include/llvm/CodeGen/ScoreboardHazardRecognizer.h deleted file mode 100644 index cefafe87a1..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ /dev/null @@ -1,127 +0,0 @@ -//=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the ScoreboardHazardRecognizer class, which -// encapsulates hazard-avoidance heuristics for scheduling, based on the -// scheduling itineraries specified for the target. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H -#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H - -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/MC/MCInstrItineraries.h" -#include -#include -#include - -namespace llvm { - -class ScheduleDAG; -class SUnit; - -class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { - // Scoreboard to track function unit usage. Scoreboard[0] is a - // mask of the FUs in use in the cycle currently being - // schedule. Scoreboard[1] is a mask for the next cycle. The - // Scoreboard is used as a circular buffer with the current cycle - // indicated by Head. - // - // Scoreboard always counts cycles in forward execution order. If used by a - // bottom-up scheduler, then the scoreboard cycles are the inverse of the - // scheduler's cycles. - class Scoreboard { - InstrStage::FuncUnits *Data = nullptr; - - // The maximum number of cycles monitored by the Scoreboard. This - // value is determined based on the target itineraries to ensure - // that all hazards can be tracked. - size_t Depth = 0; - - // Indices into the Scoreboard that represent the current cycle. - size_t Head = 0; - - public: - Scoreboard() = default; - - ~Scoreboard() { - delete[] Data; - } - - size_t getDepth() const { return Depth; } - - InstrStage::FuncUnits& operator[](size_t idx) const { - // Depth is expected to be a power-of-2. - assert(Depth && !(Depth & (Depth - 1)) && - "Scoreboard was not initialized properly!"); - - return Data[(Head + idx) & (Depth-1)]; - } - - void reset(size_t d = 1) { - if (!Data) { - Depth = d; - Data = new InstrStage::FuncUnits[Depth]; - } - - memset(Data, 0, Depth * sizeof(Data[0])); - Head = 0; - } - - void advance() { - Head = (Head + 1) & (Depth-1); - } - - void recede() { - Head = (Head - 1) & (Depth-1); - } - - // Print the scoreboard. - void dump() const; - }; - - // Support for tracing ScoreboardHazardRecognizer as a component within - // another module. - const char *DebugType; - - // Itinerary data for the target. - const InstrItineraryData *ItinData; - - const ScheduleDAG *DAG; - - /// IssueWidth - Max issue per cycle. 0=Unknown. - unsigned IssueWidth = 0; - - /// IssueCount - Count instructions issued in this cycle. - unsigned IssueCount = 0; - - Scoreboard ReservedScoreboard; - Scoreboard RequiredScoreboard; - -public: - ScoreboardHazardRecognizer(const InstrItineraryData *II, - const ScheduleDAG *DAG, - const char *ParentDebugType = ""); - - /// atIssueLimit - Return true if no more instructions may be issued in this - /// cycle. - bool atIssueLimit() const override; - - // Stalls provides an cycle offset at which SU will be scheduled. It will be - // negative for bottom-up scheduling. - HazardType getHazardType(SUnit *SU, int Stalls) override; - void Reset() override; - void EmitInstruction(SUnit *SU) override; - void AdvanceCycle() override; - void RecedeCycle() override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAG.h b/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAG.h deleted file mode 100644 index 6f140da1ef..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAG.h +++ /dev/null @@ -1,2160 +0,0 @@ -//===- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the SelectionDAG class, and transitively defines the -// SDNode class and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SELECTIONDAG_H -#define LLVM_CODEGEN_SELECTIONDAG_H - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/DAGCombine.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/ArrayRecycler.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/RecyclingAllocator.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class AAResults; -class BlockAddress; -class BlockFrequencyInfo; -class Constant; -class ConstantFP; -class ConstantInt; -class DataLayout; -struct fltSemantics; -class FunctionLoweringInfo; -class GlobalValue; -struct KnownBits; -class LegacyDivergenceAnalysis; -class LLVMContext; -class MachineBasicBlock; -class MachineConstantPoolValue; -class MCSymbol; -class OptimizationRemarkEmitter; -class ProfileSummaryInfo; -class SDDbgValue; -class SDDbgOperand; -class SDDbgLabel; -class SelectionDAG; -class SelectionDAGTargetInfo; -class TargetLibraryInfo; -class TargetLowering; -class TargetMachine; -class TargetSubtargetInfo; -class Value; - -class SDVTListNode : public FoldingSetNode { - friend struct FoldingSetTrait; - - /// A reference to an Interned FoldingSetNodeID for this node. - /// The Allocator in SelectionDAG holds the data. - /// SDVTList contains all types which are frequently accessed in SelectionDAG. - /// The size of this list is not expected to be big so it won't introduce - /// a memory penalty. - FoldingSetNodeIDRef FastID; - const EVT *VTs; - unsigned int NumVTs; - /// The hash value for SDVTList is fixed, so cache it to avoid - /// hash calculation. - unsigned HashValue; - -public: - SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : - FastID(ID), VTs(VT), NumVTs(Num) { - HashValue = ID.ComputeHash(); - } - - SDVTList getSDVTList() { - SDVTList result = {VTs, NumVTs}; - return result; - } -}; - -/// Specialize FoldingSetTrait for SDVTListNode -/// to avoid computing temp FoldingSetNodeID and hash value. -template<> struct FoldingSetTrait : DefaultFoldingSetTrait { - static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { - ID = X.FastID; - } - - static bool Equals(const SDVTListNode &X, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) { - if (X.HashValue != IDHash) - return false; - return ID == X.FastID; - } - - static unsigned ComputeHash(const SDVTListNode &X, FoldingSetNodeID &TempID) { - return X.HashValue; - } -}; - -template <> struct ilist_alloc_traits { - static void deleteNode(SDNode *) { - llvm_unreachable("ilist_traits shouldn't see a deleteNode call!"); - } -}; - -/// Keeps track of dbg_value information through SDISel. We do -/// not build SDNodes for these so as not to perturb the generated code; -/// instead the info is kept off to the side in this structure. Each SDNode may -/// have one or more associated dbg_value entries. This information is kept in -/// DbgValMap. -/// Byval parameters are handled separately because they don't use alloca's, -/// which busts the normal mechanism. There is good reason for handling all -/// parameters separately: they may not have code generated for them, they -/// should always go at the beginning of the function regardless of other code -/// motion, and debug info for them is potentially useful even if the parameter -/// is unused. Right now only byval parameters are handled separately. -class SDDbgInfo { - BumpPtrAllocator Alloc; - SmallVector DbgValues; - SmallVector ByvalParmDbgValues; - SmallVector DbgLabels; - using DbgValMapType = DenseMap>; - DbgValMapType DbgValMap; - -public: - SDDbgInfo() = default; - SDDbgInfo(const SDDbgInfo &) = delete; - SDDbgInfo &operator=(const SDDbgInfo &) = delete; - - void add(SDDbgValue *V, bool isParameter); - - void add(SDDbgLabel *L) { DbgLabels.push_back(L); } - - /// Invalidate all DbgValues attached to the node and remove - /// it from the Node-to-DbgValues map. - void erase(const SDNode *Node); - - void clear() { - DbgValMap.clear(); - DbgValues.clear(); - ByvalParmDbgValues.clear(); - DbgLabels.clear(); - Alloc.Reset(); - } - - BumpPtrAllocator &getAlloc() { return Alloc; } - - bool empty() const { - return DbgValues.empty() && ByvalParmDbgValues.empty() && DbgLabels.empty(); - } - - ArrayRef getSDDbgValues(const SDNode *Node) const { - auto I = DbgValMap.find(Node); - if (I != DbgValMap.end()) - return I->second; - return ArrayRef(); - } - - using DbgIterator = SmallVectorImpl::iterator; - using DbgLabelIterator = SmallVectorImpl::iterator; - - DbgIterator DbgBegin() { return DbgValues.begin(); } - DbgIterator DbgEnd() { return DbgValues.end(); } - DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } - DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); } - DbgLabelIterator DbgLabelBegin() { return DbgLabels.begin(); } - DbgLabelIterator DbgLabelEnd() { return DbgLabels.end(); } -}; - -void checkForCycles(const SelectionDAG *DAG, bool force = false); - -/// This is used to represent a portion of an LLVM function in a low-level -/// Data Dependence DAG representation suitable for instruction selection. -/// This DAG is constructed as the first step of instruction selection in order -/// to allow implementation of machine specific optimizations -/// and code simplifications. -/// -/// The representation used by the SelectionDAG is a target-independent -/// representation, which has some similarities to the GCC RTL representation, -/// but is significantly more simple, powerful, and is a graph form instead of a -/// linear form. -/// -class SelectionDAG { - const TargetMachine &TM; - const SelectionDAGTargetInfo *TSI = nullptr; - const TargetLowering *TLI = nullptr; - const TargetLibraryInfo *LibInfo = nullptr; - MachineFunction *MF; - Pass *SDAGISelPass = nullptr; - LLVMContext *Context; - CodeGenOpt::Level OptLevel; - - LegacyDivergenceAnalysis * DA = nullptr; - FunctionLoweringInfo * FLI = nullptr; - - /// The function-level optimization remark emitter. Used to emit remarks - /// whenever manipulating the DAG. - OptimizationRemarkEmitter *ORE; - - ProfileSummaryInfo *PSI = nullptr; - BlockFrequencyInfo *BFI = nullptr; - - /// The starting token. - SDNode EntryNode; - - /// The root of the entire DAG. - SDValue Root; - - /// A linked list of nodes in the current DAG. - ilist AllNodes; - - /// The AllocatorType for allocating SDNodes. We use - /// pool allocation with recycling. - using NodeAllocatorType = RecyclingAllocator; - - /// Pool allocation for nodes. - NodeAllocatorType NodeAllocator; - - /// This structure is used to memoize nodes, automatically performing - /// CSE with existing nodes when a duplicate is requested. - FoldingSet CSEMap; - - /// Pool allocation for machine-opcode SDNode operands. - BumpPtrAllocator OperandAllocator; - ArrayRecycler OperandRecycler; - - /// Pool allocation for misc. objects that are created once per SelectionDAG. - BumpPtrAllocator Allocator; - - /// Tracks dbg_value and dbg_label information through SDISel. - SDDbgInfo *DbgInfo; - - using CallSiteInfo = MachineFunction::CallSiteInfo; - using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; - - struct CallSiteDbgInfo { - CallSiteInfo CSInfo; - MDNode *HeapAllocSite = nullptr; - bool NoMerge = false; - }; - - DenseMap SDCallSiteDbgInfo; - - uint16_t NextPersistentId = 0; - - /// Are instruction referencing variable locations desired for this function? - bool UseInstrRefDebugInfo = false; - -public: - /// Clients of various APIs that cause global effects on - /// the DAG can optionally implement this interface. This allows the clients - /// to handle the various sorts of updates that happen. - /// - /// A DAGUpdateListener automatically registers itself with DAG when it is - /// constructed, and removes itself when destroyed in RAII fashion. - struct DAGUpdateListener { - DAGUpdateListener *const Next; - SelectionDAG &DAG; - - explicit DAGUpdateListener(SelectionDAG &D) - : Next(D.UpdateListeners), DAG(D) { - DAG.UpdateListeners = this; - } - - virtual ~DAGUpdateListener() { - assert(DAG.UpdateListeners == this && - "DAGUpdateListeners must be destroyed in LIFO order"); - DAG.UpdateListeners = Next; - } - - /// The node N that was deleted and, if E is not null, an - /// equivalent node E that replaced it. - virtual void NodeDeleted(SDNode *N, SDNode *E); - - /// The node N that was updated. - virtual void NodeUpdated(SDNode *N); - - /// The node N that was inserted. - virtual void NodeInserted(SDNode *N); - }; - - struct DAGNodeDeletedListener : public DAGUpdateListener { - std::function Callback; - - DAGNodeDeletedListener(SelectionDAG &DAG, - std::function Callback) - : DAGUpdateListener(DAG), Callback(std::move(Callback)) {} - - void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); } - - private: - virtual void anchor(); - }; - - /// Help to insert SDNodeFlags automatically in transforming. Use - /// RAII to save and resume flags in current scope. - class FlagInserter { - SelectionDAG &DAG; - SDNodeFlags Flags; - FlagInserter *LastInserter; - - public: - FlagInserter(SelectionDAG &SDAG, SDNodeFlags Flags) - : DAG(SDAG), Flags(Flags), - LastInserter(SDAG.getFlagInserter()) { - SDAG.setFlagInserter(this); - } - FlagInserter(SelectionDAG &SDAG, SDNode *N) - : FlagInserter(SDAG, N->getFlags()) {} - - FlagInserter(const FlagInserter &) = delete; - FlagInserter &operator=(const FlagInserter &) = delete; - ~FlagInserter() { DAG.setFlagInserter(LastInserter); } - - SDNodeFlags getFlags() const { return Flags; } - }; - - /// When true, additional steps are taken to - /// ensure that getConstant() and similar functions return DAG nodes that - /// have legal types. This is important after type legalization since - /// any illegally typed nodes generated after this point will not experience - /// type legalization. - bool NewNodesMustHaveLegalTypes = false; - -private: - /// DAGUpdateListener is a friend so it can manipulate the listener stack. - friend struct DAGUpdateListener; - - /// Linked list of registered DAGUpdateListener instances. - /// This stack is maintained by DAGUpdateListener RAII. - DAGUpdateListener *UpdateListeners = nullptr; - - /// Implementation of setSubgraphColor. - /// Return whether we had to truncate the search. - bool setSubgraphColorHelper(SDNode *N, const char *Color, - DenseSet &visited, - int level, bool &printed); - - template - SDNodeT *newSDNode(ArgTypes &&... Args) { - return new (NodeAllocator.template Allocate()) - SDNodeT(std::forward(Args)...); - } - - /// Build a synthetic SDNodeT with the given args and extract its subclass - /// data as an integer (e.g. for use in a folding set). - /// - /// The args to this function are the same as the args to SDNodeT's - /// constructor, except the second arg (assumed to be a const DebugLoc&) is - /// omitted. - template - static uint16_t getSyntheticNodeSubclassData(unsigned IROrder, - ArgTypes &&... Args) { - // The compiler can reduce this expression to a constant iff we pass an - // empty DebugLoc. Thankfully, the debug location doesn't have any bearing - // on the subclass data. - return SDNodeT(IROrder, DebugLoc(), std::forward(Args)...) - .getRawSubclassData(); - } - - template - static uint16_t getSyntheticNodeSubclassData(unsigned Opc, unsigned Order, - SDVTList VTs, EVT MemoryVT, - MachineMemOperand *MMO) { - return SDNodeTy(Opc, Order, DebugLoc(), VTs, MemoryVT, MMO) - .getRawSubclassData(); - } - - void createOperands(SDNode *Node, ArrayRef Vals); - - void removeOperands(SDNode *Node) { - if (!Node->OperandList) - return; - OperandRecycler.deallocate( - ArrayRecycler::Capacity::get(Node->NumOperands), - Node->OperandList); - Node->NumOperands = 0; - Node->OperandList = nullptr; - } - void CreateTopologicalOrder(std::vector& Order); - -public: - // Maximum depth for recursive analysis such as computeKnownBits, etc. - static constexpr unsigned MaxRecursionDepth = 6; - - explicit SelectionDAG(const TargetMachine &TM, CodeGenOpt::Level); - SelectionDAG(const SelectionDAG &) = delete; - SelectionDAG &operator=(const SelectionDAG &) = delete; - ~SelectionDAG(); - - /// Prepare this SelectionDAG to process code in the given MachineFunction. - void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE, - Pass *PassPtr, const TargetLibraryInfo *LibraryInfo, - LegacyDivergenceAnalysis * Divergence, - ProfileSummaryInfo *PSIin, BlockFrequencyInfo *BFIin); - - void setFunctionLoweringInfo(FunctionLoweringInfo * FuncInfo) { - FLI = FuncInfo; - } - - /// Clear state and free memory necessary to make this - /// SelectionDAG ready to process a new block. - void clear(); - - MachineFunction &getMachineFunction() const { return *MF; } - const Pass *getPass() const { return SDAGISelPass; } - - const DataLayout &getDataLayout() const { return MF->getDataLayout(); } - const TargetMachine &getTarget() const { return TM; } - const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } - const TargetLowering &getTargetLoweringInfo() const { return *TLI; } - const TargetLibraryInfo &getLibInfo() const { return *LibInfo; } - const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } - const LegacyDivergenceAnalysis *getDivergenceAnalysis() const { return DA; } - LLVMContext *getContext() const { return Context; } - OptimizationRemarkEmitter &getORE() const { return *ORE; } - ProfileSummaryInfo *getPSI() const { return PSI; } - BlockFrequencyInfo *getBFI() const { return BFI; } - - FlagInserter *getFlagInserter() { return Inserter; } - void setFlagInserter(FlagInserter *FI) { Inserter = FI; } - - /// Just dump dot graph to a user-provided path and title. - /// This doesn't open the dot viewer program and - /// helps visualization when outside debugging session. - /// FileName expects absolute path. If provided - /// without any path separators then the file - /// will be created in the current directory. - /// Error will be emitted if the path is insane. -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dumpDotGraph(const Twine &FileName, const Twine &Title); -#endif - - /// Pop up a GraphViz/gv window with the DAG rendered using 'dot'. - void viewGraph(const std::string &Title); - void viewGraph(); - -#ifndef NDEBUG - std::map NodeGraphAttrs; -#endif - - /// Clear all previously defined node graph attributes. - /// Intended to be used from a debugging tool (eg. gdb). - void clearGraphAttrs(); - - /// Set graph attributes for a node. (eg. "color=red".) - void setGraphAttrs(const SDNode *N, const char *Attrs); - - /// Get graph attributes for a node. (eg. "color=red".) - /// Used from getNodeAttributes. - std::string getGraphAttrs(const SDNode *N) const; - - /// Convenience for setting node color attribute. - void setGraphColor(const SDNode *N, const char *Color); - - /// Convenience for setting subgraph color attribute. - void setSubgraphColor(SDNode *N, const char *Color); - - using allnodes_const_iterator = ilist::const_iterator; - - allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); } - allnodes_const_iterator allnodes_end() const { return AllNodes.end(); } - - using allnodes_iterator = ilist::iterator; - - allnodes_iterator allnodes_begin() { return AllNodes.begin(); } - allnodes_iterator allnodes_end() { return AllNodes.end(); } - - ilist::size_type allnodes_size() const { - return AllNodes.size(); - } - - iterator_range allnodes() { - return make_range(allnodes_begin(), allnodes_end()); - } - iterator_range allnodes() const { - return make_range(allnodes_begin(), allnodes_end()); - } - - /// Return the root tag of the SelectionDAG. - const SDValue &getRoot() const { return Root; } - - /// Return the token chain corresponding to the entry of the function. - SDValue getEntryNode() const { - return SDValue(const_cast(&EntryNode), 0); - } - - /// Set the current root tag of the SelectionDAG. - /// - const SDValue &setRoot(SDValue N) { - assert((!N.getNode() || N.getValueType() == MVT::Other) && - "DAG root value is not a chain!"); - if (N.getNode()) - checkForCycles(N.getNode(), this); - Root = N; - if (N.getNode()) - checkForCycles(this); - return Root; - } - -#ifndef NDEBUG - void VerifyDAGDivergence(); -#endif - - /// This iterates over the nodes in the SelectionDAG, folding - /// certain types of nodes together, or eliminating superfluous nodes. The - /// Level argument controls whether Combine is allowed to produce nodes and - /// types that are illegal on the target. - void Combine(CombineLevel Level, AAResults *AA, - CodeGenOpt::Level OptLevel); - - /// This transforms the SelectionDAG into a SelectionDAG that - /// only uses types natively supported by the target. - /// Returns "true" if it made any changes. - /// - /// Note that this is an involved process that may invalidate pointers into - /// the graph. - bool LegalizeTypes(); - - /// This transforms the SelectionDAG into a SelectionDAG that is - /// compatible with the target instruction selector, as indicated by the - /// TargetLowering object. - /// - /// Note that this is an involved process that may invalidate pointers into - /// the graph. - void Legalize(); - - /// Transforms a SelectionDAG node and any operands to it into a node - /// that is compatible with the target instruction selector, as indicated by - /// the TargetLowering object. - /// - /// \returns true if \c N is a valid, legal node after calling this. - /// - /// This essentially runs a single recursive walk of the \c Legalize process - /// over the given node (and its operands). This can be used to incrementally - /// legalize the DAG. All of the nodes which are directly replaced, - /// potentially including N, are added to the output parameter \c - /// UpdatedNodes so that the delta to the DAG can be understood by the - /// caller. - /// - /// When this returns false, N has been legalized in a way that make the - /// pointer passed in no longer valid. It may have even been deleted from the - /// DAG, and so it shouldn't be used further. When this returns true, the - /// N passed in is a legal node, and can be immediately processed as such. - /// This may still have done some work on the DAG, and will still populate - /// UpdatedNodes with any new nodes replacing those originally in the DAG. - bool LegalizeOp(SDNode *N, SmallSetVector &UpdatedNodes); - - /// This transforms the SelectionDAG into a SelectionDAG - /// that only uses vector math operations supported by the target. This is - /// necessary as a separate step from Legalize because unrolling a vector - /// operation can introduce illegal types, which requires running - /// LegalizeTypes again. - /// - /// This returns true if it made any changes; in that case, LegalizeTypes - /// is called again before Legalize. - /// - /// Note that this is an involved process that may invalidate pointers into - /// the graph. - bool LegalizeVectors(); - - /// This method deletes all unreachable nodes in the SelectionDAG. - void RemoveDeadNodes(); - - /// Remove the specified node from the system. This node must - /// have no referrers. - void DeleteNode(SDNode *N); - - /// Return an SDVTList that represents the list of values specified. - SDVTList getVTList(EVT VT); - SDVTList getVTList(EVT VT1, EVT VT2); - SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); - SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4); - SDVTList getVTList(ArrayRef VTs); - - //===--------------------------------------------------------------------===// - // Node creation methods. - - /// Create a ConstantSDNode wrapping a constant value. - /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR. - /// - /// If only legal types can be produced, this does the necessary - /// transformations (e.g., if the vector element type is illegal). - /// @{ - SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, - bool isTarget = false, bool isOpaque = false); - SDValue getConstant(const APInt &Val, const SDLoc &DL, EVT VT, - bool isTarget = false, bool isOpaque = false); - - SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget = false, - bool IsOpaque = false) { - return getConstant(APInt::getAllOnes(VT.getScalarSizeInBits()), DL, VT, - IsTarget, IsOpaque); - } - - SDValue getConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT, - bool isTarget = false, bool isOpaque = false); - SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, - bool isTarget = false); - SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL, - bool LegalTypes = true); - SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, - bool isTarget = false); - - SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, - bool isOpaque = false) { - return getConstant(Val, DL, VT, true, isOpaque); - } - SDValue getTargetConstant(const APInt &Val, const SDLoc &DL, EVT VT, - bool isOpaque = false) { - return getConstant(Val, DL, VT, true, isOpaque); - } - SDValue getTargetConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT, - bool isOpaque = false) { - return getConstant(Val, DL, VT, true, isOpaque); - } - - /// Create a true or false constant of type \p VT using the target's - /// BooleanContent for type \p OpVT. - SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT); - /// @} - - /// Create a ConstantFPSDNode wrapping a constant value. - /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR. - /// - /// If only legal types can be produced, this does the necessary - /// transformations (e.g., if the vector element type is illegal). - /// The forms that take a double should only be used for simple constants - /// that can be exactly represented in VT. No checks are made. - /// @{ - SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, - bool isTarget = false); - SDValue getConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT, - bool isTarget = false); - SDValue getConstantFP(const ConstantFP &V, const SDLoc &DL, EVT VT, - bool isTarget = false); - SDValue getTargetConstantFP(double Val, const SDLoc &DL, EVT VT) { - return getConstantFP(Val, DL, VT, true); - } - SDValue getTargetConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT) { - return getConstantFP(Val, DL, VT, true); - } - SDValue getTargetConstantFP(const ConstantFP &Val, const SDLoc &DL, EVT VT) { - return getConstantFP(Val, DL, VT, true); - } - /// @} - - SDValue getGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, - int64_t offset = 0, bool isTargetGA = false, - unsigned TargetFlags = 0); - SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, - int64_t offset = 0, unsigned TargetFlags = 0) { - return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags); - } - SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false); - SDValue getTargetFrameIndex(int FI, EVT VT) { - return getFrameIndex(FI, VT, true); - } - SDValue getJumpTable(int JTI, EVT VT, bool isTarget = false, - unsigned TargetFlags = 0); - SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags = 0) { - return getJumpTable(JTI, VT, true, TargetFlags); - } - SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align = None, - int Offs = 0, bool isT = false, - unsigned TargetFlags = 0); - SDValue getTargetConstantPool(const Constant *C, EVT VT, - MaybeAlign Align = None, int Offset = 0, - unsigned TargetFlags = 0) { - return getConstantPool(C, VT, Align, Offset, true, TargetFlags); - } - SDValue getConstantPool(MachineConstantPoolValue *C, EVT VT, - MaybeAlign Align = None, int Offs = 0, - bool isT = false, unsigned TargetFlags = 0); - SDValue getTargetConstantPool(MachineConstantPoolValue *C, EVT VT, - MaybeAlign Align = None, int Offset = 0, - unsigned TargetFlags = 0) { - return getConstantPool(C, VT, Align, Offset, true, TargetFlags); - } - SDValue getTargetIndex(int Index, EVT VT, int64_t Offset = 0, - unsigned TargetFlags = 0); - // When generating a branch to a BB, we don't in general know enough - // to provide debug info for the BB at that time, so keep this one around. - SDValue getBasicBlock(MachineBasicBlock *MBB); - SDValue getExternalSymbol(const char *Sym, EVT VT); - SDValue getTargetExternalSymbol(const char *Sym, EVT VT, - unsigned TargetFlags = 0); - SDValue getMCSymbol(MCSymbol *Sym, EVT VT); - - SDValue getValueType(EVT); - SDValue getRegister(unsigned Reg, EVT VT); - SDValue getRegisterMask(const uint32_t *RegMask); - SDValue getEHLabel(const SDLoc &dl, SDValue Root, MCSymbol *Label); - SDValue getLabelNode(unsigned Opcode, const SDLoc &dl, SDValue Root, - MCSymbol *Label); - SDValue getBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset = 0, - bool isTarget = false, unsigned TargetFlags = 0); - SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, - int64_t Offset = 0, unsigned TargetFlags = 0) { - return getBlockAddress(BA, VT, Offset, true, TargetFlags); - } - - SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, - SDValue N) { - return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, - getRegister(Reg, N.getValueType()), N); - } - - // This version of the getCopyToReg method takes an extra operand, which - // indicates that there is potentially an incoming glue value (if Glue is not - // null) and that there should be a glue result. - SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N, - SDValue Glue) { - SDVTList VTs = getVTList(MVT::Other, MVT::Glue); - SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; - return getNode(ISD::CopyToReg, dl, VTs, - makeArrayRef(Ops, Glue.getNode() ? 4 : 3)); - } - - // Similar to last getCopyToReg() except parameter Reg is a SDValue - SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, SDValue Reg, SDValue N, - SDValue Glue) { - SDVTList VTs = getVTList(MVT::Other, MVT::Glue); - SDValue Ops[] = { Chain, Reg, N, Glue }; - return getNode(ISD::CopyToReg, dl, VTs, - makeArrayRef(Ops, Glue.getNode() ? 4 : 3)); - } - - SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT) { - SDVTList VTs = getVTList(VT, MVT::Other); - SDValue Ops[] = { Chain, getRegister(Reg, VT) }; - return getNode(ISD::CopyFromReg, dl, VTs, Ops); - } - - // This version of the getCopyFromReg method takes an extra operand, which - // indicates that there is potentially an incoming glue value (if Glue is not - // null) and that there should be a glue result. - SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT, - SDValue Glue) { - SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); - SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; - return getNode(ISD::CopyFromReg, dl, VTs, - makeArrayRef(Ops, Glue.getNode() ? 3 : 2)); - } - - SDValue getCondCode(ISD::CondCode Cond); - - /// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT, - /// which must be a vector type, must match the number of mask elements - /// NumElts. An integer mask element equal to -1 is treated as undefined. - SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, - ArrayRef Mask); - - /// Return an ISD::BUILD_VECTOR node. The number of elements in VT, - /// which must be a vector type, must match the number of operands in Ops. - /// The operands must have the same type as (or, for integers, a type wider - /// than) VT's element type. - SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef Ops) { - // VerifySDNode (via InsertNode) checks BUILD_VECTOR later. - return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); - } - - /// Return an ISD::BUILD_VECTOR node. The number of elements in VT, - /// which must be a vector type, must match the number of operands in Ops. - /// The operands must have the same type as (or, for integers, a type wider - /// than) VT's element type. - SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef Ops) { - // VerifySDNode (via InsertNode) checks BUILD_VECTOR later. - return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); - } - - /// Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all - /// elements. VT must be a vector type. Op's type must be the same as (or, - /// for integers, a type wider than) VT's element type. - SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op) { - // VerifySDNode (via InsertNode) checks BUILD_VECTOR later. - if (Op.getOpcode() == ISD::UNDEF) { - assert((VT.getVectorElementType() == Op.getValueType() || - (VT.isInteger() && - VT.getVectorElementType().bitsLE(Op.getValueType()))) && - "A splatted value must have a width equal or (for integers) " - "greater than the vector element type!"); - return getNode(ISD::UNDEF, SDLoc(), VT); - } - - SmallVector Ops(VT.getVectorNumElements(), Op); - return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); - } - - // Return a splat ISD::SPLAT_VECTOR node, consisting of Op splatted to all - // elements. - SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op) { - if (Op.getOpcode() == ISD::UNDEF) { - assert((VT.getVectorElementType() == Op.getValueType() || - (VT.isInteger() && - VT.getVectorElementType().bitsLE(Op.getValueType()))) && - "A splatted value must have a width equal or (for integers) " - "greater than the vector element type!"); - return getNode(ISD::UNDEF, SDLoc(), VT); - } - return getNode(ISD::SPLAT_VECTOR, DL, VT, Op); - } - - /// Returns a vector of type ResVT whose elements contain the linear sequence - /// <0, Step, Step * 2, Step * 3, ...> - SDValue getStepVector(const SDLoc &DL, EVT ResVT, APInt StepVal); - - /// Returns a vector of type ResVT whose elements contain the linear sequence - /// <0, 1, 2, 3, ...> - SDValue getStepVector(const SDLoc &DL, EVT ResVT); - - /// Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to - /// the shuffle node in input but with swapped operands. - /// - /// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3> - SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV); - - /// Convert Op, which must be of float type, to the - /// float type VT, by either extending or rounding (by truncation). - SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be a STRICT operation of float type, to the - /// float type VT, by either extending or rounding (by truncation). - std::pair - getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be of integer type, to the - /// integer type VT, by either any-extending or truncating it. - SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be of integer type, to the - /// integer type VT, by either sign-extending or truncating it. - SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be of integer type, to the - /// integer type VT, by either zero-extending or truncating it. - SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); - - /// Return the expression required to zero extend the Op - /// value assuming it was the smaller SrcTy value. - SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be of integer type, to the integer type VT, by - /// either truncating it or performing either zero or sign extension as - /// appropriate extension for the pointer's semantics. - SDValue getPtrExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); - - /// Return the expression required to extend the Op as a pointer value - /// assuming it was the smaller SrcTy value. This may be either a zero extend - /// or a sign extend. - SDValue getPtrExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); - - /// Convert Op, which must be of integer type, to the integer type VT, - /// by using an extension appropriate for the target's - /// BooleanContent for type OpVT or truncating it. - SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT); - - /// Create a bitwise NOT operation as (XOR Val, -1). - SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT); - - /// Create a logical NOT operation as (XOR Val, BooleanOne). - SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT); - - /// Returns sum of the base pointer and offset. - /// Unlike getObjectPtrOffset this does not set NoUnsignedWrap by default. - SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, - const SDNodeFlags Flags = SDNodeFlags()); - SDValue getMemBasePlusOffset(SDValue Base, SDValue Offset, const SDLoc &DL, - const SDNodeFlags Flags = SDNodeFlags()); - - /// Create an add instruction with appropriate flags when used for - /// addressing some offset of an object. i.e. if a load is split into multiple - /// components, create an add nuw from the base pointer to the offset. - SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset) { - SDNodeFlags Flags; - Flags.setNoUnsignedWrap(true); - return getMemBasePlusOffset(Ptr, Offset, SL, Flags); - } - - SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, SDValue Offset) { - // The object itself can't wrap around the address space, so it shouldn't be - // possible for the adds of the offsets to the split parts to overflow. - SDNodeFlags Flags; - Flags.setNoUnsignedWrap(true); - return getMemBasePlusOffset(Ptr, Offset, SL, Flags); - } - - /// Return a new CALLSEQ_START node, that starts new call frame, in which - /// InSize bytes are set up inside CALLSEQ_START..CALLSEQ_END sequence and - /// OutSize specifies part of the frame set up prior to the sequence. - SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, - const SDLoc &DL) { - SDVTList VTs = getVTList(MVT::Other, MVT::Glue); - SDValue Ops[] = { Chain, - getIntPtrConstant(InSize, DL, true), - getIntPtrConstant(OutSize, DL, true) }; - return getNode(ISD::CALLSEQ_START, DL, VTs, Ops); - } - - /// Return a new CALLSEQ_END node, which always must have a - /// glue result (to ensure it's not CSE'd). - /// CALLSEQ_END does not have a useful SDLoc. - SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, - SDValue InGlue, const SDLoc &DL) { - SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); - SmallVector Ops; - Ops.push_back(Chain); - Ops.push_back(Op1); - Ops.push_back(Op2); - if (InGlue.getNode()) - Ops.push_back(InGlue); - return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops); - } - - /// Return true if the result of this operation is always undefined. - bool isUndef(unsigned Opcode, ArrayRef Ops); - - /// Return an UNDEF node. UNDEF does not have a useful SDLoc. - SDValue getUNDEF(EVT VT) { - return getNode(ISD::UNDEF, SDLoc(), VT); - } - - /// Return a node that represents the runtime scaling 'MulImm * RuntimeVL'. - SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm) { - assert(MulImm.getMinSignedBits() <= VT.getSizeInBits() && - "Immediate does not fit VT"); - return getNode(ISD::VSCALE, DL, VT, - getConstant(MulImm.sextOrTrunc(VT.getSizeInBits()), DL, VT)); - } - - /// Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc. - SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { - return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), VT); - } - - /// Gets or creates the specified node. - /// - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, - ArrayRef Ops, const SDNodeFlags Flags); - SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef ResultTys, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, - ArrayRef Ops, const SDNodeFlags Flags); - - // Use flags from current flag inserter. - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3); - - // Specialize based on number of operands. - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand, - const SDNodeFlags Flags); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, const SDNodeFlags Flags); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3, const SDNodeFlags Flags); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3, SDValue N4, SDValue N5); - - // Specialize again based on number of operands for nodes with a VTList - // rather than a single VT. - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, - SDValue N2); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, - SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, - SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, - SDValue N2, SDValue N3, SDValue N4, SDValue N5); - - /// Compute a TokenFactor to force all the incoming stack arguments to be - /// loaded from the stack. This is used in tail call lowering to protect - /// stack arguments from being clobbered. - SDValue getStackArgumentTokenFactor(SDValue Chain); - - SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, - SDValue Size, Align Alignment, bool isVol, - bool AlwaysInline, bool isTailCall, - MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo, - const AAMDNodes &AAInfo = AAMDNodes()); - - SDValue getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, - SDValue Size, Align Alignment, bool isVol, bool isTailCall, - MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo, - const AAMDNodes &AAInfo = AAMDNodes()); - - SDValue getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, - SDValue Size, Align Alignment, bool isVol, bool isTailCall, - MachinePointerInfo DstPtrInfo, - const AAMDNodes &AAInfo = AAMDNodes()); - - SDValue getAtomicMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, - unsigned DstAlign, SDValue Src, unsigned SrcAlign, - SDValue Size, Type *SizeTy, unsigned ElemSz, - bool isTailCall, MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo); - - SDValue getAtomicMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, - unsigned DstAlign, SDValue Src, unsigned SrcAlign, - SDValue Size, Type *SizeTy, unsigned ElemSz, - bool isTailCall, MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo); - - SDValue getAtomicMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, - unsigned DstAlign, SDValue Value, SDValue Size, - Type *SizeTy, unsigned ElemSz, bool isTailCall, - MachinePointerInfo DstPtrInfo); - - /// Helper function to make it easier to build SetCC's if you just have an - /// ISD::CondCode instead of an SDValue. - SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, - ISD::CondCode Cond, SDValue Chain = SDValue(), - bool IsSignaling = false) { - assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() && - "Cannot compare scalars to vectors"); - assert(LHS.getValueType().isVector() == VT.isVector() && - "Cannot compare scalars to vectors"); - assert(Cond != ISD::SETCC_INVALID && - "Cannot create a setCC of an invalid node."); - if (Chain) - return getNode(IsSignaling ? ISD::STRICT_FSETCCS : ISD::STRICT_FSETCC, DL, - {VT, MVT::Other}, {Chain, LHS, RHS, getCondCode(Cond)}); - return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); - } - - /// Helper function to make it easier to build Select's if you just have - /// operands and don't want to check for vector. - SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, - SDValue RHS) { - assert(LHS.getValueType() == RHS.getValueType() && - "Cannot use select on differing types"); - assert(VT.isVector() == LHS.getValueType().isVector() && - "Cannot mix vectors and scalars"); - auto Opcode = Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT; - return getNode(Opcode, DL, VT, Cond, LHS, RHS); - } - - /// Helper function to make it easier to build SelectCC's if you just have an - /// ISD::CondCode instead of an SDValue. - SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, - SDValue False, ISD::CondCode Cond) { - return getNode(ISD::SELECT_CC, DL, True.getValueType(), LHS, RHS, True, - False, getCondCode(Cond)); - } - - /// Try to simplify a select/vselect into 1 of its operands or a constant. - SDValue simplifySelect(SDValue Cond, SDValue TVal, SDValue FVal); - - /// Try to simplify a shift into 1 of its operands or a constant. - SDValue simplifyShift(SDValue X, SDValue Y); - - /// Try to simplify a floating-point binary operation into 1 of its operands - /// or a constant. - SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y, - SDNodeFlags Flags); - - /// VAArg produces a result and token chain, and takes a pointer - /// and a source value as input. - SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - SDValue SV, unsigned Align); - - /// Gets a node for an atomic cmpxchg op. There are two - /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a - /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, - /// a success flag (initially i1), and a chain. - SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT, - SDVTList VTs, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, MachineMemOperand *MMO); - - /// Gets a node for an atomic op, produces result (if relevant) - /// and chain and takes 2 operands. - SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Val, MachineMemOperand *MMO); - - /// Gets a node for an atomic op, produces result and chain and - /// takes 1 operand. - SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, EVT VT, - SDValue Chain, SDValue Ptr, MachineMemOperand *MMO); - - /// Gets a node for an atomic op, produces result and chain and takes N - /// operands. - SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, - SDVTList VTList, ArrayRef Ops, - MachineMemOperand *MMO); - - /// Creates a MemIntrinsicNode that may produce a - /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, - /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not - /// less than FIRST_TARGET_MEMORY_OPCODE. - SDValue getMemIntrinsicNode( - unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef Ops, - EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, - MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | - MachineMemOperand::MOStore, - uint64_t Size = 0, const AAMDNodes &AAInfo = AAMDNodes()); - - inline SDValue getMemIntrinsicNode( - unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef Ops, - EVT MemVT, MachinePointerInfo PtrInfo, MaybeAlign Alignment = None, - MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | - MachineMemOperand::MOStore, - uint64_t Size = 0, const AAMDNodes &AAInfo = AAMDNodes()) { - // Ensure that codegen never sees alignment 0 - return getMemIntrinsicNode(Opcode, dl, VTList, Ops, MemVT, PtrInfo, - Alignment.getValueOr(getEVTAlign(MemVT)), Flags, - Size, AAInfo); - } - - SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, - ArrayRef Ops, EVT MemVT, - MachineMemOperand *MMO); - - /// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends - /// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between - /// offsets `Offset` and `Offset + Size`. - SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain, - int FrameIndex, int64_t Size, int64_t Offset = -1); - - /// Creates a PseudoProbeSDNode with function GUID `Guid` and - /// the index of the block `Index` it is probing, as well as the attributes - /// `attr` of the probe. - SDValue getPseudoProbeNode(const SDLoc &Dl, SDValue Chain, uint64_t Guid, - uint64_t Index, uint32_t Attr); - - /// Create a MERGE_VALUES node from the given operands. - SDValue getMergeValues(ArrayRef Ops, const SDLoc &dl); - - /// Loads are not normal binary operators: their result type is not - /// determined by their operands, and they produce a value AND a token chain. - /// - /// This function will set the MOLoad flag on MMOFlags, but you can set it if - /// you want. The MOStore flag must not be set. - SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - MachinePointerInfo PtrInfo, - MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr); - /// FIXME: Remove once transition to Align is over. - inline SDValue - getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - MachinePointerInfo PtrInfo, unsigned Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr) { - return getLoad(VT, dl, Chain, Ptr, PtrInfo, MaybeAlign(Alignment), MMOFlags, - AAInfo, Ranges); - } - SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - MachineMemOperand *MMO); - SDValue - getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, - SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, - MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()); - /// FIXME: Remove once transition to Align is over. - inline SDValue - getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, - SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, - unsigned Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()) { - return getExtLoad(ExtType, dl, VT, Chain, Ptr, PtrInfo, MemVT, - MaybeAlign(Alignment), MMOFlags, AAInfo); - } - SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, - SDValue Chain, SDValue Ptr, EVT MemVT, - MachineMemOperand *MMO); - SDValue getIndexedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, - SDValue Offset, ISD::MemIndexedMode AM); - SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr); - inline SDValue getLoad( - ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, - SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, - EVT MemVT, MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr) { - // Ensures that codegen never sees a None Alignment. - return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, PtrInfo, MemVT, - Alignment.getValueOr(getEVTAlign(MemVT)), MMOFlags, AAInfo, - Ranges); - } - /// FIXME: Remove once transition to Align is over. - inline SDValue - getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - MachinePointerInfo PtrInfo, EVT MemVT, unsigned Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr) { - return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, PtrInfo, MemVT, - MaybeAlign(Alignment), MMOFlags, AAInfo, Ranges); - } - SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - EVT MemVT, MachineMemOperand *MMO); - - /// Helper function to build ISD::STORE nodes. - /// - /// This function will set the MOStore flag on MMOFlags, but you can set it if - /// you want. The MOLoad and MOInvariant flags must not be set. - - SDValue - getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, Align Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()); - inline SDValue - getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()) { - return getStore(Chain, dl, Val, Ptr, PtrInfo, - Alignment.getValueOr(getEVTAlign(Val.getValueType())), - MMOFlags, AAInfo); - } - /// FIXME: Remove once transition to Align is over. - inline SDValue - getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, unsigned Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()) { - return getStore(Chain, dl, Val, Ptr, PtrInfo, MaybeAlign(Alignment), - MMOFlags, AAInfo); - } - SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachineMemOperand *MMO); - SDValue - getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()); - inline SDValue - getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT SVT, - MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()) { - return getTruncStore(Chain, dl, Val, Ptr, PtrInfo, SVT, - Alignment.getValueOr(getEVTAlign(SVT)), MMOFlags, - AAInfo); - } - /// FIXME: Remove once transition to Align is over. - inline SDValue - getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes()) { - return getTruncStore(Chain, dl, Val, Ptr, PtrInfo, SVT, - MaybeAlign(Alignment), MMOFlags, AAInfo); - } - SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, - SDValue Ptr, EVT SVT, MachineMemOperand *MMO); - SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, - SDValue Offset, ISD::MemIndexedMode AM); - - SDValue getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, - EVT MemVT, Align Alignment, - MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo, - const MDNode *Ranges = nullptr, bool IsExpanding = false); - inline SDValue - getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, EVT MemVT, - MaybeAlign Alignment = MaybeAlign(), - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr, bool IsExpanding = false) { - // Ensures that codegen never sees a None Alignment. - return getLoadVP(AM, ExtType, VT, dl, Chain, Ptr, Offset, Mask, EVL, - PtrInfo, MemVT, Alignment.getValueOr(getEVTAlign(MemVT)), - MMOFlags, AAInfo, Ranges, IsExpanding); - } - SDValue getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - SDValue Mask, SDValue EVL, EVT MemVT, - MachineMemOperand *MMO, bool IsExpanding = false); - SDValue getLoadVP(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, - MaybeAlign Alignment, MachineMemOperand::Flags MMOFlags, - const AAMDNodes &AAInfo, const MDNode *Ranges = nullptr, - bool IsExpanding = false); - SDValue getLoadVP(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - SDValue Mask, SDValue EVL, MachineMemOperand *MMO, - bool IsExpanding = false); - SDValue getExtLoadVP(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, - SDValue Chain, SDValue Ptr, SDValue Mask, SDValue EVL, - MachinePointerInfo PtrInfo, EVT MemVT, - MaybeAlign Alignment, MachineMemOperand::Flags MMOFlags, - const AAMDNodes &AAInfo, bool IsExpanding = false); - SDValue getExtLoadVP(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, - SDValue Chain, SDValue Ptr, SDValue Mask, SDValue EVL, - EVT MemVT, MachineMemOperand *MMO, - bool IsExpanding = false); - SDValue getIndexedLoadVP(SDValue OrigLoad, const SDLoc &dl, SDValue Base, - SDValue Offset, ISD::MemIndexedMode AM); - SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexedMode AM, - bool IsTruncating = false, bool IsCompressing = false); - SDValue getTruncStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, - SDValue Ptr, SDValue Mask, SDValue EVL, - MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, - MachineMemOperand::Flags MMOFlags, - const AAMDNodes &AAInfo, bool IsCompressing = false); - SDValue getTruncStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, - SDValue Ptr, SDValue Mask, SDValue EVL, EVT SVT, - MachineMemOperand *MMO, bool IsCompressing = false); - SDValue getIndexedStoreVP(SDValue OrigStore, const SDLoc &dl, SDValue Base, - SDValue Offset, ISD::MemIndexedMode AM); - - SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, - ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType); - SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, - ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType); - - SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, - SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexedMode AM, - ISD::LoadExtType, bool IsExpanding = false); - SDValue getIndexedMaskedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, - SDValue Offset, ISD::MemIndexedMode AM); - SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, - SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexedMode AM, - bool IsTruncating = false, bool IsCompressing = false); - SDValue getIndexedMaskedStore(SDValue OrigStore, const SDLoc &dl, - SDValue Base, SDValue Offset, - ISD::MemIndexedMode AM); - SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, - ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy); - SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, - ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType, - bool IsTruncating = false); - - /// Construct a node to track a Value* through the backend. - SDValue getSrcValue(const Value *v); - - /// Return an MDNodeSDNode which holds an MDNode. - SDValue getMDNode(const MDNode *MD); - - /// Return a bitcast using the SDLoc of the value operand, and casting to the - /// provided type. Use getNode to set a custom SDLoc. - SDValue getBitcast(EVT VT, SDValue V); - - /// Return an AddrSpaceCastSDNode. - SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, - unsigned DestAS); - - /// Return a freeze using the SDLoc of the value operand. - SDValue getFreeze(SDValue V); - - /// Return an AssertAlignSDNode. - SDValue getAssertAlign(const SDLoc &DL, SDValue V, Align A); - - /// Return the specified value casted to - /// the target's desired shift amount type. - SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); - - /// Expand the specified \c ISD::VAARG node as the Legalize pass would. - SDValue expandVAArg(SDNode *Node); - - /// Expand the specified \c ISD::VACOPY node as the Legalize pass would. - SDValue expandVACopy(SDNode *Node); - - /// Returns an GlobalAddress of the function from the current module with - /// name matching the given ExternalSymbol. Additionally can provide the - /// matched function. - /// Panics the function doesn't exists. - SDValue getSymbolFunctionGlobalAddress(SDValue Op, - Function **TargetFunction = nullptr); - - /// *Mutate* the specified node in-place to have the - /// specified operands. If the resultant node already exists in the DAG, - /// this does not modify the specified node, instead it returns the node that - /// already exists. If the resultant node does not exist in the DAG, the - /// input node is returned. As a degenerate case, if you specify the same - /// input operands as the node already has, the input node is returned. - SDNode *UpdateNodeOperands(SDNode *N, SDValue Op); - SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2); - SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, - SDValue Op3); - SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, - SDValue Op3, SDValue Op4); - SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, - SDValue Op3, SDValue Op4, SDValue Op5); - SDNode *UpdateNodeOperands(SDNode *N, ArrayRef Ops); - - /// Creates a new TokenFactor containing \p Vals. If \p Vals contains 64k - /// values or more, move values into new TokenFactors in 64k-1 blocks, until - /// the final TokenFactor has less than 64k operands. - SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl &Vals); - - /// *Mutate* the specified machine node's memory references to the provided - /// list. - void setNodeMemRefs(MachineSDNode *N, - ArrayRef NewMemRefs); - - // Calculate divergence of node \p N based on its operands. - bool calculateDivergence(SDNode *N); - - // Propagates the change in divergence to users - void updateDivergence(SDNode * N); - - /// These are used for target selectors to *mutate* the - /// specified node to have the specified return type, Target opcode, and - /// operands. Note that target opcodes are stored as - /// ~TargetOpcode in the node opcode field. The resultant node is returned. - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, SDValue Op1); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, - SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, - SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, - ArrayRef Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, - EVT VT2, ArrayRef Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, - EVT VT2, EVT VT3, ArrayRef Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, - EVT VT2, SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, SDVTList VTs, - ArrayRef Ops); - - /// This *mutates* the specified node to have the specified - /// return type, opcode, and operands. - SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, - ArrayRef Ops); - - /// Mutate the specified strict FP node to its non-strict equivalent, - /// unlinking the node from its chain and dropping the metadata arguments. - /// The node must be a strict FP node. - SDNode *mutateStrictFPToFP(SDNode *Node); - - /// These are used for target selectors to create a new node - /// with specified return type(s), MachineInstr opcode, and operands. - /// - /// Note that getMachineNode returns the resultant node. If there is already - /// a node of the specified opcode and operands, it returns that node instead - /// of the current one. - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT, - SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT, - SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT, - SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT, - ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, EVT VT3, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, - SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1, - EVT VT2, EVT VT3, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, - ArrayRef ResultTys, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, SDVTList VTs, - ArrayRef Ops); - - /// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes. - SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, - SDValue Operand); - - /// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes. - SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, - SDValue Operand, SDValue Subreg); - - /// Get the specified node if it's already available, or else return NULL. - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, - ArrayRef Ops, const SDNodeFlags Flags); - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, - ArrayRef Ops); - - /// Check if a node exists without modifying its flags. - bool doesNodeExist(unsigned Opcode, SDVTList VTList, ArrayRef Ops); - - /// Creates a SDDbgValue node. - SDDbgValue *getDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, - unsigned R, bool IsIndirect, const DebugLoc &DL, - unsigned O); - - /// Creates a constant SDDbgValue node. - SDDbgValue *getConstantDbgValue(DIVariable *Var, DIExpression *Expr, - const Value *C, const DebugLoc &DL, - unsigned O); - - /// Creates a FrameIndex SDDbgValue node. - SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr, - unsigned FI, bool IsIndirect, - const DebugLoc &DL, unsigned O); - - /// Creates a FrameIndex SDDbgValue node. - SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr, - unsigned FI, - ArrayRef Dependencies, - bool IsIndirect, const DebugLoc &DL, - unsigned O); - - /// Creates a VReg SDDbgValue node. - SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr, - unsigned VReg, bool IsIndirect, - const DebugLoc &DL, unsigned O); - - /// Creates a SDDbgValue node from a list of locations. - SDDbgValue *getDbgValueList(DIVariable *Var, DIExpression *Expr, - ArrayRef Locs, - ArrayRef Dependencies, bool IsIndirect, - const DebugLoc &DL, unsigned O, bool IsVariadic); - - /// Creates a SDDbgLabel node. - SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O); - - /// Transfer debug values from one node to another, while optionally - /// generating fragment expressions for split-up values. If \p InvalidateDbg - /// is set, debug values are invalidated after they are transferred. - void transferDbgValues(SDValue From, SDValue To, unsigned OffsetInBits = 0, - unsigned SizeInBits = 0, bool InvalidateDbg = true); - - /// Remove the specified node from the system. If any of its - /// operands then becomes dead, remove them as well. Inform UpdateListener - /// for each node deleted. - void RemoveDeadNode(SDNode *N); - - /// This method deletes the unreachable nodes in the - /// given list, and any nodes that become unreachable as a result. - void RemoveDeadNodes(SmallVectorImpl &DeadNodes); - - /// Modify anything using 'From' to use 'To' instead. - /// This can cause recursive merging of nodes in the DAG. Use the first - /// version if 'From' is known to have a single result, use the second - /// if you have two nodes with identical results (or if 'To' has a superset - /// of the results of 'From'), use the third otherwise. - /// - /// These methods all take an optional UpdateListener, which (if not null) is - /// informed about nodes that are deleted and modified due to recursive - /// changes in the dag. - /// - /// These functions only replace all existing uses. It's possible that as - /// these replacements are being performed, CSE may cause the From node - /// to be given new uses. These new uses of From are left in place, and - /// not automatically transferred to To. - /// - void ReplaceAllUsesWith(SDValue From, SDValue To); - void ReplaceAllUsesWith(SDNode *From, SDNode *To); - void ReplaceAllUsesWith(SDNode *From, const SDValue *To); - - /// Replace any uses of From with To, leaving - /// uses of other values produced by From.getNode() alone. - void ReplaceAllUsesOfValueWith(SDValue From, SDValue To); - - /// Like ReplaceAllUsesOfValueWith, but for multiple values at once. - /// This correctly handles the case where - /// there is an overlap between the From values and the To values. - void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, - unsigned Num); - - /// If an existing load has uses of its chain, create a token factor node with - /// that chain and the new memory node's chain and update users of the old - /// chain to the token factor. This ensures that the new memory node will have - /// the same relative memory dependency position as the old load. Returns the - /// new merged load chain. - SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain); - - /// If an existing load has uses of its chain, create a token factor node with - /// that chain and the new memory node's chain and update users of the old - /// chain to the token factor. This ensures that the new memory node will have - /// the same relative memory dependency position as the old load. Returns the - /// new merged load chain. - SDValue makeEquivalentMemoryOrdering(LoadSDNode *OldLoad, SDValue NewMemOp); - - /// Topological-sort the AllNodes list and a - /// assign a unique node id for each node in the DAG based on their - /// topological order. Returns the number of nodes. - unsigned AssignTopologicalOrder(); - - /// Move node N in the AllNodes list to be immediately - /// before the given iterator Position. This may be used to update the - /// topological ordering when the list of nodes is modified. - void RepositionNode(allnodes_iterator Position, SDNode *N) { - AllNodes.insert(Position, AllNodes.remove(N)); - } - - /// Returns an APFloat semantics tag appropriate for the given type. If VT is - /// a vector type, the element semantics are returned. - static const fltSemantics &EVTToAPFloatSemantics(EVT VT) { - switch (VT.getScalarType().getSimpleVT().SimpleTy) { - default: llvm_unreachable("Unknown FP format"); - case MVT::f16: return APFloat::IEEEhalf(); - case MVT::bf16: return APFloat::BFloat(); - case MVT::f32: return APFloat::IEEEsingle(); - case MVT::f64: return APFloat::IEEEdouble(); - case MVT::f80: return APFloat::x87DoubleExtended(); - case MVT::f128: return APFloat::IEEEquad(); - case MVT::ppcf128: return APFloat::PPCDoubleDouble(); - } - } - - /// Add a dbg_value SDNode. If SD is non-null that means the - /// value is produced by SD. - void AddDbgValue(SDDbgValue *DB, bool isParameter); - - /// Add a dbg_label SDNode. - void AddDbgLabel(SDDbgLabel *DB); - - /// Get the debug values which reference the given SDNode. - ArrayRef GetDbgValues(const SDNode* SD) const { - return DbgInfo->getSDDbgValues(SD); - } - -public: - /// Return true if there are any SDDbgValue nodes associated - /// with this SelectionDAG. - bool hasDebugValues() const { return !DbgInfo->empty(); } - - SDDbgInfo::DbgIterator DbgBegin() const { return DbgInfo->DbgBegin(); } - SDDbgInfo::DbgIterator DbgEnd() const { return DbgInfo->DbgEnd(); } - - SDDbgInfo::DbgIterator ByvalParmDbgBegin() const { - return DbgInfo->ByvalParmDbgBegin(); - } - SDDbgInfo::DbgIterator ByvalParmDbgEnd() const { - return DbgInfo->ByvalParmDbgEnd(); - } - - SDDbgInfo::DbgLabelIterator DbgLabelBegin() const { - return DbgInfo->DbgLabelBegin(); - } - SDDbgInfo::DbgLabelIterator DbgLabelEnd() const { - return DbgInfo->DbgLabelEnd(); - } - - /// To be invoked on an SDNode that is slated to be erased. This - /// function mirrors \c llvm::salvageDebugInfo. - void salvageDebugInfo(SDNode &N); - - /// Signal whether instruction referencing variable locations are desired for - /// this function's debug-info. - void useInstrRefDebugInfo(bool Flag) { - UseInstrRefDebugInfo = Flag; - } - - bool getUseInstrRefDebugInfo() const { - return UseInstrRefDebugInfo; - } - - void dump() const; - - /// In most cases this function returns the ABI alignment for a given type, - /// except for illegal vector types where the alignment exceeds that of the - /// stack. In such cases we attempt to break the vector down to a legal type - /// and return the ABI alignment for that instead. - Align getReducedAlign(EVT VT, bool UseABI); - - /// Create a stack temporary based on the size in bytes and the alignment - SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment); - - /// Create a stack temporary, suitable for holding the specified value type. - /// If minAlign is specified, the slot size will have at least that alignment. - SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); - - /// Create a stack temporary suitable for holding either of the specified - /// value types. - SDValue CreateStackTemporary(EVT VT1, EVT VT2); - - SDValue FoldSymbolOffset(unsigned Opcode, EVT VT, - const GlobalAddressSDNode *GA, - const SDNode *N2); - - SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, - ArrayRef Ops); - - /// Fold floating-point operations with 2 operands when both operands are - /// constants and/or undefined. - SDValue foldConstantFPMath(unsigned Opcode, const SDLoc &DL, EVT VT, - SDValue N1, SDValue N2); - - /// Constant fold a setcc to true or false. - SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, - const SDLoc &dl); - - /// See if the specified operand can be simplified with the knowledge that - /// only the bits specified by DemandedBits are used. If so, return the - /// simpler operand, otherwise return a null SDValue. - /// - /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can - /// simplify nodes with multiple uses more aggressively.) - SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits); - - /// See if the specified operand can be simplified with the knowledge that - /// only the bits specified by DemandedBits are used in the elements specified - /// by DemandedElts. If so, return the simpler operand, otherwise return a - /// null SDValue. - /// - /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can - /// simplify nodes with multiple uses more aggressively.) - SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits, - const APInt &DemandedElts); - - /// Return true if the sign bit of Op is known to be zero. - /// We use this predicate to simplify operations downstream. - bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const; - - /// Return true if 'Op & Mask' is known to be zero. We - /// use this predicate to simplify operations downstream. Op and Mask are - /// known to be the same type. - bool MaskedValueIsZero(SDValue Op, const APInt &Mask, - unsigned Depth = 0) const; - - /// Return true if 'Op & Mask' is known to be zero in DemandedElts. We - /// use this predicate to simplify operations downstream. Op and Mask are - /// known to be the same type. - bool MaskedValueIsZero(SDValue Op, const APInt &Mask, - const APInt &DemandedElts, unsigned Depth = 0) const; - - /// Return true if '(Op & Mask) == Mask'. - /// Op and Mask are known to be the same type. - bool MaskedValueIsAllOnes(SDValue Op, const APInt &Mask, - unsigned Depth = 0) const; - - /// Determine which bits of Op are known to be either zero or one and return - /// them in Known. For vectors, the known bits are those that are shared by - /// every vector element. - /// Targets can implement the computeKnownBitsForTargetNode method in the - /// TargetLowering class to allow target nodes to be understood. - KnownBits computeKnownBits(SDValue Op, unsigned Depth = 0) const; - - /// Determine which bits of Op are known to be either zero or one and return - /// them in Known. The DemandedElts argument allows us to only collect the - /// known bits that are shared by the requested vector elements. - /// Targets can implement the computeKnownBitsForTargetNode method in the - /// TargetLowering class to allow target nodes to be understood. - KnownBits computeKnownBits(SDValue Op, const APInt &DemandedElts, - unsigned Depth = 0) const; - - /// Used to represent the possible overflow behavior of an operation. - /// Never: the operation cannot overflow. - /// Always: the operation will always overflow. - /// Sometime: the operation may or may not overflow. - enum OverflowKind { - OFK_Never, - OFK_Sometime, - OFK_Always, - }; - - /// Determine if the result of the addition of 2 node can overflow. - OverflowKind computeOverflowKind(SDValue N0, SDValue N1) const; - - /// Test if the given value is known to have exactly one bit set. This differs - /// from computeKnownBits in that it doesn't necessarily determine which bit - /// is set. - bool isKnownToBeAPowerOfTwo(SDValue Val) const; - - /// Return the number of times the sign bit of the register is replicated into - /// the other bits. We know that at least 1 bit is always equal to the sign - /// bit (itself), but other cases can give us information. For example, - /// immediately after an "SRA X, 2", we know that the top 3 bits are all equal - /// to each other, so we return 3. Targets can implement the - /// ComputeNumSignBitsForTarget method in the TargetLowering class to allow - /// target nodes to be understood. - unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; - - /// Return the number of times the sign bit of the register is replicated into - /// the other bits. We know that at least 1 bit is always equal to the sign - /// bit (itself), but other cases can give us information. For example, - /// immediately after an "SRA X, 2", we know that the top 3 bits are all equal - /// to each other, so we return 3. The DemandedElts argument allows - /// us to only collect the minimum sign bits of the requested vector elements. - /// Targets can implement the ComputeNumSignBitsForTarget method in the - /// TargetLowering class to allow target nodes to be understood. - unsigned ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, - unsigned Depth = 0) const; - - /// Get the upper bound on bit size for this Value \p Op as a signed integer. - /// i.e. x == sext(trunc(x to MaxSignedBits) to bitwidth(x)). - /// Similar to the APInt::getSignificantBits function. - /// Helper wrapper to ComputeNumSignBits. - unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth = 0) const; - - /// Get the upper bound on bit size for this Value \p Op as a signed integer. - /// i.e. x == sext(trunc(x to MaxSignedBits) to bitwidth(x)). - /// Similar to the APInt::getSignificantBits function. - /// Helper wrapper to ComputeNumSignBits. - unsigned ComputeMaxSignificantBits(SDValue Op, const APInt &DemandedElts, - unsigned Depth = 0) const; - - /// Return true if this function can prove that \p Op is never poison - /// and, if \p PoisonOnly is false, does not have undef bits. - bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly = false, - unsigned Depth = 0) const; - - /// Return true if this function can prove that \p Op is never poison - /// and, if \p PoisonOnly is false, does not have undef bits. The DemandedElts - /// argument limits the check to the requested vector elements. - bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, const APInt &DemandedElts, - bool PoisonOnly = false, - unsigned Depth = 0) const; - - /// Return true if this function can prove that \p Op is never poison. - bool isGuaranteedNotToBePoison(SDValue Op, unsigned Depth = 0) const { - return isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly*/ true, Depth); - } - - /// Return true if this function can prove that \p Op is never poison. The - /// DemandedElts argument limits the check to the requested vector elements. - bool isGuaranteedNotToBePoison(SDValue Op, const APInt &DemandedElts, - unsigned Depth = 0) const { - return isGuaranteedNotToBeUndefOrPoison(Op, DemandedElts, - /*PoisonOnly*/ true, Depth); - } - - /// Return true if the specified operand is an ISD::ADD with a ConstantSDNode - /// on the right-hand side, or if it is an ISD::OR with a ConstantSDNode that - /// is guaranteed to have the same semantics as an ADD. This handles the - /// equivalence: - /// X|Cst == X+Cst iff X&Cst = 0. - bool isBaseWithConstantOffset(SDValue Op) const; - - /// Test whether the given SDValue is known to never be NaN. If \p SNaN is - /// true, returns if \p Op is known to never be a signaling NaN (it may still - /// be a qNaN). - bool isKnownNeverNaN(SDValue Op, bool SNaN = false, unsigned Depth = 0) const; - - /// \returns true if \p Op is known to never be a signaling NaN. - bool isKnownNeverSNaN(SDValue Op, unsigned Depth = 0) const { - return isKnownNeverNaN(Op, true, Depth); - } - - /// Test whether the given floating point SDValue is known to never be - /// positive or negative zero. - bool isKnownNeverZeroFloat(SDValue Op) const; - - /// Test whether the given SDValue is known to contain non-zero value(s). - bool isKnownNeverZero(SDValue Op) const; - - /// Test whether two SDValues are known to compare equal. This - /// is true if they are the same value, or if one is negative zero and the - /// other positive zero. - bool isEqualTo(SDValue A, SDValue B) const; - - /// Return true if A and B have no common bits set. As an example, this can - /// allow an 'add' to be transformed into an 'or'. - bool haveNoCommonBitsSet(SDValue A, SDValue B) const; - - /// Test whether \p V has a splatted value for all the demanded elements. - /// - /// On success \p UndefElts will indicate the elements that have UNDEF - /// values instead of the splat value, this is only guaranteed to be correct - /// for \p DemandedElts. - /// - /// NOTE: The function will return true for a demanded splat of UNDEF values. - bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, - unsigned Depth = 0) const; - - /// Test whether \p V has a splatted value. - bool isSplatValue(SDValue V, bool AllowUndefs = false) const; - - /// If V is a splatted value, return the source vector and its splat index. - SDValue getSplatSourceVector(SDValue V, int &SplatIndex); - - /// If V is a splat vector, return its scalar source operand by extracting - /// that element from the source vector. If LegalTypes is true, this method - /// may only return a legally-typed splat value. If it cannot legalize the - /// splatted value it will return SDValue(). - SDValue getSplatValue(SDValue V, bool LegalTypes = false); - - /// If a SHL/SRA/SRL node \p V has a constant or splat constant shift amount - /// that is less than the element bit-width of the shift node, return it. - const APInt *getValidShiftAmountConstant(SDValue V, - const APInt &DemandedElts) const; - - /// If a SHL/SRA/SRL node \p V has constant shift amounts that are all less - /// than the element bit-width of the shift node, return the minimum value. - const APInt * - getValidMinimumShiftAmountConstant(SDValue V, - const APInt &DemandedElts) const; - - /// If a SHL/SRA/SRL node \p V has constant shift amounts that are all less - /// than the element bit-width of the shift node, return the maximum value. - const APInt * - getValidMaximumShiftAmountConstant(SDValue V, - const APInt &DemandedElts) const; - - /// Match a binop + shuffle pyramid that represents a horizontal reduction - /// over the elements of a vector starting from the EXTRACT_VECTOR_ELT node /p - /// Extract. The reduction must use one of the opcodes listed in /p - /// CandidateBinOps and on success /p BinOp will contain the matching opcode. - /// Returns the vector that is being reduced on, or SDValue() if a reduction - /// was not matched. If \p AllowPartials is set then in the case of a - /// reduction pattern that only matches the first few stages, the extracted - /// subvector of the start of the reduction is returned. - SDValue matchBinOpReduction(SDNode *Extract, ISD::NodeType &BinOp, - ArrayRef CandidateBinOps, - bool AllowPartials = false); - - /// Utility function used by legalize and lowering to - /// "unroll" a vector operation by splitting out the scalars and operating - /// on each element individually. If the ResNE is 0, fully unroll the vector - /// op. If ResNE is less than the width of the vector op, unroll up to ResNE. - /// If the ResNE is greater than the width of the vector op, unroll the - /// vector op and fill the end of the resulting vector with UNDEFS. - SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); - - /// Like UnrollVectorOp(), but for the [US](ADD|SUB|MUL)O family of opcodes. - /// This is a separate function because those opcodes have two results. - std::pair UnrollVectorOverflowOp(SDNode *N, - unsigned ResNE = 0); - - /// Return true if loads are next to each other and can be - /// merged. Check that both are nonvolatile and if LD is loading - /// 'Bytes' bytes from a location that is 'Dist' units away from the - /// location that the 'Base' load is loading from. - bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, - unsigned Bytes, int Dist) const; - - /// Infer alignment of a load / store address. Return None if it cannot be - /// inferred. - MaybeAlign InferPtrAlign(SDValue Ptr) const; - - /// Compute the VTs needed for the low/hi parts of a type - /// which is split (or expanded) into two not necessarily identical pieces. - std::pair GetSplitDestVTs(const EVT &VT) const; - - /// Compute the VTs needed for the low/hi parts of a type, dependent on an - /// enveloping VT that has been split into two identical pieces. Sets the - /// HisIsEmpty flag when hi type has zero storage size. - std::pair GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, - bool *HiIsEmpty) const; - - /// Split the vector with EXTRACT_SUBVECTOR using the provides - /// VTs and return the low/high part. - std::pair SplitVector(const SDValue &N, const SDLoc &DL, - const EVT &LoVT, const EVT &HiVT); - - /// Split the vector with EXTRACT_SUBVECTOR and return the low/high part. - std::pair SplitVector(const SDValue &N, const SDLoc &DL) { - EVT LoVT, HiVT; - std::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); - return SplitVector(N, DL, LoVT, HiVT); - } - - /// Split the explicit vector length parameter of a VP operation. - std::pair SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL); - - /// Split the node's operand with EXTRACT_SUBVECTOR and - /// return the low/high part. - std::pair SplitVectorOperand(const SDNode *N, unsigned OpNo) - { - return SplitVector(N->getOperand(OpNo), SDLoc(N)); - } - - /// Widen the vector up to the next power of two using INSERT_SUBVECTOR. - SDValue WidenVector(const SDValue &N, const SDLoc &DL); - - /// Append the extracted elements from Start to Count out of the vector Op in - /// Args. If Count is 0, all of the elements will be extracted. The extracted - /// elements will have type EVT if it is provided, and otherwise their type - /// will be Op's element type. - void ExtractVectorElements(SDValue Op, SmallVectorImpl &Args, - unsigned Start = 0, unsigned Count = 0, - EVT EltVT = EVT()); - - /// Compute the default alignment value for the given type. - Align getEVTAlign(EVT MemoryVT) const; - /// Compute the default alignment value for the given type. - /// FIXME: Remove once transition to Align is over. - inline unsigned getEVTAlignment(EVT MemoryVT) const { - return getEVTAlign(MemoryVT).value(); - } - - /// Test whether the given value is a constant int or similar node. - SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N) const; - - /// Test whether the given value is a constant FP or similar node. - SDNode *isConstantFPBuildVectorOrConstantFP(SDValue N) const ; - - /// \returns true if \p N is any kind of constant or build_vector of - /// constants, int or float. If a vector, it may not necessarily be a splat. - inline bool isConstantValueOfAnyType(SDValue N) const { - return isConstantIntBuildVectorOrConstantInt(N) || - isConstantFPBuildVectorOrConstantFP(N); - } - - void addCallSiteInfo(const SDNode *CallNode, CallSiteInfoImpl &&CallInfo) { - SDCallSiteDbgInfo[CallNode].CSInfo = std::move(CallInfo); - } - - CallSiteInfo getSDCallSiteInfo(const SDNode *CallNode) { - auto I = SDCallSiteDbgInfo.find(CallNode); - if (I != SDCallSiteDbgInfo.end()) - return std::move(I->second).CSInfo; - return CallSiteInfo(); - } - - void addHeapAllocSite(const SDNode *Node, MDNode *MD) { - SDCallSiteDbgInfo[Node].HeapAllocSite = MD; - } - - /// Return the HeapAllocSite type associated with the SDNode, if it exists. - MDNode *getHeapAllocSite(const SDNode *Node) { - auto It = SDCallSiteDbgInfo.find(Node); - if (It == SDCallSiteDbgInfo.end()) - return nullptr; - return It->second.HeapAllocSite; - } - - void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge) { - if (NoMerge) - SDCallSiteDbgInfo[Node].NoMerge = NoMerge; - } - - bool getNoMergeSiteInfo(const SDNode *Node) { - auto I = SDCallSiteDbgInfo.find(Node); - if (I == SDCallSiteDbgInfo.end()) - return false; - return I->second.NoMerge; - } - - /// Return the current function's default denormal handling kind for the given - /// floating point type. - DenormalMode getDenormalMode(EVT VT) const { - return MF->getDenormalMode(EVTToAPFloatSemantics(VT)); - } - - bool shouldOptForSize() const; - - /// Get the (commutative) neutral element for the given opcode, if it exists. - SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, - SDNodeFlags Flags); - -private: - void InsertNode(SDNode *N); - bool RemoveNodeFromCSEMaps(SDNode *N); - void AddModifiedNodeToCSEMaps(SDNode *N); - SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); - SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2, - void *&InsertPos); - SDNode *FindModifiedNodeSlot(SDNode *N, ArrayRef Ops, - void *&InsertPos); - SDNode *UpdateSDLocOnMergeSDNode(SDNode *N, const SDLoc &loc); - - void DeleteNodeNotInCSEMaps(SDNode *N); - void DeallocateNode(SDNode *N); - - void allnodes_clear(); - - /// Look up the node specified by ID in CSEMap. If it exists, return it. If - /// not, return the insertion token that will make insertion faster. This - /// overload is for nodes other than Constant or ConstantFP, use the other one - /// for those. - SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); - - /// Look up the node specified by ID in CSEMap. If it exists, return it. If - /// not, return the insertion token that will make insertion faster. Performs - /// additional processing for constant nodes. - SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, const SDLoc &DL, - void *&InsertPos); - - /// List of non-single value types. - FoldingSet VTListMap; - - /// Maps to auto-CSE operations. - std::vector CondCodeNodes; - - std::vector ValueTypeNodes; - std::map ExtendedValueTypeNodes; - StringMap ExternalSymbols; - - std::map, SDNode *> TargetExternalSymbols; - DenseMap MCSymbols; - - FlagInserter *Inserter = nullptr; -}; - -template <> struct GraphTraits : public GraphTraits { - using nodes_iterator = pointer_iterator; - - static nodes_iterator nodes_begin(SelectionDAG *G) { - return nodes_iterator(G->allnodes_begin()); - } - - static nodes_iterator nodes_end(SelectionDAG *G) { - return nodes_iterator(G->allnodes_end()); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SELECTIONDAG_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h deleted file mode 100644 index 0f3af915da..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ /dev/null @@ -1,96 +0,0 @@ -//===- SelectionDAGAddressAnalysis.h - DAG Address Analysis -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H -#define LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H - -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include - -namespace llvm { - -class SelectionDAG; - -/// Helper struct to parse and store a memory address as base + index + offset. -/// We ignore sign extensions when it is safe to do so. -/// The following two expressions are not equivalent. To differentiate we need -/// to store whether there was a sign extension involved in the index -/// computation. -/// (load (i64 add (i64 copyfromreg %c) -/// (i64 signextend (add (i8 load %index) -/// (i8 1)))) -/// vs -/// -/// (load (i64 add (i64 copyfromreg %c) -/// (i64 signextend (i32 add (i32 signextend (i8 load %index)) -/// (i32 1))))) -class BaseIndexOffset { -private: - SDValue Base; - SDValue Index; - Optional Offset; - bool IsIndexSignExt = false; - -public: - BaseIndexOffset() = default; - BaseIndexOffset(SDValue Base, SDValue Index, bool IsIndexSignExt) - : Base(Base), Index(Index), IsIndexSignExt(IsIndexSignExt) {} - BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset, - bool IsIndexSignExt) - : Base(Base), Index(Index), Offset(Offset), - IsIndexSignExt(IsIndexSignExt) {} - - SDValue getBase() { return Base; } - SDValue getBase() const { return Base; } - SDValue getIndex() { return Index; } - SDValue getIndex() const { return Index; } - bool hasValidOffset() const { return Offset.hasValue(); } - int64_t getOffset() const { return *Offset; } - - // Returns true if `Other` and `*this` are both some offset from the same base - // pointer. In that case, `Off` is set to the offset between `*this` and - // `Other` (negative if `Other` is before `*this`). - bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) const; - - bool equalBaseIndex(const BaseIndexOffset &Other, - const SelectionDAG &DAG) const { - int64_t Off; - return equalBaseIndex(Other, DAG, Off); - } - - // Returns true if `Other` (with size `OtherSize`) can be proven to be fully - // contained in `*this` (with size `Size`). - bool contains(const SelectionDAG &DAG, int64_t BitSize, - const BaseIndexOffset &Other, int64_t OtherBitSize, - int64_t &BitOffset) const; - - bool contains(const SelectionDAG &DAG, int64_t BitSize, - const BaseIndexOffset &Other, int64_t OtherBitSize) const { - int64_t BitOffset; - return contains(DAG, BitSize, Other, OtherBitSize, BitOffset); - } - - // Returns true `Op0` and `Op1` can be proven to alias/not alias, in - // which case `IsAlias` is set to true/false. - static bool computeAliasing(const SDNode *Op0, - const Optional NumBytes0, - const SDNode *Op1, - const Optional NumBytes1, - const SelectionDAG &DAG, bool &IsAlias); - - /// Parses tree in N for base, index, offset addresses. - static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG); - - void print(raw_ostream& OS) const; - void dump() const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGISel.h b/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGISel.h deleted file mode 100644 index fc3fdf3e45..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGISel.h +++ /dev/null @@ -1,370 +0,0 @@ -//===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the SelectionDAGISel class, which is used as the common -// base class for SelectionDAG-based instruction selectors. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SELECTIONDAGISEL_H -#define LLVM_CODEGEN_SELECTIONDAGISEL_H - -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/BasicBlock.h" -#include - -namespace llvm { -class AAResults; -class SelectionDAGBuilder; -class SDValue; -class MachineRegisterInfo; -class MachineFunction; -class OptimizationRemarkEmitter; -class TargetLowering; -class TargetLibraryInfo; -class FunctionLoweringInfo; -class SwiftErrorValueTracking; -class GCFunctionInfo; -class ScheduleDAGSDNodes; - -/// SelectionDAGISel - This is the common base class used for SelectionDAG-based -/// pattern-matching instruction selectors. -class SelectionDAGISel : public MachineFunctionPass { -public: - TargetMachine &TM; - const TargetLibraryInfo *LibInfo; - std::unique_ptr FuncInfo; - SwiftErrorValueTracking *SwiftError; - MachineFunction *MF; - MachineRegisterInfo *RegInfo; - SelectionDAG *CurDAG; - std::unique_ptr SDB; - AAResults *AA = nullptr; - GCFunctionInfo *GFI = nullptr; - CodeGenOpt::Level OptLevel; - const TargetInstrInfo *TII; - const TargetLowering *TLI; - bool FastISelFailed; - SmallPtrSet ElidedArgCopyInstrs; - bool UseInstrRefDebugInfo = false; - - /// Current optimization remark emitter. - /// Used to report things like combines and FastISel failures. - std::unique_ptr ORE; - - static char ID; - - explicit SelectionDAGISel(TargetMachine &tm, - CodeGenOpt::Level OL = CodeGenOpt::Default); - ~SelectionDAGISel() override; - - const TargetLowering *getTargetLowering() const { return TLI; } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &MF) override; - - virtual void emitFunctionEntryCode() {} - - /// PreprocessISelDAG - This hook allows targets to hack on the graph before - /// instruction selection starts. - virtual void PreprocessISelDAG() {} - - /// PostprocessISelDAG() - This hook allows the target to hack on the graph - /// right after selection. - virtual void PostprocessISelDAG() {} - - /// Main hook for targets to transform nodes into machine nodes. - virtual void Select(SDNode *N) = 0; - - /// SelectInlineAsmMemoryOperand - Select the specified address as a target - /// addressing mode, according to the specified constraint. If this does - /// not match or is not implemented, return true. The resultant operands - /// (which will appear in the machine instruction) should be added to the - /// OutOps vector. - virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, - std::vector &OutOps) { - return true; - } - - /// IsProfitableToFold - Returns true if it's profitable to fold the specific - /// operand node N of U during instruction selection that starts at Root. - virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const; - - /// IsLegalToFold - Returns true if the specific operand node N of - /// U can be folded during instruction selection that starts at Root. - /// FIXME: This is a static member function because the MSP430/X86 - /// targets, which uses it during isel. This could become a proper member. - static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, - CodeGenOpt::Level OptLevel, - bool IgnoreChains = false); - - static void InvalidateNodeId(SDNode *N); - static int getUninvalidatedNodeId(SDNode *N); - - static void EnforceNodeIdInvariant(SDNode *N); - - // Opcodes used by the DAG state machine: - enum BuiltinOpcodes { - OPC_Scope, - OPC_RecordNode, - OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, - OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7, - OPC_RecordMemRef, - OPC_CaptureGlueInput, - OPC_MoveChild, - OPC_MoveChild0, OPC_MoveChild1, OPC_MoveChild2, OPC_MoveChild3, - OPC_MoveChild4, OPC_MoveChild5, OPC_MoveChild6, OPC_MoveChild7, - OPC_MoveParent, - OPC_CheckSame, - OPC_CheckChild0Same, OPC_CheckChild1Same, - OPC_CheckChild2Same, OPC_CheckChild3Same, - OPC_CheckPatternPredicate, - OPC_CheckPredicate, - OPC_CheckPredicateWithOperands, - OPC_CheckOpcode, - OPC_SwitchOpcode, - OPC_CheckType, - OPC_CheckTypeRes, - OPC_SwitchType, - OPC_CheckChild0Type, OPC_CheckChild1Type, OPC_CheckChild2Type, - OPC_CheckChild3Type, OPC_CheckChild4Type, OPC_CheckChild5Type, - OPC_CheckChild6Type, OPC_CheckChild7Type, - OPC_CheckInteger, - OPC_CheckChild0Integer, OPC_CheckChild1Integer, OPC_CheckChild2Integer, - OPC_CheckChild3Integer, OPC_CheckChild4Integer, - OPC_CheckCondCode, OPC_CheckChild2CondCode, - OPC_CheckValueType, - OPC_CheckComplexPat, - OPC_CheckAndImm, OPC_CheckOrImm, - OPC_CheckImmAllOnesV, - OPC_CheckImmAllZerosV, - OPC_CheckFoldableChainNode, - - OPC_EmitInteger, - OPC_EmitStringInteger, - OPC_EmitRegister, - OPC_EmitRegister2, - OPC_EmitConvertToTarget, - OPC_EmitMergeInputChains, - OPC_EmitMergeInputChains1_0, - OPC_EmitMergeInputChains1_1, - OPC_EmitMergeInputChains1_2, - OPC_EmitCopyToReg, - OPC_EmitCopyToReg2, - OPC_EmitNodeXForm, - OPC_EmitNode, - // Space-optimized forms that implicitly encode number of result VTs. - OPC_EmitNode0, OPC_EmitNode1, OPC_EmitNode2, - OPC_MorphNodeTo, - // Space-optimized forms that implicitly encode number of result VTs. - OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2, - OPC_CompleteMatch, - // Contains offset in table for pattern being selected - OPC_Coverage - }; - - enum { - OPFL_None = 0, // Node has no chain or glue input and isn't variadic. - OPFL_Chain = 1, // Node has a chain input. - OPFL_GlueInput = 2, // Node has a glue input. - OPFL_GlueOutput = 4, // Node has a glue output. - OPFL_MemRefs = 8, // Node gets accumulated MemRefs. - OPFL_Variadic0 = 1<<4, // Node is variadic, root has 0 fixed inputs. - OPFL_Variadic1 = 2<<4, // Node is variadic, root has 1 fixed inputs. - OPFL_Variadic2 = 3<<4, // Node is variadic, root has 2 fixed inputs. - OPFL_Variadic3 = 4<<4, // Node is variadic, root has 3 fixed inputs. - OPFL_Variadic4 = 5<<4, // Node is variadic, root has 4 fixed inputs. - OPFL_Variadic5 = 6<<4, // Node is variadic, root has 5 fixed inputs. - OPFL_Variadic6 = 7<<4, // Node is variadic, root has 6 fixed inputs. - - OPFL_VariadicInfo = OPFL_Variadic6 - }; - - /// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the - /// number of fixed arity values that should be skipped when copying from the - /// root. - static inline int getNumFixedFromVariadicInfo(unsigned Flags) { - return ((Flags&OPFL_VariadicInfo) >> 4)-1; - } - - -protected: - /// DAGSize - Size of DAG being instruction selected. - /// - unsigned DAGSize = 0; - - /// ReplaceUses - replace all uses of the old node F with the use - /// of the new node T. - void ReplaceUses(SDValue F, SDValue T) { - CurDAG->ReplaceAllUsesOfValueWith(F, T); - EnforceNodeIdInvariant(T.getNode()); - } - - /// ReplaceUses - replace all uses of the old nodes F with the use - /// of the new nodes T. - void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { - CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num); - for (unsigned i = 0; i < Num; ++i) - EnforceNodeIdInvariant(T[i].getNode()); - } - - /// ReplaceUses - replace all uses of the old node F with the use - /// of the new node T. - void ReplaceUses(SDNode *F, SDNode *T) { - CurDAG->ReplaceAllUsesWith(F, T); - EnforceNodeIdInvariant(T); - } - - /// Replace all uses of \c F with \c T, then remove \c F from the DAG. - void ReplaceNode(SDNode *F, SDNode *T) { - CurDAG->ReplaceAllUsesWith(F, T); - EnforceNodeIdInvariant(T); - CurDAG->RemoveDeadNode(F); - } - - /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated - /// by tblgen. Others should not call it. - void SelectInlineAsmMemoryOperands(std::vector &Ops, - const SDLoc &DL); - - /// getPatternForIndex - Patterns selected by tablegen during ISEL - virtual StringRef getPatternForIndex(unsigned index) { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - /// getIncludePathForIndex - get the td source location of pattern instantiation - virtual StringRef getIncludePathForIndex(unsigned index) { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - bool shouldOptForSize(const MachineFunction *MF) const { - return CurDAG->shouldOptForSize(); - } - -public: - // Calls to these predicates are generated by tblgen. - bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, - int64_t DesiredMaskS) const; - bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS, - int64_t DesiredMaskS) const; - - - /// CheckPatternPredicate - This function is generated by tblgen in the - /// target. It runs the specified pattern predicate and returns true if it - /// succeeds or false if it fails. The number is a private implementation - /// detail to the code tblgen produces. - virtual bool CheckPatternPredicate(unsigned PredNo) const { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - /// CheckNodePredicate - This function is generated by tblgen in the target. - /// It runs node predicate number PredNo and returns true if it succeeds or - /// false if it fails. The number is a private implementation - /// detail to the code tblgen produces. - virtual bool CheckNodePredicate(SDNode *N, unsigned PredNo) const { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - /// CheckNodePredicateWithOperands - This function is generated by tblgen in - /// the target. - /// It runs node predicate number PredNo and returns true if it succeeds or - /// false if it fails. The number is a private implementation detail to the - /// code tblgen produces. - virtual bool CheckNodePredicateWithOperands( - SDNode *N, unsigned PredNo, - const SmallVectorImpl &Operands) const { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, - unsigned PatternNo, - SmallVectorImpl > &Result) { - llvm_unreachable("Tblgen should generate the implementation of this!"); - } - - virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { - llvm_unreachable("Tblgen should generate this!"); - } - - void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, - unsigned TableSize); - - /// Return true if complex patterns for this target can mutate the - /// DAG. - virtual bool ComplexPatternFuncMutatesDAG() const { - return false; - } - - /// Return whether the node may raise an FP exception. - bool mayRaiseFPException(SDNode *Node) const; - - bool isOrEquivalentToAdd(const SDNode *N) const; - -private: - - // Calls to these functions are generated by tblgen. - void Select_INLINEASM(SDNode *N); - void Select_READ_REGISTER(SDNode *Op); - void Select_WRITE_REGISTER(SDNode *Op); - void Select_UNDEF(SDNode *N); - void CannotYetSelect(SDNode *N); - - void Select_FREEZE(SDNode *N); - void Select_ARITH_FENCE(SDNode *N); - -private: - void DoInstructionSelection(); - SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList, - ArrayRef Ops, unsigned EmitNodeInfo); - - /// Prepares the landing pad to take incoming values or do other EH - /// personality specific tasks. Returns true if the block should be - /// instruction selected, false if no code should be emitted for it. - bool PrepareEHLandingPad(); - - /// Perform instruction selection on all basic blocks in the function. - void SelectAllBasicBlocks(const Function &Fn); - - /// Perform instruction selection on a single basic block, for - /// instructions between \p Begin and \p End. \p HadTailCall will be set - /// to true if a call in the block was translated as a tail call. - void SelectBasicBlock(BasicBlock::const_iterator Begin, - BasicBlock::const_iterator End, - bool &HadTailCall); - void FinishBasicBlock(); - - void CodeGenAndEmitDAG(); - - /// Generate instructions for lowering the incoming arguments of the - /// given function. - void LowerArguments(const Function &F); - - void ComputeLiveOutVRegInfo(); - - /// Create the scheduler. If a specific scheduler was specified - /// via the SchedulerRegistry, use it, otherwise select the - /// one preferred by the target. - /// - ScheduleDAGSDNodes *CreateScheduler(); - - /// OpcodeOffset - This is a cache used to dispatch efficiently into isel - /// state machines that start with a OPC_SwitchOpcode node. - std::vector OpcodeOffset; - - void UpdateChains(SDNode *NodeToMatch, SDValue InputChain, - SmallVectorImpl &ChainNodesMatched, - bool isMorphNodeTo); -}; - -} - -#endif /* LLVM_CODEGEN_SELECTIONDAGISEL_H */ diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGNodes.h b/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGNodes.h deleted file mode 100644 index 40d7c4d6d1..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGNodes.h +++ /dev/null @@ -1,2990 +0,0 @@ -//===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the SDNode class and derived classes, which are used to -// represent the nodes and operations present in a SelectionDAG. These nodes -// and operations are machine code level operations, with some similarities to -// the GCC RTL representation. -// -// Clients should include the SelectionDAG.h file instead of this file directly. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H -#define LLVM_CODEGEN_SELECTIONDAGNODES_H - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Operator.h" -#include "llvm/Support/AlignOf.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/TypeSize.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class APInt; -class Constant; -class GlobalValue; -class MachineBasicBlock; -class MachineConstantPoolValue; -class MCSymbol; -class raw_ostream; -class SDNode; -class SelectionDAG; -class Type; -class Value; - -void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, - bool force = false); - -/// This represents a list of ValueType's that has been intern'd by -/// a SelectionDAG. Instances of this simple value class are returned by -/// SelectionDAG::getVTList(...). -/// -struct SDVTList { - const EVT *VTs; - unsigned int NumVTs; -}; - -namespace ISD { - - /// Node predicates - -/// If N is a BUILD_VECTOR or SPLAT_VECTOR node whose elements are all the -/// same constant or undefined, return true and return the constant value in -/// \p SplatValue. -bool isConstantSplatVector(const SDNode *N, APInt &SplatValue); - -/// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where -/// all of the elements are ~0 or undef. If \p BuildVectorOnly is set to -/// true, it only checks BUILD_VECTOR. -bool isConstantSplatVectorAllOnes(const SDNode *N, - bool BuildVectorOnly = false); - -/// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where -/// all of the elements are 0 or undef. If \p BuildVectorOnly is set to true, it -/// only checks BUILD_VECTOR. -bool isConstantSplatVectorAllZeros(const SDNode *N, - bool BuildVectorOnly = false); - -/// Return true if the specified node is a BUILD_VECTOR where all of the -/// elements are ~0 or undef. -bool isBuildVectorAllOnes(const SDNode *N); - -/// Return true if the specified node is a BUILD_VECTOR where all of the -/// elements are 0 or undef. -bool isBuildVectorAllZeros(const SDNode *N); - -/// Return true if the specified node is a BUILD_VECTOR node of all -/// ConstantSDNode or undef. -bool isBuildVectorOfConstantSDNodes(const SDNode *N); - -/// Return true if the specified node is a BUILD_VECTOR node of all -/// ConstantFPSDNode or undef. -bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); - -/// Return true if the node has at least one operand and all operands of the -/// specified node are ISD::UNDEF. -bool allOperandsUndef(const SDNode *N); - -} // end namespace ISD - -//===----------------------------------------------------------------------===// -/// Unlike LLVM values, Selection DAG nodes may return multiple -/// values as the result of a computation. Many nodes return multiple values, -/// from loads (which define a token and a return value) to ADDC (which returns -/// a result and a carry value), to calls (which may return an arbitrary number -/// of values). -/// -/// As such, each use of a SelectionDAG computation must indicate the node that -/// computes it as well as which return value to use from that node. This pair -/// of information is represented with the SDValue value type. -/// -class SDValue { - friend struct DenseMapInfo; - - SDNode *Node = nullptr; // The node defining the value we are using. - unsigned ResNo = 0; // Which return value of the node we are using. - -public: - SDValue() = default; - SDValue(SDNode *node, unsigned resno); - - /// get the index which selects a specific result in the SDNode - unsigned getResNo() const { return ResNo; } - - /// get the SDNode which holds the desired result - SDNode *getNode() const { return Node; } - - /// set the SDNode - void setNode(SDNode *N) { Node = N; } - - inline SDNode *operator->() const { return Node; } - - bool operator==(const SDValue &O) const { - return Node == O.Node && ResNo == O.ResNo; - } - bool operator!=(const SDValue &O) const { - return !operator==(O); - } - bool operator<(const SDValue &O) const { - return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); - } - explicit operator bool() const { - return Node != nullptr; - } - - SDValue getValue(unsigned R) const { - return SDValue(Node, R); - } - - /// Return true if this node is an operand of N. - bool isOperandOf(const SDNode *N) const; - - /// Return the ValueType of the referenced return value. - inline EVT getValueType() const; - - /// Return the simple ValueType of the referenced return value. - MVT getSimpleValueType() const { - return getValueType().getSimpleVT(); - } - - /// Returns the size of the value in bits. - /// - /// If the value type is a scalable vector type, the scalable property will - /// be set and the runtime size will be a positive integer multiple of the - /// base size. - TypeSize getValueSizeInBits() const { - return getValueType().getSizeInBits(); - } - - uint64_t getScalarValueSizeInBits() const { - return getValueType().getScalarType().getFixedSizeInBits(); - } - - // Forwarding methods - These forward to the corresponding methods in SDNode. - inline unsigned getOpcode() const; - inline unsigned getNumOperands() const; - inline const SDValue &getOperand(unsigned i) const; - inline uint64_t getConstantOperandVal(unsigned i) const; - inline const APInt &getConstantOperandAPInt(unsigned i) const; - inline bool isTargetMemoryOpcode() const; - inline bool isTargetOpcode() const; - inline bool isMachineOpcode() const; - inline bool isUndef() const; - inline unsigned getMachineOpcode() const; - inline const DebugLoc &getDebugLoc() const; - inline void dump() const; - inline void dump(const SelectionDAG *G) const; - inline void dumpr() const; - inline void dumpr(const SelectionDAG *G) const; - - /// Return true if this operand (which must be a chain) reaches the - /// specified operand without crossing any side-effecting instructions. - /// In practice, this looks through token factors and non-volatile loads. - /// In order to remain efficient, this only - /// looks a couple of nodes in, it does not do an exhaustive search. - bool reachesChainWithoutSideEffects(SDValue Dest, - unsigned Depth = 2) const; - - /// Return true if there are no nodes using value ResNo of Node. - inline bool use_empty() const; - - /// Return true if there is exactly one node using value ResNo of Node. - inline bool hasOneUse() const; -}; - -template<> struct DenseMapInfo { - static inline SDValue getEmptyKey() { - SDValue V; - V.ResNo = -1U; - return V; - } - - static inline SDValue getTombstoneKey() { - SDValue V; - V.ResNo = -2U; - return V; - } - - static unsigned getHashValue(const SDValue &Val) { - return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ - (unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo(); - } - - static bool isEqual(const SDValue &LHS, const SDValue &RHS) { - return LHS == RHS; - } -}; - -/// Allow casting operators to work directly on -/// SDValues as if they were SDNode*'s. -template<> struct simplify_type { - using SimpleType = SDNode *; - - static SimpleType getSimplifiedValue(SDValue &Val) { - return Val.getNode(); - } -}; -template<> struct simplify_type { - using SimpleType = /*const*/ SDNode *; - - static SimpleType getSimplifiedValue(const SDValue &Val) { - return Val.getNode(); - } -}; - -/// Represents a use of a SDNode. This class holds an SDValue, -/// which records the SDNode being used and the result number, a -/// pointer to the SDNode using the value, and Next and Prev pointers, -/// which link together all the uses of an SDNode. -/// -class SDUse { - /// Val - The value being used. - SDValue Val; - /// User - The user of this value. - SDNode *User = nullptr; - /// Prev, Next - Pointers to the uses list of the SDNode referred by - /// this operand. - SDUse **Prev = nullptr; - SDUse *Next = nullptr; - -public: - SDUse() = default; - SDUse(const SDUse &U) = delete; - SDUse &operator=(const SDUse &) = delete; - - /// Normally SDUse will just implicitly convert to an SDValue that it holds. - operator const SDValue&() const { return Val; } - - /// If implicit conversion to SDValue doesn't work, the get() method returns - /// the SDValue. - const SDValue &get() const { return Val; } - - /// This returns the SDNode that contains this Use. - SDNode *getUser() { return User; } - - /// Get the next SDUse in the use list. - SDUse *getNext() const { return Next; } - - /// Convenience function for get().getNode(). - SDNode *getNode() const { return Val.getNode(); } - /// Convenience function for get().getResNo(). - unsigned getResNo() const { return Val.getResNo(); } - /// Convenience function for get().getValueType(). - EVT getValueType() const { return Val.getValueType(); } - - /// Convenience function for get().operator== - bool operator==(const SDValue &V) const { - return Val == V; - } - - /// Convenience function for get().operator!= - bool operator!=(const SDValue &V) const { - return Val != V; - } - - /// Convenience function for get().operator< - bool operator<(const SDValue &V) const { - return Val < V; - } - -private: - friend class SelectionDAG; - friend class SDNode; - // TODO: unfriend HandleSDNode once we fix its operand handling. - friend class HandleSDNode; - - void setUser(SDNode *p) { User = p; } - - /// Remove this use from its existing use list, assign it the - /// given value, and add it to the new value's node's use list. - inline void set(const SDValue &V); - /// Like set, but only supports initializing a newly-allocated - /// SDUse with a non-null value. - inline void setInitial(const SDValue &V); - /// Like set, but only sets the Node portion of the value, - /// leaving the ResNo portion unmodified. - inline void setNode(SDNode *N); - - void addToList(SDUse **List) { - Next = *List; - if (Next) Next->Prev = &Next; - Prev = List; - *List = this; - } - - void removeFromList() { - *Prev = Next; - if (Next) Next->Prev = Prev; - } -}; - -/// simplify_type specializations - Allow casting operators to work directly on -/// SDValues as if they were SDNode*'s. -template<> struct simplify_type { - using SimpleType = SDNode *; - - static SimpleType getSimplifiedValue(SDUse &Val) { - return Val.getNode(); - } -}; - -/// These are IR-level optimization flags that may be propagated to SDNodes. -/// TODO: This data structure should be shared by the IR optimizer and the -/// the backend. -struct SDNodeFlags { -private: - bool NoUnsignedWrap : 1; - bool NoSignedWrap : 1; - bool Exact : 1; - bool NoNaNs : 1; - bool NoInfs : 1; - bool NoSignedZeros : 1; - bool AllowReciprocal : 1; - bool AllowContract : 1; - bool ApproximateFuncs : 1; - bool AllowReassociation : 1; - - // We assume instructions do not raise floating-point exceptions by default, - // and only those marked explicitly may do so. We could choose to represent - // this via a positive "FPExcept" flags like on the MI level, but having a - // negative "NoFPExcept" flag here (that defaults to true) makes the flag - // intersection logic more straightforward. - bool NoFPExcept : 1; - -public: - /// Default constructor turns off all optimization flags. - SDNodeFlags() - : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), NoNaNs(false), - NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), - AllowContract(false), ApproximateFuncs(false), - AllowReassociation(false), NoFPExcept(false) {} - - /// Propagate the fast-math-flags from an IR FPMathOperator. - void copyFMF(const FPMathOperator &FPMO) { - setNoNaNs(FPMO.hasNoNaNs()); - setNoInfs(FPMO.hasNoInfs()); - setNoSignedZeros(FPMO.hasNoSignedZeros()); - setAllowReciprocal(FPMO.hasAllowReciprocal()); - setAllowContract(FPMO.hasAllowContract()); - setApproximateFuncs(FPMO.hasApproxFunc()); - setAllowReassociation(FPMO.hasAllowReassoc()); - } - - // These are mutators for each flag. - void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } - void setNoSignedWrap(bool b) { NoSignedWrap = b; } - void setExact(bool b) { Exact = b; } - void setNoNaNs(bool b) { NoNaNs = b; } - void setNoInfs(bool b) { NoInfs = b; } - void setNoSignedZeros(bool b) { NoSignedZeros = b; } - void setAllowReciprocal(bool b) { AllowReciprocal = b; } - void setAllowContract(bool b) { AllowContract = b; } - void setApproximateFuncs(bool b) { ApproximateFuncs = b; } - void setAllowReassociation(bool b) { AllowReassociation = b; } - void setNoFPExcept(bool b) { NoFPExcept = b; } - - // These are accessors for each flag. - bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } - bool hasNoSignedWrap() const { return NoSignedWrap; } - bool hasExact() const { return Exact; } - bool hasNoNaNs() const { return NoNaNs; } - bool hasNoInfs() const { return NoInfs; } - bool hasNoSignedZeros() const { return NoSignedZeros; } - bool hasAllowReciprocal() const { return AllowReciprocal; } - bool hasAllowContract() const { return AllowContract; } - bool hasApproximateFuncs() const { return ApproximateFuncs; } - bool hasAllowReassociation() const { return AllowReassociation; } - bool hasNoFPExcept() const { return NoFPExcept; } - - /// Clear any flags in this flag set that aren't also set in Flags. All - /// flags will be cleared if Flags are undefined. - void intersectWith(const SDNodeFlags Flags) { - NoUnsignedWrap &= Flags.NoUnsignedWrap; - NoSignedWrap &= Flags.NoSignedWrap; - Exact &= Flags.Exact; - NoNaNs &= Flags.NoNaNs; - NoInfs &= Flags.NoInfs; - NoSignedZeros &= Flags.NoSignedZeros; - AllowReciprocal &= Flags.AllowReciprocal; - AllowContract &= Flags.AllowContract; - ApproximateFuncs &= Flags.ApproximateFuncs; - AllowReassociation &= Flags.AllowReassociation; - NoFPExcept &= Flags.NoFPExcept; - } -}; - -/// Represents one node in the SelectionDAG. -/// -class SDNode : public FoldingSetNode, public ilist_node { -private: - /// The operation that this node performs. - int16_t NodeType; - -protected: - // We define a set of mini-helper classes to help us interpret the bits in our - // SubclassData. These are designed to fit within a uint16_t so they pack - // with NodeType. - -#if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__)) -// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words -// and give the `pack` pragma push semantics. -#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)") -#define END_TWO_BYTE_PACK() _Pragma("pack(pop)") -#else -#define BEGIN_TWO_BYTE_PACK() -#define END_TWO_BYTE_PACK() -#endif - -BEGIN_TWO_BYTE_PACK() - class SDNodeBitfields { - friend class SDNode; - friend class MemIntrinsicSDNode; - friend class MemSDNode; - friend class SelectionDAG; - - uint16_t HasDebugValue : 1; - uint16_t IsMemIntrinsic : 1; - uint16_t IsDivergent : 1; - }; - enum { NumSDNodeBits = 3 }; - - class ConstantSDNodeBitfields { - friend class ConstantSDNode; - - uint16_t : NumSDNodeBits; - - uint16_t IsOpaque : 1; - }; - - class MemSDNodeBitfields { - friend class MemSDNode; - friend class MemIntrinsicSDNode; - friend class AtomicSDNode; - - uint16_t : NumSDNodeBits; - - uint16_t IsVolatile : 1; - uint16_t IsNonTemporal : 1; - uint16_t IsDereferenceable : 1; - uint16_t IsInvariant : 1; - }; - enum { NumMemSDNodeBits = NumSDNodeBits + 4 }; - - class LSBaseSDNodeBitfields { - friend class LSBaseSDNode; - friend class VPLoadStoreSDNode; - friend class MaskedLoadStoreSDNode; - friend class MaskedGatherScatterSDNode; - friend class VPGatherScatterSDNode; - - uint16_t : NumMemSDNodeBits; - - // This storage is shared between disparate class hierarchies to hold an - // enumeration specific to the class hierarchy in use. - // LSBaseSDNode => enum ISD::MemIndexedMode - // VPLoadStoreBaseSDNode => enum ISD::MemIndexedMode - // MaskedLoadStoreBaseSDNode => enum ISD::MemIndexedMode - // VPGatherScatterSDNode => enum ISD::MemIndexType - // MaskedGatherScatterSDNode => enum ISD::MemIndexType - uint16_t AddressingMode : 3; - }; - enum { NumLSBaseSDNodeBits = NumMemSDNodeBits + 3 }; - - class LoadSDNodeBitfields { - friend class LoadSDNode; - friend class VPLoadSDNode; - friend class MaskedLoadSDNode; - friend class MaskedGatherSDNode; - friend class VPGatherSDNode; - - uint16_t : NumLSBaseSDNodeBits; - - uint16_t ExtTy : 2; // enum ISD::LoadExtType - uint16_t IsExpanding : 1; - }; - - class StoreSDNodeBitfields { - friend class StoreSDNode; - friend class VPStoreSDNode; - friend class MaskedStoreSDNode; - friend class MaskedScatterSDNode; - friend class VPScatterSDNode; - - uint16_t : NumLSBaseSDNodeBits; - - uint16_t IsTruncating : 1; - uint16_t IsCompressing : 1; - }; - - union { - char RawSDNodeBits[sizeof(uint16_t)]; - SDNodeBitfields SDNodeBits; - ConstantSDNodeBitfields ConstantSDNodeBits; - MemSDNodeBitfields MemSDNodeBits; - LSBaseSDNodeBitfields LSBaseSDNodeBits; - LoadSDNodeBitfields LoadSDNodeBits; - StoreSDNodeBitfields StoreSDNodeBits; - }; -END_TWO_BYTE_PACK() -#undef BEGIN_TWO_BYTE_PACK -#undef END_TWO_BYTE_PACK - - // RawSDNodeBits must cover the entirety of the union. This means that all of - // the union's members must have size <= RawSDNodeBits. We write the RHS as - // "2" instead of sizeof(RawSDNodeBits) because MSVC can't handle the latter. - static_assert(sizeof(SDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide"); - -private: - friend class SelectionDAG; - // TODO: unfriend HandleSDNode once we fix its operand handling. - friend class HandleSDNode; - - /// Unique id per SDNode in the DAG. - int NodeId = -1; - - /// The values that are used by this operation. - SDUse *OperandList = nullptr; - - /// The types of the values this node defines. SDNode's may - /// define multiple values simultaneously. - const EVT *ValueList; - - /// List of uses for this SDNode. - SDUse *UseList = nullptr; - - /// The number of entries in the Operand/Value list. - unsigned short NumOperands = 0; - unsigned short NumValues; - - // The ordering of the SDNodes. It roughly corresponds to the ordering of the - // original LLVM instructions. - // This is used for turning off scheduling, because we'll forgo - // the normal scheduling algorithms and output the instructions according to - // this ordering. - unsigned IROrder; - - /// Source line information. - DebugLoc debugLoc; - - /// Return a pointer to the specified value type. - static const EVT *getValueTypeList(EVT VT); - - SDNodeFlags Flags; - -public: - /// Unique and persistent id per SDNode in the DAG. - /// Used for debug printing. - uint16_t PersistentId; - - //===--------------------------------------------------------------------===// - // Accessors - // - - /// Return the SelectionDAG opcode value for this node. For - /// pre-isel nodes (those for which isMachineOpcode returns false), these - /// are the opcode values in the ISD and ISD namespaces. For - /// post-isel opcodes, see getMachineOpcode. - unsigned getOpcode() const { return (unsigned short)NodeType; } - - /// Test if this node has a target-specific opcode (in the - /// \ISD namespace). - bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } - - /// Test if this node has a target-specific opcode that may raise - /// FP exceptions (in the \ISD namespace and greater than - /// FIRST_TARGET_STRICTFP_OPCODE). Note that all target memory - /// opcode are currently automatically considered to possibly raise - /// FP exceptions as well. - bool isTargetStrictFPOpcode() const { - return NodeType >= ISD::FIRST_TARGET_STRICTFP_OPCODE; - } - - /// Test if this node has a target-specific - /// memory-referencing opcode (in the \ISD namespace and - /// greater than FIRST_TARGET_MEMORY_OPCODE). - bool isTargetMemoryOpcode() const { - return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; - } - - /// Return true if the type of the node type undefined. - bool isUndef() const { return NodeType == ISD::UNDEF; } - - /// Test if this node is a memory intrinsic (with valid pointer information). - /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for - /// non-memory intrinsics (with chains) that are not really instances of - /// MemSDNode. For such nodes, we need some extra state to determine the - /// proper classof relationship. - bool isMemIntrinsic() const { - return (NodeType == ISD::INTRINSIC_W_CHAIN || - NodeType == ISD::INTRINSIC_VOID) && - SDNodeBits.IsMemIntrinsic; - } - - /// Test if this node is a strict floating point pseudo-op. - bool isStrictFPOpcode() { - switch (NodeType) { - default: - return false; - case ISD::STRICT_FP16_TO_FP: - case ISD::STRICT_FP_TO_FP16: -#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ - case ISD::STRICT_##DAGN: -#include "llvm/IR/ConstrainedOps.def" - return true; - } - } - - /// Test if this node is a vector predication operation. - bool isVPOpcode() const { return ISD::isVPOpcode(getOpcode()); } - - /// Test if this node has a post-isel opcode, directly - /// corresponding to a MachineInstr opcode. - bool isMachineOpcode() const { return NodeType < 0; } - - /// This may only be called if isMachineOpcode returns - /// true. It returns the MachineInstr opcode value that the node's opcode - /// corresponds to. - unsigned getMachineOpcode() const { - assert(isMachineOpcode() && "Not a MachineInstr opcode!"); - return ~NodeType; - } - - bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; } - void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; } - - bool isDivergent() const { return SDNodeBits.IsDivergent; } - - /// Return true if there are no uses of this node. - bool use_empty() const { return UseList == nullptr; } - - /// Return true if there is exactly one use of this node. - bool hasOneUse() const { return hasSingleElement(uses()); } - - /// Return the number of uses of this node. This method takes - /// time proportional to the number of uses. - size_t use_size() const { return std::distance(use_begin(), use_end()); } - - /// Return the unique node id. - int getNodeId() const { return NodeId; } - - /// Set unique node id. - void setNodeId(int Id) { NodeId = Id; } - - /// Return the node ordering. - unsigned getIROrder() const { return IROrder; } - - /// Set the node ordering. - void setIROrder(unsigned Order) { IROrder = Order; } - - /// Return the source location info. - const DebugLoc &getDebugLoc() const { return debugLoc; } - - /// Set source location info. Try to avoid this, putting - /// it in the constructor is preferable. - void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } - - /// This class provides iterator support for SDUse - /// operands that use a specific SDNode. - class use_iterator { - friend class SDNode; - - SDUse *Op = nullptr; - - explicit use_iterator(SDUse *op) : Op(op) {} - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = SDUse; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - use_iterator() = default; - use_iterator(const use_iterator &I) = default; - - bool operator==(const use_iterator &x) const { return Op == x.Op; } - bool operator!=(const use_iterator &x) const { - return !operator==(x); - } - - /// Return true if this iterator is at the end of uses list. - bool atEnd() const { return Op == nullptr; } - - // Iterator traversal: forward iteration only. - use_iterator &operator++() { // Preincrement - assert(Op && "Cannot increment end iterator!"); - Op = Op->getNext(); - return *this; - } - - use_iterator operator++(int) { // Postincrement - use_iterator tmp = *this; ++*this; return tmp; - } - - /// Retrieve a pointer to the current user node. - SDNode *operator*() const { - assert(Op && "Cannot dereference end iterator!"); - return Op->getUser(); - } - - SDNode *operator->() const { return operator*(); } - - SDUse &getUse() const { return *Op; } - - /// Retrieve the operand # of this use in its user. - unsigned getOperandNo() const { - assert(Op && "Cannot dereference end iterator!"); - return (unsigned)(Op - Op->getUser()->OperandList); - } - }; - - /// Provide iteration support to walk over all uses of an SDNode. - use_iterator use_begin() const { - return use_iterator(UseList); - } - - static use_iterator use_end() { return use_iterator(nullptr); } - - inline iterator_range uses() { - return make_range(use_begin(), use_end()); - } - inline iterator_range uses() const { - return make_range(use_begin(), use_end()); - } - - /// Return true if there are exactly NUSES uses of the indicated value. - /// This method ignores uses of other values defined by this operation. - bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; - - /// Return true if there are any use of the indicated value. - /// This method ignores uses of other values defined by this operation. - bool hasAnyUseOfValue(unsigned Value) const; - - /// Return true if this node is the only use of N. - bool isOnlyUserOf(const SDNode *N) const; - - /// Return true if this node is an operand of N. - bool isOperandOf(const SDNode *N) const; - - /// Return true if this node is a predecessor of N. - /// NOTE: Implemented on top of hasPredecessor and every bit as - /// expensive. Use carefully. - bool isPredecessorOf(const SDNode *N) const { - return N->hasPredecessor(this); - } - - /// Return true if N is a predecessor of this node. - /// N is either an operand of this node, or can be reached by recursively - /// traversing up the operands. - /// NOTE: This is an expensive method. Use it carefully. - bool hasPredecessor(const SDNode *N) const; - - /// Returns true if N is a predecessor of any node in Worklist. This - /// helper keeps Visited and Worklist sets externally to allow unions - /// searches to be performed in parallel, caching of results across - /// queries and incremental addition to Worklist. Stops early if N is - /// found but will resume. Remember to clear Visited and Worklists - /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before - /// giving up. The TopologicalPrune flag signals that positive NodeIds are - /// topologically ordered (Operands have strictly smaller node id) and search - /// can be pruned leveraging this. - static bool hasPredecessorHelper(const SDNode *N, - SmallPtrSetImpl &Visited, - SmallVectorImpl &Worklist, - unsigned int MaxSteps = 0, - bool TopologicalPrune = false) { - SmallVector DeferredNodes; - if (Visited.count(N)) - return true; - - // Node Id's are assigned in three places: As a topological - // ordering (> 0), during legalization (results in values set to - // 0), new nodes (set to -1). If N has a topolgical id then we - // know that all nodes with ids smaller than it cannot be - // successors and we need not check them. Filter out all node - // that can't be matches. We add them to the worklist before exit - // in case of multiple calls. Note that during selection the topological id - // may be violated if a node's predecessor is selected before it. We mark - // this at selection negating the id of unselected successors and - // restricting topological pruning to positive ids. - - int NId = N->getNodeId(); - // If we Invalidated the Id, reconstruct original NId. - if (NId < -1) - NId = -(NId + 1); - - bool Found = false; - while (!Worklist.empty()) { - const SDNode *M = Worklist.pop_back_val(); - int MId = M->getNodeId(); - if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) && - (MId > 0) && (MId < NId)) { - DeferredNodes.push_back(M); - continue; - } - for (const SDValue &OpV : M->op_values()) { - SDNode *Op = OpV.getNode(); - if (Visited.insert(Op).second) - Worklist.push_back(Op); - if (Op == N) - Found = true; - } - if (Found) - break; - if (MaxSteps != 0 && Visited.size() >= MaxSteps) - break; - } - // Push deferred nodes back on worklist. - Worklist.append(DeferredNodes.begin(), DeferredNodes.end()); - // If we bailed early, conservatively return found. - if (MaxSteps != 0 && Visited.size() >= MaxSteps) - return true; - return Found; - } - - /// Return true if all the users of N are contained in Nodes. - /// NOTE: Requires at least one match, but doesn't require them all. - static bool areOnlyUsersOf(ArrayRef Nodes, const SDNode *N); - - /// Return the number of values used by this operation. - unsigned getNumOperands() const { return NumOperands; } - - /// Return the maximum number of operands that a SDNode can hold. - static constexpr size_t getMaxNumOperands() { - return std::numeric_limits::max(); - } - - /// Helper method returns the integer value of a ConstantSDNode operand. - inline uint64_t getConstantOperandVal(unsigned Num) const; - - /// Helper method returns the APInt of a ConstantSDNode operand. - inline const APInt &getConstantOperandAPInt(unsigned Num) const; - - const SDValue &getOperand(unsigned Num) const { - assert(Num < NumOperands && "Invalid child # of SDNode!"); - return OperandList[Num]; - } - - using op_iterator = SDUse *; - - op_iterator op_begin() const { return OperandList; } - op_iterator op_end() const { return OperandList+NumOperands; } - ArrayRef ops() const { return makeArrayRef(op_begin(), op_end()); } - - /// Iterator for directly iterating over the operand SDValue's. - struct value_op_iterator - : iterator_adaptor_base { - explicit value_op_iterator(SDUse *U = nullptr) - : iterator_adaptor_base(U) {} - - const SDValue &operator*() const { return I->get(); } - }; - - iterator_range op_values() const { - return make_range(value_op_iterator(op_begin()), - value_op_iterator(op_end())); - } - - SDVTList getVTList() const { - SDVTList X = { ValueList, NumValues }; - return X; - } - - /// If this node has a glue operand, return the node - /// to which the glue operand points. Otherwise return NULL. - SDNode *getGluedNode() const { - if (getNumOperands() != 0 && - getOperand(getNumOperands()-1).getValueType() == MVT::Glue) - return getOperand(getNumOperands()-1).getNode(); - return nullptr; - } - - /// If this node has a glue value with a user, return - /// the user (there is at most one). Otherwise return NULL. - SDNode *getGluedUser() const { - for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) - if (UI.getUse().get().getValueType() == MVT::Glue) - return *UI; - return nullptr; - } - - SDNodeFlags getFlags() const { return Flags; } - void setFlags(SDNodeFlags NewFlags) { Flags = NewFlags; } - - /// Clear any flags in this node that aren't also set in Flags. - /// If Flags is not in a defined state then this has no effect. - void intersectFlagsWith(const SDNodeFlags Flags); - - /// Return the number of values defined/returned by this operator. - unsigned getNumValues() const { return NumValues; } - - /// Return the type of a specified result. - EVT getValueType(unsigned ResNo) const { - assert(ResNo < NumValues && "Illegal result number!"); - return ValueList[ResNo]; - } - - /// Return the type of a specified result as a simple type. - MVT getSimpleValueType(unsigned ResNo) const { - return getValueType(ResNo).getSimpleVT(); - } - - /// Returns MVT::getSizeInBits(getValueType(ResNo)). - /// - /// If the value type is a scalable vector type, the scalable property will - /// be set and the runtime size will be a positive integer multiple of the - /// base size. - TypeSize getValueSizeInBits(unsigned ResNo) const { - return getValueType(ResNo).getSizeInBits(); - } - - using value_iterator = const EVT *; - - value_iterator value_begin() const { return ValueList; } - value_iterator value_end() const { return ValueList+NumValues; } - iterator_range values() const { - return llvm::make_range(value_begin(), value_end()); - } - - /// Return the opcode of this operation for printing. - std::string getOperationName(const SelectionDAG *G = nullptr) const; - static const char* getIndexedModeName(ISD::MemIndexedMode AM); - void print_types(raw_ostream &OS, const SelectionDAG *G) const; - void print_details(raw_ostream &OS, const SelectionDAG *G) const; - void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const; - void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const; - - /// Print a SelectionDAG node and all children down to - /// the leaves. The given SelectionDAG allows target-specific nodes - /// to be printed in human-readable form. Unlike printr, this will - /// print the whole DAG, including children that appear multiple - /// times. - /// - void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const; - - /// Print a SelectionDAG node and children up to - /// depth "depth." The given SelectionDAG allows target-specific - /// nodes to be printed in human-readable form. Unlike printr, this - /// will print children that appear multiple times wherever they are - /// used. - /// - void printrWithDepth(raw_ostream &O, const SelectionDAG *G = nullptr, - unsigned depth = 100) const; - - /// Dump this node, for debugging. - void dump() const; - - /// Dump (recursively) this node and its use-def subgraph. - void dumpr() const; - - /// Dump this node, for debugging. - /// The given SelectionDAG allows target-specific nodes to be printed - /// in human-readable form. - void dump(const SelectionDAG *G) const; - - /// Dump (recursively) this node and its use-def subgraph. - /// The given SelectionDAG allows target-specific nodes to be printed - /// in human-readable form. - void dumpr(const SelectionDAG *G) const; - - /// printrFull to dbgs(). The given SelectionDAG allows - /// target-specific nodes to be printed in human-readable form. - /// Unlike dumpr, this will print the whole DAG, including children - /// that appear multiple times. - void dumprFull(const SelectionDAG *G = nullptr) const; - - /// printrWithDepth to dbgs(). The given - /// SelectionDAG allows target-specific nodes to be printed in - /// human-readable form. Unlike dumpr, this will print children - /// that appear multiple times wherever they are used. - /// - void dumprWithDepth(const SelectionDAG *G = nullptr, - unsigned depth = 100) const; - - /// Gather unique data for the node. - void Profile(FoldingSetNodeID &ID) const; - - /// This method should only be used by the SDUse class. - void addUse(SDUse &U) { U.addToList(&UseList); } - -protected: - static SDVTList getSDVTList(EVT VT) { - SDVTList Ret = { getValueTypeList(VT), 1 }; - return Ret; - } - - /// Create an SDNode. - /// - /// SDNodes are created without any operands, and never own the operand - /// storage. To add operands, see SelectionDAG::createOperands. - SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) - : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs), - IROrder(Order), debugLoc(std::move(dl)) { - memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits)); - assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); - assert(NumValues == VTs.NumVTs && - "NumValues wasn't wide enough for its operands!"); - } - - /// Release the operands and set this node to have zero operands. - void DropOperands(); -}; - -/// Wrapper class for IR location info (IR ordering and DebugLoc) to be passed -/// into SDNode creation functions. -/// When an SDNode is created from the DAGBuilder, the DebugLoc is extracted -/// from the original Instruction, and IROrder is the ordinal position of -/// the instruction. -/// When an SDNode is created after the DAG is being built, both DebugLoc and -/// the IROrder are propagated from the original SDNode. -/// So SDLoc class provides two constructors besides the default one, one to -/// be used by the DAGBuilder, the other to be used by others. -class SDLoc { -private: - DebugLoc DL; - int IROrder = 0; - -public: - SDLoc() = default; - SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {} - SDLoc(const SDValue V) : SDLoc(V.getNode()) {} - SDLoc(const Instruction *I, int Order) : IROrder(Order) { - assert(Order >= 0 && "bad IROrder"); - if (I) - DL = I->getDebugLoc(); - } - - unsigned getIROrder() const { return IROrder; } - const DebugLoc &getDebugLoc() const { return DL; } -}; - -// Define inline functions from the SDValue class. - -inline SDValue::SDValue(SDNode *node, unsigned resno) - : Node(node), ResNo(resno) { - // Explicitly check for !ResNo to avoid use-after-free, because there are - // callers that use SDValue(N, 0) with a deleted N to indicate successful - // combines. - assert((!Node || !ResNo || ResNo < Node->getNumValues()) && - "Invalid result number for the given node!"); - assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps."); -} - -inline unsigned SDValue::getOpcode() const { - return Node->getOpcode(); -} - -inline EVT SDValue::getValueType() const { - return Node->getValueType(ResNo); -} - -inline unsigned SDValue::getNumOperands() const { - return Node->getNumOperands(); -} - -inline const SDValue &SDValue::getOperand(unsigned i) const { - return Node->getOperand(i); -} - -inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { - return Node->getConstantOperandVal(i); -} - -inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const { - return Node->getConstantOperandAPInt(i); -} - -inline bool SDValue::isTargetOpcode() const { - return Node->isTargetOpcode(); -} - -inline bool SDValue::isTargetMemoryOpcode() const { - return Node->isTargetMemoryOpcode(); -} - -inline bool SDValue::isMachineOpcode() const { - return Node->isMachineOpcode(); -} - -inline unsigned SDValue::getMachineOpcode() const { - return Node->getMachineOpcode(); -} - -inline bool SDValue::isUndef() const { - return Node->isUndef(); -} - -inline bool SDValue::use_empty() const { - return !Node->hasAnyUseOfValue(ResNo); -} - -inline bool SDValue::hasOneUse() const { - return Node->hasNUsesOfValue(1, ResNo); -} - -inline const DebugLoc &SDValue::getDebugLoc() const { - return Node->getDebugLoc(); -} - -inline void SDValue::dump() const { - return Node->dump(); -} - -inline void SDValue::dump(const SelectionDAG *G) const { - return Node->dump(G); -} - -inline void SDValue::dumpr() const { - return Node->dumpr(); -} - -inline void SDValue::dumpr(const SelectionDAG *G) const { - return Node->dumpr(G); -} - -// Define inline functions from the SDUse class. - -inline void SDUse::set(const SDValue &V) { - if (Val.getNode()) removeFromList(); - Val = V; - if (V.getNode()) V.getNode()->addUse(*this); -} - -inline void SDUse::setInitial(const SDValue &V) { - Val = V; - V.getNode()->addUse(*this); -} - -inline void SDUse::setNode(SDNode *N) { - if (Val.getNode()) removeFromList(); - Val.setNode(N); - if (N) N->addUse(*this); -} - -/// This class is used to form a handle around another node that -/// is persistent and is updated across invocations of replaceAllUsesWith on its -/// operand. This node should be directly created by end-users and not added to -/// the AllNodes list. -class HandleSDNode : public SDNode { - SDUse Op; - -public: - explicit HandleSDNode(SDValue X) - : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) { - // HandleSDNodes are never inserted into the DAG, so they won't be - // auto-numbered. Use ID 65535 as a sentinel. - PersistentId = 0xffff; - - // Manually set up the operand list. This node type is special in that it's - // always stack allocated and SelectionDAG does not manage its operands. - // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not - // be so special. - Op.setUser(this); - Op.setInitial(X); - NumOperands = 1; - OperandList = &Op; - } - ~HandleSDNode(); - - const SDValue &getValue() const { return Op; } -}; - -class AddrSpaceCastSDNode : public SDNode { -private: - unsigned SrcAddrSpace; - unsigned DestAddrSpace; - -public: - AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, EVT VT, - unsigned SrcAS, unsigned DestAS); - - unsigned getSrcAddressSpace() const { return SrcAddrSpace; } - unsigned getDestAddressSpace() const { return DestAddrSpace; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ADDRSPACECAST; - } -}; - -/// This is an abstract virtual class for memory operations. -class MemSDNode : public SDNode { -private: - // VT of in-memory value. - EVT MemoryVT; - -protected: - /// Memory reference information. - MachineMemOperand *MMO; - -public: - MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs, - EVT memvt, MachineMemOperand *MMO); - - bool readMem() const { return MMO->isLoad(); } - bool writeMem() const { return MMO->isStore(); } - - /// Returns alignment and volatility of the memory access - Align getOriginalAlign() const { return MMO->getBaseAlign(); } - Align getAlign() const { return MMO->getAlign(); } - // FIXME: Remove once transition to getAlign is over. - unsigned getAlignment() const { return MMO->getAlign().value(); } - - /// Return the SubclassData value, without HasDebugValue. This contains an - /// encoding of the volatile flag, as well as bits used by subclasses. This - /// function should only be used to compute a FoldingSetNodeID value. - /// The HasDebugValue bit is masked out because CSE map needs to match - /// nodes with debug info with nodes without debug info. Same is about - /// isDivergent bit. - unsigned getRawSubclassData() const { - uint16_t Data; - union { - char RawSDNodeBits[sizeof(uint16_t)]; - SDNodeBitfields SDNodeBits; - }; - memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits)); - SDNodeBits.HasDebugValue = 0; - SDNodeBits.IsDivergent = false; - memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits)); - return Data; - } - - bool isVolatile() const { return MemSDNodeBits.IsVolatile; } - bool isNonTemporal() const { return MemSDNodeBits.IsNonTemporal; } - bool isDereferenceable() const { return MemSDNodeBits.IsDereferenceable; } - bool isInvariant() const { return MemSDNodeBits.IsInvariant; } - - // Returns the offset from the location of the access. - int64_t getSrcValueOffset() const { return MMO->getOffset(); } - - /// Returns the AA info that describes the dereference. - AAMDNodes getAAInfo() const { return MMO->getAAInfo(); } - - /// Returns the Ranges that describes the dereference. - const MDNode *getRanges() const { return MMO->getRanges(); } - - /// Returns the synchronization scope ID for this memory operation. - SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); } - - /// Return the atomic ordering requirements for this memory operation. For - /// cmpxchg atomic operations, return the atomic ordering requirements when - /// store occurs. - AtomicOrdering getSuccessOrdering() const { - return MMO->getSuccessOrdering(); - } - - /// Return a single atomic ordering that is at least as strong as both the - /// success and failure orderings for an atomic operation. (For operations - /// other than cmpxchg, this is equivalent to getSuccessOrdering().) - AtomicOrdering getMergedOrdering() const { return MMO->getMergedOrdering(); } - - /// Return true if the memory operation ordering is Unordered or higher. - bool isAtomic() const { return MMO->isAtomic(); } - - /// Returns true if the memory operation doesn't imply any ordering - /// constraints on surrounding memory operations beyond the normal memory - /// aliasing rules. - bool isUnordered() const { return MMO->isUnordered(); } - - /// Returns true if the memory operation is neither atomic or volatile. - bool isSimple() const { return !isAtomic() && !isVolatile(); } - - /// Return the type of the in-memory value. - EVT getMemoryVT() const { return MemoryVT; } - - /// Return a MachineMemOperand object describing the memory - /// reference performed by operation. - MachineMemOperand *getMemOperand() const { return MMO; } - - const MachinePointerInfo &getPointerInfo() const { - return MMO->getPointerInfo(); - } - - /// Return the address space for the associated pointer - unsigned getAddressSpace() const { - return getPointerInfo().getAddrSpace(); - } - - /// Update this MemSDNode's MachineMemOperand information - /// to reflect the alignment of NewMMO, if it has a greater alignment. - /// This must only be used when the new alignment applies to all users of - /// this MachineMemOperand. - void refineAlignment(const MachineMemOperand *NewMMO) { - MMO->refineAlignment(NewMMO); - } - - const SDValue &getChain() const { return getOperand(0); } - - const SDValue &getBasePtr() const { - switch (getOpcode()) { - case ISD::STORE: - case ISD::VP_STORE: - case ISD::MSTORE: - case ISD::VP_SCATTER: - return getOperand(2); - case ISD::MGATHER: - case ISD::MSCATTER: - return getOperand(3); - default: - return getOperand(1); - } - } - - // Methods to support isa and dyn_cast - static bool classof(const SDNode *N) { - // For some targets, we lower some target intrinsics to a MemIntrinsicNode - // with either an intrinsic or a target opcode. - switch (N->getOpcode()) { - case ISD::LOAD: - case ISD::STORE: - case ISD::PREFETCH: - case ISD::ATOMIC_CMP_SWAP: - case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: - case ISD::ATOMIC_SWAP: - case ISD::ATOMIC_LOAD_ADD: - case ISD::ATOMIC_LOAD_SUB: - case ISD::ATOMIC_LOAD_AND: - case ISD::ATOMIC_LOAD_CLR: - case ISD::ATOMIC_LOAD_OR: - case ISD::ATOMIC_LOAD_XOR: - case ISD::ATOMIC_LOAD_NAND: - case ISD::ATOMIC_LOAD_MIN: - case ISD::ATOMIC_LOAD_MAX: - case ISD::ATOMIC_LOAD_UMIN: - case ISD::ATOMIC_LOAD_UMAX: - case ISD::ATOMIC_LOAD_FADD: - case ISD::ATOMIC_LOAD_FSUB: - case ISD::ATOMIC_LOAD: - case ISD::ATOMIC_STORE: - case ISD::MLOAD: - case ISD::MSTORE: - case ISD::MGATHER: - case ISD::MSCATTER: - case ISD::VP_LOAD: - case ISD::VP_STORE: - case ISD::VP_GATHER: - case ISD::VP_SCATTER: - return true; - default: - return N->isMemIntrinsic() || N->isTargetMemoryOpcode(); - } - } -}; - -/// This is an SDNode representing atomic operations. -class AtomicSDNode : public MemSDNode { -public: - AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL, - EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) || - MMO->isAtomic()) && "then why are we using an AtomicSDNode?"); - } - - const SDValue &getBasePtr() const { return getOperand(1); } - const SDValue &getVal() const { return getOperand(2); } - - /// Returns true if this SDNode represents cmpxchg atomic operation, false - /// otherwise. - bool isCompareAndSwap() const { - unsigned Op = getOpcode(); - return Op == ISD::ATOMIC_CMP_SWAP || - Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS; - } - - /// For cmpxchg atomic operations, return the atomic ordering requirements - /// when store does not occur. - AtomicOrdering getFailureOrdering() const { - assert(isCompareAndSwap() && "Must be cmpxchg operation"); - return MMO->getFailureOrdering(); - } - - // Methods to support isa and dyn_cast - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || - N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || - N->getOpcode() == ISD::ATOMIC_SWAP || - N->getOpcode() == ISD::ATOMIC_LOAD_ADD || - N->getOpcode() == ISD::ATOMIC_LOAD_SUB || - N->getOpcode() == ISD::ATOMIC_LOAD_AND || - N->getOpcode() == ISD::ATOMIC_LOAD_CLR || - N->getOpcode() == ISD::ATOMIC_LOAD_OR || - N->getOpcode() == ISD::ATOMIC_LOAD_XOR || - N->getOpcode() == ISD::ATOMIC_LOAD_NAND || - N->getOpcode() == ISD::ATOMIC_LOAD_MIN || - N->getOpcode() == ISD::ATOMIC_LOAD_MAX || - N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || - N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || - N->getOpcode() == ISD::ATOMIC_LOAD_FADD || - N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || - N->getOpcode() == ISD::ATOMIC_LOAD || - N->getOpcode() == ISD::ATOMIC_STORE; - } -}; - -/// This SDNode is used for target intrinsics that touch -/// memory and need an associated MachineMemOperand. Its opcode may be -/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode -/// with a value not less than FIRST_TARGET_MEMORY_OPCODE. -class MemIntrinsicSDNode : public MemSDNode { -public: - MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, - SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) { - SDNodeBits.IsMemIntrinsic = true; - } - - // Methods to support isa and dyn_cast - static bool classof(const SDNode *N) { - // We lower some target intrinsics to their target opcode - // early a node with a target opcode can be of this class - return N->isMemIntrinsic() || - N->getOpcode() == ISD::PREFETCH || - N->isTargetMemoryOpcode(); - } -}; - -/// This SDNode is used to implement the code generator -/// support for the llvm IR shufflevector instruction. It combines elements -/// from two input vectors into a new input vector, with the selection and -/// ordering of elements determined by an array of integers, referred to as -/// the shuffle mask. For input vectors of width N, mask indices of 0..N-1 -/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS. -/// An index of -1 is treated as undef, such that the code generator may put -/// any value in the corresponding element of the result. -class ShuffleVectorSDNode : public SDNode { - // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and - // is freed when the SelectionDAG object is destroyed. - const int *Mask; - -protected: - friend class SelectionDAG; - - ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M) - : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {} - -public: - ArrayRef getMask() const { - EVT VT = getValueType(0); - return makeArrayRef(Mask, VT.getVectorNumElements()); - } - - int getMaskElt(unsigned Idx) const { - assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); - return Mask[Idx]; - } - - bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - - int getSplatIndex() const { - assert(isSplat() && "Cannot get splat index for non-splat!"); - EVT VT = getValueType(0); - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) - if (Mask[i] >= 0) - return Mask[i]; - - // We can choose any index value here and be correct because all elements - // are undefined. Return 0 for better potential for callers to simplify. - return 0; - } - - static bool isSplatMask(const int *Mask, EVT VT); - - /// Change values in a shuffle permute mask assuming - /// the two vector operands have swapped position. - static void commuteMask(MutableArrayRef Mask) { - unsigned NumElems = Mask.size(); - for (unsigned i = 0; i != NumElems; ++i) { - int idx = Mask[i]; - if (idx < 0) - continue; - else if (idx < (int)NumElems) - Mask[i] = idx + NumElems; - else - Mask[i] = idx - NumElems; - } - } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VECTOR_SHUFFLE; - } -}; - -class ConstantSDNode : public SDNode { - friend class SelectionDAG; - - const ConstantInt *Value; - - ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) - : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(), - getSDVTList(VT)), - Value(val) { - ConstantSDNodeBits.IsOpaque = isOpaque; - } - -public: - const ConstantInt *getConstantIntValue() const { return Value; } - const APInt &getAPIntValue() const { return Value->getValue(); } - uint64_t getZExtValue() const { return Value->getZExtValue(); } - int64_t getSExtValue() const { return Value->getSExtValue(); } - uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) { - return Value->getLimitedValue(Limit); - } - MaybeAlign getMaybeAlignValue() const { return Value->getMaybeAlignValue(); } - Align getAlignValue() const { return Value->getAlignValue(); } - - bool isOne() const { return Value->isOne(); } - bool isZero() const { return Value->isZero(); } - // NOTE: This is soft-deprecated. Please use `isZero()` instead. - bool isNullValue() const { return isZero(); } - bool isAllOnes() const { return Value->isMinusOne(); } - // NOTE: This is soft-deprecated. Please use `isAllOnes()` instead. - bool isAllOnesValue() const { return isAllOnes(); } - bool isMaxSignedValue() const { return Value->isMaxValue(true); } - bool isMinSignedValue() const { return Value->isMinValue(true); } - - bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::Constant || - N->getOpcode() == ISD::TargetConstant; - } -}; - -uint64_t SDNode::getConstantOperandVal(unsigned Num) const { - return cast(getOperand(Num))->getZExtValue(); -} - -const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const { - return cast(getOperand(Num))->getAPIntValue(); -} - -class ConstantFPSDNode : public SDNode { - friend class SelectionDAG; - - const ConstantFP *Value; - - ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) - : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, - DebugLoc(), getSDVTList(VT)), - Value(val) {} - -public: - const APFloat& getValueAPF() const { return Value->getValueAPF(); } - const ConstantFP *getConstantFPValue() const { return Value; } - - /// Return true if the value is positive or negative zero. - bool isZero() const { return Value->isZero(); } - - /// Return true if the value is a NaN. - bool isNaN() const { return Value->isNaN(); } - - /// Return true if the value is an infinity - bool isInfinity() const { return Value->isInfinity(); } - - /// Return true if the value is negative. - bool isNegative() const { return Value->isNegative(); } - - /// We don't rely on operator== working on double values, as - /// it returns true for things that are clearly not equal, like -0.0 and 0.0. - /// As such, this method can be used to do an exact bit-for-bit comparison of - /// two floating point values. - - /// We leave the version with the double argument here because it's just so - /// convenient to write "2.0" and the like. Without this function we'd - /// have to duplicate its logic everywhere it's called. - bool isExactlyValue(double V) const { - return Value->getValueAPF().isExactlyValue(V); - } - bool isExactlyValue(const APFloat& V) const; - - static bool isValueValidForType(EVT VT, const APFloat& Val); - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ConstantFP || - N->getOpcode() == ISD::TargetConstantFP; - } -}; - -/// Returns true if \p V is a constant integer zero. -bool isNullConstant(SDValue V); - -/// Returns true if \p V is an FP constant with a value of positive zero. -bool isNullFPConstant(SDValue V); - -/// Returns true if \p V is an integer constant with all bits set. -bool isAllOnesConstant(SDValue V); - -/// Returns true if \p V is a constant integer one. -bool isOneConstant(SDValue V); - -/// Return the non-bitcasted source operand of \p V if it exists. -/// If \p V is not a bitcasted value, it is returned as-is. -SDValue peekThroughBitcasts(SDValue V); - -/// Return the non-bitcasted and one-use source operand of \p V if it exists. -/// If \p V is not a bitcasted one-use value, it is returned as-is. -SDValue peekThroughOneUseBitcasts(SDValue V); - -/// Return the non-extracted vector source operand of \p V if it exists. -/// If \p V is not an extracted subvector, it is returned as-is. -SDValue peekThroughExtractSubvectors(SDValue V); - -/// Returns true if \p V is a bitwise not operation. Assumes that an all ones -/// constant is canonicalized to be operand 1. -bool isBitwiseNot(SDValue V, bool AllowUndefs = false); - -/// Returns the SDNode if it is a constant splat BuildVector or constant int. -ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false, - bool AllowTruncation = false); - -/// Returns the SDNode if it is a demanded constant splat BuildVector or -/// constant int. -ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts, - bool AllowUndefs = false, - bool AllowTruncation = false); - -/// Returns the SDNode if it is a constant splat BuildVector or constant float. -ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false); - -/// Returns the SDNode if it is a demanded constant splat BuildVector or -/// constant float. -ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts, - bool AllowUndefs = false); - -/// Return true if the value is a constant 0 integer or a splatted vector of -/// a constant 0 integer (with no undefs by default). -/// Build vector implicit truncation is not an issue for null values. -bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false); - -/// Return true if the value is a constant 1 integer or a splatted vector of a -/// constant 1 integer (with no undefs). -/// Does not permit build vector implicit truncation. -bool isOneOrOneSplat(SDValue V, bool AllowUndefs = false); - -/// Return true if the value is a constant -1 integer or a splatted vector of a -/// constant -1 integer (with no undefs). -/// Does not permit build vector implicit truncation. -bool isAllOnesOrAllOnesSplat(SDValue V, bool AllowUndefs = false); - -/// Return true if \p V is either a integer or FP constant. -inline bool isIntOrFPConstant(SDValue V) { - return isa(V) || isa(V); -} - -class GlobalAddressSDNode : public SDNode { - friend class SelectionDAG; - - const GlobalValue *TheGlobal; - int64_t Offset; - unsigned TargetFlags; - - GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, - const GlobalValue *GA, EVT VT, int64_t o, - unsigned TF); - -public: - const GlobalValue *getGlobal() const { return TheGlobal; } - int64_t getOffset() const { return Offset; } - unsigned getTargetFlags() const { return TargetFlags; } - // Return the address space this GlobalAddress belongs to. - unsigned getAddressSpace() const; - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::GlobalAddress || - N->getOpcode() == ISD::TargetGlobalAddress || - N->getOpcode() == ISD::GlobalTLSAddress || - N->getOpcode() == ISD::TargetGlobalTLSAddress; - } -}; - -class FrameIndexSDNode : public SDNode { - friend class SelectionDAG; - - int FI; - - FrameIndexSDNode(int fi, EVT VT, bool isTarg) - : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, - 0, DebugLoc(), getSDVTList(VT)), FI(fi) { - } - -public: - int getIndex() const { return FI; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::FrameIndex || - N->getOpcode() == ISD::TargetFrameIndex; - } -}; - -/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate -/// the offset and size that are started/ended in the underlying FrameIndex. -class LifetimeSDNode : public SDNode { - friend class SelectionDAG; - int64_t Size; - int64_t Offset; // -1 if offset is unknown. - - LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, - SDVTList VTs, int64_t Size, int64_t Offset) - : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {} -public: - int64_t getFrameIndex() const { - return cast(getOperand(1))->getIndex(); - } - - bool hasOffset() const { return Offset >= 0; } - int64_t getOffset() const { - assert(hasOffset() && "offset is unknown"); - return Offset; - } - int64_t getSize() const { - assert(hasOffset() && "offset is unknown"); - return Size; - } - - // Methods to support isa and dyn_cast - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::LIFETIME_START || - N->getOpcode() == ISD::LIFETIME_END; - } -}; - -/// This SDNode is used for PSEUDO_PROBE values, which are the function guid and -/// the index of the basic block being probed. A pseudo probe serves as a place -/// holder and will be removed at the end of compilation. It does not have any -/// operand because we do not want the instruction selection to deal with any. -class PseudoProbeSDNode : public SDNode { - friend class SelectionDAG; - uint64_t Guid; - uint64_t Index; - uint32_t Attributes; - - PseudoProbeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &Dl, - SDVTList VTs, uint64_t Guid, uint64_t Index, uint32_t Attr) - : SDNode(Opcode, Order, Dl, VTs), Guid(Guid), Index(Index), - Attributes(Attr) {} - -public: - uint64_t getGuid() const { return Guid; } - uint64_t getIndex() const { return Index; } - uint32_t getAttributes() const { return Attributes; } - - // Methods to support isa and dyn_cast - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::PSEUDO_PROBE; - } -}; - -class JumpTableSDNode : public SDNode { - friend class SelectionDAG; - - int JTI; - unsigned TargetFlags; - - JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned TF) - : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, - 0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { - } - -public: - int getIndex() const { return JTI; } - unsigned getTargetFlags() const { return TargetFlags; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::JumpTable || - N->getOpcode() == ISD::TargetJumpTable; - } -}; - -class ConstantPoolSDNode : public SDNode { - friend class SelectionDAG; - - union { - const Constant *ConstVal; - MachineConstantPoolValue *MachineCPVal; - } Val; - int Offset; // It's a MachineConstantPoolValue if top bit is set. - Align Alignment; // Minimum alignment requirement of CP. - unsigned TargetFlags; - - ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, - Align Alignment, unsigned TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, - DebugLoc(), getSDVTList(VT)), - Offset(o), Alignment(Alignment), TargetFlags(TF) { - assert(Offset >= 0 && "Offset is too large"); - Val.ConstVal = c; - } - - ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, EVT VT, int o, - Align Alignment, unsigned TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, - DebugLoc(), getSDVTList(VT)), - Offset(o), Alignment(Alignment), TargetFlags(TF) { - assert(Offset >= 0 && "Offset is too large"); - Val.MachineCPVal = v; - Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); - } - -public: - bool isMachineConstantPoolEntry() const { - return Offset < 0; - } - - const Constant *getConstVal() const { - assert(!isMachineConstantPoolEntry() && "Wrong constantpool type"); - return Val.ConstVal; - } - - MachineConstantPoolValue *getMachineCPVal() const { - assert(isMachineConstantPoolEntry() && "Wrong constantpool type"); - return Val.MachineCPVal; - } - - int getOffset() const { - return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); - } - - // Return the alignment of this constant pool object, which is either 0 (for - // default alignment) or the desired value. - Align getAlign() const { return Alignment; } - unsigned getTargetFlags() const { return TargetFlags; } - - Type *getType() const; - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ConstantPool || - N->getOpcode() == ISD::TargetConstantPool; - } -}; - -/// Completely target-dependent object reference. -class TargetIndexSDNode : public SDNode { - friend class SelectionDAG; - - unsigned TargetFlags; - int Index; - int64_t Offset; - -public: - TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned TF) - : SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)), - TargetFlags(TF), Index(Idx), Offset(Ofs) {} - - unsigned getTargetFlags() const { return TargetFlags; } - int getIndex() const { return Index; } - int64_t getOffset() const { return Offset; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::TargetIndex; - } -}; - -class BasicBlockSDNode : public SDNode { - friend class SelectionDAG; - - MachineBasicBlock *MBB; - - /// Debug info is meaningful and potentially useful here, but we create - /// blocks out of order when they're jumped to, which makes it a bit - /// harder. Let's see if we need it first. - explicit BasicBlockSDNode(MachineBasicBlock *mbb) - : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) - {} - -public: - MachineBasicBlock *getBasicBlock() const { return MBB; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::BasicBlock; - } -}; - -/// A "pseudo-class" with methods for operating on BUILD_VECTORs. -class BuildVectorSDNode : public SDNode { -public: - // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode() = delete; - - /// Check if this is a constant splat, and if so, find the - /// smallest element size that splats the vector. If MinSplatBits is - /// nonzero, the element size must be at least that large. Note that the - /// splat element may be the entire vector (i.e., a one element vector). - /// Returns the splat element value in SplatValue. Any undefined bits in - /// that value are zero, and the corresponding bits in the SplatUndef mask - /// are set. The SplatBitSize value is set to the splat element size in - /// bits. HasAnyUndefs is set to true if any bits in the vector are - /// undefined. isBigEndian describes the endianness of the target. - bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, - unsigned &SplatBitSize, bool &HasAnyUndefs, - unsigned MinSplatBits = 0, - bool isBigEndian = false) const; - - /// Returns the demanded splatted value or a null value if this is not a - /// splat. - /// - /// The DemandedElts mask indicates the elements that must be in the splat. - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - SDValue getSplatValue(const APInt &DemandedElts, - BitVector *UndefElements = nullptr) const; - - /// Returns the splatted value or a null value if this is not a splat. - /// - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - SDValue getSplatValue(BitVector *UndefElements = nullptr) const; - - /// Find the shortest repeating sequence of values in the build vector. - /// - /// e.g. { u, X, u, X, u, u, X, u } -> { X } - /// { X, Y, u, Y, u, u, X, u } -> { X, Y } - /// - /// Currently this must be a power-of-2 build vector. - /// The DemandedElts mask indicates the elements that must be present, - /// undemanded elements in Sequence may be null (SDValue()). If passed a - /// non-null UndefElements bitvector, it will resize it to match the original - /// vector width and set the bits where elements are undef. If result is - /// false, Sequence will be empty. - bool getRepeatedSequence(const APInt &DemandedElts, - SmallVectorImpl &Sequence, - BitVector *UndefElements = nullptr) const; - - /// Find the shortest repeating sequence of values in the build vector. - /// - /// e.g. { u, X, u, X, u, u, X, u } -> { X } - /// { X, Y, u, Y, u, u, X, u } -> { X, Y } - /// - /// Currently this must be a power-of-2 build vector. - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the original vector width and set the bits where elements are undef. - /// If result is false, Sequence will be empty. - bool getRepeatedSequence(SmallVectorImpl &Sequence, - BitVector *UndefElements = nullptr) const; - - /// Returns the demanded splatted constant or null if this is not a constant - /// splat. - /// - /// The DemandedElts mask indicates the elements that must be in the splat. - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - ConstantSDNode * - getConstantSplatNode(const APInt &DemandedElts, - BitVector *UndefElements = nullptr) const; - - /// Returns the splatted constant or null if this is not a constant - /// splat. - /// - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - ConstantSDNode * - getConstantSplatNode(BitVector *UndefElements = nullptr) const; - - /// Returns the demanded splatted constant FP or null if this is not a - /// constant FP splat. - /// - /// The DemandedElts mask indicates the elements that must be in the splat. - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - ConstantFPSDNode * - getConstantFPSplatNode(const APInt &DemandedElts, - BitVector *UndefElements = nullptr) const; - - /// Returns the splatted constant FP or null if this is not a constant - /// FP splat. - /// - /// If passed a non-null UndefElements bitvector, it will resize it to match - /// the vector width and set the bits where elements are undef. - ConstantFPSDNode * - getConstantFPSplatNode(BitVector *UndefElements = nullptr) const; - - /// If this is a constant FP splat and the splatted constant FP is an - /// exact power or 2, return the log base 2 integer value. Otherwise, - /// return -1. - /// - /// The BitWidth specifies the necessary bit precision. - int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, - uint32_t BitWidth) const; - - /// Extract the raw bit data from a build vector of Undef, Constant or - /// ConstantFP node elements. Each raw bit element will be \p - /// DstEltSizeInBits wide, undef elements are treated as zero, and entirely - /// undefined elements are flagged in \p UndefElements. - bool getConstantRawBits(bool IsLittleEndian, unsigned DstEltSizeInBits, - SmallVectorImpl &RawBitElements, - BitVector &UndefElements) const; - - bool isConstant() const; - - /// Recast bit data \p SrcBitElements to \p DstEltSizeInBits wide elements. - /// Undef elements are treated as zero, and entirely undefined elements are - /// flagged in \p DstUndefElements. - static void recastRawBits(bool IsLittleEndian, unsigned DstEltSizeInBits, - SmallVectorImpl &DstBitElements, - ArrayRef SrcBitElements, - BitVector &DstUndefElements, - const BitVector &SrcUndefElements); - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::BUILD_VECTOR; - } -}; - -/// An SDNode that holds an arbitrary LLVM IR Value. This is -/// used when the SelectionDAG needs to make a simple reference to something -/// in the LLVM IR representation. -/// -class SrcValueSDNode : public SDNode { - friend class SelectionDAG; - - const Value *V; - - /// Create a SrcValue for a general value. - explicit SrcValueSDNode(const Value *v) - : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} - -public: - /// Return the contained Value. - const Value *getValue() const { return V; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::SRCVALUE; - } -}; - -class MDNodeSDNode : public SDNode { - friend class SelectionDAG; - - const MDNode *MD; - - explicit MDNodeSDNode(const MDNode *md) - : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) - {} - -public: - const MDNode *getMD() const { return MD; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MDNODE_SDNODE; - } -}; - -class RegisterSDNode : public SDNode { - friend class SelectionDAG; - - Register Reg; - - RegisterSDNode(Register reg, EVT VT) - : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {} - -public: - Register getReg() const { return Reg; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::Register; - } -}; - -class RegisterMaskSDNode : public SDNode { - friend class SelectionDAG; - - // The memory for RegMask is not owned by the node. - const uint32_t *RegMask; - - RegisterMaskSDNode(const uint32_t *mask) - : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)), - RegMask(mask) {} - -public: - const uint32_t *getRegMask() const { return RegMask; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::RegisterMask; - } -}; - -class BlockAddressSDNode : public SDNode { - friend class SelectionDAG; - - const BlockAddress *BA; - int64_t Offset; - unsigned TargetFlags; - - BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, - int64_t o, unsigned Flags) - : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), - BA(ba), Offset(o), TargetFlags(Flags) {} - -public: - const BlockAddress *getBlockAddress() const { return BA; } - int64_t getOffset() const { return Offset; } - unsigned getTargetFlags() const { return TargetFlags; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::BlockAddress || - N->getOpcode() == ISD::TargetBlockAddress; - } -}; - -class LabelSDNode : public SDNode { - friend class SelectionDAG; - - MCSymbol *Label; - - LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L) - : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) { - assert(LabelSDNode::classof(this) && "not a label opcode"); - } - -public: - MCSymbol *getLabel() const { return Label; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::EH_LABEL || - N->getOpcode() == ISD::ANNOTATION_LABEL; - } -}; - -class ExternalSymbolSDNode : public SDNode { - friend class SelectionDAG; - - const char *Symbol; - unsigned TargetFlags; - - ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned TF, EVT VT) - : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, 0, - DebugLoc(), getSDVTList(VT)), - Symbol(Sym), TargetFlags(TF) {} - -public: - const char *getSymbol() const { return Symbol; } - unsigned getTargetFlags() const { return TargetFlags; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::ExternalSymbol || - N->getOpcode() == ISD::TargetExternalSymbol; - } -}; - -class MCSymbolSDNode : public SDNode { - friend class SelectionDAG; - - MCSymbol *Symbol; - - MCSymbolSDNode(MCSymbol *Symbol, EVT VT) - : SDNode(ISD::MCSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Symbol) {} - -public: - MCSymbol *getMCSymbol() const { return Symbol; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MCSymbol; - } -}; - -class CondCodeSDNode : public SDNode { - friend class SelectionDAG; - - ISD::CondCode Condition; - - explicit CondCodeSDNode(ISD::CondCode Cond) - : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)), - Condition(Cond) {} - -public: - ISD::CondCode get() const { return Condition; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::CONDCODE; - } -}; - -/// This class is used to represent EVT's, which are used -/// to parameterize some operations. -class VTSDNode : public SDNode { - friend class SelectionDAG; - - EVT ValueType; - - explicit VTSDNode(EVT VT) - : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)), - ValueType(VT) {} - -public: - EVT getVT() const { return ValueType; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VALUETYPE; - } -}; - -/// Base class for LoadSDNode and StoreSDNode -class LSBaseSDNode : public MemSDNode { -public: - LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl, - SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, - MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - LSBaseSDNodeBits.AddressingMode = AM; - assert(getAddressingMode() == AM && "Value truncated"); - } - - const SDValue &getOffset() const { - return getOperand(getOpcode() == ISD::LOAD ? 2 : 3); - } - - /// Return the addressing mode for this load or store: - /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. - ISD::MemIndexedMode getAddressingMode() const { - return static_cast(LSBaseSDNodeBits.AddressingMode); - } - - /// Return true if this is a pre/post inc/dec load/store. - bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } - - /// Return true if this is NOT a pre/post inc/dec load/store. - bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::LOAD || - N->getOpcode() == ISD::STORE; - } -}; - -/// This class is used to represent ISD::LOAD nodes. -class LoadSDNode : public LSBaseSDNode { - friend class SelectionDAG; - - LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, - MachineMemOperand *MMO) - : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) { - LoadSDNodeBits.ExtTy = ETy; - assert(readMem() && "Load MachineMemOperand is not a load!"); - assert(!writeMem() && "Load MachineMemOperand is a store!"); - } - -public: - /// Return whether this is a plain node, - /// or one of the varieties of value-extending loads. - ISD::LoadExtType getExtensionType() const { - return static_cast(LoadSDNodeBits.ExtTy); - } - - const SDValue &getBasePtr() const { return getOperand(1); } - const SDValue &getOffset() const { return getOperand(2); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::LOAD; - } -}; - -/// This class is used to represent ISD::STORE nodes. -class StoreSDNode : public LSBaseSDNode { - friend class SelectionDAG; - - StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, - MachineMemOperand *MMO) - : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) { - StoreSDNodeBits.IsTruncating = isTrunc; - assert(!readMem() && "Store MachineMemOperand is a load!"); - assert(writeMem() && "Store MachineMemOperand is not a store!"); - } - -public: - /// Return true if the op does a truncation before store. - /// For integers this is the same as doing a TRUNCATE and storing the result. - /// For floats, it is the same as doing an FP_ROUND and storing the result. - bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } - void setTruncatingStore(bool Truncating) { - StoreSDNodeBits.IsTruncating = Truncating; - } - - const SDValue &getValue() const { return getOperand(1); } - const SDValue &getBasePtr() const { return getOperand(2); } - const SDValue &getOffset() const { return getOperand(3); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::STORE; - } -}; - -/// This base class is used to represent VP_LOAD and VP_STORE nodes -class VPLoadStoreSDNode : public MemSDNode { -public: - friend class SelectionDAG; - - VPLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl, - SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, - MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - LSBaseSDNodeBits.AddressingMode = AM; - assert(getAddressingMode() == AM && "Value truncated"); - } - - // VPLoadSDNode (Chain, Ptr, Offset, Mask, EVL) - // VPStoreSDNode (Chain, Data, Ptr, Offset, Mask, EVL) - // Mask is a vector of i1 elements; - // the type of EVL is TLI.getVPExplicitVectorLengthTy(). - const SDValue &getOffset() const { - return getOperand(getOpcode() == ISD::VP_LOAD ? 2 : 3); - } - const SDValue &getBasePtr() const { - return getOperand(getOpcode() == ISD::VP_LOAD ? 1 : 2); - } - const SDValue &getMask() const { - return getOperand(getOpcode() == ISD::VP_LOAD ? 3 : 4); - } - const SDValue &getVectorLength() const { - return getOperand(getOpcode() == ISD::VP_LOAD ? 4 : 5); - } - - /// Return the addressing mode for this load or store: - /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. - ISD::MemIndexedMode getAddressingMode() const { - return static_cast(LSBaseSDNodeBits.AddressingMode); - } - - /// Return true if this is a pre/post inc/dec load/store. - bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } - - /// Return true if this is NOT a pre/post inc/dec load/store. - bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_LOAD || N->getOpcode() == ISD::VP_STORE; - } -}; - -/// This class is used to represent a VP_LOAD node -class VPLoadSDNode : public VPLoadStoreSDNode { -public: - friend class SelectionDAG; - - VPLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, bool isExpanding, - EVT MemVT, MachineMemOperand *MMO) - : VPLoadStoreSDNode(ISD::VP_LOAD, Order, dl, VTs, AM, MemVT, MMO) { - LoadSDNodeBits.ExtTy = ETy; - LoadSDNodeBits.IsExpanding = isExpanding; - } - - ISD::LoadExtType getExtensionType() const { - return static_cast(LoadSDNodeBits.ExtTy); - } - - const SDValue &getBasePtr() const { return getOperand(1); } - const SDValue &getOffset() const { return getOperand(2); } - const SDValue &getMask() const { return getOperand(3); } - const SDValue &getVectorLength() const { return getOperand(4); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_LOAD; - } - bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; } -}; - -/// This class is used to represent a VP_STORE node -class VPStoreSDNode : public VPLoadStoreSDNode { -public: - friend class SelectionDAG; - - VPStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, bool isCompressing, - EVT MemVT, MachineMemOperand *MMO) - : VPLoadStoreSDNode(ISD::VP_STORE, Order, dl, VTs, AM, MemVT, MMO) { - StoreSDNodeBits.IsTruncating = isTrunc; - StoreSDNodeBits.IsCompressing = isCompressing; - } - - /// Return true if this is a truncating store. - /// For integers this is the same as doing a TRUNCATE and storing the result. - /// For floats, it is the same as doing an FP_ROUND and storing the result. - bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } - - /// Returns true if the op does a compression to the vector before storing. - /// The node contiguously stores the active elements (integers or floats) - /// in src (those with their respective bit set in writemask k) to unaligned - /// memory at base_addr. - bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; } - - const SDValue &getValue() const { return getOperand(1); } - const SDValue &getBasePtr() const { return getOperand(2); } - const SDValue &getOffset() const { return getOperand(3); } - const SDValue &getMask() const { return getOperand(4); } - const SDValue &getVectorLength() const { return getOperand(5); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_STORE; - } -}; - -/// This base class is used to represent MLOAD and MSTORE nodes -class MaskedLoadStoreSDNode : public MemSDNode { -public: - friend class SelectionDAG; - - MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, - const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, EVT MemVT, - MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - LSBaseSDNodeBits.AddressingMode = AM; - assert(getAddressingMode() == AM && "Value truncated"); - } - - // MaskedLoadSDNode (Chain, ptr, offset, mask, passthru) - // MaskedStoreSDNode (Chain, data, ptr, offset, mask) - // Mask is a vector of i1 elements - const SDValue &getOffset() const { - return getOperand(getOpcode() == ISD::MLOAD ? 2 : 3); - } - const SDValue &getMask() const { - return getOperand(getOpcode() == ISD::MLOAD ? 3 : 4); - } - - /// Return the addressing mode for this load or store: - /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. - ISD::MemIndexedMode getAddressingMode() const { - return static_cast(LSBaseSDNodeBits.AddressingMode); - } - - /// Return true if this is a pre/post inc/dec load/store. - bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } - - /// Return true if this is NOT a pre/post inc/dec load/store. - bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MLOAD || - N->getOpcode() == ISD::MSTORE; - } -}; - -/// This class is used to represent an MLOAD node -class MaskedLoadSDNode : public MaskedLoadStoreSDNode { -public: - friend class SelectionDAG; - - MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, - bool IsExpanding, EVT MemVT, MachineMemOperand *MMO) - : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, AM, MemVT, MMO) { - LoadSDNodeBits.ExtTy = ETy; - LoadSDNodeBits.IsExpanding = IsExpanding; - } - - ISD::LoadExtType getExtensionType() const { - return static_cast(LoadSDNodeBits.ExtTy); - } - - const SDValue &getBasePtr() const { return getOperand(1); } - const SDValue &getOffset() const { return getOperand(2); } - const SDValue &getMask() const { return getOperand(3); } - const SDValue &getPassThru() const { return getOperand(4); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MLOAD; - } - - bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; } -}; - -/// This class is used to represent an MSTORE node -class MaskedStoreSDNode : public MaskedLoadStoreSDNode { -public: - friend class SelectionDAG; - - MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, bool isCompressing, - EVT MemVT, MachineMemOperand *MMO) - : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, AM, MemVT, MMO) { - StoreSDNodeBits.IsTruncating = isTrunc; - StoreSDNodeBits.IsCompressing = isCompressing; - } - - /// Return true if the op does a truncation before store. - /// For integers this is the same as doing a TRUNCATE and storing the result. - /// For floats, it is the same as doing an FP_ROUND and storing the result. - bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } - - /// Returns true if the op does a compression to the vector before storing. - /// The node contiguously stores the active elements (integers or floats) - /// in src (those with their respective bit set in writemask k) to unaligned - /// memory at base_addr. - bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; } - - const SDValue &getValue() const { return getOperand(1); } - const SDValue &getBasePtr() const { return getOperand(2); } - const SDValue &getOffset() const { return getOperand(3); } - const SDValue &getMask() const { return getOperand(4); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MSTORE; - } -}; - -/// This is a base class used to represent -/// VP_GATHER and VP_SCATTER nodes -/// -class VPGatherScatterSDNode : public MemSDNode { -public: - friend class SelectionDAG; - - VPGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, - const DebugLoc &dl, SDVTList VTs, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexType IndexType) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - LSBaseSDNodeBits.AddressingMode = IndexType; - assert(getIndexType() == IndexType && "Value truncated"); - } - - /// How is Index applied to BasePtr when computing addresses. - ISD::MemIndexType getIndexType() const { - return static_cast(LSBaseSDNodeBits.AddressingMode); - } - bool isIndexScaled() const { - return (getIndexType() == ISD::SIGNED_SCALED) || - (getIndexType() == ISD::UNSIGNED_SCALED); - } - bool isIndexSigned() const { - return (getIndexType() == ISD::SIGNED_SCALED) || - (getIndexType() == ISD::SIGNED_UNSCALED); - } - - // In the both nodes address is Op1, mask is Op2: - // VPGatherSDNode (Chain, base, index, scale, mask, vlen) - // VPScatterSDNode (Chain, value, base, index, scale, mask, vlen) - // Mask is a vector of i1 elements - const SDValue &getBasePtr() const { - return getOperand((getOpcode() == ISD::VP_GATHER) ? 1 : 2); - } - const SDValue &getIndex() const { - return getOperand((getOpcode() == ISD::VP_GATHER) ? 2 : 3); - } - const SDValue &getScale() const { - return getOperand((getOpcode() == ISD::VP_GATHER) ? 3 : 4); - } - const SDValue &getMask() const { - return getOperand((getOpcode() == ISD::VP_GATHER) ? 4 : 5); - } - const SDValue &getVectorLength() const { - return getOperand((getOpcode() == ISD::VP_GATHER) ? 5 : 6); - } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_GATHER || - N->getOpcode() == ISD::VP_SCATTER; - } -}; - -/// This class is used to represent an VP_GATHER node -/// -class VPGatherSDNode : public VPGatherScatterSDNode { -public: - friend class SelectionDAG; - - VPGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexType IndexType) - : VPGatherScatterSDNode(ISD::VP_GATHER, Order, dl, VTs, MemVT, MMO, - IndexType) {} - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_GATHER; - } -}; - -/// This class is used to represent an VP_SCATTER node -/// -class VPScatterSDNode : public VPGatherScatterSDNode { -public: - friend class SelectionDAG; - - VPScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexType IndexType) - : VPGatherScatterSDNode(ISD::VP_SCATTER, Order, dl, VTs, MemVT, MMO, - IndexType) {} - - const SDValue &getValue() const { return getOperand(1); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VP_SCATTER; - } -}; - -/// This is a base class used to represent -/// MGATHER and MSCATTER nodes -/// -class MaskedGatherScatterSDNode : public MemSDNode { -public: - friend class SelectionDAG; - - MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, - const DebugLoc &dl, SDVTList VTs, EVT MemVT, - MachineMemOperand *MMO, ISD::MemIndexType IndexType) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - LSBaseSDNodeBits.AddressingMode = IndexType; - assert(getIndexType() == IndexType && "Value truncated"); - } - - /// How is Index applied to BasePtr when computing addresses. - ISD::MemIndexType getIndexType() const { - return static_cast(LSBaseSDNodeBits.AddressingMode); - } - void setIndexType(ISD::MemIndexType IndexType) { - LSBaseSDNodeBits.AddressingMode = IndexType; - } - bool isIndexScaled() const { - return (getIndexType() == ISD::SIGNED_SCALED) || - (getIndexType() == ISD::UNSIGNED_SCALED); - } - bool isIndexSigned() const { - return (getIndexType() == ISD::SIGNED_SCALED) || - (getIndexType() == ISD::SIGNED_UNSCALED); - } - - // In the both nodes address is Op1, mask is Op2: - // MaskedGatherSDNode (Chain, passthru, mask, base, index, scale) - // MaskedScatterSDNode (Chain, value, mask, base, index, scale) - // Mask is a vector of i1 elements - const SDValue &getBasePtr() const { return getOperand(3); } - const SDValue &getIndex() const { return getOperand(4); } - const SDValue &getMask() const { return getOperand(2); } - const SDValue &getScale() const { return getOperand(5); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MGATHER || - N->getOpcode() == ISD::MSCATTER; - } -}; - -/// This class is used to represent an MGATHER node -/// -class MaskedGatherSDNode : public MaskedGatherScatterSDNode { -public: - friend class SelectionDAG; - - MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - EVT MemVT, MachineMemOperand *MMO, - ISD::MemIndexType IndexType, ISD::LoadExtType ETy) - : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO, - IndexType) { - LoadSDNodeBits.ExtTy = ETy; - } - - const SDValue &getPassThru() const { return getOperand(1); } - - ISD::LoadExtType getExtensionType() const { - return ISD::LoadExtType(LoadSDNodeBits.ExtTy); - } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MGATHER; - } -}; - -/// This class is used to represent an MSCATTER node -/// -class MaskedScatterSDNode : public MaskedGatherScatterSDNode { -public: - friend class SelectionDAG; - - MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - EVT MemVT, MachineMemOperand *MMO, - ISD::MemIndexType IndexType, bool IsTrunc) - : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO, - IndexType) { - StoreSDNodeBits.IsTruncating = IsTrunc; - } - - /// Return true if the op does a truncation before store. - /// For integers this is the same as doing a TRUNCATE and storing the result. - /// For floats, it is the same as doing an FP_ROUND and storing the result. - bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } - - const SDValue &getValue() const { return getOperand(1); } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MSCATTER; - } -}; - -/// An SDNode that represents everything that will be needed -/// to construct a MachineInstr. These nodes are created during the -/// instruction selection proper phase. -/// -/// Note that the only supported way to set the `memoperands` is by calling the -/// `SelectionDAG::setNodeMemRefs` function as the memory management happens -/// inside the DAG rather than in the node. -class MachineSDNode : public SDNode { -private: - friend class SelectionDAG; - - MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs) - : SDNode(Opc, Order, DL, VTs) {} - - // We use a pointer union between a single `MachineMemOperand` pointer and - // a pointer to an array of `MachineMemOperand` pointers. This is null when - // the number of these is zero, the single pointer variant used when the - // number is one, and the array is used for larger numbers. - // - // The array is allocated via the `SelectionDAG`'s allocator and so will - // always live until the DAG is cleaned up and doesn't require ownership here. - // - // We can't use something simpler like `TinyPtrVector` here because `SDNode` - // subclasses aren't managed in a conforming C++ manner. See the comments on - // `SelectionDAG::MorphNodeTo` which details what all goes on, but the - // constraint here is that these don't manage memory with their constructor or - // destructor and can be initialized to a good state even if they start off - // uninitialized. - PointerUnion MemRefs = {}; - - // Note that this could be folded into the above `MemRefs` member if doing so - // is advantageous at some point. We don't need to store this in most cases. - // However, at the moment this doesn't appear to make the allocation any - // smaller and makes the code somewhat simpler to read. - int NumMemRefs = 0; - -public: - using mmo_iterator = ArrayRef::const_iterator; - - ArrayRef memoperands() const { - // Special case the common cases. - if (NumMemRefs == 0) - return {}; - if (NumMemRefs == 1) - return makeArrayRef(MemRefs.getAddrOfPtr1(), 1); - - // Otherwise we have an actual array. - return makeArrayRef(MemRefs.get(), NumMemRefs); - } - mmo_iterator memoperands_begin() const { return memoperands().begin(); } - mmo_iterator memoperands_end() const { return memoperands().end(); } - bool memoperands_empty() const { return memoperands().empty(); } - - /// Clear out the memory reference descriptor list. - void clearMemRefs() { - MemRefs = nullptr; - NumMemRefs = 0; - } - - static bool classof(const SDNode *N) { - return N->isMachineOpcode(); - } -}; - -/// An SDNode that records if a register contains a value that is guaranteed to -/// be aligned accordingly. -class AssertAlignSDNode : public SDNode { - Align Alignment; - -public: - AssertAlignSDNode(unsigned Order, const DebugLoc &DL, EVT VT, Align A) - : SDNode(ISD::AssertAlign, Order, DL, getSDVTList(VT)), Alignment(A) {} - - Align getAlign() const { return Alignment; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::AssertAlign; - } -}; - -class SDNodeIterator { - const SDNode *Node; - unsigned Operand; - - SDNodeIterator(const SDNode *N, unsigned Op) : Node(N), Operand(Op) {} - -public: - using iterator_category = std::forward_iterator_tag; - using value_type = SDNode; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - bool operator==(const SDNodeIterator& x) const { - return Operand == x.Operand; - } - bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } - - pointer operator*() const { - return Node->getOperand(Operand).getNode(); - } - pointer operator->() const { return operator*(); } - - SDNodeIterator& operator++() { // Preincrement - ++Operand; - return *this; - } - SDNodeIterator operator++(int) { // Postincrement - SDNodeIterator tmp = *this; ++*this; return tmp; - } - size_t operator-(SDNodeIterator Other) const { - assert(Node == Other.Node && - "Cannot compare iterators of two different nodes!"); - return Operand - Other.Operand; - } - - static SDNodeIterator begin(const SDNode *N) { return SDNodeIterator(N, 0); } - static SDNodeIterator end (const SDNode *N) { - return SDNodeIterator(N, N->getNumOperands()); - } - - unsigned getOperand() const { return Operand; } - const SDNode *getNode() const { return Node; } -}; - -template <> struct GraphTraits { - using NodeRef = SDNode *; - using ChildIteratorType = SDNodeIterator; - - static NodeRef getEntryNode(SDNode *N) { return N; } - - static ChildIteratorType child_begin(NodeRef N) { - return SDNodeIterator::begin(N); - } - - static ChildIteratorType child_end(NodeRef N) { - return SDNodeIterator::end(N); - } -}; - -/// A representation of the largest SDNode, for use in sizeof(). -/// -/// This needs to be a union because the largest node differs on 32 bit systems -/// with 4 and 8 byte pointer alignment, respectively. -using LargestSDNode = AlignedCharArrayUnion; - -/// The SDNode class with the greatest alignment requirement. -using MostAlignedSDNode = GlobalAddressSDNode; - -namespace ISD { - - /// Returns true if the specified node is a non-extending and unindexed load. - inline bool isNormalLoad(const SDNode *N) { - const LoadSDNode *Ld = dyn_cast(N); - return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && - Ld->getAddressingMode() == ISD::UNINDEXED; - } - - /// Returns true if the specified node is a non-extending load. - inline bool isNON_EXTLoad(const SDNode *N) { - return isa(N) && - cast(N)->getExtensionType() == ISD::NON_EXTLOAD; - } - - /// Returns true if the specified node is a EXTLOAD. - inline bool isEXTLoad(const SDNode *N) { - return isa(N) && - cast(N)->getExtensionType() == ISD::EXTLOAD; - } - - /// Returns true if the specified node is a SEXTLOAD. - inline bool isSEXTLoad(const SDNode *N) { - return isa(N) && - cast(N)->getExtensionType() == ISD::SEXTLOAD; - } - - /// Returns true if the specified node is a ZEXTLOAD. - inline bool isZEXTLoad(const SDNode *N) { - return isa(N) && - cast(N)->getExtensionType() == ISD::ZEXTLOAD; - } - - /// Returns true if the specified node is an unindexed load. - inline bool isUNINDEXEDLoad(const SDNode *N) { - return isa(N) && - cast(N)->getAddressingMode() == ISD::UNINDEXED; - } - - /// Returns true if the specified node is a non-truncating - /// and unindexed store. - inline bool isNormalStore(const SDNode *N) { - const StoreSDNode *St = dyn_cast(N); - return St && !St->isTruncatingStore() && - St->getAddressingMode() == ISD::UNINDEXED; - } - - /// Returns true if the specified node is an unindexed store. - inline bool isUNINDEXEDStore(const SDNode *N) { - return isa(N) && - cast(N)->getAddressingMode() == ISD::UNINDEXED; - } - - /// Attempt to match a unary predicate against a scalar/splat constant or - /// every element of a constant BUILD_VECTOR. - /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. - bool matchUnaryPredicate(SDValue Op, - std::function Match, - bool AllowUndefs = false); - - /// Attempt to match a binary predicate against a pair of scalar/splat - /// constants or every element of a pair of constant BUILD_VECTORs. - /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. - /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match. - bool matchBinaryPredicate( - SDValue LHS, SDValue RHS, - std::function Match, - bool AllowUndefs = false, bool AllowTypeMismatch = false); - - /// Returns true if the specified value is the overflow result from one - /// of the overflow intrinsic nodes. - inline bool isOverflowIntrOpRes(SDValue Op) { - unsigned Opc = Op.getOpcode(); - return (Op.getResNo() == 1 && - (Opc == ISD::SADDO || Opc == ISD::UADDO || Opc == ISD::SSUBO || - Opc == ISD::USUBO || Opc == ISD::SMULO || Opc == ISD::UMULO)); - } - -} // end namespace ISD - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SELECTIONDAGNODES_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGTargetInfo.h deleted file mode 100644 index 722c3275fd..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SelectionDAGTargetInfo.h +++ /dev/null @@ -1,166 +0,0 @@ -//==- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info --*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the SelectionDAGTargetInfo class, which targets can -// subclass to parameterize the SelectionDAG lowering and instruction -// selection process. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H -#define LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H - -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/Support/CodeGen.h" -#include - -namespace llvm { - -class SelectionDAG; - -//===----------------------------------------------------------------------===// -/// Targets can subclass this to parameterize the -/// SelectionDAG lowering and instruction selection process. -/// -class SelectionDAGTargetInfo { -public: - explicit SelectionDAGTargetInfo() = default; - SelectionDAGTargetInfo(const SelectionDAGTargetInfo &) = delete; - SelectionDAGTargetInfo &operator=(const SelectionDAGTargetInfo &) = delete; - virtual ~SelectionDAGTargetInfo(); - - /// Emit target-specific code that performs a memcpy. - /// This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple loads/stores and can be - /// more efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - /// - /// If AlwaysInline is true, the size is constant and the target should not - /// emit any calls and is strongly encouraged to attempt to emit inline code - /// even if it is beyond the usual threshold because this intrinsic is being - /// expanded in a place where calls are not feasible (e.g. within the prologue - /// for another call). If the target chooses to decline an AlwaysInline - /// request here, legalize will resort to using simple loads and stores. - virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl, - SDValue Chain, SDValue Op1, - SDValue Op2, SDValue Op3, - Align Alignment, bool isVolatile, - bool AlwaysInline, - MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo) const { - return SDValue(); - } - - /// Emit target-specific code that performs a memmove. - /// This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple loads/stores and can be - /// more efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - virtual SDValue EmitTargetCodeForMemmove( - SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1, - SDValue Op2, SDValue Op3, Align Alignment, bool isVolatile, - MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { - return SDValue(); - } - - /// Emit target-specific code that performs a memset. - /// This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple stores and can be more - /// efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - virtual SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl, - SDValue Chain, SDValue Op1, - SDValue Op2, SDValue Op3, - Align Alignment, bool isVolatile, - MachinePointerInfo DstPtrInfo) const { - return SDValue(); - } - - /// Emit target-specific code that performs a memcmp/bcmp, in cases where that is - /// faster than a libcall. The first returned SDValue is the result of the - /// memcmp and the second is the chain. Both SDValues can be null if a normal - /// libcall should be used. - virtual std::pair - EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, - SDValue Op1, SDValue Op2, SDValue Op3, - MachinePointerInfo Op1PtrInfo, - MachinePointerInfo Op2PtrInfo) const { - return std::make_pair(SDValue(), SDValue()); - } - - /// Emit target-specific code that performs a memchr, in cases where that is - /// faster than a libcall. The first returned SDValue is the result of the - /// memchr and the second is the chain. Both SDValues can be null if a normal - /// libcall should be used. - virtual std::pair - EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, - SDValue Src, SDValue Char, SDValue Length, - MachinePointerInfo SrcPtrInfo) const { - return std::make_pair(SDValue(), SDValue()); - } - - /// Emit target-specific code that performs a strcpy or stpcpy, in cases - /// where that is faster than a libcall. - /// The first returned SDValue is the result of the copy (the start - /// of the destination string for strcpy, a pointer to the null terminator - /// for stpcpy) and the second is the chain. Both SDValues can be null - /// if a normal libcall should be used. - virtual std::pair - EmitTargetCodeForStrcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, - SDValue Dest, SDValue Src, - MachinePointerInfo DestPtrInfo, - MachinePointerInfo SrcPtrInfo, bool isStpcpy) const { - return std::make_pair(SDValue(), SDValue()); - } - - /// Emit target-specific code that performs a strcmp, in cases where that is - /// faster than a libcall. - /// The first returned SDValue is the result of the strcmp and the second is - /// the chain. Both SDValues can be null if a normal libcall should be used. - virtual std::pair - EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, - SDValue Op1, SDValue Op2, - MachinePointerInfo Op1PtrInfo, - MachinePointerInfo Op2PtrInfo) const { - return std::make_pair(SDValue(), SDValue()); - } - - virtual std::pair - EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, - SDValue Src, MachinePointerInfo SrcPtrInfo) const { - return std::make_pair(SDValue(), SDValue()); - } - - virtual std::pair - EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, - SDValue Src, SDValue MaxLength, - MachinePointerInfo SrcPtrInfo) const { - return std::make_pair(SDValue(), SDValue()); - } - - virtual SDValue EmitTargetCodeForSetTag(SelectionDAG &DAG, const SDLoc &dl, - SDValue Chain, SDValue Addr, - SDValue Size, - MachinePointerInfo DstPtrInfo, - bool ZeroData) const { - return SDValue(); - } - - // Return true if the DAG Combiner should disable generic combines. - virtual bool disableGenericCombines(CodeGenOpt::Level OptLevel) const { - return false; - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SlotIndexes.h b/suite/synctools/tablegen/include/llvm/CodeGen/SlotIndexes.h deleted file mode 100644 index e8d618a24f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SlotIndexes.h +++ /dev/null @@ -1,647 +0,0 @@ -//===- llvm/CodeGen/SlotIndexes.h - Slot indexes representation -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements SlotIndex and related classes. The purpose of SlotIndex -// is to describe a position at which a register can become live, or cease to -// be live. -// -// SlotIndex is mostly a proxy for entries of the SlotIndexList, a class which -// is held is LiveIntervals and provides the real numbering. This allows -// LiveIntervals to perform largely transparent renumbering. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SLOTINDEXES_H -#define LLVM_CODEGEN_SLOTINDEXES_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ilist.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/Pass.h" -#include "llvm/Support/Allocator.h" -#include -#include -#include -#include - -namespace llvm { - -class raw_ostream; - - /// This class represents an entry in the slot index list held in the - /// SlotIndexes pass. It should not be used directly. See the - /// SlotIndex & SlotIndexes classes for the public interface to this - /// information. - class IndexListEntry : public ilist_node { - MachineInstr *mi; - unsigned index; - - public: - IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {} - - MachineInstr* getInstr() const { return mi; } - void setInstr(MachineInstr *mi) { - this->mi = mi; - } - - unsigned getIndex() const { return index; } - void setIndex(unsigned index) { - this->index = index; - } - -#ifdef EXPENSIVE_CHECKS - // When EXPENSIVE_CHECKS is defined, "erased" index list entries will - // actually be moved to a "graveyard" list, and have their pointers - // poisoned, so that dangling SlotIndex access can be reliably detected. - void setPoison() { - intptr_t tmp = reinterpret_cast(mi); - assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); - tmp |= 0x1; - mi = reinterpret_cast(tmp); - } - - bool isPoisoned() const { return (reinterpret_cast(mi) & 0x1) == 0x1; } -#endif // EXPENSIVE_CHECKS - }; - - template <> - struct ilist_alloc_traits - : public ilist_noalloc_traits {}; - - /// SlotIndex - An opaque wrapper around machine indexes. - class SlotIndex { - friend class SlotIndexes; - - enum Slot { - /// Basic block boundary. Used for live ranges entering and leaving a - /// block without being live in the layout neighbor. Also used as the - /// def slot of PHI-defs. - Slot_Block, - - /// Early-clobber register use/def slot. A live range defined at - /// Slot_EarlyClobber interferes with normal live ranges killed at - /// Slot_Register. Also used as the kill slot for live ranges tied to an - /// early-clobber def. - Slot_EarlyClobber, - - /// Normal register use/def slot. Normal instructions kill and define - /// register live ranges at this slot. - Slot_Register, - - /// Dead def kill point. Kill slot for a live range that is defined by - /// the same instruction (Slot_Register or Slot_EarlyClobber), but isn't - /// used anywhere. - Slot_Dead, - - Slot_Count - }; - - PointerIntPair lie; - - SlotIndex(IndexListEntry *entry, unsigned slot) - : lie(entry, slot) {} - - IndexListEntry* listEntry() const { - assert(isValid() && "Attempt to compare reserved index."); -#ifdef EXPENSIVE_CHECKS - assert(!lie.getPointer()->isPoisoned() && - "Attempt to access deleted list-entry."); -#endif // EXPENSIVE_CHECKS - return lie.getPointer(); - } - - unsigned getIndex() const { - return listEntry()->getIndex() | getSlot(); - } - - /// Returns the slot for this SlotIndex. - Slot getSlot() const { - return static_cast(lie.getInt()); - } - - public: - enum { - /// The default distance between instructions as returned by distance(). - /// This may vary as instructions are inserted and removed. - InstrDist = 4 * Slot_Count - }; - - /// Construct an invalid index. - SlotIndex() = default; - - // Construct a new slot index from the given one, and set the slot. - SlotIndex(const SlotIndex &li, Slot s) : lie(li.listEntry(), unsigned(s)) { - assert(lie.getPointer() != nullptr && - "Attempt to construct index with 0 pointer."); - } - - /// Returns true if this is a valid index. Invalid indices do - /// not point into an index table, and cannot be compared. - bool isValid() const { - return lie.getPointer(); - } - - /// Return true for a valid index. - explicit operator bool() const { return isValid(); } - - /// Print this index to the given raw_ostream. - void print(raw_ostream &os) const; - - /// Dump this index to stderr. - void dump() const; - - /// Compare two SlotIndex objects for equality. - bool operator==(SlotIndex other) const { - return lie == other.lie; - } - /// Compare two SlotIndex objects for inequality. - bool operator!=(SlotIndex other) const { - return lie != other.lie; - } - - /// Compare two SlotIndex objects. Return true if the first index - /// is strictly lower than the second. - bool operator<(SlotIndex other) const { - return getIndex() < other.getIndex(); - } - /// Compare two SlotIndex objects. Return true if the first index - /// is lower than, or equal to, the second. - bool operator<=(SlotIndex other) const { - return getIndex() <= other.getIndex(); - } - - /// Compare two SlotIndex objects. Return true if the first index - /// is greater than the second. - bool operator>(SlotIndex other) const { - return getIndex() > other.getIndex(); - } - - /// Compare two SlotIndex objects. Return true if the first index - /// is greater than, or equal to, the second. - bool operator>=(SlotIndex other) const { - return getIndex() >= other.getIndex(); - } - - /// isSameInstr - Return true if A and B refer to the same instruction. - static bool isSameInstr(SlotIndex A, SlotIndex B) { - return A.lie.getPointer() == B.lie.getPointer(); - } - - /// isEarlierInstr - Return true if A refers to an instruction earlier than - /// B. This is equivalent to A < B && !isSameInstr(A, B). - static bool isEarlierInstr(SlotIndex A, SlotIndex B) { - return A.listEntry()->getIndex() < B.listEntry()->getIndex(); - } - - /// Return true if A refers to the same instruction as B or an earlier one. - /// This is equivalent to !isEarlierInstr(B, A). - static bool isEarlierEqualInstr(SlotIndex A, SlotIndex B) { - return !isEarlierInstr(B, A); - } - - /// Return the distance from this index to the given one. - int distance(SlotIndex other) const { - return other.getIndex() - getIndex(); - } - - /// Return the scaled distance from this index to the given one, where all - /// slots on the same instruction have zero distance. - int getInstrDistance(SlotIndex other) const { - return (other.listEntry()->getIndex() - listEntry()->getIndex()) - / Slot_Count; - } - - /// isBlock - Returns true if this is a block boundary slot. - bool isBlock() const { return getSlot() == Slot_Block; } - - /// isEarlyClobber - Returns true if this is an early-clobber slot. - bool isEarlyClobber() const { return getSlot() == Slot_EarlyClobber; } - - /// isRegister - Returns true if this is a normal register use/def slot. - /// Note that early-clobber slots may also be used for uses and defs. - bool isRegister() const { return getSlot() == Slot_Register; } - - /// isDead - Returns true if this is a dead def kill slot. - bool isDead() const { return getSlot() == Slot_Dead; } - - /// Returns the base index for associated with this index. The base index - /// is the one associated with the Slot_Block slot for the instruction - /// pointed to by this index. - SlotIndex getBaseIndex() const { - return SlotIndex(listEntry(), Slot_Block); - } - - /// Returns the boundary index for associated with this index. The boundary - /// index is the one associated with the Slot_Block slot for the instruction - /// pointed to by this index. - SlotIndex getBoundaryIndex() const { - return SlotIndex(listEntry(), Slot_Dead); - } - - /// Returns the register use/def slot in the current instruction for a - /// normal or early-clobber def. - SlotIndex getRegSlot(bool EC = false) const { - return SlotIndex(listEntry(), EC ? Slot_EarlyClobber : Slot_Register); - } - - /// Returns the dead def kill slot for the current instruction. - SlotIndex getDeadSlot() const { - return SlotIndex(listEntry(), Slot_Dead); - } - - /// Returns the next slot in the index list. This could be either the - /// next slot for the instruction pointed to by this index or, if this - /// index is a STORE, the first slot for the next instruction. - /// WARNING: This method is considerably more expensive than the methods - /// that return specific slots (getUseIndex(), etc). If you can - please - /// use one of those methods. - SlotIndex getNextSlot() const { - Slot s = getSlot(); - if (s == Slot_Dead) { - return SlotIndex(&*++listEntry()->getIterator(), Slot_Block); - } - return SlotIndex(listEntry(), s + 1); - } - - /// Returns the next index. This is the index corresponding to the this - /// index's slot, but for the next instruction. - SlotIndex getNextIndex() const { - return SlotIndex(&*++listEntry()->getIterator(), getSlot()); - } - - /// Returns the previous slot in the index list. This could be either the - /// previous slot for the instruction pointed to by this index or, if this - /// index is a Slot_Block, the last slot for the previous instruction. - /// WARNING: This method is considerably more expensive than the methods - /// that return specific slots (getUseIndex(), etc). If you can - please - /// use one of those methods. - SlotIndex getPrevSlot() const { - Slot s = getSlot(); - if (s == Slot_Block) { - return SlotIndex(&*--listEntry()->getIterator(), Slot_Dead); - } - return SlotIndex(listEntry(), s - 1); - } - - /// Returns the previous index. This is the index corresponding to this - /// index's slot, but for the previous instruction. - SlotIndex getPrevIndex() const { - return SlotIndex(&*--listEntry()->getIterator(), getSlot()); - } - }; - - inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { - li.print(os); - return os; - } - - using IdxMBBPair = std::pair; - - /// SlotIndexes pass. - /// - /// This pass assigns indexes to each instruction. - class SlotIndexes : public MachineFunctionPass { - private: - // IndexListEntry allocator. - BumpPtrAllocator ileAllocator; - - using IndexList = ilist; - IndexList indexList; - - MachineFunction *mf = nullptr; - - using Mi2IndexMap = DenseMap; - Mi2IndexMap mi2iMap; - - /// MBBRanges - Map MBB number to (start, stop) indexes. - SmallVector, 8> MBBRanges; - - /// Idx2MBBMap - Sorted list of pairs of index of first instruction - /// and MBB id. - SmallVector idx2MBBMap; - - IndexListEntry* createEntry(MachineInstr *mi, unsigned index) { - IndexListEntry *entry = - static_cast(ileAllocator.Allocate( - sizeof(IndexListEntry), alignof(IndexListEntry))); - - new (entry) IndexListEntry(mi, index); - - return entry; - } - - /// Renumber locally after inserting curItr. - void renumberIndexes(IndexList::iterator curItr); - - public: - static char ID; - - SlotIndexes(); - - ~SlotIndexes() override; - - void getAnalysisUsage(AnalysisUsage &au) const override; - void releaseMemory() override; - - bool runOnMachineFunction(MachineFunction &fn) override; - - /// Dump the indexes. - void dump() const; - - /// Repair indexes after adding and removing instructions. - void repairIndexesInRange(MachineBasicBlock *MBB, - MachineBasicBlock::iterator Begin, - MachineBasicBlock::iterator End); - - /// Returns the zero index for this analysis. - SlotIndex getZeroIndex() { - assert(indexList.front().getIndex() == 0 && "First index is not 0?"); - return SlotIndex(&indexList.front(), 0); - } - - /// Returns the base index of the last slot in this analysis. - SlotIndex getLastIndex() { - return SlotIndex(&indexList.back(), 0); - } - - /// Returns true if the given machine instr is mapped to an index, - /// otherwise returns false. - bool hasIndex(const MachineInstr &instr) const { - return mi2iMap.count(&instr); - } - - /// Returns the base index for the given instruction. - SlotIndex getInstructionIndex(const MachineInstr &MI, - bool IgnoreBundle = false) const { - // Instructions inside a bundle have the same number as the bundle itself. - auto BundleStart = getBundleStart(MI.getIterator()); - auto BundleEnd = getBundleEnd(MI.getIterator()); - // Use the first non-debug instruction in the bundle to get SlotIndex. - const MachineInstr &BundleNonDebug = - IgnoreBundle ? MI - : *skipDebugInstructionsForward(BundleStart, BundleEnd); - assert(!BundleNonDebug.isDebugInstr() && - "Could not use a debug instruction to query mi2iMap."); - Mi2IndexMap::const_iterator itr = mi2iMap.find(&BundleNonDebug); - assert(itr != mi2iMap.end() && "Instruction not found in maps."); - return itr->second; - } - - /// Returns the instruction for the given index, or null if the given - /// index has no instruction associated with it. - MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return index.isValid() ? index.listEntry()->getInstr() : nullptr; - } - - /// Returns the next non-null index, if one exists. - /// Otherwise returns getLastIndex(). - SlotIndex getNextNonNullIndex(SlotIndex Index) { - IndexList::iterator I = Index.listEntry()->getIterator(); - IndexList::iterator E = indexList.end(); - while (++I != E) - if (I->getInstr()) - return SlotIndex(&*I, Index.getSlot()); - // We reached the end of the function. - return getLastIndex(); - } - - /// getIndexBefore - Returns the index of the last indexed instruction - /// before MI, or the start index of its basic block. - /// MI is not required to have an index. - SlotIndex getIndexBefore(const MachineInstr &MI) const { - const MachineBasicBlock *MBB = MI.getParent(); - assert(MBB && "MI must be inserted in a basic block"); - MachineBasicBlock::const_iterator I = MI, B = MBB->begin(); - while (true) { - if (I == B) - return getMBBStartIdx(MBB); - --I; - Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I); - if (MapItr != mi2iMap.end()) - return MapItr->second; - } - } - - /// getIndexAfter - Returns the index of the first indexed instruction - /// after MI, or the end index of its basic block. - /// MI is not required to have an index. - SlotIndex getIndexAfter(const MachineInstr &MI) const { - const MachineBasicBlock *MBB = MI.getParent(); - assert(MBB && "MI must be inserted in a basic block"); - MachineBasicBlock::const_iterator I = MI, E = MBB->end(); - while (true) { - ++I; - if (I == E) - return getMBBEndIdx(MBB); - Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I); - if (MapItr != mi2iMap.end()) - return MapItr->second; - } - } - - /// Return the (start,end) range of the given basic block number. - const std::pair & - getMBBRange(unsigned Num) const { - return MBBRanges[Num]; - } - - /// Return the (start,end) range of the given basic block. - const std::pair & - getMBBRange(const MachineBasicBlock *MBB) const { - return getMBBRange(MBB->getNumber()); - } - - /// Returns the first index in the given basic block number. - SlotIndex getMBBStartIdx(unsigned Num) const { - return getMBBRange(Num).first; - } - - /// Returns the first index in the given basic block. - SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { - return getMBBRange(mbb).first; - } - - /// Returns the last index in the given basic block number. - SlotIndex getMBBEndIdx(unsigned Num) const { - return getMBBRange(Num).second; - } - - /// Returns the last index in the given basic block. - SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { - return getMBBRange(mbb).second; - } - - /// Iterator over the idx2MBBMap (sorted pairs of slot index of basic block - /// begin and basic block) - using MBBIndexIterator = SmallVectorImpl::const_iterator; - - /// Move iterator to the next IdxMBBPair where the SlotIndex is greater or - /// equal to \p To. - MBBIndexIterator advanceMBBIndex(MBBIndexIterator I, SlotIndex To) const { - return std::partition_point( - I, idx2MBBMap.end(), - [=](const IdxMBBPair &IM) { return IM.first < To; }); - } - - /// Get an iterator pointing to the IdxMBBPair with the biggest SlotIndex - /// that is greater or equal to \p Idx. - MBBIndexIterator findMBBIndex(SlotIndex Idx) const { - return advanceMBBIndex(idx2MBBMap.begin(), Idx); - } - - /// Returns an iterator for the begin of the idx2MBBMap. - MBBIndexIterator MBBIndexBegin() const { - return idx2MBBMap.begin(); - } - - /// Return an iterator for the end of the idx2MBBMap. - MBBIndexIterator MBBIndexEnd() const { - return idx2MBBMap.end(); - } - - /// Returns the basic block which the given index falls in. - MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { - if (MachineInstr *MI = getInstructionFromIndex(index)) - return MI->getParent(); - - MBBIndexIterator I = findMBBIndex(index); - // Take the pair containing the index - MBBIndexIterator J = - ((I != MBBIndexEnd() && I->first > index) || - (I == MBBIndexEnd() && !idx2MBBMap.empty())) ? std::prev(I) : I; - - assert(J != MBBIndexEnd() && J->first <= index && - index < getMBBEndIdx(J->second) && - "index does not correspond to an MBB"); - return J->second; - } - - /// Insert the given machine instruction into the mapping. Returns the - /// assigned index. - /// If Late is set and there are null indexes between mi's neighboring - /// instructions, create the new index after the null indexes instead of - /// before them. - SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late = false) { - assert(!MI.isInsideBundle() && - "Instructions inside bundles should use bundle start's slot."); - assert(mi2iMap.find(&MI) == mi2iMap.end() && "Instr already indexed."); - // Numbering debug instructions could cause code generation to be - // affected by debug information. - assert(!MI.isDebugInstr() && "Cannot number debug instructions."); - - assert(MI.getParent() != nullptr && "Instr must be added to function."); - - // Get the entries where MI should be inserted. - IndexList::iterator prevItr, nextItr; - if (Late) { - // Insert MI's index immediately before the following instruction. - nextItr = getIndexAfter(MI).listEntry()->getIterator(); - prevItr = std::prev(nextItr); - } else { - // Insert MI's index immediately after the preceding instruction. - prevItr = getIndexBefore(MI).listEntry()->getIterator(); - nextItr = std::next(prevItr); - } - - // Get a number for the new instr, or 0 if there's no room currently. - // In the latter case we'll force a renumber later. - unsigned dist = ((nextItr->getIndex() - prevItr->getIndex())/2) & ~3u; - unsigned newNumber = prevItr->getIndex() + dist; - - // Insert a new list entry for MI. - IndexList::iterator newItr = - indexList.insert(nextItr, createEntry(&MI, newNumber)); - - // Renumber locally if we need to. - if (dist == 0) - renumberIndexes(newItr); - - SlotIndex newIndex(&*newItr, SlotIndex::Slot_Block); - mi2iMap.insert(std::make_pair(&MI, newIndex)); - return newIndex; - } - - /// Removes machine instruction (bundle) \p MI from the mapping. - /// This should be called before MachineInstr::eraseFromParent() is used to - /// remove a whole bundle or an unbundled instruction. - /// If \p AllowBundled is set then this can be used on a bundled - /// instruction; however, this exists to support handleMoveIntoBundle, - /// and in general removeSingleMachineInstrFromMaps should be used instead. - void removeMachineInstrFromMaps(MachineInstr &MI, - bool AllowBundled = false); - - /// Removes a single machine instruction \p MI from the mapping. - /// This should be called before MachineInstr::eraseFromBundle() is used to - /// remove a single instruction (out of a bundle). - void removeSingleMachineInstrFromMaps(MachineInstr &MI); - - /// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in - /// maps used by register allocator. \returns the index where the new - /// instruction was inserted. - SlotIndex replaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) { - Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI); - if (mi2iItr == mi2iMap.end()) - return SlotIndex(); - SlotIndex replaceBaseIndex = mi2iItr->second; - IndexListEntry *miEntry(replaceBaseIndex.listEntry()); - assert(miEntry->getInstr() == &MI && - "Mismatched instruction in index tables."); - miEntry->setInstr(&NewMI); - mi2iMap.erase(mi2iItr); - mi2iMap.insert(std::make_pair(&NewMI, replaceBaseIndex)); - return replaceBaseIndex; - } - - /// Add the given MachineBasicBlock into the maps. - /// If it contains any instructions then they must already be in the maps. - /// This is used after a block has been split by moving some suffix of its - /// instructions into a newly created block. - void insertMBBInMaps(MachineBasicBlock *mbb) { - assert(mbb != &mbb->getParent()->front() && - "Can't insert a new block at the beginning of a function."); - auto prevMBB = std::prev(MachineFunction::iterator(mbb)); - - // Create a new entry to be used for the start of mbb and the end of - // prevMBB. - IndexListEntry *startEntry = createEntry(nullptr, 0); - IndexListEntry *endEntry = getMBBEndIdx(&*prevMBB).listEntry(); - IndexListEntry *insEntry = - mbb->empty() ? endEntry - : getInstructionIndex(mbb->front()).listEntry(); - IndexList::iterator newItr = - indexList.insert(insEntry->getIterator(), startEntry); - - SlotIndex startIdx(startEntry, SlotIndex::Slot_Block); - SlotIndex endIdx(endEntry, SlotIndex::Slot_Block); - - MBBRanges[prevMBB->getNumber()].second = startIdx; - - assert(unsigned(mbb->getNumber()) == MBBRanges.size() && - "Blocks must be added in order"); - MBBRanges.push_back(std::make_pair(startIdx, endIdx)); - idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); - - renumberIndexes(newItr); - llvm::sort(idx2MBBMap, less_first()); - } - }; - - // Specialize IntervalMapInfo for half-open slot index intervals. - template <> - struct IntervalMapInfo : IntervalMapHalfOpenInfo { - }; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SLOTINDEXES_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/Spiller.h b/suite/synctools/tablegen/include/llvm/CodeGen/Spiller.h deleted file mode 100644 index b2f5485eba..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/Spiller.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- llvm/CodeGen/Spiller.h - Spiller -------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SPILLER_H -#define LLVM_CODEGEN_SPILLER_H - -namespace llvm { - -class LiveRangeEdit; -class MachineFunction; -class MachineFunctionPass; -class VirtRegMap; -class VirtRegAuxInfo; - -/// Spiller interface. -/// -/// Implementations are utility classes which insert spill or remat code on -/// demand. -class Spiller { - virtual void anchor(); - -public: - virtual ~Spiller() = 0; - - /// spill - Spill the LRE.getParent() live interval. - virtual void spill(LiveRangeEdit &LRE) = 0; - - virtual void postOptimization() {} -}; - -/// Create and return a spiller that will insert spill code directly instead -/// of deferring though VirtRegMap. -Spiller *createInlineSpiller(MachineFunctionPass &Pass, MachineFunction &MF, - VirtRegMap &VRM, VirtRegAuxInfo &VRAI); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_SPILLER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/StableHashing.h b/suite/synctools/tablegen/include/llvm/CodeGen/StableHashing.h deleted file mode 100644 index caf27e152e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/StableHashing.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- llvm/CodeGen/StableHashing.h - Utilities for stable hashing * C++ *-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides types and functions for computing and combining stable -// hashes. Stable hashes can be useful for hashing across different modules, -// processes, or compiler runs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_STABLEHASHING_H -#define LLVM_CODEGEN_STABLEHASHING_H - -#include "llvm/ADT/StringRef.h" - -namespace llvm { - -/// An opaque object representing a stable hash code. It can be serialized, -/// deserialized, and is stable across processes and executions. -using stable_hash = uint64_t; - -// Implementation details -namespace hashing { -namespace detail { - -// Stable hashes are based on the 64-bit FNV-1 hash: -// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function - -const uint64_t FNV_PRIME_64 = 1099511628211u; -const uint64_t FNV_OFFSET_64 = 14695981039346656037u; - -inline void stable_hash_append(stable_hash &Hash, const char Value) { - Hash = Hash ^ (Value & 0xFF); - Hash = Hash * FNV_PRIME_64; -} - -inline void stable_hash_append(stable_hash &Hash, stable_hash Value) { - for (unsigned I = 0; I < 8; ++I) { - stable_hash_append(Hash, static_cast(Value)); - Value >>= 8; - } -} - -} // namespace detail -} // namespace hashing - -inline stable_hash stable_hash_combine(stable_hash A, stable_hash B) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - hashing::detail::stable_hash_append(Hash, A); - hashing::detail::stable_hash_append(Hash, B); - return Hash; -} - -inline stable_hash stable_hash_combine(stable_hash A, stable_hash B, - stable_hash C) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - hashing::detail::stable_hash_append(Hash, A); - hashing::detail::stable_hash_append(Hash, B); - hashing::detail::stable_hash_append(Hash, C); - return Hash; -} - -inline stable_hash stable_hash_combine(stable_hash A, stable_hash B, - stable_hash C, stable_hash D) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - hashing::detail::stable_hash_append(Hash, A); - hashing::detail::stable_hash_append(Hash, B); - hashing::detail::stable_hash_append(Hash, C); - hashing::detail::stable_hash_append(Hash, D); - return Hash; -} - -/// Compute a stable_hash for a sequence of values. -/// -/// This hashes a sequence of values. It produces the same stable_hash as -/// 'stable_hash_combine(a, b, c, ...)', but can run over arbitrary sized -/// sequences and is significantly faster given pointers and types which -/// can be hashed as a sequence of bytes. -template -stable_hash stable_hash_combine_range(InputIteratorT First, - InputIteratorT Last) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - for (auto I = First; I != Last; ++I) - hashing::detail::stable_hash_append(Hash, *I); - return Hash; -} - -inline stable_hash stable_hash_combine_array(const stable_hash *P, size_t C) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - for (size_t I = 0; I < C; ++I) - hashing::detail::stable_hash_append(Hash, P[I]); - return Hash; -} - -inline stable_hash stable_hash_combine_string(const StringRef &S) { - return stable_hash_combine_range(S.begin(), S.end()); -} - -inline stable_hash stable_hash_combine_string(const char *C) { - stable_hash Hash = hashing::detail::FNV_OFFSET_64; - while (*C) - hashing::detail::stable_hash_append(Hash, *(C++)); - return Hash; -} - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/StackMaps.h b/suite/synctools/tablegen/include/llvm/CodeGen/StackMaps.h deleted file mode 100644 index c2f374d689..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/StackMaps.h +++ /dev/null @@ -1,412 +0,0 @@ -//===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_STACKMAPS_H -#define LLVM_CODEGEN_STACKMAPS_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Debug.h" -#include -#include -#include -#include - -namespace llvm { - -class AsmPrinter; -class MCExpr; -class MCStreamer; -class raw_ostream; -class TargetRegisterInfo; - -/// MI-level stackmap operands. -/// -/// MI stackmap operations take the form: -/// , , live args... -class StackMapOpers { -public: - /// Enumerate the meta operands. - enum { IDPos, NBytesPos }; - -private: - const MachineInstr* MI; - -public: - explicit StackMapOpers(const MachineInstr *MI); - - /// Return the ID for the given stackmap - uint64_t getID() const { return MI->getOperand(IDPos).getImm(); } - - /// Return the number of patchable bytes the given stackmap should emit. - uint32_t getNumPatchBytes() const { - return MI->getOperand(NBytesPos).getImm(); - } - - /// Get the operand index of the variable list of non-argument operands. - /// These hold the "live state". - unsigned getVarIdx() const { - // Skip ID, nShadowBytes. - return 2; - } -}; - -/// MI-level patchpoint operands. -/// -/// MI patchpoint operations take the form: -/// [], , , , , , ... -/// -/// IR patchpoint intrinsics do not have the operand because calling -/// convention is part of the subclass data. -/// -/// SD patchpoint nodes do not have a def operand because it is part of the -/// SDValue. -/// -/// Patchpoints following the anyregcc convention are handled specially. For -/// these, the stack map also records the location of the return value and -/// arguments. -class PatchPointOpers { -public: - /// Enumerate the meta operands. - enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; - -private: - const MachineInstr *MI; - bool HasDef; - - unsigned getMetaIdx(unsigned Pos = 0) const { - assert(Pos < MetaEnd && "Meta operand index out of range."); - return (HasDef ? 1 : 0) + Pos; - } - - const MachineOperand &getMetaOper(unsigned Pos) const { - return MI->getOperand(getMetaIdx(Pos)); - } - -public: - explicit PatchPointOpers(const MachineInstr *MI); - - bool isAnyReg() const { return (getCallingConv() == CallingConv::AnyReg); } - bool hasDef() const { return HasDef; } - - /// Return the ID for the given patchpoint. - uint64_t getID() const { return getMetaOper(IDPos).getImm(); } - - /// Return the number of patchable bytes the given patchpoint should emit. - uint32_t getNumPatchBytes() const { - return getMetaOper(NBytesPos).getImm(); - } - - /// Returns the target of the underlying call. - const MachineOperand &getCallTarget() const { - return getMetaOper(TargetPos); - } - - /// Returns the calling convention - CallingConv::ID getCallingConv() const { - return getMetaOper(CCPos).getImm(); - } - - unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } - - /// Return the number of call arguments - uint32_t getNumCallArgs() const { - return MI->getOperand(getMetaIdx(NArgPos)).getImm(); - } - - /// Get the operand index of the variable list of non-argument operands. - /// These hold the "live state". - unsigned getVarIdx() const { - return getMetaIdx() + MetaEnd + getNumCallArgs(); - } - - /// Get the index at which stack map locations will be recorded. - /// Arguments are not recorded unless the anyregcc convention is used. - unsigned getStackMapStartIdx() const { - if (isAnyReg()) - return getArgIdx(); - return getVarIdx(); - } - - /// Get the next scratch register operand index. - unsigned getNextScratchIdx(unsigned StartIdx = 0) const; -}; - -/// MI-level Statepoint operands -/// -/// Statepoint operands take the form: -/// , , , , -/// [call arguments...], -/// , , -/// , , -/// , , [deopt args...], -/// , , [gc pointer args...], -/// , , [gc allocas args...], -/// , , [base/derived pairs] -/// base/derived pairs in gc map are logical indices into -/// section. -/// All gc pointers assigned to VRegs produce new value (in form of MI Def -/// operand) and are tied to it. -class StatepointOpers { - // TODO:: we should change the STATEPOINT representation so that CC and - // Flags should be part of meta operands, with args and deopt operands, and - // gc operands all prefixed by their length and a type code. This would be - // much more consistent. - - // These values are absolute offsets into the operands of the statepoint - // instruction. - enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd }; - - // These values are relative offsets from the start of the statepoint meta - // arguments (i.e. the end of the call arguments). - enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 }; - -public: - explicit StatepointOpers(const MachineInstr *MI) : MI(MI) { - NumDefs = MI->getNumDefs(); - } - - /// Get index of statepoint ID operand. - unsigned getIDPos() const { return NumDefs + IDPos; } - - /// Get index of Num Patch Bytes operand. - unsigned getNBytesPos() const { return NumDefs + NBytesPos; } - - /// Get index of Num Call Arguments operand. - unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; } - - /// Get starting index of non call related arguments - /// (calling convention, statepoint flags, vm state and gc state). - unsigned getVarIdx() const { - return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs; - } - - /// Get index of Calling Convention operand. - unsigned getCCIdx() const { return getVarIdx() + CCOffset; } - - /// Get index of Flags operand. - unsigned getFlagsIdx() const { return getVarIdx() + FlagsOffset; } - - /// Get index of Number Deopt Arguments operand. - unsigned getNumDeoptArgsIdx() const { - return getVarIdx() + NumDeoptOperandsOffset; - } - - /// Return the ID for the given statepoint. - uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); } - - /// Return the number of patchable bytes the given statepoint should emit. - uint32_t getNumPatchBytes() const { - return MI->getOperand(NumDefs + NBytesPos).getImm(); - } - - /// Return the target of the underlying call. - const MachineOperand &getCallTarget() const { - return MI->getOperand(NumDefs + CallTargetPos); - } - - /// Return the calling convention. - CallingConv::ID getCallingConv() const { - return MI->getOperand(getCCIdx()).getImm(); - } - - /// Return the statepoint flags. - uint64_t getFlags() const { return MI->getOperand(getFlagsIdx()).getImm(); } - - uint64_t getNumDeoptArgs() const { - return MI->getOperand(getNumDeoptArgsIdx()).getImm(); - } - - /// Get index of number of gc map entries. - unsigned getNumGcMapEntriesIdx(); - - /// Get index of number of gc allocas. - unsigned getNumAllocaIdx(); - - /// Get index of number of GC pointers. - unsigned getNumGCPtrIdx(); - - /// Get index of first GC pointer operand of -1 if there are none. - int getFirstGCPtrIdx(); - - /// Get vector of base/derived pairs from statepoint. - /// Elements are indices into GC Pointer operand list (logical). - /// Returns number of elements in GCMap. - unsigned - getGCPointerMap(SmallVectorImpl> &GCMap); - -private: - const MachineInstr *MI; - unsigned NumDefs; -}; - -class StackMaps { -public: - struct Location { - enum LocationType { - Unprocessed, - Register, - Direct, - Indirect, - Constant, - ConstantIndex - }; - LocationType Type = Unprocessed; - unsigned Size = 0; - unsigned Reg = 0; - int64_t Offset = 0; - - Location() = default; - Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset) - : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {} - }; - - struct LiveOutReg { - unsigned short Reg = 0; - unsigned short DwarfRegNum = 0; - unsigned short Size = 0; - - LiveOutReg() = default; - LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum, - unsigned short Size) - : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {} - }; - - // OpTypes are used to encode information about the following logical - // operand (which may consist of several MachineOperands) for the - // OpParser. - using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp }; - - StackMaps(AsmPrinter &AP); - - /// Get index of next meta operand. - /// Similar to parseOperand, but does not actually parses operand meaning. - static unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx); - - void reset() { - CSInfos.clear(); - ConstPool.clear(); - FnInfos.clear(); - } - - using LocationVec = SmallVector; - using LiveOutVec = SmallVector; - using ConstantPool = MapVector; - - struct FunctionInfo { - uint64_t StackSize = 0; - uint64_t RecordCount = 1; - - FunctionInfo() = default; - explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {} - }; - - struct CallsiteInfo { - const MCExpr *CSOffsetExpr = nullptr; - uint64_t ID = 0; - LocationVec Locations; - LiveOutVec LiveOuts; - - CallsiteInfo() = default; - CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, - LocationVec &&Locations, LiveOutVec &&LiveOuts) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), - LiveOuts(std::move(LiveOuts)) {} - }; - - using FnInfoMap = MapVector; - using CallsiteInfoList = std::vector; - - /// Generate a stackmap record for a stackmap instruction. - /// - /// MI must be a raw STACKMAP, not a PATCHPOINT. - void recordStackMap(const MCSymbol &L, - const MachineInstr &MI); - - /// Generate a stackmap record for a patchpoint instruction. - void recordPatchPoint(const MCSymbol &L, - const MachineInstr &MI); - - /// Generate a stackmap record for a statepoint instruction. - void recordStatepoint(const MCSymbol &L, - const MachineInstr &MI); - - /// If there is any stack map data, create a stack map section and serialize - /// the map info into it. This clears the stack map data structures - /// afterwards. - void serializeToStackMapSection(); - - /// Get call site info. - CallsiteInfoList &getCSInfos() { return CSInfos; } - - /// Get function info. - FnInfoMap &getFnInfos() { return FnInfos; } - -private: - static const char *WSMP; - - AsmPrinter &AP; - CallsiteInfoList CSInfos; - ConstantPool ConstPool; - FnInfoMap FnInfos; - - MachineInstr::const_mop_iterator - parseOperand(MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE, LocationVec &Locs, - LiveOutVec &LiveOuts) const; - - /// Specialized parser of statepoint operands. - /// They do not directly correspond to StackMap record entries. - void parseStatepointOpers(const MachineInstr &MI, - MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE, - LocationVec &Locations, LiveOutVec &LiveOuts); - - /// Create a live-out register record for the given register @p Reg. - LiveOutReg createLiveOutReg(unsigned Reg, - const TargetRegisterInfo *TRI) const; - - /// Parse the register live-out mask and return a vector of live-out - /// registers that need to be recorded in the stackmap. - LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const; - - /// Record the locations of the operands of the provided instruction in a - /// record keyed by the provided label. For instructions w/AnyReg calling - /// convention the return register is also recorded if requested. For - /// STACKMAP, and PATCHPOINT the label is expected to immediately *precede* - /// lowering of the MI to MCInsts. For STATEPOINT, it expected to - /// immediately *follow*. It's not clear this difference was intentional, - /// but it exists today. - void recordStackMapOpers(const MCSymbol &L, - const MachineInstr &MI, uint64_t ID, - MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE, - bool recordResult = false); - - /// Emit the stackmap header. - void emitStackmapHeader(MCStreamer &OS); - - /// Emit the function frame record for each function. - void emitFunctionFrameRecords(MCStreamer &OS); - - /// Emit the constant pool. - void emitConstantPoolEntries(MCStreamer &OS); - - /// Emit the callsite info for each stackmap/patchpoint intrinsic call. - void emitCallsiteEntries(MCStreamer &OS); - - void print(raw_ostream &OS); - void debug() { print(dbgs()); } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_STACKMAPS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/StackProtector.h b/suite/synctools/tablegen/include/llvm/CodeGen/StackProtector.h deleted file mode 100644 index 57456b3f6c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/StackProtector.h +++ /dev/null @@ -1,121 +0,0 @@ -//===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass inserts stack protectors into functions which need them. A variable -// with a random value in it is stored onto the stack before the local variables -// are allocated. Upon exiting the block, the stored value is checked. If it's -// changed, then there was some sort of violation and the program aborts. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_STACKPROTECTOR_H -#define LLVM_CODEGEN_STACKPROTECTOR_H - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/Triple.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/ValueMap.h" -#include "llvm/Pass.h" - -namespace llvm { - -class BasicBlock; -class DominatorTree; -class Function; -class Instruction; -class Module; -class TargetLoweringBase; -class TargetMachine; -class Type; - -class StackProtector : public FunctionPass { -private: - /// A mapping of AllocaInsts to their required SSP layout. - using SSPLayoutMap = DenseMap; - - const TargetMachine *TM = nullptr; - - /// TLI - Keep a pointer of a TargetLowering to consult for determining - /// target type sizes. - const TargetLoweringBase *TLI = nullptr; - Triple Trip; - - Function *F; - Module *M; - - DominatorTree *DT; - - /// Layout - Mapping of allocations to the required SSPLayoutKind. - /// StackProtector analysis will update this map when determining if an - /// AllocaInst triggers a stack protector. - SSPLayoutMap Layout; - - /// The minimum size of buffers that will receive stack smashing - /// protection when -fstack-protection is used. - unsigned SSPBufferSize = 0; - - /// VisitedPHIs - The set of PHI nodes visited when determining - /// if a variable's reference has been taken. This set - /// is maintained to ensure we don't visit the same PHI node multiple - /// times. - SmallPtrSet VisitedPHIs; - - // A prologue is generated. - bool HasPrologue = false; - - // IR checking code is generated. - bool HasIRCheck = false; - - /// InsertStackProtectors - Insert code into the prologue and epilogue of - /// the function. - /// - /// - The prologue code loads and stores the stack guard onto the stack. - /// - The epilogue checks the value stored in the prologue against the - /// original value. It calls __stack_chk_fail if they differ. - bool InsertStackProtectors(); - - /// CreateFailBB - Create a basic block to jump to when the stack protector - /// check fails. - BasicBlock *CreateFailBB(); - - /// ContainsProtectableArray - Check whether the type either is an array or - /// contains an array of sufficient size so that we need stack protectors - /// for it. - /// \param [out] IsLarge is set to true if a protectable array is found and - /// it is "large" ( >= ssp-buffer-size). In the case of a structure with - /// multiple arrays, this gets set if any of them is large. - bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false, - bool InStruct = false) const; - - /// Check whether a stack allocation has its address taken. - bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize); - - /// RequiresStackProtector - Check whether or not this function needs a - /// stack protector based upon the stack protector level. - bool RequiresStackProtector(); - -public: - static char ID; // Pass identification, replacement for typeid. - - StackProtector(); - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - // Return true if StackProtector is supposed to be handled by SelectionDAG. - bool shouldEmitSDCheck(const BasicBlock &BB) const; - - bool runOnFunction(Function &Fn) override; - - void copyToMachineFrameInfo(MachineFrameInfo &MFI) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_STACKPROTECTOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SwiftErrorValueTracking.h b/suite/synctools/tablegen/include/llvm/CodeGen/SwiftErrorValueTracking.h deleted file mode 100644 index 08ab2abbdd..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SwiftErrorValueTracking.h +++ /dev/null @@ -1,110 +0,0 @@ -//===- SwiftErrorValueTracking.h - Track swifterror VReg vals --*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This implements a limited mem2reg-like analysis to promote uses of function -// arguments and allocas marked with swiftalloc from memory into virtual -// registers tracked by this class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SWIFTERRORVALUETRACKING_H -#define LLVM_CODEGEN_SWIFTERRORVALUETRACKING_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/Register.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/DebugLoc.h" -#include -#include -#include - - -namespace llvm { - class Function; - class MachineBasicBlock; - class MachineFunction; - class MachineInstr; - class TargetInstrInfo; - class TargetLowering; - -class SwiftErrorValueTracking { - // Some useful objects to reduce the number of function arguments needed. - MachineFunction *MF; - const Function *Fn; - const TargetLowering *TLI; - const TargetInstrInfo *TII; - - /// A map from swifterror value in a basic block to the virtual register it is - /// currently represented by. - DenseMap, Register> - VRegDefMap; - - /// A list of upward exposed vreg uses that need to be satisfied by either a - /// copy def or a phi node at the beginning of the basic block representing - /// the predecessor(s) swifterror value. - DenseMap, Register> - VRegUpwardsUse; - - /// A map from instructions that define/use a swifterror value to the virtual - /// register that represents that def/use. - llvm::DenseMap, Register> - VRegDefUses; - - /// The swifterror argument of the current function. - const Value *SwiftErrorArg; - - using SwiftErrorValues = SmallVector; - /// A function can only have a single swifterror argument. And if it does - /// have a swifterror argument, it must be the first entry in - /// SwiftErrorVals. - SwiftErrorValues SwiftErrorVals; - -public: - /// Initialize data structures for specified new function. - void setFunction(MachineFunction &MF); - - /// Get the (unique) function argument that was marked swifterror, or nullptr - /// if this function has no swifterror args. - const Value *getFunctionArg() const { - return SwiftErrorArg; - } - - /// Get or create the swifterror value virtual register in - /// VRegDefMap for this basic block. - Register getOrCreateVReg(const MachineBasicBlock *, const Value *); - - /// Set the swifterror virtual register in the VRegDefMap for this - /// basic block. - void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register); - - /// Get or create the swifterror value virtual register for a def of a - /// swifterror by an instruction. - Register getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, - const Value *); - - /// Get or create the swifterror value virtual register for a use of a - /// swifterror by an instruction. - Register getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, - const Value *); - - /// Create initial definitions of swifterror values in the entry block of the - /// current function. - bool createEntriesInEntryBlock(DebugLoc DbgLoc); - - /// Propagate assigned swifterror vregs through a function, synthesizing PHI - /// nodes when needed to maintain consistency. - void propagateVRegs(); - - void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, - BasicBlock::const_iterator End); -}; - -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/SwitchLoweringUtils.h b/suite/synctools/tablegen/include/llvm/CodeGen/SwitchLoweringUtils.h deleted file mode 100644 index 47bedd9bef..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/SwitchLoweringUtils.h +++ /dev/null @@ -1,304 +0,0 @@ -//===- SwitchLoweringUtils.h - Switch Lowering ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SWITCHLOWERINGUTILS_H -#define LLVM_CODEGEN_SWITCHLOWERINGUTILS_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/Support/BranchProbability.h" -#include - -namespace llvm { - -class BlockFrequencyInfo; -class ConstantInt; -class FunctionLoweringInfo; -class MachineBasicBlock; -class ProfileSummaryInfo; -class TargetLowering; -class TargetMachine; - -namespace SwitchCG { - -enum CaseClusterKind { - /// A cluster of adjacent case labels with the same destination, or just one - /// case. - CC_Range, - /// A cluster of cases suitable for jump table lowering. - CC_JumpTable, - /// A cluster of cases suitable for bit test lowering. - CC_BitTests -}; - -/// A cluster of case labels. -struct CaseCluster { - CaseClusterKind Kind; - const ConstantInt *Low, *High; - union { - MachineBasicBlock *MBB; - unsigned JTCasesIndex; - unsigned BTCasesIndex; - }; - BranchProbability Prob; - - static CaseCluster range(const ConstantInt *Low, const ConstantInt *High, - MachineBasicBlock *MBB, BranchProbability Prob) { - CaseCluster C; - C.Kind = CC_Range; - C.Low = Low; - C.High = High; - C.MBB = MBB; - C.Prob = Prob; - return C; - } - - static CaseCluster jumpTable(const ConstantInt *Low, const ConstantInt *High, - unsigned JTCasesIndex, BranchProbability Prob) { - CaseCluster C; - C.Kind = CC_JumpTable; - C.Low = Low; - C.High = High; - C.JTCasesIndex = JTCasesIndex; - C.Prob = Prob; - return C; - } - - static CaseCluster bitTests(const ConstantInt *Low, const ConstantInt *High, - unsigned BTCasesIndex, BranchProbability Prob) { - CaseCluster C; - C.Kind = CC_BitTests; - C.Low = Low; - C.High = High; - C.BTCasesIndex = BTCasesIndex; - C.Prob = Prob; - return C; - } -}; - -using CaseClusterVector = std::vector; -using CaseClusterIt = CaseClusterVector::iterator; - -/// Sort Clusters and merge adjacent cases. -void sortAndRangeify(CaseClusterVector &Clusters); - -struct CaseBits { - uint64_t Mask = 0; - MachineBasicBlock *BB = nullptr; - unsigned Bits = 0; - BranchProbability ExtraProb; - - CaseBits() = default; - CaseBits(uint64_t mask, MachineBasicBlock *bb, unsigned bits, - BranchProbability Prob) - : Mask(mask), BB(bb), Bits(bits), ExtraProb(Prob) {} -}; - -using CaseBitsVector = std::vector; - -/// This structure is used to communicate between SelectionDAGBuilder and -/// SDISel for the code generation of additional basic blocks needed by -/// multi-case switch statements. -struct CaseBlock { - // For the GISel interface. - struct PredInfoPair { - CmpInst::Predicate Pred; - // Set when no comparison should be emitted. - bool NoCmp; - }; - union { - // The condition code to use for the case block's setcc node. - // Besides the integer condition codes, this can also be SETTRUE, in which - // case no comparison gets emitted. - ISD::CondCode CC; - struct PredInfoPair PredInfo; - }; - - // The LHS/MHS/RHS of the comparison to emit. - // Emit by default LHS op RHS. MHS is used for range comparisons: - // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). - const Value *CmpLHS, *CmpMHS, *CmpRHS; - - // The block to branch to if the setcc is true/false. - MachineBasicBlock *TrueBB, *FalseBB; - - // The block into which to emit the code for the setcc and branches. - MachineBasicBlock *ThisBB; - - /// The debug location of the instruction this CaseBlock was - /// produced from. - SDLoc DL; - DebugLoc DbgLoc; - - // Branch weights. - BranchProbability TrueProb, FalseProb; - - // Constructor for SelectionDAG. - CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs, - const Value *cmpmiddle, MachineBasicBlock *truebb, - MachineBasicBlock *falsebb, MachineBasicBlock *me, SDLoc dl, - BranchProbability trueprob = BranchProbability::getUnknown(), - BranchProbability falseprob = BranchProbability::getUnknown()) - : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), - TrueBB(truebb), FalseBB(falsebb), ThisBB(me), DL(dl), - TrueProb(trueprob), FalseProb(falseprob) {} - - // Constructor for GISel. - CaseBlock(CmpInst::Predicate pred, bool nocmp, const Value *cmplhs, - const Value *cmprhs, const Value *cmpmiddle, - MachineBasicBlock *truebb, MachineBasicBlock *falsebb, - MachineBasicBlock *me, DebugLoc dl, - BranchProbability trueprob = BranchProbability::getUnknown(), - BranchProbability falseprob = BranchProbability::getUnknown()) - : PredInfo({pred, nocmp}), CmpLHS(cmplhs), CmpMHS(cmpmiddle), - CmpRHS(cmprhs), TrueBB(truebb), FalseBB(falsebb), ThisBB(me), - DbgLoc(dl), TrueProb(trueprob), FalseProb(falseprob) {} -}; - -struct JumpTable { - /// The virtual register containing the index of the jump table entry - /// to jump to. - unsigned Reg; - /// The JumpTableIndex for this jump table in the function. - unsigned JTI; - /// The MBB into which to emit the code for the indirect jump. - MachineBasicBlock *MBB; - /// The MBB of the default bb, which is a successor of the range - /// check MBB. This is when updating PHI nodes in successors. - MachineBasicBlock *Default; - - JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, MachineBasicBlock *D) - : Reg(R), JTI(J), MBB(M), Default(D) {} -}; -struct JumpTableHeader { - APInt First; - APInt Last; - const Value *SValue; - MachineBasicBlock *HeaderBB; - bool Emitted; - bool FallthroughUnreachable = false; - - JumpTableHeader(APInt F, APInt L, const Value *SV, MachineBasicBlock *H, - bool E = false) - : First(std::move(F)), Last(std::move(L)), SValue(SV), HeaderBB(H), - Emitted(E) {} -}; -using JumpTableBlock = std::pair; - -struct BitTestCase { - uint64_t Mask; - MachineBasicBlock *ThisBB; - MachineBasicBlock *TargetBB; - BranchProbability ExtraProb; - - BitTestCase(uint64_t M, MachineBasicBlock *T, MachineBasicBlock *Tr, - BranchProbability Prob) - : Mask(M), ThisBB(T), TargetBB(Tr), ExtraProb(Prob) {} -}; - -using BitTestInfo = SmallVector; - -struct BitTestBlock { - APInt First; - APInt Range; - const Value *SValue; - unsigned Reg; - MVT RegVT; - bool Emitted; - bool ContiguousRange; - MachineBasicBlock *Parent; - MachineBasicBlock *Default; - BitTestInfo Cases; - BranchProbability Prob; - BranchProbability DefaultProb; - bool FallthroughUnreachable = false; - - BitTestBlock(APInt F, APInt R, const Value *SV, unsigned Rg, MVT RgVT, bool E, - bool CR, MachineBasicBlock *P, MachineBasicBlock *D, - BitTestInfo C, BranchProbability Pr) - : First(std::move(F)), Range(std::move(R)), SValue(SV), Reg(Rg), - RegVT(RgVT), Emitted(E), ContiguousRange(CR), Parent(P), Default(D), - Cases(std::move(C)), Prob(Pr) {} -}; - -/// Return the range of values within a range. -uint64_t getJumpTableRange(const CaseClusterVector &Clusters, unsigned First, - unsigned Last); - -/// Return the number of cases within a range. -uint64_t getJumpTableNumCases(const SmallVectorImpl &TotalCases, - unsigned First, unsigned Last); - -struct SwitchWorkListItem { - MachineBasicBlock *MBB; - CaseClusterIt FirstCluster; - CaseClusterIt LastCluster; - const ConstantInt *GE; - const ConstantInt *LT; - BranchProbability DefaultProb; -}; -using SwitchWorkList = SmallVector; - -class SwitchLowering { -public: - SwitchLowering(FunctionLoweringInfo &funcinfo) : FuncInfo(funcinfo) {} - - void init(const TargetLowering &tli, const TargetMachine &tm, - const DataLayout &dl) { - TLI = &tli; - TM = &tm; - DL = &dl; - } - - /// Vector of CaseBlock structures used to communicate SwitchInst code - /// generation information. - std::vector SwitchCases; - - /// Vector of JumpTable structures used to communicate SwitchInst code - /// generation information. - std::vector JTCases; - - /// Vector of BitTestBlock structures used to communicate SwitchInst code - /// generation information. - std::vector BitTestCases; - - void findJumpTables(CaseClusterVector &Clusters, const SwitchInst *SI, - MachineBasicBlock *DefaultMBB, - ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI); - - bool buildJumpTable(const CaseClusterVector &Clusters, unsigned First, - unsigned Last, const SwitchInst *SI, - MachineBasicBlock *DefaultMBB, CaseCluster &JTCluster); - - - void findBitTestClusters(CaseClusterVector &Clusters, const SwitchInst *SI); - - /// Build a bit test cluster from Clusters[First..Last]. Returns false if it - /// decides it's not a good idea. - bool buildBitTests(CaseClusterVector &Clusters, unsigned First, unsigned Last, - const SwitchInst *SI, CaseCluster &BTCluster); - - virtual void addSuccessorWithProb( - MachineBasicBlock *Src, MachineBasicBlock *Dst, - BranchProbability Prob = BranchProbability::getUnknown()) = 0; - - virtual ~SwitchLowering() = default; - -private: - const TargetLowering *TLI; - const TargetMachine *TM; - const DataLayout *DL; - FunctionLoweringInfo &FuncInfo; -}; - -} // namespace SwitchCG -} // namespace llvm - -#endif // LLVM_CODEGEN_SWITCHLOWERINGUTILS_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TailDuplicator.h b/suite/synctools/tablegen/include/llvm/CodeGen/TailDuplicator.h deleted file mode 100644 index 4ff43bfcd4..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TailDuplicator.h +++ /dev/null @@ -1,136 +0,0 @@ -//===- llvm/CodeGen/TailDuplicator.h ----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the TailDuplicator class. Used by the -// TailDuplication pass, and MachineBlockPlacement. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TAILDUPLICATOR_H -#define LLVM_CODEGEN_TAILDUPLICATOR_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MBFIWrapper.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineBranchProbabilityInfo; -class MachineFunction; -class MachineInstr; -class MachineModuleInfo; -class MachineRegisterInfo; -class ProfileSummaryInfo; -class TargetRegisterInfo; - -/// Utility class to perform tail duplication. -class TailDuplicator { - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - const MachineBranchProbabilityInfo *MBPI; - const MachineModuleInfo *MMI; - MachineRegisterInfo *MRI; - MachineFunction *MF; - MBFIWrapper *MBFI; - ProfileSummaryInfo *PSI; - bool PreRegAlloc; - bool LayoutMode; - unsigned TailDupSize; - - // A list of virtual registers for which to update SSA form. - SmallVector SSAUpdateVRs; - - // For each virtual register in SSAUpdateVals keep a list of source virtual - // registers. - using AvailableValsTy = std::vector>; - - DenseMap SSAUpdateVals; - -public: - /// Prepare to run on a specific machine function. - /// @param MF - Function that will be processed - /// @param PreRegAlloc - true if used before register allocation - /// @param MBPI - Branch Probability Info. Used to propagate correct - /// probabilities when modifying the CFG. - /// @param LayoutMode - When true, don't use the existing layout to make - /// decisions. - /// @param TailDupSize - Maximum size of blocks to tail-duplicate. Zero - /// default implies using the command line value TailDupSize. - void initMF(MachineFunction &MF, bool PreRegAlloc, - const MachineBranchProbabilityInfo *MBPI, - MBFIWrapper *MBFI, - ProfileSummaryInfo *PSI, - bool LayoutMode, unsigned TailDupSize = 0); - - bool tailDuplicateBlocks(); - static bool isSimpleBB(MachineBasicBlock *TailBB); - bool shouldTailDuplicate(bool IsSimple, MachineBasicBlock &TailBB); - - /// Returns true if TailBB can successfully be duplicated into PredBB - bool canTailDuplicate(MachineBasicBlock *TailBB, MachineBasicBlock *PredBB); - - /// Tail duplicate a single basic block into its predecessors, and then clean - /// up. - /// If \p DuplicatePreds is not null, it will be updated to contain the list - /// of predecessors that received a copy of \p MBB. - /// If \p RemovalCallback is non-null. It will be called before MBB is - /// deleted. - /// If \p CandidatePtr is not null, duplicate into these blocks only. - bool tailDuplicateAndUpdate( - bool IsSimple, MachineBasicBlock *MBB, - MachineBasicBlock *ForcedLayoutPred, - SmallVectorImpl *DuplicatedPreds = nullptr, - function_ref *RemovalCallback = nullptr, - SmallVectorImpl *CandidatePtr = nullptr); - -private: - using RegSubRegPair = TargetInstrInfo::RegSubRegPair; - - void addSSAUpdateEntry(Register OrigReg, Register NewReg, - MachineBasicBlock *BB); - void processPHI(MachineInstr *MI, MachineBasicBlock *TailBB, - MachineBasicBlock *PredBB, - DenseMap &LocalVRMap, - SmallVectorImpl> &Copies, - const DenseSet &UsedByPhi, bool Remove); - void duplicateInstruction(MachineInstr *MI, MachineBasicBlock *TailBB, - MachineBasicBlock *PredBB, - DenseMap &LocalVRMap, - const DenseSet &UsedByPhi); - void updateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, - SmallVectorImpl &TDBBs, - SmallSetVector &Succs); - bool canCompletelyDuplicateBB(MachineBasicBlock &BB); - bool duplicateSimpleBB(MachineBasicBlock *TailBB, - SmallVectorImpl &TDBBs, - const DenseSet &RegsUsedByPhi, - SmallVectorImpl &Copies); - bool tailDuplicate(bool IsSimple, - MachineBasicBlock *TailBB, - MachineBasicBlock *ForcedLayoutPred, - SmallVectorImpl &TDBBs, - SmallVectorImpl &Copies, - SmallVectorImpl *CandidatePtr); - void appendCopies(MachineBasicBlock *MBB, - SmallVectorImpl> &CopyInfos, - SmallVectorImpl &Copies); - - void removeDeadBlock( - MachineBasicBlock *MBB, - function_ref *RemovalCallback = nullptr); -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TAILDUPLICATOR_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetCallingConv.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetCallingConv.h deleted file mode 100644 index 6236533037..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetCallingConv.h +++ /dev/null @@ -1,261 +0,0 @@ -//===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines types for working with calling-convention information. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H -#define LLVM_CODEGEN_TARGETCALLINGCONV_H - -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include -#include -#include - -namespace llvm { -namespace ISD { - - struct ArgFlagsTy { - private: - unsigned IsZExt : 1; ///< Zero extended - unsigned IsSExt : 1; ///< Sign extended - unsigned IsInReg : 1; ///< Passed in register - unsigned IsSRet : 1; ///< Hidden struct-ret ptr - unsigned IsByVal : 1; ///< Struct passed by value - unsigned IsByRef : 1; ///< Passed in memory - unsigned IsNest : 1; ///< Nested fn static chain - unsigned IsReturned : 1; ///< Always returned - unsigned IsSplit : 1; - unsigned IsInAlloca : 1; ///< Passed with inalloca - unsigned IsPreallocated : 1; ///< ByVal without the copy - unsigned IsSplitEnd : 1; ///< Last part of a split - unsigned IsSwiftSelf : 1; ///< Swift self parameter - unsigned IsSwiftAsync : 1; ///< Swift async context parameter - unsigned IsSwiftError : 1; ///< Swift error parameter - unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target - unsigned IsHva : 1; ///< HVA field for - unsigned IsHvaStart : 1; ///< HVA structure start - unsigned IsSecArgPass : 1; ///< Second argument - unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory - ///< (including byval/byref) - unsigned OrigAlign : 5; ///< Log 2 of original alignment - unsigned IsInConsecutiveRegsLast : 1; - unsigned IsInConsecutiveRegs : 1; - unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate - unsigned IsPointer : 1; - - unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size - - unsigned PointerAddrSpace = 0; ///< Address space of pointer argument - - public: - ArgFlagsTy() - : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0), - IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), - IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0), - IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0), - IsSecArgPass(0), MemAlign(0), OrigAlign(0), - IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), IsPointer(0) { - static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); - } - - bool isZExt() const { return IsZExt; } - void setZExt() { IsZExt = 1; } - - bool isSExt() const { return IsSExt; } - void setSExt() { IsSExt = 1; } - - bool isInReg() const { return IsInReg; } - void setInReg() { IsInReg = 1; } - - bool isSRet() const { return IsSRet; } - void setSRet() { IsSRet = 1; } - - bool isByVal() const { return IsByVal; } - void setByVal() { IsByVal = 1; } - - bool isByRef() const { return IsByRef; } - void setByRef() { IsByRef = 1; } - - bool isInAlloca() const { return IsInAlloca; } - void setInAlloca() { IsInAlloca = 1; } - - bool isPreallocated() const { return IsPreallocated; } - void setPreallocated() { IsPreallocated = 1; } - - bool isSwiftSelf() const { return IsSwiftSelf; } - void setSwiftSelf() { IsSwiftSelf = 1; } - - bool isSwiftAsync() const { return IsSwiftAsync; } - void setSwiftAsync() { IsSwiftAsync = 1; } - - bool isSwiftError() const { return IsSwiftError; } - void setSwiftError() { IsSwiftError = 1; } - - bool isCFGuardTarget() const { return IsCFGuardTarget; } - void setCFGuardTarget() { IsCFGuardTarget = 1; } - - bool isHva() const { return IsHva; } - void setHva() { IsHva = 1; } - - bool isHvaStart() const { return IsHvaStart; } - void setHvaStart() { IsHvaStart = 1; } - - bool isSecArgPass() const { return IsSecArgPass; } - void setSecArgPass() { IsSecArgPass = 1; } - - bool isNest() const { return IsNest; } - void setNest() { IsNest = 1; } - - bool isReturned() const { return IsReturned; } - void setReturned(bool V = true) { IsReturned = V; } - - bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; } - void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; } - - bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; } - void setInConsecutiveRegsLast(bool Flag = true) { - IsInConsecutiveRegsLast = Flag; - } - - bool isSplit() const { return IsSplit; } - void setSplit() { IsSplit = 1; } - - bool isSplitEnd() const { return IsSplitEnd; } - void setSplitEnd() { IsSplitEnd = 1; } - - bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } - void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } - - bool isPointer() const { return IsPointer; } - void setPointer() { IsPointer = 1; } - - Align getNonZeroMemAlign() const { - return decodeMaybeAlign(MemAlign).valueOrOne(); - } - - void setMemAlign(Align A) { - MemAlign = encode(A); - assert(getNonZeroMemAlign() == A && "bitfield overflow"); - } - - Align getNonZeroByValAlign() const { - assert(isByVal()); - MaybeAlign A = decodeMaybeAlign(MemAlign); - assert(A && "ByValAlign must be defined"); - return *A; - } - - Align getNonZeroOrigAlign() const { - return decodeMaybeAlign(OrigAlign).valueOrOne(); - } - - void setOrigAlign(Align A) { - OrigAlign = encode(A); - assert(getNonZeroOrigAlign() == A && "bitfield overflow"); - } - - unsigned getByValSize() const { - assert(isByVal() && !isByRef()); - return ByValOrByRefSize; - } - void setByValSize(unsigned S) { - assert(isByVal() && !isByRef()); - ByValOrByRefSize = S; - } - - unsigned getByRefSize() const { - assert(!isByVal() && isByRef()); - return ByValOrByRefSize; - } - void setByRefSize(unsigned S) { - assert(!isByVal() && isByRef()); - ByValOrByRefSize = S; - } - - unsigned getPointerAddrSpace() const { return PointerAddrSpace; } - void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } -}; - - /// InputArg - This struct carries flags and type information about a - /// single incoming (formal) argument or incoming (from the perspective - /// of the caller) return value virtual register. - /// - struct InputArg { - ArgFlagsTy Flags; - MVT VT = MVT::Other; - EVT ArgVT; - bool Used = false; - - /// Index original Function's argument. - unsigned OrigArgIndex; - /// Sentinel value for implicit machine-level input arguments. - static const unsigned NoArgIndex = UINT_MAX; - - /// Offset in bytes of current input value relative to the beginning of - /// original argument. E.g. if argument was splitted into four 32 bit - /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12. - unsigned PartOffset; - - InputArg() = default; - InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used, - unsigned origIdx, unsigned partOffs) - : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { - VT = vt.getSimpleVT(); - ArgVT = argvt; - } - - bool isOrigArg() const { - return OrigArgIndex != NoArgIndex; - } - - unsigned getOrigArgIndex() const { - assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument"); - return OrigArgIndex; - } - }; - - /// OutputArg - This struct carries flags and a value for a - /// single outgoing (actual) argument or outgoing (from the perspective - /// of the caller) return value virtual register. - /// - struct OutputArg { - ArgFlagsTy Flags; - MVT VT; - EVT ArgVT; - - /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". - bool IsFixed = false; - - /// Index original Function's argument. - unsigned OrigArgIndex; - - /// Offset in bytes of current output value relative to the beginning of - /// original argument. E.g. if argument was splitted into four 32 bit - /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12. - unsigned PartOffset; - - OutputArg() = default; - OutputArg(ArgFlagsTy flags, MVT vt, EVT argvt, bool isfixed, - unsigned origIdx, unsigned partOffs) - : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), - PartOffset(partOffs) { - VT = vt; - ArgVT = argvt; - } - }; - -} // end namespace ISD -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETCALLINGCONV_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetFrameLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetFrameLowering.h deleted file mode 100644 index f2ca1590fc..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetFrameLowering.h +++ /dev/null @@ -1,458 +0,0 @@ -//===-- llvm/CodeGen/TargetFrameLowering.h ----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Interface to describe the layout of a stack frame on the target machine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETFRAMELOWERING_H -#define LLVM_CODEGEN_TARGETFRAMELOWERING_H - -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Support/TypeSize.h" -#include - -namespace llvm { - class BitVector; - class CalleeSavedInfo; - class MachineFunction; - class RegScavenger; - -namespace TargetStackID { -enum Value { - Default = 0, - SGPRSpill = 1, - ScalableVector = 2, - WasmLocal = 3, - NoAlloc = 255 -}; -} - -/// Information about stack frame layout on the target. It holds the direction -/// of stack growth, the known stack alignment on entry to each function, and -/// the offset to the locals area. -/// -/// The offset to the local area is the offset from the stack pointer on -/// function entry to the first location where function data (local variables, -/// spill locations) can be stored. -class TargetFrameLowering { -public: - enum StackDirection { - StackGrowsUp, // Adding to the stack increases the stack address - StackGrowsDown // Adding to the stack decreases the stack address - }; - - // Maps a callee saved register to a stack slot with a fixed offset. - struct SpillSlot { - unsigned Reg; - int Offset; // Offset relative to stack pointer on function entry. - }; - - struct DwarfFrameBase { - // The frame base may be either a register (the default), the CFA, - // or a WebAssembly-specific location description. - enum FrameBaseKind { Register, CFA, WasmFrameBase } Kind; - struct WasmFrameBase { - unsigned Kind; // Wasm local, global, or value stack - unsigned Index; - }; - union { - unsigned Reg; - struct WasmFrameBase WasmLoc; - } Location; - }; - -private: - StackDirection StackDir; - Align StackAlignment; - Align TransientStackAlignment; - int LocalAreaOffset; - bool StackRealignable; -public: - TargetFrameLowering(StackDirection D, Align StackAl, int LAO, - Align TransAl = Align(1), bool StackReal = true) - : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), - LocalAreaOffset(LAO), StackRealignable(StackReal) {} - - virtual ~TargetFrameLowering(); - - // These methods return information that describes the abstract stack layout - // of the target machine. - - /// getStackGrowthDirection - Return the direction the stack grows - /// - StackDirection getStackGrowthDirection() const { return StackDir; } - - /// getStackAlignment - This method returns the number of bytes to which the - /// stack pointer must be aligned on entry to a function. Typically, this - /// is the largest alignment for any data object in the target. - /// - unsigned getStackAlignment() const { return StackAlignment.value(); } - /// getStackAlignment - This method returns the number of bytes to which the - /// stack pointer must be aligned on entry to a function. Typically, this - /// is the largest alignment for any data object in the target. - /// - Align getStackAlign() const { return StackAlignment; } - - /// alignSPAdjust - This method aligns the stack adjustment to the correct - /// alignment. - /// - int alignSPAdjust(int SPAdj) const { - if (SPAdj < 0) { - SPAdj = -alignTo(-SPAdj, StackAlignment); - } else { - SPAdj = alignTo(SPAdj, StackAlignment); - } - return SPAdj; - } - - /// getTransientStackAlignment - This method returns the number of bytes to - /// which the stack pointer must be aligned at all times, even between - /// calls. - /// - Align getTransientStackAlign() const { return TransientStackAlignment; } - - /// isStackRealignable - This method returns whether the stack can be - /// realigned. - bool isStackRealignable() const { - return StackRealignable; - } - - /// Return the skew that has to be applied to stack alignment under - /// certain conditions (e.g. stack was adjusted before function \p MF - /// was called). - virtual unsigned getStackAlignmentSkew(const MachineFunction &MF) const; - - /// This method returns whether or not it is safe for an object with the - /// given stack id to be bundled into the local area. - virtual bool isStackIdSafeForLocalArea(unsigned StackId) const { - return true; - } - - /// getOffsetOfLocalArea - This method returns the offset of the local area - /// from the stack pointer on entrance to a function. - /// - int getOffsetOfLocalArea() const { return LocalAreaOffset; } - - /// Control the placement of special register scavenging spill slots when - /// allocating a stack frame. - /// - /// If this returns true, the frame indexes used by the RegScavenger will be - /// allocated closest to the incoming stack pointer. - virtual bool allocateScavengingFrameIndexesNearIncomingSP( - const MachineFunction &MF) const; - - /// assignCalleeSavedSpillSlots - Allows target to override spill slot - /// assignment logic. If implemented, assignCalleeSavedSpillSlots() should - /// assign frame slots to all CSI entries and return true. If this method - /// returns false, spill slots will be assigned using generic implementation. - /// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of - /// CSI. - virtual bool assignCalleeSavedSpillSlots(MachineFunction &MF, - const TargetRegisterInfo *TRI, - std::vector &CSI, - unsigned &MinCSFrameIndex, - unsigned &MaxCSFrameIndex) const { - return assignCalleeSavedSpillSlots(MF, TRI, CSI); - } - - virtual bool - assignCalleeSavedSpillSlots(MachineFunction &MF, - const TargetRegisterInfo *TRI, - std::vector &CSI) const { - return false; - } - - /// getCalleeSavedSpillSlots - This method returns a pointer to an array of - /// pairs, that contains an entry for each callee saved register that must be - /// spilled to a particular stack location if it is spilled. - /// - /// Each entry in this array contains a pair, indicating the - /// fixed offset from the incoming stack pointer that each register should be - /// spilled at. If a register is not listed here, the code generator is - /// allowed to spill it anywhere it chooses. - /// - virtual const SpillSlot * - getCalleeSavedSpillSlots(unsigned &NumEntries) const { - NumEntries = 0; - return nullptr; - } - - /// targetHandlesStackFrameRounding - Returns true if the target is - /// responsible for rounding up the stack frame (probably at emitPrologue - /// time). - virtual bool targetHandlesStackFrameRounding() const { - return false; - } - - /// Returns true if the target will correctly handle shrink wrapping. - virtual bool enableShrinkWrapping(const MachineFunction &MF) const { - return false; - } - - /// Returns true if the stack slot holes in the fixed and callee-save stack - /// area should be used when allocating other stack locations to reduce stack - /// size. - virtual bool enableStackSlotScavenging(const MachineFunction &MF) const { - return false; - } - - /// Returns true if the target can safely skip saving callee-saved registers - /// for noreturn nounwind functions. - virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const; - - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - virtual void emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; - - /// With basic block sections, emit callee saved frame moves for basic blocks - /// that are in a different section. - virtual void - emitCalleeSavedFrameMovesFullCFA(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI) const {} - - /// Replace a StackProbe stub (if any) with the actual probe code inline - virtual void inlineStackProbe(MachineFunction &MF, - MachineBasicBlock &PrologueMBB) const {} - - /// Does the stack probe function call return with a modified stack pointer? - virtual bool stackProbeFunctionModifiesSP() const { return false; } - - /// Adjust the prologue to have the function use segmented stacks. This works - /// by adding a check even before the "normal" function prologue. - virtual void adjustForSegmentedStacks(MachineFunction &MF, - MachineBasicBlock &PrologueMBB) const {} - - /// Adjust the prologue to add Erlang Run-Time System (ERTS) specific code in - /// the assembly prologue to explicitly handle the stack. - virtual void adjustForHiPEPrologue(MachineFunction &MF, - MachineBasicBlock &PrologueMBB) const {} - - /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of store instructions via - /// storeRegToStackSlot(). Returns false otherwise. - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - ArrayRef CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - - /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of load instructions via loadRegToStackSlot(). - /// If it returns true, and any of the registers in CSI is not restored, - /// it sets the corresponding Restored flag in CSI to false. - /// Returns false otherwise. - virtual bool - restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - MutableArrayRef CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - - /// Return true if the target wants to keep the frame pointer regardless of - /// the function attribute "frame-pointer". - virtual bool keepFramePointer(const MachineFunction &MF) const { - return false; - } - - /// hasFP - Return true if the specified function should have a dedicated - /// frame pointer register. For most targets this is true only if the function - /// has variable sized allocas or if frame pointer elimination is disabled. - virtual bool hasFP(const MachineFunction &MF) const = 0; - - /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is - /// not required, we reserve argument space for call sites in the function - /// immediately on entry to the current function. This eliminates the need for - /// add/sub sp brackets around call sites. Returns true if the call frame is - /// included as part of the stack frame. - virtual bool hasReservedCallFrame(const MachineFunction &MF) const { - return !hasFP(MF); - } - - /// canSimplifyCallFramePseudos - When possible, it's best to simplify the - /// call frame pseudo ops before doing frame index elimination. This is - /// possible only when frame index references between the pseudos won't - /// need adjusting for the call frame adjustments. Normally, that's true - /// if the function has a reserved call frame or a frame pointer. Some - /// targets (Thumb2, for example) may have more complicated criteria, - /// however, and can override this behavior. - virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { - return hasReservedCallFrame(MF) || hasFP(MF); - } - - // needsFrameIndexResolution - Do we need to perform FI resolution for - // this function. Normally, this is required only when the function - // has any stack objects. However, targets may want to override this. - virtual bool needsFrameIndexResolution(const MachineFunction &MF) const; - - /// getFrameIndexReference - This method should return the base register - /// and offset used to reference a frame index location. The offset is - /// returned directly, and the base register is returned via FrameReg. - virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, - Register &FrameReg) const; - - /// Same as \c getFrameIndexReference, except that the stack pointer (as - /// opposed to the frame pointer) will be the preferred value for \p - /// FrameReg. This is generally used for emitting statepoint or EH tables that - /// use offsets from RSP. If \p IgnoreSPUpdates is true, the returned - /// offset is only guaranteed to be valid with respect to the value of SP at - /// the end of the prologue. - virtual StackOffset - getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, - Register &FrameReg, - bool IgnoreSPUpdates) const { - // Always safe to dispatch to getFrameIndexReference. - return getFrameIndexReference(MF, FI, FrameReg); - } - - /// getNonLocalFrameIndexReference - This method returns the offset used to - /// reference a frame index location. The offset can be from either FP/BP/SP - /// based on which base register is returned by llvm.localaddress. - virtual StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, - int FI) const { - // By default, dispatch to getFrameIndexReference. Interested targets can - // override this. - Register FrameReg; - return getFrameIndexReference(MF, FI, FrameReg); - } - - /// Returns the callee-saved registers as computed by determineCalleeSaves - /// in the BitVector \p SavedRegs. - virtual void getCalleeSaves(const MachineFunction &MF, - BitVector &SavedRegs) const; - - /// This method determines which of the registers reported by - /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. - /// The default implementation checks populates the \p SavedRegs bitset with - /// all registers which are modified in the function, targets may override - /// this function to save additional registers. - /// This method also sets up the register scavenger ensuring there is a free - /// register or a frameindex available. - /// This method should not be called by any passes outside of PEI, because - /// it may change state passed in by \p MF and \p RS. The preferred - /// interface outside PEI is getCalleeSaves. - virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS = nullptr) const; - - /// processFunctionBeforeFrameFinalized - This method is called immediately - /// before the specified function's frame layout (MF.getFrameInfo()) is - /// finalized. Once the frame is finalized, MO_FrameIndex operands are - /// replaced with direct constants. This method is optional. - /// - virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, - RegScavenger *RS = nullptr) const { - } - - /// processFunctionBeforeFrameIndicesReplaced - This method is called - /// immediately before MO_FrameIndex operands are eliminated, but after the - /// frame is finalized. This method is optional. - virtual void - processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, - RegScavenger *RS = nullptr) const {} - - virtual unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const { - report_fatal_error("WinEH not implemented for this target"); - } - - /// This method is called during prolog/epilog code insertion to eliminate - /// call frame setup and destroy pseudo instructions (but only if the Target - /// is using them). It is responsible for eliminating these instructions, - /// replacing them with concrete instructions. This method need only be - /// implemented if using call frame setup/destroy pseudo instructions. - /// Returns an iterator pointing to the instruction after the replaced one. - virtual MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const { - llvm_unreachable("Call Frame Pseudo Instructions do not exist on this " - "target!"); - } - - - /// Order the symbols in the local stack frame. - /// The list of objects that we want to order is in \p objectsToAllocate as - /// indices into the MachineFrameInfo. The array can be reordered in any way - /// upon return. The contents of the array, however, may not be modified (i.e. - /// only their order may be changed). - /// By default, just maintain the original order. - virtual void - orderFrameObjects(const MachineFunction &MF, - SmallVectorImpl &objectsToAllocate) const { - } - - /// Check whether or not the given \p MBB can be used as a prologue - /// for the target. - /// The prologue will be inserted first in this basic block. - /// This method is used by the shrink-wrapping pass to decide if - /// \p MBB will be correctly handled by the target. - /// As soon as the target enable shrink-wrapping without overriding - /// this method, we assume that each basic block is a valid - /// prologue. - virtual bool canUseAsPrologue(const MachineBasicBlock &MBB) const { - return true; - } - - /// Check whether or not the given \p MBB can be used as a epilogue - /// for the target. - /// The epilogue will be inserted before the first terminator of that block. - /// This method is used by the shrink-wrapping pass to decide if - /// \p MBB will be correctly handled by the target. - /// As soon as the target enable shrink-wrapping without overriding - /// this method, we assume that each basic block is a valid - /// epilogue. - virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const { - return true; - } - - /// Returns the StackID that scalable vectors should be associated with. - virtual TargetStackID::Value getStackIDForScalableVectors() const { - return TargetStackID::Default; - } - - virtual bool isSupportedStackID(TargetStackID::Value ID) const { - switch (ID) { - default: - return false; - case TargetStackID::Default: - case TargetStackID::NoAlloc: - return true; - } - } - - /// Check if given function is safe for not having callee saved registers. - /// This is used when interprocedural register allocation is enabled. - static bool isSafeForNoCSROpt(const Function &F); - - /// Check if the no-CSR optimisation is profitable for the given function. - virtual bool isProfitableForNoCSROpt(const Function &F) const { - return true; - } - - /// Return initial CFA offset value i.e. the one valid at the beginning of the - /// function (before any stack operations). - virtual int getInitialCFAOffset(const MachineFunction &MF) const; - - /// Return initial CFA register value i.e. the one valid at the beginning of - /// the function (before any stack operations). - virtual Register getInitialCFARegister(const MachineFunction &MF) const; - - /// Return the frame base information to be encoded in the DWARF subprogram - /// debug info. - virtual DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const; -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetInstrInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetInstrInfo.h deleted file mode 100644 index c46328fdec..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetInstrInfo.h +++ /dev/null @@ -1,2036 +0,0 @@ -//===- llvm/CodeGen/TargetInstrInfo.h - Instruction Info --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the target machine instruction set to the code generator. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETINSTRINFO_H -#define LLVM_CODEGEN_TARGETINSTRINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/None.h" -#include "llvm/CodeGen/MIRFormatter.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineCombinerPattern.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineOutliner.h" -#include "llvm/CodeGen/RegisterClassInfo.h" -#include "llvm/CodeGen/VirtRegMap.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/Support/BranchProbability.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include - -namespace llvm { - -class AAResults; -class DFAPacketizer; -class InstrItineraryData; -class LiveIntervals; -class LiveVariables; -class MachineLoop; -class MachineMemOperand; -class MachineRegisterInfo; -class MCAsmInfo; -class MCInst; -struct MCSchedModel; -class Module; -class ScheduleDAG; -class ScheduleDAGMI; -class ScheduleHazardRecognizer; -class SDNode; -class SelectionDAG; -class RegScavenger; -class TargetRegisterClass; -class TargetRegisterInfo; -class TargetSchedModel; -class TargetSubtargetInfo; - -template class SmallVectorImpl; - -using ParamLoadedValue = std::pair; - -struct DestSourcePair { - const MachineOperand *Destination; - const MachineOperand *Source; - - DestSourcePair(const MachineOperand &Dest, const MachineOperand &Src) - : Destination(&Dest), Source(&Src) {} -}; - -/// Used to describe a register and immediate addition. -struct RegImmPair { - Register Reg; - int64_t Imm; - - RegImmPair(Register Reg, int64_t Imm) : Reg(Reg), Imm(Imm) {} -}; - -/// Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare. -/// It holds the register values, the scale value and the displacement. -struct ExtAddrMode { - Register BaseReg; - Register ScaledReg; - int64_t Scale; - int64_t Displacement; -}; - -//--------------------------------------------------------------------------- -/// -/// TargetInstrInfo - Interface to description of machine instruction set -/// -class TargetInstrInfo : public MCInstrInfo { -public: - TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u, - unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u) - : CallFrameSetupOpcode(CFSetupOpcode), - CallFrameDestroyOpcode(CFDestroyOpcode), CatchRetOpcode(CatchRetOpcode), - ReturnOpcode(ReturnOpcode) {} - TargetInstrInfo(const TargetInstrInfo &) = delete; - TargetInstrInfo &operator=(const TargetInstrInfo &) = delete; - virtual ~TargetInstrInfo(); - - static bool isGenericOpcode(unsigned Opc) { - return Opc <= TargetOpcode::GENERIC_OP_END; - } - - /// Given a machine instruction descriptor, returns the register - /// class constraint for OpNum, or NULL. - virtual - const TargetRegisterClass *getRegClass(const MCInstrDesc &MCID, unsigned OpNum, - const TargetRegisterInfo *TRI, - const MachineFunction &MF) const; - - /// Return true if the instruction is trivially rematerializable, meaning it - /// has no side effects and requires no operands that aren't always available. - /// This means the only allowed uses are constants and unallocatable physical - /// registers so that the instructions result is independent of the place - /// in the function. - bool isTriviallyReMaterializable(const MachineInstr &MI, - AAResults *AA = nullptr) const { - return MI.getOpcode() == TargetOpcode::IMPLICIT_DEF || - (MI.getDesc().isRematerializable() && - (isReallyTriviallyReMaterializable(MI, AA) || - isReallyTriviallyReMaterializableGeneric(MI, AA))); - } - - /// Given \p MO is a PhysReg use return if it can be ignored for the purpose - /// of instruction rematerialization or sinking. - virtual bool isIgnorableUse(const MachineOperand &MO) const { - return false; - } - -protected: - /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is - /// set, this hook lets the target specify whether the instruction is actually - /// trivially rematerializable, taking into consideration its operands. This - /// predicate must return false if the instruction has any side effects other - /// than producing a value, or if it requires any address registers that are - /// not always available. - /// Requirements must be check as stated in isTriviallyReMaterializable() . - virtual bool isReallyTriviallyReMaterializable(const MachineInstr &MI, - AAResults *AA) const { - return false; - } - - /// This method commutes the operands of the given machine instruction MI. - /// The operands to be commuted are specified by their indices OpIdx1 and - /// OpIdx2. - /// - /// If a target has any instructions that are commutable but require - /// converting to different instructions or making non-trivial changes - /// to commute them, this method can be overloaded to do that. - /// The default implementation simply swaps the commutable operands. - /// - /// If NewMI is false, MI is modified in place and returned; otherwise, a - /// new machine instruction is created and returned. - /// - /// Do not call this method for a non-commutable instruction. - /// Even though the instruction is commutable, the method may still - /// fail to commute the operands, null pointer is returned in such cases. - virtual MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, - unsigned OpIdx1, - unsigned OpIdx2) const; - - /// Assigns the (CommutableOpIdx1, CommutableOpIdx2) pair of commutable - /// operand indices to (ResultIdx1, ResultIdx2). - /// One or both input values of the pair: (ResultIdx1, ResultIdx2) may be - /// predefined to some indices or be undefined (designated by the special - /// value 'CommuteAnyOperandIndex'). - /// The predefined result indices cannot be re-defined. - /// The function returns true iff after the result pair redefinition - /// the fixed result pair is equal to or equivalent to the source pair of - /// indices: (CommutableOpIdx1, CommutableOpIdx2). It is assumed here that - /// the pairs (x,y) and (y,x) are equivalent. - static bool fixCommutedOpIndices(unsigned &ResultIdx1, unsigned &ResultIdx2, - unsigned CommutableOpIdx1, - unsigned CommutableOpIdx2); - -private: - /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is - /// set and the target hook isReallyTriviallyReMaterializable returns false, - /// this function does target-independent tests to determine if the - /// instruction is really trivially rematerializable. - bool isReallyTriviallyReMaterializableGeneric(const MachineInstr &MI, - AAResults *AA) const; - -public: - /// These methods return the opcode of the frame setup/destroy instructions - /// if they exist (-1 otherwise). Some targets use pseudo instructions in - /// order to abstract away the difference between operating with a frame - /// pointer and operating without, through the use of these two instructions. - /// - unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } - unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } - - /// Returns true if the argument is a frame pseudo instruction. - bool isFrameInstr(const MachineInstr &I) const { - return I.getOpcode() == getCallFrameSetupOpcode() || - I.getOpcode() == getCallFrameDestroyOpcode(); - } - - /// Returns true if the argument is a frame setup pseudo instruction. - bool isFrameSetup(const MachineInstr &I) const { - return I.getOpcode() == getCallFrameSetupOpcode(); - } - - /// Returns size of the frame associated with the given frame instruction. - /// For frame setup instruction this is frame that is set up space set up - /// after the instruction. For frame destroy instruction this is the frame - /// freed by the caller. - /// Note, in some cases a call frame (or a part of it) may be prepared prior - /// to the frame setup instruction. It occurs in the calls that involve - /// inalloca arguments. This function reports only the size of the frame part - /// that is set up between the frame setup and destroy pseudo instructions. - int64_t getFrameSize(const MachineInstr &I) const { - assert(isFrameInstr(I) && "Not a frame instruction"); - assert(I.getOperand(0).getImm() >= 0); - return I.getOperand(0).getImm(); - } - - /// Returns the total frame size, which is made up of the space set up inside - /// the pair of frame start-stop instructions and the space that is set up - /// prior to the pair. - int64_t getFrameTotalSize(const MachineInstr &I) const { - if (isFrameSetup(I)) { - assert(I.getOperand(1).getImm() >= 0 && - "Frame size must not be negative"); - return getFrameSize(I) + I.getOperand(1).getImm(); - } - return getFrameSize(I); - } - - unsigned getCatchReturnOpcode() const { return CatchRetOpcode; } - unsigned getReturnOpcode() const { return ReturnOpcode; } - - /// Returns the actual stack pointer adjustment made by an instruction - /// as part of a call sequence. By default, only call frame setup/destroy - /// instructions adjust the stack, but targets may want to override this - /// to enable more fine-grained adjustment, or adjust by a different value. - virtual int getSPAdjust(const MachineInstr &MI) const; - - /// Return true if the instruction is a "coalescable" extension instruction. - /// That is, it's like a copy where it's legal for the source to overlap the - /// destination. e.g. X86::MOVSX64rr32. If this returns true, then it's - /// expected the pre-extension value is available as a subreg of the result - /// register. This also returns the sub-register index in SubIdx. - virtual bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, - Register &DstReg, unsigned &SubIdx) const { - return false; - } - - /// If the specified machine instruction is a direct - /// load from a stack slot, return the virtual or physical register number of - /// the destination along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than loading from the stack slot. - virtual unsigned isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - return 0; - } - - /// Optional extension of isLoadFromStackSlot that returns the number of - /// bytes loaded from the stack. This must be implemented if a backend - /// supports partial stack slot spills/loads to further disambiguate - /// what the load does. - virtual unsigned isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex, - unsigned &MemBytes) const { - MemBytes = 0; - return isLoadFromStackSlot(MI, FrameIndex); - } - - /// Check for post-frame ptr elimination stack locations as well. - /// This uses a heuristic so it isn't reliable for correctness. - virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI, - int &FrameIndex) const { - return 0; - } - - /// If the specified machine instruction has a load from a stack slot, - /// return true along with the FrameIndices of the loaded stack slot and the - /// machine mem operands containing the reference. - /// If not, return false. Unlike isLoadFromStackSlot, this returns true for - /// any instructions that loads from the stack. This is just a hint, as some - /// cases may be missed. - virtual bool hasLoadFromStackSlot( - const MachineInstr &MI, - SmallVectorImpl &Accesses) const; - - /// If the specified machine instruction is a direct - /// store to a stack slot, return the virtual or physical register number of - /// the source reg along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than storing to the stack slot. - virtual unsigned isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - return 0; - } - - /// Optional extension of isStoreToStackSlot that returns the number of - /// bytes stored to the stack. This must be implemented if a backend - /// supports partial stack slot spills/loads to further disambiguate - /// what the store does. - virtual unsigned isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex, - unsigned &MemBytes) const { - MemBytes = 0; - return isStoreToStackSlot(MI, FrameIndex); - } - - /// Check for post-frame ptr elimination stack locations as well. - /// This uses a heuristic, so it isn't reliable for correctness. - virtual unsigned isStoreToStackSlotPostFE(const MachineInstr &MI, - int &FrameIndex) const { - return 0; - } - - /// If the specified machine instruction has a store to a stack slot, - /// return true along with the FrameIndices of the loaded stack slot and the - /// machine mem operands containing the reference. - /// If not, return false. Unlike isStoreToStackSlot, - /// this returns true for any instructions that stores to the - /// stack. This is just a hint, as some cases may be missed. - virtual bool hasStoreToStackSlot( - const MachineInstr &MI, - SmallVectorImpl &Accesses) const; - - /// Return true if the specified machine instruction - /// is a copy of one stack slot to another and has no other effect. - /// Provide the identity of the two frame indices. - virtual bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex, - int &SrcFrameIndex) const { - return false; - } - - /// Compute the size in bytes and offset within a stack slot of a spilled - /// register or subregister. - /// - /// \param [out] Size in bytes of the spilled value. - /// \param [out] Offset in bytes within the stack slot. - /// \returns true if both Size and Offset are successfully computed. - /// - /// Not all subregisters have computable spill slots. For example, - /// subregisters registers may not be byte-sized, and a pair of discontiguous - /// subregisters has no single offset. - /// - /// Targets with nontrivial bigendian implementations may need to override - /// this, particularly to support spilled vector registers. - virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx, - unsigned &Size, unsigned &Offset, - const MachineFunction &MF) const; - - /// Return true if the given instruction is terminator that is unspillable, - /// according to isUnspillableTerminatorImpl. - bool isUnspillableTerminator(const MachineInstr *MI) const { - return MI->isTerminator() && isUnspillableTerminatorImpl(MI); - } - - /// Returns the size in bytes of the specified MachineInstr, or ~0U - /// when this function is not implemented by a target. - virtual unsigned getInstSizeInBytes(const MachineInstr &MI) const { - return ~0U; - } - - /// Return true if the instruction is as cheap as a move instruction. - /// - /// Targets for different archs need to override this, and different - /// micro-architectures can also be finely tuned inside. - virtual bool isAsCheapAsAMove(const MachineInstr &MI) const { - return MI.isAsCheapAsAMove(); - } - - /// Return true if the instruction should be sunk by MachineSink. - /// - /// MachineSink determines on its own whether the instruction is safe to sink; - /// this gives the target a hook to override the default behavior with regards - /// to which instructions should be sunk. - virtual bool shouldSink(const MachineInstr &MI) const { return true; } - - /// Re-issue the specified 'original' instruction at the - /// specific location targeting a new destination register. - /// The register in Orig->getOperand(0).getReg() will be substituted by - /// DestReg:SubIdx. Any existing subreg index is preserved or composed with - /// SubIdx. - virtual void reMaterialize(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, Register DestReg, - unsigned SubIdx, const MachineInstr &Orig, - const TargetRegisterInfo &TRI) const; - - /// Clones instruction or the whole instruction bundle \p Orig and - /// insert into \p MBB before \p InsertBefore. The target may update operands - /// that are required to be unique. - /// - /// \p Orig must not return true for MachineInstr::isNotDuplicable(). - virtual MachineInstr &duplicate(MachineBasicBlock &MBB, - MachineBasicBlock::iterator InsertBefore, - const MachineInstr &Orig) const; - - /// This method must be implemented by targets that - /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target - /// may be able to convert a two-address instruction into one or more true - /// three-address instructions on demand. This allows the X86 target (for - /// example) to convert ADD and SHL instructions into LEA instructions if they - /// would require register copies due to two-addressness. - /// - /// This method returns a null pointer if the transformation cannot be - /// performed, otherwise it returns the last new instruction. - /// - /// If \p LIS is not nullptr, the LiveIntervals info should be updated for - /// replacing \p MI with new instructions, even though this function does not - /// remove MI. - virtual MachineInstr *convertToThreeAddress(MachineInstr &MI, - LiveVariables *LV, - LiveIntervals *LIS) const { - return nullptr; - } - - // This constant can be used as an input value of operand index passed to - // the method findCommutedOpIndices() to tell the method that the - // corresponding operand index is not pre-defined and that the method - // can pick any commutable operand. - static const unsigned CommuteAnyOperandIndex = ~0U; - - /// This method commutes the operands of the given machine instruction MI. - /// - /// The operands to be commuted are specified by their indices OpIdx1 and - /// OpIdx2. OpIdx1 and OpIdx2 arguments may be set to a special value - /// 'CommuteAnyOperandIndex', which means that the method is free to choose - /// any arbitrarily chosen commutable operand. If both arguments are set to - /// 'CommuteAnyOperandIndex' then the method looks for 2 different commutable - /// operands; then commutes them if such operands could be found. - /// - /// If NewMI is false, MI is modified in place and returned; otherwise, a - /// new machine instruction is created and returned. - /// - /// Do not call this method for a non-commutable instruction or - /// for non-commuable operands. - /// Even though the instruction is commutable, the method may still - /// fail to commute the operands, null pointer is returned in such cases. - MachineInstr * - commuteInstruction(MachineInstr &MI, bool NewMI = false, - unsigned OpIdx1 = CommuteAnyOperandIndex, - unsigned OpIdx2 = CommuteAnyOperandIndex) const; - - /// Returns true iff the routine could find two commutable operands in the - /// given machine instruction. - /// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. - /// If any of the INPUT values is set to the special value - /// 'CommuteAnyOperandIndex' then the method arbitrarily picks a commutable - /// operand, then returns its index in the corresponding argument. - /// If both of INPUT values are set to 'CommuteAnyOperandIndex' then method - /// looks for 2 commutable operands. - /// If INPUT values refer to some operands of MI, then the method simply - /// returns true if the corresponding operands are commutable and returns - /// false otherwise. - /// - /// For example, calling this method this way: - /// unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex; - /// findCommutedOpIndices(MI, Op1, Op2); - /// can be interpreted as a query asking to find an operand that would be - /// commutable with the operand#1. - virtual bool findCommutedOpIndices(const MachineInstr &MI, - unsigned &SrcOpIdx1, - unsigned &SrcOpIdx2) const; - - /// Returns true if the target has a preference on the operands order of - /// the given machine instruction. And specify if \p Commute is required to - /// get the desired operands order. - virtual bool hasCommutePreference(MachineInstr &MI, bool &Commute) const { - return false; - } - - /// A pair composed of a register and a sub-register index. - /// Used to give some type checking when modeling Reg:SubReg. - struct RegSubRegPair { - Register Reg; - unsigned SubReg; - - RegSubRegPair(Register Reg = Register(), unsigned SubReg = 0) - : Reg(Reg), SubReg(SubReg) {} - - bool operator==(const RegSubRegPair& P) const { - return Reg == P.Reg && SubReg == P.SubReg; - } - bool operator!=(const RegSubRegPair& P) const { - return !(*this == P); - } - }; - - /// A pair composed of a pair of a register and a sub-register index, - /// and another sub-register index. - /// Used to give some type checking when modeling Reg:SubReg1, SubReg2. - struct RegSubRegPairAndIdx : RegSubRegPair { - unsigned SubIdx; - - RegSubRegPairAndIdx(Register Reg = Register(), unsigned SubReg = 0, - unsigned SubIdx = 0) - : RegSubRegPair(Reg, SubReg), SubIdx(SubIdx) {} - }; - - /// Build the equivalent inputs of a REG_SEQUENCE for the given \p MI - /// and \p DefIdx. - /// \p [out] InputRegs of the equivalent REG_SEQUENCE. Each element of - /// the list is modeled as . Operands with the undef - /// flag are not added to this list. - /// E.g., REG_SEQUENCE %1:sub1, sub0, %2, sub1 would produce - /// two elements: - /// - %1:sub1, sub0 - /// - %2<:0>, sub1 - /// - /// \returns true if it is possible to build such an input sequence - /// with the pair \p MI, \p DefIdx. False otherwise. - /// - /// \pre MI.isRegSequence() or MI.isRegSequenceLike(). - /// - /// \note The generic implementation does not provide any support for - /// MI.isRegSequenceLike(). In other words, one has to override - /// getRegSequenceLikeInputs for target specific instructions. - bool - getRegSequenceInputs(const MachineInstr &MI, unsigned DefIdx, - SmallVectorImpl &InputRegs) const; - - /// Build the equivalent inputs of a EXTRACT_SUBREG for the given \p MI - /// and \p DefIdx. - /// \p [out] InputReg of the equivalent EXTRACT_SUBREG. - /// E.g., EXTRACT_SUBREG %1:sub1, sub0, sub1 would produce: - /// - %1:sub1, sub0 - /// - /// \returns true if it is possible to build such an input sequence - /// with the pair \p MI, \p DefIdx and the operand has no undef flag set. - /// False otherwise. - /// - /// \pre MI.isExtractSubreg() or MI.isExtractSubregLike(). - /// - /// \note The generic implementation does not provide any support for - /// MI.isExtractSubregLike(). In other words, one has to override - /// getExtractSubregLikeInputs for target specific instructions. - bool getExtractSubregInputs(const MachineInstr &MI, unsigned DefIdx, - RegSubRegPairAndIdx &InputReg) const; - - /// Build the equivalent inputs of a INSERT_SUBREG for the given \p MI - /// and \p DefIdx. - /// \p [out] BaseReg and \p [out] InsertedReg contain - /// the equivalent inputs of INSERT_SUBREG. - /// E.g., INSERT_SUBREG %0:sub0, %1:sub1, sub3 would produce: - /// - BaseReg: %0:sub0 - /// - InsertedReg: %1:sub1, sub3 - /// - /// \returns true if it is possible to build such an input sequence - /// with the pair \p MI, \p DefIdx and the operand has no undef flag set. - /// False otherwise. - /// - /// \pre MI.isInsertSubreg() or MI.isInsertSubregLike(). - /// - /// \note The generic implementation does not provide any support for - /// MI.isInsertSubregLike(). In other words, one has to override - /// getInsertSubregLikeInputs for target specific instructions. - bool getInsertSubregInputs(const MachineInstr &MI, unsigned DefIdx, - RegSubRegPair &BaseReg, - RegSubRegPairAndIdx &InsertedReg) const; - - /// Return true if two machine instructions would produce identical values. - /// By default, this is only true when the two instructions - /// are deemed identical except for defs. If this function is called when the - /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for - /// aggressive checks. - virtual bool produceSameValue(const MachineInstr &MI0, - const MachineInstr &MI1, - const MachineRegisterInfo *MRI = nullptr) const; - - /// \returns true if a branch from an instruction with opcode \p BranchOpc - /// bytes is capable of jumping to a position \p BrOffset bytes away. - virtual bool isBranchOffsetInRange(unsigned BranchOpc, - int64_t BrOffset) const { - llvm_unreachable("target did not implement"); - } - - /// \returns The block that branch instruction \p MI jumps to. - virtual MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const { - llvm_unreachable("target did not implement"); - } - - /// Insert an unconditional indirect branch at the end of \p MBB to \p - /// NewDestBB. Optionally, insert the clobbered register restoring in \p - /// RestoreBB. \p BrOffset indicates the offset of \p NewDestBB relative to - /// the offset of the position to insert the new branch. - virtual void insertIndirectBranch(MachineBasicBlock &MBB, - MachineBasicBlock &NewDestBB, - MachineBasicBlock &RestoreBB, - const DebugLoc &DL, int64_t BrOffset = 0, - RegScavenger *RS = nullptr) const { - llvm_unreachable("target did not implement"); - } - - /// Analyze the branching code at the end of MBB, returning - /// true if it cannot be understood (e.g. it's a switch dispatch or isn't - /// implemented for a target). Upon success, this returns false and returns - /// with the following information in various cases: - /// - /// 1. If this block ends with no branches (it just falls through to its succ) - /// just return false, leaving TBB/FBB null. - /// 2. If this block ends with only an unconditional branch, it sets TBB to be - /// the destination block. - /// 3. If this block ends with a conditional branch and it falls through to a - /// successor block, it sets TBB to be the branch destination block and a - /// list of operands that evaluate the condition. These operands can be - /// passed to other TargetInstrInfo methods to create new branches. - /// 4. If this block ends with a conditional branch followed by an - /// unconditional branch, it returns the 'true' destination in TBB, the - /// 'false' destination in FBB, and a list of operands that evaluate the - /// condition. These operands can be passed to other TargetInstrInfo - /// methods to create new branches. - /// - /// Note that removeBranch and insertBranch must be implemented to support - /// cases where this method returns success. - /// - /// If AllowModify is true, then this routine is allowed to modify the basic - /// block (e.g. delete instructions after the unconditional branch). - /// - /// The CFG information in MBB.Predecessors and MBB.Successors must be valid - /// before calling this function. - virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl &Cond, - bool AllowModify = false) const { - return true; - } - - /// Represents a predicate at the MachineFunction level. The control flow a - /// MachineBranchPredicate represents is: - /// - /// Reg = LHS `Predicate` RHS == ConditionDef - /// if Reg then goto TrueDest else goto FalseDest - /// - struct MachineBranchPredicate { - enum ComparePredicate { - PRED_EQ, // True if two values are equal - PRED_NE, // True if two values are not equal - PRED_INVALID // Sentinel value - }; - - ComparePredicate Predicate = PRED_INVALID; - MachineOperand LHS = MachineOperand::CreateImm(0); - MachineOperand RHS = MachineOperand::CreateImm(0); - MachineBasicBlock *TrueDest = nullptr; - MachineBasicBlock *FalseDest = nullptr; - MachineInstr *ConditionDef = nullptr; - - /// SingleUseCondition is true if ConditionDef is dead except for the - /// branch(es) at the end of the basic block. - /// - bool SingleUseCondition = false; - - explicit MachineBranchPredicate() = default; - }; - - /// Analyze the branching code at the end of MBB and parse it into the - /// MachineBranchPredicate structure if possible. Returns false on success - /// and true on failure. - /// - /// If AllowModify is true, then this routine is allowed to modify the basic - /// block (e.g. delete instructions after the unconditional branch). - /// - virtual bool analyzeBranchPredicate(MachineBasicBlock &MBB, - MachineBranchPredicate &MBP, - bool AllowModify = false) const { - return true; - } - - /// Remove the branching code at the end of the specific MBB. - /// This is only invoked in cases where analyzeBranch returns success. It - /// returns the number of instructions that were removed. - /// If \p BytesRemoved is non-null, report the change in code size from the - /// removed instructions. - virtual unsigned removeBranch(MachineBasicBlock &MBB, - int *BytesRemoved = nullptr) const { - llvm_unreachable("Target didn't implement TargetInstrInfo::removeBranch!"); - } - - /// Insert branch code into the end of the specified MachineBasicBlock. The - /// operands to this method are the same as those returned by analyzeBranch. - /// This is only invoked in cases where analyzeBranch returns success. It - /// returns the number of instructions inserted. If \p BytesAdded is non-null, - /// report the change in code size from the added instructions. - /// - /// It is also invoked by tail merging to add unconditional branches in - /// cases where analyzeBranch doesn't apply because there was no original - /// branch to analyze. At least this much must be implemented, else tail - /// merging needs to be disabled. - /// - /// The CFG information in MBB.Predecessors and MBB.Successors must be valid - /// before calling this function. - virtual unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - ArrayRef Cond, - const DebugLoc &DL, - int *BytesAdded = nullptr) const { - llvm_unreachable("Target didn't implement TargetInstrInfo::insertBranch!"); - } - - unsigned insertUnconditionalBranch(MachineBasicBlock &MBB, - MachineBasicBlock *DestBB, - const DebugLoc &DL, - int *BytesAdded = nullptr) const { - return insertBranch(MBB, DestBB, nullptr, ArrayRef(), DL, - BytesAdded); - } - - /// Object returned by analyzeLoopForPipelining. Allows software pipelining - /// implementations to query attributes of the loop being pipelined and to - /// apply target-specific updates to the loop once pipelining is complete. - class PipelinerLoopInfo { - public: - virtual ~PipelinerLoopInfo(); - /// Return true if the given instruction should not be pipelined and should - /// be ignored. An example could be a loop comparison, or induction variable - /// update with no users being pipelined. - virtual bool shouldIgnoreForPipelining(const MachineInstr *MI) const = 0; - - /// Create a condition to determine if the trip count of the loop is greater - /// than TC. - /// - /// If the trip count is statically known to be greater than TC, return - /// true. If the trip count is statically known to be not greater than TC, - /// return false. Otherwise return nullopt and fill out Cond with the test - /// condition. - virtual Optional - createTripCountGreaterCondition(int TC, MachineBasicBlock &MBB, - SmallVectorImpl &Cond) = 0; - - /// Modify the loop such that the trip count is - /// OriginalTC + TripCountAdjust. - virtual void adjustTripCount(int TripCountAdjust) = 0; - - /// Called when the loop's preheader has been modified to NewPreheader. - virtual void setPreheader(MachineBasicBlock *NewPreheader) = 0; - - /// Called when the loop is being removed. Any instructions in the preheader - /// should be removed. - /// - /// Once this function is called, no other functions on this object are - /// valid; the loop has been removed. - virtual void disposed() = 0; - }; - - /// Analyze loop L, which must be a single-basic-block loop, and if the - /// conditions can be understood enough produce a PipelinerLoopInfo object. - virtual std::unique_ptr - analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const { - return nullptr; - } - - /// Analyze the loop code, return true if it cannot be understood. Upon - /// success, this function returns false and returns information about the - /// induction variable and compare instruction used at the end. - virtual bool analyzeLoop(MachineLoop &L, MachineInstr *&IndVarInst, - MachineInstr *&CmpInst) const { - return true; - } - - /// Generate code to reduce the loop iteration by one and check if the loop - /// is finished. Return the value/register of the new loop count. We need - /// this function when peeling off one or more iterations of a loop. This - /// function assumes the nth iteration is peeled first. - virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, - MachineBasicBlock &PreHeader, - MachineInstr *IndVar, MachineInstr &Cmp, - SmallVectorImpl &Cond, - SmallVectorImpl &PrevInsts, - unsigned Iter, unsigned MaxIter) const { - llvm_unreachable("Target didn't implement ReduceLoopCount"); - } - - /// Delete the instruction OldInst and everything after it, replacing it with - /// an unconditional branch to NewDest. This is used by the tail merging pass. - virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, - MachineBasicBlock *NewDest) const; - - /// Return true if it's legal to split the given basic - /// block at the specified instruction (i.e. instruction would be the start - /// of a new basic block). - virtual bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI) const { - return true; - } - - /// Return true if it's profitable to predicate - /// instructions with accumulated instruction latency of "NumCycles" - /// of the specified basic block, where the probability of the instructions - /// being executed is given by Probability, and Confidence is a measure - /// of our confidence that it will be properly predicted. - virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, - unsigned ExtraPredCycles, - BranchProbability Probability) const { - return false; - } - - /// Second variant of isProfitableToIfCvt. This one - /// checks for the case where two basic blocks from true and false path - /// of a if-then-else (diamond) are predicated on mutually exclusive - /// predicates, where the probability of the true path being taken is given - /// by Probability, and Confidence is a measure of our confidence that it - /// will be properly predicted. - virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumTCycles, - unsigned ExtraTCycles, - MachineBasicBlock &FMBB, unsigned NumFCycles, - unsigned ExtraFCycles, - BranchProbability Probability) const { - return false; - } - - /// Return true if it's profitable for if-converter to duplicate instructions - /// of specified accumulated instruction latencies in the specified MBB to - /// enable if-conversion. - /// The probability of the instructions being executed is given by - /// Probability, and Confidence is a measure of our confidence that it - /// will be properly predicted. - virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, - unsigned NumCycles, - BranchProbability Probability) const { - return false; - } - - /// Return the increase in code size needed to predicate a contiguous run of - /// NumInsts instructions. - virtual unsigned extraSizeToPredicateInstructions(const MachineFunction &MF, - unsigned NumInsts) const { - return 0; - } - - /// Return an estimate for the code size reduction (in bytes) which will be - /// caused by removing the given branch instruction during if-conversion. - virtual unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const { - return getInstSizeInBytes(MI); - } - - /// Return true if it's profitable to unpredicate - /// one side of a 'diamond', i.e. two sides of if-else predicated on mutually - /// exclusive predicates. - /// e.g. - /// subeq r0, r1, #1 - /// addne r0, r1, #1 - /// => - /// sub r0, r1, #1 - /// addne r0, r1, #1 - /// - /// This may be profitable is conditional instructions are always executed. - virtual bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, - MachineBasicBlock &FMBB) const { - return false; - } - - /// Return true if it is possible to insert a select - /// instruction that chooses between TrueReg and FalseReg based on the - /// condition code in Cond. - /// - /// When successful, also return the latency in cycles from TrueReg, - /// FalseReg, and Cond to the destination register. In most cases, a select - /// instruction will be 1 cycle, so CondCycles = TrueCycles = FalseCycles = 1 - /// - /// Some x86 implementations have 2-cycle cmov instructions. - /// - /// @param MBB Block where select instruction would be inserted. - /// @param Cond Condition returned by analyzeBranch. - /// @param DstReg Virtual dest register that the result should write to. - /// @param TrueReg Virtual register to select when Cond is true. - /// @param FalseReg Virtual register to select when Cond is false. - /// @param CondCycles Latency from Cond+Branch to select output. - /// @param TrueCycles Latency from TrueReg to select output. - /// @param FalseCycles Latency from FalseReg to select output. - virtual bool canInsertSelect(const MachineBasicBlock &MBB, - ArrayRef Cond, Register DstReg, - Register TrueReg, Register FalseReg, - int &CondCycles, int &TrueCycles, - int &FalseCycles) const { - return false; - } - - /// Insert a select instruction into MBB before I that will copy TrueReg to - /// DstReg when Cond is true, and FalseReg to DstReg when Cond is false. - /// - /// This function can only be called after canInsertSelect() returned true. - /// The condition in Cond comes from analyzeBranch, and it can be assumed - /// that the same flags or registers required by Cond are available at the - /// insertion point. - /// - /// @param MBB Block where select instruction should be inserted. - /// @param I Insertion point. - /// @param DL Source location for debugging. - /// @param DstReg Virtual register to be defined by select instruction. - /// @param Cond Condition as computed by analyzeBranch. - /// @param TrueReg Virtual register to copy when Cond is true. - /// @param FalseReg Virtual register to copy when Cons is false. - virtual void insertSelect(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, const DebugLoc &DL, - Register DstReg, ArrayRef Cond, - Register TrueReg, Register FalseReg) const { - llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!"); - } - - /// Analyze the given select instruction, returning true if - /// it cannot be understood. It is assumed that MI->isSelect() is true. - /// - /// When successful, return the controlling condition and the operands that - /// determine the true and false result values. - /// - /// Result = SELECT Cond, TrueOp, FalseOp - /// - /// Some targets can optimize select instructions, for example by predicating - /// the instruction defining one of the operands. Such targets should set - /// Optimizable. - /// - /// @param MI Select instruction to analyze. - /// @param Cond Condition controlling the select. - /// @param TrueOp Operand number of the value selected when Cond is true. - /// @param FalseOp Operand number of the value selected when Cond is false. - /// @param Optimizable Returned as true if MI is optimizable. - /// @returns False on success. - virtual bool analyzeSelect(const MachineInstr &MI, - SmallVectorImpl &Cond, - unsigned &TrueOp, unsigned &FalseOp, - bool &Optimizable) const { - assert(MI.getDesc().isSelect() && "MI must be a select instruction"); - return true; - } - - /// Given a select instruction that was understood by - /// analyzeSelect and returned Optimizable = true, attempt to optimize MI by - /// merging it with one of its operands. Returns NULL on failure. - /// - /// When successful, returns the new select instruction. The client is - /// responsible for deleting MI. - /// - /// If both sides of the select can be optimized, PreferFalse is used to pick - /// a side. - /// - /// @param MI Optimizable select instruction. - /// @param NewMIs Set that record all MIs in the basic block up to \p - /// MI. Has to be updated with any newly created MI or deleted ones. - /// @param PreferFalse Try to optimize FalseOp instead of TrueOp. - /// @returns Optimized instruction or NULL. - virtual MachineInstr *optimizeSelect(MachineInstr &MI, - SmallPtrSetImpl &NewMIs, - bool PreferFalse = false) const { - // This function must be implemented if Optimizable is ever set. - llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!"); - } - - /// Emit instructions to copy a pair of physical registers. - /// - /// This function should support copies within any legal register class as - /// well as any cross-class copies created during instruction selection. - /// - /// The source and destination registers may overlap, which may require a - /// careful implementation when multiple copy instructions are required for - /// large registers. See for example the ARM target. - virtual void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, const DebugLoc &DL, - MCRegister DestReg, MCRegister SrcReg, - bool KillSrc) const { - llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); - } - - /// Allow targets to tell MachineVerifier whether a specific register - /// MachineOperand can be used as part of PC-relative addressing. - /// PC-relative addressing modes in many CISC architectures contain - /// (non-PC) registers as offsets or scaling values, which inherently - /// tags the corresponding MachineOperand with OPERAND_PCREL. - /// - /// @param MO The MachineOperand in question. MO.isReg() should always - /// be true. - /// @return Whether this operand is allowed to be used PC-relatively. - virtual bool isPCRelRegisterOperandLegal(const MachineOperand &MO) const { - return false; - } - -protected: - /// Target-dependent implementation for IsCopyInstr. - /// If the specific machine instruction is an instruction that moves/copies - /// value from one register to another register return destination and source - /// registers as machine operands. - virtual Optional - isCopyInstrImpl(const MachineInstr &MI) const { - return None; - } - - /// Return true if the given terminator MI is not expected to spill. This - /// sets the live interval as not spillable and adjusts phi node lowering to - /// not introduce copies after the terminator. Use with care, these are - /// currently used for hardware loop intrinsics in very controlled situations, - /// created prior to registry allocation in loops that only have single phi - /// users for the terminators value. They may run out of registers if not used - /// carefully. - virtual bool isUnspillableTerminatorImpl(const MachineInstr *MI) const { - return false; - } - -public: - /// If the specific machine instruction is an instruction that moves/copies - /// value from one register to another register return destination and source - /// registers as machine operands. - /// For COPY-instruction the method naturally returns destination and source - /// registers as machine operands, for all other instructions the method calls - /// target-dependent implementation. - Optional isCopyInstr(const MachineInstr &MI) const { - if (MI.isCopy()) { - return DestSourcePair{MI.getOperand(0), MI.getOperand(1)}; - } - return isCopyInstrImpl(MI); - } - - /// If the specific machine instruction is an instruction that adds an - /// immediate value and a physical register, and stores the result in - /// the given physical register \c Reg, return a pair of the source - /// register and the offset which has been added. - virtual Optional isAddImmediate(const MachineInstr &MI, - Register Reg) const { - return None; - } - - /// Returns true if MI is an instruction that defines Reg to have a constant - /// value and the value is recorded in ImmVal. The ImmVal is a result that - /// should be interpreted as modulo size of Reg. - virtual bool getConstValDefinedInReg(const MachineInstr &MI, - const Register Reg, - int64_t &ImmVal) const { - return false; - } - - /// Store the specified register of the given register class to the specified - /// stack frame index. The store instruction is to be added to the given - /// machine basic block before the specified machine instruction. If isKill - /// is true, the register operand is the last use and must be marked kill. - virtual void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - Register SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - llvm_unreachable("Target didn't implement " - "TargetInstrInfo::storeRegToStackSlot!"); - } - - /// Load the specified register of the given register class from the specified - /// stack frame index. The load instruction is to be added to the given - /// machine basic block before the specified machine instruction. - virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - Register DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - llvm_unreachable("Target didn't implement " - "TargetInstrInfo::loadRegFromStackSlot!"); - } - - /// This function is called for all pseudo instructions - /// that remain after register allocation. Many pseudo instructions are - /// created to help register allocation. This is the place to convert them - /// into real instructions. The target can edit MI in place, or it can insert - /// new instructions and erase MI. The function should return true if - /// anything was changed. - virtual bool expandPostRAPseudo(MachineInstr &MI) const { return false; } - - /// Check whether the target can fold a load that feeds a subreg operand - /// (or a subreg operand that feeds a store). - /// For example, X86 may want to return true if it can fold - /// movl (%esp), %eax - /// subb, %al, ... - /// Into: - /// subb (%esp), ... - /// - /// Ideally, we'd like the target implementation of foldMemoryOperand() to - /// reject subregs - but since this behavior used to be enforced in the - /// target-independent code, moving this responsibility to the targets - /// has the potential of causing nasty silent breakage in out-of-tree targets. - virtual bool isSubregFoldable() const { return false; } - - /// For a patchpoint, stackmap, or statepoint intrinsic, return the range of - /// operands which can't be folded into stack references. Operands outside - /// of the range are most likely foldable but it is not guaranteed. - /// These instructions are unique in that stack references for some operands - /// have the same execution cost (e.g. none) as the unfolded register forms. - /// The ranged return is guaranteed to include all operands which can't be - /// folded at zero cost. - virtual std::pair - getPatchpointUnfoldableRange(const MachineInstr &MI) const; - - /// Attempt to fold a load or store of the specified stack - /// slot into the specified machine instruction for the specified operand(s). - /// If this is possible, a new instruction is returned with the specified - /// operand folded, otherwise NULL is returned. - /// The new instruction is inserted before MI, and the client is responsible - /// for removing the old instruction. - /// If VRM is passed, the assigned physregs can be inspected by target to - /// decide on using an opcode (note that those assignments can still change). - MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef Ops, - int FI, - LiveIntervals *LIS = nullptr, - VirtRegMap *VRM = nullptr) const; - - /// Same as the previous version except it allows folding of any load and - /// store from / to any address, not just from a specific stack slot. - MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef Ops, - MachineInstr &LoadMI, - LiveIntervals *LIS = nullptr) const; - - /// Return true when there is potentially a faster code sequence - /// for an instruction chain ending in \p Root. All potential patterns are - /// returned in the \p Pattern vector. Pattern should be sorted in priority - /// order since the pattern evaluator stops checking as soon as it finds a - /// faster sequence. - /// \param Root - Instruction that could be combined with one of its operands - /// \param Patterns - Vector of possible combination patterns - virtual bool - getMachineCombinerPatterns(MachineInstr &Root, - SmallVectorImpl &Patterns, - bool DoRegPressureReduce) const; - - /// Return true if target supports reassociation of instructions in machine - /// combiner pass to reduce register pressure for a given BB. - virtual bool - shouldReduceRegisterPressure(MachineBasicBlock *MBB, - RegisterClassInfo *RegClassInfo) const { - return false; - } - - /// Fix up the placeholder we may add in genAlternativeCodeSequence(). - virtual void - finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P, - SmallVectorImpl &InsInstrs) const {} - - /// Return true when a code sequence can improve throughput. It - /// should be called only for instructions in loops. - /// \param Pattern - combiner pattern - virtual bool isThroughputPattern(MachineCombinerPattern Pattern) const; - - /// Return true if the input \P Inst is part of a chain of dependent ops - /// that are suitable for reassociation, otherwise return false. - /// If the instruction's operands must be commuted to have a previous - /// instruction of the same type define the first source operand, \P Commuted - /// will be set to true. - bool isReassociationCandidate(const MachineInstr &Inst, bool &Commuted) const; - - /// Return true when \P Inst is both associative and commutative. - virtual bool isAssociativeAndCommutative(const MachineInstr &Inst) const { - return false; - } - - /// Return true when \P Inst has reassociable operands in the same \P MBB. - virtual bool hasReassociableOperands(const MachineInstr &Inst, - const MachineBasicBlock *MBB) const; - - /// Return true when \P Inst has reassociable sibling. - bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const; - - /// When getMachineCombinerPatterns() finds patterns, this function generates - /// the instructions that could replace the original code sequence. The client - /// has to decide whether the actual replacement is beneficial or not. - /// \param Root - Instruction that could be combined with one of its operands - /// \param Pattern - Combination pattern for Root - /// \param InsInstrs - Vector of new instructions that implement P - /// \param DelInstrs - Old instructions, including Root, that could be - /// replaced by InsInstr - /// \param InstIdxForVirtReg - map of virtual register to instruction in - /// InsInstr that defines it - virtual void genAlternativeCodeSequence( - MachineInstr &Root, MachineCombinerPattern Pattern, - SmallVectorImpl &InsInstrs, - SmallVectorImpl &DelInstrs, - DenseMap &InstIdxForVirtReg) const; - - /// Attempt to reassociate \P Root and \P Prev according to \P Pattern to - /// reduce critical path length. - void reassociateOps(MachineInstr &Root, MachineInstr &Prev, - MachineCombinerPattern Pattern, - SmallVectorImpl &InsInstrs, - SmallVectorImpl &DelInstrs, - DenseMap &InstrIdxForVirtReg) const; - - /// The limit on resource length extension we accept in MachineCombiner Pass. - virtual int getExtendResourceLenLimit() const { return 0; } - - /// This is an architecture-specific helper function of reassociateOps. - /// Set special operand attributes for new instructions after reassociation. - virtual void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2, - MachineInstr &NewMI1, - MachineInstr &NewMI2) const {} - - /// Return true when a target supports MachineCombiner. - virtual bool useMachineCombiner() const { return false; } - - /// Return true if the given SDNode can be copied during scheduling - /// even if it has glue. - virtual bool canCopyGluedNodeDuringSchedule(SDNode *N) const { return false; } - -protected: - /// Target-dependent implementation for foldMemoryOperand. - /// Target-independent code in foldMemoryOperand will - /// take care of adding a MachineMemOperand to the newly created instruction. - /// The instruction and any auxiliary instructions necessary will be inserted - /// at InsertPt. - virtual MachineInstr * - foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, - ArrayRef Ops, - MachineBasicBlock::iterator InsertPt, int FrameIndex, - LiveIntervals *LIS = nullptr, - VirtRegMap *VRM = nullptr) const { - return nullptr; - } - - /// Target-dependent implementation for foldMemoryOperand. - /// Target-independent code in foldMemoryOperand will - /// take care of adding a MachineMemOperand to the newly created instruction. - /// The instruction and any auxiliary instructions necessary will be inserted - /// at InsertPt. - virtual MachineInstr *foldMemoryOperandImpl( - MachineFunction &MF, MachineInstr &MI, ArrayRef Ops, - MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, - LiveIntervals *LIS = nullptr) const { - return nullptr; - } - - /// Target-dependent implementation of getRegSequenceInputs. - /// - /// \returns true if it is possible to build the equivalent - /// REG_SEQUENCE inputs with the pair \p MI, \p DefIdx. False otherwise. - /// - /// \pre MI.isRegSequenceLike(). - /// - /// \see TargetInstrInfo::getRegSequenceInputs. - virtual bool getRegSequenceLikeInputs( - const MachineInstr &MI, unsigned DefIdx, - SmallVectorImpl &InputRegs) const { - return false; - } - - /// Target-dependent implementation of getExtractSubregInputs. - /// - /// \returns true if it is possible to build the equivalent - /// EXTRACT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. - /// - /// \pre MI.isExtractSubregLike(). - /// - /// \see TargetInstrInfo::getExtractSubregInputs. - virtual bool getExtractSubregLikeInputs(const MachineInstr &MI, - unsigned DefIdx, - RegSubRegPairAndIdx &InputReg) const { - return false; - } - - /// Target-dependent implementation of getInsertSubregInputs. - /// - /// \returns true if it is possible to build the equivalent - /// INSERT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. - /// - /// \pre MI.isInsertSubregLike(). - /// - /// \see TargetInstrInfo::getInsertSubregInputs. - virtual bool - getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, - RegSubRegPair &BaseReg, - RegSubRegPairAndIdx &InsertedReg) const { - return false; - } - -public: - /// getAddressSpaceForPseudoSourceKind - Given the kind of memory - /// (e.g. stack) the target returns the corresponding address space. - virtual unsigned - getAddressSpaceForPseudoSourceKind(unsigned Kind) const { - return 0; - } - - /// unfoldMemoryOperand - Separate a single instruction which folded a load or - /// a store or a load and a store into two or more instruction. If this is - /// possible, returns true as well as the new instructions by reference. - virtual bool - unfoldMemoryOperand(MachineFunction &MF, MachineInstr &MI, unsigned Reg, - bool UnfoldLoad, bool UnfoldStore, - SmallVectorImpl &NewMIs) const { - return false; - } - - virtual bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, - SmallVectorImpl &NewNodes) const { - return false; - } - - /// Returns the opcode of the would be new - /// instruction after load / store are unfolded from an instruction of the - /// specified opcode. It returns zero if the specified unfolding is not - /// possible. If LoadRegIndex is non-null, it is filled in with the operand - /// index of the operand which will hold the register holding the loaded - /// value. - virtual unsigned - getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore, - unsigned *LoadRegIndex = nullptr) const { - return 0; - } - - /// This is used by the pre-regalloc scheduler to determine if two loads are - /// loading from the same base address. It should only return true if the base - /// pointers are the same and the only differences between the two addresses - /// are the offset. It also returns the offsets by reference. - virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, - int64_t &Offset1, - int64_t &Offset2) const { - return false; - } - - /// This is a used by the pre-regalloc scheduler to determine (in conjunction - /// with areLoadsFromSameBasePtr) if two loads should be scheduled together. - /// On some targets if two loads are loading from - /// addresses in the same cache line, it's better if they are scheduled - /// together. This function takes two integers that represent the load offsets - /// from the common base address. It returns true if it decides it's desirable - /// to schedule the two loads together. "NumLoads" is the number of loads that - /// have already been scheduled after Load1. - virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, - int64_t Offset1, int64_t Offset2, - unsigned NumLoads) const { - return false; - } - - /// Get the base operand and byte offset of an instruction that reads/writes - /// memory. This is a convenience function for callers that are only prepared - /// to handle a single base operand. - bool getMemOperandWithOffset(const MachineInstr &MI, - const MachineOperand *&BaseOp, int64_t &Offset, - bool &OffsetIsScalable, - const TargetRegisterInfo *TRI) const; - - /// Get zero or more base operands and the byte offset of an instruction that - /// reads/writes memory. Note that there may be zero base operands if the - /// instruction accesses a constant address. - /// It returns false if MI does not read/write memory. - /// It returns false if base operands and offset could not be determined. - /// It is not guaranteed to always recognize base operands and offsets in all - /// cases. - virtual bool getMemOperandsWithOffsetWidth( - const MachineInstr &MI, SmallVectorImpl &BaseOps, - int64_t &Offset, bool &OffsetIsScalable, unsigned &Width, - const TargetRegisterInfo *TRI) const { - return false; - } - - /// Return true if the instruction contains a base register and offset. If - /// true, the function also sets the operand position in the instruction - /// for the base register and offset. - virtual bool getBaseAndOffsetPosition(const MachineInstr &MI, - unsigned &BasePos, - unsigned &OffsetPos) const { - return false; - } - - /// Target dependent implementation to get the values constituting the address - /// MachineInstr that is accessing memory. These values are returned as a - /// struct ExtAddrMode which contains all relevant information to make up the - /// address. - virtual Optional - getAddrModeFromMemoryOp(const MachineInstr &MemI, - const TargetRegisterInfo *TRI) const { - return None; - } - - /// Returns true if MI's Def is NullValueReg, and the MI - /// does not change the Zero value. i.e. cases such as rax = shr rax, X where - /// NullValueReg = rax. Note that if the NullValueReg is non-zero, this - /// function can return true even if becomes zero. Specifically cases such as - /// NullValueReg = shl NullValueReg, 63. - virtual bool preservesZeroValueInReg(const MachineInstr *MI, - const Register NullValueReg, - const TargetRegisterInfo *TRI) const { - return false; - } - - /// If the instruction is an increment of a constant value, return the amount. - virtual bool getIncrementValue(const MachineInstr &MI, int &Value) const { - return false; - } - - /// Returns true if the two given memory operations should be scheduled - /// adjacent. Note that you have to add: - /// DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI)); - /// or - /// DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); - /// to TargetPassConfig::createMachineScheduler() to have an effect. - /// - /// \p BaseOps1 and \p BaseOps2 are memory operands of two memory operations. - /// \p NumLoads is the number of loads that will be in the cluster if this - /// hook returns true. - /// \p NumBytes is the number of bytes that will be loaded from all the - /// clustered loads if this hook returns true. - virtual bool shouldClusterMemOps(ArrayRef BaseOps1, - ArrayRef BaseOps2, - unsigned NumLoads, unsigned NumBytes) const { - llvm_unreachable("target did not implement shouldClusterMemOps()"); - } - - /// Reverses the branch condition of the specified condition list, - /// returning false on success and true if it cannot be reversed. - virtual bool - reverseBranchCondition(SmallVectorImpl &Cond) const { - return true; - } - - /// Insert a noop into the instruction stream at the specified point. - virtual void insertNoop(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const; - - /// Insert noops into the instruction stream at the specified point. - virtual void insertNoops(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned Quantity) const; - - /// Return the noop instruction to use for a noop. - virtual MCInst getNop() const; - - /// Return true for post-incremented instructions. - virtual bool isPostIncrement(const MachineInstr &MI) const { return false; } - - /// Returns true if the instruction is already predicated. - virtual bool isPredicated(const MachineInstr &MI) const { return false; } - - // Returns a MIRPrinter comment for this machine operand. - virtual std::string - createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, - unsigned OpIdx, const TargetRegisterInfo *TRI) const; - - /// Returns true if the instruction is a - /// terminator instruction that has not been predicated. - bool isUnpredicatedTerminator(const MachineInstr &MI) const; - - /// Returns true if MI is an unconditional tail call. - virtual bool isUnconditionalTailCall(const MachineInstr &MI) const { - return false; - } - - /// Returns true if the tail call can be made conditional on BranchCond. - virtual bool canMakeTailCallConditional(SmallVectorImpl &Cond, - const MachineInstr &TailCall) const { - return false; - } - - /// Replace the conditional branch in MBB with a conditional tail call. - virtual void replaceBranchWithTailCall(MachineBasicBlock &MBB, - SmallVectorImpl &Cond, - const MachineInstr &TailCall) const { - llvm_unreachable("Target didn't implement replaceBranchWithTailCall!"); - } - - /// Convert the instruction into a predicated instruction. - /// It returns true if the operation was successful. - virtual bool PredicateInstruction(MachineInstr &MI, - ArrayRef Pred) const; - - /// Returns true if the first specified predicate - /// subsumes the second, e.g. GE subsumes GT. - virtual bool SubsumesPredicate(ArrayRef Pred1, - ArrayRef Pred2) const { - return false; - } - - /// If the specified instruction defines any predicate - /// or condition code register(s) used for predication, returns true as well - /// as the definition predicate(s) by reference. - /// SkipDead should be set to false at any point that dead - /// predicate instructions should be considered as being defined. - /// A dead predicate instruction is one that is guaranteed to be removed - /// after a call to PredicateInstruction. - virtual bool ClobbersPredicate(MachineInstr &MI, - std::vector &Pred, - bool SkipDead) const { - return false; - } - - /// Return true if the specified instruction can be predicated. - /// By default, this returns true for every instruction with a - /// PredicateOperand. - virtual bool isPredicable(const MachineInstr &MI) const { - return MI.getDesc().isPredicable(); - } - - /// Return true if it's safe to move a machine - /// instruction that defines the specified register class. - virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { - return true; - } - - /// Test if the given instruction should be considered a scheduling boundary. - /// This primarily includes labels and terminators. - virtual bool isSchedulingBoundary(const MachineInstr &MI, - const MachineBasicBlock *MBB, - const MachineFunction &MF) const; - - /// Measure the specified inline asm to determine an approximation of its - /// length. - virtual unsigned getInlineAsmLength( - const char *Str, const MCAsmInfo &MAI, - const TargetSubtargetInfo *STI = nullptr) const; - - /// Allocate and return a hazard recognizer to use for this target when - /// scheduling the machine instructions before register allocation. - virtual ScheduleHazardRecognizer * - CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, - const ScheduleDAG *DAG) const; - - /// Allocate and return a hazard recognizer to use for this target when - /// scheduling the machine instructions before register allocation. - virtual ScheduleHazardRecognizer * - CreateTargetMIHazardRecognizer(const InstrItineraryData *, - const ScheduleDAGMI *DAG) const; - - /// Allocate and return a hazard recognizer to use for this target when - /// scheduling the machine instructions after register allocation. - virtual ScheduleHazardRecognizer * - CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, - const ScheduleDAG *DAG) const; - - /// Allocate and return a hazard recognizer to use for by non-scheduling - /// passes. - virtual ScheduleHazardRecognizer * - CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const { - return nullptr; - } - - /// Provide a global flag for disabling the PreRA hazard recognizer that - /// targets may choose to honor. - bool usePreRAHazardRecognizer() const; - - /// For a comparison instruction, return the source registers - /// in SrcReg and SrcReg2 if having two register operands, and the value it - /// compares against in CmpValue. Return true if the comparison instruction - /// can be analyzed. - virtual bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, - Register &SrcReg2, int64_t &Mask, - int64_t &Value) const { - return false; - } - - /// See if the comparison instruction can be converted - /// into something more efficient. E.g., on ARM most instructions can set the - /// flags register, obviating the need for a separate CMP. - virtual bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, - Register SrcReg2, int64_t Mask, - int64_t Value, - const MachineRegisterInfo *MRI) const { - return false; - } - virtual bool optimizeCondBranch(MachineInstr &MI) const { return false; } - - /// Try to remove the load by folding it to a register operand at the use. - /// We fold the load instructions if and only if the - /// def and use are in the same BB. We only look at one load and see - /// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register - /// defined by the load we are trying to fold. DefMI returns the machine - /// instruction that defines FoldAsLoadDefReg, and the function returns - /// the machine instruction generated due to folding. - virtual MachineInstr *optimizeLoadInstr(MachineInstr &MI, - const MachineRegisterInfo *MRI, - Register &FoldAsLoadDefReg, - MachineInstr *&DefMI) const { - return nullptr; - } - - /// 'Reg' is known to be defined by a move immediate instruction, - /// try to fold the immediate into the use instruction. - /// If MRI->hasOneNonDBGUse(Reg) is true, and this function returns true, - /// then the caller may assume that DefMI has been erased from its parent - /// block. The caller may assume that it will not be erased by this - /// function otherwise. - virtual bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, - Register Reg, MachineRegisterInfo *MRI) const { - return false; - } - - /// Return the number of u-operations the given machine - /// instruction will be decoded to on the target cpu. The itinerary's - /// IssueWidth is the number of microops that can be dispatched each - /// cycle. An instruction with zero microops takes no dispatch resources. - virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, - const MachineInstr &MI) const; - - /// Return true for pseudo instructions that don't consume any - /// machine resources in their current form. These are common cases that the - /// scheduler should consider free, rather than conservatively handling them - /// as instructions with no itinerary. - bool isZeroCost(unsigned Opcode) const { - return Opcode <= TargetOpcode::COPY; - } - - virtual int getOperandLatency(const InstrItineraryData *ItinData, - SDNode *DefNode, unsigned DefIdx, - SDNode *UseNode, unsigned UseIdx) const; - - /// Compute and return the use operand latency of a given pair of def and use. - /// In most cases, the static scheduling itinerary was enough to determine the - /// operand latency. But it may not be possible for instructions with variable - /// number of defs / uses. - /// - /// This is a raw interface to the itinerary that may be directly overridden - /// by a target. Use computeOperandLatency to get the best estimate of - /// latency. - virtual int getOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr &DefMI, unsigned DefIdx, - const MachineInstr &UseMI, - unsigned UseIdx) const; - - /// Compute the instruction latency of a given instruction. - /// If the instruction has higher cost when predicated, it's returned via - /// PredCost. - virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, - const MachineInstr &MI, - unsigned *PredCost = nullptr) const; - - virtual unsigned getPredicationCost(const MachineInstr &MI) const; - - virtual int getInstrLatency(const InstrItineraryData *ItinData, - SDNode *Node) const; - - /// Return the default expected latency for a def based on its opcode. - unsigned defaultDefLatency(const MCSchedModel &SchedModel, - const MachineInstr &DefMI) const; - - /// Return true if this opcode has high latency to its result. - virtual bool isHighLatencyDef(int opc) const { return false; } - - /// Compute operand latency between a def of 'Reg' - /// and a use in the current loop. Return true if the target considered - /// it 'high'. This is used by optimization passes such as machine LICM to - /// determine whether it makes sense to hoist an instruction out even in a - /// high register pressure situation. - virtual bool hasHighOperandLatency(const TargetSchedModel &SchedModel, - const MachineRegisterInfo *MRI, - const MachineInstr &DefMI, unsigned DefIdx, - const MachineInstr &UseMI, - unsigned UseIdx) const { - return false; - } - - /// Compute operand latency of a def of 'Reg'. Return true - /// if the target considered it 'low'. - virtual bool hasLowDefLatency(const TargetSchedModel &SchedModel, - const MachineInstr &DefMI, - unsigned DefIdx) const; - - /// Perform target-specific instruction verification. - virtual bool verifyInstruction(const MachineInstr &MI, - StringRef &ErrInfo) const { - return true; - } - - /// Return the current execution domain and bit mask of - /// possible domains for instruction. - /// - /// Some micro-architectures have multiple execution domains, and multiple - /// opcodes that perform the same operation in different domains. For - /// example, the x86 architecture provides the por, orps, and orpd - /// instructions that all do the same thing. There is a latency penalty if a - /// register is written in one domain and read in another. - /// - /// This function returns a pair (domain, mask) containing the execution - /// domain of MI, and a bit mask of possible domains. The setExecutionDomain - /// function can be used to change the opcode to one of the domains in the - /// bit mask. Instructions whose execution domain can't be changed should - /// return a 0 mask. - /// - /// The execution domain numbers don't have any special meaning except domain - /// 0 is used for instructions that are not associated with any interesting - /// execution domain. - /// - virtual std::pair - getExecutionDomain(const MachineInstr &MI) const { - return std::make_pair(0, 0); - } - - /// Change the opcode of MI to execute in Domain. - /// - /// The bit (1 << Domain) must be set in the mask returned from - /// getExecutionDomain(MI). - virtual void setExecutionDomain(MachineInstr &MI, unsigned Domain) const {} - - /// Returns the preferred minimum clearance - /// before an instruction with an unwanted partial register update. - /// - /// Some instructions only write part of a register, and implicitly need to - /// read the other parts of the register. This may cause unwanted stalls - /// preventing otherwise unrelated instructions from executing in parallel in - /// an out-of-order CPU. - /// - /// For example, the x86 instruction cvtsi2ss writes its result to bits - /// [31:0] of the destination xmm register. Bits [127:32] are unaffected, so - /// the instruction needs to wait for the old value of the register to become - /// available: - /// - /// addps %xmm1, %xmm0 - /// movaps %xmm0, (%rax) - /// cvtsi2ss %rbx, %xmm0 - /// - /// In the code above, the cvtsi2ss instruction needs to wait for the addps - /// instruction before it can issue, even though the high bits of %xmm0 - /// probably aren't needed. - /// - /// This hook returns the preferred clearance before MI, measured in - /// instructions. Other defs of MI's operand OpNum are avoided in the last N - /// instructions before MI. It should only return a positive value for - /// unwanted dependencies. If the old bits of the defined register have - /// useful values, or if MI is determined to otherwise read the dependency, - /// the hook should return 0. - /// - /// The unwanted dependency may be handled by: - /// - /// 1. Allocating the same register for an MI def and use. That makes the - /// unwanted dependency identical to a required dependency. - /// - /// 2. Allocating a register for the def that has no defs in the previous N - /// instructions. - /// - /// 3. Calling breakPartialRegDependency() with the same arguments. This - /// allows the target to insert a dependency breaking instruction. - /// - virtual unsigned - getPartialRegUpdateClearance(const MachineInstr &MI, unsigned OpNum, - const TargetRegisterInfo *TRI) const { - // The default implementation returns 0 for no partial register dependency. - return 0; - } - - /// Return the minimum clearance before an instruction that reads an - /// unused register. - /// - /// For example, AVX instructions may copy part of a register operand into - /// the unused high bits of the destination register. - /// - /// vcvtsi2sdq %rax, undef %xmm0, %xmm14 - /// - /// In the code above, vcvtsi2sdq copies %xmm0[127:64] into %xmm14 creating a - /// false dependence on any previous write to %xmm0. - /// - /// This hook works similarly to getPartialRegUpdateClearance, except that it - /// does not take an operand index. Instead sets \p OpNum to the index of the - /// unused register. - virtual unsigned getUndefRegClearance(const MachineInstr &MI, unsigned OpNum, - const TargetRegisterInfo *TRI) const { - // The default implementation returns 0 for no undef register dependency. - return 0; - } - - /// Insert a dependency-breaking instruction - /// before MI to eliminate an unwanted dependency on OpNum. - /// - /// If it wasn't possible to avoid a def in the last N instructions before MI - /// (see getPartialRegUpdateClearance), this hook will be called to break the - /// unwanted dependency. - /// - /// On x86, an xorps instruction can be used as a dependency breaker: - /// - /// addps %xmm1, %xmm0 - /// movaps %xmm0, (%rax) - /// xorps %xmm0, %xmm0 - /// cvtsi2ss %rbx, %xmm0 - /// - /// An operand should be added to MI if an instruction was - /// inserted. This ties the instructions together in the post-ra scheduler. - /// - virtual void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, - const TargetRegisterInfo *TRI) const {} - - /// Create machine specific model for scheduling. - virtual DFAPacketizer * - CreateTargetScheduleState(const TargetSubtargetInfo &) const { - return nullptr; - } - - /// Sometimes, it is possible for the target - /// to tell, even without aliasing information, that two MIs access different - /// memory addresses. This function returns true if two MIs access different - /// memory addresses and false otherwise. - /// - /// Assumes any physical registers used to compute addresses have the same - /// value for both instructions. (This is the most useful assumption for - /// post-RA scheduling.) - /// - /// See also MachineInstr::mayAlias, which is implemented on top of this - /// function. - virtual bool - areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, - const MachineInstr &MIb) const { - assert(MIa.mayLoadOrStore() && - "MIa must load from or modify a memory location"); - assert(MIb.mayLoadOrStore() && - "MIb must load from or modify a memory location"); - return false; - } - - /// Return the value to use for the MachineCSE's LookAheadLimit, - /// which is a heuristic used for CSE'ing phys reg defs. - virtual unsigned getMachineCSELookAheadLimit() const { - // The default lookahead is small to prevent unprofitable quadratic - // behavior. - return 5; - } - - /// Return the maximal number of alias checks on memory operands. For - /// instructions with more than one memory operands, the alias check on a - /// single MachineInstr pair has quadratic overhead and results in - /// unacceptable performance in the worst case. The limit here is to clamp - /// that maximal checks performed. Usually, that's the product of memory - /// operand numbers from that pair of MachineInstr to be checked. For - /// instance, with two MachineInstrs with 4 and 5 memory operands - /// correspondingly, a total of 20 checks are required. With this limit set to - /// 16, their alias check is skipped. We choose to limit the product instead - /// of the individual instruction as targets may have special MachineInstrs - /// with a considerably high number of memory operands, such as `ldm` in ARM. - /// Setting this limit per MachineInstr would result in either too high - /// overhead or too rigid restriction. - virtual unsigned getMemOperandAACheckLimit() const { return 16; } - - /// Return an array that contains the ids of the target indices (used for the - /// TargetIndex machine operand) and their names. - /// - /// MIR Serialization is able to serialize only the target indices that are - /// defined by this method. - virtual ArrayRef> - getSerializableTargetIndices() const { - return None; - } - - /// Decompose the machine operand's target flags into two values - the direct - /// target flag value and any of bit flags that are applied. - virtual std::pair - decomposeMachineOperandsTargetFlags(unsigned /*TF*/) const { - return std::make_pair(0u, 0u); - } - - /// Return an array that contains the direct target flag values and their - /// names. - /// - /// MIR Serialization is able to serialize only the target flags that are - /// defined by this method. - virtual ArrayRef> - getSerializableDirectMachineOperandTargetFlags() const { - return None; - } - - /// Return an array that contains the bitmask target flag values and their - /// names. - /// - /// MIR Serialization is able to serialize only the target flags that are - /// defined by this method. - virtual ArrayRef> - getSerializableBitmaskMachineOperandTargetFlags() const { - return None; - } - - /// Return an array that contains the MMO target flag values and their - /// names. - /// - /// MIR Serialization is able to serialize only the MMO target flags that are - /// defined by this method. - virtual ArrayRef> - getSerializableMachineMemOperandTargetFlags() const { - return None; - } - - /// Determines whether \p Inst is a tail call instruction. Override this - /// method on targets that do not properly set MCID::Return and MCID::Call on - /// tail call instructions." - virtual bool isTailCall(const MachineInstr &Inst) const { - return Inst.isReturn() && Inst.isCall(); - } - - /// True if the instruction is bound to the top of its basic block and no - /// other instructions shall be inserted before it. This can be implemented - /// to prevent register allocator to insert spills before such instructions. - virtual bool isBasicBlockPrologue(const MachineInstr &MI) const { - return false; - } - - /// During PHI eleimination lets target to make necessary checks and - /// insert the copy to the PHI destination register in a target specific - /// manner. - virtual MachineInstr *createPHIDestinationCopy( - MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, - const DebugLoc &DL, Register Src, Register Dst) const { - return BuildMI(MBB, InsPt, DL, get(TargetOpcode::COPY), Dst) - .addReg(Src); - } - - /// During PHI eleimination lets target to make necessary checks and - /// insert the copy to the PHI destination register in a target specific - /// manner. - virtual MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB, - MachineBasicBlock::iterator InsPt, - const DebugLoc &DL, Register Src, - unsigned SrcSubReg, - Register Dst) const { - return BuildMI(MBB, InsPt, DL, get(TargetOpcode::COPY), Dst) - .addReg(Src, 0, SrcSubReg); - } - - /// Returns a \p outliner::OutlinedFunction struct containing target-specific - /// information for a set of outlining candidates. - virtual outliner::OutlinedFunction getOutliningCandidateInfo( - std::vector &RepeatedSequenceLocs) const { - llvm_unreachable( - "Target didn't implement TargetInstrInfo::getOutliningCandidateInfo!"); - } - - /// Optional target hook to create the LLVM IR attributes for the outlined - /// function. If overridden, the overriding function must call the default - /// implementation. - virtual void mergeOutliningCandidateAttributes( - Function &F, std::vector &Candidates) const; - - /// Returns how or if \p MI should be outlined. - virtual outliner::InstrType - getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const { - llvm_unreachable( - "Target didn't implement TargetInstrInfo::getOutliningType!"); - } - - /// Optional target hook that returns true if \p MBB is safe to outline from, - /// and returns any target-specific information in \p Flags. - virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, - unsigned &Flags) const; - - /// Insert a custom frame for outlined functions. - virtual void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, - const outliner::OutlinedFunction &OF) const { - llvm_unreachable( - "Target didn't implement TargetInstrInfo::buildOutlinedFrame!"); - } - - /// Insert a call to an outlined function into the program. - /// Returns an iterator to the spot where we inserted the call. This must be - /// implemented by the target. - virtual MachineBasicBlock::iterator - insertOutlinedCall(Module &M, MachineBasicBlock &MBB, - MachineBasicBlock::iterator &It, MachineFunction &MF, - const outliner::Candidate &C) const { - llvm_unreachable( - "Target didn't implement TargetInstrInfo::insertOutlinedCall!"); - } - - /// Return true if the function can safely be outlined from. - /// A function \p MF is considered safe for outlining if an outlined function - /// produced from instructions in F will produce a program which produces the - /// same output for any set of given inputs. - virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF, - bool OutlineFromLinkOnceODRs) const { - llvm_unreachable("Target didn't implement " - "TargetInstrInfo::isFunctionSafeToOutlineFrom!"); - } - - /// Return true if the function should be outlined from by default. - virtual bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const { - return false; - } - - /// Produce the expression describing the \p MI loading a value into - /// the physical register \p Reg. This hook should only be used with - /// \p MIs belonging to VReg-less functions. - virtual Optional describeLoadedValue(const MachineInstr &MI, - Register Reg) const; - - /// Given the generic extension instruction \p ExtMI, returns true if this - /// extension is a likely candidate for being folded into an another - /// instruction. - virtual bool isExtendLikelyToBeFolded(MachineInstr &ExtMI, - MachineRegisterInfo &MRI) const { - return false; - } - - /// Return MIR formatter to format/parse MIR operands. Target can override - /// this virtual function and return target specific MIR formatter. - virtual const MIRFormatter *getMIRFormatter() const { - if (!Formatter.get()) - Formatter = std::make_unique(); - return Formatter.get(); - } - - /// Returns the target-specific default value for tail duplication. - /// This value will be used if the tail-dup-placement-threshold argument is - /// not provided. - virtual unsigned getTailDuplicateSize(CodeGenOpt::Level OptLevel) const { - return OptLevel >= CodeGenOpt::Aggressive ? 4 : 2; - } - - /// Returns the callee operand from the given \p MI. - virtual const MachineOperand &getCalleeOperand(const MachineInstr &MI) const { - return MI.getOperand(0); - } - -private: - mutable std::unique_ptr Formatter; - unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; - unsigned CatchRetOpcode; - unsigned ReturnOpcode; -}; - -/// Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair. -template <> struct DenseMapInfo { - using RegInfo = DenseMapInfo; - - static inline TargetInstrInfo::RegSubRegPair getEmptyKey() { - return TargetInstrInfo::RegSubRegPair(RegInfo::getEmptyKey(), - RegInfo::getEmptyKey()); - } - - static inline TargetInstrInfo::RegSubRegPair getTombstoneKey() { - return TargetInstrInfo::RegSubRegPair(RegInfo::getTombstoneKey(), - RegInfo::getTombstoneKey()); - } - - /// Reuse getHashValue implementation from - /// std::pair. - static unsigned getHashValue(const TargetInstrInfo::RegSubRegPair &Val) { - std::pair PairVal = std::make_pair(Val.Reg, Val.SubReg); - return DenseMapInfo>::getHashValue(PairVal); - } - - static bool isEqual(const TargetInstrInfo::RegSubRegPair &LHS, - const TargetInstrInfo::RegSubRegPair &RHS) { - return RegInfo::isEqual(LHS.Reg, RHS.Reg) && - RegInfo::isEqual(LHS.SubReg, RHS.SubReg); - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETINSTRINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetLowering.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetLowering.h deleted file mode 100644 index 6d7df1d1ef..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetLowering.h +++ /dev/null @@ -1,4823 +0,0 @@ -//===- llvm/CodeGen/TargetLowering.h - Target Lowering Info -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file describes how to lower LLVM code to machine code. This has two -/// main components: -/// -/// 1. Which ValueTypes are natively supported by the target. -/// 2. Which operations are supported for supported ValueTypes. -/// 3. Cost thresholds for alternative implementations of certain operations. -/// -/// In addition it has a few other components, like information about FP -/// immediates. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETLOWERING_H -#define LLVM_CODEGEN_TARGETLOWERING_H - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/DAGCombine.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/LowLevelType.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetCallingConv.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/InstructionCost.h" -#include "llvm/Support/MachineValueType.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class CCState; -class CCValAssign; -class Constant; -class FastISel; -class FunctionLoweringInfo; -class GlobalValue; -class GISelKnownBits; -class IntrinsicInst; -class IRBuilderBase; -struct KnownBits; -class LegacyDivergenceAnalysis; -class LLVMContext; -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MachineJumpTableInfo; -class MachineLoop; -class MachineRegisterInfo; -class MCContext; -class MCExpr; -class Module; -class ProfileSummaryInfo; -class TargetLibraryInfo; -class TargetMachine; -class TargetRegisterClass; -class TargetRegisterInfo; -class TargetTransformInfo; -class Value; - -namespace Sched { - -enum Preference { - None, // No preference - Source, // Follow source order. - RegPressure, // Scheduling for lowest register pressure. - Hybrid, // Scheduling for both latency and register pressure. - ILP, // Scheduling for ILP in low register pressure mode. - VLIW, // Scheduling for VLIW targets. - Fast, // Fast suboptimal list scheduling - Linearize // Linearize DAG, no scheduling -}; - -} // end namespace Sched - -// MemOp models a memory operation, either memset or memcpy/memmove. -struct MemOp { -private: - // Shared - uint64_t Size; - bool DstAlignCanChange; // true if destination alignment can satisfy any - // constraint. - Align DstAlign; // Specified alignment of the memory operation. - - bool AllowOverlap; - // memset only - bool IsMemset; // If setthis memory operation is a memset. - bool ZeroMemset; // If set clears out memory with zeros. - // memcpy only - bool MemcpyStrSrc; // Indicates whether the memcpy source is an in-register - // constant so it does not need to be loaded. - Align SrcAlign; // Inferred alignment of the source or default value if the - // memory operation does not need to load the value. -public: - static MemOp Copy(uint64_t Size, bool DstAlignCanChange, Align DstAlign, - Align SrcAlign, bool IsVolatile, - bool MemcpyStrSrc = false) { - MemOp Op; - Op.Size = Size; - Op.DstAlignCanChange = DstAlignCanChange; - Op.DstAlign = DstAlign; - Op.AllowOverlap = !IsVolatile; - Op.IsMemset = false; - Op.ZeroMemset = false; - Op.MemcpyStrSrc = MemcpyStrSrc; - Op.SrcAlign = SrcAlign; - return Op; - } - - static MemOp Set(uint64_t Size, bool DstAlignCanChange, Align DstAlign, - bool IsZeroMemset, bool IsVolatile) { - MemOp Op; - Op.Size = Size; - Op.DstAlignCanChange = DstAlignCanChange; - Op.DstAlign = DstAlign; - Op.AllowOverlap = !IsVolatile; - Op.IsMemset = true; - Op.ZeroMemset = IsZeroMemset; - Op.MemcpyStrSrc = false; - return Op; - } - - uint64_t size() const { return Size; } - Align getDstAlign() const { - assert(!DstAlignCanChange); - return DstAlign; - } - bool isFixedDstAlign() const { return !DstAlignCanChange; } - bool allowOverlap() const { return AllowOverlap; } - bool isMemset() const { return IsMemset; } - bool isMemcpy() const { return !IsMemset; } - bool isMemcpyWithFixedDstAlign() const { - return isMemcpy() && !DstAlignCanChange; - } - bool isZeroMemset() const { return isMemset() && ZeroMemset; } - bool isMemcpyStrSrc() const { - assert(isMemcpy() && "Must be a memcpy"); - return MemcpyStrSrc; - } - Align getSrcAlign() const { - assert(isMemcpy() && "Must be a memcpy"); - return SrcAlign; - } - bool isSrcAligned(Align AlignCheck) const { - return isMemset() || llvm::isAligned(AlignCheck, SrcAlign.value()); - } - bool isDstAligned(Align AlignCheck) const { - return DstAlignCanChange || llvm::isAligned(AlignCheck, DstAlign.value()); - } - bool isAligned(Align AlignCheck) const { - return isSrcAligned(AlignCheck) && isDstAligned(AlignCheck); - } -}; - -/// This base class for TargetLowering contains the SelectionDAG-independent -/// parts that can be used from the rest of CodeGen. -class TargetLoweringBase { -public: - /// This enum indicates whether operations are valid for a target, and if not, - /// what action should be used to make them valid. - enum LegalizeAction : uint8_t { - Legal, // The target natively supports this operation. - Promote, // This operation should be executed in a larger type. - Expand, // Try to expand this to other ops, otherwise use a libcall. - LibCall, // Don't try to expand this to other ops, always use a libcall. - Custom // Use the LowerOperation hook to implement custom lowering. - }; - - /// This enum indicates whether a types are legal for a target, and if not, - /// what action should be used to make them valid. - enum LegalizeTypeAction : uint8_t { - TypeLegal, // The target natively supports this type. - TypePromoteInteger, // Replace this integer with a larger one. - TypeExpandInteger, // Split this integer into two of half the size. - TypeSoftenFloat, // Convert this float to a same size integer type. - TypeExpandFloat, // Split this float into two of half the size. - TypeScalarizeVector, // Replace this one-element vector with its element. - TypeSplitVector, // Split this vector into two of half the size. - TypeWidenVector, // This vector should be widened into a larger vector. - TypePromoteFloat, // Replace this float with a larger one. - TypeSoftPromoteHalf, // Soften half to i16 and use float to do arithmetic. - TypeScalarizeScalableVector, // This action is explicitly left unimplemented. - // While it is theoretically possible to - // legalize operations on scalable types with a - // loop that handles the vscale * #lanes of the - // vector, this is non-trivial at SelectionDAG - // level and these types are better to be - // widened or promoted. - }; - - /// LegalizeKind holds the legalization kind that needs to happen to EVT - /// in order to type-legalize it. - using LegalizeKind = std::pair; - - /// Enum that describes how the target represents true/false values. - enum BooleanContent { - UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage. - ZeroOrOneBooleanContent, // All bits zero except for bit 0. - ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. - }; - - /// Enum that describes what type of support for selects the target has. - enum SelectSupportKind { - ScalarValSelect, // The target supports scalar selects (ex: cmov). - ScalarCondVectorVal, // The target supports selects with a scalar condition - // and vector values (ex: cmov). - VectorMaskSelect // The target supports vector selects with a vector - // mask (ex: x86 blends). - }; - - /// Enum that specifies what an atomic load/AtomicRMWInst is expanded - /// to, if at all. Exists because different targets have different levels of - /// support for these atomic instructions, and also have different options - /// w.r.t. what they should expand to. - enum class AtomicExpansionKind { - None, // Don't expand the instruction. - LLSC, // Expand the instruction into loadlinked/storeconditional; used - // by ARM/AArch64. - LLOnly, // Expand the (load) instruction into just a load-linked, which has - // greater atomic guarantees than a normal load. - CmpXChg, // Expand the instruction into cmpxchg; used by at least X86. - MaskedIntrinsic, // Use a target-specific intrinsic for the LL/SC loop. - }; - - /// Enum that specifies when a multiplication should be expanded. - enum class MulExpansionKind { - Always, // Always expand the instruction. - OnlyLegalOrCustom, // Only expand when the resulting instructions are legal - // or custom. - }; - - /// Enum that specifies when a float negation is beneficial. - enum class NegatibleCost { - Cheaper = 0, // Negated expression is cheaper. - Neutral = 1, // Negated expression has the same cost. - Expensive = 2 // Negated expression is more expensive. - }; - - class ArgListEntry { - public: - Value *Val = nullptr; - SDValue Node = SDValue(); - Type *Ty = nullptr; - bool IsSExt : 1; - bool IsZExt : 1; - bool IsInReg : 1; - bool IsSRet : 1; - bool IsNest : 1; - bool IsByVal : 1; - bool IsByRef : 1; - bool IsInAlloca : 1; - bool IsPreallocated : 1; - bool IsReturned : 1; - bool IsSwiftSelf : 1; - bool IsSwiftAsync : 1; - bool IsSwiftError : 1; - bool IsCFGuardTarget : 1; - MaybeAlign Alignment = None; - Type *IndirectType = nullptr; - - ArgListEntry() - : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), - IsNest(false), IsByVal(false), IsByRef(false), IsInAlloca(false), - IsPreallocated(false), IsReturned(false), IsSwiftSelf(false), - IsSwiftAsync(false), IsSwiftError(false), IsCFGuardTarget(false) {} - - void setAttributes(const CallBase *Call, unsigned ArgIdx); - }; - using ArgListTy = std::vector; - - virtual void markLibCallAttributes(MachineFunction *MF, unsigned CC, - ArgListTy &Args) const {}; - - static ISD::NodeType getExtendForContent(BooleanContent Content) { - switch (Content) { - case UndefinedBooleanContent: - // Extend by adding rubbish bits. - return ISD::ANY_EXTEND; - case ZeroOrOneBooleanContent: - // Extend by adding zero bits. - return ISD::ZERO_EXTEND; - case ZeroOrNegativeOneBooleanContent: - // Extend by copying the sign bit. - return ISD::SIGN_EXTEND; - } - llvm_unreachable("Invalid content kind"); - } - - explicit TargetLoweringBase(const TargetMachine &TM); - TargetLoweringBase(const TargetLoweringBase &) = delete; - TargetLoweringBase &operator=(const TargetLoweringBase &) = delete; - virtual ~TargetLoweringBase() = default; - - /// Return true if the target support strict float operation - bool isStrictFPEnabled() const { - return IsStrictFPEnabled; - } - -protected: - /// Initialize all of the actions to default values. - void initActions(); - -public: - const TargetMachine &getTargetMachine() const { return TM; } - - virtual bool useSoftFloat() const { return false; } - - /// Return the pointer type for the given address space, defaults to - /// the pointer type from the data layout. - /// FIXME: The default needs to be removed once all the code is updated. - virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { - return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); - } - - /// Return the in-memory pointer type for the given address space, defaults to - /// the pointer type from the data layout. FIXME: The default needs to be - /// removed once all the code is updated. - virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const { - return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); - } - - /// Return the type for frame index, which is determined by - /// the alloca address space specified through the data layout. - MVT getFrameIndexTy(const DataLayout &DL) const { - return getPointerTy(DL, DL.getAllocaAddrSpace()); - } - - /// Return the type for code pointers, which is determined by the program - /// address space specified through the data layout. - MVT getProgramPointerTy(const DataLayout &DL) const { - return getPointerTy(DL, DL.getProgramAddressSpace()); - } - - /// Return the type for operands of fence. - /// TODO: Let fence operands be of i32 type and remove this. - virtual MVT getFenceOperandTy(const DataLayout &DL) const { - return getPointerTy(DL); - } - - /// Return the type to use for a scalar shift opcode, given the shifted amount - /// type. Targets should return a legal type if the input type is legal. - /// Targets can return a type that is too small if the input type is illegal. - virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const; - - /// Returns the type for the shift amount of a shift opcode. For vectors, - /// returns the input type. For scalars, behavior depends on \p LegalTypes. If - /// \p LegalTypes is true, calls getScalarShiftAmountTy, otherwise uses - /// pointer type. If getScalarShiftAmountTy or pointer type cannot represent - /// all possible shift amounts, returns MVT::i32. In general, \p LegalTypes - /// should be set to true for calls during type legalization and after type - /// legalization has been completed. - EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL, - bool LegalTypes = true) const; - - /// Return the preferred type to use for a shift opcode, given the shifted - /// amount type is \p ShiftValueTy. - LLVM_READONLY - virtual LLT getPreferredShiftAmountTy(LLT ShiftValueTy) const { - return ShiftValueTy; - } - - /// Returns the type to be used for the index operand of: - /// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT, - /// ISD::INSERT_SUBVECTOR, and ISD::EXTRACT_SUBVECTOR - virtual MVT getVectorIdxTy(const DataLayout &DL) const { - return getPointerTy(DL); - } - - /// Returns the type to be used for the EVL/AVL operand of VP nodes: - /// ISD::VP_ADD, ISD::VP_SUB, etc. It must be a legal scalar integer type, - /// and must be at least as large as i32. The EVL is implicitly zero-extended - /// to any larger type. - virtual MVT getVPExplicitVectorLengthTy() const { return MVT::i32; } - - /// This callback is used to inspect load/store instructions and add - /// target-specific MachineMemOperand flags to them. The default - /// implementation does nothing. - virtual MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const { - return MachineMemOperand::MONone; - } - - MachineMemOperand::Flags getLoadMemOperandFlags(const LoadInst &LI, - const DataLayout &DL) const; - MachineMemOperand::Flags getStoreMemOperandFlags(const StoreInst &SI, - const DataLayout &DL) const; - MachineMemOperand::Flags getAtomicMemOperandFlags(const Instruction &AI, - const DataLayout &DL) const; - - virtual bool isSelectSupported(SelectSupportKind /*kind*/) const { - return true; - } - - /// Return true if the @llvm.get.active.lane.mask intrinsic should be expanded - /// using generic code in SelectionDAGBuilder. - virtual bool shouldExpandGetActiveLaneMask(EVT VT, EVT OpVT) const { - return true; - } - - /// Return true if it is profitable to convert a select of FP constants into - /// a constant pool load whose address depends on the select condition. The - /// parameter may be used to differentiate a select with FP compare from - /// integer compare. - virtual bool reduceSelectOfFPConstantLoads(EVT CmpOpVT) const { - return true; - } - - /// Return true if multiple condition registers are available. - bool hasMultipleConditionRegisters() const { - return HasMultipleConditionRegisters; - } - - /// Return true if the target has BitExtract instructions. - bool hasExtractBitsInsn() const { return HasExtractBitsInsn; } - - /// Return the preferred vector type legalization action. - virtual TargetLoweringBase::LegalizeTypeAction - getPreferredVectorAction(MVT VT) const { - // The default action for one element vectors is to scalarize - if (VT.getVectorElementCount().isScalar()) - return TypeScalarizeVector; - // The default action for an odd-width vector is to widen. - if (!VT.isPow2VectorType()) - return TypeWidenVector; - // The default action for other vectors is to promote - return TypePromoteInteger; - } - - // Return true if the half type should be passed around as i16, but promoted - // to float around arithmetic. The default behavior is to pass around as - // float and convert around loads/stores/bitcasts and other places where - // the size matters. - virtual bool softPromoteHalfType() const { return false; } - - // There are two general methods for expanding a BUILD_VECTOR node: - // 1. Use SCALAR_TO_VECTOR on the defined scalar values and then shuffle - // them together. - // 2. Build the vector on the stack and then load it. - // If this function returns true, then method (1) will be used, subject to - // the constraint that all of the necessary shuffles are legal (as determined - // by isShuffleMaskLegal). If this function returns false, then method (2) is - // always used. The vector type, and the number of defined values, are - // provided. - virtual bool - shouldExpandBuildVectorWithShuffles(EVT /* VT */, - unsigned DefinedValues) const { - return DefinedValues < 3; - } - - /// Return true if integer divide is usually cheaper than a sequence of - /// several shifts, adds, and multiplies for this target. - /// The definition of "cheaper" may depend on whether we're optimizing - /// for speed or for size. - virtual bool isIntDivCheap(EVT VT, AttributeList Attr) const { return false; } - - /// Return true if the target can handle a standalone remainder operation. - virtual bool hasStandaloneRem(EVT VT) const { - return true; - } - - /// Return true if SQRT(X) shouldn't be replaced with X*RSQRT(X). - virtual bool isFsqrtCheap(SDValue X, SelectionDAG &DAG) const { - // Default behavior is to replace SQRT(X) with X*RSQRT(X). - return false; - } - - /// Reciprocal estimate status values used by the functions below. - enum ReciprocalEstimate : int { - Unspecified = -1, - Disabled = 0, - Enabled = 1 - }; - - /// Return a ReciprocalEstimate enum value for a square root of the given type - /// based on the function's attributes. If the operation is not overridden by - /// the function's attributes, "Unspecified" is returned and target defaults - /// are expected to be used for instruction selection. - int getRecipEstimateSqrtEnabled(EVT VT, MachineFunction &MF) const; - - /// Return a ReciprocalEstimate enum value for a division of the given type - /// based on the function's attributes. If the operation is not overridden by - /// the function's attributes, "Unspecified" is returned and target defaults - /// are expected to be used for instruction selection. - int getRecipEstimateDivEnabled(EVT VT, MachineFunction &MF) const; - - /// Return the refinement step count for a square root of the given type based - /// on the function's attributes. If the operation is not overridden by - /// the function's attributes, "Unspecified" is returned and target defaults - /// are expected to be used for instruction selection. - int getSqrtRefinementSteps(EVT VT, MachineFunction &MF) const; - - /// Return the refinement step count for a division of the given type based - /// on the function's attributes. If the operation is not overridden by - /// the function's attributes, "Unspecified" is returned and target defaults - /// are expected to be used for instruction selection. - int getDivRefinementSteps(EVT VT, MachineFunction &MF) const; - - /// Returns true if target has indicated at least one type should be bypassed. - bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); } - - /// Returns map of slow types for division or remainder with corresponding - /// fast types - const DenseMap &getBypassSlowDivWidths() const { - return BypassSlowDivWidths; - } - - /// Return true if Flow Control is an expensive operation that should be - /// avoided. - bool isJumpExpensive() const { return JumpIsExpensive; } - - /// Return true if selects are only cheaper than branches if the branch is - /// unlikely to be predicted right. - bool isPredictableSelectExpensive() const { - return PredictableSelectIsExpensive; - } - - virtual bool fallBackToDAGISel(const Instruction &Inst) const { - return false; - } - - /// Return true if the following transform is beneficial: - /// fold (conv (load x)) -> (load (conv*)x) - /// On architectures that don't natively support some vector loads - /// efficiently, casting the load to a smaller vector of larger types and - /// loading is more efficient, however, this can be undone by optimizations in - /// dag combiner. - virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, - const SelectionDAG &DAG, - const MachineMemOperand &MMO) const { - // Don't do if we could do an indexed load on the original type, but not on - // the new one. - if (!LoadVT.isSimple() || !BitcastVT.isSimple()) - return true; - - MVT LoadMVT = LoadVT.getSimpleVT(); - - // Don't bother doing this if it's just going to be promoted again later, as - // doing so might interfere with other combines. - if (getOperationAction(ISD::LOAD, LoadMVT) == Promote && - getTypeToPromoteTo(ISD::LOAD, LoadMVT) == BitcastVT.getSimpleVT()) - return false; - - bool Fast = false; - return allowsMemoryAccess(*DAG.getContext(), DAG.getDataLayout(), BitcastVT, - MMO, &Fast) && Fast; - } - - /// Return true if the following transform is beneficial: - /// (store (y (conv x)), y*)) -> (store x, (x*)) - virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, - const SelectionDAG &DAG, - const MachineMemOperand &MMO) const { - // Default to the same logic as loads. - return isLoadBitCastBeneficial(StoreVT, BitcastVT, DAG, MMO); - } - - /// Return true if it is expected to be cheaper to do a store of a non-zero - /// vector constant with the given size and type for the address space than to - /// store the individual scalar element constants. - virtual bool storeOfVectorConstantIsCheap(EVT MemVT, - unsigned NumElem, - unsigned AddrSpace) const { - return false; - } - - /// Allow store merging for the specified type after legalization in addition - /// to before legalization. This may transform stores that do not exist - /// earlier (for example, stores created from intrinsics). - virtual bool mergeStoresAfterLegalization(EVT MemVT) const { - return true; - } - - /// Returns if it's reasonable to merge stores to MemVT size. - virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, - const MachineFunction &MF) const { - return true; - } - - /// Return true if it is cheap to speculate a call to intrinsic cttz. - virtual bool isCheapToSpeculateCttz() const { - return false; - } - - /// Return true if it is cheap to speculate a call to intrinsic ctlz. - virtual bool isCheapToSpeculateCtlz() const { - return false; - } - - /// Return true if ctlz instruction is fast. - virtual bool isCtlzFast() const { - return false; - } - - /// Return the maximum number of "x & (x - 1)" operations that can be done - /// instead of deferring to a custom CTPOP. - virtual unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const { - return 1; - } - - /// Return true if instruction generated for equality comparison is folded - /// with instruction generated for signed comparison. - virtual bool isEqualityCmpFoldedWithSignedCmp() const { return true; } - - /// Return true if the heuristic to prefer icmp eq zero should be used in code - /// gen prepare. - virtual bool preferZeroCompareBranch() const { return false; } - - /// Return true if it is safe to transform an integer-domain bitwise operation - /// into the equivalent floating-point operation. This should be set to true - /// if the target has IEEE-754-compliant fabs/fneg operations for the input - /// type. - virtual bool hasBitPreservingFPLogic(EVT VT) const { - return false; - } - - /// Return true if it is cheaper to split the store of a merged int val - /// from a pair of smaller values into multiple stores. - virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const { - return false; - } - - /// Return if the target supports combining a - /// chain like: - /// \code - /// %andResult = and %val1, #mask - /// %icmpResult = icmp %andResult, 0 - /// \endcode - /// into a single machine instruction of a form like: - /// \code - /// cc = test %register, #mask - /// \endcode - virtual bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const { - return false; - } - - /// Use bitwise logic to make pairs of compares more efficient. For example: - /// and (seteq A, B), (seteq C, D) --> seteq (or (xor A, B), (xor C, D)), 0 - /// This should be true when it takes more than one instruction to lower - /// setcc (cmp+set on x86 scalar), when bitwise ops are faster than logic on - /// condition bits (crand on PowerPC), and/or when reducing cmp+br is a win. - virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const { - return false; - } - - /// Return the preferred operand type if the target has a quick way to compare - /// integer values of the given size. Assume that any legal integer type can - /// be compared efficiently. Targets may override this to allow illegal wide - /// types to return a vector type if there is support to compare that type. - virtual MVT hasFastEqualityCompare(unsigned NumBits) const { - MVT VT = MVT::getIntegerVT(NumBits); - return isTypeLegal(VT) ? VT : MVT::INVALID_SIMPLE_VALUE_TYPE; - } - - /// Return true if the target should transform: - /// (X & Y) == Y ---> (~X & Y) == 0 - /// (X & Y) != Y ---> (~X & Y) != 0 - /// - /// This may be profitable if the target has a bitwise and-not operation that - /// sets comparison flags. A target may want to limit the transformation based - /// on the type of Y or if Y is a constant. - /// - /// Note that the transform will not occur if Y is known to be a power-of-2 - /// because a mask and compare of a single bit can be handled by inverting the - /// predicate, for example: - /// (X & 8) == 8 ---> (X & 8) != 0 - virtual bool hasAndNotCompare(SDValue Y) const { - return false; - } - - /// Return true if the target has a bitwise and-not operation: - /// X = ~A & B - /// This can be used to simplify select or other instructions. - virtual bool hasAndNot(SDValue X) const { - // If the target has the more complex version of this operation, assume that - // it has this operation too. - return hasAndNotCompare(X); - } - - /// Return true if the target has a bit-test instruction: - /// (X & (1 << Y)) ==/!= 0 - /// This knowledge can be used to prevent breaking the pattern, - /// or creating it if it could be recognized. - virtual bool hasBitTest(SDValue X, SDValue Y) const { return false; } - - /// There are two ways to clear extreme bits (either low or high): - /// Mask: x & (-1 << y) (the instcombine canonical form) - /// Shifts: x >> y << y - /// Return true if the variant with 2 variable shifts is preferred. - /// Return false if there is no preference. - virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const { - // By default, let's assume that no one prefers shifts. - return false; - } - - /// Return true if it is profitable to fold a pair of shifts into a mask. - /// This is usually true on most targets. But some targets, like Thumb1, - /// have immediate shift instructions, but no immediate "and" instruction; - /// this makes the fold unprofitable. - virtual bool shouldFoldConstantShiftPairToMask(const SDNode *N, - CombineLevel Level) const { - return true; - } - - /// Should we transform the IR-optimal check for whether given truncation - /// down into KeptBits would be truncating or not: - /// (add %x, (1 << (KeptBits-1))) srccond (1 << KeptBits) - /// Into its more traditional form: - /// ((%x << C) a>> C) dstcond %x - /// Return true if we should transform. - /// Return false if there is no preference. - virtual bool shouldTransformSignedTruncationCheck(EVT XVT, - unsigned KeptBits) const { - // By default, let's assume that no one prefers shifts. - return false; - } - - /// Given the pattern - /// (X & (C l>>/<< Y)) ==/!= 0 - /// return true if it should be transformed into: - /// ((X <> Y) & C) ==/!= 0 - /// WARNING: if 'X' is a constant, the fold may deadlock! - /// FIXME: we could avoid passing XC, but we can't use isConstOrConstSplat() - /// here because it can end up being not linked in. - virtual bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd( - SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, - unsigned OldShiftOpcode, unsigned NewShiftOpcode, - SelectionDAG &DAG) const { - if (hasBitTest(X, Y)) { - // One interesting pattern that we'd want to form is 'bit test': - // ((1 << Y) & C) ==/!= 0 - // But we also need to be careful not to try to reverse that fold. - - // Is this '1 << Y' ? - if (OldShiftOpcode == ISD::SHL && CC->isOne()) - return false; // Keep the 'bit test' pattern. - - // Will it be '1 << Y' after the transform ? - if (XC && NewShiftOpcode == ISD::SHL && XC->isOne()) - return true; // Do form the 'bit test' pattern. - } - - // If 'X' is a constant, and we transform, then we will immediately - // try to undo the fold, thus causing endless combine loop. - // So by default, let's assume everyone prefers the fold - // iff 'X' is not a constant. - return !XC; - } - - /// These two forms are equivalent: - /// sub %y, (xor %x, -1) - /// add (add %x, 1), %y - /// The variant with two add's is IR-canonical. - /// Some targets may prefer one to the other. - virtual bool preferIncOfAddToSubOfNot(EVT VT) const { - // By default, let's assume that everyone prefers the form with two add's. - return true; - } - - /// Return true if the target wants to use the optimization that - /// turns ext(promotableInst1(...(promotableInstN(load)))) into - /// promotedInst1(...(promotedInstN(ext(load)))). - bool enableExtLdPromotion() const { return EnableExtLdPromotion; } - - /// Return true if the target can combine store(extractelement VectorTy, - /// Idx). - /// \p Cost[out] gives the cost of that transformation when this is true. - virtual bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, - unsigned &Cost) const { - return false; - } - - /// Return true if inserting a scalar into a variable element of an undef - /// vector is more efficiently handled by splatting the scalar instead. - virtual bool shouldSplatInsEltVarIndex(EVT) const { - return false; - } - - /// Return true if target always benefits from combining into FMA for a - /// given value type. This must typically return false on targets where FMA - /// takes more cycles to execute than FADD. - virtual bool enableAggressiveFMAFusion(EVT VT) const { return false; } - - /// Return true if target always benefits from combining into FMA for a - /// given value type. This must typically return false on targets where FMA - /// takes more cycles to execute than FADD. - virtual bool enableAggressiveFMAFusion(LLT Ty) const { return false; } - - /// Return the ValueType of the result of SETCC operations. - virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, - EVT VT) const; - - /// Return the ValueType for comparison libcalls. Comparison libcalls include - /// floating point comparison calls, and Ordered/Unordered check calls on - /// floating point numbers. - virtual - MVT::SimpleValueType getCmpLibcallReturnType() const; - - /// For targets without i1 registers, this gives the nature of the high-bits - /// of boolean values held in types wider than i1. - /// - /// "Boolean values" are special true/false values produced by nodes like - /// SETCC and consumed (as the condition) by nodes like SELECT and BRCOND. - /// Not to be confused with general values promoted from i1. Some cpus - /// distinguish between vectors of boolean and scalars; the isVec parameter - /// selects between the two kinds. For example on X86 a scalar boolean should - /// be zero extended from i1, while the elements of a vector of booleans - /// should be sign extended from i1. - /// - /// Some cpus also treat floating point types the same way as they treat - /// vectors instead of the way they treat scalars. - BooleanContent getBooleanContents(bool isVec, bool isFloat) const { - if (isVec) - return BooleanVectorContents; - return isFloat ? BooleanFloatContents : BooleanContents; - } - - BooleanContent getBooleanContents(EVT Type) const { - return getBooleanContents(Type.isVector(), Type.isFloatingPoint()); - } - - /// Promote the given target boolean to a target boolean of the given type. - /// A target boolean is an integer value, not necessarily of type i1, the bits - /// of which conform to getBooleanContents. - /// - /// ValVT is the type of values that produced the boolean. - SDValue promoteTargetBoolean(SelectionDAG &DAG, SDValue Bool, - EVT ValVT) const { - SDLoc dl(Bool); - EVT BoolVT = - getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), ValVT); - ISD::NodeType ExtendCode = getExtendForContent(getBooleanContents(ValVT)); - return DAG.getNode(ExtendCode, dl, BoolVT, Bool); - } - - /// Return target scheduling preference. - Sched::Preference getSchedulingPreference() const { - return SchedPreferenceInfo; - } - - /// Some scheduler, e.g. hybrid, can switch to different scheduling heuristics - /// for different nodes. This function returns the preference (or none) for - /// the given node. - virtual Sched::Preference getSchedulingPreference(SDNode *) const { - return Sched::None; - } - - /// Return the register class that should be used for the specified value - /// type. - virtual const TargetRegisterClass *getRegClassFor(MVT VT, bool isDivergent = false) const { - (void)isDivergent; - const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy]; - assert(RC && "This value type is not natively supported!"); - return RC; - } - - /// Allows target to decide about the register class of the - /// specific value that is live outside the defining block. - /// Returns true if the value needs uniform register class. - virtual bool requiresUniformRegister(MachineFunction &MF, - const Value *) const { - return false; - } - - /// Return the 'representative' register class for the specified value - /// type. - /// - /// The 'representative' register class is the largest legal super-reg - /// register class for the register class of the value type. For example, on - /// i386 the rep register class for i8, i16, and i32 are GR32; while the rep - /// register class is GR64 on x86_64. - virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const { - const TargetRegisterClass *RC = RepRegClassForVT[VT.SimpleTy]; - return RC; - } - - /// Return the cost of the 'representative' register class for the specified - /// value type. - virtual uint8_t getRepRegClassCostFor(MVT VT) const { - return RepRegClassCostForVT[VT.SimpleTy]; - } - - /// Return true if SHIFT instructions should be expanded to SHIFT_PARTS - /// instructions, and false if a library call is preferred (e.g for code-size - /// reasons). - virtual bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const { - return true; - } - - /// Return true if the target has native support for the specified value type. - /// This means that it has a register that directly holds it without - /// promotions or expansions. - bool isTypeLegal(EVT VT) const { - assert(!VT.isSimple() || - (unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); - return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != nullptr; - } - - class ValueTypeActionImpl { - /// ValueTypeActions - For each value type, keep a LegalizeTypeAction enum - /// that indicates how instruction selection should deal with the type. - LegalizeTypeAction ValueTypeActions[MVT::VALUETYPE_SIZE]; - - public: - ValueTypeActionImpl() { - std::fill(std::begin(ValueTypeActions), std::end(ValueTypeActions), - TypeLegal); - } - - LegalizeTypeAction getTypeAction(MVT VT) const { - return ValueTypeActions[VT.SimpleTy]; - } - - void setTypeAction(MVT VT, LegalizeTypeAction Action) { - ValueTypeActions[VT.SimpleTy] = Action; - } - }; - - const ValueTypeActionImpl &getValueTypeActions() const { - return ValueTypeActions; - } - - /// Return how we should legalize values of this type, either it is already - /// legal (return 'Legal') or we need to promote it to a larger type (return - /// 'Promote'), or we need to expand it into multiple registers of smaller - /// integer type (return 'Expand'). 'Custom' is not an option. - LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const { - return getTypeConversion(Context, VT).first; - } - LegalizeTypeAction getTypeAction(MVT VT) const { - return ValueTypeActions.getTypeAction(VT); - } - - /// For types supported by the target, this is an identity function. For - /// types that must be promoted to larger types, this returns the larger type - /// to promote to. For integer types that are larger than the largest integer - /// register, this contains one step in the expansion to get to the smaller - /// register. For illegal floating point types, this returns the integer type - /// to transform to. - EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { - return getTypeConversion(Context, VT).second; - } - - /// For types supported by the target, this is an identity function. For - /// types that must be expanded (i.e. integer types that are larger than the - /// largest integer register or illegal floating point types), this returns - /// the largest legal type it will be expanded to. - EVT getTypeToExpandTo(LLVMContext &Context, EVT VT) const { - assert(!VT.isVector()); - while (true) { - switch (getTypeAction(Context, VT)) { - case TypeLegal: - return VT; - case TypeExpandInteger: - VT = getTypeToTransformTo(Context, VT); - break; - default: - llvm_unreachable("Type is not legal nor is it to be expanded!"); - } - } - } - - /// Vector types are broken down into some number of legal first class types. - /// For example, EVT::v8f32 maps to 2 EVT::v4f32 with Altivec or SSE1, or 8 - /// promoted EVT::f64 values with the X86 FP stack. Similarly, EVT::v2i64 - /// turns into 4 EVT::i32 values with both PPC and X86. - /// - /// This method returns the number of registers needed, and the VT for each - /// register. It also returns the VT and quantity of the intermediate values - /// before they are promoted/expanded. - unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT, - EVT &IntermediateVT, - unsigned &NumIntermediates, - MVT &RegisterVT) const; - - /// Certain targets such as MIPS require that some types such as vectors are - /// always broken down into scalars in some contexts. This occurs even if the - /// vector type is legal. - virtual unsigned getVectorTypeBreakdownForCallingConv( - LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, - unsigned &NumIntermediates, MVT &RegisterVT) const { - return getVectorTypeBreakdown(Context, VT, IntermediateVT, NumIntermediates, - RegisterVT); - } - - struct IntrinsicInfo { - unsigned opc = 0; // target opcode - EVT memVT; // memory VT - - // value representing memory location - PointerUnion ptrVal; - - int offset = 0; // offset off of ptrVal - uint64_t size = 0; // the size of the memory location - // (taken from memVT if zero) - MaybeAlign align = Align(1); // alignment - - MachineMemOperand::Flags flags = MachineMemOperand::MONone; - IntrinsicInfo() = default; - }; - - /// Given an intrinsic, checks if on the target the intrinsic will need to map - /// to a MemIntrinsicNode (touches memory). If this is the case, it returns - /// true and store the intrinsic information into the IntrinsicInfo that was - /// passed to the function. - virtual bool getTgtMemIntrinsic(IntrinsicInfo &, const CallInst &, - MachineFunction &, - unsigned /*Intrinsic*/) const { - return false; - } - - /// Returns true if the target can instruction select the specified FP - /// immediate natively. If false, the legalizer will materialize the FP - /// immediate as a load from a constant pool. - virtual bool isFPImmLegal(const APFloat & /*Imm*/, EVT /*VT*/, - bool ForCodeSize = false) const { - return false; - } - - /// Targets can use this to indicate that they only support *some* - /// VECTOR_SHUFFLE operations, those with specific masks. By default, if a - /// target supports the VECTOR_SHUFFLE node, all mask values are assumed to be - /// legal. - virtual bool isShuffleMaskLegal(ArrayRef /*Mask*/, EVT /*VT*/) const { - return true; - } - - /// Returns true if the operation can trap for the value type. - /// - /// VT must be a legal type. By default, we optimistically assume most - /// operations don't trap except for integer divide and remainder. - virtual bool canOpTrap(unsigned Op, EVT VT) const; - - /// Similar to isShuffleMaskLegal. Targets can use this to indicate if there - /// is a suitable VECTOR_SHUFFLE that can be used to replace a VAND with a - /// constant pool entry. - virtual bool isVectorClearMaskLegal(ArrayRef /*Mask*/, - EVT /*VT*/) const { - return false; - } - - /// Return how this operation should be treated: either it is legal, needs to - /// be promoted to a larger size, needs to be expanded to some other code - /// sequence, or the target has a custom expander for it. - LegalizeAction getOperationAction(unsigned Op, EVT VT) const { - if (VT.isExtended()) return Expand; - // If a target-specific SDNode requires legalization, require the target - // to provide custom legalization for it. - if (Op >= array_lengthof(OpActions[0])) return Custom; - return OpActions[(unsigned)VT.getSimpleVT().SimpleTy][Op]; - } - - /// Custom method defined by each target to indicate if an operation which - /// may require a scale is supported natively by the target. - /// If not, the operation is illegal. - virtual bool isSupportedFixedPointOperation(unsigned Op, EVT VT, - unsigned Scale) const { - return false; - } - - /// Some fixed point operations may be natively supported by the target but - /// only for specific scales. This method allows for checking - /// if the width is supported by the target for a given operation that may - /// depend on scale. - LegalizeAction getFixedPointOperationAction(unsigned Op, EVT VT, - unsigned Scale) const { - auto Action = getOperationAction(Op, VT); - if (Action != Legal) - return Action; - - // This operation is supported in this type but may only work on specific - // scales. - bool Supported; - switch (Op) { - default: - llvm_unreachable("Unexpected fixed point operation."); - case ISD::SMULFIX: - case ISD::SMULFIXSAT: - case ISD::UMULFIX: - case ISD::UMULFIXSAT: - case ISD::SDIVFIX: - case ISD::SDIVFIXSAT: - case ISD::UDIVFIX: - case ISD::UDIVFIXSAT: - Supported = isSupportedFixedPointOperation(Op, VT, Scale); - break; - } - - return Supported ? Action : Expand; - } - - // If Op is a strict floating-point operation, return the result - // of getOperationAction for the equivalent non-strict operation. - LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const { - unsigned EqOpc; - switch (Op) { - default: llvm_unreachable("Unexpected FP pseudo-opcode"); -#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ - case ISD::STRICT_##DAGN: EqOpc = ISD::DAGN; break; -#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ - case ISD::STRICT_##DAGN: EqOpc = ISD::SETCC; break; -#include "llvm/IR/ConstrainedOps.def" - } - - return getOperationAction(EqOpc, VT); - } - - /// Return true if the specified operation is legal on this target or can be - /// made legal with custom lowering. This is used to help guide high-level - /// lowering decisions. LegalOnly is an optional convenience for code paths - /// traversed pre and post legalisation. - bool isOperationLegalOrCustom(unsigned Op, EVT VT, - bool LegalOnly = false) const { - if (LegalOnly) - return isOperationLegal(Op, VT); - - return (VT == MVT::Other || isTypeLegal(VT)) && - (getOperationAction(Op, VT) == Legal || - getOperationAction(Op, VT) == Custom); - } - - /// Return true if the specified operation is legal on this target or can be - /// made legal using promotion. This is used to help guide high-level lowering - /// decisions. LegalOnly is an optional convenience for code paths traversed - /// pre and post legalisation. - bool isOperationLegalOrPromote(unsigned Op, EVT VT, - bool LegalOnly = false) const { - if (LegalOnly) - return isOperationLegal(Op, VT); - - return (VT == MVT::Other || isTypeLegal(VT)) && - (getOperationAction(Op, VT) == Legal || - getOperationAction(Op, VT) == Promote); - } - - /// Return true if the specified operation is legal on this target or can be - /// made legal with custom lowering or using promotion. This is used to help - /// guide high-level lowering decisions. LegalOnly is an optional convenience - /// for code paths traversed pre and post legalisation. - bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, - bool LegalOnly = false) const { - if (LegalOnly) - return isOperationLegal(Op, VT); - - return (VT == MVT::Other || isTypeLegal(VT)) && - (getOperationAction(Op, VT) == Legal || - getOperationAction(Op, VT) == Custom || - getOperationAction(Op, VT) == Promote); - } - - /// Return true if the operation uses custom lowering, regardless of whether - /// the type is legal or not. - bool isOperationCustom(unsigned Op, EVT VT) const { - return getOperationAction(Op, VT) == Custom; - } - - /// Return true if lowering to a jump table is allowed. - virtual bool areJTsAllowed(const Function *Fn) const { - if (Fn->getFnAttribute("no-jump-tables").getValueAsBool()) - return false; - - return isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || - isOperationLegalOrCustom(ISD::BRIND, MVT::Other); - } - - /// Check whether the range [Low,High] fits in a machine word. - bool rangeFitsInWord(const APInt &Low, const APInt &High, - const DataLayout &DL) const { - // FIXME: Using the pointer type doesn't seem ideal. - uint64_t BW = DL.getIndexSizeInBits(0u); - uint64_t Range = (High - Low).getLimitedValue(UINT64_MAX - 1) + 1; - return Range <= BW; - } - - /// Return true if lowering to a jump table is suitable for a set of case - /// clusters which may contain \p NumCases cases, \p Range range of values. - virtual bool isSuitableForJumpTable(const SwitchInst *SI, uint64_t NumCases, - uint64_t Range, ProfileSummaryInfo *PSI, - BlockFrequencyInfo *BFI) const; - - /// Return true if lowering to a bit test is suitable for a set of case - /// clusters which contains \p NumDests unique destinations, \p Low and - /// \p High as its lowest and highest case values, and expects \p NumCmps - /// case value comparisons. Check if the number of destinations, comparison - /// metric, and range are all suitable. - bool isSuitableForBitTests(unsigned NumDests, unsigned NumCmps, - const APInt &Low, const APInt &High, - const DataLayout &DL) const { - // FIXME: I don't think NumCmps is the correct metric: a single case and a - // range of cases both require only one branch to lower. Just looking at the - // number of clusters and destinations should be enough to decide whether to - // build bit tests. - - // To lower a range with bit tests, the range must fit the bitwidth of a - // machine word. - if (!rangeFitsInWord(Low, High, DL)) - return false; - - // Decide whether it's profitable to lower this range with bit tests. Each - // destination requires a bit test and branch, and there is an overall range - // check branch. For a small number of clusters, separate comparisons might - // be cheaper, and for many destinations, splitting the range might be - // better. - return (NumDests == 1 && NumCmps >= 3) || (NumDests == 2 && NumCmps >= 5) || - (NumDests == 3 && NumCmps >= 6); - } - - /// Return true if the specified operation is illegal on this target or - /// unlikely to be made legal with custom lowering. This is used to help guide - /// high-level lowering decisions. - bool isOperationExpand(unsigned Op, EVT VT) const { - return (!isTypeLegal(VT) || getOperationAction(Op, VT) == Expand); - } - - /// Return true if the specified operation is legal on this target. - bool isOperationLegal(unsigned Op, EVT VT) const { - return (VT == MVT::Other || isTypeLegal(VT)) && - getOperationAction(Op, VT) == Legal; - } - - /// Return how this load with extension should be treated: either it is legal, - /// needs to be promoted to a larger size, needs to be expanded to some other - /// code sequence, or the target has a custom expander for it. - LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, - EVT MemVT) const { - if (ValVT.isExtended() || MemVT.isExtended()) return Expand; - unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; - unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; - assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::VALUETYPE_SIZE && - MemI < MVT::VALUETYPE_SIZE && "Table isn't big enough!"); - unsigned Shift = 4 * ExtType; - return (LegalizeAction)((LoadExtActions[ValI][MemI] >> Shift) & 0xf); - } - - /// Return true if the specified load with extension is legal on this target. - bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const { - return getLoadExtAction(ExtType, ValVT, MemVT) == Legal; - } - - /// Return true if the specified load with extension is legal or custom - /// on this target. - bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const { - return getLoadExtAction(ExtType, ValVT, MemVT) == Legal || - getLoadExtAction(ExtType, ValVT, MemVT) == Custom; - } - - /// Return how this store with truncation should be treated: either it is - /// legal, needs to be promoted to a larger size, needs to be expanded to some - /// other code sequence, or the target has a custom expander for it. - LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { - if (ValVT.isExtended() || MemVT.isExtended()) return Expand; - unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; - unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; - assert(ValI < MVT::VALUETYPE_SIZE && MemI < MVT::VALUETYPE_SIZE && - "Table isn't big enough!"); - return TruncStoreActions[ValI][MemI]; - } - - /// Return true if the specified store with truncation is legal on this - /// target. - bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { - return isTypeLegal(ValVT) && getTruncStoreAction(ValVT, MemVT) == Legal; - } - - /// Return true if the specified store with truncation has solution on this - /// target. - bool isTruncStoreLegalOrCustom(EVT ValVT, EVT MemVT) const { - return isTypeLegal(ValVT) && - (getTruncStoreAction(ValVT, MemVT) == Legal || - getTruncStoreAction(ValVT, MemVT) == Custom); - } - - virtual bool canCombineTruncStore(EVT ValVT, EVT MemVT, - bool LegalOnly) const { - if (LegalOnly) - return isTruncStoreLegal(ValVT, MemVT); - - return isTruncStoreLegalOrCustom(ValVT, MemVT); - } - - /// Return how the indexed load should be treated: either it is legal, needs - /// to be promoted to a larger size, needs to be expanded to some other code - /// sequence, or the target has a custom expander for it. - LegalizeAction getIndexedLoadAction(unsigned IdxMode, MVT VT) const { - return getIndexedModeAction(IdxMode, VT, IMAB_Load); - } - - /// Return true if the specified indexed load is legal on this target. - bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const { - return VT.isSimple() && - (getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Legal || - getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Custom); - } - - /// Return how the indexed store should be treated: either it is legal, needs - /// to be promoted to a larger size, needs to be expanded to some other code - /// sequence, or the target has a custom expander for it. - LegalizeAction getIndexedStoreAction(unsigned IdxMode, MVT VT) const { - return getIndexedModeAction(IdxMode, VT, IMAB_Store); - } - - /// Return true if the specified indexed load is legal on this target. - bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const { - return VT.isSimple() && - (getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Legal || - getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Custom); - } - - /// Return how the indexed load should be treated: either it is legal, needs - /// to be promoted to a larger size, needs to be expanded to some other code - /// sequence, or the target has a custom expander for it. - LegalizeAction getIndexedMaskedLoadAction(unsigned IdxMode, MVT VT) const { - return getIndexedModeAction(IdxMode, VT, IMAB_MaskedLoad); - } - - /// Return true if the specified indexed load is legal on this target. - bool isIndexedMaskedLoadLegal(unsigned IdxMode, EVT VT) const { - return VT.isSimple() && - (getIndexedMaskedLoadAction(IdxMode, VT.getSimpleVT()) == Legal || - getIndexedMaskedLoadAction(IdxMode, VT.getSimpleVT()) == Custom); - } - - /// Return how the indexed store should be treated: either it is legal, needs - /// to be promoted to a larger size, needs to be expanded to some other code - /// sequence, or the target has a custom expander for it. - LegalizeAction getIndexedMaskedStoreAction(unsigned IdxMode, MVT VT) const { - return getIndexedModeAction(IdxMode, VT, IMAB_MaskedStore); - } - - /// Return true if the specified indexed load is legal on this target. - bool isIndexedMaskedStoreLegal(unsigned IdxMode, EVT VT) const { - return VT.isSimple() && - (getIndexedMaskedStoreAction(IdxMode, VT.getSimpleVT()) == Legal || - getIndexedMaskedStoreAction(IdxMode, VT.getSimpleVT()) == Custom); - } - - /// Returns true if the index type for a masked gather/scatter requires - /// extending - virtual bool shouldExtendGSIndex(EVT VT, EVT &EltTy) const { return false; } - - // Returns true if VT is a legal index type for masked gathers/scatters - // on this target - virtual bool shouldRemoveExtendFromGSIndex(EVT VT) const { return false; } - - /// Return how the condition code should be treated: either it is legal, needs - /// to be expanded to some other code sequence, or the target has a custom - /// expander for it. - LegalizeAction - getCondCodeAction(ISD::CondCode CC, MVT VT) const { - assert((unsigned)CC < array_lengthof(CondCodeActions) && - ((unsigned)VT.SimpleTy >> 3) < array_lengthof(CondCodeActions[0]) && - "Table isn't big enough!"); - // See setCondCodeAction for how this is encoded. - uint32_t Shift = 4 * (VT.SimpleTy & 0x7); - uint32_t Value = CondCodeActions[CC][VT.SimpleTy >> 3]; - LegalizeAction Action = (LegalizeAction) ((Value >> Shift) & 0xF); - assert(Action != Promote && "Can't promote condition code!"); - return Action; - } - - /// Return true if the specified condition code is legal on this target. - bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const { - return getCondCodeAction(CC, VT) == Legal; - } - - /// Return true if the specified condition code is legal or custom on this - /// target. - bool isCondCodeLegalOrCustom(ISD::CondCode CC, MVT VT) const { - return getCondCodeAction(CC, VT) == Legal || - getCondCodeAction(CC, VT) == Custom; - } - - /// If the action for this operation is to promote, this method returns the - /// ValueType to promote to. - MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { - assert(getOperationAction(Op, VT) == Promote && - "This operation isn't promoted!"); - - // See if this has an explicit type specified. - std::map, - MVT::SimpleValueType>::const_iterator PTTI = - PromoteToType.find(std::make_pair(Op, VT.SimpleTy)); - if (PTTI != PromoteToType.end()) return PTTI->second; - - assert((VT.isInteger() || VT.isFloatingPoint()) && - "Cannot autopromote this type, add it with AddPromotedToType."); - - MVT NVT = VT; - do { - NVT = (MVT::SimpleValueType)(NVT.SimpleTy+1); - assert(NVT.isInteger() == VT.isInteger() && NVT != MVT::isVoid && - "Didn't find type to promote to!"); - } while (!isTypeLegal(NVT) || - getOperationAction(Op, NVT) == Promote); - return NVT; - } - - virtual EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty, - bool AllowUnknown = false) const { - return getValueType(DL, Ty, AllowUnknown); - } - - /// Return the EVT corresponding to this LLVM type. This is fixed by the LLVM - /// operations except for the pointer size. If AllowUnknown is true, this - /// will return MVT::Other for types with no EVT counterpart (e.g. structs), - /// otherwise it will assert. - EVT getValueType(const DataLayout &DL, Type *Ty, - bool AllowUnknown = false) const { - // Lower scalar pointers to native pointer types. - if (auto *PTy = dyn_cast(Ty)) - return getPointerTy(DL, PTy->getAddressSpace()); - - if (auto *VTy = dyn_cast(Ty)) { - Type *EltTy = VTy->getElementType(); - // Lower vectors of pointers to native pointer types. - if (auto *PTy = dyn_cast(EltTy)) { - EVT PointerTy(getPointerTy(DL, PTy->getAddressSpace())); - EltTy = PointerTy.getTypeForEVT(Ty->getContext()); - } - return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(EltTy, false), - VTy->getElementCount()); - } - - return EVT::getEVT(Ty, AllowUnknown); - } - - EVT getMemValueType(const DataLayout &DL, Type *Ty, - bool AllowUnknown = false) const { - // Lower scalar pointers to native pointer types. - if (PointerType *PTy = dyn_cast(Ty)) - return getPointerMemTy(DL, PTy->getAddressSpace()); - else if (VectorType *VTy = dyn_cast(Ty)) { - Type *Elm = VTy->getElementType(); - if (PointerType *PT = dyn_cast(Elm)) { - EVT PointerTy(getPointerMemTy(DL, PT->getAddressSpace())); - Elm = PointerTy.getTypeForEVT(Ty->getContext()); - } - return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(Elm, false), - VTy->getElementCount()); - } - - return getValueType(DL, Ty, AllowUnknown); - } - - - /// Return the MVT corresponding to this LLVM type. See getValueType. - MVT getSimpleValueType(const DataLayout &DL, Type *Ty, - bool AllowUnknown = false) const { - return getValueType(DL, Ty, AllowUnknown).getSimpleVT(); - } - - /// Return the desired alignment for ByVal or InAlloca aggregate function - /// arguments in the caller parameter area. This is the actual alignment, not - /// its logarithm. - virtual uint64_t getByValTypeAlignment(Type *Ty, const DataLayout &DL) const; - - /// Return the type of registers that this ValueType will eventually require. - MVT getRegisterType(MVT VT) const { - assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT)); - return RegisterTypeForVT[VT.SimpleTy]; - } - - /// Return the type of registers that this ValueType will eventually require. - MVT getRegisterType(LLVMContext &Context, EVT VT) const { - if (VT.isSimple()) { - assert((unsigned)VT.getSimpleVT().SimpleTy < - array_lengthof(RegisterTypeForVT)); - return RegisterTypeForVT[VT.getSimpleVT().SimpleTy]; - } - if (VT.isVector()) { - EVT VT1; - MVT RegisterVT; - unsigned NumIntermediates; - (void)getVectorTypeBreakdown(Context, VT, VT1, - NumIntermediates, RegisterVT); - return RegisterVT; - } - if (VT.isInteger()) { - return getRegisterType(Context, getTypeToTransformTo(Context, VT)); - } - llvm_unreachable("Unsupported extended type!"); - } - - /// Return the number of registers that this ValueType will eventually - /// require. - /// - /// This is one for any types promoted to live in larger registers, but may be - /// more than one for types (like i64) that are split into pieces. For types - /// like i140, which are first promoted then expanded, it is the number of - /// registers needed to hold all the bits of the original type. For an i140 - /// on a 32 bit machine this means 5 registers. - /// - /// RegisterVT may be passed as a way to override the default settings, for - /// instance with i128 inline assembly operands on SystemZ. - virtual unsigned - getNumRegisters(LLVMContext &Context, EVT VT, - Optional RegisterVT = None) const { - if (VT.isSimple()) { - assert((unsigned)VT.getSimpleVT().SimpleTy < - array_lengthof(NumRegistersForVT)); - return NumRegistersForVT[VT.getSimpleVT().SimpleTy]; - } - if (VT.isVector()) { - EVT VT1; - MVT VT2; - unsigned NumIntermediates; - return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2); - } - if (VT.isInteger()) { - unsigned BitWidth = VT.getSizeInBits(); - unsigned RegWidth = getRegisterType(Context, VT).getSizeInBits(); - return (BitWidth + RegWidth - 1) / RegWidth; - } - llvm_unreachable("Unsupported extended type!"); - } - - /// Certain combinations of ABIs, Targets and features require that types - /// are legal for some operations and not for other operations. - /// For MIPS all vector types must be passed through the integer register set. - virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, - CallingConv::ID CC, EVT VT) const { - return getRegisterType(Context, VT); - } - - /// Certain targets require unusual breakdowns of certain types. For MIPS, - /// this occurs when a vector type is used, as vector are passed through the - /// integer register set. - virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, - CallingConv::ID CC, - EVT VT) const { - return getNumRegisters(Context, VT); - } - - /// Certain targets have context sensitive alignment requirements, where one - /// type has the alignment requirement of another type. - virtual Align getABIAlignmentForCallingConv(Type *ArgTy, - const DataLayout &DL) const { - return DL.getABITypeAlign(ArgTy); - } - - /// If true, then instruction selection should seek to shrink the FP constant - /// of the specified type to a smaller type in order to save space and / or - /// reduce runtime. - virtual bool ShouldShrinkFPConstant(EVT) const { return true; } - - /// Return true if it is profitable to reduce a load to a smaller type. - /// Example: (i16 (trunc (i32 (load x))) -> i16 load x - virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, - EVT NewVT) const { - // By default, assume that it is cheaper to extract a subvector from a wide - // vector load rather than creating multiple narrow vector loads. - if (NewVT.isVector() && !Load->hasOneUse()) - return false; - - return true; - } - - /// When splitting a value of the specified type into parts, does the Lo - /// or Hi part come first? This usually follows the endianness, except - /// for ppcf128, where the Hi part always comes first. - bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const { - return DL.isBigEndian() || VT == MVT::ppcf128; - } - - /// If true, the target has custom DAG combine transformations that it can - /// perform for the specified node. - bool hasTargetDAGCombine(ISD::NodeType NT) const { - assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); - return TargetDAGCombineArray[NT >> 3] & (1 << (NT&7)); - } - - unsigned getGatherAllAliasesMaxDepth() const { - return GatherAllAliasesMaxDepth; - } - - /// Returns the size of the platform's va_list object. - virtual unsigned getVaListSizeInBits(const DataLayout &DL) const { - return getPointerTy(DL).getSizeInBits(); - } - - /// Get maximum # of store operations permitted for llvm.memset - /// - /// This function returns the maximum number of store operations permitted - /// to replace a call to llvm.memset. The value is set by the target at the - /// performance threshold for such a replacement. If OptSize is true, - /// return the limit for functions that have OptSize attribute. - unsigned getMaxStoresPerMemset(bool OptSize) const { - return OptSize ? MaxStoresPerMemsetOptSize : MaxStoresPerMemset; - } - - /// Get maximum # of store operations permitted for llvm.memcpy - /// - /// This function returns the maximum number of store operations permitted - /// to replace a call to llvm.memcpy. The value is set by the target at the - /// performance threshold for such a replacement. If OptSize is true, - /// return the limit for functions that have OptSize attribute. - unsigned getMaxStoresPerMemcpy(bool OptSize) const { - return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy; - } - - /// \brief Get maximum # of store operations to be glued together - /// - /// This function returns the maximum number of store operations permitted - /// to glue together during lowering of llvm.memcpy. The value is set by - // the target at the performance threshold for such a replacement. - virtual unsigned getMaxGluedStoresPerMemcpy() const { - return MaxGluedStoresPerMemcpy; - } - - /// Get maximum # of load operations permitted for memcmp - /// - /// This function returns the maximum number of load operations permitted - /// to replace a call to memcmp. The value is set by the target at the - /// performance threshold for such a replacement. If OptSize is true, - /// return the limit for functions that have OptSize attribute. - unsigned getMaxExpandSizeMemcmp(bool OptSize) const { - return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp; - } - - /// Get maximum # of store operations permitted for llvm.memmove - /// - /// This function returns the maximum number of store operations permitted - /// to replace a call to llvm.memmove. The value is set by the target at the - /// performance threshold for such a replacement. If OptSize is true, - /// return the limit for functions that have OptSize attribute. - unsigned getMaxStoresPerMemmove(bool OptSize) const { - return OptSize ? MaxStoresPerMemmoveOptSize : MaxStoresPerMemmove; - } - - /// Determine if the target supports unaligned memory accesses. - /// - /// This function returns true if the target allows unaligned memory accesses - /// of the specified type in the given address space. If true, it also returns - /// whether the unaligned memory access is "fast" in the last argument by - /// reference. This is used, for example, in situations where an array - /// copy/move/set is converted to a sequence of store operations. Its use - /// helps to ensure that such replacements don't generate code that causes an - /// alignment error (trap) on the target machine. - virtual bool allowsMisalignedMemoryAccesses( - EVT, unsigned AddrSpace = 0, Align Alignment = Align(1), - MachineMemOperand::Flags Flags = MachineMemOperand::MONone, - bool * /*Fast*/ = nullptr) const { - return false; - } - - /// LLT handling variant. - virtual bool allowsMisalignedMemoryAccesses( - LLT, unsigned AddrSpace = 0, Align Alignment = Align(1), - MachineMemOperand::Flags Flags = MachineMemOperand::MONone, - bool * /*Fast*/ = nullptr) const { - return false; - } - - /// This function returns true if the memory access is aligned or if the - /// target allows this specific unaligned memory access. If the access is - /// allowed, the optional final parameter returns if the access is also fast - /// (as defined by the target). - bool allowsMemoryAccessForAlignment( - LLVMContext &Context, const DataLayout &DL, EVT VT, - unsigned AddrSpace = 0, Align Alignment = Align(1), - MachineMemOperand::Flags Flags = MachineMemOperand::MONone, - bool *Fast = nullptr) const; - - /// Return true if the memory access of this type is aligned or if the target - /// allows this specific unaligned access for the given MachineMemOperand. - /// If the access is allowed, the optional final parameter returns if the - /// access is also fast (as defined by the target). - bool allowsMemoryAccessForAlignment(LLVMContext &Context, - const DataLayout &DL, EVT VT, - const MachineMemOperand &MMO, - bool *Fast = nullptr) const; - - /// Return true if the target supports a memory access of this type for the - /// given address space and alignment. If the access is allowed, the optional - /// final parameter returns if the access is also fast (as defined by the - /// target). - virtual bool - allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, - unsigned AddrSpace = 0, Align Alignment = Align(1), - MachineMemOperand::Flags Flags = MachineMemOperand::MONone, - bool *Fast = nullptr) const; - - /// Return true if the target supports a memory access of this type for the - /// given MachineMemOperand. If the access is allowed, the optional - /// final parameter returns if the access is also fast (as defined by the - /// target). - bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, - const MachineMemOperand &MMO, - bool *Fast = nullptr) const; - - /// LLT handling variant. - bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, LLT Ty, - const MachineMemOperand &MMO, - bool *Fast = nullptr) const; - - /// Returns the target specific optimal type for load and store operations as - /// a result of memset, memcpy, and memmove lowering. - /// It returns EVT::Other if the type should be determined using generic - /// target-independent logic. - virtual EVT - getOptimalMemOpType(const MemOp &Op, - const AttributeList & /*FuncAttributes*/) const { - return MVT::Other; - } - - /// LLT returning variant. - virtual LLT - getOptimalMemOpLLT(const MemOp &Op, - const AttributeList & /*FuncAttributes*/) const { - return LLT(); - } - - /// Returns true if it's safe to use load / store of the specified type to - /// expand memcpy / memset inline. - /// - /// This is mostly true for all types except for some special cases. For - /// example, on X86 targets without SSE2 f64 load / store are done with fldl / - /// fstpl which also does type conversion. Note the specified type doesn't - /// have to be legal as the hook is used before type legalization. - virtual bool isSafeMemOpType(MVT /*VT*/) const { return true; } - - /// Return lower limit for number of blocks in a jump table. - virtual unsigned getMinimumJumpTableEntries() const; - - /// Return lower limit of the density in a jump table. - unsigned getMinimumJumpTableDensity(bool OptForSize) const; - - /// Return upper limit for number of entries in a jump table. - /// Zero if no limit. - unsigned getMaximumJumpTableSize() const; - - virtual bool isJumpTableRelative() const; - - /// If a physical register, this specifies the register that - /// llvm.savestack/llvm.restorestack should save and restore. - Register getStackPointerRegisterToSaveRestore() const { - return StackPointerRegisterToSaveRestore; - } - - /// If a physical register, this returns the register that receives the - /// exception address on entry to an EH pad. - virtual Register - getExceptionPointerRegister(const Constant *PersonalityFn) const { - return Register(); - } - - /// If a physical register, this returns the register that receives the - /// exception typeid on entry to a landing pad. - virtual Register - getExceptionSelectorRegister(const Constant *PersonalityFn) const { - return Register(); - } - - virtual bool needsFixedCatchObjects() const { - report_fatal_error("Funclet EH is not implemented for this target"); - } - - /// Return the minimum stack alignment of an argument. - Align getMinStackArgumentAlignment() const { - return MinStackArgumentAlignment; - } - - /// Return the minimum function alignment. - Align getMinFunctionAlignment() const { return MinFunctionAlignment; } - - /// Return the preferred function alignment. - Align getPrefFunctionAlignment() const { return PrefFunctionAlignment; } - - /// Return the preferred loop alignment. - virtual Align getPrefLoopAlignment(MachineLoop *ML = nullptr) const; - - /// Return the maximum amount of bytes allowed to be emitted when padding for - /// alignment - virtual unsigned - getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const; - - /// Should loops be aligned even when the function is marked OptSize (but not - /// MinSize). - virtual bool alignLoopsWithOptSize() const { return false; } - - /// If the target has a standard location for the stack protector guard, - /// returns the address of that location. Otherwise, returns nullptr. - /// DEPRECATED: please override useLoadStackGuardNode and customize - /// LOAD_STACK_GUARD, or customize \@llvm.stackguard(). - virtual Value *getIRStackGuard(IRBuilderBase &IRB) const; - - /// Inserts necessary declarations for SSP (stack protection) purpose. - /// Should be used only when getIRStackGuard returns nullptr. - virtual void insertSSPDeclarations(Module &M) const; - - /// Return the variable that's previously inserted by insertSSPDeclarations, - /// if any, otherwise return nullptr. Should be used only when - /// getIRStackGuard returns nullptr. - virtual Value *getSDagStackGuard(const Module &M) const; - - /// If this function returns true, stack protection checks should XOR the - /// frame pointer (or whichever pointer is used to address locals) into the - /// stack guard value before checking it. getIRStackGuard must return nullptr - /// if this returns true. - virtual bool useStackGuardXorFP() const { return false; } - - /// If the target has a standard stack protection check function that - /// performs validation and error handling, returns the function. Otherwise, - /// returns nullptr. Must be previously inserted by insertSSPDeclarations. - /// Should be used only when getIRStackGuard returns nullptr. - virtual Function *getSSPStackGuardCheck(const Module &M) const; - - /// \returns true if a constant G_UBFX is legal on the target. - virtual bool isConstantUnsignedBitfieldExtractLegal(unsigned Opc, LLT Ty1, - LLT Ty2) const { - return false; - } - -protected: - Value *getDefaultSafeStackPointerLocation(IRBuilderBase &IRB, - bool UseTLS) const; - -public: - /// Returns the target-specific address of the unsafe stack pointer. - virtual Value *getSafeStackPointerLocation(IRBuilderBase &IRB) const; - - /// Returns the name of the symbol used to emit stack probes or the empty - /// string if not applicable. - virtual bool hasStackProbeSymbol(MachineFunction &MF) const { return false; } - - virtual bool hasInlineStackProbe(MachineFunction &MF) const { return false; } - - virtual StringRef getStackProbeSymbolName(MachineFunction &MF) const { - return ""; - } - - /// Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g. we - /// are happy to sink it into basic blocks. A cast may be free, but not - /// necessarily a no-op. e.g. a free truncate from a 64-bit to 32-bit pointer. - virtual bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const; - - /// Return true if the pointer arguments to CI should be aligned by aligning - /// the object whose address is being passed. If so then MinSize is set to the - /// minimum size the object must be to be aligned and PrefAlign is set to the - /// preferred alignment. - virtual bool shouldAlignPointerArgs(CallInst * /*CI*/, unsigned & /*MinSize*/, - unsigned & /*PrefAlign*/) const { - return false; - } - - //===--------------------------------------------------------------------===// - /// \name Helpers for TargetTransformInfo implementations - /// @{ - - /// Get the ISD node that corresponds to the Instruction class opcode. - int InstructionOpcodeToISD(unsigned Opcode) const; - - /// Estimate the cost of type-legalization and the legalized type. - std::pair getTypeLegalizationCost(const DataLayout &DL, - Type *Ty) const; - - /// @} - - //===--------------------------------------------------------------------===// - /// \name Helpers for atomic expansion. - /// @{ - - /// Returns the maximum atomic operation size (in bits) supported by - /// the backend. Atomic operations greater than this size (as well - /// as ones that are not naturally aligned), will be expanded by - /// AtomicExpandPass into an __atomic_* library call. - unsigned getMaxAtomicSizeInBitsSupported() const { - return MaxAtomicSizeInBitsSupported; - } - - /// Returns the size of the smallest cmpxchg or ll/sc instruction - /// the backend supports. Any smaller operations are widened in - /// AtomicExpandPass. - /// - /// Note that *unlike* operations above the maximum size, atomic ops - /// are still natively supported below the minimum; they just - /// require a more complex expansion. - unsigned getMinCmpXchgSizeInBits() const { return MinCmpXchgSizeInBits; } - - /// Whether the target supports unaligned atomic operations. - bool supportsUnalignedAtomics() const { return SupportsUnalignedAtomics; } - - /// Whether AtomicExpandPass should automatically insert fences and reduce - /// ordering for this atomic. This should be true for most architectures with - /// weak memory ordering. Defaults to false. - virtual bool shouldInsertFencesForAtomic(const Instruction *I) const { - return false; - } - - /// Perform a load-linked operation on Addr, returning a "Value *" with the - /// corresponding pointee type. This may entail some non-trivial operations to - /// truncate or reconstruct types that will be illegal in the backend. See - /// ARMISelLowering for an example implementation. - virtual Value *emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, - Value *Addr, AtomicOrdering Ord) const { - llvm_unreachable("Load linked unimplemented on this target"); - } - - /// Perform a store-conditional operation to Addr. Return the status of the - /// store. This should be 0 if the store succeeded, non-zero otherwise. - virtual Value *emitStoreConditional(IRBuilderBase &Builder, Value *Val, - Value *Addr, AtomicOrdering Ord) const { - llvm_unreachable("Store conditional unimplemented on this target"); - } - - /// Perform a masked atomicrmw using a target-specific intrinsic. This - /// represents the core LL/SC loop which will be lowered at a late stage by - /// the backend. - virtual Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, - AtomicRMWInst *AI, - Value *AlignedAddr, Value *Incr, - Value *Mask, Value *ShiftAmt, - AtomicOrdering Ord) const { - llvm_unreachable("Masked atomicrmw expansion unimplemented on this target"); - } - - /// Perform a masked cmpxchg using a target-specific intrinsic. This - /// represents the core LL/SC loop which will be lowered at a late stage by - /// the backend. - virtual Value *emitMaskedAtomicCmpXchgIntrinsic( - IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, - Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const { - llvm_unreachable("Masked cmpxchg expansion unimplemented on this target"); - } - - /// Inserts in the IR a target-specific intrinsic specifying a fence. - /// It is called by AtomicExpandPass before expanding an - /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad - /// if shouldInsertFencesForAtomic returns true. - /// - /// Inst is the original atomic instruction, prior to other expansions that - /// may be performed. - /// - /// This function should either return a nullptr, or a pointer to an IR-level - /// Instruction*. Even complex fence sequences can be represented by a - /// single Instruction* through an intrinsic to be lowered later. - /// Backends should override this method to produce target-specific intrinsic - /// for their fences. - /// FIXME: Please note that the default implementation here in terms of - /// IR-level fences exists for historical/compatibility reasons and is - /// *unsound* ! Fences cannot, in general, be used to restore sequential - /// consistency. For example, consider the following example: - /// atomic x = y = 0; - /// int r1, r2, r3, r4; - /// Thread 0: - /// x.store(1); - /// Thread 1: - /// y.store(1); - /// Thread 2: - /// r1 = x.load(); - /// r2 = y.load(); - /// Thread 3: - /// r3 = y.load(); - /// r4 = x.load(); - /// r1 = r3 = 1 and r2 = r4 = 0 is impossible as long as the accesses are all - /// seq_cst. But if they are lowered to monotonic accesses, no amount of - /// IR-level fences can prevent it. - /// @{ - virtual Instruction *emitLeadingFence(IRBuilderBase &Builder, - Instruction *Inst, - AtomicOrdering Ord) const; - - virtual Instruction *emitTrailingFence(IRBuilderBase &Builder, - Instruction *Inst, - AtomicOrdering Ord) const; - /// @} - - // Emits code that executes when the comparison result in the ll/sc - // expansion of a cmpxchg instruction is such that the store-conditional will - // not execute. This makes it possible to balance out the load-linked with - // a dedicated instruction, if desired. - // E.g., on ARM, if ldrex isn't followed by strex, the exclusive monitor would - // be unnecessarily held, except if clrex, inserted by this hook, is executed. - virtual void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const {} - - /// Returns true if the given (atomic) store should be expanded by the - /// IR-level AtomicExpand pass into an "atomic xchg" which ignores its input. - virtual bool shouldExpandAtomicStoreInIR(StoreInst *SI) const { - return false; - } - - /// Returns true if arguments should be sign-extended in lib calls. - virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - return IsSigned; - } - - /// Returns true if arguments should be extended in lib calls. - virtual bool shouldExtendTypeInLibCall(EVT Type) const { - return true; - } - - /// Returns how the given (atomic) load should be expanded by the - /// IR-level AtomicExpand pass. - virtual AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const { - return AtomicExpansionKind::None; - } - - /// Returns how the given atomic cmpxchg should be expanded by the IR-level - /// AtomicExpand pass. - virtual AtomicExpansionKind - shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const { - return AtomicExpansionKind::None; - } - - /// Returns how the IR-level AtomicExpand pass should expand the given - /// AtomicRMW, if at all. Default is to never expand. - virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { - return RMW->isFloatingPointOperation() ? - AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None; - } - - /// On some platforms, an AtomicRMW that never actually modifies the value - /// (such as fetch_add of 0) can be turned into a fence followed by an - /// atomic load. This may sound useless, but it makes it possible for the - /// processor to keep the cacheline shared, dramatically improving - /// performance. And such idempotent RMWs are useful for implementing some - /// kinds of locks, see for example (justification + benchmarks): - /// http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf - /// This method tries doing that transformation, returning the atomic load if - /// it succeeds, and nullptr otherwise. - /// If shouldExpandAtomicLoadInIR returns true on that load, it will undergo - /// another round of expansion. - virtual LoadInst * - lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { - return nullptr; - } - - /// Returns how the platform's atomic operations are extended (ZERO_EXTEND, - /// SIGN_EXTEND, or ANY_EXTEND). - virtual ISD::NodeType getExtendForAtomicOps() const { - return ISD::ZERO_EXTEND; - } - - /// Returns how the platform's atomic compare and swap expects its comparison - /// value to be extended (ZERO_EXTEND, SIGN_EXTEND, or ANY_EXTEND). This is - /// separate from getExtendForAtomicOps, which is concerned with the - /// sign-extension of the instruction's output, whereas here we are concerned - /// with the sign-extension of the input. For targets with compare-and-swap - /// instructions (or sub-word comparisons in their LL/SC loop expansions), - /// the input can be ANY_EXTEND, but the output will still have a specific - /// extension. - virtual ISD::NodeType getExtendForAtomicCmpSwapArg() const { - return ISD::ANY_EXTEND; - } - - /// @} - - /// Returns true if we should normalize - /// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and - /// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely - /// that it saves us from materializing N0 and N1 in an integer register. - /// Targets that are able to perform and/or on flags should return false here. - virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, - EVT VT) const { - // If a target has multiple condition registers, then it likely has logical - // operations on those registers. - if (hasMultipleConditionRegisters()) - return false; - // Only do the transform if the value won't be split into multiple - // registers. - LegalizeTypeAction Action = getTypeAction(Context, VT); - return Action != TypeExpandInteger && Action != TypeExpandFloat && - Action != TypeSplitVector; - } - - virtual bool isProfitableToCombineMinNumMaxNum(EVT VT) const { return true; } - - /// Return true if a select of constants (select Cond, C1, C2) should be - /// transformed into simple math ops with the condition value. For example: - /// select Cond, C1, C1-1 --> add (zext Cond), C1-1 - virtual bool convertSelectOfConstantsToMath(EVT VT) const { - return false; - } - - /// Return true if it is profitable to transform an integer - /// multiplication-by-constant into simpler operations like shifts and adds. - /// This may be true if the target does not directly support the - /// multiplication operation for the specified type or the sequence of simpler - /// ops is faster than the multiply. - virtual bool decomposeMulByConstant(LLVMContext &Context, - EVT VT, SDValue C) const { - return false; - } - - /// Return true if it may be profitable to transform - /// (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2). - /// This may not be true if c1 and c2 can be represented as immediates but - /// c1*c2 cannot, for example. - /// The target should check if c1, c2 and c1*c2 can be represented as - /// immediates, or have to be materialized into registers. If it is not sure - /// about some cases, a default true can be returned to let the DAGCombiner - /// decide. - /// AddNode is (add x, c1), and ConstNode is c2. - virtual bool isMulAddWithConstProfitable(const SDValue &AddNode, - const SDValue &ConstNode) const { - return true; - } - - /// Return true if it is more correct/profitable to use strict FP_TO_INT - /// conversion operations - canonicalizing the FP source value instead of - /// converting all cases and then selecting based on value. - /// This may be true if the target throws exceptions for out of bounds - /// conversions or has fast FP CMOV. - virtual bool shouldUseStrictFP_TO_INT(EVT FpVT, EVT IntVT, - bool IsSigned) const { - return false; - } - - //===--------------------------------------------------------------------===// - // TargetLowering Configuration Methods - These methods should be invoked by - // the derived class constructor to configure this object for the target. - // -protected: - /// Specify how the target extends the result of integer and floating point - /// boolean values from i1 to a wider type. See getBooleanContents. - void setBooleanContents(BooleanContent Ty) { - BooleanContents = Ty; - BooleanFloatContents = Ty; - } - - /// Specify how the target extends the result of integer and floating point - /// boolean values from i1 to a wider type. See getBooleanContents. - void setBooleanContents(BooleanContent IntTy, BooleanContent FloatTy) { - BooleanContents = IntTy; - BooleanFloatContents = FloatTy; - } - - /// Specify how the target extends the result of a vector boolean value from a - /// vector of i1 to a wider type. See getBooleanContents. - void setBooleanVectorContents(BooleanContent Ty) { - BooleanVectorContents = Ty; - } - - /// Specify the target scheduling preference. - void setSchedulingPreference(Sched::Preference Pref) { - SchedPreferenceInfo = Pref; - } - - /// Indicate the minimum number of blocks to generate jump tables. - void setMinimumJumpTableEntries(unsigned Val); - - /// Indicate the maximum number of entries in jump tables. - /// Set to zero to generate unlimited jump tables. - void setMaximumJumpTableSize(unsigned); - - /// If set to a physical register, this specifies the register that - /// llvm.savestack/llvm.restorestack should save and restore. - void setStackPointerRegisterToSaveRestore(Register R) { - StackPointerRegisterToSaveRestore = R; - } - - /// Tells the code generator that the target has multiple (allocatable) - /// condition registers that can be used to store the results of comparisons - /// for use by selects and conditional branches. With multiple condition - /// registers, the code generator will not aggressively sink comparisons into - /// the blocks of their users. - void setHasMultipleConditionRegisters(bool hasManyRegs = true) { - HasMultipleConditionRegisters = hasManyRegs; - } - - /// Tells the code generator that the target has BitExtract instructions. - /// The code generator will aggressively sink "shift"s into the blocks of - /// their users if the users will generate "and" instructions which can be - /// combined with "shift" to BitExtract instructions. - void setHasExtractBitsInsn(bool hasExtractInsn = true) { - HasExtractBitsInsn = hasExtractInsn; - } - - /// Tells the code generator not to expand logic operations on comparison - /// predicates into separate sequences that increase the amount of flow - /// control. - void setJumpIsExpensive(bool isExpensive = true); - - /// Tells the code generator which bitwidths to bypass. - void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { - BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; - } - - /// Add the specified register class as an available regclass for the - /// specified value type. This indicates the selector can handle values of - /// that class natively. - void addRegisterClass(MVT VT, const TargetRegisterClass *RC) { - assert((unsigned)VT.SimpleTy < array_lengthof(RegClassForVT)); - RegClassForVT[VT.SimpleTy] = RC; - } - - /// Return the largest legal super-reg register class of the register class - /// for the specified type and its associated "cost". - virtual std::pair - findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const; - - /// Once all of the register classes are added, this allows us to compute - /// derived properties we expose. - void computeRegisterProperties(const TargetRegisterInfo *TRI); - - /// Indicate that the specified operation does not work with the specified - /// type and indicate what to do about it. Note that VT may refer to either - /// the type of a result or that of an operand of Op. - void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action) { - assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); - OpActions[(unsigned)VT.SimpleTy][Op] = Action; - } - - /// Indicate that the specified load with extension does not work with the - /// specified type and indicate what to do about it. - void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, - LegalizeAction Action) { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() && - MemVT.isValid() && "Table isn't big enough!"); - assert((unsigned)Action < 0x10 && "too many bits for bitfield array"); - unsigned Shift = 4 * ExtType; - LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= ~((uint16_t)0xF << Shift); - LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= (uint16_t)Action << Shift; - } - - /// Indicate that the specified truncating store does not work with the - /// specified type and indicate what to do about it. - void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { - assert(ValVT.isValid() && MemVT.isValid() && "Table isn't big enough!"); - TruncStoreActions[(unsigned)ValVT.SimpleTy][MemVT.SimpleTy] = Action; - } - - /// Indicate that the specified indexed load does or does not work with the - /// specified type and indicate what to do abort it. - /// - /// NOTE: All indexed mode loads are initialized to Expand in - /// TargetLowering.cpp - void setIndexedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - setIndexedModeAction(IdxMode, VT, IMAB_Load, Action); - } - - /// Indicate that the specified indexed store does or does not work with the - /// specified type and indicate what to do about it. - /// - /// NOTE: All indexed mode stores are initialized to Expand in - /// TargetLowering.cpp - void setIndexedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - setIndexedModeAction(IdxMode, VT, IMAB_Store, Action); - } - - /// Indicate that the specified indexed masked load does or does not work with - /// the specified type and indicate what to do about it. - /// - /// NOTE: All indexed mode masked loads are initialized to Expand in - /// TargetLowering.cpp - void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, - LegalizeAction Action) { - setIndexedModeAction(IdxMode, VT, IMAB_MaskedLoad, Action); - } - - /// Indicate that the specified indexed masked store does or does not work - /// with the specified type and indicate what to do about it. - /// - /// NOTE: All indexed mode masked stores are initialized to Expand in - /// TargetLowering.cpp - void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, - LegalizeAction Action) { - setIndexedModeAction(IdxMode, VT, IMAB_MaskedStore, Action); - } - - /// Indicate that the specified condition code is or isn't supported on the - /// target and indicate what to do about it. - void setCondCodeAction(ISD::CondCode CC, MVT VT, - LegalizeAction Action) { - assert(VT.isValid() && (unsigned)CC < array_lengthof(CondCodeActions) && - "Table isn't big enough!"); - assert((unsigned)Action < 0x10 && "too many bits for bitfield array"); - /// The lower 3 bits of the SimpleTy index into Nth 4bit set from the 32-bit - /// value and the upper 29 bits index into the second dimension of the array - /// to select what 32-bit value to use. - uint32_t Shift = 4 * (VT.SimpleTy & 0x7); - CondCodeActions[CC][VT.SimpleTy >> 3] &= ~((uint32_t)0xF << Shift); - CondCodeActions[CC][VT.SimpleTy >> 3] |= (uint32_t)Action << Shift; - } - - /// If Opc/OrigVT is specified as being promoted, the promotion code defaults - /// to trying a larger integer/fp until it can find one that works. If that - /// default is insufficient, this method can be used by the target to override - /// the default. - void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) { - PromoteToType[std::make_pair(Opc, OrigVT.SimpleTy)] = DestVT.SimpleTy; - } - - /// Convenience method to set an operation to Promote and specify the type - /// in a single call. - void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) { - setOperationAction(Opc, OrigVT, Promote); - AddPromotedToType(Opc, OrigVT, DestVT); - } - - /// Targets should invoke this method for each target independent node that - /// they want to provide a custom DAG combiner for by implementing the - /// PerformDAGCombine virtual method. - void setTargetDAGCombine(ISD::NodeType NT) { - assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); - TargetDAGCombineArray[NT >> 3] |= 1 << (NT&7); - } - - /// Set the target's minimum function alignment. - void setMinFunctionAlignment(Align Alignment) { - MinFunctionAlignment = Alignment; - } - - /// Set the target's preferred function alignment. This should be set if - /// there is a performance benefit to higher-than-minimum alignment - void setPrefFunctionAlignment(Align Alignment) { - PrefFunctionAlignment = Alignment; - } - - /// Set the target's preferred loop alignment. Default alignment is one, it - /// means the target does not care about loop alignment. The target may also - /// override getPrefLoopAlignment to provide per-loop values. - void setPrefLoopAlignment(Align Alignment) { PrefLoopAlignment = Alignment; } - void setMaxBytesForAlignment(unsigned MaxBytes) { - MaxBytesForAlignment = MaxBytes; - } - - /// Set the minimum stack alignment of an argument. - void setMinStackArgumentAlignment(Align Alignment) { - MinStackArgumentAlignment = Alignment; - } - - /// Set the maximum atomic operation size supported by the - /// backend. Atomic operations greater than this size (as well as - /// ones that are not naturally aligned), will be expanded by - /// AtomicExpandPass into an __atomic_* library call. - void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits) { - MaxAtomicSizeInBitsSupported = SizeInBits; - } - - /// Sets the minimum cmpxchg or ll/sc size supported by the backend. - void setMinCmpXchgSizeInBits(unsigned SizeInBits) { - MinCmpXchgSizeInBits = SizeInBits; - } - - /// Sets whether unaligned atomic operations are supported. - void setSupportsUnalignedAtomics(bool UnalignedSupported) { - SupportsUnalignedAtomics = UnalignedSupported; - } - -public: - //===--------------------------------------------------------------------===// - // Addressing mode description hooks (used by LSR etc). - // - - /// CodeGenPrepare sinks address calculations into the same BB as Load/Store - /// instructions reading the address. This allows as much computation as - /// possible to be done in the address mode for that operand. This hook lets - /// targets also pass back when this should be done on intrinsics which - /// load/store. - virtual bool getAddrModeArguments(IntrinsicInst * /*I*/, - SmallVectorImpl &/*Ops*/, - Type *&/*AccessTy*/) const { - return false; - } - - /// This represents an addressing mode of: - /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg - /// If BaseGV is null, there is no BaseGV. - /// If BaseOffs is zero, there is no base offset. - /// If HasBaseReg is false, there is no base register. - /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with - /// no scale. - struct AddrMode { - GlobalValue *BaseGV = nullptr; - int64_t BaseOffs = 0; - bool HasBaseReg = false; - int64_t Scale = 0; - AddrMode() = default; - }; - - /// Return true if the addressing mode represented by AM is legal for this - /// target, for a load/store of the specified type. - /// - /// The type may be VoidTy, in which case only return true if the addressing - /// mode is legal for a load/store of any legal type. TODO: Handle - /// pre/postinc as well. - /// - /// If the address space cannot be determined, it will be -1. - /// - /// TODO: Remove default argument - virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, - Type *Ty, unsigned AddrSpace, - Instruction *I = nullptr) const; - - /// Return the cost of the scaling factor used in the addressing mode - /// represented by AM for this target, for a load/store of the specified type. - /// - /// If the AM is supported, the return value must be >= 0. - /// If the AM is not supported, it returns a negative value. - /// TODO: Handle pre/postinc as well. - /// TODO: Remove default argument - virtual InstructionCost getScalingFactorCost(const DataLayout &DL, - const AddrMode &AM, Type *Ty, - unsigned AS = 0) const { - // Default: assume that any scaling factor used in a legal AM is free. - if (isLegalAddressingMode(DL, AM, Ty, AS)) - return 0; - return -1; - } - - /// Return true if the specified immediate is legal icmp immediate, that is - /// the target has icmp instructions which can compare a register against the - /// immediate without having to materialize the immediate into a register. - virtual bool isLegalICmpImmediate(int64_t) const { - return true; - } - - /// Return true if the specified immediate is legal add immediate, that is the - /// target has add instructions which can add a register with the immediate - /// without having to materialize the immediate into a register. - virtual bool isLegalAddImmediate(int64_t) const { - return true; - } - - /// Return true if the specified immediate is legal for the value input of a - /// store instruction. - virtual bool isLegalStoreImmediate(int64_t Value) const { - // Default implementation assumes that at least 0 works since it is likely - // that a zero register exists or a zero immediate is allowed. - return Value == 0; - } - - /// Return true if it's significantly cheaper to shift a vector by a uniform - /// scalar than by an amount which will vary across each lane. On x86 before - /// AVX2 for example, there is a "psllw" instruction for the former case, but - /// no simple instruction for a general "a << b" operation on vectors. - /// This should also apply to lowering for vector funnel shifts (rotates). - virtual bool isVectorShiftByScalarCheap(Type *Ty) const { - return false; - } - - /// Given a shuffle vector SVI representing a vector splat, return a new - /// scalar type of size equal to SVI's scalar type if the new type is more - /// profitable. Returns nullptr otherwise. For example under MVE float splats - /// are converted to integer to prevent the need to move from SPR to GPR - /// registers. - virtual Type* shouldConvertSplatType(ShuffleVectorInst* SVI) const { - return nullptr; - } - - /// Given a set in interconnected phis of type 'From' that are loaded/stored - /// or bitcast to type 'To', return true if the set should be converted to - /// 'To'. - virtual bool shouldConvertPhiType(Type *From, Type *To) const { - return (From->isIntegerTy() || From->isFloatingPointTy()) && - (To->isIntegerTy() || To->isFloatingPointTy()); - } - - /// Returns true if the opcode is a commutative binary operation. - virtual bool isCommutativeBinOp(unsigned Opcode) const { - // FIXME: This should get its info from the td file. - switch (Opcode) { - case ISD::ADD: - case ISD::SMIN: - case ISD::SMAX: - case ISD::UMIN: - case ISD::UMAX: - case ISD::MUL: - case ISD::MULHU: - case ISD::MULHS: - case ISD::SMUL_LOHI: - case ISD::UMUL_LOHI: - case ISD::FADD: - case ISD::FMUL: - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::SADDO: - case ISD::UADDO: - case ISD::ADDC: - case ISD::ADDE: - case ISD::SADDSAT: - case ISD::UADDSAT: - case ISD::FMINNUM: - case ISD::FMAXNUM: - case ISD::FMINNUM_IEEE: - case ISD::FMAXNUM_IEEE: - case ISD::FMINIMUM: - case ISD::FMAXIMUM: - return true; - default: return false; - } - } - - /// Return true if the node is a math/logic binary operator. - virtual bool isBinOp(unsigned Opcode) const { - // A commutative binop must be a binop. - if (isCommutativeBinOp(Opcode)) - return true; - // These are non-commutative binops. - switch (Opcode) { - case ISD::SUB: - case ISD::SHL: - case ISD::SRL: - case ISD::SRA: - case ISD::ROTL: - case ISD::ROTR: - case ISD::SDIV: - case ISD::UDIV: - case ISD::SREM: - case ISD::UREM: - case ISD::SSUBSAT: - case ISD::USUBSAT: - case ISD::FSUB: - case ISD::FDIV: - case ISD::FREM: - return true; - default: - return false; - } - } - - /// Return true if it's free to truncate a value of type FromTy to type - /// ToTy. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 - /// by referencing its sub-register AX. - /// Targets must return false when FromTy <= ToTy. - virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const { - return false; - } - - /// Return true if a truncation from FromTy to ToTy is permitted when deciding - /// whether a call is in tail position. Typically this means that both results - /// would be assigned to the same register or stack slot, but it could mean - /// the target performs adequate checks of its own before proceeding with the - /// tail call. Targets must return false when FromTy <= ToTy. - virtual bool allowTruncateForTailCall(Type *FromTy, Type *ToTy) const { - return false; - } - - virtual bool isTruncateFree(EVT FromVT, EVT ToVT) const { return false; } - virtual bool isTruncateFree(LLT FromTy, LLT ToTy, const DataLayout &DL, - LLVMContext &Ctx) const { - return isTruncateFree(getApproximateEVTForLLT(FromTy, DL, Ctx), - getApproximateEVTForLLT(ToTy, DL, Ctx)); - } - - virtual bool isProfitableToHoist(Instruction *I) const { return true; } - - /// Return true if the extension represented by \p I is free. - /// Unlikely the is[Z|FP]ExtFree family which is based on types, - /// this method can use the context provided by \p I to decide - /// whether or not \p I is free. - /// This method extends the behavior of the is[Z|FP]ExtFree family. - /// In other words, if is[Z|FP]Free returns true, then this method - /// returns true as well. The converse is not true. - /// The target can perform the adequate checks by overriding isExtFreeImpl. - /// \pre \p I must be a sign, zero, or fp extension. - bool isExtFree(const Instruction *I) const { - switch (I->getOpcode()) { - case Instruction::FPExt: - if (isFPExtFree(EVT::getEVT(I->getType()), - EVT::getEVT(I->getOperand(0)->getType()))) - return true; - break; - case Instruction::ZExt: - if (isZExtFree(I->getOperand(0)->getType(), I->getType())) - return true; - break; - case Instruction::SExt: - break; - default: - llvm_unreachable("Instruction is not an extension"); - } - return isExtFreeImpl(I); - } - - /// Return true if \p Load and \p Ext can form an ExtLoad. - /// For example, in AArch64 - /// %L = load i8, i8* %ptr - /// %E = zext i8 %L to i32 - /// can be lowered into one load instruction - /// ldrb w0, [x0] - bool isExtLoad(const LoadInst *Load, const Instruction *Ext, - const DataLayout &DL) const { - EVT VT = getValueType(DL, Ext->getType()); - EVT LoadVT = getValueType(DL, Load->getType()); - - // If the load has other users and the truncate is not free, the ext - // probably isn't free. - if (!Load->hasOneUse() && (isTypeLegal(LoadVT) || !isTypeLegal(VT)) && - !isTruncateFree(Ext->getType(), Load->getType())) - return false; - - // Check whether the target supports casts folded into loads. - unsigned LType; - if (isa(Ext)) - LType = ISD::ZEXTLOAD; - else { - assert(isa(Ext) && "Unexpected ext type!"); - LType = ISD::SEXTLOAD; - } - - return isLoadExtLegal(LType, VT, LoadVT); - } - - /// Return true if any actual instruction that defines a value of type FromTy - /// implicitly zero-extends the value to ToTy in the result register. - /// - /// The function should return true when it is likely that the truncate can - /// be freely folded with an instruction defining a value of FromTy. If - /// the defining instruction is unknown (because you're looking at a - /// function argument, PHI, etc.) then the target may require an - /// explicit truncate, which is not necessarily free, but this function - /// does not deal with those cases. - /// Targets must return false when FromTy >= ToTy. - virtual bool isZExtFree(Type *FromTy, Type *ToTy) const { - return false; - } - - virtual bool isZExtFree(EVT FromTy, EVT ToTy) const { return false; } - virtual bool isZExtFree(LLT FromTy, LLT ToTy, const DataLayout &DL, - LLVMContext &Ctx) const { - return isZExtFree(getApproximateEVTForLLT(FromTy, DL, Ctx), - getApproximateEVTForLLT(ToTy, DL, Ctx)); - } - - /// Return true if sign-extension from FromTy to ToTy is cheaper than - /// zero-extension. - virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const { - return false; - } - - /// Return true if sinking I's operands to the same basic block as I is - /// profitable, e.g. because the operands can be folded into a target - /// instruction during instruction selection. After calling the function - /// \p Ops contains the Uses to sink ordered by dominance (dominating users - /// come first). - virtual bool shouldSinkOperands(Instruction *I, - SmallVectorImpl &Ops) const { - return false; - } - - /// Return true if the target supplies and combines to a paired load - /// two loaded values of type LoadedType next to each other in memory. - /// RequiredAlignment gives the minimal alignment constraints that must be met - /// to be able to select this paired load. - /// - /// This information is *not* used to generate actual paired loads, but it is - /// used to generate a sequence of loads that is easier to combine into a - /// paired load. - /// For instance, something like this: - /// a = load i64* addr - /// b = trunc i64 a to i32 - /// c = lshr i64 a, 32 - /// d = trunc i64 c to i32 - /// will be optimized into: - /// b = load i32* addr1 - /// d = load i32* addr2 - /// Where addr1 = addr2 +/- sizeof(i32). - /// - /// In other words, unless the target performs a post-isel load combining, - /// this information should not be provided because it will generate more - /// loads. - virtual bool hasPairedLoad(EVT /*LoadedType*/, - Align & /*RequiredAlignment*/) const { - return false; - } - - /// Return true if the target has a vector blend instruction. - virtual bool hasVectorBlend() const { return false; } - - /// Get the maximum supported factor for interleaved memory accesses. - /// Default to be the minimum interleave factor: 2. - virtual unsigned getMaxSupportedInterleaveFactor() const { return 2; } - - /// Lower an interleaved load to target specific intrinsics. Return - /// true on success. - /// - /// \p LI is the vector load instruction. - /// \p Shuffles is the shufflevector list to DE-interleave the loaded vector. - /// \p Indices is the corresponding indices for each shufflevector. - /// \p Factor is the interleave factor. - virtual bool lowerInterleavedLoad(LoadInst *LI, - ArrayRef Shuffles, - ArrayRef Indices, - unsigned Factor) const { - return false; - } - - /// Lower an interleaved store to target specific intrinsics. Return - /// true on success. - /// - /// \p SI is the vector store instruction. - /// \p SVI is the shufflevector to RE-interleave the stored vector. - /// \p Factor is the interleave factor. - virtual bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI, - unsigned Factor) const { - return false; - } - - /// Return true if zero-extending the specific node Val to type VT2 is free - /// (either because it's implicitly zero-extended such as ARM ldrb / ldrh or - /// because it's folded such as X86 zero-extending loads). - virtual bool isZExtFree(SDValue Val, EVT VT2) const { - return isZExtFree(Val.getValueType(), VT2); - } - - /// Return true if an fpext operation is free (for instance, because - /// single-precision floating-point numbers are implicitly extended to - /// double-precision). - virtual bool isFPExtFree(EVT DestVT, EVT SrcVT) const { - assert(SrcVT.isFloatingPoint() && DestVT.isFloatingPoint() && - "invalid fpext types"); - return false; - } - - /// Return true if an fpext operation input to an \p Opcode operation is free - /// (for instance, because half-precision floating-point numbers are - /// implicitly extended to float-precision) for an FMA instruction. - virtual bool isFPExtFoldable(const MachineInstr &MI, unsigned Opcode, - LLT DestTy, LLT SrcTy) const { - return false; - } - - /// Return true if an fpext operation input to an \p Opcode operation is free - /// (for instance, because half-precision floating-point numbers are - /// implicitly extended to float-precision) for an FMA instruction. - virtual bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, - EVT DestVT, EVT SrcVT) const { - assert(DestVT.isFloatingPoint() && SrcVT.isFloatingPoint() && - "invalid fpext types"); - return isFPExtFree(DestVT, SrcVT); - } - - /// Return true if folding a vector load into ExtVal (a sign, zero, or any - /// extend node) is profitable. - virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; } - - /// Return true if an fneg operation is free to the point where it is never - /// worthwhile to replace it with a bitwise operation. - virtual bool isFNegFree(EVT VT) const { - assert(VT.isFloatingPoint()); - return false; - } - - /// Return true if an fabs operation is free to the point where it is never - /// worthwhile to replace it with a bitwise operation. - virtual bool isFAbsFree(EVT VT) const { - assert(VT.isFloatingPoint()); - return false; - } - - /// Return true if an FMA operation is faster than a pair of fmul and fadd - /// instructions. fmuladd intrinsics will be expanded to FMAs when this method - /// returns true, otherwise fmuladd is expanded to fmul + fadd. - /// - /// NOTE: This may be called before legalization on types for which FMAs are - /// not legal, but should return true if those types will eventually legalize - /// to types that support FMAs. After legalization, it will only be called on - /// types that support FMAs (via Legal or Custom actions) - virtual bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, - EVT) const { - return false; - } - - /// Return true if an FMA operation is faster than a pair of fmul and fadd - /// instructions. fmuladd intrinsics will be expanded to FMAs when this method - /// returns true, otherwise fmuladd is expanded to fmul + fadd. - /// - /// NOTE: This may be called before legalization on types for which FMAs are - /// not legal, but should return true if those types will eventually legalize - /// to types that support FMAs. After legalization, it will only be called on - /// types that support FMAs (via Legal or Custom actions) - virtual bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, - LLT) const { - return false; - } - - /// IR version - virtual bool isFMAFasterThanFMulAndFAdd(const Function &F, Type *) const { - return false; - } - - /// Returns true if \p MI can be combined with another instruction to - /// form TargetOpcode::G_FMAD. \p N may be an TargetOpcode::G_FADD, - /// TargetOpcode::G_FSUB, or an TargetOpcode::G_FMUL which will be - /// distributed into an fadd/fsub. - virtual bool isFMADLegal(const MachineInstr &MI, LLT Ty) const { - assert((MI.getOpcode() == TargetOpcode::G_FADD || - MI.getOpcode() == TargetOpcode::G_FSUB || - MI.getOpcode() == TargetOpcode::G_FMUL) && - "unexpected node in FMAD forming combine"); - switch (Ty.getScalarSizeInBits()) { - case 16: - return isOperationLegal(TargetOpcode::G_FMAD, MVT::f16); - case 32: - return isOperationLegal(TargetOpcode::G_FMAD, MVT::f32); - case 64: - return isOperationLegal(TargetOpcode::G_FMAD, MVT::f64); - default: - break; - } - - return false; - } - - /// Returns true if be combined with to form an ISD::FMAD. \p N may be an - /// ISD::FADD, ISD::FSUB, or an ISD::FMUL which will be distributed into an - /// fadd/fsub. - virtual bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const { - assert((N->getOpcode() == ISD::FADD || N->getOpcode() == ISD::FSUB || - N->getOpcode() == ISD::FMUL) && - "unexpected node in FMAD forming combine"); - return isOperationLegal(ISD::FMAD, N->getValueType(0)); - } - - // Return true when the decision to generate FMA's (or FMS, FMLA etc) rather - // than FMUL and ADD is delegated to the machine combiner. - virtual bool generateFMAsInMachineCombiner(EVT VT, - CodeGenOpt::Level OptLevel) const { - return false; - } - - /// Return true if it's profitable to narrow operations of type VT1 to - /// VT2. e.g. on x86, it's profitable to narrow from i32 to i8 but not from - /// i32 to i16. - virtual bool isNarrowingProfitable(EVT /*VT1*/, EVT /*VT2*/) const { - return false; - } - - /// Return true if pulling a binary operation into a select with an identity - /// constant is profitable. This is the inverse of an IR transform. - /// Example: X + (Cond ? Y : 0) --> Cond ? (X + Y) : X - virtual bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, - EVT VT) const { - return false; - } - - /// Return true if it is beneficial to convert a load of a constant to - /// just the constant itself. - /// On some targets it might be more efficient to use a combination of - /// arithmetic instructions to materialize the constant instead of loading it - /// from a constant pool. - virtual bool shouldConvertConstantLoadToIntImm(const APInt &Imm, - Type *Ty) const { - return false; - } - - /// Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type - /// from this source type with this index. This is needed because - /// EXTRACT_SUBVECTOR usually has custom lowering that depends on the index of - /// the first element, and only the target knows which lowering is cheap. - virtual bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, - unsigned Index) const { - return false; - } - - /// Try to convert an extract element of a vector binary operation into an - /// extract element followed by a scalar operation. - virtual bool shouldScalarizeBinop(SDValue VecOp) const { - return false; - } - - /// Return true if extraction of a scalar element from the given vector type - /// at the given index is cheap. For example, if scalar operations occur on - /// the same register file as vector operations, then an extract element may - /// be a sub-register rename rather than an actual instruction. - virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const { - return false; - } - - /// Try to convert math with an overflow comparison into the corresponding DAG - /// node operation. Targets may want to override this independently of whether - /// the operation is legal/custom for the given type because it may obscure - /// matching of other patterns. - virtual bool shouldFormOverflowOp(unsigned Opcode, EVT VT, - bool MathUsed) const { - // TODO: The default logic is inherited from code in CodeGenPrepare. - // The opcode should not make a difference by default? - if (Opcode != ISD::UADDO) - return false; - - // Allow the transform as long as we have an integer type that is not - // obviously illegal and unsupported and if the math result is used - // besides the overflow check. On some targets (e.g. SPARC), it is - // not profitable to form on overflow op if the math result has no - // concrete users. - if (VT.isVector()) - return false; - return MathUsed && (VT.isSimple() || !isOperationExpand(Opcode, VT)); - } - - // Return true if it is profitable to use a scalar input to a BUILD_VECTOR - // even if the vector itself has multiple uses. - virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const { - return false; - } - - // Return true if CodeGenPrepare should consider splitting large offset of a - // GEP to make the GEP fit into the addressing mode and can be sunk into the - // same blocks of its users. - virtual bool shouldConsiderGEPOffsetSplit() const { return false; } - - /// Return true if creating a shift of the type by the given - /// amount is not profitable. - virtual bool shouldAvoidTransformToShift(EVT VT, unsigned Amount) const { - return false; - } - - /// Does this target require the clearing of high-order bits in a register - /// passed to the fp16 to fp conversion library function. - virtual bool shouldKeepZExtForFP16Conv() const { return false; } - - /// Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT - /// from min(max(fptoi)) saturation patterns. - virtual bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const { - return isOperationLegalOrCustom(Op, VT); - } - - //===--------------------------------------------------------------------===// - // Runtime Library hooks - // - - /// Rename the default libcall routine name for the specified libcall. - void setLibcallName(RTLIB::Libcall Call, const char *Name) { - LibcallRoutineNames[Call] = Name; - } - - /// Get the libcall routine name for the specified libcall. - const char *getLibcallName(RTLIB::Libcall Call) const { - return LibcallRoutineNames[Call]; - } - - /// Override the default CondCode to be used to test the result of the - /// comparison libcall against zero. - void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { - CmpLibcallCCs[Call] = CC; - } - - /// Get the CondCode that's to be used to test the result of the comparison - /// libcall against zero. - ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { - return CmpLibcallCCs[Call]; - } - - /// Set the CallingConv that should be used for the specified libcall. - void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { - LibcallCallingConvs[Call] = CC; - } - - /// Get the CallingConv that should be used for the specified libcall. - CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { - return LibcallCallingConvs[Call]; - } - - /// Execute target specific actions to finalize target lowering. - /// This is used to set extra flags in MachineFrameInformation and freezing - /// the set of reserved registers. - /// The default implementation just freezes the set of reserved registers. - virtual void finalizeLowering(MachineFunction &MF) const; - - //===----------------------------------------------------------------------===// - // GlobalISel Hooks - //===----------------------------------------------------------------------===// - /// Check whether or not \p MI needs to be moved close to its uses. - virtual bool shouldLocalize(const MachineInstr &MI, const TargetTransformInfo *TTI) const; - - -private: - const TargetMachine &TM; - - /// Tells the code generator that the target has multiple (allocatable) - /// condition registers that can be used to store the results of comparisons - /// for use by selects and conditional branches. With multiple condition - /// registers, the code generator will not aggressively sink comparisons into - /// the blocks of their users. - bool HasMultipleConditionRegisters; - - /// Tells the code generator that the target has BitExtract instructions. - /// The code generator will aggressively sink "shift"s into the blocks of - /// their users if the users will generate "and" instructions which can be - /// combined with "shift" to BitExtract instructions. - bool HasExtractBitsInsn; - - /// Tells the code generator to bypass slow divide or remainder - /// instructions. For example, BypassSlowDivWidths[32,8] tells the code - /// generator to bypass 32-bit integer div/rem with an 8-bit unsigned integer - /// div/rem when the operands are positive and less than 256. - DenseMap BypassSlowDivWidths; - - /// Tells the code generator that it shouldn't generate extra flow control - /// instructions and should attempt to combine flow control instructions via - /// predication. - bool JumpIsExpensive; - - /// Information about the contents of the high-bits in boolean values held in - /// a type wider than i1. See getBooleanContents. - BooleanContent BooleanContents; - - /// Information about the contents of the high-bits in boolean values held in - /// a type wider than i1. See getBooleanContents. - BooleanContent BooleanFloatContents; - - /// Information about the contents of the high-bits in boolean vector values - /// when the element type is wider than i1. See getBooleanContents. - BooleanContent BooleanVectorContents; - - /// The target scheduling preference: shortest possible total cycles or lowest - /// register usage. - Sched::Preference SchedPreferenceInfo; - - /// The minimum alignment that any argument on the stack needs to have. - Align MinStackArgumentAlignment; - - /// The minimum function alignment (used when optimizing for size, and to - /// prevent explicitly provided alignment from leading to incorrect code). - Align MinFunctionAlignment; - - /// The preferred function alignment (used when alignment unspecified and - /// optimizing for speed). - Align PrefFunctionAlignment; - - /// The preferred loop alignment (in log2 bot in bytes). - Align PrefLoopAlignment; - /// The maximum amount of bytes permitted to be emitted for alignment. - unsigned MaxBytesForAlignment; - - /// Size in bits of the maximum atomics size the backend supports. - /// Accesses larger than this will be expanded by AtomicExpandPass. - unsigned MaxAtomicSizeInBitsSupported; - - /// Size in bits of the minimum cmpxchg or ll/sc operation the - /// backend supports. - unsigned MinCmpXchgSizeInBits; - - /// This indicates if the target supports unaligned atomic operations. - bool SupportsUnalignedAtomics; - - /// If set to a physical register, this specifies the register that - /// llvm.savestack/llvm.restorestack should save and restore. - Register StackPointerRegisterToSaveRestore; - - /// This indicates the default register class to use for each ValueType the - /// target supports natively. - const TargetRegisterClass *RegClassForVT[MVT::VALUETYPE_SIZE]; - uint16_t NumRegistersForVT[MVT::VALUETYPE_SIZE]; - MVT RegisterTypeForVT[MVT::VALUETYPE_SIZE]; - - /// This indicates the "representative" register class to use for each - /// ValueType the target supports natively. This information is used by the - /// scheduler to track register pressure. By default, the representative - /// register class is the largest legal super-reg register class of the - /// register class of the specified type. e.g. On x86, i8, i16, and i32's - /// representative class would be GR32. - const TargetRegisterClass *RepRegClassForVT[MVT::VALUETYPE_SIZE]; - - /// This indicates the "cost" of the "representative" register class for each - /// ValueType. The cost is used by the scheduler to approximate register - /// pressure. - uint8_t RepRegClassCostForVT[MVT::VALUETYPE_SIZE]; - - /// For any value types we are promoting or expanding, this contains the value - /// type that we are changing to. For Expanded types, this contains one step - /// of the expand (e.g. i64 -> i32), even if there are multiple steps required - /// (e.g. i64 -> i16). For types natively supported by the system, this holds - /// the same type (e.g. i32 -> i32). - MVT TransformToType[MVT::VALUETYPE_SIZE]; - - /// For each operation and each value type, keep a LegalizeAction that - /// indicates how instruction selection should deal with the operation. Most - /// operations are Legal (aka, supported natively by the target), but - /// operations that are not should be described. Note that operations on - /// non-legal value types are not described here. - LegalizeAction OpActions[MVT::VALUETYPE_SIZE][ISD::BUILTIN_OP_END]; - - /// For each load extension type and each value type, keep a LegalizeAction - /// that indicates how instruction selection should deal with a load of a - /// specific value type and extension type. Uses 4-bits to store the action - /// for each of the 4 load ext types. - uint16_t LoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; - - /// For each value type pair keep a LegalizeAction that indicates whether a - /// truncating store of a specific value type and truncating type is legal. - LegalizeAction TruncStoreActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; - - /// For each indexed mode and each value type, keep a quad of LegalizeAction - /// that indicates how instruction selection should deal with the load / - /// store / maskedload / maskedstore. - /// - /// The first dimension is the value_type for the reference. The second - /// dimension represents the various modes for load store. - uint16_t IndexedModeActions[MVT::VALUETYPE_SIZE][ISD::LAST_INDEXED_MODE]; - - /// For each condition code (ISD::CondCode) keep a LegalizeAction that - /// indicates how instruction selection should deal with the condition code. - /// - /// Because each CC action takes up 4 bits, we need to have the array size be - /// large enough to fit all of the value types. This can be done by rounding - /// up the MVT::VALUETYPE_SIZE value to the next multiple of 8. - uint32_t CondCodeActions[ISD::SETCC_INVALID][(MVT::VALUETYPE_SIZE + 7) / 8]; - - ValueTypeActionImpl ValueTypeActions; - -private: - LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const; - - /// Targets can specify ISD nodes that they would like PerformDAGCombine - /// callbacks for by calling setTargetDAGCombine(), which sets a bit in this - /// array. - unsigned char - TargetDAGCombineArray[(ISD::BUILTIN_OP_END+CHAR_BIT-1)/CHAR_BIT]; - - /// For operations that must be promoted to a specific type, this holds the - /// destination type. This map should be sparse, so don't hold it as an - /// array. - /// - /// Targets add entries to this map with AddPromotedToType(..), clients access - /// this with getTypeToPromoteTo(..). - std::map, MVT::SimpleValueType> - PromoteToType; - - /// Stores the name each libcall. - const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1]; - - /// The ISD::CondCode that should be used to test the result of each of the - /// comparison libcall against zero. - ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; - - /// Stores the CallingConv that should be used for each libcall. - CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; - - /// Set default libcall names and calling conventions. - void InitLibcalls(const Triple &TT); - - /// The bits of IndexedModeActions used to store the legalisation actions - /// We store the data as | ML | MS | L | S | each taking 4 bits. - enum IndexedModeActionsBits { - IMAB_Store = 0, - IMAB_Load = 4, - IMAB_MaskedStore = 8, - IMAB_MaskedLoad = 12 - }; - - void setIndexedModeAction(unsigned IdxMode, MVT VT, unsigned Shift, - LegalizeAction Action) { - assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE && - (unsigned)Action < 0xf && "Table isn't big enough!"); - unsigned Ty = (unsigned)VT.SimpleTy; - IndexedModeActions[Ty][IdxMode] &= ~(0xf << Shift); - IndexedModeActions[Ty][IdxMode] |= ((uint16_t)Action) << Shift; - } - - LegalizeAction getIndexedModeAction(unsigned IdxMode, MVT VT, - unsigned Shift) const { - assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() && - "Table isn't big enough!"); - unsigned Ty = (unsigned)VT.SimpleTy; - return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] >> Shift) & 0xf); - } - -protected: - /// Return true if the extension represented by \p I is free. - /// \pre \p I is a sign, zero, or fp extension and - /// is[Z|FP]ExtFree of the related types is not true. - virtual bool isExtFreeImpl(const Instruction *I) const { return false; } - - /// Depth that GatherAllAliases should continue looking for chain - /// dependencies when trying to find a more preferable chain. As an - /// approximation, this should be more than the number of consecutive stores - /// expected to be merged. - unsigned GatherAllAliasesMaxDepth; - - /// \brief Specify maximum number of store instructions per memset call. - /// - /// When lowering \@llvm.memset this field specifies the maximum number of - /// store operations that may be substituted for the call to memset. Targets - /// must set this value based on the cost threshold for that target. Targets - /// should assume that the memset will be done using as many of the largest - /// store operations first, followed by smaller ones, if necessary, per - /// alignment restrictions. For example, storing 9 bytes on a 32-bit machine - /// with 16-bit alignment would result in four 2-byte stores and one 1-byte - /// store. This only applies to setting a constant array of a constant size. - unsigned MaxStoresPerMemset; - /// Likewise for functions with the OptSize attribute. - unsigned MaxStoresPerMemsetOptSize; - - /// \brief Specify maximum number of store instructions per memcpy call. - /// - /// When lowering \@llvm.memcpy this field specifies the maximum number of - /// store operations that may be substituted for a call to memcpy. Targets - /// must set this value based on the cost threshold for that target. Targets - /// should assume that the memcpy will be done using as many of the largest - /// store operations first, followed by smaller ones, if necessary, per - /// alignment restrictions. For example, storing 7 bytes on a 32-bit machine - /// with 32-bit alignment would result in one 4-byte store, a one 2-byte store - /// and one 1-byte store. This only applies to copying a constant array of - /// constant size. - unsigned MaxStoresPerMemcpy; - /// Likewise for functions with the OptSize attribute. - unsigned MaxStoresPerMemcpyOptSize; - /// \brief Specify max number of store instructions to glue in inlined memcpy. - /// - /// When memcpy is inlined based on MaxStoresPerMemcpy, specify maximum number - /// of store instructions to keep together. This helps in pairing and - // vectorization later on. - unsigned MaxGluedStoresPerMemcpy = 0; - - /// \brief Specify maximum number of load instructions per memcmp call. - /// - /// When lowering \@llvm.memcmp this field specifies the maximum number of - /// pairs of load operations that may be substituted for a call to memcmp. - /// Targets must set this value based on the cost threshold for that target. - /// Targets should assume that the memcmp will be done using as many of the - /// largest load operations first, followed by smaller ones, if necessary, per - /// alignment restrictions. For example, loading 7 bytes on a 32-bit machine - /// with 32-bit alignment would result in one 4-byte load, a one 2-byte load - /// and one 1-byte load. This only applies to copying a constant array of - /// constant size. - unsigned MaxLoadsPerMemcmp; - /// Likewise for functions with the OptSize attribute. - unsigned MaxLoadsPerMemcmpOptSize; - - /// \brief Specify maximum number of store instructions per memmove call. - /// - /// When lowering \@llvm.memmove this field specifies the maximum number of - /// store instructions that may be substituted for a call to memmove. Targets - /// must set this value based on the cost threshold for that target. Targets - /// should assume that the memmove will be done using as many of the largest - /// store operations first, followed by smaller ones, if necessary, per - /// alignment restrictions. For example, moving 9 bytes on a 32-bit machine - /// with 8-bit alignment would result in nine 1-byte stores. This only - /// applies to copying a constant array of constant size. - unsigned MaxStoresPerMemmove; - /// Likewise for functions with the OptSize attribute. - unsigned MaxStoresPerMemmoveOptSize; - - /// Tells the code generator that select is more expensive than a branch if - /// the branch is usually predicted right. - bool PredictableSelectIsExpensive; - - /// \see enableExtLdPromotion. - bool EnableExtLdPromotion; - - /// Return true if the value types that can be represented by the specified - /// register class are all legal. - bool isLegalRC(const TargetRegisterInfo &TRI, - const TargetRegisterClass &RC) const; - - /// Replace/modify any TargetFrameIndex operands with a target-dependent - /// sequence of memory operands that is recognized by PrologEpilogInserter. - MachineBasicBlock *emitPatchPoint(MachineInstr &MI, - MachineBasicBlock *MBB) const; - - bool IsStrictFPEnabled; -}; - -/// This class defines information used to lower LLVM code to legal SelectionDAG -/// operators that the target instruction selector can accept natively. -/// -/// This class also defines callbacks that targets must implement to lower -/// target-specific constructs to SelectionDAG operators. -class TargetLowering : public TargetLoweringBase { -public: - struct DAGCombinerInfo; - struct MakeLibCallOptions; - - TargetLowering(const TargetLowering &) = delete; - TargetLowering &operator=(const TargetLowering &) = delete; - - explicit TargetLowering(const TargetMachine &TM); - - bool isPositionIndependent() const; - - virtual bool isSDNodeSourceOfDivergence(const SDNode *N, - FunctionLoweringInfo *FLI, - LegacyDivergenceAnalysis *DA) const { - return false; - } - - // Lets target to control the following reassociation of operands: (op (op x, - // c1), y) -> (op (op x, y), c1) where N0 is (op x, c1) and N1 is y. By - // default consider profitable any case where N0 has single use. This - // behavior reflects the condition replaced by this target hook call in the - // DAGCombiner. Any particular target can implement its own heuristic to - // restrict common combiner. - virtual bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, - SDValue N1) const { - return N0.hasOneUse(); - } - - virtual bool isSDNodeAlwaysUniform(const SDNode * N) const { - return false; - } - - /// Returns true by value, base pointer and offset pointer and addressing mode - /// by reference if the node's address can be legally represented as - /// pre-indexed load / store address. - virtual bool getPreIndexedAddressParts(SDNode * /*N*/, SDValue &/*Base*/, - SDValue &/*Offset*/, - ISD::MemIndexedMode &/*AM*/, - SelectionDAG &/*DAG*/) const { - return false; - } - - /// Returns true by value, base pointer and offset pointer and addressing mode - /// by reference if this node can be combined with a load / store to form a - /// post-indexed load / store. - virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, - SDValue &/*Base*/, - SDValue &/*Offset*/, - ISD::MemIndexedMode &/*AM*/, - SelectionDAG &/*DAG*/) const { - return false; - } - - /// Returns true if the specified base+offset is a legal indexed addressing - /// mode for this target. \p MI is the load or store instruction that is being - /// considered for transformation. - virtual bool isIndexingLegal(MachineInstr &MI, Register Base, Register Offset, - bool IsPre, MachineRegisterInfo &MRI) const { - return false; - } - - /// Return the entry encoding for a jump table in the current function. The - /// returned value is a member of the MachineJumpTableInfo::JTEntryKind enum. - virtual unsigned getJumpTableEncoding() const; - - virtual const MCExpr * - LowerCustomJumpTableEntry(const MachineJumpTableInfo * /*MJTI*/, - const MachineBasicBlock * /*MBB*/, unsigned /*uid*/, - MCContext &/*Ctx*/) const { - llvm_unreachable("Need to implement this hook if target has custom JTIs"); - } - - /// Returns relocation base for the given PIC jumptable. - virtual SDValue getPICJumpTableRelocBase(SDValue Table, - SelectionDAG &DAG) const; - - /// This returns the relocation base for the given PIC jumptable, the same as - /// getPICJumpTableRelocBase, but as an MCExpr. - virtual const MCExpr * - getPICJumpTableRelocBaseExpr(const MachineFunction *MF, - unsigned JTI, MCContext &Ctx) const; - - /// Return true if folding a constant offset with the given GlobalAddress is - /// legal. It is frequently not legal in PIC relocation models. - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; - - bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, - SDValue &Chain) const; - - void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, - SDValue &NewRHS, ISD::CondCode &CCCode, - const SDLoc &DL, const SDValue OldLHS, - const SDValue OldRHS) const; - - void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, - SDValue &NewRHS, ISD::CondCode &CCCode, - const SDLoc &DL, const SDValue OldLHS, - const SDValue OldRHS, SDValue &Chain, - bool IsSignaling = false) const; - - /// Returns a pair of (return value, chain). - /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC. - std::pair makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, - EVT RetVT, ArrayRef Ops, - MakeLibCallOptions CallOptions, - const SDLoc &dl, - SDValue Chain = SDValue()) const; - - /// Check whether parameters to a call that are passed in callee saved - /// registers are the same as from the calling function. This needs to be - /// checked for tail call eligibility. - bool parametersInCSRMatch(const MachineRegisterInfo &MRI, - const uint32_t *CallerPreservedMask, - const SmallVectorImpl &ArgLocs, - const SmallVectorImpl &OutVals) const; - - //===--------------------------------------------------------------------===// - // TargetLowering Optimization Methods - // - - /// A convenience struct that encapsulates a DAG, and two SDValues for - /// returning information from TargetLowering to its clients that want to - /// combine. - struct TargetLoweringOpt { - SelectionDAG &DAG; - bool LegalTys; - bool LegalOps; - SDValue Old; - SDValue New; - - explicit TargetLoweringOpt(SelectionDAG &InDAG, - bool LT, bool LO) : - DAG(InDAG), LegalTys(LT), LegalOps(LO) {} - - bool LegalTypes() const { return LegalTys; } - bool LegalOperations() const { return LegalOps; } - - bool CombineTo(SDValue O, SDValue N) { - Old = O; - New = N; - return true; - } - }; - - /// Determines the optimal series of memory ops to replace the memset / memcpy. - /// Return true if the number of memory ops is below the threshold (Limit). - /// It returns the types of the sequence of memory ops to perform - /// memset / memcpy by reference. - bool findOptimalMemOpLowering(std::vector &MemOps, unsigned Limit, - const MemOp &Op, unsigned DstAS, unsigned SrcAS, - const AttributeList &FuncAttributes) const; - - /// Check to see if the specified operand of the specified instruction is a - /// constant integer. If so, check to see if there are any bits set in the - /// constant that are not demanded. If so, shrink the constant and return - /// true. - bool ShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, - const APInt &DemandedElts, - TargetLoweringOpt &TLO) const; - - /// Helper wrapper around ShrinkDemandedConstant, demanding all elements. - bool ShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, - TargetLoweringOpt &TLO) const; - - // Target hook to do target-specific const optimization, which is called by - // ShrinkDemandedConstant. This function should return true if the target - // doesn't want ShrinkDemandedConstant to further optimize the constant. - virtual bool targetShrinkDemandedConstant(SDValue Op, - const APInt &DemandedBits, - const APInt &DemandedElts, - TargetLoweringOpt &TLO) const { - return false; - } - - /// Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the casts are free. This - /// uses isZExtFree and ZERO_EXTEND for the widening cast, but it could be - /// generalized for targets with other types of implicit widening casts. - bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, - TargetLoweringOpt &TLO) const; - - /// Look at Op. At this point, we know that only the DemandedBits bits of the - /// result of Op are ever used downstream. If we can use this information to - /// simplify Op, create a new simplified DAG node and return true, returning - /// the original and new nodes in Old and New. Otherwise, analyze the - /// expression and return a mask of KnownOne and KnownZero bits for the - /// expression (used to simplify the caller). The KnownZero/One bits may only - /// be accurate for those bits in the Demanded masks. - /// \p AssumeSingleUse When this parameter is true, this function will - /// attempt to simplify \p Op even if there are multiple uses. - /// Callers are responsible for correctly updating the DAG based on the - /// results of this function, because simply replacing TLO.Old - /// with TLO.New will be incorrect when this parameter is true and TLO.Old - /// has multiple uses. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, - const APInt &DemandedElts, KnownBits &Known, - TargetLoweringOpt &TLO, unsigned Depth = 0, - bool AssumeSingleUse = false) const; - - /// Helper wrapper around SimplifyDemandedBits, demanding all elements. - /// Adds Op back to the worklist upon success. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, - KnownBits &Known, TargetLoweringOpt &TLO, - unsigned Depth = 0, - bool AssumeSingleUse = false) const; - - /// Helper wrapper around SimplifyDemandedBits. - /// Adds Op back to the worklist upon success. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, - DAGCombinerInfo &DCI) const; - - /// Helper wrapper around SimplifyDemandedBits. - /// Adds Op back to the worklist upon success. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, - const APInt &DemandedElts, - DAGCombinerInfo &DCI) const; - - /// More limited version of SimplifyDemandedBits that can be used to "look - /// through" ops that don't contribute to the DemandedBits/DemandedElts - - /// bitwise ops etc. - SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, - const APInt &DemandedElts, - SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// Helper wrapper around SimplifyMultipleUseDemandedBits, demanding all - /// elements. - SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, - SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// Helper wrapper around SimplifyMultipleUseDemandedBits, demanding all - /// bits from only some vector elements. - SDValue SimplifyMultipleUseDemandedVectorElts(SDValue Op, - const APInt &DemandedElts, - SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// Look at Vector Op. At this point, we know that only the DemandedElts - /// elements of the result of Op are ever used downstream. If we can use - /// this information to simplify Op, create a new simplified DAG node and - /// return true, storing the original and new nodes in TLO. - /// Otherwise, analyze the expression and return a mask of KnownUndef and - /// KnownZero elements for the expression (used to simplify the caller). - /// The KnownUndef/Zero elements may only be accurate for those bits - /// in the DemandedMask. - /// \p AssumeSingleUse When this parameter is true, this function will - /// attempt to simplify \p Op even if there are multiple uses. - /// Callers are responsible for correctly updating the DAG based on the - /// results of this function, because simply replacing TLO.Old - /// with TLO.New will be incorrect when this parameter is true and TLO.Old - /// has multiple uses. - bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, - APInt &KnownUndef, APInt &KnownZero, - TargetLoweringOpt &TLO, unsigned Depth = 0, - bool AssumeSingleUse = false) const; - - /// Helper wrapper around SimplifyDemandedVectorElts. - /// Adds Op back to the worklist upon success. - bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedElts, - APInt &KnownUndef, APInt &KnownZero, - DAGCombinerInfo &DCI) const; - - /// Determine which of the bits specified in Mask are known to be either zero - /// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts - /// argument allows us to only collect the known bits that are shared by the - /// requested vector elements. - virtual void computeKnownBitsForTargetNode(const SDValue Op, - KnownBits &Known, - const APInt &DemandedElts, - const SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// Determine which of the bits specified in Mask are known to be either zero - /// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts - /// argument allows us to only collect the known bits that are shared by the - /// requested vector elements. This is for GISel. - virtual void computeKnownBitsForTargetInstr(GISelKnownBits &Analysis, - Register R, KnownBits &Known, - const APInt &DemandedElts, - const MachineRegisterInfo &MRI, - unsigned Depth = 0) const; - - /// Determine the known alignment for the pointer value \p R. This is can - /// typically be inferred from the number of low known 0 bits. However, for a - /// pointer with a non-integral address space, the alignment value may be - /// independent from the known low bits. - virtual Align computeKnownAlignForTargetInstr(GISelKnownBits &Analysis, - Register R, - const MachineRegisterInfo &MRI, - unsigned Depth = 0) const; - - /// Determine which of the bits of FrameIndex \p FIOp are known to be 0. - /// Default implementation computes low bits based on alignment - /// information. This should preserve known bits passed into it. - virtual void computeKnownBitsForFrameIndex(int FIOp, - KnownBits &Known, - const MachineFunction &MF) const; - - /// This method can be implemented by targets that want to expose additional - /// information about sign bits to the DAG Combiner. The DemandedElts - /// argument allows us to only collect the minimum sign bits that are shared - /// by the requested vector elements. - virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, - const APInt &DemandedElts, - const SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// This method can be implemented by targets that want to expose additional - /// information about sign bits to GlobalISel combiners. The DemandedElts - /// argument allows us to only collect the minimum sign bits that are shared - /// by the requested vector elements. - virtual unsigned computeNumSignBitsForTargetInstr(GISelKnownBits &Analysis, - Register R, - const APInt &DemandedElts, - const MachineRegisterInfo &MRI, - unsigned Depth = 0) const; - - /// Attempt to simplify any target nodes based on the demanded vector - /// elements, returning true on success. Otherwise, analyze the expression and - /// return a mask of KnownUndef and KnownZero elements for the expression - /// (used to simplify the caller). The KnownUndef/Zero elements may only be - /// accurate for those bits in the DemandedMask. - virtual bool SimplifyDemandedVectorEltsForTargetNode( - SDValue Op, const APInt &DemandedElts, APInt &KnownUndef, - APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth = 0) const; - - /// Attempt to simplify any target nodes based on the demanded bits/elts, - /// returning true on success. Otherwise, analyze the - /// expression and return a mask of KnownOne and KnownZero bits for the - /// expression (used to simplify the caller). The KnownZero/One bits may only - /// be accurate for those bits in the Demanded masks. - virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, - const APInt &DemandedBits, - const APInt &DemandedElts, - KnownBits &Known, - TargetLoweringOpt &TLO, - unsigned Depth = 0) const; - - /// More limited version of SimplifyDemandedBits that can be used to "look - /// through" ops that don't contribute to the DemandedBits/DemandedElts - - /// bitwise ops etc. - virtual SDValue SimplifyMultipleUseDemandedBitsForTargetNode( - SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, - SelectionDAG &DAG, unsigned Depth) const; - - /// Return true if this function can prove that \p Op is never poison - /// and, if \p PoisonOnly is false, does not have undef bits. The DemandedElts - /// argument limits the check to the requested vector elements. - virtual bool isGuaranteedNotToBeUndefOrPoisonForTargetNode( - SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, - bool PoisonOnly, unsigned Depth) const; - - /// Tries to build a legal vector shuffle using the provided parameters - /// or equivalent variations. The Mask argument maybe be modified as the - /// function tries different variations. - /// Returns an empty SDValue if the operation fails. - SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, - SDValue N1, MutableArrayRef Mask, - SelectionDAG &DAG) const; - - /// This method returns the constant pool value that will be loaded by LD. - /// NOTE: You must check for implicit extensions of the constant by LD. - virtual const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const; - - /// If \p SNaN is false, \returns true if \p Op is known to never be any - /// NaN. If \p sNaN is true, returns if \p Op is known to never be a signaling - /// NaN. - virtual bool isKnownNeverNaNForTargetNode(SDValue Op, - const SelectionDAG &DAG, - bool SNaN = false, - unsigned Depth = 0) const; - - /// Return true if vector \p Op has the same value across all \p DemandedElts, - /// indicating any elements which may be undef in the output \p UndefElts. - virtual bool isSplatValueForTargetNode(SDValue Op, const APInt &DemandedElts, - APInt &UndefElts, - unsigned Depth = 0) const; - - struct DAGCombinerInfo { - void *DC; // The DAG Combiner object. - CombineLevel Level; - bool CalledByLegalizer; - - public: - SelectionDAG &DAG; - - DAGCombinerInfo(SelectionDAG &dag, CombineLevel level, bool cl, void *dc) - : DC(dc), Level(level), CalledByLegalizer(cl), DAG(dag) {} - - bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; } - bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; } - bool isAfterLegalizeDAG() const { return Level >= AfterLegalizeDAG; } - CombineLevel getDAGCombineLevel() { return Level; } - bool isCalledByLegalizer() const { return CalledByLegalizer; } - - void AddToWorklist(SDNode *N); - SDValue CombineTo(SDNode *N, ArrayRef To, bool AddTo = true); - SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); - SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true); - - bool recursivelyDeleteUnusedNodes(SDNode *N); - - void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); - }; - - /// Return if the N is a constant or constant vector equal to the true value - /// from getBooleanContents(). - bool isConstTrueVal(SDValue N) const; - - /// Return if the N is a constant or constant vector equal to the false value - /// from getBooleanContents(). - bool isConstFalseVal(SDValue N) const; - - /// Return if \p N is a True value when extended to \p VT. - bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool SExt) const; - - /// Try to simplify a setcc built with the specified operands and cc. If it is - /// unable to simplify it, return a null SDValue. - SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, - bool foldBooleans, DAGCombinerInfo &DCI, - const SDLoc &dl) const; - - // For targets which wrap address, unwrap for analysis. - virtual SDValue unwrapAddress(SDValue N) const { return N; } - - /// Returns true (and the GlobalValue and the offset) if the node is a - /// GlobalAddress + offset. - virtual bool - isGAPlusOffset(SDNode *N, const GlobalValue* &GA, int64_t &Offset) const; - - /// This method will be invoked for all target nodes and for any - /// target-independent nodes that the target has registered with invoke it - /// for. - /// - /// The semantics are as follows: - /// Return Value: - /// SDValue.Val == 0 - No change was made - /// SDValue.Val == N - N was replaced, is dead, and is already handled. - /// otherwise - N should be replaced by the returned Operand. - /// - /// In addition, methods provided by DAGCombinerInfo may be used to perform - /// more complex transformations. - /// - virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; - - /// Return true if it is profitable to move this shift by a constant amount - /// though its operand, adjusting any immediate operands as necessary to - /// preserve semantics. This transformation may not be desirable if it - /// disrupts a particularly auspicious target-specific tree (e.g. bitfield - /// extraction in AArch64). By default, it returns true. - /// - /// @param N the shift node - /// @param Level the current DAGCombine legalization level. - virtual bool isDesirableToCommuteWithShift(const SDNode *N, - CombineLevel Level) const { - return true; - } - - /// Return true if the target has native support for the specified value type - /// and it is 'desirable' to use the type for the given node type. e.g. On x86 - /// i16 is legal, but undesirable since i16 instruction encodings are longer - /// and some i16 instructions are slow. - virtual bool isTypeDesirableForOp(unsigned /*Opc*/, EVT VT) const { - // By default, assume all legal types are desirable. - return isTypeLegal(VT); - } - - /// Return true if it is profitable for dag combiner to transform a floating - /// point op of specified opcode to a equivalent op of an integer - /// type. e.g. f32 load -> i32 load can be profitable on ARM. - virtual bool isDesirableToTransformToIntegerOp(unsigned /*Opc*/, - EVT /*VT*/) const { - return false; - } - - /// This method query the target whether it is beneficial for dag combiner to - /// promote the specified node. If true, it should return the desired - /// promotion type by reference. - virtual bool IsDesirableToPromoteOp(SDValue /*Op*/, EVT &/*PVT*/) const { - return false; - } - - /// Return true if the target supports swifterror attribute. It optimizes - /// loads and stores to reading and writing a specific register. - virtual bool supportSwiftError() const { - return false; - } - - /// Return true if the target supports that a subset of CSRs for the given - /// machine function is handled explicitly via copies. - virtual bool supportSplitCSR(MachineFunction *MF) const { - return false; - } - - /// Perform necessary initialization to handle a subset of CSRs explicitly - /// via copies. This function is called at the beginning of instruction - /// selection. - virtual void initializeSplitCSR(MachineBasicBlock *Entry) const { - llvm_unreachable("Not Implemented"); - } - - /// Insert explicit copies in entry and exit blocks. We copy a subset of - /// CSRs to virtual registers in the entry block, and copy them back to - /// physical registers in the exit blocks. This function is called at the end - /// of instruction selection. - virtual void insertCopiesSplitCSR( - MachineBasicBlock *Entry, - const SmallVectorImpl &Exits) const { - llvm_unreachable("Not Implemented"); - } - - /// Return the newly negated expression if the cost is not expensive and - /// set the cost in \p Cost to indicate that if it is cheaper or neutral to - /// do the negation. - virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, - bool LegalOps, bool OptForSize, - NegatibleCost &Cost, - unsigned Depth = 0) const; - - /// This is the helper function to return the newly negated expression only - /// when the cost is cheaper. - SDValue getCheaperNegatedExpression(SDValue Op, SelectionDAG &DAG, - bool LegalOps, bool OptForSize, - unsigned Depth = 0) const { - NegatibleCost Cost = NegatibleCost::Expensive; - SDValue Neg = - getNegatedExpression(Op, DAG, LegalOps, OptForSize, Cost, Depth); - if (Neg && Cost == NegatibleCost::Cheaper) - return Neg; - // Remove the new created node to avoid the side effect to the DAG. - if (Neg && Neg.getNode()->use_empty()) - DAG.RemoveDeadNode(Neg.getNode()); - return SDValue(); - } - - /// This is the helper function to return the newly negated expression if - /// the cost is not expensive. - SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, - bool OptForSize, unsigned Depth = 0) const { - NegatibleCost Cost = NegatibleCost::Expensive; - return getNegatedExpression(Op, DAG, LegalOps, OptForSize, Cost, Depth); - } - - //===--------------------------------------------------------------------===// - // Lowering methods - These methods must be implemented by targets so that - // the SelectionDAGBuilder code knows how to lower these. - // - - /// Target-specific splitting of values into parts that fit a register - /// storing a legal type - virtual bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, - SDValue Val, SDValue *Parts, - unsigned NumParts, MVT PartVT, - Optional CC) const { - return false; - } - - /// Target-specific combining of register parts into its original value - virtual SDValue - joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, - const SDValue *Parts, unsigned NumParts, - MVT PartVT, EVT ValueVT, - Optional CC) const { - return SDValue(); - } - - /// This hook must be implemented to lower the incoming (formal) arguments, - /// described by the Ins array, into the specified DAG. The implementation - /// should fill in the InVals array with legal-type argument values, and - /// return the resulting token chain value. - virtual SDValue LowerFormalArguments( - SDValue /*Chain*/, CallingConv::ID /*CallConv*/, bool /*isVarArg*/, - const SmallVectorImpl & /*Ins*/, const SDLoc & /*dl*/, - SelectionDAG & /*DAG*/, SmallVectorImpl & /*InVals*/) const { - llvm_unreachable("Not Implemented"); - } - - /// This structure contains all information that is necessary for lowering - /// calls. It is passed to TLI::LowerCallTo when the SelectionDAG builder - /// needs to lower a call, and targets will see this struct in their LowerCall - /// implementation. - struct CallLoweringInfo { - SDValue Chain; - Type *RetTy = nullptr; - bool RetSExt : 1; - bool RetZExt : 1; - bool IsVarArg : 1; - bool IsInReg : 1; - bool DoesNotReturn : 1; - bool IsReturnValueUsed : 1; - bool IsConvergent : 1; - bool IsPatchPoint : 1; - bool IsPreallocated : 1; - bool NoMerge : 1; - - // IsTailCall should be modified by implementations of - // TargetLowering::LowerCall that perform tail call conversions. - bool IsTailCall = false; - - // Is Call lowering done post SelectionDAG type legalization. - bool IsPostTypeLegalization = false; - - unsigned NumFixedArgs = -1; - CallingConv::ID CallConv = CallingConv::C; - SDValue Callee; - ArgListTy Args; - SelectionDAG &DAG; - SDLoc DL; - const CallBase *CB = nullptr; - SmallVector Outs; - SmallVector OutVals; - SmallVector Ins; - SmallVector InVals; - - CallLoweringInfo(SelectionDAG &DAG) - : RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), - DoesNotReturn(false), IsReturnValueUsed(true), IsConvergent(false), - IsPatchPoint(false), IsPreallocated(false), NoMerge(false), - DAG(DAG) {} - - CallLoweringInfo &setDebugLoc(const SDLoc &dl) { - DL = dl; - return *this; - } - - CallLoweringInfo &setChain(SDValue InChain) { - Chain = InChain; - return *this; - } - - // setCallee with target/module-specific attributes - CallLoweringInfo &setLibCallee(CallingConv::ID CC, Type *ResultType, - SDValue Target, ArgListTy &&ArgsList) { - RetTy = ResultType; - Callee = Target; - CallConv = CC; - NumFixedArgs = ArgsList.size(); - Args = std::move(ArgsList); - - DAG.getTargetLoweringInfo().markLibCallAttributes( - &(DAG.getMachineFunction()), CC, Args); - return *this; - } - - CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType, - SDValue Target, ArgListTy &&ArgsList) { - RetTy = ResultType; - Callee = Target; - CallConv = CC; - NumFixedArgs = ArgsList.size(); - Args = std::move(ArgsList); - return *this; - } - - CallLoweringInfo &setCallee(Type *ResultType, FunctionType *FTy, - SDValue Target, ArgListTy &&ArgsList, - const CallBase &Call) { - RetTy = ResultType; - - IsInReg = Call.hasRetAttr(Attribute::InReg); - DoesNotReturn = - Call.doesNotReturn() || - (!isa(Call) && isa(Call.getNextNode())); - IsVarArg = FTy->isVarArg(); - IsReturnValueUsed = !Call.use_empty(); - RetSExt = Call.hasRetAttr(Attribute::SExt); - RetZExt = Call.hasRetAttr(Attribute::ZExt); - NoMerge = Call.hasFnAttr(Attribute::NoMerge); - - Callee = Target; - - CallConv = Call.getCallingConv(); - NumFixedArgs = FTy->getNumParams(); - Args = std::move(ArgsList); - - CB = &Call; - - return *this; - } - - CallLoweringInfo &setInRegister(bool Value = true) { - IsInReg = Value; - return *this; - } - - CallLoweringInfo &setNoReturn(bool Value = true) { - DoesNotReturn = Value; - return *this; - } - - CallLoweringInfo &setVarArg(bool Value = true) { - IsVarArg = Value; - return *this; - } - - CallLoweringInfo &setTailCall(bool Value = true) { - IsTailCall = Value; - return *this; - } - - CallLoweringInfo &setDiscardResult(bool Value = true) { - IsReturnValueUsed = !Value; - return *this; - } - - CallLoweringInfo &setConvergent(bool Value = true) { - IsConvergent = Value; - return *this; - } - - CallLoweringInfo &setSExtResult(bool Value = true) { - RetSExt = Value; - return *this; - } - - CallLoweringInfo &setZExtResult(bool Value = true) { - RetZExt = Value; - return *this; - } - - CallLoweringInfo &setIsPatchPoint(bool Value = true) { - IsPatchPoint = Value; - return *this; - } - - CallLoweringInfo &setIsPreallocated(bool Value = true) { - IsPreallocated = Value; - return *this; - } - - CallLoweringInfo &setIsPostTypeLegalization(bool Value=true) { - IsPostTypeLegalization = Value; - return *this; - } - - ArgListTy &getArgs() { - return Args; - } - }; - - /// This structure is used to pass arguments to makeLibCall function. - struct MakeLibCallOptions { - // By passing type list before soften to makeLibCall, the target hook - // shouldExtendTypeInLibCall can get the original type before soften. - ArrayRef OpsVTBeforeSoften; - EVT RetVTBeforeSoften; - bool IsSExt : 1; - bool DoesNotReturn : 1; - bool IsReturnValueUsed : 1; - bool IsPostTypeLegalization : 1; - bool IsSoften : 1; - - MakeLibCallOptions() - : IsSExt(false), DoesNotReturn(false), IsReturnValueUsed(true), - IsPostTypeLegalization(false), IsSoften(false) {} - - MakeLibCallOptions &setSExt(bool Value = true) { - IsSExt = Value; - return *this; - } - - MakeLibCallOptions &setNoReturn(bool Value = true) { - DoesNotReturn = Value; - return *this; - } - - MakeLibCallOptions &setDiscardResult(bool Value = true) { - IsReturnValueUsed = !Value; - return *this; - } - - MakeLibCallOptions &setIsPostTypeLegalization(bool Value = true) { - IsPostTypeLegalization = Value; - return *this; - } - - MakeLibCallOptions &setTypeListBeforeSoften(ArrayRef OpsVT, EVT RetVT, - bool Value = true) { - OpsVTBeforeSoften = OpsVT; - RetVTBeforeSoften = RetVT; - IsSoften = Value; - return *this; - } - }; - - /// This function lowers an abstract call to a function into an actual call. - /// This returns a pair of operands. The first element is the return value - /// for the function (if RetTy is not VoidTy). The second element is the - /// outgoing token chain. It calls LowerCall to do the actual lowering. - std::pair LowerCallTo(CallLoweringInfo &CLI) const; - - /// This hook must be implemented to lower calls into the specified - /// DAG. The outgoing arguments to the call are described by the Outs array, - /// and the values to be returned by the call are described by the Ins - /// array. The implementation should fill in the InVals array with legal-type - /// return values from the call, and return the resulting token chain value. - virtual SDValue - LowerCall(CallLoweringInfo &/*CLI*/, - SmallVectorImpl &/*InVals*/) const { - llvm_unreachable("Not Implemented"); - } - - /// Target-specific cleanup for formal ByVal parameters. - virtual void HandleByVal(CCState *, unsigned &, Align) const {} - - /// This hook should be implemented to check whether the return values - /// described by the Outs array can fit into the return registers. If false - /// is returned, an sret-demotion is performed. - virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, - MachineFunction &/*MF*/, bool /*isVarArg*/, - const SmallVectorImpl &/*Outs*/, - LLVMContext &/*Context*/) const - { - // Return true by default to get preexisting behavior. - return true; - } - - /// This hook must be implemented to lower outgoing return values, described - /// by the Outs array, into the specified DAG. The implementation should - /// return the resulting token chain value. - virtual SDValue LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, - bool /*isVarArg*/, - const SmallVectorImpl & /*Outs*/, - const SmallVectorImpl & /*OutVals*/, - const SDLoc & /*dl*/, - SelectionDAG & /*DAG*/) const { - llvm_unreachable("Not Implemented"); - } - - /// Return true if result of the specified node is used by a return node - /// only. It also compute and return the input chain for the tail call. - /// - /// This is used to determine whether it is possible to codegen a libcall as - /// tail call at legalization time. - virtual bool isUsedByReturnOnly(SDNode *, SDValue &/*Chain*/) const { - return false; - } - - /// Return true if the target may be able emit the call instruction as a tail - /// call. This is used by optimization passes to determine if it's profitable - /// to duplicate return instructions to enable tailcall optimization. - virtual bool mayBeEmittedAsTailCall(const CallInst *) const { - return false; - } - - /// Return the builtin name for the __builtin___clear_cache intrinsic - /// Default is to invoke the clear cache library call - virtual const char * getClearCacheBuiltinName() const { - return "__clear_cache"; - } - - /// Return the register ID of the name passed in. Used by named register - /// global variables extension. There is no target-independent behaviour - /// so the default action is to bail. - virtual Register getRegisterByName(const char* RegName, LLT Ty, - const MachineFunction &MF) const { - report_fatal_error("Named registers not implemented for this target"); - } - - /// Return the type that should be used to zero or sign extend a - /// zeroext/signext integer return value. FIXME: Some C calling conventions - /// require the return type to be promoted, but this is not true all the time, - /// e.g. i1/i8/i16 on x86/x86_64. It is also not necessary for non-C calling - /// conventions. The frontend should handle this and include all of the - /// necessary information. - virtual EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, - ISD::NodeType /*ExtendKind*/) const { - EVT MinVT = getRegisterType(Context, MVT::i32); - return VT.bitsLT(MinVT) ? MinVT : VT; - } - - /// For some targets, an LLVM struct type must be broken down into multiple - /// simple types, but the calling convention specifies that the entire struct - /// must be passed in a block of consecutive registers. - virtual bool - functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, - bool isVarArg, - const DataLayout &DL) const { - return false; - } - - /// For most targets, an LLVM type must be broken down into multiple - /// smaller types. Usually the halves are ordered according to the endianness - /// but for some platform that would break. So this method will default to - /// matching the endianness but can be overridden. - virtual bool - shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) const { - return DL.isLittleEndian(); - } - - /// Returns a 0 terminated array of registers that can be safely used as - /// scratch registers. - virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const { - return nullptr; - } - - /// This callback is used to prepare for a volatile or atomic load. - /// It takes a chain node as input and returns the chain for the load itself. - /// - /// Having a callback like this is necessary for targets like SystemZ, - /// which allows a CPU to reuse the result of a previous load indefinitely, - /// even if a cache-coherent store is performed by another CPU. The default - /// implementation does nothing. - virtual SDValue prepareVolatileOrAtomicLoad(SDValue Chain, const SDLoc &DL, - SelectionDAG &DAG) const { - return Chain; - } - - /// Should SelectionDAG lower an atomic store of the given kind as a normal - /// StoreSDNode (as opposed to an AtomicSDNode)? NOTE: The intention is to - /// eventually migrate all targets to the using StoreSDNodes, but porting is - /// being done target at a time. - virtual bool lowerAtomicStoreAsStoreSDNode(const StoreInst &SI) const { - assert(SI.isAtomic() && "violated precondition"); - return false; - } - - /// Should SelectionDAG lower an atomic load of the given kind as a normal - /// LoadSDNode (as opposed to an AtomicSDNode)? NOTE: The intention is to - /// eventually migrate all targets to the using LoadSDNodes, but porting is - /// being done target at a time. - virtual bool lowerAtomicLoadAsLoadSDNode(const LoadInst &LI) const { - assert(LI.isAtomic() && "violated precondition"); - return false; - } - - - /// This callback is invoked by the type legalizer to legalize nodes with an - /// illegal operand type but legal result types. It replaces the - /// LowerOperation callback in the type Legalizer. The reason we can not do - /// away with LowerOperation entirely is that LegalizeDAG isn't yet ready to - /// use this callback. - /// - /// TODO: Consider merging with ReplaceNodeResults. - /// - /// The target places new result values for the node in Results (their number - /// and types must exactly match those of the original return values of - /// the node), or leaves Results empty, which indicates that the node is not - /// to be custom lowered after all. - /// The default implementation calls LowerOperation. - virtual void LowerOperationWrapper(SDNode *N, - SmallVectorImpl &Results, - SelectionDAG &DAG) const; - - /// This callback is invoked for operations that are unsupported by the - /// target, which are registered to use 'custom' lowering, and whose defined - /// values are all legal. If the target has no operations that require custom - /// lowering, it need not implement this. The default implementation of this - /// aborts. - virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; - - /// This callback is invoked when a node result type is illegal for the - /// target, and the operation was registered to use 'custom' lowering for that - /// result type. The target places new result values for the node in Results - /// (their number and types must exactly match those of the original return - /// values of the node), or leaves Results empty, which indicates that the - /// node is not to be custom lowered after all. - /// - /// If the target has no operations that require custom lowering, it need not - /// implement this. The default implementation aborts. - virtual void ReplaceNodeResults(SDNode * /*N*/, - SmallVectorImpl &/*Results*/, - SelectionDAG &/*DAG*/) const { - llvm_unreachable("ReplaceNodeResults not implemented for this target!"); - } - - /// This method returns the name of a target specific DAG node. - virtual const char *getTargetNodeName(unsigned Opcode) const; - - /// This method returns a target specific FastISel object, or null if the - /// target does not support "fast" ISel. - virtual FastISel *createFastISel(FunctionLoweringInfo &, - const TargetLibraryInfo *) const { - return nullptr; - } - - bool verifyReturnAddressArgumentIsConstant(SDValue Op, - SelectionDAG &DAG) const; - - //===--------------------------------------------------------------------===// - // Inline Asm Support hooks - // - - /// This hook allows the target to expand an inline asm call to be explicit - /// llvm code if it wants to. This is useful for turning simple inline asms - /// into LLVM intrinsics, which gives the compiler more information about the - /// behavior of the code. - virtual bool ExpandInlineAsm(CallInst *) const { - return false; - } - - enum ConstraintType { - C_Register, // Constraint represents specific register(s). - C_RegisterClass, // Constraint represents any of register(s) in class. - C_Memory, // Memory constraint. - C_Immediate, // Requires an immediate. - C_Other, // Something else. - C_Unknown // Unsupported constraint. - }; - - enum ConstraintWeight { - // Generic weights. - CW_Invalid = -1, // No match. - CW_Okay = 0, // Acceptable. - CW_Good = 1, // Good weight. - CW_Better = 2, // Better weight. - CW_Best = 3, // Best weight. - - // Well-known weights. - CW_SpecificReg = CW_Okay, // Specific register operands. - CW_Register = CW_Good, // Register operands. - CW_Memory = CW_Better, // Memory operands. - CW_Constant = CW_Best, // Constant operand. - CW_Default = CW_Okay // Default or don't know type. - }; - - /// This contains information for each constraint that we are lowering. - struct AsmOperandInfo : public InlineAsm::ConstraintInfo { - /// This contains the actual string for the code, like "m". TargetLowering - /// picks the 'best' code from ConstraintInfo::Codes that most closely - /// matches the operand. - std::string ConstraintCode; - - /// Information about the constraint code, e.g. Register, RegisterClass, - /// Memory, Other, Unknown. - TargetLowering::ConstraintType ConstraintType = TargetLowering::C_Unknown; - - /// If this is the result output operand or a clobber, this is null, - /// otherwise it is the incoming operand to the CallInst. This gets - /// modified as the asm is processed. - Value *CallOperandVal = nullptr; - - /// The ValueType for the operand value. - MVT ConstraintVT = MVT::Other; - - /// Copy constructor for copying from a ConstraintInfo. - AsmOperandInfo(InlineAsm::ConstraintInfo Info) - : InlineAsm::ConstraintInfo(std::move(Info)) {} - - /// Return true of this is an input operand that is a matching constraint - /// like "4". - bool isMatchingInputConstraint() const; - - /// If this is an input matching constraint, this method returns the output - /// operand it matches. - unsigned getMatchedOperand() const; - }; - - using AsmOperandInfoVector = std::vector; - - /// Split up the constraint string from the inline assembly value into the - /// specific constraints and their prefixes, and also tie in the associated - /// operand values. If this returns an empty vector, and if the constraint - /// string itself isn't empty, there was an error parsing. - virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, - const TargetRegisterInfo *TRI, - const CallBase &Call) const; - - /// Examine constraint type and operand type and determine a weight value. - /// The operand object must already have been set up with the operand type. - virtual ConstraintWeight getMultipleConstraintMatchWeight( - AsmOperandInfo &info, int maIndex) const; - - /// Examine constraint string and operand type and determine a weight value. - /// The operand object must already have been set up with the operand type. - virtual ConstraintWeight getSingleConstraintMatchWeight( - AsmOperandInfo &info, const char *constraint) const; - - /// Determines the constraint code and constraint type to use for the specific - /// AsmOperandInfo, setting OpInfo.ConstraintCode and OpInfo.ConstraintType. - /// If the actual operand being passed in is available, it can be passed in as - /// Op, otherwise an empty SDValue can be passed. - virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, - SDValue Op, - SelectionDAG *DAG = nullptr) const; - - /// Given a constraint, return the type of constraint it is for this target. - virtual ConstraintType getConstraintType(StringRef Constraint) const; - - /// Given a physical register constraint (e.g. {edx}), return the register - /// number and the register class for the register. - /// - /// Given a register class constraint, like 'r', if this corresponds directly - /// to an LLVM register class, return a register of 0 and the register class - /// pointer. - /// - /// This should only be used for C_Register constraints. On error, this - /// returns a register number of 0 and a null register class pointer. - virtual std::pair - getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, MVT VT) const; - - virtual unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const { - if (ConstraintCode == "m") - return InlineAsm::Constraint_m; - if (ConstraintCode == "o") - return InlineAsm::Constraint_o; - if (ConstraintCode == "X") - return InlineAsm::Constraint_X; - return InlineAsm::Constraint_Unknown; - } - - /// Try to replace an X constraint, which matches anything, with another that - /// has more specific requirements based on the type of the corresponding - /// operand. This returns null if there is no replacement to make. - virtual const char *LowerXConstraint(EVT ConstraintVT) const; - - /// Lower the specified operand into the Ops vector. If it is invalid, don't - /// add anything to Ops. - virtual void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, - std::vector &Ops, - SelectionDAG &DAG) const; - - // Lower custom output constraints. If invalid, return SDValue(). - virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag, - const SDLoc &DL, - const AsmOperandInfo &OpInfo, - SelectionDAG &DAG) const; - - //===--------------------------------------------------------------------===// - // Div utility functions - // - SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - SmallVectorImpl &Created) const; - SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - SmallVectorImpl &Created) const; - - /// Targets may override this function to provide custom SDIV lowering for - /// power-of-2 denominators. If the target returns an empty SDValue, LLVM - /// assumes SDIV is expensive and replaces it with a series of other integer - /// operations. - virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, - SelectionDAG &DAG, - SmallVectorImpl &Created) const; - - /// Indicate whether this target prefers to combine FDIVs with the same - /// divisor. If the transform should never be done, return zero. If the - /// transform should be done, return the minimum number of divisor uses - /// that must exist. - virtual unsigned combineRepeatedFPDivisors() const { - return 0; - } - - /// Hooks for building estimates in place of slower divisions and square - /// roots. - - /// Return either a square root or its reciprocal estimate value for the input - /// operand. - /// \p Enabled is a ReciprocalEstimate enum with value either 'Unspecified' or - /// 'Enabled' as set by a potential default override attribute. - /// If \p RefinementSteps is 'Unspecified', the number of Newton-Raphson - /// refinement iterations required to generate a sufficient (though not - /// necessarily IEEE-754 compliant) estimate is returned in that parameter. - /// The boolean UseOneConstNR output is used to select a Newton-Raphson - /// algorithm implementation that uses either one or two constants. - /// The boolean Reciprocal is used to select whether the estimate is for the - /// square root of the input operand or the reciprocal of its square root. - /// A target may choose to implement its own refinement within this function. - /// If that's true, then return '0' as the number of RefinementSteps to avoid - /// any further refinement of the estimate. - /// An empty SDValue return means no estimate sequence can be created. - virtual SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, - int Enabled, int &RefinementSteps, - bool &UseOneConstNR, bool Reciprocal) const { - return SDValue(); - } - - /// Return a reciprocal estimate value for the input operand. - /// \p Enabled is a ReciprocalEstimate enum with value either 'Unspecified' or - /// 'Enabled' as set by a potential default override attribute. - /// If \p RefinementSteps is 'Unspecified', the number of Newton-Raphson - /// refinement iterations required to generate a sufficient (though not - /// necessarily IEEE-754 compliant) estimate is returned in that parameter. - /// A target may choose to implement its own refinement within this function. - /// If that's true, then return '0' as the number of RefinementSteps to avoid - /// any further refinement of the estimate. - /// An empty SDValue return means no estimate sequence can be created. - virtual SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, - int Enabled, int &RefinementSteps) const { - return SDValue(); - } - - /// Return a target-dependent comparison result if the input operand is - /// suitable for use with a square root estimate calculation. For example, the - /// comparison may check if the operand is NAN, INF, zero, normal, etc. The - /// result should be used as the condition operand for a select or branch. - virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, - const DenormalMode &Mode) const; - - /// Return a target-dependent result if the input operand is not suitable for - /// use with a square root estimate calculation. - virtual SDValue getSqrtResultForDenormInput(SDValue Operand, - SelectionDAG &DAG) const { - return DAG.getConstantFP(0.0, SDLoc(Operand), Operand.getValueType()); - } - - //===--------------------------------------------------------------------===// - // Legalization utility functions - // - - /// Expand a MUL or [US]MUL_LOHI of n-bit values into two or four nodes, - /// respectively, each computing an n/2-bit part of the result. - /// \param Result A vector that will be filled with the parts of the result - /// in little-endian order. - /// \param LL Low bits of the LHS of the MUL. You can use this parameter - /// if you want to control how low bits are extracted from the LHS. - /// \param LH High bits of the LHS of the MUL. See LL for meaning. - /// \param RL Low bits of the RHS of the MUL. See LL for meaning - /// \param RH High bits of the RHS of the MUL. See LL for meaning. - /// \returns true if the node has been expanded, false if it has not - bool expandMUL_LOHI(unsigned Opcode, EVT VT, const SDLoc &dl, SDValue LHS, - SDValue RHS, SmallVectorImpl &Result, EVT HiLoVT, - SelectionDAG &DAG, MulExpansionKind Kind, - SDValue LL = SDValue(), SDValue LH = SDValue(), - SDValue RL = SDValue(), SDValue RH = SDValue()) const; - - /// Expand a MUL into two nodes. One that computes the high bits of - /// the result and one that computes the low bits. - /// \param HiLoVT The value type to use for the Lo and Hi nodes. - /// \param LL Low bits of the LHS of the MUL. You can use this parameter - /// if you want to control how low bits are extracted from the LHS. - /// \param LH High bits of the LHS of the MUL. See LL for meaning. - /// \param RL Low bits of the RHS of the MUL. See LL for meaning - /// \param RH High bits of the RHS of the MUL. See LL for meaning. - /// \returns true if the node has been expanded. false if it has not - bool expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT, - SelectionDAG &DAG, MulExpansionKind Kind, - SDValue LL = SDValue(), SDValue LH = SDValue(), - SDValue RL = SDValue(), SDValue RH = SDValue()) const; - - /// Expand funnel shift. - /// \param N Node to expand - /// \returns The expansion if successful, SDValue() otherwise - SDValue expandFunnelShift(SDNode *N, SelectionDAG &DAG) const; - - /// Expand rotations. - /// \param N Node to expand - /// \param AllowVectorOps expand vector rotate, this should only be performed - /// if the legalization is happening outside of LegalizeVectorOps - /// \returns The expansion if successful, SDValue() otherwise - SDValue expandROT(SDNode *N, bool AllowVectorOps, SelectionDAG &DAG) const; - - /// Expand shift-by-parts. - /// \param N Node to expand - /// \param Lo lower-output-part after conversion - /// \param Hi upper-output-part after conversion - void expandShiftParts(SDNode *N, SDValue &Lo, SDValue &Hi, - SelectionDAG &DAG) const; - - /// Expand float(f32) to SINT(i64) conversion - /// \param N Node to expand - /// \param Result output after conversion - /// \returns True, if the expansion was successful, false otherwise - bool expandFP_TO_SINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; - - /// Expand float to UINT conversion - /// \param N Node to expand - /// \param Result output after conversion - /// \param Chain output chain after conversion - /// \returns True, if the expansion was successful, false otherwise - bool expandFP_TO_UINT(SDNode *N, SDValue &Result, SDValue &Chain, - SelectionDAG &DAG) const; - - /// Expand UINT(i64) to double(f64) conversion - /// \param N Node to expand - /// \param Result output after conversion - /// \param Chain output chain after conversion - /// \returns True, if the expansion was successful, false otherwise - bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SDValue &Chain, - SelectionDAG &DAG) const; - - /// Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs. - SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const; - - /// Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max. - /// \param N Node to expand - /// \returns The expansion result - SDValue expandFP_TO_INT_SAT(SDNode *N, SelectionDAG &DAG) const; - - /// Expand CTPOP nodes. Expands vector/scalar CTPOP nodes, - /// vector nodes can only succeed if all operations are legal/custom. - /// \param N Node to expand - /// \returns The expansion result or SDValue() if it fails. - SDValue expandCTPOP(SDNode *N, SelectionDAG &DAG) const; - - /// Expand CTLZ/CTLZ_ZERO_UNDEF nodes. Expands vector/scalar CTLZ nodes, - /// vector nodes can only succeed if all operations are legal/custom. - /// \param N Node to expand - /// \returns The expansion result or SDValue() if it fails. - SDValue expandCTLZ(SDNode *N, SelectionDAG &DAG) const; - - /// Expand CTTZ/CTTZ_ZERO_UNDEF nodes. Expands vector/scalar CTTZ nodes, - /// vector nodes can only succeed if all operations are legal/custom. - /// \param N Node to expand - /// \returns The expansion result or SDValue() if it fails. - SDValue expandCTTZ(SDNode *N, SelectionDAG &DAG) const; - - /// Expand ABS nodes. Expands vector/scalar ABS nodes, - /// vector nodes can only succeed if all operations are legal/custom. - /// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size)) - /// \param N Node to expand - /// \param IsNegative indicate negated abs - /// \returns The expansion result or SDValue() if it fails. - SDValue expandABS(SDNode *N, SelectionDAG &DAG, - bool IsNegative = false) const; - - /// Expand BSWAP nodes. Expands scalar/vector BSWAP nodes with i16/i32/i64 - /// scalar types. Returns SDValue() if expand fails. - /// \param N Node to expand - /// \returns The expansion result or SDValue() if it fails. - SDValue expandBSWAP(SDNode *N, SelectionDAG &DAG) const; - - /// Expand BITREVERSE nodes. Expands scalar/vector BITREVERSE nodes. - /// Returns SDValue() if expand fails. - /// \param N Node to expand - /// \returns The expansion result or SDValue() if it fails. - SDValue expandBITREVERSE(SDNode *N, SelectionDAG &DAG) const; - - /// Turn load of vector type into a load of the individual elements. - /// \param LD load to expand - /// \returns BUILD_VECTOR and TokenFactor nodes. - std::pair scalarizeVectorLoad(LoadSDNode *LD, - SelectionDAG &DAG) const; - - // Turn a store of a vector type into stores of the individual elements. - /// \param ST Store with a vector value type - /// \returns TokenFactor of the individual store chains. - SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const; - - /// Expands an unaligned load to 2 half-size loads for an integer, and - /// possibly more for vectors. - std::pair expandUnalignedLoad(LoadSDNode *LD, - SelectionDAG &DAG) const; - - /// Expands an unaligned store to 2 half-size stores for integer values, and - /// possibly more for vectors. - SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const; - - /// Increments memory address \p Addr according to the type of the value - /// \p DataVT that should be stored. If the data is stored in compressed - /// form, the memory address should be incremented according to the number of - /// the stored elements. This number is equal to the number of '1's bits - /// in the \p Mask. - /// \p DataVT is a vector type. \p Mask is a vector value. - /// \p DataVT and \p Mask have the same number of vector elements. - SDValue IncrementMemoryAddress(SDValue Addr, SDValue Mask, const SDLoc &DL, - EVT DataVT, SelectionDAG &DAG, - bool IsCompressedMemory) const; - - /// Get a pointer to vector element \p Idx located in memory for a vector of - /// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of - /// bounds the returned pointer is unspecified, but will be within the vector - /// bounds. - SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, - SDValue Index) const; - - /// Get a pointer to a sub-vector of type \p SubVecVT at index \p Idx located - /// in memory for a vector of type \p VecVT starting at a base address of - /// \p VecPtr. If \p Idx plus the size of \p SubVecVT is out of bounds the - /// returned pointer is unspecified, but the value returned will be such that - /// the entire subvector would be within the vector bounds. - SDValue getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, - EVT SubVecVT, SDValue Index) const; - - /// Method for building the DAG expansion of ISD::[US][MIN|MAX]. This - /// method accepts integers as its arguments. - SDValue expandIntMINMAX(SDNode *Node, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT. This - /// method accepts integers as its arguments. - SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::[US]SHLSAT. This - /// method accepts integers as its arguments. - SDValue expandShlSat(SDNode *Node, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::[U|S]MULFIX[SAT]. This - /// method accepts integers as its arguments. - SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::[US]DIVFIX[SAT]. This - /// method accepts integers as its arguments. - /// Note: This method may fail if the division could not be performed - /// within the type. Clients must retry with a wider type if this happens. - SDValue expandFixedPointDiv(unsigned Opcode, const SDLoc &dl, - SDValue LHS, SDValue RHS, - unsigned Scale, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::U(ADD|SUB)O. Expansion - /// always succeeds and populates the Result and Overflow arguments. - void expandUADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, - SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::S(ADD|SUB)O. Expansion - /// always succeeds and populates the Result and Overflow arguments. - void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, - SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::[US]MULO. Returns whether - /// expansion was successful and populates the Result and Overflow arguments. - bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, - SelectionDAG &DAG) const; - - /// Expand a VECREDUCE_* into an explicit calculation. If Count is specified, - /// only the first Count elements of the vector are used. - SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const; - - /// Expand a VECREDUCE_SEQ_* into an explicit ordered calculation. - SDValue expandVecReduceSeq(SDNode *Node, SelectionDAG &DAG) const; - - /// Expand an SREM or UREM using SDIV/UDIV or SDIVREM/UDIVREM, if legal. - /// Returns true if the expansion was successful. - bool expandREM(SDNode *Node, SDValue &Result, SelectionDAG &DAG) const; - - /// Method for building the DAG expansion of ISD::VECTOR_SPLICE. This - /// method accepts vectors as its arguments. - SDValue expandVectorSplice(SDNode *Node, SelectionDAG &DAG) const; - - /// Legalize a SETCC with given LHS and RHS and condition code CC on the - /// current target. - /// - /// If the SETCC has been legalized using AND / OR, then the legalized node - /// will be stored in LHS. RHS and CC will be set to SDValue(). NeedInvert - /// will be set to false. - /// - /// If the SETCC has been legalized by using getSetCCSwappedOperands(), - /// then the values of LHS and RHS will be swapped, CC will be set to the - /// new condition, and NeedInvert will be set to false. - /// - /// If the SETCC has been legalized using the inverse condcode, then LHS and - /// RHS will be unchanged, CC will set to the inverted condcode, and - /// NeedInvert will be set to true. The caller must invert the result of the - /// SETCC with SelectionDAG::getLogicalNOT() or take equivalent action to swap - /// the effect of a true/false result. - /// - /// \returns true if the SetCC has been legalized, false if it hasn't. - bool LegalizeSetCCCondCode(SelectionDAG &DAG, EVT VT, SDValue &LHS, - SDValue &RHS, SDValue &CC, bool &NeedInvert, - const SDLoc &dl, SDValue &Chain, - bool IsSignaling = false) const; - - //===--------------------------------------------------------------------===// - // Instruction Emitting Hooks - // - - /// This method should be implemented by targets that mark instructions with - /// the 'usesCustomInserter' flag. These instructions are special in various - /// ways, which require special support to insert. The specified MachineInstr - /// is created but not inserted into any basic blocks, and this method is - /// called to expand it into a sequence of instructions, potentially also - /// creating new basic blocks and control flow. - /// As long as the returned basic block is different (i.e., we created a new - /// one), the custom inserter is free to modify the rest of \p MBB. - virtual MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const; - - /// This method should be implemented by targets that mark instructions with - /// the 'hasPostISelHook' flag. These instructions must be adjusted after - /// instruction selection by target hooks. e.g. To fill in optional defs for - /// ARM 's' setting instructions. - virtual void AdjustInstrPostInstrSelection(MachineInstr &MI, - SDNode *Node) const; - - /// If this function returns true, SelectionDAGBuilder emits a - /// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector. - virtual bool useLoadStackGuardNode() const { - return false; - } - - virtual SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val, - const SDLoc &DL) const { - llvm_unreachable("not implemented for this target"); - } - - /// Lower TLS global address SDNode for target independent emulated TLS model. - virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, - SelectionDAG &DAG) const; - - /// Expands target specific indirect branch for the case of JumpTable - /// expanasion. - virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr, - SelectionDAG &DAG) const { - return DAG.getNode(ISD::BRIND, dl, MVT::Other, Value, Addr); - } - - // seteq(x, 0) -> truncate(srl(ctlz(zext(x)), log2(#bits))) - // If we're comparing for equality to zero and isCtlzFast is true, expose the - // fact that this can be implemented as a ctlz/srl pair, so that the dag - // combiner can fold the new nodes. - SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const; - - /// Give targets the chance to reduce the number of distinct addressing modes. - ISD::MemIndexType getCanonicalIndexType(ISD::MemIndexType IndexType, - EVT MemVT, SDValue Offsets) const; - -private: - SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, - const SDLoc &DL, DAGCombinerInfo &DCI) const; - SDValue foldSetCCWithBinOp(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, - const SDLoc &DL, DAGCombinerInfo &DCI) const; - - SDValue optimizeSetCCOfSignedTruncationCheck(EVT SCCVT, SDValue N0, - SDValue N1, ISD::CondCode Cond, - DAGCombinerInfo &DCI, - const SDLoc &DL) const; - - // (X & (C l>>/<< Y)) ==/!= 0 --> ((X <> Y) & C) ==/!= 0 - SDValue optimizeSetCCByHoistingAndByConstFromLogicalShift( - EVT SCCVT, SDValue N0, SDValue N1C, ISD::CondCode Cond, - DAGCombinerInfo &DCI, const SDLoc &DL) const; - - SDValue prepareUREMEqFold(EVT SETCCVT, SDValue REMNode, - SDValue CompTargetNode, ISD::CondCode Cond, - DAGCombinerInfo &DCI, const SDLoc &DL, - SmallVectorImpl &Created) const; - SDValue buildUREMEqFold(EVT SETCCVT, SDValue REMNode, SDValue CompTargetNode, - ISD::CondCode Cond, DAGCombinerInfo &DCI, - const SDLoc &DL) const; - - SDValue prepareSREMEqFold(EVT SETCCVT, SDValue REMNode, - SDValue CompTargetNode, ISD::CondCode Cond, - DAGCombinerInfo &DCI, const SDLoc &DL, - SmallVectorImpl &Created) const; - SDValue buildSREMEqFold(EVT SETCCVT, SDValue REMNode, SDValue CompTargetNode, - ISD::CondCode Cond, DAGCombinerInfo &DCI, - const SDLoc &DL) const; -}; - -/// Given an LLVM IR type and return type attributes, compute the return value -/// EVTs and flags, and optionally also the offsets, if the return value is -/// being lowered to memory. -void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, - SmallVectorImpl &Outs, - const TargetLowering &TLI, const DataLayout &DL); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETLOWERING_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h deleted file mode 100644 index 2c8b17807f..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ /dev/null @@ -1,300 +0,0 @@ -//==- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info --*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements classes used to handle lowerings specific to common -// object file formats. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H -#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/BinaryFormat/XCOFF.h" -#include "llvm/Target/TargetLoweringObjectFile.h" - -namespace llvm { - -class GlobalValue; -class MachineModuleInfo; -class MachineFunction; -class MCContext; -class MCExpr; -class MCSection; -class MCSymbol; -class Module; -class TargetMachine; - -class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { - bool UseInitArray = false; - mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections - SmallPtrSet Used; - -protected: - MCSymbolRefExpr::VariantKind PLTRelativeVariantKind = - MCSymbolRefExpr::VK_None; - -public: - TargetLoweringObjectFileELF(); - ~TargetLoweringObjectFileELF() override = default; - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - void getModuleMetadata(Module &M) override; - - /// Emit Obj-C garbage collection and linker options. - void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; - - void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL, - const MCSymbol *Sym) const override; - - /// Given a constant with the SectionKind, return a section that it should be - /// placed in. - MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C, - Align &Alignment) const override; - - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *getSectionForJumpTable(const Function &F, - const TargetMachine &TM) const override; - MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym, - const TargetMachine &TM) const override; - - MCSection * - getSectionForMachineBasicBlock(const Function &F, - const MachineBasicBlock &MBB, - const TargetMachine &TM) const override; - - MCSection * - getUniqueSectionForFunction(const Function &F, - const TargetMachine &TM) const override; - - bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, - const Function &F) const override; - - /// Return an MCExpr to use for a reference to the specified type info global - /// variable from exception handling information. - const MCExpr *getTTypeGlobalReference(const GlobalValue *GV, - unsigned Encoding, - const TargetMachine &TM, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const override; - - // The symbol that gets passed to .cfi_personality. - MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, - const TargetMachine &TM, - MachineModuleInfo *MMI) const override; - - void InitializeELF(bool UseInitArray_); - MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - - const MCExpr *lowerRelativeReference(const GlobalValue *LHS, - const GlobalValue *RHS, - const TargetMachine &TM) const override; - - const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv, - const TargetMachine &TM) const override; - - MCSection *getSectionForCommandLines() const override; -}; - -class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { -public: - TargetLoweringObjectFileMachO(); - ~TargetLoweringObjectFileMachO() override = default; - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - /// Emit the module flags that specify the garbage collection information. - void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C, - Align &Alignment) const override; - - /// The mach-o version of this method defaults to returning a stub reference. - const MCExpr *getTTypeGlobalReference(const GlobalValue *GV, - unsigned Encoding, - const TargetMachine &TM, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const override; - - // The symbol that gets passed to .cfi_personality. - MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, - const TargetMachine &TM, - MachineModuleInfo *MMI) const override; - - /// Get MachO PC relative GOT entry relocation - const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV, - const MCSymbol *Sym, - const MCValue &MV, int64_t Offset, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const override; - - void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, - const TargetMachine &TM) const override; -}; - -class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { - mutable unsigned NextUniqueID = 0; - const TargetMachine *TM = nullptr; - -public: - ~TargetLoweringObjectFileCOFF() override = default; - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, - const TargetMachine &TM) const override; - - MCSection *getSectionForJumpTable(const Function &F, - const TargetMachine &TM) const override; - - /// Emit Obj-C garbage collection and linker options. - void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; - - MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - - const MCExpr *lowerRelativeReference(const GlobalValue *LHS, - const GlobalValue *RHS, - const TargetMachine &TM) const override; - - /// Given a mergeable constant with the specified size and relocation - /// information, return a section that it should be placed in. - MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C, - Align &Alignment) const override; - -private: - void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const; -}; - -class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile { - mutable unsigned NextUniqueID = 0; - -public: - TargetLoweringObjectFileWasm() = default; - ~TargetLoweringObjectFileWasm() override = default; - - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, - const Function &F) const override; - - void InitializeWasm(); - MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - - const MCExpr *lowerRelativeReference(const GlobalValue *LHS, - const GlobalValue *RHS, - const TargetMachine &TM) const override; -}; - -class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile { -public: - TargetLoweringObjectFileXCOFF() = default; - ~TargetLoweringObjectFileXCOFF() override = default; - - static bool ShouldEmitEHBlock(const MachineFunction *MF); - static bool ShouldSetSSPCanaryBitInTB(const MachineFunction *MF); - - static MCSymbol *getEHInfoTableSymbol(const MachineFunction *MF); - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, - const Function &F) const override; - - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - - const MCExpr *lowerRelativeReference(const GlobalValue *LHS, - const GlobalValue *RHS, - const TargetMachine &TM) const override; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - MCSection *getSectionForJumpTable(const Function &F, - const TargetMachine &TM) const override; - - /// Given a constant with the SectionKind, return a section that it should be - /// placed in. - MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C, - Align &Alignment) const override; - - static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV); - - MCSection * - getSectionForFunctionDescriptor(const Function *F, - const TargetMachine &TM) const override; - MCSection *getSectionForTOCEntry(const MCSymbol *Sym, - const TargetMachine &TM) const override; - - /// For external functions, this will always return a function descriptor - /// csect. - MCSection * - getSectionForExternalReference(const GlobalObject *GO, - const TargetMachine &TM) const override; - - /// For functions, this will always return a function descriptor symbol. - MCSymbol *getTargetSymbol(const GlobalValue *GV, - const TargetMachine &TM) const override; - - MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func, - const TargetMachine &TM) const override; -}; - -class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile { -public: - TargetLoweringObjectFileGOFF(); - ~TargetLoweringObjectFileGOFF() override = default; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetOpcodes.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetOpcodes.h deleted file mode 100644 index 169caf30bb..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetOpcodes.h +++ /dev/null @@ -1,49 +0,0 @@ -//===-- llvm/CodeGen/TargetOpcodes.h - Target Indep Opcodes -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target independent instruction opcodes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETOPCODES_H -#define LLVM_CODEGEN_TARGETOPCODES_H - -namespace llvm { - -/// Invariant opcodes: All instruction sets have these as their low opcodes. -/// -namespace TargetOpcode { -enum { -#define HANDLE_TARGET_OPCODE(OPC) OPC, -#define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC) IDENT = OPC, -#include "llvm/Support/TargetOpcodes.def" -}; -} // end namespace TargetOpcode - -/// Check whether the given Opcode is a generic opcode that is not supposed -/// to appear after ISel. -inline bool isPreISelGenericOpcode(unsigned Opcode) { - return Opcode >= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START && - Opcode <= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; -} - -/// Check whether the given Opcode is a target-specific opcode. -inline bool isTargetSpecificOpcode(unsigned Opcode) { - return Opcode > TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; -} - -/// \returns true if \p Opcode is an optimization hint opcode which is not -/// supposed to appear after ISel. -inline bool isPreISelGenericOptimizationHint(unsigned Opcode) { - return Opcode >= TargetOpcode::PRE_ISEL_GENERIC_OPTIMIZATION_HINT_START && - Opcode <= TargetOpcode::PRE_ISEL_GENERIC_OPTIMIZATION_HINT_END; -} - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetPassConfig.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetPassConfig.h deleted file mode 100644 index 6f04a1b713..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetPassConfig.h +++ /dev/null @@ -1,472 +0,0 @@ -//===- TargetPassConfig.h - Code Generation pass options --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Target-Independent Code Generator Pass Configuration Options pass. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETPASSCONFIG_H -#define LLVM_CODEGEN_TARGETPASSCONFIG_H - -#include "llvm/Pass.h" -#include "llvm/Support/CodeGen.h" -#include -#include - -namespace llvm { - -class LLVMTargetMachine; -struct MachineSchedContext; -class PassConfigImpl; -class ScheduleDAGInstrs; -class CSEConfigBase; -class PassInstrumentationCallbacks; - -// The old pass manager infrastructure is hidden in a legacy namespace now. -namespace legacy { - -class PassManagerBase; - -} // end namespace legacy - -using legacy::PassManagerBase; - -/// Discriminated union of Pass ID types. -/// -/// The PassConfig API prefers dealing with IDs because they are safer and more -/// efficient. IDs decouple configuration from instantiation. This way, when a -/// pass is overridden, it isn't unnecessarily instantiated. It is also unsafe to -/// refer to a Pass pointer after adding it to a pass manager, which deletes -/// redundant pass instances. -/// -/// However, it is convenient to directly instantiate target passes with -/// non-default ctors. These often don't have a registered PassInfo. Rather than -/// force all target passes to implement the pass registry boilerplate, allow -/// the PassConfig API to handle either type. -/// -/// AnalysisID is sadly char*, so PointerIntPair won't work. -class IdentifyingPassPtr { - union { - AnalysisID ID; - Pass *P; - }; - bool IsInstance = false; - -public: - IdentifyingPassPtr() : P(nullptr) {} - IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr) {} - IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {} - - bool isValid() const { return P; } - bool isInstance() const { return IsInstance; } - - AnalysisID getID() const { - assert(!IsInstance && "Not a Pass ID"); - return ID; - } - - Pass *getInstance() const { - assert(IsInstance && "Not a Pass Instance"); - return P; - } -}; - - -/// Target-Independent Code Generator Pass Configuration Options. -/// -/// This is an ImmutablePass solely for the purpose of exposing CodeGen options -/// to the internals of other CodeGen passes. -class TargetPassConfig : public ImmutablePass { -private: - PassManagerBase *PM = nullptr; - AnalysisID StartBefore = nullptr; - AnalysisID StartAfter = nullptr; - AnalysisID StopBefore = nullptr; - AnalysisID StopAfter = nullptr; - - unsigned StartBeforeInstanceNum = 0; - unsigned StartBeforeCount = 0; - - unsigned StartAfterInstanceNum = 0; - unsigned StartAfterCount = 0; - - unsigned StopBeforeInstanceNum = 0; - unsigned StopBeforeCount = 0; - - unsigned StopAfterInstanceNum = 0; - unsigned StopAfterCount = 0; - - bool Started = true; - bool Stopped = false; - bool AddingMachinePasses = false; - bool DebugifyIsSafe = true; - - /// Set the StartAfter, StartBefore and StopAfter passes to allow running only - /// a portion of the normal code-gen pass sequence. - /// - /// If the StartAfter and StartBefore pass ID is zero, then compilation will - /// begin at the normal point; otherwise, clear the Started flag to indicate - /// that passes should not be added until the starting pass is seen. If the - /// Stop pass ID is zero, then compilation will continue to the end. - /// - /// This function expects that at least one of the StartAfter or the - /// StartBefore pass IDs is null. - void setStartStopPasses(); - -protected: - LLVMTargetMachine *TM; - PassConfigImpl *Impl = nullptr; // Internal data structures - bool Initialized = false; // Flagged after all passes are configured. - - // Target Pass Options - // Targets provide a default setting, user flags override. - bool DisableVerify = false; - - /// Default setting for -enable-tail-merge on this target. - bool EnableTailMerge = true; - - /// Require processing of functions such that callees are generated before - /// callers. - bool RequireCodeGenSCCOrder = false; - - /// Add the actual instruction selection passes. This does not include - /// preparation passes on IR. - bool addCoreISelPasses(); - -public: - TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm); - // Dummy constructor. - TargetPassConfig(); - - ~TargetPassConfig() override; - - static char ID; - - /// Get the right type of TargetMachine for this target. - template TMC &getTM() const { - return *static_cast(TM); - } - - // - void setInitialized() { Initialized = true; } - - CodeGenOpt::Level getOptLevel() const; - - /// Returns true if one of the `-start-after`, `-start-before`, `-stop-after` - /// or `-stop-before` options is set. - static bool hasLimitedCodeGenPipeline(); - - /// Returns true if none of the `-stop-before` and `-stop-after` options is - /// set. - static bool willCompleteCodeGenPipeline(); - - /// If hasLimitedCodeGenPipeline is true, this method - /// returns a string with the name of the options, separated - /// by \p Separator that caused this pipeline to be limited. - static std::string - getLimitedCodeGenPipelineReason(const char *Separator = "/"); - - void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } - - bool getEnableTailMerge() const { return EnableTailMerge; } - void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); } - - bool requiresCodeGenSCCOrder() const { return RequireCodeGenSCCOrder; } - void setRequiresCodeGenSCCOrder(bool Enable = true) { - setOpt(RequireCodeGenSCCOrder, Enable); - } - - /// Allow the target to override a specific pass without overriding the pass - /// pipeline. When passes are added to the standard pipeline at the - /// point where StandardID is expected, add TargetID in its place. - void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID); - - /// Insert InsertedPassID pass after TargetPassID pass. - void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID); - - /// Allow the target to enable a specific standard pass by default. - void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } - - /// Allow the target to disable a specific standard pass by default. - void disablePass(AnalysisID PassID) { - substitutePass(PassID, IdentifyingPassPtr()); - } - - /// Return the pass substituted for StandardID by the target. - /// If no substitution exists, return StandardID. - IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const; - - /// Return true if the pass has been substituted by the target or - /// overridden on the command line. - bool isPassSubstitutedOrOverridden(AnalysisID ID) const; - - /// Return true if the optimized regalloc pipeline is enabled. - bool getOptimizeRegAlloc() const; - - /// Return true if the default global register allocator is in use and - /// has not be overridden on the command line with '-regalloc=...' - bool usingDefaultRegAlloc() const; - - /// High level function that adds all passes necessary to go from llvm IR - /// representation to the MI representation. - /// Adds IR based lowering and target specific optimization passes and finally - /// the core instruction selection passes. - /// \returns true if an error occurred, false otherwise. - bool addISelPasses(); - - /// Add common target configurable passes that perform LLVM IR to IR - /// transforms following machine independent optimization. - virtual void addIRPasses(); - - /// Add passes to lower exception handling for the code generator. - void addPassesToHandleExceptions(); - - /// Add pass to prepare the LLVM IR for code generation. This should be done - /// before exception handling preparation passes. - virtual void addCodeGenPrepare(); - - /// Add common passes that perform LLVM IR to IR transforms in preparation for - /// instruction selection. - virtual void addISelPrepare(); - - /// addInstSelector - This method should install an instruction selector pass, - /// which converts from LLVM code to machine instructions. - virtual bool addInstSelector() { - return true; - } - - /// This method should install an IR translator pass, which converts from - /// LLVM code to machine instructions with possibly generic opcodes. - virtual bool addIRTranslator() { return true; } - - /// This method may be implemented by targets that want to run passes - /// immediately before legalization. - virtual void addPreLegalizeMachineIR() {} - - /// This method should install a legalize pass, which converts the instruction - /// sequence into one that can be selected by the target. - virtual bool addLegalizeMachineIR() { return true; } - - /// This method may be implemented by targets that want to run passes - /// immediately before the register bank selection. - virtual void addPreRegBankSelect() {} - - /// This method should install a register bank selector pass, which - /// assigns register banks to virtual registers without a register - /// class or register banks. - virtual bool addRegBankSelect() { return true; } - - /// This method may be implemented by targets that want to run passes - /// immediately before the (global) instruction selection. - virtual void addPreGlobalInstructionSelect() {} - - /// This method should install a (global) instruction selector pass, which - /// converts possibly generic instructions to fully target-specific - /// instructions, thereby constraining all generic virtual registers to - /// register classes. - virtual bool addGlobalInstructionSelect() { return true; } - - /// Add the complete, standard set of LLVM CodeGen passes. - /// Fully developed targets will not generally override this. - virtual void addMachinePasses(); - - /// Create an instance of ScheduleDAGInstrs to be run within the standard - /// MachineScheduler pass for this function and target at the current - /// optimization level. - /// - /// This can also be used to plug a new MachineSchedStrategy into an instance - /// of the standard ScheduleDAGMI: - /// return new ScheduleDAGMI(C, std::make_unique(C), /*RemoveKillFlags=*/false) - /// - /// Return NULL to select the default (generic) machine scheduler. - virtual ScheduleDAGInstrs * - createMachineScheduler(MachineSchedContext *C) const { - return nullptr; - } - - /// Similar to createMachineScheduler but used when postRA machine scheduling - /// is enabled. - virtual ScheduleDAGInstrs * - createPostMachineScheduler(MachineSchedContext *C) const { - return nullptr; - } - - /// printAndVerify - Add a pass to dump then verify the machine function, if - /// those steps are enabled. - void printAndVerify(const std::string &Banner); - - /// Add a pass to print the machine function if printing is enabled. - void addPrintPass(const std::string &Banner); - - /// Add a pass to perform basic verification of the machine function if - /// verification is enabled. - void addVerifyPass(const std::string &Banner); - - /// Add a pass to add synthesized debug info to the MIR. - void addDebugifyPass(); - - /// Add a pass to remove debug info from the MIR. - void addStripDebugPass(); - - /// Add a pass to check synthesized debug info for MIR. - void addCheckDebugPass(); - - /// Add standard passes before a pass that's about to be added. For example, - /// the DebugifyMachineModulePass if it is enabled. - void addMachinePrePasses(bool AllowDebugify = true); - - /// Add standard passes after a pass that has just been added. For example, - /// the MachineVerifier if it is enabled. - void addMachinePostPasses(const std::string &Banner); - - /// Check whether or not GlobalISel should abort on error. - /// When this is disabled, GlobalISel will fall back on SDISel instead of - /// erroring out. - bool isGlobalISelAbortEnabled() const; - - /// Check whether or not a diagnostic should be emitted when GlobalISel - /// uses the fallback path. In other words, it will emit a diagnostic - /// when GlobalISel failed and isGlobalISelAbortEnabled is false. - virtual bool reportDiagnosticWhenGlobalISelFallback() const; - - /// Check whether continuous CSE should be enabled in GISel passes. - /// By default, it's enabled for non O0 levels. - virtual bool isGISelCSEEnabled() const; - - /// Returns the CSEConfig object to use for the current optimization level. - virtual std::unique_ptr getCSEConfig() const; - -protected: - // Helper to verify the analysis is really immutable. - void setOpt(bool &Opt, bool Val); - - /// Methods with trivial inline returns are convenient points in the common - /// codegen pass pipeline where targets may insert passes. Methods with - /// out-of-line standard implementations are major CodeGen stages called by - /// addMachinePasses. Some targets may override major stages when inserting - /// passes is insufficient, but maintaining overridden stages is more work. - /// - - /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM - /// passes (which are run just before instruction selector). - virtual bool addPreISel() { - return true; - } - - /// addMachineSSAOptimization - Add standard passes that optimize machine - /// instructions in SSA form. - virtual void addMachineSSAOptimization(); - - /// Add passes that optimize instruction level parallelism for out-of-order - /// targets. These passes are run while the machine code is still in SSA - /// form, so they can use MachineTraceMetrics to control their heuristics. - /// - /// All passes added here should preserve the MachineDominatorTree, - /// MachineLoopInfo, and MachineTraceMetrics analyses. - virtual bool addILPOpts() { - return false; - } - - /// This method may be implemented by targets that want to run passes - /// immediately before register allocation. - virtual void addPreRegAlloc() { } - - /// createTargetRegisterAllocator - Create the register allocator pass for - /// this target at the current optimization level. - virtual FunctionPass *createTargetRegisterAllocator(bool Optimized); - - /// addFastRegAlloc - Add the minimum set of target-independent passes that - /// are required for fast register allocation. - virtual void addFastRegAlloc(); - - /// addOptimizedRegAlloc - Add passes related to register allocation. - /// LLVMTargetMachine provides standard regalloc passes for most targets. - virtual void addOptimizedRegAlloc(); - - /// addPreRewrite - Add passes to the optimized register allocation pipeline - /// after register allocation is complete, but before virtual registers are - /// rewritten to physical registers. - /// - /// These passes must preserve VirtRegMap and LiveIntervals, and when running - /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. - /// When these passes run, VirtRegMap contains legal physreg assignments for - /// all virtual registers. - /// - /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not - /// be honored. This is also not generally used for the fast variant, - /// where the allocation and rewriting are done in one pass. - virtual bool addPreRewrite() { - return false; - } - - /// addPostFastRegAllocRewrite - Add passes to the optimized register - /// allocation pipeline after fast register allocation is complete. - virtual bool addPostFastRegAllocRewrite() { return false; } - - /// Add passes to be run immediately after virtual registers are rewritten - /// to physical registers. - virtual void addPostRewrite() { } - - /// This method may be implemented by targets that want to run passes after - /// register allocation pass pipeline but before prolog-epilog insertion. - virtual void addPostRegAlloc() { } - - /// Add passes that optimize machine instructions after register allocation. - virtual void addMachineLateOptimization(); - - /// This method may be implemented by targets that want to run passes after - /// prolog-epilog insertion and before the second instruction scheduling pass. - virtual void addPreSched2() { } - - /// addGCPasses - Add late codegen passes that analyze code for garbage - /// collection. This should return true if GC info should be printed after - /// these passes. - virtual bool addGCPasses(); - - /// Add standard basic block placement passes. - virtual void addBlockPlacement(); - - /// This pass may be implemented by targets that want to run passes - /// immediately before machine code is emitted. - virtual void addPreEmitPass() { } - - /// Targets may add passes immediately before machine code is emitted in this - /// callback. This is called even later than `addPreEmitPass`. - // FIXME: Rename `addPreEmitPass` to something more sensible given its actual - // position and remove the `2` suffix here as this callback is what - // `addPreEmitPass` *should* be but in reality isn't. - virtual void addPreEmitPass2() {} - - /// Utilities for targets to add passes to the pass manager. - /// - - /// Add a CodeGen pass at this point in the pipeline after checking overrides. - /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); - - /// Add a pass to the PassManager if that pass is supposed to be run, as - /// determined by the StartAfter and StopAfter options. Takes ownership of the - /// pass. - void addPass(Pass *P); - - /// addMachinePasses helper to create the target-selected or overridden - /// regalloc pass. - virtual FunctionPass *createRegAllocPass(bool Optimized); - - /// Add core register allocator passes which do the actual register assignment - /// and rewriting. \returns true if any passes were added. - virtual bool addRegAssignAndRewriteFast(); - virtual bool addRegAssignAndRewriteOptimized(); -}; - -void registerCodeGenCallback(PassInstrumentationCallbacks &PIC, - LLVMTargetMachine &); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETPASSCONFIG_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetRegisterInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetRegisterInfo.h deleted file mode 100644 index 04a1252512..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetRegisterInfo.h +++ /dev/null @@ -1,1294 +0,0 @@ -//==- CodeGen/TargetRegisterInfo.h - Target Register Information -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes an abstract interface used to get information about a -// target machines register file. This information is used for a variety of -// purposed, especially register allocation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETREGISTERINFO_H -#define LLVM_CODEGEN_TARGETREGISTERINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/MC/LaneBitmask.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Printable.h" -#include -#include -#include - -namespace llvm { - -class BitVector; -class DIExpression; -class LiveRegMatrix; -class MachineFunction; -class MachineInstr; -class RegScavenger; -class VirtRegMap; -class LiveIntervals; -class LiveInterval; - -class TargetRegisterClass { -public: - using iterator = const MCPhysReg *; - using const_iterator = const MCPhysReg *; - using sc_iterator = const TargetRegisterClass* const *; - - // Instance variables filled by tablegen, do not use! - const MCRegisterClass *MC; - const uint32_t *SubClassMask; - const uint16_t *SuperRegIndices; - const LaneBitmask LaneMask; - /// Classes with a higher priority value are assigned first by register - /// allocators using a greedy heuristic. The value is in the range [0,63]. - const uint8_t AllocationPriority; - /// Configurable target specific flags. - const uint8_t TSFlags; - /// Whether the class supports two (or more) disjunct subregister indices. - const bool HasDisjunctSubRegs; - /// Whether a combination of subregisters can cover every register in the - /// class. See also the CoveredBySubRegs description in Target.td. - const bool CoveredBySubRegs; - const sc_iterator SuperClasses; - ArrayRef (*OrderFunc)(const MachineFunction&); - - /// Return the register class ID number. - unsigned getID() const { return MC->getID(); } - - /// begin/end - Return all of the registers in this class. - /// - iterator begin() const { return MC->begin(); } - iterator end() const { return MC->end(); } - - /// Return the number of registers in this class. - unsigned getNumRegs() const { return MC->getNumRegs(); } - - iterator_range::const_iterator> - getRegisters() const { - return make_range(MC->begin(), MC->end()); - } - - /// Return the specified register in the class. - MCRegister getRegister(unsigned i) const { - return MC->getRegister(i); - } - - /// Return true if the specified register is included in this register class. - /// This does not include virtual registers. - bool contains(Register Reg) const { - /// FIXME: Historically this function has returned false when given vregs - /// but it should probably only receive physical registers - if (!Reg.isPhysical()) - return false; - return MC->contains(Reg.asMCReg()); - } - - /// Return true if both registers are in this class. - bool contains(Register Reg1, Register Reg2) const { - /// FIXME: Historically this function has returned false when given a vregs - /// but it should probably only receive physical registers - if (!Reg1.isPhysical() || !Reg2.isPhysical()) - return false; - return MC->contains(Reg1.asMCReg(), Reg2.asMCReg()); - } - - /// Return the cost of copying a value between two registers in this class. - /// A negative number means the register class is very expensive - /// to copy e.g. status flag register classes. - int getCopyCost() const { return MC->getCopyCost(); } - - /// Return true if this register class may be used to create virtual - /// registers. - bool isAllocatable() const { return MC->isAllocatable(); } - - /// Return true if the specified TargetRegisterClass - /// is a proper sub-class of this TargetRegisterClass. - bool hasSubClass(const TargetRegisterClass *RC) const { - return RC != this && hasSubClassEq(RC); - } - - /// Returns true if RC is a sub-class of or equal to this class. - bool hasSubClassEq(const TargetRegisterClass *RC) const { - unsigned ID = RC->getID(); - return (SubClassMask[ID / 32] >> (ID % 32)) & 1; - } - - /// Return true if the specified TargetRegisterClass is a - /// proper super-class of this TargetRegisterClass. - bool hasSuperClass(const TargetRegisterClass *RC) const { - return RC->hasSubClass(this); - } - - /// Returns true if RC is a super-class of or equal to this class. - bool hasSuperClassEq(const TargetRegisterClass *RC) const { - return RC->hasSubClassEq(this); - } - - /// Returns a bit vector of subclasses, including this one. - /// The vector is indexed by class IDs. - /// - /// To use it, consider the returned array as a chunk of memory that - /// contains an array of bits of size NumRegClasses. Each 32-bit chunk - /// contains a bitset of the ID of the subclasses in big-endian style. - - /// I.e., the representation of the memory from left to right at the - /// bit level looks like: - /// [31 30 ... 1 0] [ 63 62 ... 33 32] ... - /// [ XXX NumRegClasses NumRegClasses - 1 ... ] - /// Where the number represents the class ID and XXX bits that - /// should be ignored. - /// - /// See the implementation of hasSubClassEq for an example of how it - /// can be used. - const uint32_t *getSubClassMask() const { - return SubClassMask; - } - - /// Returns a 0-terminated list of sub-register indices that project some - /// super-register class into this register class. The list has an entry for - /// each Idx such that: - /// - /// There exists SuperRC where: - /// For all Reg in SuperRC: - /// this->contains(Reg:Idx) - const uint16_t *getSuperRegIndices() const { - return SuperRegIndices; - } - - /// Returns a NULL-terminated list of super-classes. The - /// classes are ordered by ID which is also a topological ordering from large - /// to small classes. The list does NOT include the current class. - sc_iterator getSuperClasses() const { - return SuperClasses; - } - - /// Return true if this TargetRegisterClass is a subset - /// class of at least one other TargetRegisterClass. - bool isASubClass() const { - return SuperClasses[0] != nullptr; - } - - /// Returns the preferred order for allocating registers from this register - /// class in MF. The raw order comes directly from the .td file and may - /// include reserved registers that are not allocatable. - /// Register allocators should also make sure to allocate - /// callee-saved registers only after all the volatiles are used. The - /// RegisterClassInfo class provides filtered allocation orders with - /// callee-saved registers moved to the end. - /// - /// The MachineFunction argument can be used to tune the allocatable - /// registers based on the characteristics of the function, subtarget, or - /// other criteria. - /// - /// By default, this method returns all registers in the class. - ArrayRef getRawAllocationOrder(const MachineFunction &MF) const { - return OrderFunc ? OrderFunc(MF) : makeArrayRef(begin(), getNumRegs()); - } - - /// Returns the combination of all lane masks of register in this class. - /// The lane masks of the registers are the combination of all lane masks - /// of their subregisters. Returns 1 if there are no subregisters. - LaneBitmask getLaneMask() const { - return LaneMask; - } -}; - -/// Extra information, not in MCRegisterDesc, about registers. -/// These are used by codegen, not by MC. -struct TargetRegisterInfoDesc { - const uint8_t *CostPerUse; // Extra cost of instructions using register. - unsigned NumCosts; // Number of cost values associated with each register. - const bool - *InAllocatableClass; // Register belongs to an allocatable regclass. -}; - -/// Each TargetRegisterClass has a per register weight, and weight -/// limit which must be less than the limits of its pressure sets. -struct RegClassWeight { - unsigned RegWeight; - unsigned WeightLimit; -}; - -/// TargetRegisterInfo base class - We assume that the target defines a static -/// array of TargetRegisterDesc objects that represent all of the machine -/// registers that the target has. As such, we simply have to track a pointer -/// to this array so that we can turn register number into a register -/// descriptor. -/// -class TargetRegisterInfo : public MCRegisterInfo { -public: - using regclass_iterator = const TargetRegisterClass * const *; - using vt_iterator = const MVT::SimpleValueType *; - struct RegClassInfo { - unsigned RegSize, SpillSize, SpillAlignment; - vt_iterator VTList; - }; -private: - const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen - const char *const *SubRegIndexNames; // Names of subreg indexes. - // Pointer to array of lane masks, one per sub-reg index. - const LaneBitmask *SubRegIndexLaneMasks; - - regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses - LaneBitmask CoveringLanes; - const RegClassInfo *const RCInfos; - unsigned HwMode; - -protected: - TargetRegisterInfo(const TargetRegisterInfoDesc *ID, - regclass_iterator RCB, - regclass_iterator RCE, - const char *const *SRINames, - const LaneBitmask *SRILaneMasks, - LaneBitmask CoveringLanes, - const RegClassInfo *const RCIs, - unsigned Mode = 0); - virtual ~TargetRegisterInfo(); - -public: - // Register numbers can represent physical registers, virtual registers, and - // sometimes stack slots. The unsigned values are divided into these ranges: - // - // 0 Not a register, can be used as a sentinel. - // [1;2^30) Physical registers assigned by TableGen. - // [2^30;2^31) Stack slots. (Rarely used.) - // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. - // - // Further sentinels can be allocated from the small negative integers. - // DenseMapInfo uses -1u and -2u. - - /// Return the size in bits of a register from class RC. - unsigned getRegSizeInBits(const TargetRegisterClass &RC) const { - return getRegClassInfo(RC).RegSize; - } - - /// Return the size in bytes of the stack slot allocated to hold a spilled - /// copy of a register from class RC. - unsigned getSpillSize(const TargetRegisterClass &RC) const { - return getRegClassInfo(RC).SpillSize / 8; - } - - /// Return the minimum required alignment in bytes for a spill slot for - /// a register of this class. - Align getSpillAlign(const TargetRegisterClass &RC) const { - return Align(getRegClassInfo(RC).SpillAlignment / 8); - } - - /// Return true if the given TargetRegisterClass has the ValueType T. - bool isTypeLegalForClass(const TargetRegisterClass &RC, MVT T) const { - for (auto I = legalclasstypes_begin(RC); *I != MVT::Other; ++I) - if (MVT(*I) == T) - return true; - return false; - } - - /// Return true if the given TargetRegisterClass is compatible with LLT T. - bool isTypeLegalForClass(const TargetRegisterClass &RC, LLT T) const { - for (auto I = legalclasstypes_begin(RC); *I != MVT::Other; ++I) { - MVT VT(*I); - if (VT == MVT::Untyped) - return true; - - if (LLT(VT) == T) - return true; - } - return false; - } - - /// Loop over all of the value types that can be represented by values - /// in the given register class. - vt_iterator legalclasstypes_begin(const TargetRegisterClass &RC) const { - return getRegClassInfo(RC).VTList; - } - - vt_iterator legalclasstypes_end(const TargetRegisterClass &RC) const { - vt_iterator I = legalclasstypes_begin(RC); - while (*I != MVT::Other) - ++I; - return I; - } - - /// Returns the Register Class of a physical register of the given type, - /// picking the most sub register class of the right type that contains this - /// physreg. - const TargetRegisterClass *getMinimalPhysRegClass(MCRegister Reg, - MVT VT = MVT::Other) const; - - /// Returns the Register Class of a physical register of the given type, - /// picking the most sub register class of the right type that contains this - /// physreg. If there is no register class compatible with the given type, - /// returns nullptr. - const TargetRegisterClass *getMinimalPhysRegClassLLT(MCRegister Reg, - LLT Ty = LLT()) const; - - /// Return the maximal subclass of the given register class that is - /// allocatable or NULL. - const TargetRegisterClass * - getAllocatableClass(const TargetRegisterClass *RC) const; - - /// Returns a bitset indexed by register number indicating if a register is - /// allocatable or not. If a register class is specified, returns the subset - /// for the class. - BitVector getAllocatableSet(const MachineFunction &MF, - const TargetRegisterClass *RC = nullptr) const; - - /// Get a list of cost values for all registers that correspond to the index - /// returned by RegisterCostTableIndex. - ArrayRef getRegisterCosts(const MachineFunction &MF) const { - unsigned Idx = getRegisterCostTableIndex(MF); - unsigned NumRegs = getNumRegs(); - assert(Idx < InfoDesc->NumCosts && "CostPerUse index out of bounds"); - - return makeArrayRef(&InfoDesc->CostPerUse[Idx * NumRegs], NumRegs); - } - - /// Return true if the register is in the allocation of any register class. - bool isInAllocatableClass(MCRegister RegNo) const { - return InfoDesc->InAllocatableClass[RegNo]; - } - - /// Return the human-readable symbolic target-specific - /// name for the specified SubRegIndex. - const char *getSubRegIndexName(unsigned SubIdx) const { - assert(SubIdx && SubIdx < getNumSubRegIndices() && - "This is not a subregister index"); - return SubRegIndexNames[SubIdx-1]; - } - - /// Return a bitmask representing the parts of a register that are covered by - /// SubIdx \see LaneBitmask. - /// - /// SubIdx == 0 is allowed, it has the lane mask ~0u. - LaneBitmask getSubRegIndexLaneMask(unsigned SubIdx) const { - assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index"); - return SubRegIndexLaneMasks[SubIdx]; - } - - /// Try to find one or more subregister indexes to cover \p LaneMask. - /// - /// If this is possible, returns true and appends the best matching set of - /// indexes to \p Indexes. If this is not possible, returns false. - bool getCoveringSubRegIndexes(const MachineRegisterInfo &MRI, - const TargetRegisterClass *RC, - LaneBitmask LaneMask, - SmallVectorImpl &Indexes) const; - - /// The lane masks returned by getSubRegIndexLaneMask() above can only be - /// used to determine if sub-registers overlap - they can't be used to - /// determine if a set of sub-registers completely cover another - /// sub-register. - /// - /// The X86 general purpose registers have two lanes corresponding to the - /// sub_8bit and sub_8bit_hi sub-registers. Both sub_32bit and sub_16bit have - /// lane masks '3', but the sub_16bit sub-register doesn't fully cover the - /// sub_32bit sub-register. - /// - /// On the other hand, the ARM NEON lanes fully cover their registers: The - /// dsub_0 sub-register is completely covered by the ssub_0 and ssub_1 lanes. - /// This is related to the CoveredBySubRegs property on register definitions. - /// - /// This function returns a bit mask of lanes that completely cover their - /// sub-registers. More precisely, given: - /// - /// Covering = getCoveringLanes(); - /// MaskA = getSubRegIndexLaneMask(SubA); - /// MaskB = getSubRegIndexLaneMask(SubB); - /// - /// If (MaskA & ~(MaskB & Covering)) == 0, then SubA is completely covered by - /// SubB. - LaneBitmask getCoveringLanes() const { return CoveringLanes; } - - /// Returns true if the two registers are equal or alias each other. - /// The registers may be virtual registers. - bool regsOverlap(Register regA, Register regB) const { - if (regA == regB) return true; - if (!regA.isPhysical() || !regB.isPhysical()) - return false; - - // Regunits are numerically ordered. Find a common unit. - MCRegUnitIterator RUA(regA.asMCReg(), this); - MCRegUnitIterator RUB(regB.asMCReg(), this); - do { - if (*RUA == *RUB) return true; - if (*RUA < *RUB) ++RUA; - else ++RUB; - } while (RUA.isValid() && RUB.isValid()); - return false; - } - - /// Returns true if Reg contains RegUnit. - bool hasRegUnit(MCRegister Reg, Register RegUnit) const { - for (MCRegUnitIterator Units(Reg, this); Units.isValid(); ++Units) - if (Register(*Units) == RegUnit) - return true; - return false; - } - - /// Returns the original SrcReg unless it is the target of a copy-like - /// operation, in which case we chain backwards through all such operations - /// to the ultimate source register. If a physical register is encountered, - /// we stop the search. - virtual Register lookThruCopyLike(Register SrcReg, - const MachineRegisterInfo *MRI) const; - - /// Find the original SrcReg unless it is the target of a copy-like operation, - /// in which case we chain backwards through all such operations to the - /// ultimate source register. If a physical register is encountered, we stop - /// the search. - /// Return the original SrcReg if all the definitions in the chain only have - /// one user and not a physical register. - virtual Register - lookThruSingleUseCopyChain(Register SrcReg, - const MachineRegisterInfo *MRI) const; - - /// Return a null-terminated list of all of the callee-saved registers on - /// this target. The register should be in the order of desired callee-save - /// stack frame offset. The first register is closest to the incoming stack - /// pointer if stack grows down, and vice versa. - /// Notice: This function does not take into account disabled CSRs. - /// In most cases you will want to use instead the function - /// getCalleeSavedRegs that is implemented in MachineRegisterInfo. - virtual const MCPhysReg* - getCalleeSavedRegs(const MachineFunction *MF) const = 0; - - /// Return a mask of call-preserved registers for the given calling convention - /// on the current function. The mask should include all call-preserved - /// aliases. This is used by the register allocator to determine which - /// registers can be live across a call. - /// - /// The mask is an array containing (TRI::getNumRegs()+31)/32 entries. - /// A set bit indicates that all bits of the corresponding register are - /// preserved across the function call. The bit mask is expected to be - /// sub-register complete, i.e. if A is preserved, so are all its - /// sub-registers. - /// - /// Bits are numbered from the LSB, so the bit for physical register Reg can - /// be found as (Mask[Reg / 32] >> Reg % 32) & 1. - /// - /// A NULL pointer means that no register mask will be used, and call - /// instructions should use implicit-def operands to indicate call clobbered - /// registers. - /// - virtual const uint32_t *getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID) const { - // The default mask clobbers everything. All targets should override. - return nullptr; - } - - /// Return a register mask for the registers preserved by the unwinder, - /// or nullptr if no custom mask is needed. - virtual const uint32_t * - getCustomEHPadPreservedMask(const MachineFunction &MF) const { - return nullptr; - } - - /// Return a register mask that clobbers everything. - virtual const uint32_t *getNoPreservedMask() const { - llvm_unreachable("target does not provide no preserved mask"); - } - - /// Return a list of all of the registers which are clobbered "inside" a call - /// to the given function. For example, these might be needed for PLT - /// sequences of long-branch veneers. - virtual ArrayRef - getIntraCallClobberedRegs(const MachineFunction *MF) const { - return {}; - } - - /// Return true if all bits that are set in mask \p mask0 are also set in - /// \p mask1. - bool regmaskSubsetEqual(const uint32_t *mask0, const uint32_t *mask1) const; - - /// Return all the call-preserved register masks defined for this target. - virtual ArrayRef getRegMasks() const = 0; - virtual ArrayRef getRegMaskNames() const = 0; - - /// Returns a bitset indexed by physical register number indicating if a - /// register is a special register that has particular uses and should be - /// considered unavailable at all times, e.g. stack pointer, return address. - /// A reserved register: - /// - is not allocatable - /// - is considered always live - /// - is ignored by liveness tracking - /// It is often necessary to reserve the super registers of a reserved - /// register as well, to avoid them getting allocated indirectly. You may use - /// markSuperRegs() and checkAllSuperRegsMarked() in this case. - virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; - - /// Returns false if we can't guarantee that Physreg, specified as an IR asm - /// clobber constraint, will be preserved across the statement. - virtual bool isAsmClobberable(const MachineFunction &MF, - MCRegister PhysReg) const { - return true; - } - - /// Returns true if PhysReg cannot be written to in inline asm statements. - virtual bool isInlineAsmReadOnlyReg(const MachineFunction &MF, - unsigned PhysReg) const { - return false; - } - - /// Returns true if PhysReg is unallocatable and constant throughout the - /// function. Used by MachineRegisterInfo::isConstantPhysReg(). - virtual bool isConstantPhysReg(MCRegister PhysReg) const { return false; } - - /// Returns true if the register class is considered divergent. - virtual bool isDivergentRegClass(const TargetRegisterClass *RC) const { - return false; - } - - /// Physical registers that may be modified within a function but are - /// guaranteed to be restored before any uses. This is useful for targets that - /// have call sequences where a GOT register may be updated by the caller - /// prior to a call and is guaranteed to be restored (also by the caller) - /// after the call. - virtual bool isCallerPreservedPhysReg(MCRegister PhysReg, - const MachineFunction &MF) const { - return false; - } - - /// This is a wrapper around getCallPreservedMask(). - /// Return true if the register is preserved after the call. - virtual bool isCalleeSavedPhysReg(MCRegister PhysReg, - const MachineFunction &MF) const; - - /// Prior to adding the live-out mask to a stackmap or patchpoint - /// instruction, provide the target the opportunity to adjust it (mainly to - /// remove pseudo-registers that should be ignored). - virtual void adjustStackMapLiveOutMask(uint32_t *Mask) const {} - - /// Return a super-register of the specified register - /// Reg so its sub-register of index SubIdx is Reg. - MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx, - const TargetRegisterClass *RC) const { - return MCRegisterInfo::getMatchingSuperReg(Reg, SubIdx, RC->MC); - } - - /// Return a subclass of the specified register - /// class A so that each register in it has a sub-register of the - /// specified sub-register index which is in the specified register class B. - /// - /// TableGen will synthesize missing A sub-classes. - virtual const TargetRegisterClass * - getMatchingSuperRegClass(const TargetRegisterClass *A, - const TargetRegisterClass *B, unsigned Idx) const; - - // For a copy-like instruction that defines a register of class DefRC with - // subreg index DefSubReg, reading from another source with class SrcRC and - // subregister SrcSubReg return true if this is a preferable copy - // instruction or an earlier use should be used. - virtual bool shouldRewriteCopySrc(const TargetRegisterClass *DefRC, - unsigned DefSubReg, - const TargetRegisterClass *SrcRC, - unsigned SrcSubReg) const; - - /// Returns the largest legal sub-class of RC that - /// supports the sub-register index Idx. - /// If no such sub-class exists, return NULL. - /// If all registers in RC already have an Idx sub-register, return RC. - /// - /// TableGen generates a version of this function that is good enough in most - /// cases. Targets can override if they have constraints that TableGen - /// doesn't understand. For example, the x86 sub_8bit sub-register index is - /// supported by the full GR32 register class in 64-bit mode, but only by the - /// GR32_ABCD regiister class in 32-bit mode. - /// - /// TableGen will synthesize missing RC sub-classes. - virtual const TargetRegisterClass * - getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const { - assert(Idx == 0 && "Target has no sub-registers"); - return RC; - } - - /// Return the subregister index you get from composing - /// two subregister indices. - /// - /// The special null sub-register index composes as the identity. - /// - /// If R:a:b is the same register as R:c, then composeSubRegIndices(a, b) - /// returns c. Note that composeSubRegIndices does not tell you about illegal - /// compositions. If R does not have a subreg a, or R:a does not have a subreg - /// b, composeSubRegIndices doesn't tell you. - /// - /// The ARM register Q0 has two D subregs dsub_0:D0 and dsub_1:D1. It also has - /// ssub_0:S0 - ssub_3:S3 subregs. - /// If you compose subreg indices dsub_1, ssub_0 you get ssub_2. - unsigned composeSubRegIndices(unsigned a, unsigned b) const { - if (!a) return b; - if (!b) return a; - return composeSubRegIndicesImpl(a, b); - } - - /// Transforms a LaneMask computed for one subregister to the lanemask that - /// would have been computed when composing the subsubregisters with IdxA - /// first. @sa composeSubRegIndices() - LaneBitmask composeSubRegIndexLaneMask(unsigned IdxA, - LaneBitmask Mask) const { - if (!IdxA) - return Mask; - return composeSubRegIndexLaneMaskImpl(IdxA, Mask); - } - - /// Transform a lanemask given for a virtual register to the corresponding - /// lanemask before using subregister with index \p IdxA. - /// This is the reverse of composeSubRegIndexLaneMask(), assuming Mask is a - /// valie lane mask (no invalid bits set) the following holds: - /// X0 = composeSubRegIndexLaneMask(Idx, Mask) - /// X1 = reverseComposeSubRegIndexLaneMask(Idx, X0) - /// => X1 == Mask - LaneBitmask reverseComposeSubRegIndexLaneMask(unsigned IdxA, - LaneBitmask LaneMask) const { - if (!IdxA) - return LaneMask; - return reverseComposeSubRegIndexLaneMaskImpl(IdxA, LaneMask); - } - - /// Debugging helper: dump register in human readable form to dbgs() stream. - static void dumpReg(Register Reg, unsigned SubRegIndex = 0, - const TargetRegisterInfo *TRI = nullptr); - -protected: - /// Overridden by TableGen in targets that have sub-registers. - virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const { - llvm_unreachable("Target has no sub-registers"); - } - - /// Overridden by TableGen in targets that have sub-registers. - virtual LaneBitmask - composeSubRegIndexLaneMaskImpl(unsigned, LaneBitmask) const { - llvm_unreachable("Target has no sub-registers"); - } - - virtual LaneBitmask reverseComposeSubRegIndexLaneMaskImpl(unsigned, - LaneBitmask) const { - llvm_unreachable("Target has no sub-registers"); - } - - /// Return the register cost table index. This implementation is sufficient - /// for most architectures and can be overridden by targets in case there are - /// multiple cost values associated with each register. - virtual unsigned getRegisterCostTableIndex(const MachineFunction &MF) const { - return 0; - } - -public: - /// Find a common super-register class if it exists. - /// - /// Find a register class, SuperRC and two sub-register indices, PreA and - /// PreB, such that: - /// - /// 1. PreA + SubA == PreB + SubB (using composeSubRegIndices()), and - /// - /// 2. For all Reg in SuperRC: Reg:PreA in RCA and Reg:PreB in RCB, and - /// - /// 3. SuperRC->getSize() >= max(RCA->getSize(), RCB->getSize()). - /// - /// SuperRC will be chosen such that no super-class of SuperRC satisfies the - /// requirements, and there is no register class with a smaller spill size - /// that satisfies the requirements. - /// - /// SubA and SubB must not be 0. Use getMatchingSuperRegClass() instead. - /// - /// Either of the PreA and PreB sub-register indices may be returned as 0. In - /// that case, the returned register class will be a sub-class of the - /// corresponding argument register class. - /// - /// The function returns NULL if no register class can be found. - const TargetRegisterClass* - getCommonSuperRegClass(const TargetRegisterClass *RCA, unsigned SubA, - const TargetRegisterClass *RCB, unsigned SubB, - unsigned &PreA, unsigned &PreB) const; - - //===--------------------------------------------------------------------===// - // Register Class Information - // -protected: - const RegClassInfo &getRegClassInfo(const TargetRegisterClass &RC) const { - return RCInfos[getNumRegClasses() * HwMode + RC.getID()]; - } - -public: - /// Register class iterators - regclass_iterator regclass_begin() const { return RegClassBegin; } - regclass_iterator regclass_end() const { return RegClassEnd; } - iterator_range regclasses() const { - return make_range(regclass_begin(), regclass_end()); - } - - unsigned getNumRegClasses() const { - return (unsigned)(regclass_end()-regclass_begin()); - } - - /// Returns the register class associated with the enumeration value. - /// See class MCOperandInfo. - const TargetRegisterClass *getRegClass(unsigned i) const { - assert(i < getNumRegClasses() && "Register Class ID out of range"); - return RegClassBegin[i]; - } - - /// Returns the name of the register class. - const char *getRegClassName(const TargetRegisterClass *Class) const { - return MCRegisterInfo::getRegClassName(Class->MC); - } - - /// Find the largest common subclass of A and B. - /// Return NULL if there is no common subclass. - const TargetRegisterClass * - getCommonSubClass(const TargetRegisterClass *A, - const TargetRegisterClass *B) const; - - /// Returns a TargetRegisterClass used for pointer values. - /// If a target supports multiple different pointer register classes, - /// kind specifies which one is indicated. - virtual const TargetRegisterClass * - getPointerRegClass(const MachineFunction &MF, unsigned Kind=0) const { - llvm_unreachable("Target didn't implement getPointerRegClass!"); - } - - /// Returns a legal register class to copy a register in the specified class - /// to or from. If it is possible to copy the register directly without using - /// a cross register class copy, return the specified RC. Returns NULL if it - /// is not possible to copy between two registers of the specified class. - virtual const TargetRegisterClass * - getCrossCopyRegClass(const TargetRegisterClass *RC) const { - return RC; - } - - /// Returns the largest super class of RC that is legal to use in the current - /// sub-target and has the same spill size. - /// The returned register class can be used to create virtual registers which - /// means that all its registers can be copied and spilled. - virtual const TargetRegisterClass * - getLargestLegalSuperClass(const TargetRegisterClass *RC, - const MachineFunction &) const { - /// The default implementation is very conservative and doesn't allow the - /// register allocator to inflate register classes. - return RC; - } - - /// Return the register pressure "high water mark" for the specific register - /// class. The scheduler is in high register pressure mode (for the specific - /// register class) if it goes over the limit. - /// - /// Note: this is the old register pressure model that relies on a manually - /// specified representative register class per value type. - virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const { - return 0; - } - - /// Return a heuristic for the machine scheduler to compare the profitability - /// of increasing one register pressure set versus another. The scheduler - /// will prefer increasing the register pressure of the set which returns - /// the largest value for this function. - virtual unsigned getRegPressureSetScore(const MachineFunction &MF, - unsigned PSetID) const { - return PSetID; - } - - /// Get the weight in units of pressure for this register class. - virtual const RegClassWeight &getRegClassWeight( - const TargetRegisterClass *RC) const = 0; - - /// Returns size in bits of a phys/virtual/generic register. - unsigned getRegSizeInBits(Register Reg, const MachineRegisterInfo &MRI) const; - - /// Get the weight in units of pressure for this register unit. - virtual unsigned getRegUnitWeight(unsigned RegUnit) const = 0; - - /// Get the number of dimensions of register pressure. - virtual unsigned getNumRegPressureSets() const = 0; - - /// Get the name of this register unit pressure set. - virtual const char *getRegPressureSetName(unsigned Idx) const = 0; - - /// Get the register unit pressure limit for this dimension. - /// This limit must be adjusted dynamically for reserved registers. - virtual unsigned getRegPressureSetLimit(const MachineFunction &MF, - unsigned Idx) const = 0; - - /// Get the dimensions of register pressure impacted by this register class. - /// Returns a -1 terminated array of pressure set IDs. - virtual const int *getRegClassPressureSets( - const TargetRegisterClass *RC) const = 0; - - /// Get the dimensions of register pressure impacted by this register unit. - /// Returns a -1 terminated array of pressure set IDs. - virtual const int *getRegUnitPressureSets(unsigned RegUnit) const = 0; - - /// Get a list of 'hint' registers that the register allocator should try - /// first when allocating a physical register for the virtual register - /// VirtReg. These registers are effectively moved to the front of the - /// allocation order. If true is returned, regalloc will try to only use - /// hints to the greatest extent possible even if it means spilling. - /// - /// The Order argument is the allocation order for VirtReg's register class - /// as returned from RegisterClassInfo::getOrder(). The hint registers must - /// come from Order, and they must not be reserved. - /// - /// The default implementation of this function will only add target - /// independent register allocation hints. Targets that override this - /// function should typically call this default implementation as well and - /// expect to see generic copy hints added. - virtual bool - getRegAllocationHints(Register VirtReg, ArrayRef Order, - SmallVectorImpl &Hints, - const MachineFunction &MF, - const VirtRegMap *VRM = nullptr, - const LiveRegMatrix *Matrix = nullptr) const; - - /// A callback to allow target a chance to update register allocation hints - /// when a register is "changed" (e.g. coalesced) to another register. - /// e.g. On ARM, some virtual registers should target register pairs, - /// if one of pair is coalesced to another register, the allocation hint of - /// the other half of the pair should be changed to point to the new register. - virtual void updateRegAllocHint(Register Reg, Register NewReg, - MachineFunction &MF) const { - // Do nothing. - } - - /// Allow the target to reverse allocation order of local live ranges. This - /// will generally allocate shorter local live ranges first. For targets with - /// many registers, this could reduce regalloc compile time by a large - /// factor. It is disabled by default for three reasons: - /// (1) Top-down allocation is simpler and easier to debug for targets that - /// don't benefit from reversing the order. - /// (2) Bottom-up allocation could result in poor evicition decisions on some - /// targets affecting the performance of compiled code. - /// (3) Bottom-up allocation is no longer guaranteed to optimally color. - virtual bool reverseLocalAssignment() const { return false; } - - /// Allow the target to override the cost of using a callee-saved register for - /// the first time. Default value of 0 means we will use a callee-saved - /// register if it is available. - virtual unsigned getCSRFirstUseCost() const { return 0; } - - /// Returns true if the target requires (and can make use of) the register - /// scavenger. - virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { - return false; - } - - /// Returns true if the target wants to use frame pointer based accesses to - /// spill to the scavenger emergency spill slot. - virtual bool useFPForScavengingIndex(const MachineFunction &MF) const { - return true; - } - - /// Returns true if the target requires post PEI scavenging of registers for - /// materializing frame index constants. - virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const { - return false; - } - - /// Returns true if the target requires using the RegScavenger directly for - /// frame elimination despite using requiresFrameIndexScavenging. - virtual bool requiresFrameIndexReplacementScavenging( - const MachineFunction &MF) const { - return false; - } - - /// Returns true if the target wants the LocalStackAllocation pass to be run - /// and virtual base registers used for more efficient stack access. - virtual bool requiresVirtualBaseRegisters(const MachineFunction &MF) const { - return false; - } - - /// Return true if target has reserved a spill slot in the stack frame of - /// the given function for the specified register. e.g. On x86, if the frame - /// register is required, the first fixed stack object is reserved as its - /// spill slot. This tells PEI not to create a new stack frame - /// object for the given register. It should be called only after - /// determineCalleeSaves(). - virtual bool hasReservedSpillSlot(const MachineFunction &MF, Register Reg, - int &FrameIdx) const { - return false; - } - - /// Returns true if the live-ins should be tracked after register allocation. - virtual bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const { - return true; - } - - /// True if the stack can be realigned for the target. - virtual bool canRealignStack(const MachineFunction &MF) const; - - /// True if storage within the function requires the stack pointer to be - /// aligned more than the normal calling convention calls for. - virtual bool shouldRealignStack(const MachineFunction &MF) const; - - /// True if stack realignment is required and still possible. - bool hasStackRealignment(const MachineFunction &MF) const { - return shouldRealignStack(MF) && canRealignStack(MF); - } - - /// Get the offset from the referenced frame index in the instruction, - /// if there is one. - virtual int64_t getFrameIndexInstrOffset(const MachineInstr *MI, - int Idx) const { - return 0; - } - - /// Returns true if the instruction's frame index reference would be better - /// served by a base register other than FP or SP. - /// Used by LocalStackFrameAllocation to determine which frame index - /// references it should create new base registers for. - virtual bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { - return false; - } - - /// Insert defining instruction(s) for a pointer to FrameIdx before - /// insertion point I. Return materialized frame pointer. - virtual Register materializeFrameBaseRegister(MachineBasicBlock *MBB, - int FrameIdx, - int64_t Offset) const { - llvm_unreachable("materializeFrameBaseRegister does not exist on this " - "target"); - } - - /// Resolve a frame index operand of an instruction - /// to reference the indicated base register plus offset instead. - virtual void resolveFrameIndex(MachineInstr &MI, Register BaseReg, - int64_t Offset) const { - llvm_unreachable("resolveFrameIndex does not exist on this target"); - } - - /// Determine whether a given base register plus offset immediate is - /// encodable to resolve a frame index. - virtual bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, - int64_t Offset) const { - llvm_unreachable("isFrameOffsetLegal does not exist on this target"); - } - - /// Gets the DWARF expression opcodes for \p Offset. - virtual void getOffsetOpcodes(const StackOffset &Offset, - SmallVectorImpl &Ops) const; - - /// Prepends a DWARF expression for \p Offset to DIExpression \p Expr. - DIExpression * - prependOffsetExpression(const DIExpression *Expr, unsigned PrependFlags, - const StackOffset &Offset) const; - - /// Spill the register so it can be used by the register scavenger. - /// Return true if the register was spilled, false otherwise. - /// If this function does not spill the register, the scavenger - /// will instead spill it to the emergency spill slot. - virtual bool saveScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &UseMI, - const TargetRegisterClass *RC, - Register Reg) const { - return false; - } - - /// This method must be overridden to eliminate abstract frame indices from - /// instructions which may use them. The instruction referenced by the - /// iterator contains an MO_FrameIndex operand which must be eliminated by - /// this method. This method may modify or replace the specified instruction, - /// as long as it keeps the iterator pointing at the finished product. - /// SPAdj is the SP adjustment due to call frame setup instruction. - /// FIOperandNum is the FI operand number. - virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = nullptr) const = 0; - - /// Return the assembly name for \p Reg. - virtual StringRef getRegAsmName(MCRegister Reg) const { - // FIXME: We are assuming that the assembly name is equal to the TableGen - // name converted to lower case - // - // The TableGen name is the name of the definition for this register in the - // target's tablegen files. For example, the TableGen name of - // def EAX : Register <...>; is "EAX" - return StringRef(getName(Reg)); - } - - //===--------------------------------------------------------------------===// - /// Subtarget Hooks - - /// SrcRC and DstRC will be morphed into NewRC if this returns true. - virtual bool shouldCoalesce(MachineInstr *MI, - const TargetRegisterClass *SrcRC, - unsigned SubReg, - const TargetRegisterClass *DstRC, - unsigned DstSubReg, - const TargetRegisterClass *NewRC, - LiveIntervals &LIS) const - { return true; } - - /// Region split has a high compile time cost especially for large live range. - /// This method is used to decide whether or not \p VirtReg should - /// go through this expensive splitting heuristic. - virtual bool shouldRegionSplitForVirtReg(const MachineFunction &MF, - const LiveInterval &VirtReg) const; - - /// Last chance recoloring has a high compile time cost especially for - /// targets with a lot of registers. - /// This method is used to decide whether or not \p VirtReg should - /// go through this expensive heuristic. - /// When this target hook is hit, by returning false, there is a high - /// chance that the register allocation will fail altogether (usually with - /// "ran out of registers"). - /// That said, this error usually points to another problem in the - /// optimization pipeline. - virtual bool - shouldUseLastChanceRecoloringForVirtReg(const MachineFunction &MF, - const LiveInterval &VirtReg) const { - return true; - } - - /// Deferred spilling delays the spill insertion of a virtual register - /// after every other allocation. By deferring the spilling, it is - /// sometimes possible to eliminate that spilling altogether because - /// something else could have been eliminated, thus leaving some space - /// for the virtual register. - /// However, this comes with a compile time impact because it adds one - /// more stage to the greedy register allocator. - /// This method is used to decide whether \p VirtReg should use the deferred - /// spilling stage instead of being spilled right away. - virtual bool - shouldUseDeferredSpillingForVirtReg(const MachineFunction &MF, - const LiveInterval &VirtReg) const { - return false; - } - - //===--------------------------------------------------------------------===// - /// Debug information queries. - - /// getFrameRegister - This method should return the register used as a base - /// for values allocated in the current stack frame. - virtual Register getFrameRegister(const MachineFunction &MF) const = 0; - - /// Mark a register and all its aliases as reserved in the given set. - void markSuperRegs(BitVector &RegisterSet, MCRegister Reg) const; - - /// Returns true if for every register in the set all super registers are part - /// of the set as well. - bool checkAllSuperRegsMarked(const BitVector &RegisterSet, - ArrayRef Exceptions = ArrayRef()) const; - - virtual const TargetRegisterClass * - getConstrainedRegClassForOperand(const MachineOperand &MO, - const MachineRegisterInfo &MRI) const { - return nullptr; - } - - /// Returns the physical register number of sub-register "Index" - /// for physical register RegNo. Return zero if the sub-register does not - /// exist. - inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { - return static_cast(this)->getSubReg(Reg, Idx); - } - - /// Some targets have non-allocatable registers that aren't technically part - /// of the explicit callee saved register list, but should be handled as such - /// in certain cases. - virtual bool isNonallocatableRegisterCalleeSave(MCRegister Reg) const { - return false; - } -}; - -//===----------------------------------------------------------------------===// -// SuperRegClassIterator -//===----------------------------------------------------------------------===// -// -// Iterate over the possible super-registers for a given register class. The -// iterator will visit a list of pairs (Idx, Mask) corresponding to the -// possible classes of super-registers. -// -// Each bit mask will have at least one set bit, and each set bit in Mask -// corresponds to a SuperRC such that: -// -// For all Reg in SuperRC: Reg:Idx is in RC. -// -// The iterator can include (O, RC->getSubClassMask()) as the first entry which -// also satisfies the above requirement, assuming Reg:0 == Reg. -// -class SuperRegClassIterator { - const unsigned RCMaskWords; - unsigned SubReg = 0; - const uint16_t *Idx; - const uint32_t *Mask; - -public: - /// Create a SuperRegClassIterator that visits all the super-register classes - /// of RC. When IncludeSelf is set, also include the (0, sub-classes) entry. - SuperRegClassIterator(const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - bool IncludeSelf = false) - : RCMaskWords((TRI->getNumRegClasses() + 31) / 32), - Idx(RC->getSuperRegIndices()), Mask(RC->getSubClassMask()) { - if (!IncludeSelf) - ++*this; - } - - /// Returns true if this iterator is still pointing at a valid entry. - bool isValid() const { return Idx; } - - /// Returns the current sub-register index. - unsigned getSubReg() const { return SubReg; } - - /// Returns the bit mask of register classes that getSubReg() projects into - /// RC. - /// See TargetRegisterClass::getSubClassMask() for how to use it. - const uint32_t *getMask() const { return Mask; } - - /// Advance iterator to the next entry. - void operator++() { - assert(isValid() && "Cannot move iterator past end."); - Mask += RCMaskWords; - SubReg = *Idx++; - if (!SubReg) - Idx = nullptr; - } -}; - -//===----------------------------------------------------------------------===// -// BitMaskClassIterator -//===----------------------------------------------------------------------===// -/// This class encapuslates the logic to iterate over bitmask returned by -/// the various RegClass related APIs. -/// E.g., this class can be used to iterate over the subclasses provided by -/// TargetRegisterClass::getSubClassMask or SuperRegClassIterator::getMask. -class BitMaskClassIterator { - /// Total number of register classes. - const unsigned NumRegClasses; - /// Base index of CurrentChunk. - /// In other words, the number of bit we read to get at the - /// beginning of that chunk. - unsigned Base = 0; - /// Adjust base index of CurrentChunk. - /// Base index + how many bit we read within CurrentChunk. - unsigned Idx = 0; - /// Current register class ID. - unsigned ID = 0; - /// Mask we are iterating over. - const uint32_t *Mask; - /// Current chunk of the Mask we are traversing. - uint32_t CurrentChunk; - - /// Move ID to the next set bit. - void moveToNextID() { - // If the current chunk of memory is empty, move to the next one, - // while making sure we do not go pass the number of register - // classes. - while (!CurrentChunk) { - // Move to the next chunk. - Base += 32; - if (Base >= NumRegClasses) { - ID = NumRegClasses; - return; - } - CurrentChunk = *++Mask; - Idx = Base; - } - // Otherwise look for the first bit set from the right - // (representation of the class ID is big endian). - // See getSubClassMask for more details on the representation. - unsigned Offset = countTrailingZeros(CurrentChunk); - // Add the Offset to the adjusted base number of this chunk: Idx. - // This is the ID of the register class. - ID = Idx + Offset; - - // Consume the zeros, if any, and the bit we just read - // so that we are at the right spot for the next call. - // Do not do Offset + 1 because Offset may be 31 and 32 - // will be UB for the shift, though in that case we could - // have make the chunk being equal to 0, but that would - // have introduced a if statement. - moveNBits(Offset); - moveNBits(1); - } - - /// Move \p NumBits Bits forward in CurrentChunk. - void moveNBits(unsigned NumBits) { - assert(NumBits < 32 && "Undefined behavior spotted!"); - // Consume the bit we read for the next call. - CurrentChunk >>= NumBits; - // Adjust the base for the chunk. - Idx += NumBits; - } - -public: - /// Create a BitMaskClassIterator that visits all the register classes - /// represented by \p Mask. - /// - /// \pre \p Mask != nullptr - BitMaskClassIterator(const uint32_t *Mask, const TargetRegisterInfo &TRI) - : NumRegClasses(TRI.getNumRegClasses()), Mask(Mask), CurrentChunk(*Mask) { - // Move to the first ID. - moveToNextID(); - } - - /// Returns true if this iterator is still pointing at a valid entry. - bool isValid() const { return getID() != NumRegClasses; } - - /// Returns the current register class ID. - unsigned getID() const { return ID; } - - /// Advance iterator to the next entry. - void operator++() { - assert(isValid() && "Cannot move iterator past end."); - moveToNextID(); - } -}; - -// This is useful when building IndexedMaps keyed on virtual registers -struct VirtReg2IndexFunctor { - using argument_type = Register; - unsigned operator()(Register Reg) const { - return Register::virtReg2Index(Reg); - } -}; - -/// Prints virtual and physical registers with or without a TRI instance. -/// -/// The format is: -/// %noreg - NoRegister -/// %5 - a virtual register. -/// %5:sub_8bit - a virtual register with sub-register index (with TRI). -/// %eax - a physical register -/// %physreg17 - a physical register when no TRI instance given. -/// -/// Usage: OS << printReg(Reg, TRI, SubRegIdx) << '\n'; -Printable printReg(Register Reg, const TargetRegisterInfo *TRI = nullptr, - unsigned SubIdx = 0, - const MachineRegisterInfo *MRI = nullptr); - -/// Create Printable object to print register units on a \ref raw_ostream. -/// -/// Register units are named after their root registers: -/// -/// al - Single root. -/// fp0~st7 - Dual roots. -/// -/// Usage: OS << printRegUnit(Unit, TRI) << '\n'; -Printable printRegUnit(unsigned Unit, const TargetRegisterInfo *TRI); - -/// Create Printable object to print virtual registers and physical -/// registers on a \ref raw_ostream. -Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI); - -/// Create Printable object to print register classes or register banks -/// on a \ref raw_ostream. -Printable printRegClassOrBank(Register Reg, const MachineRegisterInfo &RegInfo, - const TargetRegisterInfo *TRI); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETREGISTERINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetSchedule.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetSchedule.h deleted file mode 100644 index 049ede89ab..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetSchedule.h +++ /dev/null @@ -1,208 +0,0 @@ -//===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a wrapper around MCSchedModel that allows the interface to -// benefit from information currently only available in TargetInstrInfo. -// Ideally, the scheduling interface would be fully defined in the MC layer. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETSCHEDULE_H -#define LLVM_CODEGEN_TARGETSCHEDULE_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCInstrItineraries.h" -#include "llvm/MC/MCSchedule.h" - -namespace llvm { - -class MachineInstr; -class TargetInstrInfo; - -/// Provide an instruction scheduling machine model to CodeGen passes. -class TargetSchedModel { - // For efficiency, hold a copy of the statically defined MCSchedModel for this - // processor. - MCSchedModel SchedModel; - InstrItineraryData InstrItins; - const TargetSubtargetInfo *STI = nullptr; - const TargetInstrInfo *TII = nullptr; - - SmallVector ResourceFactors; - - // Multiply to normalize microops to resource units. - unsigned MicroOpFactor = 0; - - // Resource units per cycle. Latency normalization factor. - unsigned ResourceLCM = 0; - - unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const; - -public: - TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {} - - /// Initialize the machine model for instruction scheduling. - /// - /// The machine model API keeps a copy of the top-level MCSchedModel table - /// indices and may query TargetSubtargetInfo and TargetInstrInfo to resolve - /// dynamic properties. - void init(const TargetSubtargetInfo *TSInfo); - - /// Return the MCSchedClassDesc for this instruction. - const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const; - - /// TargetSubtargetInfo getter. - const TargetSubtargetInfo *getSubtargetInfo() const { return STI; } - - /// TargetInstrInfo getter. - const TargetInstrInfo *getInstrInfo() const { return TII; } - - /// Return true if this machine model includes an instruction-level - /// scheduling model. - /// - /// This is more detailed than the course grain IssueWidth and default - /// latency properties, but separate from the per-cycle itinerary data. - bool hasInstrSchedModel() const; - - const MCSchedModel *getMCSchedModel() const { return &SchedModel; } - - /// Return true if this machine model includes cycle-to-cycle itinerary - /// data. - /// - /// This models scheduling at each stage in the processor pipeline. - bool hasInstrItineraries() const; - - const InstrItineraryData *getInstrItineraries() const { - if (hasInstrItineraries()) - return &InstrItins; - return nullptr; - } - - /// Return true if this machine model includes an instruction-level - /// scheduling model or cycle-to-cycle itinerary data. - bool hasInstrSchedModelOrItineraries() const { - return hasInstrSchedModel() || hasInstrItineraries(); - } - - /// Identify the processor corresponding to the current subtarget. - unsigned getProcessorID() const { return SchedModel.getProcessorID(); } - - /// Maximum number of micro-ops that may be scheduled per cycle. - unsigned getIssueWidth() const { return SchedModel.IssueWidth; } - - /// Return true if new group must begin. - bool mustBeginGroup(const MachineInstr *MI, - const MCSchedClassDesc *SC = nullptr) const; - /// Return true if current group must end. - bool mustEndGroup(const MachineInstr *MI, - const MCSchedClassDesc *SC = nullptr) const; - - /// Return the number of issue slots required for this MI. - unsigned getNumMicroOps(const MachineInstr *MI, - const MCSchedClassDesc *SC = nullptr) const; - - /// Get the number of kinds of resources for this target. - unsigned getNumProcResourceKinds() const { - return SchedModel.getNumProcResourceKinds(); - } - - /// Get a processor resource by ID for convenience. - const MCProcResourceDesc *getProcResource(unsigned PIdx) const { - return SchedModel.getProcResource(PIdx); - } - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - const char *getResourceName(unsigned PIdx) const { - if (!PIdx) - return "MOps"; - return SchedModel.getProcResource(PIdx)->Name; - } -#endif - - using ProcResIter = const MCWriteProcResEntry *; - - // Get an iterator into the processor resources consumed by this - // scheduling class. - ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const { - // The subtarget holds a single resource table for all processors. - return STI->getWriteProcResBegin(SC); - } - ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const { - return STI->getWriteProcResEnd(SC); - } - - /// Multiply the number of units consumed for a resource by this factor - /// to normalize it relative to other resources. - unsigned getResourceFactor(unsigned ResIdx) const { - return ResourceFactors[ResIdx]; - } - - /// Multiply number of micro-ops by this factor to normalize it - /// relative to other resources. - unsigned getMicroOpFactor() const { - return MicroOpFactor; - } - - /// Multiply cycle count by this factor to normalize it relative to - /// other resources. This is the number of resource units per cycle. - unsigned getLatencyFactor() const { - return ResourceLCM; - } - - /// Number of micro-ops that may be buffered for OOO execution. - unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; } - - /// Number of resource units that may be buffered for OOO execution. - /// \return The buffer size in resource units or -1 for unlimited. - int getResourceBufferSize(unsigned PIdx) const { - return SchedModel.getProcResource(PIdx)->BufferSize; - } - - /// Compute operand latency based on the available machine model. - /// - /// Compute and return the latency of the given data dependent def and use - /// when the operand indices are already known. UseMI may be NULL for an - /// unknown user. - unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, - const MachineInstr *UseMI, unsigned UseOperIdx) - const; - - /// Compute the instruction latency based on the available machine - /// model. - /// - /// Compute and return the expected latency of this instruction independent of - /// a particular use. computeOperandLatency is the preferred API, but this is - /// occasionally useful to help estimate instruction cost. - /// - /// If UseDefaultDefLatency is false and no new machine sched model is - /// present this method falls back to TII->getInstrLatency with an empty - /// instruction itinerary (this is so we preserve the previous behavior of the - /// if converter after moving it to TargetSchedModel). - unsigned computeInstrLatency(const MachineInstr *MI, - bool UseDefaultDefLatency = true) const; - unsigned computeInstrLatency(const MCInst &Inst) const; - unsigned computeInstrLatency(unsigned Opcode) const; - - - /// Output dependency latency of a pair of defs of the same register. - /// - /// This is typically one cycle. - unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx, - const MachineInstr *DepMI) const; - - /// Compute the reciprocal throughput of the given instruction. - double computeReciprocalThroughput(const MachineInstr *MI) const; - double computeReciprocalThroughput(const MCInst &MI) const; - double computeReciprocalThroughput(unsigned Opcode) const; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETSCHEDULE_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TargetSubtargetInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/TargetSubtargetInfo.h deleted file mode 100644 index 3fac2f688d..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TargetSubtargetInfo.h +++ /dev/null @@ -1,319 +0,0 @@ -//===- llvm/CodeGen/TargetSubtargetInfo.h - Target Information --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the subtarget options of a Target machine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETSUBTARGETINFO_H -#define LLVM_CODEGEN_TARGETSUBTARGETINFO_H - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/PBQPRAConstraint.h" -#include "llvm/CodeGen/ScheduleDAGMutation.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/CodeGen.h" -#include -#include - -namespace llvm { - -class CallLowering; -class InlineAsmLowering; -class InstrItineraryData; -struct InstrStage; -class InstructionSelector; -class LegalizerInfo; -class MachineInstr; -struct MachineSchedPolicy; -struct MCReadAdvanceEntry; -struct MCWriteLatencyEntry; -struct MCWriteProcResEntry; -class RegisterBankInfo; -class SDep; -class SelectionDAGTargetInfo; -class SUnit; -class TargetFrameLowering; -class TargetInstrInfo; -class TargetLowering; -class TargetRegisterClass; -class TargetRegisterInfo; -class TargetSchedModel; -class Triple; - -//===----------------------------------------------------------------------===// -/// -/// TargetSubtargetInfo - Generic base class for all target subtargets. All -/// Target-specific options that control code generation and printing should -/// be exposed through a TargetSubtargetInfo-derived class. -/// -class TargetSubtargetInfo : public MCSubtargetInfo { -protected: // Can only create subclasses... - TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, - StringRef FS, ArrayRef PF, - ArrayRef PD, - const MCWriteProcResEntry *WPR, - const MCWriteLatencyEntry *WL, - const MCReadAdvanceEntry *RA, const InstrStage *IS, - const unsigned *OC, const unsigned *FP); - -public: - // AntiDepBreakMode - Type of anti-dependence breaking that should - // be performed before post-RA scheduling. - using AntiDepBreakMode = enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL }; - using RegClassVector = SmallVectorImpl; - - TargetSubtargetInfo() = delete; - TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; - TargetSubtargetInfo &operator=(const TargetSubtargetInfo &) = delete; - ~TargetSubtargetInfo() override; - - virtual bool isXRaySupported() const { return false; } - - // Interfaces to the major aspects of target machine information: - // - // -- Instruction opcode and operand information - // -- Pipelines and scheduling information - // -- Stack frame information - // -- Selection DAG lowering information - // -- Call lowering information - // - // N.B. These objects may change during compilation. It's not safe to cache - // them between functions. - virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } - virtual const TargetFrameLowering *getFrameLowering() const { - return nullptr; - } - virtual const TargetLowering *getTargetLowering() const { return nullptr; } - virtual const SelectionDAGTargetInfo *getSelectionDAGInfo() const { - return nullptr; - } - virtual const CallLowering *getCallLowering() const { return nullptr; } - - virtual const InlineAsmLowering *getInlineAsmLowering() const { - return nullptr; - } - - // FIXME: This lets targets specialize the selector by subtarget (which lets - // us do things like a dedicated avx512 selector). However, we might want - // to also specialize selectors by MachineFunction, which would let us be - // aware of optsize/optnone and such. - virtual InstructionSelector *getInstructionSelector() const { - return nullptr; - } - - /// Target can subclass this hook to select a different DAG scheduler. - virtual RegisterScheduler::FunctionPassCtor - getDAGScheduler(CodeGenOpt::Level) const { - return nullptr; - } - - virtual const LegalizerInfo *getLegalizerInfo() const { return nullptr; } - - /// getRegisterInfo - If register information is available, return it. If - /// not, return null. - virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } - - /// If the information for the register banks is available, return it. - /// Otherwise return nullptr. - virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr; } - - /// getInstrItineraryData - Returns instruction itinerary data for the target - /// or specific subtarget. - virtual const InstrItineraryData *getInstrItineraryData() const { - return nullptr; - } - - /// Resolve a SchedClass at runtime, where SchedClass identifies an - /// MCSchedClassDesc with the isVariant property. This may return the ID of - /// another variant SchedClass, but repeated invocation must quickly terminate - /// in a nonvariant SchedClass. - virtual unsigned resolveSchedClass(unsigned SchedClass, - const MachineInstr *MI, - const TargetSchedModel *SchedModel) const { - return 0; - } - - /// Returns true if MI is a dependency breaking zero-idiom instruction for the - /// subtarget. - /// - /// This function also sets bits in Mask related to input operands that - /// are not in a data dependency relationship. There is one bit for each - /// machine operand; implicit operands follow explicit operands in the bit - /// representation used for Mask. An empty (i.e. a mask with all bits - /// cleared) means: data dependencies are "broken" for all the explicit input - /// machine operands of MI. - virtual bool isZeroIdiom(const MachineInstr *MI, APInt &Mask) const { - return false; - } - - /// Returns true if MI is a dependency breaking instruction for the subtarget. - /// - /// Similar in behavior to `isZeroIdiom`. However, it knows how to identify - /// all dependency breaking instructions (i.e. not just zero-idioms). - /// - /// As for `isZeroIdiom`, this method returns a mask of "broken" dependencies. - /// (See method `isZeroIdiom` for a detailed description of Mask). - virtual bool isDependencyBreaking(const MachineInstr *MI, APInt &Mask) const { - return isZeroIdiom(MI, Mask); - } - - /// Returns true if MI is a candidate for move elimination. - /// - /// A candidate for move elimination may be optimized out at register renaming - /// stage. Subtargets can specify the set of optimizable moves by - /// instantiating tablegen class `IsOptimizableRegisterMove` (see - /// llvm/Target/TargetInstrPredicate.td). - /// - /// SubtargetEmitter is responsible for processing all the definitions of class - /// IsOptimizableRegisterMove, and auto-generate an override for this method. - virtual bool isOptimizableRegisterMove(const MachineInstr *MI) const { - return false; - } - - /// True if the subtarget should run MachineScheduler after aggressive - /// coalescing. - /// - /// This currently replaces the SelectionDAG scheduler with the "source" order - /// scheduler (though see below for an option to turn this off and use the - /// TargetLowering preference). It does not yet disable the postRA scheduler. - virtual bool enableMachineScheduler() const; - - /// True if the machine scheduler should disable the TLI preference - /// for preRA scheduling with the source level scheduler. - virtual bool enableMachineSchedDefaultSched() const { return true; } - - /// True if the subtarget should run MachinePipeliner - virtual bool enableMachinePipeliner() const { return true; }; - - /// True if the subtarget should enable joining global copies. - /// - /// By default this is enabled if the machine scheduler is enabled, but - /// can be overridden. - virtual bool enableJoinGlobalCopies() const; - - /// True if the subtarget should run a scheduler after register allocation. - /// - /// By default this queries the PostRAScheduling bit in the scheduling model - /// which is the preferred way to influence this. - virtual bool enablePostRAScheduler() const; - - /// True if the subtarget should run a machine scheduler after register - /// allocation. - virtual bool enablePostRAMachineScheduler() const; - - /// True if the subtarget should run the atomic expansion pass. - virtual bool enableAtomicExpand() const; - - /// True if the subtarget should run the indirectbr expansion pass. - virtual bool enableIndirectBrExpand() const; - - /// Override generic scheduling policy within a region. - /// - /// This is a convenient way for targets that don't provide any custom - /// scheduling heuristics (no custom MachineSchedStrategy) to make - /// changes to the generic scheduling policy. - virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, - unsigned NumRegionInstrs) const {} - - // Perform target-specific adjustments to the latency of a schedule - // dependency. - // If a pair of operands is associated with the schedule dependency, DefOpIdx - // and UseOpIdx are the indices of the operands in Def and Use, respectively. - // Otherwise, either may be -1. - virtual void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, - int UseOpIdx, SDep &Dep) const {} - - // For use with PostRAScheduling: get the anti-dependence breaking that should - // be performed before post-RA scheduling. - virtual AntiDepBreakMode getAntiDepBreakMode() const { return ANTIDEP_NONE; } - - // For use with PostRAScheduling: in CriticalPathRCs, return any register - // classes that should only be considered for anti-dependence breaking if they - // are on the critical path. - virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { - return CriticalPathRCs.clear(); - } - - // Provide an ordered list of schedule DAG mutations for the post-RA - // scheduler. - virtual void getPostRAMutations( - std::vector> &Mutations) const { - } - - // Provide an ordered list of schedule DAG mutations for the machine - // pipeliner. - virtual void getSMSMutations( - std::vector> &Mutations) const { - } - - /// Default to DFA for resource management, return false when target will use - /// ProcResource in InstrSchedModel instead. - virtual bool useDFAforSMS() const { return true; } - - // For use with PostRAScheduling: get the minimum optimization level needed - // to enable post-RA scheduling. - virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { - return CodeGenOpt::Default; - } - - /// True if the subtarget should run the local reassignment - /// heuristic of the register allocator. - /// This heuristic may be compile time intensive, \p OptLevel provides - /// a finer grain to tune the register allocator. - virtual bool enableRALocalReassignment(CodeGenOpt::Level OptLevel) const; - - /// True if the subtarget should consider the cost of local intervals - /// created by a split candidate when choosing the best split candidate. This - /// heuristic may be compile time intensive. - virtual bool enableAdvancedRASplitCost() const; - - /// Enable use of alias analysis during code generation (during MI - /// scheduling, DAGCombine, etc.). - virtual bool useAA() const; - - /// \brief Sink addresses into blocks using GEP instructions rather than - /// pointer casts and arithmetic. - virtual bool addrSinkUsingGEPs() const { - return useAA(); - } - - /// Enable the use of the early if conversion pass. - virtual bool enableEarlyIfConversion() const { return false; } - - /// Return PBQPConstraint(s) for the target. - /// - /// Override to provide custom PBQP constraints. - virtual std::unique_ptr getCustomPBQPConstraints() const { - return nullptr; - } - - /// Enable tracking of subregister liveness in register allocator. - /// Please use MachineRegisterInfo::subRegLivenessEnabled() instead where - /// possible. - virtual bool enableSubRegLiveness() const { return false; } - - /// This is called after a .mir file was loaded. - virtual void mirFileLoaded(MachineFunction &MF) const; - - /// True if the register allocator should use the allocation orders exactly as - /// written in the tablegen descriptions, false if it should allocate - /// the specified physical register later if is it callee-saved. - virtual bool ignoreCSRForAllocationOrder(const MachineFunction &MF, - unsigned PhysReg) const { - return false; - } -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_TARGETSUBTARGETINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/TileShapeInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/TileShapeInfo.h deleted file mode 100644 index 4e574bd96c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/TileShapeInfo.h +++ /dev/null @@ -1,96 +0,0 @@ -//===- llvm/CodeGen/TileShapeInfo.h - ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Shape utility for AMX. -/// AMX hardware requires to config the shape of tile data register before use. -/// The 2D shape includes row and column. In AMX intrinsics interface the shape -/// is passed as 1st and 2nd parameter and they are lowered as the 1st and 2nd -/// machine operand of AMX pseudo instructions. ShapeT class is to facilitate -/// tile config and register allocator. The row and column are machine operand -/// of AMX pseudo instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TILESHAPEINFO_H -#define LLVM_CODEGEN_TILESHAPEINFO_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Register.h" - -namespace llvm { - -class ShapeT { -public: - ShapeT(MachineOperand *Row, MachineOperand *Col, - const MachineRegisterInfo *MRI = nullptr) - : Row(Row), Col(Col) { - if (MRI) - deduceImm(MRI); - } - ShapeT() - : Row(nullptr), Col(nullptr), RowImm(InvalidImmShape), - ColImm(InvalidImmShape) {} - bool operator==(const ShapeT &Shape) { - MachineOperand *R = Shape.Row; - MachineOperand *C = Shape.Col; - if (!R || !C) - return false; - if (!Row || !Col) - return false; - if (Row->getReg() == R->getReg() && Col->getReg() == C->getReg()) - return true; - if ((RowImm != InvalidImmShape) && (ColImm != InvalidImmShape)) - return RowImm == Shape.getRowImm() && ColImm == Shape.getColImm(); - return false; - } - - bool operator!=(const ShapeT &Shape) { return !(*this == Shape); } - - MachineOperand *getRow() const { return Row; } - - MachineOperand *getCol() const { return Col; } - - int64_t getRowImm() const { return RowImm; } - - int64_t getColImm() const { return ColImm; } - - bool isValid() { return (Row != nullptr) && (Col != nullptr); } - - void deduceImm(const MachineRegisterInfo *MRI) { - // All def must be the same value, otherwise it is invalid MIs. - // Find the immediate. - // TODO copy propagation. - auto GetImm = [&](Register Reg) { - int64_t Imm = InvalidImmShape; - for (const MachineOperand &DefMO : MRI->def_operands(Reg)) { - const auto *MI = DefMO.getParent(); - if (MI->isMoveImmediate()) { - Imm = MI->getOperand(1).getImm(); - break; - } - } - return Imm; - }; - RowImm = GetImm(Row->getReg()); - ColImm = GetImm(Col->getReg()); - } - -private: - static constexpr int64_t InvalidImmShape = -1; - MachineOperand *Row; - MachineOperand *Col; - int64_t RowImm; - int64_t ColImm; -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/UnreachableBlockElim.h b/suite/synctools/tablegen/include/llvm/CodeGen/UnreachableBlockElim.h deleted file mode 100644 index 7dbae77e34..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/UnreachableBlockElim.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- UnreachableBlockElim.h - Remove unreachable blocks for codegen --===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass is an extremely simple version of the SimplifyCFG pass. Its sole -// job is to delete LLVM basic blocks that are not reachable from the entry -// node. To do this, it performs a simple depth first traversal of the CFG, -// then deletes any unvisited nodes. -// -// Note that this pass is really a hack. In particular, the instruction -// selectors for various targets should just not generate code for unreachable -// blocks. Until LLVM has a more systematic way of defining instruction -// selectors, however, we cannot really expect them to handle additional -// complexity. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_UNREACHABLEBLOCKELIM_H -#define LLVM_CODEGEN_UNREACHABLEBLOCKELIM_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class UnreachableBlockElimPass - : public PassInfoMixin { -public: - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; -} // end namespace llvm - -#endif // LLVM_CODEGEN_UNREACHABLEBLOCKELIM_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/VLIWMachineScheduler.h b/suite/synctools/tablegen/include/llvm/CodeGen/VLIWMachineScheduler.h deleted file mode 100644 index e0ed86e97e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/VLIWMachineScheduler.h +++ /dev/null @@ -1,268 +0,0 @@ -//===- VLIWMachineScheduler.h - VLIW-Focused Scheduling Pass ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// // -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_VLIWMACHINESCHEDULER_H -#define LLVM_CODEGEN_VLIWMACHINESCHEDULER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/CodeGen/MachineScheduler.h" -#include "llvm/CodeGen/TargetSchedule.h" -#include -#include -#include - -namespace llvm { - -class DFAPacketizer; -class RegisterClassInfo; -class ScheduleHazardRecognizer; -class SUnit; -class TargetInstrInfo; -class TargetSubtargetInfo; - -class VLIWResourceModel { -protected: - const TargetInstrInfo *TII; - - /// ResourcesModel - Represents VLIW state. - /// Not limited to VLIW targets per se, but assumes definition of resource - /// model by a target. - DFAPacketizer *ResourcesModel; - - const TargetSchedModel *SchedModel; - - /// Local packet/bundle model. Purely - /// internal to the MI scheduler at the time. - SmallVector Packet; - - /// Total packets created. - unsigned TotalPackets = 0; - -public: - VLIWResourceModel(const TargetSubtargetInfo &STI, const TargetSchedModel *SM); - - virtual ~VLIWResourceModel(); - - virtual void reset(); - - virtual bool hasDependence(const SUnit *SUd, const SUnit *SUu); - virtual bool isResourceAvailable(SUnit *SU, bool IsTop); - virtual bool reserveResources(SUnit *SU, bool IsTop); - unsigned getTotalPackets() const { return TotalPackets; } - size_t getPacketInstCount() const { return Packet.size(); } - bool isInPacket(SUnit *SU) const { return is_contained(Packet, SU); } - -protected: - virtual DFAPacketizer *createPacketizer(const TargetSubtargetInfo &STI) const; -}; - -/// Extend the standard ScheduleDAGMILive to provide more context and override -/// the top-level schedule() driver. -class VLIWMachineScheduler : public ScheduleDAGMILive { -public: - VLIWMachineScheduler(MachineSchedContext *C, - std::unique_ptr S) - : ScheduleDAGMILive(C, std::move(S)) {} - - /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's - /// time to do some work. - void schedule() override; - - RegisterClassInfo *getRegClassInfo() { return RegClassInfo; } - int getBBSize() { return BB->size(); } -}; - -//===----------------------------------------------------------------------===// -// ConvergingVLIWScheduler - Implementation of a VLIW-aware -// MachineSchedStrategy. -//===----------------------------------------------------------------------===// - -class ConvergingVLIWScheduler : public MachineSchedStrategy { -protected: - /// Store the state used by ConvergingVLIWScheduler heuristics, required - /// for the lifetime of one invocation of pickNode(). - struct SchedCandidate { - // The best SUnit candidate. - SUnit *SU = nullptr; - - // Register pressure values for the best candidate. - RegPressureDelta RPDelta; - - // Best scheduling cost. - int SCost = 0; - - SchedCandidate() = default; - }; - /// Represent the type of SchedCandidate found within a single queue. - enum CandResult { - NoCand, - NodeOrder, - SingleExcess, - SingleCritical, - SingleMax, - MultiPressure, - BestCost, - Weak - }; - - // Constants used to denote relative importance of - // heuristic components for cost computation. - static constexpr unsigned PriorityOne = 200; - static constexpr unsigned PriorityTwo = 50; - static constexpr unsigned PriorityThree = 75; - static constexpr unsigned ScaleTwo = 10; - - /// Each Scheduling boundary is associated with ready queues. It tracks the - /// current cycle in whichever direction at has moved, and maintains the state - /// of "hazards" and other interlocks at the current cycle. - struct VLIWSchedBoundary { - VLIWMachineScheduler *DAG = nullptr; - const TargetSchedModel *SchedModel = nullptr; - - ReadyQueue Available; - ReadyQueue Pending; - bool CheckPending = false; - - ScheduleHazardRecognizer *HazardRec = nullptr; - VLIWResourceModel *ResourceModel = nullptr; - - unsigned CurrCycle = 0; - unsigned IssueCount = 0; - unsigned CriticalPathLength = 0; - - /// MinReadyCycle - Cycle of the soonest available instruction. - unsigned MinReadyCycle = std::numeric_limits::max(); - - // Remember the greatest min operand latency. - unsigned MaxMinLatency = 0; - - /// Pending queues extend the ready queues with the same ID and the - /// PendingFlag set. - VLIWSchedBoundary(unsigned ID, const Twine &Name) - : Available(ID, Name + ".A"), - Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name + ".P") {} - - ~VLIWSchedBoundary(); - - void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) { - DAG = dag; - SchedModel = smodel; - CurrCycle = 0; - IssueCount = 0; - // Initialize the critical path length limit, which used by the scheduling - // cost model to determine the value for scheduling an instruction. We use - // a slightly different heuristic for small and large functions. For small - // functions, it's important to use the height/depth of the instruction. - // For large functions, prioritizing by height or depth increases spills. - CriticalPathLength = DAG->getBBSize() / SchedModel->getIssueWidth(); - if (DAG->getBBSize() < 50) - // We divide by two as a cheap and simple heuristic to reduce the - // critical path length, which increases the priority of using the graph - // height/depth in the scheduler's cost computation. - CriticalPathLength >>= 1; - else { - // For large basic blocks, we prefer a larger critical path length to - // decrease the priority of using the graph height/depth. - unsigned MaxPath = 0; - for (auto &SU : DAG->SUnits) - MaxPath = std::max(MaxPath, isTop() ? SU.getHeight() : SU.getDepth()); - CriticalPathLength = std::max(CriticalPathLength, MaxPath) + 1; - } - } - - bool isTop() const { - return Available.getID() == ConvergingVLIWScheduler::TopQID; - } - - bool checkHazard(SUnit *SU); - - void releaseNode(SUnit *SU, unsigned ReadyCycle); - - void bumpCycle(); - - void bumpNode(SUnit *SU); - - void releasePending(); - - void removeReady(SUnit *SU); - - SUnit *pickOnlyChoice(); - - bool isLatencyBound(SUnit *SU) { - if (CurrCycle >= CriticalPathLength) - return true; - unsigned PathLength = isTop() ? SU->getHeight() : SU->getDepth(); - return CriticalPathLength - CurrCycle <= PathLength; - } - }; - - VLIWMachineScheduler *DAG = nullptr; - const TargetSchedModel *SchedModel = nullptr; - - // State of the top and bottom scheduled instruction boundaries. - VLIWSchedBoundary Top; - VLIWSchedBoundary Bot; - - /// List of pressure sets that have a high pressure level in the region. - SmallVector HighPressureSets; - -public: - /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) - enum { TopQID = 1, BotQID = 2, LogMaxQID = 2 }; - - ConvergingVLIWScheduler() : Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {} - virtual ~ConvergingVLIWScheduler() = default; - - void initialize(ScheduleDAGMI *dag) override; - - SUnit *pickNode(bool &IsTopNode) override; - - void schedNode(SUnit *SU, bool IsTopNode) override; - - void releaseTopNode(SUnit *SU) override; - - void releaseBottomNode(SUnit *SU) override; - - unsigned reportPackets() { - return Top.ResourceModel->getTotalPackets() + - Bot.ResourceModel->getTotalPackets(); - } - -protected: - virtual VLIWResourceModel * - createVLIWResourceModel(const TargetSubtargetInfo &STI, - const TargetSchedModel *SchedModel) const; - - SUnit *pickNodeBidrectional(bool &IsTopNode); - - int pressureChange(const SUnit *SU, bool isBotUp); - - virtual int SchedulingCost(ReadyQueue &Q, SUnit *SU, - SchedCandidate &Candidate, RegPressureDelta &Delta, - bool verbose); - - CandResult pickNodeFromQueue(VLIWSchedBoundary &Zone, - const RegPressureTracker &RPTracker, - SchedCandidate &Candidate); -#ifndef NDEBUG - void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU, - int Cost, PressureChange P = PressureChange()); - - void readyQueueVerboseDump(const RegPressureTracker &RPTracker, - SchedCandidate &Candidate, ReadyQueue &Q); -#endif -}; - -ScheduleDAGMILive *createVLIWSched(MachineSchedContext *C); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_VLIWMACHINESCHEDULER_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.h b/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.h deleted file mode 100644 index 7b17b98d5c..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.h +++ /dev/null @@ -1,516 +0,0 @@ -//===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the set of low-level target independent types which various -// values in the code generator are. This allows the target specific behavior -// of instructions to be described to target independent passes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_VALUETYPES_H -#define LLVM_CODEGEN_VALUETYPES_H - -#include "llvm/Support/Compiler.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/TypeSize.h" -#include "llvm/Support/WithColor.h" -#include -#include -#include - -namespace llvm { - - class LLVMContext; - class Type; - - /// Extended Value Type. Capable of holding value types which are not native - /// for any processor (such as the i12345 type), as well as the types an MVT - /// can represent. - struct EVT { - private: - MVT V = MVT::INVALID_SIMPLE_VALUE_TYPE; - Type *LLVMTy = nullptr; - - public: - constexpr EVT() = default; - constexpr EVT(MVT::SimpleValueType SVT) : V(SVT) {} - constexpr EVT(MVT S) : V(S) {} - - bool operator==(EVT VT) const { - return !(*this != VT); - } - bool operator!=(EVT VT) const { - if (V.SimpleTy != VT.V.SimpleTy) - return true; - if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) - return LLVMTy != VT.LLVMTy; - return false; - } - - /// Returns the EVT that represents a floating-point type with the given - /// number of bits. There are two floating-point types with 128 bits - this - /// returns f128 rather than ppcf128. - static EVT getFloatingPointVT(unsigned BitWidth) { - return MVT::getFloatingPointVT(BitWidth); - } - - /// Returns the EVT that represents an integer with the given number of - /// bits. - static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { - MVT M = MVT::getIntegerVT(BitWidth); - if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) - return M; - return getExtendedIntegerVT(Context, BitWidth); - } - - /// Returns the EVT that represents a vector NumElements in length, where - /// each element is of type VT. - static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, - bool IsScalable = false) { - MVT M = MVT::getVectorVT(VT.V, NumElements, IsScalable); - if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) - return M; - return getExtendedVectorVT(Context, VT, NumElements, IsScalable); - } - - /// Returns the EVT that represents a vector EC.Min elements in length, - /// where each element is of type VT. - static EVT getVectorVT(LLVMContext &Context, EVT VT, ElementCount EC) { - MVT M = MVT::getVectorVT(VT.V, EC); - if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) - return M; - return getExtendedVectorVT(Context, VT, EC); - } - - /// Return a vector with the same number of elements as this vector, but - /// with the element type converted to an integer type with the same - /// bitwidth. - EVT changeVectorElementTypeToInteger() const { - if (isSimple()) - return getSimpleVT().changeVectorElementTypeToInteger(); - return changeExtendedVectorElementTypeToInteger(); - } - - /// Return a VT for a vector type whose attributes match ourselves - /// with the exception of the element type that is chosen by the caller. - EVT changeVectorElementType(EVT EltVT) const { - if (isSimple()) { - assert(EltVT.isSimple() && - "Can't change simple vector VT to have extended element VT"); - return getSimpleVT().changeVectorElementType(EltVT.getSimpleVT()); - } - return changeExtendedVectorElementType(EltVT); - } - - /// Return the type converted to an equivalently sized integer or vector - /// with integer element type. Similar to changeVectorElementTypeToInteger, - /// but also handles scalars. - EVT changeTypeToInteger() { - if (isVector()) - return changeVectorElementTypeToInteger(); - - if (isSimple()) - return getSimpleVT().changeTypeToInteger(); - return changeExtendedTypeToInteger(); - } - - /// Test if the given EVT has zero size, this will fail if called on a - /// scalable type - bool isZeroSized() const { - return !isScalableVector() && getSizeInBits() == 0; - } - - /// Test if the given EVT is simple (as opposed to being extended). - bool isSimple() const { - return V.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE; - } - - /// Test if the given EVT is extended (as opposed to being simple). - bool isExtended() const { - return !isSimple(); - } - - /// Return true if this is a FP or a vector FP type. - bool isFloatingPoint() const { - return isSimple() ? V.isFloatingPoint() : isExtendedFloatingPoint(); - } - - /// Return true if this is an integer or a vector integer type. - bool isInteger() const { - return isSimple() ? V.isInteger() : isExtendedInteger(); - } - - /// Return true if this is an integer, but not a vector. - bool isScalarInteger() const { - return isSimple() ? V.isScalarInteger() : isExtendedScalarInteger(); - } - - /// Return true if this is a vector value type. - bool isVector() const { - return isSimple() ? V.isVector() : isExtendedVector(); - } - - /// Return true if this is a vector type where the runtime - /// length is machine dependent - bool isScalableVector() const { - return isSimple() ? V.isScalableVector() : isExtendedScalableVector(); - } - - bool isFixedLengthVector() const { - return isSimple() ? V.isFixedLengthVector() - : isExtendedFixedLengthVector(); - } - - /// Return true if this is a 16-bit vector type. - bool is16BitVector() const { - return isSimple() ? V.is16BitVector() : isExtended16BitVector(); - } - - /// Return true if this is a 32-bit vector type. - bool is32BitVector() const { - return isSimple() ? V.is32BitVector() : isExtended32BitVector(); - } - - /// Return true if this is a 64-bit vector type. - bool is64BitVector() const { - return isSimple() ? V.is64BitVector() : isExtended64BitVector(); - } - - /// Return true if this is a 128-bit vector type. - bool is128BitVector() const { - return isSimple() ? V.is128BitVector() : isExtended128BitVector(); - } - - /// Return true if this is a 256-bit vector type. - bool is256BitVector() const { - return isSimple() ? V.is256BitVector() : isExtended256BitVector(); - } - - /// Return true if this is a 512-bit vector type. - bool is512BitVector() const { - return isSimple() ? V.is512BitVector() : isExtended512BitVector(); - } - - /// Return true if this is a 1024-bit vector type. - bool is1024BitVector() const { - return isSimple() ? V.is1024BitVector() : isExtended1024BitVector(); - } - - /// Return true if this is a 2048-bit vector type. - bool is2048BitVector() const { - return isSimple() ? V.is2048BitVector() : isExtended2048BitVector(); - } - - /// Return true if this is an overloaded type for TableGen. - bool isOverloaded() const { - return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); - } - - /// Return true if the bit size is a multiple of 8. - bool isByteSized() const { - return !isZeroSized() && getSizeInBits().isKnownMultipleOf(8); - } - - /// Return true if the size is a power-of-two number of bytes. - bool isRound() const { - if (isScalableVector()) - return false; - unsigned BitSize = getSizeInBits(); - return BitSize >= 8 && !(BitSize & (BitSize - 1)); - } - - /// Return true if this has the same number of bits as VT. - bool bitsEq(EVT VT) const { - if (EVT::operator==(VT)) return true; - return getSizeInBits() == VT.getSizeInBits(); - } - - /// Return true if we know at compile time this has more bits than VT. - bool knownBitsGT(EVT VT) const { - return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits()); - } - - /// Return true if we know at compile time this has more than or the same - /// bits as VT. - bool knownBitsGE(EVT VT) const { - return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits()); - } - - /// Return true if we know at compile time this has fewer bits than VT. - bool knownBitsLT(EVT VT) const { - return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits()); - } - - /// Return true if we know at compile time this has fewer than or the same - /// bits as VT. - bool knownBitsLE(EVT VT) const { - return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits()); - } - - /// Return true if this has more bits than VT. - bool bitsGT(EVT VT) const { - if (EVT::operator==(VT)) return false; - assert(isScalableVector() == VT.isScalableVector() && - "Comparison between scalable and fixed types"); - return knownBitsGT(VT); - } - - /// Return true if this has no less bits than VT. - bool bitsGE(EVT VT) const { - if (EVT::operator==(VT)) return true; - assert(isScalableVector() == VT.isScalableVector() && - "Comparison between scalable and fixed types"); - return knownBitsGE(VT); - } - - /// Return true if this has less bits than VT. - bool bitsLT(EVT VT) const { - if (EVT::operator==(VT)) return false; - assert(isScalableVector() == VT.isScalableVector() && - "Comparison between scalable and fixed types"); - return knownBitsLT(VT); - } - - /// Return true if this has no more bits than VT. - bool bitsLE(EVT VT) const { - if (EVT::operator==(VT)) return true; - assert(isScalableVector() == VT.isScalableVector() && - "Comparison between scalable and fixed types"); - return knownBitsLE(VT); - } - - /// Return the SimpleValueType held in the specified simple EVT. - MVT getSimpleVT() const { - assert(isSimple() && "Expected a SimpleValueType!"); - return V; - } - - /// If this is a vector type, return the element type, otherwise return - /// this. - EVT getScalarType() const { - return isVector() ? getVectorElementType() : *this; - } - - /// Given a vector type, return the type of each element. - EVT getVectorElementType() const { - assert(isVector() && "Invalid vector type!"); - if (isSimple()) - return V.getVectorElementType(); - return getExtendedVectorElementType(); - } - - /// Given a vector type, return the number of elements it contains. - unsigned getVectorNumElements() const { - assert(isVector() && "Invalid vector type!"); - - if (isScalableVector()) - llvm::reportInvalidSizeRequest( - "Possible incorrect use of EVT::getVectorNumElements() for " - "scalable vector. Scalable flag may be dropped, use " - "EVT::getVectorElementCount() instead"); - - return isSimple() ? V.getVectorNumElements() - : getExtendedVectorNumElements(); - } - - // Given a (possibly scalable) vector type, return the ElementCount - ElementCount getVectorElementCount() const { - assert((isVector()) && "Invalid vector type!"); - if (isSimple()) - return V.getVectorElementCount(); - - return getExtendedVectorElementCount(); - } - - /// Given a vector type, return the minimum number of elements it contains. - unsigned getVectorMinNumElements() const { - return getVectorElementCount().getKnownMinValue(); - } - - /// Return the size of the specified value type in bits. - /// - /// If the value type is a scalable vector type, the scalable property will - /// be set and the runtime size will be a positive integer multiple of the - /// base size. - TypeSize getSizeInBits() const { - if (isSimple()) - return V.getSizeInBits(); - return getExtendedSizeInBits(); - } - - /// Return the size of the specified fixed width value type in bits. The - /// function will assert if the type is scalable. - uint64_t getFixedSizeInBits() const { - return getSizeInBits().getFixedSize(); - } - - uint64_t getScalarSizeInBits() const { - return getScalarType().getSizeInBits().getFixedSize(); - } - - /// Return the number of bytes overwritten by a store of the specified value - /// type. - /// - /// If the value type is a scalable vector type, the scalable property will - /// be set and the runtime size will be a positive integer multiple of the - /// base size. - TypeSize getStoreSize() const { - TypeSize BaseSize = getSizeInBits(); - return {(BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable()}; - } - - /// Return the number of bits overwritten by a store of the specified value - /// type. - /// - /// If the value type is a scalable vector type, the scalable property will - /// be set and the runtime size will be a positive integer multiple of the - /// base size. - TypeSize getStoreSizeInBits() const { - return getStoreSize() * 8; - } - - /// Rounds the bit-width of the given integer EVT up to the nearest power of - /// two (and at least to eight), and returns the integer EVT with that - /// number of bits. - EVT getRoundIntegerType(LLVMContext &Context) const { - assert(isInteger() && !isVector() && "Invalid integer type!"); - unsigned BitWidth = getSizeInBits(); - if (BitWidth <= 8) - return EVT(MVT::i8); - return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth)); - } - - /// Finds the smallest simple value type that is greater than or equal to - /// half the width of this EVT. If no simple value type can be found, an - /// extended integer value type of half the size (rounded up) is returned. - EVT getHalfSizedIntegerVT(LLVMContext &Context) const { - assert(isInteger() && !isVector() && "Invalid integer type!"); - unsigned EVTSize = getSizeInBits(); - for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE; - IntVT <= MVT::LAST_INTEGER_VALUETYPE; ++IntVT) { - EVT HalfVT = EVT((MVT::SimpleValueType)IntVT); - if (HalfVT.getSizeInBits() * 2 >= EVTSize) - return HalfVT; - } - return getIntegerVT(Context, (EVTSize + 1) / 2); - } - - /// Return a VT for an integer vector type with the size of the - /// elements doubled. The typed returned may be an extended type. - EVT widenIntegerVectorElementType(LLVMContext &Context) const { - EVT EltVT = getVectorElementType(); - EltVT = EVT::getIntegerVT(Context, 2 * EltVT.getSizeInBits()); - return EVT::getVectorVT(Context, EltVT, getVectorElementCount()); - } - - // Return a VT for a vector type with the same element type but - // half the number of elements. The type returned may be an - // extended type. - EVT getHalfNumVectorElementsVT(LLVMContext &Context) const { - EVT EltVT = getVectorElementType(); - auto EltCnt = getVectorElementCount(); - assert(EltCnt.isKnownEven() && "Splitting vector, but not in half!"); - return EVT::getVectorVT(Context, EltVT, EltCnt.divideCoefficientBy(2)); - } - - // Return a VT for a vector type with the same element type but - // double the number of elements. The type returned may be an - // extended type. - EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const { - EVT EltVT = getVectorElementType(); - auto EltCnt = getVectorElementCount(); - return EVT::getVectorVT(Context, EltVT, EltCnt * 2); - } - - /// Returns true if the given vector is a power of 2. - bool isPow2VectorType() const { - unsigned NElts = getVectorMinNumElements(); - return !(NElts & (NElts - 1)); - } - - /// Widens the length of the given vector EVT up to the nearest power of 2 - /// and returns that type. - EVT getPow2VectorType(LLVMContext &Context) const { - if (!isPow2VectorType()) { - ElementCount NElts = getVectorElementCount(); - unsigned NewMinCount = 1 << Log2_32_Ceil(NElts.getKnownMinValue()); - NElts = ElementCount::get(NewMinCount, NElts.isScalable()); - return EVT::getVectorVT(Context, getVectorElementType(), NElts); - } - else { - return *this; - } - } - - /// This function returns value type as a string, e.g. "i32". - std::string getEVTString() const; - - /// This method returns an LLVM type corresponding to the specified EVT. - /// For integer types, this returns an unsigned type. Note that this will - /// abort for types that cannot be represented. - Type *getTypeForEVT(LLVMContext &Context) const; - - /// Return the value type corresponding to the specified type. - /// This returns all pointers as iPTR. If HandleUnknown is true, unknown - /// types are returned as Other, otherwise they are invalid. - static EVT getEVT(Type *Ty, bool HandleUnknown = false); - - intptr_t getRawBits() const { - if (isSimple()) - return V.SimpleTy; - else - return (intptr_t)(LLVMTy); - } - - /// A meaningless but well-behaved order, useful for constructing - /// containers. - struct compareRawBits { - bool operator()(EVT L, EVT R) const { - if (L.V.SimpleTy == R.V.SimpleTy) - return L.LLVMTy < R.LLVMTy; - else - return L.V.SimpleTy < R.V.SimpleTy; - } - }; - - private: - // Methods for handling the Extended-type case in functions above. - // These are all out-of-line to prevent users of this header file - // from having a dependency on Type.h. - EVT changeExtendedTypeToInteger() const; - EVT changeExtendedVectorElementType(EVT EltVT) const; - EVT changeExtendedVectorElementTypeToInteger() const; - static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); - static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, unsigned NumElements, - bool IsScalable); - static EVT getExtendedVectorVT(LLVMContext &Context, EVT VT, - ElementCount EC); - bool isExtendedFloatingPoint() const LLVM_READONLY; - bool isExtendedInteger() const LLVM_READONLY; - bool isExtendedScalarInteger() const LLVM_READONLY; - bool isExtendedVector() const LLVM_READONLY; - bool isExtended16BitVector() const LLVM_READONLY; - bool isExtended32BitVector() const LLVM_READONLY; - bool isExtended64BitVector() const LLVM_READONLY; - bool isExtended128BitVector() const LLVM_READONLY; - bool isExtended256BitVector() const LLVM_READONLY; - bool isExtended512BitVector() const LLVM_READONLY; - bool isExtended1024BitVector() const LLVM_READONLY; - bool isExtended2048BitVector() const LLVM_READONLY; - bool isExtendedFixedLengthVector() const LLVM_READONLY; - bool isExtendedScalableVector() const LLVM_READONLY; - EVT getExtendedVectorElementType() const; - unsigned getExtendedVectorNumElements() const LLVM_READONLY; - ElementCount getExtendedVectorElementCount() const LLVM_READONLY; - TypeSize getExtendedSizeInBits() const LLVM_READONLY; - }; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_VALUETYPES_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.td b/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.td deleted file mode 100644 index 7f989e08e9..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/ValueTypes.td +++ /dev/null @@ -1,253 +0,0 @@ -//===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Value types - These values correspond to the register types defined in the -// MachineValueTypes.h file. If you update anything here, you must update it -// there as well! -// -//===----------------------------------------------------------------------===// - -class ValueType { - string Namespace = "MVT"; - int Size = size; - int Value = value; -} - -def OtherVT : ValueType<0, 1>; // "Other" value -def i1 : ValueType<1, 2>; // One bit boolean value -def i8 : ValueType<8, 3>; // 8-bit integer value -def i16 : ValueType<16, 4>; // 16-bit integer value -def i32 : ValueType<32, 5>; // 32-bit integer value -def i64 : ValueType<64, 6>; // 64-bit integer value -def i128 : ValueType<128, 7>; // 128-bit integer value - -def bf16 : ValueType<16, 8>; // 16-bit brain floating point value -def f16 : ValueType<16, 9>; // 16-bit floating point value -def f32 : ValueType<32, 10>; // 32-bit floating point value -def f64 : ValueType<64, 11>; // 64-bit floating point value -def f80 : ValueType<80, 12>; // 80-bit floating point value -def f128 : ValueType<128, 13>; // 128-bit floating point value -def ppcf128 : ValueType<128, 14>; // PPC 128-bit floating point value - -def v1i1 : ValueType<1, 15>; // 1 x i1 vector value -def v2i1 : ValueType<2, 16>; // 2 x i1 vector value -def v4i1 : ValueType<4, 17>; // 4 x i1 vector value -def v8i1 : ValueType<8, 18>; // 8 x i1 vector value -def v16i1 : ValueType<16, 19>; // 16 x i1 vector value -def v32i1 : ValueType<32, 20>; // 32 x i1 vector value -def v64i1 : ValueType<64, 21>; // 64 x i1 vector value -def v128i1 : ValueType<128, 22>; // 128 x i1 vector value -def v256i1 : ValueType<256, 23>; // 256 x i1 vector value -def v512i1 : ValueType<512, 24>; // 512 x i1 vector value -def v1024i1 : ValueType<1024, 25>; // 1024 x i1 vector value - -def v1i8 : ValueType<8, 26>; // 1 x i8 vector value -def v2i8 : ValueType<16, 27>; // 2 x i8 vector value -def v4i8 : ValueType<32, 28>; // 4 x i8 vector value -def v8i8 : ValueType<64, 29>; // 8 x i8 vector value -def v16i8 : ValueType<128, 30>; // 16 x i8 vector value -def v32i8 : ValueType<256, 31>; // 32 x i8 vector value -def v64i8 : ValueType<512, 32>; // 64 x i8 vector value -def v128i8 : ValueType<1024, 33>; // 128 x i8 vector value -def v256i8 : ValueType<2048, 34>; // 256 x i8 vector value -def v512i8 : ValueType<4096, 35>; // 512 x i8 vector value -def v1024i8 : ValueType<8192, 36>; // 1024 x i8 vector value - -def v1i16 : ValueType<16, 37>; // 1 x i16 vector value -def v2i16 : ValueType<32, 38>; // 2 x i16 vector value -def v3i16 : ValueType<48, 39>; // 3 x i16 vector value -def v4i16 : ValueType<64, 40>; // 4 x i16 vector value -def v8i16 : ValueType<128, 41>; // 8 x i16 vector value -def v16i16 : ValueType<256, 42>; // 16 x i16 vector value -def v32i16 : ValueType<512, 43>; // 32 x i16 vector value -def v64i16 : ValueType<1024, 44>; // 64 x i16 vector value -def v128i16 : ValueType<2048, 45>; // 128 x i16 vector value -def v256i16 : ValueType<4096, 46>; // 256 x i16 vector value -def v512i16 : ValueType<8192, 47>; // 512 x i16 vector value - -def v1i32 : ValueType<32, 48>; // 1 x i32 vector value -def v2i32 : ValueType<64, 49>; // 2 x i32 vector value -def v3i32 : ValueType<96, 50>; // 3 x i32 vector value -def v4i32 : ValueType<128, 51>; // 4 x i32 vector value -def v5i32 : ValueType<160, 52>; // 5 x i32 vector value -def v6i32 : ValueType<192, 53>; // 6 x f32 vector value -def v7i32 : ValueType<224, 54>; // 7 x f32 vector value -def v8i32 : ValueType<256, 55>; // 8 x i32 vector value -def v16i32 : ValueType<512, 56>; // 16 x i32 vector value -def v32i32 : ValueType<1024, 57>; // 32 x i32 vector value -def v64i32 : ValueType<2048, 58>; // 64 x i32 vector value -def v128i32 : ValueType<4096, 59>; // 128 x i32 vector value -def v256i32 : ValueType<8192, 60>; // 256 x i32 vector value -def v512i32 : ValueType<16384, 61>; // 512 x i32 vector value -def v1024i32 : ValueType<32768, 62>; // 1024 x i32 vector value -def v2048i32 : ValueType<65536, 63>; // 2048 x i32 vector value - -def v1i64 : ValueType<64, 64>; // 1 x i64 vector value -def v2i64 : ValueType<128, 65>; // 2 x i64 vector value -def v3i64 : ValueType<192, 66>; // 3 x i64 vector value -def v4i64 : ValueType<256, 67>; // 4 x i64 vector value -def v8i64 : ValueType<512, 68>; // 8 x i64 vector value -def v16i64 : ValueType<1024, 69>; // 16 x i64 vector value -def v32i64 : ValueType<2048, 70>; // 32 x i64 vector value -def v64i64 : ValueType<4096, 71>; // 64 x i64 vector value -def v128i64 : ValueType<8192, 72>; // 128 x i64 vector value -def v256i64 : ValueType<16384, 73>; // 256 x i64 vector value - -def v1i128 : ValueType<128, 74>; // 1 x i128 vector value - -def v1f16 : ValueType<16, 75>; // 1 x f16 vector value -def v2f16 : ValueType<32, 76>; // 2 x f16 vector value -def v3f16 : ValueType<48, 77>; // 3 x f16 vector value -def v4f16 : ValueType<64, 78>; // 4 x f16 vector value -def v8f16 : ValueType<128, 79>; // 8 x f16 vector value -def v16f16 : ValueType<256, 80>; // 16 x f16 vector value -def v32f16 : ValueType<512, 81>; // 32 x f16 vector value -def v64f16 : ValueType<1024, 82>; // 64 x f16 vector value -def v128f16 : ValueType<2048, 83>; // 128 x f16 vector value -def v256f16 : ValueType<4096, 84>; // 256 x f16 vector value -def v512f16 : ValueType<8192, 85>; // 512 x f16 vector value - -def v2bf16 : ValueType<32, 86>; // 2 x bf16 vector value -def v3bf16 : ValueType<48, 87>; // 3 x bf16 vector value -def v4bf16 : ValueType<64, 88>; // 4 x bf16 vector value -def v8bf16 : ValueType<128, 89>; // 8 x bf16 vector value -def v16bf16 : ValueType<256, 90>; // 16 x bf16 vector value -def v32bf16 : ValueType<512, 91>; // 32 x bf16 vector value -def v64bf16 : ValueType<1024, 92>; // 64 x bf16 vector value -def v128bf16 : ValueType<2048, 93>; // 128 x bf16 vector value - -def v1f32 : ValueType<32, 94>; // 1 x f32 vector value -def v2f32 : ValueType<64, 95>; // 2 x f32 vector value -def v3f32 : ValueType<96, 96>; // 3 x f32 vector value -def v4f32 : ValueType<128, 97>; // 4 x f32 vector value -def v5f32 : ValueType<160, 98>; // 5 x f32 vector value -def v6f32 : ValueType<192, 99>; // 6 x f32 vector value -def v7f32 : ValueType<224, 100>; // 7 x f32 vector value -def v8f32 : ValueType<256, 101>; // 8 x f32 vector value -def v16f32 : ValueType<512, 102>; // 16 x f32 vector value -def v32f32 : ValueType<1024, 103>; // 32 x f32 vector value -def v64f32 : ValueType<2048, 104>; // 64 x f32 vector value -def v128f32 : ValueType<4096, 105>; // 128 x f32 vector value -def v256f32 : ValueType<8192, 106>; // 256 x f32 vector value -def v512f32 : ValueType<16384, 107>; // 512 x f32 vector value -def v1024f32 : ValueType<32768, 108>; // 1024 x f32 vector value -def v2048f32 : ValueType<65536, 109>; // 2048 x f32 vector value - -def v1f64 : ValueType<64, 110>; // 1 x f64 vector value -def v2f64 : ValueType<128, 111>; // 2 x f64 vector value -def v3f64 : ValueType<192, 112>; // 3 x f64 vector value -def v4f64 : ValueType<256, 113>; // 4 x f64 vector value -def v8f64 : ValueType<512, 114>; // 8 x f64 vector value -def v16f64 : ValueType<1024, 115>; // 16 x f64 vector value -def v32f64 : ValueType<2048, 116>; // 32 x f64 vector value -def v64f64 : ValueType<4096, 117>; // 64 x f64 vector value -def v128f64 : ValueType<8192, 118>; // 128 x f64 vector value -def v256f64 : ValueType<16384, 119>; // 256 x f64 vector value - -def nxv1i1 : ValueType<1, 120>; // n x 1 x i1 vector value -def nxv2i1 : ValueType<2, 121>; // n x 2 x i1 vector value -def nxv4i1 : ValueType<4, 122>; // n x 4 x i1 vector value -def nxv8i1 : ValueType<8, 123>; // n x 8 x i1 vector value -def nxv16i1 : ValueType<16, 124>; // n x 16 x i1 vector value -def nxv32i1 : ValueType<32, 125>; // n x 32 x i1 vector value -def nxv64i1 : ValueType<64, 126>; // n x 64 x i1 vector value - -def nxv1i8 : ValueType<8, 127>; // n x 1 x i8 vector value -def nxv2i8 : ValueType<16, 128>; // n x 2 x i8 vector value -def nxv4i8 : ValueType<32, 129>; // n x 4 x i8 vector value -def nxv8i8 : ValueType<64, 130>; // n x 8 x i8 vector value -def nxv16i8 : ValueType<128, 131>; // n x 16 x i8 vector value -def nxv32i8 : ValueType<256, 132>; // n x 32 x i8 vector value -def nxv64i8 : ValueType<512, 133>; // n x 64 x i8 vector value - -def nxv1i16 : ValueType<16, 134>; // n x 1 x i16 vector value -def nxv2i16 : ValueType<32, 135>; // n x 2 x i16 vector value -def nxv4i16 : ValueType<64, 136>; // n x 4 x i16 vector value -def nxv8i16 : ValueType<128, 137>; // n x 8 x i16 vector value -def nxv16i16 : ValueType<256, 138>; // n x 16 x i16 vector value -def nxv32i16 : ValueType<512, 139>; // n x 32 x i16 vector value - -def nxv1i32 : ValueType<32, 140>; // n x 1 x i32 vector value -def nxv2i32 : ValueType<64, 141>; // n x 2 x i32 vector value -def nxv4i32 : ValueType<128, 142>; // n x 4 x i32 vector value -def nxv8i32 : ValueType<256, 143>; // n x 8 x i32 vector value -def nxv16i32 : ValueType<512, 144>; // n x 16 x i32 vector value -def nxv32i32 : ValueType<1024, 145>; // n x 32 x i32 vector value - -def nxv1i64 : ValueType<64, 146>; // n x 1 x i64 vector value -def nxv2i64 : ValueType<128, 147>; // n x 2 x i64 vector value -def nxv4i64 : ValueType<256, 148>; // n x 4 x i64 vector value -def nxv8i64 : ValueType<512, 149>; // n x 8 x i64 vector value -def nxv16i64 : ValueType<1024, 150>; // n x 16 x i64 vector value -def nxv32i64 : ValueType<2048, 151>; // n x 32 x i64 vector value - -def nxv1f16 : ValueType<16, 152>; // n x 1 x f16 vector value -def nxv2f16 : ValueType<32, 153>; // n x 2 x f16 vector value -def nxv4f16 : ValueType<64, 154>; // n x 4 x f16 vector value -def nxv8f16 : ValueType<128, 155>; // n x 8 x f16 vector value -def nxv16f16 : ValueType<256, 156>; // n x 16 x f16 vector value -def nxv32f16 : ValueType<512, 157>; // n x 32 x f16 vector value - -def nxv1bf16 : ValueType<16, 158>; // n x 1 x bf16 vector value -def nxv2bf16 : ValueType<32, 159>; // n x 2 x bf16 vector value -def nxv4bf16 : ValueType<64, 160>; // n x 4 x bf16 vector value -def nxv8bf16 : ValueType<128, 161>; // n x 8 x bf16 vector value - -def nxv1f32 : ValueType<32, 162>; // n x 1 x f32 vector value -def nxv2f32 : ValueType<64, 163>; // n x 2 x f32 vector value -def nxv4f32 : ValueType<128, 164>; // n x 4 x f32 vector value -def nxv8f32 : ValueType<256, 165>; // n x 8 x f32 vector value -def nxv16f32 : ValueType<512, 166>; // n x 16 x f32 vector value - -def nxv1f64 : ValueType<64, 167>; // n x 1 x f64 vector value -def nxv2f64 : ValueType<128, 168>; // n x 2 x f64 vector value -def nxv4f64 : ValueType<256, 169>; // n x 4 x f64 vector value -def nxv8f64 : ValueType<512, 170>; // n x 8 x f64 vector value - -def x86mmx : ValueType<64, 171>; // X86 MMX value -def FlagVT : ValueType<0, 172>; // Pre-RA sched glue -def isVoid : ValueType<0, 173>; // Produces no value -def untyped : ValueType<8, 174>; // Produces an untyped value -def funcref : ValueType<0, 175>; // WebAssembly's funcref type -def externref : ValueType<0, 176>; // WebAssembly's externref type -def x86amx : ValueType<8192, 177>; // X86 AMX value -def i64x8 : ValueType<512, 178>; // 8 Consecutive GPRs (AArch64) - - -def token : ValueType<0, 248>; // TokenTy -def MetadataVT : ValueType<0, 249>; // Metadata - -// Pseudo valuetype mapped to the current pointer size to any address space. -// Should only be used in TableGen. -def iPTRAny : ValueType<0, 250>; - -// Pseudo valuetype to represent "vector of any size" -def vAny : ValueType<0, 251>; - -// Pseudo valuetype to represent "float of any format" -def fAny : ValueType<0, 252>; - -// Pseudo valuetype to represent "integer of any bit width" -def iAny : ValueType<0, 253>; - -// Pseudo valuetype mapped to the current pointer size. -def iPTR : ValueType<0, 254>; - -// Pseudo valuetype to represent "any type of any size". -def Any : ValueType<0, 255>; - -/// This class is for targets that want to use pointer types in patterns -/// with the GlobalISelEmitter. Targets must define their own pointer -/// derived from this class. The scalar argument should be an -/// integer type with the same bit size as the pointer. -/// e.g. def p0 : PtrValueType ; - -class PtrValueType : - ValueType { - int AddrSpace = addrspace; -} diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/VirtRegMap.h b/suite/synctools/tablegen/include/llvm/CodeGen/VirtRegMap.h deleted file mode 100644 index 639368fe5e..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/VirtRegMap.h +++ /dev/null @@ -1,211 +0,0 @@ -//===- llvm/CodeGen/VirtRegMap.h - Virtual Register Map ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements a virtual register map. This maps virtual registers to -// physical registers and virtual registers to stack slots. It is created and -// updated by a register allocator and then used by a machine code rewriter that -// adds spill code and rewrites virtual into physical register references. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_VIRTREGMAP_H -#define LLVM_CODEGEN_VIRTREGMAP_H - -#include "llvm/ADT/IndexedMap.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TileShapeInfo.h" -#include "llvm/Pass.h" -#include - -namespace llvm { - -class MachineFunction; -class MachineRegisterInfo; -class raw_ostream; -class TargetInstrInfo; - - class VirtRegMap : public MachineFunctionPass { - public: - enum { - NO_PHYS_REG = 0, - NO_STACK_SLOT = (1L << 30)-1, - MAX_STACK_SLOT = (1L << 18)-1 - }; - - private: - MachineRegisterInfo *MRI = nullptr; - const TargetInstrInfo *TII = nullptr; - const TargetRegisterInfo *TRI = nullptr; - MachineFunction *MF = nullptr; - - /// Virt2PhysMap - This is a virtual to physical register - /// mapping. Each virtual register is required to have an entry in - /// it; even spilled virtual registers (the register mapped to a - /// spilled register is the temporary used to load it from the - /// stack). - IndexedMap Virt2PhysMap; - - /// Virt2StackSlotMap - This is virtual register to stack slot - /// mapping. Each spilled virtual register has an entry in it - /// which corresponds to the stack slot this register is spilled - /// at. - IndexedMap Virt2StackSlotMap; - - /// Virt2SplitMap - This is virtual register to splitted virtual register - /// mapping. - IndexedMap Virt2SplitMap; - - /// Virt2ShapeMap - For X86 AMX register whose register is bound shape - /// information. - DenseMap Virt2ShapeMap; - - /// createSpillSlot - Allocate a spill slot for RC from MFI. - unsigned createSpillSlot(const TargetRegisterClass *RC); - - public: - static char ID; - - VirtRegMap() - : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), - Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} - VirtRegMap(const VirtRegMap &) = delete; - VirtRegMap &operator=(const VirtRegMap &) = delete; - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - MachineFunction &getMachineFunction() const { - assert(MF && "getMachineFunction called before runOnMachineFunction"); - return *MF; - } - - MachineRegisterInfo &getRegInfo() const { return *MRI; } - const TargetRegisterInfo &getTargetRegInfo() const { return *TRI; } - - void grow(); - - /// returns true if the specified virtual register is - /// mapped to a physical register - bool hasPhys(Register virtReg) const { - return getPhys(virtReg) != NO_PHYS_REG; - } - - /// returns the physical register mapped to the specified - /// virtual register - MCRegister getPhys(Register virtReg) const { - assert(virtReg.isVirtual()); - return MCRegister::from(Virt2PhysMap[virtReg.id()]); - } - - /// creates a mapping for the specified virtual register to - /// the specified physical register - void assignVirt2Phys(Register virtReg, MCPhysReg physReg); - - bool isShapeMapEmpty() const { return Virt2ShapeMap.empty(); } - - bool hasShape(Register virtReg) const { - return getShape(virtReg).isValid(); - } - - ShapeT getShape(Register virtReg) const { - assert(virtReg.isVirtual()); - return Virt2ShapeMap.lookup(virtReg); - } - - void assignVirt2Shape(Register virtReg, ShapeT shape) { - Virt2ShapeMap[virtReg.id()] = shape; - } - - /// clears the specified virtual register's, physical - /// register mapping - void clearVirt(Register virtReg) { - assert(virtReg.isVirtual()); - assert(Virt2PhysMap[virtReg.id()] != NO_PHYS_REG && - "attempt to clear a not assigned virtual register"); - Virt2PhysMap[virtReg.id()] = NO_PHYS_REG; - } - - /// clears all virtual to physical register mappings - void clearAllVirt() { - Virt2PhysMap.clear(); - grow(); - } - - /// returns true if VirtReg is assigned to its preferred physreg. - bool hasPreferredPhys(Register VirtReg) const; - - /// returns true if VirtReg has a known preferred register. - /// This returns false if VirtReg has a preference that is a virtual - /// register that hasn't been assigned yet. - bool hasKnownPreference(Register VirtReg) const; - - /// records virtReg is a split live interval from SReg. - void setIsSplitFromReg(Register virtReg, Register SReg) { - Virt2SplitMap[virtReg.id()] = SReg; - if (hasShape(SReg)) { - Virt2ShapeMap[virtReg.id()] = getShape(SReg); - } - } - - /// returns the live interval virtReg is split from. - Register getPreSplitReg(Register virtReg) const { - return Virt2SplitMap[virtReg.id()]; - } - - /// getOriginal - Return the original virtual register that VirtReg descends - /// from through splitting. - /// A register that was not created by splitting is its own original. - /// This operation is idempotent. - Register getOriginal(Register VirtReg) const { - Register Orig = getPreSplitReg(VirtReg); - return Orig ? Orig : VirtReg; - } - - /// returns true if the specified virtual register is not - /// mapped to a stack slot or rematerialized. - bool isAssignedReg(Register virtReg) const { - if (getStackSlot(virtReg) == NO_STACK_SLOT) - return true; - // Split register can be assigned a physical register as well as a - // stack slot or remat id. - return (Virt2SplitMap[virtReg.id()] && - Virt2PhysMap[virtReg.id()] != NO_PHYS_REG); - } - - /// returns the stack slot mapped to the specified virtual - /// register - int getStackSlot(Register virtReg) const { - assert(virtReg.isVirtual()); - return Virt2StackSlotMap[virtReg.id()]; - } - - /// create a mapping for the specified virtual register to - /// the next available stack slot - int assignVirt2StackSlot(Register virtReg); - - /// create a mapping for the specified virtual register to - /// the specified stack slot - void assignVirt2StackSlot(Register virtReg, int SS); - - void print(raw_ostream &OS, const Module* M = nullptr) const override; - void dump() const; - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) { - VRM.print(OS); - return OS; - } - -} // end llvm namespace - -#endif // LLVM_CODEGEN_VIRTREGMAP_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/WasmEHFuncInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/WasmEHFuncInfo.h deleted file mode 100644 index 8b55a45b61..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/WasmEHFuncInfo.h +++ /dev/null @@ -1,96 +0,0 @@ -//===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Data structures for Wasm exception handling schemes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H -#define LLVM_CODEGEN_WASMEHFUNCINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallPtrSet.h" - -namespace llvm { - -class BasicBlock; -class Function; -class MachineBasicBlock; - -namespace WebAssembly { -enum Tag { CPP_EXCEPTION = 0, C_LONGJMP = 1 }; -} - -using BBOrMBB = PointerUnion; - -struct WasmEHFuncInfo { - // When there is an entry , if an exception is not caught by A, it - // should next unwind to the EH pad B. - DenseMap SrcToUnwindDest; - DenseMap> UnwindDestToSrcs; // reverse map - - // Helper functions - const BasicBlock *getUnwindDest(const BasicBlock *BB) const { - assert(hasUnwindDest(BB)); - return SrcToUnwindDest.lookup(BB).get(); - } - SmallPtrSet getUnwindSrcs(const BasicBlock *BB) const { - assert(hasUnwindSrcs(BB)); - const auto &Set = UnwindDestToSrcs.lookup(BB); - SmallPtrSet Ret; - for (const auto P : Set) - Ret.insert(P.get()); - return Ret; - } - void setUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { - SrcToUnwindDest[BB] = Dest; - if (!UnwindDestToSrcs.count(Dest)) - UnwindDestToSrcs[Dest] = SmallPtrSet(); - UnwindDestToSrcs[Dest].insert(BB); - } - bool hasUnwindDest(const BasicBlock *BB) const { - return SrcToUnwindDest.count(BB); - } - bool hasUnwindSrcs(const BasicBlock *BB) const { - return UnwindDestToSrcs.count(BB); - } - - MachineBasicBlock *getUnwindDest(MachineBasicBlock *MBB) const { - assert(hasUnwindDest(MBB)); - return SrcToUnwindDest.lookup(MBB).get(); - } - SmallPtrSet - getUnwindSrcs(MachineBasicBlock *MBB) const { - assert(hasUnwindSrcs(MBB)); - const auto &Set = UnwindDestToSrcs.lookup(MBB); - SmallPtrSet Ret; - for (const auto P : Set) - Ret.insert(P.get()); - return Ret; - } - void setUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { - SrcToUnwindDest[MBB] = Dest; - if (!UnwindDestToSrcs.count(Dest)) - UnwindDestToSrcs[Dest] = SmallPtrSet(); - UnwindDestToSrcs[Dest].insert(MBB); - } - bool hasUnwindDest(MachineBasicBlock *MBB) const { - return SrcToUnwindDest.count(MBB); - } - bool hasUnwindSrcs(MachineBasicBlock *MBB) const { - return UnwindDestToSrcs.count(MBB); - } -}; - -// Analyze the IR in the given function to build WasmEHFuncInfo. -void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo); - -} // namespace llvm - -#endif // LLVM_CODEGEN_WASMEHFUNCINFO_H diff --git a/suite/synctools/tablegen/include/llvm/CodeGen/WinEHFuncInfo.h b/suite/synctools/tablegen/include/llvm/CodeGen/WinEHFuncInfo.h deleted file mode 100644 index ddfb49a2a3..0000000000 --- a/suite/synctools/tablegen/include/llvm/CodeGen/WinEHFuncInfo.h +++ /dev/null @@ -1,128 +0,0 @@ -//===- llvm/CodeGen/WinEHFuncInfo.h -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Data structures and associated state for Windows exception handling schemes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_WINEHFUNCINFO_H -#define LLVM_CODEGEN_WINEHFUNCINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" -#include -#include -#include - -namespace llvm { - -class AllocaInst; -class BasicBlock; -class FuncletPadInst; -class Function; -class GlobalVariable; -class Instruction; -class InvokeInst; -class MachineBasicBlock; -class MCSymbol; - -// The following structs represent the .xdata tables for various -// Windows-related EH personalities. - -using MBBOrBasicBlock = PointerUnion; - -struct CxxUnwindMapEntry { - int ToState; - MBBOrBasicBlock Cleanup; -}; - -/// Similar to CxxUnwindMapEntry, but supports SEH filters. -struct SEHUnwindMapEntry { - /// If unwinding continues through this handler, transition to the handler at - /// this state. This indexes into SEHUnwindMap. - int ToState = -1; - - bool IsFinally = false; - - /// Holds the filter expression function. - const Function *Filter = nullptr; - - /// Holds the __except or __finally basic block. - MBBOrBasicBlock Handler; -}; - -struct WinEHHandlerType { - int Adjectives; - /// The CatchObj starts out life as an LLVM alloca and is eventually turned - /// frame index. - union { - const AllocaInst *Alloca; - int FrameIndex; - } CatchObj = {}; - GlobalVariable *TypeDescriptor; - MBBOrBasicBlock Handler; -}; - -struct WinEHTryBlockMapEntry { - int TryLow = -1; - int TryHigh = -1; - int CatchHigh = -1; - SmallVector HandlerArray; -}; - -enum class ClrHandlerType { Catch, Finally, Fault, Filter }; - -struct ClrEHUnwindMapEntry { - MBBOrBasicBlock Handler; - uint32_t TypeToken; - int HandlerParentState; ///< Outer handler enclosing this entry's handler - int TryParentState; ///< Outer try region enclosing this entry's try region, - ///< treating later catches on same try as "outer" - ClrHandlerType HandlerType; -}; - -struct WinEHFuncInfo { - DenseMap EHPadStateMap; - DenseMap FuncletBaseStateMap; - DenseMap InvokeStateMap; - DenseMap> LabelToStateMap; - SmallVector CxxUnwindMap; - SmallVector TryBlockMap; - SmallVector SEHUnwindMap; - SmallVector ClrEHUnwindMap; - int UnwindHelpFrameIdx = std::numeric_limits::max(); - int PSPSymFrameIdx = std::numeric_limits::max(); - - int getLastStateNumber() const { return CxxUnwindMap.size() - 1; } - - void addIPToStateRange(const InvokeInst *II, MCSymbol *InvokeBegin, - MCSymbol *InvokeEnd); - - int EHRegNodeFrameIndex = std::numeric_limits::max(); - int EHRegNodeEndOffset = std::numeric_limits::max(); - int EHGuardFrameIndex = std::numeric_limits::max(); - int SEHSetFrameOffset = std::numeric_limits::max(); - - WinEHFuncInfo(); -}; - -/// Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which -/// describes the state numbers and tables used by __CxxFrameHandler3. This -/// analysis assumes that WinEHPrepare has already been run. -void calculateWinCXXEHStateNumbers(const Function *ParentFn, - WinEHFuncInfo &FuncInfo); - -void calculateSEHStateNumbers(const Function *ParentFn, - WinEHFuncInfo &FuncInfo); - -void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo); - -} // end namespace llvm - -#endif // LLVM_CODEGEN_WINEHFUNCINFO_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/Directive/DirectiveBase.td b/suite/synctools/tablegen/include/llvm/Frontend/Directive/DirectiveBase.td deleted file mode 100644 index d47c12483a..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/Directive/DirectiveBase.td +++ /dev/null @@ -1,145 +0,0 @@ -//===-- DirectiveBase.td - Base directive definition file --*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This is the base definition file directives and clauses. -// -//===----------------------------------------------------------------------===// - - -// General information about the directive language. -class DirectiveLanguage { - // Name of the directive language such as omp or acc. - string name = ?; - - // The C++ namespace that code of this directive language should be placed - // into. This namespace is nested in llvm namespace. - // - // By default, uses the name of the directive language as the only namespace. - // To avoid placing in any namespace, use "". To specify nested namespaces, - // use "::" as the delimiter, e.g., given "A::B", ops will be placed in - // `namespace A { namespace B { } }`. - string cppNamespace = name; - - // Optional prefix used for the generation of the enumerator in the Directive - // enum. - string directivePrefix = ""; - - // Optional prefix used for the generation of the enumerator in the Clause - // enum. - string clausePrefix = ""; - - // Make the enum values available in the namespace. This allows us to - // write something like Enum_X if we have a `using namespace cppNamespace`. - bit makeEnumAvailableInNamespace = false; - - // Generate include and macro to enable LLVM BitmaskEnum. - bit enableBitmaskEnumInNamespace = false; - - // Header file included in the implementation code generated. Usually the - // output file of the declaration code generation. Can be left blank. - string includeHeader = ""; - - // EnumSet class name used for clauses to generated the allowed clauses map. - string clauseEnumSetClass = ""; - - // Class holding the clauses in the flang parse-tree. - string flangClauseBaseClass = ""; -} - -// Information about values accepted by enum-like clauses -class ClauseVal { - // Name of the clause value. - string name = n; - - // Integer value of the clause. - int value = v; - - // Can user specify this value? - bit isUserValue = uv; - - // Set clause value used by default when unknown. - bit isDefault = false; -} - -// Information about a specific clause. -class Clause { - // Name of the clause. - string name = c; - - // Define an alternative name return in getClauseName function. - string alternativeName = ""; - - // Optional class holding value of the clause in clang AST. - string clangClass = ""; - - // Optional class holding value of the clause in flang AST. - string flangClass = ""; - - // If set to true, value is optional. Not optional by default. - bit isValueOptional = false; - - // Name of enum when there is a list of allowed clause values. - string enumClauseValue = ""; - - // List of allowed clause values - list allowedClauseValues = []; - // If set to true, value class is part of a list. Single class by default. - bit isValueList = false; - - // Define a default value such as "*". - string defaultValue = ""; - - // Is clause implicit? If clause is set as implicit, the default kind will - // be return in getClauseKind instead of their own kind. - bit isImplicit = false; - - // Set clause used by default when unknown. Function returning the kind - // of enumeration will use this clause as the default. - bit isDefault = false; -} - -// Hold information about clause validity by version. -class VersionedClause { - // Actual clause. - Clause clause = c; - - // Minimum version number where this clause is valid. - int minVersion = min; - - // Maximum version number where this clause is valid. - int maxVersion = max; -} - -// Information about a specific directive. -class Directive { - // Name of the directive. Can be composite directive separated by whitespace. - string name = d; - - // Define an alternative name return in getDirectiveName - // function. - string alternativeName = ""; - - // Clauses cannot appear twice in the three allowed lists below. Also, since - // required implies allowed, the same clause cannot appear in both the - // allowedClauses and requiredClauses lists. - - // List of allowed clauses for the directive. - list allowedClauses = []; - - // List of clauses that are allowed to appear only once. - list allowedOnceClauses = []; - - // List of clauses that are allowed but mutually exclusive. - list allowedExclusiveClauses = []; - - // List of clauses that are required. - list requiredClauses = []; - - // Set directive used by default when unknown. - bit isDefault = false; -} diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenACC/ACC.td b/suite/synctools/tablegen/include/llvm/Frontend/OpenACC/ACC.td deleted file mode 100644 index c68330665b..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenACC/ACC.td +++ /dev/null @@ -1,633 +0,0 @@ -//===-- ACC.td - OpenACC directive definition file ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This is the definition file for OpenACC 3.1 directives and clauses. -// -//===----------------------------------------------------------------------===// - -include "llvm/Frontend/Directive/DirectiveBase.td" - -//===----------------------------------------------------------------------===// -// Definition of general OpenACC information -//===----------------------------------------------------------------------===// - -def OpenACC : DirectiveLanguage { - let name = "OpenACC"; - let cppNamespace = "acc"; // final namespace will be llvm::acc - let directivePrefix = "ACCD_"; - let clausePrefix = "ACCC_"; - let makeEnumAvailableInNamespace = true; - let enableBitmaskEnumInNamespace = true; - let clauseEnumSetClass = "AccClauseSet"; - let flangClauseBaseClass = "AccClause"; -} - -//===----------------------------------------------------------------------===// -// Definition of OpenACC clauses -//===----------------------------------------------------------------------===// - -// 2.16.1 -def ACCC_Async : Clause<"async"> { - let flangClass = "ScalarIntExpr"; - let isValueOptional = true; -} - -// 2.9.7 -def ACCC_Auto : Clause<"auto"> {} - -// 2.7.12 -def ACCC_Attach : Clause<"attach"> { - let flangClass = "AccObjectList"; -} - -// 2.15.1 -def ACCC_Bind : Clause<"bind"> { - let flangClass = "AccBindClause"; -} - -// 2.12 -def ACCC_Capture : Clause<"capture"> { -} - -// 2.9.1 -def ACCC_Collapse : Clause<"collapse"> { - let flangClass = "ScalarIntConstantExpr"; -} - -// 2.7.6 -def ACCC_Copy : Clause<"copy"> { - let flangClass = "AccObjectList"; -} -// 2.7.7 -def ACCC_Copyin : Clause<"copyin"> { - let flangClass = "AccObjectListWithModifier"; -} - -// 2.7.8 -def ACCC_Copyout : Clause<"copyout"> { - let flangClass = "AccObjectListWithModifier"; -} - -// 2.7.9 -def ACCC_Create : Clause<"create"> { - let flangClass = "AccObjectListWithModifier"; -} - -// 2.5.15 -def ACC_Default_none : ClauseVal<"none", 1, 1> { let isDefault = 1; } -def ACC_Default_present : ClauseVal<"present", 0, 1> {} - -def ACCC_Default : Clause<"default"> { - let flangClass = "AccDefaultClause"; - let enumClauseValue = "DefaultValue"; - let allowedClauseValues = [ - ACC_Default_present, - ACC_Default_none - ]; -} - -// 2.14.3 -def ACCC_DefaultAsync : Clause<"default_async"> { - let flangClass = "ScalarIntExpr"; -} - -// 2.7.11 -def ACCC_Delete : Clause<"delete"> { - let flangClass = "AccObjectList"; -} - -// 2.7.13 -def ACCC_Detach : Clause<"detach"> { - let flangClass = "AccObjectList"; -} - -// 2.14.4 -def ACCC_Device : Clause<"device"> { - let flangClass = "AccObjectList"; -} - -// 2.14.1 - 2.14.2 -def ACCC_DeviceNum : Clause<"device_num"> { - let flangClass = "ScalarIntExpr"; -} - -// 2.7.4 -def ACCC_DevicePtr : Clause<"deviceptr"> { - let flangClass = "AccObjectList"; -} - -// 2.13.1 -def ACCC_DeviceResident : Clause<"device_resident"> { - let flangClass = "AccObjectList"; -} - -// 2.4 -def ACCC_DeviceType : Clause<"device_type"> { - let flangClass = "ScalarIntExpr"; - let defaultValue = "*"; - let isValueOptional = true; - let isValueList = true; -} - -// 2.6.6 -def ACCC_Finalize : Clause<"finalize"> {} - -// 2.5.13 -def ACCC_FirstPrivate : Clause<"firstprivate"> { - let flangClass = "AccObjectList"; -} - -// 2.9.2 -def ACCC_Gang : Clause<"gang"> { - let flangClass = "AccGangArgument"; - let isValueOptional = true; -} - -// 2.14.4 -def ACCC_Host : Clause<"host"> { - let flangClass = "AccObjectList"; -} - -// 2.5.5 -def ACCC_If : Clause <"if"> { - let flangClass = "ScalarLogicalExpr"; -} - -// 2.14.4 -def ACCC_IfPresent : Clause<"if_present"> {} - -// 2.9.6 -def ACCC_Independent : Clause<"independent"> {} - -// 2.13.3 -def ACCC_Link : Clause<"link"> { - let flangClass = "AccObjectList"; -} - -// 2.7.10 -def ACCC_NoCreate : Clause<"no_create"> { - let flangClass = "AccObjectList"; -} - -// 2.15.1 -def ACCC_NoHost : Clause<"nohost"> {} - -// 2.5.9 -def ACCC_NumGangs : Clause<"num_gangs"> { - let flangClass = "ScalarIntExpr"; -} - -// 2.5.10 -def ACCC_NumWorkers : Clause<"num_workers"> { - let flangClass = "ScalarIntExpr"; -} - -// 2.7.5 -def ACCC_Present : Clause<"present"> { - let flangClass = "AccObjectList"; -} - -// 2.5.12 -def ACCC_Private : Clause<"private"> { - let flangClass = "AccObjectList"; -} - -// 2.9.8 -def ACCC_Tile : Clause <"tile"> { - let flangClass = "AccTileExprList"; -} - -// 2.8.1 -def ACCC_UseDevice : Clause <"use_device"> { - let flangClass = "AccObjectList"; -} - -// 2.12 -def ACCC_Read : Clause<"read"> {} - -// 2.5.14 -def ACCC_Reduction : Clause<"reduction"> { - let flangClass = "AccObjectListWithReduction"; -} - -// 2.5.6 -def ACCC_Self : Clause<"self"> { - let flangClass = "AccSelfClause"; -} - -// 2.9.5 -def ACCC_Seq : Clause<"seq"> {} - -// 2.9.4 -def ACCC_Vector : Clause<"vector"> { - let flangClass = "ScalarIntExpr"; - let isValueOptional = true; -} - -// 2.5.11 -def ACCC_VectorLength : Clause<"vector_length"> { - let flangClass = "ScalarIntExpr"; -} - -// 2.16.2 -def ACCC_Wait : Clause<"wait"> { - let flangClass = "AccWaitArgument"; - let isValueOptional = true; -} - -// 2.9.3 -def ACCC_Worker: Clause<"worker"> { - let flangClass = "ScalarIntExpr"; - let isValueOptional = true; -} - -// 2.12 -def ACCC_Write : Clause<"write"> {} - -def ACCC_Unknown : Clause<"unknown"> { - let isDefault = true; -} - -//===----------------------------------------------------------------------===// -// Definition of OpenACC directives -//===----------------------------------------------------------------------===// - -// 2.12 -def ACC_Atomic : Directive<"atomic"> {} - -// 2.6.5 -def ACC_Data : Directive<"data"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.13 -def ACC_Declare : Directive<"declare"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.5.3 -def ACC_Kernels : Directive<"kernels"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.5.1 -def ACC_Parallel : Directive<"parallel"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.5.2 -def ACC_Serial : Directive<"serial"> { - // Spec line 950-951: clause is as for the parallel construct except that the - // num_gangs, num_workers, and vector_length clauses are not permitted. - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.9 -def ACC_Loop : Directive<"loop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.10 -def ACC_Cache : Directive<"cache"> {} - -// 2.14.1 -def ACC_Init : Directive<"init"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.15.1 -def ACC_Routine : Directive<"routine"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.14.3 -def ACC_Set : Directive<"set"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - // The three following clauses are also in allowedOnceClauses list due to - // restriction 2255 - Two instances of the same clause may not appear on the - // same directive. - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.14.2 -def ACC_Shutdown : Directive<"shutdown"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.14.4 -def ACC_Update : Directive<"update"> { - let allowedClauses = [ - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.16.3 -def ACC_Wait : Directive<"wait"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; -} - -// 2.14.6 -def ACC_EnterData : Directive<"enter data"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.14.7 -def ACC_ExitData : Directive<"exit data"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.8 -def ACC_HostData : Directive<"host_data"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause - ]; -} - -// 2.11 -def ACC_KernelsLoop : Directive<"kernels loop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.11 -def ACC_ParallelLoop : Directive<"parallel loop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -// 2.11 -def ACC_SerialLoop : Directive<"serial loop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -def ACC_Unknown : Directive<"unknown"> { - let isDefault = true; -} diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMP.td b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMP.td deleted file mode 100644 index c5abb16dd9..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMP.td +++ /dev/null @@ -1,1766 +0,0 @@ -//===-- OMP.td - OpenMP directive definition file ----------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This is the definition file for OpenMP directives and clauses. -// -//===----------------------------------------------------------------------===// - -include "llvm/Frontend/Directive/DirectiveBase.td" - -//===----------------------------------------------------------------------===// -// Definition of general OpenMP information -//===----------------------------------------------------------------------===// - -def OpenMP : DirectiveLanguage { - let name = "OpenMP"; - let cppNamespace = "omp"; // final namespace will be llvm::omp - let directivePrefix = "OMPD_"; - let clausePrefix = "OMPC_"; - let makeEnumAvailableInNamespace = true; - let enableBitmaskEnumInNamespace = true; - let clauseEnumSetClass = "OmpClauseSet"; - let flangClauseBaseClass = "OmpClause"; -} - -//===----------------------------------------------------------------------===// -// Definition of OpenMP clauses -//===----------------------------------------------------------------------===// - -def OMPC_Allocator : Clause<"allocator"> { - let clangClass = "OMPAllocatorClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_If : Clause<"if"> { - let clangClass = "OMPIfClause"; - let flangClass = "OmpIfClause"; -} -def OMPC_Final : Clause<"final"> { - let clangClass = "OMPFinalClause"; - let flangClass = "ScalarLogicalExpr"; -} -def OMPC_NumThreads : Clause<"num_threads"> { - let clangClass = "OMPNumThreadsClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_SafeLen : Clause<"safelen"> { - let clangClass = "OMPSafelenClause"; - let flangClass = "ScalarIntConstantExpr"; -} -def OMPC_SimdLen : Clause<"simdlen"> { - let clangClass = "OMPSimdlenClause"; - let flangClass = "ScalarIntConstantExpr"; -} -def OMPC_Collapse : Clause<"collapse"> { - let clangClass = "OMPCollapseClause"; - let flangClass = "ScalarIntConstantExpr"; -} -def OMPC_Default : Clause<"default"> { - let clangClass = "OMPDefaultClause"; - let flangClass = "OmpDefaultClause"; -} -def OMPC_Private : Clause<"private"> { - let clangClass = "OMPPrivateClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_Sizes: Clause<"sizes"> { let clangClass = "OMPSizesClause"; } -def OMPC_Full: Clause<"full"> { let clangClass = "OMPFullClause"; } -def OMPC_Partial: Clause<"partial"> { let clangClass = "OMPPartialClause"; } -def OMPC_FirstPrivate : Clause<"firstprivate"> { - let clangClass = "OMPFirstprivateClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_LastPrivate : Clause<"lastprivate"> { - let clangClass = "OMPLastprivateClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_Shared : Clause<"shared"> { - let clangClass = "OMPSharedClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_Reduction : Clause<"reduction"> { - let clangClass = "OMPReductionClause"; - let flangClass = "OmpReductionClause"; -} -def OMPC_Linear : Clause<"linear"> { - let clangClass = "OMPLinearClause"; - let flangClass = "OmpLinearClause"; -} -def OMPC_Aligned : Clause<"aligned"> { - let clangClass = "OMPAlignedClause"; - let flangClass = "OmpAlignedClause"; -} -def OMPC_Copyin : Clause<"copyin"> { - let clangClass = "OMPCopyinClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_CopyPrivate : Clause<"copyprivate"> { - let clangClass = "OMPCopyprivateClause"; - let flangClass = "OmpObjectList"; -} -def OMP_PROC_BIND_master : ClauseVal<"master",2,1> {} -def OMP_PROC_BIND_close : ClauseVal<"close",3,1> {} -def OMP_PROC_BIND_spread : ClauseVal<"spread",4,1> {} -def OMP_PROC_BIND_primary : ClauseVal<"primary",5,1> {} -def OMP_PROC_BIND_default : ClauseVal<"default",6,0> {} -def OMP_PROC_BIND_unknown : ClauseVal<"unknown",7,0> { let isDefault = true; } -def OMPC_ProcBind : Clause<"proc_bind"> { - let clangClass = "OMPProcBindClause"; - let flangClass = "OmpProcBindClause"; - let enumClauseValue = "ProcBindKind"; - let allowedClauseValues = [ - OMP_PROC_BIND_primary, - OMP_PROC_BIND_master, - OMP_PROC_BIND_close, - OMP_PROC_BIND_spread, - OMP_PROC_BIND_default, - OMP_PROC_BIND_unknown - ]; -} - -// static and auto are C++ keywords so need a capital to disambiguate. -def OMP_SCHEDULE_Static : ClauseVal<"Static", 2, 1> {} -def OMP_SCHEDULE_Dynamic : ClauseVal<"Dynamic", 3, 1> {} -def OMP_SCHEDULE_Guided : ClauseVal<"Guided", 4, 1> {} -def OMP_SCHEDULE_Auto : ClauseVal<"Auto", 5, 1> {} -def OMP_SCHEDULE_Runtime : ClauseVal<"Runtime", 6, 1> {} -def OMP_SCHEDULE_Default : ClauseVal<"Default", 7, 0> { let isDefault = 1; } - -def OMPC_Schedule : Clause<"schedule"> { - let clangClass = "OMPScheduleClause"; - let flangClass = "OmpScheduleClause"; - let enumClauseValue = "ScheduleKind"; - let allowedClauseValues = [ - OMP_SCHEDULE_Static, - OMP_SCHEDULE_Dynamic, - OMP_SCHEDULE_Guided, - OMP_SCHEDULE_Auto, - OMP_SCHEDULE_Runtime, - OMP_SCHEDULE_Default - ]; -} - -def OMP_MEMORY_ORDER_SeqCst : ClauseVal<"seq_cst", 1, 1> {} -def OMP_MEMORY_ORDER_AcqRel : ClauseVal<"acq_rel", 2, 1> {} -def OMP_MEMORY_ORDER_Acquire : ClauseVal<"acquire", 3, 1> {} -def OMP_MEMORY_ORDER_Release : ClauseVal<"release", 4, 1> {} -def OMP_MEMORY_ORDER_Relaxed : ClauseVal<"relaxed", 5, 1> {} -def OMP_MEMORY_ORDER_Default : ClauseVal<"default", 6, 0> { - let isDefault = 1; -} -def OMPC_MemoryOrder : Clause<"memory_order"> { - let enumClauseValue = "MemoryOrderKind"; - let allowedClauseValues = [ - OMP_MEMORY_ORDER_SeqCst, - OMP_MEMORY_ORDER_AcqRel, - OMP_MEMORY_ORDER_Acquire, - OMP_MEMORY_ORDER_Release, - OMP_MEMORY_ORDER_Relaxed, - OMP_MEMORY_ORDER_Default - ]; -} - -def OMPC_Ordered : Clause<"ordered"> { - let clangClass = "OMPOrderedClause"; - let flangClass = "ScalarIntConstantExpr"; - let isValueOptional = true; -} -def OMPC_NoWait : Clause<"nowait"> { - let clangClass = "OMPNowaitClause"; -} -def OMPC_Untied : Clause<"untied"> { let clangClass = "OMPUntiedClause"; } -def OMPC_Mergeable : Clause<"mergeable"> { - let clangClass = "OMPMergeableClause"; -} -def OMPC_Read : Clause<"read"> { let clangClass = "OMPReadClause"; } -def OMPC_Write : Clause<"write"> { let clangClass = "OMPWriteClause"; } -def OMPC_Update : Clause<"update"> { let clangClass = "OMPUpdateClause"; } -def OMPC_Capture : Clause<"capture"> { let clangClass = "OMPCaptureClause"; } -def OMPC_Compare : Clause<"compare"> { let clangClass = "OMPCompareClause"; } -def OMPC_SeqCst : Clause<"seq_cst"> { let clangClass = "OMPSeqCstClause"; } -def OMPC_AcqRel : Clause<"acq_rel"> { let clangClass = "OMPAcqRelClause"; } -def OMPC_Acquire : Clause<"acquire"> { let clangClass = "OMPAcquireClause"; } -def OMPC_Release : Clause<"release"> { let clangClass = "OMPReleaseClause"; } -def OMPC_Relaxed : Clause<"relaxed"> { let clangClass = "OMPRelaxedClause"; } -def OMPC_Depend : Clause<"depend"> { - let clangClass = "OMPDependClause"; - let flangClass = "OmpDependClause"; -} -def OMPC_Device : Clause<"device"> { - let clangClass = "OMPDeviceClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_Threads : Clause<"threads"> { let clangClass = "OMPThreadsClause"; } -def OMPC_Simd : Clause<"simd"> { let clangClass = "OMPSIMDClause"; } -def OMPC_Map : Clause<"map"> { - let clangClass = "OMPMapClause"; - let flangClass = "OmpMapClause"; -} -def OMPC_NumTeams : Clause<"num_teams"> { - let clangClass = "OMPNumTeamsClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_ThreadLimit : Clause<"thread_limit"> { - let clangClass = "OMPThreadLimitClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_Priority : Clause<"priority"> { - let clangClass = "OMPPriorityClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_GrainSize : Clause<"grainsize"> { - let clangClass = "OMPGrainsizeClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_NoGroup : Clause<"nogroup"> { - let clangClass = "OMPNogroupClause"; -} -def OMPC_NumTasks : Clause<"num_tasks"> { - let clangClass = "OMPNumTasksClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_Hint : Clause<"hint"> { - let clangClass = "OMPHintClause"; - let flangClass = "ConstantExpr"; -} -def OMPC_DistSchedule : Clause<"dist_schedule"> { - let clangClass = "OMPDistScheduleClause"; - let flangClass = "ScalarIntExpr"; - let isValueOptional = true; -} -def OMPC_DefaultMap : Clause<"defaultmap"> { - let clangClass = "OMPDefaultmapClause"; - let flangClass = "OmpDefaultmapClause"; -} -def OMPC_To : Clause<"to"> { - let clangClass = "OMPToClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_From : Clause<"from"> { - let clangClass = "OMPFromClause"; - let flangClass = "OmpObjectList"; -} -def OMPC_UseDevicePtr : Clause<"use_device_ptr"> { - let clangClass = "OMPUseDevicePtrClause"; - let flangClass = "Name"; - let isValueList = true; -} -def OMPC_IsDevicePtr : Clause<"is_device_ptr"> { - let clangClass = "OMPIsDevicePtrClause"; - let flangClass = "Name"; - let isValueList = true; -} -def OMPC_TaskReduction : Clause<"task_reduction"> { - let clangClass = "OMPTaskReductionClause"; - let flangClass = "OmpReductionClause"; -} -def OMPC_InReduction : Clause<"in_reduction"> { - let clangClass = "OMPInReductionClause"; -} -def OMPC_UnifiedAddress : Clause<"unified_address"> { - let clangClass = "OMPUnifiedAddressClause"; -} -def OMPC_UnifiedSharedMemory : Clause<"unified_shared_memory"> { - let clangClass = "OMPUnifiedSharedMemoryClause"; -} -def OMPC_ReverseOffload : Clause<"reverse_offload"> { - let clangClass = "OMPReverseOffloadClause"; -} -def OMPC_DynamicAllocators : Clause<"dynamic_allocators"> { - let clangClass = "OMPDynamicAllocatorsClause"; -} -def OMPC_AtomicDefaultMemOrder : Clause<"atomic_default_mem_order"> { - let clangClass = "OMPAtomicDefaultMemOrderClause"; -} -def OMPC_Allocate : Clause<"allocate"> { - let clangClass = "OMPAllocateClause"; - let flangClass = "OmpAllocateClause"; -} -def OMPC_NonTemporal : Clause<"nontemporal"> { - let clangClass = "OMPNontemporalClause"; - let flangClass = "Name"; - let isValueList = true; -} - -def OMP_ORDER_concurrent : ClauseVal<"concurrent",1,1> {} -def OMP_ORDER_unknown : ClauseVal<"unknown",2,0> { let isDefault = 1; } -def OMPC_Order : Clause<"order"> { - let clangClass = "OMPOrderClause"; - let enumClauseValue = "OrderKind"; - let allowedClauseValues = [ - OMP_ORDER_unknown, - OMP_ORDER_concurrent - ]; -} -def OMPC_Init : Clause<"init"> { - let clangClass = "OMPInitClause"; -} -def OMPC_Use : Clause<"use"> { - let clangClass = "OMPUseClause"; -} -def OMPC_Destroy : Clause<"destroy"> { - let clangClass = "OMPDestroyClause"; -} -def OMPC_Novariants : Clause<"novariants"> { - let clangClass = "OMPNovariantsClause"; - let flangClass = "ScalarLogicalExpr"; -} -def OMPC_Nocontext : Clause<"nocontext"> { - let clangClass = "OMPNocontextClause"; - let flangClass = "ScalarLogicalExpr"; -} -def OMPC_Detach : Clause<"detach"> { - let clangClass = "OMPDetachClause"; -} -def OMPC_Inclusive : Clause<"inclusive"> { - let clangClass = "OMPInclusiveClause"; -} -def OMPC_Exclusive : Clause<"exclusive"> { - let clangClass = "OMPExclusiveClause"; -} -def OMPC_UsesAllocators : Clause<"uses_allocators"> { - let clangClass = "OMPUsesAllocatorsClause"; -} -def OMPC_Affinity : Clause<"affinity"> { - let clangClass = "OMPAffinityClause"; -} -def OMPC_UseDeviceAddr : Clause<"use_device_addr"> { - let clangClass = "OMPUseDeviceAddrClause"; -} -def OMPC_Uniform : Clause<"uniform"> { - let flangClass = "Name"; - let isValueList = true; -} -def OMPC_DeviceType : Clause<"device_type"> {} -def OMPC_Match : Clause<"match"> {} -def OMPC_AdjustArgs : Clause<"adjust_args"> { } -def OMPC_AppendArgs : Clause<"append_args"> { } -def OMPC_Depobj : Clause<"depobj"> { - let clangClass = "OMPDepobjClause"; - let isImplicit = true; -} -def OMPC_Flush : Clause<"flush"> { - let clangClass = "OMPFlushClause"; - let isImplicit = true; -} -def OMPC_ThreadPrivate : Clause<"threadprivate"> { - let alternativeName = "threadprivate or thread local"; - let isImplicit = true; -} -def OMPC_Unknown : Clause<"unknown"> { - let isImplicit = true; - let isDefault = true; -} -def OMPC_Link : Clause<"link"> { - let flangClass = "OmpObjectList"; -} -def OMPC_Indirect : Clause<"indirect"> {} -def OMPC_Inbranch : Clause<"inbranch"> {} -def OMPC_Notinbranch : Clause<"notinbranch"> {} -def OMPC_Filter : Clause<"filter"> { - let clangClass = "OMPFilterClause"; - let flangClass = "ScalarIntExpr"; -} -def OMPC_Align : Clause<"align"> { - let clangClass = "OMPAlignClause"; -} -def OMPC_When: Clause<"when"> {} - -def OMPC_Bind : Clause<"bind"> { - let clangClass = "OMPBindClause"; -} - -//===----------------------------------------------------------------------===// -// Definition of OpenMP directives -//===----------------------------------------------------------------------===// - -def OMP_ThreadPrivate : Directive<"threadprivate"> {} -def OMP_Parallel : Directive<"parallel"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_Task : Directive<"task"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Simd : Directive<"simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_Tile : Directive<"tile"> { - let allowedOnceClauses = [ - VersionedClause, - ]; -} -def OMP_Unroll : Directive<"unroll"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - ]; -} -def OMP_For : Directive<"for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Do : Directive<"do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Sections : Directive<"sections"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Section : Directive<"section"> {} -def OMP_Single : Directive<"single"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Master : Directive<"master"> {} -def OMP_Critical : Directive<"critical"> { - let allowedClauses = [ - VersionedClause - ]; -} -def OMP_TaskYield : Directive<"taskyield"> {} -def OMP_Barrier : Directive<"barrier"> {} -def OMP_TaskWait : Directive<"taskwait"> { - let allowedClauses = [ - VersionedClause - ]; -} -def OMP_TaskGroup : Directive<"taskgroup"> { - let allowedClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_Flush : Directive<"flush"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - // TODO This should ne `none` instead. Comment carried over from - // OMPKinds.def. - VersionedClause - ]; -} -def OMP_Ordered : Directive<"ordered"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_Atomic : Directive<"atomic"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Target : Directive<"target"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Teams : Directive<"teams"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Cancel : Directive<"cancel"> { - let allowedClauses = [ - VersionedClause - ]; -} -def OMP_Requires : Directive<"requires"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetData : Directive<"target data"> { - let allowedClauses = [ - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause - ]; -} -def OMP_TargetEnterData : Directive<"target enter data"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause - ]; -} -def OMP_TargetExitData : Directive<"target exit data"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let requiredClauses = [ - VersionedClause - ]; -} -def OMP_TargetParallel : Directive<"target parallel"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetParallelFor : Directive<"target parallel for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetParallelDo : Directive<"target parallel do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetUpdate : Directive<"target update"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelFor : Directive<"parallel for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelDo : Directive<"parallel do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelForSimd : Directive<"parallel for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelDoSimd : Directive<"parallel do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelMaster : Directive<"parallel master"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelSections : Directive<"parallel sections"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause - ]; -} -def OMP_ForSimd : Directive<"for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_DoSimd : Directive<"do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_CancellationPoint : Directive<"cancellation point"> {} -def OMP_DeclareReduction : Directive<"declare reduction"> {} -def OMP_DeclareMapper : Directive<"declare mapper"> { - let allowedClauses = [ - VersionedClause - ]; -} -def OMP_DeclareSimd : Directive<"declare simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_TaskLoop : Directive<"taskloop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_TaskLoopSimd : Directive<"taskloop simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_Distribute : Directive<"distribute"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_BeginDeclareTarget : Directive<"begin declare target"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_DeclareTarget : Directive<"declare target"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_EndDeclareTarget : Directive<"end declare target"> {} -def OMP_DistributeParallelFor : Directive<"distribute parallel for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_DistributeParallelDo : Directive<"distribute parallel do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_DistributeSimd : Directive<"distribute simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetSimd : Directive<"target simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TeamsDistribute : Directive<"teams distribute"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -def OMP_TeamsDistributeParallelForSimd : - Directive<"teams distribute parallel for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TeamsDistributeParallelDoSimd : - Directive<"teams distribute parallel do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_TeamsDistributeParallelFor : - Directive<"teams distribute parallel for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TeamsDistributeParallelDo : - Directive<"teams distribute parallel do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetTeams : Directive<"target teams"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} - -def OMP_TargetTeamsDistributeParallelFor : - Directive<"target teams distribute parallel for"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetTeamsDistributeParallelDo : - Directive<"target teams distribute parallel do"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_TargetTeamsDistributeParallelForSimd : - Directive<"target teams distribute parallel for simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetTeamsDistributeParallelDoSimd : - Directive<"target teams distribute parallel do simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_TargetTeamsDistributeSimd : - Directive<"target teams distribute simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_Allocate : Directive<"allocate"> { - let allowedOnceClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_DeclareVariant : Directive<"declare variant"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedExclusiveClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_MasterTaskloop : Directive<"master taskloop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelMasterTaskloop : - Directive<"parallel master taskloop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_MasterTaskloopSimd : Directive<"master taskloop simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_ParallelMasterTaskloopSimd : - Directive<"parallel master taskloop simd"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Depobj : Directive<"depobj"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - // TODO This should ne `none` instead. Comment carried over from - // OMPKinds.def. - VersionedClause - ]; -} -def OMP_Scan : Directive<"scan"> { - let allowedClauses = [ - VersionedClause, - VersionedClause - ]; -} -def OMP_Assumes : Directive<"assumes"> {} -def OMP_BeginAssumes : Directive<"begin assumes"> {} -def OMP_EndAssumes : Directive<"end assumes"> {} -def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {} -def OMP_EndDeclareVariant : Directive<"end declare variant"> {} -def OMP_ParallelWorkshare : Directive<"parallel workshare"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_Workshare : Directive<"workshare"> {} -def OMP_EndDo : Directive<"end do"> {} -def OMP_EndDoSimd : Directive<"end do simd"> {} -def OMP_EndSections : Directive<"end sections"> { - let allowedOnceClauses = [ - VersionedClause - ]; -} -def OMP_EndSingle : Directive<"end single"> { - let allowedClauses = [ - VersionedClause - ]; - let allowedOnceClauses = [ - VersionedClause - ]; -} -def OMP_EndWorkshare : Directive<"end workshare"> { - let allowedClauses = [ - VersionedClause - ]; -} -def OMP_interop : Directive<"interop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_dispatch : Directive<"dispatch"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause - ]; -} -def OMP_masked : Directive<"masked"> { - let allowedOnceClauses = [ - VersionedClause - ]; -} -def OMP_loop : Directive<"loop"> { - let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - ]; - let allowedOnceClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - ]; -} -def OMP_Metadirective : Directive<"metadirective"> { - let allowedClauses = [VersionedClause]; - let allowedOnceClauses = [VersionedClause]; -} -def OMP_Unknown : Directive<"unknown"> { - let isDefault = true; -} diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPAssume.h b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPAssume.h deleted file mode 100644 index c7462ffe6b..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPAssume.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- OpenMP/OMPAssume.h --- OpenMP assumption helper functions - C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file provides helper functions and classes to deal with OpenMP -/// assumptions, e.g., as used by `[begin/end] assumes` and `assume`. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FRONTEND_OPENMP_OMPASSUME_H -#define LLVM_FRONTEND_OPENMP_OMPASSUME_H - -#include "llvm/ADT/StringRef.h" - -namespace llvm { - -namespace omp { - -/// Helper to describe assume clauses. -struct AssumptionClauseMappingInfo { - /// The identifier describing the (beginning of the) clause. - llvm::StringLiteral Identifier; - /// Flag to determine if the identifier is a full name or the start of a name. - bool StartsWith; - /// Flag to determine if a directive lists follows. - bool HasDirectiveList; - /// Flag to determine if an expression follows. - bool HasExpression; -}; - -/// All known assume clauses. -static constexpr AssumptionClauseMappingInfo AssumptionClauseMappings[] = { -#define OMP_ASSUME_CLAUSE(Identifier, StartsWith, HasDirectiveList, \ - HasExpression) \ - {Identifier, StartsWith, HasDirectiveList, HasExpression}, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -inline std::string getAllAssumeClauseOptions() { - std::string S; - for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) - S += (S.empty() ? "'" : "', '") + ACMI.Identifier.str(); - return S + "'"; -} - -} // namespace omp - -} // namespace llvm - -#endif // LLVM_FRONTEND_OPENMP_OMPASSUME_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPConstants.h b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPConstants.h deleted file mode 100644 index 695eca784f..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPConstants.h +++ /dev/null @@ -1,123 +0,0 @@ -//===- OMPConstants.h - OpenMP related constants and helpers ------ C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file defines constants and helpers used when dealing with OpenMP. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FRONTEND_OPENMP_OMPCONSTANTS_H -#define LLVM_FRONTEND_OPENMP_OMPCONSTANTS_H - -#include "llvm/ADT/BitmaskEnum.h" - -#include "llvm/ADT/StringRef.h" -#include "llvm/Frontend/OpenMP/OMP.h.inc" - -namespace llvm { -namespace omp { -LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); - -/// IDs for all Internal Control Variables (ICVs). -enum class InternalControlVar { -#define ICV_DATA_ENV(Enum, ...) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -#define ICV_DATA_ENV(Enum, ...) \ - constexpr auto Enum = omp::InternalControlVar::Enum; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - -enum class ICVInitValue { -#define ICV_INIT_VALUE(Enum, Name) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -#define ICV_INIT_VALUE(Enum, Name) \ - constexpr auto Enum = omp::ICVInitValue::Enum; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - -/// IDs for all omp runtime library (RTL) functions. -enum class RuntimeFunction { -#define OMP_RTL(Enum, ...) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -#define OMP_RTL(Enum, ...) constexpr auto Enum = omp::RuntimeFunction::Enum; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - -/// IDs for the different default kinds. -enum class DefaultKind { -#define OMP_DEFAULT_KIND(Enum, Str) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -#define OMP_DEFAULT_KIND(Enum, ...) \ - constexpr auto Enum = omp::DefaultKind::Enum; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - -/// IDs for all omp runtime library ident_t flag encodings (see -/// their definition in openmp/runtime/src/kmp.h). -enum class IdentFlag { -#define OMP_IDENT_FLAG(Enum, Str, Value) Enum = Value, -#include "llvm/Frontend/OpenMP/OMPKinds.def" - LLVM_MARK_AS_BITMASK_ENUM(0x7FFFFFFF) -}; - -#define OMP_IDENT_FLAG(Enum, ...) constexpr auto Enum = omp::IdentFlag::Enum; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - -/// \note This needs to be kept in sync with kmp.h enum sched_type. -/// Todo: Update kmp.h to include this file, and remove the enums in kmp.h -/// To complete this, more enum values will need to be moved here. -enum class OMPScheduleType { - StaticChunked = 33, - Static = 34, // static unspecialized - DistributeChunked = 91, - Distribute = 92, - DynamicChunked = 35, - GuidedChunked = 36, // guided unspecialized - Runtime = 37, - Auto = 38, // auto - - StaticBalancedChunked = 45, // static with chunk adjustment (e.g., simd) - GuidedSimd = 46, // guided with chunk adjustment - RuntimeSimd = 47, // runtime with chunk adjustment - - ModifierMonotonic = - (1 << 29), // Set if the monotonic schedule modifier was present - ModifierNonmonotonic = - (1 << 30), // Set if the nonmonotonic schedule modifier was present - ModifierMask = ModifierMonotonic | ModifierNonmonotonic, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue */ ModifierMask) -}; - -enum OMPTgtExecModeFlags : int8_t { - OMP_TGT_EXEC_MODE_GENERIC = 1 << 0, - OMP_TGT_EXEC_MODE_SPMD = 1 << 1, - OMP_TGT_EXEC_MODE_GENERIC_SPMD = - OMP_TGT_EXEC_MODE_GENERIC | OMP_TGT_EXEC_MODE_SPMD, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue */ OMP_TGT_EXEC_MODE_GENERIC_SPMD) -}; - -enum class AddressSpace : unsigned { - Generic = 0, - Global = 1, - Shared = 3, - Constant = 4, - Local = 5, -}; - -/// \note This needs to be kept in sync with interop.h enum kmp_interop_type_t.: -enum class OMPInteropType { Unknown, Target, TargetSync }; - -} // end namespace omp - -} // end namespace llvm - -#endif // LLVM_FRONTEND_OPENMP_OMPCONSTANTS_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPContext.h b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPContext.h deleted file mode 100644 index ca81b94b9c..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPContext.h +++ /dev/null @@ -1,210 +0,0 @@ -//===- OpenMP/OMPContext.h ----- OpenMP context helper functions - C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file provides helper functions and classes to deal with OpenMP -/// contexts as used by `[begin/end] declare variant` and `metadirective`. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FRONTEND_OPENMP_OMPCONTEXT_H -#define LLVM_FRONTEND_OPENMP_OMPCONTEXT_H - -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Frontend/OpenMP/OMPConstants.h" - -namespace llvm { -namespace omp { - -/// OpenMP Context related IDs and helpers -/// -///{ - -/// IDs for all OpenMP context selector trait sets (construct/device/...). -enum class TraitSet { -#define OMP_TRAIT_SET(Enum, ...) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -/// IDs for all OpenMP context selector trait (device={kind/isa...}/...). -enum class TraitSelector { -#define OMP_TRAIT_SELECTOR(Enum, ...) Enum, -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -/// IDs for all OpenMP context trait properties (host/gpu/bsc/llvm/...) -enum class TraitProperty { -#define OMP_TRAIT_PROPERTY(Enum, ...) Enum, -#define OMP_LAST_TRAIT_PROPERTY(Enum) Last = Enum -#include "llvm/Frontend/OpenMP/OMPKinds.def" -}; - -/// Parse \p Str and return the trait set it matches or TraitSet::invalid. -TraitSet getOpenMPContextTraitSetKind(StringRef Str); - -/// Return the trait set for which \p Selector is a selector. -TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); - -/// Return the trait set for which \p Property is a property. -TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); - -/// Return a textual representation of the trait set \p Kind. -StringRef getOpenMPContextTraitSetName(TraitSet Kind); - -/// Parse \p Str and return the trait set it matches or -/// TraitSelector::invalid. -TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str); - -/// Return the trait selector for which \p Property is a property. -TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property); - -/// Return a textual representation of the trait selector \p Kind. -StringRef getOpenMPContextTraitSelectorName(TraitSelector Kind); - -/// Parse \p Str and return the trait property it matches in the set \p Set and -/// selector \p Selector or TraitProperty::invalid. -TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, - TraitSelector Selector, - StringRef Str); - -/// Return the trait property for a singleton selector \p Selector. -TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector); - -/// Return a textual representation of the trait property \p Kind, which might -/// be the raw string we parsed (\p RawString) if we do not translate the -/// property into a (distinct) enum. -StringRef getOpenMPContextTraitPropertyName(TraitProperty Kind, - StringRef RawString); - -/// Return a textual representation of the trait property \p Kind with selector -/// and set name included. -StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); - -/// Return a string listing all trait sets. -std::string listOpenMPContextTraitSets(); - -/// Return a string listing all trait selectors for \p Set. -std::string listOpenMPContextTraitSelectors(TraitSet Set); - -/// Return a string listing all trait properties for \p Set and \p Selector. -std::string listOpenMPContextTraitProperties(TraitSet Set, - TraitSelector Selector); -///} - -/// Return true if \p Selector can be nested in \p Set. Also sets -/// \p AllowsTraitScore and \p RequiresProperty to true/false if the user can -/// specify a score for properties in \p Selector and if the \p Selector -/// requires at least one property. -bool isValidTraitSelectorForTraitSet(TraitSelector Selector, TraitSet Set, - bool &AllowsTraitScore, - bool &RequiresProperty); - -/// Return true if \p Property can be nested in \p Selector and \p Set. -bool isValidTraitPropertyForTraitSetAndSelector(TraitProperty Property, - TraitSelector Selector, - TraitSet Set); - -/// Variant match information describes the required traits and how they are -/// scored (via the ScoresMap). In addition, the required construct nesting is -/// described as well. -struct VariantMatchInfo { - /// Add the trait \p Property to the required trait set. \p RawString is the - /// string we parsed and derived \p Property from. If \p Score is not null, it - /// recorded as well. If \p Property is in the `construct` set it is recorded - /// in-order in the ConstructTraits as well. - void addTrait(TraitProperty Property, StringRef RawString, - APInt *Score = nullptr) { - addTrait(getOpenMPContextTraitSetForProperty(Property), Property, RawString, - Score); - } - /// Add the trait \p Property which is in set \p Set to the required trait - /// set. \p RawString is the string we parsed and derived \p Property from. If - /// \p Score is not null, it recorded as well. If \p Set is the `construct` - /// set it is recorded in-order in the ConstructTraits as well. - void addTrait(TraitSet Set, TraitProperty Property, StringRef RawString, - APInt *Score = nullptr) { - if (Score) - ScoreMap[Property] = *Score; - - // Special handling for `device={isa(...)}` as we do not match the enum but - // the raw string. - if (Property == TraitProperty::device_isa___ANY) - ISATraits.push_back(RawString); - - RequiredTraits.set(unsigned(Property)); - if (Set == TraitSet::construct) - ConstructTraits.push_back(Property); - } - - BitVector RequiredTraits = BitVector(unsigned(TraitProperty::Last) + 1); - SmallVector ISATraits; - SmallVector ConstructTraits; - SmallDenseMap ScoreMap; -}; - -/// The context for a source location is made up of active property traits, -/// e.g., device={kind(host)}, and constructs traits which describe the nesting -/// in OpenMP constructs at the location. -struct OMPContext { - OMPContext(bool IsDeviceCompilation, Triple TargetTriple); - virtual ~OMPContext() = default; - - void addTrait(TraitProperty Property) { - addTrait(getOpenMPContextTraitSetForProperty(Property), Property); - } - void addTrait(TraitSet Set, TraitProperty Property) { - ActiveTraits.set(unsigned(Property)); - if (Set == TraitSet::construct) - ConstructTraits.push_back(Property); - } - - /// Hook for users to check if an ISA trait matches. The trait is described as - /// the string that got parsed and it depends on the target and context if - /// this matches or not. - virtual bool matchesISATrait(StringRef) const { return false; } - - BitVector ActiveTraits = BitVector(unsigned(TraitProperty::Last) + 1); - SmallVector ConstructTraits; -}; - -/// Return true if \p VMI is applicable in \p Ctx, that is, all traits required -/// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is -/// true, only the device selector set, if present, are checked. Note that we -/// still honor extension traits provided by the user. -bool isVariantApplicableInContext(const VariantMatchInfo &VMI, - const OMPContext &Ctx, - bool DeviceSetOnly = false); - -/// Return the index (into \p VMIs) of the variant with the highest score -/// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext. -int getBestVariantMatchForContext(const SmallVectorImpl &VMIs, - const OMPContext &Ctx); - -} // namespace omp - -template <> struct DenseMapInfo { - static inline omp::TraitProperty getEmptyKey() { - return omp::TraitProperty(-1); - } - static inline omp::TraitProperty getTombstoneKey() { - return omp::TraitProperty(-2); - } - static unsigned getHashValue(omp::TraitProperty val) { - return std::hash{}(unsigned(val)); - } - static bool isEqual(omp::TraitProperty LHS, omp::TraitProperty RHS) { - return LHS == RHS; - } -}; - -} // end namespace llvm -#endif // LLVM_FRONTEND_OPENMP_OMPCONTEXT_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPGridValues.h b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPGridValues.h deleted file mode 100644 index 89f5de229b..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPGridValues.h +++ /dev/null @@ -1,120 +0,0 @@ -//====--- OMPGridValues.h - Language-specific address spaces --*- C++ -*-====// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Provides definitions for Target specific Grid Values -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FRONTEND_OPENMP_OMPGRIDVALUES_H -#define LLVM_FRONTEND_OPENMP_OMPGRIDVALUES_H - -namespace llvm { - -namespace omp { - -/// \brief Defines various target-specific GPU grid values that must be -/// consistent between host RTL (plugin), device RTL, and clang. -/// We can change grid values for a "fat" binary so that different -/// passes get the correct values when generating code for a -/// multi-target binary. Both amdgcn and nvptx values are stored in -/// this file. In the future, should there be differences between GPUs -/// of the same architecture, then simply make a different array and -/// use the new array name. -/// -/// Example usage in clang: -/// const unsigned slot_size = -/// ctx.GetTargetInfo().getGridValue().GV_Warp_Size; -/// -/// Example usage in libomptarget/deviceRTLs: -/// #include "llvm/Frontend/OpenMP/OMPGridValues.h" -/// #ifdef __AMDGPU__ -/// #define GRIDVAL AMDGPUGridValues -/// #else -/// #define GRIDVAL NVPTXGridValues -/// #endif -/// ... Then use this reference for GV_Warp_Size in the deviceRTL source. -/// llvm::omp::GRIDVAL().GV_Warp_Size -/// -/// Example usage in libomptarget hsa plugin: -/// #include "llvm/Frontend/OpenMP/OMPGridValues.h" -/// #define GRIDVAL AMDGPUGridValues -/// ... Then use this reference to access GV_Warp_Size in the hsa plugin. -/// llvm::omp::GRIDVAL().GV_Warp_Size -/// -/// Example usage in libomptarget cuda plugin: -/// #include "llvm/Frontend/OpenMP/OMPGridValues.h" -/// #define GRIDVAL NVPTXGridValues -/// ... Then use this reference to access GV_Warp_Size in the cuda plugin. -/// llvm::omp::GRIDVAL().GV_Warp_Size -/// - -struct GV { - /// The size reserved for data in a shared memory slot. - const unsigned GV_Slot_Size; - /// The default value of maximum number of threads in a worker warp. - const unsigned GV_Warp_Size; - - constexpr unsigned warpSlotSize() const { - return GV_Warp_Size * GV_Slot_Size; - } - - /// the maximum number of teams. - const unsigned GV_Max_Teams; - // An alternative to the heavy data sharing infrastructure that uses global - // memory is one that uses device __shared__ memory. The amount of such space - // (in bytes) reserved by the OpenMP runtime is noted here. - const unsigned GV_SimpleBufferSize; - // The absolute maximum team size for a working group - const unsigned GV_Max_WG_Size; - // The default maximum team size for a working group - const unsigned GV_Default_WG_Size; - - constexpr unsigned maxWarpNumber() const { - return GV_Max_WG_Size / GV_Warp_Size; - } -}; - -/// For AMDGPU GPUs -static constexpr GV AMDGPUGridValues64 = { - 256, // GV_Slot_Size - 64, // GV_Warp_Size - 128, // GV_Max_Teams - 896, // GV_SimpleBufferSize - 1024, // GV_Max_WG_Size, - 256, // GV_Default_WG_Size -}; - -static constexpr GV AMDGPUGridValues32 = { - 256, // GV_Slot_Size - 32, // GV_Warp_Size - 128, // GV_Max_Teams - 896, // GV_SimpleBufferSize - 1024, // GV_Max_WG_Size, - 256, // GV_Default_WG_Size -}; - -template constexpr const GV &getAMDGPUGridValues() { - static_assert(wavesize == 32 || wavesize == 64, ""); - return wavesize == 32 ? AMDGPUGridValues32 : AMDGPUGridValues64; -} - -/// For Nvidia GPUs -static constexpr GV NVPTXGridValues = { - 256, // GV_Slot_Size - 32, // GV_Warp_Size - 1024, // GV_Max_Teams - 896, // GV_SimpleBufferSize - 1024, // GV_Max_WG_Size - 128, // GV_Default_WG_Size -}; - -} // namespace omp -} // namespace llvm - -#endif // LLVM_FRONTEND_OPENMP_OMPGRIDVALUES_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPIRBuilder.h deleted file mode 100644 index dd3e197b3c..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ /dev/null @@ -1,1606 +0,0 @@ -//===- IR/OpenMPIRBuilder.h - OpenMP encoding builder for LLVM IR - C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the OpenMPIRBuilder class and helpers used as a convenient -// way to create LLVM instructions for OpenMP directives. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FRONTEND_OPENMP_OMPIRBUILDER_H -#define LLVM_FRONTEND_OPENMP_OMPIRBUILDER_H - -#include "llvm/Frontend/OpenMP/OMPConstants.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/Support/Allocator.h" -#include - -namespace llvm { -class CanonicalLoopInfo; - -/// An interface to create LLVM-IR for OpenMP directives. -/// -/// Each OpenMP directive has a corresponding public generator method. -class OpenMPIRBuilder { -public: - /// Create a new OpenMPIRBuilder operating on the given module \p M. This will - /// not have an effect on \p M (see initialize). - OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {} - ~OpenMPIRBuilder(); - - /// Initialize the internal state, this will put structures types and - /// potentially other helpers into the underlying module. Must be called - /// before any other method and only once! - void initialize(); - - /// Finalize the underlying module, e.g., by outlining regions. - /// \param Fn The function to be finalized. If not used, - /// all functions are finalized. - void finalize(Function *Fn = nullptr); - - /// Add attributes known for \p FnID to \p Fn. - void addAttributes(omp::RuntimeFunction FnID, Function &Fn); - - /// Type used throughout for insertion points. - using InsertPointTy = IRBuilder<>::InsertPoint; - - /// Callback type for variable finalization (think destructors). - /// - /// \param CodeGenIP is the insertion point at which the finalization code - /// should be placed. - /// - /// A finalize callback knows about all objects that need finalization, e.g. - /// destruction, when the scope of the currently generated construct is left - /// at the time, and location, the callback is invoked. - using FinalizeCallbackTy = std::function; - - struct FinalizationInfo { - /// The finalization callback provided by the last in-flight invocation of - /// createXXXX for the directive of kind DK. - FinalizeCallbackTy FiniCB; - - /// The directive kind of the innermost directive that has an associated - /// region which might require finalization when it is left. - omp::Directive DK; - - /// Flag to indicate if the directive is cancellable. - bool IsCancellable; - }; - - /// Push a finalization callback on the finalization stack. - /// - /// NOTE: Temporary solution until Clang CG is gone. - void pushFinalizationCB(const FinalizationInfo &FI) { - FinalizationStack.push_back(FI); - } - - /// Pop the last finalization callback from the finalization stack. - /// - /// NOTE: Temporary solution until Clang CG is gone. - void popFinalizationCB() { FinalizationStack.pop_back(); } - - /// Callback type for body (=inner region) code generation - /// - /// The callback takes code locations as arguments, each describing a - /// location at which code might need to be generated or a location that is - /// the target of control transfer. - /// - /// \param AllocaIP is the insertion point at which new alloca instructions - /// should be placed. - /// \param CodeGenIP is the insertion point at which the body code should be - /// placed. - /// \param ContinuationBB is the basic block target to leave the body. - /// - /// Note that all blocks pointed to by the arguments have terminators. - using BodyGenCallbackTy = - function_ref; - - // This is created primarily for sections construct as llvm::function_ref - // (BodyGenCallbackTy) is not storable (as described in the comments of - // function_ref class - function_ref contains non-ownable reference - // to the callable. - using StorableBodyGenCallbackTy = - std::function; - - /// Callback type for loop body code generation. - /// - /// \param CodeGenIP is the insertion point where the loop's body code must be - /// placed. This will be a dedicated BasicBlock with a - /// conditional branch from the loop condition check and - /// terminated with an unconditional branch to the loop - /// latch. - /// \param IndVar is the induction variable usable at the insertion point. - using LoopBodyGenCallbackTy = - function_ref; - - /// Callback type for variable privatization (think copy & default - /// constructor). - /// - /// \param AllocaIP is the insertion point at which new alloca instructions - /// should be placed. - /// \param CodeGenIP is the insertion point at which the privatization code - /// should be placed. - /// \param Original The value being copied/created, should not be used in the - /// generated IR. - /// \param Inner The equivalent of \p Original that should be used in the - /// generated IR; this is equal to \p Original if the value is - /// a pointer and can thus be passed directly, otherwise it is - /// an equivalent but different value. - /// \param ReplVal The replacement value, thus a copy or new created version - /// of \p Inner. - /// - /// \returns The new insertion point where code generation continues and - /// \p ReplVal the replacement value. - using PrivatizeCallbackTy = function_ref; - - /// Description of a LLVM-IR insertion point (IP) and a debug/source location - /// (filename, line, column, ...). - struct LocationDescription { - template - LocationDescription(const IRBuilder &IRB) - : IP(IRB.saveIP()), DL(IRB.getCurrentDebugLocation()) {} - LocationDescription(const InsertPointTy &IP) : IP(IP) {} - LocationDescription(const InsertPointTy &IP, const DebugLoc &DL) - : IP(IP), DL(DL) {} - InsertPointTy IP; - DebugLoc DL; - }; - - /// Emitter methods for OpenMP directives. - /// - ///{ - - /// Generator for '#omp barrier' - /// - /// \param Loc The location where the barrier directive was encountered. - /// \param DK The kind of directive that caused the barrier. - /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. - /// \param CheckCancelFlag Flag to indicate a cancel barrier return value - /// should be checked and acted upon. - /// - /// \returns The insertion point after the barrier. - InsertPointTy createBarrier(const LocationDescription &Loc, omp::Directive DK, - bool ForceSimpleCall = false, - bool CheckCancelFlag = true); - - /// Generator for '#omp cancel' - /// - /// \param Loc The location where the directive was encountered. - /// \param IfCondition The evaluated 'if' clause expression, if any. - /// \param CanceledDirective The kind of directive that is canceled. - /// - /// \returns The insertion point after the barrier. - InsertPointTy createCancel(const LocationDescription &Loc, Value *IfCondition, - omp::Directive CanceledDirective); - - /// Generator for '#omp parallel' - /// - /// \param Loc The insert and source location description. - /// \param AllocaIP The insertion points to be used for alloca instructions. - /// \param BodyGenCB Callback that will generate the region code. - /// \param PrivCB Callback to copy a given variable (think copy constructor). - /// \param FiniCB Callback to finalize variable copies. - /// \param IfCondition The evaluated 'if' clause expression, if any. - /// \param NumThreads The evaluated 'num_threads' clause expression, if any. - /// \param ProcBind The value of the 'proc_bind' clause (see ProcBindKind). - /// \param IsCancellable Flag to indicate a cancellable parallel region. - /// - /// \returns The insertion position *after* the parallel. - IRBuilder<>::InsertPoint - createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, - BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, - FinalizeCallbackTy FiniCB, Value *IfCondition, - Value *NumThreads, omp::ProcBindKind ProcBind, - bool IsCancellable); - - /// Generator for the control flow structure of an OpenMP canonical loop. - /// - /// This generator operates on the logical iteration space of the loop, i.e. - /// the caller only has to provide a loop trip count of the loop as defined by - /// base language semantics. The trip count is interpreted as an unsigned - /// integer. The induction variable passed to \p BodyGenCB will be of the same - /// type and run from 0 to \p TripCount - 1. It is up to the callback to - /// convert the logical iteration variable to the loop counter variable in the - /// loop body. - /// - /// \param Loc The insert and source location description. The insert - /// location can be between two instructions or the end of a - /// degenerate block (e.g. a BB under construction). - /// \param BodyGenCB Callback that will generate the loop body code. - /// \param TripCount Number of iterations the loop body is executed. - /// \param Name Base name used to derive BB and instruction names. - /// - /// \returns An object representing the created control flow structure which - /// can be used for loop-associated directives. - CanonicalLoopInfo *createCanonicalLoop(const LocationDescription &Loc, - LoopBodyGenCallbackTy BodyGenCB, - Value *TripCount, - const Twine &Name = "loop"); - - /// Generator for the control flow structure of an OpenMP canonical loop. - /// - /// Instead of a logical iteration space, this allows specifying user-defined - /// loop counter values using increment, upper- and lower bounds. To - /// disambiguate the terminology when counting downwards, instead of lower - /// bounds we use \p Start for the loop counter value in the first body - /// iteration. - /// - /// Consider the following limitations: - /// - /// * A loop counter space over all integer values of its bit-width cannot be - /// represented. E.g using uint8_t, its loop trip count of 256 cannot be - /// stored into an 8 bit integer): - /// - /// DO I = 0, 255, 1 - /// - /// * Unsigned wrapping is only supported when wrapping only "once"; E.g. - /// effectively counting downwards: - /// - /// for (uint8_t i = 100u; i > 0; i += 127u) - /// - /// - /// TODO: May need to add additional parameters to represent: - /// - /// * Allow representing downcounting with unsigned integers. - /// - /// * Sign of the step and the comparison operator might disagree: - /// - /// for (int i = 0; i < 42; i -= 1u) - /// - // - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the loop body code. - /// \param Start Value of the loop counter for the first iterations. - /// \param Stop Loop counter values past this will stop the loop. - /// \param Step Loop counter increment after each iteration; negative - /// means counting down. - /// \param IsSigned Whether Start, Stop and Step are signed integers. - /// \param InclusiveStop Whether \p Stop itself is a valid value for the loop - /// counter. - /// \param ComputeIP Insertion point for instructions computing the trip - /// count. Can be used to ensure the trip count is available - /// at the outermost loop of a loop nest. If not set, - /// defaults to the preheader of the generated loop. - /// \param Name Base name used to derive BB and instruction names. - /// - /// \returns An object representing the created control flow structure which - /// can be used for loop-associated directives. - CanonicalLoopInfo *createCanonicalLoop(const LocationDescription &Loc, - LoopBodyGenCallbackTy BodyGenCB, - Value *Start, Value *Stop, Value *Step, - bool IsSigned, bool InclusiveStop, - InsertPointTy ComputeIP = {}, - const Twine &Name = "loop"); - - /// Collapse a loop nest into a single loop. - /// - /// Merges loops of a loop nest into a single CanonicalLoopNest representation - /// that has the same number of innermost loop iterations as the origin loop - /// nest. The induction variables of the input loops are derived from the - /// collapsed loop's induction variable. This is intended to be used to - /// implement OpenMP's collapse clause. Before applying a directive, - /// collapseLoops normalizes a loop nest to contain only a single loop and the - /// directive's implementation does not need to handle multiple loops itself. - /// This does not remove the need to handle all loop nest handling by - /// directives, such as the ordered() clause or the simd schedule-clause - /// modifier of the worksharing-loop directive. - /// - /// Example: - /// \code - /// for (int i = 0; i < 7; ++i) // Canonical loop "i" - /// for (int j = 0; j < 9; ++j) // Canonical loop "j" - /// body(i, j); - /// \endcode - /// - /// After collapsing with Loops={i,j}, the loop is changed to - /// \code - /// for (int ij = 0; ij < 63; ++ij) { - /// int i = ij / 9; - /// int j = ij % 9; - /// body(i, j); - /// } - /// \endcode - /// - /// In the current implementation, the following limitations apply: - /// - /// * All input loops have an induction variable of the same type. - /// - /// * The collapsed loop will have the same trip count integer type as the - /// input loops. Therefore it is possible that the collapsed loop cannot - /// represent all iterations of the input loops. For instance, assuming a - /// 32 bit integer type, and two input loops both iterating 2^16 times, the - /// theoretical trip count of the collapsed loop would be 2^32 iteration, - /// which cannot be represented in an 32-bit integer. Behavior is undefined - /// in this case. - /// - /// * The trip counts of every input loop must be available at \p ComputeIP. - /// Non-rectangular loops are not yet supported. - /// - /// * At each nest level, code between a surrounding loop and its nested loop - /// is hoisted into the loop body, and such code will be executed more - /// often than before collapsing (or not at all if any inner loop iteration - /// has a trip count of 0). This is permitted by the OpenMP specification. - /// - /// \param DL Debug location for instructions added for collapsing, - /// such as instructions to compute/derive the input loop's - /// induction variables. - /// \param Loops Loops in the loop nest to collapse. Loops are specified - /// from outermost-to-innermost and every control flow of a - /// loop's body must pass through its directly nested loop. - /// \param ComputeIP Where additional instruction that compute the collapsed - /// trip count. If not set, defaults to before the generated - /// loop. - /// - /// \returns The CanonicalLoopInfo object representing the collapsed loop. - CanonicalLoopInfo *collapseLoops(DebugLoc DL, - ArrayRef Loops, - InsertPointTy ComputeIP); - - /// Modifies the canonical loop to be a statically-scheduled workshare loop. - /// - /// This takes a \p LoopInfo representing a canonical loop, such as the one - /// created by \p createCanonicalLoop and emits additional instructions to - /// turn it into a workshare loop. In particular, it calls to an OpenMP - /// runtime function in the preheader to obtain the loop bounds to be used in - /// the current thread, updates the relevant instructions in the canonical - /// loop and calls to an OpenMP runtime finalization function after the loop. - /// - /// TODO: Workshare loops with static scheduling may contain up to two loops - /// that fulfill the requirements of an OpenMP canonical loop. One for - /// iterating over all iterations of a chunk and another one for iterating - /// over all chunks that are executed on the same thread. Returning - /// CanonicalLoopInfo objects representing them may eventually be useful for - /// the apply clause planned in OpenMP 6.0, but currently whether these are - /// canonical loops is irrelevant. - /// - /// \param DL Debug location for instructions added for the - /// workshare-loop construct itself. - /// \param CLI A descriptor of the canonical loop to workshare. - /// \param AllocaIP An insertion point for Alloca instructions usable in the - /// preheader of the loop. - /// \param NeedsBarrier Indicates whether a barrier must be inserted after - /// the loop. - /// \param Chunk The size of loop chunk considered as a unit when - /// scheduling. If \p nullptr, defaults to 1. - /// - /// \returns Point where to insert code after the workshare construct. - InsertPointTy applyStaticWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, - InsertPointTy AllocaIP, - bool NeedsBarrier, - Value *Chunk = nullptr); - - /// Modifies the canonical loop to be a dynamically-scheduled workshare loop. - /// - /// This takes a \p LoopInfo representing a canonical loop, such as the one - /// created by \p createCanonicalLoop and emits additional instructions to - /// turn it into a workshare loop. In particular, it calls to an OpenMP - /// runtime function in the preheader to obtain, and then in each iteration - /// to update the loop counter. - /// - /// \param DL Debug location for instructions added for the - /// workshare-loop construct itself. - /// \param CLI A descriptor of the canonical loop to workshare. - /// \param AllocaIP An insertion point for Alloca instructions usable in the - /// preheader of the loop. - /// \param SchedType Type of scheduling to be passed to the init function. - /// \param NeedsBarrier Indicates whether a barrier must be inserted after - /// the loop. - /// \param Chunk The size of loop chunk considered as a unit when - /// scheduling. If \p nullptr, defaults to 1. - /// - /// \returns Point where to insert code after the workshare construct. - InsertPointTy applyDynamicWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, - InsertPointTy AllocaIP, - omp::OMPScheduleType SchedType, - bool NeedsBarrier, - Value *Chunk = nullptr); - - /// Modifies the canonical loop to be a workshare loop. - /// - /// This takes a \p LoopInfo representing a canonical loop, such as the one - /// created by \p createCanonicalLoop and emits additional instructions to - /// turn it into a workshare loop. In particular, it calls to an OpenMP - /// runtime function in the preheader to obtain the loop bounds to be used in - /// the current thread, updates the relevant instructions in the canonical - /// loop and calls to an OpenMP runtime finalization function after the loop. - /// - /// \param DL Debug location for instructions added for the - /// workshare-loop construct itself. - /// \param CLI A descriptor of the canonical loop to workshare. - /// \param AllocaIP An insertion point for Alloca instructions usable in the - /// preheader of the loop. - /// \param NeedsBarrier Indicates whether a barrier must be inserted after - /// the loop. - /// - /// \returns Point where to insert code after the workshare construct. - InsertPointTy applyWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, - InsertPointTy AllocaIP, bool NeedsBarrier); - - /// Tile a loop nest. - /// - /// Tiles the loops of \p Loops by the tile sizes in \p TileSizes. Loops in - /// \p/ Loops must be perfectly nested, from outermost to innermost loop - /// (i.e. Loops.front() is the outermost loop). The trip count llvm::Value - /// of every loop and every tile sizes must be usable in the outermost - /// loop's preheader. This implies that the loop nest is rectangular. - /// - /// Example: - /// \code - /// for (int i = 0; i < 15; ++i) // Canonical loop "i" - /// for (int j = 0; j < 14; ++j) // Canonical loop "j" - /// body(i, j); - /// \endcode - /// - /// After tiling with Loops={i,j} and TileSizes={5,7}, the loop is changed to - /// \code - /// for (int i1 = 0; i1 < 3; ++i1) - /// for (int j1 = 0; j1 < 2; ++j1) - /// for (int i2 = 0; i2 < 5; ++i2) - /// for (int j2 = 0; j2 < 7; ++j2) - /// body(i1*3+i2, j1*3+j2); - /// \endcode - /// - /// The returned vector are the loops {i1,j1,i2,j2}. The loops i1 and j1 are - /// referred to the floor, and the loops i2 and j2 are the tiles. Tiling also - /// handles non-constant trip counts, non-constant tile sizes and trip counts - /// that are not multiples of the tile size. In the latter case the tile loop - /// of the last floor-loop iteration will have fewer iterations than specified - /// as its tile size. - /// - /// - /// @param DL Debug location for instructions added by tiling, for - /// instance the floor- and tile trip count computation. - /// @param Loops Loops to tile. The CanonicalLoopInfo objects are - /// invalidated by this method, i.e. should not used after - /// tiling. - /// @param TileSizes For each loop in \p Loops, the tile size for that - /// dimensions. - /// - /// \returns A list of generated loops. Contains twice as many loops as the - /// input loop nest; the first half are the floor loops and the - /// second half are the tile loops. - std::vector - tileLoops(DebugLoc DL, ArrayRef Loops, - ArrayRef TileSizes); - - /// Fully unroll a loop. - /// - /// Instead of unrolling the loop immediately (and duplicating its body - /// instructions), it is deferred to LLVM's LoopUnrollPass by adding loop - /// metadata. - /// - /// \param DL Debug location for instructions added by unrolling. - /// \param Loop The loop to unroll. The loop will be invalidated. - void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop); - - /// Fully or partially unroll a loop. How the loop is unrolled is determined - /// using LLVM's LoopUnrollPass. - /// - /// \param DL Debug location for instructions added by unrolling. - /// \param Loop The loop to unroll. The loop will be invalidated. - void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop); - - /// Partially unroll a loop. - /// - /// The CanonicalLoopInfo of the unrolled loop for use with chained - /// loop-associated directive can be requested using \p UnrolledCLI. Not - /// needing the CanonicalLoopInfo allows more efficient code generation by - /// deferring the actual unrolling to the LoopUnrollPass using loop metadata. - /// A loop-associated directive applied to the unrolled loop needs to know the - /// new trip count which means that if using a heuristically determined unroll - /// factor (\p Factor == 0), that factor must be computed immediately. We are - /// using the same logic as the LoopUnrollPass to derived the unroll factor, - /// but which assumes that some canonicalization has taken place (e.g. - /// Mem2Reg, LICM, GVN, Inlining, etc.). That is, the heuristic will perform - /// better when the unrolled loop's CanonicalLoopInfo is not needed. - /// - /// \param DL Debug location for instructions added by unrolling. - /// \param Loop The loop to unroll. The loop will be invalidated. - /// \param Factor The factor to unroll the loop by. A factor of 0 - /// indicates that a heuristic should be used to determine - /// the unroll-factor. - /// \param UnrolledCLI If non-null, receives the CanonicalLoopInfo of the - /// partially unrolled loop. Otherwise, uses loop metadata - /// to defer unrolling to the LoopUnrollPass. - void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, - CanonicalLoopInfo **UnrolledCLI); - - /// Add metadata to simd-ize a loop. - /// - /// \param DL Debug location for instructions added by unrolling. - /// \param Loop The loop to simd-ize. - void applySimd(DebugLoc DL, CanonicalLoopInfo *Loop); - - /// Generator for '#omp flush' - /// - /// \param Loc The location where the flush directive was encountered - void createFlush(const LocationDescription &Loc); - - /// Generator for '#omp taskwait' - /// - /// \param Loc The location where the taskwait directive was encountered. - void createTaskwait(const LocationDescription &Loc); - - /// Generator for '#omp taskyield' - /// - /// \param Loc The location where the taskyield directive was encountered. - void createTaskyield(const LocationDescription &Loc); - - /// Functions used to generate reductions. Such functions take two Values - /// representing LHS and RHS of the reduction, respectively, and a reference - /// to the value that is updated to refer to the reduction result. - using ReductionGenTy = - function_ref; - - /// Functions used to generate atomic reductions. Such functions take two - /// Values representing pointers to LHS and RHS of the reduction, as well as - /// the element type of these pointers. They are expected to atomically - /// update the LHS to the reduced value. - using AtomicReductionGenTy = - function_ref; - - /// Information about an OpenMP reduction. - struct ReductionInfo { - ReductionInfo(Type *ElementType, Value *Variable, Value *PrivateVariable, - ReductionGenTy ReductionGen, - AtomicReductionGenTy AtomicReductionGen) - : ElementType(ElementType), Variable(Variable), - PrivateVariable(PrivateVariable), ReductionGen(ReductionGen), - AtomicReductionGen(AtomicReductionGen) { - assert(cast(Variable->getType()) - ->isOpaqueOrPointeeTypeMatches(ElementType) && "Invalid elem type"); - } - - /// Reduction element type, must match pointee type of variable. - Type *ElementType; - - /// Reduction variable of pointer type. - Value *Variable; - - /// Thread-private partial reduction variable. - Value *PrivateVariable; - - /// Callback for generating the reduction body. The IR produced by this will - /// be used to combine two values in a thread-safe context, e.g., under - /// lock or within the same thread, and therefore need not be atomic. - ReductionGenTy ReductionGen; - - /// Callback for generating the atomic reduction body, may be null. The IR - /// produced by this will be used to atomically combine two values during - /// reduction. If null, the implementation will use the non-atomic version - /// along with the appropriate synchronization mechanisms. - AtomicReductionGenTy AtomicReductionGen; - }; - - // TODO: provide atomic and non-atomic reduction generators for reduction - // operators defined by the OpenMP specification. - - /// Generator for '#omp reduction'. - /// - /// Emits the IR instructing the runtime to perform the specific kind of - /// reductions. Expects reduction variables to have been privatized and - /// initialized to reduction-neutral values separately. Emits the calls to - /// runtime functions as well as the reduction function and the basic blocks - /// performing the reduction atomically and non-atomically. - /// - /// The code emitted for the following: - /// - /// \code - /// type var_1; - /// type var_2; - /// #pragma omp reduction(reduction-op:var_1,var_2) - /// /* body */; - /// \endcode - /// - /// corresponds to the following sketch. - /// - /// \code - /// void _outlined_par() { - /// // N is the number of different reductions. - /// void *red_array[] = {privatized_var_1, privatized_var_2, ...}; - /// switch(__kmpc_reduce(..., N, /*size of data in red array*/, red_array, - /// _omp_reduction_func, - /// _gomp_critical_user.reduction.var)) { - /// case 1: { - /// var_1 = var_1 privatized_var_1; - /// var_2 = var_2 privatized_var_2; - /// // ... - /// __kmpc_end_reduce(...); - /// break; - /// } - /// case 2: { - /// _Atomic(var_1, privatized_var_1); - /// _Atomic(var_2, privatized_var_2); - /// // ... - /// break; - /// } - /// default: break; - /// } - /// } - /// - /// void _omp_reduction_func(void **lhs, void **rhs) { - /// *(type *)lhs[0] = *(type *)lhs[0] *(type *)rhs[0]; - /// *(type *)lhs[1] = *(type *)lhs[1] *(type *)rhs[1]; - /// // ... - /// } - /// \endcode - /// - /// \param Loc The location where the reduction was - /// encountered. Must be within the associate - /// directive and after the last local access to the - /// reduction variables. - /// \param AllocaIP An insertion point suitable for allocas usable - /// in reductions. - /// \param ReductionInfos A list of info on each reduction variable. - /// \param IsNoWait A flag set if the reduction is marked as nowait. - InsertPointTy createReductions(const LocationDescription &Loc, - InsertPointTy AllocaIP, - ArrayRef ReductionInfos, - bool IsNoWait = false); - - ///} - - /// Return the insertion point used by the underlying IRBuilder. - InsertPointTy getInsertionPoint() { return Builder.saveIP(); } - - /// Update the internal location to \p Loc. - bool updateToLocation(const LocationDescription &Loc) { - Builder.restoreIP(Loc.IP); - Builder.SetCurrentDebugLocation(Loc.DL); - return Loc.IP.getBlock() != nullptr; - } - - /// Return the function declaration for the runtime function with \p FnID. - FunctionCallee getOrCreateRuntimeFunction(Module &M, - omp::RuntimeFunction FnID); - - Function *getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID); - - /// Return the (LLVM-IR) string describing the source location \p LocStr. - Constant *getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize); - - /// Return the (LLVM-IR) string describing the default source location. - Constant *getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize); - - /// Return the (LLVM-IR) string describing the source location identified by - /// the arguments. - Constant *getOrCreateSrcLocStr(StringRef FunctionName, StringRef FileName, - unsigned Line, unsigned Column, - uint32_t &SrcLocStrSize); - - /// Return the (LLVM-IR) string describing the DebugLoc \p DL. Use \p F as - /// fallback if \p DL does not specify the function name. - Constant *getOrCreateSrcLocStr(DebugLoc DL, uint32_t &SrcLocStrSize, - Function *F = nullptr); - - /// Return the (LLVM-IR) string describing the source location \p Loc. - Constant *getOrCreateSrcLocStr(const LocationDescription &Loc, - uint32_t &SrcLocStrSize); - - /// Return an ident_t* encoding the source location \p SrcLocStr and \p Flags. - /// TODO: Create a enum class for the Reserve2Flags - Constant *getOrCreateIdent(Constant *SrcLocStr, uint32_t SrcLocStrSize, - omp::IdentFlag Flags = omp::IdentFlag(0), - unsigned Reserve2Flags = 0); - - /// Create a hidden global flag \p Name in the module with initial value \p - /// Value. - GlobalValue *createGlobalFlag(unsigned Value, StringRef Name); - - /// Generate control flow and cleanup for cancellation. - /// - /// \param CancelFlag Flag indicating if the cancellation is performed. - /// \param CanceledDirective The kind of directive that is canceled. - /// \param ExitCB Extra code to be generated in the exit block. - void emitCancelationCheckImpl(Value *CancelFlag, - omp::Directive CanceledDirective, - FinalizeCallbackTy ExitCB = {}); - - /// Generate a barrier runtime call. - /// - /// \param Loc The location at which the request originated and is fulfilled. - /// \param DK The directive which caused the barrier - /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. - /// \param CheckCancelFlag Flag to indicate a cancel barrier return value - /// should be checked and acted upon. - /// - /// \returns The insertion point after the barrier. - InsertPointTy emitBarrierImpl(const LocationDescription &Loc, - omp::Directive DK, bool ForceSimpleCall, - bool CheckCancelFlag); - - /// Generate a flush runtime call. - /// - /// \param Loc The location at which the request originated and is fulfilled. - void emitFlush(const LocationDescription &Loc); - - /// The finalization stack made up of finalize callbacks currently in-flight, - /// wrapped into FinalizationInfo objects that reference also the finalization - /// target block and the kind of cancellable directive. - SmallVector FinalizationStack; - - /// Return true if the last entry in the finalization stack is of kind \p DK - /// and cancellable. - bool isLastFinalizationInfoCancellable(omp::Directive DK) { - return !FinalizationStack.empty() && - FinalizationStack.back().IsCancellable && - FinalizationStack.back().DK == DK; - } - - /// Generate a taskwait runtime call. - /// - /// \param Loc The location at which the request originated and is fulfilled. - void emitTaskwaitImpl(const LocationDescription &Loc); - - /// Generate a taskyield runtime call. - /// - /// \param Loc The location at which the request originated and is fulfilled. - void emitTaskyieldImpl(const LocationDescription &Loc); - - /// Return the current thread ID. - /// - /// \param Ident The ident (ident_t*) describing the query origin. - Value *getOrCreateThreadID(Value *Ident); - - /// The underlying LLVM-IR module - Module &M; - - /// The LLVM-IR Builder used to create IR. - IRBuilder<> Builder; - - /// Map to remember source location strings - StringMap SrcLocStrMap; - - /// Map to remember existing ident_t*. - DenseMap, Constant *> IdentMap; - - /// Helper that contains information about regions we need to outline - /// during finalization. - struct OutlineInfo { - using PostOutlineCBTy = std::function; - PostOutlineCBTy PostOutlineCB; - BasicBlock *EntryBB, *ExitBB; - SmallVector ExcludeArgsFromAggregate; - - /// Collect all blocks in between EntryBB and ExitBB in both the given - /// vector and set. - void collectBlocks(SmallPtrSetImpl &BlockSet, - SmallVectorImpl &BlockVector); - - /// Return the function that contains the region to be outlined. - Function *getFunction() const { return EntryBB->getParent(); } - }; - - /// Collection of regions that need to be outlined during finalization. - SmallVector OutlineInfos; - - /// Collection of owned canonical loop objects that eventually need to be - /// free'd. - std::forward_list LoopInfos; - - /// Add a new region that will be outlined later. - void addOutlineInfo(OutlineInfo &&OI) { OutlineInfos.emplace_back(OI); } - - /// An ordered map of auto-generated variables to their unique names. - /// It stores variables with the following names: 1) ".gomp_critical_user_" + - /// + ".var" for "omp critical" directives; 2) - /// + ".cache." for cache for threadprivate - /// variables. - StringMap, BumpPtrAllocator> InternalVars; - - /// Create the global variable holding the offload mappings information. - GlobalVariable *createOffloadMaptypes(SmallVectorImpl &Mappings, - std::string VarName); - - /// Create the global variable holding the offload names information. - GlobalVariable * - createOffloadMapnames(SmallVectorImpl &Names, - std::string VarName); - - struct MapperAllocas { - AllocaInst *ArgsBase = nullptr; - AllocaInst *Args = nullptr; - AllocaInst *ArgSizes = nullptr; - }; - - /// Create the allocas instruction used in call to mapper functions. - void createMapperAllocas(const LocationDescription &Loc, - InsertPointTy AllocaIP, unsigned NumOperands, - struct MapperAllocas &MapperAllocas); - - /// Create the call for the target mapper function. - /// \param Loc The source location description. - /// \param MapperFunc Function to be called. - /// \param SrcLocInfo Source location information global. - /// \param MaptypesArg The argument types. - /// \param MapnamesArg The argument names. - /// \param MapperAllocas The AllocaInst used for the call. - /// \param DeviceID Device ID for the call. - /// \param NumOperands Number of operands in the call. - void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, - Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, - struct MapperAllocas &MapperAllocas, int64_t DeviceID, - unsigned NumOperands); - -public: - /// Generator for __kmpc_copyprivate - /// - /// \param Loc The source location description. - /// \param BufSize Number of elements in the buffer. - /// \param CpyBuf List of pointers to data to be copied. - /// \param CpyFn function to call for copying data. - /// \param DidIt flag variable; 1 for 'single' thread, 0 otherwise. - /// - /// \return The insertion position *after* the CopyPrivate call. - - InsertPointTy createCopyPrivate(const LocationDescription &Loc, - llvm::Value *BufSize, llvm::Value *CpyBuf, - llvm::Value *CpyFn, llvm::Value *DidIt); - - /// Generator for '#omp single' - /// - /// \param Loc The source location description. - /// \param BodyGenCB Callback that will generate the region code. - /// \param FiniCB Callback to finalize variable copies. - /// \param DidIt Local variable used as a flag to indicate 'single' thread - /// - /// \returns The insertion position *after* the single call. - InsertPointTy createSingle(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB, llvm::Value *DidIt); - - /// Generator for '#omp master' - /// - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the region code. - /// \param FiniCB Callback to finalize variable copies. - /// - /// \returns The insertion position *after* the master. - InsertPointTy createMaster(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB); - - /// Generator for '#omp masked' - /// - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the region code. - /// \param FiniCB Callback to finalize variable copies. - /// - /// \returns The insertion position *after* the masked. - InsertPointTy createMasked(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB, Value *Filter); - - /// Generator for '#omp critical' - /// - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the region body code. - /// \param FiniCB Callback to finalize variable copies. - /// \param CriticalName name of the lock used by the critical directive - /// \param HintInst Hint Instruction for hint clause associated with critical - /// - /// \returns The insertion position *after* the critical. - InsertPointTy createCritical(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB, - StringRef CriticalName, Value *HintInst); - - /// Generator for '#omp ordered depend (source | sink)' - /// - /// \param Loc The insert and source location description. - /// \param AllocaIP The insertion point to be used for alloca instructions. - /// \param NumLoops The number of loops in depend clause. - /// \param StoreValues The value will be stored in vector address. - /// \param Name The name of alloca instruction. - /// \param IsDependSource If true, depend source; otherwise, depend sink. - /// - /// \return The insertion position *after* the ordered. - InsertPointTy createOrderedDepend(const LocationDescription &Loc, - InsertPointTy AllocaIP, unsigned NumLoops, - ArrayRef StoreValues, - const Twine &Name, bool IsDependSource); - - /// Generator for '#omp ordered [threads | simd]' - /// - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the region code. - /// \param FiniCB Callback to finalize variable copies. - /// \param IsThreads If true, with threads clause or without clause; - /// otherwise, with simd clause; - /// - /// \returns The insertion position *after* the ordered. - InsertPointTy createOrderedThreadsSimd(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB, - bool IsThreads); - - /// Generator for '#omp sections' - /// - /// \param Loc The insert and source location description. - /// \param AllocaIP The insertion points to be used for alloca instructions. - /// \param SectionCBs Callbacks that will generate body of each section. - /// \param PrivCB Callback to copy a given variable (think copy constructor). - /// \param FiniCB Callback to finalize variable copies. - /// \param IsCancellable Flag to indicate a cancellable parallel region. - /// \param IsNowait If true, barrier - to ensure all sections are executed - /// before moving forward will not be generated. - /// \returns The insertion position *after* the sections. - InsertPointTy createSections(const LocationDescription &Loc, - InsertPointTy AllocaIP, - ArrayRef SectionCBs, - PrivatizeCallbackTy PrivCB, - FinalizeCallbackTy FiniCB, bool IsCancellable, - bool IsNowait); - - /// Generator for '#omp section' - /// - /// \param Loc The insert and source location description. - /// \param BodyGenCB Callback that will generate the region body code. - /// \param FiniCB Callback to finalize variable copies. - /// \returns The insertion position *after* the section. - InsertPointTy createSection(const LocationDescription &Loc, - BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB); - - /// Generate conditional branch and relevant BasicBlocks through which private - /// threads copy the 'copyin' variables from Master copy to threadprivate - /// copies. - /// - /// \param IP insertion block for copyin conditional - /// \param MasterVarPtr a pointer to the master variable - /// \param PrivateVarPtr a pointer to the threadprivate variable - /// \param IntPtrTy Pointer size type - /// \param BranchtoEnd Create a branch between the copyin.not.master blocks - // and copy.in.end block - /// - /// \returns The insertion point where copying operation to be emitted. - InsertPointTy createCopyinClauseBlocks(InsertPointTy IP, Value *MasterAddr, - Value *PrivateAddr, - llvm::IntegerType *IntPtrTy, - bool BranchtoEnd = true); - - /// Create a runtime call for kmpc_Alloc - /// - /// \param Loc The insert and source location description. - /// \param Size Size of allocated memory space - /// \param Allocator Allocator information instruction - /// \param Name Name of call Instruction for OMP_alloc - /// - /// \returns CallInst to the OMP_Alloc call - CallInst *createOMPAlloc(const LocationDescription &Loc, Value *Size, - Value *Allocator, std::string Name = ""); - - /// Create a runtime call for kmpc_free - /// - /// \param Loc The insert and source location description. - /// \param Addr Address of memory space to be freed - /// \param Allocator Allocator information instruction - /// \param Name Name of call Instruction for OMP_Free - /// - /// \returns CallInst to the OMP_Free call - CallInst *createOMPFree(const LocationDescription &Loc, Value *Addr, - Value *Allocator, std::string Name = ""); - - /// Create a runtime call for kmpc_threadprivate_cached - /// - /// \param Loc The insert and source location description. - /// \param Pointer pointer to data to be cached - /// \param Size size of data to be cached - /// \param Name Name of call Instruction for callinst - /// - /// \returns CallInst to the thread private cache call. - CallInst *createCachedThreadPrivate(const LocationDescription &Loc, - llvm::Value *Pointer, - llvm::ConstantInt *Size, - const llvm::Twine &Name = Twine("")); - - /// Create a runtime call for __tgt_interop_init - /// - /// \param Loc The insert and source location description. - /// \param InteropVar variable to be allocated - /// \param InteropType type of interop operation - /// \param Device device to which offloading will occur - /// \param NumDependences number of dependence variables - /// \param DependenceAddress pointer to dependence variables - /// \param HaveNowaitClause does nowait clause exist - /// - /// \returns CallInst to the __tgt_interop_init call - CallInst *createOMPInteropInit(const LocationDescription &Loc, - Value *InteropVar, - omp::OMPInteropType InteropType, Value *Device, - Value *NumDependences, - Value *DependenceAddress, - bool HaveNowaitClause); - - /// Create a runtime call for __tgt_interop_destroy - /// - /// \param Loc The insert and source location description. - /// \param InteropVar variable to be allocated - /// \param Device device to which offloading will occur - /// \param NumDependences number of dependence variables - /// \param DependenceAddress pointer to dependence variables - /// \param HaveNowaitClause does nowait clause exist - /// - /// \returns CallInst to the __tgt_interop_destroy call - CallInst *createOMPInteropDestroy(const LocationDescription &Loc, - Value *InteropVar, Value *Device, - Value *NumDependences, - Value *DependenceAddress, - bool HaveNowaitClause); - - /// Create a runtime call for __tgt_interop_use - /// - /// \param Loc The insert and source location description. - /// \param InteropVar variable to be allocated - /// \param Device device to which offloading will occur - /// \param NumDependences number of dependence variables - /// \param DependenceAddress pointer to dependence variables - /// \param HaveNowaitClause does nowait clause exist - /// - /// \returns CallInst to the __tgt_interop_use call - CallInst *createOMPInteropUse(const LocationDescription &Loc, - Value *InteropVar, Value *Device, - Value *NumDependences, Value *DependenceAddress, - bool HaveNowaitClause); - - /// The `omp target` interface - /// - /// For more information about the usage of this interface, - /// \see openmp/libomptarget/deviceRTLs/common/include/target.h - /// - ///{ - - /// Create a runtime call for kmpc_target_init - /// - /// \param Loc The insert and source location description. - /// \param IsSPMD Flag to indicate if the kernel is an SPMD kernel or not. - /// \param RequiresFullRuntime Indicate if a full device runtime is necessary. - InsertPointTy createTargetInit(const LocationDescription &Loc, bool IsSPMD, - bool RequiresFullRuntime); - - /// Create a runtime call for kmpc_target_deinit - /// - /// \param Loc The insert and source location description. - /// \param IsSPMD Flag to indicate if the kernel is an SPMD kernel or not. - /// \param RequiresFullRuntime Indicate if a full device runtime is necessary. - void createTargetDeinit(const LocationDescription &Loc, bool IsSPMD, - bool RequiresFullRuntime); - - ///} - - /// Declarations for LLVM-IR types (simple, array, function and structure) are - /// generated below. Their names are defined and used in OpenMPKinds.def. Here - /// we provide the declarations, the initializeTypes function will provide the - /// values. - /// - ///{ -#define OMP_TYPE(VarName, InitValue) Type *VarName = nullptr; -#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ - ArrayType *VarName##Ty = nullptr; \ - PointerType *VarName##PtrTy = nullptr; -#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \ - FunctionType *VarName = nullptr; \ - PointerType *VarName##Ptr = nullptr; -#define OMP_STRUCT_TYPE(VarName, StrName, ...) \ - StructType *VarName = nullptr; \ - PointerType *VarName##Ptr = nullptr; -#include "llvm/Frontend/OpenMP/OMPKinds.def" - - ///} - -private: - /// Create all simple and struct types exposed by the runtime and remember - /// the llvm::PointerTypes of them for easy access later. - void initializeTypes(Module &M); - - /// Common interface for generating entry calls for OMP Directives. - /// if the directive has a region/body, It will set the insertion - /// point to the body - /// - /// \param OMPD Directive to generate entry blocks for - /// \param EntryCall Call to the entry OMP Runtime Function - /// \param ExitBB block where the region ends. - /// \param Conditional indicate if the entry call result will be used - /// to evaluate a conditional of whether a thread will execute - /// body code or not. - /// - /// \return The insertion position in exit block - InsertPointTy emitCommonDirectiveEntry(omp::Directive OMPD, Value *EntryCall, - BasicBlock *ExitBB, - bool Conditional = false); - - /// Common interface to finalize the region - /// - /// \param OMPD Directive to generate exiting code for - /// \param FinIP Insertion point for emitting Finalization code and exit call - /// \param ExitCall Call to the ending OMP Runtime Function - /// \param HasFinalize indicate if the directive will require finalization - /// and has a finalization callback in the stack that - /// should be called. - /// - /// \return The insertion position in exit block - InsertPointTy emitCommonDirectiveExit(omp::Directive OMPD, - InsertPointTy FinIP, - Instruction *ExitCall, - bool HasFinalize = true); - - /// Common Interface to generate OMP inlined regions - /// - /// \param OMPD Directive to generate inlined region for - /// \param EntryCall Call to the entry OMP Runtime Function - /// \param ExitCall Call to the ending OMP Runtime Function - /// \param BodyGenCB Body code generation callback. - /// \param FiniCB Finalization Callback. Will be called when finalizing region - /// \param Conditional indicate if the entry call result will be used - /// to evaluate a conditional of whether a thread will execute - /// body code or not. - /// \param HasFinalize indicate if the directive will require finalization - /// and has a finalization callback in the stack that - /// should be called. - /// \param IsCancellable if HasFinalize is set to true, indicate if the - /// the directive should be cancellable. - /// \return The insertion point after the region - - InsertPointTy - EmitOMPInlinedRegion(omp::Directive OMPD, Instruction *EntryCall, - Instruction *ExitCall, BodyGenCallbackTy BodyGenCB, - FinalizeCallbackTy FiniCB, bool Conditional = false, - bool HasFinalize = true, bool IsCancellable = false); - - /// Get the platform-specific name separator. - /// \param Parts different parts of the final name that needs separation - /// \param FirstSeparator First separator used between the initial two - /// parts of the name. - /// \param Separator separator used between all of the rest consecutive - /// parts of the name - static std::string getNameWithSeparators(ArrayRef Parts, - StringRef FirstSeparator, - StringRef Separator); - - /// Gets (if variable with the given name already exist) or creates - /// internal global variable with the specified Name. The created variable has - /// linkage CommonLinkage by default and is initialized by null value. - /// \param Ty Type of the global variable. If it is exist already the type - /// must be the same. - /// \param Name Name of the variable. - Constant *getOrCreateOMPInternalVariable(Type *Ty, const Twine &Name, - unsigned AddressSpace = 0); - - /// Returns corresponding lock object for the specified critical region - /// name. If the lock object does not exist it is created, otherwise the - /// reference to the existing copy is returned. - /// \param CriticalName Name of the critical region. - /// - Value *getOMPCriticalRegionLock(StringRef CriticalName); - - /// Callback type for Atomic Expression update - /// ex: - /// \code{.cpp} - /// unsigned x = 0; - /// #pragma omp atomic update - /// x = Expr(x_old); //Expr() is any legal operation - /// \endcode - /// - /// \param XOld the value of the atomic memory address to use for update - /// \param IRB reference to the IRBuilder to use - /// - /// \returns Value to update X to. - using AtomicUpdateCallbackTy = - const function_ref &IRB)>; - -private: - enum AtomicKind { Read, Write, Update, Capture }; - - /// Determine whether to emit flush or not - /// - /// \param Loc The insert and source location description. - /// \param AO The required atomic ordering - /// \param AK The OpenMP atomic operation kind used. - /// - /// \returns whether a flush was emitted or not - bool checkAndEmitFlushAfterAtomic(const LocationDescription &Loc, - AtomicOrdering AO, AtomicKind AK); - - /// Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X - /// For complex Operations: X = UpdateOp(X) => CmpExch X, old_X, UpdateOp(X) - /// Only Scalar data types. - /// - /// \param AllocIP Instruction to create AllocaInst before. - /// \param X The target atomic pointer to be updated - /// \param XElemTy The element type of the atomic pointer. - /// \param Expr The value to update X with. - /// \param AO Atomic ordering of the generated atomic - /// instructions. - /// \param RMWOp The binary operation used for update. If - /// operation is not supported by atomicRMW, - /// or belong to {FADD, FSUB, BAD_BINOP}. - /// Then a `cmpExch` based atomic will be generated. - /// \param UpdateOp Code generator for complex expressions that cannot be - /// expressed through atomicrmw instruction. - /// \param VolatileX true if \a X volatile? - /// \param IsXBinopExpr true if \a X is Left H.S. in Right H.S. part of the - /// update expression, false otherwise. - /// (e.g. true for X = X BinOp Expr) - /// - /// \returns A pair of the old value of X before the update, and the value - /// used for the update. - std::pair - emitAtomicUpdate(Instruction *AllocIP, Value *X, Type *XElemTy, Value *Expr, - AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, - AtomicUpdateCallbackTy &UpdateOp, bool VolatileX, - bool IsXBinopExpr); - - /// Emit the binary op. described by \p RMWOp, using \p Src1 and \p Src2 . - /// - /// \Return The instruction - Value *emitRMWOpAsInstruction(Value *Src1, Value *Src2, - AtomicRMWInst::BinOp RMWOp); - -public: - /// a struct to pack relevant information while generating atomic Ops - struct AtomicOpValue { - Value *Var = nullptr; - Type *ElemTy = nullptr; - bool IsSigned = false; - bool IsVolatile = false; - }; - - /// Emit atomic Read for : V = X --- Only Scalar data types. - /// - /// \param Loc The insert and source location description. - /// \param X The target pointer to be atomically read - /// \param V Memory address where to store atomically read - /// value - /// \param AO Atomic ordering of the generated atomic - /// instructions. - /// - /// \return Insertion point after generated atomic read IR. - InsertPointTy createAtomicRead(const LocationDescription &Loc, - AtomicOpValue &X, AtomicOpValue &V, - AtomicOrdering AO); - - /// Emit atomic write for : X = Expr --- Only Scalar data types. - /// - /// \param Loc The insert and source location description. - /// \param X The target pointer to be atomically written to - /// \param Expr The value to store. - /// \param AO Atomic ordering of the generated atomic - /// instructions. - /// - /// \return Insertion point after generated atomic Write IR. - InsertPointTy createAtomicWrite(const LocationDescription &Loc, - AtomicOpValue &X, Value *Expr, - AtomicOrdering AO); - - /// Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X - /// For complex Operations: X = UpdateOp(X) => CmpExch X, old_X, UpdateOp(X) - /// Only Scalar data types. - /// - /// \param Loc The insert and source location description. - /// \param AllocIP Instruction to create AllocaInst before. - /// \param X The target atomic pointer to be updated - /// \param Expr The value to update X with. - /// \param AO Atomic ordering of the generated atomic instructions. - /// \param RMWOp The binary operation used for update. If operation - /// is not supported by atomicRMW, or belong to - /// {FADD, FSUB, BAD_BINOP}. Then a `cmpExch` based - /// atomic will be generated. - /// \param UpdateOp Code generator for complex expressions that cannot be - /// expressed through atomicrmw instruction. - /// \param IsXBinopExpr true if \a X is Left H.S. in Right H.S. part of the - /// update expression, false otherwise. - /// (e.g. true for X = X BinOp Expr) - /// - /// \return Insertion point after generated atomic update IR. - InsertPointTy createAtomicUpdate(const LocationDescription &Loc, - Instruction *AllocIP, AtomicOpValue &X, - Value *Expr, AtomicOrdering AO, - AtomicRMWInst::BinOp RMWOp, - AtomicUpdateCallbackTy &UpdateOp, - bool IsXBinopExpr); - - /// Emit atomic update for constructs: --- Only Scalar data types - /// V = X; X = X BinOp Expr , - /// X = X BinOp Expr; V = X, - /// V = X; X = Expr BinOp X, - /// X = Expr BinOp X; V = X, - /// V = X; X = UpdateOp(X), - /// X = UpdateOp(X); V = X, - /// - /// \param Loc The insert and source location description. - /// \param AllocIP Instruction to create AllocaInst before. - /// \param X The target atomic pointer to be updated - /// \param V Memory address where to store captured value - /// \param Expr The value to update X with. - /// \param AO Atomic ordering of the generated atomic instructions - /// \param RMWOp The binary operation used for update. If - /// operation is not supported by atomicRMW, or belong to - /// {FADD, FSUB, BAD_BINOP}. Then a cmpExch based - /// atomic will be generated. - /// \param UpdateOp Code generator for complex expressions that cannot be - /// expressed through atomicrmw instruction. - /// \param UpdateExpr true if X is an in place update of the form - /// X = X BinOp Expr or X = Expr BinOp X - /// \param IsXBinopExpr true if X is Left H.S. in Right H.S. part of the - /// update expression, false otherwise. - /// (e.g. true for X = X BinOp Expr) - /// \param IsPostfixUpdate true if original value of 'x' must be stored in - /// 'v', not an updated one. - /// - /// \return Insertion point after generated atomic capture IR. - InsertPointTy - createAtomicCapture(const LocationDescription &Loc, Instruction *AllocIP, - AtomicOpValue &X, AtomicOpValue &V, Value *Expr, - AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, - AtomicUpdateCallbackTy &UpdateOp, bool UpdateExpr, - bool IsPostfixUpdate, bool IsXBinopExpr); - - /// Create the control flow structure of a canonical OpenMP loop. - /// - /// The emitted loop will be disconnected, i.e. no edge to the loop's - /// preheader and no terminator in the AfterBB. The OpenMPIRBuilder's - /// IRBuilder location is not preserved. - /// - /// \param DL DebugLoc used for the instructions in the skeleton. - /// \param TripCount Value to be used for the trip count. - /// \param F Function in which to insert the BasicBlocks. - /// \param PreInsertBefore Where to insert BBs that execute before the body, - /// typically the body itself. - /// \param PostInsertBefore Where to insert BBs that execute after the body. - /// \param Name Base name used to derive BB - /// and instruction names. - /// - /// \returns The CanonicalLoopInfo that represents the emitted loop. - CanonicalLoopInfo *createLoopSkeleton(DebugLoc DL, Value *TripCount, - Function *F, - BasicBlock *PreInsertBefore, - BasicBlock *PostInsertBefore, - const Twine &Name = {}); -}; - -/// Class to represented the control flow structure of an OpenMP canonical loop. -/// -/// The control-flow structure is standardized for easy consumption by -/// directives associated with loops. For instance, the worksharing-loop -/// construct may change this control flow such that each loop iteration is -/// executed on only one thread. The constraints of a canonical loop in brief -/// are: -/// -/// * The number of loop iterations must have been computed before entering the -/// loop. -/// -/// * Has an (unsigned) logical induction variable that starts at zero and -/// increments by one. -/// -/// * The loop's CFG itself has no side-effects. The OpenMP specification -/// itself allows side-effects, but the order in which they happen, including -/// how often or whether at all, is unspecified. We expect that the frontend -/// will emit those side-effect instructions somewhere (e.g. before the loop) -/// such that the CanonicalLoopInfo itself can be side-effect free. -/// -/// Keep in mind that CanonicalLoopInfo is meant to only describe a repeated -/// execution of a loop body that satisfies these constraints. It does NOT -/// represent arbitrary SESE regions that happen to contain a loop. Do not use -/// CanonicalLoopInfo for such purposes. -/// -/// The control flow can be described as follows: -/// -/// Preheader -/// | -/// /-> Header -/// | | -/// | Cond---\ -/// | | | -/// | Body | -/// | | | | -/// | <...> | -/// | | | | -/// \--Latch | -/// | -/// Exit -/// | -/// After -/// -/// The loop is thought to start at PreheaderIP (at the Preheader's terminator, -/// including) and end at AfterIP (at the After's first instruction, excluding). -/// That is, instructions in the Preheader and After blocks (except the -/// Preheader's terminator) are out of CanonicalLoopInfo's control and may have -/// side-effects. Typically, the Preheader is used to compute the loop's trip -/// count. The instructions from BodyIP (at the Body block's first instruction, -/// excluding) until the Latch are also considered outside CanonicalLoopInfo's -/// control and thus can have side-effects. The body block is the single entry -/// point into the loop body, which may contain arbitrary control flow as long -/// as all control paths eventually branch to the Latch block. -/// -/// TODO: Consider adding another standardized BasicBlock between Body CFG and -/// Latch to guarantee that there is only a single edge to the latch. It would -/// make loop transformations easier to not needing to consider multiple -/// predecessors of the latch (See redirectAllPredecessorsTo) and would give us -/// an equivalent to PreheaderIP, AfterIP and BodyIP for inserting code that -/// executes after each body iteration. -/// -/// There must be no loop-carried dependencies through llvm::Values. This is -/// equivalent to that the Latch has no PHINode and the Header's only PHINode is -/// for the induction variable. -/// -/// All code in Header, Cond, Latch and Exit (plus the terminator of the -/// Preheader) are CanonicalLoopInfo's responsibility and their build-up checked -/// by assertOK(). They are expected to not be modified unless explicitly -/// modifying the CanonicalLoopInfo through a methods that applies a OpenMP -/// loop-associated construct such as applyWorkshareLoop, tileLoops, unrollLoop, -/// etc. These methods usually invalidate the CanonicalLoopInfo and re-use its -/// basic blocks. After invalidation, the CanonicalLoopInfo must not be used -/// anymore as its underlying control flow may not exist anymore. -/// Loop-transformation methods such as tileLoops, collapseLoops and unrollLoop -/// may also return a new CanonicalLoopInfo that can be passed to other -/// loop-associated construct implementing methods. These loop-transforming -/// methods may either create a new CanonicalLoopInfo usually using -/// createLoopSkeleton and invalidate the input CanonicalLoopInfo, or reuse and -/// modify one of the input CanonicalLoopInfo and return it as representing the -/// modified loop. What is done is an implementation detail of -/// transformation-implementing method and callers should always assume that the -/// CanonicalLoopInfo passed to it is invalidated and a new object is returned. -/// Returned CanonicalLoopInfo have the same structure and guarantees as the one -/// created by createCanonicalLoop, such that transforming methods do not have -/// to special case where the CanonicalLoopInfo originated from. -/// -/// Generally, methods consuming CanonicalLoopInfo do not need an -/// OpenMPIRBuilder::InsertPointTy as argument, but use the locations of the -/// CanonicalLoopInfo to insert new or modify existing instructions. Unless -/// documented otherwise, methods consuming CanonicalLoopInfo do not invalidate -/// any InsertPoint that is outside CanonicalLoopInfo's control. Specifically, -/// any InsertPoint in the Preheader, After or Block can still be used after -/// calling such a method. -/// -/// TODO: Provide mechanisms for exception handling and cancellation points. -/// -/// Defined outside OpenMPIRBuilder because nested classes cannot be -/// forward-declared, e.g. to avoid having to include the entire OMPIRBuilder.h. -class CanonicalLoopInfo { - friend class OpenMPIRBuilder; - -private: - BasicBlock *Header = nullptr; - BasicBlock *Cond = nullptr; - BasicBlock *Latch = nullptr; - BasicBlock *Exit = nullptr; - - /// Add the control blocks of this loop to \p BBs. - /// - /// This does not include any block from the body, including the one returned - /// by getBody(). - /// - /// FIXME: This currently includes the Preheader and After blocks even though - /// their content is (mostly) not under CanonicalLoopInfo's control. - /// Re-evaluated whether this makes sense. - void collectControlBlocks(SmallVectorImpl &BBs); - -public: - /// Returns whether this object currently represents the IR of a loop. If - /// returning false, it may have been consumed by a loop transformation or not - /// been initialized. Do not use in this case; - bool isValid() const { return Header; } - - /// The preheader ensures that there is only a single edge entering the loop. - /// Code that must be execute before any loop iteration can be emitted here, - /// such as computing the loop trip count and begin lifetime markers. Code in - /// the preheader is not considered part of the canonical loop. - BasicBlock *getPreheader() const; - - /// The header is the entry for each iteration. In the canonical control flow, - /// it only contains the PHINode for the induction variable. - BasicBlock *getHeader() const { - assert(isValid() && "Requires a valid canonical loop"); - return Header; - } - - /// The condition block computes whether there is another loop iteration. If - /// yes, branches to the body; otherwise to the exit block. - BasicBlock *getCond() const { - assert(isValid() && "Requires a valid canonical loop"); - return Cond; - } - - /// The body block is the single entry for a loop iteration and not controlled - /// by CanonicalLoopInfo. It can contain arbitrary control flow but must - /// eventually branch to the \p Latch block. - BasicBlock *getBody() const { - assert(isValid() && "Requires a valid canonical loop"); - return cast(Cond->getTerminator())->getSuccessor(0); - } - - /// Reaching the latch indicates the end of the loop body code. In the - /// canonical control flow, it only contains the increment of the induction - /// variable. - BasicBlock *getLatch() const { - assert(isValid() && "Requires a valid canonical loop"); - return Latch; - } - - /// Reaching the exit indicates no more iterations are being executed. - BasicBlock *getExit() const { - assert(isValid() && "Requires a valid canonical loop"); - return Exit; - } - - /// The after block is intended for clean-up code such as lifetime end - /// markers. It is separate from the exit block to ensure, analogous to the - /// preheader, it having just a single entry edge and being free from PHI - /// nodes should there be multiple loop exits (such as from break - /// statements/cancellations). - BasicBlock *getAfter() const { - assert(isValid() && "Requires a valid canonical loop"); - return Exit->getSingleSuccessor(); - } - - /// Returns the llvm::Value containing the number of loop iterations. It must - /// be valid in the preheader and always interpreted as an unsigned integer of - /// any bit-width. - Value *getTripCount() const { - assert(isValid() && "Requires a valid canonical loop"); - Instruction *CmpI = &Cond->front(); - assert(isa(CmpI) && "First inst must compare IV with TripCount"); - return CmpI->getOperand(1); - } - - /// Returns the instruction representing the current logical induction - /// variable. Always unsigned, always starting at 0 with an increment of one. - Instruction *getIndVar() const { - assert(isValid() && "Requires a valid canonical loop"); - Instruction *IndVarPHI = &Header->front(); - assert(isa(IndVarPHI) && "First inst must be the IV PHI"); - return IndVarPHI; - } - - /// Return the type of the induction variable (and the trip count). - Type *getIndVarType() const { - assert(isValid() && "Requires a valid canonical loop"); - return getIndVar()->getType(); - } - - /// Return the insertion point for user code before the loop. - OpenMPIRBuilder::InsertPointTy getPreheaderIP() const { - assert(isValid() && "Requires a valid canonical loop"); - BasicBlock *Preheader = getPreheader(); - return {Preheader, std::prev(Preheader->end())}; - }; - - /// Return the insertion point for user code in the body. - OpenMPIRBuilder::InsertPointTy getBodyIP() const { - assert(isValid() && "Requires a valid canonical loop"); - BasicBlock *Body = getBody(); - return {Body, Body->begin()}; - }; - - /// Return the insertion point for user code after the loop. - OpenMPIRBuilder::InsertPointTy getAfterIP() const { - assert(isValid() && "Requires a valid canonical loop"); - BasicBlock *After = getAfter(); - return {After, After->begin()}; - }; - - Function *getFunction() const { - assert(isValid() && "Requires a valid canonical loop"); - return Header->getParent(); - } - - /// Consistency self-check. - void assertOK() const; - - /// Invalidate this loop. That is, the underlying IR does not fulfill the - /// requirements of an OpenMP canonical loop anymore. - void invalidate(); -}; - -} // end namespace llvm - -#endif // LLVM_FRONTEND_OPENMP_OMPIRBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPKinds.def b/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPKinds.def deleted file mode 100644 index 0c3cb3f431..0000000000 --- a/suite/synctools/tablegen/include/llvm/Frontend/OpenMP/OMPKinds.def +++ /dev/null @@ -1,1238 +0,0 @@ -//===--- OMPKinds.def - OpenMP directives, clauses, rt-calls -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file defines the list of supported OpenMP runtime -/// calls, and other things that need to be listed in enums. -/// -/// This file is under transition to OMP.td with TableGen code generation. -/// -//===----------------------------------------------------------------------===// - -/// OpenMP Directives, combined directives and Clauses -/// - Moved to OMP.td - -/// Types used in runtime structs or runtime functions -/// -///{ - -#ifndef OMP_TYPE -#define OMP_TYPE(VarName, InitValue) -#endif - -#define __OMP_TYPE(VarName) OMP_TYPE(VarName, Type::get##VarName##Ty(Ctx)) - -__OMP_TYPE(Void) -__OMP_TYPE(Int1) -__OMP_TYPE(Int8) -__OMP_TYPE(Int16) -__OMP_TYPE(Int32) -__OMP_TYPE(Int64) -__OMP_TYPE(Int8Ptr) -__OMP_TYPE(Int16Ptr) -__OMP_TYPE(Int32Ptr) -__OMP_TYPE(Int64Ptr) - -OMP_TYPE(SizeTy, M.getDataLayout().getIntPtrType(Ctx)) - -#define __OMP_PTR_TYPE(NAME, BASE) OMP_TYPE(NAME, BASE->getPointerTo()) - -__OMP_PTR_TYPE(VoidPtr, Int8) -__OMP_PTR_TYPE(VoidPtrPtr, VoidPtr) -__OMP_PTR_TYPE(VoidPtrPtrPtr, VoidPtrPtr) - -__OMP_PTR_TYPE(Int8PtrPtr, Int8Ptr) -__OMP_PTR_TYPE(Int8PtrPtrPtr, Int8PtrPtr) - -#undef __OMP_PTR_TYPE - -#undef __OMP_TYPE -#undef OMP_TYPE - -///} - -/// array types -/// -///{ - -#ifndef OMP_ARRAY_TYPE -#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) -#endif - -#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ - OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) - -__OMP_ARRAY_TYPE(KmpCriticalName, Int32, 8) - -#undef __OMP_ARRAY_TYPE -#undef OMP_ARRAY_TYPE - -///} - -/// Struct and function types -/// -///{ - -#ifndef OMP_STRUCT_TYPE -#define OMP_STRUCT_TYPE(VarName, StructName, ...) -#endif - -#define __OMP_STRUCT_TYPE(VarName, Name, ...) \ - OMP_STRUCT_TYPE(VarName, "struct." #Name, __VA_ARGS__) - -__OMP_STRUCT_TYPE(Ident, ident_t, Int32, Int32, Int32, Int32, Int8Ptr) -__OMP_STRUCT_TYPE(AsyncInfo, __tgt_async_info, Int8Ptr) - -#undef __OMP_STRUCT_TYPE -#undef OMP_STRUCT_TYPE - -#ifndef OMP_FUNCTION_TYPE -#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) -#endif - -#define __OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \ - OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, __VA_ARGS__) - -__OMP_FUNCTION_TYPE(ParallelTask, true, Void, Int32Ptr, Int32Ptr) -__OMP_FUNCTION_TYPE(ReduceFunction, false, Void, VoidPtr, VoidPtr) -__OMP_FUNCTION_TYPE(CopyFunction, false, Void, VoidPtr, VoidPtr) -__OMP_FUNCTION_TYPE(KmpcCtor, false, VoidPtr, VoidPtr) -__OMP_FUNCTION_TYPE(KmpcDtor, false, Void, VoidPtr) -__OMP_FUNCTION_TYPE(KmpcCopyCtor, false, VoidPtr, VoidPtr, VoidPtr) -__OMP_FUNCTION_TYPE(TaskRoutineEntry, false, Int32, Int32, - /* kmp_task_t */ VoidPtr) -__OMP_FUNCTION_TYPE(ShuffleReduce, false, Void, VoidPtr, Int16, Int16, Int16) -__OMP_FUNCTION_TYPE(InterWarpCopy, false, Void, VoidPtr, Int32) -__OMP_FUNCTION_TYPE(GlobalList, false, Void, VoidPtr, Int32, VoidPtr) - -#undef __OMP_FUNCTION_TYPE -#undef OMP_FUNCTION_TYPE - -///} - -/// Internal Control Variables information -/// -///{ - -#ifndef ICV_INIT_VALUE -#define ICV_INIT_VALUE(Enum, Name) -#endif - -#define __ICV_INIT_VALUE(Name) ICV_INIT_VALUE(ICV_##Name, #Name) - -__ICV_INIT_VALUE(ZERO) -__ICV_INIT_VALUE(FALSE) -__ICV_INIT_VALUE(IMPLEMENTATION_DEFINED) -__ICV_INIT_VALUE(LAST) - -#undef __ICV_INIT_VALUE -#undef ICV_INIT_VALUE - -#ifndef ICV_DATA_ENV -#define ICV_DATA_ENV(Enum, Name, EnvVarName, Init) -#endif - -#define __ICV_DATA_ENV(Name, EnvVarName, Init) \ - ICV_DATA_ENV(ICV_##Name, #Name, #EnvVarName, Init) - -__ICV_DATA_ENV(nthreads, OMP_NUM_THREADS, ICV_IMPLEMENTATION_DEFINED) -__ICV_DATA_ENV(active_levels, NONE, ICV_ZERO) -__ICV_DATA_ENV(cancel, OMP_CANCELLATION, ICV_FALSE) -__ICV_DATA_ENV(proc_bind, OMP_PROC_BIND, ICV_IMPLEMENTATION_DEFINED) -__ICV_DATA_ENV(__last, last, ICV_LAST) - -#undef __ICV_DATA_ENV -#undef ICV_DATA_ENV - -#ifndef ICV_RT_SET -#define ICV_RT_SET(Name, RTL) -#endif - -#define __ICV_RT_SET(Name, RTL) ICV_RT_SET(ICV_##Name, OMPRTL_##RTL) - -__ICV_RT_SET(nthreads, omp_set_num_threads) - -#undef __ICV_RT_SET -#undef ICV_RT_SET - -#ifndef ICV_RT_GET -#define ICV_RT_GET(Name, RTL) -#endif - -#define __ICV_RT_GET(Name, RTL) ICV_RT_GET(ICV_##Name, OMPRTL_##RTL) - -__ICV_RT_GET(nthreads, omp_get_max_threads) -__ICV_RT_GET(active_levels, omp_get_active_level) -__ICV_RT_GET(cancel, omp_get_cancellation) -__ICV_RT_GET(proc_bind, omp_get_proc_bind) - -#undef __ICV_RT_GET -#undef ICV_RT_GET - -///} - -/// Runtime library function (and their attributes) -/// -///{ - -#ifndef OMP_RTL -#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) -#endif - -#define __OMP_RTL(Name, IsVarArg, ReturnType, ...) \ - OMP_RTL(OMPRTL_##Name, #Name, IsVarArg, ReturnType, __VA_ARGS__) - - - -__OMP_RTL(__kmpc_barrier, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_cancel, false, Int32, IdentPtr, Int32, Int32) -__OMP_RTL(__kmpc_cancel_barrier, false, Int32, IdentPtr, Int32) -__OMP_RTL(__kmpc_flush, false, Void, IdentPtr) -__OMP_RTL(__kmpc_global_thread_num, false, Int32, IdentPtr) -__OMP_RTL(__kmpc_get_hardware_thread_id_in_block, false, Int32, ) -__OMP_RTL(__kmpc_fork_call, true, Void, IdentPtr, Int32, ParallelTaskPtr) -__OMP_RTL(__kmpc_omp_taskwait, false, Int32, IdentPtr, Int32) -__OMP_RTL(__kmpc_omp_taskyield, false, Int32, IdentPtr, Int32, /* Int */ Int32) -__OMP_RTL(__kmpc_push_num_threads, false, Void, IdentPtr, Int32, - /* Int */ Int32) -__OMP_RTL(__kmpc_push_proc_bind, false, Void, IdentPtr, Int32, /* Int */ Int32) -__OMP_RTL(__kmpc_omp_reg_task_with_affinity, false, Int32, IdentPtr, Int32, - /* kmp_task_t */ VoidPtr, Int32, - /* kmp_task_affinity_info_t */ VoidPtr) - -__OMP_RTL(__kmpc_get_hardware_num_blocks, false, Int32, ) -__OMP_RTL(__kmpc_get_hardware_num_threads_in_block, false, Int32, ) -__OMP_RTL(__kmpc_get_warp_size, false, Int32, ) - -__OMP_RTL(omp_get_thread_num, false, Int32, ) -__OMP_RTL(omp_get_num_threads, false, Int32, ) -__OMP_RTL(omp_get_max_threads, false, Int32, ) -__OMP_RTL(omp_in_parallel, false, Int32, ) -__OMP_RTL(omp_get_dynamic, false, Int32, ) -__OMP_RTL(omp_get_cancellation, false, Int32, ) -__OMP_RTL(omp_get_nested, false, Int32, ) -__OMP_RTL(omp_get_schedule, false, Void, Int32Ptr, Int32Ptr) -__OMP_RTL(omp_get_thread_limit, false, Int32, ) -__OMP_RTL(omp_get_supported_active_levels, false, Int32, ) -__OMP_RTL(omp_get_max_active_levels, false, Int32, ) -__OMP_RTL(omp_get_level, false, Int32, ) -__OMP_RTL(omp_get_ancestor_thread_num, false, Int32, Int32) -__OMP_RTL(omp_get_team_size, false, Int32, Int32) -__OMP_RTL(omp_get_active_level, false, Int32, ) -__OMP_RTL(omp_in_final, false, Int32, ) -__OMP_RTL(omp_get_proc_bind, false, Int32, ) -__OMP_RTL(omp_get_num_places, false, Int32, ) -__OMP_RTL(omp_get_num_procs, false, Int32, ) -__OMP_RTL(omp_get_place_proc_ids, false, Void, Int32, Int32Ptr) -__OMP_RTL(omp_get_place_num, false, Int32, ) -__OMP_RTL(omp_get_partition_num_places, false, Int32, ) -__OMP_RTL(omp_get_partition_place_nums, false, Void, Int32Ptr) - -__OMP_RTL(omp_set_num_threads, false, Void, Int32) -__OMP_RTL(omp_set_dynamic, false, Void, Int32) -__OMP_RTL(omp_set_nested, false, Void, Int32) -__OMP_RTL(omp_set_schedule, false, Void, Int32, Int32) -__OMP_RTL(omp_set_max_active_levels, false, Void, Int32) - -__OMP_RTL(__kmpc_master, false, Int32, IdentPtr, Int32) -__OMP_RTL(__kmpc_end_master, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_masked, false, Int32, IdentPtr, Int32, Int32) -__OMP_RTL(__kmpc_end_masked, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_critical, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_critical_with_hint, false, Void, IdentPtr, Int32, - KmpCriticalNamePtrTy, Int32) -__OMP_RTL(__kmpc_end_critical, false, Void, IdentPtr, Int32, - KmpCriticalNamePtrTy) - -__OMP_RTL(__kmpc_begin, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_end, false, Void, IdentPtr) - -__OMP_RTL(__kmpc_reduce, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, - ReduceFunctionPtr, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_reduce_nowait, false, Int32, IdentPtr, Int32, Int32, SizeTy, - VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_end_reduce_nowait, false, Void, IdentPtr, Int32, - KmpCriticalNamePtrTy) - -__OMP_RTL(__kmpc_ordered, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_end_ordered, false, Void, IdentPtr, Int32) - -__OMP_RTL(__kmpc_for_static_init_4, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_for_static_init_4u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_for_static_init_8, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_for_static_init_8u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_for_static_fini, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_distribute_static_init_4, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_distribute_static_init_4u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_distribute_static_init_8, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_distribute_static_init_8u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_distribute_static_fini, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_dist_dispatch_init_4, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32, Int32, Int32, Int32) -__OMP_RTL(__kmpc_dist_dispatch_init_4u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32, Int32, Int32, Int32) -__OMP_RTL(__kmpc_dist_dispatch_init_8, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64, Int64, Int64, Int64) -__OMP_RTL(__kmpc_dist_dispatch_init_8u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64, Int64, Int64, Int64) -__OMP_RTL(__kmpc_dispatch_init_4, false, Void, IdentPtr, Int32, Int32, Int32, - Int32, Int32, Int32) -__OMP_RTL(__kmpc_dispatch_init_4u, false, Void, IdentPtr, Int32, Int32, Int32, - Int32, Int32, Int32) -__OMP_RTL(__kmpc_dispatch_init_8, false, Void, IdentPtr, Int32, Int32, Int64, - Int64, Int64, Int64) -__OMP_RTL(__kmpc_dispatch_init_8u, false, Void, IdentPtr, Int32, Int32, Int64, - Int64, Int64, Int64) -__OMP_RTL(__kmpc_dispatch_next_4, false, Int32, IdentPtr, Int32, Int32Ptr, - Int32Ptr, Int32Ptr, Int32Ptr) -__OMP_RTL(__kmpc_dispatch_next_4u, false, Int32, IdentPtr, Int32, Int32Ptr, - Int32Ptr, Int32Ptr, Int32Ptr) -__OMP_RTL(__kmpc_dispatch_next_8, false, Int32, IdentPtr, Int32, Int32Ptr, - Int64Ptr, Int64Ptr, Int64Ptr) -__OMP_RTL(__kmpc_dispatch_next_8u, false, Int32, IdentPtr, Int32, Int32Ptr, - Int64Ptr, Int64Ptr, Int64Ptr) -__OMP_RTL(__kmpc_dispatch_fini_4, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_dispatch_fini_4u, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_dispatch_fini_8, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_dispatch_fini_8u, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_team_static_init_4, false, Void, IdentPtr, Int32, Int32Ptr, - Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_team_static_init_4u, false, Void, IdentPtr, Int32, Int32Ptr, - Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_team_static_init_8, false, Void, IdentPtr, Int32, Int32Ptr, - Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_team_static_init_8u, false, Void, IdentPtr, Int32, Int32Ptr, - Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_dist_for_static_init_4, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_dist_for_static_init_4u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32Ptr, Int32, Int32) -__OMP_RTL(__kmpc_dist_for_static_init_8, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) -__OMP_RTL(__kmpc_dist_for_static_init_8u, false, Void, IdentPtr, Int32, Int32, - Int32Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64Ptr, Int64, Int64) - -__OMP_RTL(__kmpc_single, false, Int32, IdentPtr, Int32) -__OMP_RTL(__kmpc_end_single, false, Void, IdentPtr, Int32) - -__OMP_RTL(__kmpc_omp_task_alloc, false, /* kmp_task_t */ VoidPtr, IdentPtr, - Int32, Int32, SizeTy, SizeTy, TaskRoutineEntryPtr) -__OMP_RTL(__kmpc_omp_task, false, Int32, IdentPtr, Int32, - /* kmp_task_t */ VoidPtr) -__OMP_RTL(__kmpc_end_taskgroup, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_taskgroup, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_omp_task_begin_if0, false, Void, IdentPtr, Int32, - /* kmp_task_t */ VoidPtr) -__OMP_RTL(__kmpc_omp_task_complete_if0, false, Void, IdentPtr, Int32, - /* kmp_tasK_t */ VoidPtr) -__OMP_RTL(__kmpc_omp_task_with_deps, false, Int32, IdentPtr, Int32, - /* kmp_task_t */ VoidPtr, Int32, - /* kmp_depend_info_t */ VoidPtr, Int32, - /* kmp_depend_info_t */ VoidPtr) -__OMP_RTL(__kmpc_taskloop, false, Void, IdentPtr, /* Int */ Int32, VoidPtr, - /* Int */ Int32, Int64Ptr, Int64Ptr, Int64, /* Int */ Int32, - /* Int */ Int32, Int64, VoidPtr) -__OMP_RTL(__kmpc_omp_target_task_alloc, false, /* kmp_task_t */ VoidPtr, - IdentPtr, Int32, Int32, SizeTy, SizeTy, TaskRoutineEntryPtr, Int64) -__OMP_RTL(__kmpc_taskred_modifier_init, false, /* kmp_taskgroup */ VoidPtr, - IdentPtr, /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) -__OMP_RTL(__kmpc_taskred_init, false, /* kmp_taskgroup */ VoidPtr, - /* Int */ Int32, /* Int */ Int32, VoidPtr) -__OMP_RTL(__kmpc_task_reduction_modifier_fini, false, Void, IdentPtr, - /* Int */ Int32, /* Int */ Int32) -__OMP_RTL(__kmpc_task_reduction_get_th_data, false, VoidPtr, Int32, VoidPtr, - VoidPtr) -__OMP_RTL(__kmpc_task_reduction_init, false, VoidPtr, Int32, Int32, VoidPtr) -__OMP_RTL(__kmpc_task_reduction_modifier_init, false, VoidPtr, VoidPtr, Int32, - Int32, Int32, VoidPtr) -__OMP_RTL(__kmpc_proxy_task_completed_ooo, false, Void, VoidPtr) - -__OMP_RTL(__kmpc_omp_wait_deps, false, Void, IdentPtr, Int32, Int32, - /* kmp_depend_info_t */ VoidPtr, Int32, VoidPtr) -__OMP_RTL(__kmpc_cancellationpoint, false, Int32, IdentPtr, Int32, Int32) - -__OMP_RTL(__kmpc_fork_teams, true, Void, IdentPtr, Int32, ParallelTaskPtr) -__OMP_RTL(__kmpc_push_num_teams, false, Void, IdentPtr, Int32, Int32, Int32) - -__OMP_RTL(__kmpc_copyprivate, false, Void, IdentPtr, Int32, SizeTy, VoidPtr, - CopyFunctionPtr, Int32) -__OMP_RTL(__kmpc_threadprivate_cached, false, VoidPtr, IdentPtr, Int32, VoidPtr, - SizeTy, VoidPtrPtrPtr) -__OMP_RTL(__kmpc_threadprivate_register, false, Void, IdentPtr, VoidPtr, - KmpcCtorPtr, KmpcCopyCtorPtr, KmpcDtorPtr) - -__OMP_RTL(__kmpc_doacross_init, false, Void, IdentPtr, Int32, Int32, - /* kmp_dim */ VoidPtr) -__OMP_RTL(__kmpc_doacross_post, false, Void, IdentPtr, Int32, Int64Ptr) -__OMP_RTL(__kmpc_doacross_wait, false, Void, IdentPtr, Int32, Int64Ptr) -__OMP_RTL(__kmpc_doacross_fini, false, Void, IdentPtr, Int32) - -__OMP_RTL(__kmpc_alloc, false, VoidPtr, /* Int */ Int32, SizeTy, VoidPtr) -__OMP_RTL(__kmpc_aligned_alloc, false, VoidPtr, /* Int */ Int32, SizeTy, SizeTy, - VoidPtr) -__OMP_RTL(__kmpc_free, false, Void, /* Int */ Int32, VoidPtr, VoidPtr) - -__OMP_RTL(__tgt_interop_init, false, Void, IdentPtr, Int32, VoidPtrPtr, Int64, - Int32, Int32, VoidPtr, Int32) -__OMP_RTL(__tgt_interop_destroy, false, Void, IdentPtr, Int32, VoidPtrPtr, - Int32, Int32, VoidPtr, Int32) -__OMP_RTL(__tgt_interop_use, false, Void, IdentPtr, Int32, VoidPtrPtr, Int32, - Int32, VoidPtr, Int32) - -__OMP_RTL(__kmpc_init_allocator, false, /* omp_allocator_handle_t */ VoidPtr, - /* Int */ Int32, /* omp_memespace_handle_t */ VoidPtr, - /* Int */ Int32, /* omp_alloctrait_t */ VoidPtr) -__OMP_RTL(__kmpc_destroy_allocator, false, Void, /* Int */ Int32, - /* omp_allocator_handle_t */ VoidPtr) - -__OMP_RTL(__kmpc_push_target_tripcount_mapper, false, Void, IdentPtr, Int64, Int64) -__OMP_RTL(__tgt_target_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, VoidPtrPtr, - VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_nowait_mapper, false, Int32, IdentPtr, Int64, VoidPtr, - Int32, VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, - VoidPtrPtr, Int32, VoidPtr, Int32, VoidPtr) -__OMP_RTL(__tgt_target_teams_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr, Int32, Int32) -__OMP_RTL(__tgt_target_teams_nowait_mapper, false, Int32, IdentPtr, Int64, - VoidPtr, Int32, VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, - VoidPtrPtr, VoidPtrPtr, Int32, Int32, Int32, VoidPtr, Int32, VoidPtr) -__OMP_RTL(__tgt_register_requires, false, Void, Int64) -__OMP_RTL(__tgt_target_data_begin_mapper, false, Void, IdentPtr, Int64, Int32, VoidPtrPtr, - VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_data_begin_nowait_mapper, false, Void, IdentPtr, Int64, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_data_begin_mapper_issue, false, Void, IdentPtr, Int64, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr, AsyncInfoPtr) -__OMP_RTL(__tgt_target_data_begin_mapper_wait, false, Void, Int64, AsyncInfoPtr) -__OMP_RTL(__tgt_target_data_end_mapper, false, Void, IdentPtr, Int64, Int32, VoidPtrPtr, - VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_data_end_nowait_mapper, false, Void, IdentPtr, Int64, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_data_update_mapper, false, Void, IdentPtr, Int64, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_target_data_update_nowait_mapper, false, Void, IdentPtr, Int64, Int32, - VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) -__OMP_RTL(__tgt_mapper_num_components, false, Int64, VoidPtr) -__OMP_RTL(__tgt_push_mapper_component, false, Void, VoidPtr, VoidPtr, VoidPtr, - Int64, Int64, VoidPtr) -__OMP_RTL(__kmpc_task_allow_completion_event, false, VoidPtr, IdentPtr, - /* Int */ Int32, /* kmp_task_t */ VoidPtr) - -/// OpenMP Device runtime functions -__OMP_RTL(__kmpc_target_init, false, Int32, IdentPtr, Int8, Int1, Int1) -__OMP_RTL(__kmpc_target_deinit, false, Void, IdentPtr, Int8, Int1) -__OMP_RTL(__kmpc_kernel_prepare_parallel, false, Void, VoidPtr) -__OMP_RTL(__kmpc_parallel_51, false, Void, IdentPtr, Int32, Int32, Int32, Int32, - VoidPtr, VoidPtr, VoidPtrPtr, SizeTy) -__OMP_RTL(__kmpc_kernel_parallel, false, Int1, VoidPtrPtr) -__OMP_RTL(__kmpc_kernel_end_parallel, false, Void, ) -__OMP_RTL(__kmpc_serialized_parallel, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_end_serialized_parallel, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_shuffle_int32, false, Int32, Int32, Int16, Int16) -__OMP_RTL(__kmpc_nvptx_parallel_reduce_nowait_v2, false, Int32, IdentPtr, Int32, - Int32, SizeTy, VoidPtr, ShuffleReducePtr, InterWarpCopyPtr) -__OMP_RTL(__kmpc_nvptx_end_reduce_nowait, false, Void, Int32) -__OMP_RTL(__kmpc_nvptx_teams_reduce_nowait_v2, false, Int32, IdentPtr, Int32, - VoidPtr, Int32, VoidPtr, ShuffleReducePtr, InterWarpCopyPtr, - GlobalListPtr, GlobalListPtr, GlobalListPtr, GlobalListPtr) - -__OMP_RTL(__kmpc_shuffle_int64, false, Int64, Int64, Int16, Int16) - -__OMP_RTL(__kmpc_alloc_shared, false, VoidPtr, SizeTy) -__OMP_RTL(__kmpc_free_shared, false, Void, VoidPtr, SizeTy) -__OMP_RTL(__kmpc_begin_sharing_variables, false, Void, VoidPtrPtrPtr, SizeTy) -__OMP_RTL(__kmpc_end_sharing_variables, false, Void, ) -__OMP_RTL(__kmpc_get_shared_variables, false, Void, VoidPtrPtrPtr) -__OMP_RTL(__kmpc_parallel_level, false, Int8, ) -__OMP_RTL(__kmpc_is_spmd_exec_mode, false, Int8, ) -__OMP_RTL(__kmpc_barrier_simple_spmd, false, Void, IdentPtr, Int32) -__OMP_RTL(__kmpc_barrier_simple_generic, false, Void, IdentPtr, Int32) - -__OMP_RTL(__kmpc_warp_active_thread_mask, false, Int64,) -__OMP_RTL(__kmpc_syncwarp, false, Void, Int64) - -__OMP_RTL(__kmpc_is_generic_main_thread_id, false, Int8, Int32) - -__OMP_RTL(__last, false, Void, ) - -#undef __OMP_RTL -#undef OMP_RTL - -#define ParamAttrs(...) ArrayRef({__VA_ARGS__}) -#define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind) -#define EnumAttrInt(Kind, N) Attribute::get(Ctx, Attribute::AttrKind::Kind, N) -#define AttributeSet(...) \ - AttributeSet::get(Ctx, ArrayRef({__VA_ARGS__})) - -#ifndef OMP_ATTRS_SET -#define OMP_ATTRS_SET(VarName, AttrSet) -#endif - -#define __OMP_ATTRS_SET(VarName, AttrSet) OMP_ATTRS_SET(VarName, AttrSet) - -__OMP_ATTRS_SET(GetterAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) -__OMP_ATTRS_SET(GetterArgWriteAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(NoFree), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) -__OMP_ATTRS_SET(SetterAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(WriteOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(DefaultAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(BarrierAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(Convergent)) - : AttributeSet(EnumAttr(NoUnwind), EnumAttr(Convergent))) - -__OMP_ATTRS_SET(InaccessibleArgOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(NoCaptureAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoCapture)) - : AttributeSet(EnumAttr(NoCapture))) - -__OMP_ATTRS_SET(AlwaysInlineAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(AlwaysInline)) - : AttributeSet(EnumAttr(AlwaysInline))) - -#if 0 -__OMP_ATTRS_SET(InaccessibleOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) -#endif - -__OMP_ATTRS_SET(AllocAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(ForkAttrs, OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(ReadOnlyPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(ReadOnly), EnumAttr(NoFree), - EnumAttr(NoCapture)) - : AttributeSet()) - -__OMP_ATTRS_SET(DeviceAllocAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync)) - : AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync))) - -#if 0 -__OMP_ATTRS_SET(WriteOnlyPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(WriteOnly), EnumAttr(NoFree), - EnumAttr(NoCapture)) - : AttributeSet()) -#endif - -__OMP_ATTRS_SET(ArgPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoCapture), EnumAttr(NoFree)) - : AttributeSet()) - -__OMP_ATTRS_SET(ReturnPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoAlias)) - : AttributeSet()) - -#if 0 -__OMP_ATTRS_SET(ReturnAlignedPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoAlias), EnumAttrInt(Alignment, 8), - EnumAttrInt(DereferenceableOrNull, 8)) - : AttributeSet()) -#endif - -#undef __OMP_ATTRS_SET -#undef OMP_ATTRS_SET - -#ifndef OMP_RTL_ATTRS -#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) -#endif - -#define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets) \ - OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets) - -__OMP_RTL_ATTRS(__kmpc_barrier, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_barrier_simple_spmd, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_barrier_simple_generic, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_warp_active_thread_mask, BarrierAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_syncwarp, BarrierAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_cancel, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_cancel_barrier, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_flush, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_fork_call, ForkAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_taskwait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_taskyield, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_num_threads, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_proc_bind, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_serialized_parallel, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_reg_task_with_affinity, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, - AttributeSet(), ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_get_hardware_num_blocks, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_get_hardware_num_threads_in_block, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_get_warp_size, GetterAttrs, AttributeSet(), ParamAttrs()) - -__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS( - omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), - AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)))) -__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_supported_active_levels, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_place_proc_ids, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(AttributeSet(), AttributeSet(EnumAttr(NoCapture), - EnumAttr(WriteOnly)))) -__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_master, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_master, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_masked, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_masked, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_critical, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_critical_with_hint, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_critical, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) - -__OMP_RTL_ATTRS(__kmpc_begin, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_reduce, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_reduce_nowait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_reduce, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) - -__OMP_RTL_ATTRS(__kmpc_ordered, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_ordered, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_for_static_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_fini, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_distribute_static_init_4, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_distribute_static_init_4u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_distribute_static_init_8, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_distribute_static_init_8u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_distribute_static_fini, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_single, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_single, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_taskgroup, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskgroup, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskloop, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs, - AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskred_init, DefaultAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, BarrierAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_init, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, DefaultAttrs, - ReturnPtrAttrs, ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, DefaultAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_cancellationpoint, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_fork_teams, ForkAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_num_teams, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_copyprivate, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_threadprivate_register, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, - ReadOnlyPtrAttrs, ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_doacross_init, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_post, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_wait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_fini, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_alloc_shared, DeviceAllocAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_free_shared, DeviceAllocAttrs, AttributeSet(), - ParamAttrs(NoCaptureAttrs)) - -__OMP_RTL_ATTRS(__kmpc_alloc, DefaultAttrs, ReturnPtrAttrs, ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_aligned_alloc, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount_mapper, SetterAttrs, - AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_register_requires, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, ForkAttrs, - AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, ForkAttrs, - AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, ForkAttrs, - AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_mapper_num_components, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__tgt_push_mapper_component, ForkAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, DefaultAttrs, - ReturnPtrAttrs, ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_parallel_51, AlwaysInlineAttrs, AttributeSet(), - ParamAttrs()) - -#undef __OMP_RTL_ATTRS -#undef OMP_RTL_ATTRS -#undef AttributeSet -#undef EnumAttr -#undef EnumAttrInt -#undef ParamAttrs - -///} - -/// KMP ident_t bit flags -/// -/// In accordance with the values in `openmp/runtime/src/kmp.h`. -/// -///{ - -#ifndef OMP_IDENT_FLAG -#define OMP_IDENT_FLAG(Enum, Str, Value) -#endif - -#define __OMP_IDENT_FLAG(Name, Value) \ - OMP_IDENT_FLAG(OMP_IDENT_FLAG_##Name, #Name, Value) - -__OMP_IDENT_FLAG(KMPC, 0x02) -__OMP_IDENT_FLAG(ATOMIC_REDUCE, 0x10) -__OMP_IDENT_FLAG(BARRIER_EXPL, 0x20) -__OMP_IDENT_FLAG(BARRIER_IMPL, 0x0040) -__OMP_IDENT_FLAG(BARRIER_IMPL_MASK, 0x01C0) -__OMP_IDENT_FLAG(BARRIER_IMPL_FOR, 0x0040) -__OMP_IDENT_FLAG(BARRIER_IMPL_SECTIONS, 0x00C0) -__OMP_IDENT_FLAG(BARRIER_IMPL_SINGLE, 0x0140) -__OMP_IDENT_FLAG(BARRIER_IMPL_WORKSHARE, 0x01C0) - -#undef __OMP_IDENT_FLAG -#undef OMP_IDENT_FLAG - -///} - -/// KMP cancel kind -/// -///{ - -#ifndef OMP_CANCEL_KIND -#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) -#endif - -#define __OMP_CANCEL_KIND(Name, Value) \ - OMP_CANCEL_KIND(OMP_CANCEL_KIND_##Name, #Name, OMPD_##Name, Value) - -__OMP_CANCEL_KIND(parallel, 1) -__OMP_CANCEL_KIND(for, 2) -__OMP_CANCEL_KIND(sections, 3) -__OMP_CANCEL_KIND(taskgroup, 4) - -#undef __OMP_CANCEL_KIND -#undef OMP_CANCEL_KIND - -///} - -/// Default kinds -/// -///{ - -#ifndef OMP_DEFAULT_KIND -#define OMP_DEFAULT_KIND(Enum, Str) -#endif - -#define __OMP_DEFAULT_KIND(Name) OMP_DEFAULT_KIND(OMP_DEFAULT_##Name, #Name) - -__OMP_DEFAULT_KIND(none) -__OMP_DEFAULT_KIND(shared) -__OMP_DEFAULT_KIND(firstprivate) -__OMP_DEFAULT_KIND(unknown) - -#undef __OMP_DEFAULT_KIND -#undef OMP_DEFAULT_KIND - -///} - -/// Proc bind kinds -/// -///{ - -#ifndef OMP_PROC_BIND_KIND -#define OMP_PROC_BIND_KIND(Enum, Str, Value) -#endif - -#define __OMP_PROC_BIND_KIND(Name, Value) \ - OMP_PROC_BIND_KIND(OMP_PROC_BIND_##Name, #Name, Value) - -__OMP_PROC_BIND_KIND(master, 2) -__OMP_PROC_BIND_KIND(close, 3) -__OMP_PROC_BIND_KIND(spread, 4) -__OMP_PROC_BIND_KIND(primary, 5) -__OMP_PROC_BIND_KIND(default, 6) -__OMP_PROC_BIND_KIND(unknown, 7) - -#undef __OMP_PROC_BIND_KIND -#undef OMP_PROC_BIND_KIND - -///} - -/// OpenMP context related definitions: -/// - trait set selector -/// - trait selector -/// - trait property -/// -///{ - -#ifndef OMP_TRAIT_SET -#define OMP_TRAIT_SET(Enum, Str) -#endif -#ifndef OMP_TRAIT_SELECTOR -#define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, RequiresProperty) -#endif -#ifndef OMP_TRAIT_PROPERTY -#define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) -#endif -#ifndef OMP_LAST_TRAIT_PROPERTY -#define OMP_LAST_TRAIT_PROPERTY(Enum) -#endif - -#define __OMP_TRAIT_SET(Name) OMP_TRAIT_SET(Name, #Name) -#define __OMP_TRAIT_SELECTOR(TraitSet, Name, RequiresProperty) \ - OMP_TRAIT_SELECTOR(TraitSet##_##Name, TraitSet, #Name, RequiresProperty) -#define __OMP_TRAIT_SELECTOR_AND_PROPERTY(TraitSet, Name) \ - OMP_TRAIT_SELECTOR(TraitSet##_##Name, TraitSet, #Name, false) \ - OMP_TRAIT_PROPERTY(TraitSet##_##Name##_##Name, TraitSet, TraitSet##_##Name, \ - #Name) -#define __OMP_TRAIT_PROPERTY(TraitSet, TraitSelector, Name) \ - OMP_TRAIT_PROPERTY(TraitSet##_##TraitSelector##_##Name, TraitSet, \ - TraitSet##_##TraitSelector, #Name) - -// "invalid" must go first. -OMP_TRAIT_SET(invalid, "invalid") -OMP_TRAIT_SELECTOR(invalid, invalid, "invalid", false) -OMP_TRAIT_PROPERTY(invalid, invalid, invalid, "invalid") - -__OMP_TRAIT_SET(construct) -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, target) -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, teams) -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, parallel) -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, for) -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, simd) - -__OMP_TRAIT_SET(device) - -__OMP_TRAIT_SELECTOR(device, kind, true) - -__OMP_TRAIT_PROPERTY(device, kind, host) -__OMP_TRAIT_PROPERTY(device, kind, nohost) -__OMP_TRAIT_PROPERTY(device, kind, cpu) -__OMP_TRAIT_PROPERTY(device, kind, gpu) -__OMP_TRAIT_PROPERTY(device, kind, fpga) -__OMP_TRAIT_PROPERTY(device, kind, any) - -__OMP_TRAIT_SELECTOR(device, arch, true) - -__OMP_TRAIT_PROPERTY(device, arch, arm) -__OMP_TRAIT_PROPERTY(device, arch, armeb) -__OMP_TRAIT_PROPERTY(device, arch, aarch64) -__OMP_TRAIT_PROPERTY(device, arch, aarch64_be) -__OMP_TRAIT_PROPERTY(device, arch, aarch64_32) -__OMP_TRAIT_PROPERTY(device, arch, ppc) -__OMP_TRAIT_PROPERTY(device, arch, ppcle) -__OMP_TRAIT_PROPERTY(device, arch, ppc64) -__OMP_TRAIT_PROPERTY(device, arch, ppc64le) -__OMP_TRAIT_PROPERTY(device, arch, x86) -__OMP_TRAIT_PROPERTY(device, arch, x86_64) -__OMP_TRAIT_PROPERTY(device, arch, amdgcn) -__OMP_TRAIT_PROPERTY(device, arch, nvptx) -__OMP_TRAIT_PROPERTY(device, arch, nvptx64) - -__OMP_TRAIT_SET(implementation) - -__OMP_TRAIT_SELECTOR(implementation, vendor, true) - -__OMP_TRAIT_PROPERTY(implementation, vendor, amd) -__OMP_TRAIT_PROPERTY(implementation, vendor, arm) -__OMP_TRAIT_PROPERTY(implementation, vendor, bsc) -__OMP_TRAIT_PROPERTY(implementation, vendor, cray) -__OMP_TRAIT_PROPERTY(implementation, vendor, fujitsu) -__OMP_TRAIT_PROPERTY(implementation, vendor, gnu) -__OMP_TRAIT_PROPERTY(implementation, vendor, ibm) -__OMP_TRAIT_PROPERTY(implementation, vendor, intel) -__OMP_TRAIT_PROPERTY(implementation, vendor, llvm) -__OMP_TRAIT_PROPERTY(implementation, vendor, nec) -__OMP_TRAIT_PROPERTY(implementation, vendor, nvidia) -__OMP_TRAIT_PROPERTY(implementation, vendor, pgi) -__OMP_TRAIT_PROPERTY(implementation, vendor, ti) -__OMP_TRAIT_PROPERTY(implementation, vendor, unknown) - -__OMP_TRAIT_SELECTOR(implementation, extension, true) -__OMP_TRAIT_PROPERTY(implementation, extension, match_all) -__OMP_TRAIT_PROPERTY(implementation, extension, match_any) -__OMP_TRAIT_PROPERTY(implementation, extension, match_none) -__OMP_TRAIT_PROPERTY(implementation, extension, disable_implicit_base) -__OMP_TRAIT_PROPERTY(implementation, extension, allow_templates) - -__OMP_TRAIT_SET(user) - -__OMP_TRAIT_SELECTOR(user, condition, true) - -__OMP_TRAIT_PROPERTY(user, condition, true) -__OMP_TRAIT_PROPERTY(user, condition, false) -__OMP_TRAIT_PROPERTY(user, condition, unknown) - -__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, dispatch) - -// Note that we put isa last so that the other conditions are checked first. -// This allows us to issue warnings wrt. isa only if we match otherwise. -__OMP_TRAIT_SELECTOR(device, isa, true) - -// We use "__ANY" as a placeholder in the isa property to denote the -// conceptual "any", not the literal `any` used in kind. The string we -// we use is not important except that it will show up in diagnostics. -OMP_TRAIT_PROPERTY(device_isa___ANY, device, device_isa, - "") - - -#undef OMP_TRAIT_SET -#undef __OMP_TRAIT_SET -///} - -/// Traits for the requires directive -/// -/// These will (potentially) become trait selectors for the OpenMP context if -/// the OMP_REQUIRES_TRAIT macro is not defined. -/// -///{ - -#ifdef OMP_REQUIRES_TRAIT -#define __OMP_REQUIRES_TRAIT(Name) \ - OMP_REQUIRES_TRAIT(OMP_REQUIRES_TRAIT_##Name, #Name) -#else -#define __OMP_REQUIRES_TRAIT(Name) \ - __OMP_TRAIT_SELECTOR_AND_PROPERTY(implementation, Name) -#endif - -__OMP_REQUIRES_TRAIT(unified_address) -__OMP_REQUIRES_TRAIT(unified_shared_memory) -__OMP_REQUIRES_TRAIT(reverse_offload) -__OMP_REQUIRES_TRAIT(dynamic_allocators) -__OMP_REQUIRES_TRAIT(atomic_default_mem_order) - -OMP_LAST_TRAIT_PROPERTY( - implementation_atomic_default_mem_order_atomic_default_mem_order) - -#undef __OMP_TRAIT_SELECTOR_AND_PROPERTY -#undef OMP_TRAIT_SELECTOR -#undef __OMP_TRAIT_SELECTOR -#undef OMP_TRAIT_PROPERTY -#undef OMP_LAST_TRAIT_PROPERTY -#undef __OMP_TRAIT_PROPERTY -#undef __OMP_REQUIRES_TRAIT -#undef OMP_REQUIRES_TRAIT -///} - - -/// Assumption clauses -/// -///{ - -#ifdef OMP_ASSUME_CLAUSE -#define __OMP_ASSUME_CLAUSE(Identifier, StartsWith, HasDirectiveList, HasExpression) \ -OMP_ASSUME_CLAUSE(Identifier, StartsWith, HasDirectiveList, HasExpression) -#else -#define __OMP_ASSUME_CLAUSE(...) -#endif - -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("ext_"), true, false, false) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("absent"), false, true, false) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("contains"), false, true, false) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("holds"), false, false, true) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("no_openmp"), false, false, false) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("no_openmp_routines"), false, false, false) -__OMP_ASSUME_CLAUSE(llvm::StringLiteral("no_parallelism"), false, false, false) - -#undef __OMP_ASSUME_CLAUSE -#undef OMP_ASSUME_CLAUSE -///} diff --git a/suite/synctools/tablegen/include/llvm/IR/AbstractCallSite.h b/suite/synctools/tablegen/include/llvm/IR/AbstractCallSite.h deleted file mode 100644 index 69048554a0..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/AbstractCallSite.h +++ /dev/null @@ -1,247 +0,0 @@ -//===- AbstractCallSite.h - Abstract call sites -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the AbstractCallSite class, which is a is a wrapper that -// allows treating direct, indirect, and callback calls the same. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_ABSTRACTCALLSITE_H -#define LLVM_IR_ABSTRACTCALLSITE_H - -#include "llvm/IR/Argument.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Use.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include - -namespace llvm { - -/// AbstractCallSite -/// -/// An abstract call site is a wrapper that allows to treat direct, -/// indirect, and callback calls the same. If an abstract call site -/// represents a direct or indirect call site it behaves like a stripped -/// down version of a normal call site object. The abstract call site can -/// also represent a callback call, thus the fact that the initially -/// called function (=broker) may invoke a third one (=callback callee). -/// In this case, the abstract call site hides the middle man, hence the -/// broker function. The result is a representation of the callback call, -/// inside the broker, but in the context of the original call to the broker. -/// -/// There are up to three functions involved when we talk about callback call -/// sites. The caller (1), which invokes the broker function. The broker -/// function (2), that will invoke the callee zero or more times. And finally -/// the callee (3), which is the target of the callback call. -/// -/// The abstract call site will handle the mapping from parameters to arguments -/// depending on the semantic of the broker function. However, it is important -/// to note that the mapping is often partial. Thus, some arguments of the -/// call/invoke instruction are mapped to parameters of the callee while others -/// are not. -class AbstractCallSite { -public: - - /// The encoding of a callback with regards to the underlying instruction. - struct CallbackInfo { - - /// For direct/indirect calls the parameter encoding is empty. If it is not, - /// the abstract call site represents a callback. In that case, the first - /// element of the encoding vector represents which argument of the call - /// site CB is the callback callee. The remaining elements map parameters - /// (identified by their position) to the arguments that will be passed - /// through (also identified by position but in the call site instruction). - /// - /// NOTE that we use LLVM argument numbers (starting at 0) and not - /// clang/source argument numbers (starting at 1). The -1 entries represent - /// unknown values that are passed to the callee. - using ParameterEncodingTy = SmallVector; - ParameterEncodingTy ParameterEncoding; - - }; - -private: - - /// The underlying call site: - /// caller -> callee, if this is a direct or indirect call site - /// caller -> broker function, if this is a callback call site - CallBase *CB; - - /// The encoding of a callback with regards to the underlying instruction. - CallbackInfo CI; - -public: - /// Sole constructor for abstract call sites (ACS). - /// - /// An abstract call site can only be constructed through a llvm::Use because - /// each operand (=use) of an instruction could potentially be a different - /// abstract call site. Furthermore, even if the value of the llvm::Use is the - /// same, and the user is as well, the abstract call sites might not be. - /// - /// If a use is not associated with an abstract call site the constructed ACS - /// will evaluate to false if converted to a boolean. - /// - /// If the use is the callee use of a call or invoke instruction, the - /// constructed abstract call site will behave as a llvm::CallSite would. - /// - /// If the use is not a callee use of a call or invoke instruction, the - /// callback metadata is used to determine the argument <-> parameter mapping - /// as well as the callee of the abstract call site. - AbstractCallSite(const Use *U); - - /// Add operand uses of \p CB that represent callback uses into - /// \p CallbackUses. - /// - /// All uses added to \p CallbackUses can be used to create abstract call - /// sites for which AbstractCallSite::isCallbackCall() will return true. - static void getCallbackUses(const CallBase &CB, - SmallVectorImpl &CallbackUses); - - /// Conversion operator to conveniently check for a valid/initialized ACS. - explicit operator bool() const { return CB != nullptr; } - - /// Return the underlying instruction. - CallBase *getInstruction() const { return CB; } - - /// Return true if this ACS represents a direct call. - bool isDirectCall() const { - return !isCallbackCall() && !CB->isIndirectCall(); - } - - /// Return true if this ACS represents an indirect call. - bool isIndirectCall() const { - return !isCallbackCall() && CB->isIndirectCall(); - } - - /// Return true if this ACS represents a callback call. - bool isCallbackCall() const { - // For a callback call site the callee is ALWAYS stored first in the - // transitive values vector. Thus, a non-empty vector indicates a callback. - return !CI.ParameterEncoding.empty(); - } - - /// Return true if @p UI is the use that defines the callee of this ACS. - bool isCallee(Value::const_user_iterator UI) const { - return isCallee(&UI.getUse()); - } - - /// Return true if @p U is the use that defines the callee of this ACS. - bool isCallee(const Use *U) const { - if (isDirectCall()) - return CB->isCallee(U); - - assert(!CI.ParameterEncoding.empty() && - "Callback without parameter encoding!"); - - // If the use is actually in a constant cast expression which itself - // has only one use, we look through the constant cast expression. - if (auto *CE = dyn_cast(U->getUser())) - if (CE->hasOneUse() && CE->isCast()) - U = &*CE->use_begin(); - - return (int)CB->getArgOperandNo(U) == CI.ParameterEncoding[0]; - } - - /// Return the number of parameters of the callee. - unsigned getNumArgOperands() const { - if (isDirectCall()) - return CB->arg_size(); - // Subtract 1 for the callee encoding. - return CI.ParameterEncoding.size() - 1; - } - - /// Return the operand index of the underlying instruction associated with @p - /// Arg. - int getCallArgOperandNo(Argument &Arg) const { - return getCallArgOperandNo(Arg.getArgNo()); - } - - /// Return the operand index of the underlying instruction associated with - /// the function parameter number @p ArgNo or -1 if there is none. - int getCallArgOperandNo(unsigned ArgNo) const { - if (isDirectCall()) - return ArgNo; - // Add 1 for the callee encoding. - return CI.ParameterEncoding[ArgNo + 1]; - } - - /// Return the operand of the underlying instruction associated with @p Arg. - Value *getCallArgOperand(Argument &Arg) const { - return getCallArgOperand(Arg.getArgNo()); - } - - /// Return the operand of the underlying instruction associated with the - /// function parameter number @p ArgNo or nullptr if there is none. - Value *getCallArgOperand(unsigned ArgNo) const { - if (isDirectCall()) - return CB->getArgOperand(ArgNo); - // Add 1 for the callee encoding. - return CI.ParameterEncoding[ArgNo + 1] >= 0 - ? CB->getArgOperand(CI.ParameterEncoding[ArgNo + 1]) - : nullptr; - } - - /// Return the operand index of the underlying instruction associated with the - /// callee of this ACS. Only valid for callback calls! - int getCallArgOperandNoForCallee() const { - assert(isCallbackCall()); - assert(CI.ParameterEncoding.size() && CI.ParameterEncoding[0] >= 0); - return CI.ParameterEncoding[0]; - } - - /// Return the use of the callee value in the underlying instruction. Only - /// valid for callback calls! - const Use &getCalleeUseForCallback() const { - int CalleeArgIdx = getCallArgOperandNoForCallee(); - assert(CalleeArgIdx >= 0 && - unsigned(CalleeArgIdx) < getInstruction()->getNumOperands()); - return getInstruction()->getOperandUse(CalleeArgIdx); - } - - /// Return the pointer to function that is being called. - Value *getCalledOperand() const { - if (isDirectCall()) - return CB->getCalledOperand(); - return CB->getArgOperand(getCallArgOperandNoForCallee()); - } - - /// Return the function being called if this is a direct call, otherwise - /// return null (if it's an indirect call). - Function *getCalledFunction() const { - Value *V = getCalledOperand(); - return V ? dyn_cast(V->stripPointerCasts()) : nullptr; - } -}; - -/// Apply function Func to each CB's callback call site. -template -void forEachCallbackCallSite(const CallBase &CB, UnaryFunction Func) { - SmallVector CallbackUses; - AbstractCallSite::getCallbackUses(CB, CallbackUses); - for (const Use *U : CallbackUses) { - AbstractCallSite ACS(U); - assert(ACS && ACS.isCallbackCall() && "must be a callback call"); - Func(ACS); - } -} - -/// Apply function Func to each CB's callback function. -template -void forEachCallbackFunction(const CallBase &CB, UnaryFunction Func) { - forEachCallbackCallSite(CB, [&Func](AbstractCallSite &ACS) { - if (Function *Callback = ACS.getCalledFunction()) - Func(Callback); - }); -} - -} // end namespace llvm - -#endif // LLVM_IR_ABSTRACTCALLSITE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Argument.h b/suite/synctools/tablegen/include/llvm/IR/Argument.h deleted file mode 100644 index 7cbfa2a7b6..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Argument.h +++ /dev/null @@ -1,180 +0,0 @@ -//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the Argument class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_ARGUMENT_H -#define LLVM_IR_ARGUMENT_H - -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Value.h" - -namespace llvm { - -/// This class represents an incoming formal argument to a Function. A formal -/// argument, since it is ``formal'', does not contain an actual value but -/// instead represents the type, argument number, and attributes of an argument -/// for a specific function. When used in the body of said function, the -/// argument of course represents the value of the actual argument that the -/// function was called with. -class Argument final : public Value { - Function *Parent; - unsigned ArgNo; - - friend class Function; - void setParent(Function *parent); - -public: - /// Argument constructor. - explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr, - unsigned ArgNo = 0); - - inline const Function *getParent() const { return Parent; } - inline Function *getParent() { return Parent; } - - /// Return the index of this formal argument in its containing function. - /// - /// For example in "void foo(int a, float b)" a is 0 and b is 1. - unsigned getArgNo() const { - assert(Parent && "can't get number of unparented arg"); - return ArgNo; - } - - /// Return true if this argument has the nonnull attribute. Also returns true - /// if at least one byte is known to be dereferenceable and the pointer is in - /// addrspace(0). - /// If AllowUndefOrPoison is true, respect the semantics of nonnull attribute - /// and return true even if the argument can be undef or poison. - bool hasNonNullAttr(bool AllowUndefOrPoison = true) const; - - /// If this argument has the dereferenceable attribute, return the number of - /// bytes known to be dereferenceable. Otherwise, zero is returned. - uint64_t getDereferenceableBytes() const; - - /// If this argument has the dereferenceable_or_null attribute, return the - /// number of bytes known to be dereferenceable. Otherwise, zero is returned. - uint64_t getDereferenceableOrNullBytes() const; - - /// Return true if this argument has the byval attribute. - bool hasByValAttr() const; - - /// Return true if this argument has the byref attribute. - bool hasByRefAttr() const; - - /// Return true if this argument has the swiftself attribute. - bool hasSwiftSelfAttr() const; - - /// Return true if this argument has the swifterror attribute. - bool hasSwiftErrorAttr() const; - - /// Return true if this argument has the byval, inalloca, or preallocated - /// attribute. These attributes represent arguments being passed by value, - /// with an associated copy between the caller and callee - bool hasPassPointeeByValueCopyAttr() const; - - /// If this argument satisfies has hasPassPointeeByValueAttr, return the - /// in-memory ABI size copied to the stack for the call. Otherwise, return 0. - uint64_t getPassPointeeByValueCopySize(const DataLayout &DL) const; - - /// Return true if this argument has the byval, sret, inalloca, preallocated, - /// or byref attribute. These attributes represent arguments being passed by - /// value (which may or may not involve a stack copy) - bool hasPointeeInMemoryValueAttr() const; - - /// If hasPointeeInMemoryValueAttr returns true, the in-memory ABI type is - /// returned. Otherwise, nullptr. - Type *getPointeeInMemoryValueType() const; - - /// If this is a byval or inalloca argument, return its alignment. - /// FIXME: Remove this function once transition to Align is over. - /// Use getParamAlign() instead. - uint64_t getParamAlignment() const; - - /// If this is a byval or inalloca argument, return its alignment. - MaybeAlign getParamAlign() const; - - MaybeAlign getParamStackAlign() const; - - /// If this is a byval argument, return its type. - Type *getParamByValType() const; - - /// If this is an sret argument, return its type. - Type *getParamStructRetType() const; - - /// If this is a byref argument, return its type. - Type *getParamByRefType() const; - - /// If this is an inalloca argument, return its type. - Type *getParamInAllocaType() const; - - /// Return true if this argument has the nest attribute. - bool hasNestAttr() const; - - /// Return true if this argument has the noalias attribute. - bool hasNoAliasAttr() const; - - /// Return true if this argument has the nocapture attribute. - bool hasNoCaptureAttr() const; - - /// Return true if this argument has the nofree attribute. - bool hasNoFreeAttr() const; - - /// Return true if this argument has the sret attribute. - bool hasStructRetAttr() const; - - /// Return true if this argument has the inreg attribute. - bool hasInRegAttr() const; - - /// Return true if this argument has the returned attribute. - bool hasReturnedAttr() const; - - /// Return true if this argument has the readonly or readnone attribute. - bool onlyReadsMemory() const; - - /// Return true if this argument has the inalloca attribute. - bool hasInAllocaAttr() const; - - /// Return true if this argument has the preallocated attribute. - bool hasPreallocatedAttr() const; - - /// Return true if this argument has the zext attribute. - bool hasZExtAttr() const; - - /// Return true if this argument has the sext attribute. - bool hasSExtAttr() const; - - /// Add attributes to an argument. - void addAttrs(AttrBuilder &B); - - void addAttr(Attribute::AttrKind Kind); - - void addAttr(Attribute Attr); - - /// Remove attributes from an argument. - void removeAttr(Attribute::AttrKind Kind); - - void removeAttrs(const AttributeMask &AM); - - /// Check if an argument has a given attribute. - bool hasAttribute(Attribute::AttrKind Kind) const; - - Attribute getAttribute(Attribute::AttrKind Kind) const; - - /// Method for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == ArgumentVal; - } -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/AssemblyAnnotationWriter.h b/suite/synctools/tablegen/include/llvm/IR/AssemblyAnnotationWriter.h deleted file mode 100644 index 3fd3c57a67..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/AssemblyAnnotationWriter.h +++ /dev/null @@ -1,61 +0,0 @@ -//===-- AssemblyAnnotationWriter.h - Annotation .ll files -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Clients of the assembly writer can use this interface to add their own -// special-purpose annotations to LLVM assembly language printouts. Note that -// the assembly parser won't be able to parse these, in general, so -// implementations are advised to print stuff as LLVM comments. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_ASSEMBLYANNOTATIONWRITER_H -#define LLVM_IR_ASSEMBLYANNOTATIONWRITER_H - -namespace llvm { - -class Function; -class BasicBlock; -class Instruction; -class Value; -class formatted_raw_ostream; - -class AssemblyAnnotationWriter { -public: - virtual ~AssemblyAnnotationWriter(); - - /// emitFunctionAnnot - This may be implemented to emit a string right before - /// the start of a function. - virtual void emitFunctionAnnot(const Function *, - formatted_raw_ostream &) {} - - /// emitBasicBlockStartAnnot - This may be implemented to emit a string right - /// after the basic block label, but before the first instruction in the - /// block. - virtual void emitBasicBlockStartAnnot(const BasicBlock *, - formatted_raw_ostream &) { - } - - /// emitBasicBlockEndAnnot - This may be implemented to emit a string right - /// after the basic block. - virtual void emitBasicBlockEndAnnot(const BasicBlock *, - formatted_raw_ostream &) { - } - - /// emitInstructionAnnot - This may be implemented to emit a string right - /// before an instruction is emitted. - virtual void emitInstructionAnnot(const Instruction *, - formatted_raw_ostream &) {} - - /// printInfoComment - This may be implemented to emit a comment to the - /// right of an instruction or global value. - virtual void printInfoComment(const Value &, formatted_raw_ostream &) {} -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Assumptions.h b/suite/synctools/tablegen/include/llvm/IR/Assumptions.h deleted file mode 100644 index 08e6c8b6f1..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Assumptions.h +++ /dev/null @@ -1,70 +0,0 @@ -//===--- Assumptions.h - Assumption handling and organization ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// String assumptions that are known to optimization passes should be placed in -// the KnownAssumptionStrings set. This can be done in various ways, i.a., -// via a static KnownAssumptionString object. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_ASSUMPTIONS_H -#define LLVM_IR_ASSUMPTIONS_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" - -namespace llvm { - -class Function; -class CallBase; - -/// The key we use for assumption attributes. -constexpr StringRef AssumptionAttrKey = "llvm.assume"; - -/// A set of known assumption strings that are accepted without warning and -/// which can be recommended as typo correction. -extern StringSet<> KnownAssumptionStrings; - -/// Helper that allows to insert a new assumption string in the known assumption -/// set by creating a (static) object. -struct KnownAssumptionString { - KnownAssumptionString(StringRef AssumptionStr) - : AssumptionStr(AssumptionStr) { - KnownAssumptionStrings.insert(AssumptionStr); - } - operator StringRef() const { return AssumptionStr; } - -private: - StringRef AssumptionStr; -}; - -/// Return true if \p F has the assumption \p AssumptionStr attached. -bool hasAssumption(const Function &F, - const KnownAssumptionString &AssumptionStr); - -/// Return true if \p CB or the callee has the assumption \p AssumptionStr -/// attached. -bool hasAssumption(const CallBase &CB, - const KnownAssumptionString &AssumptionStr); - -/// Return the set of all assumptions for the function \p F. -DenseSet getAssumptions(const Function &F); - -/// Return the set of all assumptions for the call \p CB. -DenseSet getAssumptions(const CallBase &CB); - -/// Appends the set of assumptions \p Assumptions to \F. -bool addAssumptions(Function &F, const DenseSet &Assumptions); - -/// Appends the set of assumptions \p Assumptions to \CB. -bool addAssumptions(CallBase &CB, const DenseSet &Assumptions); - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Attributes.h b/suite/synctools/tablegen/include/llvm/IR/Attributes.h deleted file mode 100644 index b75917822f..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Attributes.h +++ /dev/null @@ -1,1237 +0,0 @@ -//===- llvm/Attributes.h - Container for Attributes -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file contains the simple types necessary to represent the -/// attributes associated with functions and their calls. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_ATTRIBUTES_H -#define LLVM_IR_ATTRIBUTES_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/PointerLikeTypeTraits.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class AttrBuilder; -class AttributeMask; -class AttributeImpl; -class AttributeListImpl; -class AttributeSetNode; -class FoldingSetNodeID; -class Function; -class LLVMContext; -class Type; - -//===----------------------------------------------------------------------===// -/// \class -/// Functions, function parameters, and return types can have attributes -/// to indicate how they should be treated by optimizations and code -/// generation. This class represents one of those attributes. It's light-weight -/// and should be passed around by-value. -class Attribute { -public: - /// This enumeration lists the attributes that can be associated with - /// parameters, function results, or the function itself. - /// - /// Note: The `uwtable' attribute is about the ABI or the user mandating an - /// entry in the unwind table. The `nounwind' attribute is about an exception - /// passing by the function. - /// - /// In a theoretical system that uses tables for profiling and SjLj for - /// exceptions, they would be fully independent. In a normal system that uses - /// tables for both, the semantics are: - /// - /// nil = Needs an entry because an exception might pass by. - /// nounwind = No need for an entry - /// uwtable = Needs an entry because the ABI says so and because - /// an exception might pass by. - /// uwtable + nounwind = Needs an entry because the ABI says so. - - enum AttrKind { - // IR-Level Attributes - None, ///< No attributes have been set - #define GET_ATTR_ENUM - #include "llvm/IR/Attributes.inc" - EndAttrKinds, ///< Sentinel value useful for loops - EmptyKey, ///< Use as Empty key for DenseMap of AttrKind - TombstoneKey, ///< Use as Tombstone key for DenseMap of AttrKind - }; - - static const unsigned NumIntAttrKinds = LastIntAttr - FirstIntAttr + 1; - static const unsigned NumTypeAttrKinds = LastTypeAttr - FirstTypeAttr + 1; - - static bool isEnumAttrKind(AttrKind Kind) { - return Kind >= FirstEnumAttr && Kind <= LastEnumAttr; - } - static bool isIntAttrKind(AttrKind Kind) { - return Kind >= FirstIntAttr && Kind <= LastIntAttr; - } - static bool isTypeAttrKind(AttrKind Kind) { - return Kind >= FirstTypeAttr && Kind <= LastTypeAttr; - } - - static bool canUseAsFnAttr(AttrKind Kind); - static bool canUseAsParamAttr(AttrKind Kind); - static bool canUseAsRetAttr(AttrKind Kind); - -private: - AttributeImpl *pImpl = nullptr; - - Attribute(AttributeImpl *A) : pImpl(A) {} - -public: - Attribute() = default; - - //===--------------------------------------------------------------------===// - // Attribute Construction - //===--------------------------------------------------------------------===// - - /// Return a uniquified Attribute object. - static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); - static Attribute get(LLVMContext &Context, StringRef Kind, - StringRef Val = StringRef()); - static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); - - /// Return a uniquified Attribute object that has the specific - /// alignment set. - static Attribute getWithAlignment(LLVMContext &Context, Align Alignment); - static Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment); - static Attribute getWithDereferenceableBytes(LLVMContext &Context, - uint64_t Bytes); - static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, - uint64_t Bytes); - static Attribute getWithAllocSizeArgs(LLVMContext &Context, - unsigned ElemSizeArg, - const Optional &NumElemsArg); - static Attribute getWithVScaleRangeArgs(LLVMContext &Context, - unsigned MinValue, unsigned MaxValue); - static Attribute getWithByValType(LLVMContext &Context, Type *Ty); - static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty); - static Attribute getWithByRefType(LLVMContext &Context, Type *Ty); - static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty); - static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty); - - /// For a typed attribute, return the equivalent attribute with the type - /// changed to \p ReplacementTy. - Attribute getWithNewType(LLVMContext &Context, Type *ReplacementTy) { - assert(isTypeAttribute() && "this requires a typed attribute"); - return get(Context, getKindAsEnum(), ReplacementTy); - } - - static Attribute::AttrKind getAttrKindFromName(StringRef AttrName); - - static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind); - - /// Return true if the provided string matches the IR name of an attribute. - /// example: "noalias" return true but not "NoAlias" - static bool isExistingAttribute(StringRef Name); - - //===--------------------------------------------------------------------===// - // Attribute Accessors - //===--------------------------------------------------------------------===// - - /// Return true if the attribute is an Attribute::AttrKind type. - bool isEnumAttribute() const; - - /// Return true if the attribute is an integer attribute. - bool isIntAttribute() const; - - /// Return true if the attribute is a string (target-dependent) - /// attribute. - bool isStringAttribute() const; - - /// Return true if the attribute is a type attribute. - bool isTypeAttribute() const; - - /// Return true if the attribute is any kind of attribute. - bool isValid() const { return pImpl; } - - /// Return true if the attribute is present. - bool hasAttribute(AttrKind Val) const; - - /// Return true if the target-dependent attribute is present. - bool hasAttribute(StringRef Val) const; - - /// Return the attribute's kind as an enum (Attribute::AttrKind). This - /// requires the attribute to be an enum, integer, or type attribute. - Attribute::AttrKind getKindAsEnum() const; - - /// Return the attribute's value as an integer. This requires that the - /// attribute be an integer attribute. - uint64_t getValueAsInt() const; - - /// Return the attribute's value as a boolean. This requires that the - /// attribute be a string attribute. - bool getValueAsBool() const; - - /// Return the attribute's kind as a string. This requires the - /// attribute to be a string attribute. - StringRef getKindAsString() const; - - /// Return the attribute's value as a string. This requires the - /// attribute to be a string attribute. - StringRef getValueAsString() const; - - /// Return the attribute's value as a Type. This requires the attribute to be - /// a type attribute. - Type *getValueAsType() const; - - /// Returns the alignment field of an attribute as a byte alignment - /// value. - MaybeAlign getAlignment() const; - - /// Returns the stack alignment field of an attribute as a byte - /// alignment value. - MaybeAlign getStackAlignment() const; - - /// Returns the number of dereferenceable bytes from the - /// dereferenceable attribute. - uint64_t getDereferenceableBytes() const; - - /// Returns the number of dereferenceable_or_null bytes from the - /// dereferenceable_or_null attribute. - uint64_t getDereferenceableOrNullBytes() const; - - /// Returns the argument numbers for the allocsize attribute (or pair(0, 0) - /// if not known). - std::pair> getAllocSizeArgs() const; - - /// Returns the minimum value for the vscale_range attribute. - unsigned getVScaleRangeMin() const; - - /// Returns the maximum value for the vscale_range attribute or None when - /// unknown. - Optional getVScaleRangeMax() const; - - /// The Attribute is converted to a string of equivalent mnemonic. This - /// is, presumably, for writing out the mnemonics for the assembly writer. - std::string getAsString(bool InAttrGrp = false) const; - - /// Return true if this attribute belongs to the LLVMContext. - bool hasParentContext(LLVMContext &C) const; - - /// Equality and non-equality operators. - bool operator==(Attribute A) const { return pImpl == A.pImpl; } - bool operator!=(Attribute A) const { return pImpl != A.pImpl; } - - /// Less-than operator. Useful for sorting the attributes list. - bool operator<(Attribute A) const; - - void Profile(FoldingSetNodeID &ID) const; - - /// Return a raw pointer that uniquely identifies this attribute. - void *getRawPointer() const { - return pImpl; - } - - /// Get an attribute from a raw pointer created by getRawPointer. - static Attribute fromRawPointer(void *RawPtr) { - return Attribute(reinterpret_cast(RawPtr)); - } -}; - -// Specialized opaque value conversions. -inline LLVMAttributeRef wrap(Attribute Attr) { - return reinterpret_cast(Attr.getRawPointer()); -} - -// Specialized opaque value conversions. -inline Attribute unwrap(LLVMAttributeRef Attr) { - return Attribute::fromRawPointer(Attr); -} - -//===----------------------------------------------------------------------===// -/// \class -/// This class holds the attributes for a particular argument, parameter, -/// function, or return value. It is an immutable value type that is cheap to -/// copy. Adding and removing enum attributes is intended to be fast, but adding -/// and removing string or integer attributes involves a FoldingSet lookup. -class AttributeSet { - friend AttributeListImpl; - template friend struct DenseMapInfo; - - // TODO: Extract AvailableAttrs from AttributeSetNode and store them here. - // This will allow an efficient implementation of addAttribute and - // removeAttribute for enum attrs. - - /// Private implementation pointer. - AttributeSetNode *SetNode = nullptr; - -private: - explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {} - -public: - /// AttributeSet is a trivially copyable value type. - AttributeSet() = default; - AttributeSet(const AttributeSet &) = default; - ~AttributeSet() = default; - - static AttributeSet get(LLVMContext &C, const AttrBuilder &B); - static AttributeSet get(LLVMContext &C, ArrayRef Attrs); - - bool operator==(const AttributeSet &O) const { return SetNode == O.SetNode; } - bool operator!=(const AttributeSet &O) const { return !(*this == O); } - - /// Add an argument attribute. Returns a new set because attribute sets are - /// immutable. - LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C, - Attribute::AttrKind Kind) const; - - /// Add a target-dependent attribute. Returns a new set because attribute sets - /// are immutable. - LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C, StringRef Kind, - StringRef Value = StringRef()) const; - - /// Add attributes to the attribute set. Returns a new set because attribute - /// sets are immutable. - LLVM_NODISCARD AttributeSet addAttributes(LLVMContext &C, - AttributeSet AS) const; - - /// Remove the specified attribute from this set. Returns a new set because - /// attribute sets are immutable. - LLVM_NODISCARD AttributeSet removeAttribute(LLVMContext &C, - Attribute::AttrKind Kind) const; - - /// Remove the specified attribute from this set. Returns a new set because - /// attribute sets are immutable. - LLVM_NODISCARD AttributeSet removeAttribute(LLVMContext &C, - StringRef Kind) const; - - /// Remove the specified attributes from this set. Returns a new set because - /// attribute sets are immutable. - LLVM_NODISCARD AttributeSet - removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const; - - /// Return the number of attributes in this set. - unsigned getNumAttributes() const; - - /// Return true if attributes exists in this set. - bool hasAttributes() const { return SetNode != nullptr; } - - /// Return true if the attribute exists in this set. - bool hasAttribute(Attribute::AttrKind Kind) const; - - /// Return true if the attribute exists in this set. - bool hasAttribute(StringRef Kind) const; - - /// Return the attribute object. - Attribute getAttribute(Attribute::AttrKind Kind) const; - - /// Return the target-dependent attribute object. - Attribute getAttribute(StringRef Kind) const; - - MaybeAlign getAlignment() const; - MaybeAlign getStackAlignment() const; - uint64_t getDereferenceableBytes() const; - uint64_t getDereferenceableOrNullBytes() const; - Type *getByValType() const; - Type *getStructRetType() const; - Type *getByRefType() const; - Type *getPreallocatedType() const; - Type *getInAllocaType() const; - Type *getElementType() const; - std::pair> getAllocSizeArgs() const; - unsigned getVScaleRangeMin() const; - Optional getVScaleRangeMax() const; - std::string getAsString(bool InAttrGrp = false) const; - - /// Return true if this attribute set belongs to the LLVMContext. - bool hasParentContext(LLVMContext &C) const; - - using iterator = const Attribute *; - - iterator begin() const; - iterator end() const; -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - void dump() const; -#endif -}; - -//===----------------------------------------------------------------------===// -/// \class -/// Provide DenseMapInfo for AttributeSet. -template <> struct DenseMapInfo { - static AttributeSet getEmptyKey() { - auto Val = static_cast(-1); - Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; - return AttributeSet(reinterpret_cast(Val)); - } - - static AttributeSet getTombstoneKey() { - auto Val = static_cast(-2); - Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; - return AttributeSet(reinterpret_cast(Val)); - } - - static unsigned getHashValue(AttributeSet AS) { - return (unsigned((uintptr_t)AS.SetNode) >> 4) ^ - (unsigned((uintptr_t)AS.SetNode) >> 9); - } - - static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; } -}; - -//===----------------------------------------------------------------------===// -/// \class -/// This class holds the attributes for a function, its return value, and -/// its parameters. You access the attributes for each of them via an index into -/// the AttributeList object. The function attributes are at index -/// `AttributeList::FunctionIndex', the return value is at index -/// `AttributeList::ReturnIndex', and the attributes for the parameters start at -/// index `AttributeList::FirstArgIndex'. -class AttributeList { -public: - enum AttrIndex : unsigned { - ReturnIndex = 0U, - FunctionIndex = ~0U, - FirstArgIndex = 1, - }; - -private: - friend class AttrBuilder; - friend class AttributeListImpl; - friend class AttributeSet; - friend class AttributeSetNode; - template friend struct DenseMapInfo; - - /// The attributes that we are managing. This can be null to represent - /// the empty attributes list. - AttributeListImpl *pImpl = nullptr; - -public: - /// Create an AttributeList with the specified parameters in it. - static AttributeList get(LLVMContext &C, - ArrayRef> Attrs); - static AttributeList get(LLVMContext &C, - ArrayRef> Attrs); - - /// Create an AttributeList from attribute sets for a function, its - /// return value, and all of its arguments. - static AttributeList get(LLVMContext &C, AttributeSet FnAttrs, - AttributeSet RetAttrs, - ArrayRef ArgAttrs); - -private: - explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {} - - static AttributeList getImpl(LLVMContext &C, ArrayRef AttrSets); - - AttributeList setAttributesAtIndex(LLVMContext &C, unsigned Index, - AttributeSet Attrs) const; - -public: - AttributeList() = default; - - //===--------------------------------------------------------------------===// - // AttributeList Construction and Mutation - //===--------------------------------------------------------------------===// - - /// Return an AttributeList with the specified parameters in it. - static AttributeList get(LLVMContext &C, ArrayRef Attrs); - static AttributeList get(LLVMContext &C, unsigned Index, - ArrayRef Kinds); - static AttributeList get(LLVMContext &C, unsigned Index, - ArrayRef Kinds, - ArrayRef Values); - static AttributeList get(LLVMContext &C, unsigned Index, - ArrayRef Kind); - static AttributeList get(LLVMContext &C, unsigned Index, - AttributeSet Attrs); - static AttributeList get(LLVMContext &C, unsigned Index, - const AttrBuilder &B); - - // TODO: remove non-AtIndex versions of these methods. - /// Add an attribute to the attribute set at the given index. - /// Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addAttributeAtIndex( - LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const; - - /// Add an attribute to the attribute set at the given index. - /// Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - addAttributeAtIndex(LLVMContext &C, unsigned Index, StringRef Kind, - StringRef Value = StringRef()) const; - - /// Add an attribute to the attribute set at the given index. - /// Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addAttributeAtIndex(LLVMContext &C, - unsigned Index, - Attribute A) const; - - /// Add attributes to the attribute set at the given index. - /// Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addAttributesAtIndex(LLVMContext &C, - unsigned Index, - const AttrBuilder &B) const; - - /// Add a function attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addFnAttribute(LLVMContext &C, - Attribute::AttrKind Kind) const { - return addAttributeAtIndex(C, FunctionIndex, Kind); - } - - /// Add a function attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addFnAttribute(LLVMContext &C, - Attribute Attr) const { - return addAttributeAtIndex(C, FunctionIndex, Attr); - } - - /// Add a function attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addFnAttribute( - LLVMContext &C, StringRef Kind, StringRef Value = StringRef()) const { - return addAttributeAtIndex(C, FunctionIndex, Kind, Value); - } - - /// Add function attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addFnAttributes(LLVMContext &C, - const AttrBuilder &B) const { - return addAttributesAtIndex(C, FunctionIndex, B); - } - - /// Add a return value attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addRetAttribute(LLVMContext &C, - Attribute::AttrKind Kind) const { - return addAttributeAtIndex(C, ReturnIndex, Kind); - } - - /// Add a return value attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addRetAttribute(LLVMContext &C, - Attribute Attr) const { - return addAttributeAtIndex(C, ReturnIndex, Attr); - } - - /// Add a return value attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addRetAttributes(LLVMContext &C, - const AttrBuilder &B) const { - return addAttributesAtIndex(C, ReturnIndex, B); - } - - /// Add an argument attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addParamAttribute( - LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const { - return addAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind); - } - - /// Add an argument attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList - addParamAttribute(LLVMContext &C, unsigned ArgNo, StringRef Kind, - StringRef Value = StringRef()) const { - return addAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind, Value); - } - - /// Add an attribute to the attribute list at the given arg indices. Returns a - /// new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addParamAttribute(LLVMContext &C, - ArrayRef ArgNos, - Attribute A) const; - - /// Add an argument attribute to the list. Returns a new list because - /// attribute lists are immutable. - LLVM_NODISCARD AttributeList addParamAttributes(LLVMContext &C, - unsigned ArgNo, - const AttrBuilder &B) const { - return addAttributesAtIndex(C, ArgNo + FirstArgIndex, B); - } - - /// Remove the specified attribute at the specified index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeAttributeAtIndex( - LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const; - - /// Remove the specified attribute at the specified index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeAttributeAtIndex(LLVMContext &C, - unsigned Index, - StringRef Kind) const; - LLVM_NODISCARD AttributeList removeAttribute(LLVMContext &C, unsigned Index, - StringRef Kind) const { - return removeAttributeAtIndex(C, Index, Kind); - } - - /// Remove the specified attributes at the specified index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeAttributesAtIndex( - LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const; - - /// Remove all attributes at the specified index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeAttributesAtIndex(LLVMContext &C, - unsigned Index) const; - - /// Remove the specified attribute at the function index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - removeFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const { - return removeAttributeAtIndex(C, FunctionIndex, Kind); - } - - /// Remove the specified attribute at the function index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeFnAttribute(LLVMContext &C, - StringRef Kind) const { - return removeAttributeAtIndex(C, FunctionIndex, Kind); - } - - /// Remove the specified attribute at the function index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - removeFnAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const { - return removeAttributesAtIndex(C, FunctionIndex, AttrsToRemove); - } - - /// Remove the attributes at the function index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeFnAttributes(LLVMContext &C) const { - return removeAttributesAtIndex(C, FunctionIndex); - } - - /// Remove the specified attribute at the return value index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - removeRetAttribute(LLVMContext &C, Attribute::AttrKind Kind) const { - return removeAttributeAtIndex(C, ReturnIndex, Kind); - } - - /// Remove the specified attribute at the return value index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeRetAttribute(LLVMContext &C, - StringRef Kind) const { - return removeAttributeAtIndex(C, ReturnIndex, Kind); - } - - /// Remove the specified attribute at the return value index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeRetAttributes( - LLVMContext &C, const AttributeMask &AttrsToRemove) const { - return removeAttributesAtIndex(C, ReturnIndex, AttrsToRemove); - } - - /// Remove the specified attribute at the specified arg index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeParamAttribute( - LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const { - return removeAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind); - } - - /// Remove the specified attribute at the specified arg index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeParamAttribute(LLVMContext &C, - unsigned ArgNo, - StringRef Kind) const { - return removeAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind); - } - - /// Remove the specified attribute at the specified arg index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - removeParamAttributes(LLVMContext &C, unsigned ArgNo, - const AttributeMask &AttrsToRemove) const { - return removeAttributesAtIndex(C, ArgNo + FirstArgIndex, AttrsToRemove); - } - - /// Remove all attributes at the specified arg index from this - /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeParamAttributes(LLVMContext &C, - unsigned ArgNo) const { - return removeAttributesAtIndex(C, ArgNo + FirstArgIndex); - } - - /// Replace the type contained by attribute \p AttrKind at index \p ArgNo with - /// \p ReplacementTy, preserving all other attributes. - LLVM_NODISCARD AttributeList replaceAttributeTypeAtIndex( - LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind, - Type *ReplacementTy) const { - Attribute Attr = getAttributeAtIndex(ArgNo, Kind); - auto Attrs = removeAttributeAtIndex(C, ArgNo, Kind); - return Attrs.addAttributeAtIndex(C, ArgNo, - Attr.getWithNewType(C, ReplacementTy)); - } - - /// \brief Add the dereferenceable attribute to the attribute set at the given - /// index. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addDereferenceableRetAttr(LLVMContext &C, - uint64_t Bytes) const; - - /// \brief Add the dereferenceable attribute to the attribute set at the given - /// arg index. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList addDereferenceableParamAttr( - LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const; - - /// Add the dereferenceable_or_null attribute to the attribute set at - /// the given arg index. Returns a new list because attribute lists are - /// immutable. - LLVM_NODISCARD AttributeList addDereferenceableOrNullParamAttr( - LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const; - - /// Add the allocsize attribute to the attribute set at the given arg index. - /// Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg, - const Optional &NumElemsArg); - - //===--------------------------------------------------------------------===// - // AttributeList Accessors - //===--------------------------------------------------------------------===// - - /// The attributes for the specified index are returned. - AttributeSet getAttributes(unsigned Index) const; - - /// The attributes for the argument or parameter at the given index are - /// returned. - AttributeSet getParamAttrs(unsigned ArgNo) const; - - /// The attributes for the ret value are returned. - AttributeSet getRetAttrs() const; - - /// The function attributes are returned. - AttributeSet getFnAttrs() const; - - /// Return true if the attribute exists at the given index. - bool hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const; - - /// Return true if the attribute exists at the given index. - bool hasAttributeAtIndex(unsigned Index, StringRef Kind) const; - - /// Return true if attribute exists at the given index. - bool hasAttributesAtIndex(unsigned Index) const; - - /// Return true if the attribute exists for the given argument - bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { - return hasAttributeAtIndex(ArgNo + FirstArgIndex, Kind); - } - - /// Return true if the attribute exists for the given argument - bool hasParamAttr(unsigned ArgNo, StringRef Kind) const { - return hasAttributeAtIndex(ArgNo + FirstArgIndex, Kind); - } - - /// Return true if attributes exists for the given argument - bool hasParamAttrs(unsigned ArgNo) const { - return hasAttributesAtIndex(ArgNo + FirstArgIndex); - } - - /// Return true if the attribute exists for the return value. - bool hasRetAttr(Attribute::AttrKind Kind) const { - return hasAttributeAtIndex(ReturnIndex, Kind); - } - - /// Return true if the attribute exists for the return value. - bool hasRetAttr(StringRef Kind) const { - return hasAttributeAtIndex(ReturnIndex, Kind); - } - - /// Return true if attributes exist for the return value. - bool hasRetAttrs() const { return hasAttributesAtIndex(ReturnIndex); } - - /// Return true if the attribute exists for the function. - bool hasFnAttr(Attribute::AttrKind Kind) const; - - /// Return true if the attribute exists for the function. - bool hasFnAttr(StringRef Kind) const; - - /// Return true the attributes exist for the function. - bool hasFnAttrs() const { return hasAttributesAtIndex(FunctionIndex); } - - /// Return true if the specified attribute is set for at least one - /// parameter or for the return value. If Index is not nullptr, the index - /// of a parameter with the specified attribute is provided. - bool hasAttrSomewhere(Attribute::AttrKind Kind, - unsigned *Index = nullptr) const; - - /// Return the attribute object that exists at the given index. - Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const; - - /// Return the attribute object that exists at the given index. - Attribute getAttributeAtIndex(unsigned Index, StringRef Kind) const; - - /// Return the attribute object that exists at the arg index. - Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { - return getAttributeAtIndex(ArgNo + FirstArgIndex, Kind); - } - - /// Return the attribute object that exists at the given index. - Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const { - return getAttributeAtIndex(ArgNo + FirstArgIndex, Kind); - } - - /// Return the attribute object that exists for the function. - Attribute getFnAttr(Attribute::AttrKind Kind) const { - return getAttributeAtIndex(FunctionIndex, Kind); - } - - /// Return the attribute object that exists for the function. - Attribute getFnAttr(StringRef Kind) const { - return getAttributeAtIndex(FunctionIndex, Kind); - } - - /// Return the alignment of the return value. - MaybeAlign getRetAlignment() const; - - /// Return the alignment for the specified function parameter. - MaybeAlign getParamAlignment(unsigned ArgNo) const; - - /// Return the stack alignment for the specified function parameter. - MaybeAlign getParamStackAlignment(unsigned ArgNo) const; - - /// Return the byval type for the specified function parameter. - Type *getParamByValType(unsigned ArgNo) const; - - /// Return the sret type for the specified function parameter. - Type *getParamStructRetType(unsigned ArgNo) const; - - /// Return the byref type for the specified function parameter. - Type *getParamByRefType(unsigned ArgNo) const; - - /// Return the preallocated type for the specified function parameter. - Type *getParamPreallocatedType(unsigned ArgNo) const; - - /// Return the inalloca type for the specified function parameter. - Type *getParamInAllocaType(unsigned ArgNo) const; - - /// Return the elementtype type for the specified function parameter. - Type *getParamElementType(unsigned ArgNo) const; - - /// Get the stack alignment of the function. - MaybeAlign getFnStackAlignment() const; - - /// Get the stack alignment of the return value. - MaybeAlign getRetStackAlignment() const; - - /// Get the number of dereferenceable bytes (or zero if unknown) of the return - /// value. - uint64_t getRetDereferenceableBytes() const; - - /// Get the number of dereferenceable bytes (or zero if unknown) of an arg. - uint64_t getParamDereferenceableBytes(unsigned Index) const; - - /// Get the number of dereferenceable_or_null bytes (or zero if unknown) of - /// the return value. - uint64_t getRetDereferenceableOrNullBytes() const; - - /// Get the number of dereferenceable_or_null bytes (or zero if unknown) of an - /// arg. - uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const; - - /// Return the attributes at the index as a string. - std::string getAsString(unsigned Index, bool InAttrGrp = false) const; - - /// Return true if this attribute list belongs to the LLVMContext. - bool hasParentContext(LLVMContext &C) const; - - //===--------------------------------------------------------------------===// - // AttributeList Introspection - //===--------------------------------------------------------------------===// - - using iterator = const AttributeSet *; - - iterator begin() const; - iterator end() const; - - unsigned getNumAttrSets() const; - - // Implementation of indexes(). Produces iterators that wrap an index. Mostly - // to hide the awkwardness of unsigned wrapping when iterating over valid - // indexes. - struct index_iterator { - unsigned NumAttrSets; - index_iterator(int NumAttrSets) : NumAttrSets(NumAttrSets) {} - struct int_wrapper { - int_wrapper(unsigned i) : i(i) {} - unsigned i; - unsigned operator*() { return i; } - bool operator!=(const int_wrapper &Other) { return i != Other.i; } - int_wrapper &operator++() { - // This is expected to undergo unsigned wrapping since FunctionIndex is - // ~0 and that's where we start. - ++i; - return *this; - } - }; - - int_wrapper begin() { return int_wrapper(AttributeList::FunctionIndex); } - - int_wrapper end() { return int_wrapper(NumAttrSets - 1); } - }; - - /// Use this to iterate over the valid attribute indexes. - index_iterator indexes() const { return index_iterator(getNumAttrSets()); } - - /// operator==/!= - Provide equality predicates. - bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; } - bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; } - - /// Return a raw pointer that uniquely identifies this attribute list. - void *getRawPointer() const { - return pImpl; - } - - /// Return true if there are no attributes. - bool isEmpty() const { return pImpl == nullptr; } - - void print(raw_ostream &O) const; - - void dump() const; -}; - -//===----------------------------------------------------------------------===// -/// \class -/// Provide DenseMapInfo for AttributeList. -template <> struct DenseMapInfo { - static AttributeList getEmptyKey() { - auto Val = static_cast(-1); - Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; - return AttributeList(reinterpret_cast(Val)); - } - - static AttributeList getTombstoneKey() { - auto Val = static_cast(-2); - Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; - return AttributeList(reinterpret_cast(Val)); - } - - static unsigned getHashValue(AttributeList AS) { - return (unsigned((uintptr_t)AS.pImpl) >> 4) ^ - (unsigned((uintptr_t)AS.pImpl) >> 9); - } - - static bool isEqual(AttributeList LHS, AttributeList RHS) { - return LHS == RHS; - } -}; - -//===----------------------------------------------------------------------===// -/// \class -/// This class stores enough information to efficiently remove some attributes -/// from an existing AttrBuilder, AttributeSet or AttributeList. -class AttributeMask { - std::bitset Attrs; - std::set, std::less<>> TargetDepAttrs; - -public: - AttributeMask() = default; - AttributeMask(const AttributeMask &) = delete; - AttributeMask(AttributeMask &&) = default; - - AttributeMask(AttributeSet AS) { - for (Attribute A : AS) - addAttribute(A); - } - - /// Add an attribute to the mask. - AttributeMask &addAttribute(Attribute::AttrKind Val) { - assert((unsigned)Val < Attribute::EndAttrKinds && - "Attribute out of range!"); - Attrs[Val] = true; - return *this; - } - - /// Add the Attribute object to the builder. - AttributeMask &addAttribute(Attribute A) { - if (A.isStringAttribute()) - addAttribute(A.getKindAsString()); - else - addAttribute(A.getKindAsEnum()); - return *this; - } - - /// Add the target-dependent attribute to the builder. - AttributeMask &addAttribute(StringRef A) { - TargetDepAttrs.insert(A); - return *this; - } - - /// Return true if the builder has the specified attribute. - bool contains(Attribute::AttrKind A) const { - assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); - return Attrs[A]; - } - - /// Return true if the builder has the specified target-dependent - /// attribute. - bool contains(StringRef A) const { return TargetDepAttrs.count(A); } - - /// Return true if the mask contains the specified attribute. - bool contains(Attribute A) const { - if (A.isStringAttribute()) - return contains(A.getKindAsString()); - return contains(A.getKindAsEnum()); - } -}; - -//===----------------------------------------------------------------------===// -/// \class -/// This class is used in conjunction with the Attribute::get method to -/// create an Attribute object. The object itself is uniquified. The Builder's -/// value, however, is not. So this can be used as a quick way to test for -/// equality, presence of attributes, etc. -class AttrBuilder { - LLVMContext &Ctx; - SmallVector Attrs; - -public: - AttrBuilder(LLVMContext &Ctx) : Ctx(Ctx) {} - AttrBuilder(const AttrBuilder &) = delete; - AttrBuilder(AttrBuilder &&) = default; - - AttrBuilder(LLVMContext &Ctx, const Attribute &A) : Ctx(Ctx) { - addAttribute(A); - } - - AttrBuilder(LLVMContext &Ctx, AttributeSet AS); - - void clear(); - - /// Add an attribute to the builder. - AttrBuilder &addAttribute(Attribute::AttrKind Val); - - /// Add the Attribute object to the builder. - AttrBuilder &addAttribute(Attribute A); - - /// Add the target-dependent attribute to the builder. - AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); - - /// Remove an attribute from the builder. - AttrBuilder &removeAttribute(Attribute::AttrKind Val); - - /// Remove the target-dependent attribute from the builder. - AttrBuilder &removeAttribute(StringRef A); - - /// Remove the target-dependent attribute from the builder. - AttrBuilder &removeAttribute(Attribute A) { - if (A.isStringAttribute()) - return removeAttribute(A.getKindAsString()); - else - return removeAttribute(A.getKindAsEnum()); - } - - /// Add the attributes from the builder. Attributes in the passed builder - /// overwrite attributes in this builder if they have the same key. - AttrBuilder &merge(const AttrBuilder &B); - - /// Remove the attributes from the builder. - AttrBuilder &remove(const AttributeMask &AM); - - /// Return true if the builder has any attribute that's in the - /// specified builder. - bool overlaps(const AttributeMask &AM) const; - - /// Return true if the builder has the specified attribute. - bool contains(Attribute::AttrKind A) const; - - /// Return true if the builder has the specified target-dependent - /// attribute. - bool contains(StringRef A) const; - - /// Return true if the builder has IR-level attributes. - bool hasAttributes() const { return !Attrs.empty(); } - - /// Return true if the builder has an alignment attribute. - bool hasAlignmentAttr() const; - - /// Return Attribute with the given Kind. The returned attribute will be - /// invalid if the Kind is not present in the builder. - Attribute getAttribute(Attribute::AttrKind Kind) const; - - /// Return Attribute with the given Kind. The returned attribute will be - /// invalid if the Kind is not present in the builder. - Attribute getAttribute(StringRef Kind) const; - - /// Return raw (possibly packed/encoded) value of integer attribute or 0 if - /// not set. - uint64_t getRawIntAttr(Attribute::AttrKind Kind) const; - - /// Retrieve the alignment attribute, if it exists. - MaybeAlign getAlignment() const { - return MaybeAlign(getRawIntAttr(Attribute::Alignment)); - } - - /// Retrieve the stack alignment attribute, if it exists. - MaybeAlign getStackAlignment() const { - return MaybeAlign(getRawIntAttr(Attribute::StackAlignment)); - } - - /// Retrieve the number of dereferenceable bytes, if the - /// dereferenceable attribute exists (zero is returned otherwise). - uint64_t getDereferenceableBytes() const { - return getRawIntAttr(Attribute::Dereferenceable); - } - - /// Retrieve the number of dereferenceable_or_null bytes, if the - /// dereferenceable_or_null attribute exists (zero is returned otherwise). - uint64_t getDereferenceableOrNullBytes() const { - return getRawIntAttr(Attribute::DereferenceableOrNull); - } - - /// Retrieve type for the given type attribute. - Type *getTypeAttr(Attribute::AttrKind Kind) const; - - /// Retrieve the byval type. - Type *getByValType() const { return getTypeAttr(Attribute::ByVal); } - - /// Retrieve the sret type. - Type *getStructRetType() const { return getTypeAttr(Attribute::StructRet); } - - /// Retrieve the byref type. - Type *getByRefType() const { return getTypeAttr(Attribute::ByRef); } - - /// Retrieve the preallocated type. - Type *getPreallocatedType() const { - return getTypeAttr(Attribute::Preallocated); - } - - /// Retrieve the inalloca type. - Type *getInAllocaType() const { return getTypeAttr(Attribute::InAlloca); } - - /// Retrieve the allocsize args, if the allocsize attribute exists. If it - /// doesn't exist, pair(0, 0) is returned. - std::pair> getAllocSizeArgs() const; - - /// Retrieve the minimum value of 'vscale_range'. - unsigned getVScaleRangeMin() const; - - /// Retrieve the maximum value of 'vscale_range' or None when unknown. - Optional getVScaleRangeMax() const; - - /// Add integer attribute with raw value (packed/encoded if necessary). - AttrBuilder &addRawIntAttr(Attribute::AttrKind Kind, uint64_t Value); - - /// This turns an alignment into the form used internally in Attribute. - /// This call has no effect if Align is not set. - AttrBuilder &addAlignmentAttr(MaybeAlign Align); - - /// This turns an int alignment (which must be a power of 2) into the - /// form used internally in Attribute. - /// This call has no effect if Align is 0. - /// Deprecated, use the version using a MaybeAlign. - inline AttrBuilder &addAlignmentAttr(unsigned Align) { - return addAlignmentAttr(MaybeAlign(Align)); - } - - /// This turns a stack alignment into the form used internally in Attribute. - /// This call has no effect if Align is not set. - AttrBuilder &addStackAlignmentAttr(MaybeAlign Align); - - /// This turns an int stack alignment (which must be a power of 2) into - /// the form used internally in Attribute. - /// This call has no effect if Align is 0. - /// Deprecated, use the version using a MaybeAlign. - inline AttrBuilder &addStackAlignmentAttr(unsigned Align) { - return addStackAlignmentAttr(MaybeAlign(Align)); - } - - /// This turns the number of dereferenceable bytes into the form used - /// internally in Attribute. - AttrBuilder &addDereferenceableAttr(uint64_t Bytes); - - /// This turns the number of dereferenceable_or_null bytes into the - /// form used internally in Attribute. - AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); - - /// This turns one (or two) ints into the form used internally in Attribute. - AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg, - const Optional &NumElemsArg); - - /// This turns two ints into the form used internally in Attribute. - AttrBuilder &addVScaleRangeAttr(unsigned MinValue, - Optional MaxValue); - - /// Add a type attribute with the given type. - AttrBuilder &addTypeAttr(Attribute::AttrKind Kind, Type *Ty); - - /// This turns a byval type into the form used internally in Attribute. - AttrBuilder &addByValAttr(Type *Ty); - - /// This turns a sret type into the form used internally in Attribute. - AttrBuilder &addStructRetAttr(Type *Ty); - - /// This turns a byref type into the form used internally in Attribute. - AttrBuilder &addByRefAttr(Type *Ty); - - /// This turns a preallocated type into the form used internally in Attribute. - AttrBuilder &addPreallocatedAttr(Type *Ty); - - /// This turns an inalloca type into the form used internally in Attribute. - AttrBuilder &addInAllocaAttr(Type *Ty); - - /// Add an allocsize attribute, using the representation returned by - /// Attribute.getIntValue(). - AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr); - - /// Add a vscale_range attribute, using the representation returned by - /// Attribute.getIntValue(). - AttrBuilder &addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr); - - ArrayRef attrs() const { return Attrs; } - - bool operator==(const AttrBuilder &B) const; - bool operator!=(const AttrBuilder &B) const { return !(*this == B); } -}; - -namespace AttributeFuncs { - -/// Which attributes cannot be applied to a type. -AttributeMask typeIncompatible(Type *Ty); - -/// Get param/return attributes which imply immediate undefined behavior if an -/// invalid value is passed. For example, this includes noundef (where undef -/// implies UB), but not nonnull (where null implies poison). It also does not -/// include attributes like nocapture, which constrain the function -/// implementation rather than the passed value. -AttributeMask getUBImplyingAttributes(); - -/// \returns Return true if the two functions have compatible target-independent -/// attributes for inlining purposes. -bool areInlineCompatible(const Function &Caller, const Function &Callee); - - -/// Checks if there are any incompatible function attributes between -/// \p A and \p B. -/// -/// \param [in] A - The first function to be compared with. -/// \param [in] B - The second function to be compared with. -/// \returns true if the functions have compatible attributes. -bool areOutlineCompatible(const Function &A, const Function &B); - -/// Merge caller's and callee's attributes. -void mergeAttributesForInlining(Function &Caller, const Function &Callee); - -/// Merges the functions attributes from \p ToMerge into function \p Base. -/// -/// \param [in,out] Base - The function being merged into. -/// \param [in] ToMerge - The function to merge attributes from. -void mergeAttributesForOutlining(Function &Base, const Function &ToMerge); - -} // end namespace AttributeFuncs - -} // end namespace llvm - -#endif // LLVM_IR_ATTRIBUTES_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Attributes.td b/suite/synctools/tablegen/include/llvm/IR/Attributes.td deleted file mode 100644 index 40c554c269..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Attributes.td +++ /dev/null @@ -1,350 +0,0 @@ -//===- Attributes.td - Defines all LLVM attributes ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all the LLVM attributes. -// -//===----------------------------------------------------------------------===// - -/// Attribute property base class. -class AttrProperty; - -/// Can be used as function attribute. -def FnAttr : AttrProperty; - -/// Can be used as parameter attribute. -def ParamAttr : AttrProperty; - -/// Can be used as return attribute. -def RetAttr : AttrProperty; - -/// Attribute base class. -class Attr P> { - // String representation of this attribute in the IR. - string AttrString = S; - list Properties = P; -} - -/// Enum attribute. -class EnumAttr P> : Attr; - -/// Int attribute. -class IntAttr P> : Attr; - -/// Type attribute. -class TypeAttr P> : Attr; - -/// StringBool attribute. -class StrBoolAttr : Attr; - -/// Target-independent enum attributes. - -/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias. -/// 0 means unaligned (different from align(1)). -def Alignment : IntAttr<"align", [ParamAttr, RetAttr]>; - -/// The result of the function is guaranteed to point to a number of bytes that -/// we can determine if we know the value of the function's arguments. -def AllocSize : IntAttr<"allocsize", [FnAttr]>; - -/// inline=always. -def AlwaysInline : EnumAttr<"alwaysinline", [FnAttr]>; - -/// Function can access memory only using pointers based on its arguments. -def ArgMemOnly : EnumAttr<"argmemonly", [FnAttr]>; - -/// Callee is recognized as a builtin, despite nobuiltin attribute on its -/// declaration. -def Builtin : EnumAttr<"builtin", [FnAttr]>; - -/// Pass structure by value. -def ByVal : TypeAttr<"byval", [ParamAttr]>; - -/// Mark in-memory ABI type. -def ByRef : TypeAttr<"byref", [ParamAttr]>; - -/// Parameter or return value may not contain uninitialized or poison bits. -def NoUndef : EnumAttr<"noundef", [ParamAttr, RetAttr]>; - -/// Marks function as being in a cold path. -def Cold : EnumAttr<"cold", [FnAttr]>; - -/// Can only be moved to control-equivalent blocks. -def Convergent : EnumAttr<"convergent", [FnAttr]>; - -/// Marks function as being in a hot path and frequently called. -def Hot: EnumAttr<"hot", [FnAttr]>; - -/// Pointer is known to be dereferenceable. -def Dereferenceable : IntAttr<"dereferenceable", [ParamAttr, RetAttr]>; - -/// Pointer is either null or dereferenceable. -def DereferenceableOrNull : IntAttr<"dereferenceable_or_null", - [ParamAttr, RetAttr]>; - -/// Do not instrument function with sanitizers. -def DisableSanitizerInstrumentation: EnumAttr<"disable_sanitizer_instrumentation", [FnAttr]>; - -/// Provide pointer element type to intrinsic. -def ElementType : TypeAttr<"elementtype", [ParamAttr]>; - -/// Function may only access memory that is inaccessible from IR. -def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>; - -/// Function may only access memory that is either inaccessible from the IR, -/// or pointed to by its pointer arguments. -def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly", - [FnAttr]>; - -/// Pass structure in an alloca. -def InAlloca : TypeAttr<"inalloca", [ParamAttr]>; - -/// Source said inlining was desirable. -def InlineHint : EnumAttr<"inlinehint", [FnAttr]>; - -/// Force argument to be passed in register. -def InReg : EnumAttr<"inreg", [ParamAttr, RetAttr]>; - -/// Build jump-instruction tables and replace refs. -def JumpTable : EnumAttr<"jumptable", [FnAttr]>; - -/// Function must be optimized for size first. -def MinSize : EnumAttr<"minsize", [FnAttr]>; - -/// Naked function. -def Naked : EnumAttr<"naked", [FnAttr]>; - -/// Nested function static chain. -def Nest : EnumAttr<"nest", [ParamAttr]>; - -/// Considered to not alias after call. -def NoAlias : EnumAttr<"noalias", [ParamAttr, RetAttr]>; - -/// Callee isn't recognized as a builtin. -def NoBuiltin : EnumAttr<"nobuiltin", [FnAttr]>; - -/// Function cannot enter into caller's translation unit. -def NoCallback : EnumAttr<"nocallback", [FnAttr]>; - -/// Function creates no aliases of pointer. -def NoCapture : EnumAttr<"nocapture", [ParamAttr]>; - -/// Call cannot be duplicated. -def NoDuplicate : EnumAttr<"noduplicate", [FnAttr]>; - -/// Function does not deallocate memory. -def NoFree : EnumAttr<"nofree", [FnAttr, ParamAttr]>; - -/// Disable implicit floating point insts. -def NoImplicitFloat : EnumAttr<"noimplicitfloat", [FnAttr]>; - -/// inline=never. -def NoInline : EnumAttr<"noinline", [FnAttr]>; - -/// Function is called early and/or often, so lazy binding isn't worthwhile. -def NonLazyBind : EnumAttr<"nonlazybind", [FnAttr]>; - -/// Disable merging for specified functions or call sites. -def NoMerge : EnumAttr<"nomerge", [FnAttr]>; - -/// Pointer is known to be not null. -def NonNull : EnumAttr<"nonnull", [ParamAttr, RetAttr]>; - -/// The function does not recurse. -def NoRecurse : EnumAttr<"norecurse", [FnAttr]>; - -/// Disable redzone. -def NoRedZone : EnumAttr<"noredzone", [FnAttr]>; - -/// Mark the function as not returning. -def NoReturn : EnumAttr<"noreturn", [FnAttr]>; - -/// Function does not synchronize. -def NoSync : EnumAttr<"nosync", [FnAttr]>; - -/// Disable Indirect Branch Tracking. -def NoCfCheck : EnumAttr<"nocf_check", [FnAttr]>; - -/// Function should not be instrumented. -def NoProfile : EnumAttr<"noprofile", [FnAttr]>; - -/// Function doesn't unwind stack. -def NoUnwind : EnumAttr<"nounwind", [FnAttr]>; - -/// No SanitizeCoverage instrumentation. -def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage", [FnAttr]>; - -/// Null pointer in address space zero is valid. -def NullPointerIsValid : EnumAttr<"null_pointer_is_valid", [FnAttr]>; - -/// Select optimizations for best fuzzing signal. -def OptForFuzzing : EnumAttr<"optforfuzzing", [FnAttr]>; - -/// opt_size. -def OptimizeForSize : EnumAttr<"optsize", [FnAttr]>; - -/// Function must not be optimized. -def OptimizeNone : EnumAttr<"optnone", [FnAttr]>; - -/// Similar to byval but without a copy. -def Preallocated : TypeAttr<"preallocated", [FnAttr, ParamAttr]>; - -/// Function does not access memory. -def ReadNone : EnumAttr<"readnone", [FnAttr, ParamAttr]>; - -/// Function only reads from memory. -def ReadOnly : EnumAttr<"readonly", [FnAttr, ParamAttr]>; - -/// Return value is always equal to this argument. -def Returned : EnumAttr<"returned", [ParamAttr]>; - -/// Parameter is required to be a trivial constant. -def ImmArg : EnumAttr<"immarg", [ParamAttr]>; - -/// Function can return twice. -def ReturnsTwice : EnumAttr<"returns_twice", [FnAttr]>; - -/// Safe Stack protection. -def SafeStack : EnumAttr<"safestack", [FnAttr]>; - -/// Shadow Call Stack protection. -def ShadowCallStack : EnumAttr<"shadowcallstack", [FnAttr]>; - -/// Sign extended before/after call. -def SExt : EnumAttr<"signext", [ParamAttr, RetAttr]>; - -/// Alignment of stack for function (3 bits) stored as log2 of alignment with -/// +1 bias 0 means unaligned (different from alignstack=(1)). -def StackAlignment : IntAttr<"alignstack", [FnAttr, ParamAttr]>; - -/// Function can be speculated. -def Speculatable : EnumAttr<"speculatable", [FnAttr]>; - -/// Stack protection. -def StackProtect : EnumAttr<"ssp", [FnAttr]>; - -/// Stack protection required. -def StackProtectReq : EnumAttr<"sspreq", [FnAttr]>; - -/// Strong Stack protection. -def StackProtectStrong : EnumAttr<"sspstrong", [FnAttr]>; - -/// Function was called in a scope requiring strict floating point semantics. -def StrictFP : EnumAttr<"strictfp", [FnAttr]>; - -/// Hidden pointer to structure to return. -def StructRet : TypeAttr<"sret", [ParamAttr]>; - -/// AddressSanitizer is on. -def SanitizeAddress : EnumAttr<"sanitize_address", [FnAttr]>; - -/// ThreadSanitizer is on. -def SanitizeThread : EnumAttr<"sanitize_thread", [FnAttr]>; - -/// MemorySanitizer is on. -def SanitizeMemory : EnumAttr<"sanitize_memory", [FnAttr]>; - -/// HWAddressSanitizer is on. -def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress", [FnAttr]>; - -/// MemTagSanitizer is on. -def SanitizeMemTag : EnumAttr<"sanitize_memtag", [FnAttr]>; - -/// Speculative Load Hardening is enabled. -/// -/// Note that this uses the default compatibility (always compatible during -/// inlining) and a conservative merge strategy where inlining an attributed -/// body will add the attribute to the caller. This ensures that code carrying -/// this attribute will always be lowered with hardening enabled. -def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening", - [FnAttr]>; - -/// Argument is swift error. -def SwiftError : EnumAttr<"swifterror", [ParamAttr]>; - -/// Argument is swift self/context. -def SwiftSelf : EnumAttr<"swiftself", [ParamAttr]>; - -/// Argument is swift async context. -def SwiftAsync : EnumAttr<"swiftasync", [ParamAttr]>; - -/// Function must be in a unwind table. -def UWTable : EnumAttr<"uwtable", [FnAttr]>; - -/// Minimum/Maximum vscale value for function. -def VScaleRange : IntAttr<"vscale_range", [FnAttr]>; - -/// Function always comes back to callsite. -def WillReturn : EnumAttr<"willreturn", [FnAttr]>; - -/// Function only writes to memory. -def WriteOnly : EnumAttr<"writeonly", [FnAttr, ParamAttr]>; - -/// Zero extended before/after call. -def ZExt : EnumAttr<"zeroext", [ParamAttr, RetAttr]>; - -/// Function is required to make Forward Progress. -def MustProgress : EnumAttr<"mustprogress", [FnAttr]>; - -/// Target-independent string attributes. -def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">; -def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">; -def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">; -def NoSignedZerosFPMath : StrBoolAttr<"no-signed-zeros-fp-math">; -def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">; -def NoJumpTables : StrBoolAttr<"no-jump-tables">; -def NoInlineLineTables : StrBoolAttr<"no-inline-line-tables">; -def ProfileSampleAccurate : StrBoolAttr<"profile-sample-accurate">; -def UseSampleProfile : StrBoolAttr<"use-sample-profile">; - -class CompatRule { - // The name of the function called to check the attribute of the caller and - // callee and decide whether inlining should be allowed. The function's - // signature must match "bool(const Function&, const Function &)", where the - // first parameter is the reference to the caller and the second parameter is - // the reference to the callee. It must return false if the attributes of the - // caller and callee are incompatible, and true otherwise. - string CompatFunc = F; -} - -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; -def : CompatRule<"isEqual">; - -class MergeRule { - // The name of the function called to merge the attributes of the caller and - // callee. The function's signature must match - // "void(Function&, const Function &)", where the first parameter is the - // reference to the caller and the second parameter is the reference to the - // callee. - string MergeFunc = F; -} - -def : MergeRule<"setAND">; -def : MergeRule<"setAND">; -def : MergeRule<"setAND">; -def : MergeRule<"setAND">; -def : MergeRule<"setAND">; -def : MergeRule<"setOR">; -def : MergeRule<"setOR">; -def : MergeRule<"setOR">; -def : MergeRule<"setOR">; -def : MergeRule<"adjustCallerSSPLevel">; -def : MergeRule<"adjustCallerStackProbes">; -def : MergeRule<"adjustCallerStackProbeSize">; -def : MergeRule<"adjustMinLegalVectorWidth">; -def : MergeRule<"adjustNullPointerValidAttr">; -def : MergeRule<"setAND">; - -// Target dependent attributes -include "llvm/IR/AttributesAMDGPU.td" diff --git a/suite/synctools/tablegen/include/llvm/IR/AttributesAMDGPU.td b/suite/synctools/tablegen/include/llvm/IR/AttributesAMDGPU.td deleted file mode 100644 index e2a0f045b6..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/AttributesAMDGPU.td +++ /dev/null @@ -1,14 +0,0 @@ -//===- AttributesAMDGPU.td - Defines AMDGPU attributes -----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines AMDGPU specific attributes. -// -//===----------------------------------------------------------------------===// - -def AMDGPUUnsafeFPAtomics : StrBoolAttr<"amdgpu-unsafe-fp-atomics">; -def : MergeRule<"setAND">; diff --git a/suite/synctools/tablegen/include/llvm/IR/AutoUpgrade.h b/suite/synctools/tablegen/include/llvm/IR/AutoUpgrade.h deleted file mode 100644 index 1e13e5be65..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/AutoUpgrade.h +++ /dev/null @@ -1,103 +0,0 @@ -//===- AutoUpgrade.h - AutoUpgrade Helpers ----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// These functions are implemented by lib/IR/AutoUpgrade.cpp. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_AUTOUPGRADE_H -#define LLVM_IR_AUTOUPGRADE_H - -#include "llvm/ADT/StringRef.h" - -namespace llvm { - class AttrBuilder; - class CallInst; - class Constant; - class Function; - class Instruction; - class MDNode; - class Module; - class GlobalVariable; - class Type; - class Value; - - /// This is a more granular function that simply checks an intrinsic function - /// for upgrading, and returns true if it requires upgrading. It may return - /// null in NewFn if the all calls to the original intrinsic function - /// should be transformed to non-function-call instructions. - bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); - - /// This is the complement to the above, replacing a specific call to an - /// intrinsic function with a call to the specified new function. - void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); - - // This upgrades the comment for objc retain release markers in inline asm - // calls - void UpgradeInlineAsmString(std::string *AsmStr); - - /// This is an auto-upgrade hook for any old intrinsic function syntaxes - /// which need to have both the function updated as well as all calls updated - /// to the new function. This should only be run in a post-processing fashion - /// so that it can update all calls to the old function. - void UpgradeCallsToIntrinsic(Function* F); - - /// This checks for global variables which should be upgraded. It is requires - /// upgrading, returns a pointer to the upgraded variable. - GlobalVariable *UpgradeGlobalVariable(GlobalVariable *GV); - - /// This checks for module flags which should be upgraded. It returns true if - /// module is modified. - bool UpgradeModuleFlags(Module &M); - - /// Convert calls to ARC runtime functions to intrinsic calls and upgrade the - /// old retain release marker to new module flag format. - void UpgradeARCRuntime(Module &M); - - void UpgradeSectionAttributes(Module &M); - - /// Correct any IR that is relying on old function attribute behavior. - void UpgradeFunctionAttributes(Function &F); - - /// If the given TBAA tag uses the scalar TBAA format, create a new node - /// corresponding to the upgrade to the struct-path aware TBAA format. - /// Otherwise return the \p TBAANode itself. - MDNode *UpgradeTBAANode(MDNode &TBAANode); - - /// This is an auto-upgrade for bitcast between pointers with different - /// address spaces: the instruction is replaced by a pair ptrtoint+inttoptr. - Instruction *UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy, - Instruction *&Temp); - - /// This is an auto-upgrade for bitcast constant expression between pointers - /// with different address spaces: the instruction is replaced by a pair - /// ptrtoint+inttoptr. - Value *UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy); - - /// Check the debug info version number, if it is out-dated, drop the debug - /// info. Return true if module is modified. - bool UpgradeDebugInfo(Module &M); - - /// Check whether a string looks like an old loop attachment tag. - inline bool mayBeOldLoopAttachmentTag(StringRef Name) { - return Name.startswith("llvm.vectorizer."); - } - - /// Upgrade the loop attachment metadata node. - MDNode *upgradeInstructionLoopAttachment(MDNode &N); - - /// Upgrade the datalayout string by adding a section for address space - /// pointers. - std::string UpgradeDataLayoutString(StringRef DL, StringRef Triple); - - /// Upgrade attributes that changed format or kind. - void UpgradeAttributes(AttrBuilder &B); - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/BasicBlock.h b/suite/synctools/tablegen/include/llvm/IR/BasicBlock.h deleted file mode 100644 index 184ddfc01c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/BasicBlock.h +++ /dev/null @@ -1,588 +0,0 @@ -//===- llvm/BasicBlock.h - Represent a basic block in the VM ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the BasicBlock class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_BASICBLOCK_H -#define LLVM_IR_BASICBLOCK_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include -#include -#include - -namespace llvm { - -class AssemblyAnnotationWriter; -class CallInst; -class Function; -class LandingPadInst; -class LLVMContext; -class Module; -class PHINode; -class ValueSymbolTable; - -/// LLVM Basic Block Representation -/// -/// This represents a single basic block in LLVM. A basic block is simply a -/// container of instructions that execute sequentially. Basic blocks are Values -/// because they are referenced by instructions such as branches and switch -/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block -/// represents a label to which a branch can jump. -/// -/// A well formed basic block is formed of a list of non-terminating -/// instructions followed by a single terminator instruction. Terminator -/// instructions may not occur in the middle of basic blocks, and must terminate -/// the blocks. The BasicBlock class allows malformed basic blocks to occur -/// because it may be useful in the intermediate stage of constructing or -/// modifying a program. However, the verifier will ensure that basic blocks are -/// "well formed". -class BasicBlock final : public Value, // Basic blocks are data objects also - public ilist_node_with_parent { -public: - using InstListType = SymbolTableList; - -private: - friend class BlockAddress; - friend class SymbolTableListTraits; - - InstListType InstList; - Function *Parent; - - void setParent(Function *parent); - - /// Constructor. - /// - /// If the function parameter is specified, the basic block is automatically - /// inserted at either the end of the function (if InsertBefore is null), or - /// before the specified basic block. - explicit BasicBlock(LLVMContext &C, const Twine &Name = "", - Function *Parent = nullptr, - BasicBlock *InsertBefore = nullptr); - -public: - BasicBlock(const BasicBlock &) = delete; - BasicBlock &operator=(const BasicBlock &) = delete; - ~BasicBlock(); - - /// Get the context in which this basic block lives. - LLVMContext &getContext() const; - - /// Instruction iterators... - using iterator = InstListType::iterator; - using const_iterator = InstListType::const_iterator; - using reverse_iterator = InstListType::reverse_iterator; - using const_reverse_iterator = InstListType::const_reverse_iterator; - - /// Creates a new BasicBlock. - /// - /// If the Parent parameter is specified, the basic block is automatically - /// inserted at either the end of the function (if InsertBefore is 0), or - /// before the specified basic block. - static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", - Function *Parent = nullptr, - BasicBlock *InsertBefore = nullptr) { - return new BasicBlock(Context, Name, Parent, InsertBefore); - } - - /// Return the enclosing method, or null if none. - const Function *getParent() const { return Parent; } - Function *getParent() { return Parent; } - - /// Return the module owning the function this basic block belongs to, or - /// nullptr if the function does not have a module. - /// - /// Note: this is undefined behavior if the block does not have a parent. - const Module *getModule() const; - Module *getModule() { - return const_cast( - static_cast(this)->getModule()); - } - - /// Returns the terminator instruction if the block is well formed or null - /// if the block is not well formed. - const Instruction *getTerminator() const LLVM_READONLY; - Instruction *getTerminator() { - return const_cast( - static_cast(this)->getTerminator()); - } - - /// Returns the call instruction calling \@llvm.experimental.deoptimize - /// prior to the terminating return instruction of this basic block, if such - /// a call is present. Otherwise, returns null. - const CallInst *getTerminatingDeoptimizeCall() const; - CallInst *getTerminatingDeoptimizeCall() { - return const_cast( - static_cast(this)->getTerminatingDeoptimizeCall()); - } - - /// Returns the call instruction calling \@llvm.experimental.deoptimize - /// that is present either in current basic block or in block that is a unique - /// successor to current block, if such call is present. Otherwise, returns null. - const CallInst *getPostdominatingDeoptimizeCall() const; - CallInst *getPostdominatingDeoptimizeCall() { - return const_cast( - static_cast(this)->getPostdominatingDeoptimizeCall()); - } - - /// Returns the call instruction marked 'musttail' prior to the terminating - /// return instruction of this basic block, if such a call is present. - /// Otherwise, returns null. - const CallInst *getTerminatingMustTailCall() const; - CallInst *getTerminatingMustTailCall() { - return const_cast( - static_cast(this)->getTerminatingMustTailCall()); - } - - /// Returns a pointer to the first instruction in this block that is not a - /// PHINode instruction. - /// - /// When adding instructions to the beginning of the basic block, they should - /// be added before the returned value, not before the first instruction, - /// which might be PHI. Returns 0 is there's no non-PHI instruction. - const Instruction* getFirstNonPHI() const; - Instruction* getFirstNonPHI() { - return const_cast( - static_cast(this)->getFirstNonPHI()); - } - - /// Returns a pointer to the first instruction in this block that is not a - /// PHINode or a debug intrinsic, or any pseudo operation if \c SkipPseudoOp - /// is true. - const Instruction *getFirstNonPHIOrDbg(bool SkipPseudoOp = true) const; - Instruction *getFirstNonPHIOrDbg(bool SkipPseudoOp = true) { - return const_cast( - static_cast(this)->getFirstNonPHIOrDbg( - SkipPseudoOp)); - } - - /// Returns a pointer to the first instruction in this block that is not a - /// PHINode, a debug intrinsic, or a lifetime intrinsic, or any pseudo - /// operation if \c SkipPseudoOp is true. - const Instruction * - getFirstNonPHIOrDbgOrLifetime(bool SkipPseudoOp = true) const; - Instruction *getFirstNonPHIOrDbgOrLifetime(bool SkipPseudoOp = true) { - return const_cast( - static_cast(this)->getFirstNonPHIOrDbgOrLifetime( - SkipPseudoOp)); - } - - /// Returns an iterator to the first instruction in this block that is - /// suitable for inserting a non-PHI instruction. - /// - /// In particular, it skips all PHIs and LandingPad instructions. - const_iterator getFirstInsertionPt() const; - iterator getFirstInsertionPt() { - return static_cast(this) - ->getFirstInsertionPt().getNonConst(); - } - - /// Return a const iterator range over the instructions in the block, skipping - /// any debug instructions. Skip any pseudo operations as well if \c - /// SkipPseudoOp is true. - iterator_range>> - instructionsWithoutDebug(bool SkipPseudoOp = true) const; - - /// Return an iterator range over the instructions in the block, skipping any - /// debug instructions. Skip and any pseudo operations as well if \c - /// SkipPseudoOp is true. - iterator_range< - filter_iterator>> - instructionsWithoutDebug(bool SkipPseudoOp = true); - - /// Return the size of the basic block ignoring debug instructions - filter_iterator>::difference_type - sizeWithoutDebug() const; - - /// Unlink 'this' from the containing function, but do not delete it. - void removeFromParent(); - - /// Unlink 'this' from the containing function and delete it. - /// - // \returns an iterator pointing to the element after the erased one. - SymbolTableList::iterator eraseFromParent(); - - /// Unlink this basic block from its current function and insert it into - /// the function that \p MovePos lives in, right before \p MovePos. - void moveBefore(BasicBlock *MovePos); - - /// Unlink this basic block from its current function and insert it - /// right after \p MovePos in the function \p MovePos lives in. - void moveAfter(BasicBlock *MovePos); - - /// Insert unlinked basic block into a function. - /// - /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is - /// provided, inserts before that basic block, otherwise inserts at the end. - /// - /// \pre \a getParent() is \c nullptr. - void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); - - /// Return the predecessor of this block if it has a single predecessor - /// block. Otherwise return a null pointer. - const BasicBlock *getSinglePredecessor() const; - BasicBlock *getSinglePredecessor() { - return const_cast( - static_cast(this)->getSinglePredecessor()); - } - - /// Return the predecessor of this block if it has a unique predecessor - /// block. Otherwise return a null pointer. - /// - /// Note that unique predecessor doesn't mean single edge, there can be - /// multiple edges from the unique predecessor to this block (for example a - /// switch statement with multiple cases having the same destination). - const BasicBlock *getUniquePredecessor() const; - BasicBlock *getUniquePredecessor() { - return const_cast( - static_cast(this)->getUniquePredecessor()); - } - - /// Return true if this block has exactly N predecessors. - bool hasNPredecessors(unsigned N) const; - - /// Return true if this block has N predecessors or more. - bool hasNPredecessorsOrMore(unsigned N) const; - - /// Return the successor of this block if it has a single successor. - /// Otherwise return a null pointer. - /// - /// This method is analogous to getSinglePredecessor above. - const BasicBlock *getSingleSuccessor() const; - BasicBlock *getSingleSuccessor() { - return const_cast( - static_cast(this)->getSingleSuccessor()); - } - - /// Return the successor of this block if it has a unique successor. - /// Otherwise return a null pointer. - /// - /// This method is analogous to getUniquePredecessor above. - const BasicBlock *getUniqueSuccessor() const; - BasicBlock *getUniqueSuccessor() { - return const_cast( - static_cast(this)->getUniqueSuccessor()); - } - - /// Print the basic block to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr, - bool ShouldPreserveUseListOrder = false, - bool IsForDebug = false) const; - - //===--------------------------------------------------------------------===// - /// Instruction iterator methods - /// - inline iterator begin() { return InstList.begin(); } - inline const_iterator begin() const { return InstList.begin(); } - inline iterator end () { return InstList.end(); } - inline const_iterator end () const { return InstList.end(); } - - inline reverse_iterator rbegin() { return InstList.rbegin(); } - inline const_reverse_iterator rbegin() const { return InstList.rbegin(); } - inline reverse_iterator rend () { return InstList.rend(); } - inline const_reverse_iterator rend () const { return InstList.rend(); } - - inline size_t size() const { return InstList.size(); } - inline bool empty() const { return InstList.empty(); } - inline const Instruction &front() const { return InstList.front(); } - inline Instruction &front() { return InstList.front(); } - inline const Instruction &back() const { return InstList.back(); } - inline Instruction &back() { return InstList.back(); } - - /// Iterator to walk just the phi nodes in the basic block. - template - class phi_iterator_impl - : public iterator_facade_base, - std::forward_iterator_tag, PHINodeT> { - friend BasicBlock; - - PHINodeT *PN; - - phi_iterator_impl(PHINodeT *PN) : PN(PN) {} - - public: - // Allow default construction to build variables, but this doesn't build - // a useful iterator. - phi_iterator_impl() = default; - - // Allow conversion between instantiations where valid. - template ::value>> - phi_iterator_impl(const phi_iterator_impl &Arg) - : PN(Arg.PN) {} - - bool operator==(const phi_iterator_impl &Arg) const { return PN == Arg.PN; } - - PHINodeT &operator*() const { return *PN; } - - using phi_iterator_impl::iterator_facade_base::operator++; - phi_iterator_impl &operator++() { - assert(PN && "Cannot increment the end iterator!"); - PN = dyn_cast(std::next(BBIteratorT(PN))); - return *this; - } - }; - using phi_iterator = phi_iterator_impl<>; - using const_phi_iterator = - phi_iterator_impl; - - /// Returns a range that iterates over the phis in the basic block. - /// - /// Note that this cannot be used with basic blocks that have no terminator. - iterator_range phis() const { - return const_cast(this)->phis(); - } - iterator_range phis(); - - /// Return the underlying instruction list container. - /// - /// Currently you need to access the underlying instruction list container - /// directly if you want to modify it. - const InstListType &getInstList() const { return InstList; } - InstListType &getInstList() { return InstList; } - - /// Returns a pointer to a member of the instruction list. - static InstListType BasicBlock::*getSublistAccess(Instruction*) { - return &BasicBlock::InstList; - } - - /// Returns a pointer to the symbol table if one exists. - ValueSymbolTable *getValueSymbolTable(); - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == Value::BasicBlockVal; - } - - /// Cause all subinstructions to "let go" of all the references that said - /// subinstructions are maintaining. - /// - /// This allows one to 'delete' a whole class at a time, even though there may - /// be circular references... first all references are dropped, and all use - /// counts go to zero. Then everything is delete'd for real. Note that no - /// operations are valid on an object that has "dropped all references", - /// except operator delete. - void dropAllReferences(); - - /// Update PHI nodes in this BasicBlock before removal of predecessor \p Pred. - /// Note that this function does not actually remove the predecessor. - /// - /// If \p KeepOneInputPHIs is true then don't remove PHIs that are left with - /// zero or one incoming values, and don't simplify PHIs with all incoming - /// values the same. - void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs = false); - - bool canSplitPredecessors() const; - - /// Split the basic block into two basic blocks at the specified instruction. - /// - /// If \p Before is true, splitBasicBlockBefore handles the - /// block splitting. Otherwise, execution proceeds as described below. - /// - /// Note that all instructions BEFORE the specified iterator - /// stay as part of the original basic block, an unconditional branch is added - /// to the original BB, and the rest of the instructions in the BB are moved - /// to the new BB, including the old terminator. The newly formed basic block - /// is returned. This function invalidates the specified iterator. - /// - /// Note that this only works on well formed basic blocks (must have a - /// terminator), and \p 'I' must not be the end of instruction list (which - /// would cause a degenerate basic block to be formed, having a terminator - /// inside of the basic block). - /// - /// Also note that this doesn't preserve any passes. To split blocks while - /// keeping loop information consistent, use the SplitBlock utility function. - BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = "", - bool Before = false); - BasicBlock *splitBasicBlock(Instruction *I, const Twine &BBName = "", - bool Before = false) { - return splitBasicBlock(I->getIterator(), BBName, Before); - } - - /// Split the basic block into two basic blocks at the specified instruction - /// and insert the new basic blocks as the predecessor of the current block. - /// - /// This function ensures all instructions AFTER and including the specified - /// iterator \p I are part of the original basic block. All Instructions - /// BEFORE the iterator \p I are moved to the new BB and an unconditional - /// branch is added to the new BB. The new basic block is returned. - /// - /// Note that this only works on well formed basic blocks (must have a - /// terminator), and \p 'I' must not be the end of instruction list (which - /// would cause a degenerate basic block to be formed, having a terminator - /// inside of the basic block). \p 'I' cannot be a iterator for a PHINode - /// with multiple incoming blocks. - /// - /// Also note that this doesn't preserve any passes. To split blocks while - /// keeping loop information consistent, use the SplitBlockBefore utility - /// function. - BasicBlock *splitBasicBlockBefore(iterator I, const Twine &BBName = ""); - BasicBlock *splitBasicBlockBefore(Instruction *I, const Twine &BBName = "") { - return splitBasicBlockBefore(I->getIterator(), BBName); - } - - /// Returns true if there are any uses of this basic block other than - /// direct branches, switches, etc. to it. - bool hasAddressTaken() const { - return getBasicBlockBits().BlockAddressRefCount != 0; - } - - /// Update all phi nodes in this basic block to refer to basic block \p New - /// instead of basic block \p Old. - void replacePhiUsesWith(BasicBlock *Old, BasicBlock *New); - - /// Update all phi nodes in this basic block's successors to refer to basic - /// block \p New instead of basic block \p Old. - void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New); - - /// Update all phi nodes in this basic block's successors to refer to basic - /// block \p New instead of to it. - void replaceSuccessorsPhiUsesWith(BasicBlock *New); - - /// Return true if this basic block is an exception handling block. - bool isEHPad() const { return getFirstNonPHI()->isEHPad(); } - - /// Return true if this basic block is a landing pad. - /// - /// Being a ``landing pad'' means that the basic block is the destination of - /// the 'unwind' edge of an invoke instruction. - bool isLandingPad() const; - - /// Return the landingpad instruction associated with the landing pad. - const LandingPadInst *getLandingPadInst() const; - LandingPadInst *getLandingPadInst() { - return const_cast( - static_cast(this)->getLandingPadInst()); - } - - /// Return true if it is legal to hoist instructions into this block. - bool isLegalToHoistInto() const; - - /// Return true if this is the entry block of the containing function. - /// This method can only be used on blocks that have a parent function. - bool isEntryBlock() const; - - Optional getIrrLoopHeaderWeight() const; - - /// Returns true if the Order field of child Instructions is valid. - bool isInstrOrderValid() const { - return getBasicBlockBits().InstrOrderValid; - } - - /// Mark instruction ordering invalid. Done on every instruction insert. - void invalidateOrders() { - validateInstrOrdering(); - BasicBlockBits Bits = getBasicBlockBits(); - Bits.InstrOrderValid = false; - setBasicBlockBits(Bits); - } - - /// Renumber instructions and mark the ordering as valid. - void renumberInstructions(); - - /// Asserts that instruction order numbers are marked invalid, or that they - /// are in ascending order. This is constant time if the ordering is invalid, - /// and linear in the number of instructions if the ordering is valid. Callers - /// should be careful not to call this in ways that make common operations - /// O(n^2). For example, it takes O(n) time to assign order numbers to - /// instructions, so the order should be validated no more than once after - /// each ordering to ensure that transforms have the same algorithmic - /// complexity when asserts are enabled as when they are disabled. - void validateInstrOrdering() const; - -private: -#if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__)) -// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words -// and give the `pack` pragma push semantics. -#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)") -#define END_TWO_BYTE_PACK() _Pragma("pack(pop)") -#else -#define BEGIN_TWO_BYTE_PACK() -#define END_TWO_BYTE_PACK() -#endif - - BEGIN_TWO_BYTE_PACK() - /// Bitfield to help interpret the bits in Value::SubclassData. - struct BasicBlockBits { - unsigned short BlockAddressRefCount : 15; - unsigned short InstrOrderValid : 1; - }; - END_TWO_BYTE_PACK() - -#undef BEGIN_TWO_BYTE_PACK -#undef END_TWO_BYTE_PACK - - /// Safely reinterpret the subclass data bits to a more useful form. - BasicBlockBits getBasicBlockBits() const { - static_assert(sizeof(BasicBlockBits) == sizeof(unsigned short), - "too many bits for Value::SubclassData"); - unsigned short ValueData = getSubclassDataFromValue(); - BasicBlockBits AsBits; - memcpy(&AsBits, &ValueData, sizeof(AsBits)); - return AsBits; - } - - /// Reinterpret our subclass bits and store them back into Value. - void setBasicBlockBits(BasicBlockBits AsBits) { - unsigned short D; - memcpy(&D, &AsBits, sizeof(D)); - Value::setValueSubclassData(D); - } - - /// Increment the internal refcount of the number of BlockAddresses - /// referencing this BasicBlock by \p Amt. - /// - /// This is almost always 0, sometimes one possibly, but almost never 2, and - /// inconceivably 3 or more. - void AdjustBlockAddressRefCount(int Amt) { - BasicBlockBits Bits = getBasicBlockBits(); - Bits.BlockAddressRefCount += Amt; - setBasicBlockBits(Bits); - assert(Bits.BlockAddressRefCount < 255 && "Refcount wrap-around"); - } - - /// Shadow Value::setValueSubclassData with a private forwarding method so - /// that any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) - -/// Advance \p It while it points to a debug instruction and return the result. -/// This assumes that \p It is not at the end of a block. -BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It); - -#ifdef NDEBUG -/// In release builds, this is a no-op. For !NDEBUG builds, the checks are -/// implemented in the .cpp file to avoid circular header deps. -inline void BasicBlock::validateInstrOrdering() const {} -#endif - -} // end namespace llvm - -#endif // LLVM_IR_BASICBLOCK_H diff --git a/suite/synctools/tablegen/include/llvm/IR/BuiltinGCs.h b/suite/synctools/tablegen/include/llvm/IR/BuiltinGCs.h deleted file mode 100644 index 16aff01dbc..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/BuiltinGCs.h +++ /dev/null @@ -1,33 +0,0 @@ -//===-- BuiltinGCs.h - Garbage collector linkage hacks --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains hack functions to force linking in the builtin GC -// components. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_BUILTINGCS_H -#define LLVM_IR_BUILTINGCS_H - -namespace llvm { - -/// FIXME: Collector instances are not useful on their own. These no longer -/// serve any purpose except to link in the plugins. - -/// Ensure the definition of the builtin GCs gets linked in -void linkAllBuiltinGCs(); - -/// Creates an ocaml-compatible metadata printer. -void linkOcamlGCPrinter(); - -/// Creates an erlang-compatible metadata printer. -void linkErlangGCPrinter(); - -} // namespace llvm - -#endif // LLVM_IR_BUILTINGCS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/CFG.h b/suite/synctools/tablegen/include/llvm/IR/CFG.h deleted file mode 100644 index 0ee584f8af..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/CFG.h +++ /dev/null @@ -1,405 +0,0 @@ -//===- CFG.h ----------------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file provides various utilities for inspecting and working with the -/// control flow graph in LLVM IR. This includes generic facilities for -/// iterating successors and predecessors of basic blocks, the successors of -/// specific terminator instructions, etc. It also defines specializations of -/// GraphTraits that allow Function and BasicBlock graphs to be treated as -/// proper graphs for generic algorithms. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CFG_H -#define LLVM_IR_CFG_H - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include -#include -#include - -namespace llvm { - -class Instruction; -class Use; - -//===----------------------------------------------------------------------===// -// BasicBlock pred_iterator definition -//===----------------------------------------------------------------------===// - -template // Predecessor Iterator -class PredIterator { -public: - using iterator_category = std::forward_iterator_tag; - using value_type = Ptr; - using difference_type = std::ptrdiff_t; - using pointer = Ptr *; - using reference = Ptr *; - -private: - using Self = PredIterator; - USE_iterator It; - - inline void advancePastNonTerminators() { - // Loop to ignore non-terminator uses (for example BlockAddresses). - while (!It.atEnd()) { - if (auto *Inst = dyn_cast(*It)) - if (Inst->isTerminator()) - break; - - ++It; - } - } - -public: - PredIterator() = default; - explicit inline PredIterator(Ptr *bb) : It(bb->user_begin()) { - advancePastNonTerminators(); - } - inline PredIterator(Ptr *bb, bool) : It(bb->user_end()) {} - - inline bool operator==(const Self& x) const { return It == x.It; } - inline bool operator!=(const Self& x) const { return !operator==(x); } - - inline reference operator*() const { - assert(!It.atEnd() && "pred_iterator out of range!"); - return cast(*It)->getParent(); - } - inline pointer *operator->() const { return &operator*(); } - - inline Self& operator++() { // Preincrement - assert(!It.atEnd() && "pred_iterator out of range!"); - ++It; advancePastNonTerminators(); - return *this; - } - - inline Self operator++(int) { // Postincrement - Self tmp = *this; ++*this; return tmp; - } - - /// getOperandNo - Return the operand number in the predecessor's - /// terminator of the successor. - unsigned getOperandNo() const { - return It.getOperandNo(); - } - - /// getUse - Return the operand Use in the predecessor's terminator - /// of the successor. - Use &getUse() const { - return It.getUse(); - } -}; - -using pred_iterator = PredIterator; -using const_pred_iterator = - PredIterator; -using pred_range = iterator_range; -using const_pred_range = iterator_range; - -inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } -inline const_pred_iterator pred_begin(const BasicBlock *BB) { - return const_pred_iterator(BB); -} -inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} -inline const_pred_iterator pred_end(const BasicBlock *BB) { - return const_pred_iterator(BB, true); -} -inline bool pred_empty(const BasicBlock *BB) { - return pred_begin(BB) == pred_end(BB); -} -/// Get the number of predecessors of \p BB. This is a linear time operation. -/// Use \ref BasicBlock::hasNPredecessors() or hasNPredecessorsOrMore if able. -inline unsigned pred_size(const BasicBlock *BB) { - return std::distance(pred_begin(BB), pred_end(BB)); -} -inline pred_range predecessors(BasicBlock *BB) { - return pred_range(pred_begin(BB), pred_end(BB)); -} -inline const_pred_range predecessors(const BasicBlock *BB) { - return const_pred_range(pred_begin(BB), pred_end(BB)); -} - -//===----------------------------------------------------------------------===// -// Instruction and BasicBlock succ_iterator helpers -//===----------------------------------------------------------------------===// - -template -class SuccIterator - : public iterator_facade_base, - std::random_access_iterator_tag, BlockT, int, - BlockT *, BlockT *> { -public: - using difference_type = int; - using pointer = BlockT *; - using reference = BlockT *; - -private: - InstructionT *Inst; - int Idx; - using Self = SuccIterator; - - inline bool index_is_valid(int Idx) { - // Note that we specially support the index of zero being valid even in the - // face of a null instruction. - return Idx >= 0 && (Idx == 0 || Idx <= (int)Inst->getNumSuccessors()); - } - - /// Proxy object to allow write access in operator[] - class SuccessorProxy { - Self It; - - public: - explicit SuccessorProxy(const Self &It) : It(It) {} - - SuccessorProxy(const SuccessorProxy &) = default; - - SuccessorProxy &operator=(SuccessorProxy RHS) { - *this = reference(RHS); - return *this; - } - - SuccessorProxy &operator=(reference RHS) { - It.Inst->setSuccessor(It.Idx, RHS); - return *this; - } - - operator reference() const { return *It; } - }; - -public: - // begin iterator - explicit inline SuccIterator(InstructionT *Inst) : Inst(Inst), Idx(0) {} - // end iterator - inline SuccIterator(InstructionT *Inst, bool) : Inst(Inst) { - if (Inst) - Idx = Inst->getNumSuccessors(); - else - // Inst == NULL happens, if a basic block is not fully constructed and - // consequently getTerminator() returns NULL. In this case we construct - // a SuccIterator which describes a basic block that has zero - // successors. - // Defining SuccIterator for incomplete and malformed CFGs is especially - // useful for debugging. - Idx = 0; - } - - /// This is used to interface between code that wants to - /// operate on terminator instructions directly. - int getSuccessorIndex() const { return Idx; } - - inline bool operator==(const Self &x) const { return Idx == x.Idx; } - - inline BlockT *operator*() const { return Inst->getSuccessor(Idx); } - - // We use the basic block pointer directly for operator->. - inline BlockT *operator->() const { return operator*(); } - - inline bool operator<(const Self &RHS) const { - assert(Inst == RHS.Inst && "Cannot compare iterators of different blocks!"); - return Idx < RHS.Idx; - } - - int operator-(const Self &RHS) const { - assert(Inst == RHS.Inst && "Cannot compare iterators of different blocks!"); - return Idx - RHS.Idx; - } - - inline Self &operator+=(int RHS) { - int NewIdx = Idx + RHS; - assert(index_is_valid(NewIdx) && "Iterator index out of bound"); - Idx = NewIdx; - return *this; - } - - inline Self &operator-=(int RHS) { return operator+=(-RHS); } - - // Specially implement the [] operation using a proxy object to support - // assignment. - inline SuccessorProxy operator[](int Offset) { - Self TmpIt = *this; - TmpIt += Offset; - return SuccessorProxy(TmpIt); - } - - /// Get the source BlockT of this iterator. - inline BlockT *getSource() { - assert(Inst && "Source not available, if basic block was malformed"); - return Inst->getParent(); - } -}; - -using succ_iterator = SuccIterator; -using const_succ_iterator = SuccIterator; -using succ_range = iterator_range; -using const_succ_range = iterator_range; - -inline succ_iterator succ_begin(Instruction *I) { return succ_iterator(I); } -inline const_succ_iterator succ_begin(const Instruction *I) { - return const_succ_iterator(I); -} -inline succ_iterator succ_end(Instruction *I) { return succ_iterator(I, true); } -inline const_succ_iterator succ_end(const Instruction *I) { - return const_succ_iterator(I, true); -} -inline bool succ_empty(const Instruction *I) { - return succ_begin(I) == succ_end(I); -} -inline unsigned succ_size(const Instruction *I) { - return std::distance(succ_begin(I), succ_end(I)); -} -inline succ_range successors(Instruction *I) { - return succ_range(succ_begin(I), succ_end(I)); -} -inline const_succ_range successors(const Instruction *I) { - return const_succ_range(succ_begin(I), succ_end(I)); -} - -inline succ_iterator succ_begin(BasicBlock *BB) { - return succ_iterator(BB->getTerminator()); -} -inline const_succ_iterator succ_begin(const BasicBlock *BB) { - return const_succ_iterator(BB->getTerminator()); -} -inline succ_iterator succ_end(BasicBlock *BB) { - return succ_iterator(BB->getTerminator(), true); -} -inline const_succ_iterator succ_end(const BasicBlock *BB) { - return const_succ_iterator(BB->getTerminator(), true); -} -inline bool succ_empty(const BasicBlock *BB) { - return succ_begin(BB) == succ_end(BB); -} -inline unsigned succ_size(const BasicBlock *BB) { - return std::distance(succ_begin(BB), succ_end(BB)); -} -inline succ_range successors(BasicBlock *BB) { - return succ_range(succ_begin(BB), succ_end(BB)); -} -inline const_succ_range successors(const BasicBlock *BB) { - return const_succ_range(succ_begin(BB), succ_end(BB)); -} - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for basic block graphs (CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... - -template <> struct GraphTraits { - using NodeRef = BasicBlock *; - using ChildIteratorType = succ_iterator; - - static NodeRef getEntryNode(BasicBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return succ_begin(N); } - static ChildIteratorType child_end(NodeRef N) { return succ_end(N); } -}; - -template <> struct GraphTraits { - using NodeRef = const BasicBlock *; - using ChildIteratorType = const_succ_iterator; - - static NodeRef getEntryNode(const BasicBlock *BB) { return BB; } - - static ChildIteratorType child_begin(NodeRef N) { return succ_begin(N); } - static ChildIteratorType child_end(NodeRef N) { return succ_end(N); } -}; - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... and to walk it in inverse order. Inverse order for -// a function is considered to be when traversing the predecessor edges of a BB -// instead of the successor edges. -// -template <> struct GraphTraits> { - using NodeRef = BasicBlock *; - using ChildIteratorType = pred_iterator; - - static NodeRef getEntryNode(Inverse G) { return G.Graph; } - static ChildIteratorType child_begin(NodeRef N) { return pred_begin(N); } - static ChildIteratorType child_end(NodeRef N) { return pred_end(N); } -}; - -template <> struct GraphTraits> { - using NodeRef = const BasicBlock *; - using ChildIteratorType = const_pred_iterator; - - static NodeRef getEntryNode(Inverse G) { return G.Graph; } - static ChildIteratorType child_begin(NodeRef N) { return pred_begin(N); } - static ChildIteratorType child_end(NodeRef N) { return pred_end(N); } -}; - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for function basic block graphs (CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... these are the same as the basic block iterators, -// except that the root node is implicitly the first node of the function. -// -template <> struct GraphTraits : public GraphTraits { - static NodeRef getEntryNode(Function *F) { return &F->getEntryBlock(); } - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - using nodes_iterator = pointer_iterator; - - static nodes_iterator nodes_begin(Function *F) { - return nodes_iterator(F->begin()); - } - - static nodes_iterator nodes_end(Function *F) { - return nodes_iterator(F->end()); - } - - static size_t size(Function *F) { return F->size(); } -}; -template <> struct GraphTraits : - public GraphTraits { - static NodeRef getEntryNode(const Function *F) { return &F->getEntryBlock(); } - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - using nodes_iterator = pointer_iterator; - - static nodes_iterator nodes_begin(const Function *F) { - return nodes_iterator(F->begin()); - } - - static nodes_iterator nodes_end(const Function *F) { - return nodes_iterator(F->end()); - } - - static size_t size(const Function *F) { return F->size(); } -}; - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... and to walk it in inverse order. Inverse order for -// a function is considered to be when traversing the predecessor edges of a BB -// instead of the successor edges. -// -template <> struct GraphTraits> : - public GraphTraits> { - static NodeRef getEntryNode(Inverse G) { - return &G.Graph->getEntryBlock(); - } -}; -template <> struct GraphTraits> : - public GraphTraits> { - static NodeRef getEntryNode(Inverse G) { - return &G.Graph->getEntryBlock(); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_CFG_H diff --git a/suite/synctools/tablegen/include/llvm/IR/CallingConv.h b/suite/synctools/tablegen/include/llvm/IR/CallingConv.h deleted file mode 100644 index ece864e731..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/CallingConv.h +++ /dev/null @@ -1,263 +0,0 @@ -//===- llvm/CallingConv.h - LLVM Calling Conventions ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines LLVM's set of calling conventions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CALLINGCONV_H -#define LLVM_IR_CALLINGCONV_H - -namespace llvm { - -/// CallingConv Namespace - This namespace contains an enum with a value for -/// the well-known calling conventions. -/// -namespace CallingConv { - - /// LLVM IR allows to use arbitrary numbers as calling convention identifiers. - using ID = unsigned; - - /// A set of enums which specify the assigned numeric values for known llvm - /// calling conventions. - /// LLVM Calling Convention Representation - enum { - /// C - The default llvm calling convention, compatible with C. This - /// convention is the only calling convention that supports varargs calls. - /// As with typical C calling conventions, the callee/caller have to - /// tolerate certain amounts of prototype mismatch. - C = 0, - - // Generic LLVM calling conventions. None of these calling conventions - // support varargs calls, and all assume that the caller and callee - // prototype exactly match. - - /// Fast - This calling convention attempts to make calls as fast as - /// possible (e.g. by passing things in registers). - Fast = 8, - - // Cold - This calling convention attempts to make code in the caller as - // efficient as possible under the assumption that the call is not commonly - // executed. As such, these calls often preserve all registers so that the - // call does not break any live ranges in the caller side. - Cold = 9, - - // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC). - GHC = 10, - - // HiPE - Calling convention used by the High-Performance Erlang Compiler - // (HiPE). - HiPE = 11, - - // WebKit JS - Calling convention for stack based JavaScript calls - WebKit_JS = 12, - - // AnyReg - Calling convention for dynamic register based calls (e.g. - // stackmap and patchpoint intrinsics). - AnyReg = 13, - - // PreserveMost - Calling convention for runtime calls that preserves most - // registers. - PreserveMost = 14, - - // PreserveAll - Calling convention for runtime calls that preserves - // (almost) all registers. - PreserveAll = 15, - - // Swift - Calling convention for Swift. - Swift = 16, - - // CXX_FAST_TLS - Calling convention for access functions. - CXX_FAST_TLS = 17, - - /// Tail - This calling convention attempts to make calls as fast as - /// possible while guaranteeing that tail call optimization can always - /// be performed. - Tail = 18, - - /// Special calling convention on Windows for calling the Control - /// Guard Check ICall function. The function takes exactly one argument - /// (address of the target function) passed in the first argument register, - /// and has no return value. All register values are preserved. - CFGuard_Check = 19, - - /// SwiftTail - This follows the Swift calling convention in how arguments - /// are passed but guarantees tail calls will be made by making the callee - /// clean up their stack. - SwiftTail = 20, - - // Target - This is the start of the target-specific calling conventions, - // e.g. fastcall and thiscall on X86. - FirstTargetCC = 64, - - /// X86_StdCall - stdcall is the calling conventions mostly used by the - /// Win32 API. It is basically the same as the C convention with the - /// difference in that the callee is responsible for popping the arguments - /// from the stack. - X86_StdCall = 64, - - /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments - /// in ECX:EDX registers, others - via stack. Callee is responsible for - /// stack cleaning. - X86_FastCall = 65, - - /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete, - /// but still used on some targets). - ARM_APCS = 66, - - /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling - /// convention (aka EABI). Soft float variant. - ARM_AAPCS = 67, - - /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI. - ARM_AAPCS_VFP = 68, - - /// MSP430_INTR - Calling convention used for MSP430 interrupt routines. - MSP430_INTR = 69, - - /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, - /// others via stack. Callee is responsible for stack cleaning. MSVC uses - /// this by default for methods in its ABI. - X86_ThisCall = 70, - - /// PTX_Kernel - Call to a PTX kernel. - /// Passes all arguments in parameter space. - PTX_Kernel = 71, - - /// PTX_Device - Call to a PTX device function. - /// Passes all arguments in register or parameter space. - PTX_Device = 72, - - /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. - /// No lowering or expansion of arguments. - /// Structures are passed as a pointer to a struct with the byval attribute. - /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions. - /// Functions can only have zero or one return values. - /// Variable arguments are not allowed, except for printf. - /// How arguments/return values are lowered are not specified. - /// Functions are only visible to the devices. - SPIR_FUNC = 75, - - /// SPIR_KERNEL - Calling convention for SPIR kernel functions. - /// Inherits the restrictions of SPIR_FUNC, except - /// Cannot have non-void return values. - /// Cannot have variable arguments. - /// Can also be called by the host. - /// Is externally visible. - SPIR_KERNEL = 76, - - /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins - Intel_OCL_BI = 77, - - /// The C convention as specified in the x86-64 supplement to the - /// System V ABI, used on most non-Windows systems. - X86_64_SysV = 78, - - /// The C convention as implemented on Windows/x86-64 and - /// AArch64. This convention differs from the more common - /// \c X86_64_SysV convention in a number of ways, most notably in - /// that XMM registers used to pass arguments are shadowed by GPRs, - /// and vice versa. - /// On AArch64, this is identical to the normal C (AAPCS) calling - /// convention for normal functions, but floats are passed in integer - /// registers to variadic functions. - Win64 = 79, - - /// MSVC calling convention that passes vectors and vector aggregates - /// in SSE registers. - X86_VectorCall = 80, - - /// Calling convention used by HipHop Virtual Machine (HHVM) to - /// perform calls to and from translation cache, and for calling PHP - /// functions. - /// HHVM calling convention supports tail/sibling call elimination. - HHVM = 81, - - /// HHVM calling convention for invoking C/C++ helpers. - HHVM_C = 82, - - /// X86_INTR - x86 hardware interrupt context. Callee may take one or two - /// parameters, where the 1st represents a pointer to hardware context frame - /// and the 2nd represents hardware error code, the presence of the later - /// depends on the interrupt vector taken. Valid for both 32- and 64-bit - /// subtargets. - X86_INTR = 83, - - /// Used for AVR interrupt routines. - AVR_INTR = 84, - - /// Calling convention used for AVR signal routines. - AVR_SIGNAL = 85, - - /// Calling convention used for special AVR rtlib functions - /// which have an "optimized" convention to preserve registers. - AVR_BUILTIN = 86, - - /// Calling convention used for Mesa vertex shaders, or AMDPAL last shader - /// stage before rasterization (vertex shader if tessellation and geometry - /// are not in use, or otherwise copy shader if one is needed). - AMDGPU_VS = 87, - - /// Calling convention used for Mesa/AMDPAL geometry shaders. - AMDGPU_GS = 88, - - /// Calling convention used for Mesa/AMDPAL pixel shaders. - AMDGPU_PS = 89, - - /// Calling convention used for Mesa/AMDPAL compute shaders. - AMDGPU_CS = 90, - - /// Calling convention for AMDGPU code object kernels. - AMDGPU_KERNEL = 91, - - /// Register calling convention used for parameters transfer optimization - X86_RegCall = 92, - - /// Calling convention used for Mesa/AMDPAL hull shaders (= tessellation - /// control shaders). - AMDGPU_HS = 93, - - /// Calling convention used for special MSP430 rtlib functions - /// which have an "optimized" convention using additional registers. - MSP430_BUILTIN = 94, - - /// Calling convention used for AMDPAL vertex shader if tessellation is in - /// use. - AMDGPU_LS = 95, - - /// Calling convention used for AMDPAL shader stage before geometry shader - /// if geometry is in use. So either the domain (= tessellation evaluation) - /// shader if tessellation is in use, or otherwise the vertex shader. - AMDGPU_ES = 96, - - // Calling convention between AArch64 Advanced SIMD functions - AArch64_VectorCall = 97, - - /// Calling convention between AArch64 SVE functions - AArch64_SVE_VectorCall = 98, - - /// Calling convention for emscripten __invoke_* functions. The first - /// argument is required to be the function ptr being indirectly called. - /// The remainder matches the regular calling convention. - WASM_EmscriptenInvoke = 99, - - /// Calling convention used for AMD graphics targets. - AMDGPU_Gfx = 100, - - /// M68k_INTR - Calling convention used for M68k interrupt routines. - M68k_INTR = 101, - - /// The highest possible calling convention ID. Must be some 2^k - 1. - MaxID = 1023 - }; - -} // end namespace CallingConv - -} // end namespace llvm - -#endif // LLVM_IR_CALLINGCONV_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Comdat.h b/suite/synctools/tablegen/include/llvm/IR/Comdat.h deleted file mode 100644 index 1701802e69..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Comdat.h +++ /dev/null @@ -1,78 +0,0 @@ -//===- llvm/IR/Comdat.h - Comdat definitions --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains the declaration of the Comdat class, which represents a -/// single COMDAT in LLVM. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_COMDAT_H -#define LLVM_IR_COMDAT_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Support/CBindingWrapping.h" - -namespace llvm { - -class GlobalObject; -class raw_ostream; -class StringRef; -template class StringMapEntry; - -// This is a Name X SelectionKind pair. The reason for having this be an -// independent object instead of just adding the name and the SelectionKind -// to a GlobalObject is that it is invalid to have two Comdats with the same -// name but different SelectionKind. This structure makes that unrepresentable. -class Comdat { -public: - enum SelectionKind { - Any, ///< The linker may choose any COMDAT. - ExactMatch, ///< The data referenced by the COMDAT must be the same. - Largest, ///< The linker will choose the largest COMDAT. - NoDeduplicate, ///< No deduplication is performed. - SameSize, ///< The data referenced by the COMDAT must be the same size. - }; - - Comdat(const Comdat &) = delete; - Comdat(Comdat &&C); - - SelectionKind getSelectionKind() const { return SK; } - void setSelectionKind(SelectionKind Val) { SK = Val; } - StringRef getName() const; - void print(raw_ostream &OS, bool IsForDebug = false) const; - void dump() const; - const SmallPtrSetImpl &getUsers() const { return Users; } - -private: - friend class Module; - friend class GlobalObject; - - Comdat(); - void addUser(GlobalObject *GO); - void removeUser(GlobalObject *GO); - - // Points to the map in Module. - StringMapEntry *Name = nullptr; - SelectionKind SK = Any; - // Globals using this comdat. - SmallPtrSet Users; -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Comdat, LLVMComdatRef) - -inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) { - C.print(OS); - return OS; -} - -} // end namespace llvm - -#endif // LLVM_IR_COMDAT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Constant.h b/suite/synctools/tablegen/include/llvm/IR/Constant.h deleted file mode 100644 index a97372ebba..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Constant.h +++ /dev/null @@ -1,259 +0,0 @@ -//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the Constant class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CONSTANT_H -#define LLVM_IR_CONSTANT_H - -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" - -namespace llvm { - -class APInt; - -/// This is an important base class in LLVM. It provides the common facilities -/// of all constant values in an LLVM program. A constant is a value that is -/// immutable at runtime. Functions are constants because their address is -/// immutable. Same with global variables. -/// -/// All constants share the capabilities provided in this class. All constants -/// can have a null value. They can have an operand list. Constants can be -/// simple (integer and floating point values), complex (arrays and structures), -/// or expression based (computations yielding a constant value composed of -/// only certain operators and other constant values). -/// -/// Note that Constants are immutable (once created they never change) -/// and are fully shared by structural equivalence. This means that two -/// structurally equivalent constants will always have the same address. -/// Constants are created on demand as needed and never deleted: thus clients -/// don't have to worry about the lifetime of the objects. -/// LLVM Constant Representation -class Constant : public User { -protected: - Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) - : User(ty, vty, Ops, NumOps) {} - - ~Constant() = default; - -public: - void operator=(const Constant &) = delete; - Constant(const Constant &) = delete; - - /// Return true if this is the value that would be returned by getNullValue. - bool isNullValue() const; - - /// Returns true if the value is one. - bool isOneValue() const; - - /// Return true if the value is not the one value, or, - /// for vectors, does not contain one value elements. - bool isNotOneValue() const; - - /// Return true if this is the value that would be returned by - /// getAllOnesValue. - bool isAllOnesValue() const; - - /// Return true if the value is what would be returned by - /// getZeroValueForNegation. - bool isNegativeZeroValue() const; - - /// Return true if the value is negative zero or null value. - bool isZeroValue() const; - - /// Return true if the value is not the smallest signed value, or, - /// for vectors, does not contain smallest signed value elements. - bool isNotMinSignedValue() const; - - /// Return true if the value is the smallest signed value. - bool isMinSignedValue() const; - - /// Return true if this is a finite and non-zero floating-point scalar - /// constant or a fixed width vector constant with all finite and non-zero - /// elements. - bool isFiniteNonZeroFP() const; - - /// Return true if this is a normal (as opposed to denormal, infinity, nan, - /// or zero) floating-point scalar constant or a vector constant with all - /// normal elements. See APFloat::isNormal. - bool isNormalFP() const; - - /// Return true if this scalar has an exact multiplicative inverse or this - /// vector has an exact multiplicative inverse for each element in the vector. - bool hasExactInverseFP() const; - - /// Return true if this is a floating-point NaN constant or a vector - /// floating-point constant with all NaN elements. - bool isNaN() const; - - /// Return true if this constant and a constant 'Y' are element-wise equal. - /// This is identical to just comparing the pointers, with the exception that - /// for vectors, if only one of the constants has an `undef` element in some - /// lane, the constants still match. - bool isElementWiseEqual(Value *Y) const; - - /// Return true if this is a vector constant that includes any undef or - /// poison elements. Since it is impossible to inspect a scalable vector - /// element- wise at compile time, this function returns true only if the - /// entire vector is undef or poison. - bool containsUndefOrPoisonElement() const; - - /// Return true if this is a vector constant that includes any poison - /// elements. - bool containsPoisonElement() const; - - /// Return true if this is a fixed width vector constant that includes - /// any constant expressions. - bool containsConstantExpression() const; - - /// Return true if evaluation of this constant could trap. This is true for - /// things like constant expressions that could divide by zero. - bool canTrap() const; - - /// Return true if the value can vary between threads. - bool isThreadDependent() const; - - /// Return true if the value is dependent on a dllimport variable. - bool isDLLImportDependent() const; - - /// Return true if the constant has users other than constant expressions and - /// other dangling things. - bool isConstantUsed() const; - - /// This method classifies the entry according to whether or not it may - /// generate a relocation entry (either static or dynamic). This must be - /// conservative, so if it might codegen to a relocatable entry, it should say - /// so. - /// - /// FIXME: This really should not be in IR. - bool needsRelocation() const; - bool needsDynamicRelocation() const; - - /// For aggregates (struct/array/vector) return the constant that corresponds - /// to the specified element if possible, or null if not. This can return null - /// if the element index is a ConstantExpr, if 'this' is a constant expr or - /// if the constant does not fit into an uint64_t. - Constant *getAggregateElement(unsigned Elt) const; - Constant *getAggregateElement(Constant *Elt) const; - - /// If all elements of the vector constant have the same value, return that - /// value. Otherwise, return nullptr. Ignore undefined elements by setting - /// AllowUndefs to true. - Constant *getSplatValue(bool AllowUndefs = false) const; - - /// If C is a constant integer then return its value, otherwise C must be a - /// vector of constant integers, all equal, and the common value is returned. - const APInt &getUniqueInteger() const; - - /// Called if some element of this constant is no longer valid. - /// At this point only other constants may be on the use_list for this - /// constant. Any constants on our Use list must also be destroy'd. The - /// implementation must be sure to remove the constant from the list of - /// available cached constants. Implementations should implement - /// destroyConstantImpl to remove constants from any pools/maps they are - /// contained it. - void destroyConstant(); - - //// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - static_assert(ConstantFirstVal == 0, "V->getValueID() >= ConstantFirstVal always succeeds"); - return V->getValueID() <= ConstantLastVal; - } - - /// This method is a special form of User::replaceUsesOfWith - /// (which does not work on constants) that does work - /// on constants. Basically this method goes through the trouble of building - /// a new constant that is equivalent to the current one, with all uses of - /// From replaced with uses of To. After this construction is completed, all - /// of the users of 'this' are replaced to use the new constant, and then - /// 'this' is deleted. In general, you should not call this method, instead, - /// use Value::replaceAllUsesWith, which automatically dispatches to this - /// method as needed. - /// - void handleOperandChange(Value *, Value *); - - static Constant *getNullValue(Type* Ty); - - /// @returns the value for an integer or vector of integer constant of the - /// given type that has all its bits set to true. - /// Get the all ones value - static Constant *getAllOnesValue(Type* Ty); - - /// Return the value for an integer or pointer constant, or a vector thereof, - /// with the given scalar value. - static Constant *getIntegerValue(Type *Ty, const APInt &V); - - /// If there are any dead constant users dangling off of this constant, remove - /// them. This method is useful for clients that want to check to see if a - /// global is unused, but don't want to deal with potentially dead constants - /// hanging off of the globals. - void removeDeadConstantUsers() const; - - /// Return true if the constant has exactly one live use. - /// - /// This returns the same result as calling Value::hasOneUse after - /// Constant::removeDeadConstantUsers, but doesn't remove dead constants. - bool hasOneLiveUse() const; - - /// Return true if the constant has no live uses. - /// - /// This returns the same result as calling Value::use_empty after - /// Constant::removeDeadConstantUsers, but doesn't remove dead constants. - bool hasZeroLiveUses() const; - - const Constant *stripPointerCasts() const { - return cast(Value::stripPointerCasts()); - } - - Constant *stripPointerCasts() { - return const_cast( - static_cast(this)->stripPointerCasts()); - } - - /// Try to replace undefined constant C or undefined elements in C with - /// Replacement. If no changes are made, the constant C is returned. - static Constant *replaceUndefsWith(Constant *C, Constant *Replacement); - - /// Merges undefs of a Constant with another Constant, along with the - /// undefs already present. Other doesn't have to be the same type as C, but - /// both must either be scalars or vectors with the same element count. If no - /// changes are made, the constant C is returned. - static Constant *mergeUndefsWith(Constant *C, Constant *Other); - - /// Return true if a constant is ConstantData or a ConstantAggregate or - /// ConstantExpr that contain only ConstantData. - bool isManifestConstant() const; - -private: - enum PossibleRelocationsTy { - /// This constant requires no relocations. That is, it holds simple - /// constants (like integrals). - NoRelocation = 0, - - /// This constant holds static relocations that can be resolved by the - /// static linker. - LocalRelocation = 1, - - /// This constant holds dynamic relocations that the dynamic linker will - /// need to resolve. - GlobalRelocation = 2, - }; - - /// Determine what potential relocations may be needed by this constant. - PossibleRelocationsTy getRelocationInfo() const; - - bool hasNLiveUses(unsigned N) const; -}; - -} // end namespace llvm - -#endif // LLVM_IR_CONSTANT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ConstantFolder.h b/suite/synctools/tablegen/include/llvm/IR/ConstantFolder.h deleted file mode 100644 index 28dc63a588..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ConstantFolder.h +++ /dev/null @@ -1,290 +0,0 @@ -//===- ConstantFolder.h - Constant folding helper ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the ConstantFolder class, a helper for IRBuilder. -// It provides IRBuilder with a set of methods for creating constants -// with minimal folding. For general constant creation and folding, -// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CONSTANTFOLDER_H -#define LLVM_IR_CONSTANTFOLDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/IRBuilderFolder.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" - -namespace llvm { - -/// ConstantFolder - Create constants with minimum, target independent, folding. -class ConstantFolder final : public IRBuilderFolder { - virtual void anchor(); - -public: - explicit ConstantFolder() = default; - - //===--------------------------------------------------------------------===// - // Value-based folders. - // - // Return an existing value or a constant if the operation can be simplified. - // Otherwise return nullptr. - //===--------------------------------------------------------------------===// - Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, - bool HasNSW = false) const override { - auto *LC = dyn_cast(LHS); - auto *RC = dyn_cast(RHS); - if (LC && RC) - return ConstantExpr::getAdd(LC, RC, HasNUW, HasNSW); - return nullptr; - } - - Value *FoldAnd(Value *LHS, Value *RHS) const override { - auto *LC = dyn_cast(LHS); - auto *RC = dyn_cast(RHS); - if (LC && RC) - return ConstantExpr::getAnd(LC, RC); - return nullptr; - } - - Value *FoldOr(Value *LHS, Value *RHS) const override { - auto *LC = dyn_cast(LHS); - auto *RC = dyn_cast(RHS); - if (LC && RC) - return ConstantExpr::getOr(LC, RC); - return nullptr; - } - - Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { - auto *LC = dyn_cast(LHS); - auto *RC = dyn_cast(RHS); - if (LC && RC) - return ConstantExpr::getCompare(P, LC, RC); - return nullptr; - } - - Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, - bool IsInBounds = false) const override { - if (auto *PC = dyn_cast(Ptr)) { - // Every index must be constant. - if (any_of(IdxList, [](Value *V) { return !isa(V); })) - return nullptr; - - if (IsInBounds) - return ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList); - else - return ConstantExpr::getGetElementPtr(Ty, PC, IdxList); - } - return nullptr; - } - - Value *FoldSelect(Value *C, Value *True, Value *False) const override { - auto *CC = dyn_cast(C); - auto *TC = dyn_cast(True); - auto *FC = dyn_cast(False); - if (CC && TC && FC) - return ConstantExpr::getSelect(CC, TC, FC); - return nullptr; - } - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getFAdd(LHS, RHS); - } - - Constant *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const override { - return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); - } - - Constant *CreateFSub(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getFSub(LHS, RHS); - } - - Constant *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const override { - return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); - } - - Constant *CreateFMul(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getFMul(LHS, RHS); - } - - Constant *CreateUDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - return ConstantExpr::getUDiv(LHS, RHS, isExact); - } - - Constant *CreateSDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - return ConstantExpr::getSDiv(LHS, RHS, isExact); - } - - Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getFDiv(LHS, RHS); - } - - Constant *CreateURem(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getURem(LHS, RHS); - } - - Constant *CreateSRem(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getSRem(LHS, RHS); - } - - Constant *CreateFRem(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getFRem(LHS, RHS); - } - - Constant *CreateShl(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const override { - return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); - } - - Constant *CreateLShr(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - return ConstantExpr::getLShr(LHS, RHS, isExact); - } - - Constant *CreateAShr(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - return ConstantExpr::getAShr(LHS, RHS, isExact); - } - - Constant *CreateOr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getOr(LHS, RHS); - } - - Constant *CreateXor(Constant *LHS, Constant *RHS) const override { - return ConstantExpr::getXor(LHS, RHS); - } - - Constant *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const override { - return ConstantExpr::get(Opc, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateNeg(Constant *C, - bool HasNUW = false, bool HasNSW = false) const override { - return ConstantExpr::getNeg(C, HasNUW, HasNSW); - } - - Constant *CreateFNeg(Constant *C) const override { - return ConstantExpr::getFNeg(C); - } - - Constant *CreateNot(Constant *C) const override { - return ConstantExpr::getNot(C); - } - - Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { - return ConstantExpr::get(Opc, C); - } - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Constant *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const override { - return ConstantExpr::getCast(Op, C, DestTy); - } - - Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { - return ConstantExpr::getPointerCast(C, DestTy); - } - - Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, - Type *DestTy) const override { - return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy); - } - - Constant *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const override { - return ConstantExpr::getIntegerCast(C, DestTy, isSigned); - } - - Constant *CreateFPCast(Constant *C, Type *DestTy) const override { - return ConstantExpr::getFPCast(C, DestTy); - } - - Constant *CreateBitCast(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::BitCast, C, DestTy); - } - - Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::IntToPtr, C, DestTy); - } - - Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::PtrToInt, C, DestTy); - } - - Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { - return ConstantExpr::getZExtOrBitCast(C, DestTy); - } - - Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { - return ConstantExpr::getSExtOrBitCast(C, DestTy); - } - - Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { - return ConstantExpr::getTruncOrBitCast(C, DestTy); - } - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const override { - return ConstantExpr::getCompare(P, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const override { - return ConstantExpr::getExtractElement(Vec, Idx); - } - - Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const override { - return ConstantExpr::getInsertElement(Vec, NewElt, Idx); - } - - Constant *CreateShuffleVector(Constant *V1, Constant *V2, - ArrayRef Mask) const override { - return ConstantExpr::getShuffleVector(V1, V2, Mask); - } - - Constant *CreateExtractValue(Constant *Agg, - ArrayRef IdxList) const override { - return ConstantExpr::getExtractValue(Agg, IdxList); - } - - Constant *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef IdxList) const override { - return ConstantExpr::getInsertValue(Agg, Val, IdxList); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_CONSTANTFOLDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ConstantRange.h b/suite/synctools/tablegen/include/llvm/IR/ConstantRange.h deleted file mode 100644 index fea4d0da1d..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ConstantRange.h +++ /dev/null @@ -1,575 +0,0 @@ -//===- ConstantRange.h - Represent a range ----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Represent a range of possible values that may occur when the program is run -// for an integral value. This keeps track of a lower and upper bound for the -// constant, which MAY wrap around the end of the numeric range. To do this, it -// keeps track of a [lower, upper) bound, which specifies an interval just like -// STL iterators. When used with boolean values, the following are important -// ranges: : -// -// [F, F) = {} = Empty set -// [T, F) = {T} -// [F, T) = {F} -// [T, T) = {F, T} = Full set -// -// The other integral ranges use min/max values for special range values. For -// example, for 8-bit types, it uses: -// [0, 0) = {} = Empty set -// [255, 255) = {0..255} = Full Set -// -// Note that ConstantRange can be used to represent either signed or -// unsigned ranges. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CONSTANTRANGE_H -#define LLVM_IR_CONSTANTRANGE_H - -#include "llvm/ADT/APInt.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/Support/Compiler.h" -#include - -namespace llvm { - -class MDNode; -class raw_ostream; -struct KnownBits; - -/// This class represents a range of values. -class LLVM_NODISCARD ConstantRange { - APInt Lower, Upper; - - /// Create empty constant range with same bitwidth. - ConstantRange getEmpty() const { - return ConstantRange(getBitWidth(), false); - } - - /// Create full constant range with same bitwidth. - ConstantRange getFull() const { - return ConstantRange(getBitWidth(), true); - } - -public: - /// Initialize a full or empty set for the specified bit width. - explicit ConstantRange(uint32_t BitWidth, bool isFullSet); - - /// Initialize a range to hold the single specified value. - ConstantRange(APInt Value); - - /// Initialize a range of values explicitly. This will assert out if - /// Lower==Upper and Lower != Min or Max value for its type. It will also - /// assert out if the two APInt's are not the same bit width. - ConstantRange(APInt Lower, APInt Upper); - - /// Create empty constant range with the given bit width. - static ConstantRange getEmpty(uint32_t BitWidth) { - return ConstantRange(BitWidth, false); - } - - /// Create full constant range with the given bit width. - static ConstantRange getFull(uint32_t BitWidth) { - return ConstantRange(BitWidth, true); - } - - /// Create non-empty constant range with the given bounds. If Lower and - /// Upper are the same, a full range is returned. - static ConstantRange getNonEmpty(APInt Lower, APInt Upper) { - if (Lower == Upper) - return getFull(Lower.getBitWidth()); - return ConstantRange(std::move(Lower), std::move(Upper)); - } - - /// Initialize a range based on a known bits constraint. The IsSigned flag - /// indicates whether the constant range should not wrap in the signed or - /// unsigned domain. - static ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned); - - /// Produce the smallest range such that all values that may satisfy the given - /// predicate with any value contained within Other is contained in the - /// returned range. Formally, this returns a superset of - /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact - /// answer is not representable as a ConstantRange, the return value will be a - /// proper superset of the above. - /// - /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4) - static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, - const ConstantRange &Other); - - /// Produce the largest range such that all values in the returned range - /// satisfy the given predicate with all values contained within Other. - /// Formally, this returns a subset of - /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the - /// exact answer is not representable as a ConstantRange, the return value - /// will be a proper subset of the above. - /// - /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2) - static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred, - const ConstantRange &Other); - - /// Produce the exact range such that all values in the returned range satisfy - /// the given predicate with any value contained within Other. Formally, this - /// returns the exact answer when the superset of 'union over all y in Other - /// is exactly same as the subset of intersection over all y in Other. - /// { x : icmp op x y is true}'. - /// - /// Example: Pred = ult and Other = i8 3 returns [0, 3) - static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, - const APInt &Other); - - /// Does the predicate \p Pred hold between ranges this and \p Other? - /// NOTE: false does not mean that inverse predicate holds! - bool icmp(CmpInst::Predicate Pred, const ConstantRange &Other) const; - - /// Return true iff CR1 ult CR2 is equivalent to CR1 slt CR2. - /// Does not depend on strictness/direction of the predicate. - static bool - areInsensitiveToSignednessOfICmpPredicate(const ConstantRange &CR1, - const ConstantRange &CR2); - - /// Return true iff CR1 ult CR2 is equivalent to CR1 sge CR2. - /// Does not depend on strictness/direction of the predicate. - static bool - areInsensitiveToSignednessOfInvertedICmpPredicate(const ConstantRange &CR1, - const ConstantRange &CR2); - - /// If the comparison between constant ranges this and Other - /// is insensitive to the signedness of the comparison predicate, - /// return a predicate equivalent to \p Pred, with flipped signedness - /// (i.e. unsigned instead of signed or vice versa), and maybe inverted, - /// otherwise returns CmpInst::Predicate::BAD_ICMP_PREDICATE. - static CmpInst::Predicate - getEquivalentPredWithFlippedSignedness(CmpInst::Predicate Pred, - const ConstantRange &CR1, - const ConstantRange &CR2); - - /// Produce the largest range containing all X such that "X BinOp Y" is - /// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may - /// be *some* Y in Other for which additional X not contained in the result - /// also do not overflow. - /// - /// NoWrapKind must be one of OBO::NoUnsignedWrap or OBO::NoSignedWrap. - /// - /// Examples: - /// typedef OverflowingBinaryOperator OBO; - /// #define MGNR makeGuaranteedNoWrapRegion - /// MGNR(Add, [i8 1, 2), OBO::NoSignedWrap) == [-128, 127) - /// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap) == [0, -1) - /// MGNR(Add, [i8 0, 1), OBO::NoUnsignedWrap) == Full Set - /// MGNR(Add, [i8 -1, 6), OBO::NoSignedWrap) == [INT_MIN+1, INT_MAX-4) - /// MGNR(Sub, [i8 1, 2), OBO::NoSignedWrap) == [-127, 128) - /// MGNR(Sub, [i8 1, 2), OBO::NoUnsignedWrap) == [1, 0) - static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, - const ConstantRange &Other, - unsigned NoWrapKind); - - /// Produce the range that contains X if and only if "X BinOp Other" does - /// not wrap. - static ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp, - const APInt &Other, - unsigned NoWrapKind); - - /// Returns true if ConstantRange calculations are supported for intrinsic - /// with \p IntrinsicID. - static bool isIntrinsicSupported(Intrinsic::ID IntrinsicID); - - /// Compute range of intrinsic result for the given operand ranges. - static ConstantRange intrinsic(Intrinsic::ID IntrinsicID, - ArrayRef Ops); - - /// Set up \p Pred and \p RHS such that - /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if - /// successful. - bool getEquivalentICmp(CmpInst::Predicate &Pred, APInt &RHS) const; - - /// Set up \p Pred, \p RHS and \p Offset such that (V + Offset) Pred RHS - /// is true iff V is in the range. Prefers using Offset == 0 if possible. - void - getEquivalentICmp(CmpInst::Predicate &Pred, APInt &RHS, APInt &Offset) const; - - /// Return the lower value for this range. - const APInt &getLower() const { return Lower; } - - /// Return the upper value for this range. - const APInt &getUpper() const { return Upper; } - - /// Get the bit width of this ConstantRange. - uint32_t getBitWidth() const { return Lower.getBitWidth(); } - - /// Return true if this set contains all of the elements possible - /// for this data-type. - bool isFullSet() const; - - /// Return true if this set contains no members. - bool isEmptySet() const; - - /// Return true if this set wraps around the unsigned domain. Special cases: - /// * Empty set: Not wrapped. - /// * Full set: Not wrapped. - /// * [X, 0) == [X, Max]: Not wrapped. - bool isWrappedSet() const; - - /// Return true if the exclusive upper bound wraps around the unsigned - /// domain. Special cases: - /// * Empty set: Not wrapped. - /// * Full set: Not wrapped. - /// * [X, 0): Wrapped. - bool isUpperWrapped() const; - - /// Return true if this set wraps around the signed domain. Special cases: - /// * Empty set: Not wrapped. - /// * Full set: Not wrapped. - /// * [X, SignedMin) == [X, SignedMax]: Not wrapped. - bool isSignWrappedSet() const; - - /// Return true if the (exclusive) upper bound wraps around the signed - /// domain. Special cases: - /// * Empty set: Not wrapped. - /// * Full set: Not wrapped. - /// * [X, SignedMin): Wrapped. - bool isUpperSignWrapped() const; - - /// Return true if the specified value is in the set. - bool contains(const APInt &Val) const; - - /// Return true if the other range is a subset of this one. - bool contains(const ConstantRange &CR) const; - - /// If this set contains a single element, return it, otherwise return null. - const APInt *getSingleElement() const { - if (Upper == Lower + 1) - return &Lower; - return nullptr; - } - - /// If this set contains all but a single element, return it, otherwise return - /// null. - const APInt *getSingleMissingElement() const { - if (Lower == Upper + 1) - return &Upper; - return nullptr; - } - - /// Return true if this set contains exactly one member. - bool isSingleElement() const { return getSingleElement() != nullptr; } - - /// Compare set size of this range with the range CR. - bool isSizeStrictlySmallerThan(const ConstantRange &CR) const; - - /// Compare set size of this range with Value. - bool isSizeLargerThan(uint64_t MaxSize) const; - - /// Return true if all values in this range are negative. - bool isAllNegative() const; - - /// Return true if all values in this range are non-negative. - bool isAllNonNegative() const; - - /// Return the largest unsigned value contained in the ConstantRange. - APInt getUnsignedMax() const; - - /// Return the smallest unsigned value contained in the ConstantRange. - APInt getUnsignedMin() const; - - /// Return the largest signed value contained in the ConstantRange. - APInt getSignedMax() const; - - /// Return the smallest signed value contained in the ConstantRange. - APInt getSignedMin() const; - - /// Return true if this range is equal to another range. - bool operator==(const ConstantRange &CR) const { - return Lower == CR.Lower && Upper == CR.Upper; - } - bool operator!=(const ConstantRange &CR) const { - return !operator==(CR); - } - - /// Compute the maximal number of active bits needed to represent every value - /// in this range. - unsigned getActiveBits() const; - - /// Compute the maximal number of bits needed to represent every value - /// in this signed range. - unsigned getMinSignedBits() const; - - /// Subtract the specified constant from the endpoints of this constant range. - ConstantRange subtract(const APInt &CI) const; - - /// Subtract the specified range from this range (aka relative complement of - /// the sets). - ConstantRange difference(const ConstantRange &CR) const; - - /// If represented precisely, the result of some range operations may consist - /// of multiple disjoint ranges. As only a single range may be returned, any - /// range covering these disjoint ranges constitutes a valid result, but some - /// may be more useful than others depending on context. The preferred range - /// type specifies whether a range that is non-wrapping in the unsigned or - /// signed domain, or has the smallest size, is preferred. If a signedness is - /// preferred but all ranges are non-wrapping or all wrapping, then the - /// smallest set size is preferred. If there are multiple smallest sets, any - /// one of them may be returned. - enum PreferredRangeType { Smallest, Unsigned, Signed }; - - /// Return the range that results from the intersection of this range with - /// another range. If the intersection is disjoint, such that two results - /// are possible, the preferred range is determined by the PreferredRangeType. - ConstantRange intersectWith(const ConstantRange &CR, - PreferredRangeType Type = Smallest) const; - - /// Return the range that results from the union of this range - /// with another range. The resultant range is guaranteed to include the - /// elements of both sets, but may contain more. For example, [3, 9) union - /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included - /// in either set before. - ConstantRange unionWith(const ConstantRange &CR, - PreferredRangeType Type = Smallest) const; - - /// Intersect the two ranges and return the result if it can be represented - /// exactly, otherwise return None. - Optional exactIntersectWith(const ConstantRange &CR) const; - - /// Union the two ranges and return the result if it can be represented - /// exactly, otherwise return None. - Optional exactUnionWith(const ConstantRange &CR) const; - - /// Return a new range representing the possible values resulting - /// from an application of the specified cast operator to this range. \p - /// BitWidth is the target bitwidth of the cast. For casts which don't - /// change bitwidth, it must be the same as the source bitwidth. For casts - /// which do change bitwidth, the bitwidth must be consistent with the - /// requested cast and source bitwidth. - ConstantRange castOp(Instruction::CastOps CastOp, - uint32_t BitWidth) const; - - /// Return a new range in the specified integer type, which must - /// be strictly larger than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// zero extended to BitWidth. - ConstantRange zeroExtend(uint32_t BitWidth) const; - - /// Return a new range in the specified integer type, which must - /// be strictly larger than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// sign extended to BitWidth. - ConstantRange signExtend(uint32_t BitWidth) const; - - /// Return a new range in the specified integer type, which must be - /// strictly smaller than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// truncated to the specified type. - ConstantRange truncate(uint32_t BitWidth) const; - - /// Make this range have the bit width given by \p BitWidth. The - /// value is zero extended, truncated, or left alone to make it that width. - ConstantRange zextOrTrunc(uint32_t BitWidth) const; - - /// Make this range have the bit width given by \p BitWidth. The - /// value is sign extended, truncated, or left alone to make it that width. - ConstantRange sextOrTrunc(uint32_t BitWidth) const; - - /// Return a new range representing the possible values resulting - /// from an application of the specified binary operator to an left hand side - /// of this range and a right hand side of \p Other. - ConstantRange binaryOp(Instruction::BinaryOps BinOp, - const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an application of the specified overflowing binary operator to a - /// left hand side of this range and a right hand side of \p Other given - /// the provided knowledge about lack of wrapping \p NoWrapKind. - ConstantRange overflowingBinaryOp(Instruction::BinaryOps BinOp, - const ConstantRange &Other, - unsigned NoWrapKind) const; - - /// Return a new range representing the possible values resulting - /// from an addition of a value in this range and a value in \p Other. - ConstantRange add(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an addition with wrap type \p NoWrapKind of a value in this - /// range and a value in \p Other. - /// If the result range is disjoint, the preferred range is determined by the - /// \p PreferredRangeType. - ConstantRange addWithNoWrap(const ConstantRange &Other, unsigned NoWrapKind, - PreferredRangeType RangeType = Smallest) const; - - /// Return a new range representing the possible values resulting - /// from a subtraction of a value in this range and a value in \p Other. - ConstantRange sub(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an subtraction with wrap type \p NoWrapKind of a value in this - /// range and a value in \p Other. - /// If the result range is disjoint, the preferred range is determined by the - /// \p PreferredRangeType. - ConstantRange subWithNoWrap(const ConstantRange &Other, unsigned NoWrapKind, - PreferredRangeType RangeType = Smallest) const; - - /// Return a new range representing the possible values resulting - /// from a multiplication of a value in this range and a value in \p Other, - /// treating both this and \p Other as unsigned ranges. - ConstantRange multiply(const ConstantRange &Other) const; - - /// Return range of possible values for a signed multiplication of this and - /// \p Other. However, if overflow is possible always return a full range - /// rather than trying to determine a more precise result. - ConstantRange smul_fast(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a signed maximum of a value in this range and a value in \p Other. - ConstantRange smax(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an unsigned maximum of a value in this range and a value in \p Other. - ConstantRange umax(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a signed minimum of a value in this range and a value in \p Other. - ConstantRange smin(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an unsigned minimum of a value in this range and a value in \p Other. - ConstantRange umin(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an unsigned division of a value in this range and a value in - /// \p Other. - ConstantRange udiv(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a signed division of a value in this range and a value in - /// \p Other. Division by zero and division of SignedMin by -1 are considered - /// undefined behavior, in line with IR, and do not contribute towards the - /// result. - ConstantRange sdiv(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from an unsigned remainder operation of a value in this range and a - /// value in \p Other. - ConstantRange urem(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a signed remainder operation of a value in this range and a - /// value in \p Other. - ConstantRange srem(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting from - /// a binary-xor of a value in this range by an all-one value, - /// aka bitwise complement operation. - ConstantRange binaryNot() const; - - /// Return a new range representing the possible values resulting - /// from a binary-and of a value in this range by a value in \p Other. - ConstantRange binaryAnd(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a binary-or of a value in this range by a value in \p Other. - ConstantRange binaryOr(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a binary-xor of a value in this range by a value in \p Other. - ConstantRange binaryXor(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting - /// from a left shift of a value in this range by a value in \p Other. - /// TODO: This isn't fully implemented yet. - ConstantRange shl(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting from a - /// logical right shift of a value in this range and a value in \p Other. - ConstantRange lshr(const ConstantRange &Other) const; - - /// Return a new range representing the possible values resulting from a - /// arithmetic right shift of a value in this range and a value in \p Other. - ConstantRange ashr(const ConstantRange &Other) const; - - /// Perform an unsigned saturating addition of two constant ranges. - ConstantRange uadd_sat(const ConstantRange &Other) const; - - /// Perform a signed saturating addition of two constant ranges. - ConstantRange sadd_sat(const ConstantRange &Other) const; - - /// Perform an unsigned saturating subtraction of two constant ranges. - ConstantRange usub_sat(const ConstantRange &Other) const; - - /// Perform a signed saturating subtraction of two constant ranges. - ConstantRange ssub_sat(const ConstantRange &Other) const; - - /// Perform an unsigned saturating multiplication of two constant ranges. - ConstantRange umul_sat(const ConstantRange &Other) const; - - /// Perform a signed saturating multiplication of two constant ranges. - ConstantRange smul_sat(const ConstantRange &Other) const; - - /// Perform an unsigned saturating left shift of this constant range by a - /// value in \p Other. - ConstantRange ushl_sat(const ConstantRange &Other) const; - - /// Perform a signed saturating left shift of this constant range by a - /// value in \p Other. - ConstantRange sshl_sat(const ConstantRange &Other) const; - - /// Return a new range that is the logical not of the current set. - ConstantRange inverse() const; - - /// Calculate absolute value range. If the original range contains signed - /// min, then the resulting range will contain signed min if and only if - /// \p IntMinIsPoison is false. - ConstantRange abs(bool IntMinIsPoison = false) const; - - /// Represents whether an operation on the given constant range is known to - /// always or never overflow. - enum class OverflowResult { - /// Always overflows in the direction of signed/unsigned min value. - AlwaysOverflowsLow, - /// Always overflows in the direction of signed/unsigned max value. - AlwaysOverflowsHigh, - /// May or may not overflow. - MayOverflow, - /// Never overflows. - NeverOverflows, - }; - - /// Return whether unsigned add of the two ranges always/never overflows. - OverflowResult unsignedAddMayOverflow(const ConstantRange &Other) const; - - /// Return whether signed add of the two ranges always/never overflows. - OverflowResult signedAddMayOverflow(const ConstantRange &Other) const; - - /// Return whether unsigned sub of the two ranges always/never overflows. - OverflowResult unsignedSubMayOverflow(const ConstantRange &Other) const; - - /// Return whether signed sub of the two ranges always/never overflows. - OverflowResult signedSubMayOverflow(const ConstantRange &Other) const; - - /// Return whether unsigned mul of the two ranges always/never overflows. - OverflowResult unsignedMulMayOverflow(const ConstantRange &Other) const; - - /// Print out the bounds to a stream. - void print(raw_ostream &OS) const; - - /// Allow printing from a debugger easily. - void dump() const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) { - CR.print(OS); - return OS; -} - -/// Parse out a conservative ConstantRange from !range metadata. -/// -/// E.g. if RangeMD is !{i32 0, i32 10, i32 15, i32 20} then return [0, 20). -ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD); - -} // end namespace llvm - -#endif // LLVM_IR_CONSTANTRANGE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Constants.h b/suite/synctools/tablegen/include/llvm/IR/Constants.h deleted file mode 100644 index 05b35ec179..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Constants.h +++ /dev/null @@ -1,1461 +0,0 @@ -//===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains the declarations for the subclasses of Constant, -/// which represent the different flavors of constant values that live in LLVM. -/// Note that Constants are immutable (once created they never change) and are -/// fully shared by structural equivalence. This means that two structurally -/// equivalent constants will always have the same address. Constants are -/// created on demand as needed and never deleted: thus clients don't have to -/// worry about the lifetime of the objects. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CONSTANTS_H -#define LLVM_IR_CONSTANTS_H - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include - -namespace llvm { - -template struct ConstantAggrKeyType; - -/// Base class for constants with no operands. -/// -/// These constants have no operands; they represent their data directly. -/// Since they can be in use by unrelated modules (and are never based on -/// GlobalValues), it never makes sense to RAUW them. -class ConstantData : public Constant { - friend class Constant; - - Value *handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Constant data does not have operands!"); - } - -protected: - explicit ConstantData(Type *Ty, ValueTy VT) : Constant(Ty, VT, nullptr, 0) {} - - void *operator new(size_t S) { return User::operator new(S, 0); } - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - ConstantData(const ConstantData &) = delete; - - /// Methods to support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() >= ConstantDataFirstVal && - V->getValueID() <= ConstantDataLastVal; - } -}; - -//===----------------------------------------------------------------------===// -/// This is the shared class of boolean and integer constants. This class -/// represents both boolean and integral constants. -/// Class for constant integers. -class ConstantInt final : public ConstantData { - friend class Constant; - - APInt Val; - - ConstantInt(IntegerType *Ty, const APInt &V); - - void destroyConstantImpl(); - -public: - ConstantInt(const ConstantInt &) = delete; - - static ConstantInt *getTrue(LLVMContext &Context); - static ConstantInt *getFalse(LLVMContext &Context); - static ConstantInt *getBool(LLVMContext &Context, bool V); - static Constant *getTrue(Type *Ty); - static Constant *getFalse(Type *Ty); - static Constant *getBool(Type *Ty, bool V); - - /// If Ty is a vector type, return a Constant with a splat of the given - /// value. Otherwise return a ConstantInt for the given value. - static Constant *get(Type *Ty, uint64_t V, bool IsSigned = false); - - /// Return a ConstantInt with the specified integer value for the specified - /// type. If the type is wider than 64 bits, the value will be zero-extended - /// to fit the type, unless IsSigned is true, in which case the value will - /// be interpreted as a 64-bit signed integer and sign-extended to fit - /// the type. - /// Get a ConstantInt for a specific value. - static ConstantInt *get(IntegerType *Ty, uint64_t V, bool IsSigned = false); - - /// Return a ConstantInt with the specified value for the specified type. The - /// value V will be canonicalized to an unsigned APInt. Accessing it with - /// either getSExtValue() or getZExtValue() will yield a correctly sized and - /// signed value for the type Ty. - /// Get a ConstantInt for a specific signed value. - static ConstantInt *getSigned(IntegerType *Ty, int64_t V); - static Constant *getSigned(Type *Ty, int64_t V); - - /// Return a ConstantInt with the specified value and an implied Type. The - /// type is the integer type that corresponds to the bit width of the value. - static ConstantInt *get(LLVMContext &Context, const APInt &V); - - /// Return a ConstantInt constructed from the string strStart with the given - /// radix. - static ConstantInt *get(IntegerType *Ty, StringRef Str, uint8_t Radix); - - /// If Ty is a vector type, return a Constant with a splat of the given - /// value. Otherwise return a ConstantInt for the given value. - static Constant *get(Type *Ty, const APInt &V); - - /// Return the constant as an APInt value reference. This allows clients to - /// obtain a full-precision copy of the value. - /// Return the constant's value. - inline const APInt &getValue() const { return Val; } - - /// getBitWidth - Return the bitwidth of this constant. - unsigned getBitWidth() const { return Val.getBitWidth(); } - - /// Return the constant as a 64-bit unsigned integer value after it - /// has been zero extended as appropriate for the type of this constant. Note - /// that this method can assert if the value does not fit in 64 bits. - /// Return the zero extended value. - inline uint64_t getZExtValue() const { return Val.getZExtValue(); } - - /// Return the constant as a 64-bit integer value after it has been sign - /// extended as appropriate for the type of this constant. Note that - /// this method can assert if the value does not fit in 64 bits. - /// Return the sign extended value. - inline int64_t getSExtValue() const { return Val.getSExtValue(); } - - /// Return the constant as an llvm::MaybeAlign. - /// Note that this method can assert if the value does not fit in 64 bits or - /// is not a power of two. - inline MaybeAlign getMaybeAlignValue() const { - return MaybeAlign(getZExtValue()); - } - - /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`. - /// Note that this method can assert if the value does not fit in 64 bits or - /// is not a power of two. - inline Align getAlignValue() const { - return getMaybeAlignValue().valueOrOne(); - } - - /// A helper method that can be used to determine if the constant contained - /// within is equal to a constant. This only works for very small values, - /// because this is all that can be represented with all types. - /// Determine if this constant's value is same as an unsigned char. - bool equalsInt(uint64_t V) const { return Val == V; } - - /// getType - Specialize the getType() method to always return an IntegerType, - /// which reduces the amount of casting needed in parts of the compiler. - /// - inline IntegerType *getType() const { - return cast(Value::getType()); - } - - /// This static method returns true if the type Ty is big enough to - /// represent the value V. This can be used to avoid having the get method - /// assert when V is larger than Ty can represent. Note that there are two - /// versions of this method, one for unsigned and one for signed integers. - /// Although ConstantInt canonicalizes everything to an unsigned integer, - /// the signed version avoids callers having to convert a signed quantity - /// to the appropriate unsigned type before calling the method. - /// @returns true if V is a valid value for type Ty - /// Determine if the value is in range for the given type. - static bool isValueValidForType(Type *Ty, uint64_t V); - static bool isValueValidForType(Type *Ty, int64_t V); - - bool isNegative() const { return Val.isNegative(); } - - /// This is just a convenience method to make client code smaller for a - /// common code. It also correctly performs the comparison without the - /// potential for an assertion from getZExtValue(). - bool isZero() const { return Val.isZero(); } - - /// This is just a convenience method to make client code smaller for a - /// common case. It also correctly performs the comparison without the - /// potential for an assertion from getZExtValue(). - /// Determine if the value is one. - bool isOne() const { return Val.isOne(); } - - /// This function will return true iff every bit in this constant is set - /// to true. - /// @returns true iff this constant's bits are all set to true. - /// Determine if the value is all ones. - bool isMinusOne() const { return Val.isAllOnes(); } - - /// This function will return true iff this constant represents the largest - /// value that may be represented by the constant's type. - /// @returns true iff this is the largest value that may be represented - /// by this type. - /// Determine if the value is maximal. - bool isMaxValue(bool IsSigned) const { - if (IsSigned) - return Val.isMaxSignedValue(); - else - return Val.isMaxValue(); - } - - /// This function will return true iff this constant represents the smallest - /// value that may be represented by this constant's type. - /// @returns true if this is the smallest value that may be represented by - /// this type. - /// Determine if the value is minimal. - bool isMinValue(bool IsSigned) const { - if (IsSigned) - return Val.isMinSignedValue(); - else - return Val.isMinValue(); - } - - /// This function will return true iff this constant represents a value with - /// active bits bigger than 64 bits or a value greater than the given uint64_t - /// value. - /// @returns true iff this constant is greater or equal to the given number. - /// Determine if the value is greater or equal to the given number. - bool uge(uint64_t Num) const { return Val.uge(Num); } - - /// getLimitedValue - If the value is smaller than the specified limit, - /// return it, otherwise return the limit value. This causes the value - /// to saturate to the limit. - /// @returns the min of the value of the constant and the specified value - /// Get the constant's value with a saturation limit - uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { - return Val.getLimitedValue(Limit); - } - - /// Methods to support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == ConstantIntVal; - } -}; - -//===----------------------------------------------------------------------===// -/// ConstantFP - Floating Point Values [float, double] -/// -class ConstantFP final : public ConstantData { - friend class Constant; - - APFloat Val; - - ConstantFP(Type *Ty, const APFloat &V); - - void destroyConstantImpl(); - -public: - ConstantFP(const ConstantFP &) = delete; - - /// Floating point negation must be implemented with f(x) = -0.0 - x. This - /// method returns the negative zero constant for floating point or vector - /// floating point types; for all other types, it returns the null value. - static Constant *getZeroValueForNegation(Type *Ty); - - /// This returns a ConstantFP, or a vector containing a splat of a ConstantFP, - /// for the specified value in the specified type. This should only be used - /// for simple constant values like 2.0/1.0 etc, that are known-valid both as - /// host double and as the target format. - static Constant *get(Type *Ty, double V); - - /// If Ty is a vector type, return a Constant with a splat of the given - /// value. Otherwise return a ConstantFP for the given value. - static Constant *get(Type *Ty, const APFloat &V); - - static Constant *get(Type *Ty, StringRef Str); - static ConstantFP *get(LLVMContext &Context, const APFloat &V); - static Constant *getNaN(Type *Ty, bool Negative = false, - uint64_t Payload = 0); - static Constant *getQNaN(Type *Ty, bool Negative = false, - APInt *Payload = nullptr); - static Constant *getSNaN(Type *Ty, bool Negative = false, - APInt *Payload = nullptr); - static Constant *getNegativeZero(Type *Ty); - static Constant *getInfinity(Type *Ty, bool Negative = false); - - /// Return true if Ty is big enough to represent V. - static bool isValueValidForType(Type *Ty, const APFloat &V); - inline const APFloat &getValueAPF() const { return Val; } - inline const APFloat &getValue() const { return Val; } - - /// Return true if the value is positive or negative zero. - bool isZero() const { return Val.isZero(); } - - /// Return true if the sign bit is set. - bool isNegative() const { return Val.isNegative(); } - - /// Return true if the value is infinity - bool isInfinity() const { return Val.isInfinity(); } - - /// Return true if the value is a NaN. - bool isNaN() const { return Val.isNaN(); } - - /// We don't rely on operator== working on double values, as it returns true - /// for things that are clearly not equal, like -0.0 and 0.0. - /// As such, this method can be used to do an exact bit-for-bit comparison of - /// two floating point values. The version with a double operand is retained - /// because it's so convenient to write isExactlyValue(2.0), but please use - /// it only for simple constants. - bool isExactlyValue(const APFloat &V) const; - - bool isExactlyValue(double V) const { - bool ignored; - APFloat FV(V); - FV.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &ignored); - return isExactlyValue(FV); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantFPVal; - } -}; - -//===----------------------------------------------------------------------===// -/// All zero aggregate value -/// -class ConstantAggregateZero final : public ConstantData { - friend class Constant; - - explicit ConstantAggregateZero(Type *Ty) - : ConstantData(Ty, ConstantAggregateZeroVal) {} - - void destroyConstantImpl(); - -public: - ConstantAggregateZero(const ConstantAggregateZero &) = delete; - - static ConstantAggregateZero *get(Type *Ty); - - /// If this CAZ has array or vector type, return a zero with the right element - /// type. - Constant *getSequentialElement() const; - - /// If this CAZ has struct type, return a zero with the right element type for - /// the specified element. - Constant *getStructElement(unsigned Elt) const; - - /// Return a zero of the right value for the specified GEP index if we can, - /// otherwise return null (e.g. if C is a ConstantExpr). - Constant *getElementValue(Constant *C) const; - - /// Return a zero of the right value for the specified GEP index. - Constant *getElementValue(unsigned Idx) const; - - /// Return the number of elements in the array, vector, or struct. - ElementCount getElementCount() const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - /// - static bool classof(const Value *V) { - return V->getValueID() == ConstantAggregateZeroVal; - } -}; - -/// Base class for aggregate constants (with operands). -/// -/// These constants are aggregates of other constants, which are stored as -/// operands. -/// -/// Subclasses are \a ConstantStruct, \a ConstantArray, and \a -/// ConstantVector. -/// -/// \note Some subclasses of \a ConstantData are semantically aggregates -- -/// such as \a ConstantDataArray -- but are not subclasses of this because they -/// use operands. -class ConstantAggregate : public Constant { -protected: - ConstantAggregate(Type *T, ValueTy VT, ArrayRef V); - -public: - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() >= ConstantAggregateFirstVal && - V->getValueID() <= ConstantAggregateLastVal; - } -}; - -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantAggregate, Constant) - -//===----------------------------------------------------------------------===// -/// ConstantArray - Constant Array Declarations -/// -class ConstantArray final : public ConstantAggregate { - friend struct ConstantAggrKeyType; - friend class Constant; - - ConstantArray(ArrayType *T, ArrayRef Val); - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - // ConstantArray accessors - static Constant *get(ArrayType *T, ArrayRef V); - -private: - static Constant *getImpl(ArrayType *T, ArrayRef V); - -public: - /// Specialize the getType() method to always return an ArrayType, - /// which reduces the amount of casting needed in parts of the compiler. - inline ArrayType *getType() const { - return cast(Value::getType()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantArrayVal; - } -}; - -//===----------------------------------------------------------------------===// -// Constant Struct Declarations -// -class ConstantStruct final : public ConstantAggregate { - friend struct ConstantAggrKeyType; - friend class Constant; - - ConstantStruct(StructType *T, ArrayRef Val); - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - // ConstantStruct accessors - static Constant *get(StructType *T, ArrayRef V); - - template - static std::enable_if_t::value, Constant *> - get(StructType *T, Csts *...Vs) { - return get(T, ArrayRef({Vs...})); - } - - /// Return an anonymous struct that has the specified elements. - /// If the struct is possibly empty, then you must specify a context. - static Constant *getAnon(ArrayRef V, bool Packed = false) { - return get(getTypeForElements(V, Packed), V); - } - static Constant *getAnon(LLVMContext &Ctx, ArrayRef V, - bool Packed = false) { - return get(getTypeForElements(Ctx, V, Packed), V); - } - - /// Return an anonymous struct type to use for a constant with the specified - /// set of elements. The list must not be empty. - static StructType *getTypeForElements(ArrayRef V, - bool Packed = false); - /// This version of the method allows an empty list. - static StructType *getTypeForElements(LLVMContext &Ctx, - ArrayRef V, - bool Packed = false); - - /// Specialization - reduce amount of casting. - inline StructType *getType() const { - return cast(Value::getType()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantStructVal; - } -}; - -//===----------------------------------------------------------------------===// -/// Constant Vector Declarations -/// -class ConstantVector final : public ConstantAggregate { - friend struct ConstantAggrKeyType; - friend class Constant; - - ConstantVector(VectorType *T, ArrayRef Val); - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - // ConstantVector accessors - static Constant *get(ArrayRef V); - -private: - static Constant *getImpl(ArrayRef V); - -public: - /// Return a ConstantVector with the specified constant in each element. - /// Note that this might not return an instance of ConstantVector - static Constant *getSplat(ElementCount EC, Constant *Elt); - - /// Specialize the getType() method to always return a FixedVectorType, - /// which reduces the amount of casting needed in parts of the compiler. - inline FixedVectorType *getType() const { - return cast(Value::getType()); - } - - /// If all elements of the vector constant have the same value, return that - /// value. Otherwise, return nullptr. Ignore undefined elements by setting - /// AllowUndefs to true. - Constant *getSplatValue(bool AllowUndefs = false) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantVectorVal; - } -}; - -//===----------------------------------------------------------------------===// -/// A constant pointer value that points to null -/// -class ConstantPointerNull final : public ConstantData { - friend class Constant; - - explicit ConstantPointerNull(PointerType *T) - : ConstantData(T, Value::ConstantPointerNullVal) {} - - void destroyConstantImpl(); - -public: - ConstantPointerNull(const ConstantPointerNull &) = delete; - - /// Static factory methods - Return objects of the specified value - static ConstantPointerNull *get(PointerType *T); - - /// Specialize the getType() method to always return an PointerType, - /// which reduces the amount of casting needed in parts of the compiler. - inline PointerType *getType() const { - return cast(Value::getType()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantPointerNullVal; - } -}; - -//===----------------------------------------------------------------------===// -/// ConstantDataSequential - A vector or array constant whose element type is a -/// simple 1/2/4/8-byte integer or half/bfloat/float/double, and whose elements -/// are just simple data values (i.e. ConstantInt/ConstantFP). This Constant -/// node has no operands because it stores all of the elements of the constant -/// as densely packed data, instead of as Value*'s. -/// -/// This is the common base class of ConstantDataArray and ConstantDataVector. -/// -class ConstantDataSequential : public ConstantData { - friend class LLVMContextImpl; - friend class Constant; - - /// A pointer to the bytes underlying this constant (which is owned by the - /// uniquing StringMap). - const char *DataElements; - - /// This forms a link list of ConstantDataSequential nodes that have - /// the same value but different type. For example, 0,0,0,1 could be a 4 - /// element array of i8, or a 1-element array of i32. They'll both end up in - /// the same StringMap bucket, linked up. - std::unique_ptr Next; - - void destroyConstantImpl(); - -protected: - explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) - : ConstantData(ty, VT), DataElements(Data) {} - - static Constant *getImpl(StringRef Bytes, Type *Ty); - -public: - ConstantDataSequential(const ConstantDataSequential &) = delete; - - /// Return true if a ConstantDataSequential can be formed with a vector or - /// array of the specified element type. - /// ConstantDataArray only works with normal float and int types that are - /// stored densely in memory, not with things like i42 or x86_f80. - static bool isElementTypeCompatible(Type *Ty); - - /// If this is a sequential container of integers (of any size), return the - /// specified element in the low bits of a uint64_t. - uint64_t getElementAsInteger(unsigned i) const; - - /// If this is a sequential container of integers (of any size), return the - /// specified element as an APInt. - APInt getElementAsAPInt(unsigned i) const; - - /// If this is a sequential container of floating point type, return the - /// specified element as an APFloat. - APFloat getElementAsAPFloat(unsigned i) const; - - /// If this is an sequential container of floats, return the specified element - /// as a float. - float getElementAsFloat(unsigned i) const; - - /// If this is an sequential container of doubles, return the specified - /// element as a double. - double getElementAsDouble(unsigned i) const; - - /// Return a Constant for a specified index's element. - /// Note that this has to compute a new constant to return, so it isn't as - /// efficient as getElementAsInteger/Float/Double. - Constant *getElementAsConstant(unsigned i) const; - - /// Return the element type of the array/vector. - Type *getElementType() const; - - /// Return the number of elements in the array or vector. - unsigned getNumElements() const; - - /// Return the size (in bytes) of each element in the array/vector. - /// The size of the elements is known to be a multiple of one byte. - uint64_t getElementByteSize() const; - - /// This method returns true if this is an array of \p CharSize integers. - bool isString(unsigned CharSize = 8) const; - - /// This method returns true if the array "isString", ends with a null byte, - /// and does not contains any other null bytes. - bool isCString() const; - - /// If this array is isString(), then this method returns the array as a - /// StringRef. Otherwise, it asserts out. - StringRef getAsString() const { - assert(isString() && "Not a string"); - return getRawDataValues(); - } - - /// If this array is isCString(), then this method returns the array (without - /// the trailing null byte) as a StringRef. Otherwise, it asserts out. - StringRef getAsCString() const { - assert(isCString() && "Isn't a C string"); - StringRef Str = getAsString(); - return Str.substr(0, Str.size() - 1); - } - - /// Return the raw, underlying, bytes of this data. Note that this is an - /// extremely tricky thing to work with, as it exposes the host endianness of - /// the data elements. - StringRef getRawDataValues() const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantDataArrayVal || - V->getValueID() == ConstantDataVectorVal; - } - -private: - const char *getElementPointer(unsigned Elt) const; -}; - -//===----------------------------------------------------------------------===// -/// An array constant whose element type is a simple 1/2/4/8-byte integer or -/// float/double, and whose elements are just simple data values -/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it -/// stores all of the elements of the constant as densely packed data, instead -/// of as Value*'s. -class ConstantDataArray final : public ConstantDataSequential { - friend class ConstantDataSequential; - - explicit ConstantDataArray(Type *ty, const char *Data) - : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {} - -public: - ConstantDataArray(const ConstantDataArray &) = delete; - - /// get() constructor - Return a constant with array type with an element - /// count and element type matching the ArrayRef passed in. Note that this - /// can return a ConstantAggregateZero object. - template - static Constant *get(LLVMContext &Context, ArrayRef Elts) { - const char *Data = reinterpret_cast(Elts.data()); - return getRaw(StringRef(Data, Elts.size() * sizeof(ElementTy)), Elts.size(), - Type::getScalarTy(Context)); - } - - /// get() constructor - ArrayTy needs to be compatible with - /// ArrayRef. Calls get(LLVMContext, ArrayRef). - template - static Constant *get(LLVMContext &Context, ArrayTy &Elts) { - return ConstantDataArray::get(Context, makeArrayRef(Elts)); - } - - /// getRaw() constructor - Return a constant with array type with an element - /// count and element type matching the NumElements and ElementTy parameters - /// passed in. Note that this can return a ConstantAggregateZero object. - /// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is - /// the buffer containing the elements. Be careful to make sure Data uses the - /// right endianness, the buffer will be used as-is. - static Constant *getRaw(StringRef Data, uint64_t NumElements, - Type *ElementTy) { - Type *Ty = ArrayType::get(ElementTy, NumElements); - return getImpl(Data, Ty); - } - - /// getFP() constructors - Return a constant of array type with a float - /// element type taken from argument `ElementType', and count taken from - /// argument `Elts'. The amount of bits of the contained type must match the - /// number of bits of the type contained in the passed in ArrayRef. - /// (i.e. half or bfloat for 16bits, float for 32bits, double for 64bits) Note - /// that this can return a ConstantAggregateZero object. - static Constant *getFP(Type *ElementType, ArrayRef Elts); - static Constant *getFP(Type *ElementType, ArrayRef Elts); - static Constant *getFP(Type *ElementType, ArrayRef Elts); - - /// This method constructs a CDS and initializes it with a text string. - /// The default behavior (AddNull==true) causes a null terminator to - /// be placed at the end of the array (increasing the length of the string by - /// one more than the StringRef would normally indicate. Pass AddNull=false - /// to disable this behavior. - static Constant *getString(LLVMContext &Context, StringRef Initializer, - bool AddNull = true); - - /// Specialize the getType() method to always return an ArrayType, - /// which reduces the amount of casting needed in parts of the compiler. - inline ArrayType *getType() const { - return cast(Value::getType()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantDataArrayVal; - } -}; - -//===----------------------------------------------------------------------===// -/// A vector constant whose element type is a simple 1/2/4/8-byte integer or -/// float/double, and whose elements are just simple data values -/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it -/// stores all of the elements of the constant as densely packed data, instead -/// of as Value*'s. -class ConstantDataVector final : public ConstantDataSequential { - friend class ConstantDataSequential; - - explicit ConstantDataVector(Type *ty, const char *Data) - : ConstantDataSequential(ty, ConstantDataVectorVal, Data), - IsSplatSet(false) {} - // Cache whether or not the constant is a splat. - mutable bool IsSplatSet : 1; - mutable bool IsSplat : 1; - bool isSplatData() const; - -public: - ConstantDataVector(const ConstantDataVector &) = delete; - - /// get() constructors - Return a constant with vector type with an element - /// count and element type matching the ArrayRef passed in. Note that this - /// can return a ConstantAggregateZero object. - static Constant *get(LLVMContext &Context, ArrayRef Elts); - static Constant *get(LLVMContext &Context, ArrayRef Elts); - static Constant *get(LLVMContext &Context, ArrayRef Elts); - static Constant *get(LLVMContext &Context, ArrayRef Elts); - static Constant *get(LLVMContext &Context, ArrayRef Elts); - static Constant *get(LLVMContext &Context, ArrayRef Elts); - - /// getRaw() constructor - Return a constant with vector type with an element - /// count and element type matching the NumElements and ElementTy parameters - /// passed in. Note that this can return a ConstantAggregateZero object. - /// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is - /// the buffer containing the elements. Be careful to make sure Data uses the - /// right endianness, the buffer will be used as-is. - static Constant *getRaw(StringRef Data, uint64_t NumElements, - Type *ElementTy) { - Type *Ty = VectorType::get(ElementTy, ElementCount::getFixed(NumElements)); - return getImpl(Data, Ty); - } - - /// getFP() constructors - Return a constant of vector type with a float - /// element type taken from argument `ElementType', and count taken from - /// argument `Elts'. The amount of bits of the contained type must match the - /// number of bits of the type contained in the passed in ArrayRef. - /// (i.e. half or bfloat for 16bits, float for 32bits, double for 64bits) Note - /// that this can return a ConstantAggregateZero object. - static Constant *getFP(Type *ElementType, ArrayRef Elts); - static Constant *getFP(Type *ElementType, ArrayRef Elts); - static Constant *getFP(Type *ElementType, ArrayRef Elts); - - /// Return a ConstantVector with the specified constant in each element. - /// The specified constant has to be a of a compatible type (i8/i16/ - /// i32/i64/half/bfloat/float/double) and must be a ConstantFP or ConstantInt. - static Constant *getSplat(unsigned NumElts, Constant *Elt); - - /// Returns true if this is a splat constant, meaning that all elements have - /// the same value. - bool isSplat() const; - - /// If this is a splat constant, meaning that all of the elements have the - /// same value, return that value. Otherwise return NULL. - Constant *getSplatValue() const; - - /// Specialize the getType() method to always return a FixedVectorType, - /// which reduces the amount of casting needed in parts of the compiler. - inline FixedVectorType *getType() const { - return cast(Value::getType()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantDataVectorVal; - } -}; - -//===----------------------------------------------------------------------===// -/// A constant token which is empty -/// -class ConstantTokenNone final : public ConstantData { - friend class Constant; - - explicit ConstantTokenNone(LLVMContext &Context) - : ConstantData(Type::getTokenTy(Context), ConstantTokenNoneVal) {} - - void destroyConstantImpl(); - -public: - ConstantTokenNone(const ConstantTokenNone &) = delete; - - /// Return the ConstantTokenNone. - static ConstantTokenNone *get(LLVMContext &Context); - - /// Methods to support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == ConstantTokenNoneVal; - } -}; - -/// The address of a basic block. -/// -class BlockAddress final : public Constant { - friend class Constant; - - BlockAddress(Function *F, BasicBlock *BB); - - void *operator new(size_t S) { return User::operator new(S, 2); } - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Return a BlockAddress for the specified function and basic block. - static BlockAddress *get(Function *F, BasicBlock *BB); - - /// Return a BlockAddress for the specified basic block. The basic - /// block must be embedded into a function. - static BlockAddress *get(BasicBlock *BB); - - /// Lookup an existing \c BlockAddress constant for the given BasicBlock. - /// - /// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress. - static BlockAddress *lookup(const BasicBlock *BB); - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - Function *getFunction() const { return (Function *)Op<0>().get(); } - BasicBlock *getBasicBlock() const { return (BasicBlock *)Op<1>().get(); } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == BlockAddressVal; - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) - -/// Wrapper for a function that represents a value that -/// functionally represents the original function. This can be a function, -/// global alias to a function, or an ifunc. -class DSOLocalEquivalent final : public Constant { - friend class Constant; - - DSOLocalEquivalent(GlobalValue *GV); - - void *operator new(size_t S) { return User::operator new(S, 1); } - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Return a DSOLocalEquivalent for the specified global value. - static DSOLocalEquivalent *get(GlobalValue *GV); - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - GlobalValue *getGlobalValue() const { - return cast(Op<0>().get()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == DSOLocalEquivalentVal; - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(DSOLocalEquivalent, Value) - -/// Wrapper for a value that won't be replaced with a CFI jump table -/// pointer in LowerTypeTestsModule. -class NoCFIValue final : public Constant { - friend class Constant; - - NoCFIValue(GlobalValue *GV); - - void *operator new(size_t S) { return User::operator new(S, 1); } - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -public: - /// Return a NoCFIValue for the specified function. - static NoCFIValue *get(GlobalValue *GV); - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - GlobalValue *getGlobalValue() const { - return cast(Op<0>().get()); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == NoCFIValueVal; - } -}; - -template <> -struct OperandTraits : public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(NoCFIValue, Value) - -//===----------------------------------------------------------------------===// -/// A constant value that is initialized with an expression using -/// other constant values. -/// -/// This class uses the standard Instruction opcodes to define the various -/// constant expressions. The Opcode field for the ConstantExpr class is -/// maintained in the Value::SubclassData field. -class ConstantExpr : public Constant { - friend struct ConstantExprKeyType; - friend class Constant; - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - -protected: - ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) - : Constant(ty, ConstantExprVal, Ops, NumOps) { - // Operation type (an Instruction opcode) is stored as the SubclassData. - setValueSubclassData(Opcode); - } - - ~ConstantExpr() = default; - -public: - // Static methods to construct a ConstantExpr of different kinds. Note that - // these methods may return an object that is not an instance of the - // ConstantExpr class, because they will attempt to fold the constant - // expression into something simpler if possible. - - /// getAlignOf constant expr - computes the alignment of a type in a target - /// independent way (Note: the return type is an i64). - static Constant *getAlignOf(Type *Ty); - - /// getSizeOf constant expr - computes the (alloc) size of a type (in - /// address-units, not bits) in a target independent way (Note: the return - /// type is an i64). - /// - static Constant *getSizeOf(Type *Ty); - - /// getOffsetOf constant expr - computes the offset of a struct field in a - /// target independent way (Note: the return type is an i64). - /// - static Constant *getOffsetOf(StructType *STy, unsigned FieldNo); - - /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, - /// which supports any aggregate type, and any Constant index. - /// - static Constant *getOffsetOf(Type *Ty, Constant *FieldNo); - - static Constant *getNeg(Constant *C, bool HasNUW = false, - bool HasNSW = false); - static Constant *getFNeg(Constant *C); - static Constant *getNot(Constant *C); - static Constant *getAdd(Constant *C1, Constant *C2, bool HasNUW = false, - bool HasNSW = false); - static Constant *getFAdd(Constant *C1, Constant *C2); - static Constant *getSub(Constant *C1, Constant *C2, bool HasNUW = false, - bool HasNSW = false); - static Constant *getFSub(Constant *C1, Constant *C2); - static Constant *getMul(Constant *C1, Constant *C2, bool HasNUW = false, - bool HasNSW = false); - static Constant *getFMul(Constant *C1, Constant *C2); - static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getFDiv(Constant *C1, Constant *C2); - static Constant *getURem(Constant *C1, Constant *C2); - static Constant *getSRem(Constant *C1, Constant *C2); - static Constant *getFRem(Constant *C1, Constant *C2); - static Constant *getAnd(Constant *C1, Constant *C2); - static Constant *getOr(Constant *C1, Constant *C2); - static Constant *getXor(Constant *C1, Constant *C2); - static Constant *getUMin(Constant *C1, Constant *C2); - static Constant *getShl(Constant *C1, Constant *C2, bool HasNUW = false, - bool HasNSW = false); - static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getSExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getZExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getFPTrunc(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - static Constant *getFPExtend(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - static Constant *getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getPtrToInt(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - static Constant *getIntToPtr(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - static Constant *getBitCast(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - static Constant *getAddrSpaceCast(Constant *C, Type *Ty, - bool OnlyIfReduced = false); - - static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } - static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } - - static Constant *getNSWAdd(Constant *C1, Constant *C2) { - return getAdd(C1, C2, false, true); - } - - static Constant *getNUWAdd(Constant *C1, Constant *C2) { - return getAdd(C1, C2, true, false); - } - - static Constant *getNSWSub(Constant *C1, Constant *C2) { - return getSub(C1, C2, false, true); - } - - static Constant *getNUWSub(Constant *C1, Constant *C2) { - return getSub(C1, C2, true, false); - } - - static Constant *getNSWMul(Constant *C1, Constant *C2) { - return getMul(C1, C2, false, true); - } - - static Constant *getNUWMul(Constant *C1, Constant *C2) { - return getMul(C1, C2, true, false); - } - - static Constant *getNSWShl(Constant *C1, Constant *C2) { - return getShl(C1, C2, false, true); - } - - static Constant *getNUWShl(Constant *C1, Constant *C2) { - return getShl(C1, C2, true, false); - } - - static Constant *getExactSDiv(Constant *C1, Constant *C2) { - return getSDiv(C1, C2, true); - } - - static Constant *getExactUDiv(Constant *C1, Constant *C2) { - return getUDiv(C1, C2, true); - } - - static Constant *getExactAShr(Constant *C1, Constant *C2) { - return getAShr(C1, C2, true); - } - - static Constant *getExactLShr(Constant *C1, Constant *C2) { - return getLShr(C1, C2, true); - } - - /// If C is a scalar/fixed width vector of known powers of 2, then this - /// function returns a new scalar/fixed width vector obtained from logBase2 - /// of C. Undef vector elements are set to zero. - /// Return a null pointer otherwise. - static Constant *getExactLogBase2(Constant *C); - - /// Return the identity constant for a binary opcode. - /// The identity constant C is defined as X op C = X and C op X = X for every - /// X when the binary operation is commutative. If the binop is not - /// commutative, callers can acquire the operand 1 identity constant by - /// setting AllowRHSConstant to true. For example, any shift has a zero - /// identity constant for operand 1: X shift 0 = X. - /// Return nullptr if the operator does not have an identity constant. - static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty, - bool AllowRHSConstant = false); - - /// Return the absorbing element for the given binary - /// operation, i.e. a constant C such that X op C = C and C op X = C for - /// every X. For example, this returns zero for integer multiplication. - /// It returns null if the operator doesn't have an absorbing element. - static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty); - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - - /// Convenience function for getting a Cast operation. - /// - /// \param ops The opcode for the conversion - /// \param C The constant to be converted - /// \param Ty The type to which the constant is converted - /// \param OnlyIfReduced see \a getWithOperands() docs. - static Constant *getCast(unsigned ops, Constant *C, Type *Ty, - bool OnlyIfReduced = false); - - // Create a ZExt or BitCast cast constant expression - static Constant * - getZExtOrBitCast(Constant *C, ///< The constant to zext or bitcast - Type *Ty ///< The type to zext or bitcast C to - ); - - // Create a SExt or BitCast cast constant expression - static Constant * - getSExtOrBitCast(Constant *C, ///< The constant to sext or bitcast - Type *Ty ///< The type to sext or bitcast C to - ); - - // Create a Trunc or BitCast cast constant expression - static Constant * - getTruncOrBitCast(Constant *C, ///< The constant to trunc or bitcast - Type *Ty ///< The type to trunc or bitcast C to - ); - - /// Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant - /// expression. - static Constant * - getPointerCast(Constant *C, ///< The pointer value to be casted (operand 0) - Type *Ty ///< The type to which cast should be made - ); - - /// Create a BitCast or AddrSpaceCast for a pointer type depending on - /// the address space. - static Constant *getPointerBitCastOrAddrSpaceCast( - Constant *C, ///< The constant to addrspacecast or bitcast - Type *Ty ///< The type to bitcast or addrspacecast C to - ); - - /// Create a ZExt, Bitcast or Trunc for integer -> integer casts - static Constant * - getIntegerCast(Constant *C, ///< The integer constant to be casted - Type *Ty, ///< The integer type to cast to - bool IsSigned ///< Whether C should be treated as signed or not - ); - - /// Create a FPExt, Bitcast or FPTrunc for fp -> fp casts - static Constant *getFPCast(Constant *C, ///< The integer constant to be casted - Type *Ty ///< The integer type to cast to - ); - - /// Return true if this is a convert constant expression - bool isCast() const; - - /// Return true if this is a compare constant expression - bool isCompare() const; - - /// Return true if this is an insertvalue or extractvalue expression, - /// and the getIndices() method may be used. - bool hasIndices() const; - - /// Select constant expr - /// - /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getSelect(Constant *C, Constant *V1, Constant *V2, - Type *OnlyIfReducedTy = nullptr); - - /// get - Return a unary operator constant expression, - /// folding if possible. - /// - /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *get(unsigned Opcode, Constant *C1, unsigned Flags = 0, - Type *OnlyIfReducedTy = nullptr); - - /// get - Return a binary or shift operator constant expression, - /// folding if possible. - /// - /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr); - - /// Return an ICmp or FCmp comparison operator constant expression. - /// - /// \param OnlyIfReduced see \a getWithOperands() docs. - static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2, - bool OnlyIfReduced = false); - - /// get* - Return some common constants without having to - /// specify the full Instruction::OPCODE identifier. - /// - static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS, - bool OnlyIfReduced = false); - static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS, - bool OnlyIfReduced = false); - - /// Getelementptr form. Value* is only accepted for convenience; - /// all elements must be Constants. - /// - /// \param InRangeIndex the inrange index if present or None. - /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getGetElementPtr(Type *Ty, Constant *C, - ArrayRef IdxList, - bool InBounds = false, - Optional InRangeIndex = None, - Type *OnlyIfReducedTy = nullptr) { - return getGetElementPtr( - Ty, C, makeArrayRef((Value *const *)IdxList.data(), IdxList.size()), - InBounds, InRangeIndex, OnlyIfReducedTy); - } - static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, - bool InBounds = false, - Optional InRangeIndex = None, - Type *OnlyIfReducedTy = nullptr) { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef or - // ArrayRef. - return getGetElementPtr(Ty, C, cast(Idx), InBounds, InRangeIndex, - OnlyIfReducedTy); - } - static Constant *getGetElementPtr(Type *Ty, Constant *C, - ArrayRef IdxList, - bool InBounds = false, - Optional InRangeIndex = None, - Type *OnlyIfReducedTy = nullptr); - - /// Create an "inbounds" getelementptr. See the documentation for the - /// "inbounds" flag in LangRef.html for details. - static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, - ArrayRef IdxList) { - return getGetElementPtr(Ty, C, IdxList, true); - } - static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, - Constant *Idx) { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef or - // ArrayRef. - return getGetElementPtr(Ty, C, Idx, true); - } - static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, - ArrayRef IdxList) { - return getGetElementPtr(Ty, C, IdxList, true); - } - - static Constant *getExtractElement(Constant *Vec, Constant *Idx, - Type *OnlyIfReducedTy = nullptr); - static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx, - Type *OnlyIfReducedTy = nullptr); - static Constant *getShuffleVector(Constant *V1, Constant *V2, - ArrayRef Mask, - Type *OnlyIfReducedTy = nullptr); - static Constant *getExtractValue(Constant *Agg, ArrayRef Idxs, - Type *OnlyIfReducedTy = nullptr); - static Constant *getInsertValue(Constant *Agg, Constant *Val, - ArrayRef Idxs, - Type *OnlyIfReducedTy = nullptr); - - /// Return the opcode at the root of this constant expression - unsigned getOpcode() const { return getSubclassDataFromValue(); } - - /// Return the ICMP or FCMP predicate value. Assert if this is not an ICMP or - /// FCMP constant expression. - unsigned getPredicate() const; - - /// Assert that this is an insertvalue or exactvalue - /// expression and return the list of indices. - ArrayRef getIndices() const; - - /// Assert that this is a shufflevector and return the mask. See class - /// ShuffleVectorInst for a description of the mask representation. - ArrayRef getShuffleMask() const; - - /// Assert that this is a shufflevector and return the mask. - /// - /// TODO: This is a temporary hack until we update the bitcode format for - /// shufflevector. - Constant *getShuffleMaskForBitcode() const; - - /// Return a string representation for an opcode. - const char *getOpcodeName() const; - - /// This returns the current constant expression with the operands replaced - /// with the specified values. The specified array must have the same number - /// of operands as our current one. - Constant *getWithOperands(ArrayRef Ops) const { - return getWithOperands(Ops, getType()); - } - - /// Get the current expression with the operands replaced. - /// - /// Return the current constant expression with the operands replaced with \c - /// Ops and the type with \c Ty. The new operands must have the same number - /// as the current ones. - /// - /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something - /// gets constant-folded, the type changes, or the expression is otherwise - /// canonicalized. This parameter should almost always be \c false. - Constant *getWithOperands(ArrayRef Ops, Type *Ty, - bool OnlyIfReduced = false, - Type *SrcTy = nullptr) const; - - /// Returns an Instruction which implements the same operation as this - /// ConstantExpr. If \p InsertBefore is not null, the new instruction is - /// inserted before it, otherwise it is not inserted into any basic block. - /// - /// A better approach to this could be to have a constructor for Instruction - /// which would take a ConstantExpr parameter, but that would have spread - /// implementation details of ConstantExpr outside of Constants.cpp, which - /// would make it harder to remove ConstantExprs altogether. - Instruction *getAsInstruction(Instruction *InsertBefore = nullptr) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == ConstantExprVal; - } - -private: - // Shadow Value::setValueSubclassData with a private forwarding method so that - // subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } -}; - -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) - -//===----------------------------------------------------------------------===// -/// 'undef' values are things that do not have specified contents. -/// These are used for a variety of purposes, including global variable -/// initializers and operands to instructions. 'undef' values can occur with -/// any first-class type. -/// -/// Undef values aren't exactly constants; if they have multiple uses, they -/// can appear to have different bit patterns at each use. See -/// LangRef.html#undefvalues for details. -/// -class UndefValue : public ConstantData { - friend class Constant; - - explicit UndefValue(Type *T) : ConstantData(T, UndefValueVal) {} - - void destroyConstantImpl(); - -protected: - explicit UndefValue(Type *T, ValueTy vty) : ConstantData(T, vty) {} - -public: - UndefValue(const UndefValue &) = delete; - - /// Static factory methods - Return an 'undef' object of the specified type. - static UndefValue *get(Type *T); - - /// If this Undef has array or vector type, return a undef with the right - /// element type. - UndefValue *getSequentialElement() const; - - /// If this undef has struct type, return a undef with the right element type - /// for the specified element. - UndefValue *getStructElement(unsigned Elt) const; - - /// Return an undef of the right value for the specified GEP index if we can, - /// otherwise return null (e.g. if C is a ConstantExpr). - UndefValue *getElementValue(Constant *C) const; - - /// Return an undef of the right value for the specified GEP index. - UndefValue *getElementValue(unsigned Idx) const; - - /// Return the number of elements in the array, vector, or struct. - unsigned getNumElements() const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == UndefValueVal || - V->getValueID() == PoisonValueVal; - } -}; - -//===----------------------------------------------------------------------===// -/// In order to facilitate speculative execution, many instructions do not -/// invoke immediate undefined behavior when provided with illegal operands, -/// and return a poison value instead. -/// -/// see LangRef.html#poisonvalues for details. -/// -class PoisonValue final : public UndefValue { - friend class Constant; - - explicit PoisonValue(Type *T) : UndefValue(T, PoisonValueVal) {} - - void destroyConstantImpl(); - -public: - PoisonValue(const PoisonValue &) = delete; - - /// Static factory methods - Return an 'poison' object of the specified type. - static PoisonValue *get(Type *T); - - /// If this poison has array or vector type, return a poison with the right - /// element type. - PoisonValue *getSequentialElement() const; - - /// If this poison has struct type, return a poison with the right element - /// type for the specified element. - PoisonValue *getStructElement(unsigned Elt) const; - - /// Return an poison of the right value for the specified GEP index if we can, - /// otherwise return null (e.g. if C is a ConstantExpr). - PoisonValue *getElementValue(Constant *C) const; - - /// Return an poison of the right value for the specified GEP index. - PoisonValue *getElementValue(unsigned Idx) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == PoisonValueVal; - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_CONSTANTS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ConstrainedOps.def b/suite/synctools/tablegen/include/llvm/IR/ConstrainedOps.def deleted file mode 100644 index ecba68fe0c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ConstrainedOps.def +++ /dev/null @@ -1,107 +0,0 @@ -//===- llvm/IR/ConstrainedOps.def - Constrained intrinsics ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines properties of constrained intrinsics, in particular corresponding -// floating point operations and DAG nodes. -// -//===----------------------------------------------------------------------===// - -// DAG_FUNCTION defers to DAG_INSTRUCTION if its defined, otherwise FUNCTION. -#ifndef DAG_FUNCTION -#ifdef DAG_INSTRUCTION -#define DAG_FUNCTION(N,A,R,I,D) DAG_INSTRUCTION(N,A,R,I,D) -#else -#define DAG_FUNCTION(N,A,R,I,D) FUNCTION(N,A,R,I) -#endif -#endif - -#ifndef INSTRUCTION -#define INSTRUCTION(N,A,R,I) -#endif - -// DAG_INSTRUCTION is treated like an INSTRUCTION if the DAG node isn't used. -#ifndef DAG_INSTRUCTION -#define DAG_INSTRUCTION(N,A,R,I,D) INSTRUCTION(N,A,R,I) -#endif - -// In most cases intrinsic function is handled similar to instruction. -#ifndef FUNCTION -#define FUNCTION(N,A,R,I) INSTRUCTION(N,A,R,I) -#endif - -// Compare instruction have a DAG node so they are treated like DAG_INSTRUCTION. -#ifndef CMP_INSTRUCTION -#define CMP_INSTRUCTION(N,A,R,I,D) DAG_INSTRUCTION(N,A,R,I,D) -#endif - -// Arguments of the entries are: -// - instruction or intrinsic function name. -// - Number of original instruction/intrinsic arguments. -// - 1 if the corresponding constrained intrinsic has rounding mode argument. -// - name of the constrained intrinsic to represent this instruction/function. -// - DAG node corresponding to the constrained intrinsic without prefix STRICT_. - -// These are definitions for instructions, that are converted into constrained -// intrinsics. -// -DAG_INSTRUCTION(FAdd, 2, 1, experimental_constrained_fadd, FADD) -DAG_INSTRUCTION(FSub, 2, 1, experimental_constrained_fsub, FSUB) -DAG_INSTRUCTION(FMul, 2, 1, experimental_constrained_fmul, FMUL) -DAG_INSTRUCTION(FDiv, 2, 1, experimental_constrained_fdiv, FDIV) -DAG_INSTRUCTION(FRem, 2, 1, experimental_constrained_frem, FREM) -DAG_INSTRUCTION(FPExt, 1, 0, experimental_constrained_fpext, FP_EXTEND) -DAG_INSTRUCTION(SIToFP, 1, 1, experimental_constrained_sitofp, SINT_TO_FP) -DAG_INSTRUCTION(UIToFP, 1, 1, experimental_constrained_uitofp, UINT_TO_FP) -DAG_INSTRUCTION(FPToSI, 1, 0, experimental_constrained_fptosi, FP_TO_SINT) -DAG_INSTRUCTION(FPToUI, 1, 0, experimental_constrained_fptoui, FP_TO_UINT) -DAG_INSTRUCTION(FPTrunc, 1, 1, experimental_constrained_fptrunc, FP_ROUND) - -// These are definitions for compare instructions (signaling and quiet version). -// Both of these match to FCmp / SETCC. -CMP_INSTRUCTION(FCmp, 2, 0, experimental_constrained_fcmp, FSETCC) -CMP_INSTRUCTION(FCmp, 2, 0, experimental_constrained_fcmps, FSETCCS) - -// Theses are definitions for intrinsic functions, that are converted into -// constrained intrinsics. -// -DAG_FUNCTION(ceil, 1, 0, experimental_constrained_ceil, FCEIL) -DAG_FUNCTION(cos, 1, 1, experimental_constrained_cos, FCOS) -DAG_FUNCTION(exp, 1, 1, experimental_constrained_exp, FEXP) -DAG_FUNCTION(exp2, 1, 1, experimental_constrained_exp2, FEXP2) -DAG_FUNCTION(floor, 1, 0, experimental_constrained_floor, FFLOOR) -DAG_FUNCTION(fma, 3, 1, experimental_constrained_fma, FMA) -DAG_FUNCTION(log, 1, 1, experimental_constrained_log, FLOG) -DAG_FUNCTION(log10, 1, 1, experimental_constrained_log10, FLOG10) -DAG_FUNCTION(log2, 1, 1, experimental_constrained_log2, FLOG2) -DAG_FUNCTION(lrint, 1, 1, experimental_constrained_lrint, LRINT) -DAG_FUNCTION(llrint, 1, 1, experimental_constrained_llrint, LLRINT) -DAG_FUNCTION(lround, 1, 0, experimental_constrained_lround, LROUND) -DAG_FUNCTION(llround, 1, 0, experimental_constrained_llround, LLROUND) -DAG_FUNCTION(maxnum, 2, 0, experimental_constrained_maxnum, FMAXNUM) -DAG_FUNCTION(minnum, 2, 0, experimental_constrained_minnum, FMINNUM) -DAG_FUNCTION(maximum, 2, 0, experimental_constrained_maximum, FMAXIMUM) -DAG_FUNCTION(minimum, 2, 0, experimental_constrained_minimum, FMINIMUM) -DAG_FUNCTION(nearbyint, 1, 1, experimental_constrained_nearbyint, FNEARBYINT) -DAG_FUNCTION(pow, 2, 1, experimental_constrained_pow, FPOW) -DAG_FUNCTION(powi, 2, 1, experimental_constrained_powi, FPOWI) -DAG_FUNCTION(rint, 1, 1, experimental_constrained_rint, FRINT) -DAG_FUNCTION(round, 1, 0, experimental_constrained_round, FROUND) -DAG_FUNCTION(roundeven, 1, 0, experimental_constrained_roundeven, FROUNDEVEN) -DAG_FUNCTION(sin, 1, 1, experimental_constrained_sin, FSIN) -DAG_FUNCTION(sqrt, 1, 1, experimental_constrained_sqrt, FSQRT) -DAG_FUNCTION(trunc, 1, 0, experimental_constrained_trunc, FTRUNC) - -// This is definition for fmuladd intrinsic function, that is converted into -// constrained FMA or FMUL + FADD intrinsics. -FUNCTION(fmuladd, 3, 1, experimental_constrained_fmuladd) - -#undef INSTRUCTION -#undef FUNCTION -#undef CMP_INSTRUCTION -#undef DAG_INSTRUCTION -#undef DAG_FUNCTION diff --git a/suite/synctools/tablegen/include/llvm/IR/DIBuilder.h b/suite/synctools/tablegen/include/llvm/IR/DIBuilder.h deleted file mode 100644 index 69949b96f7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DIBuilder.h +++ /dev/null @@ -1,1007 +0,0 @@ -//===- DIBuilder.h - Debug Information Builder ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a DIBuilder that is useful for creating debugging -// information entries in LLVM IR form. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DIBUILDER_H -#define LLVM_IR_DIBUILDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/TrackingMDRef.h" -#include "llvm/Support/Casting.h" -#include -#include - -namespace llvm { - - class BasicBlock; - class Constant; - class Function; - class Instruction; - class LLVMContext; - class Module; - class Value; - - class DIBuilder { - Module &M; - LLVMContext &VMContext; - - DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler. - Function *DeclareFn; ///< llvm.dbg.declare - Function *ValueFn; ///< llvm.dbg.value - Function *LabelFn; ///< llvm.dbg.label - Function *AddrFn; ///< llvm.dbg.addr - - SmallVector AllEnumTypes; - /// Track the RetainTypes, since they can be updated later on. - SmallVector AllRetainTypes; - SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector AllImportedModules; - /// Map Macro parent (which can be DIMacroFile or nullptr) to a list of - /// Metadata all of type DIMacroNode. - /// DIMacroNode's with nullptr parent are DICompileUnit direct children. - MapVector> AllMacrosPerParent; - - /// Track nodes that may be unresolved. - SmallVector UnresolvedNodes; - bool AllowUnresolvedNodes; - - /// Each subprogram's preserved local variables. - /// - /// Do not use a std::vector. Some versions of libc++ apparently copy - /// instead of move on grow operations, and TrackingMDRef is expensive to - /// copy. - DenseMap> PreservedVariables; - - /// Each subprogram's preserved labels. - DenseMap> PreservedLabels; - - /// Create a temporary. - /// - /// Create an \a temporary node and track it in \a UnresolvedNodes. - void trackIfUnresolved(MDNode *N); - - /// Internal helper for insertDeclare. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); - - /// Internal helper for insertLabel. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); - - /// Internal helper with common code used by insertDbg{Value,Addr}Intrinsic. - Instruction *insertDbgIntrinsic(llvm::Function *Intrinsic, llvm::Value *Val, - DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, - Instruction *InsertBefore); - - /// Internal helper for insertDbgValueIntrinsic. - Instruction * - insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); - - /// Internal helper for insertDbgAddrIntrinsic. - Instruction * - insertDbgAddrIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); - - public: - /// Construct a builder for a module. - /// - /// If \c AllowUnresolved, collect unresolved nodes attached to the module - /// in order to resolve cycles during \a finalize(). - /// - /// If \p CU is given a value other than nullptr, then set \p CUNode to CU. - explicit DIBuilder(Module &M, bool AllowUnresolved = true, - DICompileUnit *CU = nullptr); - DIBuilder(const DIBuilder &) = delete; - DIBuilder &operator=(const DIBuilder &) = delete; - - /// Construct any deferred debug info descriptors. - void finalize(); - - /// Finalize a specific subprogram - no new variables may be added to this - /// subprogram afterwards. - void finalizeSubprogram(DISubprogram *SP); - - /// A CompileUnit provides an anchor for all debugging - /// information generated during this instance of compilation. - /// \param Lang Source programming language, eg. dwarf::DW_LANG_C99 - /// \param File File info. - /// \param Producer Identify the producer of debugging information - /// and code. Usually this is a compiler - /// version string. - /// \param isOptimized A boolean flag which indicates whether optimization - /// is enabled or not. - /// \param Flags This string lists command line options. This - /// string is directly embedded in debug info - /// output which may be used by a tool - /// analyzing generated debugging information. - /// \param RV This indicates runtime version for languages like - /// Objective-C. - /// \param SplitName The name of the file that we'll split debug info - /// out into. - /// \param Kind The kind of debug information to generate. - /// \param DWOId The DWOId if this is a split skeleton compile unit. - /// \param SplitDebugInlining Whether to emit inline debug info. - /// \param DebugInfoForProfiling Whether to emit extra debug info for - /// profile collection. - /// \param NameTableKind Whether to emit .debug_gnu_pubnames, - /// .debug_pubnames, or no pubnames at all. - /// \param SysRoot The clang system root (value of -isysroot). - /// \param SDK The SDK name. On Darwin, this is the last component - /// of the sysroot. - DICompileUnit * - createCompileUnit(unsigned Lang, DIFile *File, StringRef Producer, - bool isOptimized, StringRef Flags, unsigned RV, - StringRef SplitName = StringRef(), - DICompileUnit::DebugEmissionKind Kind = - DICompileUnit::DebugEmissionKind::FullDebug, - uint64_t DWOId = 0, bool SplitDebugInlining = true, - bool DebugInfoForProfiling = false, - DICompileUnit::DebugNameTableKind NameTableKind = - DICompileUnit::DebugNameTableKind::Default, - bool RangesBaseAddress = false, StringRef SysRoot = {}, - StringRef SDK = {}); - - /// Create a file descriptor to hold debugging information for a file. - /// \param Filename File name. - /// \param Directory Directory. - /// \param Checksum Optional checksum kind (e.g. CSK_MD5, CSK_SHA1, etc.) - /// and value. - /// \param Source Optional source text. - DIFile * - createFile(StringRef Filename, StringRef Directory, - Optional> Checksum = None, - Optional Source = None); - - /// Create debugging information entry for a macro. - /// \param Parent Macro parent (could be nullptr). - /// \param Line Source line number where the macro is defined. - /// \param MacroType DW_MACINFO_define or DW_MACINFO_undef. - /// \param Name Macro name. - /// \param Value Macro value. - DIMacro *createMacro(DIMacroFile *Parent, unsigned Line, unsigned MacroType, - StringRef Name, StringRef Value = StringRef()); - - /// Create debugging information temporary entry for a macro file. - /// List of macro node direct children will be calculated by DIBuilder, - /// using the \p Parent relationship. - /// \param Parent Macro file parent (could be nullptr). - /// \param Line Source line number where the macro file is included. - /// \param File File descriptor containing the name of the macro file. - DIMacroFile *createTempMacroFile(DIMacroFile *Parent, unsigned Line, - DIFile *File); - - /// Create a single enumerator value. - DIEnumerator *createEnumerator(StringRef Name, const APSInt &Value); - DIEnumerator *createEnumerator(StringRef Name, uint64_t Val, - bool IsUnsigned = false); - - /// Create a DWARF unspecified type. - DIBasicType *createUnspecifiedType(StringRef Name); - - /// Create C++11 nullptr type. - DIBasicType *createNullPtrType(); - - /// Create debugging information entry for a basic - /// type. - /// \param Name Type name. - /// \param SizeInBits Size of the type. - /// \param Encoding DWARF encoding code, e.g., dwarf::DW_ATE_float. - /// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity. - DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, - unsigned Encoding, - DINode::DIFlags Flags = DINode::FlagZero); - - /// Create debugging information entry for a string - /// type. - /// \param Name Type name. - /// \param SizeInBits Size of the type. - DIStringType *createStringType(StringRef Name, uint64_t SizeInBits); - - /// Create debugging information entry for a qualified - /// type, e.g. 'const int'. - /// \param Tag Tag identifying type, e.g. dwarf::TAG_volatile_type - /// \param FromTy Base Type. - DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); - - /// Create debugging information entry for a pointer. - /// \param PointeeTy Type pointed by this pointer. - /// \param SizeInBits Size. - /// \param AlignInBits Alignment. (optional) - /// \param DWARFAddressSpace DWARF address space. (optional) - /// \param Name Pointer type name. (optional) - /// \param Annotations Member annotations. - DIDerivedType * - createPointerType(DIType *PointeeTy, uint64_t SizeInBits, - uint32_t AlignInBits = 0, - Optional DWARFAddressSpace = None, - StringRef Name = "", DINodeArray Annotations = nullptr); - - /// Create debugging information entry for a pointer to member. - /// \param PointeeTy Type pointed to by this pointer. - /// \param SizeInBits Size. - /// \param AlignInBits Alignment. (optional) - /// \param Class Type for which this pointer points to members of. - DIDerivedType * - createMemberPointerType(DIType *PointeeTy, DIType *Class, - uint64_t SizeInBits, uint32_t AlignInBits = 0, - DINode::DIFlags Flags = DINode::FlagZero); - - /// Create debugging information entry for a c++ - /// style reference or rvalue reference type. - DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy, - uint64_t SizeInBits = 0, - uint32_t AlignInBits = 0, - Optional DWARFAddressSpace = - None); - - /// Create debugging information entry for a typedef. - /// \param Ty Original type. - /// \param Name Typedef name. - /// \param File File where this type is defined. - /// \param LineNo Line number. - /// \param Context The surrounding context for the typedef. - /// \param AlignInBits Alignment. (optional) - /// \param Annotations Annotations. (optional) - DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File, - unsigned LineNo, DIScope *Context, - uint32_t AlignInBits = 0, - DINodeArray Annotations = nullptr); - - /// Create debugging information entry for a 'friend'. - DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); - - /// Create debugging information entry to establish - /// inheritance relationship between two types. - /// \param Ty Original type. - /// \param BaseTy Base type. Ty is inherits from base. - /// \param BaseOffset Base offset. - /// \param VBPtrOffset Virtual base pointer offset. - /// \param Flags Flags to describe inheritance attribute, - /// e.g. private - DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, - uint64_t BaseOffset, uint32_t VBPtrOffset, - DINode::DIFlags Flags); - - /// Create debugging information entry for a member. - /// \param Scope Member scope. - /// \param Name Member name. - /// \param File File where this member is defined. - /// \param LineNo Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param OffsetInBits Member offset. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Ty Parent type. - /// \param Annotations Member annotations. - DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNo, - uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, - DINode::DIFlags Flags, DIType *Ty, - DINodeArray Annotations = nullptr); - - /// Create debugging information entry for a variant. A variant - /// normally should be a member of a variant part. - /// \param Scope Member scope. - /// \param Name Member name. - /// \param File File where this member is defined. - /// \param LineNo Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param OffsetInBits Member offset. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Discriminant The discriminant for this branch; null for - /// the default branch - /// \param Ty Parent type. - DIDerivedType *createVariantMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNo, - uint64_t SizeInBits, - uint32_t AlignInBits, - uint64_t OffsetInBits, - Constant *Discriminant, - DINode::DIFlags Flags, DIType *Ty); - - /// Create debugging information entry for a bit field member. - /// \param Scope Member scope. - /// \param Name Member name. - /// \param File File where this member is defined. - /// \param LineNo Line number. - /// \param SizeInBits Member size. - /// \param OffsetInBits Member offset. - /// \param StorageOffsetInBits Member storage offset. - /// \param Flags Flags to encode member attribute. - /// \param Ty Parent type. - /// \param Annotations Member annotations. - DIDerivedType *createBitFieldMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNo, - uint64_t SizeInBits, - uint64_t OffsetInBits, - uint64_t StorageOffsetInBits, - DINode::DIFlags Flags, DIType *Ty, - DINodeArray Annotations = nullptr); - - /// Create debugging information entry for a - /// C++ static data member. - /// \param Scope Member scope. - /// \param Name Member name. - /// \param File File where this member is declared. - /// \param LineNo Line number. - /// \param Ty Type of the static member. - /// \param Flags Flags to encode member attribute, e.g. private. - /// \param Val Const initializer of the member. - /// \param AlignInBits Member alignment. - DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNo, - DIType *Ty, DINode::DIFlags Flags, - Constant *Val, - uint32_t AlignInBits = 0); - - /// Create debugging information entry for Objective-C - /// instance variable. - /// \param Name Member name. - /// \param File File where this member is defined. - /// \param LineNo Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param OffsetInBits Member offset. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Ty Parent type. - /// \param PropertyNode Property associated with this ivar. - DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo, - uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DINode::DIFlags Flags, - DIType *Ty, MDNode *PropertyNode); - - /// Create debugging information entry for Objective-C - /// property. - /// \param Name Property name. - /// \param File File where this property is defined. - /// \param LineNumber Line number. - /// \param GetterName Name of the Objective C property getter selector. - /// \param SetterName Name of the Objective C property setter selector. - /// \param PropertyAttributes Objective C property attributes. - /// \param Ty Type. - DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File, - unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, DIType *Ty); - - /// Create debugging information entry for a class. - /// \param Scope Scope in which this class is defined. - /// \param Name class name. - /// \param File File where this member is defined. - /// \param LineNumber Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param OffsetInBits Member offset. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Elements class members. - /// \param VTableHolder Debug info of the base class that contains vtable - /// for this type. This is used in - /// DW_AT_containing_type. See DWARF documentation - /// for more info. - /// \param TemplateParms Template type parameters. - /// \param UniqueIdentifier A unique identifier for the class. - DICompositeType *createClassType( - DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, - DIType *VTableHolder = nullptr, MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = ""); - - /// Create debugging information entry for a struct. - /// \param Scope Scope in which this struct is defined. - /// \param Name Struct name. - /// \param File File where this member is defined. - /// \param LineNumber Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Elements Struct elements. - /// \param RunTimeLang Optional parameter, Objective-C runtime version. - /// \param UniqueIdentifier A unique identifier for the struct. - DICompositeType *createStructType( - DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, - DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, - DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); - - /// Create debugging information entry for an union. - /// \param Scope Scope in which this union is defined. - /// \param Name Union name. - /// \param File File where this member is defined. - /// \param LineNumber Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Elements Union elements. - /// \param RunTimeLang Optional parameter, Objective-C runtime version. - /// \param UniqueIdentifier A unique identifier for the union. - DICompositeType *createUnionType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, - DINode::DIFlags Flags, - DINodeArray Elements, - unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = ""); - - /// Create debugging information entry for a variant part. A - /// variant part normally has a discriminator (though this is not - /// required) and a number of variant children. - /// \param Scope Scope in which this union is defined. - /// \param Name Union name. - /// \param File File where this member is defined. - /// \param LineNumber Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param Flags Flags to encode member attribute, e.g. private - /// \param Discriminator Discriminant member - /// \param Elements Variant elements. - /// \param UniqueIdentifier A unique identifier for the union. - DICompositeType *createVariantPart(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, - DINode::DIFlags Flags, - DIDerivedType *Discriminator, - DINodeArray Elements, - StringRef UniqueIdentifier = ""); - - /// Create debugging information for template - /// type parameter. - /// \param Scope Scope in which this type is defined. - /// \param Name Type parameter name. - /// \param Ty Parameter type. - /// \param IsDefault Parameter is default or not - DITemplateTypeParameter *createTemplateTypeParameter(DIScope *Scope, - StringRef Name, - DIType *Ty, - bool IsDefault); - - /// Create debugging information for template - /// value parameter. - /// \param Scope Scope in which this type is defined. - /// \param Name Value parameter name. - /// \param Ty Parameter type. - /// \param IsDefault Parameter is default or not - /// \param Val Constant parameter value. - DITemplateValueParameter * - createTemplateValueParameter(DIScope *Scope, StringRef Name, DIType *Ty, - bool IsDefault, Constant *Val); - - /// Create debugging information for a template template parameter. - /// \param Scope Scope in which this type is defined. - /// \param Name Value parameter name. - /// \param Ty Parameter type. - /// \param Val The fully qualified name of the template. - DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope, - StringRef Name, - DIType *Ty, - StringRef Val); - - /// Create debugging information for a template parameter pack. - /// \param Scope Scope in which this type is defined. - /// \param Name Value parameter name. - /// \param Ty Parameter type. - /// \param Val An array of types in the pack. - DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope, - StringRef Name, - DIType *Ty, - DINodeArray Val); - - /// Create debugging information entry for an array. - /// \param Size Array size. - /// \param AlignInBits Alignment. - /// \param Ty Element type. - /// \param Subscripts Subscripts. - /// \param DataLocation The location of the raw data of a descriptor-based - /// Fortran array, either a DIExpression* or - /// a DIVariable*. - /// \param Associated The associated attribute of a descriptor-based - /// Fortran array, either a DIExpression* or - /// a DIVariable*. - /// \param Allocated The allocated attribute of a descriptor-based - /// Fortran array, either a DIExpression* or - /// a DIVariable*. - /// \param Rank The rank attribute of a descriptor-based - /// Fortran array, either a DIExpression* or - /// a DIVariable*. - DICompositeType *createArrayType( - uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts, - PointerUnion DataLocation = nullptr, - PointerUnion Associated = nullptr, - PointerUnion Allocated = nullptr, - PointerUnion Rank = nullptr); - - /// Create debugging information entry for a vector type. - /// \param Size Array size. - /// \param AlignInBits Alignment. - /// \param Ty Element type. - /// \param Subscripts Subscripts. - DICompositeType *createVectorType(uint64_t Size, uint32_t AlignInBits, - DIType *Ty, DINodeArray Subscripts); - - /// Create debugging information entry for an - /// enumeration. - /// \param Scope Scope in which this enumeration is defined. - /// \param Name Union name. - /// \param File File where this member is defined. - /// \param LineNumber Line number. - /// \param SizeInBits Member size. - /// \param AlignInBits Member alignment. - /// \param Elements Enumeration elements. - /// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum. - /// \param UniqueIdentifier A unique identifier for the enum. - /// \param IsScoped Boolean flag indicate if this is C++11/ObjC 'enum class'. - DICompositeType *createEnumerationType( - DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements, - DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsScoped = false); - - /// Create debugging information entry for a set. - /// \param Scope Scope in which this set is defined. - /// \param Name Set name. - /// \param File File where this set is defined. - /// \param LineNo Line number. - /// \param SizeInBits Set size. - /// \param AlignInBits Set alignment. - /// \param Ty Base type of the set. - DIDerivedType *createSetType(DIScope *Scope, StringRef Name, DIFile *File, - unsigned LineNo, uint64_t SizeInBits, - uint32_t AlignInBits, DIType *Ty); - - /// Create subroutine type. - /// \param ParameterTypes An array of subroutine parameter types. This - /// includes return type at 0th index. - /// \param Flags E.g.: LValueReference. - /// These flags are used to emit dwarf attributes. - /// \param CC Calling convention, e.g. dwarf::DW_CC_normal - DISubroutineType * - createSubroutineType(DITypeRefArray ParameterTypes, - DINode::DIFlags Flags = DINode::FlagZero, - unsigned CC = 0); - - /// Create a distinct clone of \p SP with FlagArtificial set. - static DISubprogram *createArtificialSubprogram(DISubprogram *SP); - - /// Create a uniqued clone of \p Ty with FlagArtificial set. - static DIType *createArtificialType(DIType *Ty); - - /// Create a uniqued clone of \p Ty with FlagObjectPointer and - /// FlagArtificial set. - static DIType *createObjectPointerType(DIType *Ty); - - /// Create a permanent forward-declared type. - DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, - DIScope *Scope, DIFile *F, unsigned Line, - unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, - uint32_t AlignInBits = 0, - StringRef UniqueIdentifier = ""); - - /// Create a temporary forward-declared type. - DICompositeType *createReplaceableCompositeType( - unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, - unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint32_t AlignInBits = 0, DINode::DIFlags Flags = DINode::FlagFwdDecl, - StringRef UniqueIdentifier = "", DINodeArray Annotations = nullptr); - - /// Retain DIScope* in a module even if it is not referenced - /// through debug info anchors. - void retainType(DIScope *T); - - /// Create unspecified parameter type - /// for a subroutine type. - DIBasicType *createUnspecifiedParameter(); - - /// Get a DINodeArray, create one if required. - DINodeArray getOrCreateArray(ArrayRef Elements); - - /// Get a DIMacroNodeArray, create one if required. - DIMacroNodeArray getOrCreateMacroArray(ArrayRef Elements); - - /// Get a DITypeRefArray, create one if required. - DITypeRefArray getOrCreateTypeArray(ArrayRef Elements); - - /// Create a descriptor for a value range. This - /// implicitly uniques the values returned. - DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); - DISubrange *getOrCreateSubrange(int64_t Lo, Metadata *CountNode); - DISubrange *getOrCreateSubrange(Metadata *Count, Metadata *LowerBound, - Metadata *UpperBound, Metadata *Stride); - - DIGenericSubrange * - getOrCreateGenericSubrange(DIGenericSubrange::BoundType Count, - DIGenericSubrange::BoundType LowerBound, - DIGenericSubrange::BoundType UpperBound, - DIGenericSubrange::BoundType Stride); - - /// Create a new descriptor for the specified variable. - /// \param Context Variable scope. - /// \param Name Name of the variable. - /// \param LinkageName Mangled name of the variable. - /// \param File File where this variable is defined. - /// \param LineNo Line number. - /// \param Ty Variable Type. - /// \param IsLocalToUnit Boolean flag indicate whether this variable is - /// externally visible or not. - /// \param Expr The location of the global relative to the attached - /// GlobalVariable. - /// \param Decl Reference to the corresponding declaration. - /// \param AlignInBits Variable alignment(or 0 if no alignment attr was - /// specified) - DIGlobalVariableExpression *createGlobalVariableExpression( - DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned LineNo, DIType *Ty, bool IsLocalToUnit, bool isDefined = true, - DIExpression *Expr = nullptr, MDNode *Decl = nullptr, - MDTuple *TemplateParams = nullptr, uint32_t AlignInBits = 0, - DINodeArray Annotations = nullptr); - - /// Identical to createGlobalVariable - /// except that the resulting DbgNode is temporary and meant to be RAUWed. - DIGlobalVariable *createTempGlobalVariableFwdDecl( - DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned LineNo, DIType *Ty, bool IsLocalToUnit, MDNode *Decl = nullptr, - MDTuple *TemplateParams= nullptr, uint32_t AlignInBits = 0); - - /// Create a new descriptor for an auto variable. This is a local variable - /// that is not a subprogram parameter. - /// - /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually - /// leads to a \a DISubprogram. - /// - /// If \c AlwaysPreserve, this variable will be referenced from its - /// containing subprogram, and will survive some optimizations. - DILocalVariable * - createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, - unsigned LineNo, DIType *Ty, bool AlwaysPreserve = false, - DINode::DIFlags Flags = DINode::FlagZero, - uint32_t AlignInBits = 0); - - /// Create a new descriptor for an label. - /// - /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually - /// leads to a \a DISubprogram. - DILabel * - createLabel(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, - bool AlwaysPreserve = false); - - /// Create a new descriptor for a parameter variable. - /// - /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually - /// leads to a \a DISubprogram. - /// - /// \c ArgNo is the index (starting from \c 1) of this variable in the - /// subprogram parameters. \c ArgNo should not conflict with other - /// parameters of the same subprogram. - /// - /// If \c AlwaysPreserve, this variable will be referenced from its - /// containing subprogram, and will survive some optimizations. - DILocalVariable * - createParameterVariable(DIScope *Scope, StringRef Name, unsigned ArgNo, - DIFile *File, unsigned LineNo, DIType *Ty, - bool AlwaysPreserve = false, - DINode::DIFlags Flags = DINode::FlagZero, - DINodeArray Annotations = nullptr); - - /// Create a new descriptor for the specified - /// variable which has a complex address expression for its address. - /// \param Addr An array of complex address operations. - DIExpression *createExpression(ArrayRef Addr = None); - - /// Create an expression for a variable that does not have an address, but - /// does have a constant value. - DIExpression *createConstantValueExpression(uint64_t Val) { - return DIExpression::get( - VMContext, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_stack_value}); - } - - /// Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram* for descriptions of these fields. - /// \param Scope Function scope. - /// \param Name Function name. - /// \param LinkageName Mangled function name. - /// \param File File where this variable is defined. - /// \param LineNo Line number. - /// \param Ty Function type. - /// \param ScopeLine Set to the beginning of the scope this starts - /// \param Flags e.g. is this function prototyped or not. - /// These flags are used to emit dwarf attributes. - /// \param SPFlags Additional flags specific to subprograms. - /// \param TParams Function template parameters. - /// \param ThrownTypes Exception types this function may throw. - /// \param Annotations Attribute Annotations. - DISubprogram * - createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, - DIFile *File, unsigned LineNo, DISubroutineType *Ty, - unsigned ScopeLine, DINode::DIFlags Flags = DINode::FlagZero, - DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, - DITemplateParameterArray TParams = nullptr, - DISubprogram *Decl = nullptr, - DITypeArray ThrownTypes = nullptr, - DINodeArray Annotations = nullptr); - - /// Identical to createFunction, - /// except that the resulting DbgNode is meant to be RAUWed. - DISubprogram *createTempFunctionFwdDecl( - DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, - DINode::DIFlags Flags = DINode::FlagZero, - DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, - DITemplateParameterArray TParams = nullptr, - DISubprogram *Decl = nullptr, DITypeArray ThrownTypes = nullptr); - - /// Create a new descriptor for the specified C++ method. - /// See comments in \a DISubprogram* for descriptions of these fields. - /// \param Scope Function scope. - /// \param Name Function name. - /// \param LinkageName Mangled function name. - /// \param File File where this variable is defined. - /// \param LineNo Line number. - /// \param Ty Function type. - /// \param VTableIndex Index no of this method in virtual table, or -1u if - /// unrepresentable. - /// \param ThisAdjustment - /// MS ABI-specific adjustment of 'this' that occurs - /// in the prologue. - /// \param VTableHolder Type that holds vtable. - /// \param Flags e.g. is this function prototyped or not. - /// This flags are used to emit dwarf attributes. - /// \param SPFlags Additional flags specific to subprograms. - /// \param TParams Function template parameters. - /// \param ThrownTypes Exception types this function may throw. - DISubprogram * - createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, - DIFile *File, unsigned LineNo, DISubroutineType *Ty, - unsigned VTableIndex = 0, int ThisAdjustment = 0, - DIType *VTableHolder = nullptr, - DINode::DIFlags Flags = DINode::FlagZero, - DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, - DITemplateParameterArray TParams = nullptr, - DITypeArray ThrownTypes = nullptr); - - /// Create common block entry for a Fortran common block. - /// \param Scope Scope of this common block. - /// \param decl Global variable declaration. - /// \param Name The name of this common block. - /// \param File The file this common block is defined. - /// \param LineNo Line number. - DICommonBlock *createCommonBlock(DIScope *Scope, DIGlobalVariable *decl, - StringRef Name, DIFile *File, - unsigned LineNo); - - /// This creates new descriptor for a namespace with the specified - /// parent scope. - /// \param Scope Namespace scope - /// \param Name Name of this namespace - /// \param ExportSymbols True for C++ inline namespaces. - DINamespace *createNameSpace(DIScope *Scope, StringRef Name, - bool ExportSymbols); - - /// This creates new descriptor for a module with the specified - /// parent scope. - /// \param Scope Parent scope - /// \param Name Name of this module - /// \param ConfigurationMacros - /// A space-separated shell-quoted list of -D macro - /// definitions as they would appear on a command line. - /// \param IncludePath The path to the module map file. - /// \param APINotesFile The path to an API notes file for this module. - /// \param File Source file of the module. - /// Used for Fortran modules. - /// \param LineNo Source line number of the module. - /// Used for Fortran modules. - /// \param IsDecl This is a module declaration; default to false; - /// when set to true, only Scope and Name are required - /// as this entry is just a hint for the debugger to find - /// the corresponding definition in the global scope. - DIModule *createModule(DIScope *Scope, StringRef Name, - StringRef ConfigurationMacros, StringRef IncludePath, - StringRef APINotesFile = {}, DIFile *File = nullptr, - unsigned LineNo = 0, bool IsDecl = false); - - /// This creates a descriptor for a lexical block with a new file - /// attached. This merely extends the existing - /// lexical block as it crosses a file. - /// \param Scope Lexical block. - /// \param File Source file. - /// \param Discriminator DWARF path discriminator value. - DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File, - unsigned Discriminator = 0); - - /// This creates a descriptor for a lexical block with the - /// specified parent context. - /// \param Scope Parent lexical scope. - /// \param File Source file. - /// \param Line Line number. - /// \param Col Column number. - DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File, - unsigned Line, unsigned Col); - - /// Create a descriptor for an imported module. - /// \param Context The scope this module is imported into - /// \param NS The namespace being imported here. - /// \param File File where the declaration is located. - /// \param Line Line number of the declaration. - /// \param Elements Renamed elements. - DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, - DIFile *File, unsigned Line, - DINodeArray Elements = nullptr); - - /// Create a descriptor for an imported module. - /// \param Context The scope this module is imported into. - /// \param NS An aliased namespace. - /// \param File File where the declaration is located. - /// \param Line Line number of the declaration. - /// \param Elements Renamed elements. - DIImportedEntity *createImportedModule(DIScope *Context, - DIImportedEntity *NS, DIFile *File, - unsigned Line, - DINodeArray Elements = nullptr); - - /// Create a descriptor for an imported module. - /// \param Context The scope this module is imported into. - /// \param M The module being imported here - /// \param File File where the declaration is located. - /// \param Line Line number of the declaration. - /// \param Elements Renamed elements. - DIImportedEntity *createImportedModule(DIScope *Context, DIModule *M, - DIFile *File, unsigned Line, - DINodeArray Elements = nullptr); - - /// Create a descriptor for an imported function. - /// \param Context The scope this module is imported into. - /// \param Decl The declaration (or definition) of a function, type, or - /// variable. - /// \param File File where the declaration is located. - /// \param Line Line number of the declaration. - /// \param Elements Renamed elements. - DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, - DIFile *File, unsigned Line, - StringRef Name = "", - DINodeArray Elements = nullptr); - - /// Insert a new llvm.dbg.declare intrinsic call. - /// \param Storage llvm::Value of the variable - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertAtEnd); - - /// Insert a new llvm.dbg.declare intrinsic call. - /// \param Storage llvm::Value of the variable - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - Instruction *InsertBefore); - - /// Insert a new llvm.dbg.label intrinsic call. - /// \param LabelInfo Label's debug info descriptor. - /// \param DL Debug info location. - /// \param InsertBefore Location for the new intrinsic. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - Instruction *InsertBefore); - - /// Insert a new llvm.dbg.label intrinsic call. - /// \param LabelInfo Label's debug info descriptor. - /// \param DL Debug info location. - /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertAtEnd); - - /// Insert a new llvm.dbg.value intrinsic call. - /// \param Val llvm::Value of the variable - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertDbgValueIntrinsic(llvm::Value *Val, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - BasicBlock *InsertAtEnd); - - /// Insert a new llvm.dbg.value intrinsic call. - /// \param Val llvm::Value of the variable - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertBefore Location for the new intrinsic. - Instruction *insertDbgValueIntrinsic(llvm::Value *Val, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - Instruction *InsertBefore); - - /// Insert a new llvm.dbg.addr intrinsic call. - /// \param Addr llvm::Value of the address - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertDbgAddrIntrinsic(llvm::Value *Addr, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - BasicBlock *InsertAtEnd); - - /// Insert a new llvm.dbg.addr intrinsic call. - /// \param Addr llvm::Value of the address. - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertBefore Location for the new intrinsic. - Instruction *insertDbgAddrIntrinsic(llvm::Value *Addr, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - Instruction *InsertBefore); - - /// Replace the vtable holder in the given type. - /// - /// If this creates a self reference, it may orphan some unresolved cycles - /// in the operands of \c T, so \a DIBuilder needs to track that. - void replaceVTableHolder(DICompositeType *&T, - DIType *VTableHolder); - - /// Replace arrays on a composite type. - /// - /// If \c T is resolved, but the arrays aren't -- which can happen if \c T - /// has a self-reference -- \a DIBuilder needs to track the array to - /// resolve cycles. - void replaceArrays(DICompositeType *&T, DINodeArray Elements, - DINodeArray TParams = DINodeArray()); - - /// Replace a temporary node. - /// - /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c - /// Replacement. - /// - /// If \c Replacement is the same as \c N.get(), instead call \a - /// MDNode::replaceWithUniqued(). In this case, the uniqued node could - /// have a different address, so we return the final address. - template - NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) { - if (N.get() == Replacement) - return cast(MDNode::replaceWithUniqued(std::move(N))); - - N->replaceAllUsesWith(Replacement); - return Replacement; - } - }; - - // Create wrappers for C Binding types (see CBindingWrapping.h). - DEFINE_ISA_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef) - -} // end namespace llvm - -#endif // LLVM_IR_DIBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DataLayout.h b/suite/synctools/tablegen/include/llvm/IR/DataLayout.h deleted file mode 100644 index 36438fc4f4..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DataLayout.h +++ /dev/null @@ -1,723 +0,0 @@ -//===- llvm/DataLayout.h - Data size & alignment info -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines layout properties related to datatype size/offset/alignment -// information. It uses lazy annotations to cache information about how -// structure types are laid out and used. -// -// This structure should be created once, filled in if the defaults are not -// correct and then passed around by const&. None of the members functions -// require modification to the object. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DATALAYOUT_H -#define LLVM_IR_DATALAYOUT_H - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/TrailingObjects.h" -#include "llvm/Support/TypeSize.h" -#include -#include -#include - -// This needs to be outside of the namespace, to avoid conflict with llvm-c -// decl. -using LLVMTargetDataRef = struct LLVMOpaqueTargetData *; - -namespace llvm { - -class GlobalVariable; -class LLVMContext; -class Module; -class StructLayout; -class Triple; -class Value; - -/// Enum used to categorize the alignment types stored by LayoutAlignElem -enum AlignTypeEnum { - INVALID_ALIGN = 0, - INTEGER_ALIGN = 'i', - VECTOR_ALIGN = 'v', - FLOAT_ALIGN = 'f', - AGGREGATE_ALIGN = 'a' -}; - -// FIXME: Currently the DataLayout string carries a "preferred alignment" -// for types. As the DataLayout is module/global, this should likely be -// sunk down to an FTTI element that is queried rather than a global -// preference. - -/// Layout alignment element. -/// -/// Stores the alignment data associated with a given alignment type (integer, -/// vector, float) and type bit width. -/// -/// \note The unusual order of elements in the structure attempts to reduce -/// padding and make the structure slightly more cache friendly. -struct LayoutAlignElem { - /// Alignment type from \c AlignTypeEnum - unsigned AlignType : 8; - unsigned TypeBitWidth : 24; - Align ABIAlign; - Align PrefAlign; - - static LayoutAlignElem get(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width); - - bool operator==(const LayoutAlignElem &rhs) const; -}; - -/// Layout pointer alignment element. -/// -/// Stores the alignment data associated with a given pointer and address space. -/// -/// \note The unusual order of elements in the structure attempts to reduce -/// padding and make the structure slightly more cache friendly. -struct PointerAlignElem { - Align ABIAlign; - Align PrefAlign; - uint32_t TypeBitWidth; - uint32_t AddressSpace; - uint32_t IndexBitWidth; - - /// Initializer - static PointerAlignElem getInBits(uint32_t AddressSpace, Align ABIAlign, - Align PrefAlign, uint32_t TypeBitWidth, - uint32_t IndexBitWidth); - - bool operator==(const PointerAlignElem &rhs) const; -}; - -/// A parsed version of the target data layout string in and methods for -/// querying it. -/// -/// The target data layout string is specified *by the target* - a frontend -/// generating LLVM IR is required to generate the right target data for the -/// target being codegen'd to. -class DataLayout { -public: - enum class FunctionPtrAlignType { - /// The function pointer alignment is independent of the function alignment. - Independent, - /// The function pointer alignment is a multiple of the function alignment. - MultipleOfFunctionAlign, - }; -private: - /// Defaults to false. - bool BigEndian; - - unsigned AllocaAddrSpace; - MaybeAlign StackNaturalAlign; - unsigned ProgramAddrSpace; - unsigned DefaultGlobalsAddrSpace; - - MaybeAlign FunctionPtrAlign; - FunctionPtrAlignType TheFunctionPtrAlignType; - - enum ManglingModeT { - MM_None, - MM_ELF, - MM_MachO, - MM_WinCOFF, - MM_WinCOFFX86, - MM_GOFF, - MM_Mips, - MM_XCOFF - }; - ManglingModeT ManglingMode; - - SmallVector LegalIntWidths; - - /// Primitive type alignment data. This is sorted by type and bit - /// width during construction. - using AlignmentsTy = SmallVector; - AlignmentsTy Alignments; - - AlignmentsTy::const_iterator - findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth) const { - return const_cast(this)->findAlignmentLowerBound(AlignType, - BitWidth); - } - - AlignmentsTy::iterator - findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth); - - /// The string representation used to create this DataLayout - std::string StringRepresentation; - - using PointersTy = SmallVector; - PointersTy Pointers; - - const PointerAlignElem &getPointerAlignElem(uint32_t AddressSpace) const; - - // The StructType -> StructLayout map. - mutable void *LayoutMap = nullptr; - - /// Pointers in these address spaces are non-integral, and don't have a - /// well-defined bitwise representation. - SmallVector NonIntegralAddressSpaces; - - /// Attempts to set the alignment of the given type. Returns an error - /// description on failure. - Error setAlignment(AlignTypeEnum align_type, Align abi_align, - Align pref_align, uint32_t bit_width); - - /// Attempts to set the alignment of a pointer in the given address space. - /// Returns an error description on failure. - Error setPointerAlignmentInBits(uint32_t AddrSpace, Align ABIAlign, - Align PrefAlign, uint32_t TypeBitWidth, - uint32_t IndexBitWidth); - - /// Internal helper to get alignment for integer of given bitwidth. - Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const; - - /// Internal helper method that returns requested alignment for type. - Align getAlignment(Type *Ty, bool abi_or_pref) const; - - /// Attempts to parse a target data specification string and reports an error - /// if the string is malformed. - Error parseSpecifier(StringRef Desc); - - // Free all internal data structures. - void clear(); - -public: - /// Constructs a DataLayout from a specification string. See reset(). - explicit DataLayout(StringRef LayoutDescription) { - reset(LayoutDescription); - } - - /// Initialize target data from properties stored in the module. - explicit DataLayout(const Module *M); - - DataLayout(const DataLayout &DL) { *this = DL; } - - ~DataLayout(); // Not virtual, do not subclass this class - - DataLayout &operator=(const DataLayout &DL) { - clear(); - StringRepresentation = DL.StringRepresentation; - BigEndian = DL.isBigEndian(); - AllocaAddrSpace = DL.AllocaAddrSpace; - StackNaturalAlign = DL.StackNaturalAlign; - FunctionPtrAlign = DL.FunctionPtrAlign; - TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType; - ProgramAddrSpace = DL.ProgramAddrSpace; - DefaultGlobalsAddrSpace = DL.DefaultGlobalsAddrSpace; - ManglingMode = DL.ManglingMode; - LegalIntWidths = DL.LegalIntWidths; - Alignments = DL.Alignments; - Pointers = DL.Pointers; - NonIntegralAddressSpaces = DL.NonIntegralAddressSpaces; - return *this; - } - - bool operator==(const DataLayout &Other) const; - bool operator!=(const DataLayout &Other) const { return !(*this == Other); } - - void init(const Module *M); - - /// Parse a data layout string (with fallback to default values). - void reset(StringRef LayoutDescription); - - /// Parse a data layout string and return the layout. Return an error - /// description on failure. - static Expected parse(StringRef LayoutDescription); - - /// Layout endianness... - bool isLittleEndian() const { return !BigEndian; } - bool isBigEndian() const { return BigEndian; } - - /// Returns the string representation of the DataLayout. - /// - /// This representation is in the same format accepted by the string - /// constructor above. This should not be used to compare two DataLayout as - /// different string can represent the same layout. - const std::string &getStringRepresentation() const { - return StringRepresentation; - } - - /// Test if the DataLayout was constructed from an empty string. - bool isDefault() const { return StringRepresentation.empty(); } - - /// Returns true if the specified type is known to be a native integer - /// type supported by the CPU. - /// - /// For example, i64 is not native on most 32-bit CPUs and i37 is not native - /// on any known one. This returns false if the integer width is not legal. - /// - /// The width is specified in bits. - bool isLegalInteger(uint64_t Width) const { - return llvm::is_contained(LegalIntWidths, Width); - } - - bool isIllegalInteger(uint64_t Width) const { return !isLegalInteger(Width); } - - /// Returns true if the given alignment exceeds the natural stack alignment. - bool exceedsNaturalStackAlignment(Align Alignment) const { - return StackNaturalAlign && (Alignment > *StackNaturalAlign); - } - - Align getStackAlignment() const { - assert(StackNaturalAlign && "StackNaturalAlign must be defined"); - return *StackNaturalAlign; - } - - unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } - - /// Returns the alignment of function pointers, which may or may not be - /// related to the alignment of functions. - /// \see getFunctionPtrAlignType - MaybeAlign getFunctionPtrAlign() const { return FunctionPtrAlign; } - - /// Return the type of function pointer alignment. - /// \see getFunctionPtrAlign - FunctionPtrAlignType getFunctionPtrAlignType() const { - return TheFunctionPtrAlignType; - } - - unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } - unsigned getDefaultGlobalsAddressSpace() const { - return DefaultGlobalsAddrSpace; - } - - bool hasMicrosoftFastStdCallMangling() const { - return ManglingMode == MM_WinCOFFX86; - } - - /// Returns true if symbols with leading question marks should not receive IR - /// mangling. True for Windows mangling modes. - bool doNotMangleLeadingQuestionMark() const { - return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86; - } - - bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } - - StringRef getLinkerPrivateGlobalPrefix() const { - if (ManglingMode == MM_MachO) - return "l"; - return ""; - } - - char getGlobalPrefix() const { - switch (ManglingMode) { - case MM_None: - case MM_ELF: - case MM_GOFF: - case MM_Mips: - case MM_WinCOFF: - case MM_XCOFF: - return '\0'; - case MM_MachO: - case MM_WinCOFFX86: - return '_'; - } - llvm_unreachable("invalid mangling mode"); - } - - StringRef getPrivateGlobalPrefix() const { - switch (ManglingMode) { - case MM_None: - return ""; - case MM_ELF: - case MM_WinCOFF: - return ".L"; - case MM_GOFF: - return "@"; - case MM_Mips: - return "$"; - case MM_MachO: - case MM_WinCOFFX86: - return "L"; - case MM_XCOFF: - return "L.."; - } - llvm_unreachable("invalid mangling mode"); - } - - static const char *getManglingComponent(const Triple &T); - - /// Returns true if the specified type fits in a native integer type - /// supported by the CPU. - /// - /// For example, if the CPU only supports i32 as a native integer type, then - /// i27 fits in a legal integer type but i45 does not. - bool fitsInLegalInteger(unsigned Width) const { - for (unsigned LegalIntWidth : LegalIntWidths) - if (Width <= LegalIntWidth) - return true; - return false; - } - - /// Layout pointer alignment - Align getPointerABIAlignment(unsigned AS) const; - - /// Return target's alignment for stack-based pointers - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - Align getPointerPrefAlignment(unsigned AS = 0) const; - - /// Layout pointer size in bytes, rounded up to a whole - /// number of bytes. - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const; - - /// Returns the maximum index size over all address spaces. - unsigned getMaxIndexSize() const; - - // Index size in bytes used for address calculation, - /// rounded up to a whole number of bytes. - unsigned getIndexSize(unsigned AS) const; - - /// Return the address spaces containing non-integral pointers. Pointers in - /// this address space don't have a well-defined bitwise representation. - ArrayRef getNonIntegralAddressSpaces() const { - return NonIntegralAddressSpaces; - } - - bool isNonIntegralAddressSpace(unsigned AddrSpace) const { - ArrayRef NonIntegralSpaces = getNonIntegralAddressSpaces(); - return is_contained(NonIntegralSpaces, AddrSpace); - } - - bool isNonIntegralPointerType(PointerType *PT) const { - return isNonIntegralAddressSpace(PT->getAddressSpace()); - } - - bool isNonIntegralPointerType(Type *Ty) const { - auto *PTy = dyn_cast(Ty); - return PTy && isNonIntegralPointerType(PTy); - } - - /// Layout pointer size, in bits - /// FIXME: The defaults need to be removed once all of - /// the backends/clients are updated. - unsigned getPointerSizeInBits(unsigned AS = 0) const { - return getPointerAlignElem(AS).TypeBitWidth; - } - - /// Returns the maximum index size over all address spaces. - unsigned getMaxIndexSizeInBits() const { - return getMaxIndexSize() * 8; - } - - /// Size in bits of index used for address calculation in getelementptr. - unsigned getIndexSizeInBits(unsigned AS) const { - return getPointerAlignElem(AS).IndexBitWidth; - } - - /// Layout pointer size, in bits, based on the type. If this function is - /// called with a pointer type, then the type size of the pointer is returned. - /// If this function is called with a vector of pointers, then the type size - /// of the pointer is returned. This should only be called with a pointer or - /// vector of pointers. - unsigned getPointerTypeSizeInBits(Type *) const; - - /// Layout size of the index used in GEP calculation. - /// The function should be called with pointer or vector of pointers type. - unsigned getIndexTypeSizeInBits(Type *Ty) const; - - unsigned getPointerTypeSize(Type *Ty) const { - return getPointerTypeSizeInBits(Ty) / 8; - } - - /// Size examples: - /// - /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] - /// ---- ---------- --------------- --------------- - /// i1 1 8 8 - /// i8 8 8 8 - /// i19 19 24 32 - /// i32 32 32 32 - /// i100 100 104 128 - /// i128 128 128 128 - /// Float 32 32 32 - /// Double 64 64 64 - /// X86_FP80 80 80 96 - /// - /// [*] The alloc size depends on the alignment, and thus on the target. - /// These values are for x86-32 linux. - - /// Returns the number of bits necessary to hold the specified type. - /// - /// If Ty is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must - /// have a size (Type::isSized() must return true). - TypeSize getTypeSizeInBits(Type *Ty) const; - - /// Returns the maximum number of bytes that may be overwritten by - /// storing the specified type. - /// - /// If Ty is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// For example, returns 5 for i36 and 10 for x86_fp80. - TypeSize getTypeStoreSize(Type *Ty) const { - TypeSize BaseSize = getTypeSizeInBits(Ty); - return {divideCeil(BaseSize.getKnownMinSize(), 8), BaseSize.isScalable()}; - } - - /// Returns the maximum number of bits that may be overwritten by - /// storing the specified type; always a multiple of 8. - /// - /// If Ty is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// For example, returns 40 for i36 and 80 for x86_fp80. - TypeSize getTypeStoreSizeInBits(Type *Ty) const { - return 8 * getTypeStoreSize(Ty); - } - - /// Returns true if no extra padding bits are needed when storing the - /// specified type. - /// - /// For example, returns false for i19 that has a 24-bit store size. - bool typeSizeEqualsStoreSize(Type *Ty) const { - return getTypeSizeInBits(Ty) == getTypeStoreSizeInBits(Ty); - } - - /// Returns the offset in bytes between successive objects of the - /// specified type, including alignment padding. - /// - /// If Ty is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// This is the amount that alloca reserves for this type. For example, - /// returns 12 or 16 for x86_fp80, depending on alignment. - TypeSize getTypeAllocSize(Type *Ty) const { - // Round up to the next alignment boundary. - return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); - } - - /// Returns the offset in bits between successive objects of the - /// specified type, including alignment padding; always a multiple of 8. - /// - /// If Ty is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// This is the amount that alloca reserves for this type. For example, - /// returns 96 or 128 for x86_fp80, depending on alignment. - TypeSize getTypeAllocSizeInBits(Type *Ty) const { - return 8 * getTypeAllocSize(Ty); - } - - /// Returns the minimum ABI-required alignment for the specified type. - /// FIXME: Deprecate this function once migration to Align is over. - uint64_t getABITypeAlignment(Type *Ty) const; - - /// Returns the minimum ABI-required alignment for the specified type. - Align getABITypeAlign(Type *Ty) const; - - /// Helper function to return `Alignment` if it's set or the result of - /// `getABITypeAlignment(Ty)`, in any case the result is a valid alignment. - inline Align getValueOrABITypeAlignment(MaybeAlign Alignment, - Type *Ty) const { - return Alignment ? *Alignment : getABITypeAlign(Ty); - } - - /// Returns the minimum ABI-required alignment for an integer type of - /// the specified bitwidth. - Align getABIIntegerTypeAlignment(unsigned BitWidth) const { - return getIntegerAlignment(BitWidth, /* abi_or_pref */ true); - } - - /// Returns the preferred stack/global alignment for the specified - /// type. - /// - /// This is always at least as good as the ABI alignment. - /// FIXME: Deprecate this function once migration to Align is over. - uint64_t getPrefTypeAlignment(Type *Ty) const; - - /// Returns the preferred stack/global alignment for the specified - /// type. - /// - /// This is always at least as good as the ABI alignment. - Align getPrefTypeAlign(Type *Ty) const; - - /// Returns an integer type with size at least as big as that of a - /// pointer in the given address space. - IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; - - /// Returns an integer (vector of integer) type with size at least as - /// big as that of a pointer of the given pointer (vector of pointer) type. - Type *getIntPtrType(Type *) const; - - /// Returns the smallest integer type with size at least as big as - /// Width bits. - Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; - - /// Returns the largest legal integer type, or null if none are set. - Type *getLargestLegalIntType(LLVMContext &C) const { - unsigned LargestSize = getLargestLegalIntTypeSizeInBits(); - return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); - } - - /// Returns the size of largest legal integer type size, or 0 if none - /// are set. - unsigned getLargestLegalIntTypeSizeInBits() const; - - /// Returns the type of a GEP index. - /// If it was not specified explicitly, it will be the integer type of the - /// pointer width - IntPtrType. - Type *getIndexType(Type *PtrTy) const; - - /// Returns the offset from the beginning of the type for the specified - /// indices. - /// - /// Note that this takes the element type, not the pointer type. - /// This is used to implement getelementptr. - int64_t getIndexedOffsetInType(Type *ElemTy, ArrayRef Indices) const; - - /// Get GEP indices to access Offset inside ElemTy. ElemTy is updated to be - /// the result element type and Offset to be the residual offset. - SmallVector getGEPIndicesForOffset(Type *&ElemTy, APInt &Offset) const; - - /// Get single GEP index to access Offset inside ElemTy. Returns None if - /// index cannot be computed, e.g. because the type is not an aggregate. - /// ElemTy is updated to be the result element type and Offset to be the - /// residual offset. - Optional getGEPIndexForOffset(Type *&ElemTy, APInt &Offset) const; - - /// Returns a StructLayout object, indicating the alignment of the - /// struct, its size, and the offsets of its fields. - /// - /// Note that this information is lazily cached. - const StructLayout *getStructLayout(StructType *Ty) const; - - /// Returns the preferred alignment of the specified global. - /// - /// This includes an explicitly requested alignment (if the global has one). - Align getPreferredAlign(const GlobalVariable *GV) const; -}; - -inline DataLayout *unwrap(LLVMTargetDataRef P) { - return reinterpret_cast(P); -} - -inline LLVMTargetDataRef wrap(const DataLayout *P) { - return reinterpret_cast(const_cast(P)); -} - -/// Used to lazily calculate structure layout information for a target machine, -/// based on the DataLayout structure. -class StructLayout final : public TrailingObjects { - uint64_t StructSize; - Align StructAlignment; - unsigned IsPadded : 1; - unsigned NumElements : 31; - -public: - uint64_t getSizeInBytes() const { return StructSize; } - - uint64_t getSizeInBits() const { return 8 * StructSize; } - - Align getAlignment() const { return StructAlignment; } - - /// Returns whether the struct has padding or not between its fields. - /// NB: Padding in nested element is not taken into account. - bool hasPadding() const { return IsPadded; } - - /// Given a valid byte offset into the structure, returns the structure - /// index that contains it. - unsigned getElementContainingOffset(uint64_t Offset) const; - - MutableArrayRef getMemberOffsets() { - return llvm::makeMutableArrayRef(getTrailingObjects(), - NumElements); - } - - ArrayRef getMemberOffsets() const { - return llvm::makeArrayRef(getTrailingObjects(), NumElements); - } - - uint64_t getElementOffset(unsigned Idx) const { - assert(Idx < NumElements && "Invalid element idx!"); - return getMemberOffsets()[Idx]; - } - - uint64_t getElementOffsetInBits(unsigned Idx) const { - return getElementOffset(Idx) * 8; - } - -private: - friend class DataLayout; // Only DataLayout can create this class - - StructLayout(StructType *ST, const DataLayout &DL); - - size_t numTrailingObjects(OverloadToken) const { - return NumElements; - } -}; - -// The implementation of this method is provided inline as it is particularly -// well suited to constant folding when called on a specific Type subclass. -inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const { - assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); - switch (Ty->getTypeID()) { - case Type::LabelTyID: - return TypeSize::Fixed(getPointerSizeInBits(0)); - case Type::PointerTyID: - return TypeSize::Fixed(getPointerSizeInBits(Ty->getPointerAddressSpace())); - case Type::ArrayTyID: { - ArrayType *ATy = cast(Ty); - return ATy->getNumElements() * - getTypeAllocSizeInBits(ATy->getElementType()); - } - case Type::StructTyID: - // Get the layout annotation... which is lazily created on demand. - return TypeSize::Fixed( - getStructLayout(cast(Ty))->getSizeInBits()); - case Type::IntegerTyID: - return TypeSize::Fixed(Ty->getIntegerBitWidth()); - case Type::HalfTyID: - case Type::BFloatTyID: - return TypeSize::Fixed(16); - case Type::FloatTyID: - return TypeSize::Fixed(32); - case Type::DoubleTyID: - case Type::X86_MMXTyID: - return TypeSize::Fixed(64); - case Type::PPC_FP128TyID: - case Type::FP128TyID: - return TypeSize::Fixed(128); - case Type::X86_AMXTyID: - return TypeSize::Fixed(8192); - // In memory objects this is always aligned to a higher boundary, but - // only 80 bits contain information. - case Type::X86_FP80TyID: - return TypeSize::Fixed(80); - case Type::FixedVectorTyID: - case Type::ScalableVectorTyID: { - VectorType *VTy = cast(Ty); - auto EltCnt = VTy->getElementCount(); - uint64_t MinBits = EltCnt.getKnownMinValue() * - getTypeSizeInBits(VTy->getElementType()).getFixedSize(); - return TypeSize(MinBits, EltCnt.isScalable()); - } - default: - llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type"); - } -} - -} // end namespace llvm - -#endif // LLVM_IR_DATALAYOUT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DebugInfo.h b/suite/synctools/tablegen/include/llvm/IR/DebugInfo.h deleted file mode 100644 index 730c69d0c6..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DebugInfo.h +++ /dev/null @@ -1,164 +0,0 @@ -//===- DebugInfo.h - Debug Information Helpers ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a bunch of datatypes that are useful for creating and -// walking debug info in LLVM IR form. They essentially provide wrappers around -// the information in the global variables that's needed when constructing the -// DWARF information. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DEBUGINFO_H -#define LLVM_IR_DEBUGINFO_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/DebugInfoMetadata.h" - -namespace llvm { - -class DbgDeclareInst; -class DbgValueInst; -class DbgVariableIntrinsic; -class Instruction; -class Module; - -/// Finds all intrinsics declaring local variables as living in the memory that -/// 'V' points to. This may include a mix of dbg.declare and -/// dbg.addr intrinsics. -TinyPtrVector FindDbgAddrUses(Value *V); - -/// Like \c FindDbgAddrUses, but only returns dbg.declare intrinsics, not -/// dbg.addr. -TinyPtrVector FindDbgDeclareUses(Value *V); - -/// Finds the llvm.dbg.value intrinsics describing a value. -void findDbgValues(SmallVectorImpl &DbgValues, Value *V); - -/// Finds the debug info intrinsics describing a value. -void findDbgUsers(SmallVectorImpl &DbgInsts, Value *V); - -/// Find subprogram that is enclosing this scope. -DISubprogram *getDISubprogram(const MDNode *Scope); - -/// Strip debug info in the module if it exists. -/// -/// To do this, we remove all calls to the debugger intrinsics and any named -/// metadata for debugging. We also remove debug locations for instructions. -/// Return true if module is modified. -bool StripDebugInfo(Module &M); -bool stripDebugInfo(Function &F); - -/// Downgrade the debug info in a module to contain only line table information. -/// -/// In order to convert debug info to what -gline-tables-only would have -/// created, this does the following: -/// 1) Delete all debug intrinsics. -/// 2) Delete all non-CU named metadata debug info nodes. -/// 3) Create new DebugLocs for each instruction. -/// 4) Create a new CU debug info, and similarly for every metadata node -/// that's reachable from the CU debug info. -/// All debug type metadata nodes are unreachable and garbage collected. -bool stripNonLineTableDebugInfo(Module &M); - -/// Update the debug locations contained within the MD_loop metadata attached -/// to the instruction \p I, if one exists. \p Updater is applied to Metadata -/// operand in the MD_loop metadata: the returned value is included in the -/// updated loop metadata node if it is non-null. -void updateLoopMetadataDebugLocations( - Instruction &I, function_ref Updater); - -/// Return Debug Info Metadata Version by checking module flags. -unsigned getDebugMetadataVersionFromModule(const Module &M); - -/// Utility to find all debug info in a module. -/// -/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To -/// list debug info MDNodes used by an instruction, DebugInfoFinder uses -/// processDeclare, processValue and processLocation to handle DbgDeclareInst, -/// DbgValueInst and DbgLoc attached to instructions. processModule will go -/// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes -/// used by the CUs. -class DebugInfoFinder { -public: - /// Process entire module and collect debug info anchors. - void processModule(const Module &M); - /// Process a single instruction and collect debug info anchors. - void processInstruction(const Module &M, const Instruction &I); - - /// Process DbgVariableIntrinsic. - void processVariable(const Module &M, const DbgVariableIntrinsic &DVI); - /// Process debug info location. - void processLocation(const Module &M, const DILocation *Loc); - - /// Process subprogram. - void processSubprogram(DISubprogram *SP); - - /// Clear all lists. - void reset(); - -private: - void processCompileUnit(DICompileUnit *CU); - void processScope(DIScope *Scope); - void processType(DIType *DT); - bool addCompileUnit(DICompileUnit *CU); - bool addGlobalVariable(DIGlobalVariableExpression *DIG); - bool addScope(DIScope *Scope); - bool addSubprogram(DISubprogram *SP); - bool addType(DIType *DT); - -public: - using compile_unit_iterator = - SmallVectorImpl::const_iterator; - using subprogram_iterator = SmallVectorImpl::const_iterator; - using global_variable_expression_iterator = - SmallVectorImpl::const_iterator; - using type_iterator = SmallVectorImpl::const_iterator; - using scope_iterator = SmallVectorImpl::const_iterator; - - iterator_range compile_units() const { - return make_range(CUs.begin(), CUs.end()); - } - - iterator_range subprograms() const { - return make_range(SPs.begin(), SPs.end()); - } - - iterator_range global_variables() const { - return make_range(GVs.begin(), GVs.end()); - } - - iterator_range types() const { - return make_range(TYs.begin(), TYs.end()); - } - - iterator_range scopes() const { - return make_range(Scopes.begin(), Scopes.end()); - } - - unsigned compile_unit_count() const { return CUs.size(); } - unsigned global_variable_count() const { return GVs.size(); } - unsigned subprogram_count() const { return SPs.size(); } - unsigned type_count() const { return TYs.size(); } - unsigned scope_count() const { return Scopes.size(); } - -private: - SmallVector CUs; - SmallVector SPs; - SmallVector GVs; - SmallVector TYs; - SmallVector Scopes; - SmallPtrSet NodesSeen; -}; - -} // end namespace llvm - -#endif // LLVM_IR_DEBUGINFO_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DebugInfoFlags.def b/suite/synctools/tablegen/include/llvm/IR/DebugInfoFlags.def deleted file mode 100644 index df375b6c68..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DebugInfoFlags.def +++ /dev/null @@ -1,103 +0,0 @@ -//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Macros for running through debug info flags. -// -//===----------------------------------------------------------------------===// - -#if !(defined HANDLE_DI_FLAG || defined HANDLE_DISP_FLAG) -#error "Missing macro definition of HANDLE_DI*" -#endif - -#ifndef HANDLE_DI_FLAG -#define HANDLE_DI_FLAG(ID, NAME) -#endif - -#ifndef HANDLE_DISP_FLAG -#define HANDLE_DISP_FLAG(ID, NAME) -#endif - -// General flags kept in DINode. - -HANDLE_DI_FLAG(0, Zero) // Use it as zero value. - // For example: void foo(DIFlags Flags = FlagZero). -HANDLE_DI_FLAG(1, Private) -HANDLE_DI_FLAG(2, Protected) -HANDLE_DI_FLAG(3, Public) -HANDLE_DI_FLAG((1 << 2), FwdDecl) -HANDLE_DI_FLAG((1 << 3), AppleBlock) -// Used to be BlockByRef, can be reused for anything except DICompositeType. -HANDLE_DI_FLAG((1 << 4), ReservedBit4) -HANDLE_DI_FLAG((1 << 5), Virtual) -HANDLE_DI_FLAG((1 << 6), Artificial) -HANDLE_DI_FLAG((1 << 7), Explicit) -HANDLE_DI_FLAG((1 << 8), Prototyped) -HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) -HANDLE_DI_FLAG((1 << 10), ObjectPointer) -HANDLE_DI_FLAG((1 << 11), Vector) -HANDLE_DI_FLAG((1 << 12), StaticMember) -HANDLE_DI_FLAG((1 << 13), LValueReference) -HANDLE_DI_FLAG((1 << 14), RValueReference) -HANDLE_DI_FLAG((1 << 15), ExportSymbols) -HANDLE_DI_FLAG((1 << 16), SingleInheritance) -HANDLE_DI_FLAG((2 << 16), MultipleInheritance) -HANDLE_DI_FLAG((3 << 16), VirtualInheritance) -HANDLE_DI_FLAG((1 << 18), IntroducedVirtual) -HANDLE_DI_FLAG((1 << 19), BitField) -HANDLE_DI_FLAG((1 << 20), NoReturn) -HANDLE_DI_FLAG((1 << 22), TypePassByValue) -HANDLE_DI_FLAG((1 << 23), TypePassByReference) -HANDLE_DI_FLAG((1 << 24), EnumClass) -HANDLE_DI_FLAG((1 << 25), Thunk) -HANDLE_DI_FLAG((1 << 26), NonTrivial) -HANDLE_DI_FLAG((1 << 27), BigEndian) -HANDLE_DI_FLAG((1 << 28), LittleEndian) -HANDLE_DI_FLAG((1 << 29), AllCallsDescribed) - -// To avoid needing a dedicated value for IndirectVirtualBase, we use -// the bitwise or of Virtual and FwdDecl, which does not otherwise -// make sense for inheritance. -HANDLE_DI_FLAG((1 << 2) | (1 << 5), IndirectVirtualBase) - -#ifdef DI_FLAG_LARGEST_NEEDED -// intended to be used with ADT/BitmaskEnum.h -// NOTE: always must be equal to largest flag, check this when adding new flag -HANDLE_DI_FLAG((1 << 29), Largest) -#undef DI_FLAG_LARGEST_NEEDED -#endif - -// Subprogram-specific flags kept in DISubprogram. - -// Use this as a zero/initialization value. -// For example: void foo(DISPFlags Flags = SPFlagZero). -HANDLE_DISP_FLAG(0, Zero) -// Virtuality is a two-bit enum field in the LSB of the word. -// Values should match DW_VIRTUALITY_*. -HANDLE_DISP_FLAG(1u, Virtual) -HANDLE_DISP_FLAG(2u, PureVirtual) -HANDLE_DISP_FLAG((1u << 2), LocalToUnit) -HANDLE_DISP_FLAG((1u << 3), Definition) -HANDLE_DISP_FLAG((1u << 4), Optimized) -HANDLE_DISP_FLAG((1u << 5), Pure) -HANDLE_DISP_FLAG((1u << 6), Elemental) -HANDLE_DISP_FLAG((1u << 7), Recursive) -HANDLE_DISP_FLAG((1u << 8), MainSubprogram) -// May also utilize this Flag in future, when adding support -// for defaulted functions -HANDLE_DISP_FLAG((1u << 9), Deleted) -HANDLE_DISP_FLAG((1u << 11), ObjCDirect) - -#ifdef DISP_FLAG_LARGEST_NEEDED -// Intended to be used with ADT/BitmaskEnum.h. -// NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 11), Largest) -#undef DISP_FLAG_LARGEST_NEEDED -#endif - -#undef HANDLE_DI_FLAG -#undef HANDLE_DISP_FLAG diff --git a/suite/synctools/tablegen/include/llvm/IR/DebugInfoMetadata.h b/suite/synctools/tablegen/include/llvm/IR/DebugInfoMetadata.h deleted file mode 100644 index b3e8205893..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DebugInfoMetadata.h +++ /dev/null @@ -1,3759 +0,0 @@ -//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Declarations for metadata specific to debug info. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DEBUGINFOMETADATA_H -#define LLVM_IR_DEBUGINFOMETADATA_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitmaskEnum.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Metadata.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Discriminator.h" -#include -#include -#include -#include -#include -#include - -// Helper macros for defining get() overrides. -#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ -#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS -#define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS) \ - static CLASS *getDistinct(LLVMContext &Context, \ - DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ - return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ - } \ - static Temp##CLASS getTemporary(LLVMContext &Context, \ - DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ - return Temp##CLASS( \ - getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ - } -#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ - static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ - return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ - } \ - static CLASS *getIfExists(LLVMContext &Context, \ - DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ - return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ - /* ShouldCreate */ false); \ - } \ - DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS) - -namespace llvm { - -extern cl::opt EnableFSDiscriminator; - -class DITypeRefArray { - const MDTuple *N = nullptr; - -public: - DITypeRefArray() = default; - DITypeRefArray(const MDTuple *N) : N(N) {} - - explicit operator bool() const { return get(); } - explicit operator MDTuple *() const { return get(); } - - MDTuple *get() const { return const_cast(N); } - MDTuple *operator->() const { return get(); } - MDTuple &operator*() const { return *get(); } - - // FIXME: Fix callers and remove condition on N. - unsigned size() const { return N ? N->getNumOperands() : 0u; } - DIType *operator[](unsigned I) const { - return cast_or_null(N->getOperand(I)); - } - - class iterator { - MDNode::op_iterator I = nullptr; - - public: - using iterator_category = std::input_iterator_tag; - using value_type = DIType *; - using difference_type = std::ptrdiff_t; - using pointer = void; - using reference = DIType *; - - iterator() = default; - explicit iterator(MDNode::op_iterator I) : I(I) {} - - DIType *operator*() const { return cast_or_null(*I); } - - iterator &operator++() { - ++I; - return *this; - } - - iterator operator++(int) { - iterator Temp(*this); - ++I; - return Temp; - } - - bool operator==(const iterator &X) const { return I == X.I; } - bool operator!=(const iterator &X) const { return I != X.I; } - }; - - // FIXME: Fix callers and remove condition on N. - iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } - iterator end() const { return N ? iterator(N->op_end()) : iterator(); } -}; - -/// Tagged DWARF-like metadata node. -/// -/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, -/// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's -/// potentially used for non-DWARF output. -class DINode : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - -protected: - DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - ArrayRef Ops1, ArrayRef Ops2 = None) - : MDNode(C, ID, Storage, Ops1, Ops2) { - assert(Tag < 1u << 16); - SubclassData16 = Tag; - } - ~DINode() = default; - - template Ty *getOperandAs(unsigned I) const { - return cast_or_null(getOperand(I)); - } - - StringRef getStringOperand(unsigned I) const { - if (auto *S = getOperandAs(I)) - return S->getString(); - return StringRef(); - } - - static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { - if (S.empty()) - return nullptr; - return MDString::get(Context, S); - } - - /// Allow subclasses to mutate the tag. - void setTag(unsigned Tag) { SubclassData16 = Tag; } - -public: - dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } - - /// Debug info flags. - /// - /// The three accessibility flags are mutually exclusive and rolled together - /// in the first two bits. - enum DIFlags : uint32_t { -#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, -#define DI_FLAG_LARGEST_NEEDED -#include "llvm/IR/DebugInfoFlags.def" - FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, - FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | - FlagVirtualInheritance, - LLVM_MARK_AS_BITMASK_ENUM(FlagLargest) - }; - - static DIFlags getFlag(StringRef Flag); - static StringRef getFlagString(DIFlags Flag); - - /// Split up a flags bitfield. - /// - /// Split \c Flags into \c SplitFlags, a vector of its components. Returns - /// any remaining (unrecognized) bits. - static DIFlags splitFlags(DIFlags Flags, - SmallVectorImpl &SplitFlags); - - static bool classof(const Metadata *MD) { - switch (MD->getMetadataID()) { - default: - return false; - case GenericDINodeKind: - case DISubrangeKind: - case DIEnumeratorKind: - case DIBasicTypeKind: - case DIStringTypeKind: - case DIDerivedTypeKind: - case DICompositeTypeKind: - case DISubroutineTypeKind: - case DIFileKind: - case DICompileUnitKind: - case DISubprogramKind: - case DILexicalBlockKind: - case DILexicalBlockFileKind: - case DINamespaceKind: - case DICommonBlockKind: - case DITemplateTypeParameterKind: - case DITemplateValueParameterKind: - case DIGlobalVariableKind: - case DILocalVariableKind: - case DILabelKind: - case DIObjCPropertyKind: - case DIImportedEntityKind: - case DIModuleKind: - case DIGenericSubrangeKind: - return true; - } - } -}; - -/// Generic tagged DWARF-like metadata node. -/// -/// An un-specialized DWARF-like metadata node. The first operand is a -/// (possibly empty) null-separated \a MDString header that contains arbitrary -/// fields. The remaining operands are \a dwarf_operands(), and are pointers -/// to other metadata. -class GenericDINode : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, - unsigned Tag, ArrayRef Ops1, - ArrayRef Ops2) - : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { - setHash(Hash); - } - ~GenericDINode() { dropAllReferences(); } - - void setHash(unsigned Hash) { SubclassData32 = Hash; } - void recalculateHash(); - - static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Header, ArrayRef DwarfOps, - StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Header), - DwarfOps, Storage, ShouldCreate); - } - - static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Header, ArrayRef DwarfOps, - StorageType Storage, bool ShouldCreate = true); - - TempGenericDINode cloneImpl() const { - return getTemporary(getContext(), getTag(), getHeader(), - SmallVector(dwarf_operands())); - } - -public: - unsigned getHash() const { return SubclassData32; } - - DEFINE_MDNODE_GET(GenericDINode, - (unsigned Tag, StringRef Header, - ArrayRef DwarfOps), - (Tag, Header, DwarfOps)) - DEFINE_MDNODE_GET(GenericDINode, - (unsigned Tag, MDString *Header, - ArrayRef DwarfOps), - (Tag, Header, DwarfOps)) - - /// Return a (temporary) clone of this. - TempGenericDINode clone() const { return cloneImpl(); } - - dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } - StringRef getHeader() const { return getStringOperand(0); } - MDString *getRawHeader() const { return getOperandAs(0); } - - op_iterator dwarf_op_begin() const { return op_begin() + 1; } - op_iterator dwarf_op_end() const { return op_end(); } - op_range dwarf_operands() const { - return op_range(dwarf_op_begin(), dwarf_op_end()); - } - - unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } - const MDOperand &getDwarfOperand(unsigned I) const { - return getOperand(I + 1); - } - void replaceDwarfOperandWith(unsigned I, Metadata *New) { - replaceOperandWith(I + 1, New); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == GenericDINodeKind; - } -}; - -/// Array subrange. -/// -/// TODO: Merge into node for DW_TAG_array_type, which should have a custom -/// type. -class DISubrange : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - DISubrange(LLVMContext &C, StorageType Storage, ArrayRef Ops) - : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {} - - ~DISubrange() = default; - - static DISubrange *getImpl(LLVMContext &Context, int64_t Count, - int64_t LowerBound, StorageType Storage, - bool ShouldCreate = true); - - static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, - int64_t LowerBound, StorageType Storage, - bool ShouldCreate = true); - - static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, - Metadata *LowerBound, Metadata *UpperBound, - Metadata *Stride, StorageType Storage, - bool ShouldCreate = true); - - TempDISubrange cloneImpl() const { - return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), - getRawUpperBound(), getRawStride()); - } - -public: - DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), - (Count, LowerBound)) - - DEFINE_MDNODE_GET(DISubrange, (Metadata * CountNode, int64_t LowerBound = 0), - (CountNode, LowerBound)) - - DEFINE_MDNODE_GET(DISubrange, - (Metadata * CountNode, Metadata *LowerBound, - Metadata *UpperBound, Metadata *Stride), - (CountNode, LowerBound, UpperBound, Stride)) - - TempDISubrange clone() const { return cloneImpl(); } - - Metadata *getRawCountNode() const { return getOperand(0).get(); } - - Metadata *getRawLowerBound() const { return getOperand(1).get(); } - - Metadata *getRawUpperBound() const { return getOperand(2).get(); } - - Metadata *getRawStride() const { return getOperand(3).get(); } - - typedef PointerUnion BoundType; - - BoundType getCount() const; - - BoundType getLowerBound() const; - - BoundType getUpperBound() const; - - BoundType getStride() const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DISubrangeKind; - } -}; - -class DIGenericSubrange : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - DIGenericSubrange(LLVMContext &C, StorageType Storage, - ArrayRef Ops) - : DINode(C, DIGenericSubrangeKind, Storage, - dwarf::DW_TAG_generic_subrange, Ops) {} - - ~DIGenericSubrange() = default; - - static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, - Metadata *LowerBound, Metadata *UpperBound, - Metadata *Stride, StorageType Storage, - bool ShouldCreate = true); - - TempDIGenericSubrange cloneImpl() const { - return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), - getRawUpperBound(), getRawStride()); - } - -public: - DEFINE_MDNODE_GET(DIGenericSubrange, - (Metadata * CountNode, Metadata *LowerBound, - Metadata *UpperBound, Metadata *Stride), - (CountNode, LowerBound, UpperBound, Stride)) - - TempDIGenericSubrange clone() const { return cloneImpl(); } - - Metadata *getRawCountNode() const { return getOperand(0).get(); } - Metadata *getRawLowerBound() const { return getOperand(1).get(); } - Metadata *getRawUpperBound() const { return getOperand(2).get(); } - Metadata *getRawStride() const { return getOperand(3).get(); } - - using BoundType = PointerUnion; - - BoundType getCount() const; - BoundType getLowerBound() const; - BoundType getUpperBound() const; - BoundType getStride() const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIGenericSubrangeKind; - } -}; - -/// Enumeration value. -/// -/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no -/// longer creates a type cycle. -class DIEnumerator : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - APInt Value; - DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, - bool IsUnsigned, ArrayRef Ops) - : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), - Value(Value) { - SubclassData32 = IsUnsigned; - } - DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, - bool IsUnsigned, ArrayRef Ops) - : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, - Ops) {} - ~DIEnumerator() = default; - - static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, - bool IsUnsigned, StringRef Name, - StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Value, IsUnsigned, - getCanonicalMDString(Context, Name), Storage, ShouldCreate); - } - static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, - bool IsUnsigned, MDString *Name, - StorageType Storage, bool ShouldCreate = true); - - TempDIEnumerator cloneImpl() const { - return getTemporary(getContext(), getValue(), isUnsigned(), getName()); - } - -public: - DEFINE_MDNODE_GET(DIEnumerator, - (int64_t Value, bool IsUnsigned, StringRef Name), - (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) - DEFINE_MDNODE_GET(DIEnumerator, - (int64_t Value, bool IsUnsigned, MDString *Name), - (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) - DEFINE_MDNODE_GET(DIEnumerator, - (APInt Value, bool IsUnsigned, StringRef Name), - (Value, IsUnsigned, Name)) - DEFINE_MDNODE_GET(DIEnumerator, - (APInt Value, bool IsUnsigned, MDString *Name), - (Value, IsUnsigned, Name)) - - TempDIEnumerator clone() const { return cloneImpl(); } - - const APInt &getValue() const { return Value; } - bool isUnsigned() const { return SubclassData32; } - StringRef getName() const { return getStringOperand(0); } - - MDString *getRawName() const { return getOperandAs(0); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIEnumeratorKind; - } -}; - -/// Base class for scope-like contexts. -/// -/// Base class for lexical scopes and types (which are also declaration -/// contexts). -/// -/// TODO: Separate the concepts of declaration contexts and lexical scopes. -class DIScope : public DINode { -protected: - DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - ArrayRef Ops) - : DINode(C, ID, Storage, Tag, Ops) {} - ~DIScope() = default; - -public: - DIFile *getFile() const { return cast_or_null(getRawFile()); } - - inline StringRef getFilename() const; - inline StringRef getDirectory() const; - inline Optional getSource() const; - - StringRef getName() const; - DIScope *getScope() const; - - /// Return the raw underlying file. - /// - /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it - /// \em is the file). If \c this is an \a DIFile, we need to return \c this. - /// Otherwise, return the first operand, which is where all other subclasses - /// store their file pointer. - Metadata *getRawFile() const { - return isa(this) ? const_cast(this) - : static_cast(getOperand(0)); - } - - static bool classof(const Metadata *MD) { - switch (MD->getMetadataID()) { - default: - return false; - case DIBasicTypeKind: - case DIStringTypeKind: - case DIDerivedTypeKind: - case DICompositeTypeKind: - case DISubroutineTypeKind: - case DIFileKind: - case DICompileUnitKind: - case DISubprogramKind: - case DILexicalBlockKind: - case DILexicalBlockFileKind: - case DINamespaceKind: - case DICommonBlockKind: - case DIModuleKind: - return true; - } - } -}; - -/// File. -/// -/// TODO: Merge with directory/file node (including users). -/// TODO: Canonicalize paths on creation. -class DIFile : public DIScope { - friend class LLVMContextImpl; - friend class MDNode; - -public: - /// Which algorithm (e.g. MD5) a checksum was generated with. - /// - /// The encoding is explicit because it is used directly in Bitcode. The - /// value 0 is reserved to indicate the absence of a checksum in Bitcode. - enum ChecksumKind { - // The first variant was originally CSK_None, encoded as 0. The new - // internal representation removes the need for this by wrapping the - // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 - // encoding is reserved. - CSK_MD5 = 1, - CSK_SHA1 = 2, - CSK_SHA256 = 3, - CSK_Last = CSK_SHA256 // Should be last enumeration. - }; - - /// A single checksum, represented by a \a Kind and a \a Value (a string). - template struct ChecksumInfo { - /// The kind of checksum which \a Value encodes. - ChecksumKind Kind; - /// The string value of the checksum. - T Value; - - ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) {} - ~ChecksumInfo() = default; - bool operator==(const ChecksumInfo &X) const { - return Kind == X.Kind && Value == X.Value; - } - bool operator!=(const ChecksumInfo &X) const { return !(*this == X); } - StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } - }; - -private: - Optional> Checksum; - Optional Source; - - DIFile(LLVMContext &C, StorageType Storage, - Optional> CS, Optional Src, - ArrayRef Ops) - : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), - Checksum(CS), Source(Src) {} - ~DIFile() = default; - - static DIFile *getImpl(LLVMContext &Context, StringRef Filename, - StringRef Directory, - Optional> CS, - Optional Source, StorageType Storage, - bool ShouldCreate = true) { - Optional> MDChecksum; - if (CS) - MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); - return getImpl( - Context, getCanonicalMDString(Context, Filename), - getCanonicalMDString(Context, Directory), MDChecksum, - Source ? Optional(getCanonicalMDString(Context, *Source)) - : None, - Storage, ShouldCreate); - } - static DIFile *getImpl(LLVMContext &Context, MDString *Filename, - MDString *Directory, - Optional> CS, - Optional Source, StorageType Storage, - bool ShouldCreate = true); - - TempDIFile cloneImpl() const { - return getTemporary(getContext(), getFilename(), getDirectory(), - getChecksum(), getSource()); - } - -public: - DEFINE_MDNODE_GET(DIFile, - (StringRef Filename, StringRef Directory, - Optional> CS = None, - Optional Source = None), - (Filename, Directory, CS, Source)) - DEFINE_MDNODE_GET(DIFile, - (MDString * Filename, MDString *Directory, - Optional> CS = None, - Optional Source = None), - (Filename, Directory, CS, Source)) - - TempDIFile clone() const { return cloneImpl(); } - - StringRef getFilename() const { return getStringOperand(0); } - StringRef getDirectory() const { return getStringOperand(1); } - Optional> getChecksum() const { - Optional> StringRefChecksum; - if (Checksum) - StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); - return StringRefChecksum; - } - Optional getSource() const { - return Source ? Optional((*Source)->getString()) : None; - } - - MDString *getRawFilename() const { return getOperandAs(0); } - MDString *getRawDirectory() const { return getOperandAs(1); } - Optional> getRawChecksum() const { return Checksum; } - Optional getRawSource() const { return Source; } - - static StringRef getChecksumKindAsString(ChecksumKind CSKind); - static Optional getChecksumKind(StringRef CSKindStr); - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIFileKind; - } -}; - -StringRef DIScope::getFilename() const { - if (auto *F = getFile()) - return F->getFilename(); - return ""; -} - -StringRef DIScope::getDirectory() const { - if (auto *F = getFile()) - return F->getDirectory(); - return ""; -} - -Optional DIScope::getSource() const { - if (auto *F = getFile()) - return F->getSource(); - return None; -} - -/// Base class for types. -/// -/// TODO: Remove the hardcoded name and context, since many types don't use -/// them. -/// TODO: Split up flags. -class DIType : public DIScope { - unsigned Line; - DIFlags Flags; - uint64_t SizeInBits; - uint64_t OffsetInBits; - uint32_t AlignInBits; - -protected: - DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, ArrayRef Ops) - : DIScope(C, ID, Storage, Tag, Ops) { - init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); - } - ~DIType() = default; - - void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags) { - this->Line = Line; - this->Flags = Flags; - this->SizeInBits = SizeInBits; - this->AlignInBits = AlignInBits; - this->OffsetInBits = OffsetInBits; - } - - /// Change fields in place. - void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { - assert(isDistinct() && "Only distinct nodes can mutate"); - setTag(Tag); - init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); - } - -public: - TempDIType clone() const { - return TempDIType(cast(MDNode::clone().release())); - } - - unsigned getLine() const { return Line; } - uint64_t getSizeInBits() const { return SizeInBits; } - uint32_t getAlignInBits() const { return AlignInBits; } - uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } - uint64_t getOffsetInBits() const { return OffsetInBits; } - DIFlags getFlags() const { return Flags; } - - DIScope *getScope() const { return cast_or_null(getRawScope()); } - StringRef getName() const { return getStringOperand(2); } - - Metadata *getRawScope() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - - /// Returns a new temporary DIType with updated Flags - TempDIType cloneWithFlags(DIFlags NewFlags) const { - auto NewTy = clone(); - NewTy->Flags = NewFlags; - return NewTy; - } - - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } - bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } - bool isVirtual() const { return getFlags() & FlagVirtual; } - bool isArtificial() const { return getFlags() & FlagArtificial; } - bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } - bool isObjcClassComplete() const { - return getFlags() & FlagObjcClassComplete; - } - bool isVector() const { return getFlags() & FlagVector; } - bool isBitField() const { return getFlags() & FlagBitField; } - bool isStaticMember() const { return getFlags() & FlagStaticMember; } - bool isLValueReference() const { return getFlags() & FlagLValueReference; } - bool isRValueReference() const { return getFlags() & FlagRValueReference; } - bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } - bool isTypePassByReference() const { - return getFlags() & FlagTypePassByReference; - } - bool isBigEndian() const { return getFlags() & FlagBigEndian; } - bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } - bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } - - static bool classof(const Metadata *MD) { - switch (MD->getMetadataID()) { - default: - return false; - case DIBasicTypeKind: - case DIStringTypeKind: - case DIDerivedTypeKind: - case DICompositeTypeKind: - case DISubroutineTypeKind: - return true; - } - } -}; - -/// Basic type, like 'int' or 'float'. -/// -/// TODO: Split out DW_TAG_unspecified_type. -/// TODO: Drop unused accessors. -class DIBasicType : public DIType { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Encoding; - - DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, - uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, ArrayRef Ops) - : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, - Flags, Ops), - Encoding(Encoding) {} - ~DIBasicType() = default; - - static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Flags, Storage, - ShouldCreate); - } - static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true); - - TempDIBasicType cloneImpl() const { - return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding(), getFlags()); - } - -public: - DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), - (Tag, Name, 0, 0, 0, FlagZero)) - DEFINE_MDNODE_GET(DIBasicType, - (unsigned Tag, StringRef Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) - DEFINE_MDNODE_GET(DIBasicType, - (unsigned Tag, MDString *Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) - DEFINE_MDNODE_GET(DIBasicType, - (unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) - DEFINE_MDNODE_GET(DIBasicType, - (unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) - - TempDIBasicType clone() const { return cloneImpl(); } - - unsigned getEncoding() const { return Encoding; } - - enum class Signedness { Signed, Unsigned }; - - /// Return the signedness of this type, or None if this type is neither - /// signed nor unsigned. - Optional getSignedness() const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIBasicTypeKind; - } -}; - -/// String type, Fortran CHARACTER(n) -class DIStringType : public DIType { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Encoding; - - DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, - uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - ArrayRef Ops) - : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, - FlagZero, Ops), - Encoding(Encoding) {} - ~DIStringType() = default; - - static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *StringLength, - Metadata *StrLenExp, Metadata *StrLocationExp, - uint64_t SizeInBits, uint32_t AlignInBits, - unsigned Encoding, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - StringLength, StrLenExp, StrLocationExp, SizeInBits, - AlignInBits, Encoding, Storage, ShouldCreate); - } - static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Name, Metadata *StringLength, - Metadata *StrLenExp, Metadata *StrLocationExp, - uint64_t SizeInBits, uint32_t AlignInBits, - unsigned Encoding, StorageType Storage, - bool ShouldCreate = true); - - TempDIStringType cloneImpl() const { - return getTemporary(getContext(), getTag(), getRawName(), - getRawStringLength(), getRawStringLengthExp(), - getRawStringLocationExp(), getSizeInBits(), - getAlignInBits(), getEncoding()); - } - -public: - DEFINE_MDNODE_GET(DIStringType, - (unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits), - (Tag, Name, nullptr, nullptr, nullptr, SizeInBits, - AlignInBits, 0)) - DEFINE_MDNODE_GET(DIStringType, - (unsigned Tag, MDString *Name, Metadata *StringLength, - Metadata *StringLengthExp, Metadata *StringLocationExp, - uint64_t SizeInBits, uint32_t AlignInBits, - unsigned Encoding), - (Tag, Name, StringLength, StringLengthExp, - StringLocationExp, SizeInBits, AlignInBits, Encoding)) - DEFINE_MDNODE_GET(DIStringType, - (unsigned Tag, StringRef Name, Metadata *StringLength, - Metadata *StringLengthExp, Metadata *StringLocationExp, - uint64_t SizeInBits, uint32_t AlignInBits, - unsigned Encoding), - (Tag, Name, StringLength, StringLengthExp, - StringLocationExp, SizeInBits, AlignInBits, Encoding)) - - TempDIStringType clone() const { return cloneImpl(); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIStringTypeKind; - } - - DIVariable *getStringLength() const { - return cast_or_null(getRawStringLength()); - } - - DIExpression *getStringLengthExp() const { - return cast_or_null(getRawStringLengthExp()); - } - - DIExpression *getStringLocationExp() const { - return cast_or_null(getRawStringLocationExp()); - } - - unsigned getEncoding() const { return Encoding; } - - Metadata *getRawStringLength() const { return getOperand(3); } - - Metadata *getRawStringLengthExp() const { return getOperand(4); } - - Metadata *getRawStringLocationExp() const { return getOperand(5); } -}; - -/// Derived types. -/// -/// This includes qualified types, pointers, references, friends, typedefs, and -/// class members. -/// -/// TODO: Split out members (inheritance, fields, methods, etc.). -class DIDerivedType : public DIType { - friend class LLVMContextImpl; - friend class MDNode; - - /// The DWARF address space of the memory pointed to or referenced by a - /// pointer or reference type respectively. - Optional DWARFAddressSpace; - - DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, - unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, Optional DWARFAddressSpace, - DIFlags Flags, ArrayRef Ops) - : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops), - DWARFAddressSpace(DWARFAddressSpace) {} - ~DIDerivedType() = default; - - static DIDerivedType * - getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, - unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, - Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags, ExtraData, Annotations.get(), - Storage, ShouldCreate); - } - static DIDerivedType * - getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData, Metadata *Annotations, StorageType Storage, - bool ShouldCreate = true); - - TempDIDerivedType cloneImpl() const { - return getTemporary( - getContext(), getTag(), getName(), getFile(), getLine(), getScope(), - getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), - getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); - } - -public: - DEFINE_MDNODE_GET( - DIDerivedType, - (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr), - (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, - OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations)) - DEFINE_MDNODE_GET(DIDerivedType, - (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, - DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr, - DINodeArray Annotations = nullptr), - (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData, Annotations)) - - TempDIDerivedType clone() const { return cloneImpl(); } - - /// Get the base type this is derived from. - DIType *getBaseType() const { return cast_or_null(getRawBaseType()); } - Metadata *getRawBaseType() const { return getOperand(3); } - - /// \returns The DWARF address space of the memory pointed to or referenced by - /// a pointer or reference type respectively. - Optional getDWARFAddressSpace() const { return DWARFAddressSpace; } - - /// Get extra data associated with this derived type. - /// - /// Class type for pointer-to-members, objective-c property node for ivars, - /// global constant wrapper for static members, or virtual base pointer offset - /// for inheritance. - /// - /// TODO: Separate out types that need this extra operand: pointer-to-member - /// types and member fields (static members and ivars). - Metadata *getExtraData() const { return getRawExtraData(); } - Metadata *getRawExtraData() const { return getOperand(4); } - - /// Get annotations associated with this derived type. - DINodeArray getAnnotations() const { - return cast_or_null(getRawAnnotations()); - } - Metadata *getRawAnnotations() const { return getOperand(5); } - - /// Get casted version of extra data. - /// @{ - DIType *getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return cast_or_null(getExtraData()); - } - - DIObjCProperty *getObjCProperty() const { - return dyn_cast_or_null(getExtraData()); - } - - uint32_t getVBPtrOffset() const { - assert(getTag() == dwarf::DW_TAG_inheritance); - if (auto *CM = cast_or_null(getExtraData())) - if (auto *CI = dyn_cast_or_null(CM->getValue())) - return static_cast(CI->getZExtValue()); - return 0; - } - - Constant *getStorageOffsetInBits() const { - assert(getTag() == dwarf::DW_TAG_member && isBitField()); - if (auto *C = cast_or_null(getExtraData())) - return C->getValue(); - return nullptr; - } - - Constant *getConstant() const { - assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); - if (auto *C = cast_or_null(getExtraData())) - return C->getValue(); - return nullptr; - } - Constant *getDiscriminantValue() const { - assert(getTag() == dwarf::DW_TAG_member && !isStaticMember()); - if (auto *C = cast_or_null(getExtraData())) - return C->getValue(); - return nullptr; - } - /// @} - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIDerivedTypeKind; - } -}; - -/// Composite types. -/// -/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). -/// TODO: Create a custom, unrelated node for DW_TAG_array_type. -class DICompositeType : public DIType { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned RuntimeLang; - - DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, - unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - ArrayRef Ops) - : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops), - RuntimeLang(RuntimeLang) {} - ~DICompositeType() = default; - - /// Change fields in place. - void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DIFlags Flags) { - assert(isDistinct() && "Only distinct nodes can mutate"); - assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate"); - this->RuntimeLang = RuntimeLang; - DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); - } - - static DICompositeType * - getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, - DITemplateParameterArray TemplateParams, StringRef Identifier, - DIDerivedType *Discriminator, Metadata *DataLocation, - Metadata *Associated, Metadata *Allocated, Metadata *Rank, - DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { - return getImpl( - Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, - BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), - RuntimeLang, VTableHolder, TemplateParams.get(), - getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, - Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate); - } - static DICompositeType * - getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams, - MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, - Metadata *Associated, Metadata *Allocated, Metadata *Rank, - Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); - - TempDICompositeType cloneImpl() const { - return getTemporary( - getContext(), getTag(), getName(), getFile(), getLine(), getScope(), - getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), - getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), - getTemplateParams(), getIdentifier(), getDiscriminator(), - getRawDataLocation(), getRawAssociated(), getRawAllocated(), - getRawRank(), getAnnotations()); - } - -public: - DEFINE_MDNODE_GET( - DICompositeType, - (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, - DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, - DITemplateParameterArray TemplateParams = nullptr, - StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, - Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, - Metadata *Allocated = nullptr, Metadata *Rank = nullptr, - DINodeArray Annotations = nullptr), - (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, - OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, - Annotations)) - DEFINE_MDNODE_GET( - DICompositeType, - (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, - Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, - Metadata *Associated = nullptr, Metadata *Allocated = nullptr, - Metadata *Rank = nullptr, Metadata *Annotations = nullptr), - (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, - OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, - Annotations)) - - TempDICompositeType clone() const { return cloneImpl(); } - - /// Get a DICompositeType with the given ODR identifier. - /// - /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped - /// DICompositeType for the given ODR \c Identifier. If none exists, creates - /// a new node. - /// - /// Else, returns \c nullptr. - static DICompositeType * - getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, - MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, - Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, - unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank, Metadata *Annotations); - static DICompositeType *getODRTypeIfExists(LLVMContext &Context, - MDString &Identifier); - - /// Build a DICompositeType with the given ODR identifier. - /// - /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If - /// it doesn't exist, creates a new one. If it does exist and \a - /// isForwardDecl(), and the new arguments would be a definition, mutates the - /// the type in place. In either case, returns the type. - /// - /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns - /// nullptr. - static DICompositeType * - buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, - MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, - Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, - unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, - Metadata *Allocated, Metadata *Rank, Metadata *Annotations); - - DIType *getBaseType() const { return cast_or_null(getRawBaseType()); } - DINodeArray getElements() const { - return cast_or_null(getRawElements()); - } - DIType *getVTableHolder() const { - return cast_or_null(getRawVTableHolder()); - } - DITemplateParameterArray getTemplateParams() const { - return cast_or_null(getRawTemplateParams()); - } - StringRef getIdentifier() const { return getStringOperand(7); } - unsigned getRuntimeLang() const { return RuntimeLang; } - - Metadata *getRawBaseType() const { return getOperand(3); } - Metadata *getRawElements() const { return getOperand(4); } - Metadata *getRawVTableHolder() const { return getOperand(5); } - Metadata *getRawTemplateParams() const { return getOperand(6); } - MDString *getRawIdentifier() const { return getOperandAs(7); } - Metadata *getRawDiscriminator() const { return getOperand(8); } - DIDerivedType *getDiscriminator() const { - return getOperandAs(8); - } - Metadata *getRawDataLocation() const { return getOperand(9); } - DIVariable *getDataLocation() const { - return dyn_cast_or_null(getRawDataLocation()); - } - DIExpression *getDataLocationExp() const { - return dyn_cast_or_null(getRawDataLocation()); - } - Metadata *getRawAssociated() const { return getOperand(10); } - DIVariable *getAssociated() const { - return dyn_cast_or_null(getRawAssociated()); - } - DIExpression *getAssociatedExp() const { - return dyn_cast_or_null(getRawAssociated()); - } - Metadata *getRawAllocated() const { return getOperand(11); } - DIVariable *getAllocated() const { - return dyn_cast_or_null(getRawAllocated()); - } - DIExpression *getAllocatedExp() const { - return dyn_cast_or_null(getRawAllocated()); - } - Metadata *getRawRank() const { return getOperand(12); } - ConstantInt *getRankConst() const { - if (auto *MD = dyn_cast_or_null(getRawRank())) - return dyn_cast_or_null(MD->getValue()); - return nullptr; - } - DIExpression *getRankExp() const { - return dyn_cast_or_null(getRawRank()); - } - - Metadata *getRawAnnotations() const { return getOperand(13); } - DINodeArray getAnnotations() const { - return cast_or_null(getRawAnnotations()); - } - - /// Replace operands. - /// - /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision - /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track - /// of its movement if necessary. - /// @{ - void replaceElements(DINodeArray Elements) { -#ifndef NDEBUG - for (DINode *Op : getElements()) - assert(is_contained(Elements->operands(), Op) && - "Lost a member during member list replacement"); -#endif - replaceOperandWith(4, Elements.get()); - } - - void replaceVTableHolder(DIType *VTableHolder) { - replaceOperandWith(5, VTableHolder); - } - - void replaceTemplateParams(DITemplateParameterArray TemplateParams) { - replaceOperandWith(6, TemplateParams.get()); - } - /// @} - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DICompositeTypeKind; - } -}; - -/// Type array for a subprogram. -/// -/// TODO: Fold the array of types in directly as operands. -class DISubroutineType : public DIType { - friend class LLVMContextImpl; - friend class MDNode; - - /// The calling convention used with DW_AT_calling_convention. Actually of - /// type dwarf::CallingConvention. - uint8_t CC; - - DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, - uint8_t CC, ArrayRef Ops) - : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, - 0, 0, 0, 0, Flags, Ops), - CC(CC) {} - ~DISubroutineType() = default; - - static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, - uint8_t CC, DITypeRefArray TypeArray, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); - } - static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, - uint8_t CC, Metadata *TypeArray, - StorageType Storage, - bool ShouldCreate = true); - - TempDISubroutineType cloneImpl() const { - return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); - } - -public: - DEFINE_MDNODE_GET(DISubroutineType, - (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), - (Flags, CC, TypeArray)) - DEFINE_MDNODE_GET(DISubroutineType, - (DIFlags Flags, uint8_t CC, Metadata *TypeArray), - (Flags, CC, TypeArray)) - - TempDISubroutineType clone() const { return cloneImpl(); } - - uint8_t getCC() const { return CC; } - - DITypeRefArray getTypeArray() const { - return cast_or_null(getRawTypeArray()); - } - - Metadata *getRawTypeArray() const { return getOperand(3); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DISubroutineTypeKind; - } -}; - -/// Compile unit. -class DICompileUnit : public DIScope { - friend class LLVMContextImpl; - friend class MDNode; - -public: - enum DebugEmissionKind : unsigned { - NoDebug = 0, - FullDebug, - LineTablesOnly, - DebugDirectivesOnly, - LastEmissionKind = DebugDirectivesOnly - }; - - enum class DebugNameTableKind : unsigned { - Default = 0, - GNU = 1, - None = 2, - LastDebugNameTableKind = None - }; - - static Optional getEmissionKind(StringRef Str); - static const char *emissionKindString(DebugEmissionKind EK); - static Optional getNameTableKind(StringRef Str); - static const char *nameTableKindString(DebugNameTableKind PK); - -private: - unsigned SourceLanguage; - bool IsOptimized; - unsigned RuntimeVersion; - unsigned EmissionKind; - uint64_t DWOId; - bool SplitDebugInlining; - bool DebugInfoForProfiling; - unsigned NameTableKind; - bool RangesBaseAddress; - - DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, - bool IsOptimized, unsigned RuntimeVersion, - unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, - bool DebugInfoForProfiling, unsigned NameTableKind, - bool RangesBaseAddress, ArrayRef Ops) - : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), - SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), - RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), - DWOId(DWOId), SplitDebugInlining(SplitDebugInlining), - DebugInfoForProfiling(DebugInfoForProfiling), - NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { - assert(Storage != Uniqued); - } - ~DICompileUnit() = default; - - static DICompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, - StringRef Producer, bool IsOptimized, StringRef Flags, - unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, DICompositeTypeArray EnumTypes, - DIScopeArray RetainedTypes, - DIGlobalVariableExpressionArray GlobalVariables, - DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, - uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, - unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, - StringRef SDK, StorageType Storage, bool ShouldCreate = true) { - return getImpl( - Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), - IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, - getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, - EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), - ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, - DebugInfoForProfiling, NameTableKind, RangesBaseAddress, - getCanonicalMDString(Context, SysRoot), - getCanonicalMDString(Context, SDK), Storage, ShouldCreate); - } - static DICompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, - MDString *Producer, bool IsOptimized, MDString *Flags, - unsigned RuntimeVersion, MDString *SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, - Metadata *GlobalVariables, Metadata *ImportedEntities, - Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, - bool DebugInfoForProfiling, unsigned NameTableKind, - bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, - StorageType Storage, bool ShouldCreate = true); - - TempDICompileUnit cloneImpl() const { - return getTemporary( - getContext(), getSourceLanguage(), getFile(), getProducer(), - isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), - getEmissionKind(), getEnumTypes(), getRetainedTypes(), - getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, - getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), - getRangesBaseAddress(), getSysRoot(), getSDK()); - } - -public: - static void get() = delete; - static void getIfExists() = delete; - - DEFINE_MDNODE_GET_DISTINCT_TEMPORARY( - DICompileUnit, - (unsigned SourceLanguage, DIFile *File, StringRef Producer, - bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, - StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, - DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, - DIGlobalVariableExpressionArray GlobalVariables, - DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, - uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, - DebugNameTableKind NameTableKind, bool RangesBaseAddress, - StringRef SysRoot, StringRef SDK), - (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, - SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, - GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining, - DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress, - SysRoot, SDK)) - DEFINE_MDNODE_GET_DISTINCT_TEMPORARY( - DICompileUnit, - (unsigned SourceLanguage, Metadata *File, MDString *Producer, - bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, - MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, - Metadata *RetainedTypes, Metadata *GlobalVariables, - Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, - bool SplitDebugInlining, bool DebugInfoForProfiling, - unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, - MDString *SDK), - (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, - SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, - GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining, - DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK)) - - TempDICompileUnit clone() const { return cloneImpl(); } - - unsigned getSourceLanguage() const { return SourceLanguage; } - bool isOptimized() const { return IsOptimized; } - unsigned getRuntimeVersion() const { return RuntimeVersion; } - DebugEmissionKind getEmissionKind() const { - return (DebugEmissionKind)EmissionKind; - } - bool isDebugDirectivesOnly() const { - return EmissionKind == DebugDirectivesOnly; - } - bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } - DebugNameTableKind getNameTableKind() const { - return (DebugNameTableKind)NameTableKind; - } - bool getRangesBaseAddress() const { return RangesBaseAddress; } - StringRef getProducer() const { return getStringOperand(1); } - StringRef getFlags() const { return getStringOperand(2); } - StringRef getSplitDebugFilename() const { return getStringOperand(3); } - DICompositeTypeArray getEnumTypes() const { - return cast_or_null(getRawEnumTypes()); - } - DIScopeArray getRetainedTypes() const { - return cast_or_null(getRawRetainedTypes()); - } - DIGlobalVariableExpressionArray getGlobalVariables() const { - return cast_or_null(getRawGlobalVariables()); - } - DIImportedEntityArray getImportedEntities() const { - return cast_or_null(getRawImportedEntities()); - } - DIMacroNodeArray getMacros() const { - return cast_or_null(getRawMacros()); - } - uint64_t getDWOId() const { return DWOId; } - void setDWOId(uint64_t DwoId) { DWOId = DwoId; } - bool getSplitDebugInlining() const { return SplitDebugInlining; } - void setSplitDebugInlining(bool SplitDebugInlining) { - this->SplitDebugInlining = SplitDebugInlining; - } - StringRef getSysRoot() const { return getStringOperand(9); } - StringRef getSDK() const { return getStringOperand(10); } - - MDString *getRawProducer() const { return getOperandAs(1); } - MDString *getRawFlags() const { return getOperandAs(2); } - MDString *getRawSplitDebugFilename() const { - return getOperandAs(3); - } - Metadata *getRawEnumTypes() const { return getOperand(4); } - Metadata *getRawRetainedTypes() const { return getOperand(5); } - Metadata *getRawGlobalVariables() const { return getOperand(6); } - Metadata *getRawImportedEntities() const { return getOperand(7); } - Metadata *getRawMacros() const { return getOperand(8); } - MDString *getRawSysRoot() const { return getOperandAs(9); } - MDString *getRawSDK() const { return getOperandAs(10); } - - /// Replace arrays. - /// - /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and - /// deleted on a uniquing collision. In practice, uniquing collisions on \a - /// DICompileUnit should be fairly rare. - /// @{ - void replaceEnumTypes(DICompositeTypeArray N) { - replaceOperandWith(4, N.get()); - } - void replaceRetainedTypes(DITypeArray N) { replaceOperandWith(5, N.get()); } - void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { - replaceOperandWith(6, N.get()); - } - void replaceImportedEntities(DIImportedEntityArray N) { - replaceOperandWith(7, N.get()); - } - void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } - /// @} - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DICompileUnitKind; - } -}; - -/// A scope for locals. -/// -/// A legal scope for lexical blocks, local variables, and debug info -/// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a -/// DILexicalBlockFile. -class DILocalScope : public DIScope { -protected: - DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - ArrayRef Ops) - : DIScope(C, ID, Storage, Tag, Ops) {} - ~DILocalScope() = default; - -public: - /// Get the subprogram for this scope. - /// - /// Return this if it's an \a DISubprogram; otherwise, look up the scope - /// chain. - DISubprogram *getSubprogram() const; - - /// Get the first non DILexicalBlockFile scope of this scope. - /// - /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the - /// scope chain. - DILocalScope *getNonLexicalBlockFileScope() const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DISubprogramKind || - MD->getMetadataID() == DILexicalBlockKind || - MD->getMetadataID() == DILexicalBlockFileKind; - } -}; - -/// Debug location. -/// -/// A debug location in source code, used for debug info and otherwise. -class DILocation : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - - DILocation(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, ArrayRef MDs, bool ImplicitCode); - ~DILocation() { dropAllReferences(); } - - static DILocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool ImplicitCode, - StorageType Storage, bool ShouldCreate = true); - static DILocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, DILocalScope *Scope, - DILocation *InlinedAt, bool ImplicitCode, - StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Line, Column, static_cast(Scope), - static_cast(InlinedAt), ImplicitCode, Storage, - ShouldCreate); - } - - TempDILocation cloneImpl() const { - // Get the raw scope/inlinedAt since it is possible to invoke this on - // a DILocation containing temporary metadata. - return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), - getRawInlinedAt(), isImplicitCode()); - } - -public: - // Disallow replacing operands. - void replaceOperandWith(unsigned I, Metadata *New) = delete; - - DEFINE_MDNODE_GET(DILocation, - (unsigned Line, unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr, bool ImplicitCode = false), - (Line, Column, Scope, InlinedAt, ImplicitCode)) - DEFINE_MDNODE_GET(DILocation, - (unsigned Line, unsigned Column, DILocalScope *Scope, - DILocation *InlinedAt = nullptr, - bool ImplicitCode = false), - (Line, Column, Scope, InlinedAt, ImplicitCode)) - - /// Return a (temporary) clone of this. - TempDILocation clone() const { return cloneImpl(); } - - unsigned getLine() const { return SubclassData32; } - unsigned getColumn() const { return SubclassData16; } - DILocalScope *getScope() const { return cast(getRawScope()); } - - DILocation *getInlinedAt() const { - return cast_or_null(getRawInlinedAt()); - } - - /// Check if the location corresponds to an implicit code. - /// When the ImplicitCode flag is true, it means that the Instruction - /// with this DILocation has been added by the front-end but it hasn't been - /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing - /// bracket). It's useful for code coverage to not show a counter on "empty" - /// lines. - bool isImplicitCode() const { return SubclassData1; } - void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } - - DIFile *getFile() const { return getScope()->getFile(); } - StringRef getFilename() const { return getScope()->getFilename(); } - StringRef getDirectory() const { return getScope()->getDirectory(); } - Optional getSource() const { return getScope()->getSource(); } - - /// Get the scope where this is inlined. - /// - /// Walk through \a getInlinedAt() and return \a getScope() from the deepest - /// location. - DILocalScope *getInlinedAtScope() const { - if (auto *IA = getInlinedAt()) - return IA->getInlinedAtScope(); - return getScope(); - } - - /// Get the DWARF discriminator. - /// - /// DWARF discriminators distinguish identical file locations between - /// instructions that are on different basic blocks. - /// - /// There are 3 components stored in discriminator, from lower bits: - /// - /// Base discriminator: assigned by AddDiscriminators pass to identify IRs - /// that are defined by the same source line, but - /// different basic blocks. - /// Duplication factor: assigned by optimizations that will scale down - /// the execution frequency of the original IR. - /// Copy Identifier: assigned by optimizations that clones the IR. - /// Each copy of the IR will be assigned an identifier. - /// - /// Encoding: - /// - /// The above 3 components are encoded into a 32bit unsigned integer in - /// order. If the lowest bit is 1, the current component is empty, and the - /// next component will start in the next bit. Otherwise, the current - /// component is non-empty, and its content starts in the next bit. The - /// value of each components is either 5 bit or 12 bit: if the 7th bit - /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the - /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to - /// represent the component. Thus, the number of bits used for a component - /// is either 0 (if it and all the next components are empty); 1 - if it is - /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both - /// 0); or 14, if its value is up to and including 0x1ff. Note that the last - /// component is also capped at 0x1ff, even in the case when both first - /// components are 0, and we'd technically have 29 bits available. - /// - /// For precise control over the data being encoded in the discriminator, - /// use encodeDiscriminator/decodeDiscriminator. - - inline unsigned getDiscriminator() const; - - // For the regular discriminator, it stands for all empty components if all - // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by - // default). Here we fully leverage the higher 29 bits for pseudo probe use. - // This is the format: - // [2:0] - 0x7 - // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole - // So if the lower 3 bits is non-zero and the others has at least one - // non-zero bit, it guarantees to be a pseudo probe discriminator - inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { - return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); - } - - /// Returns a new DILocation with updated \p Discriminator. - inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; - - /// Returns a new DILocation with updated base discriminator \p BD. Only the - /// base discriminator is set in the new DILocation, the other encoded values - /// are elided. - /// If the discriminator cannot be encoded, the function returns None. - inline Optional - cloneWithBaseDiscriminator(unsigned BD) const; - - /// Returns the duplication factor stored in the discriminator, or 1 if no - /// duplication factor (or 0) is encoded. - inline unsigned getDuplicationFactor() const; - - /// Returns the copy identifier stored in the discriminator. - inline unsigned getCopyIdentifier() const; - - /// Returns the base discriminator stored in the discriminator. - inline unsigned getBaseDiscriminator() const; - - /// Returns a new DILocation with duplication factor \p DF * current - /// duplication factor encoded in the discriminator. The current duplication - /// factor is as defined by getDuplicationFactor(). - /// Returns None if encoding failed. - inline Optional - cloneByMultiplyingDuplicationFactor(unsigned DF) const; - - /// When two instructions are combined into a single instruction we also - /// need to combine the original locations into a single location. - /// - /// When the locations are the same we can use either location. When they - /// differ, we need a third location which is distinct from either. If they - /// have the same file/line but have a different discriminator we could - /// create a location with a new discriminator. If they are from different - /// files/lines the location is ambiguous and can't be represented in a line - /// entry. In this case, if \p GenerateLocation is true, we will set the - /// merged debug location as line 0 of the nearest common scope where the two - /// locations are inlined from. - /// - /// \p GenerateLocation: Whether the merged location can be generated when - /// \p LocA and \p LocB differ. - static const DILocation *getMergedLocation(const DILocation *LocA, - const DILocation *LocB); - - /// Try to combine the vector of locations passed as input in a single one. - /// This function applies getMergedLocation() repeatedly left-to-right. - /// - /// \p Locs: The locations to be merged. - static const DILocation * - getMergedLocations(ArrayRef Locs); - - /// Return the masked discriminator value for an input discrimnator value D - /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). - // Example: an input of (0x1FF, 7) returns 0xFF. - static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { - return (D & getN1Bits(B)); - } - - /// Return the bits used for base discriminators. - static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } - - /// Returns the base discriminator for a given encoded discriminator \p D. - static unsigned - getBaseDiscriminatorFromDiscriminator(unsigned D, - bool IsFSDiscriminator = false) { - if (IsFSDiscriminator) - return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); - return getUnsignedFromPrefixEncoding(D); - } - - /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor - /// have certain special case behavior (e.g. treating empty duplication factor - /// as the value '1'). - /// This API, in conjunction with cloneWithDiscriminator, may be used to - /// encode the raw values provided. - /// - /// \p BD: base discriminator - /// \p DF: duplication factor - /// \p CI: copy index - /// - /// The return is None if the values cannot be encoded in 32 bits - for - /// example, values for BD or DF larger than 12 bits. Otherwise, the return is - /// the encoded value. - static Optional encodeDiscriminator(unsigned BD, unsigned DF, - unsigned CI); - - /// Raw decoder for values in an encoded discriminator D. - static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, - unsigned &CI); - - /// Returns the duplication factor for a given encoded discriminator \p D, or - /// 1 if no value or 0 is encoded. - static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { - if (EnableFSDiscriminator) - return 1; - D = getNextComponentInDiscriminator(D); - unsigned Ret = getUnsignedFromPrefixEncoding(D); - if (Ret == 0) - return 1; - return Ret; - } - - /// Returns the copy identifier for a given encoded discriminator \p D. - static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { - return getUnsignedFromPrefixEncoding( - getNextComponentInDiscriminator(getNextComponentInDiscriminator(D))); - } - - Metadata *getRawScope() const { return getOperand(0); } - Metadata *getRawInlinedAt() const { - if (getNumOperands() == 2) - return getOperand(1); - return nullptr; - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILocationKind; - } -}; - -/// Subprogram description. -class DISubprogram : public DILocalScope { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - unsigned ScopeLine; - unsigned VirtualIndex; - - /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue - /// of method overrides from secondary bases by this amount. It may be - /// negative. - int ThisAdjustment; - -public: - /// Debug info subprogram flags. - enum DISPFlags : uint32_t { -#define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, -#define DISP_FLAG_LARGEST_NEEDED -#include "llvm/IR/DebugInfoFlags.def" - SPFlagNonvirtual = SPFlagZero, - SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, - LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest) - }; - - static DISPFlags getFlag(StringRef Flag); - static StringRef getFlagString(DISPFlags Flag); - - /// Split up a flags bitfield for easier printing. - /// - /// Split \c Flags into \c SplitFlags, a vector of its components. Returns - /// any remaining (unrecognized) bits. - static DISPFlags splitFlags(DISPFlags Flags, - SmallVectorImpl &SplitFlags); - - // Helper for converting old bitfields to new flags word. - static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, - bool IsOptimized, - unsigned Virtuality = SPFlagNonvirtual, - bool IsMainSubprogram = false) { - // We're assuming virtuality is the low-order field. - static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && - int(SPFlagPureVirtual) == - int(dwarf::DW_VIRTUALITY_pure_virtual), - "Virtuality constant mismatch"); - return static_cast( - (Virtuality & SPFlagVirtuality) | - (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | - (IsDefinition ? SPFlagDefinition : SPFlagZero) | - (IsOptimized ? SPFlagOptimized : SPFlagZero) | - (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); - } - -private: - DIFlags Flags; - DISPFlags SPFlags; - - DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, - DIFlags Flags, DISPFlags SPFlags, ArrayRef Ops) - : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, - Ops), - Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), - ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) { - static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); - } - ~DISubprogram() = default; - - static DISubprogram * - getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - StringRef LinkageName, DIFile *File, unsigned Line, - DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, - unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, - DISPFlags SPFlags, DICompileUnit *Unit, - DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DINodeArray RetainedNodes, DITypeArray ThrownTypes, - DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), - getCanonicalMDString(Context, LinkageName), File, Line, Type, - ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, - Flags, SPFlags, Unit, TemplateParams.get(), Declaration, - RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), - Storage, ShouldCreate); - } - static DISubprogram * - getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, - MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, - unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, - int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, - Metadata *TemplateParams, Metadata *Declaration, - Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, - StorageType Storage, bool ShouldCreate = true); - - TempDISubprogram cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getLinkageName(), - getFile(), getLine(), getType(), getScopeLine(), - getContainingType(), getVirtualIndex(), - getThisAdjustment(), getFlags(), getSPFlags(), - getUnit(), getTemplateParams(), getDeclaration(), - getRetainedNodes(), getThrownTypes(), getAnnotations()); - } - -public: - DEFINE_MDNODE_GET( - DISubprogram, - (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned Line, DISubroutineType *Type, unsigned ScopeLine, - DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, - DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, - DITemplateParameterArray TemplateParams = nullptr, - DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, - DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr), - (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, - VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes, Annotations)) - - DEFINE_MDNODE_GET( - DISubprogram, - (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, - unsigned Line, Metadata *Type, unsigned ScopeLine, - Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, - DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, - Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, - Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, - Metadata *Annotations = nullptr), - (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, - VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes, Annotations)) - - TempDISubprogram clone() const { return cloneImpl(); } - - /// Returns a new temporary DISubprogram with updated Flags - TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { - auto NewSP = clone(); - NewSP->Flags = NewFlags; - return NewSP; - } - -public: - unsigned getLine() const { return Line; } - unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } - unsigned getVirtualIndex() const { return VirtualIndex; } - int getThisAdjustment() const { return ThisAdjustment; } - unsigned getScopeLine() const { return ScopeLine; } - void setScopeLine(unsigned L) { - assert(isDistinct()); - ScopeLine = L; - } - DIFlags getFlags() const { return Flags; } - DISPFlags getSPFlags() const { return SPFlags; } - bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } - bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } - bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } - bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } - - bool isArtificial() const { return getFlags() & FlagArtificial; } - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isExplicit() const { return getFlags() & FlagExplicit; } - bool isPrototyped() const { return getFlags() & FlagPrototyped; } - bool areAllCallsDescribed() const { - return getFlags() & FlagAllCallsDescribed; - } - bool isPure() const { return getSPFlags() & SPFlagPure; } - bool isElemental() const { return getSPFlags() & SPFlagElemental; } - bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } - bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } - - /// Check if this is deleted member function. - /// - /// Return true if this subprogram is a C++11 special - /// member function declared deleted. - bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } - - /// Check if this is reference-qualified. - /// - /// Return true if this subprogram is a C++11 reference-qualified non-static - /// member function (void foo() &). - bool isLValueReference() const { return getFlags() & FlagLValueReference; } - - /// Check if this is rvalue-reference-qualified. - /// - /// Return true if this subprogram is a C++11 rvalue-reference-qualified - /// non-static member function (void foo() &&). - bool isRValueReference() const { return getFlags() & FlagRValueReference; } - - /// Check if this is marked as noreturn. - /// - /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn - bool isNoReturn() const { return getFlags() & FlagNoReturn; } - - // Check if this routine is a compiler-generated thunk. - // - // Returns true if this subprogram is a thunk generated by the compiler. - bool isThunk() const { return getFlags() & FlagThunk; } - - DIScope *getScope() const { return cast_or_null(getRawScope()); } - - StringRef getName() const { return getStringOperand(2); } - StringRef getLinkageName() const { return getStringOperand(3); } - /// Only used by clients of CloneFunction, and only right after the cloning. - void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } - - DISubroutineType *getType() const { - return cast_or_null(getRawType()); - } - DIType *getContainingType() const { - return cast_or_null(getRawContainingType()); - } - - DICompileUnit *getUnit() const { - return cast_or_null(getRawUnit()); - } - void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } - DITemplateParameterArray getTemplateParams() const { - return cast_or_null(getRawTemplateParams()); - } - DISubprogram *getDeclaration() const { - return cast_or_null(getRawDeclaration()); - } - DINodeArray getRetainedNodes() const { - return cast_or_null(getRawRetainedNodes()); - } - DITypeArray getThrownTypes() const { - return cast_or_null(getRawThrownTypes()); - } - DINodeArray getAnnotations() const { - return cast_or_null(getRawAnnotations()); - } - - Metadata *getRawScope() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - MDString *getRawLinkageName() const { return getOperandAs(3); } - Metadata *getRawType() const { return getOperand(4); } - Metadata *getRawUnit() const { return getOperand(5); } - Metadata *getRawDeclaration() const { return getOperand(6); } - Metadata *getRawRetainedNodes() const { return getOperand(7); } - Metadata *getRawContainingType() const { - return getNumOperands() > 8 ? getOperandAs(8) : nullptr; - } - Metadata *getRawTemplateParams() const { - return getNumOperands() > 9 ? getOperandAs(9) : nullptr; - } - Metadata *getRawThrownTypes() const { - return getNumOperands() > 10 ? getOperandAs(10) : nullptr; - } - Metadata *getRawAnnotations() const { - return getNumOperands() > 11 ? getOperandAs(11) : nullptr; - } - - void replaceRawLinkageName(MDString *LinkageName) { - replaceOperandWith(3, LinkageName); - } - - /// Check if this subprogram describes the given function. - /// - /// FIXME: Should this be looking through bitcasts? - bool describes(const Function *F) const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DISubprogramKind; - } -}; - -class DILexicalBlockBase : public DILocalScope { -protected: - DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, - ArrayRef Ops) - : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} - ~DILexicalBlockBase() = default; - -public: - DILocalScope *getScope() const { return cast(getRawScope()); } - - Metadata *getRawScope() const { return getOperand(1); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILexicalBlockKind || - MD->getMetadataID() == DILexicalBlockFileKind; - } -}; - -class DILexicalBlock : public DILexicalBlockBase { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - uint16_t Column; - - DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, ArrayRef Ops) - : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), - Column(Column) { - assert(Column < (1u << 16) && "Expected 16-bit column"); - } - ~DILexicalBlock() = default; - - static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, - DIFile *File, unsigned Line, unsigned Column, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, static_cast(Scope), - static_cast(File), Line, Column, Storage, - ShouldCreate); - } - - static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *File, unsigned Line, unsigned Column, - StorageType Storage, bool ShouldCreate = true); - - TempDILexicalBlock cloneImpl() const { - return getTemporary(getContext(), getScope(), getFile(), getLine(), - getColumn()); - } - -public: - DEFINE_MDNODE_GET(DILexicalBlock, - (DILocalScope * Scope, DIFile *File, unsigned Line, - unsigned Column), - (Scope, File, Line, Column)) - DEFINE_MDNODE_GET(DILexicalBlock, - (Metadata * Scope, Metadata *File, unsigned Line, - unsigned Column), - (Scope, File, Line, Column)) - - TempDILexicalBlock clone() const { return cloneImpl(); } - - unsigned getLine() const { return Line; } - unsigned getColumn() const { return Column; } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILexicalBlockKind; - } -}; - -class DILexicalBlockFile : public DILexicalBlockBase { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Discriminator; - - DILexicalBlockFile(LLVMContext &C, StorageType Storage, - unsigned Discriminator, ArrayRef Ops) - : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), - Discriminator(Discriminator) {} - ~DILexicalBlockFile() = default; - - static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, - DIFile *File, unsigned Discriminator, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, static_cast(Scope), - static_cast(File), Discriminator, Storage, - ShouldCreate); - } - - static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *File, unsigned Discriminator, - StorageType Storage, - bool ShouldCreate = true); - - TempDILexicalBlockFile cloneImpl() const { - return getTemporary(getContext(), getScope(), getFile(), - getDiscriminator()); - } - -public: - DEFINE_MDNODE_GET(DILexicalBlockFile, - (DILocalScope * Scope, DIFile *File, - unsigned Discriminator), - (Scope, File, Discriminator)) - DEFINE_MDNODE_GET(DILexicalBlockFile, - (Metadata * Scope, Metadata *File, unsigned Discriminator), - (Scope, File, Discriminator)) - - TempDILexicalBlockFile clone() const { return cloneImpl(); } - unsigned getDiscriminator() const { return Discriminator; } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILexicalBlockFileKind; - } -}; - -unsigned DILocation::getDiscriminator() const { - if (auto *F = dyn_cast(getScope())) - return F->getDiscriminator(); - return 0; -} - -const DILocation * -DILocation::cloneWithDiscriminator(unsigned Discriminator) const { - DIScope *Scope = getScope(); - // Skip all parent DILexicalBlockFile that already have a discriminator - // assigned. We do not want to have nested DILexicalBlockFiles that have - // multiple discriminators because only the leaf DILexicalBlockFile's - // dominator will be used. - for (auto *LBF = dyn_cast(Scope); - LBF && LBF->getDiscriminator() != 0; - LBF = dyn_cast(Scope)) - Scope = LBF->getScope(); - DILexicalBlockFile *NewScope = - DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); - return DILocation::get(getContext(), getLine(), getColumn(), NewScope, - getInlinedAt()); -} - -unsigned DILocation::getBaseDiscriminator() const { - return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), - EnableFSDiscriminator); -} - -unsigned DILocation::getDuplicationFactor() const { - return getDuplicationFactorFromDiscriminator(getDiscriminator()); -} - -unsigned DILocation::getCopyIdentifier() const { - return getCopyIdentifierFromDiscriminator(getDiscriminator()); -} - -Optional -DILocation::cloneWithBaseDiscriminator(unsigned D) const { - unsigned BD, DF, CI; - - if (EnableFSDiscriminator) { - BD = getBaseDiscriminator(); - if (D == BD) - return this; - return cloneWithDiscriminator(D); - } - - decodeDiscriminator(getDiscriminator(), BD, DF, CI); - if (D == BD) - return this; - if (Optional Encoded = encodeDiscriminator(D, DF, CI)) - return cloneWithDiscriminator(*Encoded); - return None; -} - -Optional -DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { - assert(!EnableFSDiscriminator && "FSDiscriminator should not call this."); - - DF *= getDuplicationFactor(); - if (DF <= 1) - return this; - - unsigned BD = getBaseDiscriminator(); - unsigned CI = getCopyIdentifier(); - if (Optional D = encodeDiscriminator(BD, DF, CI)) - return cloneWithDiscriminator(*D); - return None; -} - -class DINamespace : public DIScope { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned ExportSymbols : 1; - - DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, - ArrayRef Ops) - : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, - Ops), - ExportSymbols(ExportSymbols) {} - ~DINamespace() = default; - - static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, - StringRef Name, bool ExportSymbols, - StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), - ExportSymbols, Storage, ShouldCreate); - } - static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, bool ExportSymbols, - StorageType Storage, bool ShouldCreate = true); - - TempDINamespace cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), - getExportSymbols()); - } - -public: - DEFINE_MDNODE_GET(DINamespace, - (DIScope * Scope, StringRef Name, bool ExportSymbols), - (Scope, Name, ExportSymbols)) - DEFINE_MDNODE_GET(DINamespace, - (Metadata * Scope, MDString *Name, bool ExportSymbols), - (Scope, Name, ExportSymbols)) - - TempDINamespace clone() const { return cloneImpl(); } - - bool getExportSymbols() const { return ExportSymbols; } - DIScope *getScope() const { return cast_or_null(getRawScope()); } - StringRef getName() const { return getStringOperand(2); } - - Metadata *getRawScope() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DINamespaceKind; - } -}; - -/// Represents a module in the programming language, for example, a Clang -/// module, or a Fortran module. -class DIModule : public DIScope { - friend class LLVMContextImpl; - friend class MDNode; - unsigned LineNo; - bool IsDecl; - - DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, - bool IsDecl, ArrayRef Ops) - : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), - LineNo(LineNo), IsDecl(IsDecl) {} - ~DIModule() = default; - - static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, - StringRef Name, StringRef ConfigurationMacros, - StringRef IncludePath, StringRef APINotesFile, - unsigned LineNo, bool IsDecl, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), - getCanonicalMDString(Context, ConfigurationMacros), - getCanonicalMDString(Context, IncludePath), - getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, - Storage, ShouldCreate); - } - static DIModule *getImpl(LLVMContext &Context, Metadata *File, - Metadata *Scope, MDString *Name, - MDString *ConfigurationMacros, MDString *IncludePath, - MDString *APINotesFile, unsigned LineNo, bool IsDecl, - StorageType Storage, bool ShouldCreate = true); - - TempDIModule cloneImpl() const { - return getTemporary(getContext(), getFile(), getScope(), getName(), - getConfigurationMacros(), getIncludePath(), - getAPINotesFile(), getLineNo(), getIsDecl()); - } - -public: - DEFINE_MDNODE_GET(DIModule, - (DIFile * File, DIScope *Scope, StringRef Name, - StringRef ConfigurationMacros, StringRef IncludePath, - StringRef APINotesFile, unsigned LineNo, - bool IsDecl = false), - (File, Scope, Name, ConfigurationMacros, IncludePath, - APINotesFile, LineNo, IsDecl)) - DEFINE_MDNODE_GET(DIModule, - (Metadata * File, Metadata *Scope, MDString *Name, - MDString *ConfigurationMacros, MDString *IncludePath, - MDString *APINotesFile, unsigned LineNo, - bool IsDecl = false), - (File, Scope, Name, ConfigurationMacros, IncludePath, - APINotesFile, LineNo, IsDecl)) - - TempDIModule clone() const { return cloneImpl(); } - - DIScope *getScope() const { return cast_or_null(getRawScope()); } - StringRef getName() const { return getStringOperand(2); } - StringRef getConfigurationMacros() const { return getStringOperand(3); } - StringRef getIncludePath() const { return getStringOperand(4); } - StringRef getAPINotesFile() const { return getStringOperand(5); } - unsigned getLineNo() const { return LineNo; } - bool getIsDecl() const { return IsDecl; } - - Metadata *getRawScope() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - MDString *getRawConfigurationMacros() const { - return getOperandAs(3); - } - MDString *getRawIncludePath() const { return getOperandAs(4); } - MDString *getRawAPINotesFile() const { return getOperandAs(5); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIModuleKind; - } -}; - -/// Base class for template parameters. -class DITemplateParameter : public DINode { -protected: - bool IsDefault; - - DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, - unsigned Tag, bool IsDefault, ArrayRef Ops) - : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} - ~DITemplateParameter() = default; - -public: - StringRef getName() const { return getStringOperand(0); } - DIType *getType() const { return cast_or_null(getRawType()); } - - MDString *getRawName() const { return getOperandAs(0); } - Metadata *getRawType() const { return getOperand(1); } - bool isDefault() const { return IsDefault; } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DITemplateTypeParameterKind || - MD->getMetadataID() == DITemplateValueParameterKind; - } -}; - -class DITemplateTypeParameter : public DITemplateParameter { - friend class LLVMContextImpl; - friend class MDNode; - - DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, - bool IsDefault, ArrayRef Ops) - : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, - dwarf::DW_TAG_template_type_parameter, IsDefault, - Ops) {} - ~DITemplateTypeParameter() = default; - - static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - DIType *Type, bool IsDefault, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, getCanonicalMDString(Context, Name), Type, - IsDefault, Storage, ShouldCreate); - } - static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, - Metadata *Type, bool IsDefault, - StorageType Storage, - bool ShouldCreate = true); - - TempDITemplateTypeParameter cloneImpl() const { - return getTemporary(getContext(), getName(), getType(), isDefault()); - } - -public: - DEFINE_MDNODE_GET(DITemplateTypeParameter, - (StringRef Name, DIType *Type, bool IsDefault), - (Name, Type, IsDefault)) - DEFINE_MDNODE_GET(DITemplateTypeParameter, - (MDString * Name, Metadata *Type, bool IsDefault), - (Name, Type, IsDefault)) - - TempDITemplateTypeParameter clone() const { return cloneImpl(); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DITemplateTypeParameterKind; - } -}; - -class DITemplateValueParameter : public DITemplateParameter { - friend class LLVMContextImpl; - friend class MDNode; - - DITemplateValueParameter(LLVMContext &Context, StorageType Storage, - unsigned Tag, bool IsDefault, - ArrayRef Ops) - : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, - IsDefault, Ops) {} - ~DITemplateValueParameter() = default; - - static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, DIType *Type, - bool IsDefault, Metadata *Value, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, - IsDefault, Value, Storage, ShouldCreate); - } - static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Name, Metadata *Type, - bool IsDefault, Metadata *Value, - StorageType Storage, - bool ShouldCreate = true); - - TempDITemplateValueParameter cloneImpl() const { - return getTemporary(getContext(), getTag(), getName(), getType(), - isDefault(), getValue()); - } - -public: - DEFINE_MDNODE_GET(DITemplateValueParameter, - (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, - Metadata *Value), - (Tag, Name, Type, IsDefault, Value)) - DEFINE_MDNODE_GET(DITemplateValueParameter, - (unsigned Tag, MDString *Name, Metadata *Type, - bool IsDefault, Metadata *Value), - (Tag, Name, Type, IsDefault, Value)) - - TempDITemplateValueParameter clone() const { return cloneImpl(); } - - Metadata *getValue() const { return getOperand(2); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DITemplateValueParameterKind; - } -}; - -/// Base class for variables. -class DIVariable : public DINode { - unsigned Line; - uint32_t AlignInBits; - -protected: - DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, - ArrayRef Ops, uint32_t AlignInBits = 0) - : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), - AlignInBits(AlignInBits) {} - ~DIVariable() = default; - -public: - unsigned getLine() const { return Line; } - DIScope *getScope() const { return cast_or_null(getRawScope()); } - StringRef getName() const { return getStringOperand(1); } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - DIType *getType() const { return cast_or_null(getRawType()); } - uint32_t getAlignInBits() const { return AlignInBits; } - uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } - /// Determines the size of the variable's type. - Optional getSizeInBits() const; - - /// Return the signedness of this variable's type, or None if this type is - /// neither signed nor unsigned. - Optional getSignedness() const { - if (auto *BT = dyn_cast(getType())) - return BT->getSignedness(); - return None; - } - - StringRef getFilename() const { - if (auto *F = getFile()) - return F->getFilename(); - return ""; - } - - StringRef getDirectory() const { - if (auto *F = getFile()) - return F->getDirectory(); - return ""; - } - - Optional getSource() const { - if (auto *F = getFile()) - return F->getSource(); - return None; - } - - Metadata *getRawScope() const { return getOperand(0); } - MDString *getRawName() const { return getOperandAs(1); } - Metadata *getRawFile() const { return getOperand(2); } - Metadata *getRawType() const { return getOperand(3); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILocalVariableKind || - MD->getMetadataID() == DIGlobalVariableKind; - } -}; - -/// DWARF expression. -/// -/// This is (almost) a DWARF expression that modifies the location of a -/// variable, or the location of a single piece of a variable, or (when using -/// DW_OP_stack_value) is the constant variable value. -/// -/// TODO: Co-allocate the expression elements. -/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary -/// storage types. -class DIExpression : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - - std::vector Elements; - - DIExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) - : MDNode(C, DIExpressionKind, Storage, None), - Elements(Elements.begin(), Elements.end()) {} - ~DIExpression() = default; - - static DIExpression *getImpl(LLVMContext &Context, - ArrayRef Elements, StorageType Storage, - bool ShouldCreate = true); - - TempDIExpression cloneImpl() const { - return getTemporary(getContext(), getElements()); - } - -public: - DEFINE_MDNODE_GET(DIExpression, (ArrayRef Elements), (Elements)) - - TempDIExpression clone() const { return cloneImpl(); } - - ArrayRef getElements() const { return Elements; } - - unsigned getNumElements() const { return Elements.size(); } - - uint64_t getElement(unsigned I) const { - assert(I < Elements.size() && "Index out of range"); - return Elements[I]; - } - - enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; - /// Determine whether this represents a constant value, if so - // return its sign information. - llvm::Optional isConstant() const; - - /// Return the number of unique location operands referred to (via - /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of - /// instances of DW_OP_LLVM_arg within the expression. - /// For example, for the expression: - /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, - /// DW_OP_LLVM_arg 0, DW_OP_mul) - /// This function would return 2, as there are two unique location operands - /// (0 and 1). - uint64_t getNumLocationOperands() const; - - using element_iterator = ArrayRef::iterator; - - element_iterator elements_begin() const { return getElements().begin(); } - element_iterator elements_end() const { return getElements().end(); } - - /// A lightweight wrapper around an expression operand. - /// - /// TODO: Store arguments directly and change \a DIExpression to store a - /// range of these. - class ExprOperand { - const uint64_t *Op = nullptr; - - public: - ExprOperand() = default; - explicit ExprOperand(const uint64_t *Op) : Op(Op) {} - - const uint64_t *get() const { return Op; } - - /// Get the operand code. - uint64_t getOp() const { return *Op; } - - /// Get an argument to the operand. - /// - /// Never returns the operand itself. - uint64_t getArg(unsigned I) const { return Op[I + 1]; } - - unsigned getNumArgs() const { return getSize() - 1; } - - /// Return the size of the operand. - /// - /// Return the number of elements in the operand (1 + args). - unsigned getSize() const; - - /// Append the elements of this operand to \p V. - void appendToVector(SmallVectorImpl &V) const { - V.append(get(), get() + getSize()); - } - }; - - /// An iterator for expression operands. - class expr_op_iterator { - ExprOperand Op; - - public: - using iterator_category = std::input_iterator_tag; - using value_type = ExprOperand; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - expr_op_iterator() = default; - explicit expr_op_iterator(element_iterator I) : Op(I) {} - - element_iterator getBase() const { return Op.get(); } - const ExprOperand &operator*() const { return Op; } - const ExprOperand *operator->() const { return &Op; } - - expr_op_iterator &operator++() { - increment(); - return *this; - } - expr_op_iterator operator++(int) { - expr_op_iterator T(*this); - increment(); - return T; - } - - /// Get the next iterator. - /// - /// \a std::next() doesn't work because this is technically an - /// input_iterator, but it's a perfectly valid operation. This is an - /// accessor to provide the same functionality. - expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } - - bool operator==(const expr_op_iterator &X) const { - return getBase() == X.getBase(); - } - bool operator!=(const expr_op_iterator &X) const { - return getBase() != X.getBase(); - } - - private: - void increment() { Op = ExprOperand(getBase() + Op.getSize()); } - }; - - /// Visit the elements via ExprOperand wrappers. - /// - /// These range iterators visit elements through \a ExprOperand wrappers. - /// This is not guaranteed to be a valid range unless \a isValid() gives \c - /// true. - /// - /// \pre \a isValid() gives \c true. - /// @{ - expr_op_iterator expr_op_begin() const { - return expr_op_iterator(elements_begin()); - } - expr_op_iterator expr_op_end() const { - return expr_op_iterator(elements_end()); - } - iterator_range expr_ops() const { - return {expr_op_begin(), expr_op_end()}; - } - /// @} - - bool isValid() const; - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIExpressionKind; - } - - /// Return whether the first element a DW_OP_deref. - bool startsWithDeref() const { - return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref; - } - - /// Holds the characteristics of one fragment of a larger variable. - struct FragmentInfo { - uint64_t SizeInBits; - uint64_t OffsetInBits; - }; - - /// Retrieve the details of this fragment expression. - static Optional getFragmentInfo(expr_op_iterator Start, - expr_op_iterator End); - - /// Retrieve the details of this fragment expression. - Optional getFragmentInfo() const { - return getFragmentInfo(expr_op_begin(), expr_op_end()); - } - - /// Return whether this is a piece of an aggregate variable. - bool isFragment() const { return getFragmentInfo().hasValue(); } - - /// Return whether this is an implicit location description. - bool isImplicit() const; - - /// Return whether the location is computed on the expression stack, meaning - /// it cannot be a simple register location. - bool isComplex() const; - - /// Append \p Ops with operations to apply the \p Offset. - static void appendOffset(SmallVectorImpl &Ops, int64_t Offset); - - /// If this is a constant offset, extract it. If there is no expression, - /// return true with an offset of zero. - bool extractIfOffset(int64_t &Offset) const; - - /// Returns true iff this DIExpression contains at least one instance of - /// `DW_OP_LLVM_arg, n` for all n in [0, N). - bool hasAllLocationOps(unsigned N) const; - - /// Checks if the last 4 elements of the expression are DW_OP_constu DW_OP_swap DW_OP_xderef and extracts the . - static const DIExpression *extractAddressClass(const DIExpression *Expr, - unsigned &AddrClass); - - /// Used for DIExpression::prepend. - enum PrependOps : uint8_t { - ApplyOffset = 0, - DerefBefore = 1 << 0, - DerefAfter = 1 << 1, - StackValue = 1 << 2, - EntryValue = 1 << 3 - }; - - /// Prepend \p DIExpr with a deref and offset operation and optionally turn it - /// into a stack value or/and an entry value. - static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, - int64_t Offset = 0); - - /// Prepend \p DIExpr with the given opcodes and optionally turn it into a - /// stack value. - static DIExpression *prependOpcodes(const DIExpression *Expr, - SmallVectorImpl &Ops, - bool StackValue = false, - bool EntryValue = false); - - /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the - /// returned expression is a stack value only if \p DIExpr is a stack value. - /// If \p DIExpr describes a fragment, the returned expression will describe - /// the same fragment. - static DIExpression *append(const DIExpression *Expr, ArrayRef Ops); - - /// Convert \p DIExpr into a stack value if it isn't one already by appending - /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. - /// If \p DIExpr describes a fragment, the returned expression will describe - /// the same fragment. - static DIExpression *appendToStack(const DIExpression *Expr, - ArrayRef Ops); - - /// Create a copy of \p Expr by appending the given list of \p Ops to each - /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to - /// modify a specific location used by \p Expr, such as when salvaging that - /// location. - static DIExpression *appendOpsToArg(const DIExpression *Expr, - ArrayRef Ops, unsigned ArgNo, - bool StackValue = false); - - /// Create a copy of \p Expr with each instance of - /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, - /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` - /// for all Arg > \p OldArg. - /// This is used when replacing one of the operands of a debug value list - /// with another operand in the same list and deleting the old operand. - static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, - uint64_t NewArg); - - /// Create a DIExpression to describe one part of an aggregate variable that - /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation - /// will be appended to the elements of \c Expr. If \c Expr already contains - /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset - /// into the existing fragment. - /// - /// \param OffsetInBits Offset of the piece in bits. - /// \param SizeInBits Size of the piece in bits. - /// \return Creating a fragment expression may fail if \c Expr - /// contains arithmetic operations that would be - /// truncated. - static Optional - createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, - unsigned SizeInBits); - - /// Determine the relative position of the fragments passed in. - /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, - /// 1 if this is entirely after Other. - static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { - uint64_t l1 = A.OffsetInBits; - uint64_t l2 = B.OffsetInBits; - uint64_t r1 = l1 + A.SizeInBits; - uint64_t r2 = l2 + B.SizeInBits; - if (r1 <= l2) - return -1; - else if (r2 <= l1) - return 1; - else - return 0; - } - - using ExtOps = std::array; - - /// Returns the ops for a zero- or sign-extension in a DIExpression. - static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); - - /// Append a zero- or sign-extension to \p Expr. Converts the expression to a - /// stack value if it isn't one already. - static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, - unsigned ToSize, bool Signed); - - /// Check if fragments overlap between a pair of FragmentInfos. - static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { - return fragmentCmp(A, B) == 0; - } - - /// Determine the relative position of the fragments described by this - /// DIExpression and \p Other. Calls static fragmentCmp implementation. - int fragmentCmp(const DIExpression *Other) const { - auto Fragment1 = *getFragmentInfo(); - auto Fragment2 = *Other->getFragmentInfo(); - return fragmentCmp(Fragment1, Fragment2); - } - - /// Check if fragments overlap between this DIExpression and \p Other. - bool fragmentsOverlap(const DIExpression *Other) const { - if (!isFragment() || !Other->isFragment()) - return true; - return fragmentCmp(Other) == 0; - } - - /// Check if the expression consists of exactly one entry value operand. - /// (This is the only configuration of entry values that is supported.) - bool isEntryValue() const { - return getNumElements() > 0 && - getElement(0) == dwarf::DW_OP_LLVM_entry_value; - } - - /// Try to shorten an expression with an initial constant operand. - /// Returns a new expression and constant on success, or the original - /// expression and constant on failure. - std::pair - constantFold(const ConstantInt *CI); -}; - -inline bool operator==(const DIExpression::FragmentInfo &A, - const DIExpression::FragmentInfo &B) { - return std::tie(A.SizeInBits, A.OffsetInBits) == - std::tie(B.SizeInBits, B.OffsetInBits); -} - -inline bool operator<(const DIExpression::FragmentInfo &A, - const DIExpression::FragmentInfo &B) { - return std::tie(A.SizeInBits, A.OffsetInBits) < - std::tie(B.SizeInBits, B.OffsetInBits); -} - -template <> struct DenseMapInfo { - using FragInfo = DIExpression::FragmentInfo; - static const uint64_t MaxVal = std::numeric_limits::max(); - - static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } - - static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } - - static unsigned getHashValue(const FragInfo &Frag) { - return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); - } - - static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } -}; - -/// Global variables. -/// -/// TODO: Remove DisplayName. It's always equal to Name. -class DIGlobalVariable : public DIVariable { - friend class LLVMContextImpl; - friend class MDNode; - - bool IsLocalToUnit; - bool IsDefinition; - - DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, - bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, - ArrayRef Ops) - : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), - IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} - ~DIGlobalVariable() = default; - - static DIGlobalVariable * - getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, - bool IsLocalToUnit, bool IsDefinition, - DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, - uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), - getCanonicalMDString(Context, LinkageName), File, Line, Type, - IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - cast_or_null(TemplateParams), AlignInBits, - Annotations.get(), Storage, ShouldCreate); - } - static DIGlobalVariable * - getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, - MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, - Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, - bool ShouldCreate = true); - - TempDIGlobalVariable cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getLinkageName(), - getFile(), getLine(), getType(), isLocalToUnit(), - isDefinition(), getStaticDataMemberDeclaration(), - getTemplateParams(), getAlignInBits(), - getAnnotations()); - } - -public: - DEFINE_MDNODE_GET( - DIGlobalVariable, - (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, - DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, - uint32_t AlignInBits, DINodeArray Annotations), - (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) - DEFINE_MDNODE_GET( - DIGlobalVariable, - (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, - unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, - Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits, Metadata *Annotations), - (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) - - TempDIGlobalVariable clone() const { return cloneImpl(); } - - bool isLocalToUnit() const { return IsLocalToUnit; } - bool isDefinition() const { return IsDefinition; } - StringRef getDisplayName() const { return getStringOperand(4); } - StringRef getLinkageName() const { return getStringOperand(5); } - DIDerivedType *getStaticDataMemberDeclaration() const { - return cast_or_null(getRawStaticDataMemberDeclaration()); - } - DINodeArray getAnnotations() const { - return cast_or_null(getRawAnnotations()); - } - - MDString *getRawLinkageName() const { return getOperandAs(5); } - Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } - Metadata *getRawTemplateParams() const { return getOperand(7); } - MDTuple *getTemplateParams() const { return getOperandAs(7); } - Metadata *getRawAnnotations() const { return getOperand(8); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIGlobalVariableKind; - } -}; - -class DICommonBlock : public DIScope { - unsigned LineNo; - - friend class LLVMContextImpl; - friend class MDNode; - - DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, - ArrayRef Ops) - : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, - Ops), - LineNo(LineNo) {} - - static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, - DIGlobalVariable *Decl, StringRef Name, - DIFile *File, unsigned LineNo, - StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), - File, LineNo, Storage, ShouldCreate); - } - static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *Decl, MDString *Name, Metadata *File, - unsigned LineNo, StorageType Storage, - bool ShouldCreate = true); - - TempDICommonBlock cloneImpl() const { - return getTemporary(getContext(), getScope(), getDecl(), getName(), - getFile(), getLineNo()); - } - -public: - DEFINE_MDNODE_GET(DICommonBlock, - (DIScope * Scope, DIGlobalVariable *Decl, StringRef Name, - DIFile *File, unsigned LineNo), - (Scope, Decl, Name, File, LineNo)) - DEFINE_MDNODE_GET(DICommonBlock, - (Metadata * Scope, Metadata *Decl, MDString *Name, - Metadata *File, unsigned LineNo), - (Scope, Decl, Name, File, LineNo)) - - TempDICommonBlock clone() const { return cloneImpl(); } - - DIScope *getScope() const { return cast_or_null(getRawScope()); } - DIGlobalVariable *getDecl() const { - return cast_or_null(getRawDecl()); - } - StringRef getName() const { return getStringOperand(2); } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - unsigned getLineNo() const { return LineNo; } - - Metadata *getRawScope() const { return getOperand(0); } - Metadata *getRawDecl() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - Metadata *getRawFile() const { return getOperand(3); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DICommonBlockKind; - } -}; - -/// Local variable. -/// -/// TODO: Split up flags. -class DILocalVariable : public DIVariable { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Arg : 16; - DIFlags Flags; - - DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Arg, DIFlags Flags, uint32_t AlignInBits, - ArrayRef Ops) - : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), - Arg(Arg), Flags(Flags) { - assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range"); - } - ~DILocalVariable() = default; - - static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, - StringRef Name, DIFile *File, unsigned Line, - DIType *Type, unsigned Arg, DIFlags Flags, - uint32_t AlignInBits, DINodeArray Annotations, - StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, - Line, Type, Arg, Flags, AlignInBits, Annotations.get(), - Storage, ShouldCreate); - } - static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, Metadata *File, unsigned Line, - Metadata *Type, unsigned Arg, DIFlags Flags, - uint32_t AlignInBits, Metadata *Annotations, - StorageType Storage, - bool ShouldCreate = true); - - TempDILocalVariable cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getFile(), - getLine(), getType(), getArg(), getFlags(), - getAlignInBits(), getAnnotations()); - } - -public: - DEFINE_MDNODE_GET(DILocalVariable, - (DILocalScope * Scope, StringRef Name, DIFile *File, - unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, - uint32_t AlignInBits, DINodeArray Annotations), - (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, - Annotations)) - DEFINE_MDNODE_GET(DILocalVariable, - (Metadata * Scope, MDString *Name, Metadata *File, - unsigned Line, Metadata *Type, unsigned Arg, DIFlags Flags, - uint32_t AlignInBits, Metadata *Annotations), - (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, - Annotations)) - - TempDILocalVariable clone() const { return cloneImpl(); } - - /// Get the local scope for this variable. - /// - /// Variables must be defined in a local scope. - DILocalScope *getScope() const { - return cast(DIVariable::getScope()); - } - - bool isParameter() const { return Arg; } - unsigned getArg() const { return Arg; } - DIFlags getFlags() const { return Flags; } - - DINodeArray getAnnotations() const { - return cast_or_null(getRawAnnotations()); - } - Metadata *getRawAnnotations() const { return getOperand(4); } - - bool isArtificial() const { return getFlags() & FlagArtificial; } - bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } - - /// Check that a location is valid for this variable. - /// - /// Check that \c DL exists, is in the same subprogram, and has the same - /// inlined-at location as \c this. (Otherwise, it's not a valid attachment - /// to a \a DbgInfoIntrinsic.) - bool isValidLocationForIntrinsic(const DILocation *DL) const { - return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILocalVariableKind; - } -}; - -/// Label. -/// -class DILabel : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - - DILabel(LLVMContext &C, StorageType Storage, unsigned Line, - ArrayRef Ops) - : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} - ~DILabel() = default; - - static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - DIFile *File, unsigned Line, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, - Line, Storage, ShouldCreate); - } - static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, - Metadata *File, unsigned Line, StorageType Storage, - bool ShouldCreate = true); - - TempDILabel cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getFile(), - getLine()); - } - -public: - DEFINE_MDNODE_GET(DILabel, - (DILocalScope * Scope, StringRef Name, DIFile *File, - unsigned Line), - (Scope, Name, File, Line)) - DEFINE_MDNODE_GET(DILabel, - (Metadata * Scope, MDString *Name, Metadata *File, - unsigned Line), - (Scope, Name, File, Line)) - - TempDILabel clone() const { return cloneImpl(); } - - /// Get the local scope for this label. - /// - /// Labels must be defined in a local scope. - DILocalScope *getScope() const { - return cast_or_null(getRawScope()); - } - unsigned getLine() const { return Line; } - StringRef getName() const { return getStringOperand(1); } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - - Metadata *getRawScope() const { return getOperand(0); } - MDString *getRawName() const { return getOperandAs(1); } - Metadata *getRawFile() const { return getOperand(2); } - - /// Check that a location is valid for this label. - /// - /// Check that \c DL exists, is in the same subprogram, and has the same - /// inlined-at location as \c this. (Otherwise, it's not a valid attachment - /// to a \a DbgInfoIntrinsic.) - bool isValidLocationForIntrinsic(const DILocation *DL) const { - return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DILabelKind; - } -}; - -class DIObjCProperty : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - unsigned Attributes; - - DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Attributes, ArrayRef Ops) - : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, - Ops), - Line(Line), Attributes(Attributes) {} - ~DIObjCProperty() = default; - - static DIObjCProperty * - getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, - StringRef GetterName, StringRef SetterName, unsigned Attributes, - DIType *Type, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, - getCanonicalMDString(Context, GetterName), - getCanonicalMDString(Context, SetterName), Attributes, Type, - Storage, ShouldCreate); - } - static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, - Metadata *File, unsigned Line, - MDString *GetterName, MDString *SetterName, - unsigned Attributes, Metadata *Type, - StorageType Storage, bool ShouldCreate = true); - - TempDIObjCProperty cloneImpl() const { - return getTemporary(getContext(), getName(), getFile(), getLine(), - getGetterName(), getSetterName(), getAttributes(), - getType()); - } - -public: - DEFINE_MDNODE_GET(DIObjCProperty, - (StringRef Name, DIFile *File, unsigned Line, - StringRef GetterName, StringRef SetterName, - unsigned Attributes, DIType *Type), - (Name, File, Line, GetterName, SetterName, Attributes, - Type)) - DEFINE_MDNODE_GET(DIObjCProperty, - (MDString * Name, Metadata *File, unsigned Line, - MDString *GetterName, MDString *SetterName, - unsigned Attributes, Metadata *Type), - (Name, File, Line, GetterName, SetterName, Attributes, - Type)) - - TempDIObjCProperty clone() const { return cloneImpl(); } - - unsigned getLine() const { return Line; } - unsigned getAttributes() const { return Attributes; } - StringRef getName() const { return getStringOperand(0); } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - StringRef getGetterName() const { return getStringOperand(2); } - StringRef getSetterName() const { return getStringOperand(3); } - DIType *getType() const { return cast_or_null(getRawType()); } - - StringRef getFilename() const { - if (auto *F = getFile()) - return F->getFilename(); - return ""; - } - - StringRef getDirectory() const { - if (auto *F = getFile()) - return F->getDirectory(); - return ""; - } - - MDString *getRawName() const { return getOperandAs(0); } - Metadata *getRawFile() const { return getOperand(1); } - MDString *getRawGetterName() const { return getOperandAs(2); } - MDString *getRawSetterName() const { return getOperandAs(3); } - Metadata *getRawType() const { return getOperand(4); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIObjCPropertyKind; - } -}; - -/// An imported module (C++ using directive or similar). -class DIImportedEntity : public DINode { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - - DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, - unsigned Line, ArrayRef Ops) - : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} - ~DIImportedEntity() = default; - - static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - DIScope *Scope, DINode *Entity, DIFile *File, - unsigned Line, StringRef Name, - DINodeArray Elements, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, Scope, Entity, File, Line, - getCanonicalMDString(Context, Name), Elements.get(), Storage, - ShouldCreate); - } - static DIImportedEntity * - getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, - Metadata *File, unsigned Line, MDString *Name, Metadata *Elements, - StorageType Storage, bool ShouldCreate = true); - - TempDIImportedEntity cloneImpl() const { - return getTemporary(getContext(), getTag(), getScope(), getEntity(), - getFile(), getLine(), getName(), getElements()); - } - -public: - DEFINE_MDNODE_GET(DIImportedEntity, - (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, - unsigned Line, StringRef Name = "", - DINodeArray Elements = nullptr), - (Tag, Scope, Entity, File, Line, Name, Elements)) - DEFINE_MDNODE_GET(DIImportedEntity, - (unsigned Tag, Metadata *Scope, Metadata *Entity, - Metadata *File, unsigned Line, MDString *Name, - Metadata *Elements = nullptr), - (Tag, Scope, Entity, File, Line, Name, Elements)) - - TempDIImportedEntity clone() const { return cloneImpl(); } - - unsigned getLine() const { return Line; } - DIScope *getScope() const { return cast_or_null(getRawScope()); } - DINode *getEntity() const { return cast_or_null(getRawEntity()); } - StringRef getName() const { return getStringOperand(2); } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - DINodeArray getElements() const { - return cast_or_null(getRawElements()); - } - - Metadata *getRawScope() const { return getOperand(0); } - Metadata *getRawEntity() const { return getOperand(1); } - MDString *getRawName() const { return getOperandAs(2); } - Metadata *getRawFile() const { return getOperand(3); } - Metadata *getRawElements() const { return getOperand(4); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIImportedEntityKind; - } -}; - -/// A pair of DIGlobalVariable and DIExpression. -class DIGlobalVariableExpression : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - - DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, - ArrayRef Ops) - : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} - ~DIGlobalVariableExpression() = default; - - static DIGlobalVariableExpression * - getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, - StorageType Storage, bool ShouldCreate = true); - - TempDIGlobalVariableExpression cloneImpl() const { - return getTemporary(getContext(), getVariable(), getExpression()); - } - -public: - DEFINE_MDNODE_GET(DIGlobalVariableExpression, - (Metadata * Variable, Metadata *Expression), - (Variable, Expression)) - - TempDIGlobalVariableExpression clone() const { return cloneImpl(); } - - Metadata *getRawVariable() const { return getOperand(0); } - - DIGlobalVariable *getVariable() const { - return cast_or_null(getRawVariable()); - } - - Metadata *getRawExpression() const { return getOperand(1); } - - DIExpression *getExpression() const { - return cast(getRawExpression()); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIGlobalVariableExpressionKind; - } -}; - -/// Macro Info DWARF-like metadata node. -/// -/// A metadata node with a DWARF macro info (i.e., a constant named -/// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a -/// DIMacroNode -/// because it's potentially used for non-DWARF output. -class DIMacroNode : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - -protected: - DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, - ArrayRef Ops1, ArrayRef Ops2 = None) - : MDNode(C, ID, Storage, Ops1, Ops2) { - assert(MIType < 1u << 16); - SubclassData16 = MIType; - } - ~DIMacroNode() = default; - - template Ty *getOperandAs(unsigned I) const { - return cast_or_null(getOperand(I)); - } - - StringRef getStringOperand(unsigned I) const { - if (auto *S = getOperandAs(I)) - return S->getString(); - return StringRef(); - } - - static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { - if (S.empty()) - return nullptr; - return MDString::get(Context, S); - } - -public: - unsigned getMacinfoType() const { return SubclassData16; } - - static bool classof(const Metadata *MD) { - switch (MD->getMetadataID()) { - default: - return false; - case DIMacroKind: - case DIMacroFileKind: - return true; - } - } -}; - -class DIMacro : public DIMacroNode { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - - DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, - ArrayRef Ops) - : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} - ~DIMacro() = default; - - static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, - StringRef Name, StringRef Value, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), - getCanonicalMDString(Context, Value), Storage, ShouldCreate); - } - static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, - MDString *Name, MDString *Value, StorageType Storage, - bool ShouldCreate = true); - - TempDIMacro cloneImpl() const { - return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), - getValue()); - } - -public: - DEFINE_MDNODE_GET(DIMacro, - (unsigned MIType, unsigned Line, StringRef Name, - StringRef Value = ""), - (MIType, Line, Name, Value)) - DEFINE_MDNODE_GET(DIMacro, - (unsigned MIType, unsigned Line, MDString *Name, - MDString *Value), - (MIType, Line, Name, Value)) - - TempDIMacro clone() const { return cloneImpl(); } - - unsigned getLine() const { return Line; } - - StringRef getName() const { return getStringOperand(0); } - StringRef getValue() const { return getStringOperand(1); } - - MDString *getRawName() const { return getOperandAs(0); } - MDString *getRawValue() const { return getOperandAs(1); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIMacroKind; - } -}; - -class DIMacroFile : public DIMacroNode { - friend class LLVMContextImpl; - friend class MDNode; - - unsigned Line; - - DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, - unsigned Line, ArrayRef Ops) - : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} - ~DIMacroFile() = default; - - static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, - unsigned Line, DIFile *File, - DIMacroNodeArray Elements, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, MIType, Line, static_cast(File), - Elements.get(), Storage, ShouldCreate); - } - - static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, - unsigned Line, Metadata *File, Metadata *Elements, - StorageType Storage, bool ShouldCreate = true); - - TempDIMacroFile cloneImpl() const { - return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), - getElements()); - } - -public: - DEFINE_MDNODE_GET(DIMacroFile, - (unsigned MIType, unsigned Line, DIFile *File, - DIMacroNodeArray Elements), - (MIType, Line, File, Elements)) - DEFINE_MDNODE_GET(DIMacroFile, - (unsigned MIType, unsigned Line, Metadata *File, - Metadata *Elements), - (MIType, Line, File, Elements)) - - TempDIMacroFile clone() const { return cloneImpl(); } - - void replaceElements(DIMacroNodeArray Elements) { -#ifndef NDEBUG - for (DIMacroNode *Op : getElements()) - assert(is_contained(Elements->operands(), Op) && - "Lost a macro node during macro node list replacement"); -#endif - replaceOperandWith(1, Elements.get()); - } - - unsigned getLine() const { return Line; } - DIFile *getFile() const { return cast_or_null(getRawFile()); } - - DIMacroNodeArray getElements() const { - return cast_or_null(getRawElements()); - } - - Metadata *getRawFile() const { return getOperand(0); } - Metadata *getRawElements() const { return getOperand(1); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIMacroFileKind; - } -}; - -/// List of ValueAsMetadata, to be used as an argument to a dbg.value -/// intrinsic. -class DIArgList : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - using iterator = SmallVectorImpl::iterator; - - SmallVector Args; - - DIArgList(LLVMContext &C, StorageType Storage, - ArrayRef Args) - : MDNode(C, DIArgListKind, Storage, None), - Args(Args.begin(), Args.end()) { - track(); - } - ~DIArgList() { untrack(); } - - static DIArgList *getImpl(LLVMContext &Context, - ArrayRef Args, - StorageType Storage, bool ShouldCreate = true); - - TempDIArgList cloneImpl() const { - return getTemporary(getContext(), getArgs()); - } - - void track(); - void untrack(); - void dropAllReferences(); - -public: - DEFINE_MDNODE_GET(DIArgList, (ArrayRef Args), (Args)) - - TempDIArgList clone() const { return cloneImpl(); } - - ArrayRef getArgs() const { return Args; } - - iterator args_begin() { return Args.begin(); } - iterator args_end() { return Args.end(); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIArgListKind; - } - - void handleChangedOperand(void *Ref, Metadata *New); -}; - -/// Identifies a unique instance of a variable. -/// -/// Storage for identifying a potentially inlined instance of a variable, -/// or a fragment thereof. This guarantees that exactly one variable instance -/// may be identified by this class, even when that variable is a fragment of -/// an aggregate variable and/or there is another inlined instance of the same -/// source code variable nearby. -/// This class does not necessarily uniquely identify that variable: it is -/// possible that a DebugVariable with different parameters may point to the -/// same variable instance, but not that one DebugVariable points to multiple -/// variable instances. -class DebugVariable { - using FragmentInfo = DIExpression::FragmentInfo; - - const DILocalVariable *Variable; - Optional Fragment; - const DILocation *InlinedAt; - - /// Fragment that will overlap all other fragments. Used as default when - /// caller demands a fragment. - static const FragmentInfo DefaultFragment; - -public: - DebugVariable(const DILocalVariable *Var, Optional FragmentInfo, - const DILocation *InlinedAt) - : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} - - DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, - const DILocation *InlinedAt) - : Variable(Var), - Fragment(DIExpr ? DIExpr->getFragmentInfo() : NoneType()), - InlinedAt(InlinedAt) {} - - const DILocalVariable *getVariable() const { return Variable; } - Optional getFragment() const { return Fragment; } - const DILocation *getInlinedAt() const { return InlinedAt; } - - FragmentInfo getFragmentOrDefault() const { - return Fragment.getValueOr(DefaultFragment); - } - - static bool isDefaultFragment(const FragmentInfo F) { - return F == DefaultFragment; - } - - bool operator==(const DebugVariable &Other) const { - return std::tie(Variable, Fragment, InlinedAt) == - std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); - } - - bool operator<(const DebugVariable &Other) const { - return std::tie(Variable, Fragment, InlinedAt) < - std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); - } -}; - -template <> struct DenseMapInfo { - using FragmentInfo = DIExpression::FragmentInfo; - - /// Empty key: no key should be generated that has no DILocalVariable. - static inline DebugVariable getEmptyKey() { - return DebugVariable(nullptr, NoneType(), nullptr); - } - - /// Difference in tombstone is that the Optional is meaningful. - static inline DebugVariable getTombstoneKey() { - return DebugVariable(nullptr, {{0, 0}}, nullptr); - } - - static unsigned getHashValue(const DebugVariable &D) { - unsigned HV = 0; - const Optional Fragment = D.getFragment(); - if (Fragment) - HV = DenseMapInfo::getHashValue(*Fragment); - - return hash_combine(D.getVariable(), HV, D.getInlinedAt()); - } - - static bool isEqual(const DebugVariable &A, const DebugVariable &B) { - return A == B; - } -}; - -} // end namespace llvm - -#undef DEFINE_MDNODE_GET_UNPACK_IMPL -#undef DEFINE_MDNODE_GET_UNPACK -#undef DEFINE_MDNODE_GET - -#endif // LLVM_IR_DEBUGINFOMETADATA_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DebugLoc.h b/suite/synctools/tablegen/include/llvm/IR/DebugLoc.h deleted file mode 100644 index 4c48f048d6..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DebugLoc.h +++ /dev/null @@ -1,116 +0,0 @@ -//===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a number of light weight data structures used -// to describe and track debug location information. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DEBUGLOC_H -#define LLVM_IR_DEBUGLOC_H - -#include "llvm/IR/TrackingMDRef.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - - class LLVMContext; - class raw_ostream; - class DILocation; - - /// A debug info location. - /// - /// This class is a wrapper around a tracking reference to an \a DILocation - /// pointer. - /// - /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a - /// one based on relatively opaque \a MDNode pointers. - class DebugLoc { - TrackingMDNodeRef Loc; - - public: - DebugLoc() = default; - - /// Construct from an \a DILocation. - DebugLoc(const DILocation *L); - - /// Construct from an \a MDNode. - /// - /// Note: if \c N is not an \a DILocation, a verifier check will fail, and - /// accessors will crash. However, construction from other nodes is - /// supported in order to handle forward references when reading textual - /// IR. - explicit DebugLoc(const MDNode *N); - - /// Get the underlying \a DILocation. - /// - /// \pre !*this or \c isa(getAsMDNode()). - /// @{ - DILocation *get() const; - operator DILocation *() const { return get(); } - DILocation *operator->() const { return get(); } - DILocation &operator*() const { return *get(); } - /// @} - - /// Check for null. - /// - /// Check for null in a way that is safe with broken debug info. Unlike - /// the conversion to \c DILocation, this doesn't require that \c Loc is of - /// the right type. Important for cases like \a llvm::StripDebugInfo() and - /// \a Instruction::hasMetadata(). - explicit operator bool() const { return Loc; } - - /// Check whether this has a trivial destructor. - bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - - enum { ReplaceLastInlinedAt = true }; - /// Rebuild the entire inlined-at chain for this instruction so that the top of - /// the chain now is inlined-at the new call site. - /// \param InlinedAt The new outermost inlined-at in the chain. - static DebugLoc appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt, - LLVMContext &Ctx, - DenseMap &Cache); - - unsigned getLine() const; - unsigned getCol() const; - MDNode *getScope() const; - DILocation *getInlinedAt() const; - - /// Get the fully inlined-at scope for a DebugLoc. - /// - /// Gets the inlined-at scope for a DebugLoc. - MDNode *getInlinedAtScope() const; - - /// Find the debug info location for the start of the function. - /// - /// Walk up the scope chain of given debug loc and find line number info - /// for the function. - /// - /// FIXME: Remove this. Users should use DILocation/DILocalScope API to - /// find the subprogram, and then DILocation::get(). - DebugLoc getFnDebugLoc() const; - - /// Return \c this as a bar \a MDNode. - MDNode *getAsMDNode() const { return Loc; } - - /// Check if the DebugLoc corresponds to an implicit code. - bool isImplicitCode() const; - void setImplicitCode(bool ImplicitCode); - - bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } - - void dump() const; - - /// prints source location /path/to/file.exe:line:col @[inlined at] - void print(raw_ostream &OS) const; - }; - -} // end namespace llvm - -#endif // LLVM_IR_DEBUGLOC_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DerivedTypes.h b/suite/synctools/tablegen/include/llvm/IR/DerivedTypes.h deleted file mode 100644 index f52ce3cde3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DerivedTypes.h +++ /dev/null @@ -1,742 +0,0 @@ -//===- llvm/DerivedTypes.h - Classes for handling data types ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declarations of classes that represent "derived -// types". These are things like "arrays of x" or "structure of x, y, z" or -// "function returning x taking (y,z) as parameters", etc... -// -// The implementations of these classes live in the Type.cpp file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DERIVEDTYPES_H -#define LLVM_IR_DERIVEDTYPES_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/TypeSize.h" -#include -#include - -namespace llvm { - -class Value; -class APInt; -class LLVMContext; - -/// Class to represent integer types. Note that this class is also used to -/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and -/// Int64Ty. -/// Integer representation type -class IntegerType : public Type { - friend class LLVMContextImpl; - -protected: - explicit IntegerType(LLVMContext &C, unsigned NumBits) : Type(C, IntegerTyID){ - setSubclassData(NumBits); - } - -public: - /// This enum is just used to hold constants we need for IntegerType. - enum { - MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified - MAX_INT_BITS = (1<<23) ///< Maximum number of bits that can be specified - ///< Note that bit width is stored in the Type classes SubclassData field - ///< which has 24 bits. SelectionDAG type legalization can require a - ///< power of 2 IntegerType, so limit to the largest representable power - ///< of 2, 8388608. - }; - - /// This static method is the primary way of constructing an IntegerType. - /// If an IntegerType with the same NumBits value was previously instantiated, - /// that instance will be returned. Otherwise a new one will be created. Only - /// one instance with a given NumBits value is ever created. - /// Get or create an IntegerType instance. - static IntegerType *get(LLVMContext &C, unsigned NumBits); - - /// Returns type twice as wide the input type. - IntegerType *getExtendedType() const { - return Type::getIntNTy(getContext(), 2 * getScalarSizeInBits()); - } - - /// Get the number of bits in this IntegerType - unsigned getBitWidth() const { return getSubclassData(); } - - /// Return a bitmask with ones set for all of the bits that can be set by an - /// unsigned version of this type. This is 0xFF for i8, 0xFFFF for i16, etc. - uint64_t getBitMask() const { - return ~uint64_t(0UL) >> (64-getBitWidth()); - } - - /// Return a uint64_t with just the most significant bit set (the sign bit, if - /// the value is treated as a signed number). - uint64_t getSignBit() const { - return 1ULL << (getBitWidth()-1); - } - - /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. - /// @returns a bit mask with ones set for all the bits of this type. - /// Get a bit mask for this type. - APInt getMask() const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == IntegerTyID; - } -}; - -unsigned Type::getIntegerBitWidth() const { - return cast(this)->getBitWidth(); -} - -/// Class to represent function types -/// -class FunctionType : public Type { - FunctionType(Type *Result, ArrayRef Params, bool IsVarArgs); - -public: - FunctionType(const FunctionType &) = delete; - FunctionType &operator=(const FunctionType &) = delete; - - /// This static method is the primary way of constructing a FunctionType. - static FunctionType *get(Type *Result, - ArrayRef Params, bool isVarArg); - - /// Create a FunctionType taking no parameters. - static FunctionType *get(Type *Result, bool isVarArg); - - /// Return true if the specified type is valid as a return type. - static bool isValidReturnType(Type *RetTy); - - /// Return true if the specified type is valid as an argument type. - static bool isValidArgumentType(Type *ArgTy); - - bool isVarArg() const { return getSubclassData()!=0; } - Type *getReturnType() const { return ContainedTys[0]; } - - using param_iterator = Type::subtype_iterator; - - param_iterator param_begin() const { return ContainedTys + 1; } - param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } - ArrayRef params() const { - return makeArrayRef(param_begin(), param_end()); - } - - /// Parameter type accessors. - Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } - - /// Return the number of fixed parameters this function type requires. - /// This does not consider varargs. - unsigned getNumParams() const { return NumContainedTys - 1; } - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == FunctionTyID; - } -}; -static_assert(alignof(FunctionType) >= alignof(Type *), - "Alignment sufficient for objects appended to FunctionType"); - -bool Type::isFunctionVarArg() const { - return cast(this)->isVarArg(); -} - -Type *Type::getFunctionParamType(unsigned i) const { - return cast(this)->getParamType(i); -} - -unsigned Type::getFunctionNumParams() const { - return cast(this)->getNumParams(); -} - -/// A handy container for a FunctionType+Callee-pointer pair, which can be -/// passed around as a single entity. This assists in replacing the use of -/// PointerType::getElementType() to access the function's type, since that's -/// slated for removal as part of the [opaque pointer types] project. -class FunctionCallee { -public: - // Allow implicit conversion from types which have a getFunctionType member - // (e.g. Function and InlineAsm). - template - FunctionCallee(T *Fn) - : FnTy(Fn ? Fn->getFunctionType() : nullptr), Callee(Fn) {} - - FunctionCallee(FunctionType *FnTy, Value *Callee) - : FnTy(FnTy), Callee(Callee) { - assert((FnTy == nullptr) == (Callee == nullptr)); - } - - FunctionCallee(std::nullptr_t) {} - - FunctionCallee() = default; - - FunctionType *getFunctionType() { return FnTy; } - - Value *getCallee() { return Callee; } - - explicit operator bool() { return Callee; } - -private: - FunctionType *FnTy = nullptr; - Value *Callee = nullptr; -}; - -/// Class to represent struct types. There are two different kinds of struct -/// types: Literal structs and Identified structs. -/// -/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must -/// always have a body when created. You can get one of these by using one of -/// the StructType::get() forms. -/// -/// Identified structs (e.g. %foo or %42) may optionally have a name and are not -/// uniqued. The names for identified structs are managed at the LLVMContext -/// level, so there can only be a single identified struct with a given name in -/// a particular LLVMContext. Identified structs may also optionally be opaque -/// (have no body specified). You get one of these by using one of the -/// StructType::create() forms. -/// -/// Independent of what kind of struct you have, the body of a struct type are -/// laid out in memory consecutively with the elements directly one after the -/// other (if the struct is packed) or (if not packed) with padding between the -/// elements as defined by DataLayout (which is required to match what the code -/// generator for a target expects). -/// -class StructType : public Type { - StructType(LLVMContext &C) : Type(C, StructTyID) {} - - enum { - /// This is the contents of the SubClassData field. - SCDB_HasBody = 1, - SCDB_Packed = 2, - SCDB_IsLiteral = 4, - SCDB_IsSized = 8 - }; - - /// For a named struct that actually has a name, this is a pointer to the - /// symbol table entry (maintained by LLVMContext) for the struct. - /// This is null if the type is an literal struct or if it is a identified - /// type that has an empty name. - void *SymbolTableEntry = nullptr; - -public: - StructType(const StructType &) = delete; - StructType &operator=(const StructType &) = delete; - - /// This creates an identified struct. - static StructType *create(LLVMContext &Context, StringRef Name); - static StructType *create(LLVMContext &Context); - - static StructType *create(ArrayRef Elements, StringRef Name, - bool isPacked = false); - static StructType *create(ArrayRef Elements); - static StructType *create(LLVMContext &Context, ArrayRef Elements, - StringRef Name, bool isPacked = false); - static StructType *create(LLVMContext &Context, ArrayRef Elements); - template - static std::enable_if_t::value, StructType *> - create(StringRef Name, Type *elt1, Tys *... elts) { - assert(elt1 && "Cannot create a struct type with no elements with this"); - return create(ArrayRef({elt1, elts...}), Name); - } - - /// This static method is the primary way to create a literal StructType. - static StructType *get(LLVMContext &Context, ArrayRef Elements, - bool isPacked = false); - - /// Create an empty structure type. - static StructType *get(LLVMContext &Context, bool isPacked = false); - - /// This static method is a convenience method for creating structure types by - /// specifying the elements as arguments. Note that this method always returns - /// a non-packed struct, and requires at least one element type. - template - static std::enable_if_t::value, StructType *> - get(Type *elt1, Tys *... elts) { - assert(elt1 && "Cannot create a struct type with no elements with this"); - LLVMContext &Ctx = elt1->getContext(); - return StructType::get(Ctx, ArrayRef({elt1, elts...})); - } - - /// Return the type with the specified name, or null if there is none by that - /// name. - static StructType *getTypeByName(LLVMContext &C, StringRef Name); - - bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } - - /// Return true if this type is uniqued by structural equivalence, false if it - /// is a struct definition. - bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; } - - /// Return true if this is a type with an identity that has no body specified - /// yet. These prints as 'opaque' in .ll files. - bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } - - /// isSized - Return true if this is a sized type. - bool isSized(SmallPtrSetImpl *Visited = nullptr) const; - - /// Returns true if this struct contains a scalable vector. - bool containsScalableVectorType() const; - - /// Return true if this is a named struct that has a non-empty name. - bool hasName() const { return SymbolTableEntry != nullptr; } - - /// Return the name for this struct type if it has an identity. - /// This may return an empty string for an unnamed struct type. Do not call - /// this on an literal type. - StringRef getName() const; - - /// Change the name of this type to the specified name, or to a name with a - /// suffix if there is a collision. Do not call this on an literal type. - void setName(StringRef Name); - - /// Specify a body for an opaque identified type. - void setBody(ArrayRef Elements, bool isPacked = false); - - template - std::enable_if_t::value, void> - setBody(Type *elt1, Tys *... elts) { - assert(elt1 && "Cannot create a struct type with no elements with this"); - setBody(ArrayRef({elt1, elts...})); - } - - /// Return true if the specified type is valid as a element type. - static bool isValidElementType(Type *ElemTy); - - // Iterator access to the elements. - using element_iterator = Type::subtype_iterator; - - element_iterator element_begin() const { return ContainedTys; } - element_iterator element_end() const { return &ContainedTys[NumContainedTys];} - ArrayRef elements() const { - return makeArrayRef(element_begin(), element_end()); - } - - /// Return true if this is layout identical to the specified struct. - bool isLayoutIdentical(StructType *Other) const; - - /// Random access to the elements - unsigned getNumElements() const { return NumContainedTys; } - Type *getElementType(unsigned N) const { - assert(N < NumContainedTys && "Element number out of range!"); - return ContainedTys[N]; - } - /// Given an index value into the type, return the type of the element. - Type *getTypeAtIndex(const Value *V) const; - Type *getTypeAtIndex(unsigned N) const { return getElementType(N); } - bool indexValid(const Value *V) const; - bool indexValid(unsigned Idx) const { return Idx < getNumElements(); } - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == StructTyID; - } -}; - -StringRef Type::getStructName() const { - return cast(this)->getName(); -} - -unsigned Type::getStructNumElements() const { - return cast(this)->getNumElements(); -} - -Type *Type::getStructElementType(unsigned N) const { - return cast(this)->getElementType(N); -} - -/// Class to represent array types. -class ArrayType : public Type { - /// The element type of the array. - Type *ContainedType; - /// Number of elements in the array. - uint64_t NumElements; - - ArrayType(Type *ElType, uint64_t NumEl); - -public: - ArrayType(const ArrayType &) = delete; - ArrayType &operator=(const ArrayType &) = delete; - - uint64_t getNumElements() const { return NumElements; } - Type *getElementType() const { return ContainedType; } - - /// This static method is the primary way to construct an ArrayType - static ArrayType *get(Type *ElementType, uint64_t NumElements); - - /// Return true if the specified type is valid as a element type. - static bool isValidElementType(Type *ElemTy); - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == ArrayTyID; - } -}; - -uint64_t Type::getArrayNumElements() const { - return cast(this)->getNumElements(); -} - -/// Base class of all SIMD vector types -class VectorType : public Type { - /// A fully specified VectorType is of the form . 'n' is the - /// minimum number of elements of type Ty contained within the vector, and - /// 'vscale x' indicates that the total element count is an integer multiple - /// of 'n', where the multiple is either guaranteed to be one, or is - /// statically unknown at compile time. - /// - /// If the multiple is known to be 1, then the extra term is discarded in - /// textual IR: - /// - /// <4 x i32> - a vector containing 4 i32s - /// - a vector containing an unknown integer multiple - /// of 4 i32s - - /// The element type of the vector. - Type *ContainedType; - -protected: - /// The element quantity of this vector. The meaning of this value depends - /// on the type of vector: - /// - For FixedVectorType = , there are - /// exactly ElementQuantity elements in this vector. - /// - For ScalableVectorType = , - /// there are vscale * ElementQuantity elements in this vector, where - /// vscale is a runtime-constant integer greater than 0. - const unsigned ElementQuantity; - - VectorType(Type *ElType, unsigned EQ, Type::TypeID TID); - -public: - VectorType(const VectorType &) = delete; - VectorType &operator=(const VectorType &) = delete; - - Type *getElementType() const { return ContainedType; } - - /// This static method is the primary way to construct an VectorType. - static VectorType *get(Type *ElementType, ElementCount EC); - - static VectorType *get(Type *ElementType, unsigned NumElements, - bool Scalable) { - return VectorType::get(ElementType, - ElementCount::get(NumElements, Scalable)); - } - - static VectorType *get(Type *ElementType, const VectorType *Other) { - return VectorType::get(ElementType, Other->getElementCount()); - } - - /// This static method gets a VectorType with the same number of elements as - /// the input type, and the element type is an integer type of the same width - /// as the input element type. - static VectorType *getInteger(VectorType *VTy) { - unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); - assert(EltBits && "Element size must be of a non-zero size"); - Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); - return VectorType::get(EltTy, VTy->getElementCount()); - } - - /// This static method is like getInteger except that the element types are - /// twice as wide as the elements in the input type. - static VectorType *getExtendedElementVectorType(VectorType *VTy) { - assert(VTy->isIntOrIntVectorTy() && "VTy expected to be a vector of ints."); - auto *EltTy = cast(VTy->getElementType()); - return VectorType::get(EltTy->getExtendedType(), VTy->getElementCount()); - } - - // This static method gets a VectorType with the same number of elements as - // the input type, and the element type is an integer or float type which - // is half as wide as the elements in the input type. - static VectorType *getTruncatedElementVectorType(VectorType *VTy) { - Type *EltTy; - if (VTy->getElementType()->isFloatingPointTy()) { - switch(VTy->getElementType()->getTypeID()) { - case DoubleTyID: - EltTy = Type::getFloatTy(VTy->getContext()); - break; - case FloatTyID: - EltTy = Type::getHalfTy(VTy->getContext()); - break; - default: - llvm_unreachable("Cannot create narrower fp vector element type"); - } - } else { - unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); - assert((EltBits & 1) == 0 && - "Cannot truncate vector element with odd bit-width"); - EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); - } - return VectorType::get(EltTy, VTy->getElementCount()); - } - - // This static method returns a VectorType with a smaller number of elements - // of a larger type than the input element type. For example, a <16 x i8> - // subdivided twice would return <4 x i32> - static VectorType *getSubdividedVectorType(VectorType *VTy, int NumSubdivs) { - for (int i = 0; i < NumSubdivs; ++i) { - VTy = VectorType::getDoubleElementsVectorType(VTy); - VTy = VectorType::getTruncatedElementVectorType(VTy); - } - return VTy; - } - - /// This static method returns a VectorType with half as many elements as the - /// input type and the same element type. - static VectorType *getHalfElementsVectorType(VectorType *VTy) { - auto EltCnt = VTy->getElementCount(); - assert(EltCnt.isKnownEven() && - "Cannot halve vector with odd number of elements."); - return VectorType::get(VTy->getElementType(), - EltCnt.divideCoefficientBy(2)); - } - - /// This static method returns a VectorType with twice as many elements as the - /// input type and the same element type. - static VectorType *getDoubleElementsVectorType(VectorType *VTy) { - auto EltCnt = VTy->getElementCount(); - assert((EltCnt.getKnownMinValue() * 2ull) <= UINT_MAX && - "Too many elements in vector"); - return VectorType::get(VTy->getElementType(), EltCnt * 2); - } - - /// Return true if the specified type is valid as a element type. - static bool isValidElementType(Type *ElemTy); - - /// Return an ElementCount instance to represent the (possibly scalable) - /// number of elements in the vector. - inline ElementCount getElementCount() const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == FixedVectorTyID || - T->getTypeID() == ScalableVectorTyID; - } -}; - -/// Class to represent fixed width SIMD vectors -class FixedVectorType : public VectorType { -protected: - FixedVectorType(Type *ElTy, unsigned NumElts) - : VectorType(ElTy, NumElts, FixedVectorTyID) {} - -public: - static FixedVectorType *get(Type *ElementType, unsigned NumElts); - - static FixedVectorType *get(Type *ElementType, const FixedVectorType *FVTy) { - return get(ElementType, FVTy->getNumElements()); - } - - static FixedVectorType *getInteger(FixedVectorType *VTy) { - return cast(VectorType::getInteger(VTy)); - } - - static FixedVectorType *getExtendedElementVectorType(FixedVectorType *VTy) { - return cast(VectorType::getExtendedElementVectorType(VTy)); - } - - static FixedVectorType *getTruncatedElementVectorType(FixedVectorType *VTy) { - return cast( - VectorType::getTruncatedElementVectorType(VTy)); - } - - static FixedVectorType *getSubdividedVectorType(FixedVectorType *VTy, - int NumSubdivs) { - return cast( - VectorType::getSubdividedVectorType(VTy, NumSubdivs)); - } - - static FixedVectorType *getHalfElementsVectorType(FixedVectorType *VTy) { - return cast(VectorType::getHalfElementsVectorType(VTy)); - } - - static FixedVectorType *getDoubleElementsVectorType(FixedVectorType *VTy) { - return cast(VectorType::getDoubleElementsVectorType(VTy)); - } - - static bool classof(const Type *T) { - return T->getTypeID() == FixedVectorTyID; - } - - unsigned getNumElements() const { return ElementQuantity; } -}; - -/// Class to represent scalable SIMD vectors -class ScalableVectorType : public VectorType { -protected: - ScalableVectorType(Type *ElTy, unsigned MinNumElts) - : VectorType(ElTy, MinNumElts, ScalableVectorTyID) {} - -public: - static ScalableVectorType *get(Type *ElementType, unsigned MinNumElts); - - static ScalableVectorType *get(Type *ElementType, - const ScalableVectorType *SVTy) { - return get(ElementType, SVTy->getMinNumElements()); - } - - static ScalableVectorType *getInteger(ScalableVectorType *VTy) { - return cast(VectorType::getInteger(VTy)); - } - - static ScalableVectorType * - getExtendedElementVectorType(ScalableVectorType *VTy) { - return cast( - VectorType::getExtendedElementVectorType(VTy)); - } - - static ScalableVectorType * - getTruncatedElementVectorType(ScalableVectorType *VTy) { - return cast( - VectorType::getTruncatedElementVectorType(VTy)); - } - - static ScalableVectorType *getSubdividedVectorType(ScalableVectorType *VTy, - int NumSubdivs) { - return cast( - VectorType::getSubdividedVectorType(VTy, NumSubdivs)); - } - - static ScalableVectorType * - getHalfElementsVectorType(ScalableVectorType *VTy) { - return cast(VectorType::getHalfElementsVectorType(VTy)); - } - - static ScalableVectorType * - getDoubleElementsVectorType(ScalableVectorType *VTy) { - return cast( - VectorType::getDoubleElementsVectorType(VTy)); - } - - /// Get the minimum number of elements in this vector. The actual number of - /// elements in the vector is an integer multiple of this value. - uint64_t getMinNumElements() const { return ElementQuantity; } - - static bool classof(const Type *T) { - return T->getTypeID() == ScalableVectorTyID; - } -}; - -inline ElementCount VectorType::getElementCount() const { - return ElementCount::get(ElementQuantity, isa(this)); -} - -/// Class to represent pointers. -class PointerType : public Type { - explicit PointerType(Type *ElType, unsigned AddrSpace); - explicit PointerType(LLVMContext &C, unsigned AddrSpace); - - Type *PointeeTy; - -public: - PointerType(const PointerType &) = delete; - PointerType &operator=(const PointerType &) = delete; - - /// This constructs a pointer to an object of the specified type in a numbered - /// address space. - static PointerType *get(Type *ElementType, unsigned AddressSpace); - /// This constructs an opaque pointer to an object in a numbered address - /// space. - static PointerType *get(LLVMContext &C, unsigned AddressSpace); - - /// This constructs a pointer to an object of the specified type in the - /// default address space (address space zero). - static PointerType *getUnqual(Type *ElementType) { - return PointerType::get(ElementType, 0); - } - - /// This constructs an opaque pointer to an object in the - /// default address space (address space zero). - static PointerType *getUnqual(LLVMContext &C) { - return PointerType::get(C, 0); - } - - /// This constructs a pointer type with the same pointee type as input - /// PointerType (or opaque pointer is the input PointerType is opaque) and the - /// given address space. This is only useful during the opaque pointer - /// transition. - /// TODO: remove after opaque pointer transition is complete. - static PointerType *getWithSamePointeeType(PointerType *PT, - unsigned AddressSpace) { - if (PT->isOpaque()) - return get(PT->getContext(), AddressSpace); - return get(PT->PointeeTy, AddressSpace); - } - - [[deprecated("Pointer element types are deprecated. You can *temporarily* " - "use Type::getPointerElementType() instead")]] - Type *getElementType() const { - assert(!isOpaque() && "Attempting to get element type of opaque pointer"); - return PointeeTy; - } - - bool isOpaque() const { return !PointeeTy; } - - /// Return true if the specified type is valid as a element type. - static bool isValidElementType(Type *ElemTy); - - /// Return true if we can load or store from a pointer to this type. - static bool isLoadableOrStorableType(Type *ElemTy); - - /// Return the address space of the Pointer type. - inline unsigned getAddressSpace() const { return getSubclassData(); } - - /// Return true if either this is an opaque pointer type or if this pointee - /// type matches Ty. Primarily used for checking if an instruction's pointer - /// operands are valid types. Will be useless after non-opaque pointers are - /// removed. - bool isOpaqueOrPointeeTypeMatches(Type *Ty) { - return isOpaque() || PointeeTy == Ty; - } - - /// Return true if both pointer types have the same element type. Two opaque - /// pointers are considered to have the same element type, while an opaque - /// and a non-opaque pointer have different element types. - /// TODO: Remove after opaque pointer transition is complete. - bool hasSameElementTypeAs(PointerType *Other) { - return PointeeTy == Other->PointeeTy; - } - - /// Implement support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == PointerTyID; - } -}; - -Type *Type::getExtendedType() const { - assert( - isIntOrIntVectorTy() && - "Original type expected to be a vector of integers or a scalar integer."); - if (auto *VTy = dyn_cast(this)) - return VectorType::getExtendedElementVectorType( - const_cast(VTy)); - return cast(this)->getExtendedType(); -} - -Type *Type::getWithNewType(Type *EltTy) const { - if (auto *VTy = dyn_cast(this)) - return VectorType::get(EltTy, VTy->getElementCount()); - return EltTy; -} - -Type *Type::getWithNewBitWidth(unsigned NewBitWidth) const { - assert( - isIntOrIntVectorTy() && - "Original type expected to be a vector of integers or a scalar integer."); - return getWithNewType(getIntNTy(getContext(), NewBitWidth)); -} - -unsigned Type::getPointerAddressSpace() const { - return cast(getScalarType())->getAddressSpace(); -} - -} // end namespace llvm - -#endif // LLVM_IR_DERIVEDTYPES_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DerivedUser.h b/suite/synctools/tablegen/include/llvm/IR/DerivedUser.h deleted file mode 100644 index a25d316c2d..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DerivedUser.h +++ /dev/null @@ -1,44 +0,0 @@ -//===- DerivedUser.h - Base for non-IR Users --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DERIVEDUSER_H -#define LLVM_IR_DERIVEDUSER_H - -#include "llvm/IR/User.h" - -namespace llvm { - -class Type; -class Use; - -/// Extension point for the Value hierarchy. All classes outside of lib/IR -/// that wish to inherit from User should instead inherit from DerivedUser -/// instead. Inheriting from this class is discouraged. -/// -/// Generally speaking, Value is the base of a closed class hierarchy -/// that can't be extended by code outside of lib/IR. This class creates a -/// loophole that allows classes outside of lib/IR to extend User to leverage -/// its use/def list machinery. -class DerivedUser : public User { -protected: - using DeleteValueTy = void (*)(DerivedUser *); - -private: - friend class Value; - - DeleteValueTy DeleteValue; - -public: - DerivedUser(Type *Ty, unsigned VK, Use *U, unsigned NumOps, - DeleteValueTy DeleteValue) - : User(Ty, VK, U, NumOps), DeleteValue(DeleteValue) {} -}; - -} // end namespace llvm - -#endif // LLVM_IR_DERIVEDUSER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DiagnosticHandler.h b/suite/synctools/tablegen/include/llvm/IR/DiagnosticHandler.h deleted file mode 100644 index 5edcc678a3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DiagnosticHandler.h +++ /dev/null @@ -1,74 +0,0 @@ -//===- DiagnosticHandler.h - DiagnosticHandler class for LLVM ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Base DiagnosticHandler class declaration. Derive from this class to provide -// custom diagnostic reporting. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DIAGNOSTICHANDLER_H -#define LLVM_IR_DIAGNOSTICHANDLER_H - -#include "llvm/ADT/StringRef.h" - -namespace llvm { -class DiagnosticInfo; - -/// This is the base class for diagnostic handling in LLVM. -/// The handleDiagnostics method must be overridden by the subclasses to handle -/// diagnostic. The *RemarkEnabled methods can be overridden to control -/// which remarks are enabled. -struct DiagnosticHandler { - void *DiagnosticContext = nullptr; - DiagnosticHandler(void *DiagContext = nullptr) - : DiagnosticContext(DiagContext) {} - virtual ~DiagnosticHandler() = default; - - using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context); - - /// DiagHandlerCallback is settable from the C API and base implementation - /// of DiagnosticHandler will call it from handleDiagnostics(). Any derived - /// class of DiagnosticHandler should not use callback but - /// implement handleDiagnostics(). - DiagnosticHandlerTy DiagHandlerCallback = nullptr; - - /// Override handleDiagnostics to provide custom implementation. - /// Return true if it handles diagnostics reporting properly otherwise - /// return false to make LLVMContext::diagnose() to print the message - /// with a prefix based on the severity. - virtual bool handleDiagnostics(const DiagnosticInfo &DI) { - if (DiagHandlerCallback) { - DiagHandlerCallback(DI, DiagnosticContext); - return true; - } - return false; - } - - /// Return true if analysis remarks are enabled, override - /// to provide different implementation. - virtual bool isAnalysisRemarkEnabled(StringRef PassName) const; - - /// Return true if missed optimization remarks are enabled, override - /// to provide different implementation. - virtual bool isMissedOptRemarkEnabled(StringRef PassName) const; - - /// Return true if passed optimization remarks are enabled, override - /// to provide different implementation. - virtual bool isPassedOptRemarkEnabled(StringRef PassName) const; - - /// Return true if any type of remarks are enabled for this pass. - bool isAnyRemarkEnabled(StringRef PassName) const { - return (isMissedOptRemarkEnabled(PassName) || - isPassedOptRemarkEnabled(PassName) || - isAnalysisRemarkEnabled(PassName)); - } - - /// Return true if any type of remarks are enabled for any pass. - virtual bool isAnyRemarkEnabled() const; -}; -} // namespace llvm - -#endif // LLVM_IR_DIAGNOSTICHANDLER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DiagnosticInfo.h b/suite/synctools/tablegen/include/llvm/IR/DiagnosticInfo.h deleted file mode 100644 index 1ea1d9787d..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DiagnosticInfo.h +++ /dev/null @@ -1,1103 +0,0 @@ -//===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the different classes involved in low level diagnostics. -// -// Diagnostics reporting is still done as part of the LLVMContext. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DIAGNOSTICINFO_H -#define LLVM_IR_DIAGNOSTICINFO_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TypeSize.h" -#include -#include -#include -#include -#include - -namespace llvm { - -// Forward declarations. -class DiagnosticPrinter; -class DIFile; -class DISubprogram; -class CallInst; -class Function; -class Instruction; -class InstructionCost; -class Module; -class Type; -class Value; - -/// Defines the different supported severity of a diagnostic. -enum DiagnosticSeverity : char { - DS_Error, - DS_Warning, - DS_Remark, - // A note attaches additional information to one of the previous diagnostic - // types. - DS_Note -}; - -/// Defines the different supported kind of a diagnostic. -/// This enum should be extended with a new ID for each added concrete subclass. -enum DiagnosticKind { - DK_InlineAsm, - DK_ResourceLimit, - DK_StackSize, - DK_Linker, - DK_Lowering, - DK_DebugMetadataVersion, - DK_DebugMetadataInvalid, - DK_ISelFallback, - DK_SampleProfile, - DK_OptimizationRemark, - DK_OptimizationRemarkMissed, - DK_OptimizationRemarkAnalysis, - DK_OptimizationRemarkAnalysisFPCommute, - DK_OptimizationRemarkAnalysisAliasing, - DK_OptimizationFailure, - DK_FirstRemark = DK_OptimizationRemark, - DK_LastRemark = DK_OptimizationFailure, - DK_MachineOptimizationRemark, - DK_MachineOptimizationRemarkMissed, - DK_MachineOptimizationRemarkAnalysis, - DK_FirstMachineRemark = DK_MachineOptimizationRemark, - DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis, - DK_MIRParser, - DK_PGOProfile, - DK_Unsupported, - DK_SrcMgr, - DK_DontCall, - DK_FirstPluginKind // Must be last value to work with - // getNextAvailablePluginDiagnosticKind -}; - -/// Get the next available kind ID for a plugin diagnostic. -/// Each time this function is called, it returns a different number. -/// Therefore, a plugin that wants to "identify" its own classes -/// with a dynamic identifier, just have to use this method to get a new ID -/// and assign it to each of its classes. -/// The returned ID will be greater than or equal to DK_FirstPluginKind. -/// Thus, the plugin identifiers will not conflict with the -/// DiagnosticKind values. -int getNextAvailablePluginDiagnosticKind(); - -/// This is the base abstract class for diagnostic reporting in -/// the backend. -/// The print method must be overloaded by the subclasses to print a -/// user-friendly message in the client of the backend (let us call it a -/// frontend). -class DiagnosticInfo { -private: - /// Kind defines the kind of report this is about. - const /* DiagnosticKind */ int Kind; - /// Severity gives the severity of the diagnostic. - const DiagnosticSeverity Severity; - - virtual void anchor(); -public: - DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity) - : Kind(Kind), Severity(Severity) {} - - virtual ~DiagnosticInfo() = default; - - /* DiagnosticKind */ int getKind() const { return Kind; } - DiagnosticSeverity getSeverity() const { return Severity; } - - /// Print using the given \p DP a user-friendly message. - /// This is the default message that will be printed to the user. - /// It is used when the frontend does not directly take advantage - /// of the information contained in fields of the subclasses. - /// The printed message must not end with '.' nor start with a severity - /// keyword. - virtual void print(DiagnosticPrinter &DP) const = 0; -}; - -using DiagnosticHandlerFunction = std::function; - -/// Diagnostic information for inline asm reporting. -/// This is basically a message and an optional location. -class DiagnosticInfoInlineAsm : public DiagnosticInfo { -private: - /// Optional line information. 0 if not set. - uint64_t LocCookie = 0; - /// Message to be reported. - const Twine &MsgStr; - /// Optional origin of the problem. - const Instruction *Instr = nullptr; - -public: - /// \p MsgStr is the message to be reported to the frontend. - /// This class does not copy \p MsgStr, therefore the reference must be valid - /// for the whole life time of the Diagnostic. - DiagnosticInfoInlineAsm(const Twine &MsgStr, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {} - - /// \p LocCookie if non-zero gives the line number for this report. - /// \p MsgStr gives the message. - /// This class does not copy \p MsgStr, therefore the reference must be valid - /// for the whole life time of the Diagnostic. - DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), - MsgStr(MsgStr) {} - - /// \p Instr gives the original instruction that triggered the diagnostic. - /// \p MsgStr gives the message. - /// This class does not copy \p MsgStr, therefore the reference must be valid - /// for the whole life time of the Diagnostic. - /// Same for \p I. - DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, - DiagnosticSeverity Severity = DS_Error); - - uint64_t getLocCookie() const { return LocCookie; } - const Twine &getMsgStr() const { return MsgStr; } - const Instruction *getInstruction() const { return Instr; } - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_InlineAsm; - } -}; - -/// Diagnostic information for stack size etc. reporting. -/// This is basically a function and a size. -class DiagnosticInfoResourceLimit : public DiagnosticInfo { -private: - /// The function that is concerned by this resource limit diagnostic. - const Function &Fn; - - /// Description of the resource type (e.g. stack size) - const char *ResourceName; - - /// The computed size usage - uint64_t ResourceSize; - - // Threshould passed - uint64_t ResourceLimit; - -public: - /// \p The function that is concerned by this stack size diagnostic. - /// \p The computed stack size. - DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName, - uint64_t ResourceSize, uint64_t ResourceLimit, - DiagnosticSeverity Severity = DS_Warning, - DiagnosticKind Kind = DK_ResourceLimit) - : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName), - ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {} - - const Function &getFunction() const { return Fn; } - const char *getResourceName() const { return ResourceName; } - uint64_t getResourceSize() const { return ResourceSize; } - uint64_t getResourceLimit() const { return ResourceLimit; } - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize; - } -}; - -class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit { - void anchor() override; -public: - DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize, - uint64_t StackLimit, - DiagnosticSeverity Severity = DS_Warning) - : DiagnosticInfoResourceLimit(Fn, "stack frame size", StackSize, - StackLimit, Severity, DK_StackSize) {} - - uint64_t getStackSize() const { return getResourceSize(); } - uint64_t getStackLimit() const { return getResourceLimit(); } - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_StackSize; - } -}; - -/// Diagnostic information for debug metadata version reporting. -/// This is basically a module and a version. -class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo { -private: - /// The module that is concerned by this debug metadata version diagnostic. - const Module &M; - /// The actual metadata version. - unsigned MetadataVersion; - -public: - /// \p The module that is concerned by this debug metadata version diagnostic. - /// \p The actual metadata version. - DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion, - DiagnosticSeverity Severity = DS_Warning) - : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M), - MetadataVersion(MetadataVersion) {} - - const Module &getModule() const { return M; } - unsigned getMetadataVersion() const { return MetadataVersion; } - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_DebugMetadataVersion; - } -}; - -/// Diagnostic information for stripping invalid debug metadata. -class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo { -private: - /// The module that is concerned by this debug metadata version diagnostic. - const Module &M; - -public: - /// \p The module that is concerned by this debug metadata version diagnostic. - DiagnosticInfoIgnoringInvalidDebugMetadata( - const Module &M, DiagnosticSeverity Severity = DS_Warning) - : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {} - - const Module &getModule() const { return M; } - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_DebugMetadataInvalid; - } -}; - -/// Diagnostic information for the sample profiler. -class DiagnosticInfoSampleProfile : public DiagnosticInfo { -public: - DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum, - const Twine &Msg, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), - LineNum(LineNum), Msg(Msg) {} - DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), - Msg(Msg) {} - DiagnosticInfoSampleProfile(const Twine &Msg, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {} - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_SampleProfile; - } - - StringRef getFileName() const { return FileName; } - unsigned getLineNum() const { return LineNum; } - const Twine &getMsg() const { return Msg; } - -private: - /// Name of the input file associated with this diagnostic. - StringRef FileName; - - /// Line number where the diagnostic occurred. If 0, no line number will - /// be emitted in the message. - unsigned LineNum = 0; - - /// Message to report. - const Twine &Msg; -}; - -/// Diagnostic information for the PGO profiler. -class DiagnosticInfoPGOProfile : public DiagnosticInfo { -public: - DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {} - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_PGOProfile; - } - - const char *getFileName() const { return FileName; } - const Twine &getMsg() const { return Msg; } - -private: - /// Name of the input file associated with this diagnostic. - const char *FileName; - - /// Message to report. - const Twine &Msg; -}; - -class DiagnosticLocation { - DIFile *File = nullptr; - unsigned Line = 0; - unsigned Column = 0; - -public: - DiagnosticLocation() = default; - DiagnosticLocation(const DebugLoc &DL); - DiagnosticLocation(const DISubprogram *SP); - - bool isValid() const { return File; } - /// Return the full path to the file. - std::string getAbsolutePath() const; - /// Return the file name relative to the compilation directory. - StringRef getRelativePath() const; - unsigned getLine() const { return Line; } - unsigned getColumn() const { return Column; } -}; - -/// Common features for diagnostics with an associated location. -class DiagnosticInfoWithLocationBase : public DiagnosticInfo { - void anchor() override; -public: - /// \p Fn is the function where the diagnostic is being emitted. \p Loc is - /// the location information to use in the diagnostic. - DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind, - enum DiagnosticSeverity Severity, - const Function &Fn, - const DiagnosticLocation &Loc) - : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {} - - /// Return true if location information is available for this diagnostic. - bool isLocationAvailable() const { return Loc.isValid(); } - - /// Return a string with the location information for this diagnostic - /// in the format "file:line:col". If location information is not available, - /// it returns ":0:0". - std::string getLocationStr() const; - - /// Return location information for this diagnostic in three parts: - /// the relative source file path, line number and column. - void getLocation(StringRef &RelativePath, unsigned &Line, - unsigned &Column) const; - - /// Return the absolute path tot the file. - std::string getAbsolutePath() const; - - const Function &getFunction() const { return Fn; } - DiagnosticLocation getLocation() const { return Loc; } - -private: - /// Function where this diagnostic is triggered. - const Function &Fn; - - /// Debug location where this diagnostic is triggered. - DiagnosticLocation Loc; -}; - -/// Common features for diagnostics dealing with optimization remarks -/// that are used by both IR and MIR passes. -class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase { -public: - /// Used to set IsVerbose via the stream interface. - struct setIsVerbose {}; - - /// When an instance of this is inserted into the stream, the arguments - /// following will not appear in the remark printed in the compiler output - /// (-Rpass) but only in the optimization record file - /// (-fsave-optimization-record). - struct setExtraArgs {}; - - /// Used in the streaming interface as the general argument type. It - /// internally converts everything into a key-value pair. - struct Argument { - std::string Key; - std::string Val; - // If set, the debug location corresponding to the value. - DiagnosticLocation Loc; - - explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {} - Argument(StringRef Key, const Value *V); - Argument(StringRef Key, const Type *T); - Argument(StringRef Key, StringRef S); - Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {}; - Argument(StringRef Key, int N); - Argument(StringRef Key, float N); - Argument(StringRef Key, long N); - Argument(StringRef Key, long long N); - Argument(StringRef Key, unsigned N); - Argument(StringRef Key, unsigned long N); - Argument(StringRef Key, unsigned long long N); - Argument(StringRef Key, ElementCount EC); - Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {} - Argument(StringRef Key, DebugLoc dl); - Argument(StringRef Key, InstructionCost C); - }; - - /// \p PassName is the name of the pass emitting this diagnostic. \p - /// RemarkName is a textual identifier for the remark (single-word, - /// camel-case). \p Fn is the function where the diagnostic is being emitted. - /// \p Loc is the location information to use in the diagnostic. If line table - /// information is available, the diagnostic will include the source code - /// location. - DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind, - enum DiagnosticSeverity Severity, - const char *PassName, StringRef RemarkName, - const Function &Fn, - const DiagnosticLocation &Loc) - : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc), - PassName(PassName), RemarkName(RemarkName) {} - - void insert(StringRef S); - void insert(Argument A); - void insert(setIsVerbose V); - void insert(setExtraArgs EA); - - /// \see DiagnosticInfo::print. - void print(DiagnosticPrinter &DP) const override; - - /// Return true if this optimization remark is enabled by one of - /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, - /// or -pass-remarks-analysis). Note that this only handles the LLVM - /// flags. We cannot access Clang flags from here (they are handled - /// in BackendConsumer::OptimizationRemarkHandler). - virtual bool isEnabled() const = 0; - - StringRef getPassName() const { return PassName; } - StringRef getRemarkName() const { return RemarkName; } - std::string getMsg() const; - Optional getHotness() const { return Hotness; } - void setHotness(Optional H) { Hotness = H; } - - bool isVerbose() const { return IsVerbose; } - - ArrayRef getArgs() const { return Args; } - - static bool classof(const DiagnosticInfo *DI) { - return (DI->getKind() >= DK_FirstRemark && - DI->getKind() <= DK_LastRemark) || - (DI->getKind() >= DK_FirstMachineRemark && - DI->getKind() <= DK_LastMachineRemark); - } - - bool isPassed() const { - return (getKind() == DK_OptimizationRemark || - getKind() == DK_MachineOptimizationRemark); - } - - bool isMissed() const { - return (getKind() == DK_OptimizationRemarkMissed || - getKind() == DK_MachineOptimizationRemarkMissed); - } - - bool isAnalysis() const { - return (getKind() == DK_OptimizationRemarkAnalysis || - getKind() == DK_MachineOptimizationRemarkAnalysis); - } - -protected: - /// Name of the pass that triggers this report. If this matches the - /// regular expression given in -Rpass=regexp, then the remark will - /// be emitted. - const char *PassName; - - /// Textual identifier for the remark (single-word, camel-case). Can be used - /// by external tools reading the output file for optimization remarks to - /// identify the remark. - StringRef RemarkName; - - /// If profile information is available, this is the number of times the - /// corresponding code was executed in a profile instrumentation run. - Optional Hotness; - - /// Arguments collected via the streaming interface. - SmallVector Args; - - /// The remark is expected to be noisy. - bool IsVerbose = false; - - /// If positive, the index of the first argument that only appear in - /// the optimization records and not in the remark printed in the compiler - /// output. - int FirstExtraArgIndex = -1; -}; - -/// Allow the insertion operator to return the actual remark type rather than a -/// common base class. This allows returning the result of the insertion -/// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah". -template -RemarkT & -operator<<(RemarkT &R, - std::enable_if_t< - std::is_base_of::value, - StringRef> - S) { - R.insert(S); - return R; -} - -/// Also allow r-value for the remark to allow insertion into a -/// temporarily-constructed remark. -template -RemarkT & -operator<<(RemarkT &&R, - std::enable_if_t< - std::is_base_of::value, - StringRef> - S) { - R.insert(S); - return R; -} - -template -RemarkT & -operator<<(RemarkT &R, - std::enable_if_t< - std::is_base_of::value, - DiagnosticInfoOptimizationBase::Argument> - A) { - R.insert(A); - return R; -} - -template -RemarkT & -operator<<(RemarkT &&R, - std::enable_if_t< - std::is_base_of::value, - DiagnosticInfoOptimizationBase::Argument> - A) { - R.insert(A); - return R; -} - -template -RemarkT & -operator<<(RemarkT &R, - std::enable_if_t< - std::is_base_of::value, - DiagnosticInfoOptimizationBase::setIsVerbose> - V) { - R.insert(V); - return R; -} - -template -RemarkT & -operator<<(RemarkT &&R, - std::enable_if_t< - std::is_base_of::value, - DiagnosticInfoOptimizationBase::setIsVerbose> - V) { - R.insert(V); - return R; -} - -template -RemarkT & -operator<<(RemarkT &R, - std::enable_if_t< - std::is_base_of::value, - DiagnosticInfoOptimizationBase::setExtraArgs> - EA) { - R.insert(EA); - return R; -} - -/// Common features for diagnostics dealing with optimization remarks -/// that are used by IR passes. -class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase { - void anchor() override; -public: - /// \p PassName is the name of the pass emitting this diagnostic. \p - /// RemarkName is a textual identifier for the remark (single-word, - /// camel-case). \p Fn is the function where the diagnostic is being emitted. - /// \p Loc is the location information to use in the diagnostic. If line table - /// information is available, the diagnostic will include the source code - /// location. \p CodeRegion is IR value (currently basic block) that the - /// optimization operates on. This is currently used to provide run-time - /// hotness information with PGO. - DiagnosticInfoIROptimization(enum DiagnosticKind Kind, - enum DiagnosticSeverity Severity, - const char *PassName, StringRef RemarkName, - const Function &Fn, - const DiagnosticLocation &Loc, - const Value *CodeRegion = nullptr) - : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn, - Loc), - CodeRegion(CodeRegion) {} - - /// This is ctor variant allows a pass to build an optimization remark - /// from an existing remark. - /// - /// This is useful when a transformation pass (e.g LV) wants to emit a remark - /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis - /// remark. The string \p Prepend will be emitted before the original - /// message. - DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend, - const DiagnosticInfoIROptimization &Orig) - : DiagnosticInfoOptimizationBase( - (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName, - Orig.RemarkName, Orig.getFunction(), Orig.getLocation()), - CodeRegion(Orig.getCodeRegion()) { - *this << Prepend; - std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args)); - } - - /// Legacy interface. - /// \p PassName is the name of the pass emitting this diagnostic. - /// \p Fn is the function where the diagnostic is being emitted. \p Loc is - /// the location information to use in the diagnostic. If line table - /// information is available, the diagnostic will include the source code - /// location. \p Msg is the message to show. Note that this class does not - /// copy this message, so this reference must be valid for the whole life time - /// of the diagnostic. - DiagnosticInfoIROptimization(enum DiagnosticKind Kind, - enum DiagnosticSeverity Severity, - const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, const Twine &Msg) - : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) { - *this << Msg.str(); - } - - const Value *getCodeRegion() const { return CodeRegion; } - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark; - } - -private: - /// The IR value (currently basic block) that the optimization operates on. - /// This is currently used to provide run-time hotness information with PGO. - const Value *CodeRegion = nullptr; -}; - -/// Diagnostic information for applied optimization remarks. -class OptimizationRemark : public DiagnosticInfoIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass=, then the diagnostic will - /// be emitted. \p RemarkName is a textual identifier for the remark (single- - /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the - /// region that the optimization operates on (currently only block is - /// supported). - OptimizationRemark(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, const Value *CodeRegion); - - /// Same as above, but the debug location and code region are derived from \p - /// Instr. - OptimizationRemark(const char *PassName, StringRef RemarkName, - const Instruction *Inst); - - /// Same as above, but the debug location and code region are derived from \p - /// Func. - OptimizationRemark(const char *PassName, StringRef RemarkName, - const Function *Func); - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationRemark; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override; - -private: - /// This is deprecated now and only used by the function API below. - /// \p PassName is the name of the pass emitting this diagnostic. If - /// this name matches the regular expression given in -Rpass=, then the - /// diagnostic will be emitted. \p Fn is the function where the diagnostic - /// is being emitted. \p Loc is the location information to use in the - /// diagnostic. If line table information is available, the diagnostic - /// will include the source code location. \p Msg is the message to show. - /// Note that this class does not copy this message, so this reference - /// must be valid for the whole life time of the diagnostic. - OptimizationRemark(const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, const Twine &Msg) - : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, - Fn, Loc, Msg) {} -}; - -/// Diagnostic information for missed-optimization remarks. -class OptimizationRemarkMissed : public DiagnosticInfoIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-missed=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark (single-word, camel-case). \p Loc is the debug location and \p - /// CodeRegion is the region that the optimization operates on (currently only - /// block is supported). - OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion); - - /// Same as above but \p Inst is used to derive code region and debug - /// location. - OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, - const Instruction *Inst); - - /// Same as above but \p F is used to derive code region and debug - /// location. - OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, - const Function *F); - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationRemarkMissed; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override; - -private: - /// This is deprecated now and only used by the function API below. - /// \p PassName is the name of the pass emitting this diagnostic. If - /// this name matches the regular expression given in -Rpass-missed=, then the - /// diagnostic will be emitted. \p Fn is the function where the diagnostic - /// is being emitted. \p Loc is the location information to use in the - /// diagnostic. If line table information is available, the diagnostic - /// will include the source code location. \p Msg is the message to show. - /// Note that this class does not copy this message, so this reference - /// must be valid for the whole life time of the diagnostic. - OptimizationRemarkMissed(const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, const Twine &Msg) - : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, - PassName, Fn, Loc, Msg) {} -}; - -/// Diagnostic information for optimization analysis remarks. -class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization { -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-analysis=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark (single-word, camel-case). \p Loc is the debug location and \p - /// CodeRegion is the region that the optimization operates on (currently only - /// block is supported). - OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion); - - /// This is ctor variant allows a pass to build an optimization remark - /// from an existing remark. - /// - /// This is useful when a transformation pass (e.g LV) wants to emit a remark - /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis - /// remark. The string \p Prepend will be emitted before the original - /// message. - OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend, - const OptimizationRemarkAnalysis &Orig) - : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {} - - /// Same as above but \p Inst is used to derive code region and debug - /// location. - OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, - const Instruction *Inst); - - /// Same as above but \p F is used to derive code region and debug - /// location. - OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, - const Function *F); - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationRemarkAnalysis; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override; - - static const char *AlwaysPrint; - - bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; } - -protected: - OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, - const Function &Fn, const DiagnosticLocation &Loc, - const Twine &Msg) - : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {} - - OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, - StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion); - -private: - /// This is deprecated now and only used by the function API below. - /// \p PassName is the name of the pass emitting this diagnostic. If - /// this name matches the regular expression given in -Rpass-analysis=, then - /// the diagnostic will be emitted. \p Fn is the function where the diagnostic - /// is being emitted. \p Loc is the location information to use in the - /// diagnostic. If line table information is available, the diagnostic will - /// include the source code location. \p Msg is the message to show. Note that - /// this class does not copy this message, so this reference must be valid for - /// the whole life time of the diagnostic. - OptimizationRemarkAnalysis(const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, const Twine &Msg) - : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, - PassName, Fn, Loc, Msg) {} -}; - -/// Diagnostic information for optimization analysis remarks related to -/// floating-point non-commutativity. -class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis { - void anchor() override; -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-analysis=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark (single-word, camel-case). \p Loc is the debug location and \p - /// CodeRegion is the region that the optimization operates on (currently only - /// block is supported). The front-end will append its own message related to - /// options that address floating-point non-commutativity. - OptimizationRemarkAnalysisFPCommute(const char *PassName, - StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion) - : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, - PassName, RemarkName, Loc, CodeRegion) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute; - } - -private: - /// This is deprecated now and only used by the function API below. - /// \p PassName is the name of the pass emitting this diagnostic. If - /// this name matches the regular expression given in -Rpass-analysis=, then - /// the diagnostic will be emitted. \p Fn is the function where the diagnostic - /// is being emitted. \p Loc is the location information to use in the - /// diagnostic. If line table information is available, the diagnostic will - /// include the source code location. \p Msg is the message to show. The - /// front-end will append its own message related to options that address - /// floating-point non-commutativity. Note that this class does not copy this - /// message, so this reference must be valid for the whole life time of the - /// diagnostic. - OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, - const Twine &Msg) - : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, - PassName, Fn, Loc, Msg) {} -}; - -/// Diagnostic information for optimization analysis remarks related to -/// pointer aliasing. -class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis { - void anchor() override; -public: - /// \p PassName is the name of the pass emitting this diagnostic. If this name - /// matches the regular expression given in -Rpass-analysis=, then the - /// diagnostic will be emitted. \p RemarkName is a textual identifier for the - /// remark (single-word, camel-case). \p Loc is the debug location and \p - /// CodeRegion is the region that the optimization operates on (currently only - /// block is supported). The front-end will append its own message related to - /// options that address pointer aliasing legality. - OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion) - : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, - PassName, RemarkName, Loc, CodeRegion) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing; - } - -private: - /// This is deprecated now and only used by the function API below. - /// \p PassName is the name of the pass emitting this diagnostic. If - /// this name matches the regular expression given in -Rpass-analysis=, then - /// the diagnostic will be emitted. \p Fn is the function where the diagnostic - /// is being emitted. \p Loc is the location information to use in the - /// diagnostic. If line table information is available, the diagnostic will - /// include the source code location. \p Msg is the message to show. The - /// front-end will append its own message related to options that address - /// pointer aliasing legality. Note that this class does not copy this - /// message, so this reference must be valid for the whole life time of the - /// diagnostic. - OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn, - const DiagnosticLocation &Loc, - const Twine &Msg) - : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, - PassName, Fn, Loc, Msg) {} -}; - -/// Diagnostic information for machine IR parser. -// FIXME: Remove this, use DiagnosticInfoSrcMgr instead. -class DiagnosticInfoMIRParser : public DiagnosticInfo { - const SMDiagnostic &Diagnostic; - -public: - DiagnosticInfoMIRParser(DiagnosticSeverity Severity, - const SMDiagnostic &Diagnostic) - : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {} - - const SMDiagnostic &getDiagnostic() const { return Diagnostic; } - - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_MIRParser; - } -}; - -/// Diagnostic information for ISel fallback path. -class DiagnosticInfoISelFallback : public DiagnosticInfo { - /// The function that is concerned by this diagnostic. - const Function &Fn; - -public: - DiagnosticInfoISelFallback(const Function &Fn, - DiagnosticSeverity Severity = DS_Warning) - : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {} - - const Function &getFunction() const { return Fn; } - - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_ISelFallback; - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) - -/// Diagnostic information for optimization failures. -class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization { -public: - /// \p Fn is the function where the diagnostic is being emitted. \p Loc is - /// the location information to use in the diagnostic. If line table - /// information is available, the diagnostic will include the source code - /// location. \p Msg is the message to show. Note that this class does not - /// copy this message, so this reference must be valid for the whole life time - /// of the diagnostic. - DiagnosticInfoOptimizationFailure(const Function &Fn, - const DiagnosticLocation &Loc, - const Twine &Msg) - : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, - nullptr, Fn, Loc, Msg) {} - - /// \p PassName is the name of the pass emitting this diagnostic. \p - /// RemarkName is a textual identifier for the remark (single-word, - /// camel-case). \p Loc is the debug location and \p CodeRegion is the - /// region that the optimization operates on (currently basic block is - /// supported). - DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName, - const DiagnosticLocation &Loc, - const Value *CodeRegion); - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_OptimizationFailure; - } - - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override; -}; - -/// Diagnostic information for unsupported feature in backend. -class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase { -private: - Twine Msg; - -public: - /// \p Fn is the function where the diagnostic is being emitted. \p Loc is - /// the location information to use in the diagnostic. If line table - /// information is available, the diagnostic will include the source code - /// location. \p Msg is the message to show. Note that this class does not - /// copy this message, so this reference must be valid for the whole life time - /// of the diagnostic. - DiagnosticInfoUnsupported( - const Function &Fn, const Twine &Msg, - const DiagnosticLocation &Loc = DiagnosticLocation(), - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc), - Msg(Msg) {} - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_Unsupported; - } - - const Twine &getMessage() const { return Msg; } - - void print(DiagnosticPrinter &DP) const override; -}; - -static DiagnosticSeverity getDiagnosticSeverity(SourceMgr::DiagKind DK) { - switch (DK) { - case llvm::SourceMgr::DK_Error: - return DS_Error; - break; - case llvm::SourceMgr::DK_Warning: - return DS_Warning; - break; - case llvm::SourceMgr::DK_Note: - return DS_Note; - break; - case llvm::SourceMgr::DK_Remark: - return DS_Remark; - break; - } - llvm_unreachable("unknown SourceMgr::DiagKind"); -} - -/// Diagnostic information for SMDiagnostic reporting. -class DiagnosticInfoSrcMgr : public DiagnosticInfo { - const SMDiagnostic &Diagnostic; - StringRef ModName; - - // For inlineasm !srcloc translation. - bool InlineAsmDiag; - unsigned LocCookie; - -public: - DiagnosticInfoSrcMgr(const SMDiagnostic &Diagnostic, StringRef ModName, - bool InlineAsmDiag = true, unsigned LocCookie = 0) - : DiagnosticInfo(DK_SrcMgr, getDiagnosticSeverity(Diagnostic.getKind())), - Diagnostic(Diagnostic), ModName(ModName), InlineAsmDiag(InlineAsmDiag), - LocCookie(LocCookie) {} - - StringRef getModuleName() const { return ModName; } - bool isInlineAsmDiag() const { return InlineAsmDiag; } - const SMDiagnostic &getSMDiag() const { return Diagnostic; } - unsigned getLocCookie() const { return LocCookie; } - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_SrcMgr; - } -}; - -void diagnoseDontCall(const CallInst &CI); - -class DiagnosticInfoDontCall : public DiagnosticInfo { - StringRef CalleeName; - StringRef Note; - unsigned LocCookie; - -public: - DiagnosticInfoDontCall(StringRef CalleeName, StringRef Note, - DiagnosticSeverity DS, unsigned LocCookie) - : DiagnosticInfo(DK_DontCall, DS), CalleeName(CalleeName), Note(Note), - LocCookie(LocCookie) {} - StringRef getFunctionName() const { return CalleeName; } - StringRef getNote() const { return Note; } - unsigned getLocCookie() const { return LocCookie; } - void print(DiagnosticPrinter &DP) const override; - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == DK_DontCall; - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_DIAGNOSTICINFO_H diff --git a/suite/synctools/tablegen/include/llvm/IR/DiagnosticPrinter.h b/suite/synctools/tablegen/include/llvm/IR/DiagnosticPrinter.h deleted file mode 100644 index 2df6fc3dfe..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/DiagnosticPrinter.h +++ /dev/null @@ -1,95 +0,0 @@ -//===- llvm/IR/DiagnosticPrinter.h - Diagnostic Printer ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the main interface for printer backend diagnostic. -// -// Clients of the backend diagnostics should overload this interface based -// on their needs. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DIAGNOSTICPRINTER_H -#define LLVM_IR_DIAGNOSTICPRINTER_H - -#include - -namespace llvm { - -// Forward declarations. -class Module; -class raw_ostream; -class SMDiagnostic; -class StringRef; -class Twine; -class Value; - -/// Interface for custom diagnostic printing. -class DiagnosticPrinter { -public: - virtual ~DiagnosticPrinter() = default; - - // Simple types. - virtual DiagnosticPrinter &operator<<(char C) = 0; - virtual DiagnosticPrinter &operator<<(unsigned char C) = 0; - virtual DiagnosticPrinter &operator<<(signed char C) = 0; - virtual DiagnosticPrinter &operator<<(StringRef Str) = 0; - virtual DiagnosticPrinter &operator<<(const char *Str) = 0; - virtual DiagnosticPrinter &operator<<(const std::string &Str) = 0; - virtual DiagnosticPrinter &operator<<(unsigned long N) = 0; - virtual DiagnosticPrinter &operator<<(long N) = 0; - virtual DiagnosticPrinter &operator<<(unsigned long long N) = 0; - virtual DiagnosticPrinter &operator<<(long long N) = 0; - virtual DiagnosticPrinter &operator<<(const void *P) = 0; - virtual DiagnosticPrinter &operator<<(unsigned int N) = 0; - virtual DiagnosticPrinter &operator<<(int N) = 0; - virtual DiagnosticPrinter &operator<<(double N) = 0; - virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0; - - // IR related types. - virtual DiagnosticPrinter &operator<<(const Value &V) = 0; - virtual DiagnosticPrinter &operator<<(const Module &M) = 0; - - // Other types. - virtual DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) = 0; -}; - -/// Basic diagnostic printer that uses an underlying raw_ostream. -class DiagnosticPrinterRawOStream : public DiagnosticPrinter { -protected: - raw_ostream &Stream; - -public: - DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {} - - // Simple types. - DiagnosticPrinter &operator<<(char C) override; - DiagnosticPrinter &operator<<(unsigned char C) override; - DiagnosticPrinter &operator<<(signed char C) override; - DiagnosticPrinter &operator<<(StringRef Str) override; - DiagnosticPrinter &operator<<(const char *Str) override; - DiagnosticPrinter &operator<<(const std::string &Str) override; - DiagnosticPrinter &operator<<(unsigned long N) override; - DiagnosticPrinter &operator<<(long N) override; - DiagnosticPrinter &operator<<(unsigned long long N) override; - DiagnosticPrinter &operator<<(long long N) override; - DiagnosticPrinter &operator<<(const void *P) override; - DiagnosticPrinter &operator<<(unsigned int N) override; - DiagnosticPrinter &operator<<(int N) override; - DiagnosticPrinter &operator<<(double N) override; - DiagnosticPrinter &operator<<(const Twine &Str) override; - - // IR related types. - DiagnosticPrinter &operator<<(const Value &V) override; - DiagnosticPrinter &operator<<(const Module &M) override; - - // Other types. - DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) override; -}; - -} // end namespace llvm - -#endif // LLVM_IR_DIAGNOSTICPRINTER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Dominators.h b/suite/synctools/tablegen/include/llvm/IR/Dominators.h deleted file mode 100644 index d13a5856df..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Dominators.h +++ /dev/null @@ -1,323 +0,0 @@ -//===- Dominators.h - Dominator Info Calculation ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the DominatorTree class, which provides fast and efficient -// dominance queries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DOMINATORS_H -#define LLVM_IR_DOMINATORS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Use.h" -#include "llvm/Pass.h" -#include "llvm/Support/CFGDiff.h" -#include "llvm/Support/CFGUpdate.h" -#include "llvm/Support/GenericDomTree.h" -#include "llvm/Support/GenericDomTreeConstruction.h" -#include -#include - -namespace llvm { - -class Function; -class Instruction; -class Module; -class Value; -class raw_ostream; -template struct GraphTraits; - -extern template class DomTreeNodeBase; -extern template class DominatorTreeBase; // DomTree -extern template class DominatorTreeBase; // PostDomTree - -extern template class cfg::Update; - -namespace DomTreeBuilder { -using BBDomTree = DomTreeBase; -using BBPostDomTree = PostDomTreeBase; - -using BBUpdates = ArrayRef>; - -using BBDomTreeGraphDiff = GraphDiff; -using BBPostDomTreeGraphDiff = GraphDiff; - -extern template void Calculate(BBDomTree &DT); -extern template void CalculateWithUpdates(BBDomTree &DT, - BBUpdates U); - -extern template void Calculate(BBPostDomTree &DT); - -extern template void InsertEdge(BBDomTree &DT, BasicBlock *From, - BasicBlock *To); -extern template void InsertEdge(BBPostDomTree &DT, - BasicBlock *From, - BasicBlock *To); - -extern template void DeleteEdge(BBDomTree &DT, BasicBlock *From, - BasicBlock *To); -extern template void DeleteEdge(BBPostDomTree &DT, - BasicBlock *From, - BasicBlock *To); - -extern template void ApplyUpdates(BBDomTree &DT, - BBDomTreeGraphDiff &, - BBDomTreeGraphDiff *); -extern template void ApplyUpdates(BBPostDomTree &DT, - BBPostDomTreeGraphDiff &, - BBPostDomTreeGraphDiff *); - -extern template bool Verify(const BBDomTree &DT, - BBDomTree::VerificationLevel VL); -extern template bool Verify(const BBPostDomTree &DT, - BBPostDomTree::VerificationLevel VL); -} // namespace DomTreeBuilder - -using DomTreeNode = DomTreeNodeBase; - -class BasicBlockEdge { - const BasicBlock *Start; - const BasicBlock *End; - -public: - BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : - Start(Start_), End(End_) {} - - BasicBlockEdge(const std::pair &Pair) - : Start(Pair.first), End(Pair.second) {} - - BasicBlockEdge(const std::pair &Pair) - : Start(Pair.first), End(Pair.second) {} - - const BasicBlock *getStart() const { - return Start; - } - - const BasicBlock *getEnd() const { - return End; - } - - /// Check if this is the only edge between Start and End. - bool isSingleEdge() const; -}; - -template <> struct DenseMapInfo { - using BBInfo = DenseMapInfo; - - static unsigned getHashValue(const BasicBlockEdge *V); - - static inline BasicBlockEdge getEmptyKey() { - return BasicBlockEdge(BBInfo::getEmptyKey(), BBInfo::getEmptyKey()); - } - - static inline BasicBlockEdge getTombstoneKey() { - return BasicBlockEdge(BBInfo::getTombstoneKey(), BBInfo::getTombstoneKey()); - } - - static unsigned getHashValue(const BasicBlockEdge &Edge) { - return hash_combine(BBInfo::getHashValue(Edge.getStart()), - BBInfo::getHashValue(Edge.getEnd())); - } - - static bool isEqual(const BasicBlockEdge &LHS, const BasicBlockEdge &RHS) { - return BBInfo::isEqual(LHS.getStart(), RHS.getStart()) && - BBInfo::isEqual(LHS.getEnd(), RHS.getEnd()); - } -}; - -/// Concrete subclass of DominatorTreeBase that is used to compute a -/// normal dominator tree. -/// -/// Definition: A block is said to be forward statically reachable if there is -/// a path from the entry of the function to the block. A statically reachable -/// block may become statically unreachable during optimization. -/// -/// A forward unreachable block may appear in the dominator tree, or it may -/// not. If it does, dominance queries will return results as if all reachable -/// blocks dominate it. When asking for a Node corresponding to a potentially -/// unreachable block, calling code must handle the case where the block was -/// unreachable and the result of getNode() is nullptr. -/// -/// Generally, a block known to be unreachable when the dominator tree is -/// constructed will not be in the tree. One which becomes unreachable after -/// the dominator tree is initially constructed may still exist in the tree, -/// even if the tree is properly updated. Calling code should not rely on the -/// preceding statements; this is stated only to assist human understanding. -class DominatorTree : public DominatorTreeBase { - public: - using Base = DominatorTreeBase; - - DominatorTree() = default; - explicit DominatorTree(Function &F) { recalculate(F); } - explicit DominatorTree(DominatorTree &DT, DomTreeBuilder::BBUpdates U) { - recalculate(*DT.Parent, U); - } - - /// Handle invalidation explicitly. - bool invalidate(Function &F, const PreservedAnalyses &PA, - FunctionAnalysisManager::Invalidator &); - - // Ensure base-class overloads are visible. - using Base::dominates; - - /// Return true if the (end of the) basic block BB dominates the use U. - bool dominates(const BasicBlock *BB, const Use &U) const; - - /// Return true if value Def dominates use U, in the sense that Def is - /// available at U, and could be substituted as the used value without - /// violating the SSA dominance requirement. - /// - /// In particular, it is worth noting that: - /// * Non-instruction Defs dominate everything. - /// * Def does not dominate a use in Def itself (outside of degenerate cases - /// like unreachable code or trivial phi cycles). - /// * Invoke/callbr Defs only dominate uses in their default destination. - bool dominates(const Value *Def, const Use &U) const; - /// Return true if value Def dominates all possible uses inside instruction - /// User. Same comments as for the Use-based API apply. - bool dominates(const Value *Def, const Instruction *User) const; - // Does not accept Value to avoid ambiguity with dominance checks between - // two basic blocks. - bool dominates(const Instruction *Def, const BasicBlock *BB) const; - - /// Return true if an edge dominates a use. - /// - /// If BBE is not a unique edge between start and end of the edge, it can - /// never dominate the use. - bool dominates(const BasicBlockEdge &BBE, const Use &U) const; - bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const; - /// Returns true if edge \p BBE1 dominates edge \p BBE2. - bool dominates(const BasicBlockEdge &BBE1, const BasicBlockEdge &BBE2) const; - - // Ensure base class overloads are visible. - using Base::isReachableFromEntry; - - /// Provide an overload for a Use. - bool isReachableFromEntry(const Use &U) const; - - // Pop up a GraphViz/gv window with the Dominator Tree rendered using `dot`. - void viewGraph(const Twine &Name, const Twine &Title); - void viewGraph(); -}; - -//===------------------------------------- -// DominatorTree GraphTraits specializations so the DominatorTree can be -// iterable by generic graph iterators. - -template struct DomTreeGraphTraitsBase { - using NodeRef = Node *; - using ChildIteratorType = ChildIterator; - using nodes_iterator = df_iterator>; - - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->end(); } - - static nodes_iterator nodes_begin(NodeRef N) { - return df_begin(getEntryNode(N)); - } - - static nodes_iterator nodes_end(NodeRef N) { return df_end(getEntryNode(N)); } -}; - -template <> -struct GraphTraits - : public DomTreeGraphTraitsBase { -}; - -template <> -struct GraphTraits - : public DomTreeGraphTraitsBase {}; - -template <> struct GraphTraits - : public GraphTraits { - static NodeRef getEntryNode(DominatorTree *DT) { return DT->getRootNode(); } - - static nodes_iterator nodes_begin(DominatorTree *N) { - return df_begin(getEntryNode(N)); - } - - static nodes_iterator nodes_end(DominatorTree *N) { - return df_end(getEntryNode(N)); - } -}; - -/// Analysis pass which computes a \c DominatorTree. -class DominatorTreeAnalysis : public AnalysisInfoMixin { - friend AnalysisInfoMixin; - static AnalysisKey Key; - -public: - /// Provide the result typedef for this analysis pass. - using Result = DominatorTree; - - /// Run the analysis pass over a function and produce a dominator tree. - DominatorTree run(Function &F, FunctionAnalysisManager &); -}; - -/// Printer pass for the \c DominatorTree. -class DominatorTreePrinterPass - : public PassInfoMixin { - raw_ostream &OS; - -public: - explicit DominatorTreePrinterPass(raw_ostream &OS); - - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; - -/// Verifier pass for the \c DominatorTree. -struct DominatorTreeVerifierPass : PassInfoMixin { - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; - -/// Enables verification of dominator trees. -/// -/// This check is expensive and is disabled by default. `-verify-dom-info` -/// allows selectively enabling the check without needing to recompile. -extern bool VerifyDomInfo; - -/// Legacy analysis pass which computes a \c DominatorTree. -class DominatorTreeWrapperPass : public FunctionPass { - DominatorTree DT; - -public: - static char ID; - - DominatorTreeWrapperPass(); - - DominatorTree &getDomTree() { return DT; } - const DominatorTree &getDomTree() const { return DT; } - - bool runOnFunction(Function &F) override; - - void verifyAnalysis() const override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - void releaseMemory() override { DT.reset(); } - - void print(raw_ostream &OS, const Module *M = nullptr) const override; -}; -} // end namespace llvm - -#endif // LLVM_IR_DOMINATORS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/FPEnv.h b/suite/synctools/tablegen/include/llvm/IR/FPEnv.h deleted file mode 100644 index bf435ec6d1..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/FPEnv.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- FPEnv.h ---- FP Environment ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains the declarations of entities that describe floating -/// point environment and related functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_FPENV_H -#define LLVM_IR_FPENV_H - -#include "llvm/ADT/FloatingPointMode.h" -#include "llvm/ADT/Optional.h" - -namespace llvm { -class StringRef; - -namespace fp { - -/// Exception behavior used for floating point operations. -/// -/// Each of these values correspond to some metadata argument value of a -/// constrained floating point intrinsic. See the LLVM Language Reference Manual -/// for details. -enum ExceptionBehavior : uint8_t { - ebIgnore, ///< This corresponds to "fpexcept.ignore". - ebMayTrap, ///< This corresponds to "fpexcept.maytrap". - ebStrict ///< This corresponds to "fpexcept.strict". -}; - -} - -/// Returns a valid RoundingMode enumerator when given a string -/// that is valid as input in constrained intrinsic rounding mode -/// metadata. -Optional convertStrToRoundingMode(StringRef); - -/// For any RoundingMode enumerator, returns a string valid as input in -/// constrained intrinsic rounding mode metadata. -Optional convertRoundingModeToStr(RoundingMode); - -/// Returns a valid ExceptionBehavior enumerator when given a string -/// valid as input in constrained intrinsic exception behavior metadata. -Optional convertStrToExceptionBehavior(StringRef); - -/// For any ExceptionBehavior enumerator, returns a string valid as -/// input in constrained intrinsic exception behavior metadata. -Optional convertExceptionBehaviorToStr(fp::ExceptionBehavior); - -/// Returns true if the exception handling behavior and rounding mode -/// match what is used in the default floating point environment. -inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) { - return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven; -} - -/// Returns true if the rounding mode RM may be QRM at compile time or -/// at run time. -inline bool canRoundingModeBe(RoundingMode RM, RoundingMode QRM) { - return RM == QRM || RM == RoundingMode::Dynamic; -} -} -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/FixedMetadataKinds.def b/suite/synctools/tablegen/include/llvm/IR/FixedMetadataKinds.def deleted file mode 100644 index 31979cd2f9..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/FixedMetadataKinds.def +++ /dev/null @@ -1,44 +0,0 @@ -/*===-- FixedMetadataKinds.def - Fixed metadata kind IDs -------*- C++ -*-=== *\ -|* -|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -|* See https://llvm.org/LICENSE.txt for license information. -|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_FIXED_MD_KIND -#error "LLVM_FIXED_MD_KIND(EnumID, Name, Value) is not defined." -#endif - -LLVM_FIXED_MD_KIND(MD_dbg, "dbg", 0) -LLVM_FIXED_MD_KIND(MD_tbaa, "tbaa", 1) -LLVM_FIXED_MD_KIND(MD_prof, "prof", 2) -LLVM_FIXED_MD_KIND(MD_fpmath, "fpmath", 3) -LLVM_FIXED_MD_KIND(MD_range, "range", 4) -LLVM_FIXED_MD_KIND(MD_tbaa_struct, "tbaa.struct", 5) -LLVM_FIXED_MD_KIND(MD_invariant_load, "invariant.load", 6) -LLVM_FIXED_MD_KIND(MD_alias_scope, "alias.scope", 7) -LLVM_FIXED_MD_KIND(MD_noalias, "noalias", 8) -LLVM_FIXED_MD_KIND(MD_nontemporal, "nontemporal", 9) -LLVM_FIXED_MD_KIND(MD_mem_parallel_loop_access, - "llvm.mem.parallel_loop_access", 10) -LLVM_FIXED_MD_KIND(MD_nonnull, "nonnull", 11) -LLVM_FIXED_MD_KIND(MD_dereferenceable, "dereferenceable", 12) -LLVM_FIXED_MD_KIND(MD_dereferenceable_or_null, "dereferenceable_or_null", 13) -LLVM_FIXED_MD_KIND(MD_make_implicit, "make.implicit", 14) -LLVM_FIXED_MD_KIND(MD_unpredictable, "unpredictable", 15) -LLVM_FIXED_MD_KIND(MD_invariant_group, "invariant.group", 16) -LLVM_FIXED_MD_KIND(MD_align, "align", 17) -LLVM_FIXED_MD_KIND(MD_loop, "llvm.loop", 18) -LLVM_FIXED_MD_KIND(MD_type, "type", 19) -LLVM_FIXED_MD_KIND(MD_section_prefix, "section_prefix", 20) -LLVM_FIXED_MD_KIND(MD_absolute_symbol, "absolute_symbol", 21) -LLVM_FIXED_MD_KIND(MD_associated, "associated", 22) -LLVM_FIXED_MD_KIND(MD_callees, "callees", 23) -LLVM_FIXED_MD_KIND(MD_irr_loop, "irr_loop", 24) -LLVM_FIXED_MD_KIND(MD_access_group, "llvm.access.group", 25) -LLVM_FIXED_MD_KIND(MD_callback, "callback", 26) -LLVM_FIXED_MD_KIND(MD_preserve_access_index, "llvm.preserve.access.index", 27) -LLVM_FIXED_MD_KIND(MD_vcall_visibility, "vcall_visibility", 28) -LLVM_FIXED_MD_KIND(MD_noundef, "noundef", 29) -LLVM_FIXED_MD_KIND(MD_annotation, "annotation", 30) diff --git a/suite/synctools/tablegen/include/llvm/IR/FixedPointBuilder.h b/suite/synctools/tablegen/include/llvm/IR/FixedPointBuilder.h deleted file mode 100644 index a99c761ad3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/FixedPointBuilder.h +++ /dev/null @@ -1,465 +0,0 @@ -//===- llvm/FixedPointBuilder.h - Builder for fixed-point ops ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the FixedPointBuilder class, which is used as a convenient -// way to lower fixed-point arithmetic operations to LLVM IR. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_FIXEDPOINTBUILDER_H -#define LLVM_IR_FIXEDPOINTBUILDER_H - -#include "llvm/ADT/APFixedPoint.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" - -namespace llvm { - -template class FixedPointBuilder { - IRBuilderTy &B; - - Value *Convert(Value *Src, const FixedPointSemantics &SrcSema, - const FixedPointSemantics &DstSema, bool DstIsInteger) { - unsigned SrcWidth = SrcSema.getWidth(); - unsigned DstWidth = DstSema.getWidth(); - unsigned SrcScale = SrcSema.getScale(); - unsigned DstScale = DstSema.getScale(); - bool SrcIsSigned = SrcSema.isSigned(); - bool DstIsSigned = DstSema.isSigned(); - - Type *DstIntTy = B.getIntNTy(DstWidth); - - Value *Result = Src; - unsigned ResultWidth = SrcWidth; - - // Downscale. - if (DstScale < SrcScale) { - // When converting to integers, we round towards zero. For negative - // numbers, right shifting rounds towards negative infinity. In this case, - // we can just round up before shifting. - if (DstIsInteger && SrcIsSigned) { - Value *Zero = Constant::getNullValue(Result->getType()); - Value *IsNegative = B.CreateICmpSLT(Result, Zero); - Value *LowBits = ConstantInt::get( - B.getContext(), APInt::getLowBitsSet(ResultWidth, SrcScale)); - Value *Rounded = B.CreateAdd(Result, LowBits); - Result = B.CreateSelect(IsNegative, Rounded, Result); - } - - Result = SrcIsSigned - ? B.CreateAShr(Result, SrcScale - DstScale, "downscale") - : B.CreateLShr(Result, SrcScale - DstScale, "downscale"); - } - - if (!DstSema.isSaturated()) { - // Resize. - Result = B.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); - - // Upscale. - if (DstScale > SrcScale) - Result = B.CreateShl(Result, DstScale - SrcScale, "upscale"); - } else { - // Adjust the number of fractional bits. - if (DstScale > SrcScale) { - // Compare to DstWidth to prevent resizing twice. - ResultWidth = std::max(SrcWidth + DstScale - SrcScale, DstWidth); - Type *UpscaledTy = B.getIntNTy(ResultWidth); - Result = B.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize"); - Result = B.CreateShl(Result, DstScale - SrcScale, "upscale"); - } - - // Handle saturation. - bool LessIntBits = DstSema.getIntegralBits() < SrcSema.getIntegralBits(); - if (LessIntBits) { - Value *Max = ConstantInt::get( - B.getContext(), - APFixedPoint::getMax(DstSema).getValue().extOrTrunc(ResultWidth)); - Value *TooHigh = SrcIsSigned ? B.CreateICmpSGT(Result, Max) - : B.CreateICmpUGT(Result, Max); - Result = B.CreateSelect(TooHigh, Max, Result, "satmax"); - } - // Cannot overflow min to dest type if src is unsigned since all fixed - // point types can cover the unsigned min of 0. - if (SrcIsSigned && (LessIntBits || !DstIsSigned)) { - Value *Min = ConstantInt::get( - B.getContext(), - APFixedPoint::getMin(DstSema).getValue().extOrTrunc(ResultWidth)); - Value *TooLow = B.CreateICmpSLT(Result, Min); - Result = B.CreateSelect(TooLow, Min, Result, "satmin"); - } - - // Resize the integer part to get the final destination size. - if (ResultWidth != DstWidth) - Result = B.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); - } - return Result; - } - - /// Get the common semantic for two semantics, with the added imposition that - /// saturated padded types retain the padding bit. - FixedPointSemantics - getCommonBinopSemantic(const FixedPointSemantics &LHSSema, - const FixedPointSemantics &RHSSema) { - auto C = LHSSema.getCommonSemantics(RHSSema); - bool BothPadded = - LHSSema.hasUnsignedPadding() && RHSSema.hasUnsignedPadding(); - return FixedPointSemantics( - C.getWidth() + (unsigned)(BothPadded && C.isSaturated()), C.getScale(), - C.isSigned(), C.isSaturated(), BothPadded); - } - - /// Given a floating point type and a fixed-point semantic, return a floating - /// point type which can accommodate the fixed-point semantic. This is either - /// \p Ty, or a floating point type with a larger exponent than Ty. - Type *getAccommodatingFloatType(Type *Ty, const FixedPointSemantics &Sema) { - const fltSemantics *FloatSema = &Ty->getFltSemantics(); - while (!Sema.fitsInFloatSemantics(*FloatSema)) - FloatSema = APFixedPoint::promoteFloatSemantics(FloatSema); - return Type::getFloatingPointTy(Ty->getContext(), *FloatSema); - } - -public: - FixedPointBuilder(IRBuilderTy &Builder) : B(Builder) {} - - /// Convert an integer value representing a fixed-point number from one - /// fixed-point semantic to another fixed-point semantic. - /// \p Src - The source value - /// \p SrcSema - The fixed-point semantic of the source value - /// \p DstSema - The resulting fixed-point semantic - Value *CreateFixedToFixed(Value *Src, const FixedPointSemantics &SrcSema, - const FixedPointSemantics &DstSema) { - return Convert(Src, SrcSema, DstSema, false); - } - - /// Convert an integer value representing a fixed-point number to an integer - /// with the given bit width and signedness. - /// \p Src - The source value - /// \p SrcSema - The fixed-point semantic of the source value - /// \p DstWidth - The bit width of the result value - /// \p DstIsSigned - The signedness of the result value - Value *CreateFixedToInteger(Value *Src, const FixedPointSemantics &SrcSema, - unsigned DstWidth, bool DstIsSigned) { - return Convert( - Src, SrcSema, - FixedPointSemantics::GetIntegerSemantics(DstWidth, DstIsSigned), true); - } - - /// Convert an integer value with the given signedness to an integer value - /// representing the given fixed-point semantic. - /// \p Src - The source value - /// \p SrcIsSigned - The signedness of the source value - /// \p DstSema - The resulting fixed-point semantic - Value *CreateIntegerToFixed(Value *Src, unsigned SrcIsSigned, - const FixedPointSemantics &DstSema) { - return Convert(Src, - FixedPointSemantics::GetIntegerSemantics( - Src->getType()->getScalarSizeInBits(), SrcIsSigned), - DstSema, false); - } - - Value *CreateFixedToFloating(Value *Src, const FixedPointSemantics &SrcSema, - Type *DstTy) { - Value *Result; - Type *OpTy = getAccommodatingFloatType(DstTy, SrcSema); - // Convert the raw fixed-point value directly to floating point. If the - // value is too large to fit, it will be rounded, not truncated. - Result = SrcSema.isSigned() ? B.CreateSIToFP(Src, OpTy) - : B.CreateUIToFP(Src, OpTy); - // Rescale the integral-in-floating point by the scaling factor. This is - // lossless, except for overflow to infinity which is unlikely. - Result = B.CreateFMul(Result, - ConstantFP::get(OpTy, std::pow(2, -(int)SrcSema.getScale()))); - if (OpTy != DstTy) - Result = B.CreateFPTrunc(Result, DstTy); - return Result; - } - - Value *CreateFloatingToFixed(Value *Src, const FixedPointSemantics &DstSema) { - bool UseSigned = DstSema.isSigned() || DstSema.hasUnsignedPadding(); - Value *Result = Src; - Type *OpTy = getAccommodatingFloatType(Src->getType(), DstSema); - if (OpTy != Src->getType()) - Result = B.CreateFPExt(Result, OpTy); - // Rescale the floating point value so that its significant bits (for the - // purposes of the conversion) are in the integral range. - Result = B.CreateFMul(Result, - ConstantFP::get(OpTy, std::pow(2, DstSema.getScale()))); - - Type *ResultTy = B.getIntNTy(DstSema.getWidth()); - if (DstSema.isSaturated()) { - Intrinsic::ID IID = - UseSigned ? Intrinsic::fptosi_sat : Intrinsic::fptoui_sat; - Result = B.CreateIntrinsic(IID, {ResultTy, OpTy}, {Result}); - } else { - Result = UseSigned ? B.CreateFPToSI(Result, ResultTy) - : B.CreateFPToUI(Result, ResultTy); - } - - // When saturating unsigned-with-padding using signed operations, we may - // get negative values. Emit an extra clamp to zero. - if (DstSema.isSaturated() && DstSema.hasUnsignedPadding()) { - Constant *Zero = Constant::getNullValue(Result->getType()); - Result = - B.CreateSelect(B.CreateICmpSLT(Result, Zero), Zero, Result, "satmin"); - } - - return Result; - } - - /// Add two fixed-point values and return the result in their common semantic. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateAdd(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - Value *Result; - if (CommonSema.isSaturated()) { - Intrinsic::ID IID = UseSigned ? Intrinsic::sadd_sat : Intrinsic::uadd_sat; - Result = B.CreateBinaryIntrinsic(IID, WideLHS, WideRHS); - } else { - Result = B.CreateAdd(WideLHS, WideRHS); - } - - return CreateFixedToFixed(Result, CommonSema, - LHSSema.getCommonSemantics(RHSSema)); - } - - /// Subtract two fixed-point values and return the result in their common - /// semantic. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateSub(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - Value *Result; - if (CommonSema.isSaturated()) { - Intrinsic::ID IID = UseSigned ? Intrinsic::ssub_sat : Intrinsic::usub_sat; - Result = B.CreateBinaryIntrinsic(IID, WideLHS, WideRHS); - } else { - Result = B.CreateSub(WideLHS, WideRHS); - } - - // Subtraction can end up below 0 for padded unsigned operations, so emit - // an extra clamp in that case. - if (CommonSema.isSaturated() && CommonSema.hasUnsignedPadding()) { - Constant *Zero = Constant::getNullValue(Result->getType()); - Result = - B.CreateSelect(B.CreateICmpSLT(Result, Zero), Zero, Result, "satmin"); - } - - return CreateFixedToFixed(Result, CommonSema, - LHSSema.getCommonSemantics(RHSSema)); - } - - /// Multiply two fixed-point values and return the result in their common - /// semantic. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateMul(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - Intrinsic::ID IID; - if (CommonSema.isSaturated()) { - IID = UseSigned ? Intrinsic::smul_fix_sat : Intrinsic::umul_fix_sat; - } else { - IID = UseSigned ? Intrinsic::smul_fix : Intrinsic::umul_fix; - } - Value *Result = B.CreateIntrinsic( - IID, {WideLHS->getType()}, - {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); - - return CreateFixedToFixed(Result, CommonSema, - LHSSema.getCommonSemantics(RHSSema)); - } - - /// Divide two fixed-point values and return the result in their common - /// semantic. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateDiv(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - Intrinsic::ID IID; - if (CommonSema.isSaturated()) { - IID = UseSigned ? Intrinsic::sdiv_fix_sat : Intrinsic::udiv_fix_sat; - } else { - IID = UseSigned ? Intrinsic::sdiv_fix : Intrinsic::udiv_fix; - } - Value *Result = B.CreateIntrinsic( - IID, {WideLHS->getType()}, - {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); - - return CreateFixedToFixed(Result, CommonSema, - LHSSema.getCommonSemantics(RHSSema)); - } - - /// Left shift a fixed-point value by an unsigned integer value. The integer - /// value can be any bit width. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - Value *CreateShl(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS) { - bool UseSigned = LHSSema.isSigned() || LHSSema.hasUnsignedPadding(); - - RHS = B.CreateIntCast(RHS, LHS->getType(), /*IsSigned=*/false); - - Value *Result; - if (LHSSema.isSaturated()) { - Intrinsic::ID IID = UseSigned ? Intrinsic::sshl_sat : Intrinsic::ushl_sat; - Result = B.CreateBinaryIntrinsic(IID, LHS, RHS); - } else { - Result = B.CreateShl(LHS, RHS); - } - - return Result; - } - - /// Right shift a fixed-point value by an unsigned integer value. The integer - /// value can be any bit width. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - Value *CreateShr(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS) { - RHS = B.CreateIntCast(RHS, LHS->getType(), false); - - return LHSSema.isSigned() ? B.CreateAShr(LHS, RHS) : B.CreateLShr(LHS, RHS); - } - - /// Compare two fixed-point values for equality. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateEQ(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return B.CreateICmpEQ(WideLHS, WideRHS); - } - - /// Compare two fixed-point values for inequality. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateNE(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return B.CreateICmpNE(WideLHS, WideRHS); - } - - /// Compare two fixed-point values as LHS < RHS. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateLT(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return CommonSema.isSigned() ? B.CreateICmpSLT(WideLHS, WideRHS) - : B.CreateICmpULT(WideLHS, WideRHS); - } - - /// Compare two fixed-point values as LHS <= RHS. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateLE(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return CommonSema.isSigned() ? B.CreateICmpSLE(WideLHS, WideRHS) - : B.CreateICmpULE(WideLHS, WideRHS); - } - - /// Compare two fixed-point values as LHS > RHS. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateGT(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return CommonSema.isSigned() ? B.CreateICmpSGT(WideLHS, WideRHS) - : B.CreateICmpUGT(WideLHS, WideRHS); - } - - /// Compare two fixed-point values as LHS >= RHS. - /// \p LHS - The left hand side - /// \p LHSSema - The semantic of the left hand side - /// \p RHS - The right hand side - /// \p RHSSema - The semantic of the right hand side - Value *CreateGE(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { - auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); - - Value *WideLHS = CreateFixedToFixed(LHS, LHSSema, CommonSema); - Value *WideRHS = CreateFixedToFixed(RHS, RHSSema, CommonSema); - - return CommonSema.isSigned() ? B.CreateICmpSGE(WideLHS, WideRHS) - : B.CreateICmpUGE(WideLHS, WideRHS); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_FIXEDPOINTBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Function.h b/suite/synctools/tablegen/include/llvm/IR/Function.h deleted file mode 100644 index 0eb3910c1b..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Function.h +++ /dev/null @@ -1,917 +0,0 @@ -//===- llvm/Function.h - Class to represent a single function ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the Function class, which represents a -// single function/procedure in LLVM. -// -// A function basically consists of a list of basic blocks, a list of arguments, -// and a symbol table. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_FUNCTION_H -#define LLVM_IR_FUNCTION_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include -#include -#include -#include -#include - -namespace llvm { - -namespace Intrinsic { -typedef unsigned ID; -} - -class AssemblyAnnotationWriter; -class Constant; -struct DenormalMode; -class DISubprogram; -class LLVMContext; -class Module; -template class Optional; -class raw_ostream; -class Type; -class User; -class BranchProbabilityInfo; -class BlockFrequencyInfo; - -class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject, - public ilist_node { -public: - using BasicBlockListType = SymbolTableList; - - // BasicBlock iterators... - using iterator = BasicBlockListType::iterator; - using const_iterator = BasicBlockListType::const_iterator; - - using arg_iterator = Argument *; - using const_arg_iterator = const Argument *; - -private: - // Important things that make up a function! - BasicBlockListType BasicBlocks; ///< The basic blocks - mutable Argument *Arguments = nullptr; ///< The formal arguments - size_t NumArgs; - std::unique_ptr - SymTab; ///< Symbol table of args/instructions - AttributeList AttributeSets; ///< Parameter attributes - - /* - * Value::SubclassData - * - * bit 0 : HasLazyArguments - * bit 1 : HasPrefixData - * bit 2 : HasPrologueData - * bit 3 : HasPersonalityFn - * bits 4-13 : CallingConvention - * bits 14 : HasGC - * bits 15 : [reserved] - */ - - /// Bits from GlobalObject::GlobalObjectSubclassData. - enum { - /// Whether this function is materializable. - IsMaterializableBit = 0, - }; - - friend class SymbolTableListTraits; - - /// hasLazyArguments/CheckLazyArguments - The argument list of a function is - /// built on demand, so that the list isn't allocated until the first client - /// needs it. The hasLazyArguments predicate returns true if the arg list - /// hasn't been set up yet. -public: - bool hasLazyArguments() const { - return getSubclassDataFromValue() & (1<<0); - } - -private: - void CheckLazyArguments() const { - if (hasLazyArguments()) - BuildLazyArguments(); - } - - void BuildLazyArguments() const; - - void clearArguments(); - - /// Function ctor - If the (optional) Module argument is specified, the - /// function is automatically inserted into the end of the function list for - /// the module. - /// - Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, - const Twine &N = "", Module *M = nullptr); - -public: - Function(const Function&) = delete; - void operator=(const Function&) = delete; - ~Function(); - - // This is here to help easily convert from FunctionT * (Function * or - // MachineFunction *) in BlockFrequencyInfoImpl to Function * by calling - // FunctionT->getFunction(). - const Function &getFunction() const { return *this; } - - static Function *Create(FunctionType *Ty, LinkageTypes Linkage, - unsigned AddrSpace, const Twine &N = "", - Module *M = nullptr) { - return new Function(Ty, Linkage, AddrSpace, N, M); - } - - // TODO: remove this once all users have been updated to pass an AddrSpace - static Function *Create(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N = "", Module *M = nullptr) { - return new Function(Ty, Linkage, static_cast(-1), N, M); - } - - /// Creates a new function and attaches it to a module. - /// - /// Places the function in the program address space as specified - /// by the module's data layout. - static Function *Create(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N, Module &M); - - /// Creates a function with some attributes recorded in llvm.module.flags - /// applied. - /// - /// Use this when synthesizing new functions that need attributes that would - /// have been set by command line options. - static Function *createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, - unsigned AddrSpace, - const Twine &N = "", - Module *M = nullptr); - - // Provide fast operand accessors. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Returns the number of non-debug IR instructions in this function. - /// This is equivalent to the sum of the sizes of each basic block contained - /// within this function. - unsigned getInstructionCount() const; - - /// Returns the FunctionType for me. - FunctionType *getFunctionType() const { - return cast(getValueType()); - } - - /// Returns the type of the ret val. - Type *getReturnType() const { return getFunctionType()->getReturnType(); } - - /// getContext - Return a reference to the LLVMContext associated with this - /// function. - LLVMContext &getContext() const; - - /// isVarArg - Return true if this function takes a variable number of - /// arguments. - bool isVarArg() const { return getFunctionType()->isVarArg(); } - - bool isMaterializable() const { - return getGlobalObjectSubClassData() & (1 << IsMaterializableBit); - } - void setIsMaterializable(bool V) { - unsigned Mask = 1 << IsMaterializableBit; - setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | - (V ? Mask : 0u)); - } - - /// getIntrinsicID - This method returns the ID number of the specified - /// function, or Intrinsic::not_intrinsic if the function is not an - /// intrinsic, or if the pointer is null. This value is always defined to be - /// zero to allow easy checking for whether a function is intrinsic or not. - /// The particular intrinsic functions which correspond to this value are - /// defined in llvm/Intrinsics.h. - Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; } - - /// isIntrinsic - Returns true if the function's name starts with "llvm.". - /// It's possible for this function to return true while getIntrinsicID() - /// returns Intrinsic::not_intrinsic! - bool isIntrinsic() const { return HasLLVMReservedName; } - - /// isTargetIntrinsic - Returns true if IID is an intrinsic specific to a - /// certain target. If it is a generic intrinsic false is returned. - static bool isTargetIntrinsic(Intrinsic::ID IID); - - /// isTargetIntrinsic - Returns true if this function is an intrinsic and the - /// intrinsic is specific to a certain target. If this is not an intrinsic - /// or a generic intrinsic, false is returned. - bool isTargetIntrinsic() const; - - /// Returns true if the function is one of the "Constrained Floating-Point - /// Intrinsics". Returns false if not, and returns false when - /// getIntrinsicID() returns Intrinsic::not_intrinsic. - bool isConstrainedFPIntrinsic() const; - - static Intrinsic::ID lookupIntrinsicID(StringRef Name); - - /// Recalculate the ID for this function if it is an Intrinsic defined - /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic - /// if the name of this function does not match an intrinsic in that header. - /// Note, this method does not need to be called directly, as it is called - /// from Value::setName() whenever the name of this function changes. - void recalculateIntrinsicID(); - - /// getCallingConv()/setCallingConv(CC) - These method get and set the - /// calling convention of this function. The enum values for the known - /// calling conventions are defined in CallingConv.h. - CallingConv::ID getCallingConv() const { - return static_cast((getSubclassDataFromValue() >> 4) & - CallingConv::MaxID); - } - void setCallingConv(CallingConv::ID CC) { - auto ID = static_cast(CC); - assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); - setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4)); - } - - enum ProfileCountType { PCT_Real, PCT_Synthetic }; - - /// Class to represent profile counts. - /// - /// This class represents both real and synthetic profile counts. - class ProfileCount { - private: - uint64_t Count = 0; - ProfileCountType PCT = PCT_Real; - - public: - ProfileCount(uint64_t Count, ProfileCountType PCT) - : Count(Count), PCT(PCT) {} - uint64_t getCount() const { return Count; } - ProfileCountType getType() const { return PCT; } - bool isSynthetic() const { return PCT == PCT_Synthetic; } - }; - - /// Set the entry count for this function. - /// - /// Entry count is the number of times this function was executed based on - /// pgo data. \p Imports points to a set of GUIDs that needs to - /// be imported by the function for sample PGO, to enable the same inlines as - /// the profiled optimized binary. - void setEntryCount(ProfileCount Count, - const DenseSet *Imports = nullptr); - - /// A convenience wrapper for setting entry count - void setEntryCount(uint64_t Count, ProfileCountType Type = PCT_Real, - const DenseSet *Imports = nullptr); - - /// Get the entry count for this function. - /// - /// Entry count is the number of times the function was executed. - /// When AllowSynthetic is false, only pgo_data will be returned. - Optional getEntryCount(bool AllowSynthetic = false) const; - - /// Return true if the function is annotated with profile data. - /// - /// Presence of entry counts from a profile run implies the function has - /// profile annotations. If IncludeSynthetic is false, only return true - /// when the profile data is real. - bool hasProfileData(bool IncludeSynthetic = false) const { - return getEntryCount(IncludeSynthetic).hasValue(); - } - - /// Returns the set of GUIDs that needs to be imported to the function for - /// sample PGO, to enable the same inlines as the profiled optimized binary. - DenseSet getImportGUIDs() const; - - /// Set the section prefix for this function. - void setSectionPrefix(StringRef Prefix); - - /// Get the section prefix for this function. - Optional getSectionPrefix() const; - - /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm - /// to use during code generation. - bool hasGC() const { - return getSubclassDataFromValue() & (1<<14); - } - const std::string &getGC() const; - void setGC(std::string Str); - void clearGC(); - - /// Return the attribute list for this Function. - AttributeList getAttributes() const { return AttributeSets; } - - /// Set the attribute list for this Function. - void setAttributes(AttributeList Attrs) { AttributeSets = Attrs; } - - // TODO: remove non-AtIndex versions of these methods. - /// adds the attribute to the list of attributes. - void addAttributeAtIndex(unsigned i, Attribute Attr); - - /// Add function attributes to this function. - void addFnAttr(Attribute::AttrKind Kind); - - /// Add function attributes to this function. - void addFnAttr(StringRef Kind, StringRef Val = StringRef()); - - /// Add function attributes to this function. - void addFnAttr(Attribute Attr); - - /// Add function attributes to this function. - void addFnAttrs(const AttrBuilder &Attrs); - - /// Add return value attributes to this function. - void addRetAttr(Attribute::AttrKind Kind); - - /// Add return value attributes to this function. - void addRetAttr(Attribute Attr); - - /// Add return value attributes to this function. - void addRetAttrs(const AttrBuilder &Attrs); - - /// adds the attribute to the list of attributes for the given arg. - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// adds the attribute to the list of attributes for the given arg. - void addParamAttr(unsigned ArgNo, Attribute Attr); - - /// adds the attributes to the list of attributes for the given arg. - void addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs); - - /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, StringRef Kind); - - /// Remove function attributes from this function. - void removeFnAttr(Attribute::AttrKind Kind); - - /// Remove function attribute from this function. - void removeFnAttr(StringRef Kind); - - void removeFnAttrs(const AttributeMask &Attrs); - - /// removes the attribute from the return value list of attributes. - void removeRetAttr(Attribute::AttrKind Kind); - - /// removes the attribute from the return value list of attributes. - void removeRetAttr(StringRef Kind); - - /// removes the attributes from the return value list of attributes. - void removeRetAttrs(const AttributeMask &Attrs); - - /// removes the attribute from the list of attributes. - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeParamAttr(unsigned ArgNo, StringRef Kind); - - /// removes the attribute from the list of attributes. - void removeParamAttrs(unsigned ArgNo, const AttributeMask &Attrs); - - /// Return true if the function has the attribute. - bool hasFnAttribute(Attribute::AttrKind Kind) const; - - /// Return true if the function has the attribute. - bool hasFnAttribute(StringRef Kind) const; - - /// check if an attribute is in the list of attributes for the return value. - bool hasRetAttribute(Attribute::AttrKind Kind) const; - - /// check if an attributes is in the list of attributes. - bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const; - - /// gets the attribute from the list of attributes. - Attribute getAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) const; - - /// gets the attribute from the list of attributes. - Attribute getAttributeAtIndex(unsigned i, StringRef Kind) const; - - /// Return the attribute for the given attribute kind. - Attribute getFnAttribute(Attribute::AttrKind Kind) const; - - /// Return the attribute for the given attribute kind. - Attribute getFnAttribute(StringRef Kind) const; - - /// gets the specified attribute from the list of attributes. - Attribute getParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const; - - /// removes noundef and other attributes that imply undefined behavior if a - /// `undef` or `poison` value is passed from the list of attributes. - void removeParamUndefImplyingAttrs(unsigned ArgNo); - - /// Return the stack alignment for the function. - MaybeAlign getFnStackAlign() const { - return AttributeSets.getFnStackAlignment(); - } - - /// Returns true if the function has ssp, sspstrong, or sspreq fn attrs. - bool hasStackProtectorFnAttr() const; - - /// adds the dereferenceable attribute to the list of attributes for - /// the given arg. - void addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes); - - /// adds the dereferenceable_or_null attribute to the list of - /// attributes for the given arg. - void addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes); - - /// Extract the alignment for a call or parameter (0=unknown). - /// FIXME: Remove this function once transition to Align is over. - /// Use getParamAlign() instead. - uint64_t getParamAlignment(unsigned ArgNo) const { - if (const auto MA = getParamAlign(ArgNo)) - return MA->value(); - return 0; - } - - MaybeAlign getParamAlign(unsigned ArgNo) const { - return AttributeSets.getParamAlignment(ArgNo); - } - - MaybeAlign getParamStackAlign(unsigned ArgNo) const { - return AttributeSets.getParamStackAlignment(ArgNo); - } - - /// Extract the byval type for a parameter. - Type *getParamByValType(unsigned ArgNo) const { - return AttributeSets.getParamByValType(ArgNo); - } - - /// Extract the sret type for a parameter. - Type *getParamStructRetType(unsigned ArgNo) const { - return AttributeSets.getParamStructRetType(ArgNo); - } - - /// Extract the inalloca type for a parameter. - Type *getParamInAllocaType(unsigned ArgNo) const { - return AttributeSets.getParamInAllocaType(ArgNo); - } - - /// Extract the byref type for a parameter. - Type *getParamByRefType(unsigned ArgNo) const { - return AttributeSets.getParamByRefType(ArgNo); - } - - /// Extract the preallocated type for a parameter. - Type *getParamPreallocatedType(unsigned ArgNo) const { - return AttributeSets.getParamPreallocatedType(ArgNo); - } - - /// Extract the number of dereferenceable bytes for a parameter. - /// @param ArgNo Index of an argument, with 0 being the first function arg. - uint64_t getParamDereferenceableBytes(unsigned ArgNo) const { - return AttributeSets.getParamDereferenceableBytes(ArgNo); - } - - /// Extract the number of dereferenceable_or_null bytes for a - /// parameter. - /// @param ArgNo AttributeList ArgNo, referring to an argument. - uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const { - return AttributeSets.getParamDereferenceableOrNullBytes(ArgNo); - } - - /// A function will have the "coroutine.presplit" attribute if it's - /// a coroutine and has not gone through full CoroSplit pass. - bool isPresplitCoroutine() const { - return hasFnAttribute("coroutine.presplit"); - } - - /// Determine if the function does not access memory. - bool doesNotAccessMemory() const { - return hasFnAttribute(Attribute::ReadNone); - } - void setDoesNotAccessMemory() { - addFnAttr(Attribute::ReadNone); - } - - /// Determine if the function does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly); - } - void setOnlyReadsMemory() { - addFnAttr(Attribute::ReadOnly); - } - - /// Determine if the function does not access or only writes memory. - bool onlyWritesMemory() const { - return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly); - } - void setOnlyWritesMemory() { - addFnAttr(Attribute::WriteOnly); - } - - /// Determine if the call can access memory only using pointers based - /// on its arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttribute(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } - - /// Determine if the function may only access memory that is - /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttribute(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addFnAttr(Attribute::InaccessibleMemOnly); - } - - /// Determine if the function may only access memory that is - /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - - /// Determine if the function cannot return. - bool doesNotReturn() const { - return hasFnAttribute(Attribute::NoReturn); - } - void setDoesNotReturn() { - addFnAttr(Attribute::NoReturn); - } - - /// Determine if the function should not perform indirect branch tracking. - bool doesNoCfCheck() const { return hasFnAttribute(Attribute::NoCfCheck); } - - /// Determine if the function cannot unwind. - bool doesNotThrow() const { - return hasFnAttribute(Attribute::NoUnwind); - } - void setDoesNotThrow() { - addFnAttr(Attribute::NoUnwind); - } - - /// Determine if the call cannot be duplicated. - bool cannotDuplicate() const { - return hasFnAttribute(Attribute::NoDuplicate); - } - void setCannotDuplicate() { - addFnAttr(Attribute::NoDuplicate); - } - - /// Determine if the call is convergent. - bool isConvergent() const { - return hasFnAttribute(Attribute::Convergent); - } - void setConvergent() { - addFnAttr(Attribute::Convergent); - } - void setNotConvergent() { - removeFnAttr(Attribute::Convergent); - } - - /// Determine if the call has sideeffects. - bool isSpeculatable() const { - return hasFnAttribute(Attribute::Speculatable); - } - void setSpeculatable() { - addFnAttr(Attribute::Speculatable); - } - - /// Determine if the call might deallocate memory. - bool doesNotFreeMemory() const { - return onlyReadsMemory() || hasFnAttribute(Attribute::NoFree); - } - void setDoesNotFreeMemory() { - addFnAttr(Attribute::NoFree); - } - - /// Determine if the call can synchroize with other threads - bool hasNoSync() const { - return hasFnAttribute(Attribute::NoSync); - } - void setNoSync() { - addFnAttr(Attribute::NoSync); - } - - /// Determine if the function is known not to recurse, directly or - /// indirectly. - bool doesNotRecurse() const { - return hasFnAttribute(Attribute::NoRecurse); - } - void setDoesNotRecurse() { - addFnAttr(Attribute::NoRecurse); - } - - /// Determine if the function is required to make forward progress. - bool mustProgress() const { - return hasFnAttribute(Attribute::MustProgress) || - hasFnAttribute(Attribute::WillReturn); - } - void setMustProgress() { addFnAttr(Attribute::MustProgress); } - - /// Determine if the function will return. - bool willReturn() const { return hasFnAttribute(Attribute::WillReturn); } - void setWillReturn() { addFnAttr(Attribute::WillReturn); } - - /// True if the ABI mandates (or the user requested) that this - /// function be in a unwind table. - bool hasUWTable() const { - return hasFnAttribute(Attribute::UWTable); - } - void setHasUWTable() { - addFnAttr(Attribute::UWTable); - } - - /// True if this function needs an unwind table. - bool needsUnwindTableEntry() const { - return hasUWTable() || !doesNotThrow() || hasPersonalityFn(); - } - - /// Determine if the function returns a structure through first - /// or second pointer argument. - bool hasStructRetAttr() const { - return AttributeSets.hasParamAttr(0, Attribute::StructRet) || - AttributeSets.hasParamAttr(1, Attribute::StructRet); - } - - /// Determine if the parameter or return value is marked with NoAlias - /// attribute. - bool returnDoesNotAlias() const { - return AttributeSets.hasRetAttr(Attribute::NoAlias); - } - void setReturnDoesNotAlias() { addRetAttr(Attribute::NoAlias); } - - /// Do not optimize this function (-O0). - bool hasOptNone() const { return hasFnAttribute(Attribute::OptimizeNone); } - - /// Optimize this function for minimum size (-Oz). - bool hasMinSize() const { return hasFnAttribute(Attribute::MinSize); } - - /// Optimize this function for size (-Os) or minimum size (-Oz). - bool hasOptSize() const { - return hasFnAttribute(Attribute::OptimizeForSize) || hasMinSize(); - } - - /// Returns the denormal handling type for the default rounding mode of the - /// function. - DenormalMode getDenormalMode(const fltSemantics &FPType) const; - - /// copyAttributesFrom - copy all additional attributes (those not needed to - /// create a Function) from the Function Src to this one. - void copyAttributesFrom(const Function *Src); - - /// deleteBody - This method deletes the body of the function, and converts - /// the linkage to external. - /// - void deleteBody() { - dropAllReferences(); - setLinkage(ExternalLinkage); - } - - /// removeFromParent - This method unlinks 'this' from the containing module, - /// but does not delete it. - /// - void removeFromParent(); - - /// eraseFromParent - This method unlinks 'this' from the containing module - /// and deletes it. - /// - void eraseFromParent(); - - /// Steal arguments from another function. - /// - /// Drop this function's arguments and splice in the ones from \c Src. - /// Requires that this has no function body. - void stealArgumentListFrom(Function &Src); - - /// Get the underlying elements of the Function... the basic block list is - /// empty for external functions. - /// - const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } - BasicBlockListType &getBasicBlockList() { return BasicBlocks; } - - static BasicBlockListType Function::*getSublistAccess(BasicBlock*) { - return &Function::BasicBlocks; - } - - const BasicBlock &getEntryBlock() const { return front(); } - BasicBlock &getEntryBlock() { return front(); } - - //===--------------------------------------------------------------------===// - // Symbol Table Accessing functions... - - /// getSymbolTable() - Return the symbol table if any, otherwise nullptr. - /// - inline ValueSymbolTable *getValueSymbolTable() { return SymTab.get(); } - inline const ValueSymbolTable *getValueSymbolTable() const { - return SymTab.get(); - } - - //===--------------------------------------------------------------------===// - // BasicBlock iterator forwarding functions - // - iterator begin() { return BasicBlocks.begin(); } - const_iterator begin() const { return BasicBlocks.begin(); } - iterator end () { return BasicBlocks.end(); } - const_iterator end () const { return BasicBlocks.end(); } - - size_t size() const { return BasicBlocks.size(); } - bool empty() const { return BasicBlocks.empty(); } - const BasicBlock &front() const { return BasicBlocks.front(); } - BasicBlock &front() { return BasicBlocks.front(); } - const BasicBlock &back() const { return BasicBlocks.back(); } - BasicBlock &back() { return BasicBlocks.back(); } - -/// @name Function Argument Iteration -/// @{ - - arg_iterator arg_begin() { - CheckLazyArguments(); - return Arguments; - } - const_arg_iterator arg_begin() const { - CheckLazyArguments(); - return Arguments; - } - - arg_iterator arg_end() { - CheckLazyArguments(); - return Arguments + NumArgs; - } - const_arg_iterator arg_end() const { - CheckLazyArguments(); - return Arguments + NumArgs; - } - - Argument* getArg(unsigned i) const { - assert (i < NumArgs && "getArg() out of range!"); - CheckLazyArguments(); - return Arguments + i; - } - - iterator_range args() { - return make_range(arg_begin(), arg_end()); - } - iterator_range args() const { - return make_range(arg_begin(), arg_end()); - } - -/// @} - - size_t arg_size() const { return NumArgs; } - bool arg_empty() const { return arg_size() == 0; } - - /// Check whether this function has a personality function. - bool hasPersonalityFn() const { - return getSubclassDataFromValue() & (1<<3); - } - - /// Get the personality function associated with this function. - Constant *getPersonalityFn() const; - void setPersonalityFn(Constant *Fn); - - /// Check whether this function has prefix data. - bool hasPrefixData() const { - return getSubclassDataFromValue() & (1<<1); - } - - /// Get the prefix data associated with this function. - Constant *getPrefixData() const; - void setPrefixData(Constant *PrefixData); - - /// Check whether this function has prologue data. - bool hasPrologueData() const { - return getSubclassDataFromValue() & (1<<2); - } - - /// Get the prologue data associated with this function. - Constant *getPrologueData() const; - void setPrologueData(Constant *PrologueData); - - /// Print the function to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr, - bool ShouldPreserveUseListOrder = false, - bool IsForDebug = false) const; - - /// viewCFG - This function is meant for use from the debugger. You can just - /// say 'call F->viewCFG()' and a ghostview window should pop up from the - /// program, displaying the CFG of the current function with the code for each - /// basic block inside. This depends on there being a 'dot' and 'gv' program - /// in your path. - /// - void viewCFG() const; - - /// Extended form to print edge weights. - void viewCFG(bool ViewCFGOnly, const BlockFrequencyInfo *BFI, - const BranchProbabilityInfo *BPI) const; - - /// viewCFGOnly - This function is meant for use from the debugger. It works - /// just like viewCFG, but it does not include the contents of basic blocks - /// into the nodes, just the label. If you are only interested in the CFG - /// this can make the graph smaller. - /// - void viewCFGOnly() const; - - /// Extended form to print edge weights. - void viewCFGOnly(const BlockFrequencyInfo *BFI, - const BranchProbabilityInfo *BPI) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::FunctionVal; - } - - /// dropAllReferences() - This method causes all the subinstructions to "let - /// go" of all references that they are maintaining. This allows one to - /// 'delete' a whole module at a time, even though there may be circular - /// references... first all references are dropped, and all use counts go to - /// zero. Then everything is deleted for real. Note that no operations are - /// valid on an object that has "dropped all references", except operator - /// delete. - /// - /// Since no other object in the module can have references into the body of a - /// function, dropping all references deletes the entire body of the function, - /// including any contained basic blocks. - /// - void dropAllReferences(); - - /// hasAddressTaken - returns true if there are any uses of this function - /// other than direct calls or invokes to it, or blockaddress expressions. - /// Optionally passes back an offending user for diagnostic purposes, - /// ignores callback uses, assume like pointer annotation calls, references in - /// llvm.used and llvm.compiler.used variables, and operand bundle - /// "clang.arc.attachedcall". - bool hasAddressTaken(const User ** = nullptr, - bool IgnoreCallbackUses = false, - bool IgnoreAssumeLikeCalls = true, - bool IngoreLLVMUsed = false, - bool IgnoreARCAttachedCall = false) const; - - /// isDefTriviallyDead - Return true if it is trivially safe to remove - /// this function definition from the module (because it isn't externally - /// visible, does not have its address taken, and has no callers). To make - /// this more accurate, call removeDeadConstantUsers first. - bool isDefTriviallyDead() const; - - /// callsFunctionThatReturnsTwice - Return true if the function has a call to - /// setjmp or other function that gcc recognizes as "returning twice". - bool callsFunctionThatReturnsTwice() const; - - /// Set the attached subprogram. - /// - /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. - void setSubprogram(DISubprogram *SP); - - /// Get the attached subprogram. - /// - /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result - /// to \a DISubprogram. - DISubprogram *getSubprogram() const; - - /// Returns true if we should emit debug info for profiling. - bool isDebugInfoForProfiling() const; - - /// Check if null pointer dereferencing is considered undefined behavior for - /// the function. - /// Return value: false => null pointer dereference is undefined. - /// Return value: true => null pointer dereference is not undefined. - bool nullPointerIsDefined() const; - -private: - void allocHungoffUselist(); - template void setHungoffOperand(Constant *C); - - /// Shadow Value::setValueSubclassData with a private forwarding method so - /// that subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } - void setValueSubclassDataBit(unsigned Bit, bool On); -}; - -/// Check whether null pointer dereferencing is considered undefined behavior -/// for a given function or an address space. -/// Null pointer access in non-zero address space is not considered undefined. -/// Return value: false => null pointer dereference is undefined. -/// Return value: true => null pointer dereference is not undefined. -bool NullPointerIsDefined(const Function *F, unsigned AS = 0); - -template <> -struct OperandTraits : public HungoffOperandTraits<3> {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value) - -} // end namespace llvm - -#endif // LLVM_IR_FUNCTION_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GCStrategy.h b/suite/synctools/tablegen/include/llvm/IR/GCStrategy.h deleted file mode 100644 index d42fcf5534..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GCStrategy.h +++ /dev/null @@ -1,139 +0,0 @@ -//===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// GCStrategy coordinates code generation algorithms and implements some itself -// in order to generate code compatible with a target code generator as -// specified in a function's 'gc' attribute. Algorithms are enabled by setting -// flags in a subclass's constructor, and some virtual methods can be -// overridden. -// -// GCStrategy is relevant for implementations using either gc.root or -// gc.statepoint based lowering strategies, but is currently focused mostly on -// options for gc.root. This will change over time. -// -// When requested by a subclass of GCStrategy, the gc.root implementation will -// populate GCModuleInfo and GCFunctionInfo with that about each Function in -// the Module that opts in to garbage collection. Specifically: -// -// - Safe points -// Garbage collection is generally only possible at certain points in code. -// GCStrategy can request that the collector insert such points: -// -// - At and after any call to a subroutine -// - Before returning from the current function -// - Before backwards branches (loops) -// -// - Roots -// When a reference to a GC-allocated object exists on the stack, it must be -// stored in an alloca registered with llvm.gcoot. -// -// This information can used to emit the metadata tables which are required by -// the target garbage collector runtime. -// -// When used with gc.statepoint, information about safepoint and roots can be -// found in the binary StackMap section after code generation. Safepoint -// placement is currently the responsibility of the frontend, though late -// insertion support is planned. gc.statepoint does not currently support -// custom stack map formats; such can be generated by parsing the standard -// stack map section if desired. -// -// The read and write barrier support can be used with either implementation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GCSTRATEGY_H -#define LLVM_IR_GCSTRATEGY_H - -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/Registry.h" -#include - -namespace llvm { - -class Type; - -/// GCStrategy describes a garbage collector algorithm's code generation -/// requirements, and provides overridable hooks for those needs which cannot -/// be abstractly described. GCStrategy objects must be looked up through -/// the Function. The objects themselves are owned by the Context and must -/// be immutable. -class GCStrategy { -private: - friend class GCModuleInfo; - - std::string Name; - -protected: - bool UseStatepoints = false; /// Uses gc.statepoints as opposed to gc.roots, - /// if set, none of the other options can be - /// anything but their default values. - - bool NeededSafePoints = false; ///< if set, calls are inferred to be safepoints - bool UsesMetadata = false; ///< If set, backend must emit metadata tables. - -public: - GCStrategy(); - virtual ~GCStrategy() = default; - - /// Return the name of the GC strategy. This is the value of the collector - /// name string specified on functions which use this strategy. - const std::string &getName() const { return Name; } - - /// Returns true if this strategy is expecting the use of gc.statepoints, - /// and false otherwise. - bool useStatepoints() const { return UseStatepoints; } - - /** @name Statepoint Specific Properties */ - ///@{ - - /// If the type specified can be reliably distinguished, returns true for - /// pointers to GC managed locations and false for pointers to non-GC - /// managed locations. Note a GCStrategy can always return 'None' (i.e. an - /// empty optional indicating it can't reliably distinguish. - virtual Optional isGCManagedPointer(const Type *Ty) const { - return None; - } - ///@} - - /** @name GCRoot Specific Properties - * These properties and overrides only apply to collector strategies using - * GCRoot. - */ - ///@{ - - /// True if safe points need to be inferred on call sites - bool needsSafePoints() const { return NeededSafePoints; } - - /// If set, appropriate metadata tables must be emitted by the back-end - /// (assembler, JIT, or otherwise). For statepoint, this method is - /// currently unsupported. The stackmap information can be found in the - /// StackMap section as described in the documentation. - bool usesMetadata() const { return UsesMetadata; } - - ///@} -}; - -/// Subclasses of GCStrategy are made available for use during compilation by -/// adding them to the global GCRegistry. This can done either within the -/// LLVM source tree or via a loadable plugin. An example registration -/// would be: -/// static GCRegistry::Add X("custom-name", -/// "my custom supper fancy gc strategy"); -/// -/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also -/// register your GCMetadataPrinter subclass with the -/// GCMetadataPrinterRegistery as well. -using GCRegistry = Registry; - -/// Lookup the GCStrategy object associated with the given gc name. -std::unique_ptr getGCStrategy(const StringRef Name); - -} // end namespace llvm - -#endif // LLVM_IR_GCSTRATEGY_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GVMaterializer.h b/suite/synctools/tablegen/include/llvm/IR/GVMaterializer.h deleted file mode 100644 index d62da41ebc..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GVMaterializer.h +++ /dev/null @@ -1,51 +0,0 @@ -//===- GVMaterializer.h - Interface for GV materializers --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides an abstract interface for loading a module from some -// place. This interface allows incremental or random access loading of -// functions from the file. This is useful for applications like JIT compilers -// or interprocedural optimizers that do not need the entire program in memory -// at the same time. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GVMATERIALIZER_H -#define LLVM_IR_GVMATERIALIZER_H - -#include - -namespace llvm { - -class Error; -class GlobalValue; -class StructType; - -class GVMaterializer { -protected: - GVMaterializer() = default; - -public: - virtual ~GVMaterializer(); - - /// Make sure the given GlobalValue is fully read. - /// - virtual Error materialize(GlobalValue *GV) = 0; - - /// Make sure the entire Module has been completely read. - /// - virtual Error materializeModule() = 0; - - virtual Error materializeMetadata() = 0; - virtual void setStripDebugInfo() = 0; - - virtual std::vector getIdentifiedStructTypes() const = 0; -}; - -} // end namespace llvm - -#endif // LLVM_IR_GVMATERIALIZER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GetElementPtrTypeIterator.h b/suite/synctools/tablegen/include/llvm/IR/GetElementPtrTypeIterator.h deleted file mode 100644 index 1fa9962297..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GetElementPtrTypeIterator.h +++ /dev/null @@ -1,159 +0,0 @@ -//===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements an iterator for walking through the types indexed by -// getelementptr instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H -#define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/User.h" -#include "llvm/Support/Casting.h" -#include -#include -#include -#include - -namespace llvm { - -template -class generic_gep_type_iterator { - - ItTy OpIt; - PointerUnion CurTy; - - generic_gep_type_iterator() = default; - -public: - using iterator_category = std::forward_iterator_tag; - using value_type = Type *; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - static generic_gep_type_iterator begin(Type *Ty, ItTy It) { - generic_gep_type_iterator I; - I.CurTy = Ty; - I.OpIt = It; - return I; - } - - static generic_gep_type_iterator end(ItTy It) { - generic_gep_type_iterator I; - I.OpIt = It; - return I; - } - - bool operator==(const generic_gep_type_iterator &x) const { - return OpIt == x.OpIt; - } - - bool operator!=(const generic_gep_type_iterator &x) const { - return !operator==(x); - } - - // FIXME: Make this the iterator's operator*() after the 4.0 release. - // operator*() had a different meaning in earlier releases, so we're - // temporarily not giving this iterator an operator*() to avoid a subtle - // semantics break. - Type *getIndexedType() const { - if (auto *T = CurTy.dyn_cast()) - return T; - return CurTy.get()->getTypeAtIndex(getOperand()); - } - - Value *getOperand() const { return const_cast(&**OpIt); } - - generic_gep_type_iterator &operator++() { // Preincrement - Type *Ty = getIndexedType(); - if (auto *ATy = dyn_cast(Ty)) - CurTy = ATy->getElementType(); - else if (auto *VTy = dyn_cast(Ty)) - CurTy = VTy->getElementType(); - else - CurTy = dyn_cast(Ty); - ++OpIt; - return *this; - } - - generic_gep_type_iterator operator++(int) { // Postincrement - generic_gep_type_iterator tmp = *this; - ++*this; - return tmp; - } - - // All of the below API is for querying properties of the "outer type", i.e. - // the type that contains the indexed type. Most of the time this is just - // the type that was visited immediately prior to the indexed type, but for - // the first element this is an unbounded array of the GEP's source element - // type, for which there is no clearly corresponding IR type (we've - // historically used a pointer type as the outer type in this case, but - // pointers will soon lose their element type). - // - // FIXME: Most current users of this class are just interested in byte - // offsets (a few need to know whether the outer type is a struct because - // they are trying to replace a constant with a variable, which is only - // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp); - // we should provide a more minimal API here that exposes not much more than - // that. - - bool isStruct() const { return CurTy.is(); } - bool isSequential() const { return CurTy.is(); } - - StructType *getStructType() const { return CurTy.get(); } - - StructType *getStructTypeOrNull() const { - return CurTy.dyn_cast(); - } -}; - - using gep_type_iterator = generic_gep_type_iterator<>; - - inline gep_type_iterator gep_type_begin(const User *GEP) { - auto *GEPOp = cast(GEP); - return gep_type_iterator::begin( - GEPOp->getSourceElementType(), - GEP->op_begin() + 1); - } - - inline gep_type_iterator gep_type_end(const User *GEP) { - return gep_type_iterator::end(GEP->op_end()); - } - - inline gep_type_iterator gep_type_begin(const User &GEP) { - auto &GEPOp = cast(GEP); - return gep_type_iterator::begin( - GEPOp.getSourceElementType(), - GEP.op_begin() + 1); - } - - inline gep_type_iterator gep_type_end(const User &GEP) { - return gep_type_iterator::end(GEP.op_end()); - } - - template - inline generic_gep_type_iterator - gep_type_begin(Type *Op0, ArrayRef A) { - return generic_gep_type_iterator::begin(Op0, A.begin()); - } - - template - inline generic_gep_type_iterator - gep_type_end(Type * /*Op0*/, ArrayRef A) { - return generic_gep_type_iterator::end(A.end()); - } - -} // end namespace llvm - -#endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GlobalAlias.h b/suite/synctools/tablegen/include/llvm/IR/GlobalAlias.h deleted file mode 100644 index 01134448a8..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GlobalAlias.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the GlobalAlias class, which -// represents a single function or variable alias in the IR. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALALIAS_H -#define LLVM_IR_GLOBALALIAS_H - -#include "llvm/ADT/ilist_node.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/Value.h" - -namespace llvm { - -class Twine; -class Module; -template class SymbolTableListTraits; - -class GlobalAlias : public GlobalValue, public ilist_node { - friend class SymbolTableListTraits; - - GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, Constant *Aliasee, Module *Parent); - -public: - GlobalAlias(const GlobalAlias &) = delete; - GlobalAlias &operator=(const GlobalAlias &) = delete; - - /// If a parent module is specified, the alias is automatically inserted into - /// the end of the specified module's alias list. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Constant *Aliasee, Module *Parent); - - // Without the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Module *Parent); - - // The module is taken from the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee); - - // Type, Parent and AddressSpace taken from the Aliasee. - static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee); - - // Linkage, Type, Parent and AddressSpace taken from the Aliasee. - static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); - - // allocate space for exactly one operand - void *operator new(size_t S) { return User::operator new(S, 1); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - - void copyAttributesFrom(const GlobalAlias *Src) { - GlobalValue::copyAttributesFrom(Src); - } - - /// removeFromParent - This method unlinks 'this' from the containing module, - /// but does not delete it. - /// - void removeFromParent(); - - /// eraseFromParent - This method unlinks 'this' from the containing module - /// and deletes it. - /// - void eraseFromParent(); - - /// These methods retrieve and set alias target. - void setAliasee(Constant *Aliasee); - const Constant *getAliasee() const { - return static_cast(Op<0>().get()); - } - Constant *getAliasee() { return static_cast(Op<0>().get()); } - - const GlobalObject *getAliaseeObject() const; - GlobalObject *getAliaseeObject() { - return const_cast( - static_cast(this)->getAliaseeObject()); - } - - static bool isValidLinkage(LinkageTypes L) { - return isExternalLinkage(L) || isLocalLinkage(L) || - isWeakLinkage(L) || isLinkOnceLinkage(L); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::GlobalAliasVal; - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant) - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALALIAS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GlobalIFunc.h b/suite/synctools/tablegen/include/llvm/IR/GlobalIFunc.h deleted file mode 100644 index 10088ee2ff..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GlobalIFunc.h +++ /dev/null @@ -1,101 +0,0 @@ -//===-------- llvm/GlobalIFunc.h - GlobalIFunc class ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the declaration of the GlobalIFunc class, which -/// represents a single indirect function in the IR. Indirect function uses -/// ELF symbol type extension to mark that the address of a declaration should -/// be resolved at runtime by calling a resolver function. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALIFUNC_H -#define LLVM_IR_GLOBALIFUNC_H - -#include "llvm/ADT/ilist_node.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/Value.h" - -namespace llvm { - -class Twine; -class Module; - -// Traits class for using GlobalIFunc in symbol table in Module. -template class SymbolTableListTraits; - -class GlobalIFunc final : public GlobalObject, public ilist_node { - friend class SymbolTableListTraits; - - GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, Constant *Resolver, Module *Parent); - -public: - GlobalIFunc(const GlobalIFunc &) = delete; - GlobalIFunc &operator=(const GlobalIFunc &) = delete; - - /// If a parent module is specified, the ifunc is automatically inserted into - /// the end of the specified module's ifunc list. - static GlobalIFunc *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Constant *Resolver, Module *Parent); - - // allocate space for exactly one operand - void *operator new(size_t S) { return User::operator new(S, 1); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - - void copyAttributesFrom(const GlobalIFunc *Src) { - GlobalObject::copyAttributesFrom(Src); - } - - /// This method unlinks 'this' from the containing module, but does not - /// delete it. - void removeFromParent(); - - /// This method unlinks 'this' from the containing module and deletes it. - void eraseFromParent(); - - /// These methods retrieve and set ifunc resolver function. - void setResolver(Constant *Resolver) { Op<0>().set(Resolver); } - const Constant *getResolver() const { - return static_cast(Op<0>().get()); - } - Constant *getResolver() { return static_cast(Op<0>().get()); } - - // Return the resolver function after peeling off potential ConstantExpr - // indirection. - const Function *getResolverFunction() const; - Function *getResolverFunction() { - return const_cast( - static_cast(this)->getResolverFunction()); - } - - static FunctionType *getResolverFunctionType(Type *IFuncValTy) { - return FunctionType::get(IFuncValTy->getPointerTo(), false); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::GlobalIFuncVal; - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalIFunc, Constant) - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALIFUNC_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GlobalObject.h b/suite/synctools/tablegen/include/llvm/IR/GlobalObject.h deleted file mode 100644 index 0bb9fd7300..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GlobalObject.h +++ /dev/null @@ -1,172 +0,0 @@ -//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This represents an independent object. That is, a function or a global -// variable, but not an alias. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALOBJECT_H -#define LLVM_IR_GLOBALOBJECT_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Alignment.h" - -namespace llvm { - -class Comdat; -class Metadata; - -class GlobalObject : public GlobalValue { -public: - // VCallVisibility - values for visibility metadata attached to vtables. This - // describes the scope in which a virtual call could end up being dispatched - // through this vtable. - enum VCallVisibility { - // Type is potentially visible to external code. - VCallVisibilityPublic = 0, - // Type is only visible to code which will be in the current Module after - // LTO internalization. - VCallVisibilityLinkageUnit = 1, - // Type is only visible to code in the current Module. - VCallVisibilityTranslationUnit = 2, - }; - -protected: - GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, - LinkageTypes Linkage, const Twine &Name, - unsigned AddressSpace = 0) - : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name, AddressSpace), - ObjComdat(nullptr) { - setGlobalValueSubClassData(0); - } - ~GlobalObject(); - - Comdat *ObjComdat; - enum { - LastAlignmentBit = 5, - HasSectionHashEntryBit, - - GlobalObjectBits, - }; - static const unsigned GlobalObjectSubClassDataBits = - GlobalValueSubClassDataBits - GlobalObjectBits; - -private: - static const unsigned AlignmentBits = LastAlignmentBit + 1; - static const unsigned AlignmentMask = (1 << AlignmentBits) - 1; - static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1; - -public: - GlobalObject(const GlobalObject &) = delete; - - /// FIXME: Remove this function once transition to Align is over. - uint64_t getAlignment() const { - MaybeAlign Align = getAlign(); - return Align ? Align->value() : 0; - } - - /// Returns the alignment of the given variable or function. - /// - /// Note that for functions this is the alignment of the code, not the - /// alignment of a function pointer. - MaybeAlign getAlign() const { - unsigned Data = getGlobalValueSubClassData(); - unsigned AlignmentData = Data & AlignmentMask; - return decodeMaybeAlign(AlignmentData); - } - - void setAlignment(MaybeAlign Align); - - unsigned getGlobalObjectSubClassData() const { - unsigned ValueData = getGlobalValueSubClassData(); - return ValueData >> GlobalObjectBits; - } - - void setGlobalObjectSubClassData(unsigned Val) { - unsigned OldData = getGlobalValueSubClassData(); - setGlobalValueSubClassData((OldData & GlobalObjectMask) | - (Val << GlobalObjectBits)); - assert(getGlobalObjectSubClassData() == Val && "representation error"); - } - - /// Check if this global has a custom object file section. - /// - /// This is more efficient than calling getSection() and checking for an empty - /// string. - bool hasSection() const { - return getGlobalValueSubClassData() & (1 << HasSectionHashEntryBit); - } - - /// Get the custom section of this global if it has one. - /// - /// If this global does not have a custom section, this will be empty and the - /// default object file section (.text, .data, etc) will be used. - StringRef getSection() const { - return hasSection() ? getSectionImpl() : StringRef(); - } - - /// Change the section for this global. - /// - /// Setting the section to the empty string tells LLVM to choose an - /// appropriate default object file section. - void setSection(StringRef S); - - bool hasComdat() const { return getComdat() != nullptr; } - const Comdat *getComdat() const { return ObjComdat; } - Comdat *getComdat() { return ObjComdat; } - void setComdat(Comdat *C); - - using Value::addMetadata; - using Value::clearMetadata; - using Value::eraseMetadata; - using Value::getAllMetadata; - using Value::getMetadata; - using Value::hasMetadata; - using Value::setMetadata; - - /// Copy metadata from Src, adjusting offsets by Offset. - void copyMetadata(const GlobalObject *Src, unsigned Offset); - - void addTypeMetadata(unsigned Offset, Metadata *TypeID); - void setVCallVisibilityMetadata(VCallVisibility Visibility); - VCallVisibility getVCallVisibility() const; - - /// Returns true if the alignment of the value can be unilaterally - /// increased. - /// - /// Note that for functions this is the alignment of the code, not the - /// alignment of a function pointer. - bool canIncreaseAlignment() const; - -protected: - void copyAttributesFrom(const GlobalObject *Src); - -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::FunctionVal || - V->getValueID() == Value::GlobalVariableVal || - V->getValueID() == Value::GlobalIFuncVal; - } - -private: - void setGlobalObjectFlag(unsigned Bit, bool Val) { - unsigned Mask = 1 << Bit; - setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | - (Val ? Mask : 0u)); - } - - StringRef getSectionImpl() const; -}; - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALOBJECT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GlobalValue.h b/suite/synctools/tablegen/include/llvm/IR/GlobalValue.h deleted file mode 100644 index d7236ca0a2..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GlobalValue.h +++ /dev/null @@ -1,599 +0,0 @@ -//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a common base class of all globally definable objects. As such, -// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is -// used because you can do certain things with these global objects that you -// can't do to anything else. For example, use the address of one as a -// constant. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALVALUE_H -#define LLVM_IR_GLOBALVALUE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MD5.h" -#include -#include -#include - -namespace llvm { - -class Comdat; -class ConstantRange; -class Error; -class GlobalObject; -class Module; - -namespace Intrinsic { -typedef unsigned ID; -} // end namespace Intrinsic - -class GlobalValue : public Constant { -public: - /// An enumeration for the kinds of linkage for global values. - enum LinkageTypes { - ExternalLinkage = 0,///< Externally visible function - AvailableExternallyLinkage, ///< Available for inspection, not emission. - LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) - LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. - WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) - WeakODRLinkage, ///< Same, but only replaced by something equivalent. - AppendingLinkage, ///< Special purpose, only applies to global arrays - InternalLinkage, ///< Rename collisions when linking (static functions). - PrivateLinkage, ///< Like Internal, but omit from symbol table. - ExternalWeakLinkage,///< ExternalWeak linkage description. - CommonLinkage ///< Tentative definitions. - }; - - /// An enumeration for the kinds of visibility of global values. - enum VisibilityTypes { - DefaultVisibility = 0, ///< The GV is visible - HiddenVisibility, ///< The GV is hidden - ProtectedVisibility ///< The GV is protected - }; - - /// Storage classes of global values for PE targets. - enum DLLStorageClassTypes { - DefaultStorageClass = 0, - DLLImportStorageClass = 1, ///< Function to be imported from DLL - DLLExportStorageClass = 2 ///< Function to be accessible from DLL. - }; - -protected: - GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, - LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) - : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), - ValueType(Ty), Visibility(DefaultVisibility), - UnnamedAddrVal(unsigned(UnnamedAddr::None)), - DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), - HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false), - IntID((Intrinsic::ID)0U), Parent(nullptr) { - setLinkage(Linkage); - setName(Name); - } - - Type *ValueType; - - static const unsigned GlobalValueSubClassDataBits = 16; - - // All bitfields use unsigned as the underlying type so that MSVC will pack - // them. - unsigned Linkage : 4; // The linkage of this global - unsigned Visibility : 2; // The visibility style of this global - unsigned UnnamedAddrVal : 2; // This value's address is not significant - unsigned DllStorageClass : 2; // DLL storage class - - unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is - // the desired model? - - /// True if the function's name starts with "llvm.". This corresponds to the - /// value of Function::isIntrinsic(), which may be true even if - /// Function::intrinsicID() returns Intrinsic::not_intrinsic. - unsigned HasLLVMReservedName : 1; - - /// If true then there is a definition within the same linkage unit and that - /// definition cannot be runtime preempted. - unsigned IsDSOLocal : 1; - - /// True if this symbol has a partition name assigned (see - /// https://lld.llvm.org/Partitions.html). - unsigned HasPartition : 1; - -private: - // Give subclasses access to what otherwise would be wasted padding. - // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32. - unsigned SubClassData : GlobalValueSubClassDataBits; - - friend class Constant; - - void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); - - /// Returns true if the definition of this global may be replaced by a - /// differently optimized variant of the same source level function at link - /// time. - bool mayBeDerefined() const { - switch (getLinkage()) { - case WeakODRLinkage: - case LinkOnceODRLinkage: - case AvailableExternallyLinkage: - return true; - - case WeakAnyLinkage: - case LinkOnceAnyLinkage: - case CommonLinkage: - case ExternalWeakLinkage: - case ExternalLinkage: - case AppendingLinkage: - case InternalLinkage: - case PrivateLinkage: - return isInterposable(); - } - - llvm_unreachable("Fully covered switch above!"); - } - -protected: - /// The intrinsic ID for this subclass (which must be a Function). - /// - /// This member is defined by this class, but not used for anything. - /// Subclasses can use it to store their intrinsic ID, if they have one. - /// - /// This is stored here to save space in Function on 64-bit hosts. - Intrinsic::ID IntID; - - unsigned getGlobalValueSubClassData() const { - return SubClassData; - } - void setGlobalValueSubClassData(unsigned V) { - assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit"); - SubClassData = V; - } - - Module *Parent; // The containing module. - - // Used by SymbolTableListTraits. - void setParent(Module *parent) { - Parent = parent; - } - - ~GlobalValue() { - removeDeadConstantUsers(); // remove any dead constants using this. - } - -public: - enum ThreadLocalMode { - NotThreadLocal = 0, - GeneralDynamicTLSModel, - LocalDynamicTLSModel, - InitialExecTLSModel, - LocalExecTLSModel - }; - - GlobalValue(const GlobalValue &) = delete; - - unsigned getAddressSpace() const; - - enum class UnnamedAddr { - None, - Local, - Global, - }; - - bool hasGlobalUnnamedAddr() const { - return getUnnamedAddr() == UnnamedAddr::Global; - } - - /// Returns true if this value's address is not significant in this module. - /// This attribute is intended to be used only by the code generator and LTO - /// to allow the linker to decide whether the global needs to be in the symbol - /// table. It should probably not be used in optimizations, as the value may - /// have uses outside the module; use hasGlobalUnnamedAddr() instead. - bool hasAtLeastLocalUnnamedAddr() const { - return getUnnamedAddr() != UnnamedAddr::None; - } - - UnnamedAddr getUnnamedAddr() const { - return UnnamedAddr(UnnamedAddrVal); - } - void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } - - static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { - if (A == UnnamedAddr::None || B == UnnamedAddr::None) - return UnnamedAddr::None; - if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) - return UnnamedAddr::Local; - return UnnamedAddr::Global; - } - - bool hasComdat() const { return getComdat() != nullptr; } - const Comdat *getComdat() const; - Comdat *getComdat() { - return const_cast( - static_cast(this)->getComdat()); - } - - VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } - bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } - bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } - bool hasProtectedVisibility() const { - return Visibility == ProtectedVisibility; - } - void setVisibility(VisibilityTypes V) { - assert((!hasLocalLinkage() || V == DefaultVisibility) && - "local linkage requires default visibility"); - Visibility = V; - if (isImplicitDSOLocal()) - setDSOLocal(true); - } - - /// If the value is "Thread Local", its value isn't shared by the threads. - bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } - void setThreadLocal(bool Val) { - setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); - } - void setThreadLocalMode(ThreadLocalMode Val) { - assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); - ThreadLocal = Val; - } - ThreadLocalMode getThreadLocalMode() const { - return static_cast(ThreadLocal); - } - - DLLStorageClassTypes getDLLStorageClass() const { - return DLLStorageClassTypes(DllStorageClass); - } - bool hasDLLImportStorageClass() const { - return DllStorageClass == DLLImportStorageClass; - } - bool hasDLLExportStorageClass() const { - return DllStorageClass == DLLExportStorageClass; - } - void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } - - bool hasSection() const { return !getSection().empty(); } - StringRef getSection() const; - - /// Global values are always pointers. - PointerType *getType() const { return cast(User::getType()); } - - Type *getValueType() const { return ValueType; } - - bool isImplicitDSOLocal() const { - return hasLocalLinkage() || - (!hasDefaultVisibility() && !hasExternalWeakLinkage()); - } - - void setDSOLocal(bool Local) { IsDSOLocal = Local; } - - bool isDSOLocal() const { - return IsDSOLocal; - } - - bool hasPartition() const { - return HasPartition; - } - StringRef getPartition() const; - void setPartition(StringRef Part); - - static LinkageTypes getLinkOnceLinkage(bool ODR) { - return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; - } - static LinkageTypes getWeakLinkage(bool ODR) { - return ODR ? WeakODRLinkage : WeakAnyLinkage; - } - - static bool isExternalLinkage(LinkageTypes Linkage) { - return Linkage == ExternalLinkage; - } - static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { - return Linkage == AvailableExternallyLinkage; - } - static bool isLinkOnceAnyLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceAnyLinkage; - } - static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceODRLinkage; - } - static bool isLinkOnceLinkage(LinkageTypes Linkage) { - return isLinkOnceAnyLinkage(Linkage) || isLinkOnceODRLinkage(Linkage); - } - static bool isWeakAnyLinkage(LinkageTypes Linkage) { - return Linkage == WeakAnyLinkage; - } - static bool isWeakODRLinkage(LinkageTypes Linkage) { - return Linkage == WeakODRLinkage; - } - static bool isWeakLinkage(LinkageTypes Linkage) { - return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage); - } - static bool isAppendingLinkage(LinkageTypes Linkage) { - return Linkage == AppendingLinkage; - } - static bool isInternalLinkage(LinkageTypes Linkage) { - return Linkage == InternalLinkage; - } - static bool isPrivateLinkage(LinkageTypes Linkage) { - return Linkage == PrivateLinkage; - } - static bool isLocalLinkage(LinkageTypes Linkage) { - return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage); - } - static bool isExternalWeakLinkage(LinkageTypes Linkage) { - return Linkage == ExternalWeakLinkage; - } - static bool isCommonLinkage(LinkageTypes Linkage) { - return Linkage == CommonLinkage; - } - static bool isValidDeclarationLinkage(LinkageTypes Linkage) { - return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage); - } - - /// Whether the definition of this global may be replaced by something - /// non-equivalent at link time. For example, if a function has weak linkage - /// then the code defining it may be replaced by different code. - static bool isInterposableLinkage(LinkageTypes Linkage) { - switch (Linkage) { - case WeakAnyLinkage: - case LinkOnceAnyLinkage: - case CommonLinkage: - case ExternalWeakLinkage: - return true; - - case AvailableExternallyLinkage: - case LinkOnceODRLinkage: - case WeakODRLinkage: - // The above three cannot be overridden but can be de-refined. - - case ExternalLinkage: - case AppendingLinkage: - case InternalLinkage: - case PrivateLinkage: - return false; - } - llvm_unreachable("Fully covered switch above!"); - } - - /// Whether the definition of this global may be discarded if it is not used - /// in its compilation unit. - static bool isDiscardableIfUnused(LinkageTypes Linkage) { - return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage) || - isAvailableExternallyLinkage(Linkage); - } - - /// Whether the definition of this global may be replaced at link time. NB: - /// Using this method outside of the code generators is almost always a - /// mistake: when working at the IR level use isInterposable instead as it - /// knows about ODR semantics. - static bool isWeakForLinker(LinkageTypes Linkage) { - return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || - Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || - Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; - } - - /// Return true if the currently visible definition of this global (if any) is - /// exactly the definition we will see at runtime. - /// - /// Non-exact linkage types inhibits most non-inlining IPO, since a - /// differently optimized variant of the same function can have different - /// observable or undefined behavior than in the variant currently visible. - /// For instance, we could have started with - /// - /// void foo(int *v) { - /// int t = 5 / v[0]; - /// (void) t; - /// } - /// - /// and "refined" it to - /// - /// void foo(int *v) { } - /// - /// However, we cannot infer readnone for `foo`, since that would justify - /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause - /// undefined behavior if the linker replaces the actual call destination with - /// the unoptimized `foo`. - /// - /// Inlining is okay across non-exact linkage types as long as they're not - /// interposable (see \c isInterposable), since in such cases the currently - /// visible variant is *a* correct implementation of the original source - /// function; it just isn't the *only* correct implementation. - bool isDefinitionExact() const { - return !mayBeDerefined(); - } - - /// Return true if this global has an exact definition. - bool hasExactDefinition() const { - // While this computes exactly the same thing as - // isStrongDefinitionForLinker, the intended uses are different. This - // function is intended to help decide if specific inter-procedural - // transforms are correct, while isStrongDefinitionForLinker's intended use - // is in low level code generation. - return !isDeclaration() && isDefinitionExact(); - } - - /// Return true if this global's definition can be substituted with an - /// *arbitrary* definition at link time or load time. We cannot do any IPO or - /// inlining across interposable call edges, since the callee can be - /// replaced with something arbitrary. - bool isInterposable() const; - bool canBenefitFromLocalAlias() const; - - bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); } - bool hasAvailableExternallyLinkage() const { - return isAvailableExternallyLinkage(getLinkage()); - } - bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); } - bool hasLinkOnceAnyLinkage() const { - return isLinkOnceAnyLinkage(getLinkage()); - } - bool hasLinkOnceODRLinkage() const { - return isLinkOnceODRLinkage(getLinkage()); - } - bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); } - bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); } - bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); } - bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); } - bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); } - bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); } - bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); } - bool hasExternalWeakLinkage() const { - return isExternalWeakLinkage(getLinkage()); - } - bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); } - bool hasValidDeclarationLinkage() const { - return isValidDeclarationLinkage(getLinkage()); - } - - void setLinkage(LinkageTypes LT) { - if (isLocalLinkage(LT)) - Visibility = DefaultVisibility; - Linkage = LT; - if (isImplicitDSOLocal()) - setDSOLocal(true); - } - LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } - - bool isDiscardableIfUnused() const { - return isDiscardableIfUnused(getLinkage()); - } - - bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } - -protected: - /// Copy all additional attributes (those not needed to create a GlobalValue) - /// from the GlobalValue Src to this one. - void copyAttributesFrom(const GlobalValue *Src); - -public: - /// If the given string begins with the GlobalValue name mangling escape - /// character '\1', drop it. - /// - /// This function applies a specific mangling that is used in PGO profiles, - /// among other things. If you're trying to get a symbol name for an - /// arbitrary GlobalValue, this is not the function you're looking for; see - /// Mangler.h. - static StringRef dropLLVMManglingEscape(StringRef Name) { - if (!Name.empty() && Name[0] == '\1') - return Name.substr(1); - return Name; - } - - /// Return the modified name for a global value suitable to be - /// used as the key for a global lookup (e.g. profile or ThinLTO). - /// The value's original name is \c Name and has linkage of type - /// \c Linkage. The value is defined in module \c FileName. - static std::string getGlobalIdentifier(StringRef Name, - GlobalValue::LinkageTypes Linkage, - StringRef FileName); - - /// Return the modified name for this global value suitable to be - /// used as the key for a global lookup (e.g. profile or ThinLTO). - std::string getGlobalIdentifier() const; - - /// Declare a type to represent a global unique identifier for a global value. - /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact - /// unique way to identify a symbol. - using GUID = uint64_t; - - /// Return a 64-bit global unique ID constructed from global value name - /// (i.e. returned by getGlobalIdentifier()). - static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } - - /// Return a 64-bit global unique ID constructed from global value name - /// (i.e. returned by getGlobalIdentifier()). - GUID getGUID() const { return getGUID(getGlobalIdentifier()); } - - /// @name Materialization - /// Materialization is used to construct functions only as they're needed. - /// This - /// is useful to reduce memory usage in LLVM or parsing work done by the - /// BitcodeReader to load the Module. - /// @{ - - /// If this function's Module is being lazily streamed in functions from disk - /// or some other source, this method can be used to check to see if the - /// function has been read in yet or not. - bool isMaterializable() const; - - /// Make sure this GlobalValue is fully read. - Error materialize(); - -/// @} - - /// Return true if the primary definition of this global value is outside of - /// the current translation unit. - bool isDeclaration() const; - - bool isDeclarationForLinker() const { - if (hasAvailableExternallyLinkage()) - return true; - - return isDeclaration(); - } - - /// Returns true if this global's definition will be the one chosen by the - /// linker. - /// - /// NB! Ideally this should not be used at the IR level at all. If you're - /// interested in optimization constraints implied by the linker's ability to - /// choose an implementation, prefer using \c hasExactDefinition. - bool isStrongDefinitionForLinker() const { - return !(isDeclarationForLinker() || isWeakForLinker()); - } - - const GlobalObject *getAliaseeObject() const; - GlobalObject *getAliaseeObject() { - return const_cast( - static_cast(this)->getAliaseeObject()); - } - - /// Returns whether this is a reference to an absolute symbol. - bool isAbsoluteSymbolRef() const; - - /// If this is an absolute symbol reference, returns the range of the symbol, - /// otherwise returns None. - Optional getAbsoluteSymbolRange() const; - - /// This method unlinks 'this' from the containing module, but does not delete - /// it. - void removeFromParent(); - - /// This method unlinks 'this' from the containing module and deletes it. - void eraseFromParent(); - - /// Get the module that this global value is contained inside of... - Module *getParent() { return Parent; } - const Module *getParent() const { return Parent; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::FunctionVal || - V->getValueID() == Value::GlobalVariableVal || - V->getValueID() == Value::GlobalAliasVal || - V->getValueID() == Value::GlobalIFuncVal; - } - - /// True if GV can be left out of the object symbol table. This is the case - /// for linkonce_odr values whose address is not significant. While legal, it - /// is not normally profitable to omit them from the .o symbol table. Using - /// this analysis makes sense when the information can be passed down to the - /// linker or we are in LTO. - bool canBeOmittedFromSymbolTable() const; -}; - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALVALUE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/GlobalVariable.h b/suite/synctools/tablegen/include/llvm/IR/GlobalVariable.h deleted file mode 100644 index d3123dba6b..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/GlobalVariable.h +++ /dev/null @@ -1,264 +0,0 @@ -//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the GlobalVariable class, which -// represents a single global variable (or constant) in the VM. -// -// Global variables are constant pointers that refer to hunks of space that are -// allocated by either the VM, or by the linker in a static compiler. A global -// variable may have an initial value, which is copied into the executables .data -// area. Global Constants are required to have initializers. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALVARIABLE_H -#define LLVM_IR_GLOBALVARIABLE_H - -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/Value.h" -#include -#include - -namespace llvm { - -class Constant; -class Module; - -template class SymbolTableListTraits; -class DIGlobalVariableExpression; - -class GlobalVariable : public GlobalObject, public ilist_node { - friend class SymbolTableListTraits; - - AttributeSet Attrs; - bool isConstantGlobal : 1; // Is this a global constant? - bool isExternallyInitializedConstant : 1; // Is this a global whose value - // can change from its initial - // value before global - // initializers are run? - -public: - /// GlobalVariable ctor - If a parent module is specified, the global is - /// automatically inserted into the end of the specified modules global list. - GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, - Constant *Initializer = nullptr, const Twine &Name = "", - ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, - bool isExternallyInitialized = false); - /// GlobalVariable ctor - This creates a global and inserts it before the - /// specified other global. - GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, - Constant *Initializer, const Twine &Name = "", - GlobalVariable *InsertBefore = nullptr, - ThreadLocalMode = NotThreadLocal, - Optional AddressSpace = None, - bool isExternallyInitialized = false); - GlobalVariable(const GlobalVariable &) = delete; - GlobalVariable &operator=(const GlobalVariable &) = delete; - - ~GlobalVariable() { - dropAllReferences(); - } - - // allocate space for exactly one operand - void *operator new(size_t s) { - return User::operator new(s, 1); - } - - // delete space for exactly one operand as created in the corresponding new operator - void operator delete(void *ptr){ - assert(ptr != nullptr && "must not be nullptr"); - User *Obj = static_cast(ptr); - // Number of operands can be set to 0 after construction and initialization. Make sure - // that number of operands is reset to 1, as this is needed in User::operator delete - Obj->setGlobalVariableNumOperands(1); - User::operator delete(Obj); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Definitions have initializers, declarations don't. - /// - inline bool hasInitializer() const { return !isDeclaration(); } - - /// hasDefinitiveInitializer - Whether the global variable has an initializer, - /// and any other instances of the global (this can happen due to weak - /// linkage) are guaranteed to have the same initializer. - /// - /// Note that if you want to transform a global, you must use - /// hasUniqueInitializer() instead, because of the *_odr linkage type. - /// - /// Example: - /// - /// @a = global SomeType* null - Initializer is both definitive and unique. - /// - /// @b = global weak SomeType* null - Initializer is neither definitive nor - /// unique. - /// - /// @c = global weak_odr SomeType* null - Initializer is definitive, but not - /// unique. - inline bool hasDefinitiveInitializer() const { - return hasInitializer() && - // The initializer of a global variable may change to something arbitrary - // at link time. - !isInterposable() && - // The initializer of a global variable with the externally_initialized - // marker may change at runtime before C++ initializers are evaluated. - !isExternallyInitialized(); - } - - /// hasUniqueInitializer - Whether the global variable has an initializer, and - /// any changes made to the initializer will turn up in the final executable. - inline bool hasUniqueInitializer() const { - return - // We need to be sure this is the definition that will actually be used - isStrongDefinitionForLinker() && - // It is not safe to modify initializers of global variables with the - // external_initializer marker since the value may be changed at runtime - // before C++ initializers are evaluated. - !isExternallyInitialized(); - } - - /// getInitializer - Return the initializer for this global variable. It is - /// illegal to call this method if the global is external, because we cannot - /// tell what the value is initialized to! - /// - inline const Constant *getInitializer() const { - assert(hasInitializer() && "GV doesn't have initializer!"); - return static_cast(Op<0>().get()); - } - inline Constant *getInitializer() { - assert(hasInitializer() && "GV doesn't have initializer!"); - return static_cast(Op<0>().get()); - } - /// setInitializer - Sets the initializer for this global variable, removing - /// any existing initializer if InitVal==NULL. If this GV has type T*, the - /// initializer must have type T. - void setInitializer(Constant *InitVal); - - /// If the value is a global constant, its value is immutable throughout the - /// runtime execution of the program. Assigning a value into the constant - /// leads to undefined behavior. - /// - bool isConstant() const { return isConstantGlobal; } - void setConstant(bool Val) { isConstantGlobal = Val; } - - bool isExternallyInitialized() const { - return isExternallyInitializedConstant; - } - void setExternallyInitialized(bool Val) { - isExternallyInitializedConstant = Val; - } - - /// copyAttributesFrom - copy all additional attributes (those not needed to - /// create a GlobalVariable) from the GlobalVariable Src to this one. - void copyAttributesFrom(const GlobalVariable *Src); - - /// removeFromParent - This method unlinks 'this' from the containing module, - /// but does not delete it. - /// - void removeFromParent(); - - /// eraseFromParent - This method unlinks 'this' from the containing module - /// and deletes it. - /// - void eraseFromParent(); - - /// Drop all references in preparation to destroy the GlobalVariable. This - /// drops not only the reference to the initializer but also to any metadata. - void dropAllReferences(); - - /// Attach a DIGlobalVariableExpression. - void addDebugInfo(DIGlobalVariableExpression *GV); - - /// Fill the vector with all debug info attachments. - void getDebugInfo(SmallVectorImpl &GVs) const; - - /// Add attribute to this global. - void addAttribute(Attribute::AttrKind Kind) { - Attrs = Attrs.addAttribute(getContext(), Kind); - } - - /// Add attribute to this global. - void addAttribute(StringRef Kind, StringRef Val = StringRef()) { - Attrs = Attrs.addAttribute(getContext(), Kind, Val); - } - - /// Return true if the attribute exists. - bool hasAttribute(Attribute::AttrKind Kind) const { - return Attrs.hasAttribute(Kind); - } - - /// Return true if the attribute exists. - bool hasAttribute(StringRef Kind) const { - return Attrs.hasAttribute(Kind); - } - - /// Return true if any attributes exist. - bool hasAttributes() const { - return Attrs.hasAttributes(); - } - - /// Return the attribute object. - Attribute getAttribute(Attribute::AttrKind Kind) const { - return Attrs.getAttribute(Kind); - } - - /// Return the attribute object. - Attribute getAttribute(StringRef Kind) const { - return Attrs.getAttribute(Kind); - } - - /// Return the attribute set for this global - AttributeSet getAttributes() const { - return Attrs; - } - - /// Return attribute set as list with index. - /// FIXME: This may not be required once ValueEnumerators - /// in bitcode-writer can enumerate attribute-set. - AttributeList getAttributesAsList(unsigned index) const { - if (!hasAttributes()) - return AttributeList(); - std::pair AS[1] = {{index, Attrs}}; - return AttributeList::get(getContext(), AS); - } - - /// Set attribute list for this global - void setAttributes(AttributeSet A) { - Attrs = A; - } - - /// Check if section name is present - bool hasImplicitSection() const { - return getAttributes().hasAttribute("bss-section") || - getAttributes().hasAttribute("data-section") || - getAttributes().hasAttribute("relro-section") || - getAttributes().hasAttribute("rodata-section"); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::GlobalVariableVal; - } -}; - -template <> -struct OperandTraits : - public OptionalOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALVARIABLE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/IRBuilder.h b/suite/synctools/tablegen/include/llvm/IR/IRBuilder.h deleted file mode 100644 index 2968a89527..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IRBuilder.h +++ /dev/null @@ -1,2580 +0,0 @@ -//===- llvm/IRBuilder.h - Builder for LLVM Instructions ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the IRBuilder class, which is used as a convenient way -// to create LLVM instructions with a consistent and simplified interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_IRBUILDER_H -#define LLVM_IR_IRBUILDER_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/ConstantFolder.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/FPEnv.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Casting.h" -#include -#include -#include -#include - -namespace llvm { - -class APInt; -class Use; - -/// This provides the default implementation of the IRBuilder -/// 'InsertHelper' method that is called whenever an instruction is created by -/// IRBuilder and needs to be inserted. -/// -/// By default, this inserts the instruction at the insertion point. -class IRBuilderDefaultInserter { -public: - virtual ~IRBuilderDefaultInserter(); - - virtual void InsertHelper(Instruction *I, const Twine &Name, - BasicBlock *BB, - BasicBlock::iterator InsertPt) const { - if (BB) BB->getInstList().insert(InsertPt, I); - I->setName(Name); - } -}; - -/// Provides an 'InsertHelper' that calls a user-provided callback after -/// performing the default insertion. -class IRBuilderCallbackInserter : public IRBuilderDefaultInserter { - std::function Callback; - -public: - virtual ~IRBuilderCallbackInserter(); - - IRBuilderCallbackInserter(std::function Callback) - : Callback(std::move(Callback)) {} - - void InsertHelper(Instruction *I, const Twine &Name, - BasicBlock *BB, - BasicBlock::iterator InsertPt) const override { - IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt); - Callback(I); - } -}; - -/// Common base class shared among various IRBuilders. -class IRBuilderBase { - /// Pairs of (metadata kind, MDNode *) that should be added to all newly - /// created instructions, like !dbg metadata. - SmallVector, 2> MetadataToCopy; - - /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not - /// null. If \p MD is null, remove the entry with \p Kind. - void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { - if (!MD) { - erase_if(MetadataToCopy, [Kind](const std::pair &KV) { - return KV.first == Kind; - }); - return; - } - - for (auto &KV : MetadataToCopy) - if (KV.first == Kind) { - KV.second = MD; - return; - } - - MetadataToCopy.emplace_back(Kind, MD); - } - -protected: - BasicBlock *BB; - BasicBlock::iterator InsertPt; - LLVMContext &Context; - const IRBuilderFolder &Folder; - const IRBuilderDefaultInserter &Inserter; - - MDNode *DefaultFPMathTag; - FastMathFlags FMF; - - bool IsFPConstrained; - fp::ExceptionBehavior DefaultConstrainedExcept; - RoundingMode DefaultConstrainedRounding; - - ArrayRef DefaultOperandBundles; - -public: - IRBuilderBase(LLVMContext &context, const IRBuilderFolder &Folder, - const IRBuilderDefaultInserter &Inserter, - MDNode *FPMathTag, ArrayRef OpBundles) - : Context(context), Folder(Folder), Inserter(Inserter), - DefaultFPMathTag(FPMathTag), IsFPConstrained(false), - DefaultConstrainedExcept(fp::ebStrict), - DefaultConstrainedRounding(RoundingMode::Dynamic), - DefaultOperandBundles(OpBundles) { - ClearInsertionPoint(); - } - - /// Insert and return the specified instruction. - template - InstTy *Insert(InstTy *I, const Twine &Name = "") const { - Inserter.InsertHelper(I, Name, BB, InsertPt); - AddMetadataToInst(I); - return I; - } - - /// No-op overload to handle constants. - Constant *Insert(Constant *C, const Twine& = "") const { - return C; - } - - Value *Insert(Value *V, const Twine &Name = "") const { - if (Instruction *I = dyn_cast(V)) - return Insert(I, Name); - assert(isa(V)); - return V; - } - - //===--------------------------------------------------------------------===// - // Builder configuration methods - //===--------------------------------------------------------------------===// - - /// Clear the insertion point: created instructions will not be - /// inserted into a block. - void ClearInsertionPoint() { - BB = nullptr; - InsertPt = BasicBlock::iterator(); - } - - BasicBlock *GetInsertBlock() const { return BB; } - BasicBlock::iterator GetInsertPoint() const { return InsertPt; } - LLVMContext &getContext() const { return Context; } - - /// This specifies that created instructions should be appended to the - /// end of the specified block. - void SetInsertPoint(BasicBlock *TheBB) { - BB = TheBB; - InsertPt = BB->end(); - } - - /// This specifies that created instructions should be inserted before - /// the specified instruction. - void SetInsertPoint(Instruction *I) { - BB = I->getParent(); - InsertPt = I->getIterator(); - assert(InsertPt != BB->end() && "Can't read debug loc from end()"); - SetCurrentDebugLocation(I->getDebugLoc()); - } - - /// This specifies that created instructions should be inserted at the - /// specified point. - void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { - BB = TheBB; - InsertPt = IP; - if (IP != TheBB->end()) - SetCurrentDebugLocation(IP->getDebugLoc()); - } - - /// Set location information used by debugging information. - void SetCurrentDebugLocation(DebugLoc L) { - AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); - } - - /// Collect metadata with IDs \p MetadataKinds from \p Src which should be - /// added to all created instructions. Entries present in MedataDataToCopy but - /// not on \p Src will be dropped from MetadataToCopy. - void CollectMetadataToCopy(Instruction *Src, - ArrayRef MetadataKinds) { - for (unsigned K : MetadataKinds) - AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); - } - - /// Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { - for (auto &KV : MetadataToCopy) - if (KV.first == LLVMContext::MD_dbg) - return {cast(KV.second)}; - - return {}; - } - - /// If this builder has a current debug location, set it on the - /// specified instruction. - void SetInstDebugLocation(Instruction *I) const { - for (const auto &KV : MetadataToCopy) - if (KV.first == LLVMContext::MD_dbg) { - I->setDebugLoc(DebugLoc(KV.second)); - return; - } - } - - /// Add all entries in MetadataToCopy to \p I. - void AddMetadataToInst(Instruction *I) const { - for (auto &KV : MetadataToCopy) - I->setMetadata(KV.first, KV.second); - } - - /// Get the return type of the current function that we're emitting - /// into. - Type *getCurrentFunctionReturnType() const; - - /// InsertPoint - A saved insertion point. - class InsertPoint { - BasicBlock *Block = nullptr; - BasicBlock::iterator Point; - - public: - /// Creates a new insertion point which doesn't point to anything. - InsertPoint() = default; - - /// Creates a new insertion point at the given location. - InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) - : Block(InsertBlock), Point(InsertPoint) {} - - /// Returns true if this insert point is set. - bool isSet() const { return (Block != nullptr); } - - BasicBlock *getBlock() const { return Block; } - BasicBlock::iterator getPoint() const { return Point; } - }; - - /// Returns the current insert point. - InsertPoint saveIP() const { - return InsertPoint(GetInsertBlock(), GetInsertPoint()); - } - - /// Returns the current insert point, clearing it in the process. - InsertPoint saveAndClearIP() { - InsertPoint IP(GetInsertBlock(), GetInsertPoint()); - ClearInsertionPoint(); - return IP; - } - - /// Sets the current insert point to a previously-saved location. - void restoreIP(InsertPoint IP) { - if (IP.isSet()) - SetInsertPoint(IP.getBlock(), IP.getPoint()); - else - ClearInsertionPoint(); - } - - /// Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// Get the flags to be applied to created floating point ops - FastMathFlags getFastMathFlags() const { return FMF; } - - FastMathFlags &getFastMathFlags() { return FMF; } - - /// Clear the fast-math flags. - void clearFastMathFlags() { FMF.clear(); } - - /// Set the floating point math metadata to be used. - void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// Set the fast-math flags to be used with generated fp-math operators - void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - - /// Enable/Disable use of constrained floating point math. When - /// enabled the CreateF() calls instead create constrained - /// floating point intrinsic calls. Fast math flags are unaffected - /// by this setting. - void setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; } - - /// Query for the use of constrained floating point math - bool getIsFPConstrained() { return IsFPConstrained; } - - /// Set the exception handling to be used with constrained floating point - void setDefaultConstrainedExcept(fp::ExceptionBehavior NewExcept) { -#ifndef NDEBUG - Optional ExceptStr = convertExceptionBehaviorToStr(NewExcept); - assert(ExceptStr.hasValue() && "Garbage strict exception behavior!"); -#endif - DefaultConstrainedExcept = NewExcept; - } - - /// Set the rounding mode handling to be used with constrained floating point - void setDefaultConstrainedRounding(RoundingMode NewRounding) { -#ifndef NDEBUG - Optional RoundingStr = convertRoundingModeToStr(NewRounding); - assert(RoundingStr.hasValue() && "Garbage strict rounding mode!"); -#endif - DefaultConstrainedRounding = NewRounding; - } - - /// Get the exception handling used with constrained floating point - fp::ExceptionBehavior getDefaultConstrainedExcept() { - return DefaultConstrainedExcept; - } - - /// Get the rounding mode handling used with constrained floating point - RoundingMode getDefaultConstrainedRounding() { - return DefaultConstrainedRounding; - } - - void setConstrainedFPFunctionAttr() { - assert(BB && "Must have a basic block to set any function attributes!"); - - Function *F = BB->getParent(); - if (!F->hasFnAttribute(Attribute::StrictFP)) { - F->addFnAttr(Attribute::StrictFP); - } - } - - void setConstrainedFPCallAttr(CallBase *I) { - I->addFnAttr(Attribute::StrictFP); - } - - void setDefaultOperandBundles(ArrayRef OpBundles) { - DefaultOperandBundles = OpBundles; - } - - //===--------------------------------------------------------------------===// - // RAII helpers. - //===--------------------------------------------------------------------===// - - // RAII object that stores the current insertion point and restores it - // when the object is destroyed. This includes the debug location. - class InsertPointGuard { - IRBuilderBase &Builder; - AssertingVH Block; - BasicBlock::iterator Point; - DebugLoc DbgLoc; - - public: - InsertPointGuard(IRBuilderBase &B) - : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()), - DbgLoc(B.getCurrentDebugLocation()) {} - - InsertPointGuard(const InsertPointGuard &) = delete; - InsertPointGuard &operator=(const InsertPointGuard &) = delete; - - ~InsertPointGuard() { - Builder.restoreIP(InsertPoint(Block, Point)); - Builder.SetCurrentDebugLocation(DbgLoc); - } - }; - - // RAII object that stores the current fast math settings and restores - // them when the object is destroyed. - class FastMathFlagGuard { - IRBuilderBase &Builder; - FastMathFlags FMF; - MDNode *FPMathTag; - bool IsFPConstrained; - fp::ExceptionBehavior DefaultConstrainedExcept; - RoundingMode DefaultConstrainedRounding; - - public: - FastMathFlagGuard(IRBuilderBase &B) - : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag), - IsFPConstrained(B.IsFPConstrained), - DefaultConstrainedExcept(B.DefaultConstrainedExcept), - DefaultConstrainedRounding(B.DefaultConstrainedRounding) {} - - FastMathFlagGuard(const FastMathFlagGuard &) = delete; - FastMathFlagGuard &operator=(const FastMathFlagGuard &) = delete; - - ~FastMathFlagGuard() { - Builder.FMF = FMF; - Builder.DefaultFPMathTag = FPMathTag; - Builder.IsFPConstrained = IsFPConstrained; - Builder.DefaultConstrainedExcept = DefaultConstrainedExcept; - Builder.DefaultConstrainedRounding = DefaultConstrainedRounding; - } - }; - - // RAII object that stores the current default operand bundles and restores - // them when the object is destroyed. - class OperandBundlesGuard { - IRBuilderBase &Builder; - ArrayRef DefaultOperandBundles; - - public: - OperandBundlesGuard(IRBuilderBase &B) - : Builder(B), DefaultOperandBundles(B.DefaultOperandBundles) {} - - OperandBundlesGuard(const OperandBundlesGuard &) = delete; - OperandBundlesGuard &operator=(const OperandBundlesGuard &) = delete; - - ~OperandBundlesGuard() { - Builder.DefaultOperandBundles = DefaultOperandBundles; - } - }; - - - //===--------------------------------------------------------------------===// - // Miscellaneous creation methods. - //===--------------------------------------------------------------------===// - - /// Make a new global variable with initializer type i8* - /// - /// Make a new global variable with an initializer that has array of i8 type - /// filled in with the null terminated string value specified. The new global - /// variable will be marked mergeable with any others of the same contents. If - /// Name is specified, it is the name of the global variable created. - /// - /// If no module is given via \p M, it is take from the insertion point basic - /// block. - GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "", - unsigned AddressSpace = 0, - Module *M = nullptr); - - /// Get a constant value representing either true or false. - ConstantInt *getInt1(bool V) { - return ConstantInt::get(getInt1Ty(), V); - } - - /// Get the constant value for i1 true. - ConstantInt *getTrue() { - return ConstantInt::getTrue(Context); - } - - /// Get the constant value for i1 false. - ConstantInt *getFalse() { - return ConstantInt::getFalse(Context); - } - - /// Get a constant 8-bit value. - ConstantInt *getInt8(uint8_t C) { - return ConstantInt::get(getInt8Ty(), C); - } - - /// Get a constant 16-bit value. - ConstantInt *getInt16(uint16_t C) { - return ConstantInt::get(getInt16Ty(), C); - } - - /// Get a constant 32-bit value. - ConstantInt *getInt32(uint32_t C) { - return ConstantInt::get(getInt32Ty(), C); - } - - /// Get a constant 64-bit value. - ConstantInt *getInt64(uint64_t C) { - return ConstantInt::get(getInt64Ty(), C); - } - - /// Get a constant N-bit value, zero extended or truncated from - /// a 64-bit value. - ConstantInt *getIntN(unsigned N, uint64_t C) { - return ConstantInt::get(getIntNTy(N), C); - } - - /// Get a constant integer value. - ConstantInt *getInt(const APInt &AI) { - return ConstantInt::get(Context, AI); - } - - //===--------------------------------------------------------------------===// - // Type creation methods - //===--------------------------------------------------------------------===// - - /// Fetch the type representing a single bit - IntegerType *getInt1Ty() { - return Type::getInt1Ty(Context); - } - - /// Fetch the type representing an 8-bit integer. - IntegerType *getInt8Ty() { - return Type::getInt8Ty(Context); - } - - /// Fetch the type representing a 16-bit integer. - IntegerType *getInt16Ty() { - return Type::getInt16Ty(Context); - } - - /// Fetch the type representing a 32-bit integer. - IntegerType *getInt32Ty() { - return Type::getInt32Ty(Context); - } - - /// Fetch the type representing a 64-bit integer. - IntegerType *getInt64Ty() { - return Type::getInt64Ty(Context); - } - - /// Fetch the type representing a 128-bit integer. - IntegerType *getInt128Ty() { return Type::getInt128Ty(Context); } - - /// Fetch the type representing an N-bit integer. - IntegerType *getIntNTy(unsigned N) { - return Type::getIntNTy(Context, N); - } - - /// Fetch the type representing a 16-bit floating point value. - Type *getHalfTy() { - return Type::getHalfTy(Context); - } - - /// Fetch the type representing a 16-bit brain floating point value. - Type *getBFloatTy() { - return Type::getBFloatTy(Context); - } - - /// Fetch the type representing a 32-bit floating point value. - Type *getFloatTy() { - return Type::getFloatTy(Context); - } - - /// Fetch the type representing a 64-bit floating point value. - Type *getDoubleTy() { - return Type::getDoubleTy(Context); - } - - /// Fetch the type representing void. - Type *getVoidTy() { - return Type::getVoidTy(Context); - } - - /// Fetch the type representing a pointer to an 8-bit integer value. - PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { - return Type::getInt8PtrTy(Context, AddrSpace); - } - - /// Fetch the type representing a pointer to an integer value. - IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { - return DL.getIntPtrType(Context, AddrSpace); - } - - //===--------------------------------------------------------------------===// - // Intrinsic creation methods - //===--------------------------------------------------------------------===// - - /// Create and insert a memset to the specified pointer and the - /// specified value. - /// - /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. Likewise with alias.scope - /// and noalias tags. - CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, - MaybeAlign Align, bool isVolatile = false, - MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, - TBAATag, ScopeTag, NoAliasTag); - } - - CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, MaybeAlign Align, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); - - /// Create and insert an element unordered-atomic memset of the region of - /// memory starting at the given pointer to the given value. - /// - /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. Likewise with alias.scope - /// and noalias tags. - CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val, - uint64_t Size, Align Alignment, - uint32_t ElementSize, - MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr) { - return CreateElementUnorderedAtomicMemSet(Ptr, Val, getInt64(Size), - Align(Alignment), ElementSize, - TBAATag, ScopeTag, NoAliasTag); - } - - CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val, - Value *Size, Align Alignment, - uint32_t ElementSize, - MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); - - /// Create and insert a memcpy between the specified pointers. - /// - /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. Likewise with alias.scope - /// and noalias tags. - CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, uint64_t Size, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr) { - return CreateMemCpy(Dst, DstAlign, Src, SrcAlign, getInt64(Size), - isVolatile, TBAATag, TBAAStructTag, ScopeTag, - NoAliasTag); - } - - CallInst *CreateMemTransferInst( - Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, Value *Size, bool isVolatile = false, - MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, - MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - - CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, Value *Size, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr) { - return CreateMemTransferInst(Intrinsic::memcpy, Dst, DstAlign, Src, - SrcAlign, Size, isVolatile, TBAATag, - TBAAStructTag, ScopeTag, NoAliasTag); - } - - CallInst * - CreateMemCpyInline(Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, Value *Size, bool IsVolatile = false, - MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, - MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - - /// Create and insert an element unordered-atomic memcpy between the - /// specified pointers. - /// - /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively. - /// - /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. Likewise with alias.scope - /// and noalias tags. - CallInst *CreateElementUnorderedAtomicMemCpy( - Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, - uint32_t ElementSize, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); - - CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, uint64_t Size, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr) { - return CreateMemMove(Dst, DstAlign, Src, SrcAlign, getInt64(Size), - isVolatile, TBAATag, ScopeTag, NoAliasTag); - } - - CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src, - MaybeAlign SrcAlign, Value *Size, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); - - /// \brief Create and insert an element unordered-atomic memmove between the - /// specified pointers. - /// - /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, - /// respectively. - /// - /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. Likewise with alias.scope - /// and noalias tags. - CallInst *CreateElementUnorderedAtomicMemMove( - Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, - uint32_t ElementSize, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); - - /// Create a sequential vector fadd reduction intrinsic of the source vector. - /// The first parameter is a scalar accumulator value. An unordered reduction - /// can be created by adding the reassoc fast-math flag to the resulting - /// sequential reduction. - CallInst *CreateFAddReduce(Value *Acc, Value *Src); - - /// Create a sequential vector fmul reduction intrinsic of the source vector. - /// The first parameter is a scalar accumulator value. An unordered reduction - /// can be created by adding the reassoc fast-math flag to the resulting - /// sequential reduction. - CallInst *CreateFMulReduce(Value *Acc, Value *Src); - - /// Create a vector int add reduction intrinsic of the source vector. - CallInst *CreateAddReduce(Value *Src); - - /// Create a vector int mul reduction intrinsic of the source vector. - CallInst *CreateMulReduce(Value *Src); - - /// Create a vector int AND reduction intrinsic of the source vector. - CallInst *CreateAndReduce(Value *Src); - - /// Create a vector int OR reduction intrinsic of the source vector. - CallInst *CreateOrReduce(Value *Src); - - /// Create a vector int XOR reduction intrinsic of the source vector. - CallInst *CreateXorReduce(Value *Src); - - /// Create a vector integer max reduction intrinsic of the source - /// vector. - CallInst *CreateIntMaxReduce(Value *Src, bool IsSigned = false); - - /// Create a vector integer min reduction intrinsic of the source - /// vector. - CallInst *CreateIntMinReduce(Value *Src, bool IsSigned = false); - - /// Create a vector float max reduction intrinsic of the source - /// vector. - CallInst *CreateFPMaxReduce(Value *Src); - - /// Create a vector float min reduction intrinsic of the source - /// vector. - CallInst *CreateFPMinReduce(Value *Src); - - /// Create a lifetime.start intrinsic. - /// - /// If the pointer isn't i8* it will be converted. - CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr); - - /// Create a lifetime.end intrinsic. - /// - /// If the pointer isn't i8* it will be converted. - CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); - - /// Create a call to invariant.start intrinsic. - /// - /// If the pointer isn't i8* it will be converted. - CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr); - - /// Create a call to Masked Load intrinsic - CallInst *CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, - Value *PassThru = nullptr, const Twine &Name = ""); - - /// Create a call to Masked Store intrinsic - CallInst *CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, - Value *Mask); - - /// Create a call to Masked Gather intrinsic - CallInst *CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment, - Value *Mask = nullptr, Value *PassThru = nullptr, - const Twine &Name = ""); - - /// Create a call to Masked Scatter intrinsic - CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment, - Value *Mask = nullptr); - - /// Create an assume intrinsic call that allows the optimizer to - /// assume that the provided condition will be true. - /// - /// The optional argument \p OpBundles specifies operand bundles that are - /// added to the call instruction. - CallInst *CreateAssumption(Value *Cond, - ArrayRef OpBundles = llvm::None); - - /// Create a llvm.experimental.noalias.scope.decl intrinsic call. - Instruction *CreateNoAliasScopeDeclaration(Value *Scope); - Instruction *CreateNoAliasScopeDeclaration(MDNode *ScopeTag) { - return CreateNoAliasScopeDeclaration( - MetadataAsValue::get(Context, ScopeTag)); - } - - /// Create a call to the experimental.gc.statepoint intrinsic to - /// start a new statepoint sequence. - CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, - Value *ActualCallee, - ArrayRef CallArgs, - Optional> DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); - - /// Create a call to the experimental.gc.statepoint intrinsic to - /// start a new statepoint sequence. - CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, - Value *ActualCallee, uint32_t Flags, - ArrayRef CallArgs, - Optional> TransitionArgs, - Optional> DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); - - /// Conveninence function for the common case when CallArgs are filled - /// in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be - /// .get()'ed to get the Value pointer. - CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, - Value *ActualCallee, ArrayRef CallArgs, - Optional> DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); - - /// Create an invoke to the experimental.gc.statepoint intrinsic to - /// start a new statepoint sequence. - InvokeInst * - CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, - Value *ActualInvokee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, ArrayRef InvokeArgs, - Optional> DeoptArgs, - ArrayRef GCArgs, const Twine &Name = ""); - - /// Create an invoke to the experimental.gc.statepoint intrinsic to - /// start a new statepoint sequence. - InvokeInst *CreateGCStatepointInvoke( - uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, - BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags, - ArrayRef InvokeArgs, Optional> TransitionArgs, - Optional> DeoptArgs, ArrayRef GCArgs, - const Twine &Name = ""); - - // Convenience function for the common case when CallArgs are filled in using - // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to - // get the Value *. - InvokeInst * - CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, - Value *ActualInvokee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, ArrayRef InvokeArgs, - Optional> DeoptArgs, - ArrayRef GCArgs, const Twine &Name = ""); - - /// Create a call to the experimental.gc.result intrinsic to extract - /// the result from a call wrapped in a statepoint. - CallInst *CreateGCResult(Instruction *Statepoint, - Type *ResultType, - const Twine &Name = ""); - - /// Create a call to the experimental.gc.relocate intrinsics to - /// project the relocated value of one pointer from the statepoint. - CallInst *CreateGCRelocate(Instruction *Statepoint, - int BaseOffset, - int DerivedOffset, - Type *ResultType, - const Twine &Name = ""); - - /// Create a call to the experimental.gc.pointer.base intrinsic to get the - /// base pointer for the specified derived pointer. - CallInst *CreateGCGetPointerBase(Value *DerivedPtr, const Twine &Name = ""); - - /// Create a call to the experimental.gc.get.pointer.offset intrinsic to get - /// the offset of the specified derived pointer from its base. - CallInst *CreateGCGetPointerOffset(Value *DerivedPtr, const Twine &Name = ""); - - /// Create a call to llvm.vscale, multiplied by \p Scaling. The type of VScale - /// will be the same type as that of \p Scaling. - Value *CreateVScale(Constant *Scaling, const Twine &Name = ""); - - /// Creates a vector of type \p DstType with the linear sequence <0, 1, ...> - Value *CreateStepVector(Type *DstType, const Twine &Name = ""); - - /// Create a call to intrinsic \p ID with 1 operand which is mangled on its - /// type. - CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V, - Instruction *FMFSource = nullptr, - const Twine &Name = ""); - - /// Create a call to intrinsic \p ID with 2 operands which is mangled on the - /// first type. - CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, - Instruction *FMFSource = nullptr, - const Twine &Name = ""); - - /// Create a call to intrinsic \p ID with \p args, mangled using \p Types. If - /// \p FMFSource is provided, copy fast-math-flags from that instruction to - /// the intrinsic. - CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef Types, - ArrayRef Args, - Instruction *FMFSource = nullptr, - const Twine &Name = ""); - - /// Create call to the minnum intrinsic. - CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name); - } - - /// Create call to the maxnum intrinsic. - CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, nullptr, Name); - } - - /// Create call to the minimum intrinsic. - CallInst *CreateMinimum(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateBinaryIntrinsic(Intrinsic::minimum, LHS, RHS, nullptr, Name); - } - - /// Create call to the maximum intrinsic. - CallInst *CreateMaximum(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name); - } - - /// Create a call to the arithmetic_fence intrinsic. - CallInst *CreateArithmeticFence(Value *Val, Type *DstType, - const Twine &Name = "") { - return CreateIntrinsic(Intrinsic::arithmetic_fence, DstType, Val, nullptr, - Name); - } - - /// Create a call to the experimental.vector.extract intrinsic. - CallInst *CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, - const Twine &Name = "") { - return CreateIntrinsic(Intrinsic::experimental_vector_extract, - {DstType, SrcVec->getType()}, {SrcVec, Idx}, nullptr, - Name); - } - - /// Create a call to the experimental.vector.insert intrinsic. - CallInst *CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec, - Value *Idx, const Twine &Name = "") { - return CreateIntrinsic(Intrinsic::experimental_vector_insert, - {DstType, SubVec->getType()}, {SrcVec, SubVec, Idx}, - nullptr, Name); - } - -private: - /// Create a call to a masked intrinsic with given Id. - CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef Ops, - ArrayRef OverloadedTypes, - const Twine &Name = ""); - - Value *getCastedInt8PtrValue(Value *Ptr); - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Terminators - //===--------------------------------------------------------------------===// - -private: - /// Helper to add branch weight and unpredictable metadata onto an - /// instruction. - /// \returns The annotated instruction. - template - InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable) { - if (Weights) - I->setMetadata(LLVMContext::MD_prof, Weights); - if (Unpredictable) - I->setMetadata(LLVMContext::MD_unpredictable, Unpredictable); - return I; - } - -public: - /// Create a 'ret void' instruction. - ReturnInst *CreateRetVoid() { - return Insert(ReturnInst::Create(Context)); - } - - /// Create a 'ret ' instruction. - ReturnInst *CreateRet(Value *V) { - return Insert(ReturnInst::Create(Context, V)); - } - - /// Create a sequence of N insertvalue instructions, - /// with one Value from the retVals array each, that build a aggregate - /// return value one value at a time, and a ret instruction to return - /// the resulting aggregate value. - /// - /// This is a convenience function for code that uses aggregate return values - /// as a vehicle for having multiple return values. - ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { - Value *V = UndefValue::get(getCurrentFunctionReturnType()); - for (unsigned i = 0; i != N; ++i) - V = CreateInsertValue(V, retVals[i], i, "mrv"); - return Insert(ReturnInst::Create(Context, V)); - } - - /// Create an unconditional 'br label X' instruction. - BranchInst *CreateBr(BasicBlock *Dest) { - return Insert(BranchInst::Create(Dest)); - } - - /// Create a conditional 'br Cond, TrueDest, FalseDest' - /// instruction. - BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, - MDNode *BranchWeights = nullptr, - MDNode *Unpredictable = nullptr) { - return Insert(addBranchMetadata(BranchInst::Create(True, False, Cond), - BranchWeights, Unpredictable)); - } - - /// Create a conditional 'br Cond, TrueDest, FalseDest' - /// instruction. Copy branch meta data if available. - BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, - Instruction *MDSrc) { - BranchInst *Br = BranchInst::Create(True, False, Cond); - if (MDSrc) { - unsigned WL[4] = {LLVMContext::MD_prof, LLVMContext::MD_unpredictable, - LLVMContext::MD_make_implicit, LLVMContext::MD_dbg}; - Br->copyMetadata(*MDSrc, makeArrayRef(&WL[0], 4)); - } - return Insert(Br); - } - - /// Create a switch instruction with the specified value, default dest, - /// and with a hint for the number of cases that will be added (for efficient - /// allocation). - SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, - MDNode *BranchWeights = nullptr, - MDNode *Unpredictable = nullptr) { - return Insert(addBranchMetadata(SwitchInst::Create(V, Dest, NumCases), - BranchWeights, Unpredictable)); - } - - /// Create an indirect branch instruction with the specified address - /// operand, with an optional hint for the number of destinations that will be - /// added (for efficient allocation). - IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { - return Insert(IndirectBrInst::Create(Addr, NumDests)); - } - - /// Create an invoke instruction. - InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee, - BasicBlock *NormalDest, BasicBlock *UnwindDest, - ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "") { - InvokeInst *II = - InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args, OpBundles); - if (IsFPConstrained) - setConstrainedFPCallAttr(II); - return Insert(II, Name); - } - InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee, - BasicBlock *NormalDest, BasicBlock *UnwindDest, - ArrayRef Args = None, - const Twine &Name = "") { - InvokeInst *II = - InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args); - if (IsFPConstrained) - setConstrainedFPCallAttr(II); - return Insert(II, Name); - } - - InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "") { - return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(), - NormalDest, UnwindDest, Args, OpBundles, Name); - } - - InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, - ArrayRef Args = None, - const Twine &Name = "") { - return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(), - NormalDest, UnwindDest, Args, Name); - } - - /// \brief Create a callbr instruction. - CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args = None, - const Twine &Name = "") { - return Insert(CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, - Args), Name); - } - CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "") { - return Insert( - CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args, - OpBundles), Name); - } - - CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args = None, - const Twine &Name = "") { - return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(), - DefaultDest, IndirectDests, Args, Name); - } - CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "") { - return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(), - DefaultDest, IndirectDests, Args, Name); - } - - ResumeInst *CreateResume(Value *Exn) { - return Insert(ResumeInst::Create(Exn)); - } - - CleanupReturnInst *CreateCleanupRet(CleanupPadInst *CleanupPad, - BasicBlock *UnwindBB = nullptr) { - return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB)); - } - - CatchSwitchInst *CreateCatchSwitch(Value *ParentPad, BasicBlock *UnwindBB, - unsigned NumHandlers, - const Twine &Name = "") { - return Insert(CatchSwitchInst::Create(ParentPad, UnwindBB, NumHandlers), - Name); - } - - CatchPadInst *CreateCatchPad(Value *ParentPad, ArrayRef Args, - const Twine &Name = "") { - return Insert(CatchPadInst::Create(ParentPad, Args), Name); - } - - CleanupPadInst *CreateCleanupPad(Value *ParentPad, - ArrayRef Args = None, - const Twine &Name = "") { - return Insert(CleanupPadInst::Create(ParentPad, Args), Name); - } - - CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) { - return Insert(CatchReturnInst::Create(CatchPad, BB)); - } - - UnreachableInst *CreateUnreachable() { - return Insert(new UnreachableInst(Context)); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Binary Operators - //===--------------------------------------------------------------------===// -private: - BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, - Value *LHS, Value *RHS, - const Twine &Name, - bool HasNUW, bool HasNSW) { - BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *setFPAttrs(Instruction *I, MDNode *FPMD, - FastMathFlags FMF) const { - if (!FPMD) - FPMD = DefaultFPMathTag; - if (FPMD) - I->setMetadata(LLVMContext::MD_fpmath, FPMD); - I->setFastMathFlags(FMF); - return I; - } - - Value *foldConstant(Instruction::BinaryOps Opc, Value *L, - Value *R, const Twine &Name) const { - auto *LC = dyn_cast(L); - auto *RC = dyn_cast(R); - return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; - } - - Value *getConstrainedFPRounding(Optional Rounding) { - RoundingMode UseRounding = DefaultConstrainedRounding; - - if (Rounding.hasValue()) - UseRounding = Rounding.getValue(); - - Optional RoundingStr = convertRoundingModeToStr(UseRounding); - assert(RoundingStr.hasValue() && "Garbage strict rounding mode!"); - auto *RoundingMDS = MDString::get(Context, RoundingStr.getValue()); - - return MetadataAsValue::get(Context, RoundingMDS); - } - - Value *getConstrainedFPExcept(Optional Except) { - fp::ExceptionBehavior UseExcept = DefaultConstrainedExcept; - - if (Except.hasValue()) - UseExcept = Except.getValue(); - - Optional ExceptStr = convertExceptionBehaviorToStr(UseExcept); - assert(ExceptStr.hasValue() && "Garbage strict exception behavior!"); - auto *ExceptMDS = MDString::get(Context, ExceptStr.getValue()); - - return MetadataAsValue::get(Context, ExceptMDS); - } - - Value *getConstrainedFPPredicate(CmpInst::Predicate Predicate) { - assert(CmpInst::isFPPredicate(Predicate) && - Predicate != CmpInst::FCMP_FALSE && - Predicate != CmpInst::FCMP_TRUE && - "Invalid constrained FP comparison predicate!"); - - StringRef PredicateStr = CmpInst::getPredicateName(Predicate); - auto *PredicateMDS = MDString::get(Context, PredicateStr); - - return MetadataAsValue::get(Context, PredicateMDS); - } - -public: - Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (auto *V = Folder.FoldAdd(LHS, RHS, HasNUW, HasNSW)) - return V; - return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, - HasNUW, HasNSW); - } - - Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateAdd(LHS, RHS, Name, false, true); - } - - Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateAdd(LHS, RHS, Name, true, false); - } - - Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name); - return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, - HasNUW, HasNSW); - } - - Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSub(LHS, RHS, Name, false, true); - } - - Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSub(LHS, RHS, Name, true, false); - } - - Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name); - return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, - HasNUW, HasNSW); - } - - Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateMul(LHS, RHS, Name, false, true); - } - - Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateMul(LHS, RHS, Name, true, false); - } - - Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); - } - - Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateUDiv(LHS, RHS, Name, true); - } - - Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); - } - - Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSDiv(LHS, RHS, Name, true); - } - - Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Value *V = foldConstant(Instruction::URem, LHS, RHS, Name)) return V; - return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); - } - - Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Value *V = foldConstant(Instruction::SRem, LHS, RHS, Name)) return V; - return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); - } - - Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); - return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, - HasNUW, HasNSW); - } - - Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, - HasNUW, HasNSW); - } - - Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, - HasNUW, HasNSW); - } - - Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateLShr(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); - } - - Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool isExact = false) { - return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool isExact = false) { - return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateAShr(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); - } - - Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool isExact = false) { - return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool isExact = false) { - return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (auto *V = Folder.FoldAnd(LHS, RHS)) - return V; - return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); - } - - Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateAnd(ArrayRef Ops) { - assert(!Ops.empty()); - Value *Accum = Ops[0]; - for (unsigned i = 1; i < Ops.size(); i++) - Accum = CreateAnd(Accum, Ops[i]); - return Accum; - } - - Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { - if (auto *V = Folder.FoldOr(LHS, RHS)) - return V; - return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); - } - - Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateOr(ArrayRef Ops) { - assert(!Ops.empty()); - Value *Accum = Ops[0]; - for (unsigned i = 1; i < Ops.size(); i++) - Accum = CreateOr(Accum, Ops[i]); - return Accum; - } - - Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Value *V = foldConstant(Instruction::Xor, LHS, RHS, Name)) return V; - return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); - } - - Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "", - MDNode *FPMD = nullptr) { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, - L, R, nullptr, Name, FPMD); - - if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF); - return Insert(I, Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, - L, R, FMFSource, Name); - - if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, - FMFSource->getFastMathFlags()); - return Insert(I, Name); - } - - Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", - MDNode *FPMD = nullptr) { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, - L, R, nullptr, Name, FPMD); - - if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF); - return Insert(I, Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, - L, R, FMFSource, Name); - - if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, - FMFSource->getFastMathFlags()); - return Insert(I, Name); - } - - Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", - MDNode *FPMD = nullptr) { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, - L, R, nullptr, Name, FPMD); - - if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF); - return Insert(I, Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, - L, R, FMFSource, Name); - - if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, - FMFSource->getFastMathFlags()); - return Insert(I, Name); - } - - Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", - MDNode *FPMD = nullptr) { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, - L, R, nullptr, Name, FPMD); - - if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF); - return Insert(I, Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, - L, R, FMFSource, Name); - - if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, - FMFSource->getFastMathFlags()); - return Insert(I, Name); - } - - Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", - MDNode *FPMD = nullptr) { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, - L, R, nullptr, Name, FPMD); - - if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF); - return Insert(I, Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, - L, R, FMFSource, Name); - - if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; - Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, - FMFSource->getFastMathFlags()); - return Insert(I, Name); - } - - Value *CreateBinOp(Instruction::BinaryOps Opc, - Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V; - Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); - if (isa(BinOp)) - setFPAttrs(BinOp, FPMathTag, FMF); - return Insert(BinOp, Name); - } - - Value *CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name = "") { - assert(Cond2->getType()->isIntOrIntVectorTy(1)); - return CreateSelect(Cond1, Cond2, - ConstantInt::getNullValue(Cond2->getType()), Name); - } - - Value *CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name = "") { - assert(Cond2->getType()->isIntOrIntVectorTy(1)); - return CreateSelect(Cond1, ConstantInt::getAllOnesValue(Cond2->getType()), - Cond2, Name); - } - - // NOTE: this is sequential, non-commutative, ordered reduction! - Value *CreateLogicalOr(ArrayRef Ops) { - assert(!Ops.empty()); - Value *Accum = Ops[0]; - for (unsigned i = 1; i < Ops.size(); i++) - Accum = CreateLogicalOr(Accum, Ops[i]); - return Accum; - } - - CallInst *CreateConstrainedFPBinOp( - Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr, - const Twine &Name = "", MDNode *FPMathTag = nullptr, - Optional Rounding = None, - Optional Except = None); - - Value *CreateNeg(Value *V, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); - BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, false, true); - } - - Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, true, false); - } - - Value *CreateFNeg(Value *V, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateFNeg(VC), Name); - return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), FPMathTag, FMF), - Name); - } - - /// Copy fast-math-flags from an instruction rather than using the builder's - /// default FMF. - Value *CreateFNegFMF(Value *V, Instruction *FMFSource, - const Twine &Name = "") { - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateFNeg(VC), Name); - return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), nullptr, - FMFSource->getFastMathFlags()), - Name); - } - - Value *CreateNot(Value *V, const Twine &Name = "") { - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateNot(VC), Name); - return Insert(BinaryOperator::CreateNot(V), Name); - } - - Value *CreateUnOp(Instruction::UnaryOps Opc, - Value *V, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateUnOp(Opc, VC), Name); - Instruction *UnOp = UnaryOperator::Create(Opc, V); - if (isa(UnOp)) - setFPAttrs(UnOp, FPMathTag, FMF); - return Insert(UnOp, Name); - } - - /// Create either a UnaryOperator or BinaryOperator depending on \p Opc. - /// Correct number of operands must be passed accordingly. - Value *CreateNAryOp(unsigned Opc, ArrayRef Ops, - const Twine &Name = "", MDNode *FPMathTag = nullptr); - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Memory Instructions - //===--------------------------------------------------------------------===// - - AllocaInst *CreateAlloca(Type *Ty, unsigned AddrSpace, - Value *ArraySize = nullptr, const Twine &Name = "") { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align AllocaAlign = DL.getPrefTypeAlign(Ty); - return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name); - } - - AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr, - const Twine &Name = "") { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align AllocaAlign = DL.getPrefTypeAlign(Ty); - unsigned AddrSpace = DL.getAllocaAddrSpace(); - return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name); - } - - /// Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of - /// converting the string to 'bool' for the isVolatile parameter. - LoadInst *CreateLoad(Type *Ty, Value *Ptr, const char *Name) { - return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name); - } - - LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { - return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name); - } - - LoadInst *CreateLoad(Type *Ty, Value *Ptr, bool isVolatile, - const Twine &Name = "") { - return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), isVolatile, Name); - } - - StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { - return CreateAlignedStore(Val, Ptr, MaybeAlign(), isVolatile); - } - - LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, - const char *Name) { - return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name); - } - - LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, - const Twine &Name = "") { - return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name); - } - - LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, - bool isVolatile, const Twine &Name = "") { - if (!Align) { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align = DL.getABITypeAlign(Ty); - } - return Insert(new LoadInst(Ty, Ptr, Twine(), isVolatile, *Align), Name); - } - - StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, - bool isVolatile = false) { - if (!Align) { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align = DL.getABITypeAlign(Val->getType()); - } - return Insert(new StoreInst(Val, Ptr, isVolatile, *Align)); - } - FenceInst *CreateFence(AtomicOrdering Ordering, - SyncScope::ID SSID = SyncScope::System, - const Twine &Name = "") { - return Insert(new FenceInst(Context, Ordering, SSID), Name); - } - - AtomicCmpXchgInst * - CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, - AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SyncScope::ID SSID = SyncScope::System) { - if (!Align) { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align = llvm::Align(DL.getTypeStoreSize(New->getType())); - } - - return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, *Align, SuccessOrdering, - FailureOrdering, SSID)); - } - - AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, - Value *Val, MaybeAlign Align, - AtomicOrdering Ordering, - SyncScope::ID SSID = SyncScope::System) { - if (!Align) { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Align = llvm::Align(DL.getTypeStoreSize(Val->getType())); - } - - return Insert(new AtomicRMWInst(Op, Ptr, Val, *Align, Ordering, SSID)); - } - - Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, - const Twine &Name = "") { - if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, /*IsInBounds=*/false)) - return V; - return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); - } - - Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, - const Twine &Name = "") { - if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, /*IsInBounds=*/true)) - return V; - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); - } - - Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { - if (auto *V = Folder.FoldGEP(Ty, Ptr, {Idx}, /*IsInBounds=*/false)) - return V; - return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); - } - - Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, - const Twine &Name = "") { - if (auto *V = Folder.FoldGEP(Ty, Ptr, {Idx}, /*IsInBounds=*/true)) - return V; - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); - } - - Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false)) - return V; - - return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); - } - - Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true)) - return V; - - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); - } - - Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt32Ty(Context), Idx0), - ConstantInt::get(Type::getInt32Ty(Context), Idx1) - }; - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false)) - return V; - - return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); - } - - Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, - unsigned Idx1, const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt32Ty(Context), Idx0), - ConstantInt::get(Type::getInt32Ty(Context), Idx1) - }; - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true)) - return V; - - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); - } - - Value *CreateConstGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false)) - return V; - - return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); - } - - Value *CreateConstInBoundsGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true)) - return V; - - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); - } - - Value *CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt64Ty(Context), Idx0), - ConstantInt::get(Type::getInt64Ty(Context), Idx1) - }; - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false)) - return V; - - return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); - } - - Value *CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, - uint64_t Idx1, const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt64Ty(Context), Idx0), - ConstantInt::get(Type::getInt64Ty(Context), Idx1) - }; - - if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true)) - return V; - - return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); - } - - Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, - const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); - } - - /// Same as CreateGlobalString, but return a pointer with "i8*" type - /// instead of a pointer to array of i8. - /// - /// If no module is given via \p M, it is take from the insertion point basic - /// block. - Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", - unsigned AddressSpace = 0, - Module *M = nullptr) { - GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace, M); - Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - Constant *Indices[] = {Zero, Zero}; - return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, - Indices); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::Trunc, V, DestTy, Name); - } - - Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::ZExt, V, DestTy, Name); - } - - Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::SExt, V, DestTy, Name); - } - - /// Create a ZExt or Trunc from the integer value V to DestTy. Return - /// the value untouched if the type of V is already DestTy. - Value *CreateZExtOrTrunc(Value *V, Type *DestTy, - const Twine &Name = "") { - assert(V->getType()->isIntOrIntVectorTy() && - DestTy->isIntOrIntVectorTy() && - "Can only zero extend/truncate integers!"); - Type *VTy = V->getType(); - if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) - return CreateZExt(V, DestTy, Name); - if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) - return CreateTrunc(V, DestTy, Name); - return V; - } - - /// Create a SExt or Trunc from the integer value V to DestTy. Return - /// the value untouched if the type of V is already DestTy. - Value *CreateSExtOrTrunc(Value *V, Type *DestTy, - const Twine &Name = "") { - assert(V->getType()->isIntOrIntVectorTy() && - DestTy->isIntOrIntVectorTy() && - "Can only sign extend/truncate integers!"); - Type *VTy = V->getType(); - if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) - return CreateSExt(V, DestTy, Name); - if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) - return CreateTrunc(V, DestTy, Name); - return V; - } - - Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptoui, - V, DestTy, nullptr, Name); - return CreateCast(Instruction::FPToUI, V, DestTy, Name); - } - - Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptosi, - V, DestTy, nullptr, Name); - return CreateCast(Instruction::FPToSI, V, DestTy, Name); - } - - Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ - if (IsFPConstrained) - return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp, - V, DestTy, nullptr, Name); - return CreateCast(Instruction::UIToFP, V, DestTy, Name); - } - - Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ - if (IsFPConstrained) - return CreateConstrainedFPCast(Intrinsic::experimental_constrained_sitofp, - V, DestTy, nullptr, Name); - return CreateCast(Instruction::SIToFP, V, DestTy, Name); - } - - Value *CreateFPTrunc(Value *V, Type *DestTy, - const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPCast( - Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr, - Name); - return CreateCast(Instruction::FPTrunc, V, DestTy, Name); - } - - Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { - if (IsFPConstrained) - return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fpext, - V, DestTy, nullptr, Name); - return CreateCast(Instruction::FPExt, V, DestTy, Name); - } - - Value *CreatePtrToInt(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::PtrToInt, V, DestTy, Name); - } - - Value *CreateIntToPtr(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::IntToPtr, V, DestTy, Name); - } - - Value *CreateBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::BitCast, V, DestTy, Name); - } - - Value *CreateAddrSpaceCast(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); - } - - Value *CreateZExtOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); - } - - Value *CreateSExtOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); - } - - Value *CreateTruncOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); - } - - Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateCast(Op, VC, DestTy), Name); - return Insert(CastInst::Create(Op, V, DestTy), Name); - } - - Value *CreatePointerCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreatePointerCast(VC, DestTy), Name); - return Insert(CastInst::CreatePointerCast(V, DestTy), Name); - } - - Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - - if (auto *VC = dyn_cast(V)) { - return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy), - Name); - } - - return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy), - Name); - } - - Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); - return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); - } - - Value *CreateBitOrPointerCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (V->getType()->isPtrOrPtrVectorTy() && DestTy->isIntOrIntVectorTy()) - return CreatePtrToInt(V, DestTy, Name); - if (V->getType()->isIntOrIntVectorTy() && DestTy->isPtrOrPtrVectorTy()) - return CreateIntToPtr(V, DestTy, Name); - - return CreateBitCast(V, DestTy, Name); - } - - Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (auto *VC = dyn_cast(V)) - return Insert(Folder.CreateFPCast(VC, DestTy), Name); - return Insert(CastInst::CreateFPCast(V, DestTy), Name); - } - - CallInst *CreateConstrainedFPCast( - Intrinsic::ID ID, Value *V, Type *DestTy, - Instruction *FMFSource = nullptr, const Twine &Name = "", - MDNode *FPMathTag = nullptr, - Optional Rounding = None, - Optional Except = None); - - // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a - // compile time error, instead of converting the string to bool for the - // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) = delete; - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Compare Instructions - //===--------------------------------------------------------------------===// - - Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); - } - - Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); - } - - Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); - } - - Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); - } - - Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); - } - - Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); - } - - Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); - } - - Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); - } - - Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); - } - - Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); - } - - Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag); - } - - Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { - if (auto *V = Folder.FoldICmp(P, LHS, RHS)) - return V; - return Insert(new ICmpInst(P, LHS, RHS), Name); - } - - // Create a quiet floating-point comparison (i.e. one that raises an FP - // exception only in the case where an input is a signaling NaN). - // Note that this differs from CreateFCmpS only if IsFPConstrained is true. - Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, false); - } - - Value *CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CmpInst::isFPPredicate(Pred) - ? CreateFCmp(Pred, LHS, RHS, Name, FPMathTag) - : CreateICmp(Pred, LHS, RHS, Name); - } - - // Create a signaling floating-point comparison (i.e. one that raises an FP - // exception whenever an input is any NaN, signaling or quiet). - // Note that this differs from CreateFCmp only if IsFPConstrained is true. - Value *CreateFCmpS(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, true); - } - -private: - // Helper routine to create either a signaling or a quiet FP comparison. - Value *CreateFCmpHelper(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name, MDNode *FPMathTag, - bool IsSignaling); - -public: - CallInst *CreateConstrainedFPCmp( - Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R, - const Twine &Name = "", Optional Except = None); - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Other Instructions - //===--------------------------------------------------------------------===// - - PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues, - const Twine &Name = "") { - PHINode *Phi = PHINode::Create(Ty, NumReservedValues); - if (isa(Phi)) - setFPAttrs(Phi, nullptr /* MDNode* */, FMF); - return Insert(Phi, Name); - } - - CallInst *CreateCall(FunctionType *FTy, Value *Callee, - ArrayRef Args = None, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles); - if (IsFPConstrained) - setConstrainedFPCallAttr(CI); - if (isa(CI)) - setFPAttrs(CI, FPMathTag, FMF); - return Insert(CI, Name); - } - - CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles); - if (IsFPConstrained) - setConstrainedFPCallAttr(CI); - if (isa(CI)) - setFPAttrs(CI, FPMathTag, FMF); - return Insert(CI, Name); - } - - CallInst *CreateCall(FunctionCallee Callee, ArrayRef Args = None, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name, - FPMathTag); - } - - CallInst *CreateCall(FunctionCallee Callee, ArrayRef Args, - ArrayRef OpBundles, - const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, - OpBundles, Name, FPMathTag); - } - - CallInst *CreateConstrainedFPCall( - Function *Callee, ArrayRef Args, const Twine &Name = "", - Optional Rounding = None, - Optional Except = None); - - Value *CreateSelect(Value *C, Value *True, Value *False, - const Twine &Name = "", Instruction *MDFrom = nullptr); - - VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") { - return Insert(new VAArgInst(List, Ty), Name); - } - - Value *CreateExtractElement(Value *Vec, Value *Idx, - const Twine &Name = "") { - if (auto *VC = dyn_cast(Vec)) - if (auto *IC = dyn_cast(Idx)) - return Insert(Folder.CreateExtractElement(VC, IC), Name); - return Insert(ExtractElementInst::Create(Vec, Idx), Name); - } - - Value *CreateExtractElement(Value *Vec, uint64_t Idx, - const Twine &Name = "") { - return CreateExtractElement(Vec, getInt64(Idx), Name); - } - - Value *CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, - const Twine &Name = "") { - return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name); - } - - Value *CreateInsertElement(Type *VecTy, Value *NewElt, uint64_t Idx, - const Twine &Name = "") { - return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name); - } - - Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, - const Twine &Name = "") { - if (auto *VC = dyn_cast(Vec)) - if (auto *NC = dyn_cast(NewElt)) - if (auto *IC = dyn_cast(Idx)) - return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); - return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); - } - - Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx, - const Twine &Name = "") { - return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name); - } - - Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, - const Twine &Name = "") { - SmallVector IntMask; - ShuffleVectorInst::getShuffleMask(cast(Mask), IntMask); - return CreateShuffleVector(V1, V2, IntMask, Name); - } - - LLVM_ATTRIBUTE_DEPRECATED(Value *CreateShuffleVector(Value *V1, Value *V2, - ArrayRef Mask, - const Twine &Name = ""), - "Pass indices as 'int' instead") { - SmallVector IntMask; - IntMask.assign(Mask.begin(), Mask.end()); - return CreateShuffleVector(V1, V2, IntMask, Name); - } - - /// See class ShuffleVectorInst for a description of the mask representation. - Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef Mask, - const Twine &Name = "") { - if (auto *V1C = dyn_cast(V1)) - if (auto *V2C = dyn_cast(V2)) - return Insert(Folder.CreateShuffleVector(V1C, V2C, Mask), Name); - return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); - } - - /// Create a unary shuffle. The second vector operand of the IR instruction - /// is poison. - Value *CreateShuffleVector(Value *V, ArrayRef Mask, - const Twine &Name = "") { - return CreateShuffleVector(V, PoisonValue::get(V->getType()), Mask, Name); - } - - Value *CreateExtractValue(Value *Agg, - ArrayRef Idxs, - const Twine &Name = "") { - if (auto *AggC = dyn_cast(Agg)) - return Insert(Folder.CreateExtractValue(AggC, Idxs), Name); - return Insert(ExtractValueInst::Create(Agg, Idxs), Name); - } - - Value *CreateInsertValue(Value *Agg, Value *Val, - ArrayRef Idxs, - const Twine &Name = "") { - if (auto *AggC = dyn_cast(Agg)) - if (auto *ValC = dyn_cast(Val)) - return Insert(Folder.CreateInsertValue(AggC, ValC, Idxs), Name); - return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); - } - - LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses, - const Twine &Name = "") { - return Insert(LandingPadInst::Create(Ty, NumClauses), Name); - } - - Value *CreateFreeze(Value *V, const Twine &Name = "") { - return Insert(new FreezeInst(V), Name); - } - - //===--------------------------------------------------------------------===// - // Utility creation methods - //===--------------------------------------------------------------------===// - - /// Return an i1 value testing if \p Arg is null. - Value *CreateIsNull(Value *Arg, const Twine &Name = "") { - return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), - Name); - } - - /// Return an i1 value testing if \p Arg is not null. - Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { - return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), - Name); - } - - /// Return the i64 difference between two pointer values, dividing out - /// the size of the pointed-to objects. - /// - /// This is intended to implement C-style pointer subtraction. As such, the - /// pointers must be appropriately aligned for their element types and - /// pointing into the same object. - Value *CreatePtrDiff(Type *ElemTy, Value *LHS, Value *RHS, - const Twine &Name = ""); - - /// Create a launder.invariant.group intrinsic call. If Ptr type is - /// different from pointer to i8, it's casted to pointer to i8 in the same - /// address space before call and casted back to Ptr type after call. - Value *CreateLaunderInvariantGroup(Value *Ptr); - - /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is - /// different from pointer to i8, it's casted to pointer to i8 in the same - /// address space before call and casted back to Ptr type after call. - Value *CreateStripInvariantGroup(Value *Ptr); - - /// Return a vector value that contains the vector V reversed - Value *CreateVectorReverse(Value *V, const Twine &Name = ""); - - /// Return a vector splice intrinsic if using scalable vectors, otherwise - /// return a shufflevector. If the immediate is positive, a vector is - /// extracted from concat(V1, V2), starting at Imm. If the immediate - /// is negative, we extract -Imm elements from V1 and the remaining - /// elements from V2. Imm is a signed integer in the range - /// -VL <= Imm < VL (where VL is the runtime vector length of the - /// source/result vector) - Value *CreateVectorSplice(Value *V1, Value *V2, int64_t Imm, - const Twine &Name = ""); - - /// Return a vector value that contains \arg V broadcasted to \p - /// NumElts elements. - Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = ""); - - /// Return a vector value that contains \arg V broadcasted to \p - /// EC elements. - Value *CreateVectorSplat(ElementCount EC, Value *V, const Twine &Name = ""); - - /// Return a value that has been extracted from a larger integer type. - Value *CreateExtractInteger(const DataLayout &DL, Value *From, - IntegerType *ExtractedTy, uint64_t Offset, - const Twine &Name); - - Value *CreatePreserveArrayAccessIndex(Type *ElTy, Value *Base, - unsigned Dimension, unsigned LastIndex, - MDNode *DbgInfo); - - Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex, - MDNode *DbgInfo); - - Value *CreatePreserveStructAccessIndex(Type *ElTy, Value *Base, - unsigned Index, unsigned FieldIndex, - MDNode *DbgInfo); - -private: - /// Helper function that creates an assume intrinsic call that - /// represents an alignment assumption on the provided pointer \p PtrValue - /// with offset \p OffsetValue and alignment value \p AlignValue. - CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL, - Value *PtrValue, Value *AlignValue, - Value *OffsetValue); - -public: - /// Create an assume intrinsic call that represents an alignment - /// assumption on the provided pointer. - /// - /// An optional offset can be provided, and if it is provided, the offset - /// must be subtracted from the provided pointer to get the pointer with the - /// specified alignment. - CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, - unsigned Alignment, - Value *OffsetValue = nullptr); - - /// Create an assume intrinsic call that represents an alignment - /// assumption on the provided pointer. - /// - /// An optional offset can be provided, and if it is provided, the offset - /// must be subtracted from the provided pointer to get the pointer with the - /// specified alignment. - /// - /// This overload handles the condition where the Alignment is dependent - /// on an existing value rather than a static value. - CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, - Value *Alignment, - Value *OffsetValue = nullptr); -}; - -/// This provides a uniform API for creating instructions and inserting -/// them into a basic block: either at the end of a BasicBlock, or at a specific -/// iterator location in a block. -/// -/// Note that the builder does not expose the full generality of LLVM -/// instructions. For access to extra instruction properties, use the mutators -/// (e.g. setVolatile) on the instructions after they have been -/// created. Convenience state exists to specify fast-math flags and fp-math -/// tags. -/// -/// The first template argument specifies a class to use for creating constants. -/// This defaults to creating minimally folded constants. The second template -/// argument allows clients to specify custom insertion hooks that are called on -/// every newly created insertion. -template -class IRBuilder : public IRBuilderBase { -private: - FolderTy Folder; - InserterTy Inserter; - -public: - IRBuilder(LLVMContext &C, FolderTy Folder, InserterTy Inserter = InserterTy(), - MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles), - Folder(Folder), Inserter(Inserter) {} - - explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles) {} - - explicit IRBuilder(BasicBlock *TheBB, FolderTy Folder, - MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter, - FPMathTag, OpBundles), Folder(Folder) { - SetInsertPoint(TheBB); - } - - explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter, - FPMathTag, OpBundles) { - SetInsertPoint(TheBB); - } - - explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(IP->getContext(), this->Folder, this->Inserter, - FPMathTag, OpBundles) { - SetInsertPoint(IP); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, FolderTy Folder, - MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter, - FPMathTag, OpBundles), Folder(Folder) { - SetInsertPoint(TheBB, IP); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, - MDNode *FPMathTag = nullptr, - ArrayRef OpBundles = None) - : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter, - FPMathTag, OpBundles) { - SetInsertPoint(TheBB, IP); - } - - /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard - /// or FastMathFlagGuard instead. - IRBuilder(const IRBuilder &) = delete; - - InserterTy &getInserter() { return Inserter; } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef) - -} // end namespace llvm - -#endif // LLVM_IR_IRBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/IRBuilderFolder.h b/suite/synctools/tablegen/include/llvm/IR/IRBuilderFolder.h deleted file mode 100644 index 2827ab553a..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IRBuilderFolder.h +++ /dev/null @@ -1,131 +0,0 @@ -//===- IRBuilderFolder.h - Const folder interface for IRBuilder -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines for constant folding interface used by IRBuilder. -// It is implemented by ConstantFolder (default), TargetFolder and NoFoler. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_IRBUILDERFOLDER_H -#define LLVM_IR_IRBUILDERFOLDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" - -namespace llvm { - -/// IRBuilderFolder - Interface for constant folding in IRBuilder. -class IRBuilderFolder { -public: - virtual ~IRBuilderFolder(); - - //===--------------------------------------------------------------------===// - // Value-based folders. - // - // Return an existing value or a constant if the operation can be simplified. - // Otherwise return nullptr. - //===--------------------------------------------------------------------===// - virtual Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, - bool HasNSW = false) const = 0; - - virtual Value *FoldAnd(Value *LHS, Value *RHS) const = 0; - - virtual Value *FoldOr(Value *LHS, Value *RHS) const = 0; - - virtual Value *FoldICmp(CmpInst::Predicate P, Value *LHS, - Value *RHS) const = 0; - - virtual Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, - bool IsInBounds = false) const = 0; - - virtual Value *FoldSelect(Value *C, Value *True, Value *False) const = 0; - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - virtual Value *CreateFAdd(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const = 0; - virtual Value *CreateFSub(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const = 0; - virtual Value *CreateFMul(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateUDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const = 0; - virtual Value *CreateSDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const = 0; - virtual Value *CreateFDiv(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateURem(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateSRem(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateFRem(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateShl(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const = 0; - virtual Value *CreateLShr(Constant *LHS, Constant *RHS, - bool isExact = false) const = 0; - virtual Value *CreateAShr(Constant *LHS, Constant *RHS, - bool isExact = false) const = 0; - virtual Value *CreateXor(Constant *LHS, Constant *RHS) const = 0; - virtual Value *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const = 0; - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - virtual Value *CreateNeg(Constant *C, - bool HasNUW = false, bool HasNSW = false) const = 0; - virtual Value *CreateFNeg(Constant *C) const = 0; - virtual Value *CreateNot(Constant *C) const = 0; - virtual Value *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const = 0; - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - virtual Value *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const = 0; - virtual Value *CreatePointerCast(Constant *C, Type *DestTy) const = 0; - virtual Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C, - Type *DestTy) const = 0; - virtual Value *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const = 0; - virtual Value *CreateFPCast(Constant *C, Type *DestTy) const = 0; - virtual Value *CreateBitCast(Constant *C, Type *DestTy) const = 0; - virtual Value *CreateIntToPtr(Constant *C, Type *DestTy) const = 0; - virtual Value *CreatePtrToInt(Constant *C, Type *DestTy) const = 0; - virtual Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const = 0; - virtual Value *CreateSExtOrBitCast(Constant *C, Type *DestTy) const = 0; - virtual Value *CreateTruncOrBitCast(Constant *C, Type *DestTy) const = 0; - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - virtual Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const = 0; - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - virtual Value *CreateExtractElement(Constant *Vec, Constant *Idx) const = 0; - virtual Value *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const = 0; - virtual Value *CreateShuffleVector(Constant *V1, Constant *V2, - ArrayRef Mask) const = 0; - virtual Value *CreateExtractValue(Constant *Agg, - ArrayRef IdxList) const = 0; - virtual Value *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef IdxList) const = 0; -}; - -} // end namespace llvm - -#endif // LLVM_IR_IRBUILDERFOLDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/IRPrintingPasses.h b/suite/synctools/tablegen/include/llvm/IR/IRPrintingPasses.h deleted file mode 100644 index 3fba5b81e3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IRPrintingPasses.h +++ /dev/null @@ -1,89 +0,0 @@ -//===- IRPrintingPasses.h - Passes to print out IR constructs ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file defines passes to print out IR in various granularities. The -/// PrintModulePass pass simply prints out the entire module when it is -/// executed. The PrintFunctionPass class is designed to be pipelined with -/// other FunctionPass's, and prints out the functions of the module as they -/// are processed. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_IRPRINTINGPASSES_H -#define LLVM_IR_IRPRINTINGPASSES_H - -#include "llvm/IR/PassManager.h" -#include - -namespace llvm { -class raw_ostream; -class StringRef; -class Function; -class FunctionPass; -class Module; -class ModulePass; -class Pass; - -/// Create and return a pass that writes the module to the specified -/// \c raw_ostream. -ModulePass *createPrintModulePass(raw_ostream &OS, - const std::string &Banner = "", - bool ShouldPreserveUseListOrder = false); - -/// Create and return a pass that prints functions to the specified -/// \c raw_ostream as they are processed. -FunctionPass *createPrintFunctionPass(raw_ostream &OS, - const std::string &Banner = ""); - -/// Print out a name of an LLVM value without any prefixes. -/// -/// The name is surrounded with ""'s and escaped if it has any special or -/// non-printable characters in it. -void printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name); - -/// Return true if a pass is for IR printing. -bool isIRPrintingPass(Pass *P); - -/// Pass for printing a Module as LLVM's text IR assembly. -/// -/// Note: This pass is for use with the new pass manager. Use the create...Pass -/// functions above to create passes for use with the legacy pass manager. -class PrintModulePass : public PassInfoMixin { - raw_ostream &OS; - std::string Banner; - bool ShouldPreserveUseListOrder; - -public: - PrintModulePass(); - PrintModulePass(raw_ostream &OS, const std::string &Banner = "", - bool ShouldPreserveUseListOrder = false); - - PreservedAnalyses run(Module &M, AnalysisManager &); - static bool isRequired() { return true; } -}; - -/// Pass for printing a Function as LLVM's text IR assembly. -/// -/// Note: This pass is for use with the new pass manager. Use the create...Pass -/// functions above to create passes for use with the legacy pass manager. -class PrintFunctionPass : public PassInfoMixin { - raw_ostream &OS; - std::string Banner; - -public: - PrintFunctionPass(); - PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - - PreservedAnalyses run(Function &F, AnalysisManager &); - static bool isRequired() { return true; } -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/InlineAsm.h b/suite/synctools/tablegen/include/llvm/IR/InlineAsm.h deleted file mode 100644 index cf6b7af969..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/InlineAsm.h +++ /dev/null @@ -1,464 +0,0 @@ -//===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class represents the inline asm strings, which are Value*'s that are -// used as the callee operand of call instructions. InlineAsm's are uniqued -// like constants, and created via InlineAsm::get(...). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INLINEASM_H -#define LLVM_IR_INLINEASM_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include - -namespace llvm { - -class FunctionType; -class PointerType; -template class ConstantUniqueMap; - -class InlineAsm final : public Value { -public: - enum AsmDialect { - AD_ATT, - AD_Intel - }; - -private: - friend struct InlineAsmKeyType; - friend class ConstantUniqueMap; - - std::string AsmString, Constraints; - FunctionType *FTy; - bool HasSideEffects; - bool IsAlignStack; - AsmDialect Dialect; - bool CanThrow; - - InlineAsm(FunctionType *Ty, const std::string &AsmString, - const std::string &Constraints, bool hasSideEffects, - bool isAlignStack, AsmDialect asmDialect, bool canThrow); - - /// When the ConstantUniqueMap merges two types and makes two InlineAsms - /// identical, it destroys one of them with this method. - void destroyConstant(); - -public: - InlineAsm(const InlineAsm &) = delete; - InlineAsm &operator=(const InlineAsm &) = delete; - - /// InlineAsm::get - Return the specified uniqued inline asm string. - /// - static InlineAsm *get(FunctionType *Ty, StringRef AsmString, - StringRef Constraints, bool hasSideEffects, - bool isAlignStack = false, - AsmDialect asmDialect = AD_ATT, bool canThrow = false); - - bool hasSideEffects() const { return HasSideEffects; } - bool isAlignStack() const { return IsAlignStack; } - AsmDialect getDialect() const { return Dialect; } - bool canThrow() const { return CanThrow; } - - /// getType - InlineAsm's are always pointers. - /// - PointerType *getType() const { - return reinterpret_cast(Value::getType()); - } - - /// getFunctionType - InlineAsm's are always pointers to functions. - /// - FunctionType *getFunctionType() const; - - const std::string &getAsmString() const { return AsmString; } - const std::string &getConstraintString() const { return Constraints; } - - /// Verify - This static method can be used by the parser to check to see if - /// the specified constraint string is legal for the type. This returns true - /// if legal, false if not. - /// - static bool Verify(FunctionType *Ty, StringRef Constraints); - - // Constraint String Parsing - enum ConstraintPrefix { - isInput, // 'x' - isOutput, // '=x' - isClobber // '~x' - }; - - using ConstraintCodeVector = std::vector; - - struct SubConstraintInfo { - /// MatchingInput - If this is not -1, this is an output constraint where an - /// input constraint is required to match it (e.g. "0"). The value is the - /// constraint number that matches this one (for example, if this is - /// constraint #0 and constraint #4 has the value "0", this will be 4). - int MatchingInput = -1; - - /// Code - The constraint code, either the register name (in braces) or the - /// constraint letter/number. - ConstraintCodeVector Codes; - - /// Default constructor. - SubConstraintInfo() = default; - }; - - using SubConstraintInfoVector = std::vector; - struct ConstraintInfo; - using ConstraintInfoVector = std::vector; - - struct ConstraintInfo { - /// Type - The basic type of the constraint: input/output/clobber - /// - ConstraintPrefix Type = isInput; - - /// isEarlyClobber - "&": output operand writes result before inputs are all - /// read. This is only ever set for an output operand. - bool isEarlyClobber = false; - - /// MatchingInput - If this is not -1, this is an output constraint where an - /// input constraint is required to match it (e.g. "0"). The value is the - /// constraint number that matches this one (for example, if this is - /// constraint #0 and constraint #4 has the value "0", this will be 4). - int MatchingInput = -1; - - /// hasMatchingInput - Return true if this is an output constraint that has - /// a matching input constraint. - bool hasMatchingInput() const { return MatchingInput != -1; } - - /// isCommutative - This is set to true for a constraint that is commutative - /// with the next operand. - bool isCommutative = false; - - /// isIndirect - True if this operand is an indirect operand. This means - /// that the address of the source or destination is present in the call - /// instruction, instead of it being returned or passed in explicitly. This - /// is represented with a '*' in the asm string. - bool isIndirect = false; - - /// Code - The constraint code, either the register name (in braces) or the - /// constraint letter/number. - ConstraintCodeVector Codes; - - /// isMultipleAlternative - '|': has multiple-alternative constraints. - bool isMultipleAlternative = false; - - /// multipleAlternatives - If there are multiple alternative constraints, - /// this array will contain them. Otherwise it will be empty. - SubConstraintInfoVector multipleAlternatives; - - /// The currently selected alternative constraint index. - unsigned currentAlternativeIndex = 0; - - /// Default constructor. - ConstraintInfo() = default; - - /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the - /// fields in this structure. If the constraint string is not understood, - /// return true, otherwise return false. - bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); - - /// selectAlternative - Point this constraint to the alternative constraint - /// indicated by the index. - void selectAlternative(unsigned index); - - /// Whether this constraint corresponds to an argument. - bool hasArg() const { - return Type == isInput || (Type == isOutput && isIndirect); - } - }; - - /// ParseConstraints - Split up the constraint string into the specific - /// constraints and their prefixes. If this returns an empty vector, and if - /// the constraint string itself isn't empty, there was an error parsing. - static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); - - /// ParseConstraints - Parse the constraints of this inlineasm object, - /// returning them the same way that ParseConstraints(str) does. - ConstraintInfoVector ParseConstraints() const { - return ParseConstraints(Constraints); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::InlineAsmVal; - } - - // These are helper methods for dealing with flags in the INLINEASM SDNode - // in the backend. - // - // The encoding of the flag word is currently: - // Bits 2-0 - A Kind_* value indicating the kind of the operand. - // Bits 15-3 - The number of SDNode operands associated with this inline - // assembly operand. - // If bit 31 is set: - // Bit 30-16 - The operand number that this operand must match. - // When bits 2-0 are Kind_Mem, the Constraint_* value must be - // obtained from the flags for this operand number. - // Else if bits 2-0 are Kind_Mem: - // Bit 30-16 - A Constraint_* value indicating the original constraint - // code. - // Else: - // Bit 30-16 - The register class ID to use for the operand. - - enum : uint32_t { - // Fixed operands on an INLINEASM SDNode. - Op_InputChain = 0, - Op_AsmString = 1, - Op_MDNode = 2, - Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect. - Op_FirstOperand = 4, - - // Fixed operands on an INLINEASM MachineInstr. - MIOp_AsmString = 0, - MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect. - MIOp_FirstOperand = 2, - - // Interpretation of the MIOp_ExtraInfo bit field. - Extra_HasSideEffects = 1, - Extra_IsAlignStack = 2, - Extra_AsmDialect = 4, - Extra_MayLoad = 8, - Extra_MayStore = 16, - Extra_IsConvergent = 32, - - // Inline asm operands map to multiple SDNode / MachineInstr operands. - // The first operand is an immediate describing the asm operand, the low - // bits is the kind: - Kind_RegUse = 1, // Input register, "r". - Kind_RegDef = 2, // Output register, "=r". - Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". - Kind_Clobber = 4, // Clobbered register, "~r". - Kind_Imm = 5, // Immediate. - Kind_Mem = 6, // Memory operand, "m". - - // Memory constraint codes. - // These could be tablegenerated but there's little need to do that since - // there's plenty of space in the encoding to support the union of all - // constraint codes for all targets. - Constraint_Unknown = 0, - Constraint_es, - Constraint_i, - Constraint_m, - Constraint_o, - Constraint_v, - Constraint_A, - Constraint_Q, - Constraint_R, - Constraint_S, - Constraint_T, - Constraint_Um, - Constraint_Un, - Constraint_Uq, - Constraint_Us, - Constraint_Ut, - Constraint_Uv, - Constraint_Uy, - Constraint_X, - Constraint_Z, - Constraint_ZC, - Constraint_Zy, - Constraints_Max = Constraint_Zy, - Constraints_ShiftAmount = 16, - - Flag_MatchingOperand = 0x80000000 - }; - - static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { - assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); - assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind"); - return Kind | (NumOps << 3); - } - - static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} - static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } - static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } - static bool isRegDefEarlyClobberKind(unsigned Flag) { - return getKind(Flag) == Kind_RegDefEarlyClobber; - } - static bool isClobberKind(unsigned Flag) { - return getKind(Flag) == Kind_Clobber; - } - - /// getFlagWordForMatchingOp - Augment an existing flag word returned by - /// getFlagWord with information indicating that this input operand is tied - /// to a previous output operand. - static unsigned getFlagWordForMatchingOp(unsigned InputFlag, - unsigned MatchedOperandNo) { - assert(MatchedOperandNo <= 0x7fff && "Too big matched operand"); - assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); - return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); - } - - /// getFlagWordForRegClass - Augment an existing flag word returned by - /// getFlagWord with the required register class for the following register - /// operands. - /// A tied use operand cannot have a register class, use the register class - /// from the def operand instead. - static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { - // Store RC + 1, reserve the value 0 to mean 'no register class'. - ++RC; - assert(!isImmKind(InputFlag) && "Immediates cannot have a register class"); - assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class"); - assert(RC <= 0x7fff && "Too large register class ID"); - assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); - return InputFlag | (RC << 16); - } - - /// Augment an existing flag word returned by getFlagWord with the constraint - /// code for a memory constraint. - static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { - assert(isMemKind(InputFlag) && "InputFlag is not a memory constraint!"); - assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); - assert(Constraint <= Constraints_Max && "Unknown constraint ID"); - assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); - return InputFlag | (Constraint << Constraints_ShiftAmount); - } - - static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { - assert(isMemKind(InputFlag)); - return InputFlag & ~(0x7fff << Constraints_ShiftAmount); - } - - static unsigned getKind(unsigned Flags) { - return Flags & 7; - } - - static unsigned getMemoryConstraintID(unsigned Flag) { - assert(isMemKind(Flag)); - return (Flag >> Constraints_ShiftAmount) & 0x7fff; - } - - /// getNumOperandRegisters - Extract the number of registers field from the - /// inline asm operand flag. - static unsigned getNumOperandRegisters(unsigned Flag) { - return (Flag & 0xffff) >> 3; - } - - /// isUseOperandTiedToDef - Return true if the flag of the inline asm - /// operand indicates it is an use operand that's matched to a def operand. - static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { - if ((Flag & Flag_MatchingOperand) == 0) - return false; - Idx = (Flag & ~Flag_MatchingOperand) >> 16; - return true; - } - - /// hasRegClassConstraint - Returns true if the flag contains a register - /// class constraint. Sets RC to the register class ID. - static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { - if (Flag & Flag_MatchingOperand) - return false; - unsigned High = Flag >> 16; - // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise - // stores RC + 1. - if (!High) - return false; - RC = High - 1; - return true; - } - - static std::vector getExtraInfoNames(unsigned ExtraInfo) { - std::vector Result; - if (ExtraInfo & InlineAsm::Extra_HasSideEffects) - Result.push_back("sideeffect"); - if (ExtraInfo & InlineAsm::Extra_MayLoad) - Result.push_back("mayload"); - if (ExtraInfo & InlineAsm::Extra_MayStore) - Result.push_back("maystore"); - if (ExtraInfo & InlineAsm::Extra_IsConvergent) - Result.push_back("isconvergent"); - if (ExtraInfo & InlineAsm::Extra_IsAlignStack) - Result.push_back("alignstack"); - - AsmDialect Dialect = - InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect)); - - if (Dialect == InlineAsm::AD_ATT) - Result.push_back("attdialect"); - if (Dialect == InlineAsm::AD_Intel) - Result.push_back("inteldialect"); - - return Result; - } - - static StringRef getKindName(unsigned Kind) { - switch (Kind) { - case InlineAsm::Kind_RegUse: - return "reguse"; - case InlineAsm::Kind_RegDef: - return "regdef"; - case InlineAsm::Kind_RegDefEarlyClobber: - return "regdef-ec"; - case InlineAsm::Kind_Clobber: - return "clobber"; - case InlineAsm::Kind_Imm: - return "imm"; - case InlineAsm::Kind_Mem: - return "mem"; - default: - llvm_unreachable("Unknown operand kind"); - } - } - - static StringRef getMemConstraintName(unsigned Constraint) { - switch (Constraint) { - case InlineAsm::Constraint_es: - return "es"; - case InlineAsm::Constraint_i: - return "i"; - case InlineAsm::Constraint_m: - return "m"; - case InlineAsm::Constraint_o: - return "o"; - case InlineAsm::Constraint_v: - return "v"; - case InlineAsm::Constraint_Q: - return "Q"; - case InlineAsm::Constraint_R: - return "R"; - case InlineAsm::Constraint_S: - return "S"; - case InlineAsm::Constraint_T: - return "T"; - case InlineAsm::Constraint_Um: - return "Um"; - case InlineAsm::Constraint_Un: - return "Un"; - case InlineAsm::Constraint_Uq: - return "Uq"; - case InlineAsm::Constraint_Us: - return "Us"; - case InlineAsm::Constraint_Ut: - return "Ut"; - case InlineAsm::Constraint_Uv: - return "Uv"; - case InlineAsm::Constraint_Uy: - return "Uy"; - case InlineAsm::Constraint_X: - return "X"; - case InlineAsm::Constraint_Z: - return "Z"; - case InlineAsm::Constraint_ZC: - return "ZC"; - case InlineAsm::Constraint_Zy: - return "Zy"; - default: - llvm_unreachable("Unknown memory constraint"); - } - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_INLINEASM_H diff --git a/suite/synctools/tablegen/include/llvm/IR/InstIterator.h b/suite/synctools/tablegen/include/llvm/IR/InstIterator.h deleted file mode 100644 index 054fe4e9cb..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/InstIterator.h +++ /dev/null @@ -1,162 +0,0 @@ -//===- InstIterator.h - Classes for inst iteration --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains definitions of two iterators for iterating over the -// instructions in a function. This is effectively a wrapper around a two level -// iterator that can probably be genericized later. -// -// Note that this iterator gets invalidated any time that basic blocks or -// instructions are moved around. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INSTITERATOR_H -#define LLVM_IR_INSTITERATOR_H - -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include - -namespace llvm { - -// This class implements inst_begin() & inst_end() for -// inst_iterator and const_inst_iterator's. -// -template class InstIterator { - using BBty = BB_t; - using BBIty = BB_i_t; - using BIty = BI_t; - using IIty = II_t; - BB_t *BBs; // BasicBlocksType - BB_i_t BB; // BasicBlocksType::iterator - BI_t BI; // BasicBlock::iterator - -public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = IIty; - using difference_type = signed; - using pointer = IIty *; - using reference = IIty &; - - // Default constructor - InstIterator() = default; - - // Copy constructor... - template - InstIterator(const InstIterator &II) - : BBs(II.BBs), BB(II.BB), BI(II.BI) {} - - template - InstIterator(InstIterator &II) - : BBs(II.BBs), BB(II.BB), BI(II.BI) {} - - template InstIterator(M &m) - : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor - if (BB != BBs->end()) { - BI = BB->begin(); - advanceToNextBB(); - } - } - - template InstIterator(M &m, bool) - : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor - } - - // Accessors to get at the underlying iterators... - inline BBIty &getBasicBlockIterator() { return BB; } - inline BIty &getInstructionIterator() { return BI; } - - inline reference operator*() const { return *BI; } - inline pointer operator->() const { return &operator*(); } - - inline bool operator==(const InstIterator &y) const { - return BB == y.BB && (BB == BBs->end() || BI == y.BI); - } - inline bool operator!=(const InstIterator& y) const { - return !operator==(y); - } - - InstIterator& operator++() { - ++BI; - advanceToNextBB(); - return *this; - } - inline InstIterator operator++(int) { - InstIterator tmp = *this; ++*this; return tmp; - } - - InstIterator& operator--() { - while (BB == BBs->end() || BI == BB->begin()) { - --BB; - BI = BB->end(); - } - --BI; - return *this; - } - inline InstIterator operator--(int) { - InstIterator tmp = *this; --*this; return tmp; - } - - inline bool atEnd() const { return BB == BBs->end(); } - -private: - inline void advanceToNextBB() { - // The only way that the II could be broken is if it is now pointing to - // the end() of the current BasicBlock and there are successor BBs. - while (BI == BB->end()) { - ++BB; - if (BB == BBs->end()) break; - BI = BB->begin(); - } - } -}; - -using inst_iterator = - InstIterator, Function::iterator, - BasicBlock::iterator, Instruction>; -using const_inst_iterator = - InstIterator, - Function::const_iterator, BasicBlock::const_iterator, - const Instruction>; -using inst_range = iterator_range; -using const_inst_range = iterator_range; - -inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } -inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } -inline inst_range instructions(Function *F) { - return inst_range(inst_begin(F), inst_end(F)); -} -inline const_inst_iterator inst_begin(const Function *F) { - return const_inst_iterator(*F); -} -inline const_inst_iterator inst_end(const Function *F) { - return const_inst_iterator(*F, true); -} -inline const_inst_range instructions(const Function *F) { - return const_inst_range(inst_begin(F), inst_end(F)); -} -inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } -inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } -inline inst_range instructions(Function &F) { - return inst_range(inst_begin(F), inst_end(F)); -} -inline const_inst_iterator inst_begin(const Function &F) { - return const_inst_iterator(F); -} -inline const_inst_iterator inst_end(const Function &F) { - return const_inst_iterator(F, true); -} -inline const_inst_range instructions(const Function &F) { - return const_inst_range(inst_begin(F), inst_end(F)); -} - -} // end namespace llvm - -#endif // LLVM_IR_INSTITERATOR_H diff --git a/suite/synctools/tablegen/include/llvm/IR/InstVisitor.h b/suite/synctools/tablegen/include/llvm/IR/InstVisitor.h deleted file mode 100644 index 359a4e6e4b..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/InstVisitor.h +++ /dev/null @@ -1,316 +0,0 @@ -//===- InstVisitor.h - Instruction visitor templates ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_IR_INSTVISITOR_H -#define LLVM_IR_INSTVISITOR_H - -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" - -namespace llvm { - -// We operate on opaque instruction classes, so forward declare all instruction -// types now... -// -#define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; -#include "llvm/IR/Instruction.def" - -#define DELEGATE(CLASS_TO_VISIT) \ - return static_cast(this)-> \ - visit##CLASS_TO_VISIT(static_cast(I)) - - -/// Base class for instruction visitors -/// -/// Instruction visitors are used when you want to perform different actions -/// for different kinds of instructions without having to use lots of casts -/// and a big switch statement (in your code, that is). -/// -/// To define your own visitor, inherit from this class, specifying your -/// new type for the 'SubClass' template parameter, and "override" visitXXX -/// functions in your class. I say "override" because this class is defined -/// in terms of statically resolved overloading, not virtual functions. -/// -/// For example, here is a visitor that counts the number of malloc -/// instructions processed: -/// -/// /// Declare the class. Note that we derive from InstVisitor instantiated -/// /// with _our new subclasses_ type. -/// /// -/// struct CountAllocaVisitor : public InstVisitor { -/// unsigned Count; -/// CountAllocaVisitor() : Count(0) {} -/// -/// void visitAllocaInst(AllocaInst &AI) { ++Count; } -/// }; -/// -/// And this class would be used like this: -/// CountAllocaVisitor CAV; -/// CAV.visit(function); -/// NumAllocas = CAV.Count; -/// -/// The defined has 'visit' methods for Instruction, and also for BasicBlock, -/// Function, and Module, which recursively process all contained instructions. -/// -/// Note that if you don't implement visitXXX for some instruction type, -/// the visitXXX method for instruction superclass will be invoked. So -/// if instructions are added in the future, they will be automatically -/// supported, if you handle one of their superclasses. -/// -/// The optional second template argument specifies the type that instruction -/// visitation functions should return. If you specify this, you *MUST* provide -/// an implementation of visitInstruction though!. -/// -/// Note that this class is specifically designed as a template to avoid -/// virtual function call overhead. Defining and using an InstVisitor is just -/// as efficient as having your own switch statement over the instruction -/// opcode. -template -class InstVisitor { - //===--------------------------------------------------------------------===// - // Interface code - This is the public interface of the InstVisitor that you - // use to visit instructions... - // - -public: - // Generic visit method - Allow visitation to all instructions in a range - template - void visit(Iterator Start, Iterator End) { - while (Start != End) - static_cast(this)->visit(*Start++); - } - - // Define visitors for functions and basic blocks... - // - void visit(Module &M) { - static_cast(this)->visitModule(M); - visit(M.begin(), M.end()); - } - void visit(Function &F) { - static_cast(this)->visitFunction(F); - visit(F.begin(), F.end()); - } - void visit(BasicBlock &BB) { - static_cast(this)->visitBasicBlock(BB); - visit(BB.begin(), BB.end()); - } - - // Forwarding functions so that the user can visit with pointers AND refs. - void visit(Module *M) { visit(*M); } - void visit(Function *F) { visit(*F); } - void visit(BasicBlock *BB) { visit(*BB); } - RetTy visit(Instruction *I) { return visit(*I); } - - // visit - Finally, code to visit an instruction... - // - RetTy visit(Instruction &I) { - static_assert(std::is_base_of::value, - "Must pass the derived type to this template!"); - - switch (I.getOpcode()) { - default: llvm_unreachable("Unknown instruction type encountered!"); - // Build the switch statement using the Instruction.def file... -#define HANDLE_INST(NUM, OPCODE, CLASS) \ - case Instruction::OPCODE: return \ - static_cast(this)-> \ - visit##OPCODE(static_cast(I)); -#include "llvm/IR/Instruction.def" - } - } - - //===--------------------------------------------------------------------===// - // Visitation functions... these functions provide default fallbacks in case - // the user does not specify what to do for a particular instruction type. - // The default behavior is to generalize the instruction type to its subtype - // and try visiting the subtype. All of this should be inlined perfectly, - // because there are no virtual functions to get in the way. - // - - // When visiting a module, function or basic block directly, these methods get - // called to indicate when transitioning into a new unit. - // - void visitModule (Module &M) {} - void visitFunction (Function &F) {} - void visitBasicBlock(BasicBlock &BB) {} - - // Define instruction specific visitor functions that can be overridden to - // handle SPECIFIC instructions. These functions automatically define - // visitMul to proxy to visitBinaryOperator for instance in case the user does - // not need this generality. - // - // These functions can also implement fan-out, when a single opcode and - // instruction have multiple more specific Instruction subclasses. The Call - // instruction currently supports this. We implement that by redirecting that - // instruction to a special delegation helper. -#define HANDLE_INST(NUM, OPCODE, CLASS) \ - RetTy visit##OPCODE(CLASS &I) { \ - if (NUM == Instruction::Call) \ - return delegateCallInst(I); \ - else \ - DELEGATE(CLASS); \ - } -#include "llvm/IR/Instruction.def" - - // Specific Instruction type classes... note that all of the casts are - // necessary because we use the instruction classes as opaque types... - // - RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} - RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} - RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitLoadInst(LoadInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction);} - RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { DELEGATE(Instruction);} - RetTy visitAtomicRMWInst(AtomicRMWInst &I) { DELEGATE(Instruction);} - RetTy visitFenceInst(FenceInst &I) { DELEGATE(Instruction);} - RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction);} - RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction);} - RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst);} - RetTy visitZExtInst(ZExtInst &I) { DELEGATE(CastInst);} - RetTy visitSExtInst(SExtInst &I) { DELEGATE(CastInst);} - RetTy visitFPTruncInst(FPTruncInst &I) { DELEGATE(CastInst);} - RetTy visitFPExtInst(FPExtInst &I) { DELEGATE(CastInst);} - RetTy visitFPToUIInst(FPToUIInst &I) { DELEGATE(CastInst);} - RetTy visitFPToSIInst(FPToSIInst &I) { DELEGATE(CastInst);} - RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst);} - RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst);} - RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);} - RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);} - RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);} - RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);} - RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);} - RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} - RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction);} - RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction);} - RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);} - RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } - RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } - RetTy visitFuncletPadInst(FuncletPadInst &I) { DELEGATE(Instruction); } - RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(FuncletPadInst); } - RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(FuncletPadInst); } - RetTy visitFreezeInst(FreezeInst &I) { DELEGATE(Instruction); } - - // Handle the special intrinsic instruction classes. - RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgVariableIntrinsic);} - RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgVariableIntrinsic);} - RetTy visitDbgVariableIntrinsic(DbgVariableIntrinsic &I) - { DELEGATE(DbgInfoIntrinsic);} - RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);} - RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I){ DELEGATE(IntrinsicInst); } - RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } - RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } - RetTy visitMemCpyInlineInst(MemCpyInlineInst &I) { - DELEGATE(MemTransferInst); - } - RetTy visitMemMoveInst(MemMoveInst &I) { DELEGATE(MemTransferInst); } - RetTy visitMemTransferInst(MemTransferInst &I) { DELEGATE(MemIntrinsic); } - RetTy visitMemIntrinsic(MemIntrinsic &I) { DELEGATE(IntrinsicInst); } - RetTy visitVAStartInst(VAStartInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitVAEndInst(VAEndInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitVACopyInst(VACopyInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } - RetTy visitCallInst(CallInst &I) { DELEGATE(CallBase); } - RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(CallBase); } - RetTy visitCallBrInst(CallBrInst &I) { DELEGATE(CallBase); } - - // While terminators don't have a distinct type modeling them, we support - // intercepting them with dedicated a visitor callback. - RetTy visitReturnInst(ReturnInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitBranchInst(BranchInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitSwitchInst(SwitchInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitIndirectBrInst(IndirectBrInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitResumeInst(ResumeInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitUnreachableInst(UnreachableInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitCleanupReturnInst(CleanupReturnInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitCatchReturnInst(CatchReturnInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitCatchSwitchInst(CatchSwitchInst &I) { - return static_cast(this)->visitTerminator(I); - } - RetTy visitTerminator(Instruction &I) { DELEGATE(Instruction);} - - // Next level propagators: If the user does not overload a specific - // instruction type, they can overload one of these to get the whole class - // of instructions... - // - RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitUnaryOperator(UnaryOperator &I) { DELEGATE(UnaryInstruction);} - RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);} - RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);} - RetTy visitUnaryInstruction(UnaryInstruction &I){ DELEGATE(Instruction);} - - // The next level delegation for `CallBase` is slightly more complex in order - // to support visiting cases where the call is also a terminator. - RetTy visitCallBase(CallBase &I) { - if (isa(I) || isa(I)) - return static_cast(this)->visitTerminator(I); - - DELEGATE(Instruction); - } - - // If the user wants a 'default' case, they can choose to override this - // function. If this function is not overloaded in the user's subclass, then - // this instruction just gets ignored. - // - // Note that you MUST override this function if your return type is not void. - // - void visitInstruction(Instruction &I) {} // Ignore unhandled instructions - -private: - // Special helper function to delegate to CallInst subclass visitors. - RetTy delegateCallInst(CallInst &I) { - if (const Function *F = I.getCalledFunction()) { - switch (F->getIntrinsicID()) { - default: DELEGATE(IntrinsicInst); - case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); - case Intrinsic::dbg_value: DELEGATE(DbgValueInst); - case Intrinsic::dbg_label: DELEGATE(DbgLabelInst); - case Intrinsic::memcpy: DELEGATE(MemCpyInst); - case Intrinsic::memmove: DELEGATE(MemMoveInst); - case Intrinsic::memset: DELEGATE(MemSetInst); - case Intrinsic::vastart: DELEGATE(VAStartInst); - case Intrinsic::vaend: DELEGATE(VAEndInst); - case Intrinsic::vacopy: DELEGATE(VACopyInst); - case Intrinsic::not_intrinsic: break; - } - } - DELEGATE(CallInst); - } - - // An overload that will never actually be called, it is used only from dead - // code in the dispatching from opcodes to instruction subclasses. - RetTy delegateCallInst(Instruction &I) { - llvm_unreachable("delegateCallInst called for non-CallInst"); - } -}; - -#undef DELEGATE - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/InstrTypes.h b/suite/synctools/tablegen/include/llvm/IR/InstrTypes.h deleted file mode 100644 index 6a1f5c67ed..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/InstrTypes.h +++ /dev/null @@ -1,2410 +0,0 @@ -//===- llvm/InstrTypes.h - Important Instruction subclasses -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines various meta classes of instructions that exist in the VM -// representation. Specific concrete subclasses of these may be found in the -// i*.h files... -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INSTRTYPES_H -#define LLVM_IR_INSTRTYPES_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Sequence.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -namespace Intrinsic { -typedef unsigned ID; -} - -//===----------------------------------------------------------------------===// -// UnaryInstruction Class -//===----------------------------------------------------------------------===// - -class UnaryInstruction : public Instruction { -protected: - UnaryInstruction(Type *Ty, unsigned iType, Value *V, - Instruction *IB = nullptr) - : Instruction(Ty, iType, &Op<0>(), 1, IB) { - Op<0>() = V; - } - UnaryInstruction(Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) - : Instruction(Ty, iType, &Op<0>(), 1, IAE) { - Op<0>() = V; - } - -public: - // allocate space for exactly one operand - void *operator new(size_t S) { return User::operator new(S, 1); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->isUnaryOp() || - I->getOpcode() == Instruction::Alloca || - I->getOpcode() == Instruction::Load || - I->getOpcode() == Instruction::VAArg || - I->getOpcode() == Instruction::ExtractValue || - (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) - -//===----------------------------------------------------------------------===// -// UnaryOperator Class -//===----------------------------------------------------------------------===// - -class UnaryOperator : public UnaryInstruction { - void AssertOK(); - -protected: - UnaryOperator(UnaryOps iType, Value *S, Type *Ty, - const Twine &Name, Instruction *InsertBefore); - UnaryOperator(UnaryOps iType, Value *S, Type *Ty, - const Twine &Name, BasicBlock *InsertAtEnd); - - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - UnaryOperator *cloneImpl() const; - -public: - - /// Construct a unary instruction, given the opcode and an operand. - /// Optionally (if InstBefore is specified) insert the instruction - /// into a BasicBlock right before the specified instruction. The specified - /// Instruction is allowed to be a dereferenced end iterator. - /// - static UnaryOperator *Create(UnaryOps Op, Value *S, - const Twine &Name = Twine(), - Instruction *InsertBefore = nullptr); - - /// Construct a unary instruction, given the opcode and an operand. - /// Also automatically insert this instruction to the end of the - /// BasicBlock specified. - /// - static UnaryOperator *Create(UnaryOps Op, Value *S, - const Twine &Name, - BasicBlock *InsertAtEnd); - - /// These methods just forward to Create, and are useful when you - /// statically know what type of instruction you're going to create. These - /// helpers just save some typing. -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryOperator *Create##OPC(Value *V, const Twine &Name = "") {\ - return Create(Instruction::OPC, V, Name);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryOperator *Create##OPC(Value *V, const Twine &Name, \ - BasicBlock *BB) {\ - return Create(Instruction::OPC, V, Name, BB);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryOperator *Create##OPC(Value *V, const Twine &Name, \ - Instruction *I) {\ - return Create(Instruction::OPC, V, Name, I);\ - } -#include "llvm/IR/Instruction.def" - - static UnaryOperator * - CreateWithCopiedFlags(UnaryOps Opc, Value *V, Instruction *CopyO, - const Twine &Name = "", - Instruction *InsertBefore = nullptr) { - UnaryOperator *UO = Create(Opc, V, Name, InsertBefore); - UO->copyIRFlags(CopyO); - return UO; - } - - static UnaryOperator *CreateFNegFMF(Value *Op, Instruction *FMFSource, - const Twine &Name = "", - Instruction *InsertBefore = nullptr) { - return CreateWithCopiedFlags(Instruction::FNeg, Op, FMFSource, Name, - InsertBefore); - } - - UnaryOps getOpcode() const { - return static_cast(Instruction::getOpcode()); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->isUnaryOp(); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// BinaryOperator Class -//===----------------------------------------------------------------------===// - -class BinaryOperator : public Instruction { - void AssertOK(); - -protected: - BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, - const Twine &Name, Instruction *InsertBefore); - BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, - const Twine &Name, BasicBlock *InsertAtEnd); - - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - BinaryOperator *cloneImpl() const; - -public: - // allocate space for exactly two operands - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Construct a binary instruction, given the opcode and the two - /// operands. Optionally (if InstBefore is specified) insert the instruction - /// into a BasicBlock right before the specified instruction. The specified - /// Instruction is allowed to be a dereferenced end iterator. - /// - static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, - const Twine &Name = Twine(), - Instruction *InsertBefore = nullptr); - - /// Construct a binary instruction, given the opcode and the two - /// operands. Also automatically insert this instruction to the end of the - /// BasicBlock specified. - /// - static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, - const Twine &Name, BasicBlock *InsertAtEnd); - - /// These methods just forward to Create, and are useful when you - /// statically know what type of instruction you're going to create. These - /// helpers just save some typing. -#define HANDLE_BINARY_INST(N, OPC, CLASS) \ - static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ - const Twine &Name = "") {\ - return Create(Instruction::OPC, V1, V2, Name);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_BINARY_INST(N, OPC, CLASS) \ - static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ - const Twine &Name, BasicBlock *BB) {\ - return Create(Instruction::OPC, V1, V2, Name, BB);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_BINARY_INST(N, OPC, CLASS) \ - static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ - const Twine &Name, Instruction *I) {\ - return Create(Instruction::OPC, V1, V2, Name, I);\ - } -#include "llvm/IR/Instruction.def" - - static BinaryOperator * - CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Instruction *CopyO, - const Twine &Name = "", - Instruction *InsertBefore = nullptr) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, InsertBefore); - BO->copyIRFlags(CopyO); - return BO; - } - - static BinaryOperator *CreateFAddFMF(Value *V1, Value *V2, - Instruction *FMFSource, - const Twine &Name = "") { - return CreateWithCopiedFlags(Instruction::FAdd, V1, V2, FMFSource, Name); - } - static BinaryOperator *CreateFSubFMF(Value *V1, Value *V2, - Instruction *FMFSource, - const Twine &Name = "") { - return CreateWithCopiedFlags(Instruction::FSub, V1, V2, FMFSource, Name); - } - static BinaryOperator *CreateFMulFMF(Value *V1, Value *V2, - Instruction *FMFSource, - const Twine &Name = "") { - return CreateWithCopiedFlags(Instruction::FMul, V1, V2, FMFSource, Name); - } - static BinaryOperator *CreateFDivFMF(Value *V1, Value *V2, - Instruction *FMFSource, - const Twine &Name = "") { - return CreateWithCopiedFlags(Instruction::FDiv, V1, V2, FMFSource, Name); - } - static BinaryOperator *CreateFRemFMF(Value *V1, Value *V2, - Instruction *FMFSource, - const Twine &Name = "") { - return CreateWithCopiedFlags(Instruction::FRem, V1, V2, FMFSource, Name); - } - - static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = Create(Opc, V1, V2, Name); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, I); - BO->setHasNoSignedWrap(true); - return BO; - } - - static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = Create(Opc, V1, V2, Name); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, I); - BO->setHasNoUnsignedWrap(true); - return BO; - } - - static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = Create(Opc, V1, V2, Name); - BO->setIsExact(true); - return BO; - } - static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); - BO->setIsExact(true); - return BO; - } - static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = Create(Opc, V1, V2, Name, I); - BO->setIsExact(true); - return BO; - } - -#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \ - static BinaryOperator *Create##NUWNSWEXACT##OPC(Value *V1, Value *V2, \ - const Twine &Name = "") { \ - return Create##NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \ - } \ - static BinaryOperator *Create##NUWNSWEXACT##OPC( \ - Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \ - return Create##NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \ - } \ - static BinaryOperator *Create##NUWNSWEXACT##OPC( \ - Value *V1, Value *V2, const Twine &Name, Instruction *I) { \ - return Create##NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \ - } - - DEFINE_HELPERS(Add, NSW) // CreateNSWAdd - DEFINE_HELPERS(Add, NUW) // CreateNUWAdd - DEFINE_HELPERS(Sub, NSW) // CreateNSWSub - DEFINE_HELPERS(Sub, NUW) // CreateNUWSub - DEFINE_HELPERS(Mul, NSW) // CreateNSWMul - DEFINE_HELPERS(Mul, NUW) // CreateNUWMul - DEFINE_HELPERS(Shl, NSW) // CreateNSWShl - DEFINE_HELPERS(Shl, NUW) // CreateNUWShl - - DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv - DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv - DEFINE_HELPERS(AShr, Exact) // CreateExactAShr - DEFINE_HELPERS(LShr, Exact) // CreateExactLShr - -#undef DEFINE_HELPERS - - /// Helper functions to construct and inspect unary operations (NEG and NOT) - /// via binary operators SUB and XOR: - /// - /// Create the NEG and NOT instructions out of SUB and XOR instructions. - /// - static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - static BinaryOperator *CreateNeg(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd); - static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd); - static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd); - static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - static BinaryOperator *CreateNot(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd); - - BinaryOps getOpcode() const { - return static_cast(Instruction::getOpcode()); - } - - /// Exchange the two operands to this instruction. - /// This instruction is safe to use on any binary instruction and - /// does not modify the semantics of the instruction. If the instruction - /// cannot be reversed (ie, it's a Div), then return true. - /// - bool swapOperands(); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->isBinaryOp(); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) - -//===----------------------------------------------------------------------===// -// CastInst Class -//===----------------------------------------------------------------------===// - -/// This is the base class for all instructions that perform data -/// casts. It is simply provided so that instruction category testing -/// can be performed with code like: -/// -/// if (isa(Instr)) { ... } -/// Base class of casting instructions. -class CastInst : public UnaryInstruction { -protected: - /// Constructor with insert-before-instruction semantics for subclasses - CastInst(Type *Ty, unsigned iType, Value *S, - const Twine &NameStr = "", Instruction *InsertBefore = nullptr) - : UnaryInstruction(Ty, iType, S, InsertBefore) { - setName(NameStr); - } - /// Constructor with insert-at-end-of-block semantics for subclasses - CastInst(Type *Ty, unsigned iType, Value *S, - const Twine &NameStr, BasicBlock *InsertAtEnd) - : UnaryInstruction(Ty, iType, S, InsertAtEnd) { - setName(NameStr); - } - -public: - /// Provides a way to construct any of the CastInst subclasses using an - /// opcode instead of the subclass's constructor. The opcode must be in the - /// CastOps category (Instruction::isCast(opcode) returns true). This - /// constructor has insert-before-instruction semantics to automatically - /// insert the new CastInst before InsertBefore (if it is non-null). - /// Construct any of the CastInst subclasses - static CastInst *Create( - Instruction::CastOps, ///< The opcode of the cast instruction - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - /// Provides a way to construct any of the CastInst subclasses using an - /// opcode instead of the subclass's constructor. The opcode must be in the - /// CastOps category. This constructor has insert-at-end-of-block semantics - /// to automatically insert the new CastInst at the end of InsertAtEnd (if - /// its non-null). - /// Construct any of the CastInst subclasses - static CastInst *Create( - Instruction::CastOps, ///< The opcode for the cast instruction - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a ZExt or BitCast cast instruction - static CastInst *CreateZExtOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a ZExt or BitCast cast instruction - static CastInst *CreateZExtOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a SExt or BitCast cast instruction - static CastInst *CreateSExtOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a SExt or BitCast cast instruction - static CastInst *CreateSExtOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction. - static CastInst *CreatePointerCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction. - static CastInst *CreatePointerCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a BitCast or an AddrSpaceCast cast instruction. - static CastInst *CreatePointerBitCastOrAddrSpaceCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a BitCast or an AddrSpaceCast cast instruction. - static CastInst *CreatePointerBitCastOrAddrSpaceCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. - /// - /// If the value is a pointer type and the destination an integer type, - /// creates a PtrToInt cast. If the value is an integer type and the - /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates - /// a bitcast. - static CastInst *CreateBitOrPointerCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a ZExt, BitCast, or Trunc for int -> int casts. - static CastInst *CreateIntegerCast( - Value *S, ///< The pointer value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - bool isSigned, ///< Whether to regard S as signed or not - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a ZExt, BitCast, or Trunc for int -> int casts. - static CastInst *CreateIntegerCast( - Value *S, ///< The integer value to be casted (operand 0) - Type *Ty, ///< The integer type to which operand is casted - bool isSigned, ///< Whether to regard S as signed or not - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts - static CastInst *CreateFPCast( - Value *S, ///< The floating point value to be casted - Type *Ty, ///< The floating point type to cast to - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts - static CastInst *CreateFPCast( - Value *S, ///< The floating point value to be casted - Type *Ty, ///< The floating point type to cast to - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Create a Trunc or BitCast cast instruction - static CastInst *CreateTruncOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which cast should be made - const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = nullptr ///< Place to insert the instruction - ); - - /// Create a Trunc or BitCast cast instruction - static CastInst *CreateTruncOrBitCast( - Value *S, ///< The value to be casted (operand 0) - Type *Ty, ///< The type to which operand is casted - const Twine &Name, ///< The name for the instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Check whether a bitcast between these types is valid - static bool isBitCastable( - Type *SrcTy, ///< The Type from which the value should be cast. - Type *DestTy ///< The Type to which the value should be cast. - ); - - /// Check whether a bitcast, inttoptr, or ptrtoint cast between these - /// types is valid and a no-op. - /// - /// This ensures that any pointer<->integer cast has enough bits in the - /// integer and any other cast is a bitcast. - static bool isBitOrNoopPointerCastable( - Type *SrcTy, ///< The Type from which the value should be cast. - Type *DestTy, ///< The Type to which the value should be cast. - const DataLayout &DL); - - /// Returns the opcode necessary to cast Val into Ty using usual casting - /// rules. - /// Infer the opcode for cast operand and type - static Instruction::CastOps getCastOpcode( - const Value *Val, ///< The value to cast - bool SrcIsSigned, ///< Whether to treat the source as signed - Type *Ty, ///< The Type to which the value should be casted - bool DstIsSigned ///< Whether to treat the dest. as signed - ); - - /// There are several places where we need to know if a cast instruction - /// only deals with integer source and destination types. To simplify that - /// logic, this method is provided. - /// @returns true iff the cast has only integral typed operand and dest type. - /// Determine if this is an integer-only cast. - bool isIntegerCast() const; - - /// A lossless cast is one that does not alter the basic value. It implies - /// a no-op cast but is more stringent, preventing things like int->float, - /// long->double, or int->ptr. - /// @returns true iff the cast is lossless. - /// Determine if this is a lossless cast. - bool isLosslessCast() const; - - /// A no-op cast is one that can be effected without changing any bits. - /// It implies that the source and destination types are the same size. The - /// DataLayout argument is to determine the pointer size when examining casts - /// involving Integer and Pointer types. They are no-op casts if the integer - /// is the same size as the pointer. However, pointer size varies with - /// platform. Note that a precondition of this method is that the cast is - /// legal - i.e. the instruction formed with these operands would verify. - static bool isNoopCast( - Instruction::CastOps Opcode, ///< Opcode of cast - Type *SrcTy, ///< SrcTy of cast - Type *DstTy, ///< DstTy of cast - const DataLayout &DL ///< DataLayout to get the Int Ptr type from. - ); - - /// Determine if this cast is a no-op cast. - /// - /// \param DL is the DataLayout to determine pointer size. - bool isNoopCast(const DataLayout &DL) const; - - /// Determine how a pair of casts can be eliminated, if they can be at all. - /// This is a helper function for both CastInst and ConstantExpr. - /// @returns 0 if the CastInst pair can't be eliminated, otherwise - /// returns Instruction::CastOps value for a cast that can replace - /// the pair, casting SrcTy to DstTy. - /// Determine if a cast pair is eliminable - static unsigned isEliminableCastPair( - Instruction::CastOps firstOpcode, ///< Opcode of first cast - Instruction::CastOps secondOpcode, ///< Opcode of second cast - Type *SrcTy, ///< SrcTy of 1st cast - Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast - Type *DstTy, ///< DstTy of 2nd cast - Type *SrcIntPtrTy, ///< Integer type corresponding to Ptr SrcTy, or null - Type *MidIntPtrTy, ///< Integer type corresponding to Ptr MidTy, or null - Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null - ); - - /// Return the opcode of this CastInst - Instruction::CastOps getOpcode() const { - return Instruction::CastOps(Instruction::getOpcode()); - } - - /// Return the source type, as a convenience - Type* getSrcTy() const { return getOperand(0)->getType(); } - /// Return the destination type, as a convenience - Type* getDestTy() const { return getType(); } - - /// This method can be used to determine if a cast from SrcTy to DstTy using - /// Opcode op is valid or not. - /// @returns true iff the proposed cast is valid. - /// Determine if a cast is valid without creating one. - static bool castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy); - static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) { - return castIsValid(op, S->getType(), DstTy); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->isCast(); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// CmpInst Class -//===----------------------------------------------------------------------===// - -/// This class is the base class for the comparison instructions. -/// Abstract base class of comparison instructions. -class CmpInst : public Instruction { -public: - /// This enumeration lists the possible predicates for CmpInst subclasses. - /// Values in the range 0-31 are reserved for FCmpInst, while values in the - /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the - /// predicate values are not overlapping between the classes. - /// - /// Some passes (e.g. InstCombine) depend on the bit-wise characteristics of - /// FCMP_* values. Changing the bit patterns requires a potential change to - /// those passes. - enum Predicate : unsigned { - // Opcode U L G E Intuitive operation - FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) - FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal - FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than - FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal - FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than - FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal - FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal - FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) - FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) - FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal - FCMP_UGT = 10, ///< 1 0 1 0 True if unordered or greater than - FCMP_UGE = 11, ///< 1 0 1 1 True if unordered, greater than, or equal - FCMP_ULT = 12, ///< 1 1 0 0 True if unordered or less than - FCMP_ULE = 13, ///< 1 1 0 1 True if unordered, less than, or equal - FCMP_UNE = 14, ///< 1 1 1 0 True if unordered or not equal - FCMP_TRUE = 15, ///< 1 1 1 1 Always true (always folded) - FIRST_FCMP_PREDICATE = FCMP_FALSE, - LAST_FCMP_PREDICATE = FCMP_TRUE, - BAD_FCMP_PREDICATE = FCMP_TRUE + 1, - ICMP_EQ = 32, ///< equal - ICMP_NE = 33, ///< not equal - ICMP_UGT = 34, ///< unsigned greater than - ICMP_UGE = 35, ///< unsigned greater or equal - ICMP_ULT = 36, ///< unsigned less than - ICMP_ULE = 37, ///< unsigned less or equal - ICMP_SGT = 38, ///< signed greater than - ICMP_SGE = 39, ///< signed greater or equal - ICMP_SLT = 40, ///< signed less than - ICMP_SLE = 41, ///< signed less or equal - FIRST_ICMP_PREDICATE = ICMP_EQ, - LAST_ICMP_PREDICATE = ICMP_SLE, - BAD_ICMP_PREDICATE = ICMP_SLE + 1 - }; - using PredicateField = - Bitfield::Element; - - /// Returns the sequence of all FCmp predicates. - static auto FCmpPredicates() { - return enum_seq_inclusive(Predicate::FIRST_FCMP_PREDICATE, - Predicate::LAST_FCMP_PREDICATE, - force_iteration_on_noniterable_enum); - } - - /// Returns the sequence of all ICmp predicates. - static auto ICmpPredicates() { - return enum_seq_inclusive(Predicate::FIRST_ICMP_PREDICATE, - Predicate::LAST_ICMP_PREDICATE, - force_iteration_on_noniterable_enum); - } - -protected: - CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred, - Value *LHS, Value *RHS, const Twine &Name = "", - Instruction *InsertBefore = nullptr, - Instruction *FlagsSource = nullptr); - - CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred, - Value *LHS, Value *RHS, const Twine &Name, - BasicBlock *InsertAtEnd); - -public: - // allocate space for exactly two operands - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Construct a compare instruction, given the opcode, the predicate and - /// the two operands. Optionally (if InstBefore is specified) insert the - /// instruction into a BasicBlock right before the specified instruction. - /// The specified Instruction is allowed to be a dereferenced end iterator. - /// Create a CmpInst - static CmpInst *Create(OtherOps Op, - Predicate predicate, Value *S1, - Value *S2, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - - /// Construct a compare instruction, given the opcode, the predicate and the - /// two operands. Also automatically insert this instruction to the end of - /// the BasicBlock specified. - /// Create a CmpInst - static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, - Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - - /// Get the opcode casted to the right type - OtherOps getOpcode() const { - return static_cast(Instruction::getOpcode()); - } - - /// Return the predicate for this instruction. - Predicate getPredicate() const { return getSubclassData(); } - - /// Set the predicate for this instruction to the specified value. - void setPredicate(Predicate P) { setSubclassData(P); } - - static bool isFPPredicate(Predicate P) { - static_assert(FIRST_FCMP_PREDICATE == 0, - "FIRST_FCMP_PREDICATE is required to be 0"); - return P <= LAST_FCMP_PREDICATE; - } - - static bool isIntPredicate(Predicate P) { - return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; - } - - static StringRef getPredicateName(Predicate P); - - bool isFPPredicate() const { return isFPPredicate(getPredicate()); } - bool isIntPredicate() const { return isIntPredicate(getPredicate()); } - - /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, - /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. - /// @returns the inverse predicate for the instruction's current predicate. - /// Return the inverse of the instruction's predicate. - Predicate getInversePredicate() const { - return getInversePredicate(getPredicate()); - } - - /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, - /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. - /// @returns the inverse predicate for predicate provided in \p pred. - /// Return the inverse of a given predicate - static Predicate getInversePredicate(Predicate pred); - - /// For example, EQ->EQ, SLE->SGE, ULT->UGT, - /// OEQ->OEQ, ULE->UGE, OLT->OGT, etc. - /// @returns the predicate that would be the result of exchanging the two - /// operands of the CmpInst instruction without changing the result - /// produced. - /// Return the predicate as if the operands were swapped - Predicate getSwappedPredicate() const { - return getSwappedPredicate(getPredicate()); - } - - /// This is a static version that you can use without an instruction - /// available. - /// Return the predicate as if the operands were swapped. - static Predicate getSwappedPredicate(Predicate pred); - - /// This is a static version that you can use without an instruction - /// available. - /// @returns true if the comparison predicate is strict, false otherwise. - static bool isStrictPredicate(Predicate predicate); - - /// @returns true if the comparison predicate is strict, false otherwise. - /// Determine if this instruction is using an strict comparison predicate. - bool isStrictPredicate() const { return isStrictPredicate(getPredicate()); } - - /// This is a static version that you can use without an instruction - /// available. - /// @returns true if the comparison predicate is non-strict, false otherwise. - static bool isNonStrictPredicate(Predicate predicate); - - /// @returns true if the comparison predicate is non-strict, false otherwise. - /// Determine if this instruction is using an non-strict comparison predicate. - bool isNonStrictPredicate() const { - return isNonStrictPredicate(getPredicate()); - } - - /// For example, SGE -> SGT, SLE -> SLT, ULE -> ULT, UGE -> UGT. - /// Returns the strict version of non-strict comparisons. - Predicate getStrictPredicate() const { - return getStrictPredicate(getPredicate()); - } - - /// This is a static version that you can use without an instruction - /// available. - /// @returns the strict version of comparison provided in \p pred. - /// If \p pred is not a strict comparison predicate, returns \p pred. - /// Returns the strict version of non-strict comparisons. - static Predicate getStrictPredicate(Predicate pred); - - /// For example, SGT -> SGE, SLT -> SLE, ULT -> ULE, UGT -> UGE. - /// Returns the non-strict version of strict comparisons. - Predicate getNonStrictPredicate() const { - return getNonStrictPredicate(getPredicate()); - } - - /// This is a static version that you can use without an instruction - /// available. - /// @returns the non-strict version of comparison provided in \p pred. - /// If \p pred is not a strict comparison predicate, returns \p pred. - /// Returns the non-strict version of strict comparisons. - static Predicate getNonStrictPredicate(Predicate pred); - - /// This is a static version that you can use without an instruction - /// available. - /// Return the flipped strictness of predicate - static Predicate getFlippedStrictnessPredicate(Predicate pred); - - /// For predicate of kind "is X or equal to 0" returns the predicate "is X". - /// For predicate of kind "is X" returns the predicate "is X or equal to 0". - /// does not support other kind of predicates. - /// @returns the predicate that does not contains is equal to zero if - /// it had and vice versa. - /// Return the flipped strictness of predicate - Predicate getFlippedStrictnessPredicate() const { - return getFlippedStrictnessPredicate(getPredicate()); - } - - /// Provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// This is just a convenience that dispatches to the subclasses. - /// Swap the operands and adjust predicate accordingly to retain - /// the same comparison. - void swapOperands(); - - /// This is just a convenience that dispatches to the subclasses. - /// Determine if this CmpInst is commutative. - bool isCommutative() const; - - /// Determine if this is an equals/not equals predicate. - /// This is a static version that you can use without an instruction - /// available. - static bool isEquality(Predicate pred); - - /// Determine if this is an equals/not equals predicate. - bool isEquality() const { return isEquality(getPredicate()); } - - /// Return true if the predicate is relational (not EQ or NE). - static bool isRelational(Predicate P) { return !isEquality(P); } - - /// Return true if the predicate is relational (not EQ or NE). - bool isRelational() const { return !isEquality(); } - - /// @returns true if the comparison is signed, false otherwise. - /// Determine if this instruction is using a signed comparison. - bool isSigned() const { - return isSigned(getPredicate()); - } - - /// @returns true if the comparison is unsigned, false otherwise. - /// Determine if this instruction is using an unsigned comparison. - bool isUnsigned() const { - return isUnsigned(getPredicate()); - } - - /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert - /// @returns the signed version of the unsigned predicate pred. - /// return the signed version of a predicate - static Predicate getSignedPredicate(Predicate pred); - - /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert - /// @returns the signed version of the predicate for this instruction (which - /// has to be an unsigned predicate). - /// return the signed version of a predicate - Predicate getSignedPredicate() { - return getSignedPredicate(getPredicate()); - } - - /// For example, SLT->ULT, SLE->ULE, SGT->UGT, SGE->UGE, ULT->Failed assert - /// @returns the unsigned version of the signed predicate pred. - static Predicate getUnsignedPredicate(Predicate pred); - - /// For example, SLT->ULT, SLE->ULE, SGT->UGT, SGE->UGE, ULT->Failed assert - /// @returns the unsigned version of the predicate for this instruction (which - /// has to be an signed predicate). - /// return the unsigned version of a predicate - Predicate getUnsignedPredicate() { - return getUnsignedPredicate(getPredicate()); - } - - /// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->Failed assert - /// @returns the unsigned version of the signed predicate pred or - /// the signed version of the signed predicate pred. - static Predicate getFlippedSignednessPredicate(Predicate pred); - - /// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->Failed assert - /// @returns the unsigned version of the signed predicate pred or - /// the signed version of the signed predicate pred. - Predicate getFlippedSignednessPredicate() { - return getFlippedSignednessPredicate(getPredicate()); - } - - /// This is just a convenience. - /// Determine if this is true when both operands are the same. - bool isTrueWhenEqual() const { - return isTrueWhenEqual(getPredicate()); - } - - /// This is just a convenience. - /// Determine if this is false when both operands are the same. - bool isFalseWhenEqual() const { - return isFalseWhenEqual(getPredicate()); - } - - /// @returns true if the predicate is unsigned, false otherwise. - /// Determine if the predicate is an unsigned operation. - static bool isUnsigned(Predicate predicate); - - /// @returns true if the predicate is signed, false otherwise. - /// Determine if the predicate is an signed operation. - static bool isSigned(Predicate predicate); - - /// Determine if the predicate is an ordered operation. - static bool isOrdered(Predicate predicate); - - /// Determine if the predicate is an unordered operation. - static bool isUnordered(Predicate predicate); - - /// Determine if the predicate is true when comparing a value with itself. - static bool isTrueWhenEqual(Predicate predicate); - - /// Determine if the predicate is false when comparing a value with itself. - static bool isFalseWhenEqual(Predicate predicate); - - /// Determine if Pred1 implies Pred2 is true when two compares have matching - /// operands. - static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2); - - /// Determine if Pred1 implies Pred2 is false when two compares have matching - /// operands. - static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::ICmp || - I->getOpcode() == Instruction::FCmp; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - /// Create a result type for fcmp/icmp - static Type* makeCmpResultType(Type* opnd_type) { - if (VectorType* vt = dyn_cast(opnd_type)) { - return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), - vt->getElementCount()); - } - return Type::getInt1Ty(opnd_type->getContext()); - } - -private: - // Shadow Value::setValueSubclassData with a private forwarding method so that - // subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } -}; - -// FIXME: these are redundant if CmpInst < BinaryOperator -template <> -struct OperandTraits : public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) - -/// A lightweight accessor for an operand bundle meant to be passed -/// around by value. -struct OperandBundleUse { - ArrayRef Inputs; - - OperandBundleUse() = default; - explicit OperandBundleUse(StringMapEntry *Tag, ArrayRef Inputs) - : Inputs(Inputs), Tag(Tag) {} - - /// Return true if the operand at index \p Idx in this operand bundle - /// has the attribute A. - bool operandHasAttr(unsigned Idx, Attribute::AttrKind A) const { - if (isDeoptOperandBundle()) - if (A == Attribute::ReadOnly || A == Attribute::NoCapture) - return Inputs[Idx]->getType()->isPointerTy(); - - // Conservative answer: no operands have any attributes. - return false; - } - - /// Return the tag of this operand bundle as a string. - StringRef getTagName() const { - return Tag->getKey(); - } - - /// Return the tag of this operand bundle as an integer. - /// - /// Operand bundle tags are interned by LLVMContextImpl::getOrInsertBundleTag, - /// and this function returns the unique integer getOrInsertBundleTag - /// associated the tag of this operand bundle to. - uint32_t getTagID() const { - return Tag->getValue(); - } - - /// Return true if this is a "deopt" operand bundle. - bool isDeoptOperandBundle() const { - return getTagID() == LLVMContext::OB_deopt; - } - - /// Return true if this is a "funclet" operand bundle. - bool isFuncletOperandBundle() const { - return getTagID() == LLVMContext::OB_funclet; - } - - /// Return true if this is a "cfguardtarget" operand bundle. - bool isCFGuardTargetOperandBundle() const { - return getTagID() == LLVMContext::OB_cfguardtarget; - } - -private: - /// Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag. - StringMapEntry *Tag; -}; - -/// A container for an operand bundle being viewed as a set of values -/// rather than a set of uses. -/// -/// Unlike OperandBundleUse, OperandBundleDefT owns the memory it carries, and -/// so it is possible to create and pass around "self-contained" instances of -/// OperandBundleDef and ConstOperandBundleDef. -template class OperandBundleDefT { - std::string Tag; - std::vector Inputs; - -public: - explicit OperandBundleDefT(std::string Tag, std::vector Inputs) - : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {} - explicit OperandBundleDefT(std::string Tag, ArrayRef Inputs) - : Tag(std::move(Tag)), Inputs(Inputs) {} - - explicit OperandBundleDefT(const OperandBundleUse &OBU) { - Tag = std::string(OBU.getTagName()); - llvm::append_range(Inputs, OBU.Inputs); - } - - ArrayRef inputs() const { return Inputs; } - - using input_iterator = typename std::vector::const_iterator; - - size_t input_size() const { return Inputs.size(); } - input_iterator input_begin() const { return Inputs.begin(); } - input_iterator input_end() const { return Inputs.end(); } - - StringRef getTag() const { return Tag; } -}; - -using OperandBundleDef = OperandBundleDefT; -using ConstOperandBundleDef = OperandBundleDefT; - -//===----------------------------------------------------------------------===// -// CallBase Class -//===----------------------------------------------------------------------===// - -/// Base class for all callable instructions (InvokeInst and CallInst) -/// Holds everything related to calling a function. -/// -/// All call-like instructions are required to use a common operand layout: -/// - Zero or more arguments to the call, -/// - Zero or more operand bundles with zero or more operand inputs each -/// bundle, -/// - Zero or more subclass controlled operands -/// - The called function. -/// -/// This allows this base class to easily access the called function and the -/// start of the arguments without knowing how many other operands a particular -/// subclass requires. Note that accessing the end of the argument list isn't -/// as cheap as most other operations on the base class. -class CallBase : public Instruction { -protected: - // The first two bits are reserved by CallInst for fast retrieval, - using CallInstReservedField = Bitfield::Element; - using CallingConvField = - Bitfield::Element; - static_assert( - Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - /// The last operand is the called operand. - static constexpr int CalledOperandOpEndIdx = -1; - - AttributeList Attrs; ///< parameter attributes for callable - FunctionType *FTy; - - template - CallBase(AttributeList const &A, FunctionType *FT, ArgsTy &&... Args) - : Instruction(std::forward(Args)...), Attrs(A), FTy(FT) {} - - using Instruction::Instruction; - - bool hasDescriptor() const { return Value::HasDescriptor; } - - unsigned getNumSubclassExtraOperands() const { - switch (getOpcode()) { - case Instruction::Call: - return 0; - case Instruction::Invoke: - return 2; - case Instruction::CallBr: - return getNumSubclassExtraOperandsDynamic(); - } - llvm_unreachable("Invalid opcode!"); - } - - /// Get the number of extra operands for instructions that don't have a fixed - /// number of extra operands. - unsigned getNumSubclassExtraOperandsDynamic() const; - -public: - using Instruction::getContext; - - /// Create a clone of \p CB with a different set of operand bundles and - /// insert it before \p InsertPt. - /// - /// The returned call instruction is identical \p CB in every way except that - /// the operand bundles for the new instruction are set to the operand bundles - /// in \p Bundles. - static CallBase *Create(CallBase *CB, ArrayRef Bundles, - Instruction *InsertPt = nullptr); - - /// Create a clone of \p CB with the operand bundle with the tag matching - /// \p Bundle's tag replaced with Bundle, and insert it before \p InsertPt. - /// - /// The returned call instruction is identical \p CI in every way except that - /// the specified operand bundle has been replaced. - static CallBase *Create(CallBase *CB, - OperandBundleDef Bundle, - Instruction *InsertPt = nullptr); - - /// Create a clone of \p CB with operand bundle \p OB added. - static CallBase *addOperandBundle(CallBase *CB, uint32_t ID, - OperandBundleDef OB, - Instruction *InsertPt = nullptr); - - /// Create a clone of \p CB with operand bundle \p ID removed. - static CallBase *removeOperandBundle(CallBase *CB, uint32_t ID, - Instruction *InsertPt = nullptr); - - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Call || - I->getOpcode() == Instruction::Invoke || - I->getOpcode() == Instruction::CallBr; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - FunctionType *getFunctionType() const { return FTy; } - - void mutateFunctionType(FunctionType *FTy) { - Value::mutateType(FTy->getReturnType()); - this->FTy = FTy; - } - - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// data_operands_begin/data_operands_end - Return iterators iterating over - /// the call / invoke argument list and bundle operands. For invokes, this is - /// the set of instruction operands except the invoke target and the two - /// successor blocks; and for calls this is the set of instruction operands - /// except the call target. - User::op_iterator data_operands_begin() { return op_begin(); } - User::const_op_iterator data_operands_begin() const { - return const_cast(this)->data_operands_begin(); - } - User::op_iterator data_operands_end() { - // Walk from the end of the operands over the called operand and any - // subclass operands. - return op_end() - getNumSubclassExtraOperands() - 1; - } - User::const_op_iterator data_operands_end() const { - return const_cast(this)->data_operands_end(); - } - iterator_range data_ops() { - return make_range(data_operands_begin(), data_operands_end()); - } - iterator_range data_ops() const { - return make_range(data_operands_begin(), data_operands_end()); - } - bool data_operands_empty() const { - return data_operands_end() == data_operands_begin(); - } - unsigned data_operands_size() const { - return std::distance(data_operands_begin(), data_operands_end()); - } - - bool isDataOperand(const Use *U) const { - assert(this == U->getUser() && - "Only valid to query with a use of this instruction!"); - return data_operands_begin() <= U && U < data_operands_end(); - } - bool isDataOperand(Value::const_user_iterator UI) const { - return isDataOperand(&UI.getUse()); - } - - /// Given a value use iterator, return the data operand corresponding to it. - /// Iterator must actually correspond to a data operand. - unsigned getDataOperandNo(Value::const_user_iterator UI) const { - return getDataOperandNo(&UI.getUse()); - } - - /// Given a use for a data operand, get the data operand number that - /// corresponds to it. - unsigned getDataOperandNo(const Use *U) const { - assert(isDataOperand(U) && "Data operand # out of range!"); - return U - data_operands_begin(); - } - - /// Return the iterator pointing to the beginning of the argument list. - User::op_iterator arg_begin() { return op_begin(); } - User::const_op_iterator arg_begin() const { - return const_cast(this)->arg_begin(); - } - - /// Return the iterator pointing to the end of the argument list. - User::op_iterator arg_end() { - // From the end of the data operands, walk backwards past the bundle - // operands. - return data_operands_end() - getNumTotalBundleOperands(); - } - User::const_op_iterator arg_end() const { - return const_cast(this)->arg_end(); - } - - /// Iteration adapter for range-for loops. - iterator_range args() { - return make_range(arg_begin(), arg_end()); - } - iterator_range args() const { - return make_range(arg_begin(), arg_end()); - } - bool arg_empty() const { return arg_end() == arg_begin(); } - unsigned arg_size() const { return arg_end() - arg_begin(); } - - Value *getArgOperand(unsigned i) const { - assert(i < arg_size() && "Out of bounds!"); - return getOperand(i); - } - - void setArgOperand(unsigned i, Value *v) { - assert(i < arg_size() && "Out of bounds!"); - setOperand(i, v); - } - - /// Wrappers for getting the \c Use of a call argument. - const Use &getArgOperandUse(unsigned i) const { - assert(i < arg_size() && "Out of bounds!"); - return User::getOperandUse(i); - } - Use &getArgOperandUse(unsigned i) { - assert(i < arg_size() && "Out of bounds!"); - return User::getOperandUse(i); - } - - bool isArgOperand(const Use *U) const { - assert(this == U->getUser() && - "Only valid to query with a use of this instruction!"); - return arg_begin() <= U && U < arg_end(); - } - bool isArgOperand(Value::const_user_iterator UI) const { - return isArgOperand(&UI.getUse()); - } - - /// Given a use for a arg operand, get the arg operand number that - /// corresponds to it. - unsigned getArgOperandNo(const Use *U) const { - assert(isArgOperand(U) && "Arg operand # out of range!"); - return U - arg_begin(); - } - - /// Given a value use iterator, return the arg operand number corresponding to - /// it. Iterator must actually correspond to a data operand. - unsigned getArgOperandNo(Value::const_user_iterator UI) const { - return getArgOperandNo(&UI.getUse()); - } - - /// Returns true if this CallSite passes the given Value* as an argument to - /// the called function. - bool hasArgument(const Value *V) const { - return llvm::is_contained(args(), V); - } - - Value *getCalledOperand() const { return Op(); } - - const Use &getCalledOperandUse() const { return Op(); } - Use &getCalledOperandUse() { return Op(); } - - /// Returns the function called, or null if this is an indirect function - /// invocation or the function signature does not match the call signature. - Function *getCalledFunction() const { - if (auto *F = dyn_cast_or_null(getCalledOperand())) - if (F->getValueType() == getFunctionType()) - return F; - return nullptr; - } - - /// Return true if the callsite is an indirect call. - bool isIndirectCall() const; - - /// Determine whether the passed iterator points to the callee operand's Use. - bool isCallee(Value::const_user_iterator UI) const { - return isCallee(&UI.getUse()); - } - - /// Determine whether this Use is the callee operand's Use. - bool isCallee(const Use *U) const { return &getCalledOperandUse() == U; } - - /// Helper to get the caller (the parent function). - Function *getCaller(); - const Function *getCaller() const { - return const_cast(this)->getCaller(); - } - - /// Tests if this call site must be tail call optimized. Only a CallInst can - /// be tail call optimized. - bool isMustTailCall() const; - - /// Tests if this call site is marked as a tail call. - bool isTailCall() const; - - /// Returns the intrinsic ID of the intrinsic called or - /// Intrinsic::not_intrinsic if the called function is not an intrinsic, or if - /// this is an indirect call. - Intrinsic::ID getIntrinsicID() const; - - void setCalledOperand(Value *V) { Op() = V; } - - /// Sets the function called, including updating the function type. - void setCalledFunction(Function *Fn) { - setCalledFunction(Fn->getFunctionType(), Fn); - } - - /// Sets the function called, including updating the function type. - void setCalledFunction(FunctionCallee Fn) { - setCalledFunction(Fn.getFunctionType(), Fn.getCallee()); - } - - /// Sets the function called, including updating to the specified function - /// type. - void setCalledFunction(FunctionType *FTy, Value *Fn) { - this->FTy = FTy; - assert(cast(Fn->getType())->isOpaqueOrPointeeTypeMatches(FTy)); - // This function doesn't mutate the return type, only the function - // type. Seems broken, but I'm just gonna stick an assert in for now. - assert(getType() == FTy->getReturnType()); - setCalledOperand(Fn); - } - - CallingConv::ID getCallingConv() const { - return getSubclassData(); - } - - void setCallingConv(CallingConv::ID CC) { - setSubclassData(CC); - } - - /// Check if this call is an inline asm statement. - bool isInlineAsm() const { return isa(getCalledOperand()); } - - /// \name Attribute API - /// - /// These methods access and modify attributes on this call (including - /// looking through to the attributes on the called function when necessary). - ///@{ - - /// Return the parameter attributes for this call. - /// - AttributeList getAttributes() const { return Attrs; } - - /// Set the parameter attributes for this call. - /// - void setAttributes(AttributeList A) { Attrs = A; } - - /// Determine whether this call has the given attribute. If it does not - /// then determine if the called function has the attribute, but only if - /// the attribute is allowed for the call. - bool hasFnAttr(Attribute::AttrKind Kind) const { - assert(Kind != Attribute::NoBuiltin && - "Use CallBase::isNoBuiltin() to check for Attribute::NoBuiltin"); - return hasFnAttrImpl(Kind); - } - - /// Determine whether this call has the given attribute. If it does not - /// then determine if the called function has the attribute, but only if - /// the attribute is allowed for the call. - bool hasFnAttr(StringRef Kind) const { return hasFnAttrImpl(Kind); } - - // TODO: remove non-AtIndex versions of these methods. - /// adds the attribute to the list of attributes. - void addAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) { - Attrs = Attrs.addAttributeAtIndex(getContext(), i, Kind); - } - - /// adds the attribute to the list of attributes. - void addAttributeAtIndex(unsigned i, Attribute Attr) { - Attrs = Attrs.addAttributeAtIndex(getContext(), i, Attr); - } - - /// Adds the attribute to the function. - void addFnAttr(Attribute::AttrKind Kind) { - Attrs = Attrs.addFnAttribute(getContext(), Kind); - } - - /// Adds the attribute to the function. - void addFnAttr(Attribute Attr) { - Attrs = Attrs.addFnAttribute(getContext(), Attr); - } - - /// Adds the attribute to the return value. - void addRetAttr(Attribute::AttrKind Kind) { - Attrs = Attrs.addRetAttribute(getContext(), Kind); - } - - /// Adds the attribute to the return value. - void addRetAttr(Attribute Attr) { - Attrs = Attrs.addRetAttribute(getContext(), Attr); - } - - /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - assert(ArgNo < arg_size() && "Out of bounds"); - Attrs = Attrs.addParamAttribute(getContext(), ArgNo, Kind); - } - - /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute Attr) { - assert(ArgNo < arg_size() && "Out of bounds"); - Attrs = Attrs.addParamAttribute(getContext(), ArgNo, Attr); - } - - /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) { - Attrs = Attrs.removeAttributeAtIndex(getContext(), i, Kind); - } - - /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, StringRef Kind) { - Attrs = Attrs.removeAttributeAtIndex(getContext(), i, Kind); - } - - /// Removes the attributes from the function - void removeFnAttrs(const AttributeMask &AttrsToRemove) { - Attrs = Attrs.removeFnAttributes(getContext(), AttrsToRemove); - } - - /// Removes the attribute from the function - void removeFnAttr(Attribute::AttrKind Kind) { - Attrs = Attrs.removeFnAttribute(getContext(), Kind); - } - - /// Removes the attribute from the return value - void removeRetAttr(Attribute::AttrKind Kind) { - Attrs = Attrs.removeRetAttribute(getContext(), Kind); - } - - /// Removes the attributes from the return value - void removeRetAttrs(const AttributeMask &AttrsToRemove) { - Attrs = Attrs.removeRetAttributes(getContext(), AttrsToRemove); - } - - /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - assert(ArgNo < arg_size() && "Out of bounds"); - Attrs = Attrs.removeParamAttribute(getContext(), ArgNo, Kind); - } - - /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, StringRef Kind) { - assert(ArgNo < arg_size() && "Out of bounds"); - Attrs = Attrs.removeParamAttribute(getContext(), ArgNo, Kind); - } - - /// Removes the attributes from the given argument - void removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove) { - Attrs = Attrs.removeParamAttributes(getContext(), ArgNo, AttrsToRemove); - } - - /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableParamAttr(unsigned i, uint64_t Bytes) { - Attrs = Attrs.addDereferenceableParamAttr(getContext(), i, Bytes); - } - - /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableRetAttr(uint64_t Bytes) { - Attrs = Attrs.addDereferenceableRetAttr(getContext(), Bytes); - } - - /// Determine whether the return value has the given attribute. - bool hasRetAttr(Attribute::AttrKind Kind) const { - return hasRetAttrImpl(Kind); - } - /// Determine whether the return value has the given attribute. - bool hasRetAttr(StringRef Kind) const { return hasRetAttrImpl(Kind); } - - /// Determine whether the argument or parameter has the given attribute. - bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; - - /// Get the attribute of a given kind at a position. - Attribute getAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) const { - return getAttributes().getAttributeAtIndex(i, Kind); - } - - /// Get the attribute of a given kind at a position. - Attribute getAttributeAtIndex(unsigned i, StringRef Kind) const { - return getAttributes().getAttributeAtIndex(i, Kind); - } - - /// Get the attribute of a given kind for the function. - Attribute getFnAttr(StringRef Kind) const { - return getAttributes().getFnAttr(Kind); - } - - /// Get the attribute of a given kind for the function. - Attribute getFnAttr(Attribute::AttrKind Kind) const { - return getAttributes().getFnAttr(Kind); - } - - /// Get the attribute of a given kind from a given arg - Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { - assert(ArgNo < arg_size() && "Out of bounds"); - return getAttributes().getParamAttr(ArgNo, Kind); - } - - /// Get the attribute of a given kind from a given arg - Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const { - assert(ArgNo < arg_size() && "Out of bounds"); - return getAttributes().getParamAttr(ArgNo, Kind); - } - - /// Return true if the data operand at index \p i has the attribute \p - /// A. - /// - /// Data operands include call arguments and values used in operand bundles, - /// but does not include the callee operand. - /// - /// The index \p i is interpreted as - /// - /// \p i in [0, arg_size) -> argument number (\p i) - /// \p i in [arg_size, data_operand_size) -> bundle operand at index - /// (\p i) in the operand list. - bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const { - // Note that we have to add one because `i` isn't zero-indexed. - assert(i < arg_size() + getNumTotalBundleOperands() && - "Data operand index out of bounds!"); - - // The attribute A can either be directly specified, if the operand in - // question is a call argument; or be indirectly implied by the kind of its - // containing operand bundle, if the operand is a bundle operand. - - if (i < arg_size()) - return paramHasAttr(i, Kind); - - assert(hasOperandBundles() && i >= getBundleOperandsStartIndex() && - "Must be either a call argument or an operand bundle!"); - return bundleOperandHasAttr(i, Kind); - } - - /// Determine whether this data operand is not captured. - // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to - // better indicate that this may return a conservative answer. - bool doesNotCapture(unsigned OpNo) const { - return dataOperandHasImpliedAttr(OpNo, Attribute::NoCapture); - } - - /// Determine whether this argument is passed by value. - bool isByValArgument(unsigned ArgNo) const { - return paramHasAttr(ArgNo, Attribute::ByVal); - } - - /// Determine whether this argument is passed in an alloca. - bool isInAllocaArgument(unsigned ArgNo) const { - return paramHasAttr(ArgNo, Attribute::InAlloca); - } - - /// Determine whether this argument is passed by value, in an alloca, or is - /// preallocated. - bool isPassPointeeByValueArgument(unsigned ArgNo) const { - return paramHasAttr(ArgNo, Attribute::ByVal) || - paramHasAttr(ArgNo, Attribute::InAlloca) || - paramHasAttr(ArgNo, Attribute::Preallocated); - } - - /// Determine whether passing undef to this argument is undefined behavior. - /// If passing undef to this argument is UB, passing poison is UB as well - /// because poison is more undefined than undef. - bool isPassingUndefUB(unsigned ArgNo) const { - return paramHasAttr(ArgNo, Attribute::NoUndef) || - // dereferenceable implies noundef. - paramHasAttr(ArgNo, Attribute::Dereferenceable) || - // dereferenceable implies noundef, and null is a well-defined value. - paramHasAttr(ArgNo, Attribute::DereferenceableOrNull); - } - - /// Determine if there is an inalloca argument. Only the last argument can - /// have the inalloca attribute. - bool hasInAllocaArgument() const { - return !arg_empty() && paramHasAttr(arg_size() - 1, Attribute::InAlloca); - } - - // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to - // better indicate that this may return a conservative answer. - bool doesNotAccessMemory(unsigned OpNo) const { - return dataOperandHasImpliedAttr(OpNo, Attribute::ReadNone); - } - - // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to - // better indicate that this may return a conservative answer. - bool onlyReadsMemory(unsigned OpNo) const { - return dataOperandHasImpliedAttr(OpNo, Attribute::ReadOnly) || - dataOperandHasImpliedAttr(OpNo, Attribute::ReadNone); - } - - // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to - // better indicate that this may return a conservative answer. - bool onlyWritesMemory(unsigned OpNo) const { - return dataOperandHasImpliedAttr(OpNo, Attribute::WriteOnly) || - dataOperandHasImpliedAttr(OpNo, Attribute::ReadNone); - } - - /// Extract the alignment of the return value. - MaybeAlign getRetAlign() const { - if (auto Align = Attrs.getRetAlignment()) - return Align; - if (const Function *F = getCalledFunction()) - return F->getAttributes().getRetAlignment(); - return None; - } - - /// Extract the alignment for a call or parameter (0=unknown). - MaybeAlign getParamAlign(unsigned ArgNo) const { - return Attrs.getParamAlignment(ArgNo); - } - - MaybeAlign getParamStackAlign(unsigned ArgNo) const { - return Attrs.getParamStackAlignment(ArgNo); - } - - /// Extract the byval type for a call or parameter. - Type *getParamByValType(unsigned ArgNo) const { - if (auto *Ty = Attrs.getParamByValType(ArgNo)) - return Ty; - if (const Function *F = getCalledFunction()) - return F->getAttributes().getParamByValType(ArgNo); - return nullptr; - } - - /// Extract the preallocated type for a call or parameter. - Type *getParamPreallocatedType(unsigned ArgNo) const { - if (auto *Ty = Attrs.getParamPreallocatedType(ArgNo)) - return Ty; - if (const Function *F = getCalledFunction()) - return F->getAttributes().getParamPreallocatedType(ArgNo); - return nullptr; - } - - /// Extract the preallocated type for a call or parameter. - Type *getParamInAllocaType(unsigned ArgNo) const { - if (auto *Ty = Attrs.getParamInAllocaType(ArgNo)) - return Ty; - if (const Function *F = getCalledFunction()) - return F->getAttributes().getParamInAllocaType(ArgNo); - return nullptr; - } - - /// Extract the number of dereferenceable bytes for a call or - /// parameter (0=unknown). - uint64_t getRetDereferenceableBytes() const { - return Attrs.getRetDereferenceableBytes(); - } - - /// Extract the number of dereferenceable bytes for a call or - /// parameter (0=unknown). - uint64_t getParamDereferenceableBytes(unsigned i) const { - return Attrs.getParamDereferenceableBytes(i); - } - - /// Extract the number of dereferenceable_or_null bytes for a call - /// (0=unknown). - uint64_t getRetDereferenceableOrNullBytes() const { - return Attrs.getRetDereferenceableOrNullBytes(); - } - - /// Extract the number of dereferenceable_or_null bytes for a - /// parameter (0=unknown). - uint64_t getParamDereferenceableOrNullBytes(unsigned i) const { - return Attrs.getParamDereferenceableOrNullBytes(i); - } - - /// Return true if the return value is known to be not null. - /// This may be because it has the nonnull attribute, or because at least - /// one byte is dereferenceable and the pointer is in addrspace(0). - bool isReturnNonNull() const; - - /// Determine if the return value is marked with NoAlias attribute. - bool returnDoesNotAlias() const { - return Attrs.hasRetAttr(Attribute::NoAlias); - } - - /// If one of the arguments has the 'returned' attribute, returns its - /// operand value. Otherwise, return nullptr. - Value *getReturnedArgOperand() const; - - /// Return true if the call should not be treated as a call to a - /// builtin. - bool isNoBuiltin() const { - return hasFnAttrImpl(Attribute::NoBuiltin) && - !hasFnAttrImpl(Attribute::Builtin); - } - - /// Determine if the call requires strict floating point semantics. - bool isStrictFP() const { return hasFnAttr(Attribute::StrictFP); } - - /// Return true if the call should not be inlined. - bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } - void setIsNoInline() { addFnAttr(Attribute::NoInline); } - /// Determine if the call does not access memory. - bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); } - void setDoesNotAccessMemory() { addFnAttr(Attribute::ReadNone); } - - /// Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return hasImpliedFnAttr(Attribute::ReadOnly); - } - - void setOnlyReadsMemory() { addFnAttr(Attribute::ReadOnly); } - - /// Determine if the call does not access or only writes memory. - bool onlyWritesMemory() const { - return hasImpliedFnAttr(Attribute::WriteOnly); - } - void setOnlyWritesMemory() { addFnAttr(Attribute::WriteOnly); } - - /// Determine if the call can access memory only using pointers based - /// on its arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttr(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } - - /// Determine if the function may only access memory that is - /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttr(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addFnAttr(Attribute::InaccessibleMemOnly); - } - - /// Determine if the function may only access memory that is - /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - /// Determine if the call cannot return. - bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } - void setDoesNotReturn() { addFnAttr(Attribute::NoReturn); } - - /// Determine if the call should not perform indirect branch tracking. - bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); } - - /// Determine if the call cannot unwind. - bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } - void setDoesNotThrow() { addFnAttr(Attribute::NoUnwind); } - - /// Determine if the invoke cannot be duplicated. - bool cannotDuplicate() const { return hasFnAttr(Attribute::NoDuplicate); } - void setCannotDuplicate() { addFnAttr(Attribute::NoDuplicate); } - - /// Determine if the call cannot be tail merged. - bool cannotMerge() const { return hasFnAttr(Attribute::NoMerge); } - void setCannotMerge() { addFnAttr(Attribute::NoMerge); } - - /// Determine if the invoke is convergent - bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } - void setConvergent() { addFnAttr(Attribute::Convergent); } - void setNotConvergent() { removeFnAttr(Attribute::Convergent); } - - /// Determine if the call returns a structure through first - /// pointer argument. - bool hasStructRetAttr() const { - if (arg_empty()) - return false; - - // Be friendly and also check the callee. - return paramHasAttr(0, Attribute::StructRet); - } - - /// Determine if any call argument is an aggregate passed by value. - bool hasByValArgument() const { - return Attrs.hasAttrSomewhere(Attribute::ByVal); - } - - ///@{ - // End of attribute API. - - /// \name Operand Bundle API - /// - /// This group of methods provides the API to access and manipulate operand - /// bundles on this call. - /// @{ - - /// Return the number of operand bundles associated with this User. - unsigned getNumOperandBundles() const { - return std::distance(bundle_op_info_begin(), bundle_op_info_end()); - } - - /// Return true if this User has any operand bundles. - bool hasOperandBundles() const { return getNumOperandBundles() != 0; } - - /// Return the index of the first bundle operand in the Use array. - unsigned getBundleOperandsStartIndex() const { - assert(hasOperandBundles() && "Don't call otherwise!"); - return bundle_op_info_begin()->Begin; - } - - /// Return the index of the last bundle operand in the Use array. - unsigned getBundleOperandsEndIndex() const { - assert(hasOperandBundles() && "Don't call otherwise!"); - return bundle_op_info_end()[-1].End; - } - - /// Return true if the operand at index \p Idx is a bundle operand. - bool isBundleOperand(unsigned Idx) const { - return hasOperandBundles() && Idx >= getBundleOperandsStartIndex() && - Idx < getBundleOperandsEndIndex(); - } - - /// Return true if the operand at index \p Idx is a bundle operand that has - /// tag ID \p ID. - bool isOperandBundleOfType(uint32_t ID, unsigned Idx) const { - return isBundleOperand(Idx) && - getOperandBundleForOperand(Idx).getTagID() == ID; - } - - /// Returns true if the use is a bundle operand. - bool isBundleOperand(const Use *U) const { - assert(this == U->getUser() && - "Only valid to query with a use of this instruction!"); - return hasOperandBundles() && isBundleOperand(U - op_begin()); - } - bool isBundleOperand(Value::const_user_iterator UI) const { - return isBundleOperand(&UI.getUse()); - } - - /// Return the total number operands (not operand bundles) used by - /// every operand bundle in this OperandBundleUser. - unsigned getNumTotalBundleOperands() const { - if (!hasOperandBundles()) - return 0; - - unsigned Begin = getBundleOperandsStartIndex(); - unsigned End = getBundleOperandsEndIndex(); - - assert(Begin <= End && "Should be!"); - return End - Begin; - } - - /// Return the operand bundle at a specific index. - OperandBundleUse getOperandBundleAt(unsigned Index) const { - assert(Index < getNumOperandBundles() && "Index out of bounds!"); - return operandBundleFromBundleOpInfo(*(bundle_op_info_begin() + Index)); - } - - /// Return the number of operand bundles with the tag Name attached to - /// this instruction. - unsigned countOperandBundlesOfType(StringRef Name) const { - unsigned Count = 0; - for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) - if (getOperandBundleAt(i).getTagName() == Name) - Count++; - - return Count; - } - - /// Return the number of operand bundles with the tag ID attached to - /// this instruction. - unsigned countOperandBundlesOfType(uint32_t ID) const { - unsigned Count = 0; - for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) - if (getOperandBundleAt(i).getTagID() == ID) - Count++; - - return Count; - } - - /// Return an operand bundle by name, if present. - /// - /// It is an error to call this for operand bundle types that may have - /// multiple instances of them on the same instruction. - Optional getOperandBundle(StringRef Name) const { - assert(countOperandBundlesOfType(Name) < 2 && "Precondition violated!"); - - for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { - OperandBundleUse U = getOperandBundleAt(i); - if (U.getTagName() == Name) - return U; - } - - return None; - } - - /// Return an operand bundle by tag ID, if present. - /// - /// It is an error to call this for operand bundle types that may have - /// multiple instances of them on the same instruction. - Optional getOperandBundle(uint32_t ID) const { - assert(countOperandBundlesOfType(ID) < 2 && "Precondition violated!"); - - for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { - OperandBundleUse U = getOperandBundleAt(i); - if (U.getTagID() == ID) - return U; - } - - return None; - } - - /// Return the list of operand bundles attached to this instruction as - /// a vector of OperandBundleDefs. - /// - /// This function copies the OperandBundeUse instances associated with this - /// OperandBundleUser to a vector of OperandBundleDefs. Note: - /// OperandBundeUses and OperandBundleDefs are non-trivially *different* - /// representations of operand bundles (see documentation above). - void getOperandBundlesAsDefs(SmallVectorImpl &Defs) const; - - /// Return the operand bundle for the operand at index OpIdx. - /// - /// It is an error to call this with an OpIdx that does not correspond to an - /// bundle operand. - OperandBundleUse getOperandBundleForOperand(unsigned OpIdx) const { - return operandBundleFromBundleOpInfo(getBundleOpInfoForOperand(OpIdx)); - } - - /// Return true if this operand bundle user has operand bundles that - /// may read from the heap. - bool hasReadingOperandBundles() const; - - /// Return true if this operand bundle user has operand bundles that - /// may write to the heap. - bool hasClobberingOperandBundles() const { - for (auto &BOI : bundle_op_infos()) { - if (BOI.Tag->second == LLVMContext::OB_deopt || - BOI.Tag->second == LLVMContext::OB_funclet) - continue; - - // This instruction has an operand bundle that is not known to us. - // Assume the worst. - return true; - } - - return false; - } - - /// Return true if the bundle operand at index \p OpIdx has the - /// attribute \p A. - bool bundleOperandHasAttr(unsigned OpIdx, Attribute::AttrKind A) const { - auto &BOI = getBundleOpInfoForOperand(OpIdx); - auto OBU = operandBundleFromBundleOpInfo(BOI); - return OBU.operandHasAttr(OpIdx - BOI.Begin, A); - } - - /// Return true if \p Other has the same sequence of operand bundle - /// tags with the same number of operands on each one of them as this - /// OperandBundleUser. - bool hasIdenticalOperandBundleSchema(const CallBase &Other) const { - if (getNumOperandBundles() != Other.getNumOperandBundles()) - return false; - - return std::equal(bundle_op_info_begin(), bundle_op_info_end(), - Other.bundle_op_info_begin()); - } - - /// Return true if this operand bundle user contains operand bundles - /// with tags other than those specified in \p IDs. - bool hasOperandBundlesOtherThan(ArrayRef IDs) const { - for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { - uint32_t ID = getOperandBundleAt(i).getTagID(); - if (!is_contained(IDs, ID)) - return true; - } - return false; - } - - /// Is the function attribute S disallowed by some operand bundle on - /// this operand bundle user? - bool isFnAttrDisallowedByOpBundle(StringRef S) const { - // Operand bundles only possibly disallow memory access attributes. All - // String attributes are fine. - return false; - } - - /// Is the function attribute A disallowed by some operand bundle on - /// this operand bundle user? - bool isFnAttrDisallowedByOpBundle(Attribute::AttrKind A) const { - switch (A) { - default: - return false; - - case Attribute::InaccessibleMemOrArgMemOnly: - return hasReadingOperandBundles(); - - case Attribute::InaccessibleMemOnly: - return hasReadingOperandBundles(); - - case Attribute::ArgMemOnly: - return hasReadingOperandBundles(); - - case Attribute::ReadNone: - return hasReadingOperandBundles(); - - case Attribute::ReadOnly: - return hasClobberingOperandBundles(); - - case Attribute::WriteOnly: - return hasReadingOperandBundles(); - } - - llvm_unreachable("switch has a default case!"); - } - - /// Used to keep track of an operand bundle. See the main comment on - /// OperandBundleUser above. - struct BundleOpInfo { - /// The operand bundle tag, interned by - /// LLVMContextImpl::getOrInsertBundleTag. - StringMapEntry *Tag; - - /// The index in the Use& vector where operands for this operand - /// bundle starts. - uint32_t Begin; - - /// The index in the Use& vector where operands for this operand - /// bundle ends. - uint32_t End; - - bool operator==(const BundleOpInfo &Other) const { - return Tag == Other.Tag && Begin == Other.Begin && End == Other.End; - } - }; - - /// Simple helper function to map a BundleOpInfo to an - /// OperandBundleUse. - OperandBundleUse - operandBundleFromBundleOpInfo(const BundleOpInfo &BOI) const { - auto begin = op_begin(); - ArrayRef Inputs(begin + BOI.Begin, begin + BOI.End); - return OperandBundleUse(BOI.Tag, Inputs); - } - - using bundle_op_iterator = BundleOpInfo *; - using const_bundle_op_iterator = const BundleOpInfo *; - - /// Return the start of the list of BundleOpInfo instances associated - /// with this OperandBundleUser. - /// - /// OperandBundleUser uses the descriptor area co-allocated with the host User - /// to store some meta information about which operands are "normal" operands, - /// and which ones belong to some operand bundle. - /// - /// The layout of an operand bundle user is - /// - /// +-----------uint32_t End-------------------------------------+ - /// | | - /// | +--------uint32_t Begin--------------------+ | - /// | | | | - /// ^ ^ v v - /// |------|------|----|----|----|----|----|---------|----|---------|----|----- - /// | BOI0 | BOI1 | .. | DU | U0 | U1 | .. | BOI0_U0 | .. | BOI1_U0 | .. | Un - /// |------|------|----|----|----|----|----|---------|----|---------|----|----- - /// v v ^ ^ - /// | | | | - /// | +--------uint32_t Begin------------+ | - /// | | - /// +-----------uint32_t End-----------------------------+ - /// - /// - /// BOI0, BOI1 ... are descriptions of operand bundles in this User's use - /// list. These descriptions are installed and managed by this class, and - /// they're all instances of OperandBundleUser::BundleOpInfo. - /// - /// DU is an additional descriptor installed by User's 'operator new' to keep - /// track of the 'BOI0 ... BOIN' co-allocation. OperandBundleUser does not - /// access or modify DU in any way, it's an implementation detail private to - /// User. - /// - /// The regular Use& vector for the User starts at U0. The operand bundle - /// uses are part of the Use& vector, just like normal uses. In the diagram - /// above, the operand bundle uses start at BOI0_U0. Each instance of - /// BundleOpInfo has information about a contiguous set of uses constituting - /// an operand bundle, and the total set of operand bundle uses themselves - /// form a contiguous set of uses (i.e. there are no gaps between uses - /// corresponding to individual operand bundles). - /// - /// This class does not know the location of the set of operand bundle uses - /// within the use list -- that is decided by the User using this class via - /// the BeginIdx argument in populateBundleOperandInfos. - /// - /// Currently operand bundle users with hung-off operands are not supported. - bundle_op_iterator bundle_op_info_begin() { - if (!hasDescriptor()) - return nullptr; - - uint8_t *BytesBegin = getDescriptor().begin(); - return reinterpret_cast(BytesBegin); - } - - /// Return the start of the list of BundleOpInfo instances associated - /// with this OperandBundleUser. - const_bundle_op_iterator bundle_op_info_begin() const { - auto *NonConstThis = const_cast(this); - return NonConstThis->bundle_op_info_begin(); - } - - /// Return the end of the list of BundleOpInfo instances associated - /// with this OperandBundleUser. - bundle_op_iterator bundle_op_info_end() { - if (!hasDescriptor()) - return nullptr; - - uint8_t *BytesEnd = getDescriptor().end(); - return reinterpret_cast(BytesEnd); - } - - /// Return the end of the list of BundleOpInfo instances associated - /// with this OperandBundleUser. - const_bundle_op_iterator bundle_op_info_end() const { - auto *NonConstThis = const_cast(this); - return NonConstThis->bundle_op_info_end(); - } - - /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). - iterator_range bundle_op_infos() { - return make_range(bundle_op_info_begin(), bundle_op_info_end()); - } - - /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). - iterator_range bundle_op_infos() const { - return make_range(bundle_op_info_begin(), bundle_op_info_end()); - } - - /// Populate the BundleOpInfo instances and the Use& vector from \p - /// Bundles. Return the op_iterator pointing to the Use& one past the last - /// last bundle operand use. - /// - /// Each \p OperandBundleDef instance is tracked by a OperandBundleInfo - /// instance allocated in this User's descriptor. - op_iterator populateBundleOperandInfos(ArrayRef Bundles, - const unsigned BeginIndex); - -public: - /// Return the BundleOpInfo for the operand at index OpIdx. - /// - /// It is an error to call this with an OpIdx that does not correspond to an - /// bundle operand. - BundleOpInfo &getBundleOpInfoForOperand(unsigned OpIdx); - const BundleOpInfo &getBundleOpInfoForOperand(unsigned OpIdx) const { - return const_cast(this)->getBundleOpInfoForOperand(OpIdx); - } - -protected: - /// Return the total number of values used in \p Bundles. - static unsigned CountBundleInputs(ArrayRef Bundles) { - unsigned Total = 0; - for (auto &B : Bundles) - Total += B.input_size(); - return Total; - } - - /// @} - // End of operand bundle API. - -private: - bool hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const; - bool hasFnAttrOnCalledFunction(StringRef Kind) const; - - template bool hasFnAttrImpl(AttrKind Kind) const { - if (Attrs.hasFnAttr(Kind)) - return true; - - // Operand bundles override attributes on the called function, but don't - // override attributes directly present on the call instruction. - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - - return hasFnAttrOnCalledFunction(Kind); - } - - /// A specialized version of hasFnAttrImpl for when the caller wants to - /// know if an attribute's semantics are implied, not whether the attribute - /// is actually present. This distinction only exists when checking whether - /// something is readonly or writeonly since readnone implies both. The case - /// which motivates the specialized code is a callee with readnone, and an - /// operand bundle on the call which disallows readnone but not either - /// readonly or writeonly. - bool hasImpliedFnAttr(Attribute::AttrKind Kind) const { - assert((Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly) && - "use hasFnAttrImpl instead"); - if (Attrs.hasFnAttr(Kind) || Attrs.hasFnAttr(Attribute::ReadNone)) - return true; - - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - - return hasFnAttrOnCalledFunction(Kind) || - hasFnAttrOnCalledFunction(Attribute::ReadNone); - } - - /// Determine whether the return value has the given attribute. Supports - /// Attribute::AttrKind and StringRef as \p AttrKind types. - template bool hasRetAttrImpl(AttrKind Kind) const { - if (Attrs.hasRetAttr(Kind)) - return true; - - // Look at the callee, if available. - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasRetAttr(Kind); - return false; - } -}; - -template <> -struct OperandTraits : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallBase, Value) - -//===----------------------------------------------------------------------===// -// FuncletPadInst Class -//===----------------------------------------------------------------------===// -class FuncletPadInst : public Instruction { -private: - FuncletPadInst(const FuncletPadInst &CPI); - - explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad, - ArrayRef Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore); - explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad, - ArrayRef Args, unsigned Values, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(Value *ParentPad, ArrayRef Args, const Twine &NameStr); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - friend class CatchPadInst; - friend class CleanupPadInst; - - FuncletPadInst *cloneImpl() const; - -public: - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// getNumArgOperands - Return the number of funcletpad arguments. - /// - unsigned getNumArgOperands() const { return getNumOperands() - 1; } - - /// Convenience accessors - - /// Return the outer EH-pad this funclet is nested within. - /// - /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst - /// is a CatchPadInst. - Value *getParentPad() const { return Op<-1>(); } - void setParentPad(Value *ParentPad) { - assert(ParentPad); - Op<-1>() = ParentPad; - } - - /// getArgOperand/setArgOperand - Return/set the i-th funcletpad argument. - /// - Value *getArgOperand(unsigned i) const { return getOperand(i); } - void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } - - /// arg_operands - iteration adapter for range-for loops. - op_range arg_operands() { return op_range(op_begin(), op_end() - 1); } - - /// arg_operands - iteration adapter for range-for loops. - const_op_range arg_operands() const { - return const_op_range(op_begin(), op_end() - 1); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { return I->isFuncletPad(); } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value) - -} // end namespace llvm - -#endif // LLVM_IR_INSTRTYPES_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Instruction.def b/suite/synctools/tablegen/include/llvm/IR/Instruction.def deleted file mode 100644 index a5ad92f58f..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Instruction.def +++ /dev/null @@ -1,255 +0,0 @@ -//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains descriptions of the various LLVM instructions. This is -// used as a central place for enumerating the different instructions and -// should eventually be the place to put comments about the instructions. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -// Provide definitions of macros so that users of this file do not have to -// define everything to use it... -// -#ifndef FIRST_TERM_INST -#define FIRST_TERM_INST(num) -#endif -#ifndef HANDLE_TERM_INST -#ifndef HANDLE_INST -#define HANDLE_TERM_INST(num, opcode, Class) -#else -#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_TERM_INST -#define LAST_TERM_INST(num) -#endif - -#ifndef FIRST_UNARY_INST -#define FIRST_UNARY_INST(num) -#endif -#ifndef HANDLE_UNARY_INST -#ifndef HANDLE_INST -#define HANDLE_UNARY_INST(num, opcode, instclass) -#else -#define HANDLE_UNARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_UNARY_INST -#define LAST_UNARY_INST(num) -#endif - -#ifndef FIRST_BINARY_INST -#define FIRST_BINARY_INST(num) -#endif -#ifndef HANDLE_BINARY_INST -#ifndef HANDLE_INST -#define HANDLE_BINARY_INST(num, opcode, instclass) -#else -#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_BINARY_INST -#define LAST_BINARY_INST(num) -#endif - -#ifndef FIRST_MEMORY_INST -#define FIRST_MEMORY_INST(num) -#endif -#ifndef HANDLE_MEMORY_INST -#ifndef HANDLE_INST -#define HANDLE_MEMORY_INST(num, opcode, Class) -#else -#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_MEMORY_INST -#define LAST_MEMORY_INST(num) -#endif - -#ifndef FIRST_CAST_INST -#define FIRST_CAST_INST(num) -#endif -#ifndef HANDLE_CAST_INST -#ifndef HANDLE_INST -#define HANDLE_CAST_INST(num, opcode, Class) -#else -#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_CAST_INST -#define LAST_CAST_INST(num) -#endif - -#ifndef FIRST_FUNCLETPAD_INST -#define FIRST_FUNCLETPAD_INST(num) -#endif -#ifndef HANDLE_FUNCLETPAD_INST -#ifndef HANDLE_INST -#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) -#else -#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_FUNCLETPAD_INST -#define LAST_FUNCLETPAD_INST(num) -#endif - -#ifndef FIRST_OTHER_INST -#define FIRST_OTHER_INST(num) -#endif -#ifndef HANDLE_OTHER_INST -#ifndef HANDLE_INST -#define HANDLE_OTHER_INST(num, opcode, Class) -#else -#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) -#endif -#endif -#ifndef LAST_OTHER_INST -#define LAST_OTHER_INST(num) -#endif - -#ifndef HANDLE_USER_INST -#define HANDLE_USER_INST(num, opc, Class) HANDLE_OTHER_INST(num, opc, Class) -#endif - -// Terminator Instructions - These instructions are used to terminate a basic -// block of the program. Every basic block must end with one of these -// instructions for it to be a well formed basic block. -// - FIRST_TERM_INST ( 1) -HANDLE_TERM_INST ( 1, Ret , ReturnInst) -HANDLE_TERM_INST ( 2, Br , BranchInst) -HANDLE_TERM_INST ( 3, Switch , SwitchInst) -HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) -HANDLE_TERM_INST ( 5, Invoke , InvokeInst) -HANDLE_TERM_INST ( 6, Resume , ResumeInst) -HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst) -HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst) -HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst) -HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst) -HANDLE_TERM_INST (11, CallBr , CallBrInst) // A call-site terminator - LAST_TERM_INST (11) - -// Standard unary operators... - FIRST_UNARY_INST(12) -HANDLE_UNARY_INST(12, FNeg , UnaryOperator) - LAST_UNARY_INST(12) - -// Standard binary operators... - FIRST_BINARY_INST(13) -HANDLE_BINARY_INST(13, Add , BinaryOperator) -HANDLE_BINARY_INST(14, FAdd , BinaryOperator) -HANDLE_BINARY_INST(15, Sub , BinaryOperator) -HANDLE_BINARY_INST(16, FSub , BinaryOperator) -HANDLE_BINARY_INST(17, Mul , BinaryOperator) -HANDLE_BINARY_INST(18, FMul , BinaryOperator) -HANDLE_BINARY_INST(19, UDiv , BinaryOperator) -HANDLE_BINARY_INST(20, SDiv , BinaryOperator) -HANDLE_BINARY_INST(21, FDiv , BinaryOperator) -HANDLE_BINARY_INST(22, URem , BinaryOperator) -HANDLE_BINARY_INST(23, SRem , BinaryOperator) -HANDLE_BINARY_INST(24, FRem , BinaryOperator) - -// Logical operators (integer operands) -HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(28, And , BinaryOperator) -HANDLE_BINARY_INST(29, Or , BinaryOperator) -HANDLE_BINARY_INST(30, Xor , BinaryOperator) - LAST_BINARY_INST(30) - -// Memory operators... - FIRST_MEMORY_INST(31) -HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(33, Store , StoreInst ) -HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst) -HANDLE_MEMORY_INST(35, Fence , FenceInst ) -HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst ) -HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst ) - LAST_MEMORY_INST(37) - -// Cast operators ... -// NOTE: The order matters here because CastInst::isEliminableCastPair -// NOTE: (see Instructions.cpp) encodes a table based on this ordering. - FIRST_CAST_INST(38) -HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers -HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers -HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers -HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt -HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt -HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point -HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point -HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point -HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point -HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer -HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer -HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast -HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast - LAST_CAST_INST(50) - - FIRST_FUNCLETPAD_INST(51) -HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst) -HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst) - LAST_FUNCLETPAD_INST(52) - -// Other operators... - FIRST_OTHER_INST(53) -HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction -HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass -HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction. -HANDLE_OTHER_INST(67, Freeze, FreezeInst) // Freeze instruction. - LAST_OTHER_INST(67) - -#undef FIRST_TERM_INST -#undef HANDLE_TERM_INST -#undef LAST_TERM_INST - -#undef FIRST_UNARY_INST -#undef HANDLE_UNARY_INST -#undef LAST_UNARY_INST - -#undef FIRST_BINARY_INST -#undef HANDLE_BINARY_INST -#undef LAST_BINARY_INST - -#undef FIRST_MEMORY_INST -#undef HANDLE_MEMORY_INST -#undef LAST_MEMORY_INST - -#undef FIRST_CAST_INST -#undef HANDLE_CAST_INST -#undef LAST_CAST_INST - -#undef FIRST_FUNCLETPAD_INST -#undef HANDLE_FUNCLETPAD_INST -#undef LAST_FUNCLETPAD_INST - -#undef FIRST_OTHER_INST -#undef HANDLE_OTHER_INST -#undef LAST_OTHER_INST - -#undef HANDLE_USER_INST - -#ifdef HANDLE_INST -#undef HANDLE_INST -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Instruction.h b/suite/synctools/tablegen/include/llvm/IR/Instruction.h deleted file mode 100644 index a5d364f0bc..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Instruction.h +++ /dev/null @@ -1,878 +0,0 @@ -//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the Instruction class, which is the -// base class for all of the LLVM instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INSTRUCTION_H -#define LLVM_IR_INSTRUCTION_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Bitfields.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" -#include -#include - -namespace llvm { - -class BasicBlock; -class FastMathFlags; -class MDNode; -class Module; -struct AAMDNodes; - -template <> struct ilist_alloc_traits { - static inline void deleteNode(Instruction *V); -}; - -class Instruction : public User, - public ilist_node_with_parent { - BasicBlock *Parent; - DebugLoc DbgLoc; // 'dbg' Metadata cache. - - /// Relative order of this instruction in its parent basic block. Used for - /// O(1) local dominance checks between instructions. - mutable unsigned Order = 0; - -protected: - // The 15 first bits of `Value::SubclassData` are available for subclasses of - // `Instruction` to use. - using OpaqueField = Bitfield::Element; - - // Template alias so that all Instruction storing alignment use the same - // definition. - // Valid alignments are powers of two from 2^0 to 2^MaxAlignmentExponent = - // 2^32. We store them as Log2(Alignment), so we need 6 bits to encode the 33 - // possible values. - template - using AlignmentBitfieldElementT = - typename Bitfield::Element; - - template - using BoolBitfieldElementT = typename Bitfield::Element; - - template - using AtomicOrderingBitfieldElementT = - typename Bitfield::Element; - -private: - // The last bit is used to store whether the instruction has metadata attached - // or not. - using HasMetadataField = Bitfield::Element; - -protected: - ~Instruction(); // Use deleteValue() to delete a generic Instruction. - -public: - Instruction(const Instruction &) = delete; - Instruction &operator=(const Instruction &) = delete; - - /// Specialize the methods defined in Value, as we know that an instruction - /// can only be used by other instructions. - Instruction *user_back() { return cast(*user_begin());} - const Instruction *user_back() const { return cast(*user_begin());} - - inline const BasicBlock *getParent() const { return Parent; } - inline BasicBlock *getParent() { return Parent; } - - /// Return the module owning the function this instruction belongs to - /// or nullptr it the function does not have a module. - /// - /// Note: this is undefined behavior if the instruction does not have a - /// parent, or the parent basic block does not have a parent function. - const Module *getModule() const; - Module *getModule() { - return const_cast( - static_cast(this)->getModule()); - } - - /// Return the function this instruction belongs to. - /// - /// Note: it is undefined behavior to call this on an instruction not - /// currently inserted into a function. - const Function *getFunction() const; - Function *getFunction() { - return const_cast( - static_cast(this)->getFunction()); - } - - /// This method unlinks 'this' from the containing basic block, but does not - /// delete it. - void removeFromParent(); - - /// This method unlinks 'this' from the containing basic block and deletes it. - /// - /// \returns an iterator pointing to the element after the erased one - SymbolTableList::iterator eraseFromParent(); - - /// Insert an unlinked instruction into a basic block immediately before - /// the specified instruction. - void insertBefore(Instruction *InsertPos); - - /// Insert an unlinked instruction into a basic block immediately after the - /// specified instruction. - void insertAfter(Instruction *InsertPos); - - /// Unlink this instruction from its current basic block and insert it into - /// the basic block that MovePos lives in, right before MovePos. - void moveBefore(Instruction *MovePos); - - /// Unlink this instruction and insert into BB before I. - /// - /// \pre I is a valid iterator into BB. - void moveBefore(BasicBlock &BB, SymbolTableList::iterator I); - - /// Unlink this instruction from its current basic block and insert it into - /// the basic block that MovePos lives in, right after MovePos. - void moveAfter(Instruction *MovePos); - - /// Given an instruction Other in the same basic block as this instruction, - /// return true if this instruction comes before Other. In this worst case, - /// this takes linear time in the number of instructions in the block. The - /// results are cached, so in common cases when the block remains unmodified, - /// it takes constant time. - bool comesBefore(const Instruction *Other) const; - - //===--------------------------------------------------------------------===// - // Subclass classification. - //===--------------------------------------------------------------------===// - - /// Returns a member of one of the enums like Instruction::Add. - unsigned getOpcode() const { return getValueID() - InstructionVal; } - - const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } - bool isTerminator() const { return isTerminator(getOpcode()); } - bool isUnaryOp() const { return isUnaryOp(getOpcode()); } - bool isBinaryOp() const { return isBinaryOp(getOpcode()); } - bool isIntDivRem() const { return isIntDivRem(getOpcode()); } - bool isShift() const { return isShift(getOpcode()); } - bool isCast() const { return isCast(getOpcode()); } - bool isFuncletPad() const { return isFuncletPad(getOpcode()); } - bool isExceptionalTerminator() const { - return isExceptionalTerminator(getOpcode()); - } - - /// It checks if this instruction is the only user of at least one of - /// its operands. - bool isOnlyUserOfAnyOperand(); - - bool isIndirectTerminator() const { - return isIndirectTerminator(getOpcode()); - } - - static const char* getOpcodeName(unsigned OpCode); - - static inline bool isTerminator(unsigned OpCode) { - return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; - } - - static inline bool isUnaryOp(unsigned Opcode) { - return Opcode >= UnaryOpsBegin && Opcode < UnaryOpsEnd; - } - static inline bool isBinaryOp(unsigned Opcode) { - return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; - } - - static inline bool isIntDivRem(unsigned Opcode) { - return Opcode == UDiv || Opcode == SDiv || Opcode == URem || Opcode == SRem; - } - - /// Determine if the Opcode is one of the shift instructions. - static inline bool isShift(unsigned Opcode) { - return Opcode >= Shl && Opcode <= AShr; - } - - /// Return true if this is a logical shift left or a logical shift right. - inline bool isLogicalShift() const { - return getOpcode() == Shl || getOpcode() == LShr; - } - - /// Return true if this is an arithmetic shift right. - inline bool isArithmeticShift() const { - return getOpcode() == AShr; - } - - /// Determine if the Opcode is and/or/xor. - static inline bool isBitwiseLogicOp(unsigned Opcode) { - return Opcode == And || Opcode == Or || Opcode == Xor; - } - - /// Return true if this is and/or/xor. - inline bool isBitwiseLogicOp() const { - return isBitwiseLogicOp(getOpcode()); - } - - /// Determine if the OpCode is one of the CastInst instructions. - static inline bool isCast(unsigned OpCode) { - return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; - } - - /// Determine if the OpCode is one of the FuncletPadInst instructions. - static inline bool isFuncletPad(unsigned OpCode) { - return OpCode >= FuncletPadOpsBegin && OpCode < FuncletPadOpsEnd; - } - - /// Returns true if the OpCode is a terminator related to exception handling. - static inline bool isExceptionalTerminator(unsigned OpCode) { - switch (OpCode) { - case Instruction::CatchSwitch: - case Instruction::CatchRet: - case Instruction::CleanupRet: - case Instruction::Invoke: - case Instruction::Resume: - return true; - default: - return false; - } - } - - /// Returns true if the OpCode is a terminator with indirect targets. - static inline bool isIndirectTerminator(unsigned OpCode) { - switch (OpCode) { - case Instruction::IndirectBr: - case Instruction::CallBr: - return true; - default: - return false; - } - } - - //===--------------------------------------------------------------------===// - // Metadata manipulation. - //===--------------------------------------------------------------------===// - - /// Return true if this instruction has any metadata attached to it. - bool hasMetadata() const { return DbgLoc || Value::hasMetadata(); } - - /// Return true if this instruction has metadata attached to it other than a - /// debug location. - bool hasMetadataOtherThanDebugLoc() const { return Value::hasMetadata(); } - - /// Return true if this instruction has the given type of metadata attached. - bool hasMetadata(unsigned KindID) const { - return getMetadata(KindID) != nullptr; - } - - /// Return true if this instruction has the given type of metadata attached. - bool hasMetadata(StringRef Kind) const { - return getMetadata(Kind) != nullptr; - } - - /// Get the metadata of given kind attached to this Instruction. - /// If the metadata is not found then return null. - MDNode *getMetadata(unsigned KindID) const { - if (!hasMetadata()) return nullptr; - return getMetadataImpl(KindID); - } - - /// Get the metadata of given kind attached to this Instruction. - /// If the metadata is not found then return null. - MDNode *getMetadata(StringRef Kind) const { - if (!hasMetadata()) return nullptr; - return getMetadataImpl(Kind); - } - - /// Get all metadata attached to this Instruction. The first element of each - /// pair returned is the KindID, the second element is the metadata value. - /// This list is returned sorted by the KindID. - void - getAllMetadata(SmallVectorImpl> &MDs) const { - if (hasMetadata()) - getAllMetadataImpl(MDs); - } - - /// This does the same thing as getAllMetadata, except that it filters out the - /// debug location. - void getAllMetadataOtherThanDebugLoc( - SmallVectorImpl> &MDs) const { - Value::getAllMetadata(MDs); - } - - /// Set the metadata of the specified kind to the specified node. This updates - /// or replaces metadata if already present, or removes it if Node is null. - void setMetadata(unsigned KindID, MDNode *Node); - void setMetadata(StringRef Kind, MDNode *Node); - - /// Copy metadata from \p SrcInst to this instruction. \p WL, if not empty, - /// specifies the list of meta data that needs to be copied. If \p WL is - /// empty, all meta data will be copied. - void copyMetadata(const Instruction &SrcInst, - ArrayRef WL = ArrayRef()); - - /// If the instruction has "branch_weights" MD_prof metadata and the MDNode - /// has three operands (including name string), swap the order of the - /// metadata. - void swapProfMetadata(); - - /// Drop all unknown metadata except for debug locations. - /// @{ - /// Passes are required to drop metadata they don't understand. This is a - /// convenience method for passes to do so. - /// dropUndefImplyingAttrsAndUnknownMetadata should be used instead of - /// this API if the Instruction being modified is a call. - void dropUnknownNonDebugMetadata(ArrayRef KnownIDs); - void dropUnknownNonDebugMetadata() { - return dropUnknownNonDebugMetadata(None); - } - void dropUnknownNonDebugMetadata(unsigned ID1) { - return dropUnknownNonDebugMetadata(makeArrayRef(ID1)); - } - void dropUnknownNonDebugMetadata(unsigned ID1, unsigned ID2) { - unsigned IDs[] = {ID1, ID2}; - return dropUnknownNonDebugMetadata(IDs); - } - /// @} - - /// Adds an !annotation metadata node with \p Annotation to this instruction. - /// If this instruction already has !annotation metadata, append \p Annotation - /// to the existing node. - void addAnnotationMetadata(StringRef Annotation); - - /// Returns the AA metadata for this instruction. - AAMDNodes getAAMetadata() const; - - /// Sets the AA metadata on this instruction from the AAMDNodes structure. - void setAAMetadata(const AAMDNodes &N); - - /// Retrieve the raw weight values of a conditional branch or select. - /// Returns true on success with profile weights filled in. - /// Returns false if no metadata or invalid metadata was found. - bool extractProfMetadata(uint64_t &TrueVal, uint64_t &FalseVal) const; - - /// Retrieve total raw weight values of a branch. - /// Returns true on success with profile total weights filled in. - /// Returns false if no metadata was found. - bool extractProfTotalWeight(uint64_t &TotalVal) const; - - /// Set the debug location information for this instruction. - void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } - - /// Return the debug location for this node as a DebugLoc. - const DebugLoc &getDebugLoc() const { return DbgLoc; } - - /// Set or clear the nuw flag on this instruction, which must be an operator - /// which supports this flag. See LangRef.html for the meaning of this flag. - void setHasNoUnsignedWrap(bool b = true); - - /// Set or clear the nsw flag on this instruction, which must be an operator - /// which supports this flag. See LangRef.html for the meaning of this flag. - void setHasNoSignedWrap(bool b = true); - - /// Set or clear the exact flag on this instruction, which must be an operator - /// which supports this flag. See LangRef.html for the meaning of this flag. - void setIsExact(bool b = true); - - /// Determine whether the no unsigned wrap flag is set. - bool hasNoUnsignedWrap() const; - - /// Determine whether the no signed wrap flag is set. - bool hasNoSignedWrap() const; - - /// Return true if this operator has flags which may cause this instruction - /// to evaluate to poison despite having non-poison inputs. - bool hasPoisonGeneratingFlags() const; - - /// Drops flags that may cause this instruction to evaluate to poison despite - /// having non-poison inputs. - void dropPoisonGeneratingFlags(); - - /// This function drops non-debug unknown metadata (through - /// dropUnknownNonDebugMetadata). For calls, it also drops parameter and - /// return attributes that can cause undefined behaviour. Both of these should - /// be done by passes which move instructions in IR. - void - dropUndefImplyingAttrsAndUnknownMetadata(ArrayRef KnownIDs = {}); - - /// Determine whether the exact flag is set. - bool isExact() const; - - /// Set or clear all fast-math-flags on this instruction, which must be an - /// operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setFast(bool B); - - /// Set or clear the reassociation flag on this instruction, which must be - /// an operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasAllowReassoc(bool B); - - /// Set or clear the no-nans flag on this instruction, which must be an - /// operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasNoNaNs(bool B); - - /// Set or clear the no-infs flag on this instruction, which must be an - /// operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasNoInfs(bool B); - - /// Set or clear the no-signed-zeros flag on this instruction, which must be - /// an operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasNoSignedZeros(bool B); - - /// Set or clear the allow-reciprocal flag on this instruction, which must be - /// an operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasAllowReciprocal(bool B); - - /// Set or clear the allow-contract flag on this instruction, which must be - /// an operator which supports this flag. See LangRef.html for the meaning of - /// this flag. - void setHasAllowContract(bool B); - - /// Set or clear the approximate-math-functions flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html for - /// the meaning of this flag. - void setHasApproxFunc(bool B); - - /// Convenience function for setting multiple fast-math flags on this - /// instruction, which must be an operator which supports these flags. See - /// LangRef.html for the meaning of these flags. - void setFastMathFlags(FastMathFlags FMF); - - /// Convenience function for transferring all fast-math flag values to this - /// instruction, which must be an operator which supports these flags. See - /// LangRef.html for the meaning of these flags. - void copyFastMathFlags(FastMathFlags FMF); - - /// Determine whether all fast-math-flags are set. - bool isFast() const; - - /// Determine whether the allow-reassociation flag is set. - bool hasAllowReassoc() const; - - /// Determine whether the no-NaNs flag is set. - bool hasNoNaNs() const; - - /// Determine whether the no-infs flag is set. - bool hasNoInfs() const; - - /// Determine whether the no-signed-zeros flag is set. - bool hasNoSignedZeros() const; - - /// Determine whether the allow-reciprocal flag is set. - bool hasAllowReciprocal() const; - - /// Determine whether the allow-contract flag is set. - bool hasAllowContract() const; - - /// Determine whether the approximate-math-functions flag is set. - bool hasApproxFunc() const; - - /// Convenience function for getting all the fast-math flags, which must be an - /// operator which supports these flags. See LangRef.html for the meaning of - /// these flags. - FastMathFlags getFastMathFlags() const; - - /// Copy I's fast-math flags - void copyFastMathFlags(const Instruction *I); - - /// Convenience method to copy supported exact, fast-math, and (optionally) - /// wrapping flags from V to this instruction. - void copyIRFlags(const Value *V, bool IncludeWrapFlags = true); - - /// Logical 'and' of any supported wrapping, exact, and fast-math flags of - /// V and this instruction. - void andIRFlags(const Value *V); - - /// Merge 2 debug locations and apply it to the Instruction. If the - /// instruction is a CallIns, we need to traverse the inline chain to find - /// the common scope. This is not efficient for N-way merging as each time - /// you merge 2 iterations, you need to rebuild the hashmap to find the - /// common scope. However, we still choose this API because: - /// 1) Simplicity: it takes 2 locations instead of a list of locations. - /// 2) In worst case, it increases the complexity from O(N*I) to - /// O(2*N*I), where N is # of Instructions to merge, and I is the - /// maximum level of inline stack. So it is still linear. - /// 3) Merging of call instructions should be extremely rare in real - /// applications, thus the N-way merging should be in code path. - /// The DebugLoc attached to this instruction will be overwritten by the - /// merged DebugLoc. - void applyMergedLocation(const DILocation *LocA, const DILocation *LocB); - - /// Updates the debug location given that the instruction has been hoisted - /// from a block to a predecessor of that block. - /// Note: it is undefined behavior to call this on an instruction not - /// currently inserted into a function. - void updateLocationAfterHoist(); - - /// Drop the instruction's debug location. This does not guarantee removal - /// of the !dbg source location attachment, as it must set a line 0 location - /// with scope information attached on call instructions. To guarantee - /// removal of the !dbg attachment, use the \ref setDebugLoc() API. - /// Note: it is undefined behavior to call this on an instruction not - /// currently inserted into a function. - void dropLocation(); - -private: - // These are all implemented in Metadata.cpp. - MDNode *getMetadataImpl(unsigned KindID) const; - MDNode *getMetadataImpl(StringRef Kind) const; - void - getAllMetadataImpl(SmallVectorImpl> &) const; - -public: - //===--------------------------------------------------------------------===// - // Predicates and helper methods. - //===--------------------------------------------------------------------===// - - /// Return true if the instruction is associative: - /// - /// Associative operators satisfy: x op (y op z) === (x op y) op z - /// - /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. - /// - bool isAssociative() const LLVM_READONLY; - static bool isAssociative(unsigned Opcode) { - return Opcode == And || Opcode == Or || Opcode == Xor || - Opcode == Add || Opcode == Mul; - } - - /// Return true if the instruction is commutative: - /// - /// Commutative operators satisfy: (x op y) === (y op x) - /// - /// In LLVM, these are the commutative operators, plus SetEQ and SetNE, when - /// applied to any type. - /// - bool isCommutative() const LLVM_READONLY; - static bool isCommutative(unsigned Opcode) { - switch (Opcode) { - case Add: case FAdd: - case Mul: case FMul: - case And: case Or: case Xor: - return true; - default: - return false; - } - } - - /// Return true if the instruction is idempotent: - /// - /// Idempotent operators satisfy: x op x === x - /// - /// In LLVM, the And and Or operators are idempotent. - /// - bool isIdempotent() const { return isIdempotent(getOpcode()); } - static bool isIdempotent(unsigned Opcode) { - return Opcode == And || Opcode == Or; - } - - /// Return true if the instruction is nilpotent: - /// - /// Nilpotent operators satisfy: x op x === Id, - /// - /// where Id is the identity for the operator, i.e. a constant such that - /// x op Id === x and Id op x === x for all x. - /// - /// In LLVM, the Xor operator is nilpotent. - /// - bool isNilpotent() const { return isNilpotent(getOpcode()); } - static bool isNilpotent(unsigned Opcode) { - return Opcode == Xor; - } - - /// Return true if this instruction may modify memory. - bool mayWriteToMemory() const; - - /// Return true if this instruction may read memory. - bool mayReadFromMemory() const; - - /// Return true if this instruction may read or write memory. - bool mayReadOrWriteMemory() const { - return mayReadFromMemory() || mayWriteToMemory(); - } - - /// Return true if this instruction has an AtomicOrdering of unordered or - /// higher. - bool isAtomic() const; - - /// Return true if this atomic instruction loads from memory. - bool hasAtomicLoad() const; - - /// Return true if this atomic instruction stores to memory. - bool hasAtomicStore() const; - - /// Return true if this instruction has a volatile memory access. - bool isVolatile() const; - - /// Return true if this instruction may throw an exception. - bool mayThrow() const; - - /// Return true if this instruction behaves like a memory fence: it can load - /// or store to memory location without being given a memory location. - bool isFenceLike() const { - switch (getOpcode()) { - default: - return false; - // This list should be kept in sync with the list in mayWriteToMemory for - // all opcodes which don't have a memory location. - case Instruction::Fence: - case Instruction::CatchPad: - case Instruction::CatchRet: - case Instruction::Call: - case Instruction::Invoke: - return true; - } - } - - /// Return true if the instruction may have side effects. - /// - /// Side effects are: - /// * Writing to memory. - /// * Unwinding. - /// * Not returning (e.g. an infinite loop). - /// - /// Note that this does not consider malloc and alloca to have side - /// effects because the newly allocated memory is completely invisible to - /// instructions which don't use the returned value. For cases where this - /// matters, isSafeToSpeculativelyExecute may be more appropriate. - bool mayHaveSideEffects() const; - - /// Return true if the instruction can be removed if the result is unused. - /// - /// When constant folding some instructions cannot be removed even if their - /// results are unused. Specifically terminator instructions and calls that - /// may have side effects cannot be removed without semantically changing the - /// generated program. - bool isSafeToRemove() const; - - /// Return true if the instruction will return (unwinding is considered as - /// a form of returning control flow here). - bool willReturn() const; - - /// Return true if the instruction is a variety of EH-block. - bool isEHPad() const { - switch (getOpcode()) { - case Instruction::CatchSwitch: - case Instruction::CatchPad: - case Instruction::CleanupPad: - case Instruction::LandingPad: - return true; - default: - return false; - } - } - - /// Return true if the instruction is a llvm.lifetime.start or - /// llvm.lifetime.end marker. - bool isLifetimeStartOrEnd() const; - - /// Return true if the instruction is a llvm.launder.invariant.group or - /// llvm.strip.invariant.group. - bool isLaunderOrStripInvariantGroup() const; - - /// Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst. - bool isDebugOrPseudoInst() const; - - /// Return a pointer to the next non-debug instruction in the same basic - /// block as 'this', or nullptr if no such instruction exists. Skip any pseudo - /// operations if \c SkipPseudoOp is true. - const Instruction * - getNextNonDebugInstruction(bool SkipPseudoOp = false) const; - Instruction *getNextNonDebugInstruction(bool SkipPseudoOp = false) { - return const_cast( - static_cast(this)->getNextNonDebugInstruction( - SkipPseudoOp)); - } - - /// Return a pointer to the previous non-debug instruction in the same basic - /// block as 'this', or nullptr if no such instruction exists. Skip any pseudo - /// operations if \c SkipPseudoOp is true. - const Instruction * - getPrevNonDebugInstruction(bool SkipPseudoOp = false) const; - Instruction *getPrevNonDebugInstruction(bool SkipPseudoOp = false) { - return const_cast( - static_cast(this)->getPrevNonDebugInstruction( - SkipPseudoOp)); - } - - /// Create a copy of 'this' instruction that is identical in all ways except - /// the following: - /// * The instruction has no parent - /// * The instruction has no name - /// - Instruction *clone() const; - - /// Return true if the specified instruction is exactly identical to the - /// current one. This means that all operands match and any extra information - /// (e.g. load is volatile) agree. - bool isIdenticalTo(const Instruction *I) const; - - /// This is like isIdenticalTo, except that it ignores the - /// SubclassOptionalData flags, which may specify conditions under which the - /// instruction's result is undefined. - bool isIdenticalToWhenDefined(const Instruction *I) const; - - /// When checking for operation equivalence (using isSameOperationAs) it is - /// sometimes useful to ignore certain attributes. - enum OperationEquivalenceFlags { - /// Check for equivalence ignoring load/store alignment. - CompareIgnoringAlignment = 1<<0, - /// Check for equivalence treating a type and a vector of that type - /// as equivalent. - CompareUsingScalarTypes = 1<<1 - }; - - /// This function determines if the specified instruction executes the same - /// operation as the current one. This means that the opcodes, type, operand - /// types and any other factors affecting the operation must be the same. This - /// is similar to isIdenticalTo except the operands themselves don't have to - /// be identical. - /// @returns true if the specified instruction is the same operation as - /// the current one. - /// Determine if one instruction is the same operation as another. - bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; - - /// Return true if there are any uses of this instruction in blocks other than - /// the specified block. Note that PHI nodes are considered to evaluate their - /// operands in the corresponding predecessor block. - bool isUsedOutsideOfBlock(const BasicBlock *BB) const; - - /// Return the number of successors that this instruction has. The instruction - /// must be a terminator. - unsigned getNumSuccessors() const; - - /// Return the specified successor. This instruction must be a terminator. - BasicBlock *getSuccessor(unsigned Idx) const; - - /// Update the specified successor to point at the provided block. This - /// instruction must be a terminator. - void setSuccessor(unsigned Idx, BasicBlock *BB); - - /// Replace specified successor OldBB to point at the provided block. - /// This instruction must be a terminator. - void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() >= Value::InstructionVal; - } - - //---------------------------------------------------------------------- - // Exported enumerations. - // - enum TermOps { // These terminate basic blocks -#define FIRST_TERM_INST(N) TermOpsBegin = N, -#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, -#define LAST_TERM_INST(N) TermOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum UnaryOps { -#define FIRST_UNARY_INST(N) UnaryOpsBegin = N, -#define HANDLE_UNARY_INST(N, OPC, CLASS) OPC = N, -#define LAST_UNARY_INST(N) UnaryOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum BinaryOps { -#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, -#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, -#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum MemoryOps { -#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, -#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, -#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum CastOps { -#define FIRST_CAST_INST(N) CastOpsBegin = N, -#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, -#define LAST_CAST_INST(N) CastOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum FuncletPadOps { -#define FIRST_FUNCLETPAD_INST(N) FuncletPadOpsBegin = N, -#define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N, -#define LAST_FUNCLETPAD_INST(N) FuncletPadOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - - enum OtherOps { -#define FIRST_OTHER_INST(N) OtherOpsBegin = N, -#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, -#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 -#include "llvm/IR/Instruction.def" - }; - -private: - friend class SymbolTableListTraits; - friend class BasicBlock; // For renumbering. - - // Shadow Value::setValueSubclassData with a private forwarding method so that - // subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } - - unsigned short getSubclassDataFromValue() const { - return Value::getSubclassDataFromValue(); - } - - void setParent(BasicBlock *P); - -protected: - // Instruction subclasses can stick up to 15 bits of stuff into the - // SubclassData field of instruction with these members. - - template - typename BitfieldElement::Type getSubclassData() const { - static_assert( - std::is_same::value || - !Bitfield::isOverlapping(), - "Must not overlap with the metadata bit"); - return Bitfield::get(getSubclassDataFromValue()); - } - - template - void setSubclassData(typename BitfieldElement::Type Value) { - static_assert( - std::is_same::value || - !Bitfield::isOverlapping(), - "Must not overlap with the metadata bit"); - auto Storage = getSubclassDataFromValue(); - Bitfield::set(Storage, Value); - setValueSubclassData(Storage); - } - - Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, - Instruction *InsertBefore = nullptr); - Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, - BasicBlock *InsertAtEnd); - -private: - /// Create a copy of this instruction. - Instruction *cloneImpl() const; -}; - -inline void ilist_alloc_traits::deleteNode(Instruction *V) { - V->deleteValue(); -} - -} // end namespace llvm - -#endif // LLVM_IR_INSTRUCTION_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Instructions.h b/suite/synctools/tablegen/include/llvm/IR/Instructions.h deleted file mode 100644 index 5929cff3b4..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Instructions.h +++ /dev/null @@ -1,5400 +0,0 @@ -//===- llvm/Instructions.h - Instruction subclass definitions ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file exposes the class definitions of all of the subclasses of the -// Instruction class. This is meant to be an easy way to get access to all -// instruction subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INSTRUCTIONS_H -#define LLVM_IR_INSTRUCTIONS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Bitfields.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Use.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include - -namespace llvm { - -class APInt; -class ConstantInt; -class DataLayout; - -//===----------------------------------------------------------------------===// -// AllocaInst Class -//===----------------------------------------------------------------------===// - -/// an instruction to allocate memory on the stack -class AllocaInst : public UnaryInstruction { - Type *AllocatedType; - - using AlignmentField = AlignmentBitfieldElementT<0>; - using UsedWithInAllocaField = BoolBitfieldElementT; - using SwiftErrorField = BoolBitfieldElementT; - static_assert(Bitfield::areContiguous(), - "Bitfields must be contiguous"); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - AllocaInst *cloneImpl() const; - -public: - explicit AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, - const Twine &Name, Instruction *InsertBefore); - AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, - const Twine &Name, BasicBlock *InsertAtEnd); - - AllocaInst(Type *Ty, unsigned AddrSpace, const Twine &Name, - Instruction *InsertBefore); - AllocaInst(Type *Ty, unsigned AddrSpace, - const Twine &Name, BasicBlock *InsertAtEnd); - - AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, Align Align, - const Twine &Name = "", Instruction *InsertBefore = nullptr); - AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, Align Align, - const Twine &Name, BasicBlock *InsertAtEnd); - - /// Return true if there is an allocation size parameter to the allocation - /// instruction that is not 1. - bool isArrayAllocation() const; - - /// Get the number of elements allocated. For a simple allocation of a single - /// element, this will return a constant 1 value. - const Value *getArraySize() const { return getOperand(0); } - Value *getArraySize() { return getOperand(0); } - - /// Overload to return most specific pointer type. - PointerType *getType() const { - return cast(Instruction::getType()); - } - - /// Return the address space for the allocation. - unsigned getAddressSpace() const { - return getType()->getAddressSpace(); - } - - /// Get allocation size in bits. Returns None if size can't be determined, - /// e.g. in case of a VLA. - Optional getAllocationSizeInBits(const DataLayout &DL) const; - - /// Return the type that is being allocated by the instruction. - Type *getAllocatedType() const { return AllocatedType; } - /// for use only in special circumstances that need to generically - /// transform a whole instruction (eg: IR linking and vectorization). - void setAllocatedType(Type *Ty) { AllocatedType = Ty; } - - /// Return the alignment of the memory that is being allocated by the - /// instruction. - Align getAlign() const { - return Align(1ULL << getSubclassData()); - } - - void setAlignment(Align Align) { - setSubclassData(Log2(Align)); - } - - // FIXME: Remove this one transition to Align is over. - uint64_t getAlignment() const { return getAlign().value(); } - - /// Return true if this alloca is in the entry block of the function and is a - /// constant size. If so, the code generator will fold it into the - /// prolog/epilog code, so it is basically free. - bool isStaticAlloca() const; - - /// Return true if this alloca is used as an inalloca argument to a call. Such - /// allocas are never considered static even if they are in the entry block. - bool isUsedWithInAlloca() const { - return getSubclassData(); - } - - /// Specify whether this alloca is used to represent the arguments to a call. - void setUsedWithInAlloca(bool V) { - setSubclassData(V); - } - - /// Return true if this alloca is used as a swifterror argument to a call. - bool isSwiftError() const { return getSubclassData(); } - /// Specify whether this alloca is used to represent a swifterror. - void setSwiftError(bool V) { setSubclassData(V); } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::Alloca); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } -}; - -//===----------------------------------------------------------------------===// -// LoadInst Class -//===----------------------------------------------------------------------===// - -/// An instruction for reading from memory. This uses the SubclassData field in -/// Value to store whether or not the load is volatile. -class LoadInst : public UnaryInstruction { - using VolatileField = BoolBitfieldElementT<0>; - using AlignmentField = AlignmentBitfieldElementT; - using OrderingField = AtomicOrderingBitfieldElementT; - static_assert( - Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - void AssertOK(); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - LoadInst *cloneImpl() const; - -public: - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, - Instruction *InsertBefore); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - Instruction *InsertBefore); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - BasicBlock *InsertAtEnd); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - Align Align, Instruction *InsertBefore = nullptr); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - Align Align, BasicBlock *InsertAtEnd); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - Align Align, AtomicOrdering Order, - SyncScope::ID SSID = SyncScope::System, - Instruction *InsertBefore = nullptr); - LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, - Align Align, AtomicOrdering Order, SyncScope::ID SSID, - BasicBlock *InsertAtEnd); - - /// Return true if this is a load from a volatile memory location. - bool isVolatile() const { return getSubclassData(); } - - /// Specify whether this is a volatile load or not. - void setVolatile(bool V) { setSubclassData(V); } - - /// Return the alignment of the access that is being performed. - /// FIXME: Remove this function once transition to Align is over. - /// Use getAlign() instead. - uint64_t getAlignment() const { return getAlign().value(); } - - /// Return the alignment of the access that is being performed. - Align getAlign() const { - return Align(1ULL << (getSubclassData())); - } - - void setAlignment(Align Align) { - setSubclassData(Log2(Align)); - } - - /// Returns the ordering constraint of this load instruction. - AtomicOrdering getOrdering() const { - return getSubclassData(); - } - /// Sets the ordering constraint of this load instruction. May not be Release - /// or AcquireRelease. - void setOrdering(AtomicOrdering Ordering) { - setSubclassData(Ordering); - } - - /// Returns the synchronization scope ID of this load instruction. - SyncScope::ID getSyncScopeID() const { - return SSID; - } - - /// Sets the synchronization scope ID of this load instruction. - void setSyncScopeID(SyncScope::ID SSID) { - this->SSID = SSID; - } - - /// Sets the ordering constraint and the synchronization scope ID of this load - /// instruction. - void setAtomic(AtomicOrdering Ordering, - SyncScope::ID SSID = SyncScope::System) { - setOrdering(Ordering); - setSyncScopeID(SSID); - } - - bool isSimple() const { return !isAtomic() && !isVolatile(); } - - bool isUnordered() const { - return (getOrdering() == AtomicOrdering::NotAtomic || - getOrdering() == AtomicOrdering::Unordered) && - !isVolatile(); - } - - Value *getPointerOperand() { return getOperand(0); } - const Value *getPointerOperand() const { return getOperand(0); } - static unsigned getPointerOperandIndex() { return 0U; } - Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperandType()->getPointerAddressSpace(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Load; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } - - /// The synchronization scope ID of this load instruction. Not quite enough - /// room in SubClassData for everything, so synchronization scope ID gets its - /// own field. - SyncScope::ID SSID; -}; - -//===----------------------------------------------------------------------===// -// StoreInst Class -//===----------------------------------------------------------------------===// - -/// An instruction for storing to memory. -class StoreInst : public Instruction { - using VolatileField = BoolBitfieldElementT<0>; - using AlignmentField = AlignmentBitfieldElementT; - using OrderingField = AtomicOrderingBitfieldElementT; - static_assert( - Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - void AssertOK(); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - StoreInst *cloneImpl() const; - -public: - StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); - StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, Instruction *InsertBefore); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, Align Align, - Instruction *InsertBefore = nullptr); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, Align Align, - BasicBlock *InsertAtEnd); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, Align Align, - AtomicOrdering Order, SyncScope::ID SSID = SyncScope::System, - Instruction *InsertBefore = nullptr); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, Align Align, - AtomicOrdering Order, SyncScope::ID SSID, BasicBlock *InsertAtEnd); - - // allocate space for exactly two operands - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Return true if this is a store to a volatile memory location. - bool isVolatile() const { return getSubclassData(); } - - /// Specify whether this is a volatile store or not. - void setVolatile(bool V) { setSubclassData(V); } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Return the alignment of the access that is being performed - /// FIXME: Remove this function once transition to Align is over. - /// Use getAlign() instead. - uint64_t getAlignment() const { return getAlign().value(); } - - Align getAlign() const { - return Align(1ULL << (getSubclassData())); - } - - void setAlignment(Align Align) { - setSubclassData(Log2(Align)); - } - - /// Returns the ordering constraint of this store instruction. - AtomicOrdering getOrdering() const { - return getSubclassData(); - } - - /// Sets the ordering constraint of this store instruction. May not be - /// Acquire or AcquireRelease. - void setOrdering(AtomicOrdering Ordering) { - setSubclassData(Ordering); - } - - /// Returns the synchronization scope ID of this store instruction. - SyncScope::ID getSyncScopeID() const { - return SSID; - } - - /// Sets the synchronization scope ID of this store instruction. - void setSyncScopeID(SyncScope::ID SSID) { - this->SSID = SSID; - } - - /// Sets the ordering constraint and the synchronization scope ID of this - /// store instruction. - void setAtomic(AtomicOrdering Ordering, - SyncScope::ID SSID = SyncScope::System) { - setOrdering(Ordering); - setSyncScopeID(SSID); - } - - bool isSimple() const { return !isAtomic() && !isVolatile(); } - - bool isUnordered() const { - return (getOrdering() == AtomicOrdering::NotAtomic || - getOrdering() == AtomicOrdering::Unordered) && - !isVolatile(); - } - - Value *getValueOperand() { return getOperand(0); } - const Value *getValueOperand() const { return getOperand(0); } - - Value *getPointerOperand() { return getOperand(1); } - const Value *getPointerOperand() const { return getOperand(1); } - static unsigned getPointerOperandIndex() { return 1U; } - Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperandType()->getPointerAddressSpace(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Store; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } - - /// The synchronization scope ID of this store instruction. Not quite enough - /// room in SubClassData for everything, so synchronization scope ID gets its - /// own field. - SyncScope::ID SSID; -}; - -template <> -struct OperandTraits : public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) - -//===----------------------------------------------------------------------===// -// FenceInst Class -//===----------------------------------------------------------------------===// - -/// An instruction for ordering other memory operations. -class FenceInst : public Instruction { - using OrderingField = AtomicOrderingBitfieldElementT<0>; - - void Init(AtomicOrdering Ordering, SyncScope::ID SSID); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - FenceInst *cloneImpl() const; - -public: - // Ordering may only be Acquire, Release, AcquireRelease, or - // SequentiallyConsistent. - FenceInst(LLVMContext &C, AtomicOrdering Ordering, - SyncScope::ID SSID = SyncScope::System, - Instruction *InsertBefore = nullptr); - FenceInst(LLVMContext &C, AtomicOrdering Ordering, SyncScope::ID SSID, - BasicBlock *InsertAtEnd); - - // allocate space for exactly zero operands - void *operator new(size_t S) { return User::operator new(S, 0); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Returns the ordering constraint of this fence instruction. - AtomicOrdering getOrdering() const { - return getSubclassData(); - } - - /// Sets the ordering constraint of this fence instruction. May only be - /// Acquire, Release, AcquireRelease, or SequentiallyConsistent. - void setOrdering(AtomicOrdering Ordering) { - setSubclassData(Ordering); - } - - /// Returns the synchronization scope ID of this fence instruction. - SyncScope::ID getSyncScopeID() const { - return SSID; - } - - /// Sets the synchronization scope ID of this fence instruction. - void setSyncScopeID(SyncScope::ID SSID) { - this->SSID = SSID; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Fence; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } - - /// The synchronization scope ID of this fence instruction. Not quite enough - /// room in SubClassData for everything, so synchronization scope ID gets its - /// own field. - SyncScope::ID SSID; -}; - -//===----------------------------------------------------------------------===// -// AtomicCmpXchgInst Class -//===----------------------------------------------------------------------===// - -/// An instruction that atomically checks whether a -/// specified value is in a memory location, and, if it is, stores a new value -/// there. The value returned by this instruction is a pair containing the -/// original value as first element, and an i1 indicating success (true) or -/// failure (false) as second element. -/// -class AtomicCmpXchgInst : public Instruction { - void Init(Value *Ptr, Value *Cmp, Value *NewVal, Align Align, - AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, - SyncScope::ID SSID); - - template - using AtomicOrderingBitfieldElement = - typename Bitfield::Element; - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - AtomicCmpXchgInst *cloneImpl() const; - -public: - AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, Align Alignment, - AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, SyncScope::ID SSID, - Instruction *InsertBefore = nullptr); - AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, Align Alignment, - AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, SyncScope::ID SSID, - BasicBlock *InsertAtEnd); - - // allocate space for exactly three operands - void *operator new(size_t S) { return User::operator new(S, 3); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - using VolatileField = BoolBitfieldElementT<0>; - using WeakField = BoolBitfieldElementT; - using SuccessOrderingField = - AtomicOrderingBitfieldElementT; - using FailureOrderingField = - AtomicOrderingBitfieldElementT; - using AlignmentField = - AlignmentBitfieldElementT; - static_assert( - Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - /// Return the alignment of the memory that is being allocated by the - /// instruction. - Align getAlign() const { - return Align(1ULL << getSubclassData()); - } - - void setAlignment(Align Align) { - setSubclassData(Log2(Align)); - } - - /// Return true if this is a cmpxchg from a volatile memory - /// location. - /// - bool isVolatile() const { return getSubclassData(); } - - /// Specify whether this is a volatile cmpxchg. - /// - void setVolatile(bool V) { setSubclassData(V); } - - /// Return true if this cmpxchg may spuriously fail. - bool isWeak() const { return getSubclassData(); } - - void setWeak(bool IsWeak) { setSubclassData(IsWeak); } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - static bool isValidSuccessOrdering(AtomicOrdering Ordering) { - return Ordering != AtomicOrdering::NotAtomic && - Ordering != AtomicOrdering::Unordered; - } - - static bool isValidFailureOrdering(AtomicOrdering Ordering) { - return Ordering != AtomicOrdering::NotAtomic && - Ordering != AtomicOrdering::Unordered && - Ordering != AtomicOrdering::AcquireRelease && - Ordering != AtomicOrdering::Release; - } - - /// Returns the success ordering constraint of this cmpxchg instruction. - AtomicOrdering getSuccessOrdering() const { - return getSubclassData(); - } - - /// Sets the success ordering constraint of this cmpxchg instruction. - void setSuccessOrdering(AtomicOrdering Ordering) { - assert(isValidSuccessOrdering(Ordering) && - "invalid CmpXchg success ordering"); - setSubclassData(Ordering); - } - - /// Returns the failure ordering constraint of this cmpxchg instruction. - AtomicOrdering getFailureOrdering() const { - return getSubclassData(); - } - - /// Sets the failure ordering constraint of this cmpxchg instruction. - void setFailureOrdering(AtomicOrdering Ordering) { - assert(isValidFailureOrdering(Ordering) && - "invalid CmpXchg failure ordering"); - setSubclassData(Ordering); - } - - /// Returns a single ordering which is at least as strong as both the - /// success and failure orderings for this cmpxchg. - AtomicOrdering getMergedOrdering() const { - if (getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) - return AtomicOrdering::SequentiallyConsistent; - if (getFailureOrdering() == AtomicOrdering::Acquire) { - if (getSuccessOrdering() == AtomicOrdering::Monotonic) - return AtomicOrdering::Acquire; - if (getSuccessOrdering() == AtomicOrdering::Release) - return AtomicOrdering::AcquireRelease; - } - return getSuccessOrdering(); - } - - /// Returns the synchronization scope ID of this cmpxchg instruction. - SyncScope::ID getSyncScopeID() const { - return SSID; - } - - /// Sets the synchronization scope ID of this cmpxchg instruction. - void setSyncScopeID(SyncScope::ID SSID) { - this->SSID = SSID; - } - - Value *getPointerOperand() { return getOperand(0); } - const Value *getPointerOperand() const { return getOperand(0); } - static unsigned getPointerOperandIndex() { return 0U; } - - Value *getCompareOperand() { return getOperand(1); } - const Value *getCompareOperand() const { return getOperand(1); } - - Value *getNewValOperand() { return getOperand(2); } - const Value *getNewValOperand() const { return getOperand(2); } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperand()->getType()->getPointerAddressSpace(); - } - - /// Returns the strongest permitted ordering on failure, given the - /// desired ordering on success. - /// - /// If the comparison in a cmpxchg operation fails, there is no atomic store - /// so release semantics cannot be provided. So this function drops explicit - /// Release requests from the AtomicOrdering. A SequentiallyConsistent - /// operation would remain SequentiallyConsistent. - static AtomicOrdering - getStrongestFailureOrdering(AtomicOrdering SuccessOrdering) { - switch (SuccessOrdering) { - default: - llvm_unreachable("invalid cmpxchg success ordering"); - case AtomicOrdering::Release: - case AtomicOrdering::Monotonic: - return AtomicOrdering::Monotonic; - case AtomicOrdering::AcquireRelease: - case AtomicOrdering::Acquire: - return AtomicOrdering::Acquire; - case AtomicOrdering::SequentiallyConsistent: - return AtomicOrdering::SequentiallyConsistent; - } - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::AtomicCmpXchg; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } - - /// The synchronization scope ID of this cmpxchg instruction. Not quite - /// enough room in SubClassData for everything, so synchronization scope ID - /// gets its own field. - SyncScope::ID SSID; -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) - -//===----------------------------------------------------------------------===// -// AtomicRMWInst Class -//===----------------------------------------------------------------------===// - -/// an instruction that atomically reads a memory location, -/// combines it with another value, and then stores the result back. Returns -/// the old value. -/// -class AtomicRMWInst : public Instruction { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - AtomicRMWInst *cloneImpl() const; - -public: - /// This enumeration lists the possible modifications atomicrmw can make. In - /// the descriptions, 'p' is the pointer to the instruction's memory location, - /// 'old' is the initial value of *p, and 'v' is the other value passed to the - /// instruction. These instructions always return 'old'. - enum BinOp : unsigned { - /// *p = v - Xchg, - /// *p = old + v - Add, - /// *p = old - v - Sub, - /// *p = old & v - And, - /// *p = ~(old & v) - Nand, - /// *p = old | v - Or, - /// *p = old ^ v - Xor, - /// *p = old >signed v ? old : v - Max, - /// *p = old unsigned v ? old : v - UMax, - /// *p = old - using AtomicOrderingBitfieldElement = - typename Bitfield::Element; - - template - using BinOpBitfieldElement = - typename Bitfield::Element; - -public: - AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, Align Alignment, - AtomicOrdering Ordering, SyncScope::ID SSID, - Instruction *InsertBefore = nullptr); - AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, Align Alignment, - AtomicOrdering Ordering, SyncScope::ID SSID, - BasicBlock *InsertAtEnd); - - // allocate space for exactly two operands - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - using VolatileField = BoolBitfieldElementT<0>; - using AtomicOrderingField = - AtomicOrderingBitfieldElementT; - using OperationField = BinOpBitfieldElement; - using AlignmentField = AlignmentBitfieldElementT; - static_assert(Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - BinOp getOperation() const { return getSubclassData(); } - - static StringRef getOperationName(BinOp Op); - - static bool isFPOperation(BinOp Op) { - switch (Op) { - case AtomicRMWInst::FAdd: - case AtomicRMWInst::FSub: - return true; - default: - return false; - } - } - - void setOperation(BinOp Operation) { - setSubclassData(Operation); - } - - /// Return the alignment of the memory that is being allocated by the - /// instruction. - Align getAlign() const { - return Align(1ULL << getSubclassData()); - } - - void setAlignment(Align Align) { - setSubclassData(Log2(Align)); - } - - /// Return true if this is a RMW on a volatile memory location. - /// - bool isVolatile() const { return getSubclassData(); } - - /// Specify whether this is a volatile RMW or not. - /// - void setVolatile(bool V) { setSubclassData(V); } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Returns the ordering constraint of this rmw instruction. - AtomicOrdering getOrdering() const { - return getSubclassData(); - } - - /// Sets the ordering constraint of this rmw instruction. - void setOrdering(AtomicOrdering Ordering) { - assert(Ordering != AtomicOrdering::NotAtomic && - "atomicrmw instructions can only be atomic."); - setSubclassData(Ordering); - } - - /// Returns the synchronization scope ID of this rmw instruction. - SyncScope::ID getSyncScopeID() const { - return SSID; - } - - /// Sets the synchronization scope ID of this rmw instruction. - void setSyncScopeID(SyncScope::ID SSID) { - this->SSID = SSID; - } - - Value *getPointerOperand() { return getOperand(0); } - const Value *getPointerOperand() const { return getOperand(0); } - static unsigned getPointerOperandIndex() { return 0U; } - - Value *getValOperand() { return getOperand(1); } - const Value *getValOperand() const { return getOperand(1); } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperand()->getType()->getPointerAddressSpace(); - } - - bool isFloatingPointOperation() const { - return isFPOperation(getOperation()); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::AtomicRMW; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - void Init(BinOp Operation, Value *Ptr, Value *Val, Align Align, - AtomicOrdering Ordering, SyncScope::ID SSID); - - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } - - /// The synchronization scope ID of this rmw instruction. Not quite enough - /// room in SubClassData for everything, so synchronization scope ID gets its - /// own field. - SyncScope::ID SSID; -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicRMWInst, Value) - -//===----------------------------------------------------------------------===// -// GetElementPtrInst Class -//===----------------------------------------------------------------------===// - -// checkGEPType - Simple wrapper function to give a better assertion failure -// message on bad indexes for a gep instruction. -// -inline Type *checkGEPType(Type *Ty) { - assert(Ty && "Invalid GetElementPtrInst indices for type!"); - return Ty; -} - -/// an instruction for type-safe pointer arithmetic to -/// access elements of arrays and structs -/// -class GetElementPtrInst : public Instruction { - Type *SourceElementType; - Type *ResultElementType; - - GetElementPtrInst(const GetElementPtrInst &GEPI); - - /// Constructors - Create a getelementptr instruction with a base pointer an - /// list of indices. The first ctor can optionally insert before an existing - /// instruction, the second appends the new instruction to the specified - /// BasicBlock. - inline GetElementPtrInst(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore); - inline GetElementPtrInst(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, unsigned Values, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(Value *Ptr, ArrayRef IdxList, const Twine &NameStr); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - GetElementPtrInst *cloneImpl() const; - -public: - static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - unsigned Values = 1 + unsigned(IdxList.size()); - assert(PointeeType && "Must specify element type"); - assert(cast(Ptr->getType()->getScalarType()) - ->isOpaqueOrPointeeTypeMatches(PointeeType)); - return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, - NameStr, InsertBefore); - } - - static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - unsigned Values = 1 + unsigned(IdxList.size()); - assert(PointeeType && "Must specify element type"); - assert(cast(Ptr->getType()->getScalarType()) - ->isOpaqueOrPointeeTypeMatches(PointeeType)); - return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, - NameStr, InsertAtEnd); - } - - /// Create an "inbounds" getelementptr. See the documentation for the - /// "inbounds" flag in LangRef.html for details. - static GetElementPtrInst * - CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef IdxList, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - GetElementPtrInst *GEP = - Create(PointeeType, Ptr, IdxList, NameStr, InsertBefore); - GEP->setIsInBounds(true); - return GEP; - } - - static GetElementPtrInst *CreateInBounds(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = - Create(PointeeType, Ptr, IdxList, NameStr, InsertAtEnd); - GEP->setIsInBounds(true); - return GEP; - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - Type *getSourceElementType() const { return SourceElementType; } - - void setSourceElementType(Type *Ty) { SourceElementType = Ty; } - void setResultElementType(Type *Ty) { ResultElementType = Ty; } - - Type *getResultElementType() const { - assert(cast(getType()->getScalarType()) - ->isOpaqueOrPointeeTypeMatches(ResultElementType)); - return ResultElementType; - } - - /// Returns the address space of this instruction's pointer type. - unsigned getAddressSpace() const { - // Note that this is always the same as the pointer operand's address space - // and that is cheaper to compute, so cheat here. - return getPointerAddressSpace(); - } - - /// Returns the result type of a getelementptr with the given source - /// element type and indexes. - /// - /// Null is returned if the indices are invalid for the specified - /// source element type. - static Type *getIndexedType(Type *Ty, ArrayRef IdxList); - static Type *getIndexedType(Type *Ty, ArrayRef IdxList); - static Type *getIndexedType(Type *Ty, ArrayRef IdxList); - - /// Return the type of the element at the given index of an indexable - /// type. This is equivalent to "getIndexedType(Agg, {Zero, Idx})". - /// - /// Returns null if the type can't be indexed, or the given index is not - /// legal for the given type. - static Type *getTypeAtIndex(Type *Ty, Value *Idx); - static Type *getTypeAtIndex(Type *Ty, uint64_t Idx); - - inline op_iterator idx_begin() { return op_begin()+1; } - inline const_op_iterator idx_begin() const { return op_begin()+1; } - inline op_iterator idx_end() { return op_end(); } - inline const_op_iterator idx_end() const { return op_end(); } - - inline iterator_range indices() { - return make_range(idx_begin(), idx_end()); - } - - inline iterator_range indices() const { - return make_range(idx_begin(), idx_end()); - } - - Value *getPointerOperand() { - return getOperand(0); - } - const Value *getPointerOperand() const { - return getOperand(0); - } - static unsigned getPointerOperandIndex() { - return 0U; // get index for modifying correct operand. - } - - /// Method to return the pointer operand as a - /// PointerType. - Type *getPointerOperandType() const { - return getPointerOperand()->getType(); - } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperandType()->getPointerAddressSpace(); - } - - /// Returns the pointer type returned by the GEP - /// instruction, which may be a vector of pointers. - static Type *getGEPReturnType(Type *ElTy, Value *Ptr, - ArrayRef IdxList) { - PointerType *OrigPtrTy = cast(Ptr->getType()->getScalarType()); - unsigned AddrSpace = OrigPtrTy->getAddressSpace(); - Type *ResultElemTy = checkGEPType(getIndexedType(ElTy, IdxList)); - Type *PtrTy = OrigPtrTy->isOpaque() - ? PointerType::get(OrigPtrTy->getContext(), AddrSpace) - : PointerType::get(ResultElemTy, AddrSpace); - // Vector GEP - if (auto *PtrVTy = dyn_cast(Ptr->getType())) { - ElementCount EltCount = PtrVTy->getElementCount(); - return VectorType::get(PtrTy, EltCount); - } - for (Value *Index : IdxList) - if (auto *IndexVTy = dyn_cast(Index->getType())) { - ElementCount EltCount = IndexVTy->getElementCount(); - return VectorType::get(PtrTy, EltCount); - } - // Scalar GEP - return PtrTy; - } - - unsigned getNumIndices() const { // Note: always non-negative - return getNumOperands() - 1; - } - - bool hasIndices() const { - return getNumOperands() > 1; - } - - /// Return true if all of the indices of this GEP are - /// zeros. If so, the result pointer and the first operand have the same - /// value, just potentially different types. - bool hasAllZeroIndices() const; - - /// Return true if all of the indices of this GEP are - /// constant integers. If so, the result pointer and the first operand have - /// a constant offset between them. - bool hasAllConstantIndices() const; - - /// Set or clear the inbounds flag on this GEP instruction. - /// See LangRef.html for the meaning of inbounds on a getelementptr. - void setIsInBounds(bool b = true); - - /// Determine whether the GEP has the inbounds flag. - bool isInBounds() const; - - /// Accumulate the constant address offset of this GEP if possible. - /// - /// This routine accepts an APInt into which it will accumulate the constant - /// offset of this GEP if the GEP is in fact constant. If the GEP is not - /// all-constant, it returns false and the value of the offset APInt is - /// undefined (it is *not* preserved!). The APInt passed into this routine - /// must be at least as wide as the IntPtr type for the address space of - /// the base GEP pointer. - bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; - bool collectOffset(const DataLayout &DL, unsigned BitWidth, - MapVector &VariableOffsets, - APInt &ConstantOffset) const; - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::GetElementPtr); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public VariadicOperandTraits { -}; - -GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, unsigned Values, - const Twine &NameStr, - Instruction *InsertBefore) - : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, - OperandTraits::op_end(this) - Values, - Values, InsertBefore), - SourceElementType(PointeeType), - ResultElementType(getIndexedType(PointeeType, IdxList)) { - assert(cast(getType()->getScalarType()) - ->isOpaqueOrPointeeTypeMatches(ResultElementType)); - init(Ptr, IdxList, NameStr); -} - -GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, - ArrayRef IdxList, unsigned Values, - const Twine &NameStr, - BasicBlock *InsertAtEnd) - : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd), - SourceElementType(PointeeType), - ResultElementType(getIndexedType(PointeeType, IdxList)) { - assert(cast(getType()->getScalarType()) - ->isOpaqueOrPointeeTypeMatches(ResultElementType)); - init(Ptr, IdxList, NameStr); -} - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) - -//===----------------------------------------------------------------------===// -// ICmpInst Class -//===----------------------------------------------------------------------===// - -/// This instruction compares its operands according to the predicate given -/// to the constructor. It only operates on integers or pointers. The operands -/// must be identical types. -/// Represent an integer comparison operator. -class ICmpInst: public CmpInst { - void AssertOK() { - assert(isIntPredicate() && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->isPtrOrPtrVectorTy()) && - "Invalid operand types for ICmp instruction"); - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical ICmpInst - ICmpInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics. - ICmpInst( - Instruction *InsertBefore, ///< Where to insert - Predicate pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "" ///< Name of the instruction - ) : CmpInst(makeCmpResultType(LHS->getType()), - Instruction::ICmp, pred, LHS, RHS, NameStr, - InsertBefore) { -#ifndef NDEBUG - AssertOK(); -#endif - } - - /// Constructor with insert-at-end semantics. - ICmpInst( - BasicBlock &InsertAtEnd, ///< Block to insert into. - Predicate pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "" ///< Name of the instruction - ) : CmpInst(makeCmpResultType(LHS->getType()), - Instruction::ICmp, pred, LHS, RHS, NameStr, - &InsertAtEnd) { -#ifndef NDEBUG - AssertOK(); -#endif - } - - /// Constructor with no-insertion semantics - ICmpInst( - Predicate pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "" ///< Name of the instruction - ) : CmpInst(makeCmpResultType(LHS->getType()), - Instruction::ICmp, pred, LHS, RHS, NameStr) { -#ifndef NDEBUG - AssertOK(); -#endif - } - - /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. - /// @returns the predicate that would be the result if the operand were - /// regarded as signed. - /// Return the signed version of the predicate - Predicate getSignedPredicate() const { - return getSignedPredicate(getPredicate()); - } - - /// This is a static version that you can use without an instruction. - /// Return the signed version of the predicate. - static Predicate getSignedPredicate(Predicate pred); - - /// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc. - /// @returns the predicate that would be the result if the operand were - /// regarded as unsigned. - /// Return the unsigned version of the predicate - Predicate getUnsignedPredicate() const { - return getUnsignedPredicate(getPredicate()); - } - - /// This is a static version that you can use without an instruction. - /// Return the unsigned version of the predicate. - static Predicate getUnsignedPredicate(Predicate pred); - - /// Return true if this predicate is either EQ or NE. This also - /// tests for commutativity. - static bool isEquality(Predicate P) { - return P == ICMP_EQ || P == ICMP_NE; - } - - /// Return true if this predicate is either EQ or NE. This also - /// tests for commutativity. - bool isEquality() const { - return isEquality(getPredicate()); - } - - /// @returns true if the predicate of this ICmpInst is commutative - /// Determine if this relation is commutative. - bool isCommutative() const { return isEquality(); } - - /// Return true if the predicate is relational (not EQ or NE). - /// - bool isRelational() const { - return !isEquality(); - } - - /// Return true if the predicate is relational (not EQ or NE). - /// - static bool isRelational(Predicate P) { - return !isEquality(P); - } - - /// Return true if the predicate is SGT or UGT. - /// - static bool isGT(Predicate P) { - return P == ICMP_SGT || P == ICMP_UGT; - } - - /// Return true if the predicate is SLT or ULT. - /// - static bool isLT(Predicate P) { - return P == ICMP_SLT || P == ICMP_ULT; - } - - /// Return true if the predicate is SGE or UGE. - /// - static bool isGE(Predicate P) { - return P == ICMP_SGE || P == ICMP_UGE; - } - - /// Return true if the predicate is SLE or ULE. - /// - static bool isLE(Predicate P) { - return P == ICMP_SLE || P == ICMP_ULE; - } - - /// Returns the sequence of all ICmp predicates. - /// - static auto predicates() { return ICmpPredicates(); } - - /// Exchange the two operands to this instruction in such a way that it does - /// not modify the semantics of the instruction. The predicate value may be - /// changed to retain the same result if the predicate is order dependent - /// (e.g. ult). - /// Swap operands and adjust predicate. - void swapOperands() { - setPredicate(getSwappedPredicate()); - Op<0>().swap(Op<1>()); - } - - /// Return result of `LHS Pred RHS` comparison. - static bool compare(const APInt &LHS, const APInt &RHS, - ICmpInst::Predicate Pred); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::ICmp; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// FCmpInst Class -//===----------------------------------------------------------------------===// - -/// This instruction compares its operands according to the predicate given -/// to the constructor. It only operates on floating point values or packed -/// vectors of floating point values. The operands must be identical types. -/// Represents a floating point comparison operator. -class FCmpInst: public CmpInst { - void AssertOK() { - assert(isFPPredicate() && "Invalid FCmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to FCmp instruction are not of the same type!"); - // Check that the operands are the right type - assert(getOperand(0)->getType()->isFPOrFPVectorTy() && - "Invalid operand types for FCmp instruction"); - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FCmpInst - FCmpInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics. - FCmpInst( - Instruction *InsertBefore, ///< Where to insert - Predicate pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "" ///< Name of the instruction - ) : CmpInst(makeCmpResultType(LHS->getType()), - Instruction::FCmp, pred, LHS, RHS, NameStr, - InsertBefore) { - AssertOK(); - } - - /// Constructor with insert-at-end semantics. - FCmpInst( - BasicBlock &InsertAtEnd, ///< Block to insert into. - Predicate pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "" ///< Name of the instruction - ) : CmpInst(makeCmpResultType(LHS->getType()), - Instruction::FCmp, pred, LHS, RHS, NameStr, - &InsertAtEnd) { - AssertOK(); - } - - /// Constructor with no-insertion semantics - FCmpInst( - Predicate Pred, ///< The predicate to use for the comparison - Value *LHS, ///< The left-hand-side of the expression - Value *RHS, ///< The right-hand-side of the expression - const Twine &NameStr = "", ///< Name of the instruction - Instruction *FlagsSource = nullptr - ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::FCmp, Pred, LHS, - RHS, NameStr, nullptr, FlagsSource) { - AssertOK(); - } - - /// @returns true if the predicate of this instruction is EQ or NE. - /// Determine if this is an equality predicate. - static bool isEquality(Predicate Pred) { - return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ || - Pred == FCMP_UNE; - } - - /// @returns true if the predicate of this instruction is EQ or NE. - /// Determine if this is an equality predicate. - bool isEquality() const { return isEquality(getPredicate()); } - - /// @returns true if the predicate of this instruction is commutative. - /// Determine if this is a commutative predicate. - bool isCommutative() const { - return isEquality() || - getPredicate() == FCMP_FALSE || - getPredicate() == FCMP_TRUE || - getPredicate() == FCMP_ORD || - getPredicate() == FCMP_UNO; - } - - /// @returns true if the predicate is relational (not EQ or NE). - /// Determine if this a relational predicate. - bool isRelational() const { return !isEquality(); } - - /// Exchange the two operands to this instruction in such a way that it does - /// not modify the semantics of the instruction. The predicate value may be - /// changed to retain the same result if the predicate is order dependent - /// (e.g. ult). - /// Swap operands and adjust predicate. - void swapOperands() { - setPredicate(getSwappedPredicate()); - Op<0>().swap(Op<1>()); - } - - /// Returns the sequence of all FCmp predicates. - /// - static auto predicates() { return FCmpPredicates(); } - - /// Return result of `LHS Pred RHS` comparison. - static bool compare(const APFloat &LHS, const APFloat &RHS, - FCmpInst::Predicate Pred); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::FCmp; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -/// This class represents a function call, abstracting a target -/// machine's calling convention. This class uses low bit of the SubClassData -/// field to indicate whether or not this is a tail call. The rest of the bits -/// hold the calling convention of the call. -/// -class CallInst : public CallBase { - CallInst(const CallInst &CI); - - /// Construct a CallInst given a range of arguments. - /// Construct a CallInst from a range of arguments - inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - Instruction *InsertBefore); - - inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, Instruction *InsertBefore) - : CallInst(Ty, Func, Args, None, NameStr, InsertBefore) {} - - /// Construct a CallInst given a range of arguments. - /// Construct a CallInst from a range of arguments - inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - explicit CallInst(FunctionType *Ty, Value *F, const Twine &NameStr, - Instruction *InsertBefore); - - CallInst(FunctionType *ty, Value *F, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - void init(FunctionType *FTy, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr); - void init(FunctionType *FTy, Value *Func, const Twine &NameStr); - - /// Compute the number of operands to allocate. - static int ComputeNumOperands(int NumArgs, int NumBundleInputs = 0) { - // We need one operand for the called function, plus the input operand - // counts provided. - return 1 + NumArgs + NumBundleInputs; - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CallInst *cloneImpl() const; - -public: - static CallInst *Create(FunctionType *Ty, Value *F, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new (ComputeNumOperands(0)) CallInst(Ty, F, NameStr, InsertBefore); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return new (ComputeNumOperands(Args.size())) - CallInst(Ty, Func, Args, None, NameStr, InsertBefore); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - const int NumOperands = - ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)); - const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore); - } - - static CallInst *Create(FunctionType *Ty, Value *F, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new (ComputeNumOperands(0)) CallInst(Ty, F, NameStr, InsertAtEnd); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new (ComputeNumOperands(Args.size())) - CallInst(Ty, Func, Args, None, NameStr, InsertAtEnd); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - const int NumOperands = - ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)); - const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - CallInst(Ty, Func, Args, Bundles, NameStr, InsertAtEnd); - } - - static CallInst *Create(FunctionCallee Func, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), NameStr, - InsertBefore); - } - - static CallInst *Create(FunctionCallee Func, ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), Args, Bundles, - NameStr, InsertBefore); - } - - static CallInst *Create(FunctionCallee Func, ArrayRef Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), Args, NameStr, - InsertBefore); - } - - static CallInst *Create(FunctionCallee Func, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), NameStr, - InsertAtEnd); - } - - static CallInst *Create(FunctionCallee Func, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), Args, NameStr, - InsertAtEnd); - } - - static CallInst *Create(FunctionCallee Func, ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), Args, Bundles, - NameStr, InsertAtEnd); - } - - /// Create a clone of \p CI with a different set of operand bundles and - /// insert it before \p InsertPt. - /// - /// The returned call instruction is identical \p CI in every way except that - /// the operand bundles for the new instruction are set to the operand bundles - /// in \p Bundles. - static CallInst *Create(CallInst *CI, ArrayRef Bundles, - Instruction *InsertPt = nullptr); - - /// Generate the IR for a call to malloc: - /// 1. Compute the malloc call's argument as the specified type's size, - /// possibly multiplied by the array size if the array size is not - /// constant 1. - /// 2. Call malloc with that argument. - /// 3. Bitcast the result of the malloc call to the specified type. - static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, - Type *AllocTy, Value *AllocSize, - Value *ArraySize = nullptr, - Function *MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, - Type *AllocTy, Value *AllocSize, - Value *ArraySize = nullptr, - Function *MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, - Type *AllocTy, Value *AllocSize, - Value *ArraySize = nullptr, - ArrayRef Bundles = None, - Function *MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, - Type *AllocTy, Value *AllocSize, - Value *ArraySize = nullptr, - ArrayRef Bundles = None, - Function *MallocF = nullptr, - const Twine &Name = ""); - /// Generate the IR for a call to the builtin free function. - static Instruction *CreateFree(Value *Source, Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, BasicBlock *InsertAtEnd); - static Instruction *CreateFree(Value *Source, - ArrayRef Bundles, - Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, - ArrayRef Bundles, - BasicBlock *InsertAtEnd); - - // Note that 'musttail' implies 'tail'. - enum TailCallKind : unsigned { - TCK_None = 0, - TCK_Tail = 1, - TCK_MustTail = 2, - TCK_NoTail = 3, - TCK_LAST = TCK_NoTail - }; - - using TailCallKindField = Bitfield::Element; - static_assert( - Bitfield::areContiguous(), - "Bitfields must be contiguous"); - - TailCallKind getTailCallKind() const { - return getSubclassData(); - } - - bool isTailCall() const { - TailCallKind Kind = getTailCallKind(); - return Kind == TCK_Tail || Kind == TCK_MustTail; - } - - bool isMustTailCall() const { return getTailCallKind() == TCK_MustTail; } - - bool isNoTailCall() const { return getTailCallKind() == TCK_NoTail; } - - void setTailCallKind(TailCallKind TCK) { - setSubclassData(TCK); - } - - void setTailCall(bool IsTc = true) { - setTailCallKind(IsTc ? TCK_Tail : TCK_None); - } - - /// Return true if the call can return twice - bool canReturnTwice() const { return hasFnAttr(Attribute::ReturnsTwice); } - void setCanReturnTwice() { addFnAttr(Attribute::ReturnsTwice); } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Call; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - /// Updates profile metadata by scaling it by \p S / \p T. - void updateProfWeight(uint64_t S, uint64_t T); - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } -}; - -CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : CallBase(Ty->getReturnType(), Instruction::Call, - OperandTraits::op_end(this) - - (Args.size() + CountBundleInputs(Bundles) + 1), - unsigned(Args.size() + CountBundleInputs(Bundles) + 1), - InsertAtEnd) { - init(Ty, Func, Args, Bundles, NameStr); -} - -CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - Instruction *InsertBefore) - : CallBase(Ty->getReturnType(), Instruction::Call, - OperandTraits::op_end(this) - - (Args.size() + CountBundleInputs(Bundles) + 1), - unsigned(Args.size() + CountBundleInputs(Bundles) + 1), - InsertBefore) { - init(Ty, Func, Args, Bundles, NameStr); -} - -//===----------------------------------------------------------------------===// -// SelectInst Class -//===----------------------------------------------------------------------===// - -/// This class represents the LLVM 'select' instruction. -/// -class SelectInst : public Instruction { - SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, - Instruction *InsertBefore) - : Instruction(S1->getType(), Instruction::Select, - &Op<0>(), 3, InsertBefore) { - init(C, S1, S2); - setName(NameStr); - } - - SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : Instruction(S1->getType(), Instruction::Select, - &Op<0>(), 3, InsertAtEnd) { - init(C, S1, S2); - setName(NameStr); - } - - void init(Value *C, Value *S1, Value *S2) { - assert(!areInvalidOperands(C, S1, S2) && "Invalid operands for select"); - Op<0>() = C; - Op<1>() = S1; - Op<2>() = S2; - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - SelectInst *cloneImpl() const; - -public: - static SelectInst *Create(Value *C, Value *S1, Value *S2, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr, - Instruction *MDFrom = nullptr) { - SelectInst *Sel = new(3) SelectInst(C, S1, S2, NameStr, InsertBefore); - if (MDFrom) - Sel->copyMetadata(*MDFrom); - return Sel; - } - - static SelectInst *Create(Value *C, Value *S1, Value *S2, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(3) SelectInst(C, S1, S2, NameStr, InsertAtEnd); - } - - const Value *getCondition() const { return Op<0>(); } - const Value *getTrueValue() const { return Op<1>(); } - const Value *getFalseValue() const { return Op<2>(); } - Value *getCondition() { return Op<0>(); } - Value *getTrueValue() { return Op<1>(); } - Value *getFalseValue() { return Op<2>(); } - - void setCondition(Value *V) { Op<0>() = V; } - void setTrueValue(Value *V) { Op<1>() = V; } - void setFalseValue(Value *V) { Op<2>() = V; } - - /// Swap the true and false values of the select instruction. - /// This doesn't swap prof metadata. - void swapValues() { Op<1>().swap(Op<2>()); } - - /// Return a string if the specified operands are invalid - /// for a select operation, otherwise return null. - static const char *areInvalidOperands(Value *Cond, Value *True, Value *False); - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - OtherOps getOpcode() const { - return static_cast(Instruction::getOpcode()); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Select; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) - -//===----------------------------------------------------------------------===// -// VAArgInst Class -//===----------------------------------------------------------------------===// - -/// This class represents the va_arg llvm instruction, which returns -/// an argument of the specified type given a va_list and increments that list -/// -class VAArgInst : public UnaryInstruction { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - VAArgInst *cloneImpl() const; - -public: - VAArgInst(Value *List, Type *Ty, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) - : UnaryInstruction(Ty, VAArg, List, InsertBefore) { - setName(NameStr); - } - - VAArgInst(Value *List, Type *Ty, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { - setName(NameStr); - } - - Value *getPointerOperand() { return getOperand(0); } - const Value *getPointerOperand() const { return getOperand(0); } - static unsigned getPointerOperandIndex() { return 0U; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == VAArg; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// ExtractElementInst Class -//===----------------------------------------------------------------------===// - -/// This instruction extracts a single (scalar) -/// element from a VectorType value -/// -class ExtractElementInst : public Instruction { - ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, - BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - ExtractElementInst *cloneImpl() const; - -public: - static ExtractElementInst *Create(Value *Vec, Value *Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertBefore); - } - - static ExtractElementInst *Create(Value *Vec, Value *Idx, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertAtEnd); - } - - /// Return true if an extractelement instruction can be - /// formed with the specified operands. - static bool isValidOperands(const Value *Vec, const Value *Idx); - - Value *getVectorOperand() { return Op<0>(); } - Value *getIndexOperand() { return Op<1>(); } - const Value *getVectorOperand() const { return Op<0>(); } - const Value *getIndexOperand() const { return Op<1>(); } - - VectorType *getVectorOperandType() const { - return cast(getVectorOperand()->getType()); - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::ExtractElement; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) - -//===----------------------------------------------------------------------===// -// InsertElementInst Class -//===----------------------------------------------------------------------===// - -/// This instruction inserts a single (scalar) -/// element into a VectorType value -/// -class InsertElementInst : public Instruction { - InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr, - BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - InsertElementInst *cloneImpl() const; - -public: - static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertBefore); - } - - static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertAtEnd); - } - - /// Return true if an insertelement instruction can be - /// formed with the specified operands. - static bool isValidOperands(const Value *Vec, const Value *NewElt, - const Value *Idx); - - /// Overload to return most specific vector type. - /// - VectorType *getType() const { - return cast(Instruction::getType()); - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::InsertElement; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) - -//===----------------------------------------------------------------------===// -// ShuffleVectorInst Class -//===----------------------------------------------------------------------===// - -constexpr int UndefMaskElem = -1; - -/// This instruction constructs a fixed permutation of two -/// input vectors. -/// -/// For each element of the result vector, the shuffle mask selects an element -/// from one of the input vectors to copy to the result. Non-negative elements -/// in the mask represent an index into the concatenated pair of input vectors. -/// UndefMaskElem (-1) specifies that the result element is undefined. -/// -/// For scalable vectors, all the elements of the mask must be 0 or -1. This -/// requirement may be relaxed in the future. -class ShuffleVectorInst : public Instruction { - SmallVector ShuffleMask; - Constant *ShuffleMaskForBitcode; - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - ShuffleVectorInst *cloneImpl() const; - -public: - ShuffleVectorInst(Value *V1, Value *Mask, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - ShuffleVectorInst(Value *V1, Value *Mask, const Twine &NameStr, - BasicBlock *InsertAtEnd); - ShuffleVectorInst(Value *V1, ArrayRef Mask, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - ShuffleVectorInst(Value *V1, ArrayRef Mask, const Twine &NameStr, - BasicBlock *InsertAtEnd); - ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, - const Twine &NameStr = "", - Instruction *InsertBefor = nullptr); - ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, - const Twine &NameStr, BasicBlock *InsertAtEnd); - ShuffleVectorInst(Value *V1, Value *V2, ArrayRef Mask, - const Twine &NameStr = "", - Instruction *InsertBefor = nullptr); - ShuffleVectorInst(Value *V1, Value *V2, ArrayRef Mask, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { return User::operator delete(Ptr); } - - /// Swap the operands and adjust the mask to preserve the semantics - /// of the instruction. - void commute(); - - /// Return true if a shufflevector instruction can be - /// formed with the specified operands. - static bool isValidOperands(const Value *V1, const Value *V2, - const Value *Mask); - static bool isValidOperands(const Value *V1, const Value *V2, - ArrayRef Mask); - - /// Overload to return most specific vector type. - /// - VectorType *getType() const { - return cast(Instruction::getType()); - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Return the shuffle mask value of this instruction for the given element - /// index. Return UndefMaskElem if the element is undef. - int getMaskValue(unsigned Elt) const { return ShuffleMask[Elt]; } - - /// Convert the input shuffle mask operand to a vector of integers. Undefined - /// elements of the mask are returned as UndefMaskElem. - static void getShuffleMask(const Constant *Mask, - SmallVectorImpl &Result); - - /// Return the mask for this instruction as a vector of integers. Undefined - /// elements of the mask are returned as UndefMaskElem. - void getShuffleMask(SmallVectorImpl &Result) const { - Result.assign(ShuffleMask.begin(), ShuffleMask.end()); - } - - /// Return the mask for this instruction, for use in bitcode. - /// - /// TODO: This is temporary until we decide a new bitcode encoding for - /// shufflevector. - Constant *getShuffleMaskForBitcode() const { return ShuffleMaskForBitcode; } - - static Constant *convertShuffleMaskForBitcode(ArrayRef Mask, - Type *ResultTy); - - void setShuffleMask(ArrayRef Mask); - - ArrayRef getShuffleMask() const { return ShuffleMask; } - - /// Return true if this shuffle returns a vector with a different number of - /// elements than its source vectors. - /// Examples: shufflevector <4 x n> A, <4 x n> B, <1,2,3> - /// shufflevector <4 x n> A, <4 x n> B, <1,2,3,4,5> - bool changesLength() const { - unsigned NumSourceElts = cast(Op<0>()->getType()) - ->getElementCount() - .getKnownMinValue(); - unsigned NumMaskElts = ShuffleMask.size(); - return NumSourceElts != NumMaskElts; - } - - /// Return true if this shuffle returns a vector with a greater number of - /// elements than its source vectors. - /// Example: shufflevector <2 x n> A, <2 x n> B, <1,2,3> - bool increasesLength() const { - unsigned NumSourceElts = cast(Op<0>()->getType()) - ->getElementCount() - .getKnownMinValue(); - unsigned NumMaskElts = ShuffleMask.size(); - return NumSourceElts < NumMaskElts; - } - - /// Return true if this shuffle mask chooses elements from exactly one source - /// vector. - /// Example: <7,5,undef,7> - /// This assumes that vector operands are the same length as the mask. - static bool isSingleSourceMask(ArrayRef Mask); - static bool isSingleSourceMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isSingleSourceMask(MaskAsInts); - } - - /// Return true if this shuffle chooses elements from exactly one source - /// vector without changing the length of that vector. - /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3> - /// TODO: Optionally allow length-changing shuffles. - bool isSingleSource() const { - return !changesLength() && isSingleSourceMask(ShuffleMask); - } - - /// Return true if this shuffle mask chooses elements from exactly one source - /// vector without lane crossings. A shuffle using this mask is not - /// necessarily a no-op because it may change the number of elements from its - /// input vectors or it may provide demanded bits knowledge via undef lanes. - /// Example: - static bool isIdentityMask(ArrayRef Mask); - static bool isIdentityMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isIdentityMask(MaskAsInts); - } - - /// Return true if this shuffle chooses elements from exactly one source - /// vector without lane crossings and does not change the number of elements - /// from its input vectors. - /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef> - bool isIdentity() const { - return !changesLength() && isIdentityMask(ShuffleMask); - } - - /// Return true if this shuffle lengthens exactly one source vector with - /// undefs in the high elements. - bool isIdentityWithPadding() const; - - /// Return true if this shuffle extracts the first N elements of exactly one - /// source vector. - bool isIdentityWithExtract() const; - - /// Return true if this shuffle concatenates its 2 source vectors. This - /// returns false if either input is undefined. In that case, the shuffle is - /// is better classified as an identity with padding operation. - bool isConcat() const; - - /// Return true if this shuffle mask chooses elements from its source vectors - /// without lane crossings. A shuffle using this mask would be - /// equivalent to a vector select with a constant condition operand. - /// Example: <4,1,6,undef> - /// This returns false if the mask does not choose from both input vectors. - /// In that case, the shuffle is better classified as an identity shuffle. - /// This assumes that vector operands are the same length as the mask - /// (a length-changing shuffle can never be equivalent to a vector select). - static bool isSelectMask(ArrayRef Mask); - static bool isSelectMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isSelectMask(MaskAsInts); - } - - /// Return true if this shuffle chooses elements from its source vectors - /// without lane crossings and all operands have the same number of elements. - /// In other words, this shuffle is equivalent to a vector select with a - /// constant condition operand. - /// Example: shufflevector <4 x n> A, <4 x n> B, - /// This returns false if the mask does not choose from both input vectors. - /// In that case, the shuffle is better classified as an identity shuffle. - /// TODO: Optionally allow length-changing shuffles. - bool isSelect() const { - return !changesLength() && isSelectMask(ShuffleMask); - } - - /// Return true if this shuffle mask swaps the order of elements from exactly - /// one source vector. - /// Example: <7,6,undef,4> - /// This assumes that vector operands are the same length as the mask. - static bool isReverseMask(ArrayRef Mask); - static bool isReverseMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isReverseMask(MaskAsInts); - } - - /// Return true if this shuffle swaps the order of elements from exactly - /// one source vector. - /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef> - /// TODO: Optionally allow length-changing shuffles. - bool isReverse() const { - return !changesLength() && isReverseMask(ShuffleMask); - } - - /// Return true if this shuffle mask chooses all elements with the same value - /// as the first element of exactly one source vector. - /// Example: <4,undef,undef,4> - /// This assumes that vector operands are the same length as the mask. - static bool isZeroEltSplatMask(ArrayRef Mask); - static bool isZeroEltSplatMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isZeroEltSplatMask(MaskAsInts); - } - - /// Return true if all elements of this shuffle are the same value as the - /// first element of exactly one source vector without changing the length - /// of that vector. - /// Example: shufflevector <4 x n> A, <4 x n> B, - /// TODO: Optionally allow length-changing shuffles. - /// TODO: Optionally allow splats from other elements. - bool isZeroEltSplat() const { - return !changesLength() && isZeroEltSplatMask(ShuffleMask); - } - - /// Return true if this shuffle mask is a transpose mask. - /// Transpose vector masks transpose a 2xn matrix. They read corresponding - /// even- or odd-numbered vector elements from two n-dimensional source - /// vectors and write each result into consecutive elements of an - /// n-dimensional destination vector. Two shuffles are necessary to complete - /// the transpose, one for the even elements and another for the odd elements. - /// This description closely follows how the TRN1 and TRN2 AArch64 - /// instructions operate. - /// - /// For example, a simple 2x2 matrix can be transposed with: - /// - /// ; Original matrix - /// m0 = < a, b > - /// m1 = < c, d > - /// - /// ; Transposed matrix - /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 > - /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 > - /// - /// For matrices having greater than n columns, the resulting nx2 transposed - /// matrix is stored in two result vectors such that one vector contains - /// interleaved elements from all the even-numbered rows and the other vector - /// contains interleaved elements from all the odd-numbered rows. For example, - /// a 2x4 matrix can be transposed with: - /// - /// ; Original matrix - /// m0 = < a, b, c, d > - /// m1 = < e, f, g, h > - /// - /// ; Transposed matrix - /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 > - /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 > - static bool isTransposeMask(ArrayRef Mask); - static bool isTransposeMask(const Constant *Mask) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isTransposeMask(MaskAsInts); - } - - /// Return true if this shuffle transposes the elements of its inputs without - /// changing the length of the vectors. This operation may also be known as a - /// merge or interleave. See the description for isTransposeMask() for the - /// exact specification. - /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6> - bool isTranspose() const { - return !changesLength() && isTransposeMask(ShuffleMask); - } - - /// Return true if this shuffle mask is an extract subvector mask. - /// A valid extract subvector mask returns a smaller vector from a single - /// source operand. The base extraction index is returned as well. - static bool isExtractSubvectorMask(ArrayRef Mask, int NumSrcElts, - int &Index); - static bool isExtractSubvectorMask(const Constant *Mask, int NumSrcElts, - int &Index) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - // Not possible to express a shuffle mask for a scalable vector for this - // case. - if (isa(Mask->getType())) - return false; - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isExtractSubvectorMask(MaskAsInts, NumSrcElts, Index); - } - - /// Return true if this shuffle mask is an extract subvector mask. - bool isExtractSubvectorMask(int &Index) const { - // Not possible to express a shuffle mask for a scalable vector for this - // case. - if (isa(getType())) - return false; - - int NumSrcElts = - cast(Op<0>()->getType())->getNumElements(); - return isExtractSubvectorMask(ShuffleMask, NumSrcElts, Index); - } - - /// Return true if this shuffle mask is an insert subvector mask. - /// A valid insert subvector mask inserts the lowest elements of a second - /// source operand into an in-place first source operand operand. - /// Both the sub vector width and the insertion index is returned. - static bool isInsertSubvectorMask(ArrayRef Mask, int NumSrcElts, - int &NumSubElts, int &Index); - static bool isInsertSubvectorMask(const Constant *Mask, int NumSrcElts, - int &NumSubElts, int &Index) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - // Not possible to express a shuffle mask for a scalable vector for this - // case. - if (isa(Mask->getType())) - return false; - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isInsertSubvectorMask(MaskAsInts, NumSrcElts, NumSubElts, Index); - } - - /// Return true if this shuffle mask is an insert subvector mask. - bool isInsertSubvectorMask(int &NumSubElts, int &Index) const { - // Not possible to express a shuffle mask for a scalable vector for this - // case. - if (isa(getType())) - return false; - - int NumSrcElts = - cast(Op<0>()->getType())->getNumElements(); - return isInsertSubvectorMask(ShuffleMask, NumSrcElts, NumSubElts, Index); - } - - /// Return true if this shuffle mask replicates each of the \p VF elements - /// in a vector \p ReplicationFactor times. - /// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is: - /// <0,0,0,1,1,1,2,2,2,3,3,3> - static bool isReplicationMask(ArrayRef Mask, int &ReplicationFactor, - int &VF); - static bool isReplicationMask(const Constant *Mask, int &ReplicationFactor, - int &VF) { - assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); - // Not possible to express a shuffle mask for a scalable vector for this - // case. - if (isa(Mask->getType())) - return false; - SmallVector MaskAsInts; - getShuffleMask(Mask, MaskAsInts); - return isReplicationMask(MaskAsInts, ReplicationFactor, VF); - } - - /// Return true if this shuffle mask is a replication mask. - bool isReplicationMask(int &ReplicationFactor, int &VF) const; - - /// Change values in a shuffle permute mask assuming the two vector operands - /// of length InVecNumElts have swapped position. - static void commuteShuffleMask(MutableArrayRef Mask, - unsigned InVecNumElts) { - for (int &Idx : Mask) { - if (Idx == -1) - continue; - Idx = Idx < (int)InVecNumElts ? Idx + InVecNumElts : Idx - InVecNumElts; - assert(Idx >= 0 && Idx < (int)InVecNumElts * 2 && - "shufflevector mask index out of range"); - } - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::ShuffleVector; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) - -//===----------------------------------------------------------------------===// -// ExtractValueInst Class -//===----------------------------------------------------------------------===// - -/// This instruction extracts a struct member or array -/// element value from an aggregate value. -/// -class ExtractValueInst : public UnaryInstruction { - SmallVector Indices; - - ExtractValueInst(const ExtractValueInst &EVI); - - /// Constructors - Create a extractvalue instruction with a base aggregate - /// value and a list of indices. The first ctor can optionally insert before - /// an existing instruction, the second appends the new instruction to the - /// specified BasicBlock. - inline ExtractValueInst(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr, - Instruction *InsertBefore); - inline ExtractValueInst(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(ArrayRef Idxs, const Twine &NameStr); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - ExtractValueInst *cloneImpl() const; - -public: - static ExtractValueInst *Create(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new - ExtractValueInst(Agg, Idxs, NameStr, InsertBefore); - } - - static ExtractValueInst *Create(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new ExtractValueInst(Agg, Idxs, NameStr, InsertAtEnd); - } - - /// Returns the type of the element that would be extracted - /// with an extractvalue instruction with the specified parameters. - /// - /// Null is returned if the indices are invalid for the specified type. - static Type *getIndexedType(Type *Agg, ArrayRef Idxs); - - using idx_iterator = const unsigned*; - - inline idx_iterator idx_begin() const { return Indices.begin(); } - inline idx_iterator idx_end() const { return Indices.end(); } - inline iterator_range indices() const { - return make_range(idx_begin(), idx_end()); - } - - Value *getAggregateOperand() { - return getOperand(0); - } - const Value *getAggregateOperand() const { - return getOperand(0); - } - static unsigned getAggregateOperandIndex() { - return 0U; // get index for modifying correct operand - } - - ArrayRef getIndices() const { - return Indices; - } - - unsigned getNumIndices() const { - return (unsigned)Indices.size(); - } - - bool hasIndices() const { - return true; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::ExtractValue; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -ExtractValueInst::ExtractValueInst(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr, - Instruction *InsertBefore) - : UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(), Idxs)), - ExtractValue, Agg, InsertBefore) { - init(Idxs, NameStr); -} - -ExtractValueInst::ExtractValueInst(Value *Agg, - ArrayRef Idxs, - const Twine &NameStr, - BasicBlock *InsertAtEnd) - : UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(), Idxs)), - ExtractValue, Agg, InsertAtEnd) { - init(Idxs, NameStr); -} - -//===----------------------------------------------------------------------===// -// InsertValueInst Class -//===----------------------------------------------------------------------===// - -/// This instruction inserts a struct field of array element -/// value into an aggregate value. -/// -class InsertValueInst : public Instruction { - SmallVector Indices; - - InsertValueInst(const InsertValueInst &IVI); - - /// Constructors - Create a insertvalue instruction with a base aggregate - /// value, a value to insert, and a list of indices. The first ctor can - /// optionally insert before an existing instruction, the second appends - /// the new instruction to the specified BasicBlock. - inline InsertValueInst(Value *Agg, Value *Val, - ArrayRef Idxs, - const Twine &NameStr, - Instruction *InsertBefore); - inline InsertValueInst(Value *Agg, Value *Val, - ArrayRef Idxs, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - /// Constructors - These two constructors are convenience methods because one - /// and two index insertvalue instructions are so common. - InsertValueInst(Value *Agg, Value *Val, unsigned Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - InsertValueInst(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - void init(Value *Agg, Value *Val, ArrayRef Idxs, - const Twine &NameStr); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - InsertValueInst *cloneImpl() const; - -public: - // allocate space for exactly two operands - void *operator new(size_t S) { return User::operator new(S, 2); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - static InsertValueInst *Create(Value *Agg, Value *Val, - ArrayRef Idxs, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new InsertValueInst(Agg, Val, Idxs, NameStr, InsertBefore); - } - - static InsertValueInst *Create(Value *Agg, Value *Val, - ArrayRef Idxs, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new InsertValueInst(Agg, Val, Idxs, NameStr, InsertAtEnd); - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - using idx_iterator = const unsigned*; - - inline idx_iterator idx_begin() const { return Indices.begin(); } - inline idx_iterator idx_end() const { return Indices.end(); } - inline iterator_range indices() const { - return make_range(idx_begin(), idx_end()); - } - - Value *getAggregateOperand() { - return getOperand(0); - } - const Value *getAggregateOperand() const { - return getOperand(0); - } - static unsigned getAggregateOperandIndex() { - return 0U; // get index for modifying correct operand - } - - Value *getInsertedValueOperand() { - return getOperand(1); - } - const Value *getInsertedValueOperand() const { - return getOperand(1); - } - static unsigned getInsertedValueOperandIndex() { - return 1U; // get index for modifying correct operand - } - - ArrayRef getIndices() const { - return Indices; - } - - unsigned getNumIndices() const { - return (unsigned)Indices.size(); - } - - bool hasIndices() const { - return true; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::InsertValue; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -InsertValueInst::InsertValueInst(Value *Agg, - Value *Val, - ArrayRef Idxs, - const Twine &NameStr, - Instruction *InsertBefore) - : Instruction(Agg->getType(), InsertValue, - OperandTraits::op_begin(this), - 2, InsertBefore) { - init(Agg, Val, Idxs, NameStr); -} - -InsertValueInst::InsertValueInst(Value *Agg, - Value *Val, - ArrayRef Idxs, - const Twine &NameStr, - BasicBlock *InsertAtEnd) - : Instruction(Agg->getType(), InsertValue, - OperandTraits::op_begin(this), - 2, InsertAtEnd) { - init(Agg, Val, Idxs, NameStr); -} - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) - -//===----------------------------------------------------------------------===// -// PHINode Class -//===----------------------------------------------------------------------===// - -// PHINode - The PHINode class is used to represent the magical mystical PHI -// node, that can not exist in nature, but can be synthesized in a computer -// scientist's overactive imagination. -// -class PHINode : public Instruction { - /// The number of operands actually allocated. NumOperands is - /// the number actually in use. - unsigned ReservedSpace; - - PHINode(const PHINode &PN); - - explicit PHINode(Type *Ty, unsigned NumReservedValues, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) - : Instruction(Ty, Instruction::PHI, nullptr, 0, InsertBefore), - ReservedSpace(NumReservedValues) { - assert(!Ty->isTokenTy() && "PHI nodes cannot have token type!"); - setName(NameStr); - allocHungoffUses(ReservedSpace); - } - - PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : Instruction(Ty, Instruction::PHI, nullptr, 0, InsertAtEnd), - ReservedSpace(NumReservedValues) { - assert(!Ty->isTokenTy() && "PHI nodes cannot have token type!"); - setName(NameStr); - allocHungoffUses(ReservedSpace); - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - PHINode *cloneImpl() const; - - // allocHungoffUses - this is more complicated than the generic - // User::allocHungoffUses, because we have to allocate Uses for the incoming - // values and pointers to the incoming blocks, all in one allocation. - void allocHungoffUses(unsigned N) { - User::allocHungoffUses(N, /* IsPhi */ true); - } - -public: - /// Constructors - NumReservedValues is a hint for the number of incoming - /// edges that this phi node will have (use 0 if you really have no idea). - static PHINode *Create(Type *Ty, unsigned NumReservedValues, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new PHINode(Ty, NumReservedValues, NameStr, InsertBefore); - } - - static PHINode *Create(Type *Ty, unsigned NumReservedValues, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Block iterator interface. This provides access to the list of incoming - // basic blocks, which parallels the list of incoming values. - - using block_iterator = BasicBlock **; - using const_block_iterator = BasicBlock * const *; - - block_iterator block_begin() { - return reinterpret_cast(op_begin() + ReservedSpace); - } - - const_block_iterator block_begin() const { - return reinterpret_cast(op_begin() + ReservedSpace); - } - - block_iterator block_end() { - return block_begin() + getNumOperands(); - } - - const_block_iterator block_end() const { - return block_begin() + getNumOperands(); - } - - iterator_range blocks() { - return make_range(block_begin(), block_end()); - } - - iterator_range blocks() const { - return make_range(block_begin(), block_end()); - } - - op_range incoming_values() { return operands(); } - - const_op_range incoming_values() const { return operands(); } - - /// Return the number of incoming edges - /// - unsigned getNumIncomingValues() const { return getNumOperands(); } - - /// Return incoming value number x - /// - Value *getIncomingValue(unsigned i) const { - return getOperand(i); - } - void setIncomingValue(unsigned i, Value *V) { - assert(V && "PHI node got a null value!"); - assert(getType() == V->getType() && - "All operands to PHI node must be the same type as the PHI node!"); - setOperand(i, V); - } - - static unsigned getOperandNumForIncomingValue(unsigned i) { - return i; - } - - static unsigned getIncomingValueNumForOperand(unsigned i) { - return i; - } - - /// Return incoming basic block number @p i. - /// - BasicBlock *getIncomingBlock(unsigned i) const { - return block_begin()[i]; - } - - /// Return incoming basic block corresponding - /// to an operand of the PHI. - /// - BasicBlock *getIncomingBlock(const Use &U) const { - assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); - return getIncomingBlock(unsigned(&U - op_begin())); - } - - /// Return incoming basic block corresponding - /// to value use iterator. - /// - BasicBlock *getIncomingBlock(Value::const_user_iterator I) const { - return getIncomingBlock(I.getUse()); - } - - void setIncomingBlock(unsigned i, BasicBlock *BB) { - assert(BB && "PHI node got a null basic block!"); - block_begin()[i] = BB; - } - - /// Replace every incoming basic block \p Old to basic block \p New. - void replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) { - assert(New && Old && "PHI node got a null basic block!"); - for (unsigned Op = 0, NumOps = getNumOperands(); Op != NumOps; ++Op) - if (getIncomingBlock(Op) == Old) - setIncomingBlock(Op, New); - } - - /// Add an incoming value to the end of the PHI list - /// - void addIncoming(Value *V, BasicBlock *BB) { - if (getNumOperands() == ReservedSpace) - growOperands(); // Get more space! - // Initialize some new operands. - setNumHungOffUseOperands(getNumOperands() + 1); - setIncomingValue(getNumOperands() - 1, V); - setIncomingBlock(getNumOperands() - 1, BB); - } - - /// Remove an incoming value. This is useful if a - /// predecessor basic block is deleted. The value removed is returned. - /// - /// If the last incoming value for a PHI node is removed (and DeletePHIIfEmpty - /// is true), the PHI node is destroyed and any uses of it are replaced with - /// dummy values. The only time there should be zero incoming values to a PHI - /// node is when the block is dead, so this strategy is sound. - /// - Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); - - Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty=true) { - int Idx = getBasicBlockIndex(BB); - assert(Idx >= 0 && "Invalid basic block argument to remove!"); - return removeIncomingValue(Idx, DeletePHIIfEmpty); - } - - /// Return the first index of the specified basic - /// block in the value list for this PHI. Returns -1 if no instance. - /// - int getBasicBlockIndex(const BasicBlock *BB) const { - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (block_begin()[i] == BB) - return i; - return -1; - } - - Value *getIncomingValueForBlock(const BasicBlock *BB) const { - int Idx = getBasicBlockIndex(BB); - assert(Idx >= 0 && "Invalid basic block argument!"); - return getIncomingValue(Idx); - } - - /// Set every incoming value(s) for block \p BB to \p V. - void setIncomingValueForBlock(const BasicBlock *BB, Value *V) { - assert(BB && "PHI node got a null basic block!"); - bool Found = false; - for (unsigned Op = 0, NumOps = getNumOperands(); Op != NumOps; ++Op) - if (getIncomingBlock(Op) == BB) { - Found = true; - setIncomingValue(Op, V); - } - (void)Found; - assert(Found && "Invalid basic block argument to set!"); - } - - /// If the specified PHI node always merges together the - /// same value, return the value, otherwise return null. - Value *hasConstantValue() const; - - /// Whether the specified PHI node always merges - /// together the same value, assuming undefs are equal to a unique - /// non-undef value. - bool hasConstantOrUndefValue() const; - - /// If the PHI node is complete which means all of its parent's predecessors - /// have incoming value in this PHI, return true, otherwise return false. - bool isComplete() const { - return llvm::all_of(predecessors(getParent()), - [this](const BasicBlock *Pred) { - return getBasicBlockIndex(Pred) >= 0; - }); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::PHI; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - void growOperands(); -}; - -template <> -struct OperandTraits : public HungoffOperandTraits<2> { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) - -//===----------------------------------------------------------------------===// -// LandingPadInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// The landingpad instruction holds all of the information -/// necessary to generate correct exception handling. The landingpad instruction -/// cannot be moved from the top of a landing pad block, which itself is -/// accessible only from the 'unwind' edge of an invoke. This uses the -/// SubclassData field in Value to store whether or not the landingpad is a -/// cleanup. -/// -class LandingPadInst : public Instruction { - using CleanupField = BoolBitfieldElementT<0>; - - /// The number of operands actually allocated. NumOperands is - /// the number actually in use. - unsigned ReservedSpace; - - LandingPadInst(const LandingPadInst &LP); - -public: - enum ClauseType { Catch, Filter }; - -private: - explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues, - const Twine &NameStr, Instruction *InsertBefore); - explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - // Allocate space for exactly zero operands. - void *operator new(size_t S) { return User::operator new(S); } - - void growOperands(unsigned Size); - void init(unsigned NumReservedValues, const Twine &NameStr); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - LandingPadInst *cloneImpl() const; - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Constructors - NumReservedClauses is a hint for the number of incoming - /// clauses that this landingpad will have (use 0 if you really have no idea). - static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Return 'true' if this landingpad instruction is a - /// cleanup. I.e., it should be run when unwinding even if its landing pad - /// doesn't catch the exception. - bool isCleanup() const { return getSubclassData(); } - - /// Indicate that this landingpad instruction is a cleanup. - void setCleanup(bool V) { setSubclassData(V); } - - /// Add a catch or filter clause to the landing pad. - void addClause(Constant *ClauseVal); - - /// Get the value of the clause at index Idx. Use isCatch/isFilter to - /// determine what type of clause this is. - Constant *getClause(unsigned Idx) const { - return cast(getOperandList()[Idx]); - } - - /// Return 'true' if the clause and index Idx is a catch clause. - bool isCatch(unsigned Idx) const { - return !isa(getOperandList()[Idx]->getType()); - } - - /// Return 'true' if the clause and index Idx is a filter clause. - bool isFilter(unsigned Idx) const { - return isa(getOperandList()[Idx]->getType()); - } - - /// Get the number of clauses for this landing pad. - unsigned getNumClauses() const { return getNumOperands(); } - - /// Grow the size of the operand list to accommodate the new - /// number of clauses. - void reserveClauses(unsigned Size) { growOperands(Size); } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::LandingPad; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : public HungoffOperandTraits<1> { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value) - -//===----------------------------------------------------------------------===// -// ReturnInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// Return a value (possibly void), from a function. Execution -/// does not continue in this function any longer. -/// -class ReturnInst : public Instruction { - ReturnInst(const ReturnInst &RI); - -private: - // ReturnInst constructors: - // ReturnInst() - 'ret void' instruction - // ReturnInst( null) - 'ret void' instruction - // ReturnInst(Value* X) - 'ret X' instruction - // ReturnInst( null, Inst *I) - 'ret void' instruction, insert before I - // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I - // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B - // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B - // - // NOTE: If the Value* passed is of type void then the constructor behaves as - // if it was passed NULL. - explicit ReturnInst(LLVMContext &C, Value *retVal = nullptr, - Instruction *InsertBefore = nullptr); - ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); - explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - ReturnInst *cloneImpl() const; - -public: - static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr, - Instruction *InsertBefore = nullptr) { - return new(!!retVal) ReturnInst(C, retVal, InsertBefore); - } - - static ReturnInst* Create(LLVMContext &C, Value *retVal, - BasicBlock *InsertAtEnd) { - return new(!!retVal) ReturnInst(C, retVal, InsertAtEnd); - } - - static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { - return new(0) ReturnInst(C, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Convenience accessor. Returns null if there is no return value. - Value *getReturnValue() const { - return getNumOperands() != 0 ? getOperand(0) : nullptr; - } - - unsigned getNumSuccessors() const { return 0; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::Ret); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - BasicBlock *getSuccessor(unsigned idx) const { - llvm_unreachable("ReturnInst has no successors!"); - } - - void setSuccessor(unsigned idx, BasicBlock *B) { - llvm_unreachable("ReturnInst has no successors!"); - } -}; - -template <> -struct OperandTraits : public VariadicOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) - -//===----------------------------------------------------------------------===// -// BranchInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// Conditional or Unconditional Branch instruction. -/// -class BranchInst : public Instruction { - /// Ops list - Branches are strange. The operands are ordered: - /// [Cond, FalseDest,] TrueDest. This makes some accessors faster because - /// they don't have to check for cond/uncond branchness. These are mostly - /// accessed relative from op_end(). - BranchInst(const BranchInst &BI); - // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): - // BranchInst(BB *B) - 'br B' - // BranchInst(BB* T, BB *F, Value *C) - 'br C, T, F' - // BranchInst(BB* B, Inst *I) - 'br B' insert before I - // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I - // BranchInst(BB* B, BB *I) - 'br B' insert at end - // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end - explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = nullptr); - BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - Instruction *InsertBefore = nullptr); - BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); - BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - BasicBlock *InsertAtEnd); - - void AssertOK(); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - BranchInst *cloneImpl() const; - -public: - /// Iterator type that casts an operand to a basic block. - /// - /// This only makes sense because the successors are stored as adjacent - /// operands for branch instructions. - struct succ_op_iterator - : iterator_adaptor_base { - explicit succ_op_iterator(value_op_iterator I) : iterator_adaptor_base(I) {} - - BasicBlock *operator*() const { return cast(*I); } - BasicBlock *operator->() const { return operator*(); } - }; - - /// The const version of `succ_op_iterator`. - struct const_succ_op_iterator - : iterator_adaptor_base { - explicit const_succ_op_iterator(const_value_op_iterator I) - : iterator_adaptor_base(I) {} - - const BasicBlock *operator*() const { return cast(*I); } - const BasicBlock *operator->() const { return operator*(); } - }; - - static BranchInst *Create(BasicBlock *IfTrue, - Instruction *InsertBefore = nullptr) { - return new(1) BranchInst(IfTrue, InsertBefore); - } - - static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, - Value *Cond, Instruction *InsertBefore = nullptr) { - return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); - } - - static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { - return new(1) BranchInst(IfTrue, InsertAtEnd); - } - - static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, - Value *Cond, BasicBlock *InsertAtEnd) { - return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); - } - - /// Transparently provide more efficient getOperand methods. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - bool isUnconditional() const { return getNumOperands() == 1; } - bool isConditional() const { return getNumOperands() == 3; } - - Value *getCondition() const { - assert(isConditional() && "Cannot get condition of an uncond branch!"); - return Op<-3>(); - } - - void setCondition(Value *V) { - assert(isConditional() && "Cannot set condition of unconditional branch!"); - Op<-3>() = V; - } - - unsigned getNumSuccessors() const { return 1+isConditional(); } - - BasicBlock *getSuccessor(unsigned i) const { - assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); - return cast_or_null((&Op<-1>() - i)->get()); - } - - void setSuccessor(unsigned idx, BasicBlock *NewSucc) { - assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); - *(&Op<-1>() - idx) = NewSucc; - } - - /// Swap the successors of this branch instruction. - /// - /// Swaps the successors of the branch instruction. This also swaps any - /// branch weight metadata associated with the instruction so that it - /// continues to map correctly to each operand. - void swapSuccessors(); - - iterator_range successors() { - return make_range( - succ_op_iterator(std::next(value_op_begin(), isConditional() ? 1 : 0)), - succ_op_iterator(value_op_end())); - } - - iterator_range successors() const { - return make_range(const_succ_op_iterator( - std::next(value_op_begin(), isConditional() ? 1 : 0)), - const_succ_op_iterator(value_op_end())); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::Br); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : public VariadicOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) - -//===----------------------------------------------------------------------===// -// SwitchInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// Multiway switch -/// -class SwitchInst : public Instruction { - unsigned ReservedSpace; - - // Operand[0] = Value to switch on - // Operand[1] = Default basic block destination - // Operand[2n ] = Value to match - // Operand[2n+1] = BasicBlock to go to on match - SwitchInst(const SwitchInst &SI); - - /// Create a new switch instruction, specifying a value to switch on and a - /// default destination. The number of additional cases can be specified here - /// to make memory allocation more efficient. This constructor can also - /// auto-insert before another instruction. - SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, - Instruction *InsertBefore); - - /// Create a new switch instruction, specifying a value to switch on and a - /// default destination. The number of additional cases can be specified here - /// to make memory allocation more efficient. This constructor also - /// auto-inserts at the end of the specified BasicBlock. - SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, - BasicBlock *InsertAtEnd); - - // allocate space for exactly zero operands - void *operator new(size_t S) { return User::operator new(S); } - - void init(Value *Value, BasicBlock *Default, unsigned NumReserved); - void growOperands(); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - SwitchInst *cloneImpl() const; - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - // -2 - static const unsigned DefaultPseudoIndex = static_cast(~0L-1); - - template class CaseIteratorImpl; - - /// A handle to a particular switch case. It exposes a convenient interface - /// to both the case value and the successor block. - /// - /// We define this as a template and instantiate it to form both a const and - /// non-const handle. - template - class CaseHandleImpl { - // Directly befriend both const and non-const iterators. - friend class SwitchInst::CaseIteratorImpl< - CaseHandleImpl>; - - protected: - // Expose the switch type we're parameterized with to the iterator. - using SwitchInstType = SwitchInstT; - - SwitchInstT *SI; - ptrdiff_t Index; - - CaseHandleImpl() = default; - CaseHandleImpl(SwitchInstT *SI, ptrdiff_t Index) : SI(SI), Index(Index) {} - - public: - /// Resolves case value for current case. - ConstantIntT *getCaseValue() const { - assert((unsigned)Index < SI->getNumCases() && - "Index out the number of cases."); - return reinterpret_cast(SI->getOperand(2 + Index * 2)); - } - - /// Resolves successor for current case. - BasicBlockT *getCaseSuccessor() const { - assert(((unsigned)Index < SI->getNumCases() || - (unsigned)Index == DefaultPseudoIndex) && - "Index out the number of cases."); - return SI->getSuccessor(getSuccessorIndex()); - } - - /// Returns number of current case. - unsigned getCaseIndex() const { return Index; } - - /// Returns successor index for current case successor. - unsigned getSuccessorIndex() const { - assert(((unsigned)Index == DefaultPseudoIndex || - (unsigned)Index < SI->getNumCases()) && - "Index out the number of cases."); - return (unsigned)Index != DefaultPseudoIndex ? Index + 1 : 0; - } - - bool operator==(const CaseHandleImpl &RHS) const { - assert(SI == RHS.SI && "Incompatible operators."); - return Index == RHS.Index; - } - }; - - using ConstCaseHandle = - CaseHandleImpl; - - class CaseHandle - : public CaseHandleImpl { - friend class SwitchInst::CaseIteratorImpl; - - public: - CaseHandle(SwitchInst *SI, ptrdiff_t Index) : CaseHandleImpl(SI, Index) {} - - /// Sets the new value for current case. - void setValue(ConstantInt *V) const { - assert((unsigned)Index < SI->getNumCases() && - "Index out the number of cases."); - SI->setOperand(2 + Index*2, reinterpret_cast(V)); - } - - /// Sets the new successor for current case. - void setSuccessor(BasicBlock *S) const { - SI->setSuccessor(getSuccessorIndex(), S); - } - }; - - template - class CaseIteratorImpl - : public iterator_facade_base, - std::random_access_iterator_tag, - const CaseHandleT> { - using SwitchInstT = typename CaseHandleT::SwitchInstType; - - CaseHandleT Case; - - public: - /// Default constructed iterator is in an invalid state until assigned to - /// a case for a particular switch. - CaseIteratorImpl() = default; - - /// Initializes case iterator for given SwitchInst and for given - /// case number. - CaseIteratorImpl(SwitchInstT *SI, unsigned CaseNum) : Case(SI, CaseNum) {} - - /// Initializes case iterator for given SwitchInst and for given - /// successor index. - static CaseIteratorImpl fromSuccessorIndex(SwitchInstT *SI, - unsigned SuccessorIndex) { - assert(SuccessorIndex < SI->getNumSuccessors() && - "Successor index # out of range!"); - return SuccessorIndex != 0 ? CaseIteratorImpl(SI, SuccessorIndex - 1) - : CaseIteratorImpl(SI, DefaultPseudoIndex); - } - - /// Support converting to the const variant. This will be a no-op for const - /// variant. - operator CaseIteratorImpl() const { - return CaseIteratorImpl(Case.SI, Case.Index); - } - - CaseIteratorImpl &operator+=(ptrdiff_t N) { - // Check index correctness after addition. - // Note: Index == getNumCases() means end(). - assert(Case.Index + N >= 0 && - (unsigned)(Case.Index + N) <= Case.SI->getNumCases() && - "Case.Index out the number of cases."); - Case.Index += N; - return *this; - } - CaseIteratorImpl &operator-=(ptrdiff_t N) { - // Check index correctness after subtraction. - // Note: Case.Index == getNumCases() means end(). - assert(Case.Index - N >= 0 && - (unsigned)(Case.Index - N) <= Case.SI->getNumCases() && - "Case.Index out the number of cases."); - Case.Index -= N; - return *this; - } - ptrdiff_t operator-(const CaseIteratorImpl &RHS) const { - assert(Case.SI == RHS.Case.SI && "Incompatible operators."); - return Case.Index - RHS.Case.Index; - } - bool operator==(const CaseIteratorImpl &RHS) const { - return Case == RHS.Case; - } - bool operator<(const CaseIteratorImpl &RHS) const { - assert(Case.SI == RHS.Case.SI && "Incompatible operators."); - return Case.Index < RHS.Case.Index; - } - const CaseHandleT &operator*() const { return Case; } - }; - - using CaseIt = CaseIteratorImpl; - using ConstCaseIt = CaseIteratorImpl; - - static SwitchInst *Create(Value *Value, BasicBlock *Default, - unsigned NumCases, - Instruction *InsertBefore = nullptr) { - return new SwitchInst(Value, Default, NumCases, InsertBefore); - } - - static SwitchInst *Create(Value *Value, BasicBlock *Default, - unsigned NumCases, BasicBlock *InsertAtEnd) { - return new SwitchInst(Value, Default, NumCases, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Accessor Methods for Switch stmt - Value *getCondition() const { return getOperand(0); } - void setCondition(Value *V) { setOperand(0, V); } - - BasicBlock *getDefaultDest() const { - return cast(getOperand(1)); - } - - void setDefaultDest(BasicBlock *DefaultCase) { - setOperand(1, reinterpret_cast(DefaultCase)); - } - - /// Return the number of 'cases' in this switch instruction, excluding the - /// default case. - unsigned getNumCases() const { - return getNumOperands()/2 - 1; - } - - /// Returns a read/write iterator that points to the first case in the - /// SwitchInst. - CaseIt case_begin() { - return CaseIt(this, 0); - } - - /// Returns a read-only iterator that points to the first case in the - /// SwitchInst. - ConstCaseIt case_begin() const { - return ConstCaseIt(this, 0); - } - - /// Returns a read/write iterator that points one past the last in the - /// SwitchInst. - CaseIt case_end() { - return CaseIt(this, getNumCases()); - } - - /// Returns a read-only iterator that points one past the last in the - /// SwitchInst. - ConstCaseIt case_end() const { - return ConstCaseIt(this, getNumCases()); - } - - /// Iteration adapter for range-for loops. - iterator_range cases() { - return make_range(case_begin(), case_end()); - } - - /// Constant iteration adapter for range-for loops. - iterator_range cases() const { - return make_range(case_begin(), case_end()); - } - - /// Returns an iterator that points to the default case. - /// Note: this iterator allows to resolve successor only. Attempt - /// to resolve case value causes an assertion. - /// Also note, that increment and decrement also causes an assertion and - /// makes iterator invalid. - CaseIt case_default() { - return CaseIt(this, DefaultPseudoIndex); - } - ConstCaseIt case_default() const { - return ConstCaseIt(this, DefaultPseudoIndex); - } - - /// Search all of the case values for the specified constant. If it is - /// explicitly handled, return the case iterator of it, otherwise return - /// default case iterator to indicate that it is handled by the default - /// handler. - CaseIt findCaseValue(const ConstantInt *C) { - return CaseIt( - this, - const_cast(this)->findCaseValue(C)->getCaseIndex()); - } - ConstCaseIt findCaseValue(const ConstantInt *C) const { - ConstCaseIt I = llvm::find_if(cases(), [C](const ConstCaseHandle &Case) { - return Case.getCaseValue() == C; - }); - if (I != case_end()) - return I; - - return case_default(); - } - - /// Finds the unique case value for a given successor. Returns null if the - /// successor is not found, not unique, or is the default case. - ConstantInt *findCaseDest(BasicBlock *BB) { - if (BB == getDefaultDest()) - return nullptr; - - ConstantInt *CI = nullptr; - for (auto Case : cases()) { - if (Case.getCaseSuccessor() != BB) - continue; - - if (CI) - return nullptr; // Multiple cases lead to BB. - - CI = Case.getCaseValue(); - } - - return CI; - } - - /// Add an entry to the switch instruction. - /// Note: - /// This action invalidates case_end(). Old case_end() iterator will - /// point to the added case. - void addCase(ConstantInt *OnVal, BasicBlock *Dest); - - /// This method removes the specified case and its successor from the switch - /// instruction. Note that this operation may reorder the remaining cases at - /// index idx and above. - /// Note: - /// This action invalidates iterators for all cases following the one removed, - /// including the case_end() iterator. It returns an iterator for the next - /// case. - CaseIt removeCase(CaseIt I); - - unsigned getNumSuccessors() const { return getNumOperands()/2; } - BasicBlock *getSuccessor(unsigned idx) const { - assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); - return cast(getOperand(idx*2+1)); - } - void setSuccessor(unsigned idx, BasicBlock *NewSucc) { - assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); - setOperand(idx * 2 + 1, NewSucc); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Switch; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// A wrapper class to simplify modification of SwitchInst cases along with -/// their prof branch_weights metadata. -class SwitchInstProfUpdateWrapper { - SwitchInst &SI; - Optional > Weights = None; - bool Changed = false; - -protected: - static MDNode *getProfBranchWeightsMD(const SwitchInst &SI); - - MDNode *buildProfBranchWeightsMD(); - - void init(); - -public: - using CaseWeightOpt = Optional; - SwitchInst *operator->() { return &SI; } - SwitchInst &operator*() { return SI; } - operator SwitchInst *() { return &SI; } - - SwitchInstProfUpdateWrapper(SwitchInst &SI) : SI(SI) { init(); } - - ~SwitchInstProfUpdateWrapper() { - if (Changed) - SI.setMetadata(LLVMContext::MD_prof, buildProfBranchWeightsMD()); - } - - /// Delegate the call to the underlying SwitchInst::removeCase() and remove - /// correspondent branch weight. - SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I); - - /// Delegate the call to the underlying SwitchInst::addCase() and set the - /// specified branch weight for the added case. - void addCase(ConstantInt *OnVal, BasicBlock *Dest, CaseWeightOpt W); - - /// Delegate the call to the underlying SwitchInst::eraseFromParent() and mark - /// this object to not touch the underlying SwitchInst in destructor. - SymbolTableList::iterator eraseFromParent(); - - void setSuccessorWeight(unsigned idx, CaseWeightOpt W); - CaseWeightOpt getSuccessorWeight(unsigned idx); - - static CaseWeightOpt getSuccessorWeight(const SwitchInst &SI, unsigned idx); -}; - -template <> -struct OperandTraits : public HungoffOperandTraits<2> { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) - -//===----------------------------------------------------------------------===// -// IndirectBrInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// Indirect Branch Instruction. -/// -class IndirectBrInst : public Instruction { - unsigned ReservedSpace; - - // Operand[0] = Address to jump to - // Operand[n+1] = n-th destination - IndirectBrInst(const IndirectBrInst &IBI); - - /// Create a new indirectbr instruction, specifying an - /// Address to jump to. The number of expected destinations can be specified - /// here to make memory allocation more efficient. This constructor can also - /// autoinsert before another instruction. - IndirectBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore); - - /// Create a new indirectbr instruction, specifying an - /// Address to jump to. The number of expected destinations can be specified - /// here to make memory allocation more efficient. This constructor also - /// autoinserts at the end of the specified BasicBlock. - IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); - - // allocate space for exactly zero operands - void *operator new(size_t S) { return User::operator new(S); } - - void init(Value *Address, unsigned NumDests); - void growOperands(); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - IndirectBrInst *cloneImpl() const; - -public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Iterator type that casts an operand to a basic block. - /// - /// This only makes sense because the successors are stored as adjacent - /// operands for indirectbr instructions. - struct succ_op_iterator - : iterator_adaptor_base { - explicit succ_op_iterator(value_op_iterator I) : iterator_adaptor_base(I) {} - - BasicBlock *operator*() const { return cast(*I); } - BasicBlock *operator->() const { return operator*(); } - }; - - /// The const version of `succ_op_iterator`. - struct const_succ_op_iterator - : iterator_adaptor_base { - explicit const_succ_op_iterator(const_value_op_iterator I) - : iterator_adaptor_base(I) {} - - const BasicBlock *operator*() const { return cast(*I); } - const BasicBlock *operator->() const { return operator*(); } - }; - - static IndirectBrInst *Create(Value *Address, unsigned NumDests, - Instruction *InsertBefore = nullptr) { - return new IndirectBrInst(Address, NumDests, InsertBefore); - } - - static IndirectBrInst *Create(Value *Address, unsigned NumDests, - BasicBlock *InsertAtEnd) { - return new IndirectBrInst(Address, NumDests, InsertAtEnd); - } - - /// Provide fast operand accessors. - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Accessor Methods for IndirectBrInst instruction. - Value *getAddress() { return getOperand(0); } - const Value *getAddress() const { return getOperand(0); } - void setAddress(Value *V) { setOperand(0, V); } - - /// return the number of possible destinations in this - /// indirectbr instruction. - unsigned getNumDestinations() const { return getNumOperands()-1; } - - /// Return the specified destination. - BasicBlock *getDestination(unsigned i) { return getSuccessor(i); } - const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); } - - /// Add a destination. - /// - void addDestination(BasicBlock *Dest); - - /// This method removes the specified successor from the - /// indirectbr instruction. - void removeDestination(unsigned i); - - unsigned getNumSuccessors() const { return getNumOperands()-1; } - BasicBlock *getSuccessor(unsigned i) const { - return cast(getOperand(i+1)); - } - void setSuccessor(unsigned i, BasicBlock *NewSucc) { - setOperand(i + 1, NewSucc); - } - - iterator_range successors() { - return make_range(succ_op_iterator(std::next(value_op_begin())), - succ_op_iterator(value_op_end())); - } - - iterator_range successors() const { - return make_range(const_succ_op_iterator(std::next(value_op_begin())), - const_succ_op_iterator(value_op_end())); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::IndirectBr; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : public HungoffOperandTraits<1> { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) - -//===----------------------------------------------------------------------===// -// InvokeInst Class -//===----------------------------------------------------------------------===// - -/// Invoke instruction. The SubclassData field is used to hold the -/// calling convention of the call. -/// -class InvokeInst : public CallBase { - /// The number of operands for this call beyond the called function, - /// arguments, and operand bundles. - static constexpr int NumExtraOperands = 2; - - /// The index from the end of the operand array to the normal destination. - static constexpr int NormalDestOpEndIdx = -3; - - /// The index from the end of the operand array to the unwind destination. - static constexpr int UnwindDestOpEndIdx = -2; - - InvokeInst(const InvokeInst &BI); - - /// Construct an InvokeInst given a range of arguments. - /// - /// Construct an InvokeInst from a range of arguments - inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, Instruction *InsertBefore); - - inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr); - - /// Compute the number of operands to allocate. - static int ComputeNumOperands(int NumArgs, int NumBundleInputs = 0) { - // We need one operand for the called function, plus our extra operands and - // the input operand counts provided. - return 1 + NumExtraOperands + NumArgs + NumBundleInputs; - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - InvokeInst *cloneImpl() const; - -public: - static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - int NumOperands = ComputeNumOperands(Args.size()); - return new (NumOperands) - InvokeInst(Ty, Func, IfNormal, IfException, Args, None, NumOperands, - NameStr, InsertBefore); - } - - static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - int NumOperands = - ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)); - unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - InvokeInst(Ty, Func, IfNormal, IfException, Args, Bundles, NumOperands, - NameStr, InsertBefore); - } - - static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - int NumOperands = ComputeNumOperands(Args.size()); - return new (NumOperands) - InvokeInst(Ty, Func, IfNormal, IfException, Args, None, NumOperands, - NameStr, InsertAtEnd); - } - - static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - int NumOperands = - ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)); - unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - InvokeInst(Ty, Func, IfNormal, IfException, Args, Bundles, NumOperands, - NameStr, InsertAtEnd); - } - - static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, - IfException, Args, None, NameStr, InsertBefore); - } - - static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, - IfException, Args, Bundles, NameStr, InsertBefore); - } - - static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, - IfException, Args, NameStr, InsertAtEnd); - } - - static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, - IfException, Args, Bundles, NameStr, InsertAtEnd); - } - - /// Create a clone of \p II with a different set of operand bundles and - /// insert it before \p InsertPt. - /// - /// The returned invoke instruction is identical to \p II in every way except - /// that the operand bundles for the new instruction are set to the operand - /// bundles in \p Bundles. - static InvokeInst *Create(InvokeInst *II, ArrayRef Bundles, - Instruction *InsertPt = nullptr); - - // get*Dest - Return the destination basic blocks... - BasicBlock *getNormalDest() const { - return cast(Op()); - } - BasicBlock *getUnwindDest() const { - return cast(Op()); - } - void setNormalDest(BasicBlock *B) { - Op() = reinterpret_cast(B); - } - void setUnwindDest(BasicBlock *B) { - Op() = reinterpret_cast(B); - } - - /// Get the landingpad instruction from the landing pad - /// block (the unwind destination). - LandingPadInst *getLandingPadInst() const; - - BasicBlock *getSuccessor(unsigned i) const { - assert(i < 2 && "Successor # out of range for invoke!"); - return i == 0 ? getNormalDest() : getUnwindDest(); - } - - void setSuccessor(unsigned i, BasicBlock *NewSucc) { - assert(i < 2 && "Successor # out of range for invoke!"); - if (i == 0) - setNormalDest(NewSucc); - else - setUnwindDest(NewSucc); - } - - unsigned getNumSuccessors() const { return 2; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::Invoke); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } -}; - -InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, Instruction *InsertBefore) - : CallBase(Ty->getReturnType(), Instruction::Invoke, - OperandTraits::op_end(this) - NumOperands, NumOperands, - InsertBefore) { - init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); -} - -InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, BasicBlock *InsertAtEnd) - : CallBase(Ty->getReturnType(), Instruction::Invoke, - OperandTraits::op_end(this) - NumOperands, NumOperands, - InsertAtEnd) { - init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); -} - -//===----------------------------------------------------------------------===// -// CallBrInst Class -//===----------------------------------------------------------------------===// - -/// CallBr instruction, tracking function calls that may not return control but -/// instead transfer it to a third location. The SubclassData field is used to -/// hold the calling convention of the call. -/// -class CallBrInst : public CallBase { - - unsigned NumIndirectDests; - - CallBrInst(const CallBrInst &BI); - - /// Construct a CallBrInst given a range of arguments. - /// - /// Construct a CallBrInst from a range of arguments - inline CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, Instruction *InsertBefore); - - inline CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(FunctionType *FTy, Value *Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr); - - /// Should the Indirect Destinations change, scan + update the Arg list. - void updateArgBlockAddresses(unsigned i, BasicBlock *B); - - /// Compute the number of operands to allocate. - static int ComputeNumOperands(int NumArgs, int NumIndirectDests, - int NumBundleInputs = 0) { - // We need one operand for the called function, plus our extra operands and - // the input operand counts provided. - return 2 + NumIndirectDests + NumArgs + NumBundleInputs; - } - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CallBrInst *cloneImpl() const; - -public: - static CallBrInst *Create(FunctionType *Ty, Value *Func, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size()); - return new (NumOperands) - CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, None, - NumOperands, NameStr, InsertBefore); - } - - static CallBrInst *Create(FunctionType *Ty, Value *Func, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size(), - CountBundleInputs(Bundles)); - unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, - NumOperands, NameStr, InsertBefore); - } - - static CallBrInst *Create(FunctionType *Ty, Value *Func, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size()); - return new (NumOperands) - CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, None, - NumOperands, NameStr, InsertAtEnd); - } - - static CallBrInst *Create(FunctionType *Ty, Value *Func, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size(), - CountBundleInputs(Bundles)); - unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (NumOperands, DescriptorBytes) - CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, - NumOperands, NameStr, InsertAtEnd); - } - - static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, - IndirectDests, Args, NameStr, InsertBefore); - } - - static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, - IndirectDests, Args, Bundles, NameStr, InsertBefore); - } - - static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, - IndirectDests, Args, NameStr, InsertAtEnd); - } - - static CallBrInst *Create(FunctionCallee Func, - BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, - IndirectDests, Args, Bundles, NameStr, InsertAtEnd); - } - - /// Create a clone of \p CBI with a different set of operand bundles and - /// insert it before \p InsertPt. - /// - /// The returned callbr instruction is identical to \p CBI in every way - /// except that the operand bundles for the new instruction are set to the - /// operand bundles in \p Bundles. - static CallBrInst *Create(CallBrInst *CBI, - ArrayRef Bundles, - Instruction *InsertPt = nullptr); - - /// Return the number of callbr indirect dest labels. - /// - unsigned getNumIndirectDests() const { return NumIndirectDests; } - - /// getIndirectDestLabel - Return the i-th indirect dest label. - /// - Value *getIndirectDestLabel(unsigned i) const { - assert(i < getNumIndirectDests() && "Out of bounds!"); - return getOperand(i + arg_size() + getNumTotalBundleOperands() + 1); - } - - Value *getIndirectDestLabelUse(unsigned i) const { - assert(i < getNumIndirectDests() && "Out of bounds!"); - return getOperandUse(i + arg_size() + getNumTotalBundleOperands() + 1); - } - - // Return the destination basic blocks... - BasicBlock *getDefaultDest() const { - return cast(*(&Op<-1>() - getNumIndirectDests() - 1)); - } - BasicBlock *getIndirectDest(unsigned i) const { - return cast_or_null(*(&Op<-1>() - getNumIndirectDests() + i)); - } - SmallVector getIndirectDests() const { - SmallVector IndirectDests; - for (unsigned i = 0, e = getNumIndirectDests(); i < e; ++i) - IndirectDests.push_back(getIndirectDest(i)); - return IndirectDests; - } - void setDefaultDest(BasicBlock *B) { - *(&Op<-1>() - getNumIndirectDests() - 1) = reinterpret_cast(B); - } - void setIndirectDest(unsigned i, BasicBlock *B) { - updateArgBlockAddresses(i, B); - *(&Op<-1>() - getNumIndirectDests() + i) = reinterpret_cast(B); - } - - BasicBlock *getSuccessor(unsigned i) const { - assert(i < getNumSuccessors() + 1 && - "Successor # out of range for callbr!"); - return i == 0 ? getDefaultDest() : getIndirectDest(i - 1); - } - - void setSuccessor(unsigned i, BasicBlock *NewSucc) { - assert(i < getNumIndirectDests() + 1 && - "Successor # out of range for callbr!"); - return i == 0 ? setDefaultDest(NewSucc) : setIndirectDest(i - 1, NewSucc); - } - - unsigned getNumSuccessors() const { return getNumIndirectDests() + 1; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::CallBr); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } -}; - -CallBrInst::CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, Instruction *InsertBefore) - : CallBase(Ty->getReturnType(), Instruction::CallBr, - OperandTraits::op_end(this) - NumOperands, NumOperands, - InsertBefore) { - init(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, NameStr); -} - -CallBrInst::CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, - ArrayRef IndirectDests, - ArrayRef Args, - ArrayRef Bundles, int NumOperands, - const Twine &NameStr, BasicBlock *InsertAtEnd) - : CallBase(Ty->getReturnType(), Instruction::CallBr, - OperandTraits::op_end(this) - NumOperands, NumOperands, - InsertAtEnd) { - init(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, NameStr); -} - -//===----------------------------------------------------------------------===// -// ResumeInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// Resume the propagation of an exception. -/// -class ResumeInst : public Instruction { - ResumeInst(const ResumeInst &RI); - - explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); - ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - ResumeInst *cloneImpl() const; - -public: - static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = nullptr) { - return new(1) ResumeInst(Exn, InsertBefore); - } - - static ResumeInst *Create(Value *Exn, BasicBlock *InsertAtEnd) { - return new(1) ResumeInst(Exn, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Convenience accessor. - Value *getValue() const { return Op<0>(); } - - unsigned getNumSuccessors() const { return 0; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Resume; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - BasicBlock *getSuccessor(unsigned idx) const { - llvm_unreachable("ResumeInst has no successors!"); - } - - void setSuccessor(unsigned idx, BasicBlock *NewSucc) { - llvm_unreachable("ResumeInst has no successors!"); - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) - -//===----------------------------------------------------------------------===// -// CatchSwitchInst Class -//===----------------------------------------------------------------------===// -class CatchSwitchInst : public Instruction { - using UnwindDestField = BoolBitfieldElementT<0>; - - /// The number of operands actually allocated. NumOperands is - /// the number actually in use. - unsigned ReservedSpace; - - // Operand[0] = Outer scope - // Operand[1] = Unwind block destination - // Operand[n] = BasicBlock to go to on match - CatchSwitchInst(const CatchSwitchInst &CSI); - - /// Create a new switch instruction, specifying a - /// default destination. The number of additional handlers can be specified - /// here to make memory allocation more efficient. - /// This constructor can also autoinsert before another instruction. - CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, - unsigned NumHandlers, const Twine &NameStr, - Instruction *InsertBefore); - - /// Create a new switch instruction, specifying a - /// default destination. The number of additional handlers can be specified - /// here to make memory allocation more efficient. - /// This constructor also autoinserts at the end of the specified BasicBlock. - CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, - unsigned NumHandlers, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - // allocate space for exactly zero operands - void *operator new(size_t S) { return User::operator new(S); } - - void init(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReserved); - void growOperands(unsigned Size); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CatchSwitchInst *cloneImpl() const; - -public: - void operator delete(void *Ptr) { return User::operator delete(Ptr); } - - static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, - unsigned NumHandlers, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr, - InsertBefore); - } - - static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, - unsigned NumHandlers, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr, - InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - // Accessor Methods for CatchSwitch stmt - Value *getParentPad() const { return getOperand(0); } - void setParentPad(Value *ParentPad) { setOperand(0, ParentPad); } - - // Accessor Methods for CatchSwitch stmt - bool hasUnwindDest() const { return getSubclassData(); } - bool unwindsToCaller() const { return !hasUnwindDest(); } - BasicBlock *getUnwindDest() const { - if (hasUnwindDest()) - return cast(getOperand(1)); - return nullptr; - } - void setUnwindDest(BasicBlock *UnwindDest) { - assert(UnwindDest); - assert(hasUnwindDest()); - setOperand(1, UnwindDest); - } - - /// return the number of 'handlers' in this catchswitch - /// instruction, except the default handler - unsigned getNumHandlers() const { - if (hasUnwindDest()) - return getNumOperands() - 2; - return getNumOperands() - 1; - } - -private: - static BasicBlock *handler_helper(Value *V) { return cast(V); } - static const BasicBlock *handler_helper(const Value *V) { - return cast(V); - } - -public: - using DerefFnTy = BasicBlock *(*)(Value *); - using handler_iterator = mapped_iterator; - using handler_range = iterator_range; - using ConstDerefFnTy = const BasicBlock *(*)(const Value *); - using const_handler_iterator = - mapped_iterator; - using const_handler_range = iterator_range; - - /// Returns an iterator that points to the first handler in CatchSwitchInst. - handler_iterator handler_begin() { - op_iterator It = op_begin() + 1; - if (hasUnwindDest()) - ++It; - return handler_iterator(It, DerefFnTy(handler_helper)); - } - - /// Returns an iterator that points to the first handler in the - /// CatchSwitchInst. - const_handler_iterator handler_begin() const { - const_op_iterator It = op_begin() + 1; - if (hasUnwindDest()) - ++It; - return const_handler_iterator(It, ConstDerefFnTy(handler_helper)); - } - - /// Returns a read-only iterator that points one past the last - /// handler in the CatchSwitchInst. - handler_iterator handler_end() { - return handler_iterator(op_end(), DerefFnTy(handler_helper)); - } - - /// Returns an iterator that points one past the last handler in the - /// CatchSwitchInst. - const_handler_iterator handler_end() const { - return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper)); - } - - /// iteration adapter for range-for loops. - handler_range handlers() { - return make_range(handler_begin(), handler_end()); - } - - /// iteration adapter for range-for loops. - const_handler_range handlers() const { - return make_range(handler_begin(), handler_end()); - } - - /// Add an entry to the switch instruction... - /// Note: - /// This action invalidates handler_end(). Old handler_end() iterator will - /// point to the added handler. - void addHandler(BasicBlock *Dest); - - void removeHandler(handler_iterator HI); - - unsigned getNumSuccessors() const { return getNumOperands() - 1; } - BasicBlock *getSuccessor(unsigned Idx) const { - assert(Idx < getNumSuccessors() && - "Successor # out of range for catchswitch!"); - return cast(getOperand(Idx + 1)); - } - void setSuccessor(unsigned Idx, BasicBlock *NewSucc) { - assert(Idx < getNumSuccessors() && - "Successor # out of range for catchswitch!"); - setOperand(Idx + 1, NewSucc); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::CatchSwitch; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -template <> -struct OperandTraits : public HungoffOperandTraits<2> {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value) - -//===----------------------------------------------------------------------===// -// CleanupPadInst Class -//===----------------------------------------------------------------------===// -class CleanupPadInst : public FuncletPadInst { -private: - explicit CleanupPadInst(Value *ParentPad, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore) - : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values, - NameStr, InsertBefore) {} - explicit CleanupPadInst(Value *ParentPad, ArrayRef Args, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values, - NameStr, InsertAtEnd) {} - -public: - static CleanupPadInst *Create(Value *ParentPad, ArrayRef Args = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - unsigned Values = 1 + Args.size(); - return new (Values) - CleanupPadInst(ParentPad, Args, Values, NameStr, InsertBefore); - } - - static CleanupPadInst *Create(Value *ParentPad, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - unsigned Values = 1 + Args.size(); - return new (Values) - CleanupPadInst(ParentPad, Args, Values, NameStr, InsertAtEnd); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::CleanupPad; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// CatchPadInst Class -//===----------------------------------------------------------------------===// -class CatchPadInst : public FuncletPadInst { -private: - explicit CatchPadInst(Value *CatchSwitch, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore) - : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values, - NameStr, InsertBefore) {} - explicit CatchPadInst(Value *CatchSwitch, ArrayRef Args, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values, - NameStr, InsertAtEnd) {} - -public: - static CatchPadInst *Create(Value *CatchSwitch, ArrayRef Args, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - unsigned Values = 1 + Args.size(); - return new (Values) - CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore); - } - - static CatchPadInst *Create(Value *CatchSwitch, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - unsigned Values = 1 + Args.size(); - return new (Values) - CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertAtEnd); - } - - /// Convenience accessors - CatchSwitchInst *getCatchSwitch() const { - return cast(Op<-1>()); - } - void setCatchSwitch(Value *CatchSwitch) { - assert(CatchSwitch); - Op<-1>() = CatchSwitch; - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::CatchPad; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// CatchReturnInst Class -//===----------------------------------------------------------------------===// - -class CatchReturnInst : public Instruction { - CatchReturnInst(const CatchReturnInst &RI); - CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore); - CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd); - - void init(Value *CatchPad, BasicBlock *BB); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CatchReturnInst *cloneImpl() const; - -public: - static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB, - Instruction *InsertBefore = nullptr) { - assert(CatchPad); - assert(BB); - return new (2) CatchReturnInst(CatchPad, BB, InsertBefore); - } - - static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB, - BasicBlock *InsertAtEnd) { - assert(CatchPad); - assert(BB); - return new (2) CatchReturnInst(CatchPad, BB, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// Convenience accessors. - CatchPadInst *getCatchPad() const { return cast(Op<0>()); } - void setCatchPad(CatchPadInst *CatchPad) { - assert(CatchPad); - Op<0>() = CatchPad; - } - - BasicBlock *getSuccessor() const { return cast(Op<1>()); } - void setSuccessor(BasicBlock *NewSucc) { - assert(NewSucc); - Op<1>() = NewSucc; - } - unsigned getNumSuccessors() const { return 1; } - - /// Get the parentPad of this catchret's catchpad's catchswitch. - /// The successor block is implicitly a member of this funclet. - Value *getCatchSwitchParentPad() const { - return getCatchPad()->getCatchSwitch()->getParentPad(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::CatchRet); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - BasicBlock *getSuccessor(unsigned Idx) const { - assert(Idx < getNumSuccessors() && "Successor # out of range for catchret!"); - return getSuccessor(); - } - - void setSuccessor(unsigned Idx, BasicBlock *B) { - assert(Idx < getNumSuccessors() && "Successor # out of range for catchret!"); - setSuccessor(B); - } -}; - -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value) - -//===----------------------------------------------------------------------===// -// CleanupReturnInst Class -//===----------------------------------------------------------------------===// - -class CleanupReturnInst : public Instruction { - using UnwindDestField = BoolBitfieldElementT<0>; - -private: - CleanupReturnInst(const CleanupReturnInst &RI); - CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, - Instruction *InsertBefore = nullptr); - CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, - BasicBlock *InsertAtEnd); - - void init(Value *CleanupPad, BasicBlock *UnwindBB); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CleanupReturnInst *cloneImpl() const; - -public: - static CleanupReturnInst *Create(Value *CleanupPad, - BasicBlock *UnwindBB = nullptr, - Instruction *InsertBefore = nullptr) { - assert(CleanupPad); - unsigned Values = 1; - if (UnwindBB) - ++Values; - return new (Values) - CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore); - } - - static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB, - BasicBlock *InsertAtEnd) { - assert(CleanupPad); - unsigned Values = 1; - if (UnwindBB) - ++Values; - return new (Values) - CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - bool hasUnwindDest() const { return getSubclassData(); } - bool unwindsToCaller() const { return !hasUnwindDest(); } - - /// Convenience accessor. - CleanupPadInst *getCleanupPad() const { - return cast(Op<0>()); - } - void setCleanupPad(CleanupPadInst *CleanupPad) { - assert(CleanupPad); - Op<0>() = CleanupPad; - } - - unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } - - BasicBlock *getUnwindDest() const { - return hasUnwindDest() ? cast(Op<1>()) : nullptr; - } - void setUnwindDest(BasicBlock *NewDest) { - assert(NewDest); - assert(hasUnwindDest()); - Op<1>() = NewDest; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::CleanupRet); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - BasicBlock *getSuccessor(unsigned Idx) const { - assert(Idx == 0); - return getUnwindDest(); - } - - void setSuccessor(unsigned Idx, BasicBlock *B) { - assert(Idx == 0); - setUnwindDest(B); - } - - // Shadow Instruction::setInstructionSubclassData with a private forwarding - // method so that subclasses cannot accidentally use it. - template - void setSubclassData(typename Bitfield::Type Value) { - Instruction::setSubclassData(Value); - } -}; - -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value) - -//===----------------------------------------------------------------------===// -// UnreachableInst Class -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------------- -/// This function has undefined behavior. In particular, the -/// presence of this instruction indicates some higher level knowledge that the -/// end of the block cannot be reached. -/// -class UnreachableInst : public Instruction { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - UnreachableInst *cloneImpl() const; - -public: - explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = nullptr); - explicit UnreachableInst(LLVMContext &C, BasicBlock *InsertAtEnd); - - // allocate space for exactly zero operands - void *operator new(size_t S) { return User::operator new(S, 0); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - unsigned getNumSuccessors() const { return 0; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Unreachable; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: - BasicBlock *getSuccessor(unsigned idx) const { - llvm_unreachable("UnreachableInst has no successors!"); - } - - void setSuccessor(unsigned idx, BasicBlock *B) { - llvm_unreachable("UnreachableInst has no successors!"); - } -}; - -//===----------------------------------------------------------------------===// -// TruncInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a truncation of integer types. -class TruncInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical TruncInst - TruncInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - TruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The (smaller) type to truncate to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - TruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The (smaller) type to truncate to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Trunc; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// ZExtInst Class -//===----------------------------------------------------------------------===// - -/// This class represents zero extension of integer types. -class ZExtInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical ZExtInst - ZExtInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - ZExtInst( - Value *S, ///< The value to be zero extended - Type *Ty, ///< The type to zero extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end semantics. - ZExtInst( - Value *S, ///< The value to be zero extended - Type *Ty, ///< The type to zero extend to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == ZExt; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// SExtInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a sign extension of integer types. -class SExtInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical SExtInst - SExtInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - SExtInst( - Value *S, ///< The value to be sign extended - Type *Ty, ///< The type to sign extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - SExtInst( - Value *S, ///< The value to be sign extended - Type *Ty, ///< The type to sign extend to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == SExt; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// FPTruncInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a truncation of floating point types. -class FPTruncInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FPTruncInst - FPTruncInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - FPTruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The type to truncate to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-before-instruction semantics - FPTruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The type to truncate to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == FPTrunc; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// FPExtInst Class -//===----------------------------------------------------------------------===// - -/// This class represents an extension of floating point types. -class FPExtInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FPExtInst - FPExtInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - FPExtInst( - Value *S, ///< The value to be extended - Type *Ty, ///< The type to extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - FPExtInst( - Value *S, ///< The value to be extended - Type *Ty, ///< The type to extend to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == FPExt; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// UIToFPInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast unsigned integer to floating point. -class UIToFPInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical UIToFPInst - UIToFPInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - UIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - UIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == UIToFP; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// SIToFPInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast from signed integer to floating point. -class SIToFPInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical SIToFPInst - SIToFPInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - SIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - SIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == SIToFP; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// FPToUIInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast from floating point to unsigned integer -class FPToUIInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FPToUIInst - FPToUIInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - FPToUIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - FPToUIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< Where to insert the new instruction - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == FPToUI; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// FPToSIInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast from floating point to signed integer. -class FPToSIInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FPToSIInst - FPToSIInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - FPToSIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - FPToSIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == FPToSI; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// IntToPtrInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast from an integer to a pointer. -class IntToPtrInst : public CastInst { -public: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Constructor with insert-before-instruction semantics - IntToPtrInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - IntToPtrInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Clone an identical IntToPtrInst. - IntToPtrInst *cloneImpl() const; - - /// Returns the address space of this instruction's pointer type. - unsigned getAddressSpace() const { - return getType()->getPointerAddressSpace(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == IntToPtr; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// PtrToIntInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a cast from a pointer to an integer. -class PtrToIntInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical PtrToIntInst. - PtrToIntInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - PtrToIntInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - PtrToIntInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - /// Gets the pointer operand. - Value *getPointerOperand() { return getOperand(0); } - /// Gets the pointer operand. - const Value *getPointerOperand() const { return getOperand(0); } - /// Gets the operand index of the pointer operand. - static unsigned getPointerOperandIndex() { return 0U; } - - /// Returns the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperand()->getType()->getPointerAddressSpace(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == PtrToInt; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// BitCastInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a no-op cast from one type to another. -class BitCastInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical BitCastInst. - BitCastInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - BitCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - BitCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == BitCast; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -//===----------------------------------------------------------------------===// -// AddrSpaceCastInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a conversion between pointers from one address space -/// to another. -class AddrSpaceCastInst : public CastInst { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical AddrSpaceCastInst. - AddrSpaceCastInst *cloneImpl() const; - -public: - /// Constructor with insert-before-instruction semantics - AddrSpaceCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = nullptr ///< Where to insert the new instruction - ); - - /// Constructor with insert-at-end-of-block semantics - AddrSpaceCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr, ///< A name for the new instruction - BasicBlock *InsertAtEnd ///< The block to insert the instruction into - ); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == AddrSpaceCast; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - /// Gets the pointer operand. - Value *getPointerOperand() { - return getOperand(0); - } - - /// Gets the pointer operand. - const Value *getPointerOperand() const { - return getOperand(0); - } - - /// Gets the operand index of the pointer operand. - static unsigned getPointerOperandIndex() { - return 0U; - } - - /// Returns the address space of the pointer operand. - unsigned getSrcAddressSpace() const { - return getPointerOperand()->getType()->getPointerAddressSpace(); - } - - /// Returns the address space of the result. - unsigned getDestAddressSpace() const { - return getType()->getPointerAddressSpace(); - } -}; - -/// A helper function that returns the pointer operand of a load or store -/// instruction. Returns nullptr if not load or store. -inline const Value *getLoadStorePointerOperand(const Value *V) { - if (auto *Load = dyn_cast(V)) - return Load->getPointerOperand(); - if (auto *Store = dyn_cast(V)) - return Store->getPointerOperand(); - return nullptr; -} -inline Value *getLoadStorePointerOperand(Value *V) { - return const_cast( - getLoadStorePointerOperand(static_cast(V))); -} - -/// A helper function that returns the pointer operand of a load, store -/// or GEP instruction. Returns nullptr if not load, store, or GEP. -inline const Value *getPointerOperand(const Value *V) { - if (auto *Ptr = getLoadStorePointerOperand(V)) - return Ptr; - if (auto *Gep = dyn_cast(V)) - return Gep->getPointerOperand(); - return nullptr; -} -inline Value *getPointerOperand(Value *V) { - return const_cast(getPointerOperand(static_cast(V))); -} - -/// A helper function that returns the alignment of load or store instruction. -inline Align getLoadStoreAlignment(Value *I) { - assert((isa(I) || isa(I)) && - "Expected Load or Store instruction"); - if (auto *LI = dyn_cast(I)) - return LI->getAlign(); - return cast(I)->getAlign(); -} - -/// A helper function that returns the address space of the pointer operand of -/// load or store instruction. -inline unsigned getLoadStoreAddressSpace(Value *I) { - assert((isa(I) || isa(I)) && - "Expected Load or Store instruction"); - if (auto *LI = dyn_cast(I)) - return LI->getPointerAddressSpace(); - return cast(I)->getPointerAddressSpace(); -} - -/// A helper function that returns the type of a load or store instruction. -inline Type *getLoadStoreType(Value *I) { - assert((isa(I) || isa(I)) && - "Expected Load or Store instruction"); - if (auto *LI = dyn_cast(I)) - return LI->getType(); - return cast(I)->getValueOperand()->getType(); -} - -//===----------------------------------------------------------------------===// -// FreezeInst Class -//===----------------------------------------------------------------------===// - -/// This class represents a freeze function that returns random concrete -/// value if an operand is either a poison value or an undef value -class FreezeInst : public UnaryInstruction { -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - /// Clone an identical FreezeInst - FreezeInst *cloneImpl() const; - -public: - explicit FreezeInst(Value *S, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr); - FreezeInst(Value *S, const Twine &NameStr, BasicBlock *InsertAtEnd); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Freeze; - } - static inline bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_INSTRUCTIONS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicInst.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicInst.h deleted file mode 100644 index 01dada25a2..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicInst.h +++ /dev/null @@ -1,1386 +0,0 @@ -//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines classes that make it really easy to deal with intrinsic -// functions with the isa/dyncast family of functions. In particular, this -// allows you to do things like: -// -// if (MemCpyInst *MCI = dyn_cast(Inst)) -// ... MCI->getDest() ... MCI->getSource() ... -// -// All intrinsic function calls are instances of the call instruction, so these -// are all subclasses of the CallInst class. Note that none of these classes -// has state or virtual methods, which is an important part of this gross/neat -// hack working. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INTRINSICINST_H -#define LLVM_IR_INTRINSICINST_H - -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/FPEnv.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include -#include - -namespace llvm { - -/// A wrapper class for inspecting calls to intrinsic functions. -/// This allows the standard isa/dyncast/cast functionality to work with calls -/// to intrinsic functions. -class IntrinsicInst : public CallInst { -public: - IntrinsicInst() = delete; - IntrinsicInst(const IntrinsicInst &) = delete; - IntrinsicInst &operator=(const IntrinsicInst &) = delete; - - /// Return the intrinsic ID of this intrinsic. - Intrinsic::ID getIntrinsicID() const { - return getCalledFunction()->getIntrinsicID(); - } - - /// Return true if swapping the first two arguments to the intrinsic produces - /// the same result. - bool isCommutative() const { - switch (getIntrinsicID()) { - case Intrinsic::maxnum: - case Intrinsic::minnum: - case Intrinsic::maximum: - case Intrinsic::minimum: - case Intrinsic::smax: - case Intrinsic::smin: - case Intrinsic::umax: - case Intrinsic::umin: - case Intrinsic::sadd_sat: - case Intrinsic::uadd_sat: - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_fix: - case Intrinsic::umul_fix: - case Intrinsic::smul_fix_sat: - case Intrinsic::umul_fix_sat: - case Intrinsic::fma: - case Intrinsic::fmuladd: - return true; - default: - return false; - } - } - - // Checks if the intrinsic is an annotation. - bool isAssumeLikeIntrinsic() const { - switch (getIntrinsicID()) { - default: break; - case Intrinsic::assume: - case Intrinsic::sideeffect: - case Intrinsic::pseudoprobe: - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - case Intrinsic::dbg_label: - case Intrinsic::invariant_start: - case Intrinsic::invariant_end: - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::experimental_noalias_scope_decl: - case Intrinsic::objectsize: - case Intrinsic::ptr_annotation: - case Intrinsic::var_annotation: - return true; - } - return false; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const CallInst *I) { - if (const Function *CF = I->getCalledFunction()) - return CF->isIntrinsic(); - return false; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// Check if \p ID corresponds to a debug info intrinsic. -static inline bool isDbgInfoIntrinsic(Intrinsic::ID ID) { - switch (ID) { - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - case Intrinsic::dbg_addr: - case Intrinsic::dbg_label: - return true; - default: - return false; - } -} - -/// This is the common base class for debug info intrinsics. -class DbgInfoIntrinsic : public IntrinsicInst { -public: - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - return isDbgInfoIntrinsic(I->getIntrinsicID()); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - -/// This is the common base class for debug info intrinsics for variables. -class DbgVariableIntrinsic : public DbgInfoIntrinsic { -public: - // Iterator for ValueAsMetadata that internally uses direct pointer iteration - // over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the - // ValueAsMetadata . - class location_op_iterator - : public iterator_facade_base { - PointerUnion I; - - public: - location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {} - location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {} - - location_op_iterator(const location_op_iterator &R) : I(R.I) {} - location_op_iterator &operator=(const location_op_iterator &R) { - I = R.I; - return *this; - } - bool operator==(const location_op_iterator &RHS) const { - return I == RHS.I; - } - const Value *operator*() const { - ValueAsMetadata *VAM = I.is() - ? I.get() - : *I.get(); - return VAM->getValue(); - }; - Value *operator*() { - ValueAsMetadata *VAM = I.is() - ? I.get() - : *I.get(); - return VAM->getValue(); - } - location_op_iterator &operator++() { - if (I.is()) - I = I.get() + 1; - else - I = I.get() + 1; - return *this; - } - location_op_iterator &operator--() { - if (I.is()) - I = I.get() - 1; - else - I = I.get() - 1; - return *this; - } - }; - - /// Get the locations corresponding to the variable referenced by the debug - /// info intrinsic. Depending on the intrinsic, this could be the - /// variable's value or its address. - iterator_range location_ops() const; - - Value *getVariableLocationOp(unsigned OpIdx) const; - - void replaceVariableLocationOp(Value *OldValue, Value *NewValue); - void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue); - /// Adding a new location operand will always result in this intrinsic using - /// an ArgList, and must always be accompanied by a new expression that uses - /// the new operand. - void addVariableLocationOps(ArrayRef NewValues, - DIExpression *NewExpr); - - void setVariable(DILocalVariable *NewVar) { - setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar)); - } - - void setExpression(DIExpression *NewExpr) { - setArgOperand(2, MetadataAsValue::get(NewExpr->getContext(), NewExpr)); - } - - unsigned getNumVariableLocationOps() const { - if (hasArgList()) - return cast(getRawLocation())->getArgs().size(); - return 1; - } - - bool hasArgList() const { return isa(getRawLocation()); } - - /// Does this describe the address of a local variable. True for dbg.addr - /// and dbg.declare, but not dbg.value, which describes its value. - bool isAddressOfVariable() const { - return getIntrinsicID() != Intrinsic::dbg_value; - } - - void setUndef() { - // TODO: When/if we remove duplicate values from DIArgLists, we don't need - // this set anymore. - SmallPtrSet RemovedValues; - for (Value *OldValue : location_ops()) { - if (!RemovedValues.insert(OldValue).second) - continue; - Value *Undef = UndefValue::get(OldValue->getType()); - replaceVariableLocationOp(OldValue, Undef); - } - } - - bool isUndef() const { - return (getNumVariableLocationOps() == 0 && - !getExpression()->isComplex()) || - any_of(location_ops(), [](Value *V) { return isa(V); }); - } - - DILocalVariable *getVariable() const { - return cast(getRawVariable()); - } - - DIExpression *getExpression() const { - return cast(getRawExpression()); - } - - Metadata *getRawLocation() const { - return cast(getArgOperand(0))->getMetadata(); - } - - Metadata *getRawVariable() const { - return cast(getArgOperand(1))->getMetadata(); - } - - Metadata *getRawExpression() const { - return cast(getArgOperand(2))->getMetadata(); - } - - /// Use of this should generally be avoided; instead, - /// replaceVariableLocationOp and addVariableLocationOps should be used where - /// possible to avoid creating invalid state. - void setRawLocation(Metadata *Location) { - return setArgOperand(0, MetadataAsValue::get(getContext(), Location)); - } - - /// Get the size (in bits) of the variable, or fragment of the variable that - /// is described. - Optional getFragmentSizeInBits() const; - - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - case Intrinsic::dbg_addr: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -private: - void setArgOperand(unsigned i, Value *v) { - DbgInfoIntrinsic::setArgOperand(i, v); - } - void setOperand(unsigned i, Value *v) { DbgInfoIntrinsic::setOperand(i, v); } -}; - -/// This represents the llvm.dbg.declare instruction. -class DbgDeclareInst : public DbgVariableIntrinsic { -public: - Value *getAddress() const { - assert(getNumVariableLocationOps() == 1 && - "dbg.declare must have exactly 1 location operand."); - return getVariableLocationOp(0); - } - - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_declare; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - -/// This represents the llvm.dbg.addr instruction. -class DbgAddrIntrinsic : public DbgVariableIntrinsic { -public: - Value *getAddress() const { - assert(getNumVariableLocationOps() == 1 && - "dbg.addr must have exactly 1 location operand."); - return getVariableLocationOp(0); - } - - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_addr; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This represents the llvm.dbg.value instruction. -class DbgValueInst : public DbgVariableIntrinsic { -public: - // The default argument should only be used in ISel, and the default option - // should be removed once ISel support for multiple location ops is complete. - Value *getValue(unsigned OpIdx = 0) const { - return getVariableLocationOp(OpIdx); - } - iterator_range getValues() const { - return location_ops(); - } - - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_value; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - -/// This represents the llvm.dbg.label instruction. -class DbgLabelInst : public DbgInfoIntrinsic { -public: - DILabel *getLabel() const { return cast(getRawLabel()); } - - Metadata *getRawLabel() const { - return cast(getArgOperand(0))->getMetadata(); - } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - /// @{ - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_label; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - -/// This is the common base class for vector predication intrinsics. -class VPIntrinsic : public IntrinsicInst { -public: - /// \brief Declares a llvm.vp.* intrinsic in \p M that matches the parameters - /// \p Params. Additionally, the load and gather intrinsics require - /// \p ReturnType to be specified. - static Function *getDeclarationForParams(Module *M, Intrinsic::ID, - Type *ReturnType, - ArrayRef Params); - - static Optional getMaskParamPos(Intrinsic::ID IntrinsicID); - static Optional getVectorLengthParamPos(Intrinsic::ID IntrinsicID); - - /// The llvm.vp.* intrinsics for this instruction Opcode - static Intrinsic::ID getForOpcode(unsigned OC); - - // Whether \p ID is a VP intrinsic ID. - static bool isVPIntrinsic(Intrinsic::ID); - - /// \return The mask parameter or nullptr. - Value *getMaskParam() const; - void setMaskParam(Value *); - - /// \return The vector length parameter or nullptr. - Value *getVectorLengthParam() const; - void setVectorLengthParam(Value *); - - /// \return Whether the vector length param can be ignored. - bool canIgnoreVectorLengthParam() const; - - /// \return The static element count (vector number of elements) the vector - /// length parameter applies to. - ElementCount getStaticVectorLength() const; - - /// \return The alignment of the pointer used by this load/store/gather or - /// scatter. - MaybeAlign getPointerAlignment() const; - // MaybeAlign setPointerAlignment(Align NewAlign); // TODO - - /// \return The pointer operand of this load,store, gather or scatter. - Value *getMemoryPointerParam() const; - static Optional getMemoryPointerParamPos(Intrinsic::ID); - - /// \return The data (payload) operand of this store or scatter. - Value *getMemoryDataParam() const; - static Optional getMemoryDataParamPos(Intrinsic::ID); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - return isVPIntrinsic(I->getIntrinsicID()); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - // Equivalent non-predicated opcode - Optional getFunctionalOpcode() const { - return getFunctionalOpcodeForVP(getIntrinsicID()); - } - - // Equivalent non-predicated opcode - static Optional getFunctionalOpcodeForVP(Intrinsic::ID ID); -}; - -/// This represents vector predication reduction intrinsics. -class VPReductionIntrinsic : public VPIntrinsic { -public: - static bool isVPReduction(Intrinsic::ID ID); - - unsigned getStartParamPos() const; - unsigned getVectorParamPos() const; - - static Optional getStartParamPos(Intrinsic::ID ID); - static Optional getVectorParamPos(Intrinsic::ID ID); - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - /// @{ - static bool classof(const IntrinsicInst *I) { - return VPReductionIntrinsic::isVPReduction(I->getIntrinsicID()); - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - -/// This is the common base class for constrained floating point intrinsics. -class ConstrainedFPIntrinsic : public IntrinsicInst { -public: - bool isUnaryOp() const; - bool isTernaryOp() const; - Optional getRoundingMode() const; - Optional getExceptionBehavior() const; - bool isDefaultFPEnvironment() const; - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I); - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// Constrained floating point compare intrinsics. -class ConstrainedFPCmpIntrinsic : public ConstrainedFPIntrinsic { -public: - FCmpInst::Predicate getPredicate() const; - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::experimental_constrained_fcmp: - case Intrinsic::experimental_constrained_fcmps: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents min/max intrinsics. -class MinMaxIntrinsic : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::umin: - case Intrinsic::umax: - case Intrinsic::smin: - case Intrinsic::smax: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getLHS() const { return const_cast(getArgOperand(0)); } - Value *getRHS() const { return const_cast(getArgOperand(1)); } - - /// Returns the comparison predicate underlying the intrinsic. - static ICmpInst::Predicate getPredicate(Intrinsic::ID ID) { - switch (ID) { - case Intrinsic::umin: - return ICmpInst::Predicate::ICMP_ULT; - case Intrinsic::umax: - return ICmpInst::Predicate::ICMP_UGT; - case Intrinsic::smin: - return ICmpInst::Predicate::ICMP_SLT; - case Intrinsic::smax: - return ICmpInst::Predicate::ICMP_SGT; - default: - llvm_unreachable("Invalid intrinsic"); - } - } - - /// Returns the comparison predicate underlying the intrinsic. - ICmpInst::Predicate getPredicate() const { - return getPredicate(getIntrinsicID()); - } - - /// Whether the intrinsic is signed or unsigned. - static bool isSigned(Intrinsic::ID ID) { - return ICmpInst::isSigned(getPredicate(ID)); - }; - - /// Whether the intrinsic is signed or unsigned. - bool isSigned() const { return isSigned(getIntrinsicID()); }; - - /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, - /// so there is a certain threshold value, upon reaching which, - /// their value can no longer change. Return said threshold. - static APInt getSaturationPoint(Intrinsic::ID ID, unsigned numBits) { - switch (ID) { - case Intrinsic::umin: - return APInt::getMinValue(numBits); - case Intrinsic::umax: - return APInt::getMaxValue(numBits); - case Intrinsic::smin: - return APInt::getSignedMinValue(numBits); - case Intrinsic::smax: - return APInt::getSignedMaxValue(numBits); - default: - llvm_unreachable("Invalid intrinsic"); - } - } - - /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, - /// so there is a certain threshold value, upon reaching which, - /// their value can no longer change. Return said threshold. - APInt getSaturationPoint(unsigned numBits) const { - return getSaturationPoint(getIntrinsicID(), numBits); - } - - /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, - /// so there is a certain threshold value, upon reaching which, - /// their value can no longer change. Return said threshold. - static Constant *getSaturationPoint(Intrinsic::ID ID, Type *Ty) { - return Constant::getIntegerValue( - Ty, getSaturationPoint(ID, Ty->getScalarSizeInBits())); - } - - /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, - /// so there is a certain threshold value, upon reaching which, - /// their value can no longer change. Return said threshold. - Constant *getSaturationPoint(Type *Ty) const { - return getSaturationPoint(getIntrinsicID(), Ty); - } -}; - -/// This class represents an intrinsic that is based on a binary operation. -/// This includes op.with.overflow and saturating add/sub intrinsics. -class BinaryOpIntrinsic : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::uadd_sat: - case Intrinsic::sadd_sat: - case Intrinsic::usub_sat: - case Intrinsic::ssub_sat: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getLHS() const { return const_cast(getArgOperand(0)); } - Value *getRHS() const { return const_cast(getArgOperand(1)); } - - /// Returns the binary operation underlying the intrinsic. - Instruction::BinaryOps getBinaryOp() const; - - /// Whether the intrinsic is signed or unsigned. - bool isSigned() const; - - /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap. - unsigned getNoWrapKind() const; -}; - -/// Represents an op.with.overflow intrinsic. -class WithOverflowInst : public BinaryOpIntrinsic { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// Represents a saturating add/sub intrinsic. -class SaturatingInst : public BinaryOpIntrinsic { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::uadd_sat: - case Intrinsic::sadd_sat: - case Intrinsic::usub_sat: - case Intrinsic::ssub_sat: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// Common base class for all memory intrinsics. Simply provides -/// common methods. -/// Written as CRTP to avoid a common base class amongst the -/// three atomicity hierarchies. -template class MemIntrinsicBase : public IntrinsicInst { -private: - enum { ARG_DEST = 0, ARG_LENGTH = 2 }; - -public: - Value *getRawDest() const { - return const_cast(getArgOperand(ARG_DEST)); - } - const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } - Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } - - Value *getLength() const { - return const_cast(getArgOperand(ARG_LENGTH)); - } - const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } - Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } - - /// This is just like getRawDest, but it strips off any cast - /// instructions (including addrspacecast) that feed it, giving the - /// original input. The returned value is guaranteed to be a pointer. - Value *getDest() const { return getRawDest()->stripPointerCasts(); } - - unsigned getDestAddressSpace() const { - return cast(getRawDest()->getType())->getAddressSpace(); - } - - /// FIXME: Remove this function once transition to Align is over. - /// Use getDestAlign() instead. - unsigned getDestAlignment() const { - if (auto MA = getParamAlign(ARG_DEST)) - return MA->value(); - return 0; - } - MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); } - - /// Set the specified arguments of the instruction. - void setDest(Value *Ptr) { - assert(getRawDest()->getType() == Ptr->getType() && - "setDest called with pointer of wrong type!"); - setArgOperand(ARG_DEST, Ptr); - } - - /// FIXME: Remove this function once transition to Align is over. - /// Use the version that takes MaybeAlign instead of this one. - void setDestAlignment(unsigned Alignment) { - setDestAlignment(MaybeAlign(Alignment)); - } - void setDestAlignment(MaybeAlign Alignment) { - removeParamAttr(ARG_DEST, Attribute::Alignment); - if (Alignment) - addParamAttr(ARG_DEST, - Attribute::getWithAlignment(getContext(), *Alignment)); - } - void setDestAlignment(Align Alignment) { - removeParamAttr(ARG_DEST, Attribute::Alignment); - addParamAttr(ARG_DEST, - Attribute::getWithAlignment(getContext(), Alignment)); - } - - void setLength(Value *L) { - assert(getLength()->getType() == L->getType() && - "setLength called with value of wrong type!"); - setArgOperand(ARG_LENGTH, L); - } -}; - -/// Common base class for all memory transfer intrinsics. Simply provides -/// common methods. -template class MemTransferBase : public BaseCL { -private: - enum { ARG_SOURCE = 1 }; - -public: - /// Return the arguments to the instruction. - Value *getRawSource() const { - return const_cast(BaseCL::getArgOperand(ARG_SOURCE)); - } - const Use &getRawSourceUse() const { - return BaseCL::getArgOperandUse(ARG_SOURCE); - } - Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); } - - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - - unsigned getSourceAddressSpace() const { - return cast(getRawSource()->getType())->getAddressSpace(); - } - - /// FIXME: Remove this function once transition to Align is over. - /// Use getSourceAlign() instead. - unsigned getSourceAlignment() const { - if (auto MA = BaseCL::getParamAlign(ARG_SOURCE)) - return MA->value(); - return 0; - } - - MaybeAlign getSourceAlign() const { - return BaseCL::getParamAlign(ARG_SOURCE); - } - - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - BaseCL::setArgOperand(ARG_SOURCE, Ptr); - } - - /// FIXME: Remove this function once transition to Align is over. - /// Use the version that takes MaybeAlign instead of this one. - void setSourceAlignment(unsigned Alignment) { - setSourceAlignment(MaybeAlign(Alignment)); - } - void setSourceAlignment(MaybeAlign Alignment) { - BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); - if (Alignment) - BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( - BaseCL::getContext(), *Alignment)); - } - void setSourceAlignment(Align Alignment) { - BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); - BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( - BaseCL::getContext(), Alignment)); - } -}; - -/// Common base class for all memset intrinsics. Simply provides -/// common methods. -template class MemSetBase : public BaseCL { -private: - enum { ARG_VALUE = 1 }; - -public: - Value *getValue() const { - return const_cast(BaseCL::getArgOperand(ARG_VALUE)); - } - const Use &getValueUse() const { return BaseCL::getArgOperandUse(ARG_VALUE); } - Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); } - - void setValue(Value *Val) { - assert(getValue()->getType() == Val->getType() && - "setValue called with value of wrong type!"); - BaseCL::setArgOperand(ARG_VALUE, Val); - } -}; - -// The common base class for the atomic memset/memmove/memcpy intrinsics -// i.e. llvm.element.unordered.atomic.memset/memcpy/memmove -class AtomicMemIntrinsic : public MemIntrinsicBase { -private: - enum { ARG_ELEMENTSIZE = 3 }; - -public: - Value *getRawElementSizeInBytes() const { - return const_cast(getArgOperand(ARG_ELEMENTSIZE)); - } - - ConstantInt *getElementSizeInBytesCst() const { - return cast(getRawElementSizeInBytes()); - } - - uint32_t getElementSizeInBytes() const { - return getElementSizeInBytesCst()->getZExtValue(); - } - - void setElementSizeInBytes(Constant *V) { - assert(V->getType() == Type::getInt8Ty(getContext()) && - "setElementSizeInBytes called with value of wrong type!"); - setArgOperand(ARG_ELEMENTSIZE, V); - } - - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy_element_unordered_atomic: - case Intrinsic::memmove_element_unordered_atomic: - case Intrinsic::memset_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents atomic memset intrinsic -// i.e. llvm.element.unordered.atomic.memset -class AtomicMemSetInst : public MemSetBase { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -// This class wraps the atomic memcpy/memmove intrinsics -// i.e. llvm.element.unordered.atomic.memcpy/memmove -class AtomicMemTransferInst : public MemTransferBase { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy_element_unordered_atomic: - case Intrinsic::memmove_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents the atomic memcpy intrinsic -/// i.e. llvm.element.unordered.atomic.memcpy -class AtomicMemCpyInst : public AtomicMemTransferInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents the atomic memmove intrinsic -/// i.e. llvm.element.unordered.atomic.memmove -class AtomicMemMoveInst : public AtomicMemTransferInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This is the common base class for memset/memcpy/memmove. -class MemIntrinsic : public MemIntrinsicBase { -private: - enum { ARG_VOLATILE = 3 }; - -public: - ConstantInt *getVolatileCst() const { - return cast(const_cast(getArgOperand(ARG_VOLATILE))); - } - - bool isVolatile() const { return !getVolatileCst()->isZero(); } - - void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memset: - case Intrinsic::memcpy_inline: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class wraps the llvm.memset intrinsic. -class MemSetInst : public MemSetBase { -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memset; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class wraps the llvm.memcpy/memmove intrinsics. -class MemTransferInst : public MemTransferBase { -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memcpy_inline: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class wraps the llvm.memcpy intrinsic. -class MemCpyInst : public MemTransferInst { -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memcpy || - I->getIntrinsicID() == Intrinsic::memcpy_inline; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class wraps the llvm.memmove intrinsic. -class MemMoveInst : public MemTransferInst { -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memmove; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class wraps the llvm.memcpy.inline intrinsic. -class MemCpyInlineInst : public MemCpyInst { -public: - ConstantInt *getLength() const { - return cast(MemCpyInst::getLength()); - } - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memcpy_inline; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -// The common base class for any memset/memmove/memcpy intrinsics; -// whether they be atomic or non-atomic. -// i.e. llvm.element.unordered.atomic.memset/memcpy/memmove -// and llvm.memset/memcpy/memmove -class AnyMemIntrinsic : public MemIntrinsicBase { -public: - bool isVolatile() const { - // Only the non-atomic intrinsics can be volatile - if (auto *MI = dyn_cast(this)) - return MI->isVolatile(); - return false; - } - - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memcpy_inline: - case Intrinsic::memmove: - case Intrinsic::memset: - case Intrinsic::memcpy_element_unordered_atomic: - case Intrinsic::memmove_element_unordered_atomic: - case Intrinsic::memset_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents any memset intrinsic -// i.e. llvm.element.unordered.atomic.memset -// and llvm.memset -class AnyMemSetInst : public MemSetBase { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memset: - case Intrinsic::memset_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -// This class wraps any memcpy/memmove intrinsics -// i.e. llvm.element.unordered.atomic.memcpy/memmove -// and llvm.memcpy/memmove -class AnyMemTransferInst : public MemTransferBase { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memcpy_inline: - case Intrinsic::memmove: - case Intrinsic::memcpy_element_unordered_atomic: - case Intrinsic::memmove_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents any memcpy intrinsic -/// i.e. llvm.element.unordered.atomic.memcpy -/// and llvm.memcpy -class AnyMemCpyInst : public AnyMemTransferInst { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memcpy_inline: - case Intrinsic::memcpy_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This class represents any memmove intrinsic -/// i.e. llvm.element.unordered.atomic.memmove -/// and llvm.memmove -class AnyMemMoveInst : public AnyMemTransferInst { -public: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::memmove: - case Intrinsic::memmove_element_unordered_atomic: - return true; - default: - return false; - } - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This represents the llvm.va_start intrinsic. -class VAStartInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::vastart; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getArgList() const { return const_cast(getArgOperand(0)); } -}; - -/// This represents the llvm.va_end intrinsic. -class VAEndInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::vaend; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getArgList() const { return const_cast(getArgOperand(0)); } -}; - -/// This represents the llvm.va_copy intrinsic. -class VACopyInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::vacopy; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getDest() const { return const_cast(getArgOperand(0)); } - Value *getSrc() const { return const_cast(getArgOperand(1)); } -}; - -/// A base class for all instrprof intrinsics. -class InstrProfInstBase : public IntrinsicInst { -public: - // The name of the instrumented function. - GlobalVariable *getName() const { - return cast( - const_cast(getArgOperand(0))->stripPointerCasts()); - } - // The hash of the CFG for the instrumented function. - ConstantInt *getHash() const { - return cast(const_cast(getArgOperand(1))); - } - // The number of counters for the instrumented function. - ConstantInt *getNumCounters() const; - // The index of the counter that this instruction acts on. - ConstantInt *getIndex() const; -}; - -/// This represents the llvm.instrprof.cover intrinsic. -class InstrProfCoverInst : public InstrProfInstBase { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::instrprof_cover; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This represents the llvm.instrprof.increment intrinsic. -class InstrProfIncrementInst : public InstrProfInstBase { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::instrprof_increment; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - Value *getStep() const; -}; - -/// This represents the llvm.instrprof.increment.step intrinsic. -class InstrProfIncrementInstStep : public InstrProfIncrementInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::instrprof_increment_step; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -/// This represents the llvm.instrprof.value.profile intrinsic. -class InstrProfValueProfileInst : public InstrProfInstBase { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::instrprof_value_profile; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - Value *getTargetValue() const { - return cast(const_cast(getArgOperand(2))); - } - - ConstantInt *getValueKind() const { - return cast(const_cast(getArgOperand(3))); - } - - // Returns the value site index. - ConstantInt *getIndex() const { - return cast(const_cast(getArgOperand(4))); - } -}; - -class PseudoProbeInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::pseudoprobe; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - ConstantInt *getFuncGuid() const { - return cast(const_cast(getArgOperand(0))); - } - - ConstantInt *getIndex() const { - return cast(const_cast(getArgOperand(1))); - } - - ConstantInt *getAttributes() const { - return cast(const_cast(getArgOperand(2))); - } - - ConstantInt *getFactor() const { - return cast(const_cast(getArgOperand(3))); - } -}; - -class NoAliasScopeDeclInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - MDNode *getScopeList() const { - auto *MV = - cast(getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); - return cast(MV->getMetadata()); - } - - void setScopeList(MDNode *ScopeList) { - setOperand(Intrinsic::NoAliasScopeDeclScopeArg, - MetadataAsValue::get(getContext(), ScopeList)); - } -}; - -// Defined in Statepoint.h -- NOT a subclass of IntrinsicInst -class GCStatepointInst; - -/// Common base class for representing values projected from a statepoint. -/// Currently, the only projections available are gc.result and gc.relocate. -class GCProjectionInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate || - I->getIntrinsicID() == Intrinsic::experimental_gc_result; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - /// Return true if this relocate is tied to the invoke statepoint. - /// This includes relocates which are on the unwinding path. - bool isTiedToInvoke() const { - const Value *Token = getArgOperand(0); - - return isa(Token) || isa(Token); - } - - /// The statepoint with which this gc.relocate is associated. - const GCStatepointInst *getStatepoint() const; -}; - -/// Represents calls to the gc.relocate intrinsic. -class GCRelocateInst : public GCProjectionInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - /// The index into the associate statepoint's argument list - /// which contains the base pointer of the pointer whose - /// relocation this gc.relocate describes. - unsigned getBasePtrIndex() const { - return cast(getArgOperand(1))->getZExtValue(); - } - - /// The index into the associate statepoint's argument list which - /// contains the pointer whose relocation this gc.relocate describes. - unsigned getDerivedPtrIndex() const { - return cast(getArgOperand(2))->getZExtValue(); - } - - Value *getBasePtr() const; - Value *getDerivedPtr() const; -}; - -/// Represents calls to the gc.result intrinsic. -class GCResultInst : public GCProjectionInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::experimental_gc_result; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - - -/// This represents the llvm.assume intrinsic. -class AssumeInst : public IntrinsicInst { -public: - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::assume; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_INTRINSICINST_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Intrinsics.h b/suite/synctools/tablegen/include/llvm/IR/Intrinsics.h deleted file mode 100644 index fea543b795..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Intrinsics.h +++ /dev/null @@ -1,256 +0,0 @@ -//===- Intrinsics.h - LLVM Intrinsic Function Handling ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a set of enums which allow processing of intrinsic -// functions. Values of these enum types are returned by -// Function::getIntrinsicID. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_INTRINSICS_H -#define LLVM_IR_INTRINSICS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/TypeSize.h" -#include - -namespace llvm { - -class Type; -class FunctionType; -class Function; -class LLVMContext; -class Module; -class AttributeList; - -/// This namespace contains an enum with a value for every intrinsic/builtin -/// function known by LLVM. The enum values are returned by -/// Function::getIntrinsicID(). -namespace Intrinsic { - // Abstraction for the arguments of the noalias intrinsics - static const int NoAliasScopeDeclScopeArg = 0; - - // Intrinsic ID type. This is an opaque typedef to facilitate splitting up - // the enum into target-specific enums. - typedef unsigned ID; - - enum IndependentIntrinsics : unsigned { - not_intrinsic = 0, // Must be zero - - // Get the intrinsic enums generated from Intrinsics.td -#define GET_INTRINSIC_ENUM_VALUES -#include "llvm/IR/IntrinsicEnums.inc" -#undef GET_INTRINSIC_ENUM_VALUES - }; - - /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". - /// Note, this version is for intrinsics with no overloads. Use the other - /// version of getName if overloads are required. - StringRef getName(ID id); - - /// Return the LLVM name for an intrinsic, without encoded types for - /// overloading, such as "llvm.ssa.copy". - StringRef getBaseName(ID id); - - /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx" or - /// "llvm.ssa.copy.p0s_s.1". Note, this version of getName supports overloads. - /// This is less efficient than the StringRef version of this function. If no - /// overloads are required, it is safe to use this version, but better to use - /// the StringRef version. If one of the types is based on an unnamed type, a - /// function type will be computed. Providing FT will avoid this computation. - std::string getName(ID Id, ArrayRef Tys, Module *M, - FunctionType *FT = nullptr); - - /// Return the LLVM name for an intrinsic. This is a special version only to - /// be used by LLVMIntrinsicCopyOverloadedName. It only supports overloads - /// based on named types. - std::string getNameNoUnnamedTypes(ID Id, ArrayRef Tys); - - /// Return the function type for an intrinsic. - FunctionType *getType(LLVMContext &Context, ID id, - ArrayRef Tys = None); - - /// Returns true if the intrinsic can be overloaded. - bool isOverloaded(ID id); - - /// Returns true if the intrinsic is a leaf, i.e. it does not make any calls - /// itself. Most intrinsics are leafs, the exceptions being the patchpoint - /// and statepoint intrinsics. These call (or invoke) their "target" argument. - bool isLeaf(ID id); - - /// Return the attributes for an intrinsic. - AttributeList getAttributes(LLVMContext &C, ID id); - - /// Create or insert an LLVM Function declaration for an intrinsic, and return - /// it. - /// - /// The Tys parameter is for intrinsics with overloaded types (e.g., those - /// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded - /// intrinsic, Tys must provide exactly one type for each overloaded type in - /// the intrinsic. - Function *getDeclaration(Module *M, ID id, ArrayRef Tys = None); - - /// Looks up Name in NameTable via binary search. NameTable must be sorted - /// and all entries must start with "llvm.". If NameTable contains an exact - /// match for Name or a prefix of Name followed by a dot, its index in - /// NameTable is returned. Otherwise, -1 is returned. - int lookupLLVMIntrinsicByName(ArrayRef NameTable, - StringRef Name); - - /// Map a GCC builtin name to an intrinsic ID. - ID getIntrinsicForGCCBuiltin(const char *Prefix, StringRef BuiltinName); - - /// Map a MS builtin name to an intrinsic ID. - ID getIntrinsicForMSBuiltin(const char *Prefix, StringRef BuiltinName); - - /// This is a type descriptor which explains the type requirements of an - /// intrinsic. This is returned by getIntrinsicInfoTableEntries. - struct IITDescriptor { - enum IITDescriptorKind { - Void, - VarArg, - MMX, - Token, - Metadata, - Half, - BFloat, - Float, - Double, - Quad, - Integer, - Vector, - Pointer, - Struct, - Argument, - ExtendArgument, - TruncArgument, - HalfVecArgument, - SameVecWidthArgument, - PtrToArgument, - PtrToElt, - VecOfAnyPtrsToElt, - VecElementArgument, - Subdivide2Argument, - Subdivide4Argument, - VecOfBitcastsToInt, - AMX, - PPCQuad, - } Kind; - - union { - unsigned Integer_Width; - unsigned Float_Width; - unsigned Pointer_AddressSpace; - unsigned Struct_NumElements; - unsigned Argument_Info; - ElementCount Vector_Width; - }; - - enum ArgKind { - AK_Any, - AK_AnyInteger, - AK_AnyFloat, - AK_AnyVector, - AK_AnyPointer, - AK_MatchType = 7 - }; - - unsigned getArgumentNumber() const { - assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument || - Kind == PtrToElt || Kind == VecElementArgument || - Kind == Subdivide2Argument || Kind == Subdivide4Argument || - Kind == VecOfBitcastsToInt); - return Argument_Info >> 3; - } - ArgKind getArgumentKind() const { - assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument || - Kind == VecElementArgument || Kind == Subdivide2Argument || - Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt); - return (ArgKind)(Argument_Info & 7); - } - - // VecOfAnyPtrsToElt uses both an overloaded argument (for address space) - // and a reference argument (for matching vector width and element types) - unsigned getOverloadArgNumber() const { - assert(Kind == VecOfAnyPtrsToElt); - return Argument_Info >> 16; - } - unsigned getRefArgNumber() const { - assert(Kind == VecOfAnyPtrsToElt); - return Argument_Info & 0xFFFF; - } - - static IITDescriptor get(IITDescriptorKind K, unsigned Field) { - IITDescriptor Result = { K, { Field } }; - return Result; - } - - static IITDescriptor get(IITDescriptorKind K, unsigned short Hi, - unsigned short Lo) { - unsigned Field = Hi << 16 | Lo; - IITDescriptor Result = {K, {Field}}; - return Result; - } - - static IITDescriptor getVector(unsigned Width, bool IsScalable) { - IITDescriptor Result = {Vector, {0}}; - Result.Vector_Width = ElementCount::get(Width, IsScalable); - return Result; - } - }; - - /// Return the IIT table descriptor for the specified intrinsic into an array - /// of IITDescriptors. - void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); - - enum MatchIntrinsicTypesResult { - MatchIntrinsicTypes_Match = 0, - MatchIntrinsicTypes_NoMatchRet = 1, - MatchIntrinsicTypes_NoMatchArg = 2, - }; - - /// Match the specified function type with the type constraints specified by - /// the .td file. If the given type is an overloaded type it is pushed to the - /// ArgTys vector. - /// - /// Returns false if the given type matches with the constraints, true - /// otherwise. - MatchIntrinsicTypesResult - matchIntrinsicSignature(FunctionType *FTy, ArrayRef &Infos, - SmallVectorImpl &ArgTys); - - /// Verify if the intrinsic has variable arguments. This method is intended to - /// be called after all the fixed arguments have been matched first. - /// - /// This method returns true on error. - bool matchIntrinsicVarArg(bool isVarArg, ArrayRef &Infos); - - /// Gets the type arguments of an intrinsic call by matching type constraints - /// specified by the .td file. The overloaded types are pushed into the - /// AgTys vector. - /// - /// Returns false if the given function is not a valid intrinsic call. - bool getIntrinsicSignature(Function *F, SmallVectorImpl &ArgTys); - - // Checks if the intrinsic name matches with its signature and if not - // returns the declaration with the same signature and remangled name. - // An existing GlobalValue with the wanted name but with a wrong prototype - // or of the wrong kind will be renamed by adding ".renamed" to the name. - llvm::Optional remangleIntrinsicFunction(Function *F); - -} // End Intrinsic namespace - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Intrinsics.td b/suite/synctools/tablegen/include/llvm/IR/Intrinsics.td deleted file mode 100644 index f5248e82ad..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Intrinsics.td +++ /dev/null @@ -1,1939 +0,0 @@ -//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines properties of all LLVM intrinsics. -// -//===----------------------------------------------------------------------===// - -include "llvm/CodeGen/ValueTypes.td" -include "llvm/CodeGen/SDNodeProperties.td" - -//===----------------------------------------------------------------------===// -// Properties we keep track of for intrinsics. -//===----------------------------------------------------------------------===// - -class IntrinsicProperty { - bit IsDefault = is_default; -} - -// Intr*Mem - Memory properties. If no property is set, the worst case -// is assumed (it may read and write any memory it can get access to and it may -// have other side effects). - -// IntrNoMem - The intrinsic does not access memory or have any other side -// effects. It may be CSE'd deleted if dead, etc. -def IntrNoMem : IntrinsicProperty; - -// IntrReadMem - This intrinsic only reads from memory. It does not write to -// memory and has no other side effects. Therefore, it cannot be moved across -// potentially aliasing stores. However, it can be reordered otherwise and can -// be deleted if dead. -def IntrReadMem : IntrinsicProperty; - -// IntrWriteMem - This intrinsic only writes to memory, but does not read from -// memory, and has no other side effects. This means dead stores before calls -// to this intrinsics may be removed. -def IntrWriteMem : IntrinsicProperty; - -// IntrArgMemOnly - This intrinsic only accesses memory that its pointer-typed -// argument(s) points to, but may access an unspecified amount. Other than -// reads from and (possibly volatile) writes to memory, it has no side effects. -def IntrArgMemOnly : IntrinsicProperty; - -// IntrInaccessibleMemOnly -- This intrinsic only accesses memory that is not -// accessible by the module being compiled. This is a weaker form of IntrNoMem. -def IntrInaccessibleMemOnly : IntrinsicProperty; - -// IntrInaccessibleMemOrArgMemOnly -- This intrinsic only accesses memory that -// its pointer-typed arguments point to or memory that is not accessible -// by the module being compiled. This is a weaker form of IntrArgMemOnly. -def IntrInaccessibleMemOrArgMemOnly : IntrinsicProperty; - -// Commutative - This intrinsic is commutative: X op Y == Y op X. -def Commutative : IntrinsicProperty; - -// Throws - This intrinsic can throw. -def Throws : IntrinsicProperty; - -// Attribute index needs to match `AttrIndex` defined `Attributes.h`. -class AttrIndex { - int Value = idx; -} -def FuncIndex : AttrIndex<-1>; -def RetIndex : AttrIndex<0>; -class ArgIndex : AttrIndex; - -// NoCapture - The specified argument pointer is not captured by the intrinsic. -class NoCapture : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// NoAlias - The specified argument pointer is not aliasing other "noalias" pointer -// arguments of the intrinsic wrt. the intrinsic scope. -class NoAlias : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// NoUndef - The specified argument is neither undef nor poison. -class NoUndef : IntrinsicProperty { - int ArgNo = idx.Value; -} - -class Align : IntrinsicProperty { - int ArgNo = idx.Value; - int Align = align; -} - -// Returned - The specified argument is always the return value of the -// intrinsic. -class Returned : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// ImmArg - The specified argument must be an immediate. -class ImmArg : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// ReadOnly - The specified argument pointer is not written to through the -// pointer by the intrinsic. -class ReadOnly : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// WriteOnly - The intrinsic does not read memory through the specified -// argument pointer. -class WriteOnly : IntrinsicProperty { - int ArgNo = idx.Value; -} - -// ReadNone - The specified argument pointer is not dereferenced by the -// intrinsic. -class ReadNone : IntrinsicProperty { - int ArgNo = idx.Value; -} - -def IntrNoReturn : IntrinsicProperty; - -// IntrNoSync - Threads executing the intrinsic will not synchronize using -// memory or other means. Applied by default. -def IntrNoSync : IntrinsicProperty<1>; - -// Applied by default. -def IntrNoFree : IntrinsicProperty<1>; - -// Applied by default. -def IntrWillReturn : IntrinsicProperty<1>; - -// IntrCold - Calls to this intrinsic are cold. -// Parallels the cold attribute on LLVM IR functions. -def IntrCold : IntrinsicProperty; - -// IntrNoDuplicate - Calls to this intrinsic cannot be duplicated. -// Parallels the noduplicate attribute on LLVM IR functions. -def IntrNoDuplicate : IntrinsicProperty; - -// IntrNoMerge - Calls to this intrinsic cannot be merged -// Parallels the nomerge attribute on LLVM IR functions. -def IntrNoMerge : IntrinsicProperty; - -// IntrConvergent - Calls to this intrinsic are convergent and may not be made -// control-dependent on any additional values. -// Parallels the convergent attribute on LLVM IR functions. -def IntrConvergent : IntrinsicProperty; - -// This property indicates that the intrinsic is safe to speculate. -def IntrSpeculatable : IntrinsicProperty; - -// This property can be used to override the 'has no other side effects' -// language of the IntrNoMem, IntrReadMem, IntrWriteMem, and IntrArgMemOnly -// intrinsic properties. By default, intrinsics are assumed to have side -// effects, so this property is only necessary if you have defined one of -// the memory properties listed above. -// For this property, 'side effects' has the same meaning as 'side effects' -// defined by the hasSideEffects property of the TableGen Instruction class. -def IntrHasSideEffects : IntrinsicProperty; - -//===----------------------------------------------------------------------===// -// Types used by intrinsics. -//===----------------------------------------------------------------------===// - -class LLVMType { - ValueType VT = vt; - int isAny = false; -} - -class LLVMQualPointerType - : LLVMType{ - LLVMType ElTy = elty; - int AddrSpace = addrspace; -} - -class LLVMPointerType - : LLVMQualPointerType; - -class LLVMAnyPointerType - : LLVMType{ - LLVMType ElTy = elty; - - let isAny = true; -} - -// Match the type of another intrinsic parameter. Number is an index into the -// list of overloaded types for the intrinsic, excluding all the fixed types. -// The Number value must refer to a previously listed type. For example: -// Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> -// has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> -// refers to the first overloaded type, which is the 2nd argument. -class LLVMMatchType - : LLVMType{ - int Number = num; -} - -// Match the type of another intrinsic parameter that is expected to be based on -// an integral type (i.e. either iN or ), but change the scalar size to -// be twice as wide or half as wide as the other type. This is only useful when -// the intrinsic is overloaded, so the matched type should be declared as iAny. -class LLVMExtendedType : LLVMMatchType; -class LLVMTruncatedType : LLVMMatchType; - -// Match the scalar/vector of another intrinsic parameter but with a different -// element type. Either both are scalars or both are vectors with the same -// number of elements. -class LLVMScalarOrSameVectorWidth - : LLVMMatchType { - ValueType ElTy = elty.VT; -} - -class LLVMPointerTo : LLVMMatchType; -class LLVMPointerToElt : LLVMMatchType; -class LLVMVectorOfAnyPointersToElt : LLVMMatchType; -class LLVMVectorElementType : LLVMMatchType; - -// Match the type of another intrinsic parameter that is expected to be a -// vector type, but change the element count to be half as many. -class LLVMHalfElementsVectorType : LLVMMatchType; - -// Match the type of another intrinsic parameter that is expected to be a -// vector type (i.e. ) but with each element subdivided to -// form a vector with more elements that are smaller than the original. -class LLVMSubdivide2VectorType : LLVMMatchType; -class LLVMSubdivide4VectorType : LLVMMatchType; - -// Match the element count and bit width of another intrinsic parameter, but -// change the element type to an integer. -class LLVMVectorOfBitcastsToInt : LLVMMatchType; - -def llvm_void_ty : LLVMType; -let isAny = true in { - def llvm_any_ty : LLVMType; - def llvm_anyint_ty : LLVMType; - def llvm_anyfloat_ty : LLVMType; - def llvm_anyvector_ty : LLVMType; -} -def llvm_i1_ty : LLVMType; -def llvm_i8_ty : LLVMType; -def llvm_i16_ty : LLVMType; -def llvm_i32_ty : LLVMType; -def llvm_i64_ty : LLVMType; -def llvm_half_ty : LLVMType; -def llvm_bfloat_ty : LLVMType; -def llvm_float_ty : LLVMType; -def llvm_double_ty : LLVMType; -def llvm_f80_ty : LLVMType; -def llvm_f128_ty : LLVMType; -def llvm_ppcf128_ty : LLVMType; -def llvm_ptr_ty : LLVMPointerType; // i8* -def llvm_ptrptr_ty : LLVMPointerType; // i8** -def llvm_anyptr_ty : LLVMAnyPointerType; // (space)i8* -def llvm_empty_ty : LLVMType; // { } -def llvm_descriptor_ty : LLVMPointerType; // { }* -def llvm_metadata_ty : LLVMType; // !{...} -def llvm_token_ty : LLVMType; // token - -def llvm_x86mmx_ty : LLVMType; -def llvm_ptrx86mmx_ty : LLVMPointerType; // <1 x i64>* - -def llvm_x86amx_ty : LLVMType; - -def llvm_v2i1_ty : LLVMType; // 2 x i1 -def llvm_v4i1_ty : LLVMType; // 4 x i1 -def llvm_v8i1_ty : LLVMType; // 8 x i1 -def llvm_v16i1_ty : LLVMType; // 16 x i1 -def llvm_v32i1_ty : LLVMType; // 32 x i1 -def llvm_v64i1_ty : LLVMType; // 64 x i1 -def llvm_v128i1_ty : LLVMType; // 128 x i1 -def llvm_v256i1_ty : LLVMType; // 256 x i1 -def llvm_v512i1_ty : LLVMType; // 512 x i1 -def llvm_v1024i1_ty : LLVMType; //1024 x i1 - -def llvm_v1i8_ty : LLVMType; // 1 x i8 -def llvm_v2i8_ty : LLVMType; // 2 x i8 -def llvm_v4i8_ty : LLVMType; // 4 x i8 -def llvm_v8i8_ty : LLVMType; // 8 x i8 -def llvm_v16i8_ty : LLVMType; // 16 x i8 -def llvm_v32i8_ty : LLVMType; // 32 x i8 -def llvm_v64i8_ty : LLVMType; // 64 x i8 -def llvm_v128i8_ty : LLVMType; //128 x i8 -def llvm_v256i8_ty : LLVMType; //256 x i8 - -def llvm_v1i16_ty : LLVMType; // 1 x i16 -def llvm_v2i16_ty : LLVMType; // 2 x i16 -def llvm_v4i16_ty : LLVMType; // 4 x i16 -def llvm_v8i16_ty : LLVMType; // 8 x i16 -def llvm_v16i16_ty : LLVMType; // 16 x i16 -def llvm_v32i16_ty : LLVMType; // 32 x i16 -def llvm_v64i16_ty : LLVMType; // 64 x i16 -def llvm_v128i16_ty : LLVMType; //128 x i16 - -def llvm_v1i32_ty : LLVMType; // 1 x i32 -def llvm_v2i32_ty : LLVMType; // 2 x i32 -def llvm_v4i32_ty : LLVMType; // 4 x i32 -def llvm_v8i32_ty : LLVMType; // 8 x i32 -def llvm_v16i32_ty : LLVMType; // 16 x i32 -def llvm_v32i32_ty : LLVMType; // 32 x i32 -def llvm_v64i32_ty : LLVMType; // 64 x i32 -def llvm_v256i32_ty : LLVMType; //256 x i32 - -def llvm_v1i64_ty : LLVMType; // 1 x i64 -def llvm_v2i64_ty : LLVMType; // 2 x i64 -def llvm_v4i64_ty : LLVMType; // 4 x i64 -def llvm_v8i64_ty : LLVMType; // 8 x i64 -def llvm_v16i64_ty : LLVMType; // 16 x i64 -def llvm_v32i64_ty : LLVMType; // 32 x i64 - -def llvm_v1i128_ty : LLVMType; // 1 x i128 - -def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) -def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) -def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) -def llvm_v16f16_ty : LLVMType; // 16 x half (__fp16) -def llvm_v32f16_ty : LLVMType; // 32 x half (__fp16) -def llvm_v2bf16_ty : LLVMType; // 2 x bfloat (__bf16) -def llvm_v4bf16_ty : LLVMType; // 4 x bfloat (__bf16) -def llvm_v8bf16_ty : LLVMType; // 8 x bfloat (__bf16) -def llvm_v1f32_ty : LLVMType; // 1 x float -def llvm_v2f32_ty : LLVMType; // 2 x float -def llvm_v3f32_ty : LLVMType; // 3 x float -def llvm_v4f32_ty : LLVMType; // 4 x float -def llvm_v8f32_ty : LLVMType; // 8 x float -def llvm_v16f32_ty : LLVMType; // 16 x float -def llvm_v32f32_ty : LLVMType; // 32 x float -def llvm_v1f64_ty : LLVMType; // 1 x double -def llvm_v2f64_ty : LLVMType; // 2 x double -def llvm_v4f64_ty : LLVMType; // 4 x double -def llvm_v8f64_ty : LLVMType; // 8 x double -def llvm_v16f64_ty : LLVMType; // 16 x double - -def llvm_vararg_ty : LLVMType; // this means vararg here - -def llvm_externref_ty : LLVMType; -def llvm_funcref_ty : LLVMType; - -//===----------------------------------------------------------------------===// -// Intrinsic Definitions. -//===----------------------------------------------------------------------===// - -// Intrinsic class - This is used to define one LLVM intrinsic. The name of the -// intrinsic definition should start with "int_", then match the LLVM intrinsic -// name with the "llvm." prefix removed, and all "."s turned into "_"s. For -// example, llvm.bswap.i16 -> int_bswap_i16. -// -// * RetTypes is a list containing the return types expected for the -// intrinsic. -// * ParamTypes is a list containing the parameter types expected for the -// intrinsic. -// * Properties can be set to describe the behavior of the intrinsic. -// -class Intrinsic ret_types, - list param_types = [], - list intr_properties = [], - string name = "", - list sd_properties = [], - bit disable_default_attributes = true> : SDPatternOperator { - string LLVMName = name; - string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. - list RetTypes = ret_types; - list ParamTypes = param_types; - list IntrProperties = intr_properties; - let Properties = sd_properties; - - // Disable applying IntrinsicProperties that are marked default with - // IntrinsicProperty<1> - bit DisableDefaultAttributes = disable_default_attributes; - - bit isTarget = false; -} - -// Intrinsic with default attributes (disable_default_attributes = false). -class DefaultAttrsIntrinsic ret_types, - list param_types = [], - list intr_properties = [], - string name = "", - list sd_properties = []> - : Intrinsic {} - -/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this -/// specifies the name of the builtin. This provides automatic CBE and CFE -/// support. -class GCCBuiltin { - string GCCBuiltinName = name; -} - -class MSBuiltin { - string MSBuiltinName = name; -} - - -//===--------------- Variable Argument Handling Intrinsics ----------------===// -// - -def int_vastart : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; -def int_vacopy : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], - "llvm.va_copy">; -def int_vaend : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; - -//===------------------- Garbage Collection Intrinsics --------------------===// -// -def int_gcroot : Intrinsic<[], - [llvm_ptrptr_ty, llvm_ptr_ty]>; -def int_gcread : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptrptr_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_gcwrite : Intrinsic<[], - [llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], - [IntrArgMemOnly, NoCapture>, - NoCapture>]>; - -//===------------------- ObjC ARC runtime Intrinsics --------------------===// -// -// Note these are to support the Objective-C ARC optimizer which wants to -// eliminate retain and releases where possible. - -def int_objc_autorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_autoreleasePoolPop : Intrinsic<[], [llvm_ptr_ty]>; -def int_objc_autoreleasePoolPush : Intrinsic<[llvm_ptr_ty], []>; -def int_objc_autoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_copyWeak : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -def int_objc_destroyWeak : Intrinsic<[], [llvm_ptrptr_ty]>; -def int_objc_initWeak : Intrinsic<[llvm_ptr_ty], - [llvm_ptrptr_ty, - llvm_ptr_ty]>; -def int_objc_loadWeak : Intrinsic<[llvm_ptr_ty], - [llvm_ptrptr_ty]>; -def int_objc_loadWeakRetained : Intrinsic<[llvm_ptr_ty], - [llvm_ptrptr_ty]>; -def int_objc_moveWeak : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -def int_objc_release : Intrinsic<[], [llvm_ptr_ty]>; -def int_objc_retain : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retainAutorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retainAutoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retainAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retainBlock : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_storeStrong : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptr_ty]>; -def int_objc_storeWeak : Intrinsic<[llvm_ptr_ty], - [llvm_ptrptr_ty, - llvm_ptr_ty]>; -def int_objc_clang_arc_use : Intrinsic<[], - [llvm_vararg_ty]>; -def int_objc_clang_arc_noop_use : DefaultAttrsIntrinsic<[], - [llvm_vararg_ty], - [IntrInaccessibleMemOnly]>; -def int_objc_unsafeClaimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retainedObject : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_unretainedObject : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_unretainedPointer : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_retain_autorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; -def int_objc_sync_enter : Intrinsic<[llvm_i32_ty], - [llvm_ptr_ty]>; -def int_objc_sync_exit : Intrinsic<[llvm_i32_ty], - [llvm_ptr_ty]>; -def int_objc_arc_annotation_topdown_bbstart : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -def int_objc_arc_annotation_topdown_bbend : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -def int_objc_arc_annotation_bottomup_bbstart : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -def int_objc_arc_annotation_bottomup_bbend : Intrinsic<[], - [llvm_ptrptr_ty, - llvm_ptrptr_ty]>; -//===--------------- Swift asynchronous context intrinsics ----------------===// - -// Returns the location of the Swift asynchronous context (usually stored just -// before the frame pointer), and triggers the creation of a null context if it -// would otherwise be unneeded. -def int_swift_async_context_addr : Intrinsic<[llvm_ptrptr_ty], [], [IntrNoMem]>; - -//===--------------------- Code Generator Intrinsics ----------------------===// -// -def int_returnaddress : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_addressofreturnaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>; -def int_frameaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_sponentry : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>; -def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrReadMem], "llvm.read_register">; -def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], - [], "llvm.write_register">; -def int_read_volatile_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrHasSideEffects], - "llvm.read_volatile_register">; - -// Gets the address of the local variable area. This is typically a copy of the -// stack, frame, or base pointer depending on the type of prologue. -def int_localaddress : DefaultAttrsIntrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; - -// Escapes local variables to allow access from other functions. -def int_localescape : DefaultAttrsIntrinsic<[], [llvm_vararg_ty]>; - -// Given a function and the localaddress of a parent frame, returns a pointer -// to an escaped allocation indicated by the index. -def int_localrecover : DefaultAttrsIntrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -// Given the frame pointer passed into an SEH filter function, returns a -// pointer to the local variable area suitable for use with llvm.localrecover. -def int_eh_recoverfp : DefaultAttrsIntrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; - -// To mark the beginning/end of a try-scope for Windows SEH -EHa -// calls/invokes to these intrinsics are placed to model control flows -// caused by HW exceptions under option -EHa. -// calls/invokes to these intrinsics will be discarded during a codegen pass -// after EH tables are generated -def int_seh_try_begin : Intrinsic<[], [], [IntrWriteMem, IntrWillReturn]>; -def int_seh_try_end : Intrinsic<[], [], [IntrWriteMem, IntrWillReturn]>; -def int_seh_scope_begin : Intrinsic<[], [], [IntrNoMem]>; -def int_seh_scope_end : Intrinsic<[], [], [IntrNoMem]>; - -// Note: we treat stacksave/stackrestore as writemem because we don't otherwise -// model their dependencies on allocas. -def int_stacksave : DefaultAttrsIntrinsic<[llvm_ptr_ty]>, - GCCBuiltin<"__builtin_stack_save">; -def int_stackrestore : DefaultAttrsIntrinsic<[], [llvm_ptr_ty]>, - GCCBuiltin<"__builtin_stack_restore">; - -def int_get_dynamic_area_offset : DefaultAttrsIntrinsic<[llvm_anyint_ty]>; - -def int_thread_pointer : DefaultAttrsIntrinsic<[llvm_ptr_ty], [], [IntrNoMem]>, - GCCBuiltin<"__builtin_thread_pointer">; - -// IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly -// necessary for prefetch, however it does conveniently prevent the prefetch -// from being reordered overly much with respect to nearby access to the same -// memory while not impeding optimization. -def int_prefetch - : DefaultAttrsIntrinsic<[], [ llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], - [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, - ReadOnly>, NoCapture>, - ImmArg>, ImmArg>]>; -def int_pcmarker : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>; - -def int_readcyclecounter : DefaultAttrsIntrinsic<[llvm_i64_ty]>; - -// The assume intrinsic is marked InaccessibleMemOnly so that proper control -// dependencies will be maintained. -def int_assume : DefaultAttrsIntrinsic< - [], [llvm_i1_ty], [IntrInaccessibleMemOnly, NoUndef>]>; - -// 'llvm.experimental.noalias.scope.decl' intrinsic: Inserted at the location of -// noalias scope declaration. Makes it possible to identify that a noalias scope -// is only valid inside the body of a loop. -// -// Purpose of the different arguments: -// - arg0: id.scope: metadata representing the scope declaration. -def int_experimental_noalias_scope_decl - : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], - [IntrInaccessibleMemOnly]>; // blocks LICM and some more - -// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack -// guard to the correct place on the stack frame. -def int_stackprotector : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; -def int_stackguard : DefaultAttrsIntrinsic<[llvm_ptr_ty], [], []>; - -// A cover for instrumentation based profiling. -def int_instrprof_cover : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, - llvm_i32_ty, llvm_i32_ty]>; - -// A counter increment for instrumentation based profiling. -def int_instrprof_increment : Intrinsic<[], - [llvm_ptr_ty, llvm_i64_ty, - llvm_i32_ty, llvm_i32_ty]>; - -// A counter increment with step for instrumentation based profiling. -def int_instrprof_increment_step : Intrinsic<[], - [llvm_ptr_ty, llvm_i64_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i64_ty]>; - -// A call to profile runtime for value profiling of target expressions -// through instrumentation based profiling. -def int_instrprof_value_profile : Intrinsic<[], - [llvm_ptr_ty, llvm_i64_ty, - llvm_i64_ty, llvm_i32_ty, - llvm_i32_ty]>; - -def int_call_preallocated_setup : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty]>; -def int_call_preallocated_arg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_i32_ty]>; -def int_call_preallocated_teardown : DefaultAttrsIntrinsic<[], [llvm_token_ty]>; - -//===------------------- Standard C Library Intrinsics --------------------===// -// - -def int_memcpy : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, - llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, IntrNoFree, - NoCapture>, NoCapture>, - NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>, - ImmArg>]>; - -// Memcpy semantic that is guaranteed to be inlined. -// In particular this means that the generated code is not allowed to call any -// external function. -// The third argument (specifying the size) must be a constant. -def int_memcpy_inline - : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, IntrNoFree, - NoCapture>, NoCapture>, - NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>, - ImmArg>, ImmArg>]>; - -def int_memmove : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, - llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, IntrNoFree, - NoCapture>, NoCapture>, - WriteOnly>, ReadOnly>, - ImmArg>]>; -def int_memset : Intrinsic<[], - [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, - llvm_i1_ty], - [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, - IntrNoFree, - NoCapture>, WriteOnly>, - ImmArg>]>; - -// FIXME: Add version of these floating point intrinsics which allow non-default -// rounding modes and FP exception handling. - -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { - def int_fma : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>]>; - def int_fmuladd : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>]>; - - // These functions do not read memory, but are sensitive to the - // rounding mode. LLVM purposely does not model changes to the FP - // environment so they can be treated as readnone. - def int_sqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>; - def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_log10: DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_log2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_exp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_exp2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_fabs : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_copysign : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_floor : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_ceil : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_trunc : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_rint : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_nearbyint : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_round : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_roundeven : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; - def int_canonicalize : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], - [IntrNoMem]>; - - def int_lround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; - def int_llround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; - def int_lrint : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; - def int_llrint : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; -} - -def int_minnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; -def int_maxnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; -def int_minimum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; -def int_maximum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; - -// Internal interface for object size checking -def int_objectsize : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [llvm_anyptr_ty, llvm_i1_ty, - llvm_i1_ty, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>, - ImmArg>]>, - GCCBuiltin<"__builtin_object_size">; - -//===--------------- Access to Floating Point Environment -----------------===// -// - -let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in { - def int_flt_rounds : DefaultAttrsIntrinsic<[llvm_i32_ty], []>; - def int_set_rounding : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>; -} - -//===--------------- Constrained Floating Point Intrinsics ----------------===// -// - -let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in { - def int_experimental_constrained_fadd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_fsub : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_fmul : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_fdiv : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_frem : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fma : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fmuladd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fptosi : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fptoui : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_sitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ llvm_anyint_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_uitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ llvm_anyint_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fptrunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - - def int_experimental_constrained_fpext : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty ]>; - - // These intrinsics are sensitive to the rounding mode so we need constrained - // versions of each of them. When strict rounding and exception control are - // not required the non-constrained versions of these intrinsics should be - // used. - def int_experimental_constrained_sqrt : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_powi : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_i32_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_sin : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_cos : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_pow : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_log : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_log10: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_log2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_exp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_exp2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_rint : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_nearbyint : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_lrint : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_llrint : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_maxnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_minnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_maximum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_minimum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_ceil : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_floor : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_lround : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_llround : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], - [ llvm_anyfloat_ty, - llvm_metadata_ty ]>; - def int_experimental_constrained_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_roundeven : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty ]>; - def int_experimental_constrained_trunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], - [ LLVMMatchType<0>, - llvm_metadata_ty ]>; - - // Constrained floating-point comparison (quiet and signaling variants). - // Third operand is the predicate represented as a metadata string. - def int_experimental_constrained_fcmp - : DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], - [ llvm_anyfloat_ty, LLVMMatchType<0>, - llvm_metadata_ty, llvm_metadata_ty ]>; - def int_experimental_constrained_fcmps - : DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], - [ llvm_anyfloat_ty, LLVMMatchType<0>, - llvm_metadata_ty, llvm_metadata_ty ]>; -} -// FIXME: Consider maybe adding intrinsics for sitofp, uitofp. - -//===------------------------- Expect Intrinsics --------------------------===// -// -def int_expect : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrWillReturn]>; - -def int_expect_with_probability : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_double_ty], - [IntrNoMem, IntrWillReturn]>; - -//===-------------------- Bit Manipulation Intrinsics ---------------------===// -// - -// None of these intrinsics accesses memory at all. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { - def int_bswap: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_ctpop: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_bitreverse : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_fshl : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_fshr : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; -} - -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>] in { - def int_ctlz : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; - def int_cttz : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; -} - -//===------------------------ Debugger Intrinsics -------------------------===// -// - -// None of these intrinsics accesses memory at all...but that doesn't -// mean the optimizers can change them aggressively. Special handling -// needed in a few places. These synthetic intrinsics have no -// side-effects and just mark information about their operands. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { - def int_dbg_declare : DefaultAttrsIntrinsic<[], - [llvm_metadata_ty, - llvm_metadata_ty, - llvm_metadata_ty]>; - def int_dbg_value : DefaultAttrsIntrinsic<[], - [llvm_metadata_ty, - llvm_metadata_ty, - llvm_metadata_ty]>; - def int_dbg_addr : DefaultAttrsIntrinsic<[], - [llvm_metadata_ty, - llvm_metadata_ty, - llvm_metadata_ty]>; - def int_dbg_label : DefaultAttrsIntrinsic<[], - [llvm_metadata_ty]>; -} - -//===------------------ Exception Handling Intrinsics----------------------===// -// - -// The result of eh.typeid.for depends on the enclosing function, but inside a -// given function it is 'const' and may be CSE'd etc. -def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; - -def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; -def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; - -// eh.exceptionpointer returns the pointer to the exception caught by -// the given `catchpad`. -def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], - [IntrNoMem]>; - -// Gets the exception code from a catchpad token. Only used on some platforms. -def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>; - -// __builtin_unwind_init is an undocumented GCC intrinsic that causes all -// callee-saved registers to be saved and restored (regardless of whether they -// are used) in the calling function. It is used by libgcc_eh. -def int_eh_unwind_init: Intrinsic<[]>, - GCCBuiltin<"__builtin_unwind_init">; - -def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; - -def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; -def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty], [IntrNoMem]>; - -def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; -def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; -def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; -def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>; - -//===---------------- Generic Variable Attribute Intrinsics----------------===// -// -def int_var_annotation : DefaultAttrsIntrinsic< - [], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrInaccessibleMemOnly], "llvm.var.annotation">; - -def int_ptr_annotation : DefaultAttrsIntrinsic< - [LLVMAnyPointerType], - [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrInaccessibleMemOnly], "llvm.ptr.annotation">; - -def int_annotation : DefaultAttrsIntrinsic< - [llvm_anyint_ty], - [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrInaccessibleMemOnly], "llvm.annotation">; - -// Annotates the current program point with metadata strings which are emitted -// as CodeView debug info records. This is expensive, as it disables inlining -// and is modelled as having side effects. -def int_codeview_annotation : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], - [IntrInaccessibleMemOnly, IntrNoDuplicate, IntrWillReturn], - "llvm.codeview.annotation">; - -//===------------------------ Trampoline Intrinsics -----------------------===// -// -def int_init_trampoline : DefaultAttrsIntrinsic< - [], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>, WriteOnly>, - ReadNone>, ReadNone>]>, - GCCBuiltin<"__builtin_init_trampoline">; - -def int_adjust_trampoline : DefaultAttrsIntrinsic< - [llvm_ptr_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>, - GCCBuiltin<"__builtin_adjust_trampoline">; - -//===------------------------ Overflow Intrinsics -------------------------===// -// - -// Expose the carry flag from add operations on two integrals. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { - def int_sadd_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_uadd_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - - def int_ssub_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_usub_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - - def int_smul_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; - def int_umul_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMMatchType<0>, LLVMMatchType<0>]>; -} -//===------------------------- Saturation Arithmetic Intrinsics ---------------------===// -// -def int_sadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]>; -def int_uadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]>; -def int_ssub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_usub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_sshl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_ushl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -//===------------------------- Fixed Point Arithmetic Intrinsics ---------------------===// -// -def int_smul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - Commutative, ImmArg>]>; - -def int_umul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - Commutative, ImmArg>]>; - -def int_sdiv_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_udiv_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -//===------------------- Fixed Point Saturation Arithmetic Intrinsics ----------------===// -// -def int_smul_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - Commutative, ImmArg>]>; -def int_umul_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - Commutative, ImmArg>]>; - -def int_sdiv_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_udiv_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -//===------------------ Integer Min/Max/Abs Intrinsics --------------------===// -// -def int_abs : DefaultAttrsIntrinsic< - [llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>]>; - -def int_smax : DefaultAttrsIntrinsic< - [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_smin : DefaultAttrsIntrinsic< - [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_umax : DefaultAttrsIntrinsic< - [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; -def int_umin : DefaultAttrsIntrinsic< - [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -//===------------------------- Memory Use Markers -------------------------===// -// -def int_lifetime_start : DefaultAttrsIntrinsic<[], - [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, - NoCapture>, - ImmArg>]>; -def int_lifetime_end : DefaultAttrsIntrinsic<[], - [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, - NoCapture>, - ImmArg>]>; -def int_invariant_start : DefaultAttrsIntrinsic<[llvm_descriptor_ty], - [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, - NoCapture>, - ImmArg>]>; -def int_invariant_end : DefaultAttrsIntrinsic<[], - [llvm_descriptor_ty, llvm_i64_ty, - llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, - NoCapture>, - ImmArg>]>; - -// launder.invariant.group can't be marked with 'readnone' (IntrNoMem), -// because it would cause CSE of two barriers with the same argument. -// Inaccessiblememonly says that the barrier doesn't read the argument, -// but it changes state not accessible to this module. This way -// we can DSE through the barrier because it doesn't read the value -// after store. Although the barrier doesn't modify any memory it -// can't be marked as readonly, because it would be possible to -// CSE 2 barriers with store in between. -// The argument also can't be marked with 'returned' attribute, because -// it would remove barrier. -// Note that it is still experimental, which means that its semantics -// might change in the future. -def int_launder_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [LLVMMatchType<0>], - [IntrInaccessibleMemOnly, IntrSpeculatable, IntrWillReturn]>; - - -def int_strip_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [LLVMMatchType<0>], - [IntrSpeculatable, IntrNoMem, IntrWillReturn]>; - -//===------------------------ Stackmap Intrinsics -------------------------===// -// -def int_experimental_stackmap : DefaultAttrsIntrinsic<[], - [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty], - [Throws]>; -def int_experimental_patchpoint_void : DefaultAttrsIntrinsic<[], - [llvm_i64_ty, llvm_i32_ty, - llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty], - [Throws]>; -def int_experimental_patchpoint_i64 : DefaultAttrsIntrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty], - [Throws]>; - - -//===------------------------ Garbage Collection Intrinsics ---------------===// -// These are documented in docs/Statepoint.rst - -def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_anyptr_ty, llvm_i32_ty, - llvm_i32_ty, llvm_vararg_ty], - [Throws, ImmArg>, - ImmArg>, ImmArg>, - ImmArg>]>; - -def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_token_ty], - [IntrNoMem]>; -def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty], - [llvm_token_ty, llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, ImmArg>, - ImmArg>]>; - -def int_experimental_gc_get_pointer_base : Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrWillReturn, - ReadNone>, NoCapture>]>; - -def int_experimental_gc_get_pointer_offset : Intrinsic<[llvm_i64_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrWillReturn, - ReadNone>, NoCapture>]>; - -//===------------------------ Coroutine Intrinsics ---------------===// -// These are documented in docs/Coroutines.rst - -// Coroutine Structure Intrinsics. - -def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty, - llvm_ptr_ty, llvm_ptr_ty], - [IntrArgMemOnly, IntrReadMem, - ReadNone>, ReadOnly>, - NoCapture>]>; -def int_coro_id_retcon : Intrinsic<[llvm_token_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, - llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], - []>; -def int_coro_id_retcon_once : Intrinsic<[llvm_token_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, - llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], - []>; -def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>; -def int_coro_id_async : Intrinsic<[llvm_token_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], - []>; -def int_coro_async_context_alloc : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - []>; -def int_coro_async_context_dealloc : Intrinsic<[], - [llvm_ptr_ty], - []>; -def int_coro_async_resume : Intrinsic<[llvm_ptr_ty], - [], - []>; -def int_coro_async_size_replace : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], []>; -def int_coro_suspend_async - : Intrinsic<[llvm_any_ty], - [llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty], []>; -def int_coro_prepare_async : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], - [IntrNoMem]>; -def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], - [WriteOnly>]>; - -def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], - [IntrReadMem, IntrArgMemOnly, - ReadOnly>, - NoCapture>]>; -def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>; -def int_coro_end_async - : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty, llvm_vararg_ty], []>; - -def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; -def int_coro_noop : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; -def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; -def int_coro_align : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; - -def int_coro_save : Intrinsic<[llvm_token_ty], [llvm_ptr_ty], []>; -def int_coro_suspend : Intrinsic<[llvm_i8_ty], [llvm_token_ty, llvm_i1_ty], []>; -def int_coro_suspend_retcon : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], []>; -def int_coro_prepare_retcon : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], - [IntrNoMem]>; -def int_coro_alloca_alloc : Intrinsic<[llvm_token_ty], - [llvm_anyint_ty, llvm_i32_ty], []>; -def int_coro_alloca_get : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], []>; -def int_coro_alloca_free : Intrinsic<[], [llvm_token_ty], []>; - -// Coroutine Manipulation Intrinsics. - -def int_coro_resume : Intrinsic<[], [llvm_ptr_ty], [Throws]>; -def int_coro_destroy : Intrinsic<[], [llvm_ptr_ty], [Throws]>; -def int_coro_done : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], - [IntrArgMemOnly, ReadOnly>, - NoCapture>]>; -def int_coro_promise : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_i32_ty, llvm_i1_ty], - [IntrNoMem, NoCapture>]>; - -// Coroutine Lowering Intrinsics. Used internally by coroutine passes. - -def int_coro_subfn_addr : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly, - ReadOnly>, - NoCapture>]>; - -///===-------------------------- Other Intrinsics --------------------------===// -// -def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold]>, - GCCBuiltin<"__builtin_trap">; -def int_debugtrap : Intrinsic<[]>, - GCCBuiltin<"__builtin_debugtrap">; -def int_ubsantrap : Intrinsic<[], [llvm_i8_ty], - [IntrNoReturn, IntrCold, ImmArg>]>; - -// Support for dynamic deoptimization (or de-specialization) -def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], - [Throws]>; - -// Support for speculative runtime guards -def int_experimental_guard : DefaultAttrsIntrinsic<[], [llvm_i1_ty, llvm_vararg_ty], - [Throws]>; - -// Supports widenable conditions for guards represented as explicit branches. -def int_experimental_widenable_condition : DefaultAttrsIntrinsic<[llvm_i1_ty], [], - [IntrInaccessibleMemOnly, IntrWillReturn, IntrSpeculatable]>; - -// NOP: calls/invokes to this intrinsic are removed by codegen -def int_donothing : DefaultAttrsIntrinsic<[], [], [IntrNoMem, IntrWillReturn]>; - -// This instruction has no actual effect, though it is treated by the optimizer -// has having opaque side effects. This may be inserted into loops to ensure -// that they are not removed even if they turn out to be empty, for languages -// which specify that infinite loops must be preserved. -def int_sideeffect : DefaultAttrsIntrinsic<[], [], [IntrInaccessibleMemOnly, IntrWillReturn]>; - -// The pseudoprobe intrinsic works as a place holder to the block it probes. -// Like the sideeffect intrinsic defined above, this intrinsic is treated by the -// optimizer as having opaque side effects so that it won't be get rid of or moved -// out of the block it probes. -def int_pseudoprobe : DefaultAttrsIntrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrInaccessibleMemOnly, IntrWillReturn]>; - -// Arithmetic fence intrinsic. -def int_arithmetic_fence : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -// Intrinsics to support half precision floating point format -let IntrProperties = [IntrNoMem, IntrWillReturn] in { -def int_convert_to_fp16 : DefaultAttrsIntrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>; -def int_convert_from_fp16 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>; -} - -// Saturating floating point to integer intrinsics -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { -def int_fptoui_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; -def int_fptosi_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; -} - -// Clear cache intrinsic, default to ignore (ie. emit nothing) -// maps to void __clear_cache() on supporting platforms -def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], - [], "llvm.clear_cache">; - -// Intrinsic to detect whether its argument is a constant. -def int_is_constant : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], - [IntrNoMem, IntrWillReturn, IntrConvergent], - "llvm.is.constant">; - -// Intrinsic to mask out bits of a pointer. -def int_ptrmask: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_experimental_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [], [IntrNoMem]>; - -//===---------------- Vector Predication Intrinsics --------------===// -// Memory Intrinsics -def int_vp_store : DefaultAttrsIntrinsic<[], - [ llvm_anyvector_ty, - LLVMAnyPointerType>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty], - [ NoCapture>, IntrNoSync, IntrWriteMem, IntrArgMemOnly, IntrWillReturn ]>; - -def int_vp_load : DefaultAttrsIntrinsic<[ llvm_anyvector_ty], - [ LLVMAnyPointerType>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty], - [ NoCapture>, IntrNoSync, IntrReadMem, IntrWillReturn, IntrArgMemOnly ]>; - -def int_vp_gather: DefaultAttrsIntrinsic<[ llvm_anyvector_ty], - [ LLVMVectorOfAnyPointersToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty], - [ IntrReadMem, IntrNoSync, IntrWillReturn, IntrArgMemOnly ]>; - -def int_vp_scatter: DefaultAttrsIntrinsic<[], - [ llvm_anyvector_ty, - LLVMVectorOfAnyPointersToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty], - [ IntrArgMemOnly, IntrNoSync, IntrWillReturn ]>; // TODO allow IntrNoCapture for vectors of pointers - -// Speculatable Binary operators -let IntrProperties = [IntrSpeculatable, IntrNoMem, IntrNoSync, IntrWillReturn] in { - def int_vp_add : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_sub : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_mul : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_ashr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_lshr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_shl : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_or : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_and : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_xor : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; -} - -// Non-speculatable binary operators. -let IntrProperties = [IntrNoMem, IntrNoSync, IntrWillReturn] in { - def int_vp_sdiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_udiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_srem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_urem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; -} - -// Floating-point arithmetic. -let IntrProperties = - [IntrSpeculatable, IntrNoMem, IntrNoSync, IntrWillReturn] in { - def int_vp_fadd : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_fsub : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_fmul : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_fdiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_frem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; -} -// Shuffles. -def int_vp_select : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty]>; - -def int_vp_merge : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], - [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty]>; - -// Reductions -let IntrProperties = [IntrSpeculatable, IntrNoMem, IntrNoSync, IntrWillReturn] in { - def int_vp_reduce_fadd : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_fmul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_add : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_mul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_and : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_or : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_xor : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_smax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_smin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_umax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_umin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_fmax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; - def int_vp_reduce_fmin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty]>; -} - -def int_get_active_lane_mask: - DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyint_ty, LLVMMatchType<1>], - [IntrNoMem, IntrNoSync, IntrWillReturn]>; - -def int_experimental_vp_splice: - DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -//===-------------------------- Masked Intrinsics -------------------------===// -// -def int_masked_load: - DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMAnyPointerType>, llvm_i32_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrArgMemOnly, IntrWillReturn, ImmArg>]>; - -def int_masked_store: - DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMAnyPointerType>, - llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, - ImmArg>]>; - -def int_masked_gather: - DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrWillReturn, ImmArg>]>; - -def int_masked_scatter: - DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrWriteMem, IntrWillReturn, ImmArg>]>; - -def int_masked_expandload: - DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMPointerToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>], - [IntrReadMem, IntrWillReturn]>; - -def int_masked_compressstore: - DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrWriteMem, IntrArgMemOnly, IntrWillReturn]>; - -// Test whether a pointer is associated with a type metadata identifier. -def int_type_test : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], - [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; - -// Safely loads a function pointer from a virtual table pointer using type metadata. -def int_type_checked_load : DefaultAttrsIntrinsic<[llvm_ptr_ty, llvm_i1_ty], - [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], - [IntrNoMem, IntrWillReturn]>; - -// Create a branch funnel that implements an indirect call to a limited set of -// callees. This needs to be a musttail call. -def int_icall_branch_funnel : DefaultAttrsIntrinsic<[], [llvm_vararg_ty], []>; - -def int_load_relative: DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], - [IntrReadMem, IntrArgMemOnly]>; - -def int_asan_check_memaccess : - Intrinsic<[],[llvm_ptr_ty, llvm_i32_ty], [ImmArg>]>; - -def int_hwasan_check_memaccess : - Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [ImmArg>]>; -def int_hwasan_check_memaccess_shortgranules : - Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [ImmArg>]>; - -// Xray intrinsics -//===----------------------------------------------------------------------===// -// Custom event logging for x-ray. -// Takes a pointer to a string and the length of the string. -def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], - [IntrWriteMem, NoCapture>, - ReadOnly>]>; -// Typed event logging for x-ray. -// Takes a numeric type tag, a pointer to a string and the length of the string. -def int_xray_typedevent : Intrinsic<[], [llvm_i16_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrWriteMem, NoCapture>, - ReadOnly>]>; -//===----------------------------------------------------------------------===// - -//===------ Memory intrinsics with element-wise atomicity guarantees ------===// -// - -// @llvm.memcpy.element.unordered.atomic.*(dest, src, length, elementsize) -def int_memcpy_element_unordered_atomic - : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty], - [IntrArgMemOnly, IntrWillReturn, IntrNoSync, - NoCapture>, NoCapture>, - WriteOnly>, ReadOnly>, - ImmArg>]>; - -// @llvm.memmove.element.unordered.atomic.*(dest, src, length, elementsize) -def int_memmove_element_unordered_atomic - : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty], - [IntrArgMemOnly, IntrWillReturn, IntrNoSync, - NoCapture>, NoCapture>, - WriteOnly>, ReadOnly>, - ImmArg>]>; - -// @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize) -def int_memset_element_unordered_atomic - : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, IntrNoSync, - NoCapture>, WriteOnly>, - ImmArg>]>; - -//===------------------------ Reduction Intrinsics ------------------------===// -// -let IntrProperties = [IntrNoMem] in { - - def int_vector_reduce_fadd : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty]>; - def int_vector_reduce_fmul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMVectorElementType<0>, - llvm_anyvector_ty]>; - def int_vector_reduce_add : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_mul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_and : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_or : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_xor : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_smax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_smin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_umax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_umin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_fmax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; - def int_vector_reduce_fmin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty]>; -} - -//===----- Matrix intrinsics ---------------------------------------------===// - -def int_matrix_transpose - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], - [ IntrNoSync, IntrWillReturn, IntrNoMem, IntrSpeculatable, ImmArg>, - ImmArg>]>; - -def int_matrix_multiply - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_anyvector_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], - [IntrNoSync, IntrWillReturn, IntrNoMem, IntrSpeculatable, ImmArg>, - ImmArg>, ImmArg>]>; - -def int_matrix_column_major_load - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMPointerToElt<0>, llvm_anyint_ty, llvm_i1_ty, - llvm_i32_ty, llvm_i32_ty], - [IntrNoSync, IntrWillReturn, IntrArgMemOnly, IntrReadMem, - NoCapture>, ImmArg>, ImmArg>, - ImmArg>]>; - -def int_matrix_column_major_store - : DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMPointerToElt<0>, - llvm_anyint_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoSync, IntrWillReturn, IntrArgMemOnly, IntrWriteMem, - WriteOnly>, NoCapture>, - ImmArg>, ImmArg>, ImmArg>]>; - -//===---------- Intrinsics to control hardware supported loops ----------===// - -// Specify that the value given is the number of iterations that the next loop -// will execute. -def int_set_loop_iterations : - DefaultAttrsIntrinsic<[], [llvm_anyint_ty], [IntrNoDuplicate]>; - -// Same as the above, but produces a value (the same as the input operand) to -// be fed into the loop. -def int_start_loop_iterations : - DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoDuplicate]>; - -// Specify that the value given is the number of iterations that the next loop -// will execute. Also test that the given count is not zero, allowing it to -// control entry to a 'while' loop. -def int_test_set_loop_iterations : - DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; - -// Same as the above, but produces an extra value (the same as the input -// operand) to be fed into the loop. -def int_test_start_loop_iterations : - DefaultAttrsIntrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>], - [IntrNoDuplicate]>; - -// Decrement loop counter by the given argument. Return false if the loop -// should exit. -def int_loop_decrement : - DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; - -// Decrement the first operand (the loop counter) by the second operand (the -// maximum number of elements processed in an iteration). Return the remaining -// number of iterations still to be executed. This is effectively a sub which -// can be used with a phi, icmp and br to control the number of iterations -// executed, as usual. Any optimisations are allowed to treat it is a sub, and -// it's scevable, so it's the backends responsibility to handle cases where it -// may be optimised. -def int_loop_decrement_reg : - DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoDuplicate]>; - -//===----- Intrinsics that are used to provide predicate information -----===// - -def int_ssa_copy : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], - [IntrNoMem, Returned>]>; - -//===------- Intrinsics that are used to preserve debug information -------===// - -def int_preserve_array_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty, llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, - ImmArg>, - ImmArg>]>; -def int_preserve_union_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrNoMem, - ImmArg>]>; -def int_preserve_struct_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty, llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, - ImmArg>, - ImmArg>]>; - -//===------------ Intrinsics to perform common vector shuffles ------------===// - -def int_experimental_vector_reverse : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>], - [IntrNoMem]>; - -//===---------- Intrinsics to query properties of scalable vectors --------===// -def int_vscale : DefaultAttrsIntrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; - -//===---------- Intrinsics to perform subvector insertion/extraction ------===// -def int_experimental_vector_insert : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - -def int_experimental_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - -//===---------- Named shufflevector intrinsics ------===// -def int_experimental_vector_splice : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - -//===----------------- Pointer Authentication Intrinsics ------------------===// -// - -// Sign an unauthenticated pointer using the specified key and discriminator, -// passed in that order. -// Returns the first argument, with some known bits replaced with a signature. -def int_ptrauth_sign : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - -// Authenticate a signed pointer, using the specified key and discriminator. -// Returns the first argument, with the signature bits removed. -// The signature must be valid. -def int_ptrauth_auth : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem,ImmArg>]>; - -// Authenticate a signed pointer and resign it. -// The second (key) and third (discriminator) arguments specify the signing -// schema used for authenticating. -// The fourth and fifth arguments specify the schema used for signing. -// The signature must be valid. -// This is a combined form of @llvm.ptrauth.sign and @llvm.ptrauth.auth, with -// an additional integrity guarantee on the intermediate value. -def int_ptrauth_resign : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, - llvm_i32_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>, - ImmArg>]>; - -// Strip the embedded signature out of a signed pointer. -// The second argument specifies the key. -// This behaves like @llvm.ptrauth.auth, but doesn't require the signature to -// be valid. -def int_ptrauth_strip : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -// Blend a small integer discriminator with an address discriminator, producing -// a new discriminator value. -def int_ptrauth_blend : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - -// Compute the signature of a value, using a given discriminator. -// This differs from @llvm.ptrauth.sign in that it doesn't embed the computed -// signature in the pointer, but instead returns the signature as a value. -// That allows it to be used to sign non-pointer data: in that sense, it is -// generic. There is no generic @llvm.ptrauth.auth: instead, the signature -// can be computed using @llvm.ptrauth.sign_generic, and compared with icmp. -def int_ptrauth_sign_generic : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Target-specific intrinsics -//===----------------------------------------------------------------------===// - -include "llvm/IR/IntrinsicsPowerPC.td" -include "llvm/IR/IntrinsicsX86.td" -include "llvm/IR/IntrinsicsARM.td" -include "llvm/IR/IntrinsicsAArch64.td" -include "llvm/IR/IntrinsicsXCore.td" -include "llvm/IR/IntrinsicsHexagon.td" -include "llvm/IR/IntrinsicsNVVM.td" -include "llvm/IR/IntrinsicsMips.td" -include "llvm/IR/IntrinsicsAMDGPU.td" -include "llvm/IR/IntrinsicsBPF.td" -include "llvm/IR/IntrinsicsSystemZ.td" -include "llvm/IR/IntrinsicsWebAssembly.td" -include "llvm/IR/IntrinsicsRISCV.td" -include "llvm/IR/IntrinsicsVE.td" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.h deleted file mode 100644 index 9408df01d8..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.h +++ /dev/null @@ -1,899 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_AARCH64_ENUMS_H -#define LLVM_IR_INTRINSIC_AARCH64_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum AARCH64Intrinsics : unsigned { -// Enum values for intrinsics - aarch64_addg = 364, // llvm.aarch64.addg - aarch64_clrex, // llvm.aarch64.clrex - aarch64_cls, // llvm.aarch64.cls - aarch64_cls64, // llvm.aarch64.cls64 - aarch64_crc32b, // llvm.aarch64.crc32b - aarch64_crc32cb, // llvm.aarch64.crc32cb - aarch64_crc32ch, // llvm.aarch64.crc32ch - aarch64_crc32cw, // llvm.aarch64.crc32cw - aarch64_crc32cx, // llvm.aarch64.crc32cx - aarch64_crc32h, // llvm.aarch64.crc32h - aarch64_crc32w, // llvm.aarch64.crc32w - aarch64_crc32x, // llvm.aarch64.crc32x - aarch64_crypto_aesd, // llvm.aarch64.crypto.aesd - aarch64_crypto_aese, // llvm.aarch64.crypto.aese - aarch64_crypto_aesimc, // llvm.aarch64.crypto.aesimc - aarch64_crypto_aesmc, // llvm.aarch64.crypto.aesmc - aarch64_crypto_bcaxs, // llvm.aarch64.crypto.bcaxs - aarch64_crypto_bcaxu, // llvm.aarch64.crypto.bcaxu - aarch64_crypto_eor3s, // llvm.aarch64.crypto.eor3s - aarch64_crypto_eor3u, // llvm.aarch64.crypto.eor3u - aarch64_crypto_rax1, // llvm.aarch64.crypto.rax1 - aarch64_crypto_sha1c, // llvm.aarch64.crypto.sha1c - aarch64_crypto_sha1h, // llvm.aarch64.crypto.sha1h - aarch64_crypto_sha1m, // llvm.aarch64.crypto.sha1m - aarch64_crypto_sha1p, // llvm.aarch64.crypto.sha1p - aarch64_crypto_sha1su0, // llvm.aarch64.crypto.sha1su0 - aarch64_crypto_sha1su1, // llvm.aarch64.crypto.sha1su1 - aarch64_crypto_sha256h, // llvm.aarch64.crypto.sha256h - aarch64_crypto_sha256h2, // llvm.aarch64.crypto.sha256h2 - aarch64_crypto_sha256su0, // llvm.aarch64.crypto.sha256su0 - aarch64_crypto_sha256su1, // llvm.aarch64.crypto.sha256su1 - aarch64_crypto_sha512h, // llvm.aarch64.crypto.sha512h - aarch64_crypto_sha512h2, // llvm.aarch64.crypto.sha512h2 - aarch64_crypto_sha512su0, // llvm.aarch64.crypto.sha512su0 - aarch64_crypto_sha512su1, // llvm.aarch64.crypto.sha512su1 - aarch64_crypto_sm3partw1, // llvm.aarch64.crypto.sm3partw1 - aarch64_crypto_sm3partw2, // llvm.aarch64.crypto.sm3partw2 - aarch64_crypto_sm3ss1, // llvm.aarch64.crypto.sm3ss1 - aarch64_crypto_sm3tt1a, // llvm.aarch64.crypto.sm3tt1a - aarch64_crypto_sm3tt1b, // llvm.aarch64.crypto.sm3tt1b - aarch64_crypto_sm3tt2a, // llvm.aarch64.crypto.sm3tt2a - aarch64_crypto_sm3tt2b, // llvm.aarch64.crypto.sm3tt2b - aarch64_crypto_sm4e, // llvm.aarch64.crypto.sm4e - aarch64_crypto_sm4ekey, // llvm.aarch64.crypto.sm4ekey - aarch64_crypto_xar, // llvm.aarch64.crypto.xar - aarch64_dmb, // llvm.aarch64.dmb - aarch64_dsb, // llvm.aarch64.dsb - aarch64_fjcvtzs, // llvm.aarch64.fjcvtzs - aarch64_frint32x, // llvm.aarch64.frint32x - aarch64_frint32z, // llvm.aarch64.frint32z - aarch64_frint64x, // llvm.aarch64.frint64x - aarch64_frint64z, // llvm.aarch64.frint64z - aarch64_get_fpcr, // llvm.aarch64.get.fpcr - aarch64_gmi, // llvm.aarch64.gmi - aarch64_hint, // llvm.aarch64.hint - aarch64_irg, // llvm.aarch64.irg - aarch64_irg_sp, // llvm.aarch64.irg.sp - aarch64_isb, // llvm.aarch64.isb - aarch64_ld64b, // llvm.aarch64.ld64b - aarch64_ldaxp, // llvm.aarch64.ldaxp - aarch64_ldaxr, // llvm.aarch64.ldaxr - aarch64_ldg, // llvm.aarch64.ldg - aarch64_ldxp, // llvm.aarch64.ldxp - aarch64_ldxr, // llvm.aarch64.ldxr - aarch64_mops_memset_tag, // llvm.aarch64.mops.memset.tag - aarch64_neon_abs, // llvm.aarch64.neon.abs - aarch64_neon_addhn, // llvm.aarch64.neon.addhn - aarch64_neon_addp, // llvm.aarch64.neon.addp - aarch64_neon_bfcvt, // llvm.aarch64.neon.bfcvt - aarch64_neon_bfcvtn, // llvm.aarch64.neon.bfcvtn - aarch64_neon_bfcvtn2, // llvm.aarch64.neon.bfcvtn2 - aarch64_neon_bfdot, // llvm.aarch64.neon.bfdot - aarch64_neon_bfmlalb, // llvm.aarch64.neon.bfmlalb - aarch64_neon_bfmlalt, // llvm.aarch64.neon.bfmlalt - aarch64_neon_bfmmla, // llvm.aarch64.neon.bfmmla - aarch64_neon_cls, // llvm.aarch64.neon.cls - aarch64_neon_fabd, // llvm.aarch64.neon.fabd - aarch64_neon_facge, // llvm.aarch64.neon.facge - aarch64_neon_facgt, // llvm.aarch64.neon.facgt - aarch64_neon_faddp, // llvm.aarch64.neon.faddp - aarch64_neon_faddv, // llvm.aarch64.neon.faddv - aarch64_neon_fcvtas, // llvm.aarch64.neon.fcvtas - aarch64_neon_fcvtau, // llvm.aarch64.neon.fcvtau - aarch64_neon_fcvtms, // llvm.aarch64.neon.fcvtms - aarch64_neon_fcvtmu, // llvm.aarch64.neon.fcvtmu - aarch64_neon_fcvtns, // llvm.aarch64.neon.fcvtns - aarch64_neon_fcvtnu, // llvm.aarch64.neon.fcvtnu - aarch64_neon_fcvtps, // llvm.aarch64.neon.fcvtps - aarch64_neon_fcvtpu, // llvm.aarch64.neon.fcvtpu - aarch64_neon_fcvtxn, // llvm.aarch64.neon.fcvtxn - aarch64_neon_fcvtzs, // llvm.aarch64.neon.fcvtzs - aarch64_neon_fcvtzu, // llvm.aarch64.neon.fcvtzu - aarch64_neon_fmax, // llvm.aarch64.neon.fmax - aarch64_neon_fmaxnm, // llvm.aarch64.neon.fmaxnm - aarch64_neon_fmaxnmp, // llvm.aarch64.neon.fmaxnmp - aarch64_neon_fmaxnmv, // llvm.aarch64.neon.fmaxnmv - aarch64_neon_fmaxp, // llvm.aarch64.neon.fmaxp - aarch64_neon_fmaxv, // llvm.aarch64.neon.fmaxv - aarch64_neon_fmin, // llvm.aarch64.neon.fmin - aarch64_neon_fminnm, // llvm.aarch64.neon.fminnm - aarch64_neon_fminnmp, // llvm.aarch64.neon.fminnmp - aarch64_neon_fminnmv, // llvm.aarch64.neon.fminnmv - aarch64_neon_fminp, // llvm.aarch64.neon.fminp - aarch64_neon_fminv, // llvm.aarch64.neon.fminv - aarch64_neon_fmlal, // llvm.aarch64.neon.fmlal - aarch64_neon_fmlal2, // llvm.aarch64.neon.fmlal2 - aarch64_neon_fmlsl, // llvm.aarch64.neon.fmlsl - aarch64_neon_fmlsl2, // llvm.aarch64.neon.fmlsl2 - aarch64_neon_fmulx, // llvm.aarch64.neon.fmulx - aarch64_neon_frecpe, // llvm.aarch64.neon.frecpe - aarch64_neon_frecps, // llvm.aarch64.neon.frecps - aarch64_neon_frecpx, // llvm.aarch64.neon.frecpx - aarch64_neon_frint32x, // llvm.aarch64.neon.frint32x - aarch64_neon_frint32z, // llvm.aarch64.neon.frint32z - aarch64_neon_frint64x, // llvm.aarch64.neon.frint64x - aarch64_neon_frint64z, // llvm.aarch64.neon.frint64z - aarch64_neon_frsqrte, // llvm.aarch64.neon.frsqrte - aarch64_neon_frsqrts, // llvm.aarch64.neon.frsqrts - aarch64_neon_ld1x2, // llvm.aarch64.neon.ld1x2 - aarch64_neon_ld1x3, // llvm.aarch64.neon.ld1x3 - aarch64_neon_ld1x4, // llvm.aarch64.neon.ld1x4 - aarch64_neon_ld2, // llvm.aarch64.neon.ld2 - aarch64_neon_ld2lane, // llvm.aarch64.neon.ld2lane - aarch64_neon_ld2r, // llvm.aarch64.neon.ld2r - aarch64_neon_ld3, // llvm.aarch64.neon.ld3 - aarch64_neon_ld3lane, // llvm.aarch64.neon.ld3lane - aarch64_neon_ld3r, // llvm.aarch64.neon.ld3r - aarch64_neon_ld4, // llvm.aarch64.neon.ld4 - aarch64_neon_ld4lane, // llvm.aarch64.neon.ld4lane - aarch64_neon_ld4r, // llvm.aarch64.neon.ld4r - aarch64_neon_pmul, // llvm.aarch64.neon.pmul - aarch64_neon_pmull, // llvm.aarch64.neon.pmull - aarch64_neon_pmull64, // llvm.aarch64.neon.pmull64 - aarch64_neon_raddhn, // llvm.aarch64.neon.raddhn - aarch64_neon_rshrn, // llvm.aarch64.neon.rshrn - aarch64_neon_rsubhn, // llvm.aarch64.neon.rsubhn - aarch64_neon_sabd, // llvm.aarch64.neon.sabd - aarch64_neon_saddlp, // llvm.aarch64.neon.saddlp - aarch64_neon_saddlv, // llvm.aarch64.neon.saddlv - aarch64_neon_saddv, // llvm.aarch64.neon.saddv - aarch64_neon_scalar_sqxtn, // llvm.aarch64.neon.scalar.sqxtn - aarch64_neon_scalar_sqxtun, // llvm.aarch64.neon.scalar.sqxtun - aarch64_neon_scalar_uqxtn, // llvm.aarch64.neon.scalar.uqxtn - aarch64_neon_sdot, // llvm.aarch64.neon.sdot - aarch64_neon_shadd, // llvm.aarch64.neon.shadd - aarch64_neon_shll, // llvm.aarch64.neon.shll - aarch64_neon_shsub, // llvm.aarch64.neon.shsub - aarch64_neon_smax, // llvm.aarch64.neon.smax - aarch64_neon_smaxp, // llvm.aarch64.neon.smaxp - aarch64_neon_smaxv, // llvm.aarch64.neon.smaxv - aarch64_neon_smin, // llvm.aarch64.neon.smin - aarch64_neon_sminp, // llvm.aarch64.neon.sminp - aarch64_neon_sminv, // llvm.aarch64.neon.sminv - aarch64_neon_smmla, // llvm.aarch64.neon.smmla - aarch64_neon_smull, // llvm.aarch64.neon.smull - aarch64_neon_sqabs, // llvm.aarch64.neon.sqabs - aarch64_neon_sqadd, // llvm.aarch64.neon.sqadd - aarch64_neon_sqdmulh, // llvm.aarch64.neon.sqdmulh - aarch64_neon_sqdmulh_lane, // llvm.aarch64.neon.sqdmulh.lane - aarch64_neon_sqdmulh_laneq, // llvm.aarch64.neon.sqdmulh.laneq - aarch64_neon_sqdmull, // llvm.aarch64.neon.sqdmull - aarch64_neon_sqdmulls_scalar, // llvm.aarch64.neon.sqdmulls.scalar - aarch64_neon_sqneg, // llvm.aarch64.neon.sqneg - aarch64_neon_sqrdmlah, // llvm.aarch64.neon.sqrdmlah - aarch64_neon_sqrdmlsh, // llvm.aarch64.neon.sqrdmlsh - aarch64_neon_sqrdmulh, // llvm.aarch64.neon.sqrdmulh - aarch64_neon_sqrdmulh_lane, // llvm.aarch64.neon.sqrdmulh.lane - aarch64_neon_sqrdmulh_laneq, // llvm.aarch64.neon.sqrdmulh.laneq - aarch64_neon_sqrshl, // llvm.aarch64.neon.sqrshl - aarch64_neon_sqrshrn, // llvm.aarch64.neon.sqrshrn - aarch64_neon_sqrshrun, // llvm.aarch64.neon.sqrshrun - aarch64_neon_sqshl, // llvm.aarch64.neon.sqshl - aarch64_neon_sqshlu, // llvm.aarch64.neon.sqshlu - aarch64_neon_sqshrn, // llvm.aarch64.neon.sqshrn - aarch64_neon_sqshrun, // llvm.aarch64.neon.sqshrun - aarch64_neon_sqsub, // llvm.aarch64.neon.sqsub - aarch64_neon_sqxtn, // llvm.aarch64.neon.sqxtn - aarch64_neon_sqxtun, // llvm.aarch64.neon.sqxtun - aarch64_neon_srhadd, // llvm.aarch64.neon.srhadd - aarch64_neon_srshl, // llvm.aarch64.neon.srshl - aarch64_neon_sshl, // llvm.aarch64.neon.sshl - aarch64_neon_sshll, // llvm.aarch64.neon.sshll - aarch64_neon_st1x2, // llvm.aarch64.neon.st1x2 - aarch64_neon_st1x3, // llvm.aarch64.neon.st1x3 - aarch64_neon_st1x4, // llvm.aarch64.neon.st1x4 - aarch64_neon_st2, // llvm.aarch64.neon.st2 - aarch64_neon_st2lane, // llvm.aarch64.neon.st2lane - aarch64_neon_st3, // llvm.aarch64.neon.st3 - aarch64_neon_st3lane, // llvm.aarch64.neon.st3lane - aarch64_neon_st4, // llvm.aarch64.neon.st4 - aarch64_neon_st4lane, // llvm.aarch64.neon.st4lane - aarch64_neon_subhn, // llvm.aarch64.neon.subhn - aarch64_neon_suqadd, // llvm.aarch64.neon.suqadd - aarch64_neon_tbl1, // llvm.aarch64.neon.tbl1 - aarch64_neon_tbl2, // llvm.aarch64.neon.tbl2 - aarch64_neon_tbl3, // llvm.aarch64.neon.tbl3 - aarch64_neon_tbl4, // llvm.aarch64.neon.tbl4 - aarch64_neon_tbx1, // llvm.aarch64.neon.tbx1 - aarch64_neon_tbx2, // llvm.aarch64.neon.tbx2 - aarch64_neon_tbx3, // llvm.aarch64.neon.tbx3 - aarch64_neon_tbx4, // llvm.aarch64.neon.tbx4 - aarch64_neon_uabd, // llvm.aarch64.neon.uabd - aarch64_neon_uaddlp, // llvm.aarch64.neon.uaddlp - aarch64_neon_uaddlv, // llvm.aarch64.neon.uaddlv - aarch64_neon_uaddv, // llvm.aarch64.neon.uaddv - aarch64_neon_udot, // llvm.aarch64.neon.udot - aarch64_neon_uhadd, // llvm.aarch64.neon.uhadd - aarch64_neon_uhsub, // llvm.aarch64.neon.uhsub - aarch64_neon_umax, // llvm.aarch64.neon.umax - aarch64_neon_umaxp, // llvm.aarch64.neon.umaxp - aarch64_neon_umaxv, // llvm.aarch64.neon.umaxv - aarch64_neon_umin, // llvm.aarch64.neon.umin - aarch64_neon_uminp, // llvm.aarch64.neon.uminp - aarch64_neon_uminv, // llvm.aarch64.neon.uminv - aarch64_neon_ummla, // llvm.aarch64.neon.ummla - aarch64_neon_umull, // llvm.aarch64.neon.umull - aarch64_neon_uqadd, // llvm.aarch64.neon.uqadd - aarch64_neon_uqrshl, // llvm.aarch64.neon.uqrshl - aarch64_neon_uqrshrn, // llvm.aarch64.neon.uqrshrn - aarch64_neon_uqshl, // llvm.aarch64.neon.uqshl - aarch64_neon_uqshrn, // llvm.aarch64.neon.uqshrn - aarch64_neon_uqsub, // llvm.aarch64.neon.uqsub - aarch64_neon_uqxtn, // llvm.aarch64.neon.uqxtn - aarch64_neon_urecpe, // llvm.aarch64.neon.urecpe - aarch64_neon_urhadd, // llvm.aarch64.neon.urhadd - aarch64_neon_urshl, // llvm.aarch64.neon.urshl - aarch64_neon_ursqrte, // llvm.aarch64.neon.ursqrte - aarch64_neon_usdot, // llvm.aarch64.neon.usdot - aarch64_neon_ushl, // llvm.aarch64.neon.ushl - aarch64_neon_ushll, // llvm.aarch64.neon.ushll - aarch64_neon_usmmla, // llvm.aarch64.neon.usmmla - aarch64_neon_usqadd, // llvm.aarch64.neon.usqadd - aarch64_neon_vcadd_rot270, // llvm.aarch64.neon.vcadd.rot270 - aarch64_neon_vcadd_rot90, // llvm.aarch64.neon.vcadd.rot90 - aarch64_neon_vcmla_rot0, // llvm.aarch64.neon.vcmla.rot0 - aarch64_neon_vcmla_rot180, // llvm.aarch64.neon.vcmla.rot180 - aarch64_neon_vcmla_rot270, // llvm.aarch64.neon.vcmla.rot270 - aarch64_neon_vcmla_rot90, // llvm.aarch64.neon.vcmla.rot90 - aarch64_neon_vcopy_lane, // llvm.aarch64.neon.vcopy.lane - aarch64_neon_vcvtfp2fxs, // llvm.aarch64.neon.vcvtfp2fxs - aarch64_neon_vcvtfp2fxu, // llvm.aarch64.neon.vcvtfp2fxu - aarch64_neon_vcvtfp2hf, // llvm.aarch64.neon.vcvtfp2hf - aarch64_neon_vcvtfxs2fp, // llvm.aarch64.neon.vcvtfxs2fp - aarch64_neon_vcvtfxu2fp, // llvm.aarch64.neon.vcvtfxu2fp - aarch64_neon_vcvthf2fp, // llvm.aarch64.neon.vcvthf2fp - aarch64_neon_vsli, // llvm.aarch64.neon.vsli - aarch64_neon_vsri, // llvm.aarch64.neon.vsri - aarch64_rndr, // llvm.aarch64.rndr - aarch64_rndrrs, // llvm.aarch64.rndrrs - aarch64_sdiv, // llvm.aarch64.sdiv - aarch64_set_fpcr, // llvm.aarch64.set.fpcr - aarch64_settag, // llvm.aarch64.settag - aarch64_settag_zero, // llvm.aarch64.settag.zero - aarch64_sisd_fabd, // llvm.aarch64.sisd.fabd - aarch64_sisd_fcvtxn, // llvm.aarch64.sisd.fcvtxn - aarch64_space, // llvm.aarch64.space - aarch64_st64b, // llvm.aarch64.st64b - aarch64_st64bv, // llvm.aarch64.st64bv - aarch64_st64bv0, // llvm.aarch64.st64bv0 - aarch64_stg, // llvm.aarch64.stg - aarch64_stgp, // llvm.aarch64.stgp - aarch64_stlxp, // llvm.aarch64.stlxp - aarch64_stlxr, // llvm.aarch64.stlxr - aarch64_stxp, // llvm.aarch64.stxp - aarch64_stxr, // llvm.aarch64.stxr - aarch64_subp, // llvm.aarch64.subp - aarch64_sve_abs, // llvm.aarch64.sve.abs - aarch64_sve_adclb, // llvm.aarch64.sve.adclb - aarch64_sve_adclt, // llvm.aarch64.sve.adclt - aarch64_sve_add, // llvm.aarch64.sve.add - aarch64_sve_addhnb, // llvm.aarch64.sve.addhnb - aarch64_sve_addhnt, // llvm.aarch64.sve.addhnt - aarch64_sve_addp, // llvm.aarch64.sve.addp - aarch64_sve_adrb, // llvm.aarch64.sve.adrb - aarch64_sve_adrd, // llvm.aarch64.sve.adrd - aarch64_sve_adrh, // llvm.aarch64.sve.adrh - aarch64_sve_adrw, // llvm.aarch64.sve.adrw - aarch64_sve_aesd, // llvm.aarch64.sve.aesd - aarch64_sve_aese, // llvm.aarch64.sve.aese - aarch64_sve_aesimc, // llvm.aarch64.sve.aesimc - aarch64_sve_aesmc, // llvm.aarch64.sve.aesmc - aarch64_sve_and, // llvm.aarch64.sve.and - aarch64_sve_and_z, // llvm.aarch64.sve.and.z - aarch64_sve_andv, // llvm.aarch64.sve.andv - aarch64_sve_asr, // llvm.aarch64.sve.asr - aarch64_sve_asr_wide, // llvm.aarch64.sve.asr.wide - aarch64_sve_asrd, // llvm.aarch64.sve.asrd - aarch64_sve_bcax, // llvm.aarch64.sve.bcax - aarch64_sve_bdep_x, // llvm.aarch64.sve.bdep.x - aarch64_sve_bext_x, // llvm.aarch64.sve.bext.x - aarch64_sve_bfdot, // llvm.aarch64.sve.bfdot - aarch64_sve_bfdot_lane, // llvm.aarch64.sve.bfdot.lane - aarch64_sve_bfmlalb, // llvm.aarch64.sve.bfmlalb - aarch64_sve_bfmlalb_lane, // llvm.aarch64.sve.bfmlalb.lane - aarch64_sve_bfmlalt, // llvm.aarch64.sve.bfmlalt - aarch64_sve_bfmlalt_lane, // llvm.aarch64.sve.bfmlalt.lane - aarch64_sve_bfmmla, // llvm.aarch64.sve.bfmmla - aarch64_sve_bgrp_x, // llvm.aarch64.sve.bgrp.x - aarch64_sve_bic, // llvm.aarch64.sve.bic - aarch64_sve_bic_z, // llvm.aarch64.sve.bic.z - aarch64_sve_brka, // llvm.aarch64.sve.brka - aarch64_sve_brka_z, // llvm.aarch64.sve.brka.z - aarch64_sve_brkb, // llvm.aarch64.sve.brkb - aarch64_sve_brkb_z, // llvm.aarch64.sve.brkb.z - aarch64_sve_brkn_z, // llvm.aarch64.sve.brkn.z - aarch64_sve_brkpa_z, // llvm.aarch64.sve.brkpa.z - aarch64_sve_brkpb_z, // llvm.aarch64.sve.brkpb.z - aarch64_sve_bsl, // llvm.aarch64.sve.bsl - aarch64_sve_bsl1n, // llvm.aarch64.sve.bsl1n - aarch64_sve_bsl2n, // llvm.aarch64.sve.bsl2n - aarch64_sve_cadd_x, // llvm.aarch64.sve.cadd.x - aarch64_sve_cdot, // llvm.aarch64.sve.cdot - aarch64_sve_cdot_lane, // llvm.aarch64.sve.cdot.lane - aarch64_sve_clasta, // llvm.aarch64.sve.clasta - aarch64_sve_clasta_n, // llvm.aarch64.sve.clasta.n - aarch64_sve_clastb, // llvm.aarch64.sve.clastb - aarch64_sve_clastb_n, // llvm.aarch64.sve.clastb.n - aarch64_sve_cls, // llvm.aarch64.sve.cls - aarch64_sve_clz, // llvm.aarch64.sve.clz - aarch64_sve_cmla_lane_x, // llvm.aarch64.sve.cmla.lane.x - aarch64_sve_cmla_x, // llvm.aarch64.sve.cmla.x - aarch64_sve_cmpeq, // llvm.aarch64.sve.cmpeq - aarch64_sve_cmpeq_wide, // llvm.aarch64.sve.cmpeq.wide - aarch64_sve_cmpge, // llvm.aarch64.sve.cmpge - aarch64_sve_cmpge_wide, // llvm.aarch64.sve.cmpge.wide - aarch64_sve_cmpgt, // llvm.aarch64.sve.cmpgt - aarch64_sve_cmpgt_wide, // llvm.aarch64.sve.cmpgt.wide - aarch64_sve_cmphi, // llvm.aarch64.sve.cmphi - aarch64_sve_cmphi_wide, // llvm.aarch64.sve.cmphi.wide - aarch64_sve_cmphs, // llvm.aarch64.sve.cmphs - aarch64_sve_cmphs_wide, // llvm.aarch64.sve.cmphs.wide - aarch64_sve_cmple_wide, // llvm.aarch64.sve.cmple.wide - aarch64_sve_cmplo_wide, // llvm.aarch64.sve.cmplo.wide - aarch64_sve_cmpls_wide, // llvm.aarch64.sve.cmpls.wide - aarch64_sve_cmplt_wide, // llvm.aarch64.sve.cmplt.wide - aarch64_sve_cmpne, // llvm.aarch64.sve.cmpne - aarch64_sve_cmpne_wide, // llvm.aarch64.sve.cmpne.wide - aarch64_sve_cnot, // llvm.aarch64.sve.cnot - aarch64_sve_cnt, // llvm.aarch64.sve.cnt - aarch64_sve_cntb, // llvm.aarch64.sve.cntb - aarch64_sve_cntd, // llvm.aarch64.sve.cntd - aarch64_sve_cnth, // llvm.aarch64.sve.cnth - aarch64_sve_cntp, // llvm.aarch64.sve.cntp - aarch64_sve_cntw, // llvm.aarch64.sve.cntw - aarch64_sve_compact, // llvm.aarch64.sve.compact - aarch64_sve_convert_from_svbool, // llvm.aarch64.sve.convert.from.svbool - aarch64_sve_convert_to_svbool, // llvm.aarch64.sve.convert.to.svbool - aarch64_sve_dup, // llvm.aarch64.sve.dup - aarch64_sve_dup_x, // llvm.aarch64.sve.dup.x - aarch64_sve_dupq_lane, // llvm.aarch64.sve.dupq.lane - aarch64_sve_eor, // llvm.aarch64.sve.eor - aarch64_sve_eor_z, // llvm.aarch64.sve.eor.z - aarch64_sve_eor3, // llvm.aarch64.sve.eor3 - aarch64_sve_eorbt, // llvm.aarch64.sve.eorbt - aarch64_sve_eortb, // llvm.aarch64.sve.eortb - aarch64_sve_eorv, // llvm.aarch64.sve.eorv - aarch64_sve_ext, // llvm.aarch64.sve.ext - aarch64_sve_fabd, // llvm.aarch64.sve.fabd - aarch64_sve_fabs, // llvm.aarch64.sve.fabs - aarch64_sve_facge, // llvm.aarch64.sve.facge - aarch64_sve_facgt, // llvm.aarch64.sve.facgt - aarch64_sve_fadd, // llvm.aarch64.sve.fadd - aarch64_sve_fadda, // llvm.aarch64.sve.fadda - aarch64_sve_faddp, // llvm.aarch64.sve.faddp - aarch64_sve_faddv, // llvm.aarch64.sve.faddv - aarch64_sve_fcadd, // llvm.aarch64.sve.fcadd - aarch64_sve_fcmla, // llvm.aarch64.sve.fcmla - aarch64_sve_fcmla_lane, // llvm.aarch64.sve.fcmla.lane - aarch64_sve_fcmpeq, // llvm.aarch64.sve.fcmpeq - aarch64_sve_fcmpge, // llvm.aarch64.sve.fcmpge - aarch64_sve_fcmpgt, // llvm.aarch64.sve.fcmpgt - aarch64_sve_fcmpne, // llvm.aarch64.sve.fcmpne - aarch64_sve_fcmpuo, // llvm.aarch64.sve.fcmpuo - aarch64_sve_fcvt, // llvm.aarch64.sve.fcvt - aarch64_sve_fcvt_bf16f32, // llvm.aarch64.sve.fcvt.bf16f32 - aarch64_sve_fcvt_f16f32, // llvm.aarch64.sve.fcvt.f16f32 - aarch64_sve_fcvt_f16f64, // llvm.aarch64.sve.fcvt.f16f64 - aarch64_sve_fcvt_f32f16, // llvm.aarch64.sve.fcvt.f32f16 - aarch64_sve_fcvt_f32f64, // llvm.aarch64.sve.fcvt.f32f64 - aarch64_sve_fcvt_f64f16, // llvm.aarch64.sve.fcvt.f64f16 - aarch64_sve_fcvt_f64f32, // llvm.aarch64.sve.fcvt.f64f32 - aarch64_sve_fcvtlt_f32f16, // llvm.aarch64.sve.fcvtlt.f32f16 - aarch64_sve_fcvtlt_f64f32, // llvm.aarch64.sve.fcvtlt.f64f32 - aarch64_sve_fcvtnt_bf16f32, // llvm.aarch64.sve.fcvtnt.bf16f32 - aarch64_sve_fcvtnt_f16f32, // llvm.aarch64.sve.fcvtnt.f16f32 - aarch64_sve_fcvtnt_f32f64, // llvm.aarch64.sve.fcvtnt.f32f64 - aarch64_sve_fcvtx_f32f64, // llvm.aarch64.sve.fcvtx.f32f64 - aarch64_sve_fcvtxnt_f32f64, // llvm.aarch64.sve.fcvtxnt.f32f64 - aarch64_sve_fcvtzs, // llvm.aarch64.sve.fcvtzs - aarch64_sve_fcvtzs_i32f16, // llvm.aarch64.sve.fcvtzs.i32f16 - aarch64_sve_fcvtzs_i32f64, // llvm.aarch64.sve.fcvtzs.i32f64 - aarch64_sve_fcvtzs_i64f16, // llvm.aarch64.sve.fcvtzs.i64f16 - aarch64_sve_fcvtzs_i64f32, // llvm.aarch64.sve.fcvtzs.i64f32 - aarch64_sve_fcvtzu, // llvm.aarch64.sve.fcvtzu - aarch64_sve_fcvtzu_i32f16, // llvm.aarch64.sve.fcvtzu.i32f16 - aarch64_sve_fcvtzu_i32f64, // llvm.aarch64.sve.fcvtzu.i32f64 - aarch64_sve_fcvtzu_i64f16, // llvm.aarch64.sve.fcvtzu.i64f16 - aarch64_sve_fcvtzu_i64f32, // llvm.aarch64.sve.fcvtzu.i64f32 - aarch64_sve_fdiv, // llvm.aarch64.sve.fdiv - aarch64_sve_fdivr, // llvm.aarch64.sve.fdivr - aarch64_sve_fexpa_x, // llvm.aarch64.sve.fexpa.x - aarch64_sve_flogb, // llvm.aarch64.sve.flogb - aarch64_sve_fmad, // llvm.aarch64.sve.fmad - aarch64_sve_fmax, // llvm.aarch64.sve.fmax - aarch64_sve_fmaxnm, // llvm.aarch64.sve.fmaxnm - aarch64_sve_fmaxnmp, // llvm.aarch64.sve.fmaxnmp - aarch64_sve_fmaxnmv, // llvm.aarch64.sve.fmaxnmv - aarch64_sve_fmaxp, // llvm.aarch64.sve.fmaxp - aarch64_sve_fmaxv, // llvm.aarch64.sve.fmaxv - aarch64_sve_fmin, // llvm.aarch64.sve.fmin - aarch64_sve_fminnm, // llvm.aarch64.sve.fminnm - aarch64_sve_fminnmp, // llvm.aarch64.sve.fminnmp - aarch64_sve_fminnmv, // llvm.aarch64.sve.fminnmv - aarch64_sve_fminp, // llvm.aarch64.sve.fminp - aarch64_sve_fminv, // llvm.aarch64.sve.fminv - aarch64_sve_fmla, // llvm.aarch64.sve.fmla - aarch64_sve_fmla_lane, // llvm.aarch64.sve.fmla.lane - aarch64_sve_fmlalb, // llvm.aarch64.sve.fmlalb - aarch64_sve_fmlalb_lane, // llvm.aarch64.sve.fmlalb.lane - aarch64_sve_fmlalt, // llvm.aarch64.sve.fmlalt - aarch64_sve_fmlalt_lane, // llvm.aarch64.sve.fmlalt.lane - aarch64_sve_fmls, // llvm.aarch64.sve.fmls - aarch64_sve_fmls_lane, // llvm.aarch64.sve.fmls.lane - aarch64_sve_fmlslb, // llvm.aarch64.sve.fmlslb - aarch64_sve_fmlslb_lane, // llvm.aarch64.sve.fmlslb.lane - aarch64_sve_fmlslt, // llvm.aarch64.sve.fmlslt - aarch64_sve_fmlslt_lane, // llvm.aarch64.sve.fmlslt.lane - aarch64_sve_fmmla, // llvm.aarch64.sve.fmmla - aarch64_sve_fmsb, // llvm.aarch64.sve.fmsb - aarch64_sve_fmul, // llvm.aarch64.sve.fmul - aarch64_sve_fmul_lane, // llvm.aarch64.sve.fmul.lane - aarch64_sve_fmulx, // llvm.aarch64.sve.fmulx - aarch64_sve_fneg, // llvm.aarch64.sve.fneg - aarch64_sve_fnmad, // llvm.aarch64.sve.fnmad - aarch64_sve_fnmla, // llvm.aarch64.sve.fnmla - aarch64_sve_fnmls, // llvm.aarch64.sve.fnmls - aarch64_sve_fnmsb, // llvm.aarch64.sve.fnmsb - aarch64_sve_frecpe_x, // llvm.aarch64.sve.frecpe.x - aarch64_sve_frecps_x, // llvm.aarch64.sve.frecps.x - aarch64_sve_frecpx, // llvm.aarch64.sve.frecpx - aarch64_sve_frinta, // llvm.aarch64.sve.frinta - aarch64_sve_frinti, // llvm.aarch64.sve.frinti - aarch64_sve_frintm, // llvm.aarch64.sve.frintm - aarch64_sve_frintn, // llvm.aarch64.sve.frintn - aarch64_sve_frintp, // llvm.aarch64.sve.frintp - aarch64_sve_frintx, // llvm.aarch64.sve.frintx - aarch64_sve_frintz, // llvm.aarch64.sve.frintz - aarch64_sve_frsqrte_x, // llvm.aarch64.sve.frsqrte.x - aarch64_sve_frsqrts_x, // llvm.aarch64.sve.frsqrts.x - aarch64_sve_fscale, // llvm.aarch64.sve.fscale - aarch64_sve_fsqrt, // llvm.aarch64.sve.fsqrt - aarch64_sve_fsub, // llvm.aarch64.sve.fsub - aarch64_sve_fsubr, // llvm.aarch64.sve.fsubr - aarch64_sve_ftmad_x, // llvm.aarch64.sve.ftmad.x - aarch64_sve_ftsmul_x, // llvm.aarch64.sve.ftsmul.x - aarch64_sve_ftssel_x, // llvm.aarch64.sve.ftssel.x - aarch64_sve_histcnt, // llvm.aarch64.sve.histcnt - aarch64_sve_histseg, // llvm.aarch64.sve.histseg - aarch64_sve_index, // llvm.aarch64.sve.index - aarch64_sve_insr, // llvm.aarch64.sve.insr - aarch64_sve_lasta, // llvm.aarch64.sve.lasta - aarch64_sve_lastb, // llvm.aarch64.sve.lastb - aarch64_sve_ld1, // llvm.aarch64.sve.ld1 - aarch64_sve_ld1_gather, // llvm.aarch64.sve.ld1.gather - aarch64_sve_ld1_gather_index, // llvm.aarch64.sve.ld1.gather.index - aarch64_sve_ld1_gather_scalar_offset, // llvm.aarch64.sve.ld1.gather.scalar.offset - aarch64_sve_ld1_gather_sxtw, // llvm.aarch64.sve.ld1.gather.sxtw - aarch64_sve_ld1_gather_sxtw_index, // llvm.aarch64.sve.ld1.gather.sxtw.index - aarch64_sve_ld1_gather_uxtw, // llvm.aarch64.sve.ld1.gather.uxtw - aarch64_sve_ld1_gather_uxtw_index, // llvm.aarch64.sve.ld1.gather.uxtw.index - aarch64_sve_ld1ro, // llvm.aarch64.sve.ld1ro - aarch64_sve_ld1rq, // llvm.aarch64.sve.ld1rq - aarch64_sve_ld2, // llvm.aarch64.sve.ld2 - aarch64_sve_ld2_sret, // llvm.aarch64.sve.ld2.sret - aarch64_sve_ld3, // llvm.aarch64.sve.ld3 - aarch64_sve_ld3_sret, // llvm.aarch64.sve.ld3.sret - aarch64_sve_ld4, // llvm.aarch64.sve.ld4 - aarch64_sve_ld4_sret, // llvm.aarch64.sve.ld4.sret - aarch64_sve_ldff1, // llvm.aarch64.sve.ldff1 - aarch64_sve_ldff1_gather, // llvm.aarch64.sve.ldff1.gather - aarch64_sve_ldff1_gather_index, // llvm.aarch64.sve.ldff1.gather.index - aarch64_sve_ldff1_gather_scalar_offset, // llvm.aarch64.sve.ldff1.gather.scalar.offset - aarch64_sve_ldff1_gather_sxtw, // llvm.aarch64.sve.ldff1.gather.sxtw - aarch64_sve_ldff1_gather_sxtw_index, // llvm.aarch64.sve.ldff1.gather.sxtw.index - aarch64_sve_ldff1_gather_uxtw, // llvm.aarch64.sve.ldff1.gather.uxtw - aarch64_sve_ldff1_gather_uxtw_index, // llvm.aarch64.sve.ldff1.gather.uxtw.index - aarch64_sve_ldnf1, // llvm.aarch64.sve.ldnf1 - aarch64_sve_ldnt1, // llvm.aarch64.sve.ldnt1 - aarch64_sve_ldnt1_gather, // llvm.aarch64.sve.ldnt1.gather - aarch64_sve_ldnt1_gather_index, // llvm.aarch64.sve.ldnt1.gather.index - aarch64_sve_ldnt1_gather_scalar_offset, // llvm.aarch64.sve.ldnt1.gather.scalar.offset - aarch64_sve_ldnt1_gather_uxtw, // llvm.aarch64.sve.ldnt1.gather.uxtw - aarch64_sve_lsl, // llvm.aarch64.sve.lsl - aarch64_sve_lsl_wide, // llvm.aarch64.sve.lsl.wide - aarch64_sve_lsr, // llvm.aarch64.sve.lsr - aarch64_sve_lsr_wide, // llvm.aarch64.sve.lsr.wide - aarch64_sve_mad, // llvm.aarch64.sve.mad - aarch64_sve_match, // llvm.aarch64.sve.match - aarch64_sve_mla, // llvm.aarch64.sve.mla - aarch64_sve_mla_lane, // llvm.aarch64.sve.mla.lane - aarch64_sve_mls, // llvm.aarch64.sve.mls - aarch64_sve_mls_lane, // llvm.aarch64.sve.mls.lane - aarch64_sve_msb, // llvm.aarch64.sve.msb - aarch64_sve_mul, // llvm.aarch64.sve.mul - aarch64_sve_mul_lane, // llvm.aarch64.sve.mul.lane - aarch64_sve_nand_z, // llvm.aarch64.sve.nand.z - aarch64_sve_nbsl, // llvm.aarch64.sve.nbsl - aarch64_sve_neg, // llvm.aarch64.sve.neg - aarch64_sve_nmatch, // llvm.aarch64.sve.nmatch - aarch64_sve_nor_z, // llvm.aarch64.sve.nor.z - aarch64_sve_not, // llvm.aarch64.sve.not - aarch64_sve_orn_z, // llvm.aarch64.sve.orn.z - aarch64_sve_orr, // llvm.aarch64.sve.orr - aarch64_sve_orr_z, // llvm.aarch64.sve.orr.z - aarch64_sve_orv, // llvm.aarch64.sve.orv - aarch64_sve_pfirst, // llvm.aarch64.sve.pfirst - aarch64_sve_pmul, // llvm.aarch64.sve.pmul - aarch64_sve_pmullb_pair, // llvm.aarch64.sve.pmullb.pair - aarch64_sve_pmullt_pair, // llvm.aarch64.sve.pmullt.pair - aarch64_sve_pnext, // llvm.aarch64.sve.pnext - aarch64_sve_prf, // llvm.aarch64.sve.prf - aarch64_sve_prfb_gather_index, // llvm.aarch64.sve.prfb.gather.index - aarch64_sve_prfb_gather_scalar_offset, // llvm.aarch64.sve.prfb.gather.scalar.offset - aarch64_sve_prfb_gather_sxtw_index, // llvm.aarch64.sve.prfb.gather.sxtw.index - aarch64_sve_prfb_gather_uxtw_index, // llvm.aarch64.sve.prfb.gather.uxtw.index - aarch64_sve_prfd_gather_index, // llvm.aarch64.sve.prfd.gather.index - aarch64_sve_prfd_gather_scalar_offset, // llvm.aarch64.sve.prfd.gather.scalar.offset - aarch64_sve_prfd_gather_sxtw_index, // llvm.aarch64.sve.prfd.gather.sxtw.index - aarch64_sve_prfd_gather_uxtw_index, // llvm.aarch64.sve.prfd.gather.uxtw.index - aarch64_sve_prfh_gather_index, // llvm.aarch64.sve.prfh.gather.index - aarch64_sve_prfh_gather_scalar_offset, // llvm.aarch64.sve.prfh.gather.scalar.offset - aarch64_sve_prfh_gather_sxtw_index, // llvm.aarch64.sve.prfh.gather.sxtw.index - aarch64_sve_prfh_gather_uxtw_index, // llvm.aarch64.sve.prfh.gather.uxtw.index - aarch64_sve_prfw_gather_index, // llvm.aarch64.sve.prfw.gather.index - aarch64_sve_prfw_gather_scalar_offset, // llvm.aarch64.sve.prfw.gather.scalar.offset - aarch64_sve_prfw_gather_sxtw_index, // llvm.aarch64.sve.prfw.gather.sxtw.index - aarch64_sve_prfw_gather_uxtw_index, // llvm.aarch64.sve.prfw.gather.uxtw.index - aarch64_sve_ptest_any, // llvm.aarch64.sve.ptest.any - aarch64_sve_ptest_first, // llvm.aarch64.sve.ptest.first - aarch64_sve_ptest_last, // llvm.aarch64.sve.ptest.last - aarch64_sve_ptrue, // llvm.aarch64.sve.ptrue - aarch64_sve_punpkhi, // llvm.aarch64.sve.punpkhi - aarch64_sve_punpklo, // llvm.aarch64.sve.punpklo - aarch64_sve_raddhnb, // llvm.aarch64.sve.raddhnb - aarch64_sve_raddhnt, // llvm.aarch64.sve.raddhnt - aarch64_sve_rax1, // llvm.aarch64.sve.rax1 - aarch64_sve_rbit, // llvm.aarch64.sve.rbit - aarch64_sve_rdffr, // llvm.aarch64.sve.rdffr - aarch64_sve_rdffr_z, // llvm.aarch64.sve.rdffr.z - aarch64_sve_rev, // llvm.aarch64.sve.rev - aarch64_sve_revb, // llvm.aarch64.sve.revb - aarch64_sve_revh, // llvm.aarch64.sve.revh - aarch64_sve_revw, // llvm.aarch64.sve.revw - aarch64_sve_rshrnb, // llvm.aarch64.sve.rshrnb - aarch64_sve_rshrnt, // llvm.aarch64.sve.rshrnt - aarch64_sve_rsubhnb, // llvm.aarch64.sve.rsubhnb - aarch64_sve_rsubhnt, // llvm.aarch64.sve.rsubhnt - aarch64_sve_saba, // llvm.aarch64.sve.saba - aarch64_sve_sabalb, // llvm.aarch64.sve.sabalb - aarch64_sve_sabalt, // llvm.aarch64.sve.sabalt - aarch64_sve_sabd, // llvm.aarch64.sve.sabd - aarch64_sve_sabdlb, // llvm.aarch64.sve.sabdlb - aarch64_sve_sabdlt, // llvm.aarch64.sve.sabdlt - aarch64_sve_sadalp, // llvm.aarch64.sve.sadalp - aarch64_sve_saddlb, // llvm.aarch64.sve.saddlb - aarch64_sve_saddlbt, // llvm.aarch64.sve.saddlbt - aarch64_sve_saddlt, // llvm.aarch64.sve.saddlt - aarch64_sve_saddv, // llvm.aarch64.sve.saddv - aarch64_sve_saddwb, // llvm.aarch64.sve.saddwb - aarch64_sve_saddwt, // llvm.aarch64.sve.saddwt - aarch64_sve_sbclb, // llvm.aarch64.sve.sbclb - aarch64_sve_sbclt, // llvm.aarch64.sve.sbclt - aarch64_sve_scvtf, // llvm.aarch64.sve.scvtf - aarch64_sve_scvtf_f16i32, // llvm.aarch64.sve.scvtf.f16i32 - aarch64_sve_scvtf_f16i64, // llvm.aarch64.sve.scvtf.f16i64 - aarch64_sve_scvtf_f32i64, // llvm.aarch64.sve.scvtf.f32i64 - aarch64_sve_scvtf_f64i32, // llvm.aarch64.sve.scvtf.f64i32 - aarch64_sve_sdiv, // llvm.aarch64.sve.sdiv - aarch64_sve_sdivr, // llvm.aarch64.sve.sdivr - aarch64_sve_sdot, // llvm.aarch64.sve.sdot - aarch64_sve_sdot_lane, // llvm.aarch64.sve.sdot.lane - aarch64_sve_sel, // llvm.aarch64.sve.sel - aarch64_sve_setffr, // llvm.aarch64.sve.setffr - aarch64_sve_shadd, // llvm.aarch64.sve.shadd - aarch64_sve_shrnb, // llvm.aarch64.sve.shrnb - aarch64_sve_shrnt, // llvm.aarch64.sve.shrnt - aarch64_sve_shsub, // llvm.aarch64.sve.shsub - aarch64_sve_shsubr, // llvm.aarch64.sve.shsubr - aarch64_sve_sli, // llvm.aarch64.sve.sli - aarch64_sve_sm4e, // llvm.aarch64.sve.sm4e - aarch64_sve_sm4ekey, // llvm.aarch64.sve.sm4ekey - aarch64_sve_smax, // llvm.aarch64.sve.smax - aarch64_sve_smaxp, // llvm.aarch64.sve.smaxp - aarch64_sve_smaxv, // llvm.aarch64.sve.smaxv - aarch64_sve_smin, // llvm.aarch64.sve.smin - aarch64_sve_sminp, // llvm.aarch64.sve.sminp - aarch64_sve_sminv, // llvm.aarch64.sve.sminv - aarch64_sve_smlalb, // llvm.aarch64.sve.smlalb - aarch64_sve_smlalb_lane, // llvm.aarch64.sve.smlalb.lane - aarch64_sve_smlalt, // llvm.aarch64.sve.smlalt - aarch64_sve_smlalt_lane, // llvm.aarch64.sve.smlalt.lane - aarch64_sve_smlslb, // llvm.aarch64.sve.smlslb - aarch64_sve_smlslb_lane, // llvm.aarch64.sve.smlslb.lane - aarch64_sve_smlslt, // llvm.aarch64.sve.smlslt - aarch64_sve_smlslt_lane, // llvm.aarch64.sve.smlslt.lane - aarch64_sve_smmla, // llvm.aarch64.sve.smmla - aarch64_sve_smulh, // llvm.aarch64.sve.smulh - aarch64_sve_smullb, // llvm.aarch64.sve.smullb - aarch64_sve_smullb_lane, // llvm.aarch64.sve.smullb.lane - aarch64_sve_smullt, // llvm.aarch64.sve.smullt - aarch64_sve_smullt_lane, // llvm.aarch64.sve.smullt.lane - aarch64_sve_splice, // llvm.aarch64.sve.splice - aarch64_sve_sqabs, // llvm.aarch64.sve.sqabs - aarch64_sve_sqadd, // llvm.aarch64.sve.sqadd - aarch64_sve_sqadd_x, // llvm.aarch64.sve.sqadd.x - aarch64_sve_sqcadd_x, // llvm.aarch64.sve.sqcadd.x - aarch64_sve_sqdecb_n32, // llvm.aarch64.sve.sqdecb.n32 - aarch64_sve_sqdecb_n64, // llvm.aarch64.sve.sqdecb.n64 - aarch64_sve_sqdecd, // llvm.aarch64.sve.sqdecd - aarch64_sve_sqdecd_n32, // llvm.aarch64.sve.sqdecd.n32 - aarch64_sve_sqdecd_n64, // llvm.aarch64.sve.sqdecd.n64 - aarch64_sve_sqdech, // llvm.aarch64.sve.sqdech - aarch64_sve_sqdech_n32, // llvm.aarch64.sve.sqdech.n32 - aarch64_sve_sqdech_n64, // llvm.aarch64.sve.sqdech.n64 - aarch64_sve_sqdecp, // llvm.aarch64.sve.sqdecp - aarch64_sve_sqdecp_n32, // llvm.aarch64.sve.sqdecp.n32 - aarch64_sve_sqdecp_n64, // llvm.aarch64.sve.sqdecp.n64 - aarch64_sve_sqdecw, // llvm.aarch64.sve.sqdecw - aarch64_sve_sqdecw_n32, // llvm.aarch64.sve.sqdecw.n32 - aarch64_sve_sqdecw_n64, // llvm.aarch64.sve.sqdecw.n64 - aarch64_sve_sqdmlalb, // llvm.aarch64.sve.sqdmlalb - aarch64_sve_sqdmlalb_lane, // llvm.aarch64.sve.sqdmlalb.lane - aarch64_sve_sqdmlalbt, // llvm.aarch64.sve.sqdmlalbt - aarch64_sve_sqdmlalt, // llvm.aarch64.sve.sqdmlalt - aarch64_sve_sqdmlalt_lane, // llvm.aarch64.sve.sqdmlalt.lane - aarch64_sve_sqdmlslb, // llvm.aarch64.sve.sqdmlslb - aarch64_sve_sqdmlslb_lane, // llvm.aarch64.sve.sqdmlslb.lane - aarch64_sve_sqdmlslbt, // llvm.aarch64.sve.sqdmlslbt - aarch64_sve_sqdmlslt, // llvm.aarch64.sve.sqdmlslt - aarch64_sve_sqdmlslt_lane, // llvm.aarch64.sve.sqdmlslt.lane - aarch64_sve_sqdmulh, // llvm.aarch64.sve.sqdmulh - aarch64_sve_sqdmulh_lane, // llvm.aarch64.sve.sqdmulh.lane - aarch64_sve_sqdmullb, // llvm.aarch64.sve.sqdmullb - aarch64_sve_sqdmullb_lane, // llvm.aarch64.sve.sqdmullb.lane - aarch64_sve_sqdmullt, // llvm.aarch64.sve.sqdmullt - aarch64_sve_sqdmullt_lane, // llvm.aarch64.sve.sqdmullt.lane - aarch64_sve_sqincb_n32, // llvm.aarch64.sve.sqincb.n32 - aarch64_sve_sqincb_n64, // llvm.aarch64.sve.sqincb.n64 - aarch64_sve_sqincd, // llvm.aarch64.sve.sqincd - aarch64_sve_sqincd_n32, // llvm.aarch64.sve.sqincd.n32 - aarch64_sve_sqincd_n64, // llvm.aarch64.sve.sqincd.n64 - aarch64_sve_sqinch, // llvm.aarch64.sve.sqinch - aarch64_sve_sqinch_n32, // llvm.aarch64.sve.sqinch.n32 - aarch64_sve_sqinch_n64, // llvm.aarch64.sve.sqinch.n64 - aarch64_sve_sqincp, // llvm.aarch64.sve.sqincp - aarch64_sve_sqincp_n32, // llvm.aarch64.sve.sqincp.n32 - aarch64_sve_sqincp_n64, // llvm.aarch64.sve.sqincp.n64 - aarch64_sve_sqincw, // llvm.aarch64.sve.sqincw - aarch64_sve_sqincw_n32, // llvm.aarch64.sve.sqincw.n32 - aarch64_sve_sqincw_n64, // llvm.aarch64.sve.sqincw.n64 - aarch64_sve_sqneg, // llvm.aarch64.sve.sqneg - aarch64_sve_sqrdcmlah_lane_x, // llvm.aarch64.sve.sqrdcmlah.lane.x - aarch64_sve_sqrdcmlah_x, // llvm.aarch64.sve.sqrdcmlah.x - aarch64_sve_sqrdmlah, // llvm.aarch64.sve.sqrdmlah - aarch64_sve_sqrdmlah_lane, // llvm.aarch64.sve.sqrdmlah.lane - aarch64_sve_sqrdmlsh, // llvm.aarch64.sve.sqrdmlsh - aarch64_sve_sqrdmlsh_lane, // llvm.aarch64.sve.sqrdmlsh.lane - aarch64_sve_sqrdmulh, // llvm.aarch64.sve.sqrdmulh - aarch64_sve_sqrdmulh_lane, // llvm.aarch64.sve.sqrdmulh.lane - aarch64_sve_sqrshl, // llvm.aarch64.sve.sqrshl - aarch64_sve_sqrshrnb, // llvm.aarch64.sve.sqrshrnb - aarch64_sve_sqrshrnt, // llvm.aarch64.sve.sqrshrnt - aarch64_sve_sqrshrunb, // llvm.aarch64.sve.sqrshrunb - aarch64_sve_sqrshrunt, // llvm.aarch64.sve.sqrshrunt - aarch64_sve_sqshl, // llvm.aarch64.sve.sqshl - aarch64_sve_sqshlu, // llvm.aarch64.sve.sqshlu - aarch64_sve_sqshrnb, // llvm.aarch64.sve.sqshrnb - aarch64_sve_sqshrnt, // llvm.aarch64.sve.sqshrnt - aarch64_sve_sqshrunb, // llvm.aarch64.sve.sqshrunb - aarch64_sve_sqshrunt, // llvm.aarch64.sve.sqshrunt - aarch64_sve_sqsub, // llvm.aarch64.sve.sqsub - aarch64_sve_sqsub_x, // llvm.aarch64.sve.sqsub.x - aarch64_sve_sqsubr, // llvm.aarch64.sve.sqsubr - aarch64_sve_sqxtnb, // llvm.aarch64.sve.sqxtnb - aarch64_sve_sqxtnt, // llvm.aarch64.sve.sqxtnt - aarch64_sve_sqxtunb, // llvm.aarch64.sve.sqxtunb - aarch64_sve_sqxtunt, // llvm.aarch64.sve.sqxtunt - aarch64_sve_srhadd, // llvm.aarch64.sve.srhadd - aarch64_sve_sri, // llvm.aarch64.sve.sri - aarch64_sve_srshl, // llvm.aarch64.sve.srshl - aarch64_sve_srshr, // llvm.aarch64.sve.srshr - aarch64_sve_srsra, // llvm.aarch64.sve.srsra - aarch64_sve_sshllb, // llvm.aarch64.sve.sshllb - aarch64_sve_sshllt, // llvm.aarch64.sve.sshllt - aarch64_sve_ssra, // llvm.aarch64.sve.ssra - aarch64_sve_ssublb, // llvm.aarch64.sve.ssublb - aarch64_sve_ssublbt, // llvm.aarch64.sve.ssublbt - aarch64_sve_ssublt, // llvm.aarch64.sve.ssublt - aarch64_sve_ssubltb, // llvm.aarch64.sve.ssubltb - aarch64_sve_ssubwb, // llvm.aarch64.sve.ssubwb - aarch64_sve_ssubwt, // llvm.aarch64.sve.ssubwt - aarch64_sve_st1, // llvm.aarch64.sve.st1 - aarch64_sve_st1_scatter, // llvm.aarch64.sve.st1.scatter - aarch64_sve_st1_scatter_index, // llvm.aarch64.sve.st1.scatter.index - aarch64_sve_st1_scatter_scalar_offset, // llvm.aarch64.sve.st1.scatter.scalar.offset - aarch64_sve_st1_scatter_sxtw, // llvm.aarch64.sve.st1.scatter.sxtw - aarch64_sve_st1_scatter_sxtw_index, // llvm.aarch64.sve.st1.scatter.sxtw.index - aarch64_sve_st1_scatter_uxtw, // llvm.aarch64.sve.st1.scatter.uxtw - aarch64_sve_st1_scatter_uxtw_index, // llvm.aarch64.sve.st1.scatter.uxtw.index - aarch64_sve_st2, // llvm.aarch64.sve.st2 - aarch64_sve_st3, // llvm.aarch64.sve.st3 - aarch64_sve_st4, // llvm.aarch64.sve.st4 - aarch64_sve_stnt1, // llvm.aarch64.sve.stnt1 - aarch64_sve_stnt1_scatter, // llvm.aarch64.sve.stnt1.scatter - aarch64_sve_stnt1_scatter_index, // llvm.aarch64.sve.stnt1.scatter.index - aarch64_sve_stnt1_scatter_scalar_offset, // llvm.aarch64.sve.stnt1.scatter.scalar.offset - aarch64_sve_stnt1_scatter_uxtw, // llvm.aarch64.sve.stnt1.scatter.uxtw - aarch64_sve_sub, // llvm.aarch64.sve.sub - aarch64_sve_subhnb, // llvm.aarch64.sve.subhnb - aarch64_sve_subhnt, // llvm.aarch64.sve.subhnt - aarch64_sve_subr, // llvm.aarch64.sve.subr - aarch64_sve_sudot_lane, // llvm.aarch64.sve.sudot.lane - aarch64_sve_sunpkhi, // llvm.aarch64.sve.sunpkhi - aarch64_sve_sunpklo, // llvm.aarch64.sve.sunpklo - aarch64_sve_suqadd, // llvm.aarch64.sve.suqadd - aarch64_sve_sxtb, // llvm.aarch64.sve.sxtb - aarch64_sve_sxth, // llvm.aarch64.sve.sxth - aarch64_sve_sxtw, // llvm.aarch64.sve.sxtw - aarch64_sve_tbl, // llvm.aarch64.sve.tbl - aarch64_sve_tbl2, // llvm.aarch64.sve.tbl2 - aarch64_sve_tbx, // llvm.aarch64.sve.tbx - aarch64_sve_trn1, // llvm.aarch64.sve.trn1 - aarch64_sve_trn1q, // llvm.aarch64.sve.trn1q - aarch64_sve_trn2, // llvm.aarch64.sve.trn2 - aarch64_sve_trn2q, // llvm.aarch64.sve.trn2q - aarch64_sve_tuple_create2, // llvm.aarch64.sve.tuple.create2 - aarch64_sve_tuple_create3, // llvm.aarch64.sve.tuple.create3 - aarch64_sve_tuple_create4, // llvm.aarch64.sve.tuple.create4 - aarch64_sve_tuple_get, // llvm.aarch64.sve.tuple.get - aarch64_sve_tuple_set, // llvm.aarch64.sve.tuple.set - aarch64_sve_uaba, // llvm.aarch64.sve.uaba - aarch64_sve_uabalb, // llvm.aarch64.sve.uabalb - aarch64_sve_uabalt, // llvm.aarch64.sve.uabalt - aarch64_sve_uabd, // llvm.aarch64.sve.uabd - aarch64_sve_uabdlb, // llvm.aarch64.sve.uabdlb - aarch64_sve_uabdlt, // llvm.aarch64.sve.uabdlt - aarch64_sve_uadalp, // llvm.aarch64.sve.uadalp - aarch64_sve_uaddlb, // llvm.aarch64.sve.uaddlb - aarch64_sve_uaddlt, // llvm.aarch64.sve.uaddlt - aarch64_sve_uaddv, // llvm.aarch64.sve.uaddv - aarch64_sve_uaddwb, // llvm.aarch64.sve.uaddwb - aarch64_sve_uaddwt, // llvm.aarch64.sve.uaddwt - aarch64_sve_ucvtf, // llvm.aarch64.sve.ucvtf - aarch64_sve_ucvtf_f16i32, // llvm.aarch64.sve.ucvtf.f16i32 - aarch64_sve_ucvtf_f16i64, // llvm.aarch64.sve.ucvtf.f16i64 - aarch64_sve_ucvtf_f32i64, // llvm.aarch64.sve.ucvtf.f32i64 - aarch64_sve_ucvtf_f64i32, // llvm.aarch64.sve.ucvtf.f64i32 - aarch64_sve_udiv, // llvm.aarch64.sve.udiv - aarch64_sve_udivr, // llvm.aarch64.sve.udivr - aarch64_sve_udot, // llvm.aarch64.sve.udot - aarch64_sve_udot_lane, // llvm.aarch64.sve.udot.lane - aarch64_sve_uhadd, // llvm.aarch64.sve.uhadd - aarch64_sve_uhsub, // llvm.aarch64.sve.uhsub - aarch64_sve_uhsubr, // llvm.aarch64.sve.uhsubr - aarch64_sve_umax, // llvm.aarch64.sve.umax - aarch64_sve_umaxp, // llvm.aarch64.sve.umaxp - aarch64_sve_umaxv, // llvm.aarch64.sve.umaxv - aarch64_sve_umin, // llvm.aarch64.sve.umin - aarch64_sve_uminp, // llvm.aarch64.sve.uminp - aarch64_sve_uminv, // llvm.aarch64.sve.uminv - aarch64_sve_umlalb, // llvm.aarch64.sve.umlalb - aarch64_sve_umlalb_lane, // llvm.aarch64.sve.umlalb.lane - aarch64_sve_umlalt, // llvm.aarch64.sve.umlalt - aarch64_sve_umlalt_lane, // llvm.aarch64.sve.umlalt.lane - aarch64_sve_umlslb, // llvm.aarch64.sve.umlslb - aarch64_sve_umlslb_lane, // llvm.aarch64.sve.umlslb.lane - aarch64_sve_umlslt, // llvm.aarch64.sve.umlslt - aarch64_sve_umlslt_lane, // llvm.aarch64.sve.umlslt.lane - aarch64_sve_ummla, // llvm.aarch64.sve.ummla - aarch64_sve_umulh, // llvm.aarch64.sve.umulh - aarch64_sve_umullb, // llvm.aarch64.sve.umullb - aarch64_sve_umullb_lane, // llvm.aarch64.sve.umullb.lane - aarch64_sve_umullt, // llvm.aarch64.sve.umullt - aarch64_sve_umullt_lane, // llvm.aarch64.sve.umullt.lane - aarch64_sve_uqadd, // llvm.aarch64.sve.uqadd - aarch64_sve_uqadd_x, // llvm.aarch64.sve.uqadd.x - aarch64_sve_uqdecb_n32, // llvm.aarch64.sve.uqdecb.n32 - aarch64_sve_uqdecb_n64, // llvm.aarch64.sve.uqdecb.n64 - aarch64_sve_uqdecd, // llvm.aarch64.sve.uqdecd - aarch64_sve_uqdecd_n32, // llvm.aarch64.sve.uqdecd.n32 - aarch64_sve_uqdecd_n64, // llvm.aarch64.sve.uqdecd.n64 - aarch64_sve_uqdech, // llvm.aarch64.sve.uqdech - aarch64_sve_uqdech_n32, // llvm.aarch64.sve.uqdech.n32 - aarch64_sve_uqdech_n64, // llvm.aarch64.sve.uqdech.n64 - aarch64_sve_uqdecp, // llvm.aarch64.sve.uqdecp - aarch64_sve_uqdecp_n32, // llvm.aarch64.sve.uqdecp.n32 - aarch64_sve_uqdecp_n64, // llvm.aarch64.sve.uqdecp.n64 - aarch64_sve_uqdecw, // llvm.aarch64.sve.uqdecw - aarch64_sve_uqdecw_n32, // llvm.aarch64.sve.uqdecw.n32 - aarch64_sve_uqdecw_n64, // llvm.aarch64.sve.uqdecw.n64 - aarch64_sve_uqincb_n32, // llvm.aarch64.sve.uqincb.n32 - aarch64_sve_uqincb_n64, // llvm.aarch64.sve.uqincb.n64 - aarch64_sve_uqincd, // llvm.aarch64.sve.uqincd - aarch64_sve_uqincd_n32, // llvm.aarch64.sve.uqincd.n32 - aarch64_sve_uqincd_n64, // llvm.aarch64.sve.uqincd.n64 - aarch64_sve_uqinch, // llvm.aarch64.sve.uqinch - aarch64_sve_uqinch_n32, // llvm.aarch64.sve.uqinch.n32 - aarch64_sve_uqinch_n64, // llvm.aarch64.sve.uqinch.n64 - aarch64_sve_uqincp, // llvm.aarch64.sve.uqincp - aarch64_sve_uqincp_n32, // llvm.aarch64.sve.uqincp.n32 - aarch64_sve_uqincp_n64, // llvm.aarch64.sve.uqincp.n64 - aarch64_sve_uqincw, // llvm.aarch64.sve.uqincw - aarch64_sve_uqincw_n32, // llvm.aarch64.sve.uqincw.n32 - aarch64_sve_uqincw_n64, // llvm.aarch64.sve.uqincw.n64 - aarch64_sve_uqrshl, // llvm.aarch64.sve.uqrshl - aarch64_sve_uqrshrnb, // llvm.aarch64.sve.uqrshrnb - aarch64_sve_uqrshrnt, // llvm.aarch64.sve.uqrshrnt - aarch64_sve_uqshl, // llvm.aarch64.sve.uqshl - aarch64_sve_uqshrnb, // llvm.aarch64.sve.uqshrnb - aarch64_sve_uqshrnt, // llvm.aarch64.sve.uqshrnt - aarch64_sve_uqsub, // llvm.aarch64.sve.uqsub - aarch64_sve_uqsub_x, // llvm.aarch64.sve.uqsub.x - aarch64_sve_uqsubr, // llvm.aarch64.sve.uqsubr - aarch64_sve_uqxtnb, // llvm.aarch64.sve.uqxtnb - aarch64_sve_uqxtnt, // llvm.aarch64.sve.uqxtnt - aarch64_sve_urecpe, // llvm.aarch64.sve.urecpe - aarch64_sve_urhadd, // llvm.aarch64.sve.urhadd - aarch64_sve_urshl, // llvm.aarch64.sve.urshl - aarch64_sve_urshr, // llvm.aarch64.sve.urshr - aarch64_sve_ursqrte, // llvm.aarch64.sve.ursqrte - aarch64_sve_ursra, // llvm.aarch64.sve.ursra - aarch64_sve_usdot, // llvm.aarch64.sve.usdot - aarch64_sve_usdot_lane, // llvm.aarch64.sve.usdot.lane - aarch64_sve_ushllb, // llvm.aarch64.sve.ushllb - aarch64_sve_ushllt, // llvm.aarch64.sve.ushllt - aarch64_sve_usmmla, // llvm.aarch64.sve.usmmla - aarch64_sve_usqadd, // llvm.aarch64.sve.usqadd - aarch64_sve_usra, // llvm.aarch64.sve.usra - aarch64_sve_usublb, // llvm.aarch64.sve.usublb - aarch64_sve_usublt, // llvm.aarch64.sve.usublt - aarch64_sve_usubwb, // llvm.aarch64.sve.usubwb - aarch64_sve_usubwt, // llvm.aarch64.sve.usubwt - aarch64_sve_uunpkhi, // llvm.aarch64.sve.uunpkhi - aarch64_sve_uunpklo, // llvm.aarch64.sve.uunpklo - aarch64_sve_uxtb, // llvm.aarch64.sve.uxtb - aarch64_sve_uxth, // llvm.aarch64.sve.uxth - aarch64_sve_uxtw, // llvm.aarch64.sve.uxtw - aarch64_sve_uzp1, // llvm.aarch64.sve.uzp1 - aarch64_sve_uzp1q, // llvm.aarch64.sve.uzp1q - aarch64_sve_uzp2, // llvm.aarch64.sve.uzp2 - aarch64_sve_uzp2q, // llvm.aarch64.sve.uzp2q - aarch64_sve_whilege, // llvm.aarch64.sve.whilege - aarch64_sve_whilegt, // llvm.aarch64.sve.whilegt - aarch64_sve_whilehi, // llvm.aarch64.sve.whilehi - aarch64_sve_whilehs, // llvm.aarch64.sve.whilehs - aarch64_sve_whilele, // llvm.aarch64.sve.whilele - aarch64_sve_whilelo, // llvm.aarch64.sve.whilelo - aarch64_sve_whilels, // llvm.aarch64.sve.whilels - aarch64_sve_whilelt, // llvm.aarch64.sve.whilelt - aarch64_sve_whilerw_b, // llvm.aarch64.sve.whilerw.b - aarch64_sve_whilerw_d, // llvm.aarch64.sve.whilerw.d - aarch64_sve_whilerw_h, // llvm.aarch64.sve.whilerw.h - aarch64_sve_whilerw_s, // llvm.aarch64.sve.whilerw.s - aarch64_sve_whilewr_b, // llvm.aarch64.sve.whilewr.b - aarch64_sve_whilewr_d, // llvm.aarch64.sve.whilewr.d - aarch64_sve_whilewr_h, // llvm.aarch64.sve.whilewr.h - aarch64_sve_whilewr_s, // llvm.aarch64.sve.whilewr.s - aarch64_sve_wrffr, // llvm.aarch64.sve.wrffr - aarch64_sve_xar, // llvm.aarch64.sve.xar - aarch64_sve_zip1, // llvm.aarch64.sve.zip1 - aarch64_sve_zip1q, // llvm.aarch64.sve.zip1q - aarch64_sve_zip2, // llvm.aarch64.sve.zip2 - aarch64_sve_zip2q, // llvm.aarch64.sve.zip2q - aarch64_tagp, // llvm.aarch64.tagp - aarch64_tcancel, // llvm.aarch64.tcancel - aarch64_tcommit, // llvm.aarch64.tcommit - aarch64_tstart, // llvm.aarch64.tstart - aarch64_ttest, // llvm.aarch64.ttest - aarch64_udiv, // llvm.aarch64.udiv -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.td deleted file mode 100644 index a65ddff07a..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAArch64.td +++ /dev/null @@ -1,2582 +0,0 @@ -//===- IntrinsicsAARCH64.td - Defines AARCH64 intrinsics ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the AARCH64-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "aarch64" in { - -def int_aarch64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_ldaxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_stxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_stlxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty], - [IntrNoFree, IntrWillReturn]>; - -def int_aarch64_ldxp : Intrinsic<[llvm_i64_ty, llvm_i64_ty], [llvm_ptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_ldaxp : Intrinsic<[llvm_i64_ty, llvm_i64_ty], [llvm_ptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_stxp : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_ptr_ty], - [IntrNoFree, IntrWillReturn]>; -def int_aarch64_stlxp : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_ptr_ty], - [IntrNoFree, IntrWillReturn]>; - -def int_aarch64_clrex : Intrinsic<[]>; - -def int_aarch64_sdiv : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, - LLVMMatchType<0>], [IntrNoMem]>; -def int_aarch64_udiv : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, - LLVMMatchType<0>], [IntrNoMem]>; - -def int_aarch64_fjcvtzs : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; - -def int_aarch64_cls: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_cls64: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>; - -def int_aarch64_frint32z - : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ], - [ IntrNoMem ]>; -def int_aarch64_frint64z - : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ], - [ IntrNoMem ]>; -def int_aarch64_frint32x - : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ], - [ IntrNoMem ]>; -def int_aarch64_frint64x - : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ], - [ IntrNoMem ]>; - -//===----------------------------------------------------------------------===// -// HINT - -def int_aarch64_hint : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>; - -//===----------------------------------------------------------------------===// -// Data Barrier Instructions - -def int_aarch64_dmb : GCCBuiltin<"__builtin_arm_dmb">, MSBuiltin<"__dmb">, - Intrinsic<[], [llvm_i32_ty], [IntrNoFree, IntrWillReturn]>; -def int_aarch64_dsb : GCCBuiltin<"__builtin_arm_dsb">, MSBuiltin<"__dsb">, - Intrinsic<[], [llvm_i32_ty], [IntrNoFree, IntrWillReturn]>; -def int_aarch64_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">, - Intrinsic<[], [llvm_i32_ty], [IntrNoFree, IntrWillReturn]>; - -// A space-consuming intrinsic primarily for testing block and jump table -// placements. The first argument is the number of bytes this "instruction" -// takes up, the second and return value are essentially chains, used to force -// ordering during ISel. -def int_aarch64_space : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty], []>; - -} - -//===----------------------------------------------------------------------===// -// Advanced SIMD (NEON) - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - class AdvSIMD_2Scalar_Float_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_FPToIntRounding_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty], [IntrNoMem]>; - - class AdvSIMD_1IntArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoMem]>; - class AdvSIMD_1FloatArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Expand_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMTruncatedType<0>], [IntrNoMem]>; - class AdvSIMD_1IntArg_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyint_ty], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMExtendedType<0>], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Int_Across_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyvector_ty], [IntrNoMem]>; - class AdvSIMD_1VectorArg_Float_Across_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_anyvector_ty], [IntrNoMem]>; - - class AdvSIMD_2IntArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_2FloatArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Compare_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - class AdvSIMD_2Arg_FloatCompare_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, LLVMMatchType<1>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMTruncatedType<0>, LLVMTruncatedType<0>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Wide_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMTruncatedType<0>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMExtendedType<0>, LLVMExtendedType<0>], - [IntrNoMem]>; - class AdvSIMD_2Arg_Scalar_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMExtendedType<0>, llvm_i32_ty], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Scalar_Expand_BySize_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Scalar_Wide_BySize_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMTruncatedType<0>], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMTruncatedType<0>, llvm_i32_ty], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Tied_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty], - [IntrNoMem]>; - class AdvSIMD_2VectorArg_Lane_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_anyint_ty, llvm_i32_ty], - [IntrNoMem]>; - - class AdvSIMD_3IntArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_3VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_3VectorArg_Scalar_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem]>; - class AdvSIMD_3VectorArg_Tied_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty, - LLVMMatchType<1>], [IntrNoMem]>; - class AdvSIMD_3VectorArg_Scalar_Tied_Narrow_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty, llvm_i32_ty], - [IntrNoMem]>; - class AdvSIMD_CvtFxToFP_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], - [IntrNoMem]>; - class AdvSIMD_CvtFPToFx_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], - [IntrNoMem]>; - - class AdvSIMD_1Arg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem]>; - - class AdvSIMD_Dot_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - - class AdvSIMD_FP16FML_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - - class AdvSIMD_MatMul_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - - class AdvSIMD_FML_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - - class AdvSIMD_BF16FML_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v8bf16_ty, llvm_v8bf16_ty], - [IntrNoMem]>; -} - -// Arithmetic ops - -let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { - // Vector Add Across Lanes - def int_aarch64_neon_saddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_uaddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_faddv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; - - // Vector Long Add Across Lanes - def int_aarch64_neon_saddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_uaddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - - // Vector Halving Add - def int_aarch64_neon_shadd : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_uhadd : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Rounding Halving Add - def int_aarch64_neon_srhadd : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_urhadd : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Saturating Add - def int_aarch64_neon_sqadd : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_suqadd : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_usqadd : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_uqadd : AdvSIMD_2IntArg_Intrinsic; - - // Vector Add High-Half - // FIXME: this is a legacy intrinsic for aarch64_simd.h. Remove it when that - // header is no longer supported. - def int_aarch64_neon_addhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; - - // Vector Rounding Add High-Half - def int_aarch64_neon_raddhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; - - // Vector Saturating Doubling Multiply High - def int_aarch64_neon_sqdmulh : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_sqdmulh_lane : AdvSIMD_2VectorArg_Lane_Intrinsic; - def int_aarch64_neon_sqdmulh_laneq : AdvSIMD_2VectorArg_Lane_Intrinsic; - - // Vector Saturating Rounding Doubling Multiply High - def int_aarch64_neon_sqrdmulh : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_sqrdmulh_lane : AdvSIMD_2VectorArg_Lane_Intrinsic; - def int_aarch64_neon_sqrdmulh_laneq : AdvSIMD_2VectorArg_Lane_Intrinsic; - - def int_aarch64_neon_sqrdmlah : AdvSIMD_3IntArg_Intrinsic; - def int_aarch64_neon_sqrdmlsh : AdvSIMD_3IntArg_Intrinsic; - - // Vector Polynominal Multiply - def int_aarch64_neon_pmul : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Long Multiply - def int_aarch64_neon_smull : AdvSIMD_2VectorArg_Long_Intrinsic; - def int_aarch64_neon_umull : AdvSIMD_2VectorArg_Long_Intrinsic; - def int_aarch64_neon_pmull : AdvSIMD_2VectorArg_Long_Intrinsic; - - // 64-bit polynomial multiply really returns an i128, which is not legal. Fake - // it with a v16i8. - def int_aarch64_neon_pmull64 : - DefaultAttrsIntrinsic<[llvm_v16i8_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - - // Vector Extending Multiply - def int_aarch64_neon_fmulx : AdvSIMD_2FloatArg_Intrinsic { - let IntrProperties = [IntrNoMem, Commutative]; - } - - // Vector Saturating Doubling Long Multiply - def int_aarch64_neon_sqdmull : AdvSIMD_2VectorArg_Long_Intrinsic; - def int_aarch64_neon_sqdmulls_scalar - : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - - // Vector Halving Subtract - def int_aarch64_neon_shsub : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_uhsub : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Saturating Subtract - def int_aarch64_neon_sqsub : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_uqsub : AdvSIMD_2IntArg_Intrinsic; - - // Vector Subtract High-Half - // FIXME: this is a legacy intrinsic for aarch64_simd.h. Remove it when that - // header is no longer supported. - def int_aarch64_neon_subhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; - - // Vector Rounding Subtract High-Half - def int_aarch64_neon_rsubhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; - - // Vector Compare Absolute Greater-than-or-equal - def int_aarch64_neon_facge : AdvSIMD_2Arg_FloatCompare_Intrinsic; - - // Vector Compare Absolute Greater-than - def int_aarch64_neon_facgt : AdvSIMD_2Arg_FloatCompare_Intrinsic; - - // Vector Absolute Difference - def int_aarch64_neon_sabd : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_uabd : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fabd : AdvSIMD_2VectorArg_Intrinsic; - - // Scalar Absolute Difference - def int_aarch64_sisd_fabd : AdvSIMD_2Scalar_Float_Intrinsic; - - // Vector Max - def int_aarch64_neon_smax : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_umax : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fmax : AdvSIMD_2FloatArg_Intrinsic; - def int_aarch64_neon_fmaxnmp : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Max Across Lanes - def int_aarch64_neon_smaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_umaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_fmaxv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; - def int_aarch64_neon_fmaxnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; - - // Vector Min - def int_aarch64_neon_smin : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_umin : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fmin : AdvSIMD_2FloatArg_Intrinsic; - def int_aarch64_neon_fminnmp : AdvSIMD_2VectorArg_Intrinsic; - - // Vector Min/Max Number - def int_aarch64_neon_fminnm : AdvSIMD_2FloatArg_Intrinsic; - def int_aarch64_neon_fmaxnm : AdvSIMD_2FloatArg_Intrinsic; - - // Vector Min Across Lanes - def int_aarch64_neon_sminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_uminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; - def int_aarch64_neon_fminv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; - def int_aarch64_neon_fminnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; - - // Pairwise Add - def int_aarch64_neon_addp : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_faddp : AdvSIMD_2VectorArg_Intrinsic; - - // Long Pairwise Add - // FIXME: In theory, we shouldn't need intrinsics for saddlp or - // uaddlp, but tblgen's type inference currently can't handle the - // pattern fragments this ends up generating. - def int_aarch64_neon_saddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; - def int_aarch64_neon_uaddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; - - // Folding Maximum - def int_aarch64_neon_smaxp : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_umaxp : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fmaxp : AdvSIMD_2VectorArg_Intrinsic; - - // Folding Minimum - def int_aarch64_neon_sminp : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_uminp : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fminp : AdvSIMD_2VectorArg_Intrinsic; - - // Reciprocal Estimate/Step - def int_aarch64_neon_frecps : AdvSIMD_2FloatArg_Intrinsic; - def int_aarch64_neon_frsqrts : AdvSIMD_2FloatArg_Intrinsic; - - // Reciprocal Exponent - def int_aarch64_neon_frecpx : AdvSIMD_1FloatArg_Intrinsic; - - // Vector Saturating Shift Left - def int_aarch64_neon_sqshl : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_uqshl : AdvSIMD_2IntArg_Intrinsic; - - // Vector Rounding Shift Left - def int_aarch64_neon_srshl : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_urshl : AdvSIMD_2IntArg_Intrinsic; - - // Vector Saturating Rounding Shift Left - def int_aarch64_neon_sqrshl : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_uqrshl : AdvSIMD_2IntArg_Intrinsic; - - // Vector Signed->Unsigned Shift Left by Constant - def int_aarch64_neon_sqshlu : AdvSIMD_2IntArg_Intrinsic; - - // Vector Signed->Unsigned Narrowing Saturating Shift Right by Constant - def int_aarch64_neon_sqshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - - // Vector Signed->Unsigned Rounding Narrowing Saturating Shift Right by Const - def int_aarch64_neon_sqrshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - - // Vector Narrowing Shift Right by Constant - def int_aarch64_neon_sqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - def int_aarch64_neon_uqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - - // Vector Rounding Narrowing Shift Right by Constant - def int_aarch64_neon_rshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - - // Vector Rounding Narrowing Saturating Shift Right by Constant - def int_aarch64_neon_sqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - def int_aarch64_neon_uqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; - - // Vector Shift Left - def int_aarch64_neon_sshl : AdvSIMD_2IntArg_Intrinsic; - def int_aarch64_neon_ushl : AdvSIMD_2IntArg_Intrinsic; - - // Vector Widening Shift Left by Constant - def int_aarch64_neon_shll : AdvSIMD_2VectorArg_Scalar_Wide_BySize_Intrinsic; - def int_aarch64_neon_sshll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; - def int_aarch64_neon_ushll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; - - // Vector Shift Right by Constant and Insert - def int_aarch64_neon_vsri : AdvSIMD_3VectorArg_Scalar_Intrinsic; - - // Vector Shift Left by Constant and Insert - def int_aarch64_neon_vsli : AdvSIMD_3VectorArg_Scalar_Intrinsic; - - // Vector Saturating Narrow - def int_aarch64_neon_scalar_sqxtn: AdvSIMD_1IntArg_Narrow_Intrinsic; - def int_aarch64_neon_scalar_uqxtn : AdvSIMD_1IntArg_Narrow_Intrinsic; - def int_aarch64_neon_sqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; - def int_aarch64_neon_uqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; - - // Vector Saturating Extract and Unsigned Narrow - def int_aarch64_neon_scalar_sqxtun : AdvSIMD_1IntArg_Narrow_Intrinsic; - def int_aarch64_neon_sqxtun : AdvSIMD_1VectorArg_Narrow_Intrinsic; - - // Vector Absolute Value - def int_aarch64_neon_abs : AdvSIMD_1Arg_Intrinsic; - - // Vector Saturating Absolute Value - def int_aarch64_neon_sqabs : AdvSIMD_1IntArg_Intrinsic; - - // Vector Saturating Negation - def int_aarch64_neon_sqneg : AdvSIMD_1IntArg_Intrinsic; - - // Vector Count Leading Sign Bits - def int_aarch64_neon_cls : AdvSIMD_1VectorArg_Intrinsic; - - // Vector Reciprocal Estimate - def int_aarch64_neon_urecpe : AdvSIMD_1VectorArg_Intrinsic; - def int_aarch64_neon_frecpe : AdvSIMD_1FloatArg_Intrinsic; - - // Vector Square Root Estimate - def int_aarch64_neon_ursqrte : AdvSIMD_1VectorArg_Intrinsic; - def int_aarch64_neon_frsqrte : AdvSIMD_1FloatArg_Intrinsic; - - // Vector Conversions Between Half-Precision and Single-Precision. - def int_aarch64_neon_vcvtfp2hf - : DefaultAttrsIntrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_aarch64_neon_vcvthf2fp - : DefaultAttrsIntrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; - - // Vector Conversions Between Floating-point and Fixed-point. - def int_aarch64_neon_vcvtfp2fxs : AdvSIMD_CvtFPToFx_Intrinsic; - def int_aarch64_neon_vcvtfp2fxu : AdvSIMD_CvtFPToFx_Intrinsic; - def int_aarch64_neon_vcvtfxs2fp : AdvSIMD_CvtFxToFP_Intrinsic; - def int_aarch64_neon_vcvtfxu2fp : AdvSIMD_CvtFxToFP_Intrinsic; - - // Vector FP->Int Conversions - def int_aarch64_neon_fcvtas : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtau : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtms : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtmu : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtns : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtnu : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtps : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtpu : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtzs : AdvSIMD_FPToIntRounding_Intrinsic; - def int_aarch64_neon_fcvtzu : AdvSIMD_FPToIntRounding_Intrinsic; - - // v8.5-A Vector FP Rounding - def int_aarch64_neon_frint32x : AdvSIMD_1FloatArg_Intrinsic; - def int_aarch64_neon_frint32z : AdvSIMD_1FloatArg_Intrinsic; - def int_aarch64_neon_frint64x : AdvSIMD_1FloatArg_Intrinsic; - def int_aarch64_neon_frint64z : AdvSIMD_1FloatArg_Intrinsic; - - // Scalar FP->Int conversions - - // Vector FP Inexact Narrowing - def int_aarch64_neon_fcvtxn : AdvSIMD_1VectorArg_Expand_Intrinsic; - - // Scalar FP Inexact Narrowing - def int_aarch64_sisd_fcvtxn : DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], - [IntrNoMem]>; - - // v8.2-A Dot Product - def int_aarch64_neon_udot : AdvSIMD_Dot_Intrinsic; - def int_aarch64_neon_sdot : AdvSIMD_Dot_Intrinsic; - - // v8.6-A Matrix Multiply Intrinsics - def int_aarch64_neon_ummla : AdvSIMD_MatMul_Intrinsic; - def int_aarch64_neon_smmla : AdvSIMD_MatMul_Intrinsic; - def int_aarch64_neon_usmmla : AdvSIMD_MatMul_Intrinsic; - def int_aarch64_neon_usdot : AdvSIMD_Dot_Intrinsic; - def int_aarch64_neon_bfdot : AdvSIMD_Dot_Intrinsic; - def int_aarch64_neon_bfmmla - : DefaultAttrsIntrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v8bf16_ty, llvm_v8bf16_ty], - [IntrNoMem]>; - def int_aarch64_neon_bfmlalb : AdvSIMD_BF16FML_Intrinsic; - def int_aarch64_neon_bfmlalt : AdvSIMD_BF16FML_Intrinsic; - - - // v8.6-A Bfloat Intrinsics - def int_aarch64_neon_bfcvt - : DefaultAttrsIntrinsic<[llvm_bfloat_ty], [llvm_float_ty], [IntrNoMem]>; - def int_aarch64_neon_bfcvtn - : DefaultAttrsIntrinsic<[llvm_v8bf16_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_aarch64_neon_bfcvtn2 - : DefaultAttrsIntrinsic<[llvm_v8bf16_ty], - [llvm_v8bf16_ty, llvm_v4f32_ty], - [IntrNoMem]>; - - // v8.2-A FP16 Fused Multiply-Add Long - def int_aarch64_neon_fmlal : AdvSIMD_FP16FML_Intrinsic; - def int_aarch64_neon_fmlsl : AdvSIMD_FP16FML_Intrinsic; - def int_aarch64_neon_fmlal2 : AdvSIMD_FP16FML_Intrinsic; - def int_aarch64_neon_fmlsl2 : AdvSIMD_FP16FML_Intrinsic; - - // v8.3-A Floating-point complex add - def int_aarch64_neon_vcadd_rot90 : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_vcadd_rot270 : AdvSIMD_2VectorArg_Intrinsic; - - def int_aarch64_neon_vcmla_rot0 : AdvSIMD_3VectorArg_Intrinsic; - def int_aarch64_neon_vcmla_rot90 : AdvSIMD_3VectorArg_Intrinsic; - def int_aarch64_neon_vcmla_rot180 : AdvSIMD_3VectorArg_Intrinsic; - def int_aarch64_neon_vcmla_rot270 : AdvSIMD_3VectorArg_Intrinsic; -} - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - class AdvSIMD_2Vector2Index_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_i64_ty, LLVMMatchType<0>, llvm_i64_ty], - [IntrNoMem]>; -} - -// Vector element to element moves -def int_aarch64_neon_vcopy_lane: AdvSIMD_2Vector2Index_Intrinsic; - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - class AdvSIMD_1Vec_Load_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_1Vec_Store_Lane_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_2Vec_Load_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, llvm_anyvector_ty], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_2Vec_Load_Lane_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i64_ty, llvm_anyptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_2Vec_Store_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, - LLVMAnyPointerType>], - [IntrArgMemOnly, NoCapture>]>; - class AdvSIMD_2Vec_Store_Lane_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, - llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_3Vec_Load_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_3Vec_Load_Lane_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i64_ty, llvm_anyptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_3Vec_Store_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMAnyPointerType>], - [IntrArgMemOnly, NoCapture>]>; - class AdvSIMD_3Vec_Store_Lane_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_4Vec_Load_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_anyvector_ty], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_4Vec_Load_Lane_Intrinsic - : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i64_ty, llvm_anyptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - class AdvSIMD_4Vec_Store_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMAnyPointerType>], - [IntrArgMemOnly, NoCapture>]>; - class AdvSIMD_4Vec_Store_Lane_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture>]>; -} - -// Memory ops - -def int_aarch64_neon_ld1x2 : AdvSIMD_2Vec_Load_Intrinsic; -def int_aarch64_neon_ld1x3 : AdvSIMD_3Vec_Load_Intrinsic; -def int_aarch64_neon_ld1x4 : AdvSIMD_4Vec_Load_Intrinsic; - -def int_aarch64_neon_st1x2 : AdvSIMD_2Vec_Store_Intrinsic; -def int_aarch64_neon_st1x3 : AdvSIMD_3Vec_Store_Intrinsic; -def int_aarch64_neon_st1x4 : AdvSIMD_4Vec_Store_Intrinsic; - -def int_aarch64_neon_ld2 : AdvSIMD_2Vec_Load_Intrinsic; -def int_aarch64_neon_ld3 : AdvSIMD_3Vec_Load_Intrinsic; -def int_aarch64_neon_ld4 : AdvSIMD_4Vec_Load_Intrinsic; - -def int_aarch64_neon_ld2lane : AdvSIMD_2Vec_Load_Lane_Intrinsic; -def int_aarch64_neon_ld3lane : AdvSIMD_3Vec_Load_Lane_Intrinsic; -def int_aarch64_neon_ld4lane : AdvSIMD_4Vec_Load_Lane_Intrinsic; - -def int_aarch64_neon_ld2r : AdvSIMD_2Vec_Load_Intrinsic; -def int_aarch64_neon_ld3r : AdvSIMD_3Vec_Load_Intrinsic; -def int_aarch64_neon_ld4r : AdvSIMD_4Vec_Load_Intrinsic; - -def int_aarch64_neon_st2 : AdvSIMD_2Vec_Store_Intrinsic; -def int_aarch64_neon_st3 : AdvSIMD_3Vec_Store_Intrinsic; -def int_aarch64_neon_st4 : AdvSIMD_4Vec_Store_Intrinsic; - -def int_aarch64_neon_st2lane : AdvSIMD_2Vec_Store_Lane_Intrinsic; -def int_aarch64_neon_st3lane : AdvSIMD_3Vec_Store_Lane_Intrinsic; -def int_aarch64_neon_st4lane : AdvSIMD_4Vec_Store_Lane_Intrinsic; - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - class AdvSIMD_Tbl1_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_v16i8_ty, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_Tbl2_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; - class AdvSIMD_Tbl3_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_Tbl4_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_Tbx1_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_v16i8_ty, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_Tbx2_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_Tbx3_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty, LLVMMatchType<0>], - [IntrNoMem]>; - class AdvSIMD_Tbx4_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], - [IntrNoMem]>; -} -def int_aarch64_neon_tbl1 : AdvSIMD_Tbl1_Intrinsic; -def int_aarch64_neon_tbl2 : AdvSIMD_Tbl2_Intrinsic; -def int_aarch64_neon_tbl3 : AdvSIMD_Tbl3_Intrinsic; -def int_aarch64_neon_tbl4 : AdvSIMD_Tbl4_Intrinsic; - -def int_aarch64_neon_tbx1 : AdvSIMD_Tbx1_Intrinsic; -def int_aarch64_neon_tbx2 : AdvSIMD_Tbx2_Intrinsic; -def int_aarch64_neon_tbx3 : AdvSIMD_Tbx3_Intrinsic; -def int_aarch64_neon_tbx4 : AdvSIMD_Tbx4_Intrinsic; - -let TargetPrefix = "aarch64" in { - class FPCR_Get_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrHasSideEffects]>; - class FPCR_Set_Intrinsic - : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrNoMem, IntrHasSideEffects]>; - class RNDR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i64_ty, llvm_i1_ty], [], [IntrNoMem, IntrHasSideEffects]>; -} - -// FPCR -def int_aarch64_get_fpcr : FPCR_Get_Intrinsic; -def int_aarch64_set_fpcr : FPCR_Set_Intrinsic; - -// Armv8.5-A Random number generation intrinsics -def int_aarch64_rndr : RNDR_Intrinsic; -def int_aarch64_rndrrs : RNDR_Intrinsic; - -let TargetPrefix = "aarch64" in { - class Crypto_AES_DataKey_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - - class Crypto_AES_Data_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - - // SHA intrinsic taking 5 words of the hash (v4i32, i32) and 4 of the schedule - // (v4i32). - class Crypto_SHA_5Hash4Schedule_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - - // SHA intrinsic taking 5 words of the hash (v4i32, i32) and 4 of the schedule - // (v4i32). - class Crypto_SHA_1Hash_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; - - // SHA intrinsic taking 8 words of the schedule - class Crypto_SHA_8Schedule_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - - // SHA intrinsic taking 12 words of the schedule - class Crypto_SHA_12Schedule_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - - // SHA intrinsic taking 8 words of the hash and 4 of the schedule. - class Crypto_SHA_8Hash4Schedule_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - - // SHA512 intrinsic taking 2 arguments - class Crypto_SHA512_2Arg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - - // SHA512 intrinsic taking 3 Arguments - class Crypto_SHA512_3Arg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - - // SHA3 Intrinsics taking 3 arguments - class Crypto_SHA3_3Arg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - - // SHA3 Intrinsic taking 2 arguments - class Crypto_SHA3_2Arg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - - // SHA3 Intrinsic taking 3 Arguments 1 immediate - class Crypto_SHA3_2ArgImm_Intrinsic - : DefaultAttrsIntrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - - class Crypto_SM3_3Vector_Intrinsic - : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - - class Crypto_SM3_3VectorIndexed_Intrinsic - : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - - class Crypto_SM4_2Vector_Intrinsic - : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -} - -// AES -def int_aarch64_crypto_aese : Crypto_AES_DataKey_Intrinsic; -def int_aarch64_crypto_aesd : Crypto_AES_DataKey_Intrinsic; -def int_aarch64_crypto_aesmc : Crypto_AES_Data_Intrinsic; -def int_aarch64_crypto_aesimc : Crypto_AES_Data_Intrinsic; - -// SHA1 -def int_aarch64_crypto_sha1c : Crypto_SHA_5Hash4Schedule_Intrinsic; -def int_aarch64_crypto_sha1p : Crypto_SHA_5Hash4Schedule_Intrinsic; -def int_aarch64_crypto_sha1m : Crypto_SHA_5Hash4Schedule_Intrinsic; -def int_aarch64_crypto_sha1h : Crypto_SHA_1Hash_Intrinsic; - -def int_aarch64_crypto_sha1su0 : Crypto_SHA_12Schedule_Intrinsic; -def int_aarch64_crypto_sha1su1 : Crypto_SHA_8Schedule_Intrinsic; - -// SHA256 -def int_aarch64_crypto_sha256h : Crypto_SHA_8Hash4Schedule_Intrinsic; -def int_aarch64_crypto_sha256h2 : Crypto_SHA_8Hash4Schedule_Intrinsic; -def int_aarch64_crypto_sha256su0 : Crypto_SHA_8Schedule_Intrinsic; -def int_aarch64_crypto_sha256su1 : Crypto_SHA_12Schedule_Intrinsic; - -//SHA3 -def int_aarch64_crypto_eor3s : Crypto_SHA3_3Arg_Intrinsic; -def int_aarch64_crypto_eor3u : Crypto_SHA3_3Arg_Intrinsic; -def int_aarch64_crypto_bcaxs : Crypto_SHA3_3Arg_Intrinsic; -def int_aarch64_crypto_bcaxu : Crypto_SHA3_3Arg_Intrinsic; -def int_aarch64_crypto_rax1 : Crypto_SHA3_2Arg_Intrinsic; -def int_aarch64_crypto_xar : Crypto_SHA3_2ArgImm_Intrinsic; - -// SHA512 -def int_aarch64_crypto_sha512h : Crypto_SHA512_3Arg_Intrinsic; -def int_aarch64_crypto_sha512h2 : Crypto_SHA512_3Arg_Intrinsic; -def int_aarch64_crypto_sha512su0 : Crypto_SHA512_2Arg_Intrinsic; -def int_aarch64_crypto_sha512su1 : Crypto_SHA512_3Arg_Intrinsic; - -//SM3 & SM4 -def int_aarch64_crypto_sm3partw1 : Crypto_SM3_3Vector_Intrinsic; -def int_aarch64_crypto_sm3partw2 : Crypto_SM3_3Vector_Intrinsic; -def int_aarch64_crypto_sm3ss1 : Crypto_SM3_3Vector_Intrinsic; -def int_aarch64_crypto_sm3tt1a : Crypto_SM3_3VectorIndexed_Intrinsic; -def int_aarch64_crypto_sm3tt1b : Crypto_SM3_3VectorIndexed_Intrinsic; -def int_aarch64_crypto_sm3tt2a : Crypto_SM3_3VectorIndexed_Intrinsic; -def int_aarch64_crypto_sm3tt2b : Crypto_SM3_3VectorIndexed_Intrinsic; -def int_aarch64_crypto_sm4e : Crypto_SM4_2Vector_Intrinsic; -def int_aarch64_crypto_sm4ekey : Crypto_SM4_2Vector_Intrinsic; - -//===----------------------------------------------------------------------===// -// CRC32 - -let TargetPrefix = "aarch64" in { - -def int_aarch64_crc32b : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32cb : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32h : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32ch : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32w : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32cw : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_aarch64_crc32x : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_aarch64_crc32cx : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// Memory Tagging Extensions (MTE) Intrinsics -let TargetPrefix = "aarch64" in { -def int_aarch64_irg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], - [IntrNoMem, IntrHasSideEffects]>; -def int_aarch64_addg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_aarch64_gmi : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_aarch64_ldg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], - [IntrReadMem]>; -def int_aarch64_stg : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], - [IntrWriteMem]>; -def int_aarch64_subp : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; - -// The following are codegen-only intrinsics for stack instrumentation. - -// Generate a randomly tagged stack base pointer. -def int_aarch64_irg_sp : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_i64_ty], - [IntrNoMem, IntrHasSideEffects]>; - -// Transfer pointer tag with offset. -// ptr1 = tagp(ptr0, baseptr, tag_offset) returns a pointer where -// * address is the address in ptr0 -// * tag is a function of (tag in baseptr, tag_offset). -// ** Beware, this is not the same function as implemented by the ADDG instruction! -// Backend optimizations may change tag_offset; the only guarantee is that calls -// to tagp with the same pair of (baseptr, tag_offset) will produce pointers -// with the same tag value, assuming the set of excluded tags has not changed. -// Address bits in baseptr and tag bits in ptr0 are ignored. -// When offset between ptr0 and baseptr is a compile time constant, this can be emitted as -// ADDG ptr1, baseptr, (ptr0 - baseptr), tag_offset -// It is intended that ptr0 is an alloca address, and baseptr is the direct output of llvm.aarch64.irg.sp. -def int_aarch64_tagp : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_ptr_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - -// Update allocation tags for the memory range to match the tag in the pointer argument. -def int_aarch64_settag : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>]>; - -// Update allocation tags for the memory range to match the tag in the pointer argument, -// and set memory contents to zero. -def int_aarch64_settag_zero : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>]>; - -// Update allocation tags for 16-aligned, 16-sized memory region, and store a pair 8-byte values. -def int_aarch64_stgp : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>]>; -} - -//===----------------------------------------------------------------------===// -// Memory Operations (MOPS) Intrinsics -let TargetPrefix = "aarch64" in { - // Sizes are chosen to correspond to the llvm.memset intrinsic: ptr, i8, i64 - def int_aarch64_mops_memset_tag : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i8_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>]>; -} - -// Transactional Memory Extension (TME) Intrinsics -let TargetPrefix = "aarch64" in { -def int_aarch64_tstart : GCCBuiltin<"__builtin_arm_tstart">, - Intrinsic<[llvm_i64_ty], [], [IntrWillReturn]>; - -def int_aarch64_tcommit : GCCBuiltin<"__builtin_arm_tcommit">, Intrinsic<[], [], [IntrWillReturn]>; - -def int_aarch64_tcancel : GCCBuiltin<"__builtin_arm_tcancel">, - Intrinsic<[], [llvm_i64_ty], [IntrWillReturn, ImmArg>]>; - -def int_aarch64_ttest : GCCBuiltin<"__builtin_arm_ttest">, - Intrinsic<[llvm_i64_ty], [], - [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -// Armv8.7-A load/store 64-byte intrinsics -defvar data512 = !listsplat(llvm_i64_ty, 8); -def int_aarch64_ld64b: Intrinsic; -def int_aarch64_st64b: Intrinsic<[], !listconcat([llvm_ptr_ty], data512)>; -def int_aarch64_st64bv: Intrinsic<[llvm_i64_ty], !listconcat([llvm_ptr_ty], data512)>; -def int_aarch64_st64bv0: Intrinsic<[llvm_i64_ty], !listconcat([llvm_ptr_ty], data512)>; - -} - -def llvm_nxv2i1_ty : LLVMType; -def llvm_nxv4i1_ty : LLVMType; -def llvm_nxv8i1_ty : LLVMType; -def llvm_nxv16i1_ty : LLVMType; -def llvm_nxv16i8_ty : LLVMType; -def llvm_nxv4i32_ty : LLVMType; -def llvm_nxv2i64_ty : LLVMType; -def llvm_nxv8f16_ty : LLVMType; -def llvm_nxv8bf16_ty : LLVMType; -def llvm_nxv4f32_ty : LLVMType; -def llvm_nxv2f64_ty : LLVMType; - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - - class AdvSIMD_SVE_Create_2Vector_Tuple - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>], - [IntrReadMem]>; - - class AdvSIMD_SVE_Create_3Vector_Tuple - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>], - [IntrReadMem]>; - - class AdvSIMD_SVE_Create_4Vector_Tuple - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>], - [IntrReadMem]>; - - class AdvSIMD_SVE_Set_Vector_Tuple - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_anyvector_ty], - [IntrReadMem, ImmArg>]>; - - class AdvSIMD_SVE_Get_Vector_Tuple - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, ImmArg>]>; - - class AdvSIMD_ManyVec_PredLoad_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMPointerToElt<0>], - [IntrReadMem, IntrArgMemOnly]>; - - class AdvSIMD_1Vec_PredLoad_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrReadMem, IntrArgMemOnly]>; - - class AdvSIMD_2Vec_PredLoad_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrReadMem, IntrArgMemOnly]>; - - class AdvSIMD_3Vec_PredLoad_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrReadMem, IntrArgMemOnly]>; - - class AdvSIMD_4Vec_PredLoad_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrReadMem, IntrArgMemOnly]>; - - class AdvSIMD_1Vec_PredLoad_WriteFFR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrInaccessibleMemOrArgMemOnly]>; - - class AdvSIMD_1Vec_PredStore_Intrinsic - : DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_2Vec_PredStore_Intrinsic - : DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMPointerToElt<0>], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_3Vec_PredStore_Intrinsic - : DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMPointerToElt<0>], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_4Vec_PredStore_Intrinsic - : DefaultAttrsIntrinsic<[], - [llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMPointerToElt<0>], - [IntrArgMemOnly, NoCapture>]>; - - class AdvSIMD_SVE_Index_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMVectorElementType<0>, - LLVMVectorElementType<0>], - [IntrNoMem]>; - - class AdvSIMD_Merged1VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_2VectorArgIndexed_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_3VectorArgIndexed_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_Pred1VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_Pred2VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_Pred3VectorArg_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_Compare_Intrinsic - : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_CompareWide_Intrinsic - : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, - llvm_nxv2i64_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_Saturating_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrNoMem]>; - - class AdvSIMD_SVE_SaturatingWithPattern_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - class AdvSIMD_SVE_Saturating_N_Intrinsic - : DefaultAttrsIntrinsic<[T], - [T, llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic - : DefaultAttrsIntrinsic<[T], - [T, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - class AdvSIMD_SVE_CNT_Intrinsic - : DefaultAttrsIntrinsic<[LLVMVectorOfBitcastsToInt<0>], - [LLVMVectorOfBitcastsToInt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_ReduceWithInit_Intrinsic - : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMVectorElementType<0>, - llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_ShiftByImm_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_ShiftWide_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - llvm_nxv2i64_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_Unpack_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_CADD_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_CMLA_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_CMLA_LANE_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMMatchType<0>, - llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - class AdvSIMD_SVE_DUP_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMVectorElementType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_DUP_Unpred_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMVectorElementType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_DUPQ_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - llvm_i64_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_EXPA_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMVectorOfBitcastsToInt<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_FCVT_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_FCVTZS_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMVectorOfBitcastsToInt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_INSR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMVectorElementType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_PTRUE_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_PUNPKHI_Intrinsic - : DefaultAttrsIntrinsic<[LLVMHalfElementsVectorType<0>], - [llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_SCALE_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMVectorOfBitcastsToInt<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_SCVTF_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - - class AdvSIMD_SVE_TSMUL_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMVectorOfBitcastsToInt<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_CNTB_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i64_ty], - [llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_CNTP_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i64_ty], - [llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_DOT_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide4VectorType<0>, - LLVMSubdivide4VectorType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_DOT_Indexed_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide4VectorType<0>, - LLVMSubdivide4VectorType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_PTEST_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i1_ty], - [llvm_anyvector_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE_TBL_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMVectorOfBitcastsToInt<0>], - [IntrNoMem]>; - - class AdvSIMD_SVE2_TBX_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMMatchType<0>, - LLVMVectorOfBitcastsToInt<0>], - [IntrNoMem]>; - - class SVE2_1VectorArg_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class SVE2_2VectorArg_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>, - LLVMSubdivide2VectorType<0>], - [IntrNoMem]>; - - class SVE2_2VectorArgIndexed_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>, - LLVMSubdivide2VectorType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class SVE2_2VectorArg_Wide_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide2VectorType<0>], - [IntrNoMem]>; - - class SVE2_2VectorArg_Pred_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<0>, - LLVMSubdivide2VectorType<0>], - [IntrNoMem]>; - - class SVE2_3VectorArg_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide2VectorType<0>, - LLVMSubdivide2VectorType<0>], - [IntrNoMem]>; - - class SVE2_3VectorArgIndexed_Long_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide2VectorType<0>, - LLVMSubdivide2VectorType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class SVE2_1VectorArg_Narrowing_Intrinsic - : DefaultAttrsIntrinsic<[LLVMSubdivide2VectorType<0>], - [llvm_anyvector_ty], - [IntrNoMem]>; - - class SVE2_Merged1VectorArg_Narrowing_Intrinsic - : DefaultAttrsIntrinsic<[LLVMSubdivide2VectorType<0>], - [LLVMSubdivide2VectorType<0>, - llvm_anyvector_ty], - [IntrNoMem]>; - class SVE2_2VectorArg_Narrowing_Intrinsic - : DefaultAttrsIntrinsic< - [LLVMSubdivide2VectorType<0>], - [llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; - - class SVE2_Merged2VectorArg_Narrowing_Intrinsic - : DefaultAttrsIntrinsic< - [LLVMSubdivide2VectorType<0>], - [LLVMSubdivide2VectorType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; - - class SVE2_1VectorArg_Imm_Narrowing_Intrinsic - : DefaultAttrsIntrinsic<[LLVMSubdivide2VectorType<0>], - [llvm_anyvector_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class SVE2_2VectorArg_Imm_Narrowing_Intrinsic - : DefaultAttrsIntrinsic<[LLVMSubdivide2VectorType<0>], - [LLVMSubdivide2VectorType<0>, llvm_anyvector_ty, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class SVE2_CONFLICT_DETECT_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMAnyPointerType, - LLVMMatchType<1>]>; - - class SVE2_3VectorArg_Indexed_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide2VectorType<0>, - LLVMSubdivide2VectorType<0>, - llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - class AdvSIMD_SVE_CDOT_LANE_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMSubdivide4VectorType<0>, - LLVMSubdivide4VectorType<0>, - llvm_i32_ty, - llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - // NOTE: There is no relationship between these intrinsics beyond an attempt - // to reuse currently identical class definitions. - class AdvSIMD_SVE_LOGB_Intrinsic : AdvSIMD_SVE_CNT_Intrinsic; - class AdvSIMD_SVE2_CADD_Intrinsic : AdvSIMD_2VectorArgIndexed_Intrinsic; - class AdvSIMD_SVE2_CMLA_Intrinsic : AdvSIMD_3VectorArgIndexed_Intrinsic; - - // This class of intrinsics are not intended to be useful within LLVM IR but - // are instead here to support some of the more regid parts of the ACLE. - class Builtin_SVCVT - : DefaultAttrsIntrinsic<[OUT], [OUT, PRED, IN], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// SVE - -let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". - -class AdvSIMD_SVE_Reduce_Intrinsic - : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - -class AdvSIMD_SVE_SADDV_Reduce_Intrinsic - : DefaultAttrsIntrinsic<[llvm_i64_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty], - [IntrNoMem]>; - -class AdvSIMD_SVE_WHILE_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_anyint_ty, LLVMMatchType<1>], - [IntrNoMem]>; - -class AdvSIMD_GatherLoad_SV_64b_Offsets_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i64_ty> - ], - [IntrReadMem, IntrArgMemOnly]>; - -class AdvSIMD_GatherLoad_SV_64b_Offsets_WriteFFR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i64_ty> - ], - [IntrInaccessibleMemOrArgMemOnly]>; - -class AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i32_ty> - ], - [IntrReadMem, IntrArgMemOnly]>; - -class AdvSIMD_GatherLoad_SV_32b_Offsets_WriteFFR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i32_ty> - ], - [IntrInaccessibleMemOrArgMemOnly]>; - -class AdvSIMD_GatherLoad_VS_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, - llvm_i64_ty - ], - [IntrReadMem]>; - -class AdvSIMD_GatherLoad_VS_WriteFFR_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, - llvm_i64_ty - ], - [IntrInaccessibleMemOrArgMemOnly]>; - -class AdvSIMD_ScatterStore_SV_64b_Offsets_Intrinsic - : DefaultAttrsIntrinsic<[], - [ - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i64_ty> - ], - [IntrWriteMem, IntrArgMemOnly]>; - -class AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic - : DefaultAttrsIntrinsic<[], - [ - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i32_ty> - ], - [IntrWriteMem, IntrArgMemOnly]>; - -class AdvSIMD_ScatterStore_VS_Intrinsic - : DefaultAttrsIntrinsic<[], - [ - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, llvm_i64_ty - ], - [IntrWriteMem]>; - - -class SVE_gather_prf_SV - : DefaultAttrsIntrinsic<[], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, // Predicate - llvm_ptr_ty, // Base address - llvm_anyvector_ty, // Offsets - llvm_i32_ty // Prfop - ], - [IntrInaccessibleMemOrArgMemOnly, NoCapture>, ImmArg>]>; - -class SVE_gather_prf_VS - : DefaultAttrsIntrinsic<[], - [ - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, // Predicate - llvm_anyvector_ty, // Base addresses - llvm_i64_ty, // Scalar offset - llvm_i32_ty // Prfop - ], - [IntrInaccessibleMemOrArgMemOnly, ImmArg>]>; - -class SVE_MatMul_Intrinsic - : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMSubdivide4VectorType<0>, LLVMSubdivide4VectorType<0>], - [IntrNoMem]>; - -class SVE_4Vec_BF16 - : DefaultAttrsIntrinsic<[llvm_nxv4f32_ty], - [llvm_nxv4f32_ty, llvm_nxv8bf16_ty, llvm_nxv8bf16_ty], - [IntrNoMem]>; - -class SVE_4Vec_BF16_Indexed - : DefaultAttrsIntrinsic<[llvm_nxv4f32_ty], - [llvm_nxv4f32_ty, llvm_nxv8bf16_ty, llvm_nxv8bf16_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - -// -// Vector tuple creation intrinsics (ACLE) -// - -def int_aarch64_sve_tuple_create2 : AdvSIMD_SVE_Create_2Vector_Tuple; -def int_aarch64_sve_tuple_create3 : AdvSIMD_SVE_Create_3Vector_Tuple; -def int_aarch64_sve_tuple_create4 : AdvSIMD_SVE_Create_4Vector_Tuple; - -// -// Vector tuple insertion/extraction intrinsics (ACLE) -// - -def int_aarch64_sve_tuple_get : AdvSIMD_SVE_Get_Vector_Tuple; -def int_aarch64_sve_tuple_set : AdvSIMD_SVE_Set_Vector_Tuple; - -// -// Loads -// - -def int_aarch64_sve_ld1 : AdvSIMD_1Vec_PredLoad_Intrinsic; - -def int_aarch64_sve_ld2 : AdvSIMD_ManyVec_PredLoad_Intrinsic; -def int_aarch64_sve_ld3 : AdvSIMD_ManyVec_PredLoad_Intrinsic; -def int_aarch64_sve_ld4 : AdvSIMD_ManyVec_PredLoad_Intrinsic; - -def int_aarch64_sve_ld2_sret : AdvSIMD_2Vec_PredLoad_Intrinsic; -def int_aarch64_sve_ld3_sret : AdvSIMD_3Vec_PredLoad_Intrinsic; -def int_aarch64_sve_ld4_sret : AdvSIMD_4Vec_PredLoad_Intrinsic; - -def int_aarch64_sve_ldnt1 : AdvSIMD_1Vec_PredLoad_Intrinsic; -def int_aarch64_sve_ldnf1 : AdvSIMD_1Vec_PredLoad_WriteFFR_Intrinsic; -def int_aarch64_sve_ldff1 : AdvSIMD_1Vec_PredLoad_WriteFFR_Intrinsic; - -def int_aarch64_sve_ld1rq : AdvSIMD_1Vec_PredLoad_Intrinsic; -def int_aarch64_sve_ld1ro : AdvSIMD_1Vec_PredLoad_Intrinsic; - -// -// Stores -// - -def int_aarch64_sve_st1 : AdvSIMD_1Vec_PredStore_Intrinsic; -def int_aarch64_sve_st2 : AdvSIMD_2Vec_PredStore_Intrinsic; -def int_aarch64_sve_st3 : AdvSIMD_3Vec_PredStore_Intrinsic; -def int_aarch64_sve_st4 : AdvSIMD_4Vec_PredStore_Intrinsic; - -def int_aarch64_sve_stnt1 : AdvSIMD_1Vec_PredStore_Intrinsic; - -// -// Prefetches -// - -def int_aarch64_sve_prf - : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly, ImmArg>]>; - -// Scalar + 32-bit scaled offset vector, zero extend, packed and -// unpacked. -def int_aarch64_sve_prfb_gather_uxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfh_gather_uxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfw_gather_uxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfd_gather_uxtw_index : SVE_gather_prf_SV; - -// Scalar + 32-bit scaled offset vector, sign extend, packed and -// unpacked. -def int_aarch64_sve_prfb_gather_sxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfw_gather_sxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfh_gather_sxtw_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfd_gather_sxtw_index : SVE_gather_prf_SV; - -// Scalar + 64-bit scaled offset vector. -def int_aarch64_sve_prfb_gather_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfh_gather_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfw_gather_index : SVE_gather_prf_SV; -def int_aarch64_sve_prfd_gather_index : SVE_gather_prf_SV; - -// Vector + scalar. -def int_aarch64_sve_prfb_gather_scalar_offset : SVE_gather_prf_VS; -def int_aarch64_sve_prfh_gather_scalar_offset : SVE_gather_prf_VS; -def int_aarch64_sve_prfw_gather_scalar_offset : SVE_gather_prf_VS; -def int_aarch64_sve_prfd_gather_scalar_offset : SVE_gather_prf_VS; - -// -// Scalar to vector operations -// - -def int_aarch64_sve_dup : AdvSIMD_SVE_DUP_Intrinsic; -def int_aarch64_sve_dup_x : AdvSIMD_SVE_DUP_Unpred_Intrinsic; - -def int_aarch64_sve_index : AdvSIMD_SVE_Index_Intrinsic; - -// -// Address calculation -// - -def int_aarch64_sve_adrb : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_adrh : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_adrw : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_adrd : AdvSIMD_2VectorArg_Intrinsic; - -// -// Integer arithmetic -// - -def int_aarch64_sve_add : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_subr : AdvSIMD_Pred2VectorArg_Intrinsic; - -def int_aarch64_sve_pmul : AdvSIMD_2VectorArg_Intrinsic; - -def int_aarch64_sve_mul : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_mul_lane : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_smulh : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_umulh : AdvSIMD_Pred2VectorArg_Intrinsic; - -def int_aarch64_sve_sdiv : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_udiv : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sdivr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_udivr : AdvSIMD_Pred2VectorArg_Intrinsic; - -def int_aarch64_sve_smax : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_umax : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_smin : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_umin : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sabd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uabd : AdvSIMD_Pred2VectorArg_Intrinsic; - -def int_aarch64_sve_mad : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_msb : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_mla : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_mla_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; -def int_aarch64_sve_mls : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_mls_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; - -def int_aarch64_sve_saddv : AdvSIMD_SVE_SADDV_Reduce_Intrinsic; -def int_aarch64_sve_uaddv : AdvSIMD_SVE_SADDV_Reduce_Intrinsic; - -def int_aarch64_sve_smaxv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_umaxv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_sminv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_uminv : AdvSIMD_SVE_Reduce_Intrinsic; - -def int_aarch64_sve_orv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_eorv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_andv : AdvSIMD_SVE_Reduce_Intrinsic; - -def int_aarch64_sve_abs : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_neg : AdvSIMD_Merged1VectorArg_Intrinsic; - -def int_aarch64_sve_sdot : AdvSIMD_SVE_DOT_Intrinsic; -def int_aarch64_sve_sdot_lane : AdvSIMD_SVE_DOT_Indexed_Intrinsic; - -def int_aarch64_sve_udot : AdvSIMD_SVE_DOT_Intrinsic; -def int_aarch64_sve_udot_lane : AdvSIMD_SVE_DOT_Indexed_Intrinsic; - -def int_aarch64_sve_sqadd_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_sqsub_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uqadd_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uqsub_x : AdvSIMD_2VectorArg_Intrinsic; - -// Shifts - -def int_aarch64_sve_asr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_asr_wide : AdvSIMD_SVE_ShiftWide_Intrinsic; -def int_aarch64_sve_asrd : AdvSIMD_SVE_ShiftByImm_Intrinsic; -def int_aarch64_sve_insr : AdvSIMD_SVE_INSR_Intrinsic; -def int_aarch64_sve_lsl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_lsl_wide : AdvSIMD_SVE_ShiftWide_Intrinsic; -def int_aarch64_sve_lsr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_lsr_wide : AdvSIMD_SVE_ShiftWide_Intrinsic; - -// -// Integer comparisons -// - -def int_aarch64_sve_cmpeq : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_cmpge : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_cmpgt : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_cmphi : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_cmphs : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_cmpne : AdvSIMD_SVE_Compare_Intrinsic; - -def int_aarch64_sve_cmpeq_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmpge_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmpgt_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmphi_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmphs_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmple_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmplo_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmpls_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmplt_wide : AdvSIMD_SVE_CompareWide_Intrinsic; -def int_aarch64_sve_cmpne_wide : AdvSIMD_SVE_CompareWide_Intrinsic; - -// -// Counting bits -// - -def int_aarch64_sve_cls : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_clz : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_cnt : AdvSIMD_SVE_CNT_Intrinsic; - -// -// Counting elements -// - -def int_aarch64_sve_cntb : AdvSIMD_SVE_CNTB_Intrinsic; -def int_aarch64_sve_cnth : AdvSIMD_SVE_CNTB_Intrinsic; -def int_aarch64_sve_cntw : AdvSIMD_SVE_CNTB_Intrinsic; -def int_aarch64_sve_cntd : AdvSIMD_SVE_CNTB_Intrinsic; - -def int_aarch64_sve_cntp : AdvSIMD_SVE_CNTP_Intrinsic; - -// -// FFR manipulation -// - -def int_aarch64_sve_rdffr : GCCBuiltin<"__builtin_sve_svrdffr">, DefaultAttrsIntrinsic<[llvm_nxv16i1_ty], [], [IntrReadMem, IntrInaccessibleMemOnly]>; -def int_aarch64_sve_rdffr_z : GCCBuiltin<"__builtin_sve_svrdffr_z">, DefaultAttrsIntrinsic<[llvm_nxv16i1_ty], [llvm_nxv16i1_ty], [IntrReadMem, IntrInaccessibleMemOnly]>; -def int_aarch64_sve_setffr : GCCBuiltin<"__builtin_sve_svsetffr">, DefaultAttrsIntrinsic<[], [], [IntrWriteMem, IntrInaccessibleMemOnly]>; -def int_aarch64_sve_wrffr : GCCBuiltin<"__builtin_sve_svwrffr">, DefaultAttrsIntrinsic<[], [llvm_nxv16i1_ty], [IntrWriteMem, IntrInaccessibleMemOnly]>; - -// -// Saturating scalar arithmetic -// - -def int_aarch64_sve_sqdech : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqdecw : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqdecd : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqdecp : AdvSIMD_SVE_Saturating_Intrinsic; - -def int_aarch64_sve_sqdecb_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecb_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdech_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdech_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecw_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecw_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecd_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecd_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqdecp_n32 : AdvSIMD_SVE_Saturating_N_Intrinsic; -def int_aarch64_sve_sqdecp_n64 : AdvSIMD_SVE_Saturating_N_Intrinsic; - -def int_aarch64_sve_sqinch : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqincw : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqincd : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_sqincp : AdvSIMD_SVE_Saturating_Intrinsic; - -def int_aarch64_sve_sqincb_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincb_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqinch_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqinch_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincw_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincw_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincd_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincd_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_sqincp_n32 : AdvSIMD_SVE_Saturating_N_Intrinsic; -def int_aarch64_sve_sqincp_n64 : AdvSIMD_SVE_Saturating_N_Intrinsic; - -def int_aarch64_sve_uqdech : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqdecw : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqdecd : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqdecp : AdvSIMD_SVE_Saturating_Intrinsic; - -def int_aarch64_sve_uqdecb_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecb_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdech_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdech_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecw_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecw_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecd_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecd_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqdecp_n32 : AdvSIMD_SVE_Saturating_N_Intrinsic; -def int_aarch64_sve_uqdecp_n64 : AdvSIMD_SVE_Saturating_N_Intrinsic; - -def int_aarch64_sve_uqinch : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqincw : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqincd : AdvSIMD_SVE_SaturatingWithPattern_Intrinsic; -def int_aarch64_sve_uqincp : AdvSIMD_SVE_Saturating_Intrinsic; - -def int_aarch64_sve_uqincb_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincb_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqinch_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqinch_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincw_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincw_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincd_n32 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincd_n64 : AdvSIMD_SVE_SaturatingWithPattern_N_Intrinsic; -def int_aarch64_sve_uqincp_n32 : AdvSIMD_SVE_Saturating_N_Intrinsic; -def int_aarch64_sve_uqincp_n64 : AdvSIMD_SVE_Saturating_N_Intrinsic; - -// -// Reversal -// - -def int_aarch64_sve_rbit : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_revb : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_revh : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_revw : AdvSIMD_Merged1VectorArg_Intrinsic; - -// -// Permutations and selection -// - -def int_aarch64_sve_clasta : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_clasta_n : AdvSIMD_SVE_ReduceWithInit_Intrinsic; -def int_aarch64_sve_clastb : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_clastb_n : AdvSIMD_SVE_ReduceWithInit_Intrinsic; -def int_aarch64_sve_compact : AdvSIMD_Pred1VectorArg_Intrinsic; -def int_aarch64_sve_dupq_lane : AdvSIMD_SVE_DUPQ_Intrinsic; -def int_aarch64_sve_ext : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sel : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_lasta : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_lastb : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_rev : AdvSIMD_1VectorArg_Intrinsic; -def int_aarch64_sve_splice : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sunpkhi : AdvSIMD_SVE_Unpack_Intrinsic; -def int_aarch64_sve_sunpklo : AdvSIMD_SVE_Unpack_Intrinsic; -def int_aarch64_sve_tbl : AdvSIMD_SVE_TBL_Intrinsic; -def int_aarch64_sve_trn1 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_trn2 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_trn1q : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_trn2q : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uunpkhi : AdvSIMD_SVE_Unpack_Intrinsic; -def int_aarch64_sve_uunpklo : AdvSIMD_SVE_Unpack_Intrinsic; -def int_aarch64_sve_uzp1 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uzp2 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uzp1q : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_uzp2q : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_zip1 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_zip2 : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_zip1q : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_zip2q : AdvSIMD_2VectorArg_Intrinsic; - -// -// Logical operations -// - -def int_aarch64_sve_and : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_bic : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_cnot : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_eor : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_not : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_orr : AdvSIMD_Pred2VectorArg_Intrinsic; - -// -// Conversion -// - -def int_aarch64_sve_sxtb : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_sxth : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_sxtw : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_uxtb : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_uxth : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_uxtw : AdvSIMD_Merged1VectorArg_Intrinsic; - -// -// While comparisons -// - -def int_aarch64_sve_whilele : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilelo : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilels : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilelt : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilege : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilegt : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilehs : AdvSIMD_SVE_WHILE_Intrinsic; -def int_aarch64_sve_whilehi : AdvSIMD_SVE_WHILE_Intrinsic; - -// -// Floating-point arithmetic -// - -def int_aarch64_sve_fabd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fabs : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_fadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fcadd : AdvSIMD_SVE_CADD_Intrinsic; -def int_aarch64_sve_fcmla : AdvSIMD_SVE_CMLA_Intrinsic; -def int_aarch64_sve_fcmla_lane : AdvSIMD_SVE_CMLA_LANE_Intrinsic; -def int_aarch64_sve_fdiv : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fdivr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fexpa_x : AdvSIMD_SVE_EXPA_Intrinsic; -def int_aarch64_sve_fmad : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fmax : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmaxnm : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmin : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fminnm : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmla : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fmla_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; -def int_aarch64_sve_fmls : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fmls_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; -def int_aarch64_sve_fmsb : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fmul : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmulx : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fneg : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_fmul_lane : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_fnmad : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fnmla : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fnmls : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_fnmsb : AdvSIMD_Pred3VectorArg_Intrinsic; -def int_aarch64_sve_frecpe_x : AdvSIMD_1VectorArg_Intrinsic; -def int_aarch64_sve_frecps_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_frecpx : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frinta : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frinti : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frintm : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frintn : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frintp : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frintx : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frintz : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_frsqrte_x : AdvSIMD_1VectorArg_Intrinsic; -def int_aarch64_sve_frsqrts_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_fscale : AdvSIMD_SVE_SCALE_Intrinsic; -def int_aarch64_sve_fsqrt : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_fsub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fsubr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_ftmad_x : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_ftsmul_x : AdvSIMD_SVE_TSMUL_Intrinsic; -def int_aarch64_sve_ftssel_x : AdvSIMD_SVE_TSMUL_Intrinsic; - -// -// Floating-point reductions -// - -def int_aarch64_sve_fadda : AdvSIMD_SVE_ReduceWithInit_Intrinsic; -def int_aarch64_sve_faddv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_fmaxv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_fmaxnmv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_fminv : AdvSIMD_SVE_Reduce_Intrinsic; -def int_aarch64_sve_fminnmv : AdvSIMD_SVE_Reduce_Intrinsic; - -// -// Floating-point conversions -// - -def int_aarch64_sve_fcvt : AdvSIMD_SVE_FCVT_Intrinsic; -def int_aarch64_sve_fcvtzs : AdvSIMD_SVE_FCVTZS_Intrinsic; -def int_aarch64_sve_fcvtzu : AdvSIMD_SVE_FCVTZS_Intrinsic; -def int_aarch64_sve_scvtf : AdvSIMD_SVE_SCVTF_Intrinsic; -def int_aarch64_sve_ucvtf : AdvSIMD_SVE_SCVTF_Intrinsic; - -// -// Floating-point comparisons -// - -def int_aarch64_sve_facge : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_facgt : AdvSIMD_SVE_Compare_Intrinsic; - -def int_aarch64_sve_fcmpeq : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_fcmpge : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_fcmpgt : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_fcmpne : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_fcmpuo : AdvSIMD_SVE_Compare_Intrinsic; - -def int_aarch64_sve_fcvtzs_i32f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzs_i32f64 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzs_i64f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzs_i64f32 : Builtin_SVCVT; - -def int_aarch64_sve_fcvt_bf16f32 : Builtin_SVCVT; -def int_aarch64_sve_fcvtnt_bf16f32 : Builtin_SVCVT; - -def int_aarch64_sve_fcvtzu_i32f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzu_i32f64 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzu_i64f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvtzu_i64f32 : Builtin_SVCVT; - -def int_aarch64_sve_fcvt_f16f32 : Builtin_SVCVT; -def int_aarch64_sve_fcvt_f16f64 : Builtin_SVCVT; -def int_aarch64_sve_fcvt_f32f64 : Builtin_SVCVT; - -def int_aarch64_sve_fcvt_f32f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvt_f64f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvt_f64f32 : Builtin_SVCVT; - -def int_aarch64_sve_fcvtlt_f32f16 : Builtin_SVCVT; -def int_aarch64_sve_fcvtlt_f64f32 : Builtin_SVCVT; -def int_aarch64_sve_fcvtnt_f16f32 : Builtin_SVCVT; -def int_aarch64_sve_fcvtnt_f32f64 : Builtin_SVCVT; - -def int_aarch64_sve_fcvtx_f32f64 : Builtin_SVCVT; -def int_aarch64_sve_fcvtxnt_f32f64 : Builtin_SVCVT; - -def int_aarch64_sve_scvtf_f16i32 : Builtin_SVCVT; -def int_aarch64_sve_scvtf_f16i64 : Builtin_SVCVT; -def int_aarch64_sve_scvtf_f32i64 : Builtin_SVCVT; -def int_aarch64_sve_scvtf_f64i32 : Builtin_SVCVT; - -def int_aarch64_sve_ucvtf_f16i32 : Builtin_SVCVT; -def int_aarch64_sve_ucvtf_f16i64 : Builtin_SVCVT; -def int_aarch64_sve_ucvtf_f32i64 : Builtin_SVCVT; -def int_aarch64_sve_ucvtf_f64i32 : Builtin_SVCVT; - -// -// Predicate creation -// - -def int_aarch64_sve_ptrue : AdvSIMD_SVE_PTRUE_Intrinsic; - -// -// Predicate operations -// - -def int_aarch64_sve_and_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_bic_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_brka : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_brka_z : AdvSIMD_Pred1VectorArg_Intrinsic; -def int_aarch64_sve_brkb : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_brkb_z : AdvSIMD_Pred1VectorArg_Intrinsic; -def int_aarch64_sve_brkn_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_brkpa_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_brkpb_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_eor_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_nand_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_nor_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_orn_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_orr_z : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_pfirst : AdvSIMD_Pred1VectorArg_Intrinsic; -def int_aarch64_sve_pnext : AdvSIMD_Pred1VectorArg_Intrinsic; -def int_aarch64_sve_punpkhi : AdvSIMD_SVE_PUNPKHI_Intrinsic; -def int_aarch64_sve_punpklo : AdvSIMD_SVE_PUNPKHI_Intrinsic; - -// -// Testing predicates -// - -def int_aarch64_sve_ptest_any : AdvSIMD_SVE_PTEST_Intrinsic; -def int_aarch64_sve_ptest_first : AdvSIMD_SVE_PTEST_Intrinsic; -def int_aarch64_sve_ptest_last : AdvSIMD_SVE_PTEST_Intrinsic; - -// -// Reinterpreting data -// - -def int_aarch64_sve_convert_from_svbool : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [llvm_nxv16i1_ty], - [IntrNoMem]>; - -def int_aarch64_sve_convert_to_svbool : DefaultAttrsIntrinsic<[llvm_nxv16i1_ty], - [llvm_anyvector_ty], - [IntrNoMem]>; - -// -// Gather loads: scalar base + vector offsets -// - -// 64 bit unscaled offsets -def int_aarch64_sve_ld1_gather : AdvSIMD_GatherLoad_SV_64b_Offsets_Intrinsic; - -// 64 bit scaled offsets -def int_aarch64_sve_ld1_gather_index : AdvSIMD_GatherLoad_SV_64b_Offsets_Intrinsic; - -// 32 bit unscaled offsets, sign (sxtw) or zero (zxtw) extended to 64 bits -def int_aarch64_sve_ld1_gather_sxtw : AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic; -def int_aarch64_sve_ld1_gather_uxtw : AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic; - -// 32 bit scaled offsets, sign (sxtw) or zero (zxtw) extended to 64 bits -def int_aarch64_sve_ld1_gather_sxtw_index : AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic; -def int_aarch64_sve_ld1_gather_uxtw_index : AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic; - -// -// Gather loads: vector base + scalar offset -// - -def int_aarch64_sve_ld1_gather_scalar_offset : AdvSIMD_GatherLoad_VS_Intrinsic; - - -// -// First-faulting gather loads: scalar base + vector offsets -// - -// 64 bit unscaled offsets -def int_aarch64_sve_ldff1_gather : AdvSIMD_GatherLoad_SV_64b_Offsets_WriteFFR_Intrinsic; - -// 64 bit scaled offsets -def int_aarch64_sve_ldff1_gather_index : AdvSIMD_GatherLoad_SV_64b_Offsets_WriteFFR_Intrinsic; - -// 32 bit unscaled offsets, sign (sxtw) or zero (uxtw) extended to 64 bits -def int_aarch64_sve_ldff1_gather_sxtw : AdvSIMD_GatherLoad_SV_32b_Offsets_WriteFFR_Intrinsic; -def int_aarch64_sve_ldff1_gather_uxtw : AdvSIMD_GatherLoad_SV_32b_Offsets_WriteFFR_Intrinsic; - -// 32 bit scaled offsets, sign (sxtw) or zero (uxtw) extended to 64 bits -def int_aarch64_sve_ldff1_gather_sxtw_index : AdvSIMD_GatherLoad_SV_32b_Offsets_WriteFFR_Intrinsic; -def int_aarch64_sve_ldff1_gather_uxtw_index : AdvSIMD_GatherLoad_SV_32b_Offsets_WriteFFR_Intrinsic; - -// -// First-faulting gather loads: vector base + scalar offset -// - -def int_aarch64_sve_ldff1_gather_scalar_offset : AdvSIMD_GatherLoad_VS_WriteFFR_Intrinsic; - - -// -// Non-temporal gather loads: scalar base + vector offsets -// - -// 64 bit unscaled offsets -def int_aarch64_sve_ldnt1_gather : AdvSIMD_GatherLoad_SV_64b_Offsets_Intrinsic; - -// 64 bit indices -def int_aarch64_sve_ldnt1_gather_index : AdvSIMD_GatherLoad_SV_64b_Offsets_Intrinsic; - -// 32 bit unscaled offsets, zero (zxtw) extended to 64 bits -def int_aarch64_sve_ldnt1_gather_uxtw : AdvSIMD_GatherLoad_SV_32b_Offsets_Intrinsic; - -// -// Non-temporal gather loads: vector base + scalar offset -// - -def int_aarch64_sve_ldnt1_gather_scalar_offset : AdvSIMD_GatherLoad_VS_Intrinsic; - -// -// Scatter stores: scalar base + vector offsets -// - -// 64 bit unscaled offsets -def int_aarch64_sve_st1_scatter : AdvSIMD_ScatterStore_SV_64b_Offsets_Intrinsic; - -// 64 bit scaled offsets -def int_aarch64_sve_st1_scatter_index - : AdvSIMD_ScatterStore_SV_64b_Offsets_Intrinsic; - -// 32 bit unscaled offsets, sign (sxtw) or zero (zxtw) extended to 64 bits -def int_aarch64_sve_st1_scatter_sxtw - : AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic; - -def int_aarch64_sve_st1_scatter_uxtw - : AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic; - -// 32 bit scaled offsets, sign (sxtw) or zero (zxtw) extended to 64 bits -def int_aarch64_sve_st1_scatter_sxtw_index - : AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic; - -def int_aarch64_sve_st1_scatter_uxtw_index - : AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic; - -// -// Scatter stores: vector base + scalar offset -// - -def int_aarch64_sve_st1_scatter_scalar_offset : AdvSIMD_ScatterStore_VS_Intrinsic; - -// -// Non-temporal scatter stores: scalar base + vector offsets -// - -// 64 bit unscaled offsets -def int_aarch64_sve_stnt1_scatter : AdvSIMD_ScatterStore_SV_64b_Offsets_Intrinsic; - -// 64 bit indices -def int_aarch64_sve_stnt1_scatter_index - : AdvSIMD_ScatterStore_SV_64b_Offsets_Intrinsic; - -// 32 bit unscaled offsets, zero (zxtw) extended to 64 bits -def int_aarch64_sve_stnt1_scatter_uxtw : AdvSIMD_ScatterStore_SV_32b_Offsets_Intrinsic; - -// -// Non-temporal scatter stores: vector base + scalar offset -// - -def int_aarch64_sve_stnt1_scatter_scalar_offset : AdvSIMD_ScatterStore_VS_Intrinsic; - -// -// SVE2 - Uniform DSP operations -// - -def int_aarch64_sve_saba : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_shadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_shsub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_shsubr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sli : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sqabs : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_sqadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sqdmulh : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_sqdmulh_lane : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sqneg : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_sqrdmlah : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_sqrdmlah_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sqrdmlsh : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_sqrdmlsh_lane : AdvSIMD_3VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sqrdmulh : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_sqrdmulh_lane : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_sqrshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sqshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sqshlu : AdvSIMD_SVE_ShiftByImm_Intrinsic; -def int_aarch64_sve_sqsub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sqsubr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_srhadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sri : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_srshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_srshr : AdvSIMD_SVE_ShiftByImm_Intrinsic; -def int_aarch64_sve_srsra : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_ssra : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_suqadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uaba : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_uhadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uhsub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uhsubr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uqadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uqrshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uqshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uqsub : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uqsubr : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_urecpe : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_urhadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_urshl : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_urshr : AdvSIMD_SVE_ShiftByImm_Intrinsic; -def int_aarch64_sve_ursqrte : AdvSIMD_Merged1VectorArg_Intrinsic; -def int_aarch64_sve_ursra : AdvSIMD_2VectorArgIndexed_Intrinsic; -def int_aarch64_sve_usqadd : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_usra : AdvSIMD_2VectorArgIndexed_Intrinsic; - -// -// SVE2 - Widening DSP operations -// - -def int_aarch64_sve_sabalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sabalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sabdlb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_sabdlt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_saddlb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_saddlt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_saddwb : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_saddwt : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_sshllb : SVE2_1VectorArg_Long_Intrinsic; -def int_aarch64_sve_sshllt : SVE2_1VectorArg_Long_Intrinsic; -def int_aarch64_sve_ssublb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_ssublt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_ssubwb : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_ssubwt : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_uabalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_uabalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_uabdlb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_uabdlt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_uaddlb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_uaddlt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_uaddwb : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_uaddwt : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_ushllb : SVE2_1VectorArg_Long_Intrinsic; -def int_aarch64_sve_ushllt : SVE2_1VectorArg_Long_Intrinsic; -def int_aarch64_sve_usublb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_usublt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_usubwb : SVE2_2VectorArg_Wide_Intrinsic; -def int_aarch64_sve_usubwt : SVE2_2VectorArg_Wide_Intrinsic; - -// -// SVE2 - Non-widening pairwise arithmetic -// - -def int_aarch64_sve_addp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_faddp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmaxp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fmaxnmp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fminp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_fminnmp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_smaxp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_sminp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_umaxp : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_uminp : AdvSIMD_Pred2VectorArg_Intrinsic; - -// -// SVE2 - Widening pairwise arithmetic -// - -def int_aarch64_sve_sadalp : SVE2_2VectorArg_Pred_Long_Intrinsic; -def int_aarch64_sve_uadalp : SVE2_2VectorArg_Pred_Long_Intrinsic; - -// -// SVE2 - Uniform complex integer arithmetic -// - -def int_aarch64_sve_cadd_x : AdvSIMD_SVE2_CADD_Intrinsic; -def int_aarch64_sve_sqcadd_x : AdvSIMD_SVE2_CADD_Intrinsic; -def int_aarch64_sve_cmla_x : AdvSIMD_SVE2_CMLA_Intrinsic; -def int_aarch64_sve_cmla_lane_x : AdvSIMD_SVE_CMLA_LANE_Intrinsic; -def int_aarch64_sve_sqrdcmlah_x : AdvSIMD_SVE2_CMLA_Intrinsic; -def int_aarch64_sve_sqrdcmlah_lane_x : AdvSIMD_SVE_CMLA_LANE_Intrinsic; - -// -// SVE2 - Widening complex integer arithmetic -// - -def int_aarch64_sve_saddlbt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_ssublbt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_ssubltb : SVE2_2VectorArg_Long_Intrinsic; - -// -// SVE2 - Widening complex integer dot product -// - -def int_aarch64_sve_cdot : AdvSIMD_SVE_DOT_Indexed_Intrinsic; -def int_aarch64_sve_cdot_lane : AdvSIMD_SVE_CDOT_LANE_Intrinsic; - -// -// SVE2 - Floating-point widening multiply-accumulate -// - -def int_aarch64_sve_fmlalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_fmlalb_lane : SVE2_3VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_fmlalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_fmlalt_lane : SVE2_3VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_fmlslb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_fmlslb_lane : SVE2_3VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_fmlslt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_fmlslt_lane : SVE2_3VectorArgIndexed_Long_Intrinsic; - -// -// SVE2 - Floating-point integer binary logarithm -// - -def int_aarch64_sve_flogb : AdvSIMD_SVE_LOGB_Intrinsic; - -// -// SVE2 - Vector histogram count -// - -def int_aarch64_sve_histcnt : AdvSIMD_Pred2VectorArg_Intrinsic; -def int_aarch64_sve_histseg : AdvSIMD_2VectorArg_Intrinsic; - -// -// SVE2 - Character match -// - -def int_aarch64_sve_match : AdvSIMD_SVE_Compare_Intrinsic; -def int_aarch64_sve_nmatch : AdvSIMD_SVE_Compare_Intrinsic; - -// -// SVE2 - Unary narrowing operations -// - -def int_aarch64_sve_sqxtnb : SVE2_1VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_sqxtnt : SVE2_Merged1VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_sqxtunb : SVE2_1VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_sqxtunt : SVE2_Merged1VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_uqxtnb : SVE2_1VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_uqxtnt : SVE2_Merged1VectorArg_Narrowing_Intrinsic; - -// -// SVE2 - Binary narrowing DSP operations -// -def int_aarch64_sve_addhnb : SVE2_2VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_addhnt : SVE2_Merged2VectorArg_Narrowing_Intrinsic; - -def int_aarch64_sve_raddhnb : SVE2_2VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_raddhnt : SVE2_Merged2VectorArg_Narrowing_Intrinsic; - -def int_aarch64_sve_subhnb : SVE2_2VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_subhnt : SVE2_Merged2VectorArg_Narrowing_Intrinsic; - -def int_aarch64_sve_rsubhnb : SVE2_2VectorArg_Narrowing_Intrinsic; -def int_aarch64_sve_rsubhnt : SVE2_Merged2VectorArg_Narrowing_Intrinsic; - -// Narrowing shift right -def int_aarch64_sve_shrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_shrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -def int_aarch64_sve_rshrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_rshrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -// Saturating shift right - signed input/output -def int_aarch64_sve_sqshrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_sqshrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -def int_aarch64_sve_sqrshrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_sqrshrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -// Saturating shift right - unsigned input/output -def int_aarch64_sve_uqshrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_uqshrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -def int_aarch64_sve_uqrshrnb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_uqrshrnt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -// Saturating shift right - signed input, unsigned output -def int_aarch64_sve_sqshrunb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_sqshrunt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -def int_aarch64_sve_sqrshrunb : SVE2_1VectorArg_Imm_Narrowing_Intrinsic; -def int_aarch64_sve_sqrshrunt : SVE2_2VectorArg_Imm_Narrowing_Intrinsic; - -// SVE2 MLA LANE. -def int_aarch64_sve_smlalb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_smlalt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_umlalb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_umlalt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_smlslb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_smlslt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_umlslb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_umlslt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_smullb_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_smullt_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_umullb_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_umullt_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_sqdmlalb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_sqdmlalt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_sqdmlslb_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_sqdmlslt_lane : SVE2_3VectorArg_Indexed_Intrinsic; -def int_aarch64_sve_sqdmullb_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; -def int_aarch64_sve_sqdmullt_lane : SVE2_2VectorArgIndexed_Long_Intrinsic; - -// SVE2 MLA Unpredicated. -def int_aarch64_sve_smlalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_smlalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_umlalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_umlalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_smlslb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_smlslt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_umlslb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_umlslt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_smullb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_smullt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_umullb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_umullt : SVE2_2VectorArg_Long_Intrinsic; - -def int_aarch64_sve_sqdmlalb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmlalt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmlslb : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmlslt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmullb : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmullt : SVE2_2VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmlalbt : SVE2_3VectorArg_Long_Intrinsic; -def int_aarch64_sve_sqdmlslbt : SVE2_3VectorArg_Long_Intrinsic; - -// SVE2 ADDSUB Long Unpredicated. -def int_aarch64_sve_adclb : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_adclt : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_sbclb : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_sbclt : AdvSIMD_3VectorArg_Intrinsic; - -// -// SVE2 - Polynomial arithmetic -// -def int_aarch64_sve_eorbt : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_eortb : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_pmullb_pair : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_pmullt_pair : AdvSIMD_2VectorArg_Intrinsic; - -// -// SVE2 bitwise ternary operations. -// -def int_aarch64_sve_eor3 : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_bcax : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_bsl : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_bsl1n : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_bsl2n : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_nbsl : AdvSIMD_3VectorArg_Intrinsic; -def int_aarch64_sve_xar : AdvSIMD_2VectorArgIndexed_Intrinsic; - -// -// SVE2 - Optional AES, SHA-3 and SM4 -// - -def int_aarch64_sve_aesd : GCCBuiltin<"__builtin_sve_svaesd_u8">, - DefaultAttrsIntrinsic<[llvm_nxv16i8_ty], - [llvm_nxv16i8_ty, llvm_nxv16i8_ty], - [IntrNoMem]>; -def int_aarch64_sve_aesimc : GCCBuiltin<"__builtin_sve_svaesimc_u8">, - DefaultAttrsIntrinsic<[llvm_nxv16i8_ty], - [llvm_nxv16i8_ty], - [IntrNoMem]>; -def int_aarch64_sve_aese : GCCBuiltin<"__builtin_sve_svaese_u8">, - DefaultAttrsIntrinsic<[llvm_nxv16i8_ty], - [llvm_nxv16i8_ty, llvm_nxv16i8_ty], - [IntrNoMem]>; -def int_aarch64_sve_aesmc : GCCBuiltin<"__builtin_sve_svaesmc_u8">, - DefaultAttrsIntrinsic<[llvm_nxv16i8_ty], - [llvm_nxv16i8_ty], - [IntrNoMem]>; -def int_aarch64_sve_rax1 : GCCBuiltin<"__builtin_sve_svrax1_u64">, - DefaultAttrsIntrinsic<[llvm_nxv2i64_ty], - [llvm_nxv2i64_ty, llvm_nxv2i64_ty], - [IntrNoMem]>; -def int_aarch64_sve_sm4e : GCCBuiltin<"__builtin_sve_svsm4e_u32">, - DefaultAttrsIntrinsic<[llvm_nxv4i32_ty], - [llvm_nxv4i32_ty, llvm_nxv4i32_ty], - [IntrNoMem]>; -def int_aarch64_sve_sm4ekey : GCCBuiltin<"__builtin_sve_svsm4ekey_u32">, - DefaultAttrsIntrinsic<[llvm_nxv4i32_ty], - [llvm_nxv4i32_ty, llvm_nxv4i32_ty], - [IntrNoMem]>; -// -// SVE2 - Extended table lookup/permute -// - -def int_aarch64_sve_tbl2 : AdvSIMD_SVE2_TBX_Intrinsic; -def int_aarch64_sve_tbx : AdvSIMD_SVE2_TBX_Intrinsic; - -// -// SVE2 - Optional bit permutation -// - -def int_aarch64_sve_bdep_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_bext_x : AdvSIMD_2VectorArg_Intrinsic; -def int_aarch64_sve_bgrp_x : AdvSIMD_2VectorArg_Intrinsic; - - -// -// SVE ACLE: 7.3. INT8 matrix multiply extensions -// -def int_aarch64_sve_ummla : SVE_MatMul_Intrinsic; -def int_aarch64_sve_smmla : SVE_MatMul_Intrinsic; -def int_aarch64_sve_usmmla : SVE_MatMul_Intrinsic; - -def int_aarch64_sve_usdot : AdvSIMD_SVE_DOT_Intrinsic; -def int_aarch64_sve_usdot_lane : AdvSIMD_SVE_DOT_Indexed_Intrinsic; -def int_aarch64_sve_sudot_lane : AdvSIMD_SVE_DOT_Indexed_Intrinsic; - -// -// SVE ACLE: 7.4/5. FP64/FP32 matrix multiply extensions -// -def int_aarch64_sve_fmmla : AdvSIMD_3VectorArg_Intrinsic; - -// -// SVE ACLE: 7.2. BFloat16 extensions -// - -def int_aarch64_sve_bfdot : SVE_4Vec_BF16; -def int_aarch64_sve_bfmlalb : SVE_4Vec_BF16; -def int_aarch64_sve_bfmlalt : SVE_4Vec_BF16; - -def int_aarch64_sve_bfmmla : SVE_4Vec_BF16; - -def int_aarch64_sve_bfdot_lane : SVE_4Vec_BF16_Indexed; -def int_aarch64_sve_bfmlalb_lane : SVE_4Vec_BF16_Indexed; -def int_aarch64_sve_bfmlalt_lane : SVE_4Vec_BF16_Indexed; -} - -// -// SVE2 - Contiguous conflict detection -// - -def int_aarch64_sve_whilerw_b : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilerw_h : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilerw_s : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilerw_d : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilewr_b : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilewr_h : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilewr_s : SVE2_CONFLICT_DETECT_Intrinsic; -def int_aarch64_sve_whilewr_d : SVE2_CONFLICT_DETECT_Intrinsic; diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.h deleted file mode 100644 index 2c3f6d050d..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.h +++ /dev/null @@ -1,749 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_AMDGCN_ENUMS_H -#define LLVM_IR_INTRINSIC_AMDGCN_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum AMDGCNIntrinsics : unsigned { -// Enum values for intrinsics - amdgcn_alignbyte = 1243, // llvm.amdgcn.alignbyte - amdgcn_atomic_dec, // llvm.amdgcn.atomic.dec - amdgcn_atomic_inc, // llvm.amdgcn.atomic.inc - amdgcn_ballot, // llvm.amdgcn.ballot - amdgcn_buffer_atomic_add, // llvm.amdgcn.buffer.atomic.add - amdgcn_buffer_atomic_and, // llvm.amdgcn.buffer.atomic.and - amdgcn_buffer_atomic_cmpswap, // llvm.amdgcn.buffer.atomic.cmpswap - amdgcn_buffer_atomic_csub, // llvm.amdgcn.buffer.atomic.csub - amdgcn_buffer_atomic_fadd, // llvm.amdgcn.buffer.atomic.fadd - amdgcn_buffer_atomic_or, // llvm.amdgcn.buffer.atomic.or - amdgcn_buffer_atomic_smax, // llvm.amdgcn.buffer.atomic.smax - amdgcn_buffer_atomic_smin, // llvm.amdgcn.buffer.atomic.smin - amdgcn_buffer_atomic_sub, // llvm.amdgcn.buffer.atomic.sub - amdgcn_buffer_atomic_swap, // llvm.amdgcn.buffer.atomic.swap - amdgcn_buffer_atomic_umax, // llvm.amdgcn.buffer.atomic.umax - amdgcn_buffer_atomic_umin, // llvm.amdgcn.buffer.atomic.umin - amdgcn_buffer_atomic_xor, // llvm.amdgcn.buffer.atomic.xor - amdgcn_buffer_load, // llvm.amdgcn.buffer.load - amdgcn_buffer_load_format, // llvm.amdgcn.buffer.load.format - amdgcn_buffer_store, // llvm.amdgcn.buffer.store - amdgcn_buffer_store_format, // llvm.amdgcn.buffer.store.format - amdgcn_buffer_wbinvl1, // llvm.amdgcn.buffer.wbinvl1 - amdgcn_buffer_wbinvl1_sc, // llvm.amdgcn.buffer.wbinvl1.sc - amdgcn_buffer_wbinvl1_vol, // llvm.amdgcn.buffer.wbinvl1.vol - amdgcn_class, // llvm.amdgcn.class - amdgcn_cos, // llvm.amdgcn.cos - amdgcn_cubeid, // llvm.amdgcn.cubeid - amdgcn_cubema, // llvm.amdgcn.cubema - amdgcn_cubesc, // llvm.amdgcn.cubesc - amdgcn_cubetc, // llvm.amdgcn.cubetc - amdgcn_cvt_pk_i16, // llvm.amdgcn.cvt.pk.i16 - amdgcn_cvt_pk_u16, // llvm.amdgcn.cvt.pk.u16 - amdgcn_cvt_pk_u8_f32, // llvm.amdgcn.cvt.pk.u8.f32 - amdgcn_cvt_pknorm_i16, // llvm.amdgcn.cvt.pknorm.i16 - amdgcn_cvt_pknorm_u16, // llvm.amdgcn.cvt.pknorm.u16 - amdgcn_cvt_pkrtz, // llvm.amdgcn.cvt.pkrtz - amdgcn_dispatch_id, // llvm.amdgcn.dispatch.id - amdgcn_dispatch_ptr, // llvm.amdgcn.dispatch.ptr - amdgcn_div_fixup, // llvm.amdgcn.div.fixup - amdgcn_div_fmas, // llvm.amdgcn.div.fmas - amdgcn_div_scale, // llvm.amdgcn.div.scale - amdgcn_ds_append, // llvm.amdgcn.ds.append - amdgcn_ds_bpermute, // llvm.amdgcn.ds.bpermute - amdgcn_ds_consume, // llvm.amdgcn.ds.consume - amdgcn_ds_fadd, // llvm.amdgcn.ds.fadd - amdgcn_ds_fmax, // llvm.amdgcn.ds.fmax - amdgcn_ds_fmin, // llvm.amdgcn.ds.fmin - amdgcn_ds_gws_barrier, // llvm.amdgcn.ds.gws.barrier - amdgcn_ds_gws_init, // llvm.amdgcn.ds.gws.init - amdgcn_ds_gws_sema_br, // llvm.amdgcn.ds.gws.sema.br - amdgcn_ds_gws_sema_p, // llvm.amdgcn.ds.gws.sema.p - amdgcn_ds_gws_sema_release_all, // llvm.amdgcn.ds.gws.sema.release.all - amdgcn_ds_gws_sema_v, // llvm.amdgcn.ds.gws.sema.v - amdgcn_ds_ordered_add, // llvm.amdgcn.ds.ordered.add - amdgcn_ds_ordered_swap, // llvm.amdgcn.ds.ordered.swap - amdgcn_ds_permute, // llvm.amdgcn.ds.permute - amdgcn_ds_swizzle, // llvm.amdgcn.ds.swizzle - amdgcn_else, // llvm.amdgcn.else - amdgcn_end_cf, // llvm.amdgcn.end.cf - amdgcn_endpgm, // llvm.amdgcn.endpgm - amdgcn_exp, // llvm.amdgcn.exp - amdgcn_exp_compr, // llvm.amdgcn.exp.compr - amdgcn_fcmp, // llvm.amdgcn.fcmp - amdgcn_fdiv_fast, // llvm.amdgcn.fdiv.fast - amdgcn_fdot2, // llvm.amdgcn.fdot2 - amdgcn_flat_atomic_fadd, // llvm.amdgcn.flat.atomic.fadd - amdgcn_flat_atomic_fmax, // llvm.amdgcn.flat.atomic.fmax - amdgcn_flat_atomic_fmin, // llvm.amdgcn.flat.atomic.fmin - amdgcn_fma_legacy, // llvm.amdgcn.fma.legacy - amdgcn_fmad_ftz, // llvm.amdgcn.fmad.ftz - amdgcn_fmed3, // llvm.amdgcn.fmed3 - amdgcn_fmul_legacy, // llvm.amdgcn.fmul.legacy - amdgcn_fract, // llvm.amdgcn.fract - amdgcn_frexp_exp, // llvm.amdgcn.frexp.exp - amdgcn_frexp_mant, // llvm.amdgcn.frexp.mant - amdgcn_global_atomic_csub, // llvm.amdgcn.global.atomic.csub - amdgcn_global_atomic_fadd, // llvm.amdgcn.global.atomic.fadd - amdgcn_global_atomic_fmax, // llvm.amdgcn.global.atomic.fmax - amdgcn_global_atomic_fmin, // llvm.amdgcn.global.atomic.fmin - amdgcn_groupstaticsize, // llvm.amdgcn.groupstaticsize - amdgcn_icmp, // llvm.amdgcn.icmp - amdgcn_if, // llvm.amdgcn.if - amdgcn_if_break, // llvm.amdgcn.if.break - amdgcn_image_atomic_add_1d, // llvm.amdgcn.image.atomic.add.1d - amdgcn_image_atomic_add_1darray, // llvm.amdgcn.image.atomic.add.1darray - amdgcn_image_atomic_add_2d, // llvm.amdgcn.image.atomic.add.2d - amdgcn_image_atomic_add_2darray, // llvm.amdgcn.image.atomic.add.2darray - amdgcn_image_atomic_add_2darraymsaa, // llvm.amdgcn.image.atomic.add.2darraymsaa - amdgcn_image_atomic_add_2dmsaa, // llvm.amdgcn.image.atomic.add.2dmsaa - amdgcn_image_atomic_add_3d, // llvm.amdgcn.image.atomic.add.3d - amdgcn_image_atomic_add_cube, // llvm.amdgcn.image.atomic.add.cube - amdgcn_image_atomic_and_1d, // llvm.amdgcn.image.atomic.and.1d - amdgcn_image_atomic_and_1darray, // llvm.amdgcn.image.atomic.and.1darray - amdgcn_image_atomic_and_2d, // llvm.amdgcn.image.atomic.and.2d - amdgcn_image_atomic_and_2darray, // llvm.amdgcn.image.atomic.and.2darray - amdgcn_image_atomic_and_2darraymsaa, // llvm.amdgcn.image.atomic.and.2darraymsaa - amdgcn_image_atomic_and_2dmsaa, // llvm.amdgcn.image.atomic.and.2dmsaa - amdgcn_image_atomic_and_3d, // llvm.amdgcn.image.atomic.and.3d - amdgcn_image_atomic_and_cube, // llvm.amdgcn.image.atomic.and.cube - amdgcn_image_atomic_cmpswap_1d, // llvm.amdgcn.image.atomic.cmpswap.1d - amdgcn_image_atomic_cmpswap_1darray, // llvm.amdgcn.image.atomic.cmpswap.1darray - amdgcn_image_atomic_cmpswap_2d, // llvm.amdgcn.image.atomic.cmpswap.2d - amdgcn_image_atomic_cmpswap_2darray, // llvm.amdgcn.image.atomic.cmpswap.2darray - amdgcn_image_atomic_cmpswap_2darraymsaa, // llvm.amdgcn.image.atomic.cmpswap.2darraymsaa - amdgcn_image_atomic_cmpswap_2dmsaa, // llvm.amdgcn.image.atomic.cmpswap.2dmsaa - amdgcn_image_atomic_cmpswap_3d, // llvm.amdgcn.image.atomic.cmpswap.3d - amdgcn_image_atomic_cmpswap_cube, // llvm.amdgcn.image.atomic.cmpswap.cube - amdgcn_image_atomic_dec_1d, // llvm.amdgcn.image.atomic.dec.1d - amdgcn_image_atomic_dec_1darray, // llvm.amdgcn.image.atomic.dec.1darray - amdgcn_image_atomic_dec_2d, // llvm.amdgcn.image.atomic.dec.2d - amdgcn_image_atomic_dec_2darray, // llvm.amdgcn.image.atomic.dec.2darray - amdgcn_image_atomic_dec_2darraymsaa, // llvm.amdgcn.image.atomic.dec.2darraymsaa - amdgcn_image_atomic_dec_2dmsaa, // llvm.amdgcn.image.atomic.dec.2dmsaa - amdgcn_image_atomic_dec_3d, // llvm.amdgcn.image.atomic.dec.3d - amdgcn_image_atomic_dec_cube, // llvm.amdgcn.image.atomic.dec.cube - amdgcn_image_atomic_fmax_1d, // llvm.amdgcn.image.atomic.fmax.1d - amdgcn_image_atomic_fmax_1darray, // llvm.amdgcn.image.atomic.fmax.1darray - amdgcn_image_atomic_fmax_2d, // llvm.amdgcn.image.atomic.fmax.2d - amdgcn_image_atomic_fmax_2darray, // llvm.amdgcn.image.atomic.fmax.2darray - amdgcn_image_atomic_fmax_2darraymsaa, // llvm.amdgcn.image.atomic.fmax.2darraymsaa - amdgcn_image_atomic_fmax_2dmsaa, // llvm.amdgcn.image.atomic.fmax.2dmsaa - amdgcn_image_atomic_fmax_3d, // llvm.amdgcn.image.atomic.fmax.3d - amdgcn_image_atomic_fmax_cube, // llvm.amdgcn.image.atomic.fmax.cube - amdgcn_image_atomic_fmin_1d, // llvm.amdgcn.image.atomic.fmin.1d - amdgcn_image_atomic_fmin_1darray, // llvm.amdgcn.image.atomic.fmin.1darray - amdgcn_image_atomic_fmin_2d, // llvm.amdgcn.image.atomic.fmin.2d - amdgcn_image_atomic_fmin_2darray, // llvm.amdgcn.image.atomic.fmin.2darray - amdgcn_image_atomic_fmin_2darraymsaa, // llvm.amdgcn.image.atomic.fmin.2darraymsaa - amdgcn_image_atomic_fmin_2dmsaa, // llvm.amdgcn.image.atomic.fmin.2dmsaa - amdgcn_image_atomic_fmin_3d, // llvm.amdgcn.image.atomic.fmin.3d - amdgcn_image_atomic_fmin_cube, // llvm.amdgcn.image.atomic.fmin.cube - amdgcn_image_atomic_inc_1d, // llvm.amdgcn.image.atomic.inc.1d - amdgcn_image_atomic_inc_1darray, // llvm.amdgcn.image.atomic.inc.1darray - amdgcn_image_atomic_inc_2d, // llvm.amdgcn.image.atomic.inc.2d - amdgcn_image_atomic_inc_2darray, // llvm.amdgcn.image.atomic.inc.2darray - amdgcn_image_atomic_inc_2darraymsaa, // llvm.amdgcn.image.atomic.inc.2darraymsaa - amdgcn_image_atomic_inc_2dmsaa, // llvm.amdgcn.image.atomic.inc.2dmsaa - amdgcn_image_atomic_inc_3d, // llvm.amdgcn.image.atomic.inc.3d - amdgcn_image_atomic_inc_cube, // llvm.amdgcn.image.atomic.inc.cube - amdgcn_image_atomic_or_1d, // llvm.amdgcn.image.atomic.or.1d - amdgcn_image_atomic_or_1darray, // llvm.amdgcn.image.atomic.or.1darray - amdgcn_image_atomic_or_2d, // llvm.amdgcn.image.atomic.or.2d - amdgcn_image_atomic_or_2darray, // llvm.amdgcn.image.atomic.or.2darray - amdgcn_image_atomic_or_2darraymsaa, // llvm.amdgcn.image.atomic.or.2darraymsaa - amdgcn_image_atomic_or_2dmsaa, // llvm.amdgcn.image.atomic.or.2dmsaa - amdgcn_image_atomic_or_3d, // llvm.amdgcn.image.atomic.or.3d - amdgcn_image_atomic_or_cube, // llvm.amdgcn.image.atomic.or.cube - amdgcn_image_atomic_smax_1d, // llvm.amdgcn.image.atomic.smax.1d - amdgcn_image_atomic_smax_1darray, // llvm.amdgcn.image.atomic.smax.1darray - amdgcn_image_atomic_smax_2d, // llvm.amdgcn.image.atomic.smax.2d - amdgcn_image_atomic_smax_2darray, // llvm.amdgcn.image.atomic.smax.2darray - amdgcn_image_atomic_smax_2darraymsaa, // llvm.amdgcn.image.atomic.smax.2darraymsaa - amdgcn_image_atomic_smax_2dmsaa, // llvm.amdgcn.image.atomic.smax.2dmsaa - amdgcn_image_atomic_smax_3d, // llvm.amdgcn.image.atomic.smax.3d - amdgcn_image_atomic_smax_cube, // llvm.amdgcn.image.atomic.smax.cube - amdgcn_image_atomic_smin_1d, // llvm.amdgcn.image.atomic.smin.1d - amdgcn_image_atomic_smin_1darray, // llvm.amdgcn.image.atomic.smin.1darray - amdgcn_image_atomic_smin_2d, // llvm.amdgcn.image.atomic.smin.2d - amdgcn_image_atomic_smin_2darray, // llvm.amdgcn.image.atomic.smin.2darray - amdgcn_image_atomic_smin_2darraymsaa, // llvm.amdgcn.image.atomic.smin.2darraymsaa - amdgcn_image_atomic_smin_2dmsaa, // llvm.amdgcn.image.atomic.smin.2dmsaa - amdgcn_image_atomic_smin_3d, // llvm.amdgcn.image.atomic.smin.3d - amdgcn_image_atomic_smin_cube, // llvm.amdgcn.image.atomic.smin.cube - amdgcn_image_atomic_sub_1d, // llvm.amdgcn.image.atomic.sub.1d - amdgcn_image_atomic_sub_1darray, // llvm.amdgcn.image.atomic.sub.1darray - amdgcn_image_atomic_sub_2d, // llvm.amdgcn.image.atomic.sub.2d - amdgcn_image_atomic_sub_2darray, // llvm.amdgcn.image.atomic.sub.2darray - amdgcn_image_atomic_sub_2darraymsaa, // llvm.amdgcn.image.atomic.sub.2darraymsaa - amdgcn_image_atomic_sub_2dmsaa, // llvm.amdgcn.image.atomic.sub.2dmsaa - amdgcn_image_atomic_sub_3d, // llvm.amdgcn.image.atomic.sub.3d - amdgcn_image_atomic_sub_cube, // llvm.amdgcn.image.atomic.sub.cube - amdgcn_image_atomic_swap_1d, // llvm.amdgcn.image.atomic.swap.1d - amdgcn_image_atomic_swap_1darray, // llvm.amdgcn.image.atomic.swap.1darray - amdgcn_image_atomic_swap_2d, // llvm.amdgcn.image.atomic.swap.2d - amdgcn_image_atomic_swap_2darray, // llvm.amdgcn.image.atomic.swap.2darray - amdgcn_image_atomic_swap_2darraymsaa, // llvm.amdgcn.image.atomic.swap.2darraymsaa - amdgcn_image_atomic_swap_2dmsaa, // llvm.amdgcn.image.atomic.swap.2dmsaa - amdgcn_image_atomic_swap_3d, // llvm.amdgcn.image.atomic.swap.3d - amdgcn_image_atomic_swap_cube, // llvm.amdgcn.image.atomic.swap.cube - amdgcn_image_atomic_umax_1d, // llvm.amdgcn.image.atomic.umax.1d - amdgcn_image_atomic_umax_1darray, // llvm.amdgcn.image.atomic.umax.1darray - amdgcn_image_atomic_umax_2d, // llvm.amdgcn.image.atomic.umax.2d - amdgcn_image_atomic_umax_2darray, // llvm.amdgcn.image.atomic.umax.2darray - amdgcn_image_atomic_umax_2darraymsaa, // llvm.amdgcn.image.atomic.umax.2darraymsaa - amdgcn_image_atomic_umax_2dmsaa, // llvm.amdgcn.image.atomic.umax.2dmsaa - amdgcn_image_atomic_umax_3d, // llvm.amdgcn.image.atomic.umax.3d - amdgcn_image_atomic_umax_cube, // llvm.amdgcn.image.atomic.umax.cube - amdgcn_image_atomic_umin_1d, // llvm.amdgcn.image.atomic.umin.1d - amdgcn_image_atomic_umin_1darray, // llvm.amdgcn.image.atomic.umin.1darray - amdgcn_image_atomic_umin_2d, // llvm.amdgcn.image.atomic.umin.2d - amdgcn_image_atomic_umin_2darray, // llvm.amdgcn.image.atomic.umin.2darray - amdgcn_image_atomic_umin_2darraymsaa, // llvm.amdgcn.image.atomic.umin.2darraymsaa - amdgcn_image_atomic_umin_2dmsaa, // llvm.amdgcn.image.atomic.umin.2dmsaa - amdgcn_image_atomic_umin_3d, // llvm.amdgcn.image.atomic.umin.3d - amdgcn_image_atomic_umin_cube, // llvm.amdgcn.image.atomic.umin.cube - amdgcn_image_atomic_xor_1d, // llvm.amdgcn.image.atomic.xor.1d - amdgcn_image_atomic_xor_1darray, // llvm.amdgcn.image.atomic.xor.1darray - amdgcn_image_atomic_xor_2d, // llvm.amdgcn.image.atomic.xor.2d - amdgcn_image_atomic_xor_2darray, // llvm.amdgcn.image.atomic.xor.2darray - amdgcn_image_atomic_xor_2darraymsaa, // llvm.amdgcn.image.atomic.xor.2darraymsaa - amdgcn_image_atomic_xor_2dmsaa, // llvm.amdgcn.image.atomic.xor.2dmsaa - amdgcn_image_atomic_xor_3d, // llvm.amdgcn.image.atomic.xor.3d - amdgcn_image_atomic_xor_cube, // llvm.amdgcn.image.atomic.xor.cube - amdgcn_image_bvh_intersect_ray, // llvm.amdgcn.image.bvh.intersect.ray - amdgcn_image_gather4_2d, // llvm.amdgcn.image.gather4.2d - amdgcn_image_gather4_2darray, // llvm.amdgcn.image.gather4.2darray - amdgcn_image_gather4_b_2d, // llvm.amdgcn.image.gather4.b.2d - amdgcn_image_gather4_b_2darray, // llvm.amdgcn.image.gather4.b.2darray - amdgcn_image_gather4_b_cl_2d, // llvm.amdgcn.image.gather4.b.cl.2d - amdgcn_image_gather4_b_cl_2darray, // llvm.amdgcn.image.gather4.b.cl.2darray - amdgcn_image_gather4_b_cl_cube, // llvm.amdgcn.image.gather4.b.cl.cube - amdgcn_image_gather4_b_cl_o_2d, // llvm.amdgcn.image.gather4.b.cl.o.2d - amdgcn_image_gather4_b_cl_o_2darray, // llvm.amdgcn.image.gather4.b.cl.o.2darray - amdgcn_image_gather4_b_cl_o_cube, // llvm.amdgcn.image.gather4.b.cl.o.cube - amdgcn_image_gather4_b_cube, // llvm.amdgcn.image.gather4.b.cube - amdgcn_image_gather4_b_o_2d, // llvm.amdgcn.image.gather4.b.o.2d - amdgcn_image_gather4_b_o_2darray, // llvm.amdgcn.image.gather4.b.o.2darray - amdgcn_image_gather4_b_o_cube, // llvm.amdgcn.image.gather4.b.o.cube - amdgcn_image_gather4_c_2d, // llvm.amdgcn.image.gather4.c.2d - amdgcn_image_gather4_c_2darray, // llvm.amdgcn.image.gather4.c.2darray - amdgcn_image_gather4_c_b_2d, // llvm.amdgcn.image.gather4.c.b.2d - amdgcn_image_gather4_c_b_2darray, // llvm.amdgcn.image.gather4.c.b.2darray - amdgcn_image_gather4_c_b_cl_2d, // llvm.amdgcn.image.gather4.c.b.cl.2d - amdgcn_image_gather4_c_b_cl_2darray, // llvm.amdgcn.image.gather4.c.b.cl.2darray - amdgcn_image_gather4_c_b_cl_cube, // llvm.amdgcn.image.gather4.c.b.cl.cube - amdgcn_image_gather4_c_b_cl_o_2d, // llvm.amdgcn.image.gather4.c.b.cl.o.2d - amdgcn_image_gather4_c_b_cl_o_2darray, // llvm.amdgcn.image.gather4.c.b.cl.o.2darray - amdgcn_image_gather4_c_b_cl_o_cube, // llvm.amdgcn.image.gather4.c.b.cl.o.cube - amdgcn_image_gather4_c_b_cube, // llvm.amdgcn.image.gather4.c.b.cube - amdgcn_image_gather4_c_b_o_2d, // llvm.amdgcn.image.gather4.c.b.o.2d - amdgcn_image_gather4_c_b_o_2darray, // llvm.amdgcn.image.gather4.c.b.o.2darray - amdgcn_image_gather4_c_b_o_cube, // llvm.amdgcn.image.gather4.c.b.o.cube - amdgcn_image_gather4_c_cl_2d, // llvm.amdgcn.image.gather4.c.cl.2d - amdgcn_image_gather4_c_cl_2darray, // llvm.amdgcn.image.gather4.c.cl.2darray - amdgcn_image_gather4_c_cl_cube, // llvm.amdgcn.image.gather4.c.cl.cube - amdgcn_image_gather4_c_cl_o_2d, // llvm.amdgcn.image.gather4.c.cl.o.2d - amdgcn_image_gather4_c_cl_o_2darray, // llvm.amdgcn.image.gather4.c.cl.o.2darray - amdgcn_image_gather4_c_cl_o_cube, // llvm.amdgcn.image.gather4.c.cl.o.cube - amdgcn_image_gather4_c_cube, // llvm.amdgcn.image.gather4.c.cube - amdgcn_image_gather4_c_l_2d, // llvm.amdgcn.image.gather4.c.l.2d - amdgcn_image_gather4_c_l_2darray, // llvm.amdgcn.image.gather4.c.l.2darray - amdgcn_image_gather4_c_l_cube, // llvm.amdgcn.image.gather4.c.l.cube - amdgcn_image_gather4_c_l_o_2d, // llvm.amdgcn.image.gather4.c.l.o.2d - amdgcn_image_gather4_c_l_o_2darray, // llvm.amdgcn.image.gather4.c.l.o.2darray - amdgcn_image_gather4_c_l_o_cube, // llvm.amdgcn.image.gather4.c.l.o.cube - amdgcn_image_gather4_c_lz_2d, // llvm.amdgcn.image.gather4.c.lz.2d - amdgcn_image_gather4_c_lz_2darray, // llvm.amdgcn.image.gather4.c.lz.2darray - amdgcn_image_gather4_c_lz_cube, // llvm.amdgcn.image.gather4.c.lz.cube - amdgcn_image_gather4_c_lz_o_2d, // llvm.amdgcn.image.gather4.c.lz.o.2d - amdgcn_image_gather4_c_lz_o_2darray, // llvm.amdgcn.image.gather4.c.lz.o.2darray - amdgcn_image_gather4_c_lz_o_cube, // llvm.amdgcn.image.gather4.c.lz.o.cube - amdgcn_image_gather4_c_o_2d, // llvm.amdgcn.image.gather4.c.o.2d - amdgcn_image_gather4_c_o_2darray, // llvm.amdgcn.image.gather4.c.o.2darray - amdgcn_image_gather4_c_o_cube, // llvm.amdgcn.image.gather4.c.o.cube - amdgcn_image_gather4_cl_2d, // llvm.amdgcn.image.gather4.cl.2d - amdgcn_image_gather4_cl_2darray, // llvm.amdgcn.image.gather4.cl.2darray - amdgcn_image_gather4_cl_cube, // llvm.amdgcn.image.gather4.cl.cube - amdgcn_image_gather4_cl_o_2d, // llvm.amdgcn.image.gather4.cl.o.2d - amdgcn_image_gather4_cl_o_2darray, // llvm.amdgcn.image.gather4.cl.o.2darray - amdgcn_image_gather4_cl_o_cube, // llvm.amdgcn.image.gather4.cl.o.cube - amdgcn_image_gather4_cube, // llvm.amdgcn.image.gather4.cube - amdgcn_image_gather4_l_2d, // llvm.amdgcn.image.gather4.l.2d - amdgcn_image_gather4_l_2darray, // llvm.amdgcn.image.gather4.l.2darray - amdgcn_image_gather4_l_cube, // llvm.amdgcn.image.gather4.l.cube - amdgcn_image_gather4_l_o_2d, // llvm.amdgcn.image.gather4.l.o.2d - amdgcn_image_gather4_l_o_2darray, // llvm.amdgcn.image.gather4.l.o.2darray - amdgcn_image_gather4_l_o_cube, // llvm.amdgcn.image.gather4.l.o.cube - amdgcn_image_gather4_lz_2d, // llvm.amdgcn.image.gather4.lz.2d - amdgcn_image_gather4_lz_2darray, // llvm.amdgcn.image.gather4.lz.2darray - amdgcn_image_gather4_lz_cube, // llvm.amdgcn.image.gather4.lz.cube - amdgcn_image_gather4_lz_o_2d, // llvm.amdgcn.image.gather4.lz.o.2d - amdgcn_image_gather4_lz_o_2darray, // llvm.amdgcn.image.gather4.lz.o.2darray - amdgcn_image_gather4_lz_o_cube, // llvm.amdgcn.image.gather4.lz.o.cube - amdgcn_image_gather4_o_2d, // llvm.amdgcn.image.gather4.o.2d - amdgcn_image_gather4_o_2darray, // llvm.amdgcn.image.gather4.o.2darray - amdgcn_image_gather4_o_cube, // llvm.amdgcn.image.gather4.o.cube - amdgcn_image_getlod_1d, // llvm.amdgcn.image.getlod.1d - amdgcn_image_getlod_1darray, // llvm.amdgcn.image.getlod.1darray - amdgcn_image_getlod_2d, // llvm.amdgcn.image.getlod.2d - amdgcn_image_getlod_2darray, // llvm.amdgcn.image.getlod.2darray - amdgcn_image_getlod_3d, // llvm.amdgcn.image.getlod.3d - amdgcn_image_getlod_cube, // llvm.amdgcn.image.getlod.cube - amdgcn_image_getresinfo_1d, // llvm.amdgcn.image.getresinfo.1d - amdgcn_image_getresinfo_1darray, // llvm.amdgcn.image.getresinfo.1darray - amdgcn_image_getresinfo_2d, // llvm.amdgcn.image.getresinfo.2d - amdgcn_image_getresinfo_2darray, // llvm.amdgcn.image.getresinfo.2darray - amdgcn_image_getresinfo_2darraymsaa, // llvm.amdgcn.image.getresinfo.2darraymsaa - amdgcn_image_getresinfo_2dmsaa, // llvm.amdgcn.image.getresinfo.2dmsaa - amdgcn_image_getresinfo_3d, // llvm.amdgcn.image.getresinfo.3d - amdgcn_image_getresinfo_cube, // llvm.amdgcn.image.getresinfo.cube - amdgcn_image_load_1d, // llvm.amdgcn.image.load.1d - amdgcn_image_load_1darray, // llvm.amdgcn.image.load.1darray - amdgcn_image_load_2d, // llvm.amdgcn.image.load.2d - amdgcn_image_load_2darray, // llvm.amdgcn.image.load.2darray - amdgcn_image_load_2darraymsaa, // llvm.amdgcn.image.load.2darraymsaa - amdgcn_image_load_2dmsaa, // llvm.amdgcn.image.load.2dmsaa - amdgcn_image_load_3d, // llvm.amdgcn.image.load.3d - amdgcn_image_load_cube, // llvm.amdgcn.image.load.cube - amdgcn_image_load_mip_1d, // llvm.amdgcn.image.load.mip.1d - amdgcn_image_load_mip_1darray, // llvm.amdgcn.image.load.mip.1darray - amdgcn_image_load_mip_2d, // llvm.amdgcn.image.load.mip.2d - amdgcn_image_load_mip_2darray, // llvm.amdgcn.image.load.mip.2darray - amdgcn_image_load_mip_3d, // llvm.amdgcn.image.load.mip.3d - amdgcn_image_load_mip_cube, // llvm.amdgcn.image.load.mip.cube - amdgcn_image_msaa_load_x_2darraymsaa, // llvm.amdgcn.image.msaa.load.x.2darraymsaa - amdgcn_image_msaa_load_x_2dmsaa, // llvm.amdgcn.image.msaa.load.x.2dmsaa - amdgcn_image_sample_1d, // llvm.amdgcn.image.sample.1d - amdgcn_image_sample_1darray, // llvm.amdgcn.image.sample.1darray - amdgcn_image_sample_2d, // llvm.amdgcn.image.sample.2d - amdgcn_image_sample_2darray, // llvm.amdgcn.image.sample.2darray - amdgcn_image_sample_3d, // llvm.amdgcn.image.sample.3d - amdgcn_image_sample_b_1d, // llvm.amdgcn.image.sample.b.1d - amdgcn_image_sample_b_1darray, // llvm.amdgcn.image.sample.b.1darray - amdgcn_image_sample_b_2d, // llvm.amdgcn.image.sample.b.2d - amdgcn_image_sample_b_2darray, // llvm.amdgcn.image.sample.b.2darray - amdgcn_image_sample_b_3d, // llvm.amdgcn.image.sample.b.3d - amdgcn_image_sample_b_cl_1d, // llvm.amdgcn.image.sample.b.cl.1d - amdgcn_image_sample_b_cl_1darray, // llvm.amdgcn.image.sample.b.cl.1darray - amdgcn_image_sample_b_cl_2d, // llvm.amdgcn.image.sample.b.cl.2d - amdgcn_image_sample_b_cl_2darray, // llvm.amdgcn.image.sample.b.cl.2darray - amdgcn_image_sample_b_cl_3d, // llvm.amdgcn.image.sample.b.cl.3d - amdgcn_image_sample_b_cl_cube, // llvm.amdgcn.image.sample.b.cl.cube - amdgcn_image_sample_b_cl_o_1d, // llvm.amdgcn.image.sample.b.cl.o.1d - amdgcn_image_sample_b_cl_o_1darray, // llvm.amdgcn.image.sample.b.cl.o.1darray - amdgcn_image_sample_b_cl_o_2d, // llvm.amdgcn.image.sample.b.cl.o.2d - amdgcn_image_sample_b_cl_o_2darray, // llvm.amdgcn.image.sample.b.cl.o.2darray - amdgcn_image_sample_b_cl_o_3d, // llvm.amdgcn.image.sample.b.cl.o.3d - amdgcn_image_sample_b_cl_o_cube, // llvm.amdgcn.image.sample.b.cl.o.cube - amdgcn_image_sample_b_cube, // llvm.amdgcn.image.sample.b.cube - amdgcn_image_sample_b_o_1d, // llvm.amdgcn.image.sample.b.o.1d - amdgcn_image_sample_b_o_1darray, // llvm.amdgcn.image.sample.b.o.1darray - amdgcn_image_sample_b_o_2d, // llvm.amdgcn.image.sample.b.o.2d - amdgcn_image_sample_b_o_2darray, // llvm.amdgcn.image.sample.b.o.2darray - amdgcn_image_sample_b_o_3d, // llvm.amdgcn.image.sample.b.o.3d - amdgcn_image_sample_b_o_cube, // llvm.amdgcn.image.sample.b.o.cube - amdgcn_image_sample_c_1d, // llvm.amdgcn.image.sample.c.1d - amdgcn_image_sample_c_1darray, // llvm.amdgcn.image.sample.c.1darray - amdgcn_image_sample_c_2d, // llvm.amdgcn.image.sample.c.2d - amdgcn_image_sample_c_2darray, // llvm.amdgcn.image.sample.c.2darray - amdgcn_image_sample_c_3d, // llvm.amdgcn.image.sample.c.3d - amdgcn_image_sample_c_b_1d, // llvm.amdgcn.image.sample.c.b.1d - amdgcn_image_sample_c_b_1darray, // llvm.amdgcn.image.sample.c.b.1darray - amdgcn_image_sample_c_b_2d, // llvm.amdgcn.image.sample.c.b.2d - amdgcn_image_sample_c_b_2darray, // llvm.amdgcn.image.sample.c.b.2darray - amdgcn_image_sample_c_b_3d, // llvm.amdgcn.image.sample.c.b.3d - amdgcn_image_sample_c_b_cl_1d, // llvm.amdgcn.image.sample.c.b.cl.1d - amdgcn_image_sample_c_b_cl_1darray, // llvm.amdgcn.image.sample.c.b.cl.1darray - amdgcn_image_sample_c_b_cl_2d, // llvm.amdgcn.image.sample.c.b.cl.2d - amdgcn_image_sample_c_b_cl_2darray, // llvm.amdgcn.image.sample.c.b.cl.2darray - amdgcn_image_sample_c_b_cl_3d, // llvm.amdgcn.image.sample.c.b.cl.3d - amdgcn_image_sample_c_b_cl_cube, // llvm.amdgcn.image.sample.c.b.cl.cube - amdgcn_image_sample_c_b_cl_o_1d, // llvm.amdgcn.image.sample.c.b.cl.o.1d - amdgcn_image_sample_c_b_cl_o_1darray, // llvm.amdgcn.image.sample.c.b.cl.o.1darray - amdgcn_image_sample_c_b_cl_o_2d, // llvm.amdgcn.image.sample.c.b.cl.o.2d - amdgcn_image_sample_c_b_cl_o_2darray, // llvm.amdgcn.image.sample.c.b.cl.o.2darray - amdgcn_image_sample_c_b_cl_o_3d, // llvm.amdgcn.image.sample.c.b.cl.o.3d - amdgcn_image_sample_c_b_cl_o_cube, // llvm.amdgcn.image.sample.c.b.cl.o.cube - amdgcn_image_sample_c_b_cube, // llvm.amdgcn.image.sample.c.b.cube - amdgcn_image_sample_c_b_o_1d, // llvm.amdgcn.image.sample.c.b.o.1d - amdgcn_image_sample_c_b_o_1darray, // llvm.amdgcn.image.sample.c.b.o.1darray - amdgcn_image_sample_c_b_o_2d, // llvm.amdgcn.image.sample.c.b.o.2d - amdgcn_image_sample_c_b_o_2darray, // llvm.amdgcn.image.sample.c.b.o.2darray - amdgcn_image_sample_c_b_o_3d, // llvm.amdgcn.image.sample.c.b.o.3d - amdgcn_image_sample_c_b_o_cube, // llvm.amdgcn.image.sample.c.b.o.cube - amdgcn_image_sample_c_cd_1d, // llvm.amdgcn.image.sample.c.cd.1d - amdgcn_image_sample_c_cd_1darray, // llvm.amdgcn.image.sample.c.cd.1darray - amdgcn_image_sample_c_cd_2d, // llvm.amdgcn.image.sample.c.cd.2d - amdgcn_image_sample_c_cd_2darray, // llvm.amdgcn.image.sample.c.cd.2darray - amdgcn_image_sample_c_cd_3d, // llvm.amdgcn.image.sample.c.cd.3d - amdgcn_image_sample_c_cd_cl_1d, // llvm.amdgcn.image.sample.c.cd.cl.1d - amdgcn_image_sample_c_cd_cl_1darray, // llvm.amdgcn.image.sample.c.cd.cl.1darray - amdgcn_image_sample_c_cd_cl_2d, // llvm.amdgcn.image.sample.c.cd.cl.2d - amdgcn_image_sample_c_cd_cl_2darray, // llvm.amdgcn.image.sample.c.cd.cl.2darray - amdgcn_image_sample_c_cd_cl_3d, // llvm.amdgcn.image.sample.c.cd.cl.3d - amdgcn_image_sample_c_cd_cl_cube, // llvm.amdgcn.image.sample.c.cd.cl.cube - amdgcn_image_sample_c_cd_cl_o_1d, // llvm.amdgcn.image.sample.c.cd.cl.o.1d - amdgcn_image_sample_c_cd_cl_o_1darray, // llvm.amdgcn.image.sample.c.cd.cl.o.1darray - amdgcn_image_sample_c_cd_cl_o_2d, // llvm.amdgcn.image.sample.c.cd.cl.o.2d - amdgcn_image_sample_c_cd_cl_o_2darray, // llvm.amdgcn.image.sample.c.cd.cl.o.2darray - amdgcn_image_sample_c_cd_cl_o_3d, // llvm.amdgcn.image.sample.c.cd.cl.o.3d - amdgcn_image_sample_c_cd_cl_o_cube, // llvm.amdgcn.image.sample.c.cd.cl.o.cube - amdgcn_image_sample_c_cd_cube, // llvm.amdgcn.image.sample.c.cd.cube - amdgcn_image_sample_c_cd_o_1d, // llvm.amdgcn.image.sample.c.cd.o.1d - amdgcn_image_sample_c_cd_o_1darray, // llvm.amdgcn.image.sample.c.cd.o.1darray - amdgcn_image_sample_c_cd_o_2d, // llvm.amdgcn.image.sample.c.cd.o.2d - amdgcn_image_sample_c_cd_o_2darray, // llvm.amdgcn.image.sample.c.cd.o.2darray - amdgcn_image_sample_c_cd_o_3d, // llvm.amdgcn.image.sample.c.cd.o.3d - amdgcn_image_sample_c_cd_o_cube, // llvm.amdgcn.image.sample.c.cd.o.cube - amdgcn_image_sample_c_cl_1d, // llvm.amdgcn.image.sample.c.cl.1d - amdgcn_image_sample_c_cl_1darray, // llvm.amdgcn.image.sample.c.cl.1darray - amdgcn_image_sample_c_cl_2d, // llvm.amdgcn.image.sample.c.cl.2d - amdgcn_image_sample_c_cl_2darray, // llvm.amdgcn.image.sample.c.cl.2darray - amdgcn_image_sample_c_cl_3d, // llvm.amdgcn.image.sample.c.cl.3d - amdgcn_image_sample_c_cl_cube, // llvm.amdgcn.image.sample.c.cl.cube - amdgcn_image_sample_c_cl_o_1d, // llvm.amdgcn.image.sample.c.cl.o.1d - amdgcn_image_sample_c_cl_o_1darray, // llvm.amdgcn.image.sample.c.cl.o.1darray - amdgcn_image_sample_c_cl_o_2d, // llvm.amdgcn.image.sample.c.cl.o.2d - amdgcn_image_sample_c_cl_o_2darray, // llvm.amdgcn.image.sample.c.cl.o.2darray - amdgcn_image_sample_c_cl_o_3d, // llvm.amdgcn.image.sample.c.cl.o.3d - amdgcn_image_sample_c_cl_o_cube, // llvm.amdgcn.image.sample.c.cl.o.cube - amdgcn_image_sample_c_cube, // llvm.amdgcn.image.sample.c.cube - amdgcn_image_sample_c_d_1d, // llvm.amdgcn.image.sample.c.d.1d - amdgcn_image_sample_c_d_1darray, // llvm.amdgcn.image.sample.c.d.1darray - amdgcn_image_sample_c_d_2d, // llvm.amdgcn.image.sample.c.d.2d - amdgcn_image_sample_c_d_2darray, // llvm.amdgcn.image.sample.c.d.2darray - amdgcn_image_sample_c_d_3d, // llvm.amdgcn.image.sample.c.d.3d - amdgcn_image_sample_c_d_cl_1d, // llvm.amdgcn.image.sample.c.d.cl.1d - amdgcn_image_sample_c_d_cl_1darray, // llvm.amdgcn.image.sample.c.d.cl.1darray - amdgcn_image_sample_c_d_cl_2d, // llvm.amdgcn.image.sample.c.d.cl.2d - amdgcn_image_sample_c_d_cl_2darray, // llvm.amdgcn.image.sample.c.d.cl.2darray - amdgcn_image_sample_c_d_cl_3d, // llvm.amdgcn.image.sample.c.d.cl.3d - amdgcn_image_sample_c_d_cl_cube, // llvm.amdgcn.image.sample.c.d.cl.cube - amdgcn_image_sample_c_d_cl_o_1d, // llvm.amdgcn.image.sample.c.d.cl.o.1d - amdgcn_image_sample_c_d_cl_o_1darray, // llvm.amdgcn.image.sample.c.d.cl.o.1darray - amdgcn_image_sample_c_d_cl_o_2d, // llvm.amdgcn.image.sample.c.d.cl.o.2d - amdgcn_image_sample_c_d_cl_o_2darray, // llvm.amdgcn.image.sample.c.d.cl.o.2darray - amdgcn_image_sample_c_d_cl_o_3d, // llvm.amdgcn.image.sample.c.d.cl.o.3d - amdgcn_image_sample_c_d_cl_o_cube, // llvm.amdgcn.image.sample.c.d.cl.o.cube - amdgcn_image_sample_c_d_cube, // llvm.amdgcn.image.sample.c.d.cube - amdgcn_image_sample_c_d_o_1d, // llvm.amdgcn.image.sample.c.d.o.1d - amdgcn_image_sample_c_d_o_1darray, // llvm.amdgcn.image.sample.c.d.o.1darray - amdgcn_image_sample_c_d_o_2d, // llvm.amdgcn.image.sample.c.d.o.2d - amdgcn_image_sample_c_d_o_2darray, // llvm.amdgcn.image.sample.c.d.o.2darray - amdgcn_image_sample_c_d_o_3d, // llvm.amdgcn.image.sample.c.d.o.3d - amdgcn_image_sample_c_d_o_cube, // llvm.amdgcn.image.sample.c.d.o.cube - amdgcn_image_sample_c_l_1d, // llvm.amdgcn.image.sample.c.l.1d - amdgcn_image_sample_c_l_1darray, // llvm.amdgcn.image.sample.c.l.1darray - amdgcn_image_sample_c_l_2d, // llvm.amdgcn.image.sample.c.l.2d - amdgcn_image_sample_c_l_2darray, // llvm.amdgcn.image.sample.c.l.2darray - amdgcn_image_sample_c_l_3d, // llvm.amdgcn.image.sample.c.l.3d - amdgcn_image_sample_c_l_cube, // llvm.amdgcn.image.sample.c.l.cube - amdgcn_image_sample_c_l_o_1d, // llvm.amdgcn.image.sample.c.l.o.1d - amdgcn_image_sample_c_l_o_1darray, // llvm.amdgcn.image.sample.c.l.o.1darray - amdgcn_image_sample_c_l_o_2d, // llvm.amdgcn.image.sample.c.l.o.2d - amdgcn_image_sample_c_l_o_2darray, // llvm.amdgcn.image.sample.c.l.o.2darray - amdgcn_image_sample_c_l_o_3d, // llvm.amdgcn.image.sample.c.l.o.3d - amdgcn_image_sample_c_l_o_cube, // llvm.amdgcn.image.sample.c.l.o.cube - amdgcn_image_sample_c_lz_1d, // llvm.amdgcn.image.sample.c.lz.1d - amdgcn_image_sample_c_lz_1darray, // llvm.amdgcn.image.sample.c.lz.1darray - amdgcn_image_sample_c_lz_2d, // llvm.amdgcn.image.sample.c.lz.2d - amdgcn_image_sample_c_lz_2darray, // llvm.amdgcn.image.sample.c.lz.2darray - amdgcn_image_sample_c_lz_3d, // llvm.amdgcn.image.sample.c.lz.3d - amdgcn_image_sample_c_lz_cube, // llvm.amdgcn.image.sample.c.lz.cube - amdgcn_image_sample_c_lz_o_1d, // llvm.amdgcn.image.sample.c.lz.o.1d - amdgcn_image_sample_c_lz_o_1darray, // llvm.amdgcn.image.sample.c.lz.o.1darray - amdgcn_image_sample_c_lz_o_2d, // llvm.amdgcn.image.sample.c.lz.o.2d - amdgcn_image_sample_c_lz_o_2darray, // llvm.amdgcn.image.sample.c.lz.o.2darray - amdgcn_image_sample_c_lz_o_3d, // llvm.amdgcn.image.sample.c.lz.o.3d - amdgcn_image_sample_c_lz_o_cube, // llvm.amdgcn.image.sample.c.lz.o.cube - amdgcn_image_sample_c_o_1d, // llvm.amdgcn.image.sample.c.o.1d - amdgcn_image_sample_c_o_1darray, // llvm.amdgcn.image.sample.c.o.1darray - amdgcn_image_sample_c_o_2d, // llvm.amdgcn.image.sample.c.o.2d - amdgcn_image_sample_c_o_2darray, // llvm.amdgcn.image.sample.c.o.2darray - amdgcn_image_sample_c_o_3d, // llvm.amdgcn.image.sample.c.o.3d - amdgcn_image_sample_c_o_cube, // llvm.amdgcn.image.sample.c.o.cube - amdgcn_image_sample_cd_1d, // llvm.amdgcn.image.sample.cd.1d - amdgcn_image_sample_cd_1darray, // llvm.amdgcn.image.sample.cd.1darray - amdgcn_image_sample_cd_2d, // llvm.amdgcn.image.sample.cd.2d - amdgcn_image_sample_cd_2darray, // llvm.amdgcn.image.sample.cd.2darray - amdgcn_image_sample_cd_3d, // llvm.amdgcn.image.sample.cd.3d - amdgcn_image_sample_cd_cl_1d, // llvm.amdgcn.image.sample.cd.cl.1d - amdgcn_image_sample_cd_cl_1darray, // llvm.amdgcn.image.sample.cd.cl.1darray - amdgcn_image_sample_cd_cl_2d, // llvm.amdgcn.image.sample.cd.cl.2d - amdgcn_image_sample_cd_cl_2darray, // llvm.amdgcn.image.sample.cd.cl.2darray - amdgcn_image_sample_cd_cl_3d, // llvm.amdgcn.image.sample.cd.cl.3d - amdgcn_image_sample_cd_cl_cube, // llvm.amdgcn.image.sample.cd.cl.cube - amdgcn_image_sample_cd_cl_o_1d, // llvm.amdgcn.image.sample.cd.cl.o.1d - amdgcn_image_sample_cd_cl_o_1darray, // llvm.amdgcn.image.sample.cd.cl.o.1darray - amdgcn_image_sample_cd_cl_o_2d, // llvm.amdgcn.image.sample.cd.cl.o.2d - amdgcn_image_sample_cd_cl_o_2darray, // llvm.amdgcn.image.sample.cd.cl.o.2darray - amdgcn_image_sample_cd_cl_o_3d, // llvm.amdgcn.image.sample.cd.cl.o.3d - amdgcn_image_sample_cd_cl_o_cube, // llvm.amdgcn.image.sample.cd.cl.o.cube - amdgcn_image_sample_cd_cube, // llvm.amdgcn.image.sample.cd.cube - amdgcn_image_sample_cd_o_1d, // llvm.amdgcn.image.sample.cd.o.1d - amdgcn_image_sample_cd_o_1darray, // llvm.amdgcn.image.sample.cd.o.1darray - amdgcn_image_sample_cd_o_2d, // llvm.amdgcn.image.sample.cd.o.2d - amdgcn_image_sample_cd_o_2darray, // llvm.amdgcn.image.sample.cd.o.2darray - amdgcn_image_sample_cd_o_3d, // llvm.amdgcn.image.sample.cd.o.3d - amdgcn_image_sample_cd_o_cube, // llvm.amdgcn.image.sample.cd.o.cube - amdgcn_image_sample_cl_1d, // llvm.amdgcn.image.sample.cl.1d - amdgcn_image_sample_cl_1darray, // llvm.amdgcn.image.sample.cl.1darray - amdgcn_image_sample_cl_2d, // llvm.amdgcn.image.sample.cl.2d - amdgcn_image_sample_cl_2darray, // llvm.amdgcn.image.sample.cl.2darray - amdgcn_image_sample_cl_3d, // llvm.amdgcn.image.sample.cl.3d - amdgcn_image_sample_cl_cube, // llvm.amdgcn.image.sample.cl.cube - amdgcn_image_sample_cl_o_1d, // llvm.amdgcn.image.sample.cl.o.1d - amdgcn_image_sample_cl_o_1darray, // llvm.amdgcn.image.sample.cl.o.1darray - amdgcn_image_sample_cl_o_2d, // llvm.amdgcn.image.sample.cl.o.2d - amdgcn_image_sample_cl_o_2darray, // llvm.amdgcn.image.sample.cl.o.2darray - amdgcn_image_sample_cl_o_3d, // llvm.amdgcn.image.sample.cl.o.3d - amdgcn_image_sample_cl_o_cube, // llvm.amdgcn.image.sample.cl.o.cube - amdgcn_image_sample_cube, // llvm.amdgcn.image.sample.cube - amdgcn_image_sample_d_1d, // llvm.amdgcn.image.sample.d.1d - amdgcn_image_sample_d_1darray, // llvm.amdgcn.image.sample.d.1darray - amdgcn_image_sample_d_2d, // llvm.amdgcn.image.sample.d.2d - amdgcn_image_sample_d_2darray, // llvm.amdgcn.image.sample.d.2darray - amdgcn_image_sample_d_3d, // llvm.amdgcn.image.sample.d.3d - amdgcn_image_sample_d_cl_1d, // llvm.amdgcn.image.sample.d.cl.1d - amdgcn_image_sample_d_cl_1darray, // llvm.amdgcn.image.sample.d.cl.1darray - amdgcn_image_sample_d_cl_2d, // llvm.amdgcn.image.sample.d.cl.2d - amdgcn_image_sample_d_cl_2darray, // llvm.amdgcn.image.sample.d.cl.2darray - amdgcn_image_sample_d_cl_3d, // llvm.amdgcn.image.sample.d.cl.3d - amdgcn_image_sample_d_cl_cube, // llvm.amdgcn.image.sample.d.cl.cube - amdgcn_image_sample_d_cl_o_1d, // llvm.amdgcn.image.sample.d.cl.o.1d - amdgcn_image_sample_d_cl_o_1darray, // llvm.amdgcn.image.sample.d.cl.o.1darray - amdgcn_image_sample_d_cl_o_2d, // llvm.amdgcn.image.sample.d.cl.o.2d - amdgcn_image_sample_d_cl_o_2darray, // llvm.amdgcn.image.sample.d.cl.o.2darray - amdgcn_image_sample_d_cl_o_3d, // llvm.amdgcn.image.sample.d.cl.o.3d - amdgcn_image_sample_d_cl_o_cube, // llvm.amdgcn.image.sample.d.cl.o.cube - amdgcn_image_sample_d_cube, // llvm.amdgcn.image.sample.d.cube - amdgcn_image_sample_d_o_1d, // llvm.amdgcn.image.sample.d.o.1d - amdgcn_image_sample_d_o_1darray, // llvm.amdgcn.image.sample.d.o.1darray - amdgcn_image_sample_d_o_2d, // llvm.amdgcn.image.sample.d.o.2d - amdgcn_image_sample_d_o_2darray, // llvm.amdgcn.image.sample.d.o.2darray - amdgcn_image_sample_d_o_3d, // llvm.amdgcn.image.sample.d.o.3d - amdgcn_image_sample_d_o_cube, // llvm.amdgcn.image.sample.d.o.cube - amdgcn_image_sample_l_1d, // llvm.amdgcn.image.sample.l.1d - amdgcn_image_sample_l_1darray, // llvm.amdgcn.image.sample.l.1darray - amdgcn_image_sample_l_2d, // llvm.amdgcn.image.sample.l.2d - amdgcn_image_sample_l_2darray, // llvm.amdgcn.image.sample.l.2darray - amdgcn_image_sample_l_3d, // llvm.amdgcn.image.sample.l.3d - amdgcn_image_sample_l_cube, // llvm.amdgcn.image.sample.l.cube - amdgcn_image_sample_l_o_1d, // llvm.amdgcn.image.sample.l.o.1d - amdgcn_image_sample_l_o_1darray, // llvm.amdgcn.image.sample.l.o.1darray - amdgcn_image_sample_l_o_2d, // llvm.amdgcn.image.sample.l.o.2d - amdgcn_image_sample_l_o_2darray, // llvm.amdgcn.image.sample.l.o.2darray - amdgcn_image_sample_l_o_3d, // llvm.amdgcn.image.sample.l.o.3d - amdgcn_image_sample_l_o_cube, // llvm.amdgcn.image.sample.l.o.cube - amdgcn_image_sample_lz_1d, // llvm.amdgcn.image.sample.lz.1d - amdgcn_image_sample_lz_1darray, // llvm.amdgcn.image.sample.lz.1darray - amdgcn_image_sample_lz_2d, // llvm.amdgcn.image.sample.lz.2d - amdgcn_image_sample_lz_2darray, // llvm.amdgcn.image.sample.lz.2darray - amdgcn_image_sample_lz_3d, // llvm.amdgcn.image.sample.lz.3d - amdgcn_image_sample_lz_cube, // llvm.amdgcn.image.sample.lz.cube - amdgcn_image_sample_lz_o_1d, // llvm.amdgcn.image.sample.lz.o.1d - amdgcn_image_sample_lz_o_1darray, // llvm.amdgcn.image.sample.lz.o.1darray - amdgcn_image_sample_lz_o_2d, // llvm.amdgcn.image.sample.lz.o.2d - amdgcn_image_sample_lz_o_2darray, // llvm.amdgcn.image.sample.lz.o.2darray - amdgcn_image_sample_lz_o_3d, // llvm.amdgcn.image.sample.lz.o.3d - amdgcn_image_sample_lz_o_cube, // llvm.amdgcn.image.sample.lz.o.cube - amdgcn_image_sample_o_1d, // llvm.amdgcn.image.sample.o.1d - amdgcn_image_sample_o_1darray, // llvm.amdgcn.image.sample.o.1darray - amdgcn_image_sample_o_2d, // llvm.amdgcn.image.sample.o.2d - amdgcn_image_sample_o_2darray, // llvm.amdgcn.image.sample.o.2darray - amdgcn_image_sample_o_3d, // llvm.amdgcn.image.sample.o.3d - amdgcn_image_sample_o_cube, // llvm.amdgcn.image.sample.o.cube - amdgcn_image_store_1d, // llvm.amdgcn.image.store.1d - amdgcn_image_store_1darray, // llvm.amdgcn.image.store.1darray - amdgcn_image_store_2d, // llvm.amdgcn.image.store.2d - amdgcn_image_store_2darray, // llvm.amdgcn.image.store.2darray - amdgcn_image_store_2darraymsaa, // llvm.amdgcn.image.store.2darraymsaa - amdgcn_image_store_2dmsaa, // llvm.amdgcn.image.store.2dmsaa - amdgcn_image_store_3d, // llvm.amdgcn.image.store.3d - amdgcn_image_store_cube, // llvm.amdgcn.image.store.cube - amdgcn_image_store_mip_1d, // llvm.amdgcn.image.store.mip.1d - amdgcn_image_store_mip_1darray, // llvm.amdgcn.image.store.mip.1darray - amdgcn_image_store_mip_2d, // llvm.amdgcn.image.store.mip.2d - amdgcn_image_store_mip_2darray, // llvm.amdgcn.image.store.mip.2darray - amdgcn_image_store_mip_3d, // llvm.amdgcn.image.store.mip.3d - amdgcn_image_store_mip_cube, // llvm.amdgcn.image.store.mip.cube - amdgcn_implicit_buffer_ptr, // llvm.amdgcn.implicit.buffer.ptr - amdgcn_implicitarg_ptr, // llvm.amdgcn.implicitarg.ptr - amdgcn_init_exec, // llvm.amdgcn.init.exec - amdgcn_init_exec_from_input, // llvm.amdgcn.init.exec.from.input - amdgcn_interp_mov, // llvm.amdgcn.interp.mov - amdgcn_interp_p1, // llvm.amdgcn.interp.p1 - amdgcn_interp_p1_f16, // llvm.amdgcn.interp.p1.f16 - amdgcn_interp_p2, // llvm.amdgcn.interp.p2 - amdgcn_interp_p2_f16, // llvm.amdgcn.interp.p2.f16 - amdgcn_is_private, // llvm.amdgcn.is.private - amdgcn_is_shared, // llvm.amdgcn.is.shared - amdgcn_kernarg_segment_ptr, // llvm.amdgcn.kernarg.segment.ptr - amdgcn_kill, // llvm.amdgcn.kill - amdgcn_ldexp, // llvm.amdgcn.ldexp - amdgcn_lerp, // llvm.amdgcn.lerp - amdgcn_live_mask, // llvm.amdgcn.live.mask - amdgcn_log_clamp, // llvm.amdgcn.log.clamp - amdgcn_loop, // llvm.amdgcn.loop - amdgcn_mbcnt_hi, // llvm.amdgcn.mbcnt.hi - amdgcn_mbcnt_lo, // llvm.amdgcn.mbcnt.lo - amdgcn_mfma_f32_16x16x16bf16_1k, // llvm.amdgcn.mfma.f32.16x16x16bf16.1k - amdgcn_mfma_f32_16x16x16f16, // llvm.amdgcn.mfma.f32.16x16x16f16 - amdgcn_mfma_f32_16x16x1f32, // llvm.amdgcn.mfma.f32.16x16x1f32 - amdgcn_mfma_f32_16x16x2bf16, // llvm.amdgcn.mfma.f32.16x16x2bf16 - amdgcn_mfma_f32_16x16x4bf16_1k, // llvm.amdgcn.mfma.f32.16x16x4bf16.1k - amdgcn_mfma_f32_16x16x4f16, // llvm.amdgcn.mfma.f32.16x16x4f16 - amdgcn_mfma_f32_16x16x4f32, // llvm.amdgcn.mfma.f32.16x16x4f32 - amdgcn_mfma_f32_16x16x8bf16, // llvm.amdgcn.mfma.f32.16x16x8bf16 - amdgcn_mfma_f32_32x32x1f32, // llvm.amdgcn.mfma.f32.32x32x1f32 - amdgcn_mfma_f32_32x32x2bf16, // llvm.amdgcn.mfma.f32.32x32x2bf16 - amdgcn_mfma_f32_32x32x2f32, // llvm.amdgcn.mfma.f32.32x32x2f32 - amdgcn_mfma_f32_32x32x4bf16, // llvm.amdgcn.mfma.f32.32x32x4bf16 - amdgcn_mfma_f32_32x32x4bf16_1k, // llvm.amdgcn.mfma.f32.32x32x4bf16.1k - amdgcn_mfma_f32_32x32x4f16, // llvm.amdgcn.mfma.f32.32x32x4f16 - amdgcn_mfma_f32_32x32x8bf16_1k, // llvm.amdgcn.mfma.f32.32x32x8bf16.1k - amdgcn_mfma_f32_32x32x8f16, // llvm.amdgcn.mfma.f32.32x32x8f16 - amdgcn_mfma_f32_4x4x1f32, // llvm.amdgcn.mfma.f32.4x4x1f32 - amdgcn_mfma_f32_4x4x2bf16, // llvm.amdgcn.mfma.f32.4x4x2bf16 - amdgcn_mfma_f32_4x4x4bf16_1k, // llvm.amdgcn.mfma.f32.4x4x4bf16.1k - amdgcn_mfma_f32_4x4x4f16, // llvm.amdgcn.mfma.f32.4x4x4f16 - amdgcn_mfma_f64_16x16x4f64, // llvm.amdgcn.mfma.f64.16x16x4f64 - amdgcn_mfma_f64_4x4x4f64, // llvm.amdgcn.mfma.f64.4x4x4f64 - amdgcn_mfma_i32_16x16x16i8, // llvm.amdgcn.mfma.i32.16x16x16i8 - amdgcn_mfma_i32_16x16x4i8, // llvm.amdgcn.mfma.i32.16x16x4i8 - amdgcn_mfma_i32_32x32x4i8, // llvm.amdgcn.mfma.i32.32x32x4i8 - amdgcn_mfma_i32_32x32x8i8, // llvm.amdgcn.mfma.i32.32x32x8i8 - amdgcn_mfma_i32_4x4x4i8, // llvm.amdgcn.mfma.i32.4x4x4i8 - amdgcn_mov_dpp, // llvm.amdgcn.mov.dpp - amdgcn_mov_dpp8, // llvm.amdgcn.mov.dpp8 - amdgcn_mqsad_pk_u16_u8, // llvm.amdgcn.mqsad.pk.u16.u8 - amdgcn_mqsad_u32_u8, // llvm.amdgcn.mqsad.u32.u8 - amdgcn_msad_u8, // llvm.amdgcn.msad.u8 - amdgcn_mul_i24, // llvm.amdgcn.mul.i24 - amdgcn_mul_u24, // llvm.amdgcn.mul.u24 - amdgcn_mulhi_i24, // llvm.amdgcn.mulhi.i24 - amdgcn_mulhi_u24, // llvm.amdgcn.mulhi.u24 - amdgcn_perm, // llvm.amdgcn.perm - amdgcn_permlane16, // llvm.amdgcn.permlane16 - amdgcn_permlanex16, // llvm.amdgcn.permlanex16 - amdgcn_ps_live, // llvm.amdgcn.ps.live - amdgcn_qsad_pk_u16_u8, // llvm.amdgcn.qsad.pk.u16.u8 - amdgcn_queue_ptr, // llvm.amdgcn.queue.ptr - amdgcn_raw_buffer_atomic_add, // llvm.amdgcn.raw.buffer.atomic.add - amdgcn_raw_buffer_atomic_and, // llvm.amdgcn.raw.buffer.atomic.and - amdgcn_raw_buffer_atomic_cmpswap, // llvm.amdgcn.raw.buffer.atomic.cmpswap - amdgcn_raw_buffer_atomic_dec, // llvm.amdgcn.raw.buffer.atomic.dec - amdgcn_raw_buffer_atomic_fadd, // llvm.amdgcn.raw.buffer.atomic.fadd - amdgcn_raw_buffer_atomic_fmax, // llvm.amdgcn.raw.buffer.atomic.fmax - amdgcn_raw_buffer_atomic_fmin, // llvm.amdgcn.raw.buffer.atomic.fmin - amdgcn_raw_buffer_atomic_inc, // llvm.amdgcn.raw.buffer.atomic.inc - amdgcn_raw_buffer_atomic_or, // llvm.amdgcn.raw.buffer.atomic.or - amdgcn_raw_buffer_atomic_smax, // llvm.amdgcn.raw.buffer.atomic.smax - amdgcn_raw_buffer_atomic_smin, // llvm.amdgcn.raw.buffer.atomic.smin - amdgcn_raw_buffer_atomic_sub, // llvm.amdgcn.raw.buffer.atomic.sub - amdgcn_raw_buffer_atomic_swap, // llvm.amdgcn.raw.buffer.atomic.swap - amdgcn_raw_buffer_atomic_umax, // llvm.amdgcn.raw.buffer.atomic.umax - amdgcn_raw_buffer_atomic_umin, // llvm.amdgcn.raw.buffer.atomic.umin - amdgcn_raw_buffer_atomic_xor, // llvm.amdgcn.raw.buffer.atomic.xor - amdgcn_raw_buffer_load, // llvm.amdgcn.raw.buffer.load - amdgcn_raw_buffer_load_format, // llvm.amdgcn.raw.buffer.load.format - amdgcn_raw_buffer_store, // llvm.amdgcn.raw.buffer.store - amdgcn_raw_buffer_store_format, // llvm.amdgcn.raw.buffer.store.format - amdgcn_raw_tbuffer_load, // llvm.amdgcn.raw.tbuffer.load - amdgcn_raw_tbuffer_store, // llvm.amdgcn.raw.tbuffer.store - amdgcn_rcp, // llvm.amdgcn.rcp - amdgcn_rcp_legacy, // llvm.amdgcn.rcp.legacy - amdgcn_readfirstlane, // llvm.amdgcn.readfirstlane - amdgcn_readlane, // llvm.amdgcn.readlane - amdgcn_reloc_constant, // llvm.amdgcn.reloc.constant - amdgcn_rsq, // llvm.amdgcn.rsq - amdgcn_rsq_clamp, // llvm.amdgcn.rsq.clamp - amdgcn_rsq_legacy, // llvm.amdgcn.rsq.legacy - amdgcn_s_barrier, // llvm.amdgcn.s.barrier - amdgcn_s_buffer_load, // llvm.amdgcn.s.buffer.load - amdgcn_s_dcache_inv, // llvm.amdgcn.s.dcache.inv - amdgcn_s_dcache_inv_vol, // llvm.amdgcn.s.dcache.inv.vol - amdgcn_s_dcache_wb, // llvm.amdgcn.s.dcache.wb - amdgcn_s_dcache_wb_vol, // llvm.amdgcn.s.dcache.wb.vol - amdgcn_s_decperflevel, // llvm.amdgcn.s.decperflevel - amdgcn_s_get_waveid_in_workgroup, // llvm.amdgcn.s.get.waveid.in.workgroup - amdgcn_s_getpc, // llvm.amdgcn.s.getpc - amdgcn_s_getreg, // llvm.amdgcn.s.getreg - amdgcn_s_incperflevel, // llvm.amdgcn.s.incperflevel - amdgcn_s_memrealtime, // llvm.amdgcn.s.memrealtime - amdgcn_s_memtime, // llvm.amdgcn.s.memtime - amdgcn_s_sendmsg, // llvm.amdgcn.s.sendmsg - amdgcn_s_sendmsghalt, // llvm.amdgcn.s.sendmsghalt - amdgcn_s_sethalt, // llvm.amdgcn.s.sethalt - amdgcn_s_setreg, // llvm.amdgcn.s.setreg - amdgcn_s_sleep, // llvm.amdgcn.s.sleep - amdgcn_s_waitcnt, // llvm.amdgcn.s.waitcnt - amdgcn_sad_hi_u8, // llvm.amdgcn.sad.hi.u8 - amdgcn_sad_u16, // llvm.amdgcn.sad.u16 - amdgcn_sad_u8, // llvm.amdgcn.sad.u8 - amdgcn_sbfe, // llvm.amdgcn.sbfe - amdgcn_sdot2, // llvm.amdgcn.sdot2 - amdgcn_sdot4, // llvm.amdgcn.sdot4 - amdgcn_sdot8, // llvm.amdgcn.sdot8 - amdgcn_set_inactive, // llvm.amdgcn.set.inactive - amdgcn_sffbh, // llvm.amdgcn.sffbh - amdgcn_sin, // llvm.amdgcn.sin - amdgcn_softwqm, // llvm.amdgcn.softwqm - amdgcn_sqrt, // llvm.amdgcn.sqrt - amdgcn_strict_wqm, // llvm.amdgcn.strict.wqm - amdgcn_strict_wwm, // llvm.amdgcn.strict.wwm - amdgcn_struct_buffer_atomic_add, // llvm.amdgcn.struct.buffer.atomic.add - amdgcn_struct_buffer_atomic_and, // llvm.amdgcn.struct.buffer.atomic.and - amdgcn_struct_buffer_atomic_cmpswap, // llvm.amdgcn.struct.buffer.atomic.cmpswap - amdgcn_struct_buffer_atomic_dec, // llvm.amdgcn.struct.buffer.atomic.dec - amdgcn_struct_buffer_atomic_fadd, // llvm.amdgcn.struct.buffer.atomic.fadd - amdgcn_struct_buffer_atomic_fmax, // llvm.amdgcn.struct.buffer.atomic.fmax - amdgcn_struct_buffer_atomic_fmin, // llvm.amdgcn.struct.buffer.atomic.fmin - amdgcn_struct_buffer_atomic_inc, // llvm.amdgcn.struct.buffer.atomic.inc - amdgcn_struct_buffer_atomic_or, // llvm.amdgcn.struct.buffer.atomic.or - amdgcn_struct_buffer_atomic_smax, // llvm.amdgcn.struct.buffer.atomic.smax - amdgcn_struct_buffer_atomic_smin, // llvm.amdgcn.struct.buffer.atomic.smin - amdgcn_struct_buffer_atomic_sub, // llvm.amdgcn.struct.buffer.atomic.sub - amdgcn_struct_buffer_atomic_swap, // llvm.amdgcn.struct.buffer.atomic.swap - amdgcn_struct_buffer_atomic_umax, // llvm.amdgcn.struct.buffer.atomic.umax - amdgcn_struct_buffer_atomic_umin, // llvm.amdgcn.struct.buffer.atomic.umin - amdgcn_struct_buffer_atomic_xor, // llvm.amdgcn.struct.buffer.atomic.xor - amdgcn_struct_buffer_load, // llvm.amdgcn.struct.buffer.load - amdgcn_struct_buffer_load_format, // llvm.amdgcn.struct.buffer.load.format - amdgcn_struct_buffer_store, // llvm.amdgcn.struct.buffer.store - amdgcn_struct_buffer_store_format, // llvm.amdgcn.struct.buffer.store.format - amdgcn_struct_tbuffer_load, // llvm.amdgcn.struct.tbuffer.load - amdgcn_struct_tbuffer_store, // llvm.amdgcn.struct.tbuffer.store - amdgcn_tbuffer_load, // llvm.amdgcn.tbuffer.load - amdgcn_tbuffer_store, // llvm.amdgcn.tbuffer.store - amdgcn_trig_preop, // llvm.amdgcn.trig.preop - amdgcn_ubfe, // llvm.amdgcn.ubfe - amdgcn_udot2, // llvm.amdgcn.udot2 - amdgcn_udot4, // llvm.amdgcn.udot4 - amdgcn_udot8, // llvm.amdgcn.udot8 - amdgcn_unreachable, // llvm.amdgcn.unreachable - amdgcn_update_dpp, // llvm.amdgcn.update.dpp - amdgcn_wave_barrier, // llvm.amdgcn.wave.barrier - amdgcn_wavefrontsize, // llvm.amdgcn.wavefrontsize - amdgcn_workgroup_id_x, // llvm.amdgcn.workgroup.id.x - amdgcn_workgroup_id_y, // llvm.amdgcn.workgroup.id.y - amdgcn_workgroup_id_z, // llvm.amdgcn.workgroup.id.z - amdgcn_workitem_id_x, // llvm.amdgcn.workitem.id.x - amdgcn_workitem_id_y, // llvm.amdgcn.workitem.id.y - amdgcn_workitem_id_z, // llvm.amdgcn.workitem.id.z - amdgcn_wqm, // llvm.amdgcn.wqm - amdgcn_wqm_demote, // llvm.amdgcn.wqm.demote - amdgcn_wqm_vote, // llvm.amdgcn.wqm.vote - amdgcn_writelane, // llvm.amdgcn.writelane - amdgcn_wwm, // llvm.amdgcn.wwm -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.td deleted file mode 100644 index e709c77ee5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsAMDGPU.td +++ /dev/null @@ -1,2020 +0,0 @@ -//===- IntrinsicsAMDGPU.td - Defines AMDGPU intrinsics -----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the R600-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -class AMDGPUReadPreloadRegisterIntrinsic - : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -class AMDGPUReadPreloadRegisterIntrinsicNamed - : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>, GCCBuiltin; - -// Used to tag image and resource intrinsics with information used to generate -// mem operands. -class AMDGPURsrcIntrinsic { - int RsrcArg = rsrcarg; - bit IsImage = isimage; -} - -let TargetPrefix = "r600" in { - -multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz { - def _x : AMDGPUReadPreloadRegisterIntrinsic; - def _y : AMDGPUReadPreloadRegisterIntrinsic; - def _z : AMDGPUReadPreloadRegisterIntrinsic; -} - -multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz_named { - def _x : AMDGPUReadPreloadRegisterIntrinsicNamed; - def _y : AMDGPUReadPreloadRegisterIntrinsicNamed; - def _z : AMDGPUReadPreloadRegisterIntrinsicNamed; -} - -defm int_r600_read_global_size : AMDGPUReadPreloadRegisterIntrinsic_xyz_named - <"__builtin_r600_read_global_size">; -defm int_r600_read_ngroups : AMDGPUReadPreloadRegisterIntrinsic_xyz_named - <"__builtin_r600_read_ngroups">; -defm int_r600_read_tgid : AMDGPUReadPreloadRegisterIntrinsic_xyz_named - <"__builtin_r600_read_tgid">; - -defm int_r600_read_local_size : AMDGPUReadPreloadRegisterIntrinsic_xyz; -defm int_r600_read_tidig : AMDGPUReadPreloadRegisterIntrinsic_xyz; - -def int_r600_group_barrier : GCCBuiltin<"__builtin_r600_group_barrier">, - Intrinsic<[], [], [IntrConvergent, IntrWillReturn]>; - -// AS 7 is PARAM_I_ADDRESS, used for kernel arguments -def int_r600_implicitarg_ptr : - GCCBuiltin<"__builtin_r600_implicitarg_ptr">, - Intrinsic<[LLVMQualPointerType], [], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_r600_rat_store_typed : - // 1st parameter: Data - // 2nd parameter: Index - // 3rd parameter: Constant RAT ID - Intrinsic<[], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrWillReturn]>, - GCCBuiltin<"__builtin_r600_rat_store_typed">; - -def int_r600_recipsqrt_ieee : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_r600_recipsqrt_clamped : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_r600_cube : Intrinsic< - [llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_r600_store_stream_output : Intrinsic< - [], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrWillReturn] ->; - -class TextureIntrinsicFloatInput : Intrinsic<[llvm_v4f32_ty], [ - llvm_v4f32_ty, // Coord - llvm_i32_ty, // offset_x - llvm_i32_ty, // offset_y, - llvm_i32_ty, // offset_z, - llvm_i32_ty, // resource_id - llvm_i32_ty, // samplerid - llvm_i32_ty, // coord_type_x - llvm_i32_ty, // coord_type_y - llvm_i32_ty, // coord_type_z - llvm_i32_ty], // coord_type_w - [IntrNoMem, IntrWillReturn] ->; - -class TextureIntrinsicInt32Input : Intrinsic<[llvm_v4i32_ty], [ - llvm_v4i32_ty, // Coord - llvm_i32_ty, // offset_x - llvm_i32_ty, // offset_y, - llvm_i32_ty, // offset_z, - llvm_i32_ty, // resource_id - llvm_i32_ty, // samplerid - llvm_i32_ty, // coord_type_x - llvm_i32_ty, // coord_type_y - llvm_i32_ty, // coord_type_z - llvm_i32_ty], // coord_type_w - [IntrNoMem, IntrWillReturn] ->; - -def int_r600_store_swizzle : - Intrinsic<[], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], [IntrWillReturn] ->; - -def int_r600_tex : TextureIntrinsicFloatInput; -def int_r600_texc : TextureIntrinsicFloatInput; -def int_r600_txl : TextureIntrinsicFloatInput; -def int_r600_txlc : TextureIntrinsicFloatInput; -def int_r600_txb : TextureIntrinsicFloatInput; -def int_r600_txbc : TextureIntrinsicFloatInput; -def int_r600_txf : TextureIntrinsicInt32Input; -def int_r600_txq : TextureIntrinsicInt32Input; -def int_r600_ddx : TextureIntrinsicFloatInput; -def int_r600_ddy : TextureIntrinsicFloatInput; - -def int_r600_dot4 : Intrinsic<[llvm_float_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_r600_kill : Intrinsic<[], [llvm_float_ty], [IntrWillReturn]>; - -} // End TargetPrefix = "r600" - -let TargetPrefix = "amdgcn" in { - -//===----------------------------------------------------------------------===// -// ABI Special Intrinsics -//===----------------------------------------------------------------------===// - -defm int_amdgcn_workitem_id : AMDGPUReadPreloadRegisterIntrinsic_xyz; -defm int_amdgcn_workgroup_id : AMDGPUReadPreloadRegisterIntrinsic_xyz_named - <"__builtin_amdgcn_workgroup_id">; - -def int_amdgcn_dispatch_ptr : - Intrinsic<[LLVMQualPointerType], [], - [Align, IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_queue_ptr : - GCCBuiltin<"__builtin_amdgcn_queue_ptr">, - Intrinsic<[LLVMQualPointerType], [], - [Align, IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_kernarg_segment_ptr : - GCCBuiltin<"__builtin_amdgcn_kernarg_segment_ptr">, - Intrinsic<[LLVMQualPointerType], [], - [Align, IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_implicitarg_ptr : - GCCBuiltin<"__builtin_amdgcn_implicitarg_ptr">, - Intrinsic<[LLVMQualPointerType], [], - [Align, IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_groupstaticsize : - GCCBuiltin<"__builtin_amdgcn_groupstaticsize">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_dispatch_id : - GCCBuiltin<"__builtin_amdgcn_dispatch_id">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_implicit_buffer_ptr : - GCCBuiltin<"__builtin_amdgcn_implicit_buffer_ptr">, - Intrinsic<[LLVMQualPointerType], [], - [Align, IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -// Set EXEC to the 64-bit value given. -// This is always moved to the beginning of the basic block. -// FIXME: Should be mangled for wave size. -def int_amdgcn_init_exec : Intrinsic<[], - [llvm_i64_ty], // 64-bit literal constant - [IntrConvergent, ImmArg>]>; - -// Set EXEC according to a thread count packed in an SGPR input: -// thread_count = (input >> bitoffset) & 0x7f; -// This is always moved to the beginning of the basic block. -// Note: only inreg arguments to the parent function are valid as -// inputs to this intrinsic, computed values cannot be used. -def int_amdgcn_init_exec_from_input : Intrinsic<[], - [llvm_i32_ty, // 32-bit SGPR input - llvm_i32_ty], // bit offset of the thread count - [IntrConvergent, ImmArg>]>; - -def int_amdgcn_wavefrontsize : - GCCBuiltin<"__builtin_amdgcn_wavefrontsize">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - - -//===----------------------------------------------------------------------===// -// Instruction Intrinsics -//===----------------------------------------------------------------------===// - -// The first parameter is s_sendmsg immediate (i16), -// the second one is copied to m0 -def int_amdgcn_s_sendmsg : GCCBuiltin<"__builtin_amdgcn_s_sendmsg">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], - [ImmArg>, IntrNoMem, IntrHasSideEffects]>; -def int_amdgcn_s_sendmsghalt : GCCBuiltin<"__builtin_amdgcn_s_sendmsghalt">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], - [ImmArg>, IntrNoMem, IntrHasSideEffects]>; - -def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrConvergent, IntrWillReturn]>; - -def int_amdgcn_wave_barrier : GCCBuiltin<"__builtin_amdgcn_wave_barrier">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrConvergent, IntrWillReturn]>; - -def int_amdgcn_s_waitcnt : GCCBuiltin<"__builtin_amdgcn_s_waitcnt">, - Intrinsic<[], [llvm_i32_ty], [ImmArg>, IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_div_scale : Intrinsic< - // 1st parameter: Numerator - // 2nd parameter: Denominator - // 3rd parameter: Select quotient. Must equal Numerator or Denominator. - // (0 = Denominator, 1 = Numerator). - [llvm_anyfloat_ty, llvm_i1_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable, ImmArg>, IntrWillReturn] ->; - -def int_amdgcn_div_fmas : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_div_fixup : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// Look Up 2.0 / pi src0 with segment select src1[4:0] -def int_amdgcn_trig_preop : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sin : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cos : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_log_clamp : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_fmul_legacy : GCCBuiltin<"__builtin_amdgcn_fmul_legacy">, - Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; - -// Fused single-precision multiply-add with legacy behaviour for the multiply, -// which is that +/- 0.0 * anything (even NaN or infinity) is +0.0. This is -// intended for use on subtargets that have the v_fma_legacy_f32 and/or -// v_fmac_legacy_f32 instructions. (Note that v_fma_legacy_f16 is unrelated and -// has a completely different kind of legacy behaviour.) -def int_amdgcn_fma_legacy : - Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] ->; - -def int_amdgcn_rcp : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_rcp_legacy : GCCBuiltin<"__builtin_amdgcn_rcp_legacy">, - Intrinsic<[llvm_float_ty], [llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sqrt : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_rsq : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_rsq_legacy : GCCBuiltin<"__builtin_amdgcn_rsq_legacy">, - Intrinsic< - [llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// out = 1.0 / sqrt(a) result clamped to +/- max_float. -def int_amdgcn_rsq_clamp : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -def int_amdgcn_ldexp : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_frexp_mant : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_frexp_exp : Intrinsic< - [llvm_anyint_ty], [llvm_anyfloat_ty], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// v_fract is buggy on SI/CI. It mishandles infinities, may return 1.0 -// and always uses rtz, so is not suitable for implementing the OpenCL -// fract function. It should be ok on VI. -def int_amdgcn_fract : Intrinsic< - [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pkrtz : GCCBuiltin<"__builtin_amdgcn_cvt_pkrtz">, - Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pknorm_i16 : - GCCBuiltin<"__builtin_amdgcn_cvt_pknorm_i16">, - Intrinsic<[llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pknorm_u16 : - GCCBuiltin<"__builtin_amdgcn_cvt_pknorm_u16">, - Intrinsic<[llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pk_i16 : - GCCBuiltin<"__builtin_amdgcn_cvt_pk_i16">, - Intrinsic< - [llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pk_u16 : GCCBuiltin<"__builtin_amdgcn_cvt_pk_u16">, - Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_class : Intrinsic< - [llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_fmed3 : GCCBuiltin<"__builtin_amdgcn_fmed3">, - Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cubeid : GCCBuiltin<"__builtin_amdgcn_cubeid">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cubema : GCCBuiltin<"__builtin_amdgcn_cubema">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cubesc : GCCBuiltin<"__builtin_amdgcn_cubesc">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cubetc : GCCBuiltin<"__builtin_amdgcn_cubetc">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// v_ffbh_i32, as opposed to v_ffbh_u32. For v_ffbh_u32, llvm.ctlz -// should be used. -def int_amdgcn_sffbh : - Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// v_mad_f32|f16/v_mac_f32|f16, selected regardless of denorm support. -def int_amdgcn_fmad_ftz : - Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// Fields should mirror atomicrmw -class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty], - [llvm_anyptr_ty, - LLVMMatchType<0>, - llvm_i32_ty, // ordering - llvm_i32_ty, // scope - llvm_i1_ty], // isVolatile - [IntrArgMemOnly, IntrWillReturn, NoCapture>, - ImmArg>, ImmArg>, ImmArg>], "", - [SDNPMemOperand] ->; - -def int_amdgcn_atomic_inc : AMDGPUAtomicIncIntrin; -def int_amdgcn_atomic_dec : AMDGPUAtomicIncIntrin; - -class AMDGPULDSIntrin : - Intrinsic<[llvm_any_ty], - [LLVMQualPointerType, 3>, - LLVMMatchType<0>, - llvm_i32_ty, // ordering - llvm_i32_ty, // scope - llvm_i1_ty], // isVolatile - [IntrArgMemOnly, IntrWillReturn, NoCapture>, - ImmArg>, ImmArg>, ImmArg>] ->; - -// FIXME: The m0 argument should be moved after the normal arguments -class AMDGPUDSOrderedIntrinsic : Intrinsic< - [llvm_i32_ty], - // M0 = {hi16:address, lo16:waveID}. Allow passing M0 as a pointer, so that - // the bit packing can be optimized at the IR level. - [LLVMQualPointerType, // IntToPtr(M0) - llvm_i32_ty, // value to add or swap - llvm_i32_ty, // ordering - llvm_i32_ty, // scope - llvm_i1_ty, // isVolatile - llvm_i32_ty, // ordered count index (OA index), also added to the address - // gfx10: bits 24-27 indicate the number of active threads/dwords - llvm_i1_ty, // wave release, usually set to 1 - llvm_i1_ty], // wave done, set to 1 for the last ordered instruction - [IntrWillReturn, NoCapture>, - ImmArg>, ImmArg>, ImmArg>, - ImmArg>, ImmArg>, ImmArg> - ] ->; - -class AMDGPUDSAppendConsumedIntrinsic : Intrinsic< - [llvm_i32_ty], - [llvm_anyptr_ty, // LDS or GDS ptr - llvm_i1_ty], // isVolatile - [IntrConvergent, IntrWillReturn, IntrArgMemOnly, - NoCapture>, ImmArg>], - "", - [SDNPMemOperand] ->; - -def int_amdgcn_ds_ordered_add : AMDGPUDSOrderedIntrinsic; -def int_amdgcn_ds_ordered_swap : AMDGPUDSOrderedIntrinsic; - -// The pointer argument is assumed to be dynamically uniform if a VGPR. -def int_amdgcn_ds_append : AMDGPUDSAppendConsumedIntrinsic; -def int_amdgcn_ds_consume : AMDGPUDSAppendConsumedIntrinsic; - -def int_amdgcn_ds_fadd : AMDGPULDSIntrin; -def int_amdgcn_ds_fmin : AMDGPULDSIntrin; -def int_amdgcn_ds_fmax : AMDGPULDSIntrin; - -} // TargetPrefix = "amdgcn" - -// New-style image intrinsics - -////////////////////////////////////////////////////////////////////////// -// Dimension-aware image intrinsics framework -////////////////////////////////////////////////////////////////////////// - -// Helper class to represent (type, name) combinations of arguments. The -// argument names are explanatory and used as DAG operand names for codegen -// pattern matching. -class AMDGPUArg { - LLVMType Type = ty; - string Name = name; -} - -// Return [AMDGPUArg, AMDGPUArg, names[1]>, ...] -class makeArgList names, LLVMType basety> { - list ret = - !listconcat([AMDGPUArg], - !foreach(name, !tail(names), AMDGPUArg, name>)); -} - -// Return arglist, with LLVMMatchType's references shifted by 'shift'. -class arglistmatchshift arglist, int shift> { - list ret = - !foreach(arg, arglist, - !if(!isa(arg.Type), - AMDGPUArg(arg.Type).Number, shift)>, - arg.Name>, - arg)); -} - -// Return the concatenation of the given arglists. LLVMMatchType's are adjusted -// accordingly, and shifted by an additional 'shift'. -class arglistconcat> arglists, int shift = 0> { - list ret = - !foldl([], arglists, lhs, rhs, - !listconcat( - lhs, - arglistmatchshift.ret)); -} - -// Represent texture/image types / dimensionality. -class AMDGPUDimProps enc, string name, string asmsuffix, - list coord_names, list slice_names, - bit msaa = 0> { - AMDGPUDimProps Dim = !cast(NAME); - string Name = name; // e.g. "2darraymsaa" - string AsmSuffix = asmsuffix; // e.g. 2D_MSAA_ARRAY (used in assembly strings) - bits<3> Encoding = enc; - bit DA = 0; // DA bit in MIMG encoding - bit MSAA = msaa; - - list CoordSliceArgs = - makeArgList.ret; - list CoordSliceIntArgs = - makeArgList.ret; - list GradientArgs = - makeArgList.ret; - - bits<8> NumCoords = !size(CoordSliceArgs); - bits<8> NumGradients = !size(GradientArgs); -} - -def AMDGPUDim1D : AMDGPUDimProps<0x0, "1d", "1D", ["s"], []>; -def AMDGPUDim2D : AMDGPUDimProps<0x1, "2d", "2D", ["s", "t"], []>; -def AMDGPUDim3D : AMDGPUDimProps<0x2, "3d", "3D", ["s", "t", "r"], []>; -let DA = 1 in { - def AMDGPUDimCube : AMDGPUDimProps<0x3, "cube", "CUBE", ["s", "t"], ["face"]>; - def AMDGPUDim1DArray : AMDGPUDimProps<0x4, "1darray", "1D_ARRAY", ["s"], ["slice"]>; - def AMDGPUDim2DArray : AMDGPUDimProps<0x5, "2darray", "2D_ARRAY", ["s", "t"], ["slice"]>; -} -def AMDGPUDim2DMsaa : AMDGPUDimProps<0x6, "2dmsaa", "2D_MSAA", ["s", "t"], ["fragid"], 1>; -let DA = 1 in { - def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<0x7, "2darraymsaa", "2D_MSAA_ARRAY", ["s", "t"], ["slice", "fragid"], 1>; -} - -def AMDGPUDims { - list NoMsaa = [AMDGPUDim1D, AMDGPUDim2D, AMDGPUDim3D, - AMDGPUDimCube, AMDGPUDim1DArray, - AMDGPUDim2DArray]; - list Msaa = [AMDGPUDim2DMsaa, AMDGPUDim2DArrayMsaa]; - list All = !listconcat(NoMsaa, Msaa); -} - -// Represent sample variants, i.e. _C, _O, _B, ... and combinations thereof. -class AMDGPUSampleVariant extra_addr> { - string UpperCaseMod = ucmod; - string LowerCaseMod = lcmod; - - // {offset} {bias} {z-compare} - list ExtraAddrArgs = extra_addr; - bit Offset = false; - bit Bias = false; - bit ZCompare = false; - bit Gradients = false; - - // Name of the {lod} or {clamp} argument that is appended to the coordinates, - // if any. - string LodOrClamp = ""; -} - -// AMDGPUSampleVariants: all variants supported by IMAGE_SAMPLE -// AMDGPUSampleVariantsNoGradients: variants supported by IMAGE_GATHER4 -defset list AMDGPUSampleVariants = { - multiclass AMDGPUSampleHelper_Offset extra_addr> { - def NAME#lcmod : AMDGPUSampleVariant; - let Offset = true in - def NAME#lcmod#_o : AMDGPUSampleVariant< - ucmod#"_O", lcmod#"_o", !listconcat([AMDGPUArg], extra_addr)>; - } - - multiclass AMDGPUSampleHelper_Compare extra_addr> { - defm NAME : AMDGPUSampleHelper_Offset; - let ZCompare = true in - defm NAME : AMDGPUSampleHelper_Offset< - "_C"#ucmod, "_c"#lcmod, !listconcat(extra_addr, [AMDGPUArg])>; - } - - multiclass AMDGPUSampleHelper_Clamp extra_addr> { - defm NAME : AMDGPUSampleHelper_Compare; - let LodOrClamp = "clamp" in - defm NAME : AMDGPUSampleHelper_Compare; - } - - defset list AMDGPUSampleVariantsNoGradients = { - defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"", "", []>; - let Bias = true in - defm AMDGPUSample : AMDGPUSampleHelper_Clamp< - "_B", "_b", [AMDGPUArg]>; - let LodOrClamp = "lod" in - defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_L", "_l", []>; - defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_LZ", "_lz", []>; - } - - let Gradients = true in { - defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_D", "_d", []>; - defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_CD", "_cd", []>; - } -} - -// Helper class to capture the profile of a dimension-aware image intrinsic. -// This information is used to generate the intrinsic's type and to inform -// codegen pattern matching. -class AMDGPUDimProfile { - AMDGPUDimProps Dim = dim; - string OpMod = opmod; // the corresponding instruction is named IMAGE_OpMod - - // These are intended to be overwritten by subclasses - bit IsSample = false; - bit IsAtomic = false; - list RetTypes = []; - list DataArgs = []; - list ExtraAddrArgs = []; - bit Offset = false; - bit Bias = false; - bit ZCompare = false; - bit Gradients = false; - string LodClampMip = ""; - - int NumRetAndDataAnyTypes = - !foldl(0, !listconcat(RetTypes, !foreach(arg, DataArgs, arg.Type)), a, b, - !add(a, b.isAny)); - - list AddrArgs = - arglistconcat<[ExtraAddrArgs, - !if(Gradients, dim.GradientArgs, []), - !listconcat(!if(IsSample, dim.CoordSliceArgs, dim.CoordSliceIntArgs), - !if(!empty(LodClampMip), - [], - [AMDGPUArg, LodClampMip>]))], - NumRetAndDataAnyTypes>.ret; - list AddrTypes = !foreach(arg, AddrArgs, arg.Type); - list AddrDefaultArgs = - !foreach(arg, AddrArgs, - AMDGPUArg(arg.Type)), - !if(IsSample, llvm_float_ty, llvm_i32_ty), arg.Type), - arg.Name>); - list AddrA16Args = - !foreach(arg, AddrArgs, - AMDGPUArg(arg.Type)), - !if(IsSample, llvm_half_ty, llvm_i16_ty), arg.Type), - arg.Name>); -} - -class AMDGPUDimProfileCopy : AMDGPUDimProfile { - let IsSample = base.IsSample; - let IsAtomic = base.IsAtomic; - let RetTypes = base.RetTypes; - let DataArgs = base.DataArgs; - let ExtraAddrArgs = base.ExtraAddrArgs; - let Offset = base.Offset; - let Bias = base.Bias; - let ZCompare = base.ZCompare; - let Gradients = base.Gradients; - let LodClampMip = base.LodClampMip; -} - -class AMDGPUDimSampleProfile : AMDGPUDimProfile { - let IsSample = true; - let RetTypes = [llvm_any_ty]; - let ExtraAddrArgs = sample.ExtraAddrArgs; - let Offset = sample.Offset; - let Bias = sample.Bias; - let ZCompare = sample.ZCompare; - let Gradients = sample.Gradients; - let LodClampMip = sample.LodOrClamp; -} - -class AMDGPUDimNoSampleProfile retty, - list dataargs, - bit Mip = false> : AMDGPUDimProfile { - let RetTypes = retty; - let DataArgs = dataargs; - let LodClampMip = !if(Mip, "mip", ""); -} - -class AMDGPUDimAtomicProfile dataargs> : AMDGPUDimProfile { - let RetTypes = [llvm_anyint_ty]; - let DataArgs = dataargs; - let IsAtomic = true; -} - -class AMDGPUDimAtomicFloatProfile dataargs> - : AMDGPUDimAtomicProfile { - let RetTypes = [llvm_anyfloat_ty]; -} - -class AMDGPUDimGetResInfoProfile - : AMDGPUDimProfile<"GET_RESINFO", dim> { - let RetTypes = [llvm_anyfloat_ty]; - let DataArgs = []; - let AddrArgs = [AMDGPUArg]; - let LodClampMip = "mip"; -} - -// Helper class for figuring out image intrinsic argument indexes. -class AMDGPUImageDimIntrinsicEval { - int NumDataArgs = !size(P_.DataArgs); - int NumDmaskArgs = !not(P_.IsAtomic); - int NumOffsetArgs = !if(P_.Offset, 1, 0); - int NumBiasArgs = !if(P_.Bias, 1, 0); - int NumZCompareArgs = !if(P_.ZCompare, 1, 0); - int NumExtraAddrArgs = !add(NumOffsetArgs, NumBiasArgs, NumZCompareArgs); - int NumVAddrArgs = !size(P_.AddrArgs); - int NumGradientArgs = !if(P_.Gradients, !size(P_.Dim.GradientArgs), 0); - int NumCoordArgs = !if(P_.IsSample, !size(P_.Dim.CoordSliceArgs), !size(P_.Dim.CoordSliceIntArgs)); - int NumRSrcArgs = 1; - int NumSampArgs = !if(P_.IsSample, 2, 0); - int DmaskArgIndex = NumDataArgs; - int VAddrArgIndex = !add(DmaskArgIndex, NumDmaskArgs); - int OffsetArgIndex = VAddrArgIndex; - int BiasArgIndex = !add(VAddrArgIndex, NumOffsetArgs); - int ZCompareArgIndex = !add(BiasArgIndex, NumBiasArgs); - int GradientArgIndex = !add(VAddrArgIndex, NumExtraAddrArgs); - int CoordArgIndex = !add(GradientArgIndex, NumGradientArgs); - int LodArgIndex = !add(VAddrArgIndex, NumVAddrArgs, -1); - int MipArgIndex = LodArgIndex; - int RsrcArgIndex = !add(VAddrArgIndex, NumVAddrArgs); - int SampArgIndex = !add(RsrcArgIndex, NumRSrcArgs); - int UnormArgIndex = !add(SampArgIndex, 1); - int TexFailCtrlArgIndex = !add(SampArgIndex, NumSampArgs); - int CachePolicyArgIndex = !add(TexFailCtrlArgIndex, 1); -} - -// All dimension-aware intrinsics are derived from this class. -class AMDGPUImageDimIntrinsic props, - list sdnodeprops> : Intrinsic< - P_.RetTypes, // vdata(VGPR) -- for load/atomic-with-return - !listconcat( - !foreach(arg, P_.DataArgs, arg.Type), // vdata(VGPR) -- for store/atomic - !if(P_.IsAtomic, [], [llvm_i32_ty]), // dmask(imm) - P_.AddrTypes, // vaddr(VGPR) - [llvm_v8i32_ty], // rsrc(SGPR) - !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR) - llvm_i1_ty], []), // unorm(imm) - [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe) - llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc) - - !listconcat(props, - !if(P_.IsAtomic, [], [ImmArg.DmaskArgIndex>>]), - !if(P_.IsSample, [ImmArg.UnormArgIndex>>], []), - [IntrWillReturn], - [ImmArg.TexFailCtrlArgIndex>>, - ImmArg.CachePolicyArgIndex>>]), - - - "", sdnodeprops>, - AMDGPURsrcIntrinsic { - AMDGPUDimProfile P = P_; - - AMDGPUImageDimIntrinsic Intr = !cast(NAME); - - let TargetPrefix = "amdgcn"; -} - -// Marker class for intrinsics with a DMask that determines the returned -// channels. -class AMDGPUImageDMaskIntrinsic; - -defset list AMDGPUImageDimIntrinsics = { - - ////////////////////////////////////////////////////////////////////////// - // Load and store intrinsics - ////////////////////////////////////////////////////////////////////////// - multiclass AMDGPUImageDimIntrinsicsNoMsaa retty, - list dataargs, - list props, - list sdnodeprops, - bit Mip = false> { - foreach dim = AMDGPUDims.NoMsaa in { - def !strconcat(NAME, "_", dim.Name) - : AMDGPUImageDimIntrinsic< - AMDGPUDimNoSampleProfile, - props, sdnodeprops>; - } - } - - multiclass AMDGPUImageDimIntrinsicsAll retty, - list dataargs, - list props, - list sdnodeprops, - bit Mip = false> { - foreach dim = AMDGPUDims.All in { - def !strconcat(NAME, "_", dim.Name) - : AMDGPUImageDimIntrinsic< - AMDGPUDimNoSampleProfile, - props, sdnodeprops>; - } - } - - defm int_amdgcn_image_load - : AMDGPUImageDimIntrinsicsAll<"LOAD", [llvm_any_ty], [], [IntrReadMem], - [SDNPMemOperand]>, - AMDGPUImageDMaskIntrinsic; - defm int_amdgcn_image_load_mip - : AMDGPUImageDimIntrinsicsNoMsaa<"LOAD_MIP", [llvm_any_ty], [], - [IntrReadMem, IntrWillReturn], [SDNPMemOperand], 1>, - AMDGPUImageDMaskIntrinsic; - - defm int_amdgcn_image_store : AMDGPUImageDimIntrinsicsAll< - "STORE", [], [AMDGPUArg], - [IntrWriteMem, IntrWillReturn], [SDNPMemOperand]>; - defm int_amdgcn_image_store_mip : AMDGPUImageDimIntrinsicsNoMsaa< - "STORE_MIP", [], [AMDGPUArg], - [IntrWriteMem, IntrWillReturn], [SDNPMemOperand], 1>; - - ////////////////////////////////////////////////////////////////////////// - // MSAA intrinsics - ////////////////////////////////////////////////////////////////////////// - foreach dim = AMDGPUDims.Msaa in { - def int_amdgcn_image_msaa_load_x # _ # dim.Name: - AMDGPUImageDimIntrinsic< - AMDGPUDimNoSampleProfile<"MSAA_LOAD_X", dim, [llvm_any_ty], []>, - [IntrReadMem], [SDNPMemOperand]>; - } - - ////////////////////////////////////////////////////////////////////////// - // sample and getlod intrinsics - ////////////////////////////////////////////////////////////////////////// - multiclass AMDGPUImageDimSampleDims { - foreach dim = AMDGPUDims.NoMsaa in { - def !strconcat(NAME, "_", dim.Name) : AMDGPUImageDimIntrinsic< - AMDGPUDimSampleProfile, - !if(NoMem, [IntrNoMem], [IntrReadMem]), - !if(NoMem, [], [SDNPMemOperand])>; - } - } - - foreach sample = AMDGPUSampleVariants in { - defm int_amdgcn_image_sample # sample.LowerCaseMod - : AMDGPUImageDimSampleDims<"SAMPLE" # sample.UpperCaseMod, sample>, - AMDGPUImageDMaskIntrinsic; - } - - defm int_amdgcn_image_getlod - : AMDGPUImageDimSampleDims<"GET_LOD", AMDGPUSample, 1>, - AMDGPUImageDMaskIntrinsic; - - ////////////////////////////////////////////////////////////////////////// - // getresinfo intrinsics - ////////////////////////////////////////////////////////////////////////// - foreach dim = AMDGPUDims.All in { - def !strconcat("int_amdgcn_image_getresinfo_", dim.Name) - : AMDGPUImageDimIntrinsic, [IntrNoMem], []>, - AMDGPUImageDMaskIntrinsic; - } - - ////////////////////////////////////////////////////////////////////////// - // gather4 intrinsics - ////////////////////////////////////////////////////////////////////////// - foreach sample = AMDGPUSampleVariantsNoGradients in { - foreach dim = [AMDGPUDim2D, AMDGPUDimCube, AMDGPUDim2DArray] in { - def int_amdgcn_image_gather4 # sample.LowerCaseMod # _ # dim.Name: - AMDGPUImageDimIntrinsic< - AMDGPUDimSampleProfile<"GATHER4" # sample.UpperCaseMod, dim, sample>, - [IntrReadMem], [SDNPMemOperand]>; - } - } -} - -////////////////////////////////////////////////////////////////////////// -// atomic intrinsics -////////////////////////////////////////////////////////////////////////// -defset list AMDGPUImageDimAtomicIntrinsics = { - multiclass AMDGPUImageDimAtomicX dataargs, - int isFloat = 0> { - foreach dim = AMDGPUDims.All in { - def !strconcat(NAME, "_", dim.Name): AMDGPUImageDimIntrinsic< - !if (isFloat, AMDGPUDimAtomicFloatProfile, - AMDGPUDimAtomicProfile), - [], [SDNPMemOperand]>; - } - } - - multiclass AMDGPUImageDimAtomic { - defm "" - : AMDGPUImageDimAtomicX, "vdata">], - isFloat>; - } - - multiclass AMDGPUImageDimFloatAtomic { - defm "" : AMDGPUImageDimAtomic; - } - - defm int_amdgcn_image_atomic_swap : AMDGPUImageDimAtomic<"ATOMIC_SWAP">; - defm int_amdgcn_image_atomic_add : AMDGPUImageDimAtomic<"ATOMIC_ADD">; - defm int_amdgcn_image_atomic_sub : AMDGPUImageDimAtomic<"ATOMIC_SUB">; - defm int_amdgcn_image_atomic_smin : AMDGPUImageDimAtomic<"ATOMIC_SMIN">; - defm int_amdgcn_image_atomic_umin : AMDGPUImageDimAtomic<"ATOMIC_UMIN">; - defm int_amdgcn_image_atomic_fmin : AMDGPUImageDimFloatAtomic<"ATOMIC_FMIN">; - defm int_amdgcn_image_atomic_smax : AMDGPUImageDimAtomic<"ATOMIC_SMAX">; - defm int_amdgcn_image_atomic_umax : AMDGPUImageDimAtomic<"ATOMIC_UMAX">; - defm int_amdgcn_image_atomic_fmax : AMDGPUImageDimFloatAtomic<"ATOMIC_FMAX">; - defm int_amdgcn_image_atomic_and : AMDGPUImageDimAtomic<"ATOMIC_AND">; - defm int_amdgcn_image_atomic_or : AMDGPUImageDimAtomic<"ATOMIC_OR">; - defm int_amdgcn_image_atomic_xor : AMDGPUImageDimAtomic<"ATOMIC_XOR">; - defm int_amdgcn_image_atomic_inc : AMDGPUImageDimAtomic<"ATOMIC_INC">; - defm int_amdgcn_image_atomic_dec : AMDGPUImageDimAtomic<"ATOMIC_DEC">; - - defm int_amdgcn_image_atomic_cmpswap : - AMDGPUImageDimAtomicX<"ATOMIC_CMPSWAP", [AMDGPUArg, "src">, - AMDGPUArg, "cmp">]>; -} - -////////////////////////////////////////////////////////////////////////// -// Buffer intrinsics -////////////////////////////////////////////////////////////////////////// - -let TargetPrefix = "amdgcn" in { - -defset list AMDGPUBufferIntrinsics = { - -class AMDGPUBufferLoad : Intrinsic < - [data_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(SGPR/VGPR/imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty], // slc(imm) - [IntrReadMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; -def int_amdgcn_buffer_load_format : AMDGPUBufferLoad; -def int_amdgcn_buffer_load : AMDGPUBufferLoad; - -def int_amdgcn_s_buffer_load : Intrinsic < - [llvm_any_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // byte offset(SGPR/imm) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 2 = dlc) - [IntrNoMem, IntrWillReturn, ImmArg>]>, - AMDGPURsrcIntrinsic<0>; - -class AMDGPUBufferStore : Intrinsic < - [], - [data_ty, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(SGPR/VGPR/imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty], // slc(imm) - [IntrWriteMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; -def int_amdgcn_buffer_store_format : AMDGPUBufferStore; -def int_amdgcn_buffer_store : AMDGPUBufferStore; - -// New buffer intrinsics with separate raw and struct variants. The raw -// variant never has an index. The struct variant always has an index, even if -// it is const 0. A struct intrinsic with constant 0 index is different to the -// corresponding raw intrinsic on gfx9+ because the behavior of bound checking -// and swizzling changes depending on whether idxen is set in the instruction. -// These new intrinsics also keep the offset and soffset arguments separate as -// they behave differently in bounds checking and swizzling. -class AMDGPURawBufferLoad : Intrinsic < - [data_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrReadMem, IntrWillReturn, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; -def int_amdgcn_raw_buffer_load_format : AMDGPURawBufferLoad; -def int_amdgcn_raw_buffer_load : AMDGPURawBufferLoad; - -class AMDGPUStructBufferLoad : Intrinsic < - [data_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrReadMem, IntrWillReturn, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; -def int_amdgcn_struct_buffer_load_format : AMDGPUStructBufferLoad; -def int_amdgcn_struct_buffer_load : AMDGPUStructBufferLoad; - -class AMDGPURawBufferStore : Intrinsic < - [], - [data_ty, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrWriteMem, IntrWillReturn, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; -def int_amdgcn_raw_buffer_store_format : AMDGPURawBufferStore; -def int_amdgcn_raw_buffer_store : AMDGPURawBufferStore; - -class AMDGPUStructBufferStore : Intrinsic < - [], - [data_ty, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrWriteMem, IntrWillReturn, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; -def int_amdgcn_struct_buffer_store_format : AMDGPUStructBufferStore; -def int_amdgcn_struct_buffer_store : AMDGPUStructBufferStore; - -class AMDGPURawBufferAtomic : Intrinsic < - !if(NoRtn, [], [data_ty]), - [!if(NoRtn, data_ty, LLVMMatchType<0>), // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1, 0>; -def int_amdgcn_raw_buffer_atomic_swap : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_add : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_sub : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_smin : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_umin : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_fmin : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_smax : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_umax : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_fmax : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_and : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_or : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_xor : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_inc : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_dec : AMDGPURawBufferAtomic; -def int_amdgcn_raw_buffer_atomic_cmpswap : Intrinsic< - [llvm_anyint_ty], - [LLVMMatchType<0>, // src(VGPR) - LLVMMatchType<0>, // cmp(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<2, 0>; - -// gfx908 intrinsic -def int_amdgcn_raw_buffer_atomic_fadd : AMDGPURawBufferAtomic; - -class AMDGPUStructBufferAtomic : Intrinsic < - !if(NoRtn, [], [data_ty]), - [!if(NoRtn, data_ty, LLVMMatchType<0>), // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1, 0>; -def int_amdgcn_struct_buffer_atomic_swap : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_add : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_sub : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_smin : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_umin : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_smax : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_umax : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_and : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_or : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_xor : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_inc : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_dec : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_cmpswap : Intrinsic< - [llvm_anyint_ty], - [LLVMMatchType<0>, // src(VGPR) - LLVMMatchType<0>, // cmp(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<2, 0>; - -// gfx908 intrinsic -def int_amdgcn_struct_buffer_atomic_fadd : AMDGPUStructBufferAtomic; - -// gfx90a intrinsics -def int_amdgcn_struct_buffer_atomic_fmin : AMDGPUStructBufferAtomic; -def int_amdgcn_struct_buffer_atomic_fmax : AMDGPUStructBufferAtomic; - - -// Obsolescent tbuffer intrinsics. -def int_amdgcn_tbuffer_load : Intrinsic < - [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // voffset(VGPR) - llvm_i32_ty, // soffset(SGPR) - llvm_i32_ty, // offset(imm) - llvm_i32_ty, // dfmt(imm) - llvm_i32_ty, // nfmt(imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty], // slc(imm) - [IntrReadMem, IntrWillReturn, - ImmArg>, ImmArg>, ImmArg>, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; - -def int_amdgcn_tbuffer_store : Intrinsic < - [], - [llvm_any_ty, // vdata(VGPR), overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // voffset(VGPR) - llvm_i32_ty, // soffset(SGPR) - llvm_i32_ty, // offset(imm) - llvm_i32_ty, // dfmt(imm) - llvm_i32_ty, // nfmt(imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty], // slc(imm) - [IntrWriteMem, IntrWillReturn, ImmArg>, - ImmArg>, ImmArg>, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; - -// New tbuffer intrinsics, with: -// - raw and struct variants -// - joint format field -// - joint cachepolicy field -def int_amdgcn_raw_tbuffer_load : Intrinsic < - [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrReadMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; - -def int_amdgcn_raw_tbuffer_store : Intrinsic < - [], - [llvm_any_ty, // vdata(VGPR), overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrWriteMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; - -def int_amdgcn_struct_tbuffer_load : Intrinsic < - [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrReadMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<0>; - -def int_amdgcn_struct_tbuffer_store : Intrinsic < - [], - [llvm_any_ty, // vdata(VGPR), overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10+), - // swizzled buffer (bit 3 = swz)) - [IntrWriteMem, IntrWillReturn, - ImmArg>, ImmArg>], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1>; - -class AMDGPUBufferAtomic : Intrinsic < - [llvm_anyint_ty], - [LLVMMatchType<0>, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(SGPR/VGPR/imm) - llvm_i1_ty], // slc(imm) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1, 0>; -def int_amdgcn_buffer_atomic_swap : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_add : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_sub : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_smin : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_umin : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_smax : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_umax : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_and : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_or : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_xor : AMDGPUBufferAtomic; -def int_amdgcn_buffer_atomic_cmpswap : Intrinsic< - [llvm_i32_ty], - [llvm_i32_ty, // src(VGPR) - llvm_i32_ty, // cmp(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(SGPR/VGPR/imm) - llvm_i1_ty], // slc(imm) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<2, 0>; - -def int_amdgcn_buffer_atomic_csub : AMDGPUBufferAtomic; - -class AMDGPUBufferAtomicFP : Intrinsic < - [llvm_anyfloat_ty], - [LLVMMatchType<0>, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(SGPR/VGPR/imm) - llvm_i1_ty], // slc(imm) - [ImmArg>, IntrWillReturn], "", [SDNPMemOperand]>, - AMDGPURsrcIntrinsic<1, 0>; - -// Legacy form of the intrinsic. raw and struct forms should be preferred. -def int_amdgcn_buffer_atomic_fadd : AMDGPUBufferAtomicFP; -} // defset AMDGPUBufferIntrinsics - -// Uses that do not set the done bit should set IntrWriteMem on the -// call site. -def int_amdgcn_exp : Intrinsic <[], [ - llvm_i32_ty, // tgt, - llvm_i32_ty, // en - llvm_any_ty, // src0 (f32 or i32) - LLVMMatchType<0>, // src1 - LLVMMatchType<0>, // src2 - LLVMMatchType<0>, // src3 - llvm_i1_ty, // done - llvm_i1_ty // vm - ], - [ImmArg>, ImmArg>, ImmArg>, - ImmArg>, IntrWriteMem, IntrInaccessibleMemOnly, - IntrWillReturn] ->; - -// exp with compr bit set. -def int_amdgcn_exp_compr : Intrinsic <[], [ - llvm_i32_ty, // tgt, - llvm_i32_ty, // en - llvm_anyvector_ty, // src0 (v2f16 or v2i16) - LLVMMatchType<0>, // src1 - llvm_i1_ty, // done - llvm_i1_ty], // vm - [ImmArg>, ImmArg>, ImmArg>, - ImmArg>, IntrWriteMem, IntrInaccessibleMemOnly, - IntrWillReturn] ->; - -def int_amdgcn_buffer_wbinvl1_sc : - GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_sc">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_buffer_wbinvl1 : - GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_dcache_inv : - GCCBuiltin<"__builtin_amdgcn_s_dcache_inv">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_memtime : - GCCBuiltin<"__builtin_amdgcn_s_memtime">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_sleep : - GCCBuiltin<"__builtin_amdgcn_s_sleep">, - Intrinsic<[], [llvm_i32_ty], [ImmArg>, IntrNoMem, - IntrHasSideEffects, IntrWillReturn]> { -} - -def int_amdgcn_s_incperflevel : - GCCBuiltin<"__builtin_amdgcn_s_incperflevel">, - Intrinsic<[], [llvm_i32_ty], [ImmArg>, IntrNoMem, - IntrHasSideEffects, IntrWillReturn]> { -} - -def int_amdgcn_s_decperflevel : - GCCBuiltin<"__builtin_amdgcn_s_decperflevel">, - Intrinsic<[], [llvm_i32_ty], [ImmArg>, IntrNoMem, - IntrHasSideEffects, IntrWillReturn]> { -} - -def int_amdgcn_s_sethalt : - Intrinsic<[], [llvm_i32_ty], [ImmArg>, IntrNoMem, - IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_getreg : - GCCBuiltin<"__builtin_amdgcn_s_getreg">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], - [IntrInaccessibleMemOnly, IntrReadMem, IntrSpeculatable, - IntrWillReturn, ImmArg>] ->; - -// Note this can be used to set FP environment properties that are -// unsafe to change in non-strictfp functions. The register properties -// available (and value required to access them) may differ per -// subtarget. llvm.amdgcn.s.setreg(hwmode, value) -def int_amdgcn_s_setreg : - GCCBuiltin<"__builtin_amdgcn_s_setreg">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrHasSideEffects, IntrWillReturn, ImmArg>] ->; - -// int_amdgcn_s_getpc is provided to allow a specific style of position -// independent code to determine the high part of its address when it is -// known (through convention) that the code and any data of interest does -// not cross a 4Gb address boundary. Use for any other purpose may not -// produce the desired results as optimizations may cause code movement, -// especially as we explicitly use IntrNoMem to allow optimizations. -def int_amdgcn_s_getpc : - GCCBuiltin<"__builtin_amdgcn_s_getpc">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrSpeculatable, - IntrWillReturn]>; - -// __builtin_amdgcn_interp_mov , , , -// param values: 0 = P10, 1 = P20, 2 = P0 -def int_amdgcn_interp_mov : - GCCBuiltin<"__builtin_amdgcn_interp_mov">, - Intrinsic<[llvm_float_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>, ImmArg>]>; - -// __builtin_amdgcn_interp_p1 , , , -// This intrinsic reads from lds, but the memory values are constant, -// so it behaves like IntrNoMem. -def int_amdgcn_interp_p1 : - GCCBuiltin<"__builtin_amdgcn_interp_p1">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>]>; - -// __builtin_amdgcn_interp_p2 , , , , -def int_amdgcn_interp_p2 : - GCCBuiltin<"__builtin_amdgcn_interp_p2">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>]>; - // See int_amdgcn_v_interp_p1 for why this is IntrNoMem. - -// __builtin_amdgcn_interp_p1_f16 , , , , -// high selects whether high or low 16-bits are loaded from LDS -def int_amdgcn_interp_p1_f16 : - GCCBuiltin<"__builtin_amdgcn_interp_p1_f16">, - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>, ImmArg>]>; - -// __builtin_amdgcn_interp_p2_f16 , , , , , -// high selects whether high or low 16-bits are loaded from LDS -def int_amdgcn_interp_p2_f16 : - GCCBuiltin<"__builtin_amdgcn_interp_p2_f16">, - Intrinsic<[llvm_half_ty], - [llvm_float_ty, llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, ImmArg>, ImmArg>]>; - -// Deprecated: use llvm.amdgcn.live.mask instead. -def int_amdgcn_ps_live : Intrinsic < - [llvm_i1_ty], - [], - [IntrNoMem, IntrWillReturn]>; - -// Query currently live lanes. -// Returns true if lane is live (and not a helper lane). -def int_amdgcn_live_mask : Intrinsic <[llvm_i1_ty], - [], [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn] ->; - -def int_amdgcn_mbcnt_lo : - GCCBuiltin<"__builtin_amdgcn_mbcnt_lo">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrWillReturn]>; - -def int_amdgcn_mbcnt_hi : - GCCBuiltin<"__builtin_amdgcn_mbcnt_hi">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrWillReturn]>; - -// llvm.amdgcn.ds.swizzle src offset -def int_amdgcn_ds_swizzle : - GCCBuiltin<"__builtin_amdgcn_ds_swizzle">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>]>; - -def int_amdgcn_ubfe : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sbfe : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_lerp : - GCCBuiltin<"__builtin_amdgcn_lerp">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sad_u8 : - GCCBuiltin<"__builtin_amdgcn_sad_u8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_msad_u8 : - GCCBuiltin<"__builtin_amdgcn_msad_u8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sad_hi_u8 : - GCCBuiltin<"__builtin_amdgcn_sad_hi_u8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_sad_u16 : - GCCBuiltin<"__builtin_amdgcn_sad_u16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_qsad_pk_u16_u8 : - GCCBuiltin<"__builtin_amdgcn_qsad_pk_u16_u8">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mqsad_pk_u16_u8 : - GCCBuiltin<"__builtin_amdgcn_mqsad_pk_u16_u8">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mqsad_u32_u8 : - GCCBuiltin<"__builtin_amdgcn_mqsad_u32_u8">, - Intrinsic<[llvm_v4i32_ty], [llvm_i64_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_cvt_pk_u8_f32 : - GCCBuiltin<"__builtin_amdgcn_cvt_pk_u8_f32">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_icmp : - Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>]>; - -def int_amdgcn_fcmp : - Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, LLVMMatchType<1>, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>]>; - -def int_amdgcn_ballot : - Intrinsic<[llvm_anyint_ty], [llvm_i1_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -def int_amdgcn_readfirstlane : - GCCBuiltin<"__builtin_amdgcn_readfirstlane">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -// The lane argument must be uniform across the currently active threads of the -// current wave. Otherwise, the result is undefined. -def int_amdgcn_readlane : - GCCBuiltin<"__builtin_amdgcn_readlane">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -// The value to write and lane select arguments must be uniform across the -// currently active threads of the current wave. Otherwise, the result is -// undefined. -def int_amdgcn_writelane : - GCCBuiltin<"__builtin_amdgcn_writelane">, - Intrinsic<[llvm_i32_ty], [ - llvm_i32_ty, // uniform value to write: returned by the selected lane - llvm_i32_ty, // uniform lane select - llvm_i32_ty // returned by all lanes other than the selected one - ], - [IntrNoMem, IntrConvergent, IntrWillReturn] ->; - -def int_amdgcn_alignbyte : GCCBuiltin<"__builtin_amdgcn_alignbyte">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mul_i24 : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mul_u24 : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mulhi_i24 : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -def int_amdgcn_mulhi_u24 : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// llvm.amdgcn.ds.gws.init(i32 bar_val, i32 resource_id) -// -// bar_val is the total number of waves that will wait on this -// barrier, minus 1. -def int_amdgcn_ds_gws_init : - GCCBuiltin<"__builtin_amdgcn_ds_gws_init">, - Intrinsic<[], - [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrWriteMem, - IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - -// llvm.amdgcn.ds.gws.barrier(i32 vsrc0, i32 resource_id) -// bar_val is the total number of waves that will wait on this -// barrier, minus 1. -def int_amdgcn_ds_gws_barrier : - GCCBuiltin<"__builtin_amdgcn_ds_gws_barrier">, - Intrinsic<[], - [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - -// llvm.amdgcn.ds.gws.sema.v(i32 resource_id) -def int_amdgcn_ds_gws_sema_v : - GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_v">, - Intrinsic<[], - [llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - -// llvm.amdgcn.ds.gws.sema.br(i32 vsrc, i32 resource_id) -def int_amdgcn_ds_gws_sema_br : - GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_br">, - Intrinsic<[], - [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - -// llvm.amdgcn.ds.gws.sema.p(i32 resource_id) -def int_amdgcn_ds_gws_sema_p : - GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_p">, - Intrinsic<[], - [llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - -// llvm.amdgcn.ds.gws.sema.release.all(i32 resource_id) -def int_amdgcn_ds_gws_sema_release_all : - GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_release_all">, - Intrinsic<[], - [llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly, IntrWillReturn], "", - [SDNPMemOperand] ->; - - -// Copies the source value to the destination value, with the guarantee that -// the source value is computed as if the entire program were executed in WQM. -def int_amdgcn_wqm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// Copies the source value to the destination value, such that the source -// is computed as if the entire program were executed in WQM if any other -// program code executes in WQM. -def int_amdgcn_softwqm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// Return true if at least one thread within the pixel quad passes true into -// the function. -def int_amdgcn_wqm_vote : Intrinsic<[llvm_i1_ty], - [llvm_i1_ty], [IntrNoMem, IntrConvergent, IntrWillReturn] ->; - -// If false, set EXEC=0 for the current thread until the end of program. -// FIXME: Should this be IntrNoMem, IntrHasSideEffects, or IntrWillReturn? -def int_amdgcn_kill : Intrinsic<[], [llvm_i1_ty], []>; - -def int_amdgcn_endpgm : GCCBuiltin<"__builtin_amdgcn_endpgm">, - Intrinsic<[], [], [IntrNoReturn, IntrCold, IntrNoMem, IntrHasSideEffects] ->; - -// If false, mark all active lanes as helper lanes until the end of program. -def int_amdgcn_wqm_demote : Intrinsic<[], - [llvm_i1_ty], [IntrWriteMem, IntrInaccessibleMemOnly] ->; - -// Copies the active channels of the source value to the destination value, -// with the guarantee that the source value is computed as if the entire -// program were executed in Whole Wavefront Mode, i.e. with all channels -// enabled, with a few exceptions: - Phi nodes which require WWM return an -// undefined value. -def int_amdgcn_strict_wwm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, - IntrConvergent, IntrWillReturn] ->; -// Deprecated. Use int_amdgcn_strict_wwm instead. -def int_amdgcn_wwm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, - IntrConvergent, IntrWillReturn] ->; -def int_amdgcn_strict_wqm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, - IntrConvergent, IntrWillReturn] ->; - -// Given a value, copies it while setting all the inactive lanes to a given -// value. Note that OpenGL helper lanes are considered active, so if the -// program ever uses WQM, then the instruction and the first source will be -// computed in WQM. -def int_amdgcn_set_inactive : - Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, // value to be copied - LLVMMatchType<0>], // value for the inactive lanes to take - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -// Return if the given flat pointer points to a local memory address. -def int_amdgcn_is_shared : GCCBuiltin<"__builtin_amdgcn_is_shared">, - Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], - [IntrNoMem, IntrSpeculatable, NoCapture>, IntrWillReturn] ->; - -// Return if the given flat pointer points to a prvate memory address. -def int_amdgcn_is_private : GCCBuiltin<"__builtin_amdgcn_is_private">, - Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], - [IntrNoMem, IntrSpeculatable, NoCapture>, IntrWillReturn] ->; - -//===----------------------------------------------------------------------===// -// CI+ Intrinsics -//===----------------------------------------------------------------------===// - -def int_amdgcn_s_dcache_inv_vol : - GCCBuiltin<"__builtin_amdgcn_s_dcache_inv_vol">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_buffer_wbinvl1_vol : - GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_vol">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -//===----------------------------------------------------------------------===// -// VI Intrinsics -//===----------------------------------------------------------------------===// - -// llvm.amdgcn.mov.dpp.i32 -def int_amdgcn_mov_dpp : - Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i1_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>, ImmArg>, - ImmArg>, ImmArg>]>; - -// llvm.amdgcn.update.dpp.i32 -// Should be equivalent to: -// v_mov_b32 -// v_mov_b32 -def int_amdgcn_update_dpp : - Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i1_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>, ImmArg>, - ImmArg>, ImmArg>]>; - -def int_amdgcn_s_dcache_wb : - GCCBuiltin<"__builtin_amdgcn_s_dcache_wb">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_dcache_wb_vol : - GCCBuiltin<"__builtin_amdgcn_s_dcache_wb_vol">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -def int_amdgcn_s_memrealtime : - GCCBuiltin<"__builtin_amdgcn_s_memrealtime">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; - -// llvm.amdgcn.ds.permute -def int_amdgcn_ds_permute : - GCCBuiltin<"__builtin_amdgcn_ds_permute">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -// llvm.amdgcn.ds.bpermute -def int_amdgcn_ds_bpermute : - GCCBuiltin<"__builtin_amdgcn_ds_bpermute">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn]>; - -// llvm.amdgcn.perm -def int_amdgcn_perm : - GCCBuiltin<"__builtin_amdgcn_perm">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - -//===----------------------------------------------------------------------===// -// GFX10 Intrinsics -//===----------------------------------------------------------------------===// - -// llvm.amdgcn.permlane16 -def int_amdgcn_permlane16 : GCCBuiltin<"__builtin_amdgcn_permlane16">, - Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i1_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>, ImmArg>]>; - -// llvm.amdgcn.permlanex16 -def int_amdgcn_permlanex16 : GCCBuiltin<"__builtin_amdgcn_permlanex16">, - Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i1_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>, ImmArg>]>; - -// llvm.amdgcn.mov.dpp8.i32 -// is a 32-bit constant whose high 8 bits must be zero which selects -// the lanes to read from. -def int_amdgcn_mov_dpp8 : - Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrConvergent, IntrWillReturn, - ImmArg>]>; - -def int_amdgcn_s_get_waveid_in_workgroup : - GCCBuiltin<"__builtin_amdgcn_s_get_waveid_in_workgroup">, - Intrinsic<[llvm_i32_ty], [], - [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>; - -class AMDGPUGlobalAtomicRtn : Intrinsic < - [vt], - [llvm_anyptr_ty, // vaddr - vt], // vdata(VGPR) - [IntrArgMemOnly, IntrWillReturn, NoCapture>], "", - [SDNPMemOperand]>; - -def int_amdgcn_global_atomic_csub : AMDGPUGlobalAtomicRtn; - -// uint4 llvm.amdgcn.image.bvh.intersect.ray , , , -// , , -// is i32 or i64. -// and are both v3f16 or both v3f32. -def int_amdgcn_image_bvh_intersect_ray : - Intrinsic<[llvm_v4i32_ty], - [llvm_anyint_ty, llvm_float_ty, llvm_v3f32_ty, llvm_anyvector_ty, - LLVMMatchType<1>, llvm_v4i32_ty], - [IntrReadMem, IntrWillReturn]>; - -//===----------------------------------------------------------------------===// -// Deep learning intrinsics. -//===----------------------------------------------------------------------===// - -// f32 %r = llvm.amdgcn.fdot2(v2f16 %a, v2f16 %b, f32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c -def int_amdgcn_fdot2 : - GCCBuiltin<"__builtin_amdgcn_fdot2">, - Intrinsic< - [llvm_float_ty], // %r - [ - llvm_v2f16_ty, // %a - llvm_v2f16_ty, // %b - llvm_float_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// i32 %r = llvm.amdgcn.sdot2(v2i16 %a, v2i16 %b, i32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c -def int_amdgcn_sdot2 : - GCCBuiltin<"__builtin_amdgcn_sdot2">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_v2i16_ty, // %a - llvm_v2i16_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// u32 %r = llvm.amdgcn.udot2(v2u16 %a, v2u16 %b, u32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c -def int_amdgcn_udot2 : - GCCBuiltin<"__builtin_amdgcn_udot2">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_v2i16_ty, // %a - llvm_v2i16_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// i32 %r = llvm.amdgcn.sdot4(v4i8 (as i32) %a, v4i8 (as i32) %b, i32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c -def int_amdgcn_sdot4 : - GCCBuiltin<"__builtin_amdgcn_sdot4">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_i32_ty, // %a - llvm_i32_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// u32 %r = llvm.amdgcn.udot4(v4u8 (as u32) %a, v4u8 (as u32) %b, u32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c -def int_amdgcn_udot4 : - GCCBuiltin<"__builtin_amdgcn_udot4">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_i32_ty, // %a - llvm_i32_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// i32 %r = llvm.amdgcn.sdot8(v8i4 (as i32) %a, v8i4 (as i32) %b, i32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + -// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c -def int_amdgcn_sdot8 : - GCCBuiltin<"__builtin_amdgcn_sdot8">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_i32_ty, // %a - llvm_i32_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -// u32 %r = llvm.amdgcn.udot8(v8u4 (as u32) %a, v8u4 (as u32) %b, u32 %c, i1 %clamp) -// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + -// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c -def int_amdgcn_udot8 : - GCCBuiltin<"__builtin_amdgcn_udot8">, - Intrinsic< - [llvm_i32_ty], // %r - [ - llvm_i32_ty, // %a - llvm_i32_ty, // %b - llvm_i32_ty, // %c - llvm_i1_ty // %clamp - ], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg>] - >; - -//===----------------------------------------------------------------------===// -// gfx908 intrinsics -// ===----------------------------------------------------------------------===// - -def int_amdgcn_global_atomic_fadd : AMDGPUGlobalAtomicRtn; - -// llvm.amdgcn.mfma.*.* vdst, srcA, srcB, srcC, cbsz, abid, blgp -class AMDGPUMfmaIntrinsic : - GCCBuiltin, - Intrinsic<[DestTy], - [SrcABTy, SrcABTy, DestTy, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrNoMem, IntrWillReturn, - ImmArg>, ImmArg>, ImmArg>]>; - -def int_amdgcn_mfma_f32_32x32x1f32 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x1f32 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_4x4x1f32 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x2f32 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x4f32 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x4f16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x4f16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_4x4x4f16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x8f16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x16f16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_i32_32x32x4i8 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_i32_16x16x4i8 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_i32_4x4x4i8 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_i32_32x32x8i8 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_i32_16x16x16i8 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x2bf16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x2bf16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_4x4x2bf16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x4bf16 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x8bf16 : AMDGPUMfmaIntrinsic; - -//===----------------------------------------------------------------------===// -// gfx90a intrinsics -// ===----------------------------------------------------------------------===// - -def int_amdgcn_global_atomic_fmin : AMDGPUGlobalAtomicRtn; -def int_amdgcn_global_atomic_fmax : AMDGPUGlobalAtomicRtn; -def int_amdgcn_flat_atomic_fadd : AMDGPUGlobalAtomicRtn; -def int_amdgcn_flat_atomic_fmin : AMDGPUGlobalAtomicRtn; -def int_amdgcn_flat_atomic_fmax : AMDGPUGlobalAtomicRtn; - -def int_amdgcn_mfma_f32_32x32x4bf16_1k : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x4bf16_1k : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_4x4x4bf16_1k : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_32x32x8bf16_1k : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f32_16x16x16bf16_1k : AMDGPUMfmaIntrinsic; - -def int_amdgcn_mfma_f64_16x16x4f64 : AMDGPUMfmaIntrinsic; -def int_amdgcn_mfma_f64_4x4x4f64 : AMDGPUMfmaIntrinsic; - -//===----------------------------------------------------------------------===// -// Special Intrinsics for backend internal use only. No frontend -// should emit calls to these. -// ===----------------------------------------------------------------------===// -def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_anyint_ty], - [llvm_i1_ty], [IntrConvergent, IntrWillReturn] ->; - -def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_anyint_ty], - [llvm_anyint_ty], [IntrConvergent, IntrWillReturn] ->; - -def int_amdgcn_if_break : Intrinsic<[llvm_anyint_ty], - [llvm_i1_ty, LLVMMatchType<0>], - [IntrNoMem, IntrConvergent, IntrWillReturn] ->; - -def int_amdgcn_loop : Intrinsic<[llvm_i1_ty], - [llvm_anyint_ty], [IntrConvergent, IntrWillReturn] ->; - -def int_amdgcn_end_cf : Intrinsic<[], [llvm_anyint_ty], - [IntrConvergent, IntrWillReturn]>; - -// Represent unreachable in a divergent region. -def int_amdgcn_unreachable : Intrinsic<[], [], [IntrConvergent]>; - -// Emit 2.5 ulp, no denormal division. Should only be inserted by -// pass based on !fpmath metadata. -def int_amdgcn_fdiv_fast : Intrinsic< - [llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; - -// Represent a relocation constant. -def int_amdgcn_reloc_constant : Intrinsic< - [llvm_i32_ty], [llvm_metadata_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn] ->; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.h deleted file mode 100644 index 43502964ee..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.h +++ /dev/null @@ -1,511 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_ARM_ENUMS_H -#define LLVM_IR_INTRINSIC_ARM_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum ARMIntrinsics : unsigned { -// Enum values for intrinsics - arm_cde_cx1 = 1972, // llvm.arm.cde.cx1 - arm_cde_cx1a, // llvm.arm.cde.cx1a - arm_cde_cx1d, // llvm.arm.cde.cx1d - arm_cde_cx1da, // llvm.arm.cde.cx1da - arm_cde_cx2, // llvm.arm.cde.cx2 - arm_cde_cx2a, // llvm.arm.cde.cx2a - arm_cde_cx2d, // llvm.arm.cde.cx2d - arm_cde_cx2da, // llvm.arm.cde.cx2da - arm_cde_cx3, // llvm.arm.cde.cx3 - arm_cde_cx3a, // llvm.arm.cde.cx3a - arm_cde_cx3d, // llvm.arm.cde.cx3d - arm_cde_cx3da, // llvm.arm.cde.cx3da - arm_cde_vcx1, // llvm.arm.cde.vcx1 - arm_cde_vcx1a, // llvm.arm.cde.vcx1a - arm_cde_vcx1q, // llvm.arm.cde.vcx1q - arm_cde_vcx1q_predicated, // llvm.arm.cde.vcx1q.predicated - arm_cde_vcx1qa, // llvm.arm.cde.vcx1qa - arm_cde_vcx1qa_predicated, // llvm.arm.cde.vcx1qa.predicated - arm_cde_vcx2, // llvm.arm.cde.vcx2 - arm_cde_vcx2a, // llvm.arm.cde.vcx2a - arm_cde_vcx2q, // llvm.arm.cde.vcx2q - arm_cde_vcx2q_predicated, // llvm.arm.cde.vcx2q.predicated - arm_cde_vcx2qa, // llvm.arm.cde.vcx2qa - arm_cde_vcx2qa_predicated, // llvm.arm.cde.vcx2qa.predicated - arm_cde_vcx3, // llvm.arm.cde.vcx3 - arm_cde_vcx3a, // llvm.arm.cde.vcx3a - arm_cde_vcx3q, // llvm.arm.cde.vcx3q - arm_cde_vcx3q_predicated, // llvm.arm.cde.vcx3q.predicated - arm_cde_vcx3qa, // llvm.arm.cde.vcx3qa - arm_cde_vcx3qa_predicated, // llvm.arm.cde.vcx3qa.predicated - arm_cdp, // llvm.arm.cdp - arm_cdp2, // llvm.arm.cdp2 - arm_clrex, // llvm.arm.clrex - arm_cls, // llvm.arm.cls - arm_cls64, // llvm.arm.cls64 - arm_cmse_tt, // llvm.arm.cmse.tt - arm_cmse_tta, // llvm.arm.cmse.tta - arm_cmse_ttat, // llvm.arm.cmse.ttat - arm_cmse_ttt, // llvm.arm.cmse.ttt - arm_crc32b, // llvm.arm.crc32b - arm_crc32cb, // llvm.arm.crc32cb - arm_crc32ch, // llvm.arm.crc32ch - arm_crc32cw, // llvm.arm.crc32cw - arm_crc32h, // llvm.arm.crc32h - arm_crc32w, // llvm.arm.crc32w - arm_dbg, // llvm.arm.dbg - arm_dmb, // llvm.arm.dmb - arm_dsb, // llvm.arm.dsb - arm_get_fpscr, // llvm.arm.get.fpscr - arm_gnu_eabi_mcount, // llvm.arm.gnu.eabi.mcount - arm_hint, // llvm.arm.hint - arm_isb, // llvm.arm.isb - arm_ldaex, // llvm.arm.ldaex - arm_ldaexd, // llvm.arm.ldaexd - arm_ldc, // llvm.arm.ldc - arm_ldc2, // llvm.arm.ldc2 - arm_ldc2l, // llvm.arm.ldc2l - arm_ldcl, // llvm.arm.ldcl - arm_ldrex, // llvm.arm.ldrex - arm_ldrexd, // llvm.arm.ldrexd - arm_mcr, // llvm.arm.mcr - arm_mcr2, // llvm.arm.mcr2 - arm_mcrr, // llvm.arm.mcrr - arm_mcrr2, // llvm.arm.mcrr2 - arm_mrc, // llvm.arm.mrc - arm_mrc2, // llvm.arm.mrc2 - arm_mrrc, // llvm.arm.mrrc - arm_mrrc2, // llvm.arm.mrrc2 - arm_mve_abd_predicated, // llvm.arm.mve.abd.predicated - arm_mve_abs_predicated, // llvm.arm.mve.abs.predicated - arm_mve_add_predicated, // llvm.arm.mve.add.predicated - arm_mve_addlv, // llvm.arm.mve.addlv - arm_mve_addlv_predicated, // llvm.arm.mve.addlv.predicated - arm_mve_addv, // llvm.arm.mve.addv - arm_mve_addv_predicated, // llvm.arm.mve.addv.predicated - arm_mve_and_predicated, // llvm.arm.mve.and.predicated - arm_mve_asrl, // llvm.arm.mve.asrl - arm_mve_bic_predicated, // llvm.arm.mve.bic.predicated - arm_mve_cls_predicated, // llvm.arm.mve.cls.predicated - arm_mve_clz_predicated, // llvm.arm.mve.clz.predicated - arm_mve_eor_predicated, // llvm.arm.mve.eor.predicated - arm_mve_fma_predicated, // llvm.arm.mve.fma.predicated - arm_mve_hadd_predicated, // llvm.arm.mve.hadd.predicated - arm_mve_hsub_predicated, // llvm.arm.mve.hsub.predicated - arm_mve_lsll, // llvm.arm.mve.lsll - arm_mve_max_predicated, // llvm.arm.mve.max.predicated - arm_mve_maxav, // llvm.arm.mve.maxav - arm_mve_maxav_predicated, // llvm.arm.mve.maxav.predicated - arm_mve_maxnmav, // llvm.arm.mve.maxnmav - arm_mve_maxnmav_predicated, // llvm.arm.mve.maxnmav.predicated - arm_mve_maxnmv, // llvm.arm.mve.maxnmv - arm_mve_maxnmv_predicated, // llvm.arm.mve.maxnmv.predicated - arm_mve_maxv, // llvm.arm.mve.maxv - arm_mve_maxv_predicated, // llvm.arm.mve.maxv.predicated - arm_mve_min_predicated, // llvm.arm.mve.min.predicated - arm_mve_minav, // llvm.arm.mve.minav - arm_mve_minav_predicated, // llvm.arm.mve.minav.predicated - arm_mve_minnmav, // llvm.arm.mve.minnmav - arm_mve_minnmav_predicated, // llvm.arm.mve.minnmav.predicated - arm_mve_minnmv, // llvm.arm.mve.minnmv - arm_mve_minnmv_predicated, // llvm.arm.mve.minnmv.predicated - arm_mve_minv, // llvm.arm.mve.minv - arm_mve_minv_predicated, // llvm.arm.mve.minv.predicated - arm_mve_mul_predicated, // llvm.arm.mve.mul.predicated - arm_mve_mulh_predicated, // llvm.arm.mve.mulh.predicated - arm_mve_mull_int_predicated, // llvm.arm.mve.mull.int.predicated - arm_mve_mull_poly_predicated, // llvm.arm.mve.mull.poly.predicated - arm_mve_mvn_predicated, // llvm.arm.mve.mvn.predicated - arm_mve_neg_predicated, // llvm.arm.mve.neg.predicated - arm_mve_orn_predicated, // llvm.arm.mve.orn.predicated - arm_mve_orr_predicated, // llvm.arm.mve.orr.predicated - arm_mve_pred_i2v, // llvm.arm.mve.pred.i2v - arm_mve_pred_v2i, // llvm.arm.mve.pred.v2i - arm_mve_qabs_predicated, // llvm.arm.mve.qabs.predicated - arm_mve_qadd_predicated, // llvm.arm.mve.qadd.predicated - arm_mve_qdmulh_predicated, // llvm.arm.mve.qdmulh.predicated - arm_mve_qneg_predicated, // llvm.arm.mve.qneg.predicated - arm_mve_qrdmulh_predicated, // llvm.arm.mve.qrdmulh.predicated - arm_mve_qsub_predicated, // llvm.arm.mve.qsub.predicated - arm_mve_rhadd_predicated, // llvm.arm.mve.rhadd.predicated - arm_mve_rmulh_predicated, // llvm.arm.mve.rmulh.predicated - arm_mve_shl_imm_predicated, // llvm.arm.mve.shl.imm.predicated - arm_mve_shr_imm_predicated, // llvm.arm.mve.shr.imm.predicated - arm_mve_sqrshr, // llvm.arm.mve.sqrshr - arm_mve_sqrshrl, // llvm.arm.mve.sqrshrl - arm_mve_sqshl, // llvm.arm.mve.sqshl - arm_mve_sqshll, // llvm.arm.mve.sqshll - arm_mve_srshr, // llvm.arm.mve.srshr - arm_mve_srshrl, // llvm.arm.mve.srshrl - arm_mve_sub_predicated, // llvm.arm.mve.sub.predicated - arm_mve_uqrshl, // llvm.arm.mve.uqrshl - arm_mve_uqrshll, // llvm.arm.mve.uqrshll - arm_mve_uqshl, // llvm.arm.mve.uqshl - arm_mve_uqshll, // llvm.arm.mve.uqshll - arm_mve_urshr, // llvm.arm.mve.urshr - arm_mve_urshrl, // llvm.arm.mve.urshrl - arm_mve_vabav, // llvm.arm.mve.vabav - arm_mve_vabav_predicated, // llvm.arm.mve.vabav.predicated - arm_mve_vabd, // llvm.arm.mve.vabd - arm_mve_vadc, // llvm.arm.mve.vadc - arm_mve_vadc_predicated, // llvm.arm.mve.vadc.predicated - arm_mve_vbrsr, // llvm.arm.mve.vbrsr - arm_mve_vbrsr_predicated, // llvm.arm.mve.vbrsr.predicated - arm_mve_vcaddq, // llvm.arm.mve.vcaddq - arm_mve_vcaddq_predicated, // llvm.arm.mve.vcaddq.predicated - arm_mve_vcls, // llvm.arm.mve.vcls - arm_mve_vcmlaq, // llvm.arm.mve.vcmlaq - arm_mve_vcmlaq_predicated, // llvm.arm.mve.vcmlaq.predicated - arm_mve_vcmulq, // llvm.arm.mve.vcmulq - arm_mve_vcmulq_predicated, // llvm.arm.mve.vcmulq.predicated - arm_mve_vctp16, // llvm.arm.mve.vctp16 - arm_mve_vctp32, // llvm.arm.mve.vctp32 - arm_mve_vctp64, // llvm.arm.mve.vctp64 - arm_mve_vctp8, // llvm.arm.mve.vctp8 - arm_mve_vcvt_fix, // llvm.arm.mve.vcvt.fix - arm_mve_vcvt_fix_predicated, // llvm.arm.mve.vcvt.fix.predicated - arm_mve_vcvt_fp_int_predicated, // llvm.arm.mve.vcvt.fp.int.predicated - arm_mve_vcvt_narrow, // llvm.arm.mve.vcvt.narrow - arm_mve_vcvt_narrow_predicated, // llvm.arm.mve.vcvt.narrow.predicated - arm_mve_vcvt_widen, // llvm.arm.mve.vcvt.widen - arm_mve_vcvt_widen_predicated, // llvm.arm.mve.vcvt.widen.predicated - arm_mve_vcvta, // llvm.arm.mve.vcvta - arm_mve_vcvta_predicated, // llvm.arm.mve.vcvta.predicated - arm_mve_vcvtm, // llvm.arm.mve.vcvtm - arm_mve_vcvtm_predicated, // llvm.arm.mve.vcvtm.predicated - arm_mve_vcvtn, // llvm.arm.mve.vcvtn - arm_mve_vcvtn_predicated, // llvm.arm.mve.vcvtn.predicated - arm_mve_vcvtp, // llvm.arm.mve.vcvtp - arm_mve_vcvtp_predicated, // llvm.arm.mve.vcvtp.predicated - arm_mve_vddup, // llvm.arm.mve.vddup - arm_mve_vddup_predicated, // llvm.arm.mve.vddup.predicated - arm_mve_vdwdup, // llvm.arm.mve.vdwdup - arm_mve_vdwdup_predicated, // llvm.arm.mve.vdwdup.predicated - arm_mve_vhadd, // llvm.arm.mve.vhadd - arm_mve_vhsub, // llvm.arm.mve.vhsub - arm_mve_vidup, // llvm.arm.mve.vidup - arm_mve_vidup_predicated, // llvm.arm.mve.vidup.predicated - arm_mve_viwdup, // llvm.arm.mve.viwdup - arm_mve_viwdup_predicated, // llvm.arm.mve.viwdup.predicated - arm_mve_vld2q, // llvm.arm.mve.vld2q - arm_mve_vld4q, // llvm.arm.mve.vld4q - arm_mve_vldr_gather_base, // llvm.arm.mve.vldr.gather.base - arm_mve_vldr_gather_base_predicated, // llvm.arm.mve.vldr.gather.base.predicated - arm_mve_vldr_gather_base_wb, // llvm.arm.mve.vldr.gather.base.wb - arm_mve_vldr_gather_base_wb_predicated, // llvm.arm.mve.vldr.gather.base.wb.predicated - arm_mve_vldr_gather_offset, // llvm.arm.mve.vldr.gather.offset - arm_mve_vldr_gather_offset_predicated, // llvm.arm.mve.vldr.gather.offset.predicated - arm_mve_vmaxa_predicated, // llvm.arm.mve.vmaxa.predicated - arm_mve_vmaxnma_predicated, // llvm.arm.mve.vmaxnma.predicated - arm_mve_vmina_predicated, // llvm.arm.mve.vmina.predicated - arm_mve_vminnma_predicated, // llvm.arm.mve.vminnma.predicated - arm_mve_vmla_n_predicated, // llvm.arm.mve.vmla.n.predicated - arm_mve_vmlas_n_predicated, // llvm.arm.mve.vmlas.n.predicated - arm_mve_vmldava, // llvm.arm.mve.vmldava - arm_mve_vmldava_predicated, // llvm.arm.mve.vmldava.predicated - arm_mve_vmlldava, // llvm.arm.mve.vmlldava - arm_mve_vmlldava_predicated, // llvm.arm.mve.vmlldava.predicated - arm_mve_vmovl_predicated, // llvm.arm.mve.vmovl.predicated - arm_mve_vmovn_predicated, // llvm.arm.mve.vmovn.predicated - arm_mve_vmulh, // llvm.arm.mve.vmulh - arm_mve_vmull, // llvm.arm.mve.vmull - arm_mve_vmull_poly, // llvm.arm.mve.vmull.poly - arm_mve_vqdmlad, // llvm.arm.mve.vqdmlad - arm_mve_vqdmlad_predicated, // llvm.arm.mve.vqdmlad.predicated - arm_mve_vqdmlah, // llvm.arm.mve.vqdmlah - arm_mve_vqdmlah_predicated, // llvm.arm.mve.vqdmlah.predicated - arm_mve_vqdmlash, // llvm.arm.mve.vqdmlash - arm_mve_vqdmlash_predicated, // llvm.arm.mve.vqdmlash.predicated - arm_mve_vqdmulh, // llvm.arm.mve.vqdmulh - arm_mve_vqdmull, // llvm.arm.mve.vqdmull - arm_mve_vqdmull_predicated, // llvm.arm.mve.vqdmull.predicated - arm_mve_vqmovn, // llvm.arm.mve.vqmovn - arm_mve_vqmovn_predicated, // llvm.arm.mve.vqmovn.predicated - arm_mve_vqrdmlah, // llvm.arm.mve.vqrdmlah - arm_mve_vqrdmlah_predicated, // llvm.arm.mve.vqrdmlah.predicated - arm_mve_vqrdmlash, // llvm.arm.mve.vqrdmlash - arm_mve_vqrdmlash_predicated, // llvm.arm.mve.vqrdmlash.predicated - arm_mve_vqrdmulh, // llvm.arm.mve.vqrdmulh - arm_mve_vqshl_imm, // llvm.arm.mve.vqshl.imm - arm_mve_vqshl_imm_predicated, // llvm.arm.mve.vqshl.imm.predicated - arm_mve_vqshlu_imm, // llvm.arm.mve.vqshlu.imm - arm_mve_vqshlu_imm_predicated, // llvm.arm.mve.vqshlu.imm.predicated - arm_mve_vreinterpretq, // llvm.arm.mve.vreinterpretq - arm_mve_vrev_predicated, // llvm.arm.mve.vrev.predicated - arm_mve_vrhadd, // llvm.arm.mve.vrhadd - arm_mve_vrinta_predicated, // llvm.arm.mve.vrinta.predicated - arm_mve_vrintm_predicated, // llvm.arm.mve.vrintm.predicated - arm_mve_vrintn, // llvm.arm.mve.vrintn - arm_mve_vrintn_predicated, // llvm.arm.mve.vrintn.predicated - arm_mve_vrintp_predicated, // llvm.arm.mve.vrintp.predicated - arm_mve_vrintx_predicated, // llvm.arm.mve.vrintx.predicated - arm_mve_vrintz_predicated, // llvm.arm.mve.vrintz.predicated - arm_mve_vrmlldavha, // llvm.arm.mve.vrmlldavha - arm_mve_vrmlldavha_predicated, // llvm.arm.mve.vrmlldavha.predicated - arm_mve_vrmulh, // llvm.arm.mve.vrmulh - arm_mve_vrshr_imm, // llvm.arm.mve.vrshr.imm - arm_mve_vrshr_imm_predicated, // llvm.arm.mve.vrshr.imm.predicated - arm_mve_vsbc, // llvm.arm.mve.vsbc - arm_mve_vsbc_predicated, // llvm.arm.mve.vsbc.predicated - arm_mve_vshl_scalar, // llvm.arm.mve.vshl.scalar - arm_mve_vshl_scalar_predicated, // llvm.arm.mve.vshl.scalar.predicated - arm_mve_vshl_vector, // llvm.arm.mve.vshl.vector - arm_mve_vshl_vector_predicated, // llvm.arm.mve.vshl.vector.predicated - arm_mve_vshlc, // llvm.arm.mve.vshlc - arm_mve_vshlc_predicated, // llvm.arm.mve.vshlc.predicated - arm_mve_vshll_imm, // llvm.arm.mve.vshll.imm - arm_mve_vshll_imm_predicated, // llvm.arm.mve.vshll.imm.predicated - arm_mve_vshrn, // llvm.arm.mve.vshrn - arm_mve_vshrn_predicated, // llvm.arm.mve.vshrn.predicated - arm_mve_vsli, // llvm.arm.mve.vsli - arm_mve_vsli_predicated, // llvm.arm.mve.vsli.predicated - arm_mve_vsri, // llvm.arm.mve.vsri - arm_mve_vsri_predicated, // llvm.arm.mve.vsri.predicated - arm_mve_vst2q, // llvm.arm.mve.vst2q - arm_mve_vst4q, // llvm.arm.mve.vst4q - arm_mve_vstr_scatter_base, // llvm.arm.mve.vstr.scatter.base - arm_mve_vstr_scatter_base_predicated, // llvm.arm.mve.vstr.scatter.base.predicated - arm_mve_vstr_scatter_base_wb, // llvm.arm.mve.vstr.scatter.base.wb - arm_mve_vstr_scatter_base_wb_predicated, // llvm.arm.mve.vstr.scatter.base.wb.predicated - arm_mve_vstr_scatter_offset, // llvm.arm.mve.vstr.scatter.offset - arm_mve_vstr_scatter_offset_predicated, // llvm.arm.mve.vstr.scatter.offset.predicated - arm_neon_aesd, // llvm.arm.neon.aesd - arm_neon_aese, // llvm.arm.neon.aese - arm_neon_aesimc, // llvm.arm.neon.aesimc - arm_neon_aesmc, // llvm.arm.neon.aesmc - arm_neon_bfdot, // llvm.arm.neon.bfdot - arm_neon_bfmlalb, // llvm.arm.neon.bfmlalb - arm_neon_bfmlalt, // llvm.arm.neon.bfmlalt - arm_neon_bfmmla, // llvm.arm.neon.bfmmla - arm_neon_sdot, // llvm.arm.neon.sdot - arm_neon_sha1c, // llvm.arm.neon.sha1c - arm_neon_sha1h, // llvm.arm.neon.sha1h - arm_neon_sha1m, // llvm.arm.neon.sha1m - arm_neon_sha1p, // llvm.arm.neon.sha1p - arm_neon_sha1su0, // llvm.arm.neon.sha1su0 - arm_neon_sha1su1, // llvm.arm.neon.sha1su1 - arm_neon_sha256h, // llvm.arm.neon.sha256h - arm_neon_sha256h2, // llvm.arm.neon.sha256h2 - arm_neon_sha256su0, // llvm.arm.neon.sha256su0 - arm_neon_sha256su1, // llvm.arm.neon.sha256su1 - arm_neon_smmla, // llvm.arm.neon.smmla - arm_neon_udot, // llvm.arm.neon.udot - arm_neon_ummla, // llvm.arm.neon.ummla - arm_neon_usdot, // llvm.arm.neon.usdot - arm_neon_usmmla, // llvm.arm.neon.usmmla - arm_neon_vabds, // llvm.arm.neon.vabds - arm_neon_vabdu, // llvm.arm.neon.vabdu - arm_neon_vabs, // llvm.arm.neon.vabs - arm_neon_vacge, // llvm.arm.neon.vacge - arm_neon_vacgt, // llvm.arm.neon.vacgt - arm_neon_vbsl, // llvm.arm.neon.vbsl - arm_neon_vcadd_rot270, // llvm.arm.neon.vcadd.rot270 - arm_neon_vcadd_rot90, // llvm.arm.neon.vcadd.rot90 - arm_neon_vcls, // llvm.arm.neon.vcls - arm_neon_vcvtas, // llvm.arm.neon.vcvtas - arm_neon_vcvtau, // llvm.arm.neon.vcvtau - arm_neon_vcvtbfp2bf, // llvm.arm.neon.vcvtbfp2bf - arm_neon_vcvtfp2bf, // llvm.arm.neon.vcvtfp2bf - arm_neon_vcvtfp2fxs, // llvm.arm.neon.vcvtfp2fxs - arm_neon_vcvtfp2fxu, // llvm.arm.neon.vcvtfp2fxu - arm_neon_vcvtfp2hf, // llvm.arm.neon.vcvtfp2hf - arm_neon_vcvtfxs2fp, // llvm.arm.neon.vcvtfxs2fp - arm_neon_vcvtfxu2fp, // llvm.arm.neon.vcvtfxu2fp - arm_neon_vcvthf2fp, // llvm.arm.neon.vcvthf2fp - arm_neon_vcvtms, // llvm.arm.neon.vcvtms - arm_neon_vcvtmu, // llvm.arm.neon.vcvtmu - arm_neon_vcvtns, // llvm.arm.neon.vcvtns - arm_neon_vcvtnu, // llvm.arm.neon.vcvtnu - arm_neon_vcvtps, // llvm.arm.neon.vcvtps - arm_neon_vcvtpu, // llvm.arm.neon.vcvtpu - arm_neon_vhadds, // llvm.arm.neon.vhadds - arm_neon_vhaddu, // llvm.arm.neon.vhaddu - arm_neon_vhsubs, // llvm.arm.neon.vhsubs - arm_neon_vhsubu, // llvm.arm.neon.vhsubu - arm_neon_vld1, // llvm.arm.neon.vld1 - arm_neon_vld1x2, // llvm.arm.neon.vld1x2 - arm_neon_vld1x3, // llvm.arm.neon.vld1x3 - arm_neon_vld1x4, // llvm.arm.neon.vld1x4 - arm_neon_vld2, // llvm.arm.neon.vld2 - arm_neon_vld2dup, // llvm.arm.neon.vld2dup - arm_neon_vld2lane, // llvm.arm.neon.vld2lane - arm_neon_vld3, // llvm.arm.neon.vld3 - arm_neon_vld3dup, // llvm.arm.neon.vld3dup - arm_neon_vld3lane, // llvm.arm.neon.vld3lane - arm_neon_vld4, // llvm.arm.neon.vld4 - arm_neon_vld4dup, // llvm.arm.neon.vld4dup - arm_neon_vld4lane, // llvm.arm.neon.vld4lane - arm_neon_vmaxnm, // llvm.arm.neon.vmaxnm - arm_neon_vmaxs, // llvm.arm.neon.vmaxs - arm_neon_vmaxu, // llvm.arm.neon.vmaxu - arm_neon_vminnm, // llvm.arm.neon.vminnm - arm_neon_vmins, // llvm.arm.neon.vmins - arm_neon_vminu, // llvm.arm.neon.vminu - arm_neon_vmullp, // llvm.arm.neon.vmullp - arm_neon_vmulls, // llvm.arm.neon.vmulls - arm_neon_vmullu, // llvm.arm.neon.vmullu - arm_neon_vmulp, // llvm.arm.neon.vmulp - arm_neon_vpadals, // llvm.arm.neon.vpadals - arm_neon_vpadalu, // llvm.arm.neon.vpadalu - arm_neon_vpadd, // llvm.arm.neon.vpadd - arm_neon_vpaddls, // llvm.arm.neon.vpaddls - arm_neon_vpaddlu, // llvm.arm.neon.vpaddlu - arm_neon_vpmaxs, // llvm.arm.neon.vpmaxs - arm_neon_vpmaxu, // llvm.arm.neon.vpmaxu - arm_neon_vpmins, // llvm.arm.neon.vpmins - arm_neon_vpminu, // llvm.arm.neon.vpminu - arm_neon_vqabs, // llvm.arm.neon.vqabs - arm_neon_vqdmulh, // llvm.arm.neon.vqdmulh - arm_neon_vqdmull, // llvm.arm.neon.vqdmull - arm_neon_vqmovns, // llvm.arm.neon.vqmovns - arm_neon_vqmovnsu, // llvm.arm.neon.vqmovnsu - arm_neon_vqmovnu, // llvm.arm.neon.vqmovnu - arm_neon_vqneg, // llvm.arm.neon.vqneg - arm_neon_vqrdmlah, // llvm.arm.neon.vqrdmlah - arm_neon_vqrdmlsh, // llvm.arm.neon.vqrdmlsh - arm_neon_vqrdmulh, // llvm.arm.neon.vqrdmulh - arm_neon_vqrshiftns, // llvm.arm.neon.vqrshiftns - arm_neon_vqrshiftnsu, // llvm.arm.neon.vqrshiftnsu - arm_neon_vqrshiftnu, // llvm.arm.neon.vqrshiftnu - arm_neon_vqrshifts, // llvm.arm.neon.vqrshifts - arm_neon_vqrshiftu, // llvm.arm.neon.vqrshiftu - arm_neon_vqshiftns, // llvm.arm.neon.vqshiftns - arm_neon_vqshiftnsu, // llvm.arm.neon.vqshiftnsu - arm_neon_vqshiftnu, // llvm.arm.neon.vqshiftnu - arm_neon_vqshifts, // llvm.arm.neon.vqshifts - arm_neon_vqshiftsu, // llvm.arm.neon.vqshiftsu - arm_neon_vqshiftu, // llvm.arm.neon.vqshiftu - arm_neon_vraddhn, // llvm.arm.neon.vraddhn - arm_neon_vrecpe, // llvm.arm.neon.vrecpe - arm_neon_vrecps, // llvm.arm.neon.vrecps - arm_neon_vrhadds, // llvm.arm.neon.vrhadds - arm_neon_vrhaddu, // llvm.arm.neon.vrhaddu - arm_neon_vrinta, // llvm.arm.neon.vrinta - arm_neon_vrintm, // llvm.arm.neon.vrintm - arm_neon_vrintn, // llvm.arm.neon.vrintn - arm_neon_vrintp, // llvm.arm.neon.vrintp - arm_neon_vrintx, // llvm.arm.neon.vrintx - arm_neon_vrintz, // llvm.arm.neon.vrintz - arm_neon_vrshiftn, // llvm.arm.neon.vrshiftn - arm_neon_vrshifts, // llvm.arm.neon.vrshifts - arm_neon_vrshiftu, // llvm.arm.neon.vrshiftu - arm_neon_vrsqrte, // llvm.arm.neon.vrsqrte - arm_neon_vrsqrts, // llvm.arm.neon.vrsqrts - arm_neon_vrsubhn, // llvm.arm.neon.vrsubhn - arm_neon_vshiftins, // llvm.arm.neon.vshiftins - arm_neon_vshifts, // llvm.arm.neon.vshifts - arm_neon_vshiftu, // llvm.arm.neon.vshiftu - arm_neon_vst1, // llvm.arm.neon.vst1 - arm_neon_vst1x2, // llvm.arm.neon.vst1x2 - arm_neon_vst1x3, // llvm.arm.neon.vst1x3 - arm_neon_vst1x4, // llvm.arm.neon.vst1x4 - arm_neon_vst2, // llvm.arm.neon.vst2 - arm_neon_vst2lane, // llvm.arm.neon.vst2lane - arm_neon_vst3, // llvm.arm.neon.vst3 - arm_neon_vst3lane, // llvm.arm.neon.vst3lane - arm_neon_vst4, // llvm.arm.neon.vst4 - arm_neon_vst4lane, // llvm.arm.neon.vst4lane - arm_neon_vtbl1, // llvm.arm.neon.vtbl1 - arm_neon_vtbl2, // llvm.arm.neon.vtbl2 - arm_neon_vtbl3, // llvm.arm.neon.vtbl3 - arm_neon_vtbl4, // llvm.arm.neon.vtbl4 - arm_neon_vtbx1, // llvm.arm.neon.vtbx1 - arm_neon_vtbx2, // llvm.arm.neon.vtbx2 - arm_neon_vtbx3, // llvm.arm.neon.vtbx3 - arm_neon_vtbx4, // llvm.arm.neon.vtbx4 - arm_qadd, // llvm.arm.qadd - arm_qadd16, // llvm.arm.qadd16 - arm_qadd8, // llvm.arm.qadd8 - arm_qasx, // llvm.arm.qasx - arm_qsax, // llvm.arm.qsax - arm_qsub, // llvm.arm.qsub - arm_qsub16, // llvm.arm.qsub16 - arm_qsub8, // llvm.arm.qsub8 - arm_sadd16, // llvm.arm.sadd16 - arm_sadd8, // llvm.arm.sadd8 - arm_sasx, // llvm.arm.sasx - arm_sel, // llvm.arm.sel - arm_set_fpscr, // llvm.arm.set.fpscr - arm_shadd16, // llvm.arm.shadd16 - arm_shadd8, // llvm.arm.shadd8 - arm_shasx, // llvm.arm.shasx - arm_shsax, // llvm.arm.shsax - arm_shsub16, // llvm.arm.shsub16 - arm_shsub8, // llvm.arm.shsub8 - arm_smlabb, // llvm.arm.smlabb - arm_smlabt, // llvm.arm.smlabt - arm_smlad, // llvm.arm.smlad - arm_smladx, // llvm.arm.smladx - arm_smlald, // llvm.arm.smlald - arm_smlaldx, // llvm.arm.smlaldx - arm_smlatb, // llvm.arm.smlatb - arm_smlatt, // llvm.arm.smlatt - arm_smlawb, // llvm.arm.smlawb - arm_smlawt, // llvm.arm.smlawt - arm_smlsd, // llvm.arm.smlsd - arm_smlsdx, // llvm.arm.smlsdx - arm_smlsld, // llvm.arm.smlsld - arm_smlsldx, // llvm.arm.smlsldx - arm_smuad, // llvm.arm.smuad - arm_smuadx, // llvm.arm.smuadx - arm_smulbb, // llvm.arm.smulbb - arm_smulbt, // llvm.arm.smulbt - arm_smultb, // llvm.arm.smultb - arm_smultt, // llvm.arm.smultt - arm_smulwb, // llvm.arm.smulwb - arm_smulwt, // llvm.arm.smulwt - arm_smusd, // llvm.arm.smusd - arm_smusdx, // llvm.arm.smusdx - arm_space, // llvm.arm.space - arm_ssat, // llvm.arm.ssat - arm_ssat16, // llvm.arm.ssat16 - arm_ssax, // llvm.arm.ssax - arm_ssub16, // llvm.arm.ssub16 - arm_ssub8, // llvm.arm.ssub8 - arm_stc, // llvm.arm.stc - arm_stc2, // llvm.arm.stc2 - arm_stc2l, // llvm.arm.stc2l - arm_stcl, // llvm.arm.stcl - arm_stlex, // llvm.arm.stlex - arm_stlexd, // llvm.arm.stlexd - arm_strex, // llvm.arm.strex - arm_strexd, // llvm.arm.strexd - arm_sxtab16, // llvm.arm.sxtab16 - arm_sxtb16, // llvm.arm.sxtb16 - arm_uadd16, // llvm.arm.uadd16 - arm_uadd8, // llvm.arm.uadd8 - arm_uasx, // llvm.arm.uasx - arm_uhadd16, // llvm.arm.uhadd16 - arm_uhadd8, // llvm.arm.uhadd8 - arm_uhasx, // llvm.arm.uhasx - arm_uhsax, // llvm.arm.uhsax - arm_uhsub16, // llvm.arm.uhsub16 - arm_uhsub8, // llvm.arm.uhsub8 - arm_undefined, // llvm.arm.undefined - arm_uqadd16, // llvm.arm.uqadd16 - arm_uqadd8, // llvm.arm.uqadd8 - arm_uqasx, // llvm.arm.uqasx - arm_uqsax, // llvm.arm.uqsax - arm_uqsub16, // llvm.arm.uqsub16 - arm_uqsub8, // llvm.arm.uqsub8 - arm_usad8, // llvm.arm.usad8 - arm_usada8, // llvm.arm.usada8 - arm_usat, // llvm.arm.usat - arm_usat16, // llvm.arm.usat16 - arm_usax, // llvm.arm.usax - arm_usub16, // llvm.arm.usub16 - arm_usub8, // llvm.arm.usub8 - arm_uxtab16, // llvm.arm.uxtab16 - arm_uxtb16, // llvm.arm.uxtb16 - arm_vcvtr, // llvm.arm.vcvtr - arm_vcvtru, // llvm.arm.vcvtru -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.td deleted file mode 100644 index ab5f6023fa..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsARM.td +++ /dev/null @@ -1,1390 +0,0 @@ -//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the ARM-specific intrinsics. -// -//===----------------------------------------------------------------------===// - - -//===----------------------------------------------------------------------===// -// TLS - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - -// A space-consuming intrinsic primarily for testing ARMConstantIslands. The -// first argument is the number of bytes this "instruction" takes up, the second -// and return value are essentially chains, used to force ordering during ISel. -def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [ImmArg>]>; - -// 16-bit multiplications -def int_arm_smulbb : GCCBuiltin<"__builtin_arm_smulbb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smulbt : GCCBuiltin<"__builtin_arm_smulbt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smultb : GCCBuiltin<"__builtin_arm_smultb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smultt : GCCBuiltin<"__builtin_arm_smultt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smulwb : GCCBuiltin<"__builtin_arm_smulwb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smulwt : GCCBuiltin<"__builtin_arm_smulwt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Saturating Arithmetic - -def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [Commutative, IntrNoMem]>; -def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - -// Accumulating multiplications -def int_arm_smlabb : GCCBuiltin<"__builtin_arm_smlabb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlabt : GCCBuiltin<"__builtin_arm_smlabt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlatb : GCCBuiltin<"__builtin_arm_smlatb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlatt : GCCBuiltin<"__builtin_arm_smlatt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlawb : GCCBuiltin<"__builtin_arm_smlawb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlawt : GCCBuiltin<"__builtin_arm_smlawt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -// Parallel 16-bit saturation -def int_arm_ssat16 : GCCBuiltin<"__builtin_arm_ssat16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_usat16 : GCCBuiltin<"__builtin_arm_usat16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - -// Packing and unpacking -def int_arm_sxtab16 : GCCBuiltin<"__builtin_arm_sxtab16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_sxtb16 : GCCBuiltin<"__builtin_arm_sxtb16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_uxtab16 : GCCBuiltin<"__builtin_arm_uxtab16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uxtb16 : GCCBuiltin<"__builtin_arm_uxtb16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; - -// Parallel selection, reads the GE flags. -def int_arm_sel : GCCBuiltin<"__builtin_arm_sel">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadMem]>; - -// Parallel 8-bit addition and subtraction -def int_arm_qadd8 : GCCBuiltin<"__builtin_arm_qadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_qsub8 : GCCBuiltin<"__builtin_arm_qsub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_sadd8 : GCCBuiltin<"__builtin_arm_sadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -def int_arm_shadd8 : GCCBuiltin<"__builtin_arm_shadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_shsub8 : GCCBuiltin<"__builtin_arm_shsub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_ssub8 : GCCBuiltin<"__builtin_arm_ssub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_uadd8 : GCCBuiltin<"__builtin_arm_uadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -def int_arm_uhadd8 : GCCBuiltin<"__builtin_arm_uhadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uhsub8 : GCCBuiltin<"__builtin_arm_uhsub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqadd8 : GCCBuiltin<"__builtin_arm_uqadd8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqsub8 : GCCBuiltin<"__builtin_arm_uqsub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_usub8 : GCCBuiltin<"__builtin_arm_usub8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; - -// Sum of 8-bit absolute differences -def int_arm_usad8 : GCCBuiltin<"__builtin_arm_usad8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_usada8 : GCCBuiltin<"__builtin_arm_usada8">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -// Parallel 16-bit addition and subtraction -def int_arm_qadd16 : GCCBuiltin<"__builtin_arm_qadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_qasx : GCCBuiltin<"__builtin_arm_qasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_qsax : GCCBuiltin<"__builtin_arm_qsax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_qsub16 : GCCBuiltin<"__builtin_arm_qsub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_sadd16 : GCCBuiltin<"__builtin_arm_sadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_sasx : GCCBuiltin<"__builtin_arm_sasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -def int_arm_shadd16 : GCCBuiltin<"__builtin_arm_shadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_shasx : GCCBuiltin<"__builtin_arm_shasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_shsax : GCCBuiltin<"__builtin_arm_shsax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_shsub16 : GCCBuiltin<"__builtin_arm_shsub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_ssax : GCCBuiltin<"__builtin_arm_ssax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_ssub16 : GCCBuiltin<"__builtin_arm_ssub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_uadd16 : GCCBuiltin<"__builtin_arm_uadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_uasx : GCCBuiltin<"__builtin_arm_uasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -def int_arm_uhadd16 : GCCBuiltin<"__builtin_arm_uhadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uhasx : GCCBuiltin<"__builtin_arm_uhasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uhsax : GCCBuiltin<"__builtin_arm_uhsax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uhsub16 : GCCBuiltin<"__builtin_arm_uhsub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqadd16 : GCCBuiltin<"__builtin_arm_uqadd16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqasx : GCCBuiltin<"__builtin_arm_uqasx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqsax : GCCBuiltin<"__builtin_arm_uqsax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_uqsub16 : GCCBuiltin<"__builtin_arm_uqsub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -// Writes to the GE bits. -def int_arm_usax : GCCBuiltin<"__builtin_arm_usax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -// Writes to the GE bits. -def int_arm_usub16 : GCCBuiltin<"__builtin_arm_usub16">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; - -// Parallel 16-bit multiplication -def int_arm_smlad : GCCBuiltin<"__builtin_arm_smlad">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smladx : GCCBuiltin<"__builtin_arm_smladx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlald : GCCBuiltin<"__builtin_arm_smlald">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_arm_smlaldx : GCCBuiltin<"__builtin_arm_smlaldx">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_arm_smlsd : GCCBuiltin<"__builtin_arm_smlsd">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlsdx : GCCBuiltin<"__builtin_arm_smlsdx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_smlsld : GCCBuiltin<"__builtin_arm_smlsld">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_arm_smlsldx : GCCBuiltin<"__builtin_arm_smlsldx">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; -def int_arm_smuad : GCCBuiltin<"__builtin_arm_smuad">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smuadx : GCCBuiltin<"__builtin_arm_smuadx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smusd : GCCBuiltin<"__builtin_arm_smusd">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_arm_smusdx : GCCBuiltin<"__builtin_arm_smusdx">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - - -//===----------------------------------------------------------------------===// -// Load, Store and Clear exclusive - -def int_arm_ldrex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; -def int_arm_strex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; - -def int_arm_ldaex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; -def int_arm_stlex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; - -def int_arm_clrex : Intrinsic<[]>; - -def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty]>; -def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; - -def int_arm_stlexd : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>; -def int_arm_ldaexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; - -//===----------------------------------------------------------------------===// -// Data barrier instructions -def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, MSBuiltin<"__dmb">, - Intrinsic<[], [llvm_i32_ty]>; -def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, MSBuiltin<"__dsb">, - Intrinsic<[], [llvm_i32_ty]>; -def int_arm_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">, - Intrinsic<[], [llvm_i32_ty]>; - -//===----------------------------------------------------------------------===// -// VFP - -def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, - Intrinsic<[llvm_i32_ty], [], []>; -def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">, - Intrinsic<[], [llvm_i32_ty], []>; -def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], - [IntrNoMem]>; -def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], - [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Coprocessor - -def int_arm_ldc : GCCBuiltin<"__builtin_arm_ldc">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_ldcl : GCCBuiltin<"__builtin_arm_ldcl">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_ldc2 : GCCBuiltin<"__builtin_arm_ldc2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_ldc2l : GCCBuiltin<"__builtin_arm_ldc2l">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; - -def int_arm_stc : GCCBuiltin<"__builtin_arm_stc">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_stcl : GCCBuiltin<"__builtin_arm_stcl">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_stc2 : GCCBuiltin<"__builtin_arm_stc2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; -def int_arm_stc2l : GCCBuiltin<"__builtin_arm_stc2l">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg>, ImmArg>]>; - -// Move to coprocessor -def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; -def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; - -// Move from coprocessor -def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, - MSBuiltin<"_MoveFromCoprocessor">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; -def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, - MSBuiltin<"_MoveFromCoprocessor2">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; - -// Coprocessor data processing -def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; -def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; - -// Move from two registers to coprocessor -def int_arm_mcrr : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>]>; -def int_arm_mcrr2 : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>]>; - -def int_arm_mrrc : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>]>; -def int_arm_mrrc2 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>, ImmArg>]>; - -//===----------------------------------------------------------------------===// -// CRC32 - -def int_arm_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// CMSE - -def int_arm_cmse_tt : GCCBuiltin<"__builtin_arm_cmse_TT">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; -def int_arm_cmse_ttt : GCCBuiltin<"__builtin_arm_cmse_TTT">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; -def int_arm_cmse_tta : GCCBuiltin<"__builtin_arm_cmse_TTA">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; -def int_arm_cmse_ttat : GCCBuiltin<"__builtin_arm_cmse_TTAT">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// HINT - -def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; -def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>; - -//===----------------------------------------------------------------------===// -// UND (reserved undefined sequence) - -def int_arm_undefined : Intrinsic<[], [llvm_i32_ty]>; - -//===----------------------------------------------------------------------===// -// Advanced SIMD (NEON) - -// The following classes do not correspond directly to GCC builtins. -class Neon_1Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; -class Neon_1Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>], [IntrNoMem]>; -class Neon_2Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; -class Neon_2Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>, LLVMExtendedType<0>], - [IntrNoMem]>; -class Neon_2Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMTruncatedType<0>, LLVMTruncatedType<0>], - [IntrNoMem]>; -class Neon_3Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; -class Neon_3Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMTruncatedType<0>, LLVMTruncatedType<0>], - [IntrNoMem]>; - -class Neon_1FloatArg_Intrinsic - : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -class Neon_CvtFxToFP_Intrinsic - : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; -class Neon_CvtFPToFx_Intrinsic - : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; -class Neon_CvtFPtoInt_1Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -class Neon_Compare_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem]>; - -// The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. -// Besides the table, VTBL has one other v8i8 argument and VTBX has two. -// Overall, the classes range from 2 to 6 v8i8 arguments. -class Neon_Tbl2Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; -class Neon_Tbl3Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; -class Neon_Tbl4Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], - [IntrNoMem]>; -class Neon_Tbl5Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; -class Neon_Tbl6Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; - -// Arithmetic ops - -let IntrProperties = [IntrNoMem, Commutative] in { - - // Vector Add. - def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; - def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; - def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; - def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; - def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; - - // Vector Multiply. - def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; - def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; - def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; - def int_arm_neon_vmulls : Neon_2Arg_Long_Intrinsic; - def int_arm_neon_vmullu : Neon_2Arg_Long_Intrinsic; - def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; - def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; - - // Vector Maximum. - def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; - def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; - def int_arm_neon_vmaxnm : Neon_2Arg_Intrinsic; - - // Vector Minimum. - def int_arm_neon_vmins : Neon_2Arg_Intrinsic; - def int_arm_neon_vminu : Neon_2Arg_Intrinsic; - def int_arm_neon_vminnm : Neon_2Arg_Intrinsic; - - // Vector Reciprocal Step. - def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; - - // Vector Reciprocal Square Root Step. - def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; -} - -// Vector Subtract. -def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; -def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; -def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; - -// Vector Absolute Compare. -def int_arm_neon_vacge : Neon_Compare_Intrinsic; -def int_arm_neon_vacgt : Neon_Compare_Intrinsic; - -// Vector Absolute Differences. -def int_arm_neon_vabds : Neon_2Arg_Intrinsic; -def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; - -// Vector Pairwise Add. -def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; - -// Vector Pairwise Add Long. -// Note: This is different than the other "long" NEON intrinsics because -// the result vector has half as many elements as the source vector. -// The source and destination vector types must be specified separately. -def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], - [IntrNoMem]>; -def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], - [IntrNoMem]>; - -// Vector Pairwise Add and Accumulate Long. -// Note: This is similar to vpaddl but the destination vector also appears -// as the first argument. -def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; -def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; - -// Vector Pairwise Maximum and Minimum. -def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; -def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; -def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; -def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; - -// Vector Shifts: -// -// The various saturating and rounding vector shift operations need to be -// represented by intrinsics in LLVM, and even the basic VSHL variable shift -// operation cannot be safely translated to LLVM's shift operators. VSHL can -// be used for both left and right shifts, or even combinations of the two, -// depending on the signs of the shift amounts. It also has well-defined -// behavior for shift amounts that LLVM leaves undefined. Only basic shifts -// by constants can be represented with LLVM's shift operators. -// -// The shift counts for these intrinsics are always vectors, even for constant -// shifts, where the constant is replicated. For consistency with VSHL (and -// other variable shift instructions), left shifts have positive shift counts -// and right shifts have negative shift counts. This convention is also used -// for constant right shift intrinsics, and to help preserve sanity, the -// intrinsic names use "shift" instead of either "shl" or "shr". Where -// applicable, signed and unsigned versions of the intrinsics are -// distinguished with "s" and "u" suffixes. A few NEON shift instructions, -// such as VQSHLU, take signed operands but produce unsigned results; these -// use a "su" suffix. - -// Vector Shift. -def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; - -// Vector Rounding Shift. -def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; - -// Vector Saturating Shift. -def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; - -// Vector Saturating Rounding Shift. -def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; - -// Vector Shift and Insert. -def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; - -// Vector Absolute Value and Saturating Absolute Value. -def int_arm_neon_vabs : Neon_1Arg_Intrinsic; -def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; - -// Vector Saturating Negate. -def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; - -// Vector Count Leading Sign/Zero Bits. -def int_arm_neon_vcls : Neon_1Arg_Intrinsic; - -// Vector Reciprocal Estimate. -def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; - -// Vector Reciprocal Square Root Estimate. -def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; - -// Vector Conversions Between Floating-point and Integer -def int_arm_neon_vcvtau : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtas : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtnu : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtns : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtpu : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtps : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtmu : Neon_CvtFPtoInt_1Arg_Intrinsic; -def int_arm_neon_vcvtms : Neon_CvtFPtoInt_1Arg_Intrinsic; - -// Vector Conversions Between Floating-point and Fixed-point. -def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; -def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; -def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; -def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; - -// Vector Conversions Between Half-Precision and Single-Precision. -def int_arm_neon_vcvtfp2hf - : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_arm_neon_vcvthf2fp - : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; - -// Narrowing Saturating Vector Moves. -def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; -def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; -def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; - -// Vector Table Lookup. -// The first 1-4 arguments are the table. -def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; -def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; -def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; -def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; - -// Vector Table Extension. -// Some elements of the destination vector may not be updated, so the original -// value of that vector is passed as the first argument. The next 1-4 -// arguments after that are the table. -def int_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; -def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; -def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; -def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; - -// Vector and Scalar Rounding. -def int_arm_neon_vrintn : Neon_1FloatArg_Intrinsic; -def int_arm_neon_vrintx : Neon_1Arg_Intrinsic; -def int_arm_neon_vrinta : Neon_1Arg_Intrinsic; -def int_arm_neon_vrintz : Neon_1Arg_Intrinsic; -def int_arm_neon_vrintm : Neon_1Arg_Intrinsic; -def int_arm_neon_vrintp : Neon_1Arg_Intrinsic; - -// De-interleaving vector loads from N-element structures. -// Source operands are the address and alignment. -def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - -def int_arm_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMAnyPointerType>], - [IntrReadMem, IntrArgMemOnly]>; - -// Vector load N-element structure to one lane. -// Source operands are: the address, the N input vectors (since only one -// lane is assigned), the lane number, and the alignment. -def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_anyptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_anyptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_anyptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; - -// Vector load N-element structure to all lanes. -// Source operands are the address and alignment. -def int_arm_neon_vld2dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld3dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_neon_vld4dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_anyptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - -// Interleaving vector stores from N-element structures. -// Source operands are: the address, the N vectors, and the alignment. -def int_arm_neon_vst1 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - llvm_i32_ty], [IntrArgMemOnly]>; -def int_arm_neon_vst2 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_arm_neon_vst3 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>, - llvm_i32_ty], [IntrArgMemOnly]>; -def int_arm_neon_vst4 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>, llvm_i32_ty], - [IntrArgMemOnly]>; - -def int_arm_neon_vst1x2 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>], - [IntrArgMemOnly, NoCapture>]>; -def int_arm_neon_vst1x3 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>], - [IntrArgMemOnly, NoCapture>]>; -def int_arm_neon_vst1x4 : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>], - [IntrArgMemOnly, NoCapture>]>; - -// Vector store N-element structure from one lane. -// Source operands are: the address, the N vectors, the lane number, and -// the alignment. -def int_arm_neon_vst2lane : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, llvm_i32_ty, - llvm_i32_ty], [IntrArgMemOnly]>; -def int_arm_neon_vst3lane : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>, - llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_arm_neon_vst4lane : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyvector_ty, - LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>, llvm_i32_ty, - llvm_i32_ty], [IntrArgMemOnly]>; - -// Vector bitwise select. -def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - - -// Crypto instructions -class AES_1Arg_Intrinsic : Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty], [IntrNoMem]>; -class AES_2Arg_Intrinsic : Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - -class SHA_1Arg_Intrinsic : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], - [IntrNoMem]>; -class SHA_2Arg_Intrinsic : Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -class SHA_3Arg_i32_Intrinsic : Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -class SHA_3Arg_v4i32_Intrinsic : Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - -def int_arm_neon_aesd : AES_2Arg_Intrinsic; -def int_arm_neon_aese : AES_2Arg_Intrinsic; -def int_arm_neon_aesimc : AES_1Arg_Intrinsic; -def int_arm_neon_aesmc : AES_1Arg_Intrinsic; -def int_arm_neon_sha1h : SHA_1Arg_Intrinsic; -def int_arm_neon_sha1su1 : SHA_2Arg_Intrinsic; -def int_arm_neon_sha256su0 : SHA_2Arg_Intrinsic; -def int_arm_neon_sha1c : SHA_3Arg_i32_Intrinsic; -def int_arm_neon_sha1m : SHA_3Arg_i32_Intrinsic; -def int_arm_neon_sha1p : SHA_3Arg_i32_Intrinsic; -def int_arm_neon_sha1su0: SHA_3Arg_v4i32_Intrinsic; -def int_arm_neon_sha256h: SHA_3Arg_v4i32_Intrinsic; -def int_arm_neon_sha256h2: SHA_3Arg_v4i32_Intrinsic; -def int_arm_neon_sha256su1: SHA_3Arg_v4i32_Intrinsic; - -def int_arm_neon_vqrdmlah : Neon_3Arg_Intrinsic; -def int_arm_neon_vqrdmlsh : Neon_3Arg_Intrinsic; - -// Armv8.2-A dot product instructions -class Neon_Dot_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - LLVMMatchType<1>], - [IntrNoMem]>; -def int_arm_neon_udot : Neon_Dot_Intrinsic; -def int_arm_neon_sdot : Neon_Dot_Intrinsic; - -// v8.6-A Matrix Multiply Intrinsics -class Neon_MatMul_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - LLVMMatchType<1>], - [IntrNoMem]>; -def int_arm_neon_ummla : Neon_MatMul_Intrinsic; -def int_arm_neon_smmla : Neon_MatMul_Intrinsic; -def int_arm_neon_usmmla : Neon_MatMul_Intrinsic; -def int_arm_neon_usdot : Neon_Dot_Intrinsic; - -// v8.6-A Bfloat Intrinsics -def int_arm_neon_vcvtfp2bf - : Intrinsic<[llvm_anyvector_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_arm_neon_vcvtbfp2bf - : Intrinsic<[llvm_bfloat_ty], [llvm_float_ty], [IntrNoMem]>; - -def int_arm_neon_bfdot : Neon_Dot_Intrinsic; -def int_arm_neon_bfmmla - : Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v8bf16_ty, llvm_v8bf16_ty], - [IntrNoMem]>; - -class Neon_BF16FML_Intrinsic - : Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v8bf16_ty, llvm_v8bf16_ty], - [IntrNoMem]>; -def int_arm_neon_bfmlalb : Neon_BF16FML_Intrinsic; -def int_arm_neon_bfmlalt : Neon_BF16FML_Intrinsic; - -def int_arm_cls: Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_cls64: Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>; - -def int_arm_mve_vctp8 : Intrinsic<[llvm_v16i1_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_vctp16 : Intrinsic<[llvm_v8i1_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_vctp32 : Intrinsic<[llvm_v4i1_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_vctp64 : Intrinsic<[llvm_v2i1_ty], [llvm_i32_ty], [IntrNoMem]>; - -// v8.3-A Floating-point complex add -def int_arm_neon_vcadd_rot90 : Neon_2Arg_Intrinsic; -def int_arm_neon_vcadd_rot270 : Neon_2Arg_Intrinsic; - -// GNU eabi mcount -def int_arm_gnu_eabi_mcount : Intrinsic<[], [], []>; - -def int_arm_mve_pred_i2v : Intrinsic< - [llvm_anyvector_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_pred_v2i : Intrinsic< - [llvm_i32_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_arm_mve_vreinterpretq : Intrinsic< - [llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -def int_arm_mve_min_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_max_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_abd_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_add_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_and_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_bic_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_eor_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_orn_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_orr_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_sub_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_mul_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_mulh_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_qdmulh_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_rmulh_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_qrdmulh_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_mull_int_predicated: Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty /* unsigned */, - llvm_i32_ty /* top */, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_mull_poly_predicated: Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty, llvm_anyvector_ty, - LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_qadd_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_hadd_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_rhadd_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_qsub_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_hsub_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_vmina_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; -def int_arm_mve_vmaxa_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; -def int_arm_mve_vminnma_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; -def int_arm_mve_vmaxnma_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; - -multiclass MVEPredicated rets, list params, - LLVMType pred = llvm_anyvector_ty, - list props = [IntrNoMem], - list sdprops = []> { - def "": Intrinsic; - def _predicated: Intrinsic; -} -multiclass MVEPredicatedM rets, list params, - LLVMType pred = llvm_anyvector_ty, - list props = [IntrNoMem]> { - def "": Intrinsic; - def _predicated: Intrinsic, rets[0])], props>; -} - -multiclass MVE_minmaxv { - defm v: MVEPredicated<[llvm_i32_ty], - [llvm_i32_ty, llvm_anyvector_ty, llvm_i32_ty /* unsigned */]>; - defm av: MVEPredicated<[llvm_i32_ty], - [llvm_i32_ty, llvm_anyvector_ty]>; - defm nmv: MVEPredicated<[llvm_anyfloat_ty], - [LLVMMatchType<0>, llvm_anyvector_ty]>; - defm nmav: MVEPredicated<[llvm_anyfloat_ty], - [LLVMMatchType<0>, llvm_anyvector_ty]>; -} -defm int_arm_mve_min: MVE_minmaxv; -defm int_arm_mve_max: MVE_minmaxv; - -defm int_arm_mve_addv: MVEPredicated<[llvm_i32_ty], - [llvm_anyvector_ty, llvm_i32_ty /* unsigned */]>; -defm int_arm_mve_addlv: MVEPredicated<[llvm_i64_ty], - [llvm_anyvector_ty, llvm_i32_ty /* unsigned */]>; - -// Intrinsic with a predicated and a non-predicated case. The predicated case -// has two additional parameters: inactive (the value for inactive lanes, can -// be undef) and predicate. -multiclass MVEMXPredicated rets, list flags, - list params, LLVMType inactive, - LLVMType predicate, - list props = [IntrNoMem]> { - def "": Intrinsic; - def _predicated: Intrinsic; -} - -defm int_arm_mve_vcvt_narrow: MVEPredicated<[llvm_v8f16_ty], - [llvm_v8f16_ty, llvm_v4f32_ty, llvm_i32_ty], llvm_v4i1_ty>; -defm int_arm_mve_vcvt_widen: MVEMXPredicated<[llvm_v4f32_ty], [], - [llvm_v8f16_ty, llvm_i32_ty], llvm_v4f32_ty, llvm_v4i1_ty>; - -defm int_arm_mve_vldr_gather_base: MVEPredicated< - [llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty], - llvm_anyvector_ty, [IntrReadMem], [SDNPMemOperand]>; -defm int_arm_mve_vldr_gather_base_wb: MVEPredicated< - [llvm_anyvector_ty, llvm_anyvector_ty], - [LLVMMatchType<1>, llvm_i32_ty], llvm_anyvector_ty, [IntrReadMem], - [SDNPMemOperand]>; -defm int_arm_mve_vstr_scatter_base: MVEPredicated< - [], [llvm_anyvector_ty, llvm_i32_ty, llvm_anyvector_ty], - llvm_anyvector_ty, [IntrWriteMem], [SDNPMemOperand]>; -defm int_arm_mve_vstr_scatter_base_wb: MVEPredicated< - [llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty, llvm_anyvector_ty], - llvm_anyvector_ty, [IntrWriteMem], [SDNPMemOperand]>; - -// gather_offset takes three i32 parameters. The first is the size of -// memory element loaded, in bits. The second is a left bit shift to -// apply to each offset in the vector parameter (must be either 0, or -// correspond to the element size of the destination vector type). The -// last is 1 to indicate zero extension (if the load is widening), or -// 0 for sign extension. -// -// scatter_offset has the first two of those parameters, but since it -// narrows rather than widening, it doesn't have the last one. -defm int_arm_mve_vldr_gather_offset: MVEPredicated< - [llvm_anyvector_ty], [llvm_anyptr_ty, llvm_anyvector_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], llvm_anyvector_ty, [IntrReadMem], - [SDNPMemOperand]>; -defm int_arm_mve_vstr_scatter_offset: MVEPredicated< - [], [llvm_anyptr_ty, llvm_anyvector_ty, llvm_anyvector_ty, - llvm_i32_ty, llvm_i32_ty], llvm_anyvector_ty, [IntrWriteMem], - [SDNPMemOperand]>; - -def int_arm_mve_shl_imm_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; -def int_arm_mve_shr_imm_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, // extra i32 is unsigned flag - llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; - -defm int_arm_mve_vqshl_imm: MVEPredicatedM<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /*shiftcount*/, llvm_i32_ty /*unsigned*/]>; -defm int_arm_mve_vrshr_imm: MVEPredicatedM<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /*shiftcount*/, llvm_i32_ty /*unsigned*/]>; -defm int_arm_mve_vqshlu_imm: MVEPredicatedM<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /*shiftcount*/]>; -defm int_arm_mve_vshll_imm: MVEPredicatedM<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_i32_ty /*shiftcount*/, llvm_i32_ty /*unsigned*/, - llvm_i32_ty /*top-half*/]>; - -defm int_arm_mve_vsli: MVEPredicated< - [llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty]>; -defm int_arm_mve_vsri: MVEPredicated< - [llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty]>; - -defm int_arm_mve_vshrn: MVEPredicated< - [llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i32_ty /*shiftcount*/, llvm_i32_ty /*saturate*/, llvm_i32_ty /*round*/, - llvm_i32_ty /*unsigned-out*/, llvm_i32_ty /*unsigned-in*/, - llvm_i32_ty /*top-half*/]>; - -defm int_arm_mve_vshl_scalar: MVEPredicated< - [llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty /*shiftcount*/, - llvm_i32_ty /*saturate*/, llvm_i32_ty /*round*/, llvm_i32_ty /*unsigned*/]>; -defm int_arm_mve_vshl_vector: MVEPredicatedM< - [llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty /*shiftcounts*/, - llvm_i32_ty /*saturate*/, llvm_i32_ty /*round*/, llvm_i32_ty /*unsigned*/]>; - -// MVE scalar shifts. -class ARM_MVE_qrshift_single value, - list saturate = []> : - Intrinsic; -multiclass ARM_MVE_qrshift saturate = []> { - // Most of these shifts come in 32- and 64-bit versions. But only - // the 64-bit ones have the extra saturation argument (if any). - def "": ARM_MVE_qrshift_single<[llvm_i32_ty]>; - def l: ARM_MVE_qrshift_single<[llvm_i32_ty, llvm_i32_ty], saturate>; -} -defm int_arm_mve_urshr: ARM_MVE_qrshift; -defm int_arm_mve_uqshl: ARM_MVE_qrshift; -defm int_arm_mve_srshr: ARM_MVE_qrshift; -defm int_arm_mve_sqshl: ARM_MVE_qrshift; -defm int_arm_mve_uqrshl: ARM_MVE_qrshift<[llvm_i32_ty]>; -defm int_arm_mve_sqrshr: ARM_MVE_qrshift<[llvm_i32_ty]>; -// LSLL and ASRL only have 64-bit versions, not 32. -def int_arm_mve_lsll: ARM_MVE_qrshift_single<[llvm_i32_ty, llvm_i32_ty]>; -def int_arm_mve_asrl: ARM_MVE_qrshift_single<[llvm_i32_ty, llvm_i32_ty]>; - -def int_arm_mve_vabd: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vadc: Intrinsic< - [llvm_anyvector_ty, llvm_i32_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_vsbc: Intrinsic< - [llvm_anyvector_ty, llvm_i32_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; -def int_arm_mve_vadc_predicated: Intrinsic< - [llvm_anyvector_ty, llvm_i32_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty, llvm_anyvector_ty], [IntrNoMem]>; -def int_arm_mve_vsbc_predicated: Intrinsic< - [llvm_anyvector_ty, llvm_i32_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty, llvm_anyvector_ty], [IntrNoMem]>; -def int_arm_mve_vshlc: Intrinsic< - [llvm_i32_ty /* bits shifted out */, llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /* bits shifted in */, - llvm_i32_ty /* shift count */], [IntrNoMem]>; -def int_arm_mve_vshlc_predicated: Intrinsic< - [llvm_i32_ty /* bits shifted out */, llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /* bits shifted in */, - llvm_i32_ty /* shift count */, llvm_anyvector_ty], [IntrNoMem]>; -def int_arm_mve_vmulh: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vqdmulh: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_vhadd: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vrhadd: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vhsub: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vrmulh: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */], - [IntrNoMem]>; -def int_arm_mve_vqrdmulh: Intrinsic< - [llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_vmull: Intrinsic< - [llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty /* unsigned */, - llvm_i32_ty /* top */], [IntrNoMem]>; -def int_arm_mve_vmull_poly: Intrinsic< - [llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty], [IntrNoMem]>; - -// The first two parameters are compile-time constants: -// * Halving: 0 means halving (vhcaddq), 1 means non-halving (vcaddq) -// instruction. Note: the flag is inverted to match the corresponding -// bit in the instruction encoding -// * Rotation angle: 0 mean 90 deg, 1 means 180 deg -defm int_arm_mve_vcaddq : MVEMXPredicated< - [llvm_anyvector_ty], - [llvm_i32_ty, llvm_i32_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - LLVMMatchType<0>, llvm_anyvector_ty>; - -// The first operand of the following two intrinsics is the rotation angle -// (must be a compile-time constant): -// 0 - 0 deg -// 1 - 90 deg -// 2 - 180 deg -// 3 - 270 deg -defm int_arm_mve_vcmulq : MVEMXPredicated< - [llvm_anyvector_ty], - [llvm_i32_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - LLVMMatchType<0>, llvm_anyvector_ty>; - -defm int_arm_mve_vcmlaq : MVEPredicated< - [llvm_anyvector_ty], - [llvm_i32_ty, LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - llvm_anyvector_ty>; - -def int_arm_mve_vld2q: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], [llvm_anyptr_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_arm_mve_vld4q: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [llvm_anyptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - -def int_arm_mve_vst2q: Intrinsic<[], [llvm_anyptr_ty, llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], "", [SDNPMemOperand]>; -def int_arm_mve_vst4q: Intrinsic<[], [llvm_anyptr_ty, llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, LLVMMatchType<1>, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], "", [SDNPMemOperand]>; - -// MVE vector absolute difference and accumulate across vector -// The first operand is an 'unsigned' flag. The remaining operands are: -// * accumulator -// * first vector operand -// * second vector operand -// * mask (only in predicated versions) -defm int_arm_mve_vabav: MVEPredicated< - [llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>], llvm_anyvector_ty>; - -// The following 3 intrinsics are MVE vector reductions with two vector -// operands. -// The first 3 operands are boolean flags (must be compile-time constants): -// * unsigned - the instruction operates on vectors of unsigned values and -// unsigned scalars -// * subtract - the instruction performs subtraction after multiplication of -// lane pairs (e.g., vmlsdav vs vmladav) -// * exchange - the instruction exchanges successive even and odd lanes of -// the first operands before multiplication of lane pairs -// (e.g., vmladavx vs vmladav) -// The remaining operands are: -// * accumulator -// * first vector operand -// * second vector operand -// * mask (only in predicated versions) - -// Version with 32-bit result, vml{a,s}dav[a][x] -defm int_arm_mve_vmldava: MVEPredicated< - [llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>], - llvm_anyvector_ty>; - -// Version with 64-bit result, vml{a,s}ldav[a][x] -defm int_arm_mve_vmlldava: MVEPredicated< - [llvm_i32_ty, llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>], - llvm_anyvector_ty>; - -// Version with 72-bit rounded result, vrml{a,s}ldavh[a][x] -defm int_arm_mve_vrmlldavha: MVEPredicated< - [llvm_i32_ty, llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>], - llvm_anyvector_ty>; - -defm int_arm_mve_vidup: MVEMXPredicated< - [llvm_anyvector_ty /* output */, llvm_i32_ty /* written-back base */], [], - [llvm_i32_ty /* base */, llvm_i32_ty /* step */], - LLVMMatchType<0>, llvm_anyvector_ty>; -defm int_arm_mve_vddup: MVEMXPredicated< - [llvm_anyvector_ty /* output */, llvm_i32_ty /* written-back base */], [], - [llvm_i32_ty /* base */, llvm_i32_ty /* step */], - LLVMMatchType<0>, llvm_anyvector_ty>; -defm int_arm_mve_viwdup: MVEMXPredicated< - [llvm_anyvector_ty /* output */, llvm_i32_ty /* written-back base */], [], - [llvm_i32_ty /* base */, llvm_i32_ty /* limit */, llvm_i32_ty /* step */], - LLVMMatchType<0>, llvm_anyvector_ty>; -defm int_arm_mve_vdwdup: MVEMXPredicated< - [llvm_anyvector_ty /* output */, llvm_i32_ty /* written-back base */], [], - [llvm_i32_ty /* base */, llvm_i32_ty /* limit */, llvm_i32_ty /* step */], - LLVMMatchType<0>, llvm_anyvector_ty>; - -// Flags: -// * unsigned -defm int_arm_mve_vcvt_fix: MVEMXPredicated< - [llvm_anyvector_ty /* output */], [llvm_i32_ty], - [llvm_anyvector_ty /* input vector */, llvm_i32_ty /* scale */], - LLVMMatchType<0>, llvm_anyvector_ty>; - -def int_arm_mve_vcvt_fp_int_predicated: Intrinsic< - [llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty /* unsigned */, - llvm_anyvector_ty /* predicate */, LLVMMatchType<0> /* inactive */], - [IntrNoMem]>; - -foreach suffix = ["a","n","p","m"] in { - defm "int_arm_mve_vcvt"#suffix: MVEMXPredicated< - [llvm_anyvector_ty /* output */], [llvm_i32_ty /* unsigned */], - [llvm_anyvector_ty /* input */], LLVMMatchType<0>, llvm_anyvector_ty>; -} - -def int_arm_mve_vrintn: Intrinsic< - [llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_vcls: Intrinsic< - [llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -defm int_arm_mve_vbrsr: MVEMXPredicated< - [llvm_anyvector_ty], [], - [LLVMMatchType<0>, llvm_i32_ty], LLVMMatchType<0>, llvm_anyvector_ty>; - -def int_arm_mve_vqdmull: Intrinsic< - [llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty], - [IntrNoMem]>; -def int_arm_mve_vqdmull_predicated: Intrinsic< - [llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty, llvm_anyvector_ty, - LLVMMatchType<0>], - [IntrNoMem]>; - -class MVESimpleUnaryPredicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; - -def int_arm_mve_mvn_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_abs_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_neg_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_qabs_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_qneg_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_clz_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_cls_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrintz_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrintm_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrintp_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrinta_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrintx_predicated: MVESimpleUnaryPredicated; -def int_arm_mve_vrintn_predicated: MVESimpleUnaryPredicated; - -def int_arm_mve_vrev_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_i32_ty /* size to reverse */, - llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; - -def int_arm_mve_vmovl_predicated: Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_i32_ty /* unsigned */, llvm_i32_ty /* top half */, - llvm_anyvector_ty /* predicate */, LLVMMatchType<0>], [IntrNoMem]>; -def int_arm_mve_vmovn_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i32_ty /* top half */, - llvm_anyvector_ty /* predicate */], [IntrNoMem]>; - -def int_arm_mve_vqmovn: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i32_ty /* unsigned output */, llvm_i32_ty /* unsigned input */, - llvm_i32_ty /* top half */], [IntrNoMem]>; -def int_arm_mve_vqmovn_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - llvm_i32_ty /* unsigned output */, llvm_i32_ty /* unsigned input */, - llvm_i32_ty /* top half */, llvm_anyvector_ty /* pred */], [IntrNoMem]>; - -def int_arm_mve_fma_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* mult op #2 */, - LLVMMatchType<0> /* addend */, llvm_anyvector_ty /* pred */], [IntrNoMem]>; -def int_arm_mve_vmla_n_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* addend */, - llvm_i32_ty /* mult op #2 (scalar) */, llvm_anyvector_ty /* pred */], - [IntrNoMem]>; -def int_arm_mve_vmlas_n_predicated: Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* mult op #2 */, - llvm_i32_ty /* addend (scalar) */, llvm_anyvector_ty /* pred */], - [IntrNoMem]>; - -defm int_arm_mve_vqdmlah: MVEPredicated<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* addend */, - llvm_i32_ty /* mult op #2 (scalar) */]>; -defm int_arm_mve_vqrdmlah: MVEPredicated<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* addend */, - llvm_i32_ty /* mult op #2 (scalar) */]>; -defm int_arm_mve_vqdmlash: MVEPredicated<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* mult op #2 */, - llvm_i32_ty /* addend (scalar) */]>; -defm int_arm_mve_vqrdmlash: MVEPredicated<[llvm_anyvector_ty], - [LLVMMatchType<0> /* mult op #1 */, LLVMMatchType<0> /* mult op #2 */, - llvm_i32_ty /* addend (scalar) */]>; - -defm int_arm_mve_vqdmlad: MVEPredicated<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty /* exchange */, llvm_i32_ty /* round */, - llvm_i32_ty /* subtract */]>; - -// CDE (Custom Datapath Extension) - -multiclass CDEGPRIntrinsics args> { - def "" : Intrinsic< - [llvm_i32_ty], - !listconcat([llvm_i32_ty /* coproc */], args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - def a : Intrinsic< - [llvm_i32_ty], - !listconcat([llvm_i32_ty /* coproc */, llvm_i32_ty /* acc */], args, - [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - - def d: Intrinsic< - [llvm_i32_ty /* lo */, llvm_i32_ty /* hi */], - !listconcat([llvm_i32_ty /* coproc */], args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - def da: Intrinsic< - [llvm_i32_ty /* lo */, llvm_i32_ty /* hi */], - !listconcat([llvm_i32_ty /* coproc */, llvm_i32_ty /* acc_lo */, - llvm_i32_ty /* acc_hi */], args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -defm int_arm_cde_cx1: CDEGPRIntrinsics<[]>; -defm int_arm_cde_cx2: CDEGPRIntrinsics<[llvm_i32_ty]>; -defm int_arm_cde_cx3: CDEGPRIntrinsics<[llvm_i32_ty, llvm_i32_ty]>; - -multiclass CDEVCXIntrinsics args> { - def "" : Intrinsic< - [llvm_anyfloat_ty], - !listconcat([llvm_i32_ty /* coproc */], args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - def a : Intrinsic< - [llvm_anyfloat_ty], - !listconcat([llvm_i32_ty /* coproc */, LLVMMatchType<0> /* acc */], - args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -defm int_arm_cde_vcx1 : CDEVCXIntrinsics<[]>; -defm int_arm_cde_vcx2 : CDEVCXIntrinsics<[LLVMMatchType<0>]>; -defm int_arm_cde_vcx3 : CDEVCXIntrinsics<[LLVMMatchType<0>, LLVMMatchType<0>]>; - -multiclass CDEVCXVecIntrinsics args> { - def "" : Intrinsic< - [llvm_v16i8_ty], - !listconcat([llvm_i32_ty /* coproc */], args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - def a : Intrinsic< - [llvm_v16i8_ty], - !listconcat([llvm_i32_ty /* coproc */, llvm_v16i8_ty /* acc */], - args, [llvm_i32_ty /* imm */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - - def _predicated : Intrinsic< - [llvm_anyvector_ty], - !listconcat([llvm_i32_ty /* coproc */, LLVMMatchType<0> /* inactive */], - args, [llvm_i32_ty /* imm */, llvm_anyvector_ty /* mask */]), - [IntrNoMem, ImmArg>, ImmArg>]>; - def a_predicated : Intrinsic< - [llvm_anyvector_ty], - !listconcat([llvm_i32_ty /* coproc */, LLVMMatchType<0> /* acc */], - args, [llvm_i32_ty /* imm */, llvm_anyvector_ty /* mask */]), - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -defm int_arm_cde_vcx1q : CDEVCXVecIntrinsics<[]>; -defm int_arm_cde_vcx2q : CDEVCXVecIntrinsics<[llvm_v16i8_ty]>; -defm int_arm_cde_vcx3q : CDEVCXVecIntrinsics<[llvm_v16i8_ty, llvm_v16i8_ty]>; - -} // end TargetPrefix diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.h deleted file mode 100644 index 7d50877150..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.h +++ /dev/null @@ -1,30 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_BPF_ENUMS_H -#define LLVM_IR_INTRINSIC_BPF_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum BPFIntrinsics : unsigned { -// Enum values for intrinsics - bpf_btf_type_id = 2463, // llvm.bpf.btf.type.id - bpf_compare, // llvm.bpf.compare - bpf_load_byte, // llvm.bpf.load.byte - bpf_load_half, // llvm.bpf.load.half - bpf_load_word, // llvm.bpf.load.word - bpf_passthrough, // llvm.bpf.passthrough - bpf_preserve_enum_value, // llvm.bpf.preserve.enum.value - bpf_preserve_field_info, // llvm.bpf.preserve.field.info - bpf_preserve_type_info, // llvm.bpf.preserve.type.info - bpf_pseudo, // llvm.bpf.pseudo -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.td deleted file mode 100644 index a6bd6f841a..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsBPF.td +++ /dev/null @@ -1,40 +0,0 @@ -//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the BPF-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -// Specialized loads from packet -let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." - def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; - def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; - def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; - def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>; - def int_bpf_preserve_field_info : GCCBuiltin<"__builtin_bpf_preserve_field_info">, - Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; - def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_bpf_preserve_type_info : GCCBuiltin<"__builtin_bpf_preserve_type_info">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_bpf_preserve_enum_value : GCCBuiltin<"__builtin_bpf_preserve_enum_value">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_ptr_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_bpf_passthrough : GCCBuiltin<"__builtin_bpf_passthrough">, - Intrinsic<[llvm_any_ty], [llvm_i32_ty, llvm_any_ty], [IntrNoMem]>; - def int_bpf_compare : GCCBuiltin<"__builtin_bpf_compare">, - Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_anyint_ty, llvm_anyint_ty], - [IntrNoMem]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.h deleted file mode 100644 index c8dd6518f5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.h +++ /dev/null @@ -1,1988 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_HEXAGON_ENUMS_H -#define LLVM_IR_INTRINSIC_HEXAGON_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum HEXAGONIntrinsics : unsigned { -// Enum values for intrinsics - hexagon_A2_abs = 2473, // llvm.hexagon.A2.abs - hexagon_A2_absp, // llvm.hexagon.A2.absp - hexagon_A2_abssat, // llvm.hexagon.A2.abssat - hexagon_A2_add, // llvm.hexagon.A2.add - hexagon_A2_addh_h16_hh, // llvm.hexagon.A2.addh.h16.hh - hexagon_A2_addh_h16_hl, // llvm.hexagon.A2.addh.h16.hl - hexagon_A2_addh_h16_lh, // llvm.hexagon.A2.addh.h16.lh - hexagon_A2_addh_h16_ll, // llvm.hexagon.A2.addh.h16.ll - hexagon_A2_addh_h16_sat_hh, // llvm.hexagon.A2.addh.h16.sat.hh - hexagon_A2_addh_h16_sat_hl, // llvm.hexagon.A2.addh.h16.sat.hl - hexagon_A2_addh_h16_sat_lh, // llvm.hexagon.A2.addh.h16.sat.lh - hexagon_A2_addh_h16_sat_ll, // llvm.hexagon.A2.addh.h16.sat.ll - hexagon_A2_addh_l16_hl, // llvm.hexagon.A2.addh.l16.hl - hexagon_A2_addh_l16_ll, // llvm.hexagon.A2.addh.l16.ll - hexagon_A2_addh_l16_sat_hl, // llvm.hexagon.A2.addh.l16.sat.hl - hexagon_A2_addh_l16_sat_ll, // llvm.hexagon.A2.addh.l16.sat.ll - hexagon_A2_addi, // llvm.hexagon.A2.addi - hexagon_A2_addp, // llvm.hexagon.A2.addp - hexagon_A2_addpsat, // llvm.hexagon.A2.addpsat - hexagon_A2_addsat, // llvm.hexagon.A2.addsat - hexagon_A2_addsp, // llvm.hexagon.A2.addsp - hexagon_A2_and, // llvm.hexagon.A2.and - hexagon_A2_andir, // llvm.hexagon.A2.andir - hexagon_A2_andp, // llvm.hexagon.A2.andp - hexagon_A2_aslh, // llvm.hexagon.A2.aslh - hexagon_A2_asrh, // llvm.hexagon.A2.asrh - hexagon_A2_combine_hh, // llvm.hexagon.A2.combine.hh - hexagon_A2_combine_hl, // llvm.hexagon.A2.combine.hl - hexagon_A2_combine_lh, // llvm.hexagon.A2.combine.lh - hexagon_A2_combine_ll, // llvm.hexagon.A2.combine.ll - hexagon_A2_combineii, // llvm.hexagon.A2.combineii - hexagon_A2_combinew, // llvm.hexagon.A2.combinew - hexagon_A2_max, // llvm.hexagon.A2.max - hexagon_A2_maxp, // llvm.hexagon.A2.maxp - hexagon_A2_maxu, // llvm.hexagon.A2.maxu - hexagon_A2_maxup, // llvm.hexagon.A2.maxup - hexagon_A2_min, // llvm.hexagon.A2.min - hexagon_A2_minp, // llvm.hexagon.A2.minp - hexagon_A2_minu, // llvm.hexagon.A2.minu - hexagon_A2_minup, // llvm.hexagon.A2.minup - hexagon_A2_neg, // llvm.hexagon.A2.neg - hexagon_A2_negp, // llvm.hexagon.A2.negp - hexagon_A2_negsat, // llvm.hexagon.A2.negsat - hexagon_A2_not, // llvm.hexagon.A2.not - hexagon_A2_notp, // llvm.hexagon.A2.notp - hexagon_A2_or, // llvm.hexagon.A2.or - hexagon_A2_orir, // llvm.hexagon.A2.orir - hexagon_A2_orp, // llvm.hexagon.A2.orp - hexagon_A2_roundsat, // llvm.hexagon.A2.roundsat - hexagon_A2_sat, // llvm.hexagon.A2.sat - hexagon_A2_satb, // llvm.hexagon.A2.satb - hexagon_A2_sath, // llvm.hexagon.A2.sath - hexagon_A2_satub, // llvm.hexagon.A2.satub - hexagon_A2_satuh, // llvm.hexagon.A2.satuh - hexagon_A2_sub, // llvm.hexagon.A2.sub - hexagon_A2_subh_h16_hh, // llvm.hexagon.A2.subh.h16.hh - hexagon_A2_subh_h16_hl, // llvm.hexagon.A2.subh.h16.hl - hexagon_A2_subh_h16_lh, // llvm.hexagon.A2.subh.h16.lh - hexagon_A2_subh_h16_ll, // llvm.hexagon.A2.subh.h16.ll - hexagon_A2_subh_h16_sat_hh, // llvm.hexagon.A2.subh.h16.sat.hh - hexagon_A2_subh_h16_sat_hl, // llvm.hexagon.A2.subh.h16.sat.hl - hexagon_A2_subh_h16_sat_lh, // llvm.hexagon.A2.subh.h16.sat.lh - hexagon_A2_subh_h16_sat_ll, // llvm.hexagon.A2.subh.h16.sat.ll - hexagon_A2_subh_l16_hl, // llvm.hexagon.A2.subh.l16.hl - hexagon_A2_subh_l16_ll, // llvm.hexagon.A2.subh.l16.ll - hexagon_A2_subh_l16_sat_hl, // llvm.hexagon.A2.subh.l16.sat.hl - hexagon_A2_subh_l16_sat_ll, // llvm.hexagon.A2.subh.l16.sat.ll - hexagon_A2_subp, // llvm.hexagon.A2.subp - hexagon_A2_subri, // llvm.hexagon.A2.subri - hexagon_A2_subsat, // llvm.hexagon.A2.subsat - hexagon_A2_svaddh, // llvm.hexagon.A2.svaddh - hexagon_A2_svaddhs, // llvm.hexagon.A2.svaddhs - hexagon_A2_svadduhs, // llvm.hexagon.A2.svadduhs - hexagon_A2_svavgh, // llvm.hexagon.A2.svavgh - hexagon_A2_svavghs, // llvm.hexagon.A2.svavghs - hexagon_A2_svnavgh, // llvm.hexagon.A2.svnavgh - hexagon_A2_svsubh, // llvm.hexagon.A2.svsubh - hexagon_A2_svsubhs, // llvm.hexagon.A2.svsubhs - hexagon_A2_svsubuhs, // llvm.hexagon.A2.svsubuhs - hexagon_A2_swiz, // llvm.hexagon.A2.swiz - hexagon_A2_sxtb, // llvm.hexagon.A2.sxtb - hexagon_A2_sxth, // llvm.hexagon.A2.sxth - hexagon_A2_sxtw, // llvm.hexagon.A2.sxtw - hexagon_A2_tfr, // llvm.hexagon.A2.tfr - hexagon_A2_tfrih, // llvm.hexagon.A2.tfrih - hexagon_A2_tfril, // llvm.hexagon.A2.tfril - hexagon_A2_tfrp, // llvm.hexagon.A2.tfrp - hexagon_A2_tfrpi, // llvm.hexagon.A2.tfrpi - hexagon_A2_tfrsi, // llvm.hexagon.A2.tfrsi - hexagon_A2_vabsh, // llvm.hexagon.A2.vabsh - hexagon_A2_vabshsat, // llvm.hexagon.A2.vabshsat - hexagon_A2_vabsw, // llvm.hexagon.A2.vabsw - hexagon_A2_vabswsat, // llvm.hexagon.A2.vabswsat - hexagon_A2_vaddb_map, // llvm.hexagon.A2.vaddb.map - hexagon_A2_vaddh, // llvm.hexagon.A2.vaddh - hexagon_A2_vaddhs, // llvm.hexagon.A2.vaddhs - hexagon_A2_vaddub, // llvm.hexagon.A2.vaddub - hexagon_A2_vaddubs, // llvm.hexagon.A2.vaddubs - hexagon_A2_vadduhs, // llvm.hexagon.A2.vadduhs - hexagon_A2_vaddw, // llvm.hexagon.A2.vaddw - hexagon_A2_vaddws, // llvm.hexagon.A2.vaddws - hexagon_A2_vavgh, // llvm.hexagon.A2.vavgh - hexagon_A2_vavghcr, // llvm.hexagon.A2.vavghcr - hexagon_A2_vavghr, // llvm.hexagon.A2.vavghr - hexagon_A2_vavgub, // llvm.hexagon.A2.vavgub - hexagon_A2_vavgubr, // llvm.hexagon.A2.vavgubr - hexagon_A2_vavguh, // llvm.hexagon.A2.vavguh - hexagon_A2_vavguhr, // llvm.hexagon.A2.vavguhr - hexagon_A2_vavguw, // llvm.hexagon.A2.vavguw - hexagon_A2_vavguwr, // llvm.hexagon.A2.vavguwr - hexagon_A2_vavgw, // llvm.hexagon.A2.vavgw - hexagon_A2_vavgwcr, // llvm.hexagon.A2.vavgwcr - hexagon_A2_vavgwr, // llvm.hexagon.A2.vavgwr - hexagon_A2_vcmpbeq, // llvm.hexagon.A2.vcmpbeq - hexagon_A2_vcmpbgtu, // llvm.hexagon.A2.vcmpbgtu - hexagon_A2_vcmpheq, // llvm.hexagon.A2.vcmpheq - hexagon_A2_vcmphgt, // llvm.hexagon.A2.vcmphgt - hexagon_A2_vcmphgtu, // llvm.hexagon.A2.vcmphgtu - hexagon_A2_vcmpweq, // llvm.hexagon.A2.vcmpweq - hexagon_A2_vcmpwgt, // llvm.hexagon.A2.vcmpwgt - hexagon_A2_vcmpwgtu, // llvm.hexagon.A2.vcmpwgtu - hexagon_A2_vconj, // llvm.hexagon.A2.vconj - hexagon_A2_vmaxb, // llvm.hexagon.A2.vmaxb - hexagon_A2_vmaxh, // llvm.hexagon.A2.vmaxh - hexagon_A2_vmaxub, // llvm.hexagon.A2.vmaxub - hexagon_A2_vmaxuh, // llvm.hexagon.A2.vmaxuh - hexagon_A2_vmaxuw, // llvm.hexagon.A2.vmaxuw - hexagon_A2_vmaxw, // llvm.hexagon.A2.vmaxw - hexagon_A2_vminb, // llvm.hexagon.A2.vminb - hexagon_A2_vminh, // llvm.hexagon.A2.vminh - hexagon_A2_vminub, // llvm.hexagon.A2.vminub - hexagon_A2_vminuh, // llvm.hexagon.A2.vminuh - hexagon_A2_vminuw, // llvm.hexagon.A2.vminuw - hexagon_A2_vminw, // llvm.hexagon.A2.vminw - hexagon_A2_vnavgh, // llvm.hexagon.A2.vnavgh - hexagon_A2_vnavghcr, // llvm.hexagon.A2.vnavghcr - hexagon_A2_vnavghr, // llvm.hexagon.A2.vnavghr - hexagon_A2_vnavgw, // llvm.hexagon.A2.vnavgw - hexagon_A2_vnavgwcr, // llvm.hexagon.A2.vnavgwcr - hexagon_A2_vnavgwr, // llvm.hexagon.A2.vnavgwr - hexagon_A2_vraddub, // llvm.hexagon.A2.vraddub - hexagon_A2_vraddub_acc, // llvm.hexagon.A2.vraddub.acc - hexagon_A2_vrsadub, // llvm.hexagon.A2.vrsadub - hexagon_A2_vrsadub_acc, // llvm.hexagon.A2.vrsadub.acc - hexagon_A2_vsubb_map, // llvm.hexagon.A2.vsubb.map - hexagon_A2_vsubh, // llvm.hexagon.A2.vsubh - hexagon_A2_vsubhs, // llvm.hexagon.A2.vsubhs - hexagon_A2_vsubub, // llvm.hexagon.A2.vsubub - hexagon_A2_vsububs, // llvm.hexagon.A2.vsububs - hexagon_A2_vsubuhs, // llvm.hexagon.A2.vsubuhs - hexagon_A2_vsubw, // llvm.hexagon.A2.vsubw - hexagon_A2_vsubws, // llvm.hexagon.A2.vsubws - hexagon_A2_xor, // llvm.hexagon.A2.xor - hexagon_A2_xorp, // llvm.hexagon.A2.xorp - hexagon_A2_zxtb, // llvm.hexagon.A2.zxtb - hexagon_A2_zxth, // llvm.hexagon.A2.zxth - hexagon_A4_andn, // llvm.hexagon.A4.andn - hexagon_A4_andnp, // llvm.hexagon.A4.andnp - hexagon_A4_bitsplit, // llvm.hexagon.A4.bitsplit - hexagon_A4_bitspliti, // llvm.hexagon.A4.bitspliti - hexagon_A4_boundscheck, // llvm.hexagon.A4.boundscheck - hexagon_A4_cmpbeq, // llvm.hexagon.A4.cmpbeq - hexagon_A4_cmpbeqi, // llvm.hexagon.A4.cmpbeqi - hexagon_A4_cmpbgt, // llvm.hexagon.A4.cmpbgt - hexagon_A4_cmpbgti, // llvm.hexagon.A4.cmpbgti - hexagon_A4_cmpbgtu, // llvm.hexagon.A4.cmpbgtu - hexagon_A4_cmpbgtui, // llvm.hexagon.A4.cmpbgtui - hexagon_A4_cmpheq, // llvm.hexagon.A4.cmpheq - hexagon_A4_cmpheqi, // llvm.hexagon.A4.cmpheqi - hexagon_A4_cmphgt, // llvm.hexagon.A4.cmphgt - hexagon_A4_cmphgti, // llvm.hexagon.A4.cmphgti - hexagon_A4_cmphgtu, // llvm.hexagon.A4.cmphgtu - hexagon_A4_cmphgtui, // llvm.hexagon.A4.cmphgtui - hexagon_A4_combineir, // llvm.hexagon.A4.combineir - hexagon_A4_combineri, // llvm.hexagon.A4.combineri - hexagon_A4_cround_ri, // llvm.hexagon.A4.cround.ri - hexagon_A4_cround_rr, // llvm.hexagon.A4.cround.rr - hexagon_A4_modwrapu, // llvm.hexagon.A4.modwrapu - hexagon_A4_orn, // llvm.hexagon.A4.orn - hexagon_A4_ornp, // llvm.hexagon.A4.ornp - hexagon_A4_rcmpeq, // llvm.hexagon.A4.rcmpeq - hexagon_A4_rcmpeqi, // llvm.hexagon.A4.rcmpeqi - hexagon_A4_rcmpneq, // llvm.hexagon.A4.rcmpneq - hexagon_A4_rcmpneqi, // llvm.hexagon.A4.rcmpneqi - hexagon_A4_round_ri, // llvm.hexagon.A4.round.ri - hexagon_A4_round_ri_sat, // llvm.hexagon.A4.round.ri.sat - hexagon_A4_round_rr, // llvm.hexagon.A4.round.rr - hexagon_A4_round_rr_sat, // llvm.hexagon.A4.round.rr.sat - hexagon_A4_tlbmatch, // llvm.hexagon.A4.tlbmatch - hexagon_A4_vcmpbeq_any, // llvm.hexagon.A4.vcmpbeq.any - hexagon_A4_vcmpbeqi, // llvm.hexagon.A4.vcmpbeqi - hexagon_A4_vcmpbgt, // llvm.hexagon.A4.vcmpbgt - hexagon_A4_vcmpbgti, // llvm.hexagon.A4.vcmpbgti - hexagon_A4_vcmpbgtui, // llvm.hexagon.A4.vcmpbgtui - hexagon_A4_vcmpheqi, // llvm.hexagon.A4.vcmpheqi - hexagon_A4_vcmphgti, // llvm.hexagon.A4.vcmphgti - hexagon_A4_vcmphgtui, // llvm.hexagon.A4.vcmphgtui - hexagon_A4_vcmpweqi, // llvm.hexagon.A4.vcmpweqi - hexagon_A4_vcmpwgti, // llvm.hexagon.A4.vcmpwgti - hexagon_A4_vcmpwgtui, // llvm.hexagon.A4.vcmpwgtui - hexagon_A4_vrmaxh, // llvm.hexagon.A4.vrmaxh - hexagon_A4_vrmaxuh, // llvm.hexagon.A4.vrmaxuh - hexagon_A4_vrmaxuw, // llvm.hexagon.A4.vrmaxuw - hexagon_A4_vrmaxw, // llvm.hexagon.A4.vrmaxw - hexagon_A4_vrminh, // llvm.hexagon.A4.vrminh - hexagon_A4_vrminuh, // llvm.hexagon.A4.vrminuh - hexagon_A4_vrminuw, // llvm.hexagon.A4.vrminuw - hexagon_A4_vrminw, // llvm.hexagon.A4.vrminw - hexagon_A5_vaddhubs, // llvm.hexagon.A5.vaddhubs - hexagon_A6_vcmpbeq_notany, // llvm.hexagon.A6.vcmpbeq.notany - hexagon_A7_clip, // llvm.hexagon.A7.clip - hexagon_A7_croundd_ri, // llvm.hexagon.A7.croundd.ri - hexagon_A7_croundd_rr, // llvm.hexagon.A7.croundd.rr - hexagon_A7_vclip, // llvm.hexagon.A7.vclip - hexagon_C2_all8, // llvm.hexagon.C2.all8 - hexagon_C2_and, // llvm.hexagon.C2.and - hexagon_C2_andn, // llvm.hexagon.C2.andn - hexagon_C2_any8, // llvm.hexagon.C2.any8 - hexagon_C2_bitsclr, // llvm.hexagon.C2.bitsclr - hexagon_C2_bitsclri, // llvm.hexagon.C2.bitsclri - hexagon_C2_bitsset, // llvm.hexagon.C2.bitsset - hexagon_C2_cmpeq, // llvm.hexagon.C2.cmpeq - hexagon_C2_cmpeqi, // llvm.hexagon.C2.cmpeqi - hexagon_C2_cmpeqp, // llvm.hexagon.C2.cmpeqp - hexagon_C2_cmpgei, // llvm.hexagon.C2.cmpgei - hexagon_C2_cmpgeui, // llvm.hexagon.C2.cmpgeui - hexagon_C2_cmpgt, // llvm.hexagon.C2.cmpgt - hexagon_C2_cmpgti, // llvm.hexagon.C2.cmpgti - hexagon_C2_cmpgtp, // llvm.hexagon.C2.cmpgtp - hexagon_C2_cmpgtu, // llvm.hexagon.C2.cmpgtu - hexagon_C2_cmpgtui, // llvm.hexagon.C2.cmpgtui - hexagon_C2_cmpgtup, // llvm.hexagon.C2.cmpgtup - hexagon_C2_cmplt, // llvm.hexagon.C2.cmplt - hexagon_C2_cmpltu, // llvm.hexagon.C2.cmpltu - hexagon_C2_mask, // llvm.hexagon.C2.mask - hexagon_C2_mux, // llvm.hexagon.C2.mux - hexagon_C2_muxii, // llvm.hexagon.C2.muxii - hexagon_C2_muxir, // llvm.hexagon.C2.muxir - hexagon_C2_muxri, // llvm.hexagon.C2.muxri - hexagon_C2_not, // llvm.hexagon.C2.not - hexagon_C2_or, // llvm.hexagon.C2.or - hexagon_C2_orn, // llvm.hexagon.C2.orn - hexagon_C2_pxfer_map, // llvm.hexagon.C2.pxfer.map - hexagon_C2_tfrpr, // llvm.hexagon.C2.tfrpr - hexagon_C2_tfrrp, // llvm.hexagon.C2.tfrrp - hexagon_C2_vitpack, // llvm.hexagon.C2.vitpack - hexagon_C2_vmux, // llvm.hexagon.C2.vmux - hexagon_C2_xor, // llvm.hexagon.C2.xor - hexagon_C4_and_and, // llvm.hexagon.C4.and.and - hexagon_C4_and_andn, // llvm.hexagon.C4.and.andn - hexagon_C4_and_or, // llvm.hexagon.C4.and.or - hexagon_C4_and_orn, // llvm.hexagon.C4.and.orn - hexagon_C4_cmplte, // llvm.hexagon.C4.cmplte - hexagon_C4_cmpltei, // llvm.hexagon.C4.cmpltei - hexagon_C4_cmplteu, // llvm.hexagon.C4.cmplteu - hexagon_C4_cmplteui, // llvm.hexagon.C4.cmplteui - hexagon_C4_cmpneq, // llvm.hexagon.C4.cmpneq - hexagon_C4_cmpneqi, // llvm.hexagon.C4.cmpneqi - hexagon_C4_fastcorner9, // llvm.hexagon.C4.fastcorner9 - hexagon_C4_fastcorner9_not, // llvm.hexagon.C4.fastcorner9.not - hexagon_C4_nbitsclr, // llvm.hexagon.C4.nbitsclr - hexagon_C4_nbitsclri, // llvm.hexagon.C4.nbitsclri - hexagon_C4_nbitsset, // llvm.hexagon.C4.nbitsset - hexagon_C4_or_and, // llvm.hexagon.C4.or.and - hexagon_C4_or_andn, // llvm.hexagon.C4.or.andn - hexagon_C4_or_or, // llvm.hexagon.C4.or.or - hexagon_C4_or_orn, // llvm.hexagon.C4.or.orn - hexagon_F2_conv_d2df, // llvm.hexagon.F2.conv.d2df - hexagon_F2_conv_d2sf, // llvm.hexagon.F2.conv.d2sf - hexagon_F2_conv_df2d, // llvm.hexagon.F2.conv.df2d - hexagon_F2_conv_df2d_chop, // llvm.hexagon.F2.conv.df2d.chop - hexagon_F2_conv_df2sf, // llvm.hexagon.F2.conv.df2sf - hexagon_F2_conv_df2ud, // llvm.hexagon.F2.conv.df2ud - hexagon_F2_conv_df2ud_chop, // llvm.hexagon.F2.conv.df2ud.chop - hexagon_F2_conv_df2uw, // llvm.hexagon.F2.conv.df2uw - hexagon_F2_conv_df2uw_chop, // llvm.hexagon.F2.conv.df2uw.chop - hexagon_F2_conv_df2w, // llvm.hexagon.F2.conv.df2w - hexagon_F2_conv_df2w_chop, // llvm.hexagon.F2.conv.df2w.chop - hexagon_F2_conv_sf2d, // llvm.hexagon.F2.conv.sf2d - hexagon_F2_conv_sf2d_chop, // llvm.hexagon.F2.conv.sf2d.chop - hexagon_F2_conv_sf2df, // llvm.hexagon.F2.conv.sf2df - hexagon_F2_conv_sf2ud, // llvm.hexagon.F2.conv.sf2ud - hexagon_F2_conv_sf2ud_chop, // llvm.hexagon.F2.conv.sf2ud.chop - hexagon_F2_conv_sf2uw, // llvm.hexagon.F2.conv.sf2uw - hexagon_F2_conv_sf2uw_chop, // llvm.hexagon.F2.conv.sf2uw.chop - hexagon_F2_conv_sf2w, // llvm.hexagon.F2.conv.sf2w - hexagon_F2_conv_sf2w_chop, // llvm.hexagon.F2.conv.sf2w.chop - hexagon_F2_conv_ud2df, // llvm.hexagon.F2.conv.ud2df - hexagon_F2_conv_ud2sf, // llvm.hexagon.F2.conv.ud2sf - hexagon_F2_conv_uw2df, // llvm.hexagon.F2.conv.uw2df - hexagon_F2_conv_uw2sf, // llvm.hexagon.F2.conv.uw2sf - hexagon_F2_conv_w2df, // llvm.hexagon.F2.conv.w2df - hexagon_F2_conv_w2sf, // llvm.hexagon.F2.conv.w2sf - hexagon_F2_dfadd, // llvm.hexagon.F2.dfadd - hexagon_F2_dfclass, // llvm.hexagon.F2.dfclass - hexagon_F2_dfcmpeq, // llvm.hexagon.F2.dfcmpeq - hexagon_F2_dfcmpge, // llvm.hexagon.F2.dfcmpge - hexagon_F2_dfcmpgt, // llvm.hexagon.F2.dfcmpgt - hexagon_F2_dfcmpuo, // llvm.hexagon.F2.dfcmpuo - hexagon_F2_dfimm_n, // llvm.hexagon.F2.dfimm.n - hexagon_F2_dfimm_p, // llvm.hexagon.F2.dfimm.p - hexagon_F2_dfmax, // llvm.hexagon.F2.dfmax - hexagon_F2_dfmin, // llvm.hexagon.F2.dfmin - hexagon_F2_dfmpyfix, // llvm.hexagon.F2.dfmpyfix - hexagon_F2_dfmpyhh, // llvm.hexagon.F2.dfmpyhh - hexagon_F2_dfmpylh, // llvm.hexagon.F2.dfmpylh - hexagon_F2_dfmpyll, // llvm.hexagon.F2.dfmpyll - hexagon_F2_dfsub, // llvm.hexagon.F2.dfsub - hexagon_F2_sfadd, // llvm.hexagon.F2.sfadd - hexagon_F2_sfclass, // llvm.hexagon.F2.sfclass - hexagon_F2_sfcmpeq, // llvm.hexagon.F2.sfcmpeq - hexagon_F2_sfcmpge, // llvm.hexagon.F2.sfcmpge - hexagon_F2_sfcmpgt, // llvm.hexagon.F2.sfcmpgt - hexagon_F2_sfcmpuo, // llvm.hexagon.F2.sfcmpuo - hexagon_F2_sffixupd, // llvm.hexagon.F2.sffixupd - hexagon_F2_sffixupn, // llvm.hexagon.F2.sffixupn - hexagon_F2_sffixupr, // llvm.hexagon.F2.sffixupr - hexagon_F2_sffma, // llvm.hexagon.F2.sffma - hexagon_F2_sffma_lib, // llvm.hexagon.F2.sffma.lib - hexagon_F2_sffma_sc, // llvm.hexagon.F2.sffma.sc - hexagon_F2_sffms, // llvm.hexagon.F2.sffms - hexagon_F2_sffms_lib, // llvm.hexagon.F2.sffms.lib - hexagon_F2_sfimm_n, // llvm.hexagon.F2.sfimm.n - hexagon_F2_sfimm_p, // llvm.hexagon.F2.sfimm.p - hexagon_F2_sfmax, // llvm.hexagon.F2.sfmax - hexagon_F2_sfmin, // llvm.hexagon.F2.sfmin - hexagon_F2_sfmpy, // llvm.hexagon.F2.sfmpy - hexagon_F2_sfsub, // llvm.hexagon.F2.sfsub - hexagon_L2_loadrb_pbr, // llvm.hexagon.L2.loadrb.pbr - hexagon_L2_loadrb_pci, // llvm.hexagon.L2.loadrb.pci - hexagon_L2_loadrb_pcr, // llvm.hexagon.L2.loadrb.pcr - hexagon_L2_loadrd_pbr, // llvm.hexagon.L2.loadrd.pbr - hexagon_L2_loadrd_pci, // llvm.hexagon.L2.loadrd.pci - hexagon_L2_loadrd_pcr, // llvm.hexagon.L2.loadrd.pcr - hexagon_L2_loadrh_pbr, // llvm.hexagon.L2.loadrh.pbr - hexagon_L2_loadrh_pci, // llvm.hexagon.L2.loadrh.pci - hexagon_L2_loadrh_pcr, // llvm.hexagon.L2.loadrh.pcr - hexagon_L2_loadri_pbr, // llvm.hexagon.L2.loadri.pbr - hexagon_L2_loadri_pci, // llvm.hexagon.L2.loadri.pci - hexagon_L2_loadri_pcr, // llvm.hexagon.L2.loadri.pcr - hexagon_L2_loadrub_pbr, // llvm.hexagon.L2.loadrub.pbr - hexagon_L2_loadrub_pci, // llvm.hexagon.L2.loadrub.pci - hexagon_L2_loadrub_pcr, // llvm.hexagon.L2.loadrub.pcr - hexagon_L2_loadruh_pbr, // llvm.hexagon.L2.loadruh.pbr - hexagon_L2_loadruh_pci, // llvm.hexagon.L2.loadruh.pci - hexagon_L2_loadruh_pcr, // llvm.hexagon.L2.loadruh.pcr - hexagon_L2_loadw_locked, // llvm.hexagon.L2.loadw.locked - hexagon_L4_loadd_locked, // llvm.hexagon.L4.loadd.locked - hexagon_M2_acci, // llvm.hexagon.M2.acci - hexagon_M2_accii, // llvm.hexagon.M2.accii - hexagon_M2_cmaci_s0, // llvm.hexagon.M2.cmaci.s0 - hexagon_M2_cmacr_s0, // llvm.hexagon.M2.cmacr.s0 - hexagon_M2_cmacs_s0, // llvm.hexagon.M2.cmacs.s0 - hexagon_M2_cmacs_s1, // llvm.hexagon.M2.cmacs.s1 - hexagon_M2_cmacsc_s0, // llvm.hexagon.M2.cmacsc.s0 - hexagon_M2_cmacsc_s1, // llvm.hexagon.M2.cmacsc.s1 - hexagon_M2_cmpyi_s0, // llvm.hexagon.M2.cmpyi.s0 - hexagon_M2_cmpyr_s0, // llvm.hexagon.M2.cmpyr.s0 - hexagon_M2_cmpyrs_s0, // llvm.hexagon.M2.cmpyrs.s0 - hexagon_M2_cmpyrs_s1, // llvm.hexagon.M2.cmpyrs.s1 - hexagon_M2_cmpyrsc_s0, // llvm.hexagon.M2.cmpyrsc.s0 - hexagon_M2_cmpyrsc_s1, // llvm.hexagon.M2.cmpyrsc.s1 - hexagon_M2_cmpys_s0, // llvm.hexagon.M2.cmpys.s0 - hexagon_M2_cmpys_s1, // llvm.hexagon.M2.cmpys.s1 - hexagon_M2_cmpysc_s0, // llvm.hexagon.M2.cmpysc.s0 - hexagon_M2_cmpysc_s1, // llvm.hexagon.M2.cmpysc.s1 - hexagon_M2_cnacs_s0, // llvm.hexagon.M2.cnacs.s0 - hexagon_M2_cnacs_s1, // llvm.hexagon.M2.cnacs.s1 - hexagon_M2_cnacsc_s0, // llvm.hexagon.M2.cnacsc.s0 - hexagon_M2_cnacsc_s1, // llvm.hexagon.M2.cnacsc.s1 - hexagon_M2_dpmpyss_acc_s0, // llvm.hexagon.M2.dpmpyss.acc.s0 - hexagon_M2_dpmpyss_nac_s0, // llvm.hexagon.M2.dpmpyss.nac.s0 - hexagon_M2_dpmpyss_rnd_s0, // llvm.hexagon.M2.dpmpyss.rnd.s0 - hexagon_M2_dpmpyss_s0, // llvm.hexagon.M2.dpmpyss.s0 - hexagon_M2_dpmpyuu_acc_s0, // llvm.hexagon.M2.dpmpyuu.acc.s0 - hexagon_M2_dpmpyuu_nac_s0, // llvm.hexagon.M2.dpmpyuu.nac.s0 - hexagon_M2_dpmpyuu_s0, // llvm.hexagon.M2.dpmpyuu.s0 - hexagon_M2_hmmpyh_rs1, // llvm.hexagon.M2.hmmpyh.rs1 - hexagon_M2_hmmpyh_s1, // llvm.hexagon.M2.hmmpyh.s1 - hexagon_M2_hmmpyl_rs1, // llvm.hexagon.M2.hmmpyl.rs1 - hexagon_M2_hmmpyl_s1, // llvm.hexagon.M2.hmmpyl.s1 - hexagon_M2_maci, // llvm.hexagon.M2.maci - hexagon_M2_macsin, // llvm.hexagon.M2.macsin - hexagon_M2_macsip, // llvm.hexagon.M2.macsip - hexagon_M2_mmachs_rs0, // llvm.hexagon.M2.mmachs.rs0 - hexagon_M2_mmachs_rs1, // llvm.hexagon.M2.mmachs.rs1 - hexagon_M2_mmachs_s0, // llvm.hexagon.M2.mmachs.s0 - hexagon_M2_mmachs_s1, // llvm.hexagon.M2.mmachs.s1 - hexagon_M2_mmacls_rs0, // llvm.hexagon.M2.mmacls.rs0 - hexagon_M2_mmacls_rs1, // llvm.hexagon.M2.mmacls.rs1 - hexagon_M2_mmacls_s0, // llvm.hexagon.M2.mmacls.s0 - hexagon_M2_mmacls_s1, // llvm.hexagon.M2.mmacls.s1 - hexagon_M2_mmacuhs_rs0, // llvm.hexagon.M2.mmacuhs.rs0 - hexagon_M2_mmacuhs_rs1, // llvm.hexagon.M2.mmacuhs.rs1 - hexagon_M2_mmacuhs_s0, // llvm.hexagon.M2.mmacuhs.s0 - hexagon_M2_mmacuhs_s1, // llvm.hexagon.M2.mmacuhs.s1 - hexagon_M2_mmaculs_rs0, // llvm.hexagon.M2.mmaculs.rs0 - hexagon_M2_mmaculs_rs1, // llvm.hexagon.M2.mmaculs.rs1 - hexagon_M2_mmaculs_s0, // llvm.hexagon.M2.mmaculs.s0 - hexagon_M2_mmaculs_s1, // llvm.hexagon.M2.mmaculs.s1 - hexagon_M2_mmpyh_rs0, // llvm.hexagon.M2.mmpyh.rs0 - hexagon_M2_mmpyh_rs1, // llvm.hexagon.M2.mmpyh.rs1 - hexagon_M2_mmpyh_s0, // llvm.hexagon.M2.mmpyh.s0 - hexagon_M2_mmpyh_s1, // llvm.hexagon.M2.mmpyh.s1 - hexagon_M2_mmpyl_rs0, // llvm.hexagon.M2.mmpyl.rs0 - hexagon_M2_mmpyl_rs1, // llvm.hexagon.M2.mmpyl.rs1 - hexagon_M2_mmpyl_s0, // llvm.hexagon.M2.mmpyl.s0 - hexagon_M2_mmpyl_s1, // llvm.hexagon.M2.mmpyl.s1 - hexagon_M2_mmpyuh_rs0, // llvm.hexagon.M2.mmpyuh.rs0 - hexagon_M2_mmpyuh_rs1, // llvm.hexagon.M2.mmpyuh.rs1 - hexagon_M2_mmpyuh_s0, // llvm.hexagon.M2.mmpyuh.s0 - hexagon_M2_mmpyuh_s1, // llvm.hexagon.M2.mmpyuh.s1 - hexagon_M2_mmpyul_rs0, // llvm.hexagon.M2.mmpyul.rs0 - hexagon_M2_mmpyul_rs1, // llvm.hexagon.M2.mmpyul.rs1 - hexagon_M2_mmpyul_s0, // llvm.hexagon.M2.mmpyul.s0 - hexagon_M2_mmpyul_s1, // llvm.hexagon.M2.mmpyul.s1 - hexagon_M2_mnaci, // llvm.hexagon.M2.mnaci - hexagon_M2_mpy_acc_hh_s0, // llvm.hexagon.M2.mpy.acc.hh.s0 - hexagon_M2_mpy_acc_hh_s1, // llvm.hexagon.M2.mpy.acc.hh.s1 - hexagon_M2_mpy_acc_hl_s0, // llvm.hexagon.M2.mpy.acc.hl.s0 - hexagon_M2_mpy_acc_hl_s1, // llvm.hexagon.M2.mpy.acc.hl.s1 - hexagon_M2_mpy_acc_lh_s0, // llvm.hexagon.M2.mpy.acc.lh.s0 - hexagon_M2_mpy_acc_lh_s1, // llvm.hexagon.M2.mpy.acc.lh.s1 - hexagon_M2_mpy_acc_ll_s0, // llvm.hexagon.M2.mpy.acc.ll.s0 - hexagon_M2_mpy_acc_ll_s1, // llvm.hexagon.M2.mpy.acc.ll.s1 - hexagon_M2_mpy_acc_sat_hh_s0, // llvm.hexagon.M2.mpy.acc.sat.hh.s0 - hexagon_M2_mpy_acc_sat_hh_s1, // llvm.hexagon.M2.mpy.acc.sat.hh.s1 - hexagon_M2_mpy_acc_sat_hl_s0, // llvm.hexagon.M2.mpy.acc.sat.hl.s0 - hexagon_M2_mpy_acc_sat_hl_s1, // llvm.hexagon.M2.mpy.acc.sat.hl.s1 - hexagon_M2_mpy_acc_sat_lh_s0, // llvm.hexagon.M2.mpy.acc.sat.lh.s0 - hexagon_M2_mpy_acc_sat_lh_s1, // llvm.hexagon.M2.mpy.acc.sat.lh.s1 - hexagon_M2_mpy_acc_sat_ll_s0, // llvm.hexagon.M2.mpy.acc.sat.ll.s0 - hexagon_M2_mpy_acc_sat_ll_s1, // llvm.hexagon.M2.mpy.acc.sat.ll.s1 - hexagon_M2_mpy_hh_s0, // llvm.hexagon.M2.mpy.hh.s0 - hexagon_M2_mpy_hh_s1, // llvm.hexagon.M2.mpy.hh.s1 - hexagon_M2_mpy_hl_s0, // llvm.hexagon.M2.mpy.hl.s0 - hexagon_M2_mpy_hl_s1, // llvm.hexagon.M2.mpy.hl.s1 - hexagon_M2_mpy_lh_s0, // llvm.hexagon.M2.mpy.lh.s0 - hexagon_M2_mpy_lh_s1, // llvm.hexagon.M2.mpy.lh.s1 - hexagon_M2_mpy_ll_s0, // llvm.hexagon.M2.mpy.ll.s0 - hexagon_M2_mpy_ll_s1, // llvm.hexagon.M2.mpy.ll.s1 - hexagon_M2_mpy_nac_hh_s0, // llvm.hexagon.M2.mpy.nac.hh.s0 - hexagon_M2_mpy_nac_hh_s1, // llvm.hexagon.M2.mpy.nac.hh.s1 - hexagon_M2_mpy_nac_hl_s0, // llvm.hexagon.M2.mpy.nac.hl.s0 - hexagon_M2_mpy_nac_hl_s1, // llvm.hexagon.M2.mpy.nac.hl.s1 - hexagon_M2_mpy_nac_lh_s0, // llvm.hexagon.M2.mpy.nac.lh.s0 - hexagon_M2_mpy_nac_lh_s1, // llvm.hexagon.M2.mpy.nac.lh.s1 - hexagon_M2_mpy_nac_ll_s0, // llvm.hexagon.M2.mpy.nac.ll.s0 - hexagon_M2_mpy_nac_ll_s1, // llvm.hexagon.M2.mpy.nac.ll.s1 - hexagon_M2_mpy_nac_sat_hh_s0, // llvm.hexagon.M2.mpy.nac.sat.hh.s0 - hexagon_M2_mpy_nac_sat_hh_s1, // llvm.hexagon.M2.mpy.nac.sat.hh.s1 - hexagon_M2_mpy_nac_sat_hl_s0, // llvm.hexagon.M2.mpy.nac.sat.hl.s0 - hexagon_M2_mpy_nac_sat_hl_s1, // llvm.hexagon.M2.mpy.nac.sat.hl.s1 - hexagon_M2_mpy_nac_sat_lh_s0, // llvm.hexagon.M2.mpy.nac.sat.lh.s0 - hexagon_M2_mpy_nac_sat_lh_s1, // llvm.hexagon.M2.mpy.nac.sat.lh.s1 - hexagon_M2_mpy_nac_sat_ll_s0, // llvm.hexagon.M2.mpy.nac.sat.ll.s0 - hexagon_M2_mpy_nac_sat_ll_s1, // llvm.hexagon.M2.mpy.nac.sat.ll.s1 - hexagon_M2_mpy_rnd_hh_s0, // llvm.hexagon.M2.mpy.rnd.hh.s0 - hexagon_M2_mpy_rnd_hh_s1, // llvm.hexagon.M2.mpy.rnd.hh.s1 - hexagon_M2_mpy_rnd_hl_s0, // llvm.hexagon.M2.mpy.rnd.hl.s0 - hexagon_M2_mpy_rnd_hl_s1, // llvm.hexagon.M2.mpy.rnd.hl.s1 - hexagon_M2_mpy_rnd_lh_s0, // llvm.hexagon.M2.mpy.rnd.lh.s0 - hexagon_M2_mpy_rnd_lh_s1, // llvm.hexagon.M2.mpy.rnd.lh.s1 - hexagon_M2_mpy_rnd_ll_s0, // llvm.hexagon.M2.mpy.rnd.ll.s0 - hexagon_M2_mpy_rnd_ll_s1, // llvm.hexagon.M2.mpy.rnd.ll.s1 - hexagon_M2_mpy_sat_hh_s0, // llvm.hexagon.M2.mpy.sat.hh.s0 - hexagon_M2_mpy_sat_hh_s1, // llvm.hexagon.M2.mpy.sat.hh.s1 - hexagon_M2_mpy_sat_hl_s0, // llvm.hexagon.M2.mpy.sat.hl.s0 - hexagon_M2_mpy_sat_hl_s1, // llvm.hexagon.M2.mpy.sat.hl.s1 - hexagon_M2_mpy_sat_lh_s0, // llvm.hexagon.M2.mpy.sat.lh.s0 - hexagon_M2_mpy_sat_lh_s1, // llvm.hexagon.M2.mpy.sat.lh.s1 - hexagon_M2_mpy_sat_ll_s0, // llvm.hexagon.M2.mpy.sat.ll.s0 - hexagon_M2_mpy_sat_ll_s1, // llvm.hexagon.M2.mpy.sat.ll.s1 - hexagon_M2_mpy_sat_rnd_hh_s0, // llvm.hexagon.M2.mpy.sat.rnd.hh.s0 - hexagon_M2_mpy_sat_rnd_hh_s1, // llvm.hexagon.M2.mpy.sat.rnd.hh.s1 - hexagon_M2_mpy_sat_rnd_hl_s0, // llvm.hexagon.M2.mpy.sat.rnd.hl.s0 - hexagon_M2_mpy_sat_rnd_hl_s1, // llvm.hexagon.M2.mpy.sat.rnd.hl.s1 - hexagon_M2_mpy_sat_rnd_lh_s0, // llvm.hexagon.M2.mpy.sat.rnd.lh.s0 - hexagon_M2_mpy_sat_rnd_lh_s1, // llvm.hexagon.M2.mpy.sat.rnd.lh.s1 - hexagon_M2_mpy_sat_rnd_ll_s0, // llvm.hexagon.M2.mpy.sat.rnd.ll.s0 - hexagon_M2_mpy_sat_rnd_ll_s1, // llvm.hexagon.M2.mpy.sat.rnd.ll.s1 - hexagon_M2_mpy_up, // llvm.hexagon.M2.mpy.up - hexagon_M2_mpy_up_s1, // llvm.hexagon.M2.mpy.up.s1 - hexagon_M2_mpy_up_s1_sat, // llvm.hexagon.M2.mpy.up.s1.sat - hexagon_M2_mpyd_acc_hh_s0, // llvm.hexagon.M2.mpyd.acc.hh.s0 - hexagon_M2_mpyd_acc_hh_s1, // llvm.hexagon.M2.mpyd.acc.hh.s1 - hexagon_M2_mpyd_acc_hl_s0, // llvm.hexagon.M2.mpyd.acc.hl.s0 - hexagon_M2_mpyd_acc_hl_s1, // llvm.hexagon.M2.mpyd.acc.hl.s1 - hexagon_M2_mpyd_acc_lh_s0, // llvm.hexagon.M2.mpyd.acc.lh.s0 - hexagon_M2_mpyd_acc_lh_s1, // llvm.hexagon.M2.mpyd.acc.lh.s1 - hexagon_M2_mpyd_acc_ll_s0, // llvm.hexagon.M2.mpyd.acc.ll.s0 - hexagon_M2_mpyd_acc_ll_s1, // llvm.hexagon.M2.mpyd.acc.ll.s1 - hexagon_M2_mpyd_hh_s0, // llvm.hexagon.M2.mpyd.hh.s0 - hexagon_M2_mpyd_hh_s1, // llvm.hexagon.M2.mpyd.hh.s1 - hexagon_M2_mpyd_hl_s0, // llvm.hexagon.M2.mpyd.hl.s0 - hexagon_M2_mpyd_hl_s1, // llvm.hexagon.M2.mpyd.hl.s1 - hexagon_M2_mpyd_lh_s0, // llvm.hexagon.M2.mpyd.lh.s0 - hexagon_M2_mpyd_lh_s1, // llvm.hexagon.M2.mpyd.lh.s1 - hexagon_M2_mpyd_ll_s0, // llvm.hexagon.M2.mpyd.ll.s0 - hexagon_M2_mpyd_ll_s1, // llvm.hexagon.M2.mpyd.ll.s1 - hexagon_M2_mpyd_nac_hh_s0, // llvm.hexagon.M2.mpyd.nac.hh.s0 - hexagon_M2_mpyd_nac_hh_s1, // llvm.hexagon.M2.mpyd.nac.hh.s1 - hexagon_M2_mpyd_nac_hl_s0, // llvm.hexagon.M2.mpyd.nac.hl.s0 - hexagon_M2_mpyd_nac_hl_s1, // llvm.hexagon.M2.mpyd.nac.hl.s1 - hexagon_M2_mpyd_nac_lh_s0, // llvm.hexagon.M2.mpyd.nac.lh.s0 - hexagon_M2_mpyd_nac_lh_s1, // llvm.hexagon.M2.mpyd.nac.lh.s1 - hexagon_M2_mpyd_nac_ll_s0, // llvm.hexagon.M2.mpyd.nac.ll.s0 - hexagon_M2_mpyd_nac_ll_s1, // llvm.hexagon.M2.mpyd.nac.ll.s1 - hexagon_M2_mpyd_rnd_hh_s0, // llvm.hexagon.M2.mpyd.rnd.hh.s0 - hexagon_M2_mpyd_rnd_hh_s1, // llvm.hexagon.M2.mpyd.rnd.hh.s1 - hexagon_M2_mpyd_rnd_hl_s0, // llvm.hexagon.M2.mpyd.rnd.hl.s0 - hexagon_M2_mpyd_rnd_hl_s1, // llvm.hexagon.M2.mpyd.rnd.hl.s1 - hexagon_M2_mpyd_rnd_lh_s0, // llvm.hexagon.M2.mpyd.rnd.lh.s0 - hexagon_M2_mpyd_rnd_lh_s1, // llvm.hexagon.M2.mpyd.rnd.lh.s1 - hexagon_M2_mpyd_rnd_ll_s0, // llvm.hexagon.M2.mpyd.rnd.ll.s0 - hexagon_M2_mpyd_rnd_ll_s1, // llvm.hexagon.M2.mpyd.rnd.ll.s1 - hexagon_M2_mpyi, // llvm.hexagon.M2.mpyi - hexagon_M2_mpysmi, // llvm.hexagon.M2.mpysmi - hexagon_M2_mpysu_up, // llvm.hexagon.M2.mpysu.up - hexagon_M2_mpyu_acc_hh_s0, // llvm.hexagon.M2.mpyu.acc.hh.s0 - hexagon_M2_mpyu_acc_hh_s1, // llvm.hexagon.M2.mpyu.acc.hh.s1 - hexagon_M2_mpyu_acc_hl_s0, // llvm.hexagon.M2.mpyu.acc.hl.s0 - hexagon_M2_mpyu_acc_hl_s1, // llvm.hexagon.M2.mpyu.acc.hl.s1 - hexagon_M2_mpyu_acc_lh_s0, // llvm.hexagon.M2.mpyu.acc.lh.s0 - hexagon_M2_mpyu_acc_lh_s1, // llvm.hexagon.M2.mpyu.acc.lh.s1 - hexagon_M2_mpyu_acc_ll_s0, // llvm.hexagon.M2.mpyu.acc.ll.s0 - hexagon_M2_mpyu_acc_ll_s1, // llvm.hexagon.M2.mpyu.acc.ll.s1 - hexagon_M2_mpyu_hh_s0, // llvm.hexagon.M2.mpyu.hh.s0 - hexagon_M2_mpyu_hh_s1, // llvm.hexagon.M2.mpyu.hh.s1 - hexagon_M2_mpyu_hl_s0, // llvm.hexagon.M2.mpyu.hl.s0 - hexagon_M2_mpyu_hl_s1, // llvm.hexagon.M2.mpyu.hl.s1 - hexagon_M2_mpyu_lh_s0, // llvm.hexagon.M2.mpyu.lh.s0 - hexagon_M2_mpyu_lh_s1, // llvm.hexagon.M2.mpyu.lh.s1 - hexagon_M2_mpyu_ll_s0, // llvm.hexagon.M2.mpyu.ll.s0 - hexagon_M2_mpyu_ll_s1, // llvm.hexagon.M2.mpyu.ll.s1 - hexagon_M2_mpyu_nac_hh_s0, // llvm.hexagon.M2.mpyu.nac.hh.s0 - hexagon_M2_mpyu_nac_hh_s1, // llvm.hexagon.M2.mpyu.nac.hh.s1 - hexagon_M2_mpyu_nac_hl_s0, // llvm.hexagon.M2.mpyu.nac.hl.s0 - hexagon_M2_mpyu_nac_hl_s1, // llvm.hexagon.M2.mpyu.nac.hl.s1 - hexagon_M2_mpyu_nac_lh_s0, // llvm.hexagon.M2.mpyu.nac.lh.s0 - hexagon_M2_mpyu_nac_lh_s1, // llvm.hexagon.M2.mpyu.nac.lh.s1 - hexagon_M2_mpyu_nac_ll_s0, // llvm.hexagon.M2.mpyu.nac.ll.s0 - hexagon_M2_mpyu_nac_ll_s1, // llvm.hexagon.M2.mpyu.nac.ll.s1 - hexagon_M2_mpyu_up, // llvm.hexagon.M2.mpyu.up - hexagon_M2_mpyud_acc_hh_s0, // llvm.hexagon.M2.mpyud.acc.hh.s0 - hexagon_M2_mpyud_acc_hh_s1, // llvm.hexagon.M2.mpyud.acc.hh.s1 - hexagon_M2_mpyud_acc_hl_s0, // llvm.hexagon.M2.mpyud.acc.hl.s0 - hexagon_M2_mpyud_acc_hl_s1, // llvm.hexagon.M2.mpyud.acc.hl.s1 - hexagon_M2_mpyud_acc_lh_s0, // llvm.hexagon.M2.mpyud.acc.lh.s0 - hexagon_M2_mpyud_acc_lh_s1, // llvm.hexagon.M2.mpyud.acc.lh.s1 - hexagon_M2_mpyud_acc_ll_s0, // llvm.hexagon.M2.mpyud.acc.ll.s0 - hexagon_M2_mpyud_acc_ll_s1, // llvm.hexagon.M2.mpyud.acc.ll.s1 - hexagon_M2_mpyud_hh_s0, // llvm.hexagon.M2.mpyud.hh.s0 - hexagon_M2_mpyud_hh_s1, // llvm.hexagon.M2.mpyud.hh.s1 - hexagon_M2_mpyud_hl_s0, // llvm.hexagon.M2.mpyud.hl.s0 - hexagon_M2_mpyud_hl_s1, // llvm.hexagon.M2.mpyud.hl.s1 - hexagon_M2_mpyud_lh_s0, // llvm.hexagon.M2.mpyud.lh.s0 - hexagon_M2_mpyud_lh_s1, // llvm.hexagon.M2.mpyud.lh.s1 - hexagon_M2_mpyud_ll_s0, // llvm.hexagon.M2.mpyud.ll.s0 - hexagon_M2_mpyud_ll_s1, // llvm.hexagon.M2.mpyud.ll.s1 - hexagon_M2_mpyud_nac_hh_s0, // llvm.hexagon.M2.mpyud.nac.hh.s0 - hexagon_M2_mpyud_nac_hh_s1, // llvm.hexagon.M2.mpyud.nac.hh.s1 - hexagon_M2_mpyud_nac_hl_s0, // llvm.hexagon.M2.mpyud.nac.hl.s0 - hexagon_M2_mpyud_nac_hl_s1, // llvm.hexagon.M2.mpyud.nac.hl.s1 - hexagon_M2_mpyud_nac_lh_s0, // llvm.hexagon.M2.mpyud.nac.lh.s0 - hexagon_M2_mpyud_nac_lh_s1, // llvm.hexagon.M2.mpyud.nac.lh.s1 - hexagon_M2_mpyud_nac_ll_s0, // llvm.hexagon.M2.mpyud.nac.ll.s0 - hexagon_M2_mpyud_nac_ll_s1, // llvm.hexagon.M2.mpyud.nac.ll.s1 - hexagon_M2_mpyui, // llvm.hexagon.M2.mpyui - hexagon_M2_nacci, // llvm.hexagon.M2.nacci - hexagon_M2_naccii, // llvm.hexagon.M2.naccii - hexagon_M2_subacc, // llvm.hexagon.M2.subacc - hexagon_M2_vabsdiffh, // llvm.hexagon.M2.vabsdiffh - hexagon_M2_vabsdiffw, // llvm.hexagon.M2.vabsdiffw - hexagon_M2_vcmac_s0_sat_i, // llvm.hexagon.M2.vcmac.s0.sat.i - hexagon_M2_vcmac_s0_sat_r, // llvm.hexagon.M2.vcmac.s0.sat.r - hexagon_M2_vcmpy_s0_sat_i, // llvm.hexagon.M2.vcmpy.s0.sat.i - hexagon_M2_vcmpy_s0_sat_r, // llvm.hexagon.M2.vcmpy.s0.sat.r - hexagon_M2_vcmpy_s1_sat_i, // llvm.hexagon.M2.vcmpy.s1.sat.i - hexagon_M2_vcmpy_s1_sat_r, // llvm.hexagon.M2.vcmpy.s1.sat.r - hexagon_M2_vdmacs_s0, // llvm.hexagon.M2.vdmacs.s0 - hexagon_M2_vdmacs_s1, // llvm.hexagon.M2.vdmacs.s1 - hexagon_M2_vdmpyrs_s0, // llvm.hexagon.M2.vdmpyrs.s0 - hexagon_M2_vdmpyrs_s1, // llvm.hexagon.M2.vdmpyrs.s1 - hexagon_M2_vdmpys_s0, // llvm.hexagon.M2.vdmpys.s0 - hexagon_M2_vdmpys_s1, // llvm.hexagon.M2.vdmpys.s1 - hexagon_M2_vmac2, // llvm.hexagon.M2.vmac2 - hexagon_M2_vmac2es, // llvm.hexagon.M2.vmac2es - hexagon_M2_vmac2es_s0, // llvm.hexagon.M2.vmac2es.s0 - hexagon_M2_vmac2es_s1, // llvm.hexagon.M2.vmac2es.s1 - hexagon_M2_vmac2s_s0, // llvm.hexagon.M2.vmac2s.s0 - hexagon_M2_vmac2s_s1, // llvm.hexagon.M2.vmac2s.s1 - hexagon_M2_vmac2su_s0, // llvm.hexagon.M2.vmac2su.s0 - hexagon_M2_vmac2su_s1, // llvm.hexagon.M2.vmac2su.s1 - hexagon_M2_vmpy2es_s0, // llvm.hexagon.M2.vmpy2es.s0 - hexagon_M2_vmpy2es_s1, // llvm.hexagon.M2.vmpy2es.s1 - hexagon_M2_vmpy2s_s0, // llvm.hexagon.M2.vmpy2s.s0 - hexagon_M2_vmpy2s_s0pack, // llvm.hexagon.M2.vmpy2s.s0pack - hexagon_M2_vmpy2s_s1, // llvm.hexagon.M2.vmpy2s.s1 - hexagon_M2_vmpy2s_s1pack, // llvm.hexagon.M2.vmpy2s.s1pack - hexagon_M2_vmpy2su_s0, // llvm.hexagon.M2.vmpy2su.s0 - hexagon_M2_vmpy2su_s1, // llvm.hexagon.M2.vmpy2su.s1 - hexagon_M2_vraddh, // llvm.hexagon.M2.vraddh - hexagon_M2_vradduh, // llvm.hexagon.M2.vradduh - hexagon_M2_vrcmaci_s0, // llvm.hexagon.M2.vrcmaci.s0 - hexagon_M2_vrcmaci_s0c, // llvm.hexagon.M2.vrcmaci.s0c - hexagon_M2_vrcmacr_s0, // llvm.hexagon.M2.vrcmacr.s0 - hexagon_M2_vrcmacr_s0c, // llvm.hexagon.M2.vrcmacr.s0c - hexagon_M2_vrcmpyi_s0, // llvm.hexagon.M2.vrcmpyi.s0 - hexagon_M2_vrcmpyi_s0c, // llvm.hexagon.M2.vrcmpyi.s0c - hexagon_M2_vrcmpyr_s0, // llvm.hexagon.M2.vrcmpyr.s0 - hexagon_M2_vrcmpyr_s0c, // llvm.hexagon.M2.vrcmpyr.s0c - hexagon_M2_vrcmpys_acc_s1, // llvm.hexagon.M2.vrcmpys.acc.s1 - hexagon_M2_vrcmpys_s1, // llvm.hexagon.M2.vrcmpys.s1 - hexagon_M2_vrcmpys_s1rp, // llvm.hexagon.M2.vrcmpys.s1rp - hexagon_M2_vrmac_s0, // llvm.hexagon.M2.vrmac.s0 - hexagon_M2_vrmpy_s0, // llvm.hexagon.M2.vrmpy.s0 - hexagon_M2_xor_xacc, // llvm.hexagon.M2.xor.xacc - hexagon_M4_and_and, // llvm.hexagon.M4.and.and - hexagon_M4_and_andn, // llvm.hexagon.M4.and.andn - hexagon_M4_and_or, // llvm.hexagon.M4.and.or - hexagon_M4_and_xor, // llvm.hexagon.M4.and.xor - hexagon_M4_cmpyi_wh, // llvm.hexagon.M4.cmpyi.wh - hexagon_M4_cmpyi_whc, // llvm.hexagon.M4.cmpyi.whc - hexagon_M4_cmpyr_wh, // llvm.hexagon.M4.cmpyr.wh - hexagon_M4_cmpyr_whc, // llvm.hexagon.M4.cmpyr.whc - hexagon_M4_mac_up_s1_sat, // llvm.hexagon.M4.mac.up.s1.sat - hexagon_M4_mpyri_addi, // llvm.hexagon.M4.mpyri.addi - hexagon_M4_mpyri_addr, // llvm.hexagon.M4.mpyri.addr - hexagon_M4_mpyri_addr_u2, // llvm.hexagon.M4.mpyri.addr.u2 - hexagon_M4_mpyrr_addi, // llvm.hexagon.M4.mpyrr.addi - hexagon_M4_mpyrr_addr, // llvm.hexagon.M4.mpyrr.addr - hexagon_M4_nac_up_s1_sat, // llvm.hexagon.M4.nac.up.s1.sat - hexagon_M4_or_and, // llvm.hexagon.M4.or.and - hexagon_M4_or_andn, // llvm.hexagon.M4.or.andn - hexagon_M4_or_or, // llvm.hexagon.M4.or.or - hexagon_M4_or_xor, // llvm.hexagon.M4.or.xor - hexagon_M4_pmpyw, // llvm.hexagon.M4.pmpyw - hexagon_M4_pmpyw_acc, // llvm.hexagon.M4.pmpyw.acc - hexagon_M4_vpmpyh, // llvm.hexagon.M4.vpmpyh - hexagon_M4_vpmpyh_acc, // llvm.hexagon.M4.vpmpyh.acc - hexagon_M4_vrmpyeh_acc_s0, // llvm.hexagon.M4.vrmpyeh.acc.s0 - hexagon_M4_vrmpyeh_acc_s1, // llvm.hexagon.M4.vrmpyeh.acc.s1 - hexagon_M4_vrmpyeh_s0, // llvm.hexagon.M4.vrmpyeh.s0 - hexagon_M4_vrmpyeh_s1, // llvm.hexagon.M4.vrmpyeh.s1 - hexagon_M4_vrmpyoh_acc_s0, // llvm.hexagon.M4.vrmpyoh.acc.s0 - hexagon_M4_vrmpyoh_acc_s1, // llvm.hexagon.M4.vrmpyoh.acc.s1 - hexagon_M4_vrmpyoh_s0, // llvm.hexagon.M4.vrmpyoh.s0 - hexagon_M4_vrmpyoh_s1, // llvm.hexagon.M4.vrmpyoh.s1 - hexagon_M4_xor_and, // llvm.hexagon.M4.xor.and - hexagon_M4_xor_andn, // llvm.hexagon.M4.xor.andn - hexagon_M4_xor_or, // llvm.hexagon.M4.xor.or - hexagon_M4_xor_xacc, // llvm.hexagon.M4.xor.xacc - hexagon_M5_vdmacbsu, // llvm.hexagon.M5.vdmacbsu - hexagon_M5_vdmpybsu, // llvm.hexagon.M5.vdmpybsu - hexagon_M5_vmacbsu, // llvm.hexagon.M5.vmacbsu - hexagon_M5_vmacbuu, // llvm.hexagon.M5.vmacbuu - hexagon_M5_vmpybsu, // llvm.hexagon.M5.vmpybsu - hexagon_M5_vmpybuu, // llvm.hexagon.M5.vmpybuu - hexagon_M5_vrmacbsu, // llvm.hexagon.M5.vrmacbsu - hexagon_M5_vrmacbuu, // llvm.hexagon.M5.vrmacbuu - hexagon_M5_vrmpybsu, // llvm.hexagon.M5.vrmpybsu - hexagon_M5_vrmpybuu, // llvm.hexagon.M5.vrmpybuu - hexagon_M6_vabsdiffb, // llvm.hexagon.M6.vabsdiffb - hexagon_M6_vabsdiffub, // llvm.hexagon.M6.vabsdiffub - hexagon_M7_dcmpyiw, // llvm.hexagon.M7.dcmpyiw - hexagon_M7_dcmpyiw_acc, // llvm.hexagon.M7.dcmpyiw.acc - hexagon_M7_dcmpyiwc, // llvm.hexagon.M7.dcmpyiwc - hexagon_M7_dcmpyiwc_acc, // llvm.hexagon.M7.dcmpyiwc.acc - hexagon_M7_dcmpyrw, // llvm.hexagon.M7.dcmpyrw - hexagon_M7_dcmpyrw_acc, // llvm.hexagon.M7.dcmpyrw.acc - hexagon_M7_dcmpyrwc, // llvm.hexagon.M7.dcmpyrwc - hexagon_M7_dcmpyrwc_acc, // llvm.hexagon.M7.dcmpyrwc.acc - hexagon_M7_vdmpy, // llvm.hexagon.M7.vdmpy - hexagon_M7_vdmpy_acc, // llvm.hexagon.M7.vdmpy.acc - hexagon_M7_wcmpyiw, // llvm.hexagon.M7.wcmpyiw - hexagon_M7_wcmpyiw_rnd, // llvm.hexagon.M7.wcmpyiw.rnd - hexagon_M7_wcmpyiwc, // llvm.hexagon.M7.wcmpyiwc - hexagon_M7_wcmpyiwc_rnd, // llvm.hexagon.M7.wcmpyiwc.rnd - hexagon_M7_wcmpyrw, // llvm.hexagon.M7.wcmpyrw - hexagon_M7_wcmpyrw_rnd, // llvm.hexagon.M7.wcmpyrw.rnd - hexagon_M7_wcmpyrwc, // llvm.hexagon.M7.wcmpyrwc - hexagon_M7_wcmpyrwc_rnd, // llvm.hexagon.M7.wcmpyrwc.rnd - hexagon_S2_addasl_rrri, // llvm.hexagon.S2.addasl.rrri - hexagon_S2_asl_i_p, // llvm.hexagon.S2.asl.i.p - hexagon_S2_asl_i_p_acc, // llvm.hexagon.S2.asl.i.p.acc - hexagon_S2_asl_i_p_and, // llvm.hexagon.S2.asl.i.p.and - hexagon_S2_asl_i_p_nac, // llvm.hexagon.S2.asl.i.p.nac - hexagon_S2_asl_i_p_or, // llvm.hexagon.S2.asl.i.p.or - hexagon_S2_asl_i_p_xacc, // llvm.hexagon.S2.asl.i.p.xacc - hexagon_S2_asl_i_r, // llvm.hexagon.S2.asl.i.r - hexagon_S2_asl_i_r_acc, // llvm.hexagon.S2.asl.i.r.acc - hexagon_S2_asl_i_r_and, // llvm.hexagon.S2.asl.i.r.and - hexagon_S2_asl_i_r_nac, // llvm.hexagon.S2.asl.i.r.nac - hexagon_S2_asl_i_r_or, // llvm.hexagon.S2.asl.i.r.or - hexagon_S2_asl_i_r_sat, // llvm.hexagon.S2.asl.i.r.sat - hexagon_S2_asl_i_r_xacc, // llvm.hexagon.S2.asl.i.r.xacc - hexagon_S2_asl_i_vh, // llvm.hexagon.S2.asl.i.vh - hexagon_S2_asl_i_vw, // llvm.hexagon.S2.asl.i.vw - hexagon_S2_asl_r_p, // llvm.hexagon.S2.asl.r.p - hexagon_S2_asl_r_p_acc, // llvm.hexagon.S2.asl.r.p.acc - hexagon_S2_asl_r_p_and, // llvm.hexagon.S2.asl.r.p.and - hexagon_S2_asl_r_p_nac, // llvm.hexagon.S2.asl.r.p.nac - hexagon_S2_asl_r_p_or, // llvm.hexagon.S2.asl.r.p.or - hexagon_S2_asl_r_p_xor, // llvm.hexagon.S2.asl.r.p.xor - hexagon_S2_asl_r_r, // llvm.hexagon.S2.asl.r.r - hexagon_S2_asl_r_r_acc, // llvm.hexagon.S2.asl.r.r.acc - hexagon_S2_asl_r_r_and, // llvm.hexagon.S2.asl.r.r.and - hexagon_S2_asl_r_r_nac, // llvm.hexagon.S2.asl.r.r.nac - hexagon_S2_asl_r_r_or, // llvm.hexagon.S2.asl.r.r.or - hexagon_S2_asl_r_r_sat, // llvm.hexagon.S2.asl.r.r.sat - hexagon_S2_asl_r_vh, // llvm.hexagon.S2.asl.r.vh - hexagon_S2_asl_r_vw, // llvm.hexagon.S2.asl.r.vw - hexagon_S2_asr_i_p, // llvm.hexagon.S2.asr.i.p - hexagon_S2_asr_i_p_acc, // llvm.hexagon.S2.asr.i.p.acc - hexagon_S2_asr_i_p_and, // llvm.hexagon.S2.asr.i.p.and - hexagon_S2_asr_i_p_nac, // llvm.hexagon.S2.asr.i.p.nac - hexagon_S2_asr_i_p_or, // llvm.hexagon.S2.asr.i.p.or - hexagon_S2_asr_i_p_rnd, // llvm.hexagon.S2.asr.i.p.rnd - hexagon_S2_asr_i_p_rnd_goodsyntax, // llvm.hexagon.S2.asr.i.p.rnd.goodsyntax - hexagon_S2_asr_i_r, // llvm.hexagon.S2.asr.i.r - hexagon_S2_asr_i_r_acc, // llvm.hexagon.S2.asr.i.r.acc - hexagon_S2_asr_i_r_and, // llvm.hexagon.S2.asr.i.r.and - hexagon_S2_asr_i_r_nac, // llvm.hexagon.S2.asr.i.r.nac - hexagon_S2_asr_i_r_or, // llvm.hexagon.S2.asr.i.r.or - hexagon_S2_asr_i_r_rnd, // llvm.hexagon.S2.asr.i.r.rnd - hexagon_S2_asr_i_r_rnd_goodsyntax, // llvm.hexagon.S2.asr.i.r.rnd.goodsyntax - hexagon_S2_asr_i_svw_trun, // llvm.hexagon.S2.asr.i.svw.trun - hexagon_S2_asr_i_vh, // llvm.hexagon.S2.asr.i.vh - hexagon_S2_asr_i_vw, // llvm.hexagon.S2.asr.i.vw - hexagon_S2_asr_r_p, // llvm.hexagon.S2.asr.r.p - hexagon_S2_asr_r_p_acc, // llvm.hexagon.S2.asr.r.p.acc - hexagon_S2_asr_r_p_and, // llvm.hexagon.S2.asr.r.p.and - hexagon_S2_asr_r_p_nac, // llvm.hexagon.S2.asr.r.p.nac - hexagon_S2_asr_r_p_or, // llvm.hexagon.S2.asr.r.p.or - hexagon_S2_asr_r_p_xor, // llvm.hexagon.S2.asr.r.p.xor - hexagon_S2_asr_r_r, // llvm.hexagon.S2.asr.r.r - hexagon_S2_asr_r_r_acc, // llvm.hexagon.S2.asr.r.r.acc - hexagon_S2_asr_r_r_and, // llvm.hexagon.S2.asr.r.r.and - hexagon_S2_asr_r_r_nac, // llvm.hexagon.S2.asr.r.r.nac - hexagon_S2_asr_r_r_or, // llvm.hexagon.S2.asr.r.r.or - hexagon_S2_asr_r_r_sat, // llvm.hexagon.S2.asr.r.r.sat - hexagon_S2_asr_r_svw_trun, // llvm.hexagon.S2.asr.r.svw.trun - hexagon_S2_asr_r_vh, // llvm.hexagon.S2.asr.r.vh - hexagon_S2_asr_r_vw, // llvm.hexagon.S2.asr.r.vw - hexagon_S2_brev, // llvm.hexagon.S2.brev - hexagon_S2_brevp, // llvm.hexagon.S2.brevp - hexagon_S2_cl0, // llvm.hexagon.S2.cl0 - hexagon_S2_cl0p, // llvm.hexagon.S2.cl0p - hexagon_S2_cl1, // llvm.hexagon.S2.cl1 - hexagon_S2_cl1p, // llvm.hexagon.S2.cl1p - hexagon_S2_clb, // llvm.hexagon.S2.clb - hexagon_S2_clbnorm, // llvm.hexagon.S2.clbnorm - hexagon_S2_clbp, // llvm.hexagon.S2.clbp - hexagon_S2_clrbit_i, // llvm.hexagon.S2.clrbit.i - hexagon_S2_clrbit_r, // llvm.hexagon.S2.clrbit.r - hexagon_S2_ct0, // llvm.hexagon.S2.ct0 - hexagon_S2_ct0p, // llvm.hexagon.S2.ct0p - hexagon_S2_ct1, // llvm.hexagon.S2.ct1 - hexagon_S2_ct1p, // llvm.hexagon.S2.ct1p - hexagon_S2_deinterleave, // llvm.hexagon.S2.deinterleave - hexagon_S2_extractu, // llvm.hexagon.S2.extractu - hexagon_S2_extractu_rp, // llvm.hexagon.S2.extractu.rp - hexagon_S2_extractup, // llvm.hexagon.S2.extractup - hexagon_S2_extractup_rp, // llvm.hexagon.S2.extractup.rp - hexagon_S2_insert, // llvm.hexagon.S2.insert - hexagon_S2_insert_rp, // llvm.hexagon.S2.insert.rp - hexagon_S2_insertp, // llvm.hexagon.S2.insertp - hexagon_S2_insertp_rp, // llvm.hexagon.S2.insertp.rp - hexagon_S2_interleave, // llvm.hexagon.S2.interleave - hexagon_S2_lfsp, // llvm.hexagon.S2.lfsp - hexagon_S2_lsl_r_p, // llvm.hexagon.S2.lsl.r.p - hexagon_S2_lsl_r_p_acc, // llvm.hexagon.S2.lsl.r.p.acc - hexagon_S2_lsl_r_p_and, // llvm.hexagon.S2.lsl.r.p.and - hexagon_S2_lsl_r_p_nac, // llvm.hexagon.S2.lsl.r.p.nac - hexagon_S2_lsl_r_p_or, // llvm.hexagon.S2.lsl.r.p.or - hexagon_S2_lsl_r_p_xor, // llvm.hexagon.S2.lsl.r.p.xor - hexagon_S2_lsl_r_r, // llvm.hexagon.S2.lsl.r.r - hexagon_S2_lsl_r_r_acc, // llvm.hexagon.S2.lsl.r.r.acc - hexagon_S2_lsl_r_r_and, // llvm.hexagon.S2.lsl.r.r.and - hexagon_S2_lsl_r_r_nac, // llvm.hexagon.S2.lsl.r.r.nac - hexagon_S2_lsl_r_r_or, // llvm.hexagon.S2.lsl.r.r.or - hexagon_S2_lsl_r_vh, // llvm.hexagon.S2.lsl.r.vh - hexagon_S2_lsl_r_vw, // llvm.hexagon.S2.lsl.r.vw - hexagon_S2_lsr_i_p, // llvm.hexagon.S2.lsr.i.p - hexagon_S2_lsr_i_p_acc, // llvm.hexagon.S2.lsr.i.p.acc - hexagon_S2_lsr_i_p_and, // llvm.hexagon.S2.lsr.i.p.and - hexagon_S2_lsr_i_p_nac, // llvm.hexagon.S2.lsr.i.p.nac - hexagon_S2_lsr_i_p_or, // llvm.hexagon.S2.lsr.i.p.or - hexagon_S2_lsr_i_p_xacc, // llvm.hexagon.S2.lsr.i.p.xacc - hexagon_S2_lsr_i_r, // llvm.hexagon.S2.lsr.i.r - hexagon_S2_lsr_i_r_acc, // llvm.hexagon.S2.lsr.i.r.acc - hexagon_S2_lsr_i_r_and, // llvm.hexagon.S2.lsr.i.r.and - hexagon_S2_lsr_i_r_nac, // llvm.hexagon.S2.lsr.i.r.nac - hexagon_S2_lsr_i_r_or, // llvm.hexagon.S2.lsr.i.r.or - hexagon_S2_lsr_i_r_xacc, // llvm.hexagon.S2.lsr.i.r.xacc - hexagon_S2_lsr_i_vh, // llvm.hexagon.S2.lsr.i.vh - hexagon_S2_lsr_i_vw, // llvm.hexagon.S2.lsr.i.vw - hexagon_S2_lsr_r_p, // llvm.hexagon.S2.lsr.r.p - hexagon_S2_lsr_r_p_acc, // llvm.hexagon.S2.lsr.r.p.acc - hexagon_S2_lsr_r_p_and, // llvm.hexagon.S2.lsr.r.p.and - hexagon_S2_lsr_r_p_nac, // llvm.hexagon.S2.lsr.r.p.nac - hexagon_S2_lsr_r_p_or, // llvm.hexagon.S2.lsr.r.p.or - hexagon_S2_lsr_r_p_xor, // llvm.hexagon.S2.lsr.r.p.xor - hexagon_S2_lsr_r_r, // llvm.hexagon.S2.lsr.r.r - hexagon_S2_lsr_r_r_acc, // llvm.hexagon.S2.lsr.r.r.acc - hexagon_S2_lsr_r_r_and, // llvm.hexagon.S2.lsr.r.r.and - hexagon_S2_lsr_r_r_nac, // llvm.hexagon.S2.lsr.r.r.nac - hexagon_S2_lsr_r_r_or, // llvm.hexagon.S2.lsr.r.r.or - hexagon_S2_lsr_r_vh, // llvm.hexagon.S2.lsr.r.vh - hexagon_S2_lsr_r_vw, // llvm.hexagon.S2.lsr.r.vw - hexagon_S2_mask, // llvm.hexagon.S2.mask - hexagon_S2_packhl, // llvm.hexagon.S2.packhl - hexagon_S2_parityp, // llvm.hexagon.S2.parityp - hexagon_S2_setbit_i, // llvm.hexagon.S2.setbit.i - hexagon_S2_setbit_r, // llvm.hexagon.S2.setbit.r - hexagon_S2_shuffeb, // llvm.hexagon.S2.shuffeb - hexagon_S2_shuffeh, // llvm.hexagon.S2.shuffeh - hexagon_S2_shuffob, // llvm.hexagon.S2.shuffob - hexagon_S2_shuffoh, // llvm.hexagon.S2.shuffoh - hexagon_S2_storerb_pbr, // llvm.hexagon.S2.storerb.pbr - hexagon_S2_storerb_pci, // llvm.hexagon.S2.storerb.pci - hexagon_S2_storerb_pcr, // llvm.hexagon.S2.storerb.pcr - hexagon_S2_storerd_pbr, // llvm.hexagon.S2.storerd.pbr - hexagon_S2_storerd_pci, // llvm.hexagon.S2.storerd.pci - hexagon_S2_storerd_pcr, // llvm.hexagon.S2.storerd.pcr - hexagon_S2_storerf_pbr, // llvm.hexagon.S2.storerf.pbr - hexagon_S2_storerf_pci, // llvm.hexagon.S2.storerf.pci - hexagon_S2_storerf_pcr, // llvm.hexagon.S2.storerf.pcr - hexagon_S2_storerh_pbr, // llvm.hexagon.S2.storerh.pbr - hexagon_S2_storerh_pci, // llvm.hexagon.S2.storerh.pci - hexagon_S2_storerh_pcr, // llvm.hexagon.S2.storerh.pcr - hexagon_S2_storeri_pbr, // llvm.hexagon.S2.storeri.pbr - hexagon_S2_storeri_pci, // llvm.hexagon.S2.storeri.pci - hexagon_S2_storeri_pcr, // llvm.hexagon.S2.storeri.pcr - hexagon_S2_storew_locked, // llvm.hexagon.S2.storew.locked - hexagon_S2_svsathb, // llvm.hexagon.S2.svsathb - hexagon_S2_svsathub, // llvm.hexagon.S2.svsathub - hexagon_S2_tableidxb_goodsyntax, // llvm.hexagon.S2.tableidxb.goodsyntax - hexagon_S2_tableidxd_goodsyntax, // llvm.hexagon.S2.tableidxd.goodsyntax - hexagon_S2_tableidxh_goodsyntax, // llvm.hexagon.S2.tableidxh.goodsyntax - hexagon_S2_tableidxw_goodsyntax, // llvm.hexagon.S2.tableidxw.goodsyntax - hexagon_S2_togglebit_i, // llvm.hexagon.S2.togglebit.i - hexagon_S2_togglebit_r, // llvm.hexagon.S2.togglebit.r - hexagon_S2_tstbit_i, // llvm.hexagon.S2.tstbit.i - hexagon_S2_tstbit_r, // llvm.hexagon.S2.tstbit.r - hexagon_S2_valignib, // llvm.hexagon.S2.valignib - hexagon_S2_valignrb, // llvm.hexagon.S2.valignrb - hexagon_S2_vcnegh, // llvm.hexagon.S2.vcnegh - hexagon_S2_vcrotate, // llvm.hexagon.S2.vcrotate - hexagon_S2_vrcnegh, // llvm.hexagon.S2.vrcnegh - hexagon_S2_vrndpackwh, // llvm.hexagon.S2.vrndpackwh - hexagon_S2_vrndpackwhs, // llvm.hexagon.S2.vrndpackwhs - hexagon_S2_vsathb, // llvm.hexagon.S2.vsathb - hexagon_S2_vsathb_nopack, // llvm.hexagon.S2.vsathb.nopack - hexagon_S2_vsathub, // llvm.hexagon.S2.vsathub - hexagon_S2_vsathub_nopack, // llvm.hexagon.S2.vsathub.nopack - hexagon_S2_vsatwh, // llvm.hexagon.S2.vsatwh - hexagon_S2_vsatwh_nopack, // llvm.hexagon.S2.vsatwh.nopack - hexagon_S2_vsatwuh, // llvm.hexagon.S2.vsatwuh - hexagon_S2_vsatwuh_nopack, // llvm.hexagon.S2.vsatwuh.nopack - hexagon_S2_vsplatrb, // llvm.hexagon.S2.vsplatrb - hexagon_S2_vsplatrh, // llvm.hexagon.S2.vsplatrh - hexagon_S2_vspliceib, // llvm.hexagon.S2.vspliceib - hexagon_S2_vsplicerb, // llvm.hexagon.S2.vsplicerb - hexagon_S2_vsxtbh, // llvm.hexagon.S2.vsxtbh - hexagon_S2_vsxthw, // llvm.hexagon.S2.vsxthw - hexagon_S2_vtrunehb, // llvm.hexagon.S2.vtrunehb - hexagon_S2_vtrunewh, // llvm.hexagon.S2.vtrunewh - hexagon_S2_vtrunohb, // llvm.hexagon.S2.vtrunohb - hexagon_S2_vtrunowh, // llvm.hexagon.S2.vtrunowh - hexagon_S2_vzxtbh, // llvm.hexagon.S2.vzxtbh - hexagon_S2_vzxthw, // llvm.hexagon.S2.vzxthw - hexagon_S4_addaddi, // llvm.hexagon.S4.addaddi - hexagon_S4_addi_asl_ri, // llvm.hexagon.S4.addi.asl.ri - hexagon_S4_addi_lsr_ri, // llvm.hexagon.S4.addi.lsr.ri - hexagon_S4_andi_asl_ri, // llvm.hexagon.S4.andi.asl.ri - hexagon_S4_andi_lsr_ri, // llvm.hexagon.S4.andi.lsr.ri - hexagon_S4_clbaddi, // llvm.hexagon.S4.clbaddi - hexagon_S4_clbpaddi, // llvm.hexagon.S4.clbpaddi - hexagon_S4_clbpnorm, // llvm.hexagon.S4.clbpnorm - hexagon_S4_extract, // llvm.hexagon.S4.extract - hexagon_S4_extract_rp, // llvm.hexagon.S4.extract.rp - hexagon_S4_extractp, // llvm.hexagon.S4.extractp - hexagon_S4_extractp_rp, // llvm.hexagon.S4.extractp.rp - hexagon_S4_lsli, // llvm.hexagon.S4.lsli - hexagon_S4_ntstbit_i, // llvm.hexagon.S4.ntstbit.i - hexagon_S4_ntstbit_r, // llvm.hexagon.S4.ntstbit.r - hexagon_S4_or_andi, // llvm.hexagon.S4.or.andi - hexagon_S4_or_andix, // llvm.hexagon.S4.or.andix - hexagon_S4_or_ori, // llvm.hexagon.S4.or.ori - hexagon_S4_ori_asl_ri, // llvm.hexagon.S4.ori.asl.ri - hexagon_S4_ori_lsr_ri, // llvm.hexagon.S4.ori.lsr.ri - hexagon_S4_parity, // llvm.hexagon.S4.parity - hexagon_S4_stored_locked, // llvm.hexagon.S4.stored.locked - hexagon_S4_subaddi, // llvm.hexagon.S4.subaddi - hexagon_S4_subi_asl_ri, // llvm.hexagon.S4.subi.asl.ri - hexagon_S4_subi_lsr_ri, // llvm.hexagon.S4.subi.lsr.ri - hexagon_S4_vrcrotate, // llvm.hexagon.S4.vrcrotate - hexagon_S4_vrcrotate_acc, // llvm.hexagon.S4.vrcrotate.acc - hexagon_S4_vxaddsubh, // llvm.hexagon.S4.vxaddsubh - hexagon_S4_vxaddsubhr, // llvm.hexagon.S4.vxaddsubhr - hexagon_S4_vxaddsubw, // llvm.hexagon.S4.vxaddsubw - hexagon_S4_vxsubaddh, // llvm.hexagon.S4.vxsubaddh - hexagon_S4_vxsubaddhr, // llvm.hexagon.S4.vxsubaddhr - hexagon_S4_vxsubaddw, // llvm.hexagon.S4.vxsubaddw - hexagon_S5_asrhub_rnd_sat_goodsyntax, // llvm.hexagon.S5.asrhub.rnd.sat.goodsyntax - hexagon_S5_asrhub_sat, // llvm.hexagon.S5.asrhub.sat - hexagon_S5_popcountp, // llvm.hexagon.S5.popcountp - hexagon_S5_vasrhrnd_goodsyntax, // llvm.hexagon.S5.vasrhrnd.goodsyntax - hexagon_S6_rol_i_p, // llvm.hexagon.S6.rol.i.p - hexagon_S6_rol_i_p_acc, // llvm.hexagon.S6.rol.i.p.acc - hexagon_S6_rol_i_p_and, // llvm.hexagon.S6.rol.i.p.and - hexagon_S6_rol_i_p_nac, // llvm.hexagon.S6.rol.i.p.nac - hexagon_S6_rol_i_p_or, // llvm.hexagon.S6.rol.i.p.or - hexagon_S6_rol_i_p_xacc, // llvm.hexagon.S6.rol.i.p.xacc - hexagon_S6_rol_i_r, // llvm.hexagon.S6.rol.i.r - hexagon_S6_rol_i_r_acc, // llvm.hexagon.S6.rol.i.r.acc - hexagon_S6_rol_i_r_and, // llvm.hexagon.S6.rol.i.r.and - hexagon_S6_rol_i_r_nac, // llvm.hexagon.S6.rol.i.r.nac - hexagon_S6_rol_i_r_or, // llvm.hexagon.S6.rol.i.r.or - hexagon_S6_rol_i_r_xacc, // llvm.hexagon.S6.rol.i.r.xacc - hexagon_S6_vsplatrbp, // llvm.hexagon.S6.vsplatrbp - hexagon_S6_vtrunehb_ppp, // llvm.hexagon.S6.vtrunehb.ppp - hexagon_S6_vtrunohb_ppp, // llvm.hexagon.S6.vtrunohb.ppp - hexagon_V6_extractw, // llvm.hexagon.V6.extractw - hexagon_V6_extractw_128B, // llvm.hexagon.V6.extractw.128B - hexagon_V6_hi, // llvm.hexagon.V6.hi - hexagon_V6_hi_128B, // llvm.hexagon.V6.hi.128B - hexagon_V6_lo, // llvm.hexagon.V6.lo - hexagon_V6_lo_128B, // llvm.hexagon.V6.lo.128B - hexagon_V6_lvsplatb, // llvm.hexagon.V6.lvsplatb - hexagon_V6_lvsplatb_128B, // llvm.hexagon.V6.lvsplatb.128B - hexagon_V6_lvsplath, // llvm.hexagon.V6.lvsplath - hexagon_V6_lvsplath_128B, // llvm.hexagon.V6.lvsplath.128B - hexagon_V6_lvsplatw, // llvm.hexagon.V6.lvsplatw - hexagon_V6_lvsplatw_128B, // llvm.hexagon.V6.lvsplatw.128B - hexagon_V6_pred_and, // llvm.hexagon.V6.pred.and - hexagon_V6_pred_and_128B, // llvm.hexagon.V6.pred.and.128B - hexagon_V6_pred_and_n, // llvm.hexagon.V6.pred.and.n - hexagon_V6_pred_and_n_128B, // llvm.hexagon.V6.pred.and.n.128B - hexagon_V6_pred_not, // llvm.hexagon.V6.pred.not - hexagon_V6_pred_not_128B, // llvm.hexagon.V6.pred.not.128B - hexagon_V6_pred_or, // llvm.hexagon.V6.pred.or - hexagon_V6_pred_or_128B, // llvm.hexagon.V6.pred.or.128B - hexagon_V6_pred_or_n, // llvm.hexagon.V6.pred.or.n - hexagon_V6_pred_or_n_128B, // llvm.hexagon.V6.pred.or.n.128B - hexagon_V6_pred_scalar2, // llvm.hexagon.V6.pred.scalar2 - hexagon_V6_pred_scalar2_128B, // llvm.hexagon.V6.pred.scalar2.128B - hexagon_V6_pred_scalar2v2, // llvm.hexagon.V6.pred.scalar2v2 - hexagon_V6_pred_scalar2v2_128B, // llvm.hexagon.V6.pred.scalar2v2.128B - hexagon_V6_pred_typecast, // llvm.hexagon.V6.pred.typecast - hexagon_V6_pred_typecast_128B, // llvm.hexagon.V6.pred.typecast.128B - hexagon_V6_pred_xor, // llvm.hexagon.V6.pred.xor - hexagon_V6_pred_xor_128B, // llvm.hexagon.V6.pred.xor.128B - hexagon_V6_shuffeqh, // llvm.hexagon.V6.shuffeqh - hexagon_V6_shuffeqh_128B, // llvm.hexagon.V6.shuffeqh.128B - hexagon_V6_shuffeqw, // llvm.hexagon.V6.shuffeqw - hexagon_V6_shuffeqw_128B, // llvm.hexagon.V6.shuffeqw.128B - hexagon_V6_v6mpyhubs10, // llvm.hexagon.V6.v6mpyhubs10 - hexagon_V6_v6mpyhubs10_128B, // llvm.hexagon.V6.v6mpyhubs10.128B - hexagon_V6_v6mpyhubs10_vxx, // llvm.hexagon.V6.v6mpyhubs10.vxx - hexagon_V6_v6mpyhubs10_vxx_128B, // llvm.hexagon.V6.v6mpyhubs10.vxx.128B - hexagon_V6_v6mpyvubs10, // llvm.hexagon.V6.v6mpyvubs10 - hexagon_V6_v6mpyvubs10_128B, // llvm.hexagon.V6.v6mpyvubs10.128B - hexagon_V6_v6mpyvubs10_vxx, // llvm.hexagon.V6.v6mpyvubs10.vxx - hexagon_V6_v6mpyvubs10_vxx_128B, // llvm.hexagon.V6.v6mpyvubs10.vxx.128B - hexagon_V6_vL32b_npred_ai, // llvm.hexagon.V6.vL32b.npred.ai - hexagon_V6_vL32b_npred_ai_128B, // llvm.hexagon.V6.vL32b.npred.ai.128B - hexagon_V6_vL32b_npred_pi, // llvm.hexagon.V6.vL32b.npred.pi - hexagon_V6_vL32b_npred_pi_128B, // llvm.hexagon.V6.vL32b.npred.pi.128B - hexagon_V6_vL32b_npred_ppu, // llvm.hexagon.V6.vL32b.npred.ppu - hexagon_V6_vL32b_npred_ppu_128B, // llvm.hexagon.V6.vL32b.npred.ppu.128B - hexagon_V6_vL32b_nt_npred_ai, // llvm.hexagon.V6.vL32b.nt.npred.ai - hexagon_V6_vL32b_nt_npred_ai_128B, // llvm.hexagon.V6.vL32b.nt.npred.ai.128B - hexagon_V6_vL32b_nt_npred_pi, // llvm.hexagon.V6.vL32b.nt.npred.pi - hexagon_V6_vL32b_nt_npred_pi_128B, // llvm.hexagon.V6.vL32b.nt.npred.pi.128B - hexagon_V6_vL32b_nt_npred_ppu, // llvm.hexagon.V6.vL32b.nt.npred.ppu - hexagon_V6_vL32b_nt_npred_ppu_128B, // llvm.hexagon.V6.vL32b.nt.npred.ppu.128B - hexagon_V6_vL32b_nt_pred_ai, // llvm.hexagon.V6.vL32b.nt.pred.ai - hexagon_V6_vL32b_nt_pred_ai_128B, // llvm.hexagon.V6.vL32b.nt.pred.ai.128B - hexagon_V6_vL32b_nt_pred_pi, // llvm.hexagon.V6.vL32b.nt.pred.pi - hexagon_V6_vL32b_nt_pred_pi_128B, // llvm.hexagon.V6.vL32b.nt.pred.pi.128B - hexagon_V6_vL32b_nt_pred_ppu, // llvm.hexagon.V6.vL32b.nt.pred.ppu - hexagon_V6_vL32b_nt_pred_ppu_128B, // llvm.hexagon.V6.vL32b.nt.pred.ppu.128B - hexagon_V6_vL32b_pred_ai, // llvm.hexagon.V6.vL32b.pred.ai - hexagon_V6_vL32b_pred_ai_128B, // llvm.hexagon.V6.vL32b.pred.ai.128B - hexagon_V6_vL32b_pred_pi, // llvm.hexagon.V6.vL32b.pred.pi - hexagon_V6_vL32b_pred_pi_128B, // llvm.hexagon.V6.vL32b.pred.pi.128B - hexagon_V6_vL32b_pred_ppu, // llvm.hexagon.V6.vL32b.pred.ppu - hexagon_V6_vL32b_pred_ppu_128B, // llvm.hexagon.V6.vL32b.pred.ppu.128B - hexagon_V6_vS32Ub_npred_ai, // llvm.hexagon.V6.vS32Ub.npred.ai - hexagon_V6_vS32Ub_npred_ai_128B, // llvm.hexagon.V6.vS32Ub.npred.ai.128B - hexagon_V6_vS32Ub_npred_pi, // llvm.hexagon.V6.vS32Ub.npred.pi - hexagon_V6_vS32Ub_npred_pi_128B, // llvm.hexagon.V6.vS32Ub.npred.pi.128B - hexagon_V6_vS32Ub_npred_ppu, // llvm.hexagon.V6.vS32Ub.npred.ppu - hexagon_V6_vS32Ub_npred_ppu_128B, // llvm.hexagon.V6.vS32Ub.npred.ppu.128B - hexagon_V6_vS32Ub_pred_ai, // llvm.hexagon.V6.vS32Ub.pred.ai - hexagon_V6_vS32Ub_pred_ai_128B, // llvm.hexagon.V6.vS32Ub.pred.ai.128B - hexagon_V6_vS32Ub_pred_pi, // llvm.hexagon.V6.vS32Ub.pred.pi - hexagon_V6_vS32Ub_pred_pi_128B, // llvm.hexagon.V6.vS32Ub.pred.pi.128B - hexagon_V6_vS32Ub_pred_ppu, // llvm.hexagon.V6.vS32Ub.pred.ppu - hexagon_V6_vS32Ub_pred_ppu_128B, // llvm.hexagon.V6.vS32Ub.pred.ppu.128B - hexagon_V6_vS32b_npred_ai, // llvm.hexagon.V6.vS32b.npred.ai - hexagon_V6_vS32b_npred_ai_128B, // llvm.hexagon.V6.vS32b.npred.ai.128B - hexagon_V6_vS32b_npred_pi, // llvm.hexagon.V6.vS32b.npred.pi - hexagon_V6_vS32b_npred_pi_128B, // llvm.hexagon.V6.vS32b.npred.pi.128B - hexagon_V6_vS32b_npred_ppu, // llvm.hexagon.V6.vS32b.npred.ppu - hexagon_V6_vS32b_npred_ppu_128B, // llvm.hexagon.V6.vS32b.npred.ppu.128B - hexagon_V6_vS32b_nqpred_ai, // llvm.hexagon.V6.vS32b.nqpred.ai - hexagon_V6_vS32b_nqpred_ai_128B, // llvm.hexagon.V6.vS32b.nqpred.ai.128B - hexagon_V6_vS32b_nt_npred_ai, // llvm.hexagon.V6.vS32b.nt.npred.ai - hexagon_V6_vS32b_nt_npred_ai_128B, // llvm.hexagon.V6.vS32b.nt.npred.ai.128B - hexagon_V6_vS32b_nt_npred_pi, // llvm.hexagon.V6.vS32b.nt.npred.pi - hexagon_V6_vS32b_nt_npred_pi_128B, // llvm.hexagon.V6.vS32b.nt.npred.pi.128B - hexagon_V6_vS32b_nt_npred_ppu, // llvm.hexagon.V6.vS32b.nt.npred.ppu - hexagon_V6_vS32b_nt_npred_ppu_128B, // llvm.hexagon.V6.vS32b.nt.npred.ppu.128B - hexagon_V6_vS32b_nt_nqpred_ai, // llvm.hexagon.V6.vS32b.nt.nqpred.ai - hexagon_V6_vS32b_nt_nqpred_ai_128B, // llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B - hexagon_V6_vS32b_nt_pred_ai, // llvm.hexagon.V6.vS32b.nt.pred.ai - hexagon_V6_vS32b_nt_pred_ai_128B, // llvm.hexagon.V6.vS32b.nt.pred.ai.128B - hexagon_V6_vS32b_nt_pred_pi, // llvm.hexagon.V6.vS32b.nt.pred.pi - hexagon_V6_vS32b_nt_pred_pi_128B, // llvm.hexagon.V6.vS32b.nt.pred.pi.128B - hexagon_V6_vS32b_nt_pred_ppu, // llvm.hexagon.V6.vS32b.nt.pred.ppu - hexagon_V6_vS32b_nt_pred_ppu_128B, // llvm.hexagon.V6.vS32b.nt.pred.ppu.128B - hexagon_V6_vS32b_nt_qpred_ai, // llvm.hexagon.V6.vS32b.nt.qpred.ai - hexagon_V6_vS32b_nt_qpred_ai_128B, // llvm.hexagon.V6.vS32b.nt.qpred.ai.128B - hexagon_V6_vS32b_pred_ai, // llvm.hexagon.V6.vS32b.pred.ai - hexagon_V6_vS32b_pred_ai_128B, // llvm.hexagon.V6.vS32b.pred.ai.128B - hexagon_V6_vS32b_pred_pi, // llvm.hexagon.V6.vS32b.pred.pi - hexagon_V6_vS32b_pred_pi_128B, // llvm.hexagon.V6.vS32b.pred.pi.128B - hexagon_V6_vS32b_pred_ppu, // llvm.hexagon.V6.vS32b.pred.ppu - hexagon_V6_vS32b_pred_ppu_128B, // llvm.hexagon.V6.vS32b.pred.ppu.128B - hexagon_V6_vS32b_qpred_ai, // llvm.hexagon.V6.vS32b.qpred.ai - hexagon_V6_vS32b_qpred_ai_128B, // llvm.hexagon.V6.vS32b.qpred.ai.128B - hexagon_V6_vabs_hf, // llvm.hexagon.V6.vabs.hf - hexagon_V6_vabs_hf_128B, // llvm.hexagon.V6.vabs.hf.128B - hexagon_V6_vabs_sf, // llvm.hexagon.V6.vabs.sf - hexagon_V6_vabs_sf_128B, // llvm.hexagon.V6.vabs.sf.128B - hexagon_V6_vabsb, // llvm.hexagon.V6.vabsb - hexagon_V6_vabsb_128B, // llvm.hexagon.V6.vabsb.128B - hexagon_V6_vabsb_sat, // llvm.hexagon.V6.vabsb.sat - hexagon_V6_vabsb_sat_128B, // llvm.hexagon.V6.vabsb.sat.128B - hexagon_V6_vabsdiffh, // llvm.hexagon.V6.vabsdiffh - hexagon_V6_vabsdiffh_128B, // llvm.hexagon.V6.vabsdiffh.128B - hexagon_V6_vabsdiffub, // llvm.hexagon.V6.vabsdiffub - hexagon_V6_vabsdiffub_128B, // llvm.hexagon.V6.vabsdiffub.128B - hexagon_V6_vabsdiffuh, // llvm.hexagon.V6.vabsdiffuh - hexagon_V6_vabsdiffuh_128B, // llvm.hexagon.V6.vabsdiffuh.128B - hexagon_V6_vabsdiffw, // llvm.hexagon.V6.vabsdiffw - hexagon_V6_vabsdiffw_128B, // llvm.hexagon.V6.vabsdiffw.128B - hexagon_V6_vabsh, // llvm.hexagon.V6.vabsh - hexagon_V6_vabsh_128B, // llvm.hexagon.V6.vabsh.128B - hexagon_V6_vabsh_sat, // llvm.hexagon.V6.vabsh.sat - hexagon_V6_vabsh_sat_128B, // llvm.hexagon.V6.vabsh.sat.128B - hexagon_V6_vabsw, // llvm.hexagon.V6.vabsw - hexagon_V6_vabsw_128B, // llvm.hexagon.V6.vabsw.128B - hexagon_V6_vabsw_sat, // llvm.hexagon.V6.vabsw.sat - hexagon_V6_vabsw_sat_128B, // llvm.hexagon.V6.vabsw.sat.128B - hexagon_V6_vadd_hf, // llvm.hexagon.V6.vadd.hf - hexagon_V6_vadd_hf_128B, // llvm.hexagon.V6.vadd.hf.128B - hexagon_V6_vadd_hf_hf, // llvm.hexagon.V6.vadd.hf.hf - hexagon_V6_vadd_hf_hf_128B, // llvm.hexagon.V6.vadd.hf.hf.128B - hexagon_V6_vadd_qf16, // llvm.hexagon.V6.vadd.qf16 - hexagon_V6_vadd_qf16_128B, // llvm.hexagon.V6.vadd.qf16.128B - hexagon_V6_vadd_qf16_mix, // llvm.hexagon.V6.vadd.qf16.mix - hexagon_V6_vadd_qf16_mix_128B, // llvm.hexagon.V6.vadd.qf16.mix.128B - hexagon_V6_vadd_qf32, // llvm.hexagon.V6.vadd.qf32 - hexagon_V6_vadd_qf32_128B, // llvm.hexagon.V6.vadd.qf32.128B - hexagon_V6_vadd_qf32_mix, // llvm.hexagon.V6.vadd.qf32.mix - hexagon_V6_vadd_qf32_mix_128B, // llvm.hexagon.V6.vadd.qf32.mix.128B - hexagon_V6_vadd_sf, // llvm.hexagon.V6.vadd.sf - hexagon_V6_vadd_sf_128B, // llvm.hexagon.V6.vadd.sf.128B - hexagon_V6_vadd_sf_hf, // llvm.hexagon.V6.vadd.sf.hf - hexagon_V6_vadd_sf_hf_128B, // llvm.hexagon.V6.vadd.sf.hf.128B - hexagon_V6_vadd_sf_sf, // llvm.hexagon.V6.vadd.sf.sf - hexagon_V6_vadd_sf_sf_128B, // llvm.hexagon.V6.vadd.sf.sf.128B - hexagon_V6_vaddb, // llvm.hexagon.V6.vaddb - hexagon_V6_vaddb_128B, // llvm.hexagon.V6.vaddb.128B - hexagon_V6_vaddb_dv, // llvm.hexagon.V6.vaddb.dv - hexagon_V6_vaddb_dv_128B, // llvm.hexagon.V6.vaddb.dv.128B - hexagon_V6_vaddbnq, // llvm.hexagon.V6.vaddbnq - hexagon_V6_vaddbnq_128B, // llvm.hexagon.V6.vaddbnq.128B - hexagon_V6_vaddbq, // llvm.hexagon.V6.vaddbq - hexagon_V6_vaddbq_128B, // llvm.hexagon.V6.vaddbq.128B - hexagon_V6_vaddbsat, // llvm.hexagon.V6.vaddbsat - hexagon_V6_vaddbsat_128B, // llvm.hexagon.V6.vaddbsat.128B - hexagon_V6_vaddbsat_dv, // llvm.hexagon.V6.vaddbsat.dv - hexagon_V6_vaddbsat_dv_128B, // llvm.hexagon.V6.vaddbsat.dv.128B - hexagon_V6_vaddcarry, // llvm.hexagon.V6.vaddcarry - hexagon_V6_vaddcarry_128B, // llvm.hexagon.V6.vaddcarry.128B - hexagon_V6_vaddcarrysat, // llvm.hexagon.V6.vaddcarrysat - hexagon_V6_vaddcarrysat_128B, // llvm.hexagon.V6.vaddcarrysat.128B - hexagon_V6_vaddclbh, // llvm.hexagon.V6.vaddclbh - hexagon_V6_vaddclbh_128B, // llvm.hexagon.V6.vaddclbh.128B - hexagon_V6_vaddclbw, // llvm.hexagon.V6.vaddclbw - hexagon_V6_vaddclbw_128B, // llvm.hexagon.V6.vaddclbw.128B - hexagon_V6_vaddh, // llvm.hexagon.V6.vaddh - hexagon_V6_vaddh_128B, // llvm.hexagon.V6.vaddh.128B - hexagon_V6_vaddh_dv, // llvm.hexagon.V6.vaddh.dv - hexagon_V6_vaddh_dv_128B, // llvm.hexagon.V6.vaddh.dv.128B - hexagon_V6_vaddhnq, // llvm.hexagon.V6.vaddhnq - hexagon_V6_vaddhnq_128B, // llvm.hexagon.V6.vaddhnq.128B - hexagon_V6_vaddhq, // llvm.hexagon.V6.vaddhq - hexagon_V6_vaddhq_128B, // llvm.hexagon.V6.vaddhq.128B - hexagon_V6_vaddhsat, // llvm.hexagon.V6.vaddhsat - hexagon_V6_vaddhsat_128B, // llvm.hexagon.V6.vaddhsat.128B - hexagon_V6_vaddhsat_dv, // llvm.hexagon.V6.vaddhsat.dv - hexagon_V6_vaddhsat_dv_128B, // llvm.hexagon.V6.vaddhsat.dv.128B - hexagon_V6_vaddhw, // llvm.hexagon.V6.vaddhw - hexagon_V6_vaddhw_128B, // llvm.hexagon.V6.vaddhw.128B - hexagon_V6_vaddhw_acc, // llvm.hexagon.V6.vaddhw.acc - hexagon_V6_vaddhw_acc_128B, // llvm.hexagon.V6.vaddhw.acc.128B - hexagon_V6_vaddubh, // llvm.hexagon.V6.vaddubh - hexagon_V6_vaddubh_128B, // llvm.hexagon.V6.vaddubh.128B - hexagon_V6_vaddubh_acc, // llvm.hexagon.V6.vaddubh.acc - hexagon_V6_vaddubh_acc_128B, // llvm.hexagon.V6.vaddubh.acc.128B - hexagon_V6_vaddubsat, // llvm.hexagon.V6.vaddubsat - hexagon_V6_vaddubsat_128B, // llvm.hexagon.V6.vaddubsat.128B - hexagon_V6_vaddubsat_dv, // llvm.hexagon.V6.vaddubsat.dv - hexagon_V6_vaddubsat_dv_128B, // llvm.hexagon.V6.vaddubsat.dv.128B - hexagon_V6_vaddububb_sat, // llvm.hexagon.V6.vaddububb.sat - hexagon_V6_vaddububb_sat_128B, // llvm.hexagon.V6.vaddububb.sat.128B - hexagon_V6_vadduhsat, // llvm.hexagon.V6.vadduhsat - hexagon_V6_vadduhsat_128B, // llvm.hexagon.V6.vadduhsat.128B - hexagon_V6_vadduhsat_dv, // llvm.hexagon.V6.vadduhsat.dv - hexagon_V6_vadduhsat_dv_128B, // llvm.hexagon.V6.vadduhsat.dv.128B - hexagon_V6_vadduhw, // llvm.hexagon.V6.vadduhw - hexagon_V6_vadduhw_128B, // llvm.hexagon.V6.vadduhw.128B - hexagon_V6_vadduhw_acc, // llvm.hexagon.V6.vadduhw.acc - hexagon_V6_vadduhw_acc_128B, // llvm.hexagon.V6.vadduhw.acc.128B - hexagon_V6_vadduwsat, // llvm.hexagon.V6.vadduwsat - hexagon_V6_vadduwsat_128B, // llvm.hexagon.V6.vadduwsat.128B - hexagon_V6_vadduwsat_dv, // llvm.hexagon.V6.vadduwsat.dv - hexagon_V6_vadduwsat_dv_128B, // llvm.hexagon.V6.vadduwsat.dv.128B - hexagon_V6_vaddw, // llvm.hexagon.V6.vaddw - hexagon_V6_vaddw_128B, // llvm.hexagon.V6.vaddw.128B - hexagon_V6_vaddw_dv, // llvm.hexagon.V6.vaddw.dv - hexagon_V6_vaddw_dv_128B, // llvm.hexagon.V6.vaddw.dv.128B - hexagon_V6_vaddwnq, // llvm.hexagon.V6.vaddwnq - hexagon_V6_vaddwnq_128B, // llvm.hexagon.V6.vaddwnq.128B - hexagon_V6_vaddwq, // llvm.hexagon.V6.vaddwq - hexagon_V6_vaddwq_128B, // llvm.hexagon.V6.vaddwq.128B - hexagon_V6_vaddwsat, // llvm.hexagon.V6.vaddwsat - hexagon_V6_vaddwsat_128B, // llvm.hexagon.V6.vaddwsat.128B - hexagon_V6_vaddwsat_dv, // llvm.hexagon.V6.vaddwsat.dv - hexagon_V6_vaddwsat_dv_128B, // llvm.hexagon.V6.vaddwsat.dv.128B - hexagon_V6_valignb, // llvm.hexagon.V6.valignb - hexagon_V6_valignb_128B, // llvm.hexagon.V6.valignb.128B - hexagon_V6_valignbi, // llvm.hexagon.V6.valignbi - hexagon_V6_valignbi_128B, // llvm.hexagon.V6.valignbi.128B - hexagon_V6_vand, // llvm.hexagon.V6.vand - hexagon_V6_vand_128B, // llvm.hexagon.V6.vand.128B - hexagon_V6_vandnqrt, // llvm.hexagon.V6.vandnqrt - hexagon_V6_vandnqrt_128B, // llvm.hexagon.V6.vandnqrt.128B - hexagon_V6_vandnqrt_acc, // llvm.hexagon.V6.vandnqrt.acc - hexagon_V6_vandnqrt_acc_128B, // llvm.hexagon.V6.vandnqrt.acc.128B - hexagon_V6_vandqrt, // llvm.hexagon.V6.vandqrt - hexagon_V6_vandqrt_128B, // llvm.hexagon.V6.vandqrt.128B - hexagon_V6_vandqrt_acc, // llvm.hexagon.V6.vandqrt.acc - hexagon_V6_vandqrt_acc_128B, // llvm.hexagon.V6.vandqrt.acc.128B - hexagon_V6_vandvnqv, // llvm.hexagon.V6.vandvnqv - hexagon_V6_vandvnqv_128B, // llvm.hexagon.V6.vandvnqv.128B - hexagon_V6_vandvqv, // llvm.hexagon.V6.vandvqv - hexagon_V6_vandvqv_128B, // llvm.hexagon.V6.vandvqv.128B - hexagon_V6_vandvrt, // llvm.hexagon.V6.vandvrt - hexagon_V6_vandvrt_128B, // llvm.hexagon.V6.vandvrt.128B - hexagon_V6_vandvrt_acc, // llvm.hexagon.V6.vandvrt.acc - hexagon_V6_vandvrt_acc_128B, // llvm.hexagon.V6.vandvrt.acc.128B - hexagon_V6_vaslh, // llvm.hexagon.V6.vaslh - hexagon_V6_vaslh_128B, // llvm.hexagon.V6.vaslh.128B - hexagon_V6_vaslh_acc, // llvm.hexagon.V6.vaslh.acc - hexagon_V6_vaslh_acc_128B, // llvm.hexagon.V6.vaslh.acc.128B - hexagon_V6_vaslhv, // llvm.hexagon.V6.vaslhv - hexagon_V6_vaslhv_128B, // llvm.hexagon.V6.vaslhv.128B - hexagon_V6_vaslw, // llvm.hexagon.V6.vaslw - hexagon_V6_vaslw_128B, // llvm.hexagon.V6.vaslw.128B - hexagon_V6_vaslw_acc, // llvm.hexagon.V6.vaslw.acc - hexagon_V6_vaslw_acc_128B, // llvm.hexagon.V6.vaslw.acc.128B - hexagon_V6_vaslwv, // llvm.hexagon.V6.vaslwv - hexagon_V6_vaslwv_128B, // llvm.hexagon.V6.vaslwv.128B - hexagon_V6_vasr_into, // llvm.hexagon.V6.vasr.into - hexagon_V6_vasr_into_128B, // llvm.hexagon.V6.vasr.into.128B - hexagon_V6_vasrh, // llvm.hexagon.V6.vasrh - hexagon_V6_vasrh_128B, // llvm.hexagon.V6.vasrh.128B - hexagon_V6_vasrh_acc, // llvm.hexagon.V6.vasrh.acc - hexagon_V6_vasrh_acc_128B, // llvm.hexagon.V6.vasrh.acc.128B - hexagon_V6_vasrhbrndsat, // llvm.hexagon.V6.vasrhbrndsat - hexagon_V6_vasrhbrndsat_128B, // llvm.hexagon.V6.vasrhbrndsat.128B - hexagon_V6_vasrhbsat, // llvm.hexagon.V6.vasrhbsat - hexagon_V6_vasrhbsat_128B, // llvm.hexagon.V6.vasrhbsat.128B - hexagon_V6_vasrhubrndsat, // llvm.hexagon.V6.vasrhubrndsat - hexagon_V6_vasrhubrndsat_128B, // llvm.hexagon.V6.vasrhubrndsat.128B - hexagon_V6_vasrhubsat, // llvm.hexagon.V6.vasrhubsat - hexagon_V6_vasrhubsat_128B, // llvm.hexagon.V6.vasrhubsat.128B - hexagon_V6_vasrhv, // llvm.hexagon.V6.vasrhv - hexagon_V6_vasrhv_128B, // llvm.hexagon.V6.vasrhv.128B - hexagon_V6_vasruhubrndsat, // llvm.hexagon.V6.vasruhubrndsat - hexagon_V6_vasruhubrndsat_128B, // llvm.hexagon.V6.vasruhubrndsat.128B - hexagon_V6_vasruhubsat, // llvm.hexagon.V6.vasruhubsat - hexagon_V6_vasruhubsat_128B, // llvm.hexagon.V6.vasruhubsat.128B - hexagon_V6_vasruwuhrndsat, // llvm.hexagon.V6.vasruwuhrndsat - hexagon_V6_vasruwuhrndsat_128B, // llvm.hexagon.V6.vasruwuhrndsat.128B - hexagon_V6_vasruwuhsat, // llvm.hexagon.V6.vasruwuhsat - hexagon_V6_vasruwuhsat_128B, // llvm.hexagon.V6.vasruwuhsat.128B - hexagon_V6_vasrvuhubrndsat, // llvm.hexagon.V6.vasrvuhubrndsat - hexagon_V6_vasrvuhubrndsat_128B, // llvm.hexagon.V6.vasrvuhubrndsat.128B - hexagon_V6_vasrvuhubsat, // llvm.hexagon.V6.vasrvuhubsat - hexagon_V6_vasrvuhubsat_128B, // llvm.hexagon.V6.vasrvuhubsat.128B - hexagon_V6_vasrvwuhrndsat, // llvm.hexagon.V6.vasrvwuhrndsat - hexagon_V6_vasrvwuhrndsat_128B, // llvm.hexagon.V6.vasrvwuhrndsat.128B - hexagon_V6_vasrvwuhsat, // llvm.hexagon.V6.vasrvwuhsat - hexagon_V6_vasrvwuhsat_128B, // llvm.hexagon.V6.vasrvwuhsat.128B - hexagon_V6_vasrw, // llvm.hexagon.V6.vasrw - hexagon_V6_vasrw_128B, // llvm.hexagon.V6.vasrw.128B - hexagon_V6_vasrw_acc, // llvm.hexagon.V6.vasrw.acc - hexagon_V6_vasrw_acc_128B, // llvm.hexagon.V6.vasrw.acc.128B - hexagon_V6_vasrwh, // llvm.hexagon.V6.vasrwh - hexagon_V6_vasrwh_128B, // llvm.hexagon.V6.vasrwh.128B - hexagon_V6_vasrwhrndsat, // llvm.hexagon.V6.vasrwhrndsat - hexagon_V6_vasrwhrndsat_128B, // llvm.hexagon.V6.vasrwhrndsat.128B - hexagon_V6_vasrwhsat, // llvm.hexagon.V6.vasrwhsat - hexagon_V6_vasrwhsat_128B, // llvm.hexagon.V6.vasrwhsat.128B - hexagon_V6_vasrwuhrndsat, // llvm.hexagon.V6.vasrwuhrndsat - hexagon_V6_vasrwuhrndsat_128B, // llvm.hexagon.V6.vasrwuhrndsat.128B - hexagon_V6_vasrwuhsat, // llvm.hexagon.V6.vasrwuhsat - hexagon_V6_vasrwuhsat_128B, // llvm.hexagon.V6.vasrwuhsat.128B - hexagon_V6_vasrwv, // llvm.hexagon.V6.vasrwv - hexagon_V6_vasrwv_128B, // llvm.hexagon.V6.vasrwv.128B - hexagon_V6_vassign, // llvm.hexagon.V6.vassign - hexagon_V6_vassign_128B, // llvm.hexagon.V6.vassign.128B - hexagon_V6_vassign_fp, // llvm.hexagon.V6.vassign.fp - hexagon_V6_vassign_fp_128B, // llvm.hexagon.V6.vassign.fp.128B - hexagon_V6_vassignp, // llvm.hexagon.V6.vassignp - hexagon_V6_vassignp_128B, // llvm.hexagon.V6.vassignp.128B - hexagon_V6_vavgb, // llvm.hexagon.V6.vavgb - hexagon_V6_vavgb_128B, // llvm.hexagon.V6.vavgb.128B - hexagon_V6_vavgbrnd, // llvm.hexagon.V6.vavgbrnd - hexagon_V6_vavgbrnd_128B, // llvm.hexagon.V6.vavgbrnd.128B - hexagon_V6_vavgh, // llvm.hexagon.V6.vavgh - hexagon_V6_vavgh_128B, // llvm.hexagon.V6.vavgh.128B - hexagon_V6_vavghrnd, // llvm.hexagon.V6.vavghrnd - hexagon_V6_vavghrnd_128B, // llvm.hexagon.V6.vavghrnd.128B - hexagon_V6_vavgub, // llvm.hexagon.V6.vavgub - hexagon_V6_vavgub_128B, // llvm.hexagon.V6.vavgub.128B - hexagon_V6_vavgubrnd, // llvm.hexagon.V6.vavgubrnd - hexagon_V6_vavgubrnd_128B, // llvm.hexagon.V6.vavgubrnd.128B - hexagon_V6_vavguh, // llvm.hexagon.V6.vavguh - hexagon_V6_vavguh_128B, // llvm.hexagon.V6.vavguh.128B - hexagon_V6_vavguhrnd, // llvm.hexagon.V6.vavguhrnd - hexagon_V6_vavguhrnd_128B, // llvm.hexagon.V6.vavguhrnd.128B - hexagon_V6_vavguw, // llvm.hexagon.V6.vavguw - hexagon_V6_vavguw_128B, // llvm.hexagon.V6.vavguw.128B - hexagon_V6_vavguwrnd, // llvm.hexagon.V6.vavguwrnd - hexagon_V6_vavguwrnd_128B, // llvm.hexagon.V6.vavguwrnd.128B - hexagon_V6_vavgw, // llvm.hexagon.V6.vavgw - hexagon_V6_vavgw_128B, // llvm.hexagon.V6.vavgw.128B - hexagon_V6_vavgwrnd, // llvm.hexagon.V6.vavgwrnd - hexagon_V6_vavgwrnd_128B, // llvm.hexagon.V6.vavgwrnd.128B - hexagon_V6_vcl0h, // llvm.hexagon.V6.vcl0h - hexagon_V6_vcl0h_128B, // llvm.hexagon.V6.vcl0h.128B - hexagon_V6_vcl0w, // llvm.hexagon.V6.vcl0w - hexagon_V6_vcl0w_128B, // llvm.hexagon.V6.vcl0w.128B - hexagon_V6_vcombine, // llvm.hexagon.V6.vcombine - hexagon_V6_vcombine_128B, // llvm.hexagon.V6.vcombine.128B - hexagon_V6_vconv_hf_qf16, // llvm.hexagon.V6.vconv.hf.qf16 - hexagon_V6_vconv_hf_qf16_128B, // llvm.hexagon.V6.vconv.hf.qf16.128B - hexagon_V6_vconv_hf_qf32, // llvm.hexagon.V6.vconv.hf.qf32 - hexagon_V6_vconv_hf_qf32_128B, // llvm.hexagon.V6.vconv.hf.qf32.128B - hexagon_V6_vconv_sf_qf32, // llvm.hexagon.V6.vconv.sf.qf32 - hexagon_V6_vconv_sf_qf32_128B, // llvm.hexagon.V6.vconv.sf.qf32.128B - hexagon_V6_vcvt_b_hf, // llvm.hexagon.V6.vcvt.b.hf - hexagon_V6_vcvt_b_hf_128B, // llvm.hexagon.V6.vcvt.b.hf.128B - hexagon_V6_vcvt_h_hf, // llvm.hexagon.V6.vcvt.h.hf - hexagon_V6_vcvt_h_hf_128B, // llvm.hexagon.V6.vcvt.h.hf.128B - hexagon_V6_vcvt_hf_b, // llvm.hexagon.V6.vcvt.hf.b - hexagon_V6_vcvt_hf_b_128B, // llvm.hexagon.V6.vcvt.hf.b.128B - hexagon_V6_vcvt_hf_h, // llvm.hexagon.V6.vcvt.hf.h - hexagon_V6_vcvt_hf_h_128B, // llvm.hexagon.V6.vcvt.hf.h.128B - hexagon_V6_vcvt_hf_sf, // llvm.hexagon.V6.vcvt.hf.sf - hexagon_V6_vcvt_hf_sf_128B, // llvm.hexagon.V6.vcvt.hf.sf.128B - hexagon_V6_vcvt_hf_ub, // llvm.hexagon.V6.vcvt.hf.ub - hexagon_V6_vcvt_hf_ub_128B, // llvm.hexagon.V6.vcvt.hf.ub.128B - hexagon_V6_vcvt_hf_uh, // llvm.hexagon.V6.vcvt.hf.uh - hexagon_V6_vcvt_hf_uh_128B, // llvm.hexagon.V6.vcvt.hf.uh.128B - hexagon_V6_vcvt_sf_hf, // llvm.hexagon.V6.vcvt.sf.hf - hexagon_V6_vcvt_sf_hf_128B, // llvm.hexagon.V6.vcvt.sf.hf.128B - hexagon_V6_vcvt_ub_hf, // llvm.hexagon.V6.vcvt.ub.hf - hexagon_V6_vcvt_ub_hf_128B, // llvm.hexagon.V6.vcvt.ub.hf.128B - hexagon_V6_vcvt_uh_hf, // llvm.hexagon.V6.vcvt.uh.hf - hexagon_V6_vcvt_uh_hf_128B, // llvm.hexagon.V6.vcvt.uh.hf.128B - hexagon_V6_vd0, // llvm.hexagon.V6.vd0 - hexagon_V6_vd0_128B, // llvm.hexagon.V6.vd0.128B - hexagon_V6_vdd0, // llvm.hexagon.V6.vdd0 - hexagon_V6_vdd0_128B, // llvm.hexagon.V6.vdd0.128B - hexagon_V6_vdealb, // llvm.hexagon.V6.vdealb - hexagon_V6_vdealb_128B, // llvm.hexagon.V6.vdealb.128B - hexagon_V6_vdealb4w, // llvm.hexagon.V6.vdealb4w - hexagon_V6_vdealb4w_128B, // llvm.hexagon.V6.vdealb4w.128B - hexagon_V6_vdealh, // llvm.hexagon.V6.vdealh - hexagon_V6_vdealh_128B, // llvm.hexagon.V6.vdealh.128B - hexagon_V6_vdealvdd, // llvm.hexagon.V6.vdealvdd - hexagon_V6_vdealvdd_128B, // llvm.hexagon.V6.vdealvdd.128B - hexagon_V6_vdelta, // llvm.hexagon.V6.vdelta - hexagon_V6_vdelta_128B, // llvm.hexagon.V6.vdelta.128B - hexagon_V6_vdmpy_sf_hf, // llvm.hexagon.V6.vdmpy.sf.hf - hexagon_V6_vdmpy_sf_hf_128B, // llvm.hexagon.V6.vdmpy.sf.hf.128B - hexagon_V6_vdmpy_sf_hf_acc, // llvm.hexagon.V6.vdmpy.sf.hf.acc - hexagon_V6_vdmpy_sf_hf_acc_128B, // llvm.hexagon.V6.vdmpy.sf.hf.acc.128B - hexagon_V6_vdmpybus, // llvm.hexagon.V6.vdmpybus - hexagon_V6_vdmpybus_128B, // llvm.hexagon.V6.vdmpybus.128B - hexagon_V6_vdmpybus_acc, // llvm.hexagon.V6.vdmpybus.acc - hexagon_V6_vdmpybus_acc_128B, // llvm.hexagon.V6.vdmpybus.acc.128B - hexagon_V6_vdmpybus_dv, // llvm.hexagon.V6.vdmpybus.dv - hexagon_V6_vdmpybus_dv_128B, // llvm.hexagon.V6.vdmpybus.dv.128B - hexagon_V6_vdmpybus_dv_acc, // llvm.hexagon.V6.vdmpybus.dv.acc - hexagon_V6_vdmpybus_dv_acc_128B, // llvm.hexagon.V6.vdmpybus.dv.acc.128B - hexagon_V6_vdmpyhb, // llvm.hexagon.V6.vdmpyhb - hexagon_V6_vdmpyhb_128B, // llvm.hexagon.V6.vdmpyhb.128B - hexagon_V6_vdmpyhb_acc, // llvm.hexagon.V6.vdmpyhb.acc - hexagon_V6_vdmpyhb_acc_128B, // llvm.hexagon.V6.vdmpyhb.acc.128B - hexagon_V6_vdmpyhb_dv, // llvm.hexagon.V6.vdmpyhb.dv - hexagon_V6_vdmpyhb_dv_128B, // llvm.hexagon.V6.vdmpyhb.dv.128B - hexagon_V6_vdmpyhb_dv_acc, // llvm.hexagon.V6.vdmpyhb.dv.acc - hexagon_V6_vdmpyhb_dv_acc_128B, // llvm.hexagon.V6.vdmpyhb.dv.acc.128B - hexagon_V6_vdmpyhisat, // llvm.hexagon.V6.vdmpyhisat - hexagon_V6_vdmpyhisat_128B, // llvm.hexagon.V6.vdmpyhisat.128B - hexagon_V6_vdmpyhisat_acc, // llvm.hexagon.V6.vdmpyhisat.acc - hexagon_V6_vdmpyhisat_acc_128B, // llvm.hexagon.V6.vdmpyhisat.acc.128B - hexagon_V6_vdmpyhsat, // llvm.hexagon.V6.vdmpyhsat - hexagon_V6_vdmpyhsat_128B, // llvm.hexagon.V6.vdmpyhsat.128B - hexagon_V6_vdmpyhsat_acc, // llvm.hexagon.V6.vdmpyhsat.acc - hexagon_V6_vdmpyhsat_acc_128B, // llvm.hexagon.V6.vdmpyhsat.acc.128B - hexagon_V6_vdmpyhsuisat, // llvm.hexagon.V6.vdmpyhsuisat - hexagon_V6_vdmpyhsuisat_128B, // llvm.hexagon.V6.vdmpyhsuisat.128B - hexagon_V6_vdmpyhsuisat_acc, // llvm.hexagon.V6.vdmpyhsuisat.acc - hexagon_V6_vdmpyhsuisat_acc_128B, // llvm.hexagon.V6.vdmpyhsuisat.acc.128B - hexagon_V6_vdmpyhsusat, // llvm.hexagon.V6.vdmpyhsusat - hexagon_V6_vdmpyhsusat_128B, // llvm.hexagon.V6.vdmpyhsusat.128B - hexagon_V6_vdmpyhsusat_acc, // llvm.hexagon.V6.vdmpyhsusat.acc - hexagon_V6_vdmpyhsusat_acc_128B, // llvm.hexagon.V6.vdmpyhsusat.acc.128B - hexagon_V6_vdmpyhvsat, // llvm.hexagon.V6.vdmpyhvsat - hexagon_V6_vdmpyhvsat_128B, // llvm.hexagon.V6.vdmpyhvsat.128B - hexagon_V6_vdmpyhvsat_acc, // llvm.hexagon.V6.vdmpyhvsat.acc - hexagon_V6_vdmpyhvsat_acc_128B, // llvm.hexagon.V6.vdmpyhvsat.acc.128B - hexagon_V6_vdsaduh, // llvm.hexagon.V6.vdsaduh - hexagon_V6_vdsaduh_128B, // llvm.hexagon.V6.vdsaduh.128B - hexagon_V6_vdsaduh_acc, // llvm.hexagon.V6.vdsaduh.acc - hexagon_V6_vdsaduh_acc_128B, // llvm.hexagon.V6.vdsaduh.acc.128B - hexagon_V6_veqb, // llvm.hexagon.V6.veqb - hexagon_V6_veqb_128B, // llvm.hexagon.V6.veqb.128B - hexagon_V6_veqb_and, // llvm.hexagon.V6.veqb.and - hexagon_V6_veqb_and_128B, // llvm.hexagon.V6.veqb.and.128B - hexagon_V6_veqb_or, // llvm.hexagon.V6.veqb.or - hexagon_V6_veqb_or_128B, // llvm.hexagon.V6.veqb.or.128B - hexagon_V6_veqb_xor, // llvm.hexagon.V6.veqb.xor - hexagon_V6_veqb_xor_128B, // llvm.hexagon.V6.veqb.xor.128B - hexagon_V6_veqh, // llvm.hexagon.V6.veqh - hexagon_V6_veqh_128B, // llvm.hexagon.V6.veqh.128B - hexagon_V6_veqh_and, // llvm.hexagon.V6.veqh.and - hexagon_V6_veqh_and_128B, // llvm.hexagon.V6.veqh.and.128B - hexagon_V6_veqh_or, // llvm.hexagon.V6.veqh.or - hexagon_V6_veqh_or_128B, // llvm.hexagon.V6.veqh.or.128B - hexagon_V6_veqh_xor, // llvm.hexagon.V6.veqh.xor - hexagon_V6_veqh_xor_128B, // llvm.hexagon.V6.veqh.xor.128B - hexagon_V6_veqw, // llvm.hexagon.V6.veqw - hexagon_V6_veqw_128B, // llvm.hexagon.V6.veqw.128B - hexagon_V6_veqw_and, // llvm.hexagon.V6.veqw.and - hexagon_V6_veqw_and_128B, // llvm.hexagon.V6.veqw.and.128B - hexagon_V6_veqw_or, // llvm.hexagon.V6.veqw.or - hexagon_V6_veqw_or_128B, // llvm.hexagon.V6.veqw.or.128B - hexagon_V6_veqw_xor, // llvm.hexagon.V6.veqw.xor - hexagon_V6_veqw_xor_128B, // llvm.hexagon.V6.veqw.xor.128B - hexagon_V6_vfmax_hf, // llvm.hexagon.V6.vfmax.hf - hexagon_V6_vfmax_hf_128B, // llvm.hexagon.V6.vfmax.hf.128B - hexagon_V6_vfmax_sf, // llvm.hexagon.V6.vfmax.sf - hexagon_V6_vfmax_sf_128B, // llvm.hexagon.V6.vfmax.sf.128B - hexagon_V6_vfmin_hf, // llvm.hexagon.V6.vfmin.hf - hexagon_V6_vfmin_hf_128B, // llvm.hexagon.V6.vfmin.hf.128B - hexagon_V6_vfmin_sf, // llvm.hexagon.V6.vfmin.sf - hexagon_V6_vfmin_sf_128B, // llvm.hexagon.V6.vfmin.sf.128B - hexagon_V6_vfneg_hf, // llvm.hexagon.V6.vfneg.hf - hexagon_V6_vfneg_hf_128B, // llvm.hexagon.V6.vfneg.hf.128B - hexagon_V6_vfneg_sf, // llvm.hexagon.V6.vfneg.sf - hexagon_V6_vfneg_sf_128B, // llvm.hexagon.V6.vfneg.sf.128B - hexagon_V6_vgathermh, // llvm.hexagon.V6.vgathermh - hexagon_V6_vgathermh_128B, // llvm.hexagon.V6.vgathermh.128B - hexagon_V6_vgathermhq, // llvm.hexagon.V6.vgathermhq - hexagon_V6_vgathermhq_128B, // llvm.hexagon.V6.vgathermhq.128B - hexagon_V6_vgathermhw, // llvm.hexagon.V6.vgathermhw - hexagon_V6_vgathermhw_128B, // llvm.hexagon.V6.vgathermhw.128B - hexagon_V6_vgathermhwq, // llvm.hexagon.V6.vgathermhwq - hexagon_V6_vgathermhwq_128B, // llvm.hexagon.V6.vgathermhwq.128B - hexagon_V6_vgathermw, // llvm.hexagon.V6.vgathermw - hexagon_V6_vgathermw_128B, // llvm.hexagon.V6.vgathermw.128B - hexagon_V6_vgathermwq, // llvm.hexagon.V6.vgathermwq - hexagon_V6_vgathermwq_128B, // llvm.hexagon.V6.vgathermwq.128B - hexagon_V6_vgtb, // llvm.hexagon.V6.vgtb - hexagon_V6_vgtb_128B, // llvm.hexagon.V6.vgtb.128B - hexagon_V6_vgtb_and, // llvm.hexagon.V6.vgtb.and - hexagon_V6_vgtb_and_128B, // llvm.hexagon.V6.vgtb.and.128B - hexagon_V6_vgtb_or, // llvm.hexagon.V6.vgtb.or - hexagon_V6_vgtb_or_128B, // llvm.hexagon.V6.vgtb.or.128B - hexagon_V6_vgtb_xor, // llvm.hexagon.V6.vgtb.xor - hexagon_V6_vgtb_xor_128B, // llvm.hexagon.V6.vgtb.xor.128B - hexagon_V6_vgth, // llvm.hexagon.V6.vgth - hexagon_V6_vgth_128B, // llvm.hexagon.V6.vgth.128B - hexagon_V6_vgth_and, // llvm.hexagon.V6.vgth.and - hexagon_V6_vgth_and_128B, // llvm.hexagon.V6.vgth.and.128B - hexagon_V6_vgth_or, // llvm.hexagon.V6.vgth.or - hexagon_V6_vgth_or_128B, // llvm.hexagon.V6.vgth.or.128B - hexagon_V6_vgth_xor, // llvm.hexagon.V6.vgth.xor - hexagon_V6_vgth_xor_128B, // llvm.hexagon.V6.vgth.xor.128B - hexagon_V6_vgthf, // llvm.hexagon.V6.vgthf - hexagon_V6_vgthf_128B, // llvm.hexagon.V6.vgthf.128B - hexagon_V6_vgthf_and, // llvm.hexagon.V6.vgthf.and - hexagon_V6_vgthf_and_128B, // llvm.hexagon.V6.vgthf.and.128B - hexagon_V6_vgthf_or, // llvm.hexagon.V6.vgthf.or - hexagon_V6_vgthf_or_128B, // llvm.hexagon.V6.vgthf.or.128B - hexagon_V6_vgthf_xor, // llvm.hexagon.V6.vgthf.xor - hexagon_V6_vgthf_xor_128B, // llvm.hexagon.V6.vgthf.xor.128B - hexagon_V6_vgtsf, // llvm.hexagon.V6.vgtsf - hexagon_V6_vgtsf_128B, // llvm.hexagon.V6.vgtsf.128B - hexagon_V6_vgtsf_and, // llvm.hexagon.V6.vgtsf.and - hexagon_V6_vgtsf_and_128B, // llvm.hexagon.V6.vgtsf.and.128B - hexagon_V6_vgtsf_or, // llvm.hexagon.V6.vgtsf.or - hexagon_V6_vgtsf_or_128B, // llvm.hexagon.V6.vgtsf.or.128B - hexagon_V6_vgtsf_xor, // llvm.hexagon.V6.vgtsf.xor - hexagon_V6_vgtsf_xor_128B, // llvm.hexagon.V6.vgtsf.xor.128B - hexagon_V6_vgtub, // llvm.hexagon.V6.vgtub - hexagon_V6_vgtub_128B, // llvm.hexagon.V6.vgtub.128B - hexagon_V6_vgtub_and, // llvm.hexagon.V6.vgtub.and - hexagon_V6_vgtub_and_128B, // llvm.hexagon.V6.vgtub.and.128B - hexagon_V6_vgtub_or, // llvm.hexagon.V6.vgtub.or - hexagon_V6_vgtub_or_128B, // llvm.hexagon.V6.vgtub.or.128B - hexagon_V6_vgtub_xor, // llvm.hexagon.V6.vgtub.xor - hexagon_V6_vgtub_xor_128B, // llvm.hexagon.V6.vgtub.xor.128B - hexagon_V6_vgtuh, // llvm.hexagon.V6.vgtuh - hexagon_V6_vgtuh_128B, // llvm.hexagon.V6.vgtuh.128B - hexagon_V6_vgtuh_and, // llvm.hexagon.V6.vgtuh.and - hexagon_V6_vgtuh_and_128B, // llvm.hexagon.V6.vgtuh.and.128B - hexagon_V6_vgtuh_or, // llvm.hexagon.V6.vgtuh.or - hexagon_V6_vgtuh_or_128B, // llvm.hexagon.V6.vgtuh.or.128B - hexagon_V6_vgtuh_xor, // llvm.hexagon.V6.vgtuh.xor - hexagon_V6_vgtuh_xor_128B, // llvm.hexagon.V6.vgtuh.xor.128B - hexagon_V6_vgtuw, // llvm.hexagon.V6.vgtuw - hexagon_V6_vgtuw_128B, // llvm.hexagon.V6.vgtuw.128B - hexagon_V6_vgtuw_and, // llvm.hexagon.V6.vgtuw.and - hexagon_V6_vgtuw_and_128B, // llvm.hexagon.V6.vgtuw.and.128B - hexagon_V6_vgtuw_or, // llvm.hexagon.V6.vgtuw.or - hexagon_V6_vgtuw_or_128B, // llvm.hexagon.V6.vgtuw.or.128B - hexagon_V6_vgtuw_xor, // llvm.hexagon.V6.vgtuw.xor - hexagon_V6_vgtuw_xor_128B, // llvm.hexagon.V6.vgtuw.xor.128B - hexagon_V6_vgtw, // llvm.hexagon.V6.vgtw - hexagon_V6_vgtw_128B, // llvm.hexagon.V6.vgtw.128B - hexagon_V6_vgtw_and, // llvm.hexagon.V6.vgtw.and - hexagon_V6_vgtw_and_128B, // llvm.hexagon.V6.vgtw.and.128B - hexagon_V6_vgtw_or, // llvm.hexagon.V6.vgtw.or - hexagon_V6_vgtw_or_128B, // llvm.hexagon.V6.vgtw.or.128B - hexagon_V6_vgtw_xor, // llvm.hexagon.V6.vgtw.xor - hexagon_V6_vgtw_xor_128B, // llvm.hexagon.V6.vgtw.xor.128B - hexagon_V6_vinsertwr, // llvm.hexagon.V6.vinsertwr - hexagon_V6_vinsertwr_128B, // llvm.hexagon.V6.vinsertwr.128B - hexagon_V6_vlalignb, // llvm.hexagon.V6.vlalignb - hexagon_V6_vlalignb_128B, // llvm.hexagon.V6.vlalignb.128B - hexagon_V6_vlalignbi, // llvm.hexagon.V6.vlalignbi - hexagon_V6_vlalignbi_128B, // llvm.hexagon.V6.vlalignbi.128B - hexagon_V6_vlsrb, // llvm.hexagon.V6.vlsrb - hexagon_V6_vlsrb_128B, // llvm.hexagon.V6.vlsrb.128B - hexagon_V6_vlsrh, // llvm.hexagon.V6.vlsrh - hexagon_V6_vlsrh_128B, // llvm.hexagon.V6.vlsrh.128B - hexagon_V6_vlsrhv, // llvm.hexagon.V6.vlsrhv - hexagon_V6_vlsrhv_128B, // llvm.hexagon.V6.vlsrhv.128B - hexagon_V6_vlsrw, // llvm.hexagon.V6.vlsrw - hexagon_V6_vlsrw_128B, // llvm.hexagon.V6.vlsrw.128B - hexagon_V6_vlsrwv, // llvm.hexagon.V6.vlsrwv - hexagon_V6_vlsrwv_128B, // llvm.hexagon.V6.vlsrwv.128B - hexagon_V6_vlut4, // llvm.hexagon.V6.vlut4 - hexagon_V6_vlut4_128B, // llvm.hexagon.V6.vlut4.128B - hexagon_V6_vlutvvb, // llvm.hexagon.V6.vlutvvb - hexagon_V6_vlutvvb_128B, // llvm.hexagon.V6.vlutvvb.128B - hexagon_V6_vlutvvb_nm, // llvm.hexagon.V6.vlutvvb.nm - hexagon_V6_vlutvvb_nm_128B, // llvm.hexagon.V6.vlutvvb.nm.128B - hexagon_V6_vlutvvb_oracc, // llvm.hexagon.V6.vlutvvb.oracc - hexagon_V6_vlutvvb_oracc_128B, // llvm.hexagon.V6.vlutvvb.oracc.128B - hexagon_V6_vlutvvb_oracci, // llvm.hexagon.V6.vlutvvb.oracci - hexagon_V6_vlutvvb_oracci_128B, // llvm.hexagon.V6.vlutvvb.oracci.128B - hexagon_V6_vlutvvbi, // llvm.hexagon.V6.vlutvvbi - hexagon_V6_vlutvvbi_128B, // llvm.hexagon.V6.vlutvvbi.128B - hexagon_V6_vlutvwh, // llvm.hexagon.V6.vlutvwh - hexagon_V6_vlutvwh_128B, // llvm.hexagon.V6.vlutvwh.128B - hexagon_V6_vlutvwh_nm, // llvm.hexagon.V6.vlutvwh.nm - hexagon_V6_vlutvwh_nm_128B, // llvm.hexagon.V6.vlutvwh.nm.128B - hexagon_V6_vlutvwh_oracc, // llvm.hexagon.V6.vlutvwh.oracc - hexagon_V6_vlutvwh_oracc_128B, // llvm.hexagon.V6.vlutvwh.oracc.128B - hexagon_V6_vlutvwh_oracci, // llvm.hexagon.V6.vlutvwh.oracci - hexagon_V6_vlutvwh_oracci_128B, // llvm.hexagon.V6.vlutvwh.oracci.128B - hexagon_V6_vlutvwhi, // llvm.hexagon.V6.vlutvwhi - hexagon_V6_vlutvwhi_128B, // llvm.hexagon.V6.vlutvwhi.128B - hexagon_V6_vmaskedstorenq, // llvm.hexagon.V6.vmaskedstorenq - hexagon_V6_vmaskedstorenq_128B, // llvm.hexagon.V6.vmaskedstorenq.128B - hexagon_V6_vmaskedstorentnq, // llvm.hexagon.V6.vmaskedstorentnq - hexagon_V6_vmaskedstorentnq_128B, // llvm.hexagon.V6.vmaskedstorentnq.128B - hexagon_V6_vmaskedstorentq, // llvm.hexagon.V6.vmaskedstorentq - hexagon_V6_vmaskedstorentq_128B, // llvm.hexagon.V6.vmaskedstorentq.128B - hexagon_V6_vmaskedstoreq, // llvm.hexagon.V6.vmaskedstoreq - hexagon_V6_vmaskedstoreq_128B, // llvm.hexagon.V6.vmaskedstoreq.128B - hexagon_V6_vmax_hf, // llvm.hexagon.V6.vmax.hf - hexagon_V6_vmax_hf_128B, // llvm.hexagon.V6.vmax.hf.128B - hexagon_V6_vmax_sf, // llvm.hexagon.V6.vmax.sf - hexagon_V6_vmax_sf_128B, // llvm.hexagon.V6.vmax.sf.128B - hexagon_V6_vmaxb, // llvm.hexagon.V6.vmaxb - hexagon_V6_vmaxb_128B, // llvm.hexagon.V6.vmaxb.128B - hexagon_V6_vmaxh, // llvm.hexagon.V6.vmaxh - hexagon_V6_vmaxh_128B, // llvm.hexagon.V6.vmaxh.128B - hexagon_V6_vmaxub, // llvm.hexagon.V6.vmaxub - hexagon_V6_vmaxub_128B, // llvm.hexagon.V6.vmaxub.128B - hexagon_V6_vmaxuh, // llvm.hexagon.V6.vmaxuh - hexagon_V6_vmaxuh_128B, // llvm.hexagon.V6.vmaxuh.128B - hexagon_V6_vmaxw, // llvm.hexagon.V6.vmaxw - hexagon_V6_vmaxw_128B, // llvm.hexagon.V6.vmaxw.128B - hexagon_V6_vmin_hf, // llvm.hexagon.V6.vmin.hf - hexagon_V6_vmin_hf_128B, // llvm.hexagon.V6.vmin.hf.128B - hexagon_V6_vmin_sf, // llvm.hexagon.V6.vmin.sf - hexagon_V6_vmin_sf_128B, // llvm.hexagon.V6.vmin.sf.128B - hexagon_V6_vminb, // llvm.hexagon.V6.vminb - hexagon_V6_vminb_128B, // llvm.hexagon.V6.vminb.128B - hexagon_V6_vminh, // llvm.hexagon.V6.vminh - hexagon_V6_vminh_128B, // llvm.hexagon.V6.vminh.128B - hexagon_V6_vminub, // llvm.hexagon.V6.vminub - hexagon_V6_vminub_128B, // llvm.hexagon.V6.vminub.128B - hexagon_V6_vminuh, // llvm.hexagon.V6.vminuh - hexagon_V6_vminuh_128B, // llvm.hexagon.V6.vminuh.128B - hexagon_V6_vminw, // llvm.hexagon.V6.vminw - hexagon_V6_vminw_128B, // llvm.hexagon.V6.vminw.128B - hexagon_V6_vmpabus, // llvm.hexagon.V6.vmpabus - hexagon_V6_vmpabus_128B, // llvm.hexagon.V6.vmpabus.128B - hexagon_V6_vmpabus_acc, // llvm.hexagon.V6.vmpabus.acc - hexagon_V6_vmpabus_acc_128B, // llvm.hexagon.V6.vmpabus.acc.128B - hexagon_V6_vmpabusv, // llvm.hexagon.V6.vmpabusv - hexagon_V6_vmpabusv_128B, // llvm.hexagon.V6.vmpabusv.128B - hexagon_V6_vmpabuu, // llvm.hexagon.V6.vmpabuu - hexagon_V6_vmpabuu_128B, // llvm.hexagon.V6.vmpabuu.128B - hexagon_V6_vmpabuu_acc, // llvm.hexagon.V6.vmpabuu.acc - hexagon_V6_vmpabuu_acc_128B, // llvm.hexagon.V6.vmpabuu.acc.128B - hexagon_V6_vmpabuuv, // llvm.hexagon.V6.vmpabuuv - hexagon_V6_vmpabuuv_128B, // llvm.hexagon.V6.vmpabuuv.128B - hexagon_V6_vmpahb, // llvm.hexagon.V6.vmpahb - hexagon_V6_vmpahb_128B, // llvm.hexagon.V6.vmpahb.128B - hexagon_V6_vmpahb_acc, // llvm.hexagon.V6.vmpahb.acc - hexagon_V6_vmpahb_acc_128B, // llvm.hexagon.V6.vmpahb.acc.128B - hexagon_V6_vmpahhsat, // llvm.hexagon.V6.vmpahhsat - hexagon_V6_vmpahhsat_128B, // llvm.hexagon.V6.vmpahhsat.128B - hexagon_V6_vmpauhb, // llvm.hexagon.V6.vmpauhb - hexagon_V6_vmpauhb_128B, // llvm.hexagon.V6.vmpauhb.128B - hexagon_V6_vmpauhb_acc, // llvm.hexagon.V6.vmpauhb.acc - hexagon_V6_vmpauhb_acc_128B, // llvm.hexagon.V6.vmpauhb.acc.128B - hexagon_V6_vmpauhuhsat, // llvm.hexagon.V6.vmpauhuhsat - hexagon_V6_vmpauhuhsat_128B, // llvm.hexagon.V6.vmpauhuhsat.128B - hexagon_V6_vmpsuhuhsat, // llvm.hexagon.V6.vmpsuhuhsat - hexagon_V6_vmpsuhuhsat_128B, // llvm.hexagon.V6.vmpsuhuhsat.128B - hexagon_V6_vmpy_hf_hf, // llvm.hexagon.V6.vmpy.hf.hf - hexagon_V6_vmpy_hf_hf_128B, // llvm.hexagon.V6.vmpy.hf.hf.128B - hexagon_V6_vmpy_hf_hf_acc, // llvm.hexagon.V6.vmpy.hf.hf.acc - hexagon_V6_vmpy_hf_hf_acc_128B, // llvm.hexagon.V6.vmpy.hf.hf.acc.128B - hexagon_V6_vmpy_qf16, // llvm.hexagon.V6.vmpy.qf16 - hexagon_V6_vmpy_qf16_128B, // llvm.hexagon.V6.vmpy.qf16.128B - hexagon_V6_vmpy_qf16_hf, // llvm.hexagon.V6.vmpy.qf16.hf - hexagon_V6_vmpy_qf16_hf_128B, // llvm.hexagon.V6.vmpy.qf16.hf.128B - hexagon_V6_vmpy_qf16_mix_hf, // llvm.hexagon.V6.vmpy.qf16.mix.hf - hexagon_V6_vmpy_qf16_mix_hf_128B, // llvm.hexagon.V6.vmpy.qf16.mix.hf.128B - hexagon_V6_vmpy_qf32, // llvm.hexagon.V6.vmpy.qf32 - hexagon_V6_vmpy_qf32_128B, // llvm.hexagon.V6.vmpy.qf32.128B - hexagon_V6_vmpy_qf32_hf, // llvm.hexagon.V6.vmpy.qf32.hf - hexagon_V6_vmpy_qf32_hf_128B, // llvm.hexagon.V6.vmpy.qf32.hf.128B - hexagon_V6_vmpy_qf32_mix_hf, // llvm.hexagon.V6.vmpy.qf32.mix.hf - hexagon_V6_vmpy_qf32_mix_hf_128B, // llvm.hexagon.V6.vmpy.qf32.mix.hf.128B - hexagon_V6_vmpy_qf32_qf16, // llvm.hexagon.V6.vmpy.qf32.qf16 - hexagon_V6_vmpy_qf32_qf16_128B, // llvm.hexagon.V6.vmpy.qf32.qf16.128B - hexagon_V6_vmpy_qf32_sf, // llvm.hexagon.V6.vmpy.qf32.sf - hexagon_V6_vmpy_qf32_sf_128B, // llvm.hexagon.V6.vmpy.qf32.sf.128B - hexagon_V6_vmpy_sf_hf, // llvm.hexagon.V6.vmpy.sf.hf - hexagon_V6_vmpy_sf_hf_128B, // llvm.hexagon.V6.vmpy.sf.hf.128B - hexagon_V6_vmpy_sf_hf_acc, // llvm.hexagon.V6.vmpy.sf.hf.acc - hexagon_V6_vmpy_sf_hf_acc_128B, // llvm.hexagon.V6.vmpy.sf.hf.acc.128B - hexagon_V6_vmpy_sf_sf, // llvm.hexagon.V6.vmpy.sf.sf - hexagon_V6_vmpy_sf_sf_128B, // llvm.hexagon.V6.vmpy.sf.sf.128B - hexagon_V6_vmpybus, // llvm.hexagon.V6.vmpybus - hexagon_V6_vmpybus_128B, // llvm.hexagon.V6.vmpybus.128B - hexagon_V6_vmpybus_acc, // llvm.hexagon.V6.vmpybus.acc - hexagon_V6_vmpybus_acc_128B, // llvm.hexagon.V6.vmpybus.acc.128B - hexagon_V6_vmpybusv, // llvm.hexagon.V6.vmpybusv - hexagon_V6_vmpybusv_128B, // llvm.hexagon.V6.vmpybusv.128B - hexagon_V6_vmpybusv_acc, // llvm.hexagon.V6.vmpybusv.acc - hexagon_V6_vmpybusv_acc_128B, // llvm.hexagon.V6.vmpybusv.acc.128B - hexagon_V6_vmpybv, // llvm.hexagon.V6.vmpybv - hexagon_V6_vmpybv_128B, // llvm.hexagon.V6.vmpybv.128B - hexagon_V6_vmpybv_acc, // llvm.hexagon.V6.vmpybv.acc - hexagon_V6_vmpybv_acc_128B, // llvm.hexagon.V6.vmpybv.acc.128B - hexagon_V6_vmpyewuh, // llvm.hexagon.V6.vmpyewuh - hexagon_V6_vmpyewuh_128B, // llvm.hexagon.V6.vmpyewuh.128B - hexagon_V6_vmpyewuh_64, // llvm.hexagon.V6.vmpyewuh.64 - hexagon_V6_vmpyewuh_64_128B, // llvm.hexagon.V6.vmpyewuh.64.128B - hexagon_V6_vmpyh, // llvm.hexagon.V6.vmpyh - hexagon_V6_vmpyh_128B, // llvm.hexagon.V6.vmpyh.128B - hexagon_V6_vmpyh_acc, // llvm.hexagon.V6.vmpyh.acc - hexagon_V6_vmpyh_acc_128B, // llvm.hexagon.V6.vmpyh.acc.128B - hexagon_V6_vmpyhsat_acc, // llvm.hexagon.V6.vmpyhsat.acc - hexagon_V6_vmpyhsat_acc_128B, // llvm.hexagon.V6.vmpyhsat.acc.128B - hexagon_V6_vmpyhsrs, // llvm.hexagon.V6.vmpyhsrs - hexagon_V6_vmpyhsrs_128B, // llvm.hexagon.V6.vmpyhsrs.128B - hexagon_V6_vmpyhss, // llvm.hexagon.V6.vmpyhss - hexagon_V6_vmpyhss_128B, // llvm.hexagon.V6.vmpyhss.128B - hexagon_V6_vmpyhus, // llvm.hexagon.V6.vmpyhus - hexagon_V6_vmpyhus_128B, // llvm.hexagon.V6.vmpyhus.128B - hexagon_V6_vmpyhus_acc, // llvm.hexagon.V6.vmpyhus.acc - hexagon_V6_vmpyhus_acc_128B, // llvm.hexagon.V6.vmpyhus.acc.128B - hexagon_V6_vmpyhv, // llvm.hexagon.V6.vmpyhv - hexagon_V6_vmpyhv_128B, // llvm.hexagon.V6.vmpyhv.128B - hexagon_V6_vmpyhv_acc, // llvm.hexagon.V6.vmpyhv.acc - hexagon_V6_vmpyhv_acc_128B, // llvm.hexagon.V6.vmpyhv.acc.128B - hexagon_V6_vmpyhvsrs, // llvm.hexagon.V6.vmpyhvsrs - hexagon_V6_vmpyhvsrs_128B, // llvm.hexagon.V6.vmpyhvsrs.128B - hexagon_V6_vmpyieoh, // llvm.hexagon.V6.vmpyieoh - hexagon_V6_vmpyieoh_128B, // llvm.hexagon.V6.vmpyieoh.128B - hexagon_V6_vmpyiewh_acc, // llvm.hexagon.V6.vmpyiewh.acc - hexagon_V6_vmpyiewh_acc_128B, // llvm.hexagon.V6.vmpyiewh.acc.128B - hexagon_V6_vmpyiewuh, // llvm.hexagon.V6.vmpyiewuh - hexagon_V6_vmpyiewuh_128B, // llvm.hexagon.V6.vmpyiewuh.128B - hexagon_V6_vmpyiewuh_acc, // llvm.hexagon.V6.vmpyiewuh.acc - hexagon_V6_vmpyiewuh_acc_128B, // llvm.hexagon.V6.vmpyiewuh.acc.128B - hexagon_V6_vmpyih, // llvm.hexagon.V6.vmpyih - hexagon_V6_vmpyih_128B, // llvm.hexagon.V6.vmpyih.128B - hexagon_V6_vmpyih_acc, // llvm.hexagon.V6.vmpyih.acc - hexagon_V6_vmpyih_acc_128B, // llvm.hexagon.V6.vmpyih.acc.128B - hexagon_V6_vmpyihb, // llvm.hexagon.V6.vmpyihb - hexagon_V6_vmpyihb_128B, // llvm.hexagon.V6.vmpyihb.128B - hexagon_V6_vmpyihb_acc, // llvm.hexagon.V6.vmpyihb.acc - hexagon_V6_vmpyihb_acc_128B, // llvm.hexagon.V6.vmpyihb.acc.128B - hexagon_V6_vmpyiowh, // llvm.hexagon.V6.vmpyiowh - hexagon_V6_vmpyiowh_128B, // llvm.hexagon.V6.vmpyiowh.128B - hexagon_V6_vmpyiwb, // llvm.hexagon.V6.vmpyiwb - hexagon_V6_vmpyiwb_128B, // llvm.hexagon.V6.vmpyiwb.128B - hexagon_V6_vmpyiwb_acc, // llvm.hexagon.V6.vmpyiwb.acc - hexagon_V6_vmpyiwb_acc_128B, // llvm.hexagon.V6.vmpyiwb.acc.128B - hexagon_V6_vmpyiwh, // llvm.hexagon.V6.vmpyiwh - hexagon_V6_vmpyiwh_128B, // llvm.hexagon.V6.vmpyiwh.128B - hexagon_V6_vmpyiwh_acc, // llvm.hexagon.V6.vmpyiwh.acc - hexagon_V6_vmpyiwh_acc_128B, // llvm.hexagon.V6.vmpyiwh.acc.128B - hexagon_V6_vmpyiwub, // llvm.hexagon.V6.vmpyiwub - hexagon_V6_vmpyiwub_128B, // llvm.hexagon.V6.vmpyiwub.128B - hexagon_V6_vmpyiwub_acc, // llvm.hexagon.V6.vmpyiwub.acc - hexagon_V6_vmpyiwub_acc_128B, // llvm.hexagon.V6.vmpyiwub.acc.128B - hexagon_V6_vmpyowh, // llvm.hexagon.V6.vmpyowh - hexagon_V6_vmpyowh_128B, // llvm.hexagon.V6.vmpyowh.128B - hexagon_V6_vmpyowh_64_acc, // llvm.hexagon.V6.vmpyowh.64.acc - hexagon_V6_vmpyowh_64_acc_128B, // llvm.hexagon.V6.vmpyowh.64.acc.128B - hexagon_V6_vmpyowh_rnd, // llvm.hexagon.V6.vmpyowh.rnd - hexagon_V6_vmpyowh_rnd_128B, // llvm.hexagon.V6.vmpyowh.rnd.128B - hexagon_V6_vmpyowh_rnd_sacc, // llvm.hexagon.V6.vmpyowh.rnd.sacc - hexagon_V6_vmpyowh_rnd_sacc_128B, // llvm.hexagon.V6.vmpyowh.rnd.sacc.128B - hexagon_V6_vmpyowh_sacc, // llvm.hexagon.V6.vmpyowh.sacc - hexagon_V6_vmpyowh_sacc_128B, // llvm.hexagon.V6.vmpyowh.sacc.128B - hexagon_V6_vmpyub, // llvm.hexagon.V6.vmpyub - hexagon_V6_vmpyub_128B, // llvm.hexagon.V6.vmpyub.128B - hexagon_V6_vmpyub_acc, // llvm.hexagon.V6.vmpyub.acc - hexagon_V6_vmpyub_acc_128B, // llvm.hexagon.V6.vmpyub.acc.128B - hexagon_V6_vmpyubv, // llvm.hexagon.V6.vmpyubv - hexagon_V6_vmpyubv_128B, // llvm.hexagon.V6.vmpyubv.128B - hexagon_V6_vmpyubv_acc, // llvm.hexagon.V6.vmpyubv.acc - hexagon_V6_vmpyubv_acc_128B, // llvm.hexagon.V6.vmpyubv.acc.128B - hexagon_V6_vmpyuh, // llvm.hexagon.V6.vmpyuh - hexagon_V6_vmpyuh_128B, // llvm.hexagon.V6.vmpyuh.128B - hexagon_V6_vmpyuh_acc, // llvm.hexagon.V6.vmpyuh.acc - hexagon_V6_vmpyuh_acc_128B, // llvm.hexagon.V6.vmpyuh.acc.128B - hexagon_V6_vmpyuhe, // llvm.hexagon.V6.vmpyuhe - hexagon_V6_vmpyuhe_128B, // llvm.hexagon.V6.vmpyuhe.128B - hexagon_V6_vmpyuhe_acc, // llvm.hexagon.V6.vmpyuhe.acc - hexagon_V6_vmpyuhe_acc_128B, // llvm.hexagon.V6.vmpyuhe.acc.128B - hexagon_V6_vmpyuhv, // llvm.hexagon.V6.vmpyuhv - hexagon_V6_vmpyuhv_128B, // llvm.hexagon.V6.vmpyuhv.128B - hexagon_V6_vmpyuhv_acc, // llvm.hexagon.V6.vmpyuhv.acc - hexagon_V6_vmpyuhv_acc_128B, // llvm.hexagon.V6.vmpyuhv.acc.128B - hexagon_V6_vmpyuhvs, // llvm.hexagon.V6.vmpyuhvs - hexagon_V6_vmpyuhvs_128B, // llvm.hexagon.V6.vmpyuhvs.128B - hexagon_V6_vmux, // llvm.hexagon.V6.vmux - hexagon_V6_vmux_128B, // llvm.hexagon.V6.vmux.128B - hexagon_V6_vnavgb, // llvm.hexagon.V6.vnavgb - hexagon_V6_vnavgb_128B, // llvm.hexagon.V6.vnavgb.128B - hexagon_V6_vnavgh, // llvm.hexagon.V6.vnavgh - hexagon_V6_vnavgh_128B, // llvm.hexagon.V6.vnavgh.128B - hexagon_V6_vnavgub, // llvm.hexagon.V6.vnavgub - hexagon_V6_vnavgub_128B, // llvm.hexagon.V6.vnavgub.128B - hexagon_V6_vnavgw, // llvm.hexagon.V6.vnavgw - hexagon_V6_vnavgw_128B, // llvm.hexagon.V6.vnavgw.128B - hexagon_V6_vnormamth, // llvm.hexagon.V6.vnormamth - hexagon_V6_vnormamth_128B, // llvm.hexagon.V6.vnormamth.128B - hexagon_V6_vnormamtw, // llvm.hexagon.V6.vnormamtw - hexagon_V6_vnormamtw_128B, // llvm.hexagon.V6.vnormamtw.128B - hexagon_V6_vnot, // llvm.hexagon.V6.vnot - hexagon_V6_vnot_128B, // llvm.hexagon.V6.vnot.128B - hexagon_V6_vor, // llvm.hexagon.V6.vor - hexagon_V6_vor_128B, // llvm.hexagon.V6.vor.128B - hexagon_V6_vpackeb, // llvm.hexagon.V6.vpackeb - hexagon_V6_vpackeb_128B, // llvm.hexagon.V6.vpackeb.128B - hexagon_V6_vpackeh, // llvm.hexagon.V6.vpackeh - hexagon_V6_vpackeh_128B, // llvm.hexagon.V6.vpackeh.128B - hexagon_V6_vpackhb_sat, // llvm.hexagon.V6.vpackhb.sat - hexagon_V6_vpackhb_sat_128B, // llvm.hexagon.V6.vpackhb.sat.128B - hexagon_V6_vpackhub_sat, // llvm.hexagon.V6.vpackhub.sat - hexagon_V6_vpackhub_sat_128B, // llvm.hexagon.V6.vpackhub.sat.128B - hexagon_V6_vpackob, // llvm.hexagon.V6.vpackob - hexagon_V6_vpackob_128B, // llvm.hexagon.V6.vpackob.128B - hexagon_V6_vpackoh, // llvm.hexagon.V6.vpackoh - hexagon_V6_vpackoh_128B, // llvm.hexagon.V6.vpackoh.128B - hexagon_V6_vpackwh_sat, // llvm.hexagon.V6.vpackwh.sat - hexagon_V6_vpackwh_sat_128B, // llvm.hexagon.V6.vpackwh.sat.128B - hexagon_V6_vpackwuh_sat, // llvm.hexagon.V6.vpackwuh.sat - hexagon_V6_vpackwuh_sat_128B, // llvm.hexagon.V6.vpackwuh.sat.128B - hexagon_V6_vpopcounth, // llvm.hexagon.V6.vpopcounth - hexagon_V6_vpopcounth_128B, // llvm.hexagon.V6.vpopcounth.128B - hexagon_V6_vprefixqb, // llvm.hexagon.V6.vprefixqb - hexagon_V6_vprefixqb_128B, // llvm.hexagon.V6.vprefixqb.128B - hexagon_V6_vprefixqh, // llvm.hexagon.V6.vprefixqh - hexagon_V6_vprefixqh_128B, // llvm.hexagon.V6.vprefixqh.128B - hexagon_V6_vprefixqw, // llvm.hexagon.V6.vprefixqw - hexagon_V6_vprefixqw_128B, // llvm.hexagon.V6.vprefixqw.128B - hexagon_V6_vrdelta, // llvm.hexagon.V6.vrdelta - hexagon_V6_vrdelta_128B, // llvm.hexagon.V6.vrdelta.128B - hexagon_V6_vrmpybub_rtt, // llvm.hexagon.V6.vrmpybub.rtt - hexagon_V6_vrmpybub_rtt_128B, // llvm.hexagon.V6.vrmpybub.rtt.128B - hexagon_V6_vrmpybub_rtt_acc, // llvm.hexagon.V6.vrmpybub.rtt.acc - hexagon_V6_vrmpybub_rtt_acc_128B, // llvm.hexagon.V6.vrmpybub.rtt.acc.128B - hexagon_V6_vrmpybus, // llvm.hexagon.V6.vrmpybus - hexagon_V6_vrmpybus_128B, // llvm.hexagon.V6.vrmpybus.128B - hexagon_V6_vrmpybus_acc, // llvm.hexagon.V6.vrmpybus.acc - hexagon_V6_vrmpybus_acc_128B, // llvm.hexagon.V6.vrmpybus.acc.128B - hexagon_V6_vrmpybusi, // llvm.hexagon.V6.vrmpybusi - hexagon_V6_vrmpybusi_128B, // llvm.hexagon.V6.vrmpybusi.128B - hexagon_V6_vrmpybusi_acc, // llvm.hexagon.V6.vrmpybusi.acc - hexagon_V6_vrmpybusi_acc_128B, // llvm.hexagon.V6.vrmpybusi.acc.128B - hexagon_V6_vrmpybusv, // llvm.hexagon.V6.vrmpybusv - hexagon_V6_vrmpybusv_128B, // llvm.hexagon.V6.vrmpybusv.128B - hexagon_V6_vrmpybusv_acc, // llvm.hexagon.V6.vrmpybusv.acc - hexagon_V6_vrmpybusv_acc_128B, // llvm.hexagon.V6.vrmpybusv.acc.128B - hexagon_V6_vrmpybv, // llvm.hexagon.V6.vrmpybv - hexagon_V6_vrmpybv_128B, // llvm.hexagon.V6.vrmpybv.128B - hexagon_V6_vrmpybv_acc, // llvm.hexagon.V6.vrmpybv.acc - hexagon_V6_vrmpybv_acc_128B, // llvm.hexagon.V6.vrmpybv.acc.128B - hexagon_V6_vrmpyub, // llvm.hexagon.V6.vrmpyub - hexagon_V6_vrmpyub_128B, // llvm.hexagon.V6.vrmpyub.128B - hexagon_V6_vrmpyub_acc, // llvm.hexagon.V6.vrmpyub.acc - hexagon_V6_vrmpyub_acc_128B, // llvm.hexagon.V6.vrmpyub.acc.128B - hexagon_V6_vrmpyub_rtt, // llvm.hexagon.V6.vrmpyub.rtt - hexagon_V6_vrmpyub_rtt_128B, // llvm.hexagon.V6.vrmpyub.rtt.128B - hexagon_V6_vrmpyub_rtt_acc, // llvm.hexagon.V6.vrmpyub.rtt.acc - hexagon_V6_vrmpyub_rtt_acc_128B, // llvm.hexagon.V6.vrmpyub.rtt.acc.128B - hexagon_V6_vrmpyubi, // llvm.hexagon.V6.vrmpyubi - hexagon_V6_vrmpyubi_128B, // llvm.hexagon.V6.vrmpyubi.128B - hexagon_V6_vrmpyubi_acc, // llvm.hexagon.V6.vrmpyubi.acc - hexagon_V6_vrmpyubi_acc_128B, // llvm.hexagon.V6.vrmpyubi.acc.128B - hexagon_V6_vrmpyubv, // llvm.hexagon.V6.vrmpyubv - hexagon_V6_vrmpyubv_128B, // llvm.hexagon.V6.vrmpyubv.128B - hexagon_V6_vrmpyubv_acc, // llvm.hexagon.V6.vrmpyubv.acc - hexagon_V6_vrmpyubv_acc_128B, // llvm.hexagon.V6.vrmpyubv.acc.128B - hexagon_V6_vror, // llvm.hexagon.V6.vror - hexagon_V6_vror_128B, // llvm.hexagon.V6.vror.128B - hexagon_V6_vrotr, // llvm.hexagon.V6.vrotr - hexagon_V6_vrotr_128B, // llvm.hexagon.V6.vrotr.128B - hexagon_V6_vroundhb, // llvm.hexagon.V6.vroundhb - hexagon_V6_vroundhb_128B, // llvm.hexagon.V6.vroundhb.128B - hexagon_V6_vroundhub, // llvm.hexagon.V6.vroundhub - hexagon_V6_vroundhub_128B, // llvm.hexagon.V6.vroundhub.128B - hexagon_V6_vrounduhub, // llvm.hexagon.V6.vrounduhub - hexagon_V6_vrounduhub_128B, // llvm.hexagon.V6.vrounduhub.128B - hexagon_V6_vrounduwuh, // llvm.hexagon.V6.vrounduwuh - hexagon_V6_vrounduwuh_128B, // llvm.hexagon.V6.vrounduwuh.128B - hexagon_V6_vroundwh, // llvm.hexagon.V6.vroundwh - hexagon_V6_vroundwh_128B, // llvm.hexagon.V6.vroundwh.128B - hexagon_V6_vroundwuh, // llvm.hexagon.V6.vroundwuh - hexagon_V6_vroundwuh_128B, // llvm.hexagon.V6.vroundwuh.128B - hexagon_V6_vrsadubi, // llvm.hexagon.V6.vrsadubi - hexagon_V6_vrsadubi_128B, // llvm.hexagon.V6.vrsadubi.128B - hexagon_V6_vrsadubi_acc, // llvm.hexagon.V6.vrsadubi.acc - hexagon_V6_vrsadubi_acc_128B, // llvm.hexagon.V6.vrsadubi.acc.128B - hexagon_V6_vsatdw, // llvm.hexagon.V6.vsatdw - hexagon_V6_vsatdw_128B, // llvm.hexagon.V6.vsatdw.128B - hexagon_V6_vsathub, // llvm.hexagon.V6.vsathub - hexagon_V6_vsathub_128B, // llvm.hexagon.V6.vsathub.128B - hexagon_V6_vsatuwuh, // llvm.hexagon.V6.vsatuwuh - hexagon_V6_vsatuwuh_128B, // llvm.hexagon.V6.vsatuwuh.128B - hexagon_V6_vsatwh, // llvm.hexagon.V6.vsatwh - hexagon_V6_vsatwh_128B, // llvm.hexagon.V6.vsatwh.128B - hexagon_V6_vsb, // llvm.hexagon.V6.vsb - hexagon_V6_vsb_128B, // llvm.hexagon.V6.vsb.128B - hexagon_V6_vscattermh, // llvm.hexagon.V6.vscattermh - hexagon_V6_vscattermh_128B, // llvm.hexagon.V6.vscattermh.128B - hexagon_V6_vscattermh_add, // llvm.hexagon.V6.vscattermh.add - hexagon_V6_vscattermh_add_128B, // llvm.hexagon.V6.vscattermh.add.128B - hexagon_V6_vscattermhq, // llvm.hexagon.V6.vscattermhq - hexagon_V6_vscattermhq_128B, // llvm.hexagon.V6.vscattermhq.128B - hexagon_V6_vscattermhw, // llvm.hexagon.V6.vscattermhw - hexagon_V6_vscattermhw_128B, // llvm.hexagon.V6.vscattermhw.128B - hexagon_V6_vscattermhw_add, // llvm.hexagon.V6.vscattermhw.add - hexagon_V6_vscattermhw_add_128B, // llvm.hexagon.V6.vscattermhw.add.128B - hexagon_V6_vscattermhwq, // llvm.hexagon.V6.vscattermhwq - hexagon_V6_vscattermhwq_128B, // llvm.hexagon.V6.vscattermhwq.128B - hexagon_V6_vscattermw, // llvm.hexagon.V6.vscattermw - hexagon_V6_vscattermw_128B, // llvm.hexagon.V6.vscattermw.128B - hexagon_V6_vscattermw_add, // llvm.hexagon.V6.vscattermw.add - hexagon_V6_vscattermw_add_128B, // llvm.hexagon.V6.vscattermw.add.128B - hexagon_V6_vscattermwq, // llvm.hexagon.V6.vscattermwq - hexagon_V6_vscattermwq_128B, // llvm.hexagon.V6.vscattermwq.128B - hexagon_V6_vsh, // llvm.hexagon.V6.vsh - hexagon_V6_vsh_128B, // llvm.hexagon.V6.vsh.128B - hexagon_V6_vshufeh, // llvm.hexagon.V6.vshufeh - hexagon_V6_vshufeh_128B, // llvm.hexagon.V6.vshufeh.128B - hexagon_V6_vshuffb, // llvm.hexagon.V6.vshuffb - hexagon_V6_vshuffb_128B, // llvm.hexagon.V6.vshuffb.128B - hexagon_V6_vshuffeb, // llvm.hexagon.V6.vshuffeb - hexagon_V6_vshuffeb_128B, // llvm.hexagon.V6.vshuffeb.128B - hexagon_V6_vshuffh, // llvm.hexagon.V6.vshuffh - hexagon_V6_vshuffh_128B, // llvm.hexagon.V6.vshuffh.128B - hexagon_V6_vshuffob, // llvm.hexagon.V6.vshuffob - hexagon_V6_vshuffob_128B, // llvm.hexagon.V6.vshuffob.128B - hexagon_V6_vshuffvdd, // llvm.hexagon.V6.vshuffvdd - hexagon_V6_vshuffvdd_128B, // llvm.hexagon.V6.vshuffvdd.128B - hexagon_V6_vshufoeb, // llvm.hexagon.V6.vshufoeb - hexagon_V6_vshufoeb_128B, // llvm.hexagon.V6.vshufoeb.128B - hexagon_V6_vshufoeh, // llvm.hexagon.V6.vshufoeh - hexagon_V6_vshufoeh_128B, // llvm.hexagon.V6.vshufoeh.128B - hexagon_V6_vshufoh, // llvm.hexagon.V6.vshufoh - hexagon_V6_vshufoh_128B, // llvm.hexagon.V6.vshufoh.128B - hexagon_V6_vsub_hf, // llvm.hexagon.V6.vsub.hf - hexagon_V6_vsub_hf_128B, // llvm.hexagon.V6.vsub.hf.128B - hexagon_V6_vsub_hf_hf, // llvm.hexagon.V6.vsub.hf.hf - hexagon_V6_vsub_hf_hf_128B, // llvm.hexagon.V6.vsub.hf.hf.128B - hexagon_V6_vsub_qf16, // llvm.hexagon.V6.vsub.qf16 - hexagon_V6_vsub_qf16_128B, // llvm.hexagon.V6.vsub.qf16.128B - hexagon_V6_vsub_qf16_mix, // llvm.hexagon.V6.vsub.qf16.mix - hexagon_V6_vsub_qf16_mix_128B, // llvm.hexagon.V6.vsub.qf16.mix.128B - hexagon_V6_vsub_qf32, // llvm.hexagon.V6.vsub.qf32 - hexagon_V6_vsub_qf32_128B, // llvm.hexagon.V6.vsub.qf32.128B - hexagon_V6_vsub_qf32_mix, // llvm.hexagon.V6.vsub.qf32.mix - hexagon_V6_vsub_qf32_mix_128B, // llvm.hexagon.V6.vsub.qf32.mix.128B - hexagon_V6_vsub_sf, // llvm.hexagon.V6.vsub.sf - hexagon_V6_vsub_sf_128B, // llvm.hexagon.V6.vsub.sf.128B - hexagon_V6_vsub_sf_hf, // llvm.hexagon.V6.vsub.sf.hf - hexagon_V6_vsub_sf_hf_128B, // llvm.hexagon.V6.vsub.sf.hf.128B - hexagon_V6_vsub_sf_sf, // llvm.hexagon.V6.vsub.sf.sf - hexagon_V6_vsub_sf_sf_128B, // llvm.hexagon.V6.vsub.sf.sf.128B - hexagon_V6_vsubb, // llvm.hexagon.V6.vsubb - hexagon_V6_vsubb_128B, // llvm.hexagon.V6.vsubb.128B - hexagon_V6_vsubb_dv, // llvm.hexagon.V6.vsubb.dv - hexagon_V6_vsubb_dv_128B, // llvm.hexagon.V6.vsubb.dv.128B - hexagon_V6_vsubbnq, // llvm.hexagon.V6.vsubbnq - hexagon_V6_vsubbnq_128B, // llvm.hexagon.V6.vsubbnq.128B - hexagon_V6_vsubbq, // llvm.hexagon.V6.vsubbq - hexagon_V6_vsubbq_128B, // llvm.hexagon.V6.vsubbq.128B - hexagon_V6_vsubbsat, // llvm.hexagon.V6.vsubbsat - hexagon_V6_vsubbsat_128B, // llvm.hexagon.V6.vsubbsat.128B - hexagon_V6_vsubbsat_dv, // llvm.hexagon.V6.vsubbsat.dv - hexagon_V6_vsubbsat_dv_128B, // llvm.hexagon.V6.vsubbsat.dv.128B - hexagon_V6_vsubcarry, // llvm.hexagon.V6.vsubcarry - hexagon_V6_vsubcarry_128B, // llvm.hexagon.V6.vsubcarry.128B - hexagon_V6_vsubh, // llvm.hexagon.V6.vsubh - hexagon_V6_vsubh_128B, // llvm.hexagon.V6.vsubh.128B - hexagon_V6_vsubh_dv, // llvm.hexagon.V6.vsubh.dv - hexagon_V6_vsubh_dv_128B, // llvm.hexagon.V6.vsubh.dv.128B - hexagon_V6_vsubhnq, // llvm.hexagon.V6.vsubhnq - hexagon_V6_vsubhnq_128B, // llvm.hexagon.V6.vsubhnq.128B - hexagon_V6_vsubhq, // llvm.hexagon.V6.vsubhq - hexagon_V6_vsubhq_128B, // llvm.hexagon.V6.vsubhq.128B - hexagon_V6_vsubhsat, // llvm.hexagon.V6.vsubhsat - hexagon_V6_vsubhsat_128B, // llvm.hexagon.V6.vsubhsat.128B - hexagon_V6_vsubhsat_dv, // llvm.hexagon.V6.vsubhsat.dv - hexagon_V6_vsubhsat_dv_128B, // llvm.hexagon.V6.vsubhsat.dv.128B - hexagon_V6_vsubhw, // llvm.hexagon.V6.vsubhw - hexagon_V6_vsubhw_128B, // llvm.hexagon.V6.vsubhw.128B - hexagon_V6_vsububh, // llvm.hexagon.V6.vsububh - hexagon_V6_vsububh_128B, // llvm.hexagon.V6.vsububh.128B - hexagon_V6_vsububsat, // llvm.hexagon.V6.vsububsat - hexagon_V6_vsububsat_128B, // llvm.hexagon.V6.vsububsat.128B - hexagon_V6_vsububsat_dv, // llvm.hexagon.V6.vsububsat.dv - hexagon_V6_vsububsat_dv_128B, // llvm.hexagon.V6.vsububsat.dv.128B - hexagon_V6_vsubububb_sat, // llvm.hexagon.V6.vsubububb.sat - hexagon_V6_vsubububb_sat_128B, // llvm.hexagon.V6.vsubububb.sat.128B - hexagon_V6_vsubuhsat, // llvm.hexagon.V6.vsubuhsat - hexagon_V6_vsubuhsat_128B, // llvm.hexagon.V6.vsubuhsat.128B - hexagon_V6_vsubuhsat_dv, // llvm.hexagon.V6.vsubuhsat.dv - hexagon_V6_vsubuhsat_dv_128B, // llvm.hexagon.V6.vsubuhsat.dv.128B - hexagon_V6_vsubuhw, // llvm.hexagon.V6.vsubuhw - hexagon_V6_vsubuhw_128B, // llvm.hexagon.V6.vsubuhw.128B - hexagon_V6_vsubuwsat, // llvm.hexagon.V6.vsubuwsat - hexagon_V6_vsubuwsat_128B, // llvm.hexagon.V6.vsubuwsat.128B - hexagon_V6_vsubuwsat_dv, // llvm.hexagon.V6.vsubuwsat.dv - hexagon_V6_vsubuwsat_dv_128B, // llvm.hexagon.V6.vsubuwsat.dv.128B - hexagon_V6_vsubw, // llvm.hexagon.V6.vsubw - hexagon_V6_vsubw_128B, // llvm.hexagon.V6.vsubw.128B - hexagon_V6_vsubw_dv, // llvm.hexagon.V6.vsubw.dv - hexagon_V6_vsubw_dv_128B, // llvm.hexagon.V6.vsubw.dv.128B - hexagon_V6_vsubwnq, // llvm.hexagon.V6.vsubwnq - hexagon_V6_vsubwnq_128B, // llvm.hexagon.V6.vsubwnq.128B - hexagon_V6_vsubwq, // llvm.hexagon.V6.vsubwq - hexagon_V6_vsubwq_128B, // llvm.hexagon.V6.vsubwq.128B - hexagon_V6_vsubwsat, // llvm.hexagon.V6.vsubwsat - hexagon_V6_vsubwsat_128B, // llvm.hexagon.V6.vsubwsat.128B - hexagon_V6_vsubwsat_dv, // llvm.hexagon.V6.vsubwsat.dv - hexagon_V6_vsubwsat_dv_128B, // llvm.hexagon.V6.vsubwsat.dv.128B - hexagon_V6_vswap, // llvm.hexagon.V6.vswap - hexagon_V6_vswap_128B, // llvm.hexagon.V6.vswap.128B - hexagon_V6_vtmpyb, // llvm.hexagon.V6.vtmpyb - hexagon_V6_vtmpyb_128B, // llvm.hexagon.V6.vtmpyb.128B - hexagon_V6_vtmpyb_acc, // llvm.hexagon.V6.vtmpyb.acc - hexagon_V6_vtmpyb_acc_128B, // llvm.hexagon.V6.vtmpyb.acc.128B - hexagon_V6_vtmpybus, // llvm.hexagon.V6.vtmpybus - hexagon_V6_vtmpybus_128B, // llvm.hexagon.V6.vtmpybus.128B - hexagon_V6_vtmpybus_acc, // llvm.hexagon.V6.vtmpybus.acc - hexagon_V6_vtmpybus_acc_128B, // llvm.hexagon.V6.vtmpybus.acc.128B - hexagon_V6_vtmpyhb, // llvm.hexagon.V6.vtmpyhb - hexagon_V6_vtmpyhb_128B, // llvm.hexagon.V6.vtmpyhb.128B - hexagon_V6_vtmpyhb_acc, // llvm.hexagon.V6.vtmpyhb.acc - hexagon_V6_vtmpyhb_acc_128B, // llvm.hexagon.V6.vtmpyhb.acc.128B - hexagon_V6_vunpackb, // llvm.hexagon.V6.vunpackb - hexagon_V6_vunpackb_128B, // llvm.hexagon.V6.vunpackb.128B - hexagon_V6_vunpackh, // llvm.hexagon.V6.vunpackh - hexagon_V6_vunpackh_128B, // llvm.hexagon.V6.vunpackh.128B - hexagon_V6_vunpackob, // llvm.hexagon.V6.vunpackob - hexagon_V6_vunpackob_128B, // llvm.hexagon.V6.vunpackob.128B - hexagon_V6_vunpackoh, // llvm.hexagon.V6.vunpackoh - hexagon_V6_vunpackoh_128B, // llvm.hexagon.V6.vunpackoh.128B - hexagon_V6_vunpackub, // llvm.hexagon.V6.vunpackub - hexagon_V6_vunpackub_128B, // llvm.hexagon.V6.vunpackub.128B - hexagon_V6_vunpackuh, // llvm.hexagon.V6.vunpackuh - hexagon_V6_vunpackuh_128B, // llvm.hexagon.V6.vunpackuh.128B - hexagon_V6_vxor, // llvm.hexagon.V6.vxor - hexagon_V6_vxor_128B, // llvm.hexagon.V6.vxor.128B - hexagon_V6_vzb, // llvm.hexagon.V6.vzb - hexagon_V6_vzb_128B, // llvm.hexagon.V6.vzb.128B - hexagon_V6_vzh, // llvm.hexagon.V6.vzh - hexagon_V6_vzh_128B, // llvm.hexagon.V6.vzh.128B - hexagon_Y2_dccleana, // llvm.hexagon.Y2.dccleana - hexagon_Y2_dccleaninva, // llvm.hexagon.Y2.dccleaninva - hexagon_Y2_dcfetch, // llvm.hexagon.Y2.dcfetch - hexagon_Y2_dcinva, // llvm.hexagon.Y2.dcinva - hexagon_Y2_dczeroa, // llvm.hexagon.Y2.dczeroa - hexagon_Y4_l2fetch, // llvm.hexagon.Y4.l2fetch - hexagon_Y5_l2fetch, // llvm.hexagon.Y5.l2fetch - hexagon_Y6_dmlink, // llvm.hexagon.Y6.dmlink - hexagon_Y6_dmpause, // llvm.hexagon.Y6.dmpause - hexagon_Y6_dmpoll, // llvm.hexagon.Y6.dmpoll - hexagon_Y6_dmresume, // llvm.hexagon.Y6.dmresume - hexagon_Y6_dmstart, // llvm.hexagon.Y6.dmstart - hexagon_Y6_dmwait, // llvm.hexagon.Y6.dmwait - hexagon_circ_ldb, // llvm.hexagon.circ.ldb - hexagon_circ_ldd, // llvm.hexagon.circ.ldd - hexagon_circ_ldh, // llvm.hexagon.circ.ldh - hexagon_circ_ldub, // llvm.hexagon.circ.ldub - hexagon_circ_lduh, // llvm.hexagon.circ.lduh - hexagon_circ_ldw, // llvm.hexagon.circ.ldw - hexagon_circ_stb, // llvm.hexagon.circ.stb - hexagon_circ_std, // llvm.hexagon.circ.std - hexagon_circ_sth, // llvm.hexagon.circ.sth - hexagon_circ_sthhi, // llvm.hexagon.circ.sthhi - hexagon_circ_stw, // llvm.hexagon.circ.stw - hexagon_prefetch, // llvm.hexagon.prefetch - hexagon_vmemcpy, // llvm.hexagon.vmemcpy - hexagon_vmemset, // llvm.hexagon.vmemset -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.td deleted file mode 100644 index 212262c287..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagon.td +++ /dev/null @@ -1,407 +0,0 @@ -//===- IntrinsicsHexagon.td - Defines Hexagon intrinsics ---*- tablegen -*-===// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the Hexagon-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Definitions for all Hexagon intrinsics. -// -// All Hexagon intrinsics start with "llvm.hexagon.". -let TargetPrefix = "hexagon" in { - /// Hexagon_Intrinsic - Base class for the majority of Hexagon intrinsics. - class Hexagon_Intrinsic ret_types, - list param_types, - list properties> - : GCCBuiltin, - Intrinsic; - - /// Hexagon_NonGCC_Intrinsic - Base class for bitcode convertible Hexagon - /// intrinsics. - class Hexagon_NonGCC_Intrinsic ret_types, - list param_types, - list properties> - : Intrinsic; -} - -class Hexagon_mem_memmemsi_Intrinsic - : Hexagon_Intrinsic; - -class Hexagon_mem_memsisi_Intrinsic - : Hexagon_Intrinsic; - -class Hexagon_mem_memdisi_Intrinsic - : Hexagon_Intrinsic; - -class Hexagon_mem_memmemsisi_Intrinsic - : Hexagon_Intrinsic>]>; - -class Hexagon_mem_memsisisi_Intrinsic - : Hexagon_Intrinsic>]>; - -class Hexagon_mem_memdisisi_Intrinsic - : Hexagon_Intrinsic>]>; - -// -// BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_ldd : -Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; -// -// BUILTIN_INFO_NONCONST(circ_ldw,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_ldw : -Hexagon_mem_memmemsisi_Intrinsic<"circ_ldw">; -// -// BUILTIN_INFO_NONCONST(circ_ldh,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_ldh : -Hexagon_mem_memmemsisi_Intrinsic<"circ_ldh">; -// -// BUILTIN_INFO_NONCONST(circ_lduh,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_lduh : -Hexagon_mem_memmemsisi_Intrinsic<"circ_lduh">; -// -// BUILTIN_INFO_NONCONST(circ_ldb,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_ldb : -Hexagon_mem_memmemsisi_Intrinsic<"circ_ldb">; -// -// BUILTIN_INFO_NONCONST(circ_ldub,PTR_ftype_PTRPTRSISI,4) -// -def int_hexagon_circ_ldub : -Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">; - -// -// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4) -// -def int_hexagon_circ_std : -Hexagon_mem_memdisisi_Intrinsic<"circ_std">; -// -// BUILTIN_INFO_NONCONST(circ_stw,PTR_ftype_PTRSISISI,4) -// -def int_hexagon_circ_stw : -Hexagon_mem_memsisisi_Intrinsic<"circ_stw">; -// -// BUILTIN_INFO_NONCONST(circ_sth,PTR_ftype_PTRSISISI,4) -// -def int_hexagon_circ_sth : -Hexagon_mem_memsisisi_Intrinsic<"circ_sth">; -// -// BUILTIN_INFO_NONCONST(circ_sthhi,PTR_ftype_PTRSISISI,4) -// -def int_hexagon_circ_sthhi : -Hexagon_mem_memsisisi_Intrinsic<"circ_sthhi">; -// -// BUILTIN_INFO_NONCONST(circ_stb,PTR_ftype_PTRSISISI,4) -// -def int_hexagon_circ_stb : -Hexagon_mem_memsisisi_Intrinsic<"circ_stb">; - -def int_hexagon_prefetch : -Hexagon_Intrinsic<"HEXAGON_prefetch", [], [llvm_ptr_ty], []>; - -def llvm_ptr32_ty : LLVMPointerType; -def llvm_ptr64_ty : LLVMPointerType; - -// Mark locked loads as read/write to prevent any accidental reordering. -def int_hexagon_L2_loadw_locked : -Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], - [IntrArgMemOnly, NoCapture>]>; -def int_hexagon_L4_loadd_locked : -Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], - [IntrArgMemOnly, NoCapture>]>; - -def int_hexagon_S2_storew_locked : -Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], - [llvm_ptr32_ty, llvm_i32_ty], [IntrArgMemOnly, NoCapture>]>; -def int_hexagon_S4_stored_locked : -Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], - [llvm_ptr64_ty, llvm_i64_ty], [IntrArgMemOnly, NoCapture>]>; - -def int_hexagon_vmemcpy : Hexagon_Intrinsic<"hexagon_vmemcpy", - [], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>, NoCapture>, WriteOnly>, ReadOnly>]>; - -def int_hexagon_vmemset : Hexagon_Intrinsic<"hexagon_vmemset", - [], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>, WriteOnly>]>; - -multiclass Hexagon_custom_circ_ld_Intrinsic { - def NAME#_pci : Hexagon_NonGCC_Intrinsic< - [ElTy, llvm_ptr_ty], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def NAME#_pcr : Hexagon_NonGCC_Intrinsic< - [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; -} - -defm int_hexagon_L2_loadrub : Hexagon_custom_circ_ld_Intrinsic; -defm int_hexagon_L2_loadrb : Hexagon_custom_circ_ld_Intrinsic; -defm int_hexagon_L2_loadruh : Hexagon_custom_circ_ld_Intrinsic; -defm int_hexagon_L2_loadrh : Hexagon_custom_circ_ld_Intrinsic; -defm int_hexagon_L2_loadri : Hexagon_custom_circ_ld_Intrinsic; -defm int_hexagon_L2_loadrd : Hexagon_custom_circ_ld_Intrinsic; - -multiclass Hexagon_custom_circ_st_Intrinsic { - def NAME#_pci : Hexagon_NonGCC_Intrinsic< - [llvm_ptr_ty], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def NAME#_pcr : Hexagon_NonGCC_Intrinsic< - [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; -} - -defm int_hexagon_S2_storerb : Hexagon_custom_circ_st_Intrinsic; -defm int_hexagon_S2_storerh : Hexagon_custom_circ_st_Intrinsic; -defm int_hexagon_S2_storerf : Hexagon_custom_circ_st_Intrinsic; -defm int_hexagon_S2_storeri : Hexagon_custom_circ_st_Intrinsic; -defm int_hexagon_S2_storerd : Hexagon_custom_circ_st_Intrinsic; - -// The front-end emits the intrinsic call with only two arguments. The third -// argument from the builtin is already used by front-end to write to memory -// by generating a store. -class Hexagon_custom_brev_ld_Intrinsic - : Hexagon_NonGCC_Intrinsic< - [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem]>; - -def int_hexagon_L2_loadrub_pbr : Hexagon_custom_brev_ld_Intrinsic; -def int_hexagon_L2_loadrb_pbr : Hexagon_custom_brev_ld_Intrinsic; -def int_hexagon_L2_loadruh_pbr : Hexagon_custom_brev_ld_Intrinsic; -def int_hexagon_L2_loadrh_pbr : Hexagon_custom_brev_ld_Intrinsic; -def int_hexagon_L2_loadri_pbr : Hexagon_custom_brev_ld_Intrinsic; -def int_hexagon_L2_loadrd_pbr : Hexagon_custom_brev_ld_Intrinsic; - -def int_hexagon_S2_storerb_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stb">; -def int_hexagon_S2_storerh_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sth">; -def int_hexagon_S2_storerf_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; -def int_hexagon_S2_storeri_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stw">; -def int_hexagon_S2_storerd_pbr : Hexagon_mem_memdisi_Intrinsic<"brev_std">; - -// tag : V6_vrmpybub_rtt -class Hexagon_v32i32_v16i32i64_rtt_Intrinsic - : Hexagon_Intrinsic; - -// tag : V6_vrmpybub_rtt_128B -class Hexagon_v64i32_v32i32i64_rtt_Intrinsic - : Hexagon_Intrinsic; - -// tag : V6_vrmpybub_rtt_acc -class Hexagon_v32i32_v32i32v16i32i64_rtt_Intrinsic - : Hexagon_Intrinsic; - -// tag : V6_vrmpybub_rtt_acc_128B -class Hexagon_v64i32_v64i32v32i32i64_rtt_Intrinsic - : Hexagon_Intrinsic; - -def int_hexagon_V6_vrmpybub_rtt : -Hexagon_v32i32_v16i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpybub_rtt">; - -def int_hexagon_V6_vrmpybub_rtt_128B : -Hexagon_v64i32_v32i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpybub_rtt_128B">; - -def int_hexagon_V6_vrmpybub_rtt_acc : -Hexagon_v32i32_v32i32v16i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpybub_rtt_acc">; - -def int_hexagon_V6_vrmpybub_rtt_acc_128B : -Hexagon_v64i32_v64i32v32i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpybub_rtt_acc_128B">; - -def int_hexagon_V6_vrmpyub_rtt : -Hexagon_v32i32_v16i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpyub_rtt">; - -def int_hexagon_V6_vrmpyub_rtt_128B : -Hexagon_v64i32_v32i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpyub_rtt_128B">; - -def int_hexagon_V6_vrmpyub_rtt_acc : -Hexagon_v32i32_v32i32v16i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpyub_rtt_acc">; - -def int_hexagon_V6_vrmpyub_rtt_acc_128B : -Hexagon_v64i32_v64i32v32i32i64_rtt_Intrinsic<"HEXAGON_V6_vrmpyub_rtt_acc_128B">; - -// HVX conditional loads/stores - -class Hexagon_pred_vload_imm - : Hexagon_NonGCC_Intrinsic< - [ValTy], - [llvm_i1_ty, LLVMPointerType, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>, - ImmArg>]>; - -class Hexagon_pred_vload_imm_64B: Hexagon_pred_vload_imm; -class Hexagon_pred_vload_imm_128B: Hexagon_pred_vload_imm; - -def int_hexagon_V6_vL32b_pred_ai: Hexagon_pred_vload_imm_64B; -def int_hexagon_V6_vL32b_npred_ai: Hexagon_pred_vload_imm_64B; -def int_hexagon_V6_vL32b_nt_pred_ai: Hexagon_pred_vload_imm_64B; -def int_hexagon_V6_vL32b_nt_npred_ai: Hexagon_pred_vload_imm_64B; -def int_hexagon_V6_vL32b_pred_ai_128B: Hexagon_pred_vload_imm_128B; -def int_hexagon_V6_vL32b_npred_ai_128B: Hexagon_pred_vload_imm_128B; -def int_hexagon_V6_vL32b_nt_pred_ai_128B: Hexagon_pred_vload_imm_128B; -def int_hexagon_V6_vL32b_nt_npred_ai_128B: Hexagon_pred_vload_imm_128B; - -class Hexagom_pred_vload_upd - : Hexagon_NonGCC_Intrinsic< - [ValTy, LLVMPointerType], - [llvm_i1_ty, LLVMPointerType, llvm_i32_ty], - !if(TakesImm, - [IntrReadMem, IntrArgMemOnly, NoCapture>, - ImmArg>], - [IntrReadMem, IntrArgMemOnly, NoCapture>])>; - -class Hexagom_pred_vload_upd_64B - : Hexagom_pred_vload_upd; -class Hexagom_pred_vload_upd_128B - : Hexagom_pred_vload_upd; - -def int_hexagon_V6_vL32b_pred_pi: Hexagom_pred_vload_upd_64B<1>; -def int_hexagon_V6_vL32b_npred_pi: Hexagom_pred_vload_upd_64B<1>; -def int_hexagon_V6_vL32b_nt_pred_pi: Hexagom_pred_vload_upd_64B<1>; -def int_hexagon_V6_vL32b_nt_npred_pi: Hexagom_pred_vload_upd_64B<1>; -def int_hexagon_V6_vL32b_pred_pi_128B: Hexagom_pred_vload_upd_128B<1>; -def int_hexagon_V6_vL32b_npred_pi_128B: Hexagom_pred_vload_upd_128B<1>; -def int_hexagon_V6_vL32b_nt_pred_pi_128B: Hexagom_pred_vload_upd_128B<1>; -def int_hexagon_V6_vL32b_nt_npred_pi_128B: Hexagom_pred_vload_upd_128B<1>; - -def int_hexagon_V6_vL32b_pred_ppu: Hexagom_pred_vload_upd_64B<0>; -def int_hexagon_V6_vL32b_npred_ppu: Hexagom_pred_vload_upd_64B<0>; -def int_hexagon_V6_vL32b_nt_pred_ppu: Hexagom_pred_vload_upd_64B<0>; -def int_hexagon_V6_vL32b_nt_npred_ppu: Hexagom_pred_vload_upd_64B<0>; -def int_hexagon_V6_vL32b_pred_ppu_128B: Hexagom_pred_vload_upd_128B<0>; -def int_hexagon_V6_vL32b_npred_ppu_128B: Hexagom_pred_vload_upd_128B<0>; -def int_hexagon_V6_vL32b_nt_pred_ppu_128B: Hexagom_pred_vload_upd_128B<0>; -def int_hexagon_V6_vL32b_nt_npred_ppu_128B: Hexagom_pred_vload_upd_128B<0>; - - -class Hexagon_pred_vstore_imm - : Hexagon_NonGCC_Intrinsic< - [], - [llvm_i1_ty, LLVMPointerType, llvm_i32_ty, ValTy], - [IntrWriteMem, IntrArgMemOnly, NoCapture>, - ImmArg>]>; - -class Hexagon_pred_vstore_imm_64B: Hexagon_pred_vstore_imm; -class Hexagon_pred_vstore_imm_128B: Hexagon_pred_vstore_imm; - -def int_hexagon_V6_vS32b_pred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32b_npred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32Ub_pred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32Ub_npred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32b_nt_pred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32b_nt_npred_ai: Hexagon_pred_vstore_imm_64B; -def int_hexagon_V6_vS32b_pred_ai_128B: Hexagon_pred_vstore_imm_128B; -def int_hexagon_V6_vS32b_npred_ai_128B: Hexagon_pred_vstore_imm_128B; -def int_hexagon_V6_vS32Ub_pred_ai_128B: Hexagon_pred_vstore_imm_128B; -def int_hexagon_V6_vS32Ub_npred_ai_128B: Hexagon_pred_vstore_imm_128B; -def int_hexagon_V6_vS32b_nt_pred_ai_128B: Hexagon_pred_vstore_imm_128B; -def int_hexagon_V6_vS32b_nt_npred_ai_128B: Hexagon_pred_vstore_imm_128B; - -class Hexagon_pred_vstore_upd - : Hexagon_NonGCC_Intrinsic< - [LLVMPointerType], - [llvm_i1_ty, LLVMPointerType, llvm_i32_ty, ValTy], - !if(TakesImm, - [IntrWriteMem, IntrArgMemOnly, NoCapture>, - ImmArg>], - [IntrWriteMem, IntrArgMemOnly, NoCapture>])>; - -class Hexagon_pred_vstore_upd_64B - : Hexagon_pred_vstore_upd; -class Hexagon_pred_vstore_upd_128B - : Hexagon_pred_vstore_upd; - -def int_hexagon_V6_vS32b_pred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32b_npred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32Ub_pred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32Ub_npred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32b_nt_pred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32b_nt_npred_pi: Hexagon_pred_vstore_upd_64B<1>; -def int_hexagon_V6_vS32b_pred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; -def int_hexagon_V6_vS32b_npred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; -def int_hexagon_V6_vS32Ub_pred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; -def int_hexagon_V6_vS32Ub_npred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; -def int_hexagon_V6_vS32b_nt_pred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; -def int_hexagon_V6_vS32b_nt_npred_pi_128B: Hexagon_pred_vstore_upd_128B<1>; - -def int_hexagon_V6_vS32b_pred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32b_npred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32Ub_pred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32Ub_npred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32b_nt_pred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32b_nt_npred_ppu: Hexagon_pred_vstore_upd_64B<0>; -def int_hexagon_V6_vS32b_pred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; -def int_hexagon_V6_vS32b_npred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; -def int_hexagon_V6_vS32Ub_pred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; -def int_hexagon_V6_vS32Ub_npred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; -def int_hexagon_V6_vS32b_nt_pred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; -def int_hexagon_V6_vS32b_nt_npred_ppu_128B: Hexagon_pred_vstore_upd_128B<0>; - - -// HVX Vector predicate casts. -// These intrinsics do not emit (nor do they correspond to) any instructions, -// they are no-ops. - -def int_hexagon_V6_pred_typecast : -Hexagon_NonGCC_Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -def int_hexagon_V6_pred_typecast_128B : -Hexagon_NonGCC_Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -// Masked vector stores -// -// These are all deprecated, the intrinsics matching instruction names -// should be used instead, e.g. int_hexagon_V6_vS32b_qpred_ai, etc. - -class Hexagon_custom_vms_Intrinsic - : Hexagon_NonGCC_Intrinsic< - [], [llvm_v64i1_ty,llvm_ptr_ty,llvm_v16i32_ty], [IntrWriteMem]>; - -class Hexagon_custom_vms_Intrinsic_128B - : Hexagon_NonGCC_Intrinsic< - [], [llvm_v128i1_ty,llvm_ptr_ty,llvm_v32i32_ty], [IntrWriteMem]>; - -def int_hexagon_V6_vmaskedstoreq: Hexagon_custom_vms_Intrinsic; -def int_hexagon_V6_vmaskedstorenq: Hexagon_custom_vms_Intrinsic; -def int_hexagon_V6_vmaskedstorentq: Hexagon_custom_vms_Intrinsic; -def int_hexagon_V6_vmaskedstorentnq: Hexagon_custom_vms_Intrinsic; - -def int_hexagon_V6_vmaskedstoreq_128B: Hexagon_custom_vms_Intrinsic_128B; -def int_hexagon_V6_vmaskedstorenq_128B: Hexagon_custom_vms_Intrinsic_128B; -def int_hexagon_V6_vmaskedstorentq_128B: Hexagon_custom_vms_Intrinsic_128B; -def int_hexagon_V6_vmaskedstorentnq_128B: Hexagon_custom_vms_Intrinsic_128B; - -include "llvm/IR/IntrinsicsHexagonDep.td" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagonDep.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagonDep.td deleted file mode 100644 index 177114636a..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsHexagonDep.td +++ /dev/null @@ -1,6589 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Automatically generated file, do not edit! -//===----------------------------------------------------------------------===// - -// tag : A2_abs -class Hexagon_i32_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_absp -class Hexagon_i64_i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_add -class Hexagon_i32_i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_addp -class Hexagon_i64_i64i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_addsp -class Hexagon_i64_i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_combineii -class Hexagon_i64_i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_roundsat -class Hexagon_i32_i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_sxtw -class Hexagon_i64_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_vcmpbeq -class Hexagon_i32_i64i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A2_vraddub_acc -class Hexagon_i64_i64i64i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A4_boundscheck -class Hexagon_i32_i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A4_tlbmatch -class Hexagon_i32_i64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A4_vrmaxh -class Hexagon_i64_i64i64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : A7_croundd_ri -class Hexagon_i64_i64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : C2_mux -class Hexagon_i32_i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : C2_vmux -class Hexagon_i64_i32i64i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_d2df -class Hexagon_double_i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_d2sf -class Hexagon_float_i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_df2d -class Hexagon_i64_double_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_df2sf -class Hexagon_float_double_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_df2uw -class Hexagon_i32_double_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_sf2d -class Hexagon_i64_float_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_sf2df -class Hexagon_double_float_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_sf2uw -class Hexagon_i32_float_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_uw2df -class Hexagon_double_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_conv_uw2sf -class Hexagon_float_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_dfadd -class Hexagon_double_doubledouble_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_dfclass -class Hexagon_i32_doublei32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_dfcmpeq -class Hexagon_i32_doubledouble_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_dfmpyhh -class Hexagon_double_doubledoubledouble_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sfadd -class Hexagon_float_floatfloat_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sfclass -class Hexagon_i32_floati32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sfcmpeq -class Hexagon_i32_floatfloat_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sffixupr -class Hexagon_float_float_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sffma -class Hexagon_float_floatfloatfloat_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : F2_sffma_sc -class Hexagon_float_floatfloatfloati32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : M2_cmaci_s0 -class Hexagon_i64_i64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : S2_insert -class Hexagon_i32_i32i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : S2_insert_rp -class Hexagon_i32_i32i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : S2_insertp -class Hexagon_i64_i64i64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_extractw -class Hexagon_i32_v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_extractw -class Hexagon_i32_v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_hi -class Hexagon_v16i32_v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_hi -class Hexagon_v32i32_v64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_lvsplatw -class Hexagon_v16i32_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_lvsplatb -class Hexagon_v32i32_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_and -class Hexagon_v64i1_v64i1v64i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_and -class Hexagon_v128i1_v128i1v128i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_not -class Hexagon_v64i1_v64i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_not -class Hexagon_v128i1_v128i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_scalar2 -class Hexagon_v64i1_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_pred_scalar2 -class Hexagon_v128i1_i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_v6mpyhubs10 -class Hexagon_v32i32_v32i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_v6mpyhubs10 -class Hexagon_v64i32_v64i32v64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_v6mpyhubs10_vxx -class Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_v6mpyhubs10_vxx -class Hexagon_v64i32_v64i32v64i32v64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vS32b_nqpred_ai -class Hexagon__v64i1ptrv16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vS32b_nqpred_ai -class Hexagon__v128i1ptrv32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vabs_hf -class Hexagon_v16i32_v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vabs_hf -class Hexagon_v32i32_v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vabsdiffh -class Hexagon_v16i32_v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vabsdiffh -class Hexagon_v32i32_v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vadd_sf_hf -class Hexagon_v32i32_v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vadd_sf_hf -class Hexagon_v64i32_v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddb_dv -class Hexagon_v64i32_v64i32v64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddbnq -class Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddbnq -class Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddcarry -class Hexagon_custom_v16i32v64i1_v16i32v16i32v64i1_Intrinsic< - list intr_properties = [IntrNoMem]> - : Hexagon_NonGCC_Intrinsic< - [llvm_v16i32_ty,llvm_v64i1_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_v64i1_ty], - intr_properties>; - -// tag : V6_vaddcarry -class Hexagon_custom_v32i32v128i1_v32i32v32i32v128i1_Intrinsic_128B< - list intr_properties = [IntrNoMem]> - : Hexagon_NonGCC_Intrinsic< - [llvm_v32i32_ty,llvm_v128i1_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_v128i1_ty], - intr_properties>; - -// tag : V6_vaddcarrysat -class Hexagon_v16i32_v16i32v16i32v64i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddcarrysat -class Hexagon_v32i32_v32i32v32i32v128i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddhw_acc -class Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaddhw_acc -class Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_valignb -class Hexagon_v16i32_v16i32v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandnqrt -class Hexagon_v16i32_v64i1i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandnqrt -class Hexagon_v32i32_v128i1i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandnqrt_acc -class Hexagon_v16i32_v16i32v64i1i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandnqrt_acc -class Hexagon_v32i32_v32i32v128i1i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvnqv -class Hexagon_v16i32_v64i1v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvnqv -class Hexagon_v32i32_v128i1v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvrt -class Hexagon_v64i1_v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvrt -class Hexagon_v128i1_v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvrt_acc -class Hexagon_v64i1_v64i1v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vandvrt_acc -class Hexagon_v128i1_v128i1v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaslh -class Hexagon_v16i32_v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vaslh -class Hexagon_v32i32_v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vasrvuhubrndsat -class Hexagon_v16i32_v32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vasrvuhubrndsat -class Hexagon_v32i32_v64i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vassignp -class Hexagon_v64i32_v64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vcvt_hf_b -class Hexagon_v32i32_v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vcvt_hf_b -class Hexagon_v64i32_v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vd0 -class Hexagon_v16i32__Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vd0 -class Hexagon_v32i32__Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdd0 -class Hexagon_v64i32__Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdealvdd -class Hexagon_v32i32_v16i32v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdealvdd -class Hexagon_v64i32_v32i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpy_sf_hf_acc -class Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpy_sf_hf_acc -class Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpybus_dv -class Hexagon_v64i32_v64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpyhisat -class Hexagon_v16i32_v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpyhisat -class Hexagon_v32i32_v64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpyhisat_acc -class Hexagon_v16i32_v16i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vdmpyhisat_acc -class Hexagon_v32i32_v32i32v64i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_veqb -class Hexagon_v64i1_v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_veqb -class Hexagon_v128i1_v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_veqb_and -class Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_veqb_and -class Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermh -class Hexagon__ptri32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermh -class Hexagon__ptri32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermhq -class Hexagon__ptrv64i1i32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermhq -class Hexagon__ptrv128i1i32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermhw -class Hexagon__ptri32i32v64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermhwq -class Hexagon__ptrv64i1i32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vgathermhwq -class Hexagon__ptrv128i1i32i32v64i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vlut4 -class Hexagon_v16i32_v16i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vlut4 -class Hexagon_v32i32_v32i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vlutvvb_oracc -class Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vlutvwh_oracc -class Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vlutvwh_oracc -class Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpahhsat -class Hexagon_v16i32_v16i32v16i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpahhsat -class Hexagon_v32i32_v32i32v32i32i64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpybus -class Hexagon_v32i32_v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpybus -class Hexagon_v64i32_v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpybus_acc -class Hexagon_v32i32_v32i32v16i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vmpybus_acc -class Hexagon_v64i32_v64i32v32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vprefixqb -class Hexagon_v16i32_v64i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vprefixqb -class Hexagon_v32i32_v128i1_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vrmpybusi -class Hexagon_v32i32_v32i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vrmpybusi -class Hexagon_v64i32_v64i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vrmpybusi_acc -class Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vrmpybusi_acc -class Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermh -class Hexagon__i32i32v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermh -class Hexagon__i32i32v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhq -class Hexagon__v64i1i32i32v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhq -class Hexagon__v128i1i32i32v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhw -class Hexagon__i32i32v32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhw -class Hexagon__i32i32v64i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhwq -class Hexagon__v64i1i32i32v32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vscattermhwq -class Hexagon__v128i1i32i32v64i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vswap -class Hexagon_v32i32_v64i1v16i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vswap -class Hexagon_v64i32_v128i1v32i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vunpackob -class Hexagon_v32i32_v32i32v16i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : V6_vunpackob -class Hexagon_v64i32_v64i32v32i32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : Y2_dccleana -class Hexagon__ptr_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : Y4_l2fetch -class Hexagon__ptri32_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : Y5_l2fetch -class Hexagon__ptri64_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : Y6_dmlink -class Hexagon__ptrptr_Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// tag : Y6_dmpause -class Hexagon_i32__Intrinsic intr_properties = [IntrNoMem]> - : Hexagon_Intrinsic; - -// V5 Scalar Instructions. - -def int_hexagon_A2_abs : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_abs">; - -def int_hexagon_A2_absp : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_absp">; - -def int_hexagon_A2_abssat : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_abssat">; - -def int_hexagon_A2_add : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_add">; - -def int_hexagon_A2_addh_h16_hh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_hh">; - -def int_hexagon_A2_addh_h16_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_hl">; - -def int_hexagon_A2_addh_h16_lh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_lh">; - -def int_hexagon_A2_addh_h16_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_ll">; - -def int_hexagon_A2_addh_h16_sat_hh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_sat_hh">; - -def int_hexagon_A2_addh_h16_sat_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_sat_hl">; - -def int_hexagon_A2_addh_h16_sat_lh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_sat_lh">; - -def int_hexagon_A2_addh_h16_sat_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_h16_sat_ll">; - -def int_hexagon_A2_addh_l16_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_l16_hl">; - -def int_hexagon_A2_addh_l16_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_l16_ll">; - -def int_hexagon_A2_addh_l16_sat_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_l16_sat_hl">; - -def int_hexagon_A2_addh_l16_sat_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_l16_sat_ll">; - -def int_hexagon_A2_addi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_addp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_addp">; - -def int_hexagon_A2_addpsat : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_addpsat">; - -def int_hexagon_A2_addsat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addsat">; - -def int_hexagon_A2_addsp : -Hexagon_i64_i32i64_Intrinsic<"HEXAGON_A2_addsp">; - -def int_hexagon_A2_and : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_and">; - -def int_hexagon_A2_andir : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_andir", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_andp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_andp">; - -def int_hexagon_A2_aslh : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_aslh">; - -def int_hexagon_A2_asrh : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_asrh">; - -def int_hexagon_A2_combine_hh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_combine_hh">; - -def int_hexagon_A2_combine_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_combine_hl">; - -def int_hexagon_A2_combine_lh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_combine_lh">; - -def int_hexagon_A2_combine_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_combine_ll">; - -def int_hexagon_A2_combineii : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A2_combineii", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_A2_combinew : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A2_combinew">; - -def int_hexagon_A2_max : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_max">; - -def int_hexagon_A2_maxp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_maxp">; - -def int_hexagon_A2_maxu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_maxu">; - -def int_hexagon_A2_maxup : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_maxup">; - -def int_hexagon_A2_min : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_min">; - -def int_hexagon_A2_minp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_minp">; - -def int_hexagon_A2_minu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_minu">; - -def int_hexagon_A2_minup : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_minup">; - -def int_hexagon_A2_neg : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_neg">; - -def int_hexagon_A2_negp : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_negp">; - -def int_hexagon_A2_negsat : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_negsat">; - -def int_hexagon_A2_not : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_not">; - -def int_hexagon_A2_notp : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_notp">; - -def int_hexagon_A2_or : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_or">; - -def int_hexagon_A2_orir : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_orir", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_orp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_orp">; - -def int_hexagon_A2_roundsat : -Hexagon_i32_i64_Intrinsic<"HEXAGON_A2_roundsat">; - -def int_hexagon_A2_sat : -Hexagon_i32_i64_Intrinsic<"HEXAGON_A2_sat">; - -def int_hexagon_A2_satb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_satb">; - -def int_hexagon_A2_sath : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_sath">; - -def int_hexagon_A2_satub : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_satub">; - -def int_hexagon_A2_satuh : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_satuh">; - -def int_hexagon_A2_sub : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_sub">; - -def int_hexagon_A2_subh_h16_hh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_hh">; - -def int_hexagon_A2_subh_h16_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_hl">; - -def int_hexagon_A2_subh_h16_lh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_lh">; - -def int_hexagon_A2_subh_h16_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_ll">; - -def int_hexagon_A2_subh_h16_sat_hh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_sat_hh">; - -def int_hexagon_A2_subh_h16_sat_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_sat_hl">; - -def int_hexagon_A2_subh_h16_sat_lh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_sat_lh">; - -def int_hexagon_A2_subh_h16_sat_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_sat_ll">; - -def int_hexagon_A2_subh_l16_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_hl">; - -def int_hexagon_A2_subh_l16_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_ll">; - -def int_hexagon_A2_subh_l16_sat_hl : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_sat_hl">; - -def int_hexagon_A2_subh_l16_sat_ll : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_sat_ll">; - -def int_hexagon_A2_subp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_subp">; - -def int_hexagon_A2_subri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_subsat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subsat">; - -def int_hexagon_A2_svaddh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svaddh">; - -def int_hexagon_A2_svaddhs : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svaddhs">; - -def int_hexagon_A2_svadduhs : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svadduhs">; - -def int_hexagon_A2_svavgh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svavgh">; - -def int_hexagon_A2_svavghs : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svavghs">; - -def int_hexagon_A2_svnavgh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svnavgh">; - -def int_hexagon_A2_svsubh : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svsubh">; - -def int_hexagon_A2_svsubhs : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svsubhs">; - -def int_hexagon_A2_svsubuhs : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svsubuhs">; - -def int_hexagon_A2_swiz : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_swiz">; - -def int_hexagon_A2_sxtb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_sxtb">; - -def int_hexagon_A2_sxth : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_sxth">; - -def int_hexagon_A2_sxtw : -Hexagon_i64_i32_Intrinsic<"HEXAGON_A2_sxtw">; - -def int_hexagon_A2_tfr : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfr">; - -def int_hexagon_A2_tfrih : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfrih", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_tfril : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfril", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_tfrp : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_tfrp">; - -def int_hexagon_A2_tfrpi : -Hexagon_i64_i32_Intrinsic<"HEXAGON_A2_tfrpi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_tfrsi : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfrsi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A2_vabsh : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vabsh">; - -def int_hexagon_A2_vabshsat : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vabshsat">; - -def int_hexagon_A2_vabsw : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vabsw">; - -def int_hexagon_A2_vabswsat : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vabswsat">; - -def int_hexagon_A2_vaddb_map : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddb_map">; - -def int_hexagon_A2_vaddh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddh">; - -def int_hexagon_A2_vaddhs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddhs">; - -def int_hexagon_A2_vaddub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddub">; - -def int_hexagon_A2_vaddubs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddubs">; - -def int_hexagon_A2_vadduhs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vadduhs">; - -def int_hexagon_A2_vaddw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddw">; - -def int_hexagon_A2_vaddws : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddws">; - -def int_hexagon_A2_vavgh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgh">; - -def int_hexagon_A2_vavghcr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavghcr">; - -def int_hexagon_A2_vavghr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavghr">; - -def int_hexagon_A2_vavgub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgub">; - -def int_hexagon_A2_vavgubr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgubr">; - -def int_hexagon_A2_vavguh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguh">; - -def int_hexagon_A2_vavguhr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguhr">; - -def int_hexagon_A2_vavguw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguw">; - -def int_hexagon_A2_vavguwr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguwr">; - -def int_hexagon_A2_vavgw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgw">; - -def int_hexagon_A2_vavgwcr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgwcr">; - -def int_hexagon_A2_vavgwr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgwr">; - -def int_hexagon_A2_vcmpbeq : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpbeq">; - -def int_hexagon_A2_vcmpbgtu : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpbgtu">; - -def int_hexagon_A2_vcmpheq : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpheq">; - -def int_hexagon_A2_vcmphgt : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmphgt">; - -def int_hexagon_A2_vcmphgtu : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmphgtu">; - -def int_hexagon_A2_vcmpweq : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpweq">; - -def int_hexagon_A2_vcmpwgt : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpwgt">; - -def int_hexagon_A2_vcmpwgtu : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpwgtu">; - -def int_hexagon_A2_vconj : -Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vconj">; - -def int_hexagon_A2_vmaxb : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxb">; - -def int_hexagon_A2_vmaxh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxh">; - -def int_hexagon_A2_vmaxub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxub">; - -def int_hexagon_A2_vmaxuh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxuh">; - -def int_hexagon_A2_vmaxuw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxuw">; - -def int_hexagon_A2_vmaxw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxw">; - -def int_hexagon_A2_vminb : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminb">; - -def int_hexagon_A2_vminh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminh">; - -def int_hexagon_A2_vminub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminub">; - -def int_hexagon_A2_vminuh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminuh">; - -def int_hexagon_A2_vminuw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminuw">; - -def int_hexagon_A2_vminw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminw">; - -def int_hexagon_A2_vnavgh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavgh">; - -def int_hexagon_A2_vnavghcr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavghcr">; - -def int_hexagon_A2_vnavghr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavghr">; - -def int_hexagon_A2_vnavgw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavgw">; - -def int_hexagon_A2_vnavgwcr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavgwcr">; - -def int_hexagon_A2_vnavgwr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavgwr">; - -def int_hexagon_A2_vraddub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vraddub">; - -def int_hexagon_A2_vraddub_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_A2_vraddub_acc">; - -def int_hexagon_A2_vrsadub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vrsadub">; - -def int_hexagon_A2_vrsadub_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_A2_vrsadub_acc">; - -def int_hexagon_A2_vsubb_map : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubb_map">; - -def int_hexagon_A2_vsubh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubh">; - -def int_hexagon_A2_vsubhs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubhs">; - -def int_hexagon_A2_vsubub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubub">; - -def int_hexagon_A2_vsububs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsububs">; - -def int_hexagon_A2_vsubuhs : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubuhs">; - -def int_hexagon_A2_vsubw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubw">; - -def int_hexagon_A2_vsubws : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubws">; - -def int_hexagon_A2_xor : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_xor">; - -def int_hexagon_A2_xorp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_xorp">; - -def int_hexagon_A2_zxtb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_zxtb">; - -def int_hexagon_A2_zxth : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_zxth">; - -def int_hexagon_A4_andn : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_andn">; - -def int_hexagon_A4_andnp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A4_andnp">; - -def int_hexagon_A4_bitsplit : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_bitsplit">; - -def int_hexagon_A4_bitspliti : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_bitspliti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_boundscheck : -Hexagon_i32_i32i64_Intrinsic<"HEXAGON_A4_boundscheck">; - -def int_hexagon_A4_cmpbeq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbeq">; - -def int_hexagon_A4_cmpbeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbeqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cmpbgt : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgt">; - -def int_hexagon_A4_cmpbgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cmpbgtu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgtu">; - -def int_hexagon_A4_cmpbgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cmpheq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpheq">; - -def int_hexagon_A4_cmpheqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpheqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cmphgt : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgt">; - -def int_hexagon_A4_cmphgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cmphgtu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgtu">; - -def int_hexagon_A4_cmphgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_combineir : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineir", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_combineri : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cround_ri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cround_ri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_cround_rr : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cround_rr">; - -def int_hexagon_A4_modwrapu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_modwrapu">; - -def int_hexagon_A4_orn : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_orn">; - -def int_hexagon_A4_ornp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A4_ornp">; - -def int_hexagon_A4_rcmpeq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpeq">; - -def int_hexagon_A4_rcmpeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpeqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_rcmpneq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpneq">; - -def int_hexagon_A4_rcmpneqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpneqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_round_ri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_round_ri_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri_sat", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_round_rr : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_rr">; - -def int_hexagon_A4_round_rr_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_rr_sat">; - -def int_hexagon_A4_tlbmatch : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_tlbmatch">; - -def int_hexagon_A4_vcmpbeq_any : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; - -def int_hexagon_A4_vcmpbeqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbeqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpbgt : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A4_vcmpbgt">; - -def int_hexagon_A4_vcmpbgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpbgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpheqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpheqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmphgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmphgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpweqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpweqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpwgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vcmpwgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A4_vrmaxh : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxh">; - -def int_hexagon_A4_vrmaxuh : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxuh">; - -def int_hexagon_A4_vrmaxuw : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxuw">; - -def int_hexagon_A4_vrmaxw : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxw">; - -def int_hexagon_A4_vrminh : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminh">; - -def int_hexagon_A4_vrminuh : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminuh">; - -def int_hexagon_A4_vrminuw : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminuw">; - -def int_hexagon_A4_vrminw : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminw">; - -def int_hexagon_A5_vaddhubs : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A5_vaddhubs">; - -def int_hexagon_C2_all8 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_all8">; - -def int_hexagon_C2_and : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_and">; - -def int_hexagon_C2_andn : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_andn">; - -def int_hexagon_C2_any8 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_any8">; - -def int_hexagon_C2_bitsclr : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsclr">; - -def int_hexagon_C2_bitsclri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsclri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_bitsset : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsset">; - -def int_hexagon_C2_cmpeq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpeq">; - -def int_hexagon_C2_cmpeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpeqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_cmpeqp : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpeqp">; - -def int_hexagon_C2_cmpgei : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgei", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_cmpgeui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgeui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_cmpgt : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgt">; - -def int_hexagon_C2_cmpgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgti", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_cmpgtp : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpgtp">; - -def int_hexagon_C2_cmpgtu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgtu">; - -def int_hexagon_C2_cmpgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgtui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_cmpgtup : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpgtup">; - -def int_hexagon_C2_cmplt : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmplt">; - -def int_hexagon_C2_cmpltu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpltu">; - -def int_hexagon_C2_mask : -Hexagon_i64_i32_Intrinsic<"HEXAGON_C2_mask">; - -def int_hexagon_C2_mux : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_mux">; - -def int_hexagon_C2_muxii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxii", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_C2_muxir : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxir", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_muxri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C2_not : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_not">; - -def int_hexagon_C2_or : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_or">; - -def int_hexagon_C2_orn : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_orn">; - -def int_hexagon_C2_pxfer_map : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_pxfer_map">; - -def int_hexagon_C2_tfrpr : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_tfrpr">; - -def int_hexagon_C2_tfrrp : -Hexagon_i32_i32_Intrinsic<"HEXAGON_C2_tfrrp">; - -def int_hexagon_C2_vitpack : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_vitpack">; - -def int_hexagon_C2_vmux : -Hexagon_i64_i32i64i64_Intrinsic<"HEXAGON_C2_vmux">; - -def int_hexagon_C2_xor : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_xor">; - -def int_hexagon_C4_and_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_and">; - -def int_hexagon_C4_and_andn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_andn">; - -def int_hexagon_C4_and_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_or">; - -def int_hexagon_C4_and_orn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_orn">; - -def int_hexagon_C4_cmplte : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplte">; - -def int_hexagon_C4_cmpltei : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpltei", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C4_cmplteu : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplteu">; - -def int_hexagon_C4_cmplteui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplteui", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C4_cmpneq : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpneq">; - -def int_hexagon_C4_cmpneqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpneqi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C4_fastcorner9 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_fastcorner9">; - -def int_hexagon_C4_fastcorner9_not : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_fastcorner9_not">; - -def int_hexagon_C4_nbitsclr : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsclr">; - -def int_hexagon_C4_nbitsclri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsclri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_C4_nbitsset : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsset">; - -def int_hexagon_C4_or_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_or_and">; - -def int_hexagon_C4_or_andn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_or_andn">; - -def int_hexagon_C4_or_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_or_or">; - -def int_hexagon_C4_or_orn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_or_orn">; - -def int_hexagon_F2_conv_d2df : -Hexagon_double_i64_Intrinsic<"HEXAGON_F2_conv_d2df">; - -def int_hexagon_F2_conv_d2sf : -Hexagon_float_i64_Intrinsic<"HEXAGON_F2_conv_d2sf">; - -def int_hexagon_F2_conv_df2d : -Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2d">; - -def int_hexagon_F2_conv_df2d_chop : -Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2d_chop">; - -def int_hexagon_F2_conv_df2sf : -Hexagon_float_double_Intrinsic<"HEXAGON_F2_conv_df2sf">; - -def int_hexagon_F2_conv_df2ud : -Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2ud">; - -def int_hexagon_F2_conv_df2ud_chop : -Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2ud_chop">; - -def int_hexagon_F2_conv_df2uw : -Hexagon_i32_double_Intrinsic<"HEXAGON_F2_conv_df2uw">; - -def int_hexagon_F2_conv_df2uw_chop : -Hexagon_i32_double_Intrinsic<"HEXAGON_F2_conv_df2uw_chop">; - -def int_hexagon_F2_conv_df2w : -Hexagon_i32_double_Intrinsic<"HEXAGON_F2_conv_df2w">; - -def int_hexagon_F2_conv_df2w_chop : -Hexagon_i32_double_Intrinsic<"HEXAGON_F2_conv_df2w_chop">; - -def int_hexagon_F2_conv_sf2d : -Hexagon_i64_float_Intrinsic<"HEXAGON_F2_conv_sf2d">; - -def int_hexagon_F2_conv_sf2d_chop : -Hexagon_i64_float_Intrinsic<"HEXAGON_F2_conv_sf2d_chop">; - -def int_hexagon_F2_conv_sf2df : -Hexagon_double_float_Intrinsic<"HEXAGON_F2_conv_sf2df">; - -def int_hexagon_F2_conv_sf2ud : -Hexagon_i64_float_Intrinsic<"HEXAGON_F2_conv_sf2ud">; - -def int_hexagon_F2_conv_sf2ud_chop : -Hexagon_i64_float_Intrinsic<"HEXAGON_F2_conv_sf2ud_chop">; - -def int_hexagon_F2_conv_sf2uw : -Hexagon_i32_float_Intrinsic<"HEXAGON_F2_conv_sf2uw">; - -def int_hexagon_F2_conv_sf2uw_chop : -Hexagon_i32_float_Intrinsic<"HEXAGON_F2_conv_sf2uw_chop">; - -def int_hexagon_F2_conv_sf2w : -Hexagon_i32_float_Intrinsic<"HEXAGON_F2_conv_sf2w">; - -def int_hexagon_F2_conv_sf2w_chop : -Hexagon_i32_float_Intrinsic<"HEXAGON_F2_conv_sf2w_chop">; - -def int_hexagon_F2_conv_ud2df : -Hexagon_double_i64_Intrinsic<"HEXAGON_F2_conv_ud2df">; - -def int_hexagon_F2_conv_ud2sf : -Hexagon_float_i64_Intrinsic<"HEXAGON_F2_conv_ud2sf">; - -def int_hexagon_F2_conv_uw2df : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_conv_uw2df">; - -def int_hexagon_F2_conv_uw2sf : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_conv_uw2sf">; - -def int_hexagon_F2_conv_w2df : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_conv_w2df">; - -def int_hexagon_F2_conv_w2sf : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_conv_w2sf">; - -def int_hexagon_F2_dfclass : -Hexagon_i32_doublei32_Intrinsic<"HEXAGON_F2_dfclass", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_dfcmpeq : -Hexagon_i32_doubledouble_Intrinsic<"HEXAGON_F2_dfcmpeq", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfcmpge : -Hexagon_i32_doubledouble_Intrinsic<"HEXAGON_F2_dfcmpge", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfcmpgt : -Hexagon_i32_doubledouble_Intrinsic<"HEXAGON_F2_dfcmpgt", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfcmpuo : -Hexagon_i32_doubledouble_Intrinsic<"HEXAGON_F2_dfcmpuo", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfimm_n : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_n", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_dfimm_p : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_p", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_sfadd : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfadd", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfclass : -Hexagon_i32_floati32_Intrinsic<"HEXAGON_F2_sfclass", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_sfcmpeq : -Hexagon_i32_floatfloat_Intrinsic<"HEXAGON_F2_sfcmpeq", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfcmpge : -Hexagon_i32_floatfloat_Intrinsic<"HEXAGON_F2_sfcmpge", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfcmpgt : -Hexagon_i32_floatfloat_Intrinsic<"HEXAGON_F2_sfcmpgt", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfcmpuo : -Hexagon_i32_floatfloat_Intrinsic<"HEXAGON_F2_sfcmpuo", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffixupd : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sffixupd", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffixupn : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sffixupn", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffixupr : -Hexagon_float_float_Intrinsic<"HEXAGON_F2_sffixupr", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffma : -Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffma", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffma_lib : -Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffma_lib", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffma_sc : -Hexagon_float_floatfloatfloati32_Intrinsic<"HEXAGON_F2_sffma_sc", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffms : -Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffms", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sffms_lib : -Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffms_lib", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfimm_n : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_n", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_sfimm_p : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_p", [IntrNoMem, Throws, ImmArg>]>; - -def int_hexagon_F2_sfmax : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfmax", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfmin : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfmin", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfmpy : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfmpy", [IntrNoMem, Throws]>; - -def int_hexagon_F2_sfsub : -Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfsub", [IntrNoMem, Throws]>; - -def int_hexagon_M2_acci : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_acci">; - -def int_hexagon_M2_accii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_accii", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M2_cmaci_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmaci_s0">; - -def int_hexagon_M2_cmacr_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmacr_s0">; - -def int_hexagon_M2_cmacs_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmacs_s0">; - -def int_hexagon_M2_cmacs_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmacs_s1">; - -def int_hexagon_M2_cmacsc_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmacsc_s0">; - -def int_hexagon_M2_cmacsc_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmacsc_s1">; - -def int_hexagon_M2_cmpyi_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpyi_s0">; - -def int_hexagon_M2_cmpyr_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpyr_s0">; - -def int_hexagon_M2_cmpyrs_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrs_s0">; - -def int_hexagon_M2_cmpyrs_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrs_s1">; - -def int_hexagon_M2_cmpyrsc_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrsc_s0">; - -def int_hexagon_M2_cmpyrsc_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrsc_s1">; - -def int_hexagon_M2_cmpys_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpys_s0">; - -def int_hexagon_M2_cmpys_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpys_s1">; - -def int_hexagon_M2_cmpysc_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpysc_s0">; - -def int_hexagon_M2_cmpysc_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_cmpysc_s1">; - -def int_hexagon_M2_cnacs_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cnacs_s0">; - -def int_hexagon_M2_cnacs_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cnacs_s1">; - -def int_hexagon_M2_cnacsc_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cnacsc_s0">; - -def int_hexagon_M2_cnacsc_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cnacsc_s1">; - -def int_hexagon_M2_dpmpyss_acc_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_acc_s0">; - -def int_hexagon_M2_dpmpyss_nac_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_nac_s0">; - -def int_hexagon_M2_dpmpyss_rnd_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_rnd_s0">; - -def int_hexagon_M2_dpmpyss_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_s0">; - -def int_hexagon_M2_dpmpyuu_acc_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_dpmpyuu_acc_s0">; - -def int_hexagon_M2_dpmpyuu_nac_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_dpmpyuu_nac_s0">; - -def int_hexagon_M2_dpmpyuu_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_dpmpyuu_s0">; - -def int_hexagon_M2_hmmpyh_rs1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_hmmpyh_rs1">; - -def int_hexagon_M2_hmmpyh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_hmmpyh_s1">; - -def int_hexagon_M2_hmmpyl_rs1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_hmmpyl_rs1">; - -def int_hexagon_M2_hmmpyl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_hmmpyl_s1">; - -def int_hexagon_M2_maci : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_maci">; - -def int_hexagon_M2_macsin : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsin", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M2_macsip : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsip", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M2_mmachs_rs0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_rs0">; - -def int_hexagon_M2_mmachs_rs1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_rs1">; - -def int_hexagon_M2_mmachs_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_s0">; - -def int_hexagon_M2_mmachs_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_s1">; - -def int_hexagon_M2_mmacls_rs0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacls_rs0">; - -def int_hexagon_M2_mmacls_rs1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacls_rs1">; - -def int_hexagon_M2_mmacls_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacls_s0">; - -def int_hexagon_M2_mmacls_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacls_s1">; - -def int_hexagon_M2_mmacuhs_rs0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacuhs_rs0">; - -def int_hexagon_M2_mmacuhs_rs1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacuhs_rs1">; - -def int_hexagon_M2_mmacuhs_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacuhs_s0">; - -def int_hexagon_M2_mmacuhs_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacuhs_s1">; - -def int_hexagon_M2_mmaculs_rs0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmaculs_rs0">; - -def int_hexagon_M2_mmaculs_rs1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmaculs_rs1">; - -def int_hexagon_M2_mmaculs_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmaculs_s0">; - -def int_hexagon_M2_mmaculs_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmaculs_s1">; - -def int_hexagon_M2_mmpyh_rs0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyh_rs0">; - -def int_hexagon_M2_mmpyh_rs1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyh_rs1">; - -def int_hexagon_M2_mmpyh_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyh_s0">; - -def int_hexagon_M2_mmpyh_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyh_s1">; - -def int_hexagon_M2_mmpyl_rs0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyl_rs0">; - -def int_hexagon_M2_mmpyl_rs1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyl_rs1">; - -def int_hexagon_M2_mmpyl_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyl_s0">; - -def int_hexagon_M2_mmpyl_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyl_s1">; - -def int_hexagon_M2_mmpyuh_rs0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_rs0">; - -def int_hexagon_M2_mmpyuh_rs1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_rs1">; - -def int_hexagon_M2_mmpyuh_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_s0">; - -def int_hexagon_M2_mmpyuh_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_s1">; - -def int_hexagon_M2_mmpyul_rs0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_rs0">; - -def int_hexagon_M2_mmpyul_rs1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_rs1">; - -def int_hexagon_M2_mmpyul_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_s0">; - -def int_hexagon_M2_mmpyul_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_s1">; - -def int_hexagon_M2_mpy_acc_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_hh_s0">; - -def int_hexagon_M2_mpy_acc_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_hh_s1">; - -def int_hexagon_M2_mpy_acc_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_hl_s0">; - -def int_hexagon_M2_mpy_acc_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_hl_s1">; - -def int_hexagon_M2_mpy_acc_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_lh_s0">; - -def int_hexagon_M2_mpy_acc_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_lh_s1">; - -def int_hexagon_M2_mpy_acc_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_ll_s0">; - -def int_hexagon_M2_mpy_acc_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_ll_s1">; - -def int_hexagon_M2_mpy_acc_sat_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hh_s0">; - -def int_hexagon_M2_mpy_acc_sat_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hh_s1">; - -def int_hexagon_M2_mpy_acc_sat_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hl_s0">; - -def int_hexagon_M2_mpy_acc_sat_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hl_s1">; - -def int_hexagon_M2_mpy_acc_sat_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_lh_s0">; - -def int_hexagon_M2_mpy_acc_sat_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_lh_s1">; - -def int_hexagon_M2_mpy_acc_sat_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_ll_s0">; - -def int_hexagon_M2_mpy_acc_sat_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_ll_s1">; - -def int_hexagon_M2_mpy_hh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_hh_s0">; - -def int_hexagon_M2_mpy_hh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_hh_s1">; - -def int_hexagon_M2_mpy_hl_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_hl_s0">; - -def int_hexagon_M2_mpy_hl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_hl_s1">; - -def int_hexagon_M2_mpy_lh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_lh_s0">; - -def int_hexagon_M2_mpy_lh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_lh_s1">; - -def int_hexagon_M2_mpy_ll_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_ll_s0">; - -def int_hexagon_M2_mpy_ll_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_ll_s1">; - -def int_hexagon_M2_mpy_nac_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_hh_s0">; - -def int_hexagon_M2_mpy_nac_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_hh_s1">; - -def int_hexagon_M2_mpy_nac_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_hl_s0">; - -def int_hexagon_M2_mpy_nac_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_hl_s1">; - -def int_hexagon_M2_mpy_nac_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_lh_s0">; - -def int_hexagon_M2_mpy_nac_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_lh_s1">; - -def int_hexagon_M2_mpy_nac_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_ll_s0">; - -def int_hexagon_M2_mpy_nac_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_ll_s1">; - -def int_hexagon_M2_mpy_nac_sat_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hh_s0">; - -def int_hexagon_M2_mpy_nac_sat_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hh_s1">; - -def int_hexagon_M2_mpy_nac_sat_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hl_s0">; - -def int_hexagon_M2_mpy_nac_sat_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hl_s1">; - -def int_hexagon_M2_mpy_nac_sat_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_lh_s0">; - -def int_hexagon_M2_mpy_nac_sat_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_lh_s1">; - -def int_hexagon_M2_mpy_nac_sat_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_ll_s0">; - -def int_hexagon_M2_mpy_nac_sat_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_ll_s1">; - -def int_hexagon_M2_mpy_rnd_hh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_hh_s0">; - -def int_hexagon_M2_mpy_rnd_hh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_hh_s1">; - -def int_hexagon_M2_mpy_rnd_hl_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_hl_s0">; - -def int_hexagon_M2_mpy_rnd_hl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_hl_s1">; - -def int_hexagon_M2_mpy_rnd_lh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_lh_s0">; - -def int_hexagon_M2_mpy_rnd_lh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_lh_s1">; - -def int_hexagon_M2_mpy_rnd_ll_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_ll_s0">; - -def int_hexagon_M2_mpy_rnd_ll_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_ll_s1">; - -def int_hexagon_M2_mpy_sat_hh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_hh_s0">; - -def int_hexagon_M2_mpy_sat_hh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_hh_s1">; - -def int_hexagon_M2_mpy_sat_hl_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_hl_s0">; - -def int_hexagon_M2_mpy_sat_hl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_hl_s1">; - -def int_hexagon_M2_mpy_sat_lh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_lh_s0">; - -def int_hexagon_M2_mpy_sat_lh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_lh_s1">; - -def int_hexagon_M2_mpy_sat_ll_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_ll_s0">; - -def int_hexagon_M2_mpy_sat_ll_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_ll_s1">; - -def int_hexagon_M2_mpy_sat_rnd_hh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hh_s0">; - -def int_hexagon_M2_mpy_sat_rnd_hh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hh_s1">; - -def int_hexagon_M2_mpy_sat_rnd_hl_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hl_s0">; - -def int_hexagon_M2_mpy_sat_rnd_hl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hl_s1">; - -def int_hexagon_M2_mpy_sat_rnd_lh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_lh_s0">; - -def int_hexagon_M2_mpy_sat_rnd_lh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_lh_s1">; - -def int_hexagon_M2_mpy_sat_rnd_ll_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_ll_s0">; - -def int_hexagon_M2_mpy_sat_rnd_ll_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_ll_s1">; - -def int_hexagon_M2_mpy_up : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_up">; - -def int_hexagon_M2_mpy_up_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_up_s1">; - -def int_hexagon_M2_mpy_up_s1_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_up_s1_sat">; - -def int_hexagon_M2_mpyd_acc_hh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hh_s0">; - -def int_hexagon_M2_mpyd_acc_hh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hh_s1">; - -def int_hexagon_M2_mpyd_acc_hl_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hl_s0">; - -def int_hexagon_M2_mpyd_acc_hl_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hl_s1">; - -def int_hexagon_M2_mpyd_acc_lh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_lh_s0">; - -def int_hexagon_M2_mpyd_acc_lh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_lh_s1">; - -def int_hexagon_M2_mpyd_acc_ll_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_ll_s0">; - -def int_hexagon_M2_mpyd_acc_ll_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_ll_s1">; - -def int_hexagon_M2_mpyd_hh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_hh_s0">; - -def int_hexagon_M2_mpyd_hh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_hh_s1">; - -def int_hexagon_M2_mpyd_hl_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_hl_s0">; - -def int_hexagon_M2_mpyd_hl_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_hl_s1">; - -def int_hexagon_M2_mpyd_lh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_lh_s0">; - -def int_hexagon_M2_mpyd_lh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_lh_s1">; - -def int_hexagon_M2_mpyd_ll_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_ll_s0">; - -def int_hexagon_M2_mpyd_ll_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_ll_s1">; - -def int_hexagon_M2_mpyd_nac_hh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s0">; - -def int_hexagon_M2_mpyd_nac_hh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s1">; - -def int_hexagon_M2_mpyd_nac_hl_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hl_s0">; - -def int_hexagon_M2_mpyd_nac_hl_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hl_s1">; - -def int_hexagon_M2_mpyd_nac_lh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_lh_s0">; - -def int_hexagon_M2_mpyd_nac_lh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_lh_s1">; - -def int_hexagon_M2_mpyd_nac_ll_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_ll_s0">; - -def int_hexagon_M2_mpyd_nac_ll_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_ll_s1">; - -def int_hexagon_M2_mpyd_rnd_hh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_hh_s0">; - -def int_hexagon_M2_mpyd_rnd_hh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_hh_s1">; - -def int_hexagon_M2_mpyd_rnd_hl_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_hl_s0">; - -def int_hexagon_M2_mpyd_rnd_hl_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_hl_s1">; - -def int_hexagon_M2_mpyd_rnd_lh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_lh_s0">; - -def int_hexagon_M2_mpyd_rnd_lh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_lh_s1">; - -def int_hexagon_M2_mpyd_rnd_ll_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s0">; - -def int_hexagon_M2_mpyd_rnd_ll_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s1">; - -def int_hexagon_M2_mpyi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyi">; - -def int_hexagon_M2_mpysmi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysmi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M2_mpysu_up : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysu_up">; - -def int_hexagon_M2_mpyu_acc_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_hh_s0">; - -def int_hexagon_M2_mpyu_acc_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_hh_s1">; - -def int_hexagon_M2_mpyu_acc_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_hl_s0">; - -def int_hexagon_M2_mpyu_acc_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_hl_s1">; - -def int_hexagon_M2_mpyu_acc_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_lh_s0">; - -def int_hexagon_M2_mpyu_acc_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_lh_s1">; - -def int_hexagon_M2_mpyu_acc_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_ll_s0">; - -def int_hexagon_M2_mpyu_acc_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_acc_ll_s1">; - -def int_hexagon_M2_mpyu_hh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_hh_s0">; - -def int_hexagon_M2_mpyu_hh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_hh_s1">; - -def int_hexagon_M2_mpyu_hl_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_hl_s0">; - -def int_hexagon_M2_mpyu_hl_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_hl_s1">; - -def int_hexagon_M2_mpyu_lh_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_lh_s0">; - -def int_hexagon_M2_mpyu_lh_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_lh_s1">; - -def int_hexagon_M2_mpyu_ll_s0 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_ll_s0">; - -def int_hexagon_M2_mpyu_ll_s1 : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_ll_s1">; - -def int_hexagon_M2_mpyu_nac_hh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_hh_s0">; - -def int_hexagon_M2_mpyu_nac_hh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_hh_s1">; - -def int_hexagon_M2_mpyu_nac_hl_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_hl_s0">; - -def int_hexagon_M2_mpyu_nac_hl_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_hl_s1">; - -def int_hexagon_M2_mpyu_nac_lh_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_lh_s0">; - -def int_hexagon_M2_mpyu_nac_lh_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_lh_s1">; - -def int_hexagon_M2_mpyu_nac_ll_s0 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_ll_s0">; - -def int_hexagon_M2_mpyu_nac_ll_s1 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_ll_s1">; - -def int_hexagon_M2_mpyu_up : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_up">; - -def int_hexagon_M2_mpyud_acc_hh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_hh_s0">; - -def int_hexagon_M2_mpyud_acc_hh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_hh_s1">; - -def int_hexagon_M2_mpyud_acc_hl_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_hl_s0">; - -def int_hexagon_M2_mpyud_acc_hl_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_hl_s1">; - -def int_hexagon_M2_mpyud_acc_lh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_lh_s0">; - -def int_hexagon_M2_mpyud_acc_lh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_lh_s1">; - -def int_hexagon_M2_mpyud_acc_ll_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_ll_s0">; - -def int_hexagon_M2_mpyud_acc_ll_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_ll_s1">; - -def int_hexagon_M2_mpyud_hh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_hh_s0">; - -def int_hexagon_M2_mpyud_hh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_hh_s1">; - -def int_hexagon_M2_mpyud_hl_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_hl_s0">; - -def int_hexagon_M2_mpyud_hl_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_hl_s1">; - -def int_hexagon_M2_mpyud_lh_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_lh_s0">; - -def int_hexagon_M2_mpyud_lh_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_lh_s1">; - -def int_hexagon_M2_mpyud_ll_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_ll_s0">; - -def int_hexagon_M2_mpyud_ll_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyud_ll_s1">; - -def int_hexagon_M2_mpyud_nac_hh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hh_s0">; - -def int_hexagon_M2_mpyud_nac_hh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hh_s1">; - -def int_hexagon_M2_mpyud_nac_hl_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s0">; - -def int_hexagon_M2_mpyud_nac_hl_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s1">; - -def int_hexagon_M2_mpyud_nac_lh_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_lh_s0">; - -def int_hexagon_M2_mpyud_nac_lh_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_lh_s1">; - -def int_hexagon_M2_mpyud_nac_ll_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_ll_s0">; - -def int_hexagon_M2_mpyud_nac_ll_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_ll_s1">; - -def int_hexagon_M2_mpyui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyui">; - -def int_hexagon_M2_nacci : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_nacci">; - -def int_hexagon_M2_naccii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_naccii", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M2_subacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_subacc">; - -def int_hexagon_M2_vabsdiffh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vabsdiffh">; - -def int_hexagon_M2_vabsdiffw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vabsdiffw">; - -def int_hexagon_M2_vcmac_s0_sat_i : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vcmac_s0_sat_i">; - -def int_hexagon_M2_vcmac_s0_sat_r : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vcmac_s0_sat_r">; - -def int_hexagon_M2_vcmpy_s0_sat_i : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s0_sat_i">; - -def int_hexagon_M2_vcmpy_s0_sat_r : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s0_sat_r">; - -def int_hexagon_M2_vcmpy_s1_sat_i : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_i">; - -def int_hexagon_M2_vcmpy_s1_sat_r : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_r">; - -def int_hexagon_M2_vdmacs_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vdmacs_s0">; - -def int_hexagon_M2_vdmacs_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vdmacs_s1">; - -def int_hexagon_M2_vdmpyrs_s0 : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M2_vdmpyrs_s0">; - -def int_hexagon_M2_vdmpyrs_s1 : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M2_vdmpyrs_s1">; - -def int_hexagon_M2_vdmpys_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vdmpys_s0">; - -def int_hexagon_M2_vdmpys_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vdmpys_s1">; - -def int_hexagon_M2_vmac2 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2">; - -def int_hexagon_M2_vmac2es : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vmac2es">; - -def int_hexagon_M2_vmac2es_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vmac2es_s0">; - -def int_hexagon_M2_vmac2es_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vmac2es_s1">; - -def int_hexagon_M2_vmac2s_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2s_s0">; - -def int_hexagon_M2_vmac2s_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2s_s1">; - -def int_hexagon_M2_vmac2su_s0 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2su_s0">; - -def int_hexagon_M2_vmac2su_s1 : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2su_s1">; - -def int_hexagon_M2_vmpy2es_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vmpy2es_s0">; - -def int_hexagon_M2_vmpy2es_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vmpy2es_s1">; - -def int_hexagon_M2_vmpy2s_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_vmpy2s_s0">; - -def int_hexagon_M2_vmpy2s_s0pack : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_vmpy2s_s0pack">; - -def int_hexagon_M2_vmpy2s_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_vmpy2s_s1">; - -def int_hexagon_M2_vmpy2s_s1pack : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_vmpy2s_s1pack">; - -def int_hexagon_M2_vmpy2su_s0 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_vmpy2su_s0">; - -def int_hexagon_M2_vmpy2su_s1 : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_vmpy2su_s1">; - -def int_hexagon_M2_vraddh : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M2_vraddh">; - -def int_hexagon_M2_vradduh : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M2_vradduh">; - -def int_hexagon_M2_vrcmaci_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vrcmaci_s0">; - -def int_hexagon_M2_vrcmaci_s0c : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vrcmaci_s0c">; - -def int_hexagon_M2_vrcmacr_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vrcmacr_s0">; - -def int_hexagon_M2_vrcmacr_s0c : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vrcmacr_s0c">; - -def int_hexagon_M2_vrcmpyi_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrcmpyi_s0">; - -def int_hexagon_M2_vrcmpyi_s0c : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrcmpyi_s0c">; - -def int_hexagon_M2_vrcmpyr_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrcmpyr_s0">; - -def int_hexagon_M2_vrcmpyr_s0c : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrcmpyr_s0c">; - -def int_hexagon_M2_vrcmpys_acc_s1 : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_M2_vrcmpys_acc_s1">; - -def int_hexagon_M2_vrcmpys_s1 : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_M2_vrcmpys_s1">; - -def int_hexagon_M2_vrcmpys_s1rp : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M2_vrcmpys_s1rp">; - -def int_hexagon_M2_vrmac_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vrmac_s0">; - -def int_hexagon_M2_vrmpy_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrmpy_s0">; - -def int_hexagon_M2_xor_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_xor_xacc">; - -def int_hexagon_M4_and_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_and_and">; - -def int_hexagon_M4_and_andn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_and_andn">; - -def int_hexagon_M4_and_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_and_or">; - -def int_hexagon_M4_and_xor : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_and_xor">; - -def int_hexagon_M4_cmpyi_wh : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyi_wh">; - -def int_hexagon_M4_cmpyi_whc : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyi_whc">; - -def int_hexagon_M4_cmpyr_wh : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyr_wh">; - -def int_hexagon_M4_cmpyr_whc : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyr_whc">; - -def int_hexagon_M4_mac_up_s1_sat : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mac_up_s1_sat">; - -def int_hexagon_M4_mpyri_addi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addi", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_M4_mpyri_addr : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M4_mpyri_addr_u2 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr_u2", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M4_mpyrr_addi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyrr_addi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_M4_mpyrr_addr : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyrr_addr">; - -def int_hexagon_M4_nac_up_s1_sat : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_nac_up_s1_sat">; - -def int_hexagon_M4_or_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_or_and">; - -def int_hexagon_M4_or_andn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_or_andn">; - -def int_hexagon_M4_or_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_or_or">; - -def int_hexagon_M4_or_xor : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_or_xor">; - -def int_hexagon_M4_pmpyw : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M4_pmpyw">; - -def int_hexagon_M4_pmpyw_acc : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M4_pmpyw_acc">; - -def int_hexagon_M4_vpmpyh : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M4_vpmpyh">; - -def int_hexagon_M4_vpmpyh_acc : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M4_vpmpyh_acc">; - -def int_hexagon_M4_vrmpyeh_acc_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyeh_acc_s0">; - -def int_hexagon_M4_vrmpyeh_acc_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyeh_acc_s1">; - -def int_hexagon_M4_vrmpyeh_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M4_vrmpyeh_s0">; - -def int_hexagon_M4_vrmpyeh_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M4_vrmpyeh_s1">; - -def int_hexagon_M4_vrmpyoh_acc_s0 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyoh_acc_s0">; - -def int_hexagon_M4_vrmpyoh_acc_s1 : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyoh_acc_s1">; - -def int_hexagon_M4_vrmpyoh_s0 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M4_vrmpyoh_s0">; - -def int_hexagon_M4_vrmpyoh_s1 : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M4_vrmpyoh_s1">; - -def int_hexagon_M4_xor_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_xor_and">; - -def int_hexagon_M4_xor_andn : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_xor_andn">; - -def int_hexagon_M4_xor_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_xor_or">; - -def int_hexagon_M4_xor_xacc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_xor_xacc">; - -def int_hexagon_M5_vdmacbsu : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M5_vdmacbsu">; - -def int_hexagon_M5_vdmpybsu : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M5_vdmpybsu">; - -def int_hexagon_M5_vmacbsu : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M5_vmacbsu">; - -def int_hexagon_M5_vmacbuu : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M5_vmacbuu">; - -def int_hexagon_M5_vmpybsu : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M5_vmpybsu">; - -def int_hexagon_M5_vmpybuu : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M5_vmpybuu">; - -def int_hexagon_M5_vrmacbsu : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M5_vrmacbsu">; - -def int_hexagon_M5_vrmacbuu : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M5_vrmacbuu">; - -def int_hexagon_M5_vrmpybsu : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M5_vrmpybsu">; - -def int_hexagon_M5_vrmpybuu : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M5_vrmpybuu">; - -def int_hexagon_S2_addasl_rrri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_addasl_rrri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_p", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_xacc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_sat", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_xacc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vh", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vw", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asl_r_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_r_p">; - -def int_hexagon_S2_asl_r_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_acc">; - -def int_hexagon_S2_asl_r_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_and">; - -def int_hexagon_S2_asl_r_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_nac">; - -def int_hexagon_S2_asl_r_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_or">; - -def int_hexagon_S2_asl_r_p_xor : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_xor">; - -def int_hexagon_S2_asl_r_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_r_r">; - -def int_hexagon_S2_asl_r_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_acc">; - -def int_hexagon_S2_asl_r_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_and">; - -def int_hexagon_S2_asl_r_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_nac">; - -def int_hexagon_S2_asl_r_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_or">; - -def int_hexagon_S2_asl_r_r_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_sat">; - -def int_hexagon_S2_asl_r_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_r_vh">; - -def int_hexagon_S2_asl_r_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_r_vw">; - -def int_hexagon_S2_asr_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_rnd : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_p_rnd_goodsyntax : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd_goodsyntax", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_rnd : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_r_rnd_goodsyntax : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd_goodsyntax", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_svw_trun : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S2_asr_i_svw_trun", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vh", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vw", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_asr_r_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_r_p">; - -def int_hexagon_S2_asr_r_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_r_p_acc">; - -def int_hexagon_S2_asr_r_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_r_p_and">; - -def int_hexagon_S2_asr_r_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_r_p_nac">; - -def int_hexagon_S2_asr_r_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_r_p_or">; - -def int_hexagon_S2_asr_r_p_xor : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_r_p_xor">; - -def int_hexagon_S2_asr_r_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_r_r">; - -def int_hexagon_S2_asr_r_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_acc">; - -def int_hexagon_S2_asr_r_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_and">; - -def int_hexagon_S2_asr_r_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_nac">; - -def int_hexagon_S2_asr_r_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_or">; - -def int_hexagon_S2_asr_r_r_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_sat">; - -def int_hexagon_S2_asr_r_svw_trun : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S2_asr_r_svw_trun">; - -def int_hexagon_S2_asr_r_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_r_vh">; - -def int_hexagon_S2_asr_r_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_r_vw">; - -def int_hexagon_S2_brev : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_brev">; - -def int_hexagon_S2_brevp : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_brevp">; - -def int_hexagon_S2_cl0 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_cl0">; - -def int_hexagon_S2_cl0p : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_cl0p">; - -def int_hexagon_S2_cl1 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_cl1">; - -def int_hexagon_S2_cl1p : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_cl1p">; - -def int_hexagon_S2_clb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_clb">; - -def int_hexagon_S2_clbnorm : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_clbnorm">; - -def int_hexagon_S2_clbp : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_clbp">; - -def int_hexagon_S2_clrbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_clrbit_i", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_clrbit_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_clrbit_r">; - -def int_hexagon_S2_ct0 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_ct0">; - -def int_hexagon_S2_ct0p : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_ct0p">; - -def int_hexagon_S2_ct1 : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_ct1">; - -def int_hexagon_S2_ct1p : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_ct1p">; - -def int_hexagon_S2_deinterleave : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_deinterleave">; - -def int_hexagon_S2_extractu : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_extractu", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_extractu_rp : -Hexagon_i32_i32i64_Intrinsic<"HEXAGON_S2_extractu_rp">; - -def int_hexagon_S2_extractup : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S2_extractup", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_extractup_rp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_extractup_rp">; - -def int_hexagon_S2_insert : -Hexagon_i32_i32i32i32i32_Intrinsic<"HEXAGON_S2_insert", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_insert_rp : -Hexagon_i32_i32i32i64_Intrinsic<"HEXAGON_S2_insert_rp">; - -def int_hexagon_S2_insertp : -Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S2_insertp", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_insertp_rp : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_S2_insertp_rp">; - -def int_hexagon_S2_interleave : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_interleave">; - -def int_hexagon_S2_lfsp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_lfsp">; - -def int_hexagon_S2_lsl_r_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p">; - -def int_hexagon_S2_lsl_r_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_acc">; - -def int_hexagon_S2_lsl_r_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_and">; - -def int_hexagon_S2_lsl_r_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_nac">; - -def int_hexagon_S2_lsl_r_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_or">; - -def int_hexagon_S2_lsl_r_p_xor : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_xor">; - -def int_hexagon_S2_lsl_r_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r">; - -def int_hexagon_S2_lsl_r_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_acc">; - -def int_hexagon_S2_lsl_r_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_and">; - -def int_hexagon_S2_lsl_r_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_nac">; - -def int_hexagon_S2_lsl_r_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_or">; - -def int_hexagon_S2_lsl_r_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsl_r_vh">; - -def int_hexagon_S2_lsl_r_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsl_r_vw">; - -def int_hexagon_S2_lsr_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_xacc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_xacc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vh", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vw", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_lsr_r_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p">; - -def int_hexagon_S2_lsr_r_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_acc">; - -def int_hexagon_S2_lsr_r_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_and">; - -def int_hexagon_S2_lsr_r_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_nac">; - -def int_hexagon_S2_lsr_r_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_or">; - -def int_hexagon_S2_lsr_r_p_xor : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_xor">; - -def int_hexagon_S2_lsr_r_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r">; - -def int_hexagon_S2_lsr_r_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r_acc">; - -def int_hexagon_S2_lsr_r_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r_and">; - -def int_hexagon_S2_lsr_r_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r_nac">; - -def int_hexagon_S2_lsr_r_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r_or">; - -def int_hexagon_S2_lsr_r_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_r_vh">; - -def int_hexagon_S2_lsr_r_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_r_vw">; - -def int_hexagon_S2_packhl : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_S2_packhl">; - -def int_hexagon_S2_parityp : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_S2_parityp">; - -def int_hexagon_S2_setbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_setbit_i", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_setbit_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_setbit_r">; - -def int_hexagon_S2_shuffeb : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_shuffeb">; - -def int_hexagon_S2_shuffeh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_shuffeh">; - -def int_hexagon_S2_shuffob : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_shuffob">; - -def int_hexagon_S2_shuffoh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_shuffoh">; - -def int_hexagon_S2_svsathb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_svsathb">; - -def int_hexagon_S2_svsathub : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_svsathub">; - -def int_hexagon_S2_tableidxb_goodsyntax : -Hexagon_i32_i32i32i32i32_Intrinsic<"HEXAGON_S2_tableidxb_goodsyntax", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_tableidxd_goodsyntax : -Hexagon_i32_i32i32i32i32_Intrinsic<"HEXAGON_S2_tableidxd_goodsyntax", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_tableidxh_goodsyntax : -Hexagon_i32_i32i32i32i32_Intrinsic<"HEXAGON_S2_tableidxh_goodsyntax", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_tableidxw_goodsyntax : -Hexagon_i32_i32i32i32i32_Intrinsic<"HEXAGON_S2_tableidxw_goodsyntax", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S2_togglebit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_togglebit_i", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_togglebit_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_togglebit_r">; - -def int_hexagon_S2_tstbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_tstbit_i", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_tstbit_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_tstbit_r">; - -def int_hexagon_S2_valignib : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_valignib", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_valignrb : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_valignrb">; - -def int_hexagon_S2_vcnegh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_vcnegh">; - -def int_hexagon_S2_vcrotate : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_vcrotate">; - -def int_hexagon_S2_vrcnegh : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vrcnegh">; - -def int_hexagon_S2_vrndpackwh : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vrndpackwh">; - -def int_hexagon_S2_vrndpackwhs : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vrndpackwhs">; - -def int_hexagon_S2_vsathb : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vsathb">; - -def int_hexagon_S2_vsathb_nopack : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_vsathb_nopack">; - -def int_hexagon_S2_vsathub : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vsathub">; - -def int_hexagon_S2_vsathub_nopack : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_vsathub_nopack">; - -def int_hexagon_S2_vsatwh : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vsatwh">; - -def int_hexagon_S2_vsatwh_nopack : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_vsatwh_nopack">; - -def int_hexagon_S2_vsatwuh : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vsatwuh">; - -def int_hexagon_S2_vsatwuh_nopack : -Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_vsatwuh_nopack">; - -def int_hexagon_S2_vsplatrb : -Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_vsplatrb">; - -def int_hexagon_S2_vsplatrh : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vsplatrh">; - -def int_hexagon_S2_vspliceib : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vspliceib", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S2_vsplicerb : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vsplicerb">; - -def int_hexagon_S2_vsxtbh : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vsxtbh">; - -def int_hexagon_S2_vsxthw : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vsxthw">; - -def int_hexagon_S2_vtrunehb : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vtrunehb">; - -def int_hexagon_S2_vtrunewh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_vtrunewh">; - -def int_hexagon_S2_vtrunohb : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vtrunohb">; - -def int_hexagon_S2_vtrunowh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_vtrunowh">; - -def int_hexagon_S2_vzxtbh : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vzxtbh">; - -def int_hexagon_S2_vzxthw : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vzxthw">; - -def int_hexagon_S4_addaddi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addaddi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_addi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_asl_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_addi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_lsr_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_andi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_asl_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_andi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_lsr_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_clbaddi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_clbaddi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_clbpaddi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S4_clbpaddi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_clbpnorm : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S4_clbpnorm">; - -def int_hexagon_S4_extract : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_extract", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_extract_rp : -Hexagon_i32_i32i64_Intrinsic<"HEXAGON_S4_extract_rp">; - -def int_hexagon_S4_extractp : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_extractp", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_extractp_rp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_extractp_rp">; - -def int_hexagon_S4_lsli : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_lsli", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_ntstbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_ntstbit_i", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_ntstbit_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_ntstbit_r">; - -def int_hexagon_S4_or_andi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_or_andix : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andix", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_or_ori : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_ori", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_ori_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_asl_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_ori_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_lsr_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_parity : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_parity">; - -def int_hexagon_S4_subaddi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subaddi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_subi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_asl_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_subi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_lsr_ri", [IntrNoMem, ImmArg>, ImmArg>]>; - -def int_hexagon_S4_vrcrotate : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_vrcrotate_acc : -Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S4_vxaddsubh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxaddsubh">; - -def int_hexagon_S4_vxaddsubhr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxaddsubhr">; - -def int_hexagon_S4_vxaddsubw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxaddsubw">; - -def int_hexagon_S4_vxsubaddh : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxsubaddh">; - -def int_hexagon_S4_vxsubaddhr : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxsubaddhr">; - -def int_hexagon_S4_vxsubaddw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxsubaddw">; - -def int_hexagon_S5_asrhub_rnd_sat_goodsyntax : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_rnd_sat_goodsyntax", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S5_asrhub_sat : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_sat", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S5_popcountp : -Hexagon_i32_i64_Intrinsic<"HEXAGON_S5_popcountp">; - -def int_hexagon_S5_vasrhrnd_goodsyntax : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S5_vasrhrnd_goodsyntax", [IntrNoMem, ImmArg>]>; - -def int_hexagon_Y2_dccleana : -Hexagon__ptr_Intrinsic<"HEXAGON_Y2_dccleana", []>; - -def int_hexagon_Y2_dccleaninva : -Hexagon__ptr_Intrinsic<"HEXAGON_Y2_dccleaninva", []>; - -def int_hexagon_Y2_dcfetch : -Hexagon__ptr_Intrinsic<"HEXAGON_Y2_dcfetch", []>; - -def int_hexagon_Y2_dcinva : -Hexagon__ptr_Intrinsic<"HEXAGON_Y2_dcinva", []>; - -def int_hexagon_Y2_dczeroa : -Hexagon__ptr_Intrinsic<"HEXAGON_Y2_dczeroa", []>; - -def int_hexagon_Y4_l2fetch : -Hexagon__ptri32_Intrinsic<"HEXAGON_Y4_l2fetch", []>; - -def int_hexagon_Y5_l2fetch : -Hexagon__ptri64_Intrinsic<"HEXAGON_Y5_l2fetch", []>; - -// V60 Scalar Instructions. - -def int_hexagon_S6_rol_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S6_rol_i_p", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_xacc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S6_rol_i_r", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_and", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_nac", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_or", [IntrNoMem, ImmArg>]>; - -def int_hexagon_S6_rol_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_xacc", [IntrNoMem, ImmArg>]>; - -// V62 Scalar Instructions. - -def int_hexagon_M6_vabsdiffb : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M6_vabsdiffb">; - -def int_hexagon_M6_vabsdiffub : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M6_vabsdiffub">; - -def int_hexagon_S6_vsplatrbp : -Hexagon_i64_i32_Intrinsic<"HEXAGON_S6_vsplatrbp">; - -def int_hexagon_S6_vtrunehb_ppp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S6_vtrunehb_ppp">; - -def int_hexagon_S6_vtrunohb_ppp : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S6_vtrunohb_ppp">; - -// V65 Scalar Instructions. - -def int_hexagon_A6_vcmpbeq_notany : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A6_vcmpbeq_notany">; - -// V66 Scalar Instructions. - -def int_hexagon_F2_dfadd : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfadd", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfsub : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfsub", [IntrNoMem, Throws]>; - -def int_hexagon_M2_mnaci : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mnaci">; - -def int_hexagon_S2_mask : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_mask", [IntrNoMem, ImmArg>, ImmArg>]>; - -// V67 Scalar Instructions. - -def int_hexagon_A7_clip : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A7_clip", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A7_croundd_ri : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_A7_croundd_ri", [IntrNoMem, ImmArg>]>; - -def int_hexagon_A7_croundd_rr : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_A7_croundd_rr">; - -def int_hexagon_A7_vclip : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_A7_vclip", [IntrNoMem, ImmArg>]>; - -def int_hexagon_F2_dfmax : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfmax", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfmin : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfmin", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfmpyfix : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfmpyfix", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfmpyhh : -Hexagon_double_doubledoubledouble_Intrinsic<"HEXAGON_F2_dfmpyhh", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfmpylh : -Hexagon_double_doubledoubledouble_Intrinsic<"HEXAGON_F2_dfmpylh", [IntrNoMem, Throws]>; - -def int_hexagon_F2_dfmpyll : -Hexagon_double_doubledouble_Intrinsic<"HEXAGON_F2_dfmpyll", [IntrNoMem, Throws]>; - -def int_hexagon_M7_dcmpyiw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M7_dcmpyiw">; - -def int_hexagon_M7_dcmpyiw_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M7_dcmpyiw_acc">; - -def int_hexagon_M7_dcmpyiwc : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M7_dcmpyiwc">; - -def int_hexagon_M7_dcmpyiwc_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M7_dcmpyiwc_acc">; - -def int_hexagon_M7_dcmpyrw : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M7_dcmpyrw">; - -def int_hexagon_M7_dcmpyrw_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M7_dcmpyrw_acc">; - -def int_hexagon_M7_dcmpyrwc : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M7_dcmpyrwc">; - -def int_hexagon_M7_dcmpyrwc_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M7_dcmpyrwc_acc">; - -def int_hexagon_M7_vdmpy : -Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M7_vdmpy">; - -def int_hexagon_M7_vdmpy_acc : -Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M7_vdmpy_acc">; - -def int_hexagon_M7_wcmpyiw : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyiw">; - -def int_hexagon_M7_wcmpyiw_rnd : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyiw_rnd">; - -def int_hexagon_M7_wcmpyiwc : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyiwc">; - -def int_hexagon_M7_wcmpyiwc_rnd : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyiwc_rnd">; - -def int_hexagon_M7_wcmpyrw : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyrw">; - -def int_hexagon_M7_wcmpyrw_rnd : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyrw_rnd">; - -def int_hexagon_M7_wcmpyrwc : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyrwc">; - -def int_hexagon_M7_wcmpyrwc_rnd : -Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M7_wcmpyrwc_rnd">; - -// V68 Scalar Instructions. - -def int_hexagon_Y6_dmlink : -Hexagon__ptrptr_Intrinsic<"HEXAGON_Y6_dmlink", [IntrArgMemOnly, IntrHasSideEffects]>; - -def int_hexagon_Y6_dmpause : -Hexagon_i32__Intrinsic<"HEXAGON_Y6_dmpause", [IntrArgMemOnly, IntrHasSideEffects]>; - -def int_hexagon_Y6_dmpoll : -Hexagon_i32__Intrinsic<"HEXAGON_Y6_dmpoll", [IntrArgMemOnly, IntrHasSideEffects]>; - -def int_hexagon_Y6_dmresume : -Hexagon__ptr_Intrinsic<"HEXAGON_Y6_dmresume", [IntrArgMemOnly, IntrHasSideEffects]>; - -def int_hexagon_Y6_dmstart : -Hexagon__ptr_Intrinsic<"HEXAGON_Y6_dmstart", [IntrArgMemOnly, IntrHasSideEffects]>; - -def int_hexagon_Y6_dmwait : -Hexagon_i32__Intrinsic<"HEXAGON_Y6_dmwait", [IntrArgMemOnly, IntrHasSideEffects]>; - -// V60 HVX Instructions. - -def int_hexagon_V6_extractw : -Hexagon_i32_v16i32i32_Intrinsic<"HEXAGON_V6_extractw">; - -def int_hexagon_V6_extractw_128B : -Hexagon_i32_v32i32i32_Intrinsic<"HEXAGON_V6_extractw_128B">; - -def int_hexagon_V6_hi : -Hexagon_v16i32_v32i32_Intrinsic<"HEXAGON_V6_hi">; - -def int_hexagon_V6_hi_128B : -Hexagon_v32i32_v64i32_Intrinsic<"HEXAGON_V6_hi_128B">; - -def int_hexagon_V6_lo : -Hexagon_v16i32_v32i32_Intrinsic<"HEXAGON_V6_lo">; - -def int_hexagon_V6_lo_128B : -Hexagon_v32i32_v64i32_Intrinsic<"HEXAGON_V6_lo_128B">; - -def int_hexagon_V6_lvsplatw : -Hexagon_v16i32_i32_Intrinsic<"HEXAGON_V6_lvsplatw">; - -def int_hexagon_V6_lvsplatw_128B : -Hexagon_v32i32_i32_Intrinsic<"HEXAGON_V6_lvsplatw_128B">; - -def int_hexagon_V6_pred_and : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_pred_and">; - -def int_hexagon_V6_pred_and_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_pred_and_128B">; - -def int_hexagon_V6_pred_and_n : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_pred_and_n">; - -def int_hexagon_V6_pred_and_n_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_pred_and_n_128B">; - -def int_hexagon_V6_pred_not : -Hexagon_v64i1_v64i1_Intrinsic<"HEXAGON_V6_pred_not">; - -def int_hexagon_V6_pred_not_128B : -Hexagon_v128i1_v128i1_Intrinsic<"HEXAGON_V6_pred_not_128B">; - -def int_hexagon_V6_pred_or : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_pred_or">; - -def int_hexagon_V6_pred_or_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_pred_or_128B">; - -def int_hexagon_V6_pred_or_n : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_pred_or_n">; - -def int_hexagon_V6_pred_or_n_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_pred_or_n_128B">; - -def int_hexagon_V6_pred_scalar2 : -Hexagon_v64i1_i32_Intrinsic<"HEXAGON_V6_pred_scalar2">; - -def int_hexagon_V6_pred_scalar2_128B : -Hexagon_v128i1_i32_Intrinsic<"HEXAGON_V6_pred_scalar2_128B">; - -def int_hexagon_V6_pred_xor : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_pred_xor">; - -def int_hexagon_V6_pred_xor_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_pred_xor_128B">; - -def int_hexagon_V6_vS32b_nqpred_ai : -Hexagon__v64i1ptrv16i32_Intrinsic<"HEXAGON_V6_vS32b_nqpred_ai", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_nqpred_ai_128B : -Hexagon__v128i1ptrv32i32_Intrinsic<"HEXAGON_V6_vS32b_nqpred_ai_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_nt_nqpred_ai : -Hexagon__v64i1ptrv16i32_Intrinsic<"HEXAGON_V6_vS32b_nt_nqpred_ai", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_nt_nqpred_ai_128B : -Hexagon__v128i1ptrv32i32_Intrinsic<"HEXAGON_V6_vS32b_nt_nqpred_ai_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_nt_qpred_ai : -Hexagon__v64i1ptrv16i32_Intrinsic<"HEXAGON_V6_vS32b_nt_qpred_ai", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_nt_qpred_ai_128B : -Hexagon__v128i1ptrv32i32_Intrinsic<"HEXAGON_V6_vS32b_nt_qpred_ai_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_qpred_ai : -Hexagon__v64i1ptrv16i32_Intrinsic<"HEXAGON_V6_vS32b_qpred_ai", [IntrWriteMem]>; - -def int_hexagon_V6_vS32b_qpred_ai_128B : -Hexagon__v128i1ptrv32i32_Intrinsic<"HEXAGON_V6_vS32b_qpred_ai_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vabsdiffh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vabsdiffh">; - -def int_hexagon_V6_vabsdiffh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vabsdiffh_128B">; - -def int_hexagon_V6_vabsdiffub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vabsdiffub">; - -def int_hexagon_V6_vabsdiffub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vabsdiffub_128B">; - -def int_hexagon_V6_vabsdiffuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vabsdiffuh">; - -def int_hexagon_V6_vabsdiffuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vabsdiffuh_128B">; - -def int_hexagon_V6_vabsdiffw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vabsdiffw">; - -def int_hexagon_V6_vabsdiffw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vabsdiffw_128B">; - -def int_hexagon_V6_vabsh : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsh">; - -def int_hexagon_V6_vabsh_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsh_128B">; - -def int_hexagon_V6_vabsh_sat : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsh_sat">; - -def int_hexagon_V6_vabsh_sat_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsh_sat_128B">; - -def int_hexagon_V6_vabsw : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsw">; - -def int_hexagon_V6_vabsw_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsw_128B">; - -def int_hexagon_V6_vabsw_sat : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsw_sat">; - -def int_hexagon_V6_vabsw_sat_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsw_sat_128B">; - -def int_hexagon_V6_vaddb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddb">; - -def int_hexagon_V6_vaddb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddb_128B">; - -def int_hexagon_V6_vaddb_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddb_dv">; - -def int_hexagon_V6_vaddb_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddb_dv_128B">; - -def int_hexagon_V6_vaddbnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddbnq">; - -def int_hexagon_V6_vaddbnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddbnq_128B">; - -def int_hexagon_V6_vaddbq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddbq">; - -def int_hexagon_V6_vaddbq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddbq_128B">; - -def int_hexagon_V6_vaddh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddh">; - -def int_hexagon_V6_vaddh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddh_128B">; - -def int_hexagon_V6_vaddh_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddh_dv">; - -def int_hexagon_V6_vaddh_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddh_dv_128B">; - -def int_hexagon_V6_vaddhnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddhnq">; - -def int_hexagon_V6_vaddhnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhnq_128B">; - -def int_hexagon_V6_vaddhq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddhq">; - -def int_hexagon_V6_vaddhq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhq_128B">; - -def int_hexagon_V6_vaddhsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddhsat">; - -def int_hexagon_V6_vaddhsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhsat_128B">; - -def int_hexagon_V6_vaddhsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhsat_dv">; - -def int_hexagon_V6_vaddhsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddhsat_dv_128B">; - -def int_hexagon_V6_vaddhw : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddhw">; - -def int_hexagon_V6_vaddhw_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhw_128B">; - -def int_hexagon_V6_vaddubh : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddubh">; - -def int_hexagon_V6_vaddubh_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddubh_128B">; - -def int_hexagon_V6_vaddubsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddubsat">; - -def int_hexagon_V6_vaddubsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddubsat_128B">; - -def int_hexagon_V6_vaddubsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddubsat_dv">; - -def int_hexagon_V6_vaddubsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddubsat_dv_128B">; - -def int_hexagon_V6_vadduhsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadduhsat">; - -def int_hexagon_V6_vadduhsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduhsat_128B">; - -def int_hexagon_V6_vadduhsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduhsat_dv">; - -def int_hexagon_V6_vadduhsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vadduhsat_dv_128B">; - -def int_hexagon_V6_vadduhw : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadduhw">; - -def int_hexagon_V6_vadduhw_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduhw_128B">; - -def int_hexagon_V6_vaddw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddw">; - -def int_hexagon_V6_vaddw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddw_128B">; - -def int_hexagon_V6_vaddw_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddw_dv">; - -def int_hexagon_V6_vaddw_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddw_dv_128B">; - -def int_hexagon_V6_vaddwnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddwnq">; - -def int_hexagon_V6_vaddwnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddwnq_128B">; - -def int_hexagon_V6_vaddwq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddwq">; - -def int_hexagon_V6_vaddwq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddwq_128B">; - -def int_hexagon_V6_vaddwsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddwsat">; - -def int_hexagon_V6_vaddwsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddwsat_128B">; - -def int_hexagon_V6_vaddwsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddwsat_dv">; - -def int_hexagon_V6_vaddwsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddwsat_dv_128B">; - -def int_hexagon_V6_valignb : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_valignb">; - -def int_hexagon_V6_valignb_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_valignb_128B">; - -def int_hexagon_V6_valignbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_valignbi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_valignbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_valignbi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vand : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vand">; - -def int_hexagon_V6_vand_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vand_128B">; - -def int_hexagon_V6_vandqrt : -Hexagon_v16i32_v64i1i32_Intrinsic<"HEXAGON_V6_vandqrt">; - -def int_hexagon_V6_vandqrt_128B : -Hexagon_v32i32_v128i1i32_Intrinsic<"HEXAGON_V6_vandqrt_128B">; - -def int_hexagon_V6_vandqrt_acc : -Hexagon_v16i32_v16i32v64i1i32_Intrinsic<"HEXAGON_V6_vandqrt_acc">; - -def int_hexagon_V6_vandqrt_acc_128B : -Hexagon_v32i32_v32i32v128i1i32_Intrinsic<"HEXAGON_V6_vandqrt_acc_128B">; - -def int_hexagon_V6_vandvrt : -Hexagon_v64i1_v16i32i32_Intrinsic<"HEXAGON_V6_vandvrt">; - -def int_hexagon_V6_vandvrt_128B : -Hexagon_v128i1_v32i32i32_Intrinsic<"HEXAGON_V6_vandvrt_128B">; - -def int_hexagon_V6_vandvrt_acc : -Hexagon_v64i1_v64i1v16i32i32_Intrinsic<"HEXAGON_V6_vandvrt_acc">; - -def int_hexagon_V6_vandvrt_acc_128B : -Hexagon_v128i1_v128i1v32i32i32_Intrinsic<"HEXAGON_V6_vandvrt_acc_128B">; - -def int_hexagon_V6_vaslh : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vaslh">; - -def int_hexagon_V6_vaslh_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vaslh_128B">; - -def int_hexagon_V6_vaslhv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaslhv">; - -def int_hexagon_V6_vaslhv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaslhv_128B">; - -def int_hexagon_V6_vaslw : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vaslw">; - -def int_hexagon_V6_vaslw_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vaslw_128B">; - -def int_hexagon_V6_vaslw_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vaslw_acc">; - -def int_hexagon_V6_vaslw_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vaslw_acc_128B">; - -def int_hexagon_V6_vaslwv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaslwv">; - -def int_hexagon_V6_vaslwv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaslwv_128B">; - -def int_hexagon_V6_vasrh : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vasrh">; - -def int_hexagon_V6_vasrh_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vasrh_128B">; - -def int_hexagon_V6_vasrhbrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrhbrndsat">; - -def int_hexagon_V6_vasrhbrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrhbrndsat_128B">; - -def int_hexagon_V6_vasrhubrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrhubrndsat">; - -def int_hexagon_V6_vasrhubrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrhubrndsat_128B">; - -def int_hexagon_V6_vasrhubsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrhubsat">; - -def int_hexagon_V6_vasrhubsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrhubsat_128B">; - -def int_hexagon_V6_vasrhv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vasrhv">; - -def int_hexagon_V6_vasrhv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vasrhv_128B">; - -def int_hexagon_V6_vasrw : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vasrw">; - -def int_hexagon_V6_vasrw_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vasrw_128B">; - -def int_hexagon_V6_vasrw_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrw_acc">; - -def int_hexagon_V6_vasrw_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrw_acc_128B">; - -def int_hexagon_V6_vasrwh : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrwh">; - -def int_hexagon_V6_vasrwh_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwh_128B">; - -def int_hexagon_V6_vasrwhrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrwhrndsat">; - -def int_hexagon_V6_vasrwhrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwhrndsat_128B">; - -def int_hexagon_V6_vasrwhsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrwhsat">; - -def int_hexagon_V6_vasrwhsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwhsat_128B">; - -def int_hexagon_V6_vasrwuhsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrwuhsat">; - -def int_hexagon_V6_vasrwuhsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwuhsat_128B">; - -def int_hexagon_V6_vasrwv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vasrwv">; - -def int_hexagon_V6_vasrwv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vasrwv_128B">; - -def int_hexagon_V6_vassign : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vassign">; - -def int_hexagon_V6_vassign_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vassign_128B">; - -def int_hexagon_V6_vassignp : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vassignp">; - -def int_hexagon_V6_vassignp_128B : -Hexagon_v64i32_v64i32_Intrinsic<"HEXAGON_V6_vassignp_128B">; - -def int_hexagon_V6_vavgh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgh">; - -def int_hexagon_V6_vavgh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgh_128B">; - -def int_hexagon_V6_vavghrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavghrnd">; - -def int_hexagon_V6_vavghrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavghrnd_128B">; - -def int_hexagon_V6_vavgub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgub">; - -def int_hexagon_V6_vavgub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgub_128B">; - -def int_hexagon_V6_vavgubrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgubrnd">; - -def int_hexagon_V6_vavgubrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgubrnd_128B">; - -def int_hexagon_V6_vavguh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavguh">; - -def int_hexagon_V6_vavguh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavguh_128B">; - -def int_hexagon_V6_vavguhrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavguhrnd">; - -def int_hexagon_V6_vavguhrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavguhrnd_128B">; - -def int_hexagon_V6_vavgw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgw">; - -def int_hexagon_V6_vavgw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgw_128B">; - -def int_hexagon_V6_vavgwrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgwrnd">; - -def int_hexagon_V6_vavgwrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgwrnd_128B">; - -def int_hexagon_V6_vcl0h : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcl0h">; - -def int_hexagon_V6_vcl0h_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcl0h_128B">; - -def int_hexagon_V6_vcl0w : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcl0w">; - -def int_hexagon_V6_vcl0w_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcl0w_128B">; - -def int_hexagon_V6_vcombine : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vcombine">; - -def int_hexagon_V6_vcombine_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vcombine_128B">; - -def int_hexagon_V6_vd0 : -Hexagon_v16i32__Intrinsic<"HEXAGON_V6_vd0">; - -def int_hexagon_V6_vd0_128B : -Hexagon_v32i32__Intrinsic<"HEXAGON_V6_vd0_128B">; - -def int_hexagon_V6_vdealb : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vdealb">; - -def int_hexagon_V6_vdealb_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vdealb_128B">; - -def int_hexagon_V6_vdealb4w : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vdealb4w">; - -def int_hexagon_V6_vdealb4w_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vdealb4w_128B">; - -def int_hexagon_V6_vdealh : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vdealh">; - -def int_hexagon_V6_vdealh_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vdealh_128B">; - -def int_hexagon_V6_vdealvdd : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vdealvdd">; - -def int_hexagon_V6_vdealvdd_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdealvdd_128B">; - -def int_hexagon_V6_vdelta : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vdelta">; - -def int_hexagon_V6_vdelta_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vdelta_128B">; - -def int_hexagon_V6_vdmpybus : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vdmpybus">; - -def int_hexagon_V6_vdmpybus_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_128B">; - -def int_hexagon_V6_vdmpybus_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_acc">; - -def int_hexagon_V6_vdmpybus_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_acc_128B">; - -def int_hexagon_V6_vdmpybus_dv : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_dv">; - -def int_hexagon_V6_vdmpybus_dv_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_dv_128B">; - -def int_hexagon_V6_vdmpybus_dv_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_dv_acc">; - -def int_hexagon_V6_vdmpybus_dv_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vdmpybus_dv_acc_128B">; - -def int_hexagon_V6_vdmpyhb : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb">; - -def int_hexagon_V6_vdmpyhb_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_128B">; - -def int_hexagon_V6_vdmpyhb_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_acc">; - -def int_hexagon_V6_vdmpyhb_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_acc_128B">; - -def int_hexagon_V6_vdmpyhb_dv : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_dv">; - -def int_hexagon_V6_vdmpyhb_dv_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_dv_128B">; - -def int_hexagon_V6_vdmpyhb_dv_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_dv_acc">; - -def int_hexagon_V6_vdmpyhb_dv_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_dv_acc_128B">; - -def int_hexagon_V6_vdmpyhisat : -Hexagon_v16i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhisat">; - -def int_hexagon_V6_vdmpyhisat_128B : -Hexagon_v32i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhisat_128B">; - -def int_hexagon_V6_vdmpyhisat_acc : -Hexagon_v16i32_v16i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhisat_acc">; - -def int_hexagon_V6_vdmpyhisat_acc_128B : -Hexagon_v32i32_v32i32v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhisat_acc_128B">; - -def int_hexagon_V6_vdmpyhsat : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsat">; - -def int_hexagon_V6_vdmpyhsat_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsat_128B">; - -def int_hexagon_V6_vdmpyhsat_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsat_acc">; - -def int_hexagon_V6_vdmpyhsat_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsat_acc_128B">; - -def int_hexagon_V6_vdmpyhsuisat : -Hexagon_v16i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsuisat">; - -def int_hexagon_V6_vdmpyhsuisat_128B : -Hexagon_v32i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsuisat_128B">; - -def int_hexagon_V6_vdmpyhsuisat_acc : -Hexagon_v16i32_v16i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsuisat_acc">; - -def int_hexagon_V6_vdmpyhsuisat_acc_128B : -Hexagon_v32i32_v32i32v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsuisat_acc_128B">; - -def int_hexagon_V6_vdmpyhsusat : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsusat">; - -def int_hexagon_V6_vdmpyhsusat_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsusat_128B">; - -def int_hexagon_V6_vdmpyhsusat_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsusat_acc">; - -def int_hexagon_V6_vdmpyhsusat_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsusat_acc_128B">; - -def int_hexagon_V6_vdmpyhvsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vdmpyhvsat">; - -def int_hexagon_V6_vdmpyhvsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vdmpyhvsat_128B">; - -def int_hexagon_V6_vdmpyhvsat_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vdmpyhvsat_acc">; - -def int_hexagon_V6_vdmpyhvsat_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vdmpyhvsat_acc_128B">; - -def int_hexagon_V6_vdsaduh : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vdsaduh">; - -def int_hexagon_V6_vdsaduh_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdsaduh_128B">; - -def int_hexagon_V6_vdsaduh_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdsaduh_acc">; - -def int_hexagon_V6_vdsaduh_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vdsaduh_acc_128B">; - -def int_hexagon_V6_veqb : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_veqb">; - -def int_hexagon_V6_veqb_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_veqb_128B">; - -def int_hexagon_V6_veqb_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqb_and">; - -def int_hexagon_V6_veqb_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqb_and_128B">; - -def int_hexagon_V6_veqb_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqb_or">; - -def int_hexagon_V6_veqb_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqb_or_128B">; - -def int_hexagon_V6_veqb_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqb_xor">; - -def int_hexagon_V6_veqb_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqb_xor_128B">; - -def int_hexagon_V6_veqh : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_veqh">; - -def int_hexagon_V6_veqh_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_veqh_128B">; - -def int_hexagon_V6_veqh_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqh_and">; - -def int_hexagon_V6_veqh_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqh_and_128B">; - -def int_hexagon_V6_veqh_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqh_or">; - -def int_hexagon_V6_veqh_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqh_or_128B">; - -def int_hexagon_V6_veqh_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqh_xor">; - -def int_hexagon_V6_veqh_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqh_xor_128B">; - -def int_hexagon_V6_veqw : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_veqw">; - -def int_hexagon_V6_veqw_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_veqw_128B">; - -def int_hexagon_V6_veqw_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqw_and">; - -def int_hexagon_V6_veqw_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqw_and_128B">; - -def int_hexagon_V6_veqw_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqw_or">; - -def int_hexagon_V6_veqw_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqw_or_128B">; - -def int_hexagon_V6_veqw_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_veqw_xor">; - -def int_hexagon_V6_veqw_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqw_xor_128B">; - -def int_hexagon_V6_vgtb : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtb">; - -def int_hexagon_V6_vgtb_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtb_128B">; - -def int_hexagon_V6_vgtb_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtb_and">; - -def int_hexagon_V6_vgtb_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtb_and_128B">; - -def int_hexagon_V6_vgtb_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtb_or">; - -def int_hexagon_V6_vgtb_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtb_or_128B">; - -def int_hexagon_V6_vgtb_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtb_xor">; - -def int_hexagon_V6_vgtb_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtb_xor_128B">; - -def int_hexagon_V6_vgth : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgth">; - -def int_hexagon_V6_vgth_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgth_128B">; - -def int_hexagon_V6_vgth_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgth_and">; - -def int_hexagon_V6_vgth_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgth_and_128B">; - -def int_hexagon_V6_vgth_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgth_or">; - -def int_hexagon_V6_vgth_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgth_or_128B">; - -def int_hexagon_V6_vgth_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgth_xor">; - -def int_hexagon_V6_vgth_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgth_xor_128B">; - -def int_hexagon_V6_vgtub : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtub">; - -def int_hexagon_V6_vgtub_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtub_128B">; - -def int_hexagon_V6_vgtub_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtub_and">; - -def int_hexagon_V6_vgtub_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtub_and_128B">; - -def int_hexagon_V6_vgtub_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtub_or">; - -def int_hexagon_V6_vgtub_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtub_or_128B">; - -def int_hexagon_V6_vgtub_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtub_xor">; - -def int_hexagon_V6_vgtub_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtub_xor_128B">; - -def int_hexagon_V6_vgtuh : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuh">; - -def int_hexagon_V6_vgtuh_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuh_128B">; - -def int_hexagon_V6_vgtuh_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuh_and">; - -def int_hexagon_V6_vgtuh_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuh_and_128B">; - -def int_hexagon_V6_vgtuh_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuh_or">; - -def int_hexagon_V6_vgtuh_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuh_or_128B">; - -def int_hexagon_V6_vgtuh_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuh_xor">; - -def int_hexagon_V6_vgtuh_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuh_xor_128B">; - -def int_hexagon_V6_vgtuw : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuw">; - -def int_hexagon_V6_vgtuw_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuw_128B">; - -def int_hexagon_V6_vgtuw_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuw_and">; - -def int_hexagon_V6_vgtuw_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuw_and_128B">; - -def int_hexagon_V6_vgtuw_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuw_or">; - -def int_hexagon_V6_vgtuw_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuw_or_128B">; - -def int_hexagon_V6_vgtuw_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtuw_xor">; - -def int_hexagon_V6_vgtuw_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtuw_xor_128B">; - -def int_hexagon_V6_vgtw : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtw">; - -def int_hexagon_V6_vgtw_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtw_128B">; - -def int_hexagon_V6_vgtw_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtw_and">; - -def int_hexagon_V6_vgtw_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtw_and_128B">; - -def int_hexagon_V6_vgtw_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtw_or">; - -def int_hexagon_V6_vgtw_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtw_or_128B">; - -def int_hexagon_V6_vgtw_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtw_xor">; - -def int_hexagon_V6_vgtw_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtw_xor_128B">; - -def int_hexagon_V6_vinsertwr : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vinsertwr">; - -def int_hexagon_V6_vinsertwr_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vinsertwr_128B">; - -def int_hexagon_V6_vlalignb : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlalignb">; - -def int_hexagon_V6_vlalignb_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlalignb_128B">; - -def int_hexagon_V6_vlalignbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlalignbi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlalignbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlalignbi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlsrh : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vlsrh">; - -def int_hexagon_V6_vlsrh_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vlsrh_128B">; - -def int_hexagon_V6_vlsrhv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vlsrhv">; - -def int_hexagon_V6_vlsrhv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vlsrhv_128B">; - -def int_hexagon_V6_vlsrw : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vlsrw">; - -def int_hexagon_V6_vlsrw_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vlsrw_128B">; - -def int_hexagon_V6_vlsrwv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vlsrwv">; - -def int_hexagon_V6_vlsrwv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vlsrwv_128B">; - -def int_hexagon_V6_vlutvvb : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb">; - -def int_hexagon_V6_vlutvvb_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_128B">; - -def int_hexagon_V6_vlutvvb_oracc : -Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracc">; - -def int_hexagon_V6_vlutvvb_oracc_128B : -Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracc_128B">; - -def int_hexagon_V6_vlutvwh : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh">; - -def int_hexagon_V6_vlutvwh_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_128B">; - -def int_hexagon_V6_vlutvwh_oracc : -Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracc">; - -def int_hexagon_V6_vlutvwh_oracc_128B : -Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracc_128B">; - -def int_hexagon_V6_vmaxh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmaxh">; - -def int_hexagon_V6_vmaxh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmaxh_128B">; - -def int_hexagon_V6_vmaxub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmaxub">; - -def int_hexagon_V6_vmaxub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmaxub_128B">; - -def int_hexagon_V6_vmaxuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmaxuh">; - -def int_hexagon_V6_vmaxuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmaxuh_128B">; - -def int_hexagon_V6_vmaxw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmaxw">; - -def int_hexagon_V6_vmaxw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmaxw_128B">; - -def int_hexagon_V6_vminh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminh">; - -def int_hexagon_V6_vminh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vminh_128B">; - -def int_hexagon_V6_vminub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminub">; - -def int_hexagon_V6_vminub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vminub_128B">; - -def int_hexagon_V6_vminuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminuh">; - -def int_hexagon_V6_vminuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vminuh_128B">; - -def int_hexagon_V6_vminw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminw">; - -def int_hexagon_V6_vminw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vminw_128B">; - -def int_hexagon_V6_vmpabus : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpabus">; - -def int_hexagon_V6_vmpabus_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vmpabus_128B">; - -def int_hexagon_V6_vmpabus_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpabus_acc">; - -def int_hexagon_V6_vmpabus_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vmpabus_acc_128B">; - -def int_hexagon_V6_vmpabusv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpabusv">; - -def int_hexagon_V6_vmpabusv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vmpabusv_128B">; - -def int_hexagon_V6_vmpabuuv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpabuuv">; - -def int_hexagon_V6_vmpabuuv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vmpabuuv_128B">; - -def int_hexagon_V6_vmpahb : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpahb">; - -def int_hexagon_V6_vmpahb_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vmpahb_128B">; - -def int_hexagon_V6_vmpahb_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpahb_acc">; - -def int_hexagon_V6_vmpahb_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vmpahb_acc_128B">; - -def int_hexagon_V6_vmpybus : -Hexagon_v32i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpybus">; - -def int_hexagon_V6_vmpybus_128B : -Hexagon_v64i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpybus_128B">; - -def int_hexagon_V6_vmpybus_acc : -Hexagon_v32i32_v32i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpybus_acc">; - -def int_hexagon_V6_vmpybus_acc_128B : -Hexagon_v64i32_v64i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpybus_acc_128B">; - -def int_hexagon_V6_vmpybusv : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpybusv">; - -def int_hexagon_V6_vmpybusv_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpybusv_128B">; - -def int_hexagon_V6_vmpybusv_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpybusv_acc">; - -def int_hexagon_V6_vmpybusv_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpybusv_acc_128B">; - -def int_hexagon_V6_vmpybv : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpybv">; - -def int_hexagon_V6_vmpybv_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpybv_128B">; - -def int_hexagon_V6_vmpybv_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpybv_acc">; - -def int_hexagon_V6_vmpybv_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpybv_acc_128B">; - -def int_hexagon_V6_vmpyewuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyewuh">; - -def int_hexagon_V6_vmpyewuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyewuh_128B">; - -def int_hexagon_V6_vmpyh : -Hexagon_v32i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyh">; - -def int_hexagon_V6_vmpyh_128B : -Hexagon_v64i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyh_128B">; - -def int_hexagon_V6_vmpyhsat_acc : -Hexagon_v32i32_v32i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyhsat_acc">; - -def int_hexagon_V6_vmpyhsat_acc_128B : -Hexagon_v64i32_v64i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyhsat_acc_128B">; - -def int_hexagon_V6_vmpyhsrs : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyhsrs">; - -def int_hexagon_V6_vmpyhsrs_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyhsrs_128B">; - -def int_hexagon_V6_vmpyhss : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyhss">; - -def int_hexagon_V6_vmpyhss_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyhss_128B">; - -def int_hexagon_V6_vmpyhus : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyhus">; - -def int_hexagon_V6_vmpyhus_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyhus_128B">; - -def int_hexagon_V6_vmpyhus_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyhus_acc">; - -def int_hexagon_V6_vmpyhus_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyhus_acc_128B">; - -def int_hexagon_V6_vmpyhv : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyhv">; - -def int_hexagon_V6_vmpyhv_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyhv_128B">; - -def int_hexagon_V6_vmpyhv_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyhv_acc">; - -def int_hexagon_V6_vmpyhv_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyhv_acc_128B">; - -def int_hexagon_V6_vmpyhvsrs : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyhvsrs">; - -def int_hexagon_V6_vmpyhvsrs_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyhvsrs_128B">; - -def int_hexagon_V6_vmpyieoh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyieoh">; - -def int_hexagon_V6_vmpyieoh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyieoh_128B">; - -def int_hexagon_V6_vmpyiewh_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyiewh_acc">; - -def int_hexagon_V6_vmpyiewh_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyiewh_acc_128B">; - -def int_hexagon_V6_vmpyiewuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyiewuh">; - -def int_hexagon_V6_vmpyiewuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyiewuh_128B">; - -def int_hexagon_V6_vmpyiewuh_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyiewuh_acc">; - -def int_hexagon_V6_vmpyiewuh_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyiewuh_acc_128B">; - -def int_hexagon_V6_vmpyih : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyih">; - -def int_hexagon_V6_vmpyih_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyih_128B">; - -def int_hexagon_V6_vmpyih_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyih_acc">; - -def int_hexagon_V6_vmpyih_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyih_acc_128B">; - -def int_hexagon_V6_vmpyihb : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyihb">; - -def int_hexagon_V6_vmpyihb_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyihb_128B">; - -def int_hexagon_V6_vmpyihb_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyihb_acc">; - -def int_hexagon_V6_vmpyihb_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyihb_acc_128B">; - -def int_hexagon_V6_vmpyiowh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyiowh">; - -def int_hexagon_V6_vmpyiowh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyiowh_128B">; - -def int_hexagon_V6_vmpyiwb : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwb">; - -def int_hexagon_V6_vmpyiwb_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwb_128B">; - -def int_hexagon_V6_vmpyiwb_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwb_acc">; - -def int_hexagon_V6_vmpyiwb_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwb_acc_128B">; - -def int_hexagon_V6_vmpyiwh : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwh">; - -def int_hexagon_V6_vmpyiwh_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwh_128B">; - -def int_hexagon_V6_vmpyiwh_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwh_acc">; - -def int_hexagon_V6_vmpyiwh_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwh_acc_128B">; - -def int_hexagon_V6_vmpyowh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyowh">; - -def int_hexagon_V6_vmpyowh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyowh_128B">; - -def int_hexagon_V6_vmpyowh_rnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyowh_rnd">; - -def int_hexagon_V6_vmpyowh_rnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyowh_rnd_128B">; - -def int_hexagon_V6_vmpyowh_rnd_sacc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyowh_rnd_sacc">; - -def int_hexagon_V6_vmpyowh_rnd_sacc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyowh_rnd_sacc_128B">; - -def int_hexagon_V6_vmpyowh_sacc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyowh_sacc">; - -def int_hexagon_V6_vmpyowh_sacc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyowh_sacc_128B">; - -def int_hexagon_V6_vmpyub : -Hexagon_v32i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyub">; - -def int_hexagon_V6_vmpyub_128B : -Hexagon_v64i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyub_128B">; - -def int_hexagon_V6_vmpyub_acc : -Hexagon_v32i32_v32i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyub_acc">; - -def int_hexagon_V6_vmpyub_acc_128B : -Hexagon_v64i32_v64i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyub_acc_128B">; - -def int_hexagon_V6_vmpyubv : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyubv">; - -def int_hexagon_V6_vmpyubv_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyubv_128B">; - -def int_hexagon_V6_vmpyubv_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyubv_acc">; - -def int_hexagon_V6_vmpyubv_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyubv_acc_128B">; - -def int_hexagon_V6_vmpyuh : -Hexagon_v32i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyuh">; - -def int_hexagon_V6_vmpyuh_128B : -Hexagon_v64i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyuh_128B">; - -def int_hexagon_V6_vmpyuh_acc : -Hexagon_v32i32_v32i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyuh_acc">; - -def int_hexagon_V6_vmpyuh_acc_128B : -Hexagon_v64i32_v64i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyuh_acc_128B">; - -def int_hexagon_V6_vmpyuhv : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyuhv">; - -def int_hexagon_V6_vmpyuhv_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyuhv_128B">; - -def int_hexagon_V6_vmpyuhv_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyuhv_acc">; - -def int_hexagon_V6_vmpyuhv_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyuhv_acc_128B">; - -def int_hexagon_V6_vmux : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vmux">; - -def int_hexagon_V6_vmux_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vmux_128B">; - -def int_hexagon_V6_vnavgh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vnavgh">; - -def int_hexagon_V6_vnavgh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vnavgh_128B">; - -def int_hexagon_V6_vnavgub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vnavgub">; - -def int_hexagon_V6_vnavgub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vnavgub_128B">; - -def int_hexagon_V6_vnavgw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vnavgw">; - -def int_hexagon_V6_vnavgw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vnavgw_128B">; - -def int_hexagon_V6_vnormamth : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vnormamth">; - -def int_hexagon_V6_vnormamth_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vnormamth_128B">; - -def int_hexagon_V6_vnormamtw : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vnormamtw">; - -def int_hexagon_V6_vnormamtw_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vnormamtw_128B">; - -def int_hexagon_V6_vnot : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vnot">; - -def int_hexagon_V6_vnot_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vnot_128B">; - -def int_hexagon_V6_vor : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vor">; - -def int_hexagon_V6_vor_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vor_128B">; - -def int_hexagon_V6_vpackeb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackeb">; - -def int_hexagon_V6_vpackeb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackeb_128B">; - -def int_hexagon_V6_vpackeh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackeh">; - -def int_hexagon_V6_vpackeh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackeh_128B">; - -def int_hexagon_V6_vpackhb_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackhb_sat">; - -def int_hexagon_V6_vpackhb_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackhb_sat_128B">; - -def int_hexagon_V6_vpackhub_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackhub_sat">; - -def int_hexagon_V6_vpackhub_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackhub_sat_128B">; - -def int_hexagon_V6_vpackob : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackob">; - -def int_hexagon_V6_vpackob_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackob_128B">; - -def int_hexagon_V6_vpackoh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackoh">; - -def int_hexagon_V6_vpackoh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackoh_128B">; - -def int_hexagon_V6_vpackwh_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackwh_sat">; - -def int_hexagon_V6_vpackwh_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackwh_sat_128B">; - -def int_hexagon_V6_vpackwuh_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vpackwuh_sat">; - -def int_hexagon_V6_vpackwuh_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vpackwuh_sat_128B">; - -def int_hexagon_V6_vpopcounth : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vpopcounth">; - -def int_hexagon_V6_vpopcounth_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vpopcounth_128B">; - -def int_hexagon_V6_vrdelta : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrdelta">; - -def int_hexagon_V6_vrdelta_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrdelta_128B">; - -def int_hexagon_V6_vrmpybus : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vrmpybus">; - -def int_hexagon_V6_vrmpybus_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vrmpybus_128B">; - -def int_hexagon_V6_vrmpybus_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vrmpybus_acc">; - -def int_hexagon_V6_vrmpybus_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vrmpybus_acc_128B">; - -def int_hexagon_V6_vrmpybusi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpybusi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpybusi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpybusi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpybusv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpybusv">; - -def int_hexagon_V6_vrmpybusv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpybusv_128B">; - -def int_hexagon_V6_vrmpybusv_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpybusv_acc">; - -def int_hexagon_V6_vrmpybusv_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpybusv_acc_128B">; - -def int_hexagon_V6_vrmpybv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpybv">; - -def int_hexagon_V6_vrmpybv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpybv_128B">; - -def int_hexagon_V6_vrmpybv_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpybv_acc">; - -def int_hexagon_V6_vrmpybv_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpybv_acc_128B">; - -def int_hexagon_V6_vrmpyub : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vrmpyub">; - -def int_hexagon_V6_vrmpyub_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vrmpyub_128B">; - -def int_hexagon_V6_vrmpyub_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vrmpyub_acc">; - -def int_hexagon_V6_vrmpyub_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vrmpyub_acc_128B">; - -def int_hexagon_V6_vrmpyubi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpyubi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpyubi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpyubi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrmpyubv : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpyubv">; - -def int_hexagon_V6_vrmpyubv_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpyubv_128B">; - -def int_hexagon_V6_vrmpyubv_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vrmpyubv_acc">; - -def int_hexagon_V6_vrmpyubv_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vrmpyubv_acc_128B">; - -def int_hexagon_V6_vror : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vror">; - -def int_hexagon_V6_vror_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vror_128B">; - -def int_hexagon_V6_vroundhb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vroundhb">; - -def int_hexagon_V6_vroundhb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vroundhb_128B">; - -def int_hexagon_V6_vroundhub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vroundhub">; - -def int_hexagon_V6_vroundhub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vroundhub_128B">; - -def int_hexagon_V6_vroundwh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vroundwh">; - -def int_hexagon_V6_vroundwh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vroundwh_128B">; - -def int_hexagon_V6_vroundwuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vroundwuh">; - -def int_hexagon_V6_vroundwuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vroundwuh_128B">; - -def int_hexagon_V6_vrsadubi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrsadubi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrsadubi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vrsadubi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vsathub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsathub">; - -def int_hexagon_V6_vsathub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsathub_128B">; - -def int_hexagon_V6_vsatwh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsatwh">; - -def int_hexagon_V6_vsatwh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsatwh_128B">; - -def int_hexagon_V6_vsb : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vsb">; - -def int_hexagon_V6_vsb_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vsb_128B">; - -def int_hexagon_V6_vsh : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vsh">; - -def int_hexagon_V6_vsh_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vsh_128B">; - -def int_hexagon_V6_vshufeh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshufeh">; - -def int_hexagon_V6_vshufeh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshufeh_128B">; - -def int_hexagon_V6_vshuffb : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vshuffb">; - -def int_hexagon_V6_vshuffb_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vshuffb_128B">; - -def int_hexagon_V6_vshuffeb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshuffeb">; - -def int_hexagon_V6_vshuffeb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshuffeb_128B">; - -def int_hexagon_V6_vshuffh : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vshuffh">; - -def int_hexagon_V6_vshuffh_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vshuffh_128B">; - -def int_hexagon_V6_vshuffob : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshuffob">; - -def int_hexagon_V6_vshuffob_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshuffob_128B">; - -def int_hexagon_V6_vshuffvdd : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vshuffvdd">; - -def int_hexagon_V6_vshuffvdd_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vshuffvdd_128B">; - -def int_hexagon_V6_vshufoeb : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshufoeb">; - -def int_hexagon_V6_vshufoeb_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshufoeb_128B">; - -def int_hexagon_V6_vshufoeh : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshufoeh">; - -def int_hexagon_V6_vshufoeh_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshufoeh_128B">; - -def int_hexagon_V6_vshufoh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshufoh">; - -def int_hexagon_V6_vshufoh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vshufoh_128B">; - -def int_hexagon_V6_vsubb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubb">; - -def int_hexagon_V6_vsubb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubb_128B">; - -def int_hexagon_V6_vsubb_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubb_dv">; - -def int_hexagon_V6_vsubb_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubb_dv_128B">; - -def int_hexagon_V6_vsubbnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubbnq">; - -def int_hexagon_V6_vsubbnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubbnq_128B">; - -def int_hexagon_V6_vsubbq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubbq">; - -def int_hexagon_V6_vsubbq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubbq_128B">; - -def int_hexagon_V6_vsubh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubh">; - -def int_hexagon_V6_vsubh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubh_128B">; - -def int_hexagon_V6_vsubh_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubh_dv">; - -def int_hexagon_V6_vsubh_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubh_dv_128B">; - -def int_hexagon_V6_vsubhnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubhnq">; - -def int_hexagon_V6_vsubhnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhnq_128B">; - -def int_hexagon_V6_vsubhq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubhq">; - -def int_hexagon_V6_vsubhq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhq_128B">; - -def int_hexagon_V6_vsubhsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubhsat">; - -def int_hexagon_V6_vsubhsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhsat_128B">; - -def int_hexagon_V6_vsubhsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhsat_dv">; - -def int_hexagon_V6_vsubhsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubhsat_dv_128B">; - -def int_hexagon_V6_vsubhw : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubhw">; - -def int_hexagon_V6_vsubhw_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhw_128B">; - -def int_hexagon_V6_vsububh : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsububh">; - -def int_hexagon_V6_vsububh_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsububh_128B">; - -def int_hexagon_V6_vsububsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsububsat">; - -def int_hexagon_V6_vsububsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsububsat_128B">; - -def int_hexagon_V6_vsububsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsububsat_dv">; - -def int_hexagon_V6_vsububsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsububsat_dv_128B">; - -def int_hexagon_V6_vsubuhsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubuhsat">; - -def int_hexagon_V6_vsubuhsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuhsat_128B">; - -def int_hexagon_V6_vsubuhsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuhsat_dv">; - -def int_hexagon_V6_vsubuhsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubuhsat_dv_128B">; - -def int_hexagon_V6_vsubuhw : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubuhw">; - -def int_hexagon_V6_vsubuhw_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuhw_128B">; - -def int_hexagon_V6_vsubw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubw">; - -def int_hexagon_V6_vsubw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubw_128B">; - -def int_hexagon_V6_vsubw_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubw_dv">; - -def int_hexagon_V6_vsubw_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubw_dv_128B">; - -def int_hexagon_V6_vsubwnq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubwnq">; - -def int_hexagon_V6_vsubwnq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubwnq_128B">; - -def int_hexagon_V6_vsubwq : -Hexagon_v16i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubwq">; - -def int_hexagon_V6_vsubwq_128B : -Hexagon_v32i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubwq_128B">; - -def int_hexagon_V6_vsubwsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubwsat">; - -def int_hexagon_V6_vsubwsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubwsat_128B">; - -def int_hexagon_V6_vsubwsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubwsat_dv">; - -def int_hexagon_V6_vsubwsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubwsat_dv_128B">; - -def int_hexagon_V6_vswap : -Hexagon_v32i32_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vswap">; - -def int_hexagon_V6_vswap_128B : -Hexagon_v64i32_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vswap_128B">; - -def int_hexagon_V6_vtmpyb : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vtmpyb">; - -def int_hexagon_V6_vtmpyb_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vtmpyb_128B">; - -def int_hexagon_V6_vtmpyb_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vtmpyb_acc">; - -def int_hexagon_V6_vtmpyb_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vtmpyb_acc_128B">; - -def int_hexagon_V6_vtmpybus : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vtmpybus">; - -def int_hexagon_V6_vtmpybus_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vtmpybus_128B">; - -def int_hexagon_V6_vtmpybus_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vtmpybus_acc">; - -def int_hexagon_V6_vtmpybus_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vtmpybus_acc_128B">; - -def int_hexagon_V6_vtmpyhb : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vtmpyhb">; - -def int_hexagon_V6_vtmpyhb_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vtmpyhb_128B">; - -def int_hexagon_V6_vtmpyhb_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vtmpyhb_acc">; - -def int_hexagon_V6_vtmpyhb_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vtmpyhb_acc_128B">; - -def int_hexagon_V6_vunpackb : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vunpackb">; - -def int_hexagon_V6_vunpackb_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vunpackb_128B">; - -def int_hexagon_V6_vunpackh : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vunpackh">; - -def int_hexagon_V6_vunpackh_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vunpackh_128B">; - -def int_hexagon_V6_vunpackob : -Hexagon_v32i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vunpackob">; - -def int_hexagon_V6_vunpackob_128B : -Hexagon_v64i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vunpackob_128B">; - -def int_hexagon_V6_vunpackoh : -Hexagon_v32i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vunpackoh">; - -def int_hexagon_V6_vunpackoh_128B : -Hexagon_v64i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vunpackoh_128B">; - -def int_hexagon_V6_vunpackub : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vunpackub">; - -def int_hexagon_V6_vunpackub_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vunpackub_128B">; - -def int_hexagon_V6_vunpackuh : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vunpackuh">; - -def int_hexagon_V6_vunpackuh_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vunpackuh_128B">; - -def int_hexagon_V6_vxor : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vxor">; - -def int_hexagon_V6_vxor_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vxor_128B">; - -def int_hexagon_V6_vzb : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vzb">; - -def int_hexagon_V6_vzb_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vzb_128B">; - -def int_hexagon_V6_vzh : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vzh">; - -def int_hexagon_V6_vzh_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vzh_128B">; - -// V62 HVX Instructions. - -def int_hexagon_V6_lvsplatb : -Hexagon_v16i32_i32_Intrinsic<"HEXAGON_V6_lvsplatb">; - -def int_hexagon_V6_lvsplatb_128B : -Hexagon_v32i32_i32_Intrinsic<"HEXAGON_V6_lvsplatb_128B">; - -def int_hexagon_V6_lvsplath : -Hexagon_v16i32_i32_Intrinsic<"HEXAGON_V6_lvsplath">; - -def int_hexagon_V6_lvsplath_128B : -Hexagon_v32i32_i32_Intrinsic<"HEXAGON_V6_lvsplath_128B">; - -def int_hexagon_V6_pred_scalar2v2 : -Hexagon_v64i1_i32_Intrinsic<"HEXAGON_V6_pred_scalar2v2">; - -def int_hexagon_V6_pred_scalar2v2_128B : -Hexagon_v128i1_i32_Intrinsic<"HEXAGON_V6_pred_scalar2v2_128B">; - -def int_hexagon_V6_shuffeqh : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_shuffeqh">; - -def int_hexagon_V6_shuffeqh_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_shuffeqh_128B">; - -def int_hexagon_V6_shuffeqw : -Hexagon_v64i1_v64i1v64i1_Intrinsic<"HEXAGON_V6_shuffeqw">; - -def int_hexagon_V6_shuffeqw_128B : -Hexagon_v128i1_v128i1v128i1_Intrinsic<"HEXAGON_V6_shuffeqw_128B">; - -def int_hexagon_V6_vaddbsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddbsat">; - -def int_hexagon_V6_vaddbsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddbsat_128B">; - -def int_hexagon_V6_vaddbsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddbsat_dv">; - -def int_hexagon_V6_vaddbsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddbsat_dv_128B">; - -def int_hexagon_V6_vaddcarry : -Hexagon_custom_v16i32v64i1_v16i32v16i32v64i1_Intrinsic; - -def int_hexagon_V6_vaddcarry_128B : -Hexagon_custom_v32i32v128i1_v32i32v32i32v128i1_Intrinsic_128B; - -def int_hexagon_V6_vaddclbh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddclbh">; - -def int_hexagon_V6_vaddclbh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddclbh_128B">; - -def int_hexagon_V6_vaddclbw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddclbw">; - -def int_hexagon_V6_vaddclbw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddclbw_128B">; - -def int_hexagon_V6_vaddhw_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddhw_acc">; - -def int_hexagon_V6_vaddhw_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddhw_acc_128B">; - -def int_hexagon_V6_vaddubh_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddubh_acc">; - -def int_hexagon_V6_vaddubh_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddubh_acc_128B">; - -def int_hexagon_V6_vaddububb_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddububb_sat">; - -def int_hexagon_V6_vaddububb_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddububb_sat_128B">; - -def int_hexagon_V6_vadduhw_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vadduhw_acc">; - -def int_hexagon_V6_vadduhw_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduhw_acc_128B">; - -def int_hexagon_V6_vadduwsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadduwsat">; - -def int_hexagon_V6_vadduwsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduwsat_128B">; - -def int_hexagon_V6_vadduwsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadduwsat_dv">; - -def int_hexagon_V6_vadduwsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vadduwsat_dv_128B">; - -def int_hexagon_V6_vandnqrt : -Hexagon_v16i32_v64i1i32_Intrinsic<"HEXAGON_V6_vandnqrt">; - -def int_hexagon_V6_vandnqrt_128B : -Hexagon_v32i32_v128i1i32_Intrinsic<"HEXAGON_V6_vandnqrt_128B">; - -def int_hexagon_V6_vandnqrt_acc : -Hexagon_v16i32_v16i32v64i1i32_Intrinsic<"HEXAGON_V6_vandnqrt_acc">; - -def int_hexagon_V6_vandnqrt_acc_128B : -Hexagon_v32i32_v32i32v128i1i32_Intrinsic<"HEXAGON_V6_vandnqrt_acc_128B">; - -def int_hexagon_V6_vandvnqv : -Hexagon_v16i32_v64i1v16i32_Intrinsic<"HEXAGON_V6_vandvnqv">; - -def int_hexagon_V6_vandvnqv_128B : -Hexagon_v32i32_v128i1v32i32_Intrinsic<"HEXAGON_V6_vandvnqv_128B">; - -def int_hexagon_V6_vandvqv : -Hexagon_v16i32_v64i1v16i32_Intrinsic<"HEXAGON_V6_vandvqv">; - -def int_hexagon_V6_vandvqv_128B : -Hexagon_v32i32_v128i1v32i32_Intrinsic<"HEXAGON_V6_vandvqv_128B">; - -def int_hexagon_V6_vasrhbsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrhbsat">; - -def int_hexagon_V6_vasrhbsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrhbsat_128B">; - -def int_hexagon_V6_vasruwuhrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasruwuhrndsat">; - -def int_hexagon_V6_vasruwuhrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasruwuhrndsat_128B">; - -def int_hexagon_V6_vasrwuhrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrwuhrndsat">; - -def int_hexagon_V6_vasrwuhrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwuhrndsat_128B">; - -def int_hexagon_V6_vlsrb : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vlsrb">; - -def int_hexagon_V6_vlsrb_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vlsrb_128B">; - -def int_hexagon_V6_vlutvvb_nm : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_nm">; - -def int_hexagon_V6_vlutvvb_nm_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_nm_128B">; - -def int_hexagon_V6_vlutvvb_oracci : -Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvvb_oracci_128B : -Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvvbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvvbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvwh_nm : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_nm">; - -def int_hexagon_V6_vlutvwh_nm_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_nm_128B">; - -def int_hexagon_V6_vlutvwh_oracci : -Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvwh_oracci_128B : -Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvwhi : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vlutvwhi_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vmaxb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmaxb">; - -def int_hexagon_V6_vmaxb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmaxb_128B">; - -def int_hexagon_V6_vminb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminb">; - -def int_hexagon_V6_vminb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vminb_128B">; - -def int_hexagon_V6_vmpauhb : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpauhb">; - -def int_hexagon_V6_vmpauhb_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vmpauhb_128B">; - -def int_hexagon_V6_vmpauhb_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpauhb_acc">; - -def int_hexagon_V6_vmpauhb_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vmpauhb_acc_128B">; - -def int_hexagon_V6_vmpyewuh_64 : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyewuh_64">; - -def int_hexagon_V6_vmpyewuh_64_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyewuh_64_128B">; - -def int_hexagon_V6_vmpyiwub : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwub">; - -def int_hexagon_V6_vmpyiwub_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwub_128B">; - -def int_hexagon_V6_vmpyiwub_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyiwub_acc">; - -def int_hexagon_V6_vmpyiwub_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyiwub_acc_128B">; - -def int_hexagon_V6_vmpyowh_64_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc">; - -def int_hexagon_V6_vmpyowh_64_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc_128B">; - -def int_hexagon_V6_vrounduhub : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrounduhub">; - -def int_hexagon_V6_vrounduhub_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrounduhub_128B">; - -def int_hexagon_V6_vrounduwuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrounduwuh">; - -def int_hexagon_V6_vrounduwuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrounduwuh_128B">; - -def int_hexagon_V6_vsatuwuh : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsatuwuh">; - -def int_hexagon_V6_vsatuwuh_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsatuwuh_128B">; - -def int_hexagon_V6_vsubbsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubbsat">; - -def int_hexagon_V6_vsubbsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubbsat_128B">; - -def int_hexagon_V6_vsubbsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubbsat_dv">; - -def int_hexagon_V6_vsubbsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubbsat_dv_128B">; - -def int_hexagon_V6_vsubcarry : -Hexagon_custom_v16i32v64i1_v16i32v16i32v64i1_Intrinsic; - -def int_hexagon_V6_vsubcarry_128B : -Hexagon_custom_v32i32v128i1_v32i32v32i32v128i1_Intrinsic_128B; - -def int_hexagon_V6_vsubububb_sat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubububb_sat">; - -def int_hexagon_V6_vsubububb_sat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubububb_sat_128B">; - -def int_hexagon_V6_vsubuwsat : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubuwsat">; - -def int_hexagon_V6_vsubuwsat_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuwsat_128B">; - -def int_hexagon_V6_vsubuwsat_dv : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuwsat_dv">; - -def int_hexagon_V6_vsubuwsat_dv_128B : -Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vsubuwsat_dv_128B">; - -// V65 HVX Instructions. - -def int_hexagon_V6_vabsb : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsb">; - -def int_hexagon_V6_vabsb_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsb_128B">; - -def int_hexagon_V6_vabsb_sat : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsb_sat">; - -def int_hexagon_V6_vabsb_sat_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabsb_sat_128B">; - -def int_hexagon_V6_vaslh_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vaslh_acc">; - -def int_hexagon_V6_vaslh_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vaslh_acc_128B">; - -def int_hexagon_V6_vasrh_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasrh_acc">; - -def int_hexagon_V6_vasrh_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrh_acc_128B">; - -def int_hexagon_V6_vasruhubrndsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasruhubrndsat">; - -def int_hexagon_V6_vasruhubrndsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasruhubrndsat_128B">; - -def int_hexagon_V6_vasruhubsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasruhubsat">; - -def int_hexagon_V6_vasruhubsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasruhubsat_128B">; - -def int_hexagon_V6_vasruwuhsat : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vasruwuhsat">; - -def int_hexagon_V6_vasruwuhsat_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasruwuhsat_128B">; - -def int_hexagon_V6_vavgb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgb">; - -def int_hexagon_V6_vavgb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgb_128B">; - -def int_hexagon_V6_vavgbrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavgbrnd">; - -def int_hexagon_V6_vavgbrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavgbrnd_128B">; - -def int_hexagon_V6_vavguw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavguw">; - -def int_hexagon_V6_vavguw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavguw_128B">; - -def int_hexagon_V6_vavguwrnd : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vavguwrnd">; - -def int_hexagon_V6_vavguwrnd_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vavguwrnd_128B">; - -def int_hexagon_V6_vdd0 : -Hexagon_v32i32__Intrinsic<"HEXAGON_V6_vdd0">; - -def int_hexagon_V6_vdd0_128B : -Hexagon_v64i32__Intrinsic<"HEXAGON_V6_vdd0_128B">; - -def int_hexagon_V6_vgathermh : -Hexagon__ptri32i32v16i32_Intrinsic<"HEXAGON_V6_vgathermh", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermh_128B : -Hexagon__ptri32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermh_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhq : -Hexagon__ptrv64i1i32i32v16i32_Intrinsic<"HEXAGON_V6_vgathermhq", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhq_128B : -Hexagon__ptrv128i1i32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermhq_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhw : -Hexagon__ptri32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermhw", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhw_128B : -Hexagon__ptri32i32v64i32_Intrinsic<"HEXAGON_V6_vgathermhw_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhwq : -Hexagon__ptrv64i1i32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermhwq", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermhwq_128B : -Hexagon__ptrv128i1i32i32v64i32_Intrinsic<"HEXAGON_V6_vgathermhwq_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermw : -Hexagon__ptri32i32v16i32_Intrinsic<"HEXAGON_V6_vgathermw", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermw_128B : -Hexagon__ptri32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermw_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermwq : -Hexagon__ptrv64i1i32i32v16i32_Intrinsic<"HEXAGON_V6_vgathermwq", [IntrArgMemOnly]>; - -def int_hexagon_V6_vgathermwq_128B : -Hexagon__ptrv128i1i32i32v32i32_Intrinsic<"HEXAGON_V6_vgathermwq_128B", [IntrArgMemOnly]>; - -def int_hexagon_V6_vlut4 : -Hexagon_v16i32_v16i32i64_Intrinsic<"HEXAGON_V6_vlut4">; - -def int_hexagon_V6_vlut4_128B : -Hexagon_v32i32_v32i32i64_Intrinsic<"HEXAGON_V6_vlut4_128B">; - -def int_hexagon_V6_vmpabuu : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpabuu">; - -def int_hexagon_V6_vmpabuu_128B : -Hexagon_v64i32_v64i32i32_Intrinsic<"HEXAGON_V6_vmpabuu_128B">; - -def int_hexagon_V6_vmpabuu_acc : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpabuu_acc">; - -def int_hexagon_V6_vmpabuu_acc_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_vmpabuu_acc_128B">; - -def int_hexagon_V6_vmpahhsat : -Hexagon_v16i32_v16i32v16i32i64_Intrinsic<"HEXAGON_V6_vmpahhsat">; - -def int_hexagon_V6_vmpahhsat_128B : -Hexagon_v32i32_v32i32v32i32i64_Intrinsic<"HEXAGON_V6_vmpahhsat_128B">; - -def int_hexagon_V6_vmpauhuhsat : -Hexagon_v16i32_v16i32v16i32i64_Intrinsic<"HEXAGON_V6_vmpauhuhsat">; - -def int_hexagon_V6_vmpauhuhsat_128B : -Hexagon_v32i32_v32i32v32i32i64_Intrinsic<"HEXAGON_V6_vmpauhuhsat_128B">; - -def int_hexagon_V6_vmpsuhuhsat : -Hexagon_v16i32_v16i32v16i32i64_Intrinsic<"HEXAGON_V6_vmpsuhuhsat">; - -def int_hexagon_V6_vmpsuhuhsat_128B : -Hexagon_v32i32_v32i32v32i32i64_Intrinsic<"HEXAGON_V6_vmpsuhuhsat_128B">; - -def int_hexagon_V6_vmpyh_acc : -Hexagon_v32i32_v32i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyh_acc">; - -def int_hexagon_V6_vmpyh_acc_128B : -Hexagon_v64i32_v64i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyh_acc_128B">; - -def int_hexagon_V6_vmpyuhe : -Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vmpyuhe">; - -def int_hexagon_V6_vmpyuhe_128B : -Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vmpyuhe_128B">; - -def int_hexagon_V6_vmpyuhe_acc : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vmpyuhe_acc">; - -def int_hexagon_V6_vmpyuhe_acc_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vmpyuhe_acc_128B">; - -def int_hexagon_V6_vnavgb : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vnavgb">; - -def int_hexagon_V6_vnavgb_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vnavgb_128B">; - -def int_hexagon_V6_vprefixqb : -Hexagon_v16i32_v64i1_Intrinsic<"HEXAGON_V6_vprefixqb">; - -def int_hexagon_V6_vprefixqb_128B : -Hexagon_v32i32_v128i1_Intrinsic<"HEXAGON_V6_vprefixqb_128B">; - -def int_hexagon_V6_vprefixqh : -Hexagon_v16i32_v64i1_Intrinsic<"HEXAGON_V6_vprefixqh">; - -def int_hexagon_V6_vprefixqh_128B : -Hexagon_v32i32_v128i1_Intrinsic<"HEXAGON_V6_vprefixqh_128B">; - -def int_hexagon_V6_vprefixqw : -Hexagon_v16i32_v64i1_Intrinsic<"HEXAGON_V6_vprefixqw">; - -def int_hexagon_V6_vprefixqw_128B : -Hexagon_v32i32_v128i1_Intrinsic<"HEXAGON_V6_vprefixqw_128B">; - -def int_hexagon_V6_vscattermh : -Hexagon__i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermh", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermh_128B : -Hexagon__i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermh_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermh_add : -Hexagon__i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermh_add", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermh_add_128B : -Hexagon__i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermh_add_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhq : -Hexagon__v64i1i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermhq", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhq_128B : -Hexagon__v128i1i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermhq_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhw : -Hexagon__i32i32v32i32v16i32_Intrinsic<"HEXAGON_V6_vscattermhw", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhw_128B : -Hexagon__i32i32v64i32v32i32_Intrinsic<"HEXAGON_V6_vscattermhw_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhw_add : -Hexagon__i32i32v32i32v16i32_Intrinsic<"HEXAGON_V6_vscattermhw_add", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhw_add_128B : -Hexagon__i32i32v64i32v32i32_Intrinsic<"HEXAGON_V6_vscattermhw_add_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhwq : -Hexagon__v64i1i32i32v32i32v16i32_Intrinsic<"HEXAGON_V6_vscattermhwq", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermhwq_128B : -Hexagon__v128i1i32i32v64i32v32i32_Intrinsic<"HEXAGON_V6_vscattermhwq_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermw : -Hexagon__i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermw", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermw_128B : -Hexagon__i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermw_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermw_add : -Hexagon__i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermw_add", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermw_add_128B : -Hexagon__i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermw_add_128B", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermwq : -Hexagon__v64i1i32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vscattermwq", [IntrWriteMem]>; - -def int_hexagon_V6_vscattermwq_128B : -Hexagon__v128i1i32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vscattermwq_128B", [IntrWriteMem]>; - -// V66 HVX Instructions. - -def int_hexagon_V6_vaddcarrysat : -Hexagon_v16i32_v16i32v16i32v64i1_Intrinsic<"HEXAGON_V6_vaddcarrysat">; - -def int_hexagon_V6_vaddcarrysat_128B : -Hexagon_v32i32_v32i32v32i32v128i1_Intrinsic<"HEXAGON_V6_vaddcarrysat_128B">; - -def int_hexagon_V6_vasr_into : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vasr_into">; - -def int_hexagon_V6_vasr_into_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vasr_into_128B">; - -def int_hexagon_V6_vrotr : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vrotr">; - -def int_hexagon_V6_vrotr_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vrotr_128B">; - -def int_hexagon_V6_vsatdw : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsatdw">; - -def int_hexagon_V6_vsatdw_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsatdw_128B">; - -// V68 HVX Instructions. - -def int_hexagon_V6_v6mpyhubs10 : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_v6mpyhubs10", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyhubs10_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_v6mpyhubs10_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyhubs10_vxx : -Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_v6mpyhubs10_vxx", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyhubs10_vxx_128B : -Hexagon_v64i32_v64i32v64i32v64i32i32_Intrinsic<"HEXAGON_V6_v6mpyhubs10_vxx_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyvubs10 : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_v6mpyvubs10", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyvubs10_128B : -Hexagon_v64i32_v64i32v64i32i32_Intrinsic<"HEXAGON_V6_v6mpyvubs10_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyvubs10_vxx : -Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_v6mpyvubs10_vxx", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_v6mpyvubs10_vxx_128B : -Hexagon_v64i32_v64i32v64i32v64i32i32_Intrinsic<"HEXAGON_V6_v6mpyvubs10_vxx_128B", [IntrNoMem, ImmArg>]>; - -def int_hexagon_V6_vabs_hf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabs_hf">; - -def int_hexagon_V6_vabs_hf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabs_hf_128B">; - -def int_hexagon_V6_vabs_sf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabs_sf">; - -def int_hexagon_V6_vabs_sf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vabs_sf_128B">; - -def int_hexagon_V6_vadd_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_hf">; - -def int_hexagon_V6_vadd_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_hf_128B">; - -def int_hexagon_V6_vadd_hf_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_hf_hf">; - -def int_hexagon_V6_vadd_hf_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_hf_hf_128B">; - -def int_hexagon_V6_vadd_qf16 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_qf16">; - -def int_hexagon_V6_vadd_qf16_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_qf16_128B">; - -def int_hexagon_V6_vadd_qf16_mix : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_qf16_mix">; - -def int_hexagon_V6_vadd_qf16_mix_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_qf16_mix_128B">; - -def int_hexagon_V6_vadd_qf32 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_qf32">; - -def int_hexagon_V6_vadd_qf32_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_qf32_128B">; - -def int_hexagon_V6_vadd_qf32_mix : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_qf32_mix">; - -def int_hexagon_V6_vadd_qf32_mix_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_qf32_mix_128B">; - -def int_hexagon_V6_vadd_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_sf">; - -def int_hexagon_V6_vadd_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_sf_128B">; - -def int_hexagon_V6_vadd_sf_hf : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_sf_hf">; - -def int_hexagon_V6_vadd_sf_hf_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_sf_hf_128B">; - -def int_hexagon_V6_vadd_sf_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vadd_sf_sf">; - -def int_hexagon_V6_vadd_sf_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vadd_sf_sf_128B">; - -def int_hexagon_V6_vassign_fp : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vassign_fp">; - -def int_hexagon_V6_vassign_fp_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vassign_fp_128B">; - -def int_hexagon_V6_vconv_hf_qf16 : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vconv_hf_qf16">; - -def int_hexagon_V6_vconv_hf_qf16_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vconv_hf_qf16_128B">; - -def int_hexagon_V6_vconv_hf_qf32 : -Hexagon_v16i32_v32i32_Intrinsic<"HEXAGON_V6_vconv_hf_qf32">; - -def int_hexagon_V6_vconv_hf_qf32_128B : -Hexagon_v32i32_v64i32_Intrinsic<"HEXAGON_V6_vconv_hf_qf32_128B">; - -def int_hexagon_V6_vconv_sf_qf32 : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vconv_sf_qf32">; - -def int_hexagon_V6_vconv_sf_qf32_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vconv_sf_qf32_128B">; - -def int_hexagon_V6_vcvt_b_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vcvt_b_hf">; - -def int_hexagon_V6_vcvt_b_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vcvt_b_hf_128B">; - -def int_hexagon_V6_vcvt_h_hf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_h_hf">; - -def int_hexagon_V6_vcvt_h_hf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_h_hf_128B">; - -def int_hexagon_V6_vcvt_hf_b : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_hf_b">; - -def int_hexagon_V6_vcvt_hf_b_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_hf_b_128B">; - -def int_hexagon_V6_vcvt_hf_h : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_hf_h">; - -def int_hexagon_V6_vcvt_hf_h_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_hf_h_128B">; - -def int_hexagon_V6_vcvt_hf_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vcvt_hf_sf">; - -def int_hexagon_V6_vcvt_hf_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vcvt_hf_sf_128B">; - -def int_hexagon_V6_vcvt_hf_ub : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_hf_ub">; - -def int_hexagon_V6_vcvt_hf_ub_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_hf_ub_128B">; - -def int_hexagon_V6_vcvt_hf_uh : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_hf_uh">; - -def int_hexagon_V6_vcvt_hf_uh_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_hf_uh_128B">; - -def int_hexagon_V6_vcvt_sf_hf : -Hexagon_v32i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_sf_hf">; - -def int_hexagon_V6_vcvt_sf_hf_128B : -Hexagon_v64i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_sf_hf_128B">; - -def int_hexagon_V6_vcvt_ub_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vcvt_ub_hf">; - -def int_hexagon_V6_vcvt_ub_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vcvt_ub_hf_128B">; - -def int_hexagon_V6_vcvt_uh_hf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vcvt_uh_hf">; - -def int_hexagon_V6_vcvt_uh_hf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vcvt_uh_hf_128B">; - -def int_hexagon_V6_vdmpy_sf_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vdmpy_sf_hf">; - -def int_hexagon_V6_vdmpy_sf_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vdmpy_sf_hf_128B">; - -def int_hexagon_V6_vdmpy_sf_hf_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vdmpy_sf_hf_acc">; - -def int_hexagon_V6_vdmpy_sf_hf_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vdmpy_sf_hf_acc_128B">; - -def int_hexagon_V6_vfmax_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vfmax_hf">; - -def int_hexagon_V6_vfmax_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vfmax_hf_128B">; - -def int_hexagon_V6_vfmax_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vfmax_sf">; - -def int_hexagon_V6_vfmax_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vfmax_sf_128B">; - -def int_hexagon_V6_vfmin_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vfmin_hf">; - -def int_hexagon_V6_vfmin_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vfmin_hf_128B">; - -def int_hexagon_V6_vfmin_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vfmin_sf">; - -def int_hexagon_V6_vfmin_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vfmin_sf_128B">; - -def int_hexagon_V6_vfneg_hf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vfneg_hf">; - -def int_hexagon_V6_vfneg_hf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vfneg_hf_128B">; - -def int_hexagon_V6_vfneg_sf : -Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vfneg_sf">; - -def int_hexagon_V6_vfneg_sf_128B : -Hexagon_v32i32_v32i32_Intrinsic<"HEXAGON_V6_vfneg_sf_128B">; - -def int_hexagon_V6_vgthf : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgthf">; - -def int_hexagon_V6_vgthf_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgthf_128B">; - -def int_hexagon_V6_vgthf_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgthf_and">; - -def int_hexagon_V6_vgthf_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgthf_and_128B">; - -def int_hexagon_V6_vgthf_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgthf_or">; - -def int_hexagon_V6_vgthf_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgthf_or_128B">; - -def int_hexagon_V6_vgthf_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgthf_xor">; - -def int_hexagon_V6_vgthf_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgthf_xor_128B">; - -def int_hexagon_V6_vgtsf : -Hexagon_v64i1_v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtsf">; - -def int_hexagon_V6_vgtsf_128B : -Hexagon_v128i1_v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtsf_128B">; - -def int_hexagon_V6_vgtsf_and : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtsf_and">; - -def int_hexagon_V6_vgtsf_and_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtsf_and_128B">; - -def int_hexagon_V6_vgtsf_or : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtsf_or">; - -def int_hexagon_V6_vgtsf_or_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtsf_or_128B">; - -def int_hexagon_V6_vgtsf_xor : -Hexagon_v64i1_v64i1v16i32v16i32_Intrinsic<"HEXAGON_V6_vgtsf_xor">; - -def int_hexagon_V6_vgtsf_xor_128B : -Hexagon_v128i1_v128i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vgtsf_xor_128B">; - -def int_hexagon_V6_vmax_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmax_hf">; - -def int_hexagon_V6_vmax_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmax_hf_128B">; - -def int_hexagon_V6_vmax_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmax_sf">; - -def int_hexagon_V6_vmax_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmax_sf_128B">; - -def int_hexagon_V6_vmin_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmin_hf">; - -def int_hexagon_V6_vmin_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmin_hf_128B">; - -def int_hexagon_V6_vmin_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmin_sf">; - -def int_hexagon_V6_vmin_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmin_sf_128B">; - -def int_hexagon_V6_vmpy_hf_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_hf_hf">; - -def int_hexagon_V6_vmpy_hf_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_hf_hf_128B">; - -def int_hexagon_V6_vmpy_hf_hf_acc : -Hexagon_v16i32_v16i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_hf_hf_acc">; - -def int_hexagon_V6_vmpy_hf_hf_acc_128B : -Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_hf_hf_acc_128B">; - -def int_hexagon_V6_vmpy_qf16 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf16">; - -def int_hexagon_V6_vmpy_qf16_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf16_128B">; - -def int_hexagon_V6_vmpy_qf16_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf16_hf">; - -def int_hexagon_V6_vmpy_qf16_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf16_hf_128B">; - -def int_hexagon_V6_vmpy_qf16_mix_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf16_mix_hf">; - -def int_hexagon_V6_vmpy_qf16_mix_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf16_mix_hf_128B">; - -def int_hexagon_V6_vmpy_qf32 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf32">; - -def int_hexagon_V6_vmpy_qf32_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_128B">; - -def int_hexagon_V6_vmpy_qf32_hf : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_hf">; - -def int_hexagon_V6_vmpy_qf32_hf_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_hf_128B">; - -def int_hexagon_V6_vmpy_qf32_mix_hf : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_mix_hf">; - -def int_hexagon_V6_vmpy_qf32_mix_hf_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_mix_hf_128B">; - -def int_hexagon_V6_vmpy_qf32_qf16 : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_qf16">; - -def int_hexagon_V6_vmpy_qf32_qf16_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_qf16_128B">; - -def int_hexagon_V6_vmpy_qf32_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_sf">; - -def int_hexagon_V6_vmpy_qf32_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_qf32_sf_128B">; - -def int_hexagon_V6_vmpy_sf_hf : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_sf_hf">; - -def int_hexagon_V6_vmpy_sf_hf_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_sf_hf_128B">; - -def int_hexagon_V6_vmpy_sf_hf_acc : -Hexagon_v32i32_v32i32v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_sf_hf_acc">; - -def int_hexagon_V6_vmpy_sf_hf_acc_128B : -Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_sf_hf_acc_128B">; - -def int_hexagon_V6_vmpy_sf_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpy_sf_sf">; - -def int_hexagon_V6_vmpy_sf_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpy_sf_sf_128B">; - -def int_hexagon_V6_vsub_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_hf">; - -def int_hexagon_V6_vsub_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_hf_128B">; - -def int_hexagon_V6_vsub_hf_hf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_hf_hf">; - -def int_hexagon_V6_vsub_hf_hf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_hf_hf_128B">; - -def int_hexagon_V6_vsub_qf16 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_qf16">; - -def int_hexagon_V6_vsub_qf16_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_qf16_128B">; - -def int_hexagon_V6_vsub_qf16_mix : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_qf16_mix">; - -def int_hexagon_V6_vsub_qf16_mix_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_qf16_mix_128B">; - -def int_hexagon_V6_vsub_qf32 : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_qf32">; - -def int_hexagon_V6_vsub_qf32_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_qf32_128B">; - -def int_hexagon_V6_vsub_qf32_mix : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_qf32_mix">; - -def int_hexagon_V6_vsub_qf32_mix_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_qf32_mix_128B">; - -def int_hexagon_V6_vsub_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_sf">; - -def int_hexagon_V6_vsub_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_sf_128B">; - -def int_hexagon_V6_vsub_sf_hf : -Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_sf_hf">; - -def int_hexagon_V6_vsub_sf_hf_128B : -Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_sf_hf_128B">; - -def int_hexagon_V6_vsub_sf_sf : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_sf_sf">; - -def int_hexagon_V6_vsub_sf_sf_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_sf_sf_128B">; - -// V69 HVX Instructions. - -def int_hexagon_V6_vasrvuhubrndsat : -Hexagon_v16i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vasrvuhubrndsat">; - -def int_hexagon_V6_vasrvuhubrndsat_128B : -Hexagon_v32i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vasrvuhubrndsat_128B">; - -def int_hexagon_V6_vasrvuhubsat : -Hexagon_v16i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vasrvuhubsat">; - -def int_hexagon_V6_vasrvuhubsat_128B : -Hexagon_v32i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vasrvuhubsat_128B">; - -def int_hexagon_V6_vasrvwuhrndsat : -Hexagon_v16i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vasrvwuhrndsat">; - -def int_hexagon_V6_vasrvwuhrndsat_128B : -Hexagon_v32i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vasrvwuhrndsat_128B">; - -def int_hexagon_V6_vasrvwuhsat : -Hexagon_v16i32_v32i32v16i32_Intrinsic<"HEXAGON_V6_vasrvwuhsat">; - -def int_hexagon_V6_vasrvwuhsat_128B : -Hexagon_v32i32_v64i32v32i32_Intrinsic<"HEXAGON_V6_vasrvwuhsat_128B">; - -def int_hexagon_V6_vmpyuhvs : -Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vmpyuhvs">; - -def int_hexagon_V6_vmpyuhvs_128B : -Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpyuhvs_128B">; - diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.h deleted file mode 100644 index a9d35009ee..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.h +++ /dev/null @@ -1,691 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_MIPS_ENUMS_H -#define LLVM_IR_INTRINSIC_MIPS_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum MIPSIntrinsics : unsigned { -// Enum values for intrinsics - mips_absq_s_ph = 4441, // llvm.mips.absq.s.ph - mips_absq_s_qb, // llvm.mips.absq.s.qb - mips_absq_s_w, // llvm.mips.absq.s.w - mips_add_a_b, // llvm.mips.add.a.b - mips_add_a_d, // llvm.mips.add.a.d - mips_add_a_h, // llvm.mips.add.a.h - mips_add_a_w, // llvm.mips.add.a.w - mips_addq_ph, // llvm.mips.addq.ph - mips_addq_s_ph, // llvm.mips.addq.s.ph - mips_addq_s_w, // llvm.mips.addq.s.w - mips_addqh_ph, // llvm.mips.addqh.ph - mips_addqh_r_ph, // llvm.mips.addqh.r.ph - mips_addqh_r_w, // llvm.mips.addqh.r.w - mips_addqh_w, // llvm.mips.addqh.w - mips_adds_a_b, // llvm.mips.adds.a.b - mips_adds_a_d, // llvm.mips.adds.a.d - mips_adds_a_h, // llvm.mips.adds.a.h - mips_adds_a_w, // llvm.mips.adds.a.w - mips_adds_s_b, // llvm.mips.adds.s.b - mips_adds_s_d, // llvm.mips.adds.s.d - mips_adds_s_h, // llvm.mips.adds.s.h - mips_adds_s_w, // llvm.mips.adds.s.w - mips_adds_u_b, // llvm.mips.adds.u.b - mips_adds_u_d, // llvm.mips.adds.u.d - mips_adds_u_h, // llvm.mips.adds.u.h - mips_adds_u_w, // llvm.mips.adds.u.w - mips_addsc, // llvm.mips.addsc - mips_addu_ph, // llvm.mips.addu.ph - mips_addu_qb, // llvm.mips.addu.qb - mips_addu_s_ph, // llvm.mips.addu.s.ph - mips_addu_s_qb, // llvm.mips.addu.s.qb - mips_adduh_qb, // llvm.mips.adduh.qb - mips_adduh_r_qb, // llvm.mips.adduh.r.qb - mips_addv_b, // llvm.mips.addv.b - mips_addv_d, // llvm.mips.addv.d - mips_addv_h, // llvm.mips.addv.h - mips_addv_w, // llvm.mips.addv.w - mips_addvi_b, // llvm.mips.addvi.b - mips_addvi_d, // llvm.mips.addvi.d - mips_addvi_h, // llvm.mips.addvi.h - mips_addvi_w, // llvm.mips.addvi.w - mips_addwc, // llvm.mips.addwc - mips_and_v, // llvm.mips.and.v - mips_andi_b, // llvm.mips.andi.b - mips_append, // llvm.mips.append - mips_asub_s_b, // llvm.mips.asub.s.b - mips_asub_s_d, // llvm.mips.asub.s.d - mips_asub_s_h, // llvm.mips.asub.s.h - mips_asub_s_w, // llvm.mips.asub.s.w - mips_asub_u_b, // llvm.mips.asub.u.b - mips_asub_u_d, // llvm.mips.asub.u.d - mips_asub_u_h, // llvm.mips.asub.u.h - mips_asub_u_w, // llvm.mips.asub.u.w - mips_ave_s_b, // llvm.mips.ave.s.b - mips_ave_s_d, // llvm.mips.ave.s.d - mips_ave_s_h, // llvm.mips.ave.s.h - mips_ave_s_w, // llvm.mips.ave.s.w - mips_ave_u_b, // llvm.mips.ave.u.b - mips_ave_u_d, // llvm.mips.ave.u.d - mips_ave_u_h, // llvm.mips.ave.u.h - mips_ave_u_w, // llvm.mips.ave.u.w - mips_aver_s_b, // llvm.mips.aver.s.b - mips_aver_s_d, // llvm.mips.aver.s.d - mips_aver_s_h, // llvm.mips.aver.s.h - mips_aver_s_w, // llvm.mips.aver.s.w - mips_aver_u_b, // llvm.mips.aver.u.b - mips_aver_u_d, // llvm.mips.aver.u.d - mips_aver_u_h, // llvm.mips.aver.u.h - mips_aver_u_w, // llvm.mips.aver.u.w - mips_balign, // llvm.mips.balign - mips_bclr_b, // llvm.mips.bclr.b - mips_bclr_d, // llvm.mips.bclr.d - mips_bclr_h, // llvm.mips.bclr.h - mips_bclr_w, // llvm.mips.bclr.w - mips_bclri_b, // llvm.mips.bclri.b - mips_bclri_d, // llvm.mips.bclri.d - mips_bclri_h, // llvm.mips.bclri.h - mips_bclri_w, // llvm.mips.bclri.w - mips_binsl_b, // llvm.mips.binsl.b - mips_binsl_d, // llvm.mips.binsl.d - mips_binsl_h, // llvm.mips.binsl.h - mips_binsl_w, // llvm.mips.binsl.w - mips_binsli_b, // llvm.mips.binsli.b - mips_binsli_d, // llvm.mips.binsli.d - mips_binsli_h, // llvm.mips.binsli.h - mips_binsli_w, // llvm.mips.binsli.w - mips_binsr_b, // llvm.mips.binsr.b - mips_binsr_d, // llvm.mips.binsr.d - mips_binsr_h, // llvm.mips.binsr.h - mips_binsr_w, // llvm.mips.binsr.w - mips_binsri_b, // llvm.mips.binsri.b - mips_binsri_d, // llvm.mips.binsri.d - mips_binsri_h, // llvm.mips.binsri.h - mips_binsri_w, // llvm.mips.binsri.w - mips_bitrev, // llvm.mips.bitrev - mips_bmnz_v, // llvm.mips.bmnz.v - mips_bmnzi_b, // llvm.mips.bmnzi.b - mips_bmz_v, // llvm.mips.bmz.v - mips_bmzi_b, // llvm.mips.bmzi.b - mips_bneg_b, // llvm.mips.bneg.b - mips_bneg_d, // llvm.mips.bneg.d - mips_bneg_h, // llvm.mips.bneg.h - mips_bneg_w, // llvm.mips.bneg.w - mips_bnegi_b, // llvm.mips.bnegi.b - mips_bnegi_d, // llvm.mips.bnegi.d - mips_bnegi_h, // llvm.mips.bnegi.h - mips_bnegi_w, // llvm.mips.bnegi.w - mips_bnz_b, // llvm.mips.bnz.b - mips_bnz_d, // llvm.mips.bnz.d - mips_bnz_h, // llvm.mips.bnz.h - mips_bnz_v, // llvm.mips.bnz.v - mips_bnz_w, // llvm.mips.bnz.w - mips_bposge32, // llvm.mips.bposge32 - mips_bsel_v, // llvm.mips.bsel.v - mips_bseli_b, // llvm.mips.bseli.b - mips_bset_b, // llvm.mips.bset.b - mips_bset_d, // llvm.mips.bset.d - mips_bset_h, // llvm.mips.bset.h - mips_bset_w, // llvm.mips.bset.w - mips_bseti_b, // llvm.mips.bseti.b - mips_bseti_d, // llvm.mips.bseti.d - mips_bseti_h, // llvm.mips.bseti.h - mips_bseti_w, // llvm.mips.bseti.w - mips_bz_b, // llvm.mips.bz.b - mips_bz_d, // llvm.mips.bz.d - mips_bz_h, // llvm.mips.bz.h - mips_bz_v, // llvm.mips.bz.v - mips_bz_w, // llvm.mips.bz.w - mips_ceq_b, // llvm.mips.ceq.b - mips_ceq_d, // llvm.mips.ceq.d - mips_ceq_h, // llvm.mips.ceq.h - mips_ceq_w, // llvm.mips.ceq.w - mips_ceqi_b, // llvm.mips.ceqi.b - mips_ceqi_d, // llvm.mips.ceqi.d - mips_ceqi_h, // llvm.mips.ceqi.h - mips_ceqi_w, // llvm.mips.ceqi.w - mips_cfcmsa, // llvm.mips.cfcmsa - mips_cle_s_b, // llvm.mips.cle.s.b - mips_cle_s_d, // llvm.mips.cle.s.d - mips_cle_s_h, // llvm.mips.cle.s.h - mips_cle_s_w, // llvm.mips.cle.s.w - mips_cle_u_b, // llvm.mips.cle.u.b - mips_cle_u_d, // llvm.mips.cle.u.d - mips_cle_u_h, // llvm.mips.cle.u.h - mips_cle_u_w, // llvm.mips.cle.u.w - mips_clei_s_b, // llvm.mips.clei.s.b - mips_clei_s_d, // llvm.mips.clei.s.d - mips_clei_s_h, // llvm.mips.clei.s.h - mips_clei_s_w, // llvm.mips.clei.s.w - mips_clei_u_b, // llvm.mips.clei.u.b - mips_clei_u_d, // llvm.mips.clei.u.d - mips_clei_u_h, // llvm.mips.clei.u.h - mips_clei_u_w, // llvm.mips.clei.u.w - mips_clt_s_b, // llvm.mips.clt.s.b - mips_clt_s_d, // llvm.mips.clt.s.d - mips_clt_s_h, // llvm.mips.clt.s.h - mips_clt_s_w, // llvm.mips.clt.s.w - mips_clt_u_b, // llvm.mips.clt.u.b - mips_clt_u_d, // llvm.mips.clt.u.d - mips_clt_u_h, // llvm.mips.clt.u.h - mips_clt_u_w, // llvm.mips.clt.u.w - mips_clti_s_b, // llvm.mips.clti.s.b - mips_clti_s_d, // llvm.mips.clti.s.d - mips_clti_s_h, // llvm.mips.clti.s.h - mips_clti_s_w, // llvm.mips.clti.s.w - mips_clti_u_b, // llvm.mips.clti.u.b - mips_clti_u_d, // llvm.mips.clti.u.d - mips_clti_u_h, // llvm.mips.clti.u.h - mips_clti_u_w, // llvm.mips.clti.u.w - mips_cmp_eq_ph, // llvm.mips.cmp.eq.ph - mips_cmp_le_ph, // llvm.mips.cmp.le.ph - mips_cmp_lt_ph, // llvm.mips.cmp.lt.ph - mips_cmpgdu_eq_qb, // llvm.mips.cmpgdu.eq.qb - mips_cmpgdu_le_qb, // llvm.mips.cmpgdu.le.qb - mips_cmpgdu_lt_qb, // llvm.mips.cmpgdu.lt.qb - mips_cmpgu_eq_qb, // llvm.mips.cmpgu.eq.qb - mips_cmpgu_le_qb, // llvm.mips.cmpgu.le.qb - mips_cmpgu_lt_qb, // llvm.mips.cmpgu.lt.qb - mips_cmpu_eq_qb, // llvm.mips.cmpu.eq.qb - mips_cmpu_le_qb, // llvm.mips.cmpu.le.qb - mips_cmpu_lt_qb, // llvm.mips.cmpu.lt.qb - mips_copy_s_b, // llvm.mips.copy.s.b - mips_copy_s_d, // llvm.mips.copy.s.d - mips_copy_s_h, // llvm.mips.copy.s.h - mips_copy_s_w, // llvm.mips.copy.s.w - mips_copy_u_b, // llvm.mips.copy.u.b - mips_copy_u_d, // llvm.mips.copy.u.d - mips_copy_u_h, // llvm.mips.copy.u.h - mips_copy_u_w, // llvm.mips.copy.u.w - mips_ctcmsa, // llvm.mips.ctcmsa - mips_div_s_b, // llvm.mips.div.s.b - mips_div_s_d, // llvm.mips.div.s.d - mips_div_s_h, // llvm.mips.div.s.h - mips_div_s_w, // llvm.mips.div.s.w - mips_div_u_b, // llvm.mips.div.u.b - mips_div_u_d, // llvm.mips.div.u.d - mips_div_u_h, // llvm.mips.div.u.h - mips_div_u_w, // llvm.mips.div.u.w - mips_dlsa, // llvm.mips.dlsa - mips_dotp_s_d, // llvm.mips.dotp.s.d - mips_dotp_s_h, // llvm.mips.dotp.s.h - mips_dotp_s_w, // llvm.mips.dotp.s.w - mips_dotp_u_d, // llvm.mips.dotp.u.d - mips_dotp_u_h, // llvm.mips.dotp.u.h - mips_dotp_u_w, // llvm.mips.dotp.u.w - mips_dpa_w_ph, // llvm.mips.dpa.w.ph - mips_dpadd_s_d, // llvm.mips.dpadd.s.d - mips_dpadd_s_h, // llvm.mips.dpadd.s.h - mips_dpadd_s_w, // llvm.mips.dpadd.s.w - mips_dpadd_u_d, // llvm.mips.dpadd.u.d - mips_dpadd_u_h, // llvm.mips.dpadd.u.h - mips_dpadd_u_w, // llvm.mips.dpadd.u.w - mips_dpaq_s_w_ph, // llvm.mips.dpaq.s.w.ph - mips_dpaq_sa_l_w, // llvm.mips.dpaq.sa.l.w - mips_dpaqx_s_w_ph, // llvm.mips.dpaqx.s.w.ph - mips_dpaqx_sa_w_ph, // llvm.mips.dpaqx.sa.w.ph - mips_dpau_h_qbl, // llvm.mips.dpau.h.qbl - mips_dpau_h_qbr, // llvm.mips.dpau.h.qbr - mips_dpax_w_ph, // llvm.mips.dpax.w.ph - mips_dps_w_ph, // llvm.mips.dps.w.ph - mips_dpsq_s_w_ph, // llvm.mips.dpsq.s.w.ph - mips_dpsq_sa_l_w, // llvm.mips.dpsq.sa.l.w - mips_dpsqx_s_w_ph, // llvm.mips.dpsqx.s.w.ph - mips_dpsqx_sa_w_ph, // llvm.mips.dpsqx.sa.w.ph - mips_dpsu_h_qbl, // llvm.mips.dpsu.h.qbl - mips_dpsu_h_qbr, // llvm.mips.dpsu.h.qbr - mips_dpsub_s_d, // llvm.mips.dpsub.s.d - mips_dpsub_s_h, // llvm.mips.dpsub.s.h - mips_dpsub_s_w, // llvm.mips.dpsub.s.w - mips_dpsub_u_d, // llvm.mips.dpsub.u.d - mips_dpsub_u_h, // llvm.mips.dpsub.u.h - mips_dpsub_u_w, // llvm.mips.dpsub.u.w - mips_dpsx_w_ph, // llvm.mips.dpsx.w.ph - mips_extp, // llvm.mips.extp - mips_extpdp, // llvm.mips.extpdp - mips_extr_r_w, // llvm.mips.extr.r.w - mips_extr_rs_w, // llvm.mips.extr.rs.w - mips_extr_s_h, // llvm.mips.extr.s.h - mips_extr_w, // llvm.mips.extr.w - mips_fadd_d, // llvm.mips.fadd.d - mips_fadd_w, // llvm.mips.fadd.w - mips_fcaf_d, // llvm.mips.fcaf.d - mips_fcaf_w, // llvm.mips.fcaf.w - mips_fceq_d, // llvm.mips.fceq.d - mips_fceq_w, // llvm.mips.fceq.w - mips_fclass_d, // llvm.mips.fclass.d - mips_fclass_w, // llvm.mips.fclass.w - mips_fcle_d, // llvm.mips.fcle.d - mips_fcle_w, // llvm.mips.fcle.w - mips_fclt_d, // llvm.mips.fclt.d - mips_fclt_w, // llvm.mips.fclt.w - mips_fcne_d, // llvm.mips.fcne.d - mips_fcne_w, // llvm.mips.fcne.w - mips_fcor_d, // llvm.mips.fcor.d - mips_fcor_w, // llvm.mips.fcor.w - mips_fcueq_d, // llvm.mips.fcueq.d - mips_fcueq_w, // llvm.mips.fcueq.w - mips_fcule_d, // llvm.mips.fcule.d - mips_fcule_w, // llvm.mips.fcule.w - mips_fcult_d, // llvm.mips.fcult.d - mips_fcult_w, // llvm.mips.fcult.w - mips_fcun_d, // llvm.mips.fcun.d - mips_fcun_w, // llvm.mips.fcun.w - mips_fcune_d, // llvm.mips.fcune.d - mips_fcune_w, // llvm.mips.fcune.w - mips_fdiv_d, // llvm.mips.fdiv.d - mips_fdiv_w, // llvm.mips.fdiv.w - mips_fexdo_h, // llvm.mips.fexdo.h - mips_fexdo_w, // llvm.mips.fexdo.w - mips_fexp2_d, // llvm.mips.fexp2.d - mips_fexp2_w, // llvm.mips.fexp2.w - mips_fexupl_d, // llvm.mips.fexupl.d - mips_fexupl_w, // llvm.mips.fexupl.w - mips_fexupr_d, // llvm.mips.fexupr.d - mips_fexupr_w, // llvm.mips.fexupr.w - mips_ffint_s_d, // llvm.mips.ffint.s.d - mips_ffint_s_w, // llvm.mips.ffint.s.w - mips_ffint_u_d, // llvm.mips.ffint.u.d - mips_ffint_u_w, // llvm.mips.ffint.u.w - mips_ffql_d, // llvm.mips.ffql.d - mips_ffql_w, // llvm.mips.ffql.w - mips_ffqr_d, // llvm.mips.ffqr.d - mips_ffqr_w, // llvm.mips.ffqr.w - mips_fill_b, // llvm.mips.fill.b - mips_fill_d, // llvm.mips.fill.d - mips_fill_h, // llvm.mips.fill.h - mips_fill_w, // llvm.mips.fill.w - mips_flog2_d, // llvm.mips.flog2.d - mips_flog2_w, // llvm.mips.flog2.w - mips_fmadd_d, // llvm.mips.fmadd.d - mips_fmadd_w, // llvm.mips.fmadd.w - mips_fmax_a_d, // llvm.mips.fmax.a.d - mips_fmax_a_w, // llvm.mips.fmax.a.w - mips_fmax_d, // llvm.mips.fmax.d - mips_fmax_w, // llvm.mips.fmax.w - mips_fmin_a_d, // llvm.mips.fmin.a.d - mips_fmin_a_w, // llvm.mips.fmin.a.w - mips_fmin_d, // llvm.mips.fmin.d - mips_fmin_w, // llvm.mips.fmin.w - mips_fmsub_d, // llvm.mips.fmsub.d - mips_fmsub_w, // llvm.mips.fmsub.w - mips_fmul_d, // llvm.mips.fmul.d - mips_fmul_w, // llvm.mips.fmul.w - mips_frcp_d, // llvm.mips.frcp.d - mips_frcp_w, // llvm.mips.frcp.w - mips_frint_d, // llvm.mips.frint.d - mips_frint_w, // llvm.mips.frint.w - mips_frsqrt_d, // llvm.mips.frsqrt.d - mips_frsqrt_w, // llvm.mips.frsqrt.w - mips_fsaf_d, // llvm.mips.fsaf.d - mips_fsaf_w, // llvm.mips.fsaf.w - mips_fseq_d, // llvm.mips.fseq.d - mips_fseq_w, // llvm.mips.fseq.w - mips_fsle_d, // llvm.mips.fsle.d - mips_fsle_w, // llvm.mips.fsle.w - mips_fslt_d, // llvm.mips.fslt.d - mips_fslt_w, // llvm.mips.fslt.w - mips_fsne_d, // llvm.mips.fsne.d - mips_fsne_w, // llvm.mips.fsne.w - mips_fsor_d, // llvm.mips.fsor.d - mips_fsor_w, // llvm.mips.fsor.w - mips_fsqrt_d, // llvm.mips.fsqrt.d - mips_fsqrt_w, // llvm.mips.fsqrt.w - mips_fsub_d, // llvm.mips.fsub.d - mips_fsub_w, // llvm.mips.fsub.w - mips_fsueq_d, // llvm.mips.fsueq.d - mips_fsueq_w, // llvm.mips.fsueq.w - mips_fsule_d, // llvm.mips.fsule.d - mips_fsule_w, // llvm.mips.fsule.w - mips_fsult_d, // llvm.mips.fsult.d - mips_fsult_w, // llvm.mips.fsult.w - mips_fsun_d, // llvm.mips.fsun.d - mips_fsun_w, // llvm.mips.fsun.w - mips_fsune_d, // llvm.mips.fsune.d - mips_fsune_w, // llvm.mips.fsune.w - mips_ftint_s_d, // llvm.mips.ftint.s.d - mips_ftint_s_w, // llvm.mips.ftint.s.w - mips_ftint_u_d, // llvm.mips.ftint.u.d - mips_ftint_u_w, // llvm.mips.ftint.u.w - mips_ftq_h, // llvm.mips.ftq.h - mips_ftq_w, // llvm.mips.ftq.w - mips_ftrunc_s_d, // llvm.mips.ftrunc.s.d - mips_ftrunc_s_w, // llvm.mips.ftrunc.s.w - mips_ftrunc_u_d, // llvm.mips.ftrunc.u.d - mips_ftrunc_u_w, // llvm.mips.ftrunc.u.w - mips_hadd_s_d, // llvm.mips.hadd.s.d - mips_hadd_s_h, // llvm.mips.hadd.s.h - mips_hadd_s_w, // llvm.mips.hadd.s.w - mips_hadd_u_d, // llvm.mips.hadd.u.d - mips_hadd_u_h, // llvm.mips.hadd.u.h - mips_hadd_u_w, // llvm.mips.hadd.u.w - mips_hsub_s_d, // llvm.mips.hsub.s.d - mips_hsub_s_h, // llvm.mips.hsub.s.h - mips_hsub_s_w, // llvm.mips.hsub.s.w - mips_hsub_u_d, // llvm.mips.hsub.u.d - mips_hsub_u_h, // llvm.mips.hsub.u.h - mips_hsub_u_w, // llvm.mips.hsub.u.w - mips_ilvev_b, // llvm.mips.ilvev.b - mips_ilvev_d, // llvm.mips.ilvev.d - mips_ilvev_h, // llvm.mips.ilvev.h - mips_ilvev_w, // llvm.mips.ilvev.w - mips_ilvl_b, // llvm.mips.ilvl.b - mips_ilvl_d, // llvm.mips.ilvl.d - mips_ilvl_h, // llvm.mips.ilvl.h - mips_ilvl_w, // llvm.mips.ilvl.w - mips_ilvod_b, // llvm.mips.ilvod.b - mips_ilvod_d, // llvm.mips.ilvod.d - mips_ilvod_h, // llvm.mips.ilvod.h - mips_ilvod_w, // llvm.mips.ilvod.w - mips_ilvr_b, // llvm.mips.ilvr.b - mips_ilvr_d, // llvm.mips.ilvr.d - mips_ilvr_h, // llvm.mips.ilvr.h - mips_ilvr_w, // llvm.mips.ilvr.w - mips_insert_b, // llvm.mips.insert.b - mips_insert_d, // llvm.mips.insert.d - mips_insert_h, // llvm.mips.insert.h - mips_insert_w, // llvm.mips.insert.w - mips_insv, // llvm.mips.insv - mips_insve_b, // llvm.mips.insve.b - mips_insve_d, // llvm.mips.insve.d - mips_insve_h, // llvm.mips.insve.h - mips_insve_w, // llvm.mips.insve.w - mips_lbux, // llvm.mips.lbux - mips_ld_b, // llvm.mips.ld.b - mips_ld_d, // llvm.mips.ld.d - mips_ld_h, // llvm.mips.ld.h - mips_ld_w, // llvm.mips.ld.w - mips_ldi_b, // llvm.mips.ldi.b - mips_ldi_d, // llvm.mips.ldi.d - mips_ldi_h, // llvm.mips.ldi.h - mips_ldi_w, // llvm.mips.ldi.w - mips_ldr_d, // llvm.mips.ldr.d - mips_ldr_w, // llvm.mips.ldr.w - mips_lhx, // llvm.mips.lhx - mips_lsa, // llvm.mips.lsa - mips_lwx, // llvm.mips.lwx - mips_madd, // llvm.mips.madd - mips_madd_q_h, // llvm.mips.madd.q.h - mips_madd_q_w, // llvm.mips.madd.q.w - mips_maddr_q_h, // llvm.mips.maddr.q.h - mips_maddr_q_w, // llvm.mips.maddr.q.w - mips_maddu, // llvm.mips.maddu - mips_maddv_b, // llvm.mips.maddv.b - mips_maddv_d, // llvm.mips.maddv.d - mips_maddv_h, // llvm.mips.maddv.h - mips_maddv_w, // llvm.mips.maddv.w - mips_maq_s_w_phl, // llvm.mips.maq.s.w.phl - mips_maq_s_w_phr, // llvm.mips.maq.s.w.phr - mips_maq_sa_w_phl, // llvm.mips.maq.sa.w.phl - mips_maq_sa_w_phr, // llvm.mips.maq.sa.w.phr - mips_max_a_b, // llvm.mips.max.a.b - mips_max_a_d, // llvm.mips.max.a.d - mips_max_a_h, // llvm.mips.max.a.h - mips_max_a_w, // llvm.mips.max.a.w - mips_max_s_b, // llvm.mips.max.s.b - mips_max_s_d, // llvm.mips.max.s.d - mips_max_s_h, // llvm.mips.max.s.h - mips_max_s_w, // llvm.mips.max.s.w - mips_max_u_b, // llvm.mips.max.u.b - mips_max_u_d, // llvm.mips.max.u.d - mips_max_u_h, // llvm.mips.max.u.h - mips_max_u_w, // llvm.mips.max.u.w - mips_maxi_s_b, // llvm.mips.maxi.s.b - mips_maxi_s_d, // llvm.mips.maxi.s.d - mips_maxi_s_h, // llvm.mips.maxi.s.h - mips_maxi_s_w, // llvm.mips.maxi.s.w - mips_maxi_u_b, // llvm.mips.maxi.u.b - mips_maxi_u_d, // llvm.mips.maxi.u.d - mips_maxi_u_h, // llvm.mips.maxi.u.h - mips_maxi_u_w, // llvm.mips.maxi.u.w - mips_min_a_b, // llvm.mips.min.a.b - mips_min_a_d, // llvm.mips.min.a.d - mips_min_a_h, // llvm.mips.min.a.h - mips_min_a_w, // llvm.mips.min.a.w - mips_min_s_b, // llvm.mips.min.s.b - mips_min_s_d, // llvm.mips.min.s.d - mips_min_s_h, // llvm.mips.min.s.h - mips_min_s_w, // llvm.mips.min.s.w - mips_min_u_b, // llvm.mips.min.u.b - mips_min_u_d, // llvm.mips.min.u.d - mips_min_u_h, // llvm.mips.min.u.h - mips_min_u_w, // llvm.mips.min.u.w - mips_mini_s_b, // llvm.mips.mini.s.b - mips_mini_s_d, // llvm.mips.mini.s.d - mips_mini_s_h, // llvm.mips.mini.s.h - mips_mini_s_w, // llvm.mips.mini.s.w - mips_mini_u_b, // llvm.mips.mini.u.b - mips_mini_u_d, // llvm.mips.mini.u.d - mips_mini_u_h, // llvm.mips.mini.u.h - mips_mini_u_w, // llvm.mips.mini.u.w - mips_mod_s_b, // llvm.mips.mod.s.b - mips_mod_s_d, // llvm.mips.mod.s.d - mips_mod_s_h, // llvm.mips.mod.s.h - mips_mod_s_w, // llvm.mips.mod.s.w - mips_mod_u_b, // llvm.mips.mod.u.b - mips_mod_u_d, // llvm.mips.mod.u.d - mips_mod_u_h, // llvm.mips.mod.u.h - mips_mod_u_w, // llvm.mips.mod.u.w - mips_modsub, // llvm.mips.modsub - mips_move_v, // llvm.mips.move.v - mips_msub, // llvm.mips.msub - mips_msub_q_h, // llvm.mips.msub.q.h - mips_msub_q_w, // llvm.mips.msub.q.w - mips_msubr_q_h, // llvm.mips.msubr.q.h - mips_msubr_q_w, // llvm.mips.msubr.q.w - mips_msubu, // llvm.mips.msubu - mips_msubv_b, // llvm.mips.msubv.b - mips_msubv_d, // llvm.mips.msubv.d - mips_msubv_h, // llvm.mips.msubv.h - mips_msubv_w, // llvm.mips.msubv.w - mips_mthlip, // llvm.mips.mthlip - mips_mul_ph, // llvm.mips.mul.ph - mips_mul_q_h, // llvm.mips.mul.q.h - mips_mul_q_w, // llvm.mips.mul.q.w - mips_mul_s_ph, // llvm.mips.mul.s.ph - mips_muleq_s_w_phl, // llvm.mips.muleq.s.w.phl - mips_muleq_s_w_phr, // llvm.mips.muleq.s.w.phr - mips_muleu_s_ph_qbl, // llvm.mips.muleu.s.ph.qbl - mips_muleu_s_ph_qbr, // llvm.mips.muleu.s.ph.qbr - mips_mulq_rs_ph, // llvm.mips.mulq.rs.ph - mips_mulq_rs_w, // llvm.mips.mulq.rs.w - mips_mulq_s_ph, // llvm.mips.mulq.s.ph - mips_mulq_s_w, // llvm.mips.mulq.s.w - mips_mulr_q_h, // llvm.mips.mulr.q.h - mips_mulr_q_w, // llvm.mips.mulr.q.w - mips_mulsa_w_ph, // llvm.mips.mulsa.w.ph - mips_mulsaq_s_w_ph, // llvm.mips.mulsaq.s.w.ph - mips_mult, // llvm.mips.mult - mips_multu, // llvm.mips.multu - mips_mulv_b, // llvm.mips.mulv.b - mips_mulv_d, // llvm.mips.mulv.d - mips_mulv_h, // llvm.mips.mulv.h - mips_mulv_w, // llvm.mips.mulv.w - mips_nloc_b, // llvm.mips.nloc.b - mips_nloc_d, // llvm.mips.nloc.d - mips_nloc_h, // llvm.mips.nloc.h - mips_nloc_w, // llvm.mips.nloc.w - mips_nlzc_b, // llvm.mips.nlzc.b - mips_nlzc_d, // llvm.mips.nlzc.d - mips_nlzc_h, // llvm.mips.nlzc.h - mips_nlzc_w, // llvm.mips.nlzc.w - mips_nor_v, // llvm.mips.nor.v - mips_nori_b, // llvm.mips.nori.b - mips_or_v, // llvm.mips.or.v - mips_ori_b, // llvm.mips.ori.b - mips_packrl_ph, // llvm.mips.packrl.ph - mips_pckev_b, // llvm.mips.pckev.b - mips_pckev_d, // llvm.mips.pckev.d - mips_pckev_h, // llvm.mips.pckev.h - mips_pckev_w, // llvm.mips.pckev.w - mips_pckod_b, // llvm.mips.pckod.b - mips_pckod_d, // llvm.mips.pckod.d - mips_pckod_h, // llvm.mips.pckod.h - mips_pckod_w, // llvm.mips.pckod.w - mips_pcnt_b, // llvm.mips.pcnt.b - mips_pcnt_d, // llvm.mips.pcnt.d - mips_pcnt_h, // llvm.mips.pcnt.h - mips_pcnt_w, // llvm.mips.pcnt.w - mips_pick_ph, // llvm.mips.pick.ph - mips_pick_qb, // llvm.mips.pick.qb - mips_preceq_w_phl, // llvm.mips.preceq.w.phl - mips_preceq_w_phr, // llvm.mips.preceq.w.phr - mips_precequ_ph_qbl, // llvm.mips.precequ.ph.qbl - mips_precequ_ph_qbla, // llvm.mips.precequ.ph.qbla - mips_precequ_ph_qbr, // llvm.mips.precequ.ph.qbr - mips_precequ_ph_qbra, // llvm.mips.precequ.ph.qbra - mips_preceu_ph_qbl, // llvm.mips.preceu.ph.qbl - mips_preceu_ph_qbla, // llvm.mips.preceu.ph.qbla - mips_preceu_ph_qbr, // llvm.mips.preceu.ph.qbr - mips_preceu_ph_qbra, // llvm.mips.preceu.ph.qbra - mips_precr_qb_ph, // llvm.mips.precr.qb.ph - mips_precr_sra_ph_w, // llvm.mips.precr.sra.ph.w - mips_precr_sra_r_ph_w, // llvm.mips.precr.sra.r.ph.w - mips_precrq_ph_w, // llvm.mips.precrq.ph.w - mips_precrq_qb_ph, // llvm.mips.precrq.qb.ph - mips_precrq_rs_ph_w, // llvm.mips.precrq.rs.ph.w - mips_precrqu_s_qb_ph, // llvm.mips.precrqu.s.qb.ph - mips_prepend, // llvm.mips.prepend - mips_raddu_w_qb, // llvm.mips.raddu.w.qb - mips_rddsp, // llvm.mips.rddsp - mips_repl_ph, // llvm.mips.repl.ph - mips_repl_qb, // llvm.mips.repl.qb - mips_sat_s_b, // llvm.mips.sat.s.b - mips_sat_s_d, // llvm.mips.sat.s.d - mips_sat_s_h, // llvm.mips.sat.s.h - mips_sat_s_w, // llvm.mips.sat.s.w - mips_sat_u_b, // llvm.mips.sat.u.b - mips_sat_u_d, // llvm.mips.sat.u.d - mips_sat_u_h, // llvm.mips.sat.u.h - mips_sat_u_w, // llvm.mips.sat.u.w - mips_shf_b, // llvm.mips.shf.b - mips_shf_h, // llvm.mips.shf.h - mips_shf_w, // llvm.mips.shf.w - mips_shilo, // llvm.mips.shilo - mips_shll_ph, // llvm.mips.shll.ph - mips_shll_qb, // llvm.mips.shll.qb - mips_shll_s_ph, // llvm.mips.shll.s.ph - mips_shll_s_w, // llvm.mips.shll.s.w - mips_shra_ph, // llvm.mips.shra.ph - mips_shra_qb, // llvm.mips.shra.qb - mips_shra_r_ph, // llvm.mips.shra.r.ph - mips_shra_r_qb, // llvm.mips.shra.r.qb - mips_shra_r_w, // llvm.mips.shra.r.w - mips_shrl_ph, // llvm.mips.shrl.ph - mips_shrl_qb, // llvm.mips.shrl.qb - mips_sld_b, // llvm.mips.sld.b - mips_sld_d, // llvm.mips.sld.d - mips_sld_h, // llvm.mips.sld.h - mips_sld_w, // llvm.mips.sld.w - mips_sldi_b, // llvm.mips.sldi.b - mips_sldi_d, // llvm.mips.sldi.d - mips_sldi_h, // llvm.mips.sldi.h - mips_sldi_w, // llvm.mips.sldi.w - mips_sll_b, // llvm.mips.sll.b - mips_sll_d, // llvm.mips.sll.d - mips_sll_h, // llvm.mips.sll.h - mips_sll_w, // llvm.mips.sll.w - mips_slli_b, // llvm.mips.slli.b - mips_slli_d, // llvm.mips.slli.d - mips_slli_h, // llvm.mips.slli.h - mips_slli_w, // llvm.mips.slli.w - mips_splat_b, // llvm.mips.splat.b - mips_splat_d, // llvm.mips.splat.d - mips_splat_h, // llvm.mips.splat.h - mips_splat_w, // llvm.mips.splat.w - mips_splati_b, // llvm.mips.splati.b - mips_splati_d, // llvm.mips.splati.d - mips_splati_h, // llvm.mips.splati.h - mips_splati_w, // llvm.mips.splati.w - mips_sra_b, // llvm.mips.sra.b - mips_sra_d, // llvm.mips.sra.d - mips_sra_h, // llvm.mips.sra.h - mips_sra_w, // llvm.mips.sra.w - mips_srai_b, // llvm.mips.srai.b - mips_srai_d, // llvm.mips.srai.d - mips_srai_h, // llvm.mips.srai.h - mips_srai_w, // llvm.mips.srai.w - mips_srar_b, // llvm.mips.srar.b - mips_srar_d, // llvm.mips.srar.d - mips_srar_h, // llvm.mips.srar.h - mips_srar_w, // llvm.mips.srar.w - mips_srari_b, // llvm.mips.srari.b - mips_srari_d, // llvm.mips.srari.d - mips_srari_h, // llvm.mips.srari.h - mips_srari_w, // llvm.mips.srari.w - mips_srl_b, // llvm.mips.srl.b - mips_srl_d, // llvm.mips.srl.d - mips_srl_h, // llvm.mips.srl.h - mips_srl_w, // llvm.mips.srl.w - mips_srli_b, // llvm.mips.srli.b - mips_srli_d, // llvm.mips.srli.d - mips_srli_h, // llvm.mips.srli.h - mips_srli_w, // llvm.mips.srli.w - mips_srlr_b, // llvm.mips.srlr.b - mips_srlr_d, // llvm.mips.srlr.d - mips_srlr_h, // llvm.mips.srlr.h - mips_srlr_w, // llvm.mips.srlr.w - mips_srlri_b, // llvm.mips.srlri.b - mips_srlri_d, // llvm.mips.srlri.d - mips_srlri_h, // llvm.mips.srlri.h - mips_srlri_w, // llvm.mips.srlri.w - mips_st_b, // llvm.mips.st.b - mips_st_d, // llvm.mips.st.d - mips_st_h, // llvm.mips.st.h - mips_st_w, // llvm.mips.st.w - mips_str_d, // llvm.mips.str.d - mips_str_w, // llvm.mips.str.w - mips_subq_ph, // llvm.mips.subq.ph - mips_subq_s_ph, // llvm.mips.subq.s.ph - mips_subq_s_w, // llvm.mips.subq.s.w - mips_subqh_ph, // llvm.mips.subqh.ph - mips_subqh_r_ph, // llvm.mips.subqh.r.ph - mips_subqh_r_w, // llvm.mips.subqh.r.w - mips_subqh_w, // llvm.mips.subqh.w - mips_subs_s_b, // llvm.mips.subs.s.b - mips_subs_s_d, // llvm.mips.subs.s.d - mips_subs_s_h, // llvm.mips.subs.s.h - mips_subs_s_w, // llvm.mips.subs.s.w - mips_subs_u_b, // llvm.mips.subs.u.b - mips_subs_u_d, // llvm.mips.subs.u.d - mips_subs_u_h, // llvm.mips.subs.u.h - mips_subs_u_w, // llvm.mips.subs.u.w - mips_subsus_u_b, // llvm.mips.subsus.u.b - mips_subsus_u_d, // llvm.mips.subsus.u.d - mips_subsus_u_h, // llvm.mips.subsus.u.h - mips_subsus_u_w, // llvm.mips.subsus.u.w - mips_subsuu_s_b, // llvm.mips.subsuu.s.b - mips_subsuu_s_d, // llvm.mips.subsuu.s.d - mips_subsuu_s_h, // llvm.mips.subsuu.s.h - mips_subsuu_s_w, // llvm.mips.subsuu.s.w - mips_subu_ph, // llvm.mips.subu.ph - mips_subu_qb, // llvm.mips.subu.qb - mips_subu_s_ph, // llvm.mips.subu.s.ph - mips_subu_s_qb, // llvm.mips.subu.s.qb - mips_subuh_qb, // llvm.mips.subuh.qb - mips_subuh_r_qb, // llvm.mips.subuh.r.qb - mips_subv_b, // llvm.mips.subv.b - mips_subv_d, // llvm.mips.subv.d - mips_subv_h, // llvm.mips.subv.h - mips_subv_w, // llvm.mips.subv.w - mips_subvi_b, // llvm.mips.subvi.b - mips_subvi_d, // llvm.mips.subvi.d - mips_subvi_h, // llvm.mips.subvi.h - mips_subvi_w, // llvm.mips.subvi.w - mips_vshf_b, // llvm.mips.vshf.b - mips_vshf_d, // llvm.mips.vshf.d - mips_vshf_h, // llvm.mips.vshf.h - mips_vshf_w, // llvm.mips.vshf.w - mips_wrdsp, // llvm.mips.wrdsp - mips_xor_v, // llvm.mips.xor.v - mips_xori_b, // llvm.mips.xori.b -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.td deleted file mode 100644 index 271142ca77..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsMips.td +++ /dev/null @@ -1,1784 +0,0 @@ -//===- IntrinsicsMips.td - Defines Mips intrinsics ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the MIPS-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MIPS DSP data types -def mips_v2q15_ty: LLVMType; -def mips_v4q7_ty: LLVMType; -def mips_q31_ty: LLVMType; - -let TargetPrefix = "mips" in { // All intrinsics start with "llvm.mips.". - -//===----------------------------------------------------------------------===// -// MIPS DSP Rev 1 - -//===----------------------------------------------------------------------===// -// Addition/subtraction - -def int_mips_addu_qb : GCCBuiltin<"__builtin_mips_addu_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_addu_s_qb : GCCBuiltin<"__builtin_mips_addu_s_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_subu_qb : GCCBuiltin<"__builtin_mips_subu_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_subu_s_qb : GCCBuiltin<"__builtin_mips_subu_s_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; - -def int_mips_addq_ph : GCCBuiltin<"__builtin_mips_addq_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], - [Commutative, IntrNoMem]>; -def int_mips_addq_s_ph : GCCBuiltin<"__builtin_mips_addq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], - [Commutative, IntrNoMem]>; -def int_mips_subq_ph : GCCBuiltin<"__builtin_mips_subq_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; -def int_mips_subq_s_ph : GCCBuiltin<"__builtin_mips_subq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; - -def int_mips_madd: GCCBuiltin<"__builtin_mips_madd">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; -def int_mips_maddu: GCCBuiltin<"__builtin_mips_maddu">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - -def int_mips_msub: GCCBuiltin<"__builtin_mips_msub">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_mips_msubu: GCCBuiltin<"__builtin_mips_msubu">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -def int_mips_addq_s_w: GCCBuiltin<"__builtin_mips_addq_s_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; -def int_mips_subq_s_w: GCCBuiltin<"__builtin_mips_subq_s_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], []>; - -def int_mips_addsc: GCCBuiltin<"__builtin_mips_addsc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [Commutative]>; -def int_mips_addwc: GCCBuiltin<"__builtin_mips_addwc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [Commutative]>; - -def int_mips_modsub: GCCBuiltin<"__builtin_mips_modsub">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_raddu_w_qb: GCCBuiltin<"__builtin_mips_raddu_w_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Absolute value - -def int_mips_absq_s_ph: GCCBuiltin<"__builtin_mips_absq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty], []>; -def int_mips_absq_s_w: GCCBuiltin<"__builtin_mips_absq_s_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty], []>; - -//===----------------------------------------------------------------------===// -// Precision reduce/expand - -def int_mips_precrq_qb_ph: GCCBuiltin<"__builtin_mips_precrq_qb_ph">, - Intrinsic<[llvm_v4i8_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; -def int_mips_precrqu_s_qb_ph: GCCBuiltin<"__builtin_mips_precrqu_s_qb_ph">, - Intrinsic<[llvm_v4i8_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_precrq_ph_w: GCCBuiltin<"__builtin_mips_precrq_ph_w">, - Intrinsic<[mips_v2q15_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; -def int_mips_precrq_rs_ph_w: GCCBuiltin<"__builtin_mips_precrq_rs_ph_w">, - Intrinsic<[mips_v2q15_ty], [mips_q31_ty, mips_q31_ty], []>; -def int_mips_preceq_w_phl: GCCBuiltin<"__builtin_mips_preceq_w_phl">, - Intrinsic<[mips_q31_ty], [mips_v2q15_ty], [IntrNoMem]>; -def int_mips_preceq_w_phr: GCCBuiltin<"__builtin_mips_preceq_w_phr">, - Intrinsic<[mips_q31_ty], [mips_v2q15_ty], [IntrNoMem]>; -def int_mips_precequ_ph_qbl: GCCBuiltin<"__builtin_mips_precequ_ph_qbl">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_precequ_ph_qbr: GCCBuiltin<"__builtin_mips_precequ_ph_qbr">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_precequ_ph_qbla: GCCBuiltin<"__builtin_mips_precequ_ph_qbla">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_precequ_ph_qbra: GCCBuiltin<"__builtin_mips_precequ_ph_qbra">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_preceu_ph_qbl: GCCBuiltin<"__builtin_mips_preceu_ph_qbl">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_preceu_ph_qbr: GCCBuiltin<"__builtin_mips_preceu_ph_qbr">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_preceu_ph_qbla: GCCBuiltin<"__builtin_mips_preceu_ph_qbla">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_preceu_ph_qbra: GCCBuiltin<"__builtin_mips_preceu_ph_qbra">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Shift - -def int_mips_shll_qb: GCCBuiltin<"__builtin_mips_shll_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], []>; -def int_mips_shrl_qb: GCCBuiltin<"__builtin_mips_shrl_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shll_ph: GCCBuiltin<"__builtin_mips_shll_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], []>; -def int_mips_shll_s_ph: GCCBuiltin<"__builtin_mips_shll_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], []>; -def int_mips_shra_ph: GCCBuiltin<"__builtin_mips_shra_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shra_r_ph: GCCBuiltin<"__builtin_mips_shra_r_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shll_s_w: GCCBuiltin<"__builtin_mips_shll_s_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, llvm_i32_ty], []>; -def int_mips_shra_r_w: GCCBuiltin<"__builtin_mips_shra_r_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shilo: GCCBuiltin<"__builtin_mips_shilo">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Multiplication - -def int_mips_muleu_s_ph_qbl: GCCBuiltin<"__builtin_mips_muleu_s_ph_qbl">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty, mips_v2q15_ty], []>; -def int_mips_muleu_s_ph_qbr: GCCBuiltin<"__builtin_mips_muleu_s_ph_qbr">, - Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty, mips_v2q15_ty], []>; -def int_mips_mulq_rs_ph: GCCBuiltin<"__builtin_mips_mulq_rs_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; -def int_mips_muleq_s_w_phl: GCCBuiltin<"__builtin_mips_muleq_s_w_phl">, - Intrinsic<[mips_q31_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; -def int_mips_muleq_s_w_phr: GCCBuiltin<"__builtin_mips_muleq_s_w_phr">, - Intrinsic<[mips_q31_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; -def int_mips_mulsaq_s_w_ph: GCCBuiltin<"__builtin_mips_mulsaq_s_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_maq_s_w_phl: GCCBuiltin<"__builtin_mips_maq_s_w_phl">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_maq_s_w_phr: GCCBuiltin<"__builtin_mips_maq_s_w_phr">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_maq_sa_w_phl: GCCBuiltin<"__builtin_mips_maq_sa_w_phl">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_maq_sa_w_phr: GCCBuiltin<"__builtin_mips_maq_sa_w_phr">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_mult: GCCBuiltin<"__builtin_mips_mult">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; -def int_mips_multu: GCCBuiltin<"__builtin_mips_multu">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - -//===----------------------------------------------------------------------===// -// Dot product with accumulate/subtract - -def int_mips_dpau_h_qbl: GCCBuiltin<"__builtin_mips_dpau_h_qbl">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem]>; -def int_mips_dpau_h_qbr: GCCBuiltin<"__builtin_mips_dpau_h_qbr">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem]>; -def int_mips_dpsu_h_qbl: GCCBuiltin<"__builtin_mips_dpsu_h_qbl">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem]>; -def int_mips_dpsu_h_qbr: GCCBuiltin<"__builtin_mips_dpsu_h_qbr">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem]>; -def int_mips_dpaq_s_w_ph: GCCBuiltin<"__builtin_mips_dpaq_s_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_dpsq_s_w_ph: GCCBuiltin<"__builtin_mips_dpsq_s_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_dpaq_sa_l_w: GCCBuiltin<"__builtin_mips_dpaq_sa_l_w">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_q31_ty, mips_q31_ty], []>; -def int_mips_dpsq_sa_l_w: GCCBuiltin<"__builtin_mips_dpsq_sa_l_w">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_q31_ty, mips_q31_ty], []>; - -//===----------------------------------------------------------------------===// -// Comparison - -def int_mips_cmpu_eq_qb: GCCBuiltin<"__builtin_mips_cmpu_eq_qb">, - Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; -def int_mips_cmpu_lt_qb: GCCBuiltin<"__builtin_mips_cmpu_lt_qb">, - Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], []>; -def int_mips_cmpu_le_qb: GCCBuiltin<"__builtin_mips_cmpu_le_qb">, - Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], []>; -def int_mips_cmpgu_eq_qb: GCCBuiltin<"__builtin_mips_cmpgu_eq_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; -def int_mips_cmpgu_lt_qb: GCCBuiltin<"__builtin_mips_cmpgu_lt_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; -def int_mips_cmpgu_le_qb: GCCBuiltin<"__builtin_mips_cmpgu_le_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; -def int_mips_cmp_eq_ph: GCCBuiltin<"__builtin_mips_cmp_eq_ph">, - Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; -def int_mips_cmp_lt_ph: GCCBuiltin<"__builtin_mips_cmp_lt_ph">, - Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_cmp_le_ph: GCCBuiltin<"__builtin_mips_cmp_le_ph">, - Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], []>; - -//===----------------------------------------------------------------------===// -// Extracting - -def int_mips_extr_s_h: GCCBuiltin<"__builtin_mips_extr_s_h">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -def int_mips_extr_w: GCCBuiltin<"__builtin_mips_extr_w">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -def int_mips_extr_rs_w: GCCBuiltin<"__builtin_mips_extr_rs_w">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -def int_mips_extr_r_w: GCCBuiltin<"__builtin_mips_extr_r_w">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -def int_mips_extp: GCCBuiltin<"__builtin_mips_extp">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -def int_mips_extpdp: GCCBuiltin<"__builtin_mips_extpdp">, - Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; - -//===----------------------------------------------------------------------===// -// Misc - -def int_mips_wrdsp: GCCBuiltin<"__builtin_mips_wrdsp">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg>]>; -def int_mips_rddsp: GCCBuiltin<"__builtin_mips_rddsp">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrReadMem, ImmArg>]>; - -def int_mips_insv: GCCBuiltin<"__builtin_mips_insv">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadMem]>; -def int_mips_bitrev: GCCBuiltin<"__builtin_mips_bitrev">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; - -def int_mips_packrl_ph: GCCBuiltin<"__builtin_mips_packrl_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; - -def int_mips_repl_qb: GCCBuiltin<"__builtin_mips_repl_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_mips_repl_ph: GCCBuiltin<"__builtin_mips_repl_ph">, - Intrinsic<[mips_v2q15_ty], [llvm_i32_ty], [IntrNoMem]>; - -def int_mips_pick_qb: GCCBuiltin<"__builtin_mips_pick_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrReadMem]>; -def int_mips_pick_ph: GCCBuiltin<"__builtin_mips_pick_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrReadMem]>; - -def int_mips_mthlip: GCCBuiltin<"__builtin_mips_mthlip">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], []>; - -def int_mips_bposge32: GCCBuiltin<"__builtin_mips_bposge32">, - Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>; - -def int_mips_lbux: GCCBuiltin<"__builtin_mips_lbux">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_mips_lhx: GCCBuiltin<"__builtin_mips_lhx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_mips_lwx: GCCBuiltin<"__builtin_mips_lwx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; - -//===----------------------------------------------------------------------===// -// MIPS DSP Rev 2 - -def int_mips_absq_s_qb: GCCBuiltin<"__builtin_mips_absq_s_qb">, - Intrinsic<[mips_v4q7_ty], [mips_v4q7_ty], []>; - -def int_mips_addqh_ph: GCCBuiltin<"__builtin_mips_addqh_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], - [IntrNoMem, Commutative]>; -def int_mips_addqh_r_ph: GCCBuiltin<"__builtin_mips_addqh_r_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], - [IntrNoMem, Commutative]>; -def int_mips_addqh_w: GCCBuiltin<"__builtin_mips_addqh_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], - [IntrNoMem, Commutative]>; -def int_mips_addqh_r_w: GCCBuiltin<"__builtin_mips_addqh_r_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], - [IntrNoMem, Commutative]>; - -def int_mips_addu_ph: GCCBuiltin<"__builtin_mips_addu_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; -def int_mips_addu_s_ph: GCCBuiltin<"__builtin_mips_addu_s_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; - -def int_mips_adduh_qb: GCCBuiltin<"__builtin_mips_adduh_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem, Commutative]>; -def int_mips_adduh_r_qb: GCCBuiltin<"__builtin_mips_adduh_r_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], - [IntrNoMem, Commutative]>; - -def int_mips_append: GCCBuiltin<"__builtin_mips_append">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_balign: GCCBuiltin<"__builtin_mips_balign">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_cmpgdu_eq_qb: GCCBuiltin<"__builtin_mips_cmpgdu_eq_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; -def int_mips_cmpgdu_lt_qb: GCCBuiltin<"__builtin_mips_cmpgdu_lt_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; -def int_mips_cmpgdu_le_qb: GCCBuiltin<"__builtin_mips_cmpgdu_le_qb">, - Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; - -def int_mips_dpa_w_ph: GCCBuiltin<"__builtin_mips_dpa_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], - [IntrNoMem]>; -def int_mips_dps_w_ph: GCCBuiltin<"__builtin_mips_dps_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], - [IntrNoMem]>; - -def int_mips_dpaqx_s_w_ph: GCCBuiltin<"__builtin_mips_dpaqx_s_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_dpaqx_sa_w_ph: GCCBuiltin<"__builtin_mips_dpaqx_sa_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_dpax_w_ph: GCCBuiltin<"__builtin_mips_dpax_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], - [IntrNoMem]>; -def int_mips_dpsx_w_ph: GCCBuiltin<"__builtin_mips_dpsx_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], - [IntrNoMem]>; -def int_mips_dpsqx_s_w_ph: GCCBuiltin<"__builtin_mips_dpsqx_s_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; -def int_mips_dpsqx_sa_w_ph: GCCBuiltin<"__builtin_mips_dpsqx_sa_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; - -def int_mips_mul_ph: GCCBuiltin<"__builtin_mips_mul_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; -def int_mips_mul_s_ph: GCCBuiltin<"__builtin_mips_mul_s_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; - -def int_mips_mulq_rs_w: GCCBuiltin<"__builtin_mips_mulq_rs_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; -def int_mips_mulq_s_ph: GCCBuiltin<"__builtin_mips_mulq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; -def int_mips_mulq_s_w: GCCBuiltin<"__builtin_mips_mulq_s_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; -def int_mips_mulsa_w_ph: GCCBuiltin<"__builtin_mips_mulsa_w_ph">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], - [IntrNoMem]>; - -def int_mips_precr_qb_ph: GCCBuiltin<"__builtin_mips_precr_qb_ph">, - Intrinsic<[llvm_v4i8_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; -def int_mips_precr_sra_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_ph_w">, - Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_precr_sra_r_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_r_ph_w">, - Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_prepend: GCCBuiltin<"__builtin_mips_prepend">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_shra_qb: GCCBuiltin<"__builtin_mips_shra_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shra_r_qb: GCCBuiltin<"__builtin_mips_shra_r_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_shrl_ph: GCCBuiltin<"__builtin_mips_shrl_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_subqh_ph: GCCBuiltin<"__builtin_mips_subqh_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; -def int_mips_subqh_r_ph: GCCBuiltin<"__builtin_mips_subqh_r_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; -def int_mips_subqh_w: GCCBuiltin<"__builtin_mips_subqh_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; -def int_mips_subqh_r_w: GCCBuiltin<"__builtin_mips_subqh_r_w">, - Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; - -def int_mips_subu_ph: GCCBuiltin<"__builtin_mips_subu_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; -def int_mips_subu_s_ph: GCCBuiltin<"__builtin_mips_subu_s_ph">, - Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; - -def int_mips_subuh_qb: GCCBuiltin<"__builtin_mips_subuh_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; -def int_mips_subuh_r_qb: GCCBuiltin<"__builtin_mips_subuh_r_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// MIPS MSA - -//===----------------------------------------------------------------------===// -// Addition/subtraction - -def int_mips_add_a_b : GCCBuiltin<"__builtin_msa_add_a_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_add_a_h : GCCBuiltin<"__builtin_msa_add_a_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_add_a_w : GCCBuiltin<"__builtin_msa_add_a_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_add_a_d : GCCBuiltin<"__builtin_msa_add_a_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_adds_a_b : GCCBuiltin<"__builtin_msa_adds_a_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_a_h : GCCBuiltin<"__builtin_msa_adds_a_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_a_w : GCCBuiltin<"__builtin_msa_adds_a_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_a_d : GCCBuiltin<"__builtin_msa_adds_a_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_adds_s_b : GCCBuiltin<"__builtin_msa_adds_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_s_h : GCCBuiltin<"__builtin_msa_adds_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_s_w : GCCBuiltin<"__builtin_msa_adds_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_s_d : GCCBuiltin<"__builtin_msa_adds_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_adds_u_b : GCCBuiltin<"__builtin_msa_adds_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_u_h : GCCBuiltin<"__builtin_msa_adds_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_u_w : GCCBuiltin<"__builtin_msa_adds_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_adds_u_d : GCCBuiltin<"__builtin_msa_adds_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_addv_b : GCCBuiltin<"__builtin_msa_addv_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_addv_h : GCCBuiltin<"__builtin_msa_addv_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_addv_w : GCCBuiltin<"__builtin_msa_addv_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_addv_d : GCCBuiltin<"__builtin_msa_addv_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_addvi_b : GCCBuiltin<"__builtin_msa_addvi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], - [Commutative, IntrNoMem, ImmArg>]>; -def int_mips_addvi_h : GCCBuiltin<"__builtin_msa_addvi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], - [Commutative, IntrNoMem, ImmArg>]>; -def int_mips_addvi_w : GCCBuiltin<"__builtin_msa_addvi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [Commutative, IntrNoMem, ImmArg>]>; -def int_mips_addvi_d : GCCBuiltin<"__builtin_msa_addvi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], - [Commutative, IntrNoMem, ImmArg>]>; - -def int_mips_and_v : GCCBuiltin<"__builtin_msa_and_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_andi_b : GCCBuiltin<"__builtin_msa_andi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_asub_s_b : GCCBuiltin<"__builtin_msa_asub_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_asub_s_h : GCCBuiltin<"__builtin_msa_asub_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_asub_s_w : GCCBuiltin<"__builtin_msa_asub_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_asub_s_d : GCCBuiltin<"__builtin_msa_asub_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_asub_u_b : GCCBuiltin<"__builtin_msa_asub_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_asub_u_h : GCCBuiltin<"__builtin_msa_asub_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_asub_u_w : GCCBuiltin<"__builtin_msa_asub_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_asub_u_d : GCCBuiltin<"__builtin_msa_asub_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ave_s_b : GCCBuiltin<"__builtin_msa_ave_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_s_h : GCCBuiltin<"__builtin_msa_ave_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_s_w : GCCBuiltin<"__builtin_msa_ave_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_s_d : GCCBuiltin<"__builtin_msa_ave_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_ave_u_b : GCCBuiltin<"__builtin_msa_ave_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_u_h : GCCBuiltin<"__builtin_msa_ave_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_u_w : GCCBuiltin<"__builtin_msa_ave_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_ave_u_d : GCCBuiltin<"__builtin_msa_ave_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_aver_s_b : GCCBuiltin<"__builtin_msa_aver_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_s_h : GCCBuiltin<"__builtin_msa_aver_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_s_w : GCCBuiltin<"__builtin_msa_aver_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_s_d : GCCBuiltin<"__builtin_msa_aver_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_aver_u_b : GCCBuiltin<"__builtin_msa_aver_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_u_h : GCCBuiltin<"__builtin_msa_aver_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_u_w : GCCBuiltin<"__builtin_msa_aver_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [Commutative, IntrNoMem]>; -def int_mips_aver_u_d : GCCBuiltin<"__builtin_msa_aver_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [Commutative, IntrNoMem]>; - -def int_mips_bclr_b : GCCBuiltin<"__builtin_msa_bclr_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_bclr_h : GCCBuiltin<"__builtin_msa_bclr_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_bclr_w : GCCBuiltin<"__builtin_msa_bclr_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_bclr_d : GCCBuiltin<"__builtin_msa_bclr_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_bclri_b : GCCBuiltin<"__builtin_msa_bclri_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bclri_h : GCCBuiltin<"__builtin_msa_bclri_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bclri_w : GCCBuiltin<"__builtin_msa_bclri_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bclri_d : GCCBuiltin<"__builtin_msa_bclri_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_binsl_b : GCCBuiltin<"__builtin_msa_binsl_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_binsl_h : GCCBuiltin<"__builtin_msa_binsl_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_binsl_w : GCCBuiltin<"__builtin_msa_binsl_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_mips_binsl_d : GCCBuiltin<"__builtin_msa_binsl_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_mips_binsli_b : GCCBuiltin<"__builtin_msa_binsli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsli_h : GCCBuiltin<"__builtin_msa_binsli_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsli_w : GCCBuiltin<"__builtin_msa_binsli_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsli_d : GCCBuiltin<"__builtin_msa_binsli_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_binsr_b : GCCBuiltin<"__builtin_msa_binsr_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_binsr_h : GCCBuiltin<"__builtin_msa_binsr_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_binsr_w : GCCBuiltin<"__builtin_msa_binsr_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_mips_binsr_d : GCCBuiltin<"__builtin_msa_binsr_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_mips_binsri_b : GCCBuiltin<"__builtin_msa_binsri_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsri_h : GCCBuiltin<"__builtin_msa_binsri_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsri_w : GCCBuiltin<"__builtin_msa_binsri_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_binsri_d : GCCBuiltin<"__builtin_msa_binsri_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - -def int_mips_bmnzi_b : GCCBuiltin<"__builtin_msa_bmnzi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - -def int_mips_bmzi_b : GCCBuiltin<"__builtin_msa_bmzi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_bneg_b : GCCBuiltin<"__builtin_msa_bneg_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_bneg_h : GCCBuiltin<"__builtin_msa_bneg_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_bneg_w : GCCBuiltin<"__builtin_msa_bneg_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_bneg_d : GCCBuiltin<"__builtin_msa_bneg_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_bnegi_b : GCCBuiltin<"__builtin_msa_bnegi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bnegi_h : GCCBuiltin<"__builtin_msa_bnegi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bnegi_w : GCCBuiltin<"__builtin_msa_bnegi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bnegi_d : GCCBuiltin<"__builtin_msa_bnegi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_bnz_b : GCCBuiltin<"__builtin_msa_bnz_b">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_bnz_h : GCCBuiltin<"__builtin_msa_bnz_h">, - Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_bnz_w : GCCBuiltin<"__builtin_msa_bnz_w">, - Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_bnz_d : GCCBuiltin<"__builtin_msa_bnz_d">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_bnz_v : GCCBuiltin<"__builtin_msa_bnz_v">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_bsel_v : GCCBuiltin<"__builtin_msa_bsel_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - -def int_mips_bseli_b : GCCBuiltin<"__builtin_msa_bseli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_bset_b : GCCBuiltin<"__builtin_msa_bset_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_bset_h : GCCBuiltin<"__builtin_msa_bset_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_bset_w : GCCBuiltin<"__builtin_msa_bset_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_bset_d : GCCBuiltin<"__builtin_msa_bset_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_bseti_b : GCCBuiltin<"__builtin_msa_bseti_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bseti_h : GCCBuiltin<"__builtin_msa_bseti_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bseti_w : GCCBuiltin<"__builtin_msa_bseti_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_bseti_d : GCCBuiltin<"__builtin_msa_bseti_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_bz_b : GCCBuiltin<"__builtin_msa_bz_b">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_bz_h : GCCBuiltin<"__builtin_msa_bz_h">, - Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_bz_w : GCCBuiltin<"__builtin_msa_bz_w">, - Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_bz_d : GCCBuiltin<"__builtin_msa_bz_d">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_bz_v : GCCBuiltin<"__builtin_msa_bz_v">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_ceq_b : GCCBuiltin<"__builtin_msa_ceq_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_ceq_h : GCCBuiltin<"__builtin_msa_ceq_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ceq_w : GCCBuiltin<"__builtin_msa_ceq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ceq_d : GCCBuiltin<"__builtin_msa_ceq_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ceqi_b : GCCBuiltin<"__builtin_msa_ceqi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ceqi_h : GCCBuiltin<"__builtin_msa_ceqi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ceqi_w : GCCBuiltin<"__builtin_msa_ceqi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ceqi_d : GCCBuiltin<"__builtin_msa_ceqi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_cfcmsa : GCCBuiltin<"__builtin_msa_cfcmsa">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg>]>; - -def int_mips_cle_s_b : GCCBuiltin<"__builtin_msa_cle_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_cle_s_h : GCCBuiltin<"__builtin_msa_cle_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_cle_s_w : GCCBuiltin<"__builtin_msa_cle_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_cle_s_d : GCCBuiltin<"__builtin_msa_cle_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_cle_u_b : GCCBuiltin<"__builtin_msa_cle_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_cle_u_h : GCCBuiltin<"__builtin_msa_cle_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_cle_u_w : GCCBuiltin<"__builtin_msa_cle_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_cle_u_d : GCCBuiltin<"__builtin_msa_cle_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_clei_s_b : GCCBuiltin<"__builtin_msa_clei_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_s_h : GCCBuiltin<"__builtin_msa_clei_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_s_w : GCCBuiltin<"__builtin_msa_clei_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_s_d : GCCBuiltin<"__builtin_msa_clei_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_clei_u_b : GCCBuiltin<"__builtin_msa_clei_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_u_h : GCCBuiltin<"__builtin_msa_clei_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_u_w : GCCBuiltin<"__builtin_msa_clei_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clei_u_d : GCCBuiltin<"__builtin_msa_clei_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_clt_s_b : GCCBuiltin<"__builtin_msa_clt_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_clt_s_h : GCCBuiltin<"__builtin_msa_clt_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_clt_s_w : GCCBuiltin<"__builtin_msa_clt_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_clt_s_d : GCCBuiltin<"__builtin_msa_clt_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_clt_u_b : GCCBuiltin<"__builtin_msa_clt_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_clt_u_h : GCCBuiltin<"__builtin_msa_clt_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_clt_u_w : GCCBuiltin<"__builtin_msa_clt_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_clt_u_d : GCCBuiltin<"__builtin_msa_clt_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_clti_s_b : GCCBuiltin<"__builtin_msa_clti_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_s_h : GCCBuiltin<"__builtin_msa_clti_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_s_w : GCCBuiltin<"__builtin_msa_clti_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_s_d : GCCBuiltin<"__builtin_msa_clti_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_clti_u_b : GCCBuiltin<"__builtin_msa_clti_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_u_h : GCCBuiltin<"__builtin_msa_clti_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_u_w : GCCBuiltin<"__builtin_msa_clti_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_clti_u_d : GCCBuiltin<"__builtin_msa_clti_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_copy_s_b : GCCBuiltin<"__builtin_msa_copy_s_b">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_s_h : GCCBuiltin<"__builtin_msa_copy_s_h">, - Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_s_w : GCCBuiltin<"__builtin_msa_copy_s_w">, - Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_s_d : GCCBuiltin<"__builtin_msa_copy_s_d">, - Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_copy_u_b : GCCBuiltin<"__builtin_msa_copy_u_b">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_u_h : GCCBuiltin<"__builtin_msa_copy_u_h">, - Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_u_w : GCCBuiltin<"__builtin_msa_copy_u_w">, - Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_copy_u_d : GCCBuiltin<"__builtin_msa_copy_u_d">, - Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_ctcmsa : GCCBuiltin<"__builtin_msa_ctcmsa">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg>]>; - -def int_mips_div_s_b : GCCBuiltin<"__builtin_msa_div_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_div_s_h : GCCBuiltin<"__builtin_msa_div_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_div_s_w : GCCBuiltin<"__builtin_msa_div_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_div_s_d : GCCBuiltin<"__builtin_msa_div_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_div_u_b : GCCBuiltin<"__builtin_msa_div_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_div_u_h : GCCBuiltin<"__builtin_msa_div_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_div_u_w : GCCBuiltin<"__builtin_msa_div_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_div_u_d : GCCBuiltin<"__builtin_msa_div_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -// This instruction is part of the MSA spec but it does not share the -// __builtin_msa prefix because it operates on GP registers. -def int_mips_dlsa : GCCBuiltin<"__builtin_mips_dlsa">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], - [IntrNoMem]>; - -def int_mips_dotp_s_h : GCCBuiltin<"__builtin_msa_dotp_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_dotp_s_w : GCCBuiltin<"__builtin_msa_dotp_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_dotp_s_d : GCCBuiltin<"__builtin_msa_dotp_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_dotp_u_h : GCCBuiltin<"__builtin_msa_dotp_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_dotp_u_w : GCCBuiltin<"__builtin_msa_dotp_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_dotp_u_d : GCCBuiltin<"__builtin_msa_dotp_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_dpadd_s_h : GCCBuiltin<"__builtin_msa_dpadd_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_dpadd_s_w : GCCBuiltin<"__builtin_msa_dpadd_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_dpadd_s_d : GCCBuiltin<"__builtin_msa_dpadd_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_dpadd_u_h : GCCBuiltin<"__builtin_msa_dpadd_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_dpadd_u_w : GCCBuiltin<"__builtin_msa_dpadd_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_dpadd_u_d : GCCBuiltin<"__builtin_msa_dpadd_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_dpsub_s_h : GCCBuiltin<"__builtin_msa_dpsub_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_dpsub_s_w : GCCBuiltin<"__builtin_msa_dpsub_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_dpsub_s_d : GCCBuiltin<"__builtin_msa_dpsub_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_dpsub_u_h : GCCBuiltin<"__builtin_msa_dpsub_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_dpsub_u_w : GCCBuiltin<"__builtin_msa_dpsub_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_dpsub_u_d : GCCBuiltin<"__builtin_msa_dpsub_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_fadd_w : GCCBuiltin<"__builtin_msa_fadd_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fadd_d : GCCBuiltin<"__builtin_msa_fadd_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcaf_w : GCCBuiltin<"__builtin_msa_fcaf_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcaf_d : GCCBuiltin<"__builtin_msa_fcaf_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fceq_w : GCCBuiltin<"__builtin_msa_fceq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fceq_d : GCCBuiltin<"__builtin_msa_fceq_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcle_w : GCCBuiltin<"__builtin_msa_fcle_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcle_d : GCCBuiltin<"__builtin_msa_fcle_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fclt_w : GCCBuiltin<"__builtin_msa_fclt_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fclt_d : GCCBuiltin<"__builtin_msa_fclt_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fclass_w : GCCBuiltin<"__builtin_msa_fclass_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fclass_d : GCCBuiltin<"__builtin_msa_fclass_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcne_w : GCCBuiltin<"__builtin_msa_fcne_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcne_d : GCCBuiltin<"__builtin_msa_fcne_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcor_w : GCCBuiltin<"__builtin_msa_fcor_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcor_d : GCCBuiltin<"__builtin_msa_fcor_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcueq_w : GCCBuiltin<"__builtin_msa_fcueq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcueq_d : GCCBuiltin<"__builtin_msa_fcueq_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcule_w : GCCBuiltin<"__builtin_msa_fcule_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcule_d : GCCBuiltin<"__builtin_msa_fcule_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcult_w : GCCBuiltin<"__builtin_msa_fcult_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcult_d : GCCBuiltin<"__builtin_msa_fcult_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcun_w : GCCBuiltin<"__builtin_msa_fcun_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcun_d : GCCBuiltin<"__builtin_msa_fcun_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fcune_w : GCCBuiltin<"__builtin_msa_fcune_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fcune_d : GCCBuiltin<"__builtin_msa_fcune_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fdiv_w : GCCBuiltin<"__builtin_msa_fdiv_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fdiv_d : GCCBuiltin<"__builtin_msa_fdiv_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fexdo_h : GCCBuiltin<"__builtin_msa_fexdo_h">, - Intrinsic<[llvm_v8f16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fexdo_w : GCCBuiltin<"__builtin_msa_fexdo_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fexp2_w : GCCBuiltin<"__builtin_msa_fexp2_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_fexp2_d : GCCBuiltin<"__builtin_msa_fexp2_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_fexupl_w : GCCBuiltin<"__builtin_msa_fexupl_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; -def int_mips_fexupl_d : GCCBuiltin<"__builtin_msa_fexupl_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - -def int_mips_fexupr_w : GCCBuiltin<"__builtin_msa_fexupr_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; -def int_mips_fexupr_d : GCCBuiltin<"__builtin_msa_fexupr_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - -def int_mips_ffint_s_w : GCCBuiltin<"__builtin_msa_ffint_s_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ffint_s_d : GCCBuiltin<"__builtin_msa_ffint_s_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ffint_u_w : GCCBuiltin<"__builtin_msa_ffint_u_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ffint_u_d : GCCBuiltin<"__builtin_msa_ffint_u_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ffql_w : GCCBuiltin<"__builtin_msa_ffql_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ffql_d : GCCBuiltin<"__builtin_msa_ffql_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_ffqr_w : GCCBuiltin<"__builtin_msa_ffqr_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ffqr_d : GCCBuiltin<"__builtin_msa_ffqr_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_fill_b : GCCBuiltin<"__builtin_msa_fill_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_mips_fill_h : GCCBuiltin<"__builtin_msa_fill_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_mips_fill_w : GCCBuiltin<"__builtin_msa_fill_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_mips_fill_d : GCCBuiltin<"__builtin_msa_fill_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; - -def int_mips_flog2_w : GCCBuiltin<"__builtin_msa_flog2_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_flog2_d : GCCBuiltin<"__builtin_msa_flog2_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fmadd_w : GCCBuiltin<"__builtin_msa_fmadd_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; -def int_mips_fmadd_d : GCCBuiltin<"__builtin_msa_fmadd_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - -def int_mips_fmax_w : GCCBuiltin<"__builtin_msa_fmax_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fmax_d : GCCBuiltin<"__builtin_msa_fmax_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fmax_a_w : GCCBuiltin<"__builtin_msa_fmax_a_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fmax_a_d : GCCBuiltin<"__builtin_msa_fmax_a_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fmin_w : GCCBuiltin<"__builtin_msa_fmin_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fmin_d : GCCBuiltin<"__builtin_msa_fmin_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fmin_a_w : GCCBuiltin<"__builtin_msa_fmin_a_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fmin_a_d : GCCBuiltin<"__builtin_msa_fmin_a_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fmsub_w : GCCBuiltin<"__builtin_msa_fmsub_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; -def int_mips_fmsub_d : GCCBuiltin<"__builtin_msa_fmsub_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - -def int_mips_fmul_w : GCCBuiltin<"__builtin_msa_fmul_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fmul_d : GCCBuiltin<"__builtin_msa_fmul_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_frint_w : GCCBuiltin<"__builtin_msa_frint_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_frint_d : GCCBuiltin<"__builtin_msa_frint_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_frcp_w : GCCBuiltin<"__builtin_msa_frcp_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_frcp_d : GCCBuiltin<"__builtin_msa_frcp_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_frsqrt_w : GCCBuiltin<"__builtin_msa_frsqrt_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_frsqrt_d : GCCBuiltin<"__builtin_msa_frsqrt_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsaf_w : GCCBuiltin<"__builtin_msa_fsaf_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsaf_d : GCCBuiltin<"__builtin_msa_fsaf_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fseq_w : GCCBuiltin<"__builtin_msa_fseq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fseq_d : GCCBuiltin<"__builtin_msa_fseq_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsle_w : GCCBuiltin<"__builtin_msa_fsle_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsle_d : GCCBuiltin<"__builtin_msa_fsle_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fslt_w : GCCBuiltin<"__builtin_msa_fslt_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fslt_d : GCCBuiltin<"__builtin_msa_fslt_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsne_w : GCCBuiltin<"__builtin_msa_fsne_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsne_d : GCCBuiltin<"__builtin_msa_fsne_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsor_w : GCCBuiltin<"__builtin_msa_fsor_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsor_d : GCCBuiltin<"__builtin_msa_fsor_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsqrt_w : GCCBuiltin<"__builtin_msa_fsqrt_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsqrt_d : GCCBuiltin<"__builtin_msa_fsqrt_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsub_w : GCCBuiltin<"__builtin_msa_fsub_w">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsub_d : GCCBuiltin<"__builtin_msa_fsub_d">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsueq_w : GCCBuiltin<"__builtin_msa_fsueq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsueq_d : GCCBuiltin<"__builtin_msa_fsueq_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsule_w : GCCBuiltin<"__builtin_msa_fsule_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsule_d : GCCBuiltin<"__builtin_msa_fsule_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsult_w : GCCBuiltin<"__builtin_msa_fsult_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsult_d : GCCBuiltin<"__builtin_msa_fsult_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsun_w : GCCBuiltin<"__builtin_msa_fsun_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsun_d : GCCBuiltin<"__builtin_msa_fsun_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_fsune_w : GCCBuiltin<"__builtin_msa_fsune_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_fsune_d : GCCBuiltin<"__builtin_msa_fsune_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_ftint_s_w : GCCBuiltin<"__builtin_msa_ftint_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_ftint_s_d : GCCBuiltin<"__builtin_msa_ftint_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_ftint_u_w : GCCBuiltin<"__builtin_msa_ftint_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_ftint_u_d : GCCBuiltin<"__builtin_msa_ftint_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_ftq_h : GCCBuiltin<"__builtin_msa_ftq_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_ftq_w : GCCBuiltin<"__builtin_msa_ftq_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_ftrunc_s_w : GCCBuiltin<"__builtin_msa_ftrunc_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_ftrunc_s_d : GCCBuiltin<"__builtin_msa_ftrunc_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_ftrunc_u_w : GCCBuiltin<"__builtin_msa_ftrunc_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_mips_ftrunc_u_d : GCCBuiltin<"__builtin_msa_ftrunc_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -def int_mips_hadd_s_h : GCCBuiltin<"__builtin_msa_hadd_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_hadd_s_w : GCCBuiltin<"__builtin_msa_hadd_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_hadd_s_d : GCCBuiltin<"__builtin_msa_hadd_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_hadd_u_h : GCCBuiltin<"__builtin_msa_hadd_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_hadd_u_w : GCCBuiltin<"__builtin_msa_hadd_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_hadd_u_d : GCCBuiltin<"__builtin_msa_hadd_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_hsub_s_h : GCCBuiltin<"__builtin_msa_hsub_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_hsub_s_w : GCCBuiltin<"__builtin_msa_hsub_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_hsub_s_d : GCCBuiltin<"__builtin_msa_hsub_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_hsub_u_h : GCCBuiltin<"__builtin_msa_hsub_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_hsub_u_w : GCCBuiltin<"__builtin_msa_hsub_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_hsub_u_d : GCCBuiltin<"__builtin_msa_hsub_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_ilvev_b : GCCBuiltin<"__builtin_msa_ilvev_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_ilvev_h : GCCBuiltin<"__builtin_msa_ilvev_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ilvev_w : GCCBuiltin<"__builtin_msa_ilvev_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ilvev_d : GCCBuiltin<"__builtin_msa_ilvev_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ilvl_b : GCCBuiltin<"__builtin_msa_ilvl_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_ilvl_h : GCCBuiltin<"__builtin_msa_ilvl_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ilvl_w : GCCBuiltin<"__builtin_msa_ilvl_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ilvl_d : GCCBuiltin<"__builtin_msa_ilvl_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ilvod_b : GCCBuiltin<"__builtin_msa_ilvod_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_ilvod_h : GCCBuiltin<"__builtin_msa_ilvod_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ilvod_w : GCCBuiltin<"__builtin_msa_ilvod_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ilvod_d : GCCBuiltin<"__builtin_msa_ilvod_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_ilvr_b : GCCBuiltin<"__builtin_msa_ilvr_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_ilvr_h : GCCBuiltin<"__builtin_msa_ilvr_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_ilvr_w : GCCBuiltin<"__builtin_msa_ilvr_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_ilvr_d : GCCBuiltin<"__builtin_msa_ilvr_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_insert_b : GCCBuiltin<"__builtin_msa_insert_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_mips_insert_h : GCCBuiltin<"__builtin_msa_insert_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_mips_insert_w : GCCBuiltin<"__builtin_msa_insert_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; -def int_mips_insert_d : GCCBuiltin<"__builtin_msa_insert_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i64_ty], - [IntrNoMem]>; - -def int_mips_insve_b : GCCBuiltin<"__builtin_msa_insve_b">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_insve_h : GCCBuiltin<"__builtin_msa_insve_h">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_insve_w : GCCBuiltin<"__builtin_msa_insve_w">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - -def int_mips_ldr_d : GCCBuiltin<"__builtin_msa_ldr_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -def int_mips_ldr_w : GCCBuiltin<"__builtin_msa_ldr_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - -def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ldi_h : GCCBuiltin<"__builtin_msa_ldi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ldi_w : GCCBuiltin<"__builtin_msa_ldi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_ldi_d : GCCBuiltin<"__builtin_msa_ldi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -// This instruction is part of the MSA spec but it does not share the -// __builtin_msa prefix because it operates on the GPR registers. -def int_mips_lsa : GCCBuiltin<"__builtin_mips_lsa">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -def int_mips_madd_q_h : GCCBuiltin<"__builtin_msa_madd_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_madd_q_w : GCCBuiltin<"__builtin_msa_madd_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_maddr_q_h : GCCBuiltin<"__builtin_msa_maddr_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_maddr_q_w : GCCBuiltin<"__builtin_msa_maddr_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_maddv_b : GCCBuiltin<"__builtin_msa_maddv_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_maddv_h : GCCBuiltin<"__builtin_msa_maddv_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_maddv_w : GCCBuiltin<"__builtin_msa_maddv_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_mips_maddv_d : GCCBuiltin<"__builtin_msa_maddv_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_mips_max_a_b : GCCBuiltin<"__builtin_msa_max_a_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_max_a_h : GCCBuiltin<"__builtin_msa_max_a_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_max_a_w : GCCBuiltin<"__builtin_msa_max_a_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_max_a_d : GCCBuiltin<"__builtin_msa_max_a_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_max_s_b : GCCBuiltin<"__builtin_msa_max_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_max_s_h : GCCBuiltin<"__builtin_msa_max_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_max_s_w : GCCBuiltin<"__builtin_msa_max_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_max_s_d : GCCBuiltin<"__builtin_msa_max_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_max_u_b : GCCBuiltin<"__builtin_msa_max_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_max_u_h : GCCBuiltin<"__builtin_msa_max_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_max_u_w : GCCBuiltin<"__builtin_msa_max_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_max_u_d : GCCBuiltin<"__builtin_msa_max_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_maxi_s_b : GCCBuiltin<"__builtin_msa_maxi_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_s_h : GCCBuiltin<"__builtin_msa_maxi_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_s_w : GCCBuiltin<"__builtin_msa_maxi_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_s_d : GCCBuiltin<"__builtin_msa_maxi_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_maxi_u_b : GCCBuiltin<"__builtin_msa_maxi_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_u_h : GCCBuiltin<"__builtin_msa_maxi_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_u_w : GCCBuiltin<"__builtin_msa_maxi_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_maxi_u_d : GCCBuiltin<"__builtin_msa_maxi_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_min_a_b : GCCBuiltin<"__builtin_msa_min_a_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_min_a_h : GCCBuiltin<"__builtin_msa_min_a_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_min_a_w : GCCBuiltin<"__builtin_msa_min_a_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_min_a_d : GCCBuiltin<"__builtin_msa_min_a_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_min_s_b : GCCBuiltin<"__builtin_msa_min_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_min_s_h : GCCBuiltin<"__builtin_msa_min_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_min_s_w : GCCBuiltin<"__builtin_msa_min_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_min_s_d : GCCBuiltin<"__builtin_msa_min_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_min_u_b : GCCBuiltin<"__builtin_msa_min_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_min_u_h : GCCBuiltin<"__builtin_msa_min_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_min_u_w : GCCBuiltin<"__builtin_msa_min_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_min_u_d : GCCBuiltin<"__builtin_msa_min_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_mini_s_b : GCCBuiltin<"__builtin_msa_mini_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_s_h : GCCBuiltin<"__builtin_msa_mini_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_s_w : GCCBuiltin<"__builtin_msa_mini_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_s_d : GCCBuiltin<"__builtin_msa_mini_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_mini_u_b : GCCBuiltin<"__builtin_msa_mini_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_u_h : GCCBuiltin<"__builtin_msa_mini_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_u_w : GCCBuiltin<"__builtin_msa_mini_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_mini_u_d : GCCBuiltin<"__builtin_msa_mini_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_mod_s_b : GCCBuiltin<"__builtin_msa_mod_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_mod_s_h : GCCBuiltin<"__builtin_msa_mod_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_mod_s_w : GCCBuiltin<"__builtin_msa_mod_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_mod_s_d : GCCBuiltin<"__builtin_msa_mod_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_mod_u_b : GCCBuiltin<"__builtin_msa_mod_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_mod_u_h : GCCBuiltin<"__builtin_msa_mod_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_mod_u_w : GCCBuiltin<"__builtin_msa_mod_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_mod_u_d : GCCBuiltin<"__builtin_msa_mod_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_move_v : GCCBuiltin<"__builtin_msa_move_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_msub_q_h : GCCBuiltin<"__builtin_msa_msub_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_msub_q_w : GCCBuiltin<"__builtin_msa_msub_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_msubr_q_h : GCCBuiltin<"__builtin_msa_msubr_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_msubr_q_w : GCCBuiltin<"__builtin_msa_msubr_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -def int_mips_msubv_b : GCCBuiltin<"__builtin_msa_msubv_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_msubv_h : GCCBuiltin<"__builtin_msa_msubv_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_msubv_w : GCCBuiltin<"__builtin_msa_msubv_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_mips_msubv_d : GCCBuiltin<"__builtin_msa_msubv_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_mips_mul_q_h : GCCBuiltin<"__builtin_msa_mul_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_mul_q_w : GCCBuiltin<"__builtin_msa_mul_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_mulr_q_h : GCCBuiltin<"__builtin_msa_mulr_q_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_mulr_q_w : GCCBuiltin<"__builtin_msa_mulr_q_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - -def int_mips_mulv_b : GCCBuiltin<"__builtin_msa_mulv_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_mulv_h : GCCBuiltin<"__builtin_msa_mulv_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_mulv_w : GCCBuiltin<"__builtin_msa_mulv_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_mulv_d : GCCBuiltin<"__builtin_msa_mulv_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_nloc_b : GCCBuiltin<"__builtin_msa_nloc_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_nloc_h : GCCBuiltin<"__builtin_msa_nloc_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_nloc_w : GCCBuiltin<"__builtin_msa_nloc_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_nloc_d : GCCBuiltin<"__builtin_msa_nloc_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_nlzc_b : GCCBuiltin<"__builtin_msa_nlzc_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_nlzc_h : GCCBuiltin<"__builtin_msa_nlzc_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_nlzc_w : GCCBuiltin<"__builtin_msa_nlzc_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_nlzc_d : GCCBuiltin<"__builtin_msa_nlzc_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_nor_v : GCCBuiltin<"__builtin_msa_nor_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_nori_b : GCCBuiltin<"__builtin_msa_nori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_or_v : GCCBuiltin<"__builtin_msa_or_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_ori_b : GCCBuiltin<"__builtin_msa_ori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_pckev_b : GCCBuiltin<"__builtin_msa_pckev_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_pckev_h : GCCBuiltin<"__builtin_msa_pckev_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_pckev_w : GCCBuiltin<"__builtin_msa_pckev_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_pckev_d : GCCBuiltin<"__builtin_msa_pckev_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_pckod_b : GCCBuiltin<"__builtin_msa_pckod_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_pckod_h : GCCBuiltin<"__builtin_msa_pckod_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_pckod_w : GCCBuiltin<"__builtin_msa_pckod_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_pckod_d : GCCBuiltin<"__builtin_msa_pckod_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_pcnt_b : GCCBuiltin<"__builtin_msa_pcnt_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_pcnt_h : GCCBuiltin<"__builtin_msa_pcnt_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_pcnt_w : GCCBuiltin<"__builtin_msa_pcnt_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_pcnt_d : GCCBuiltin<"__builtin_msa_pcnt_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_sat_s_b : GCCBuiltin<"__builtin_msa_sat_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_s_h : GCCBuiltin<"__builtin_msa_sat_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_s_w : GCCBuiltin<"__builtin_msa_sat_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_s_d : GCCBuiltin<"__builtin_msa_sat_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_sat_u_b : GCCBuiltin<"__builtin_msa_sat_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_u_h : GCCBuiltin<"__builtin_msa_sat_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_u_w : GCCBuiltin<"__builtin_msa_sat_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_sat_u_d : GCCBuiltin<"__builtin_msa_sat_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_shf_b : GCCBuiltin<"__builtin_msa_shf_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_shf_h : GCCBuiltin<"__builtin_msa_shf_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_sld_h : GCCBuiltin<"__builtin_msa_sld_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_sld_w : GCCBuiltin<"__builtin_msa_sld_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_sll_h : GCCBuiltin<"__builtin_msa_sll_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_sll_w : GCCBuiltin<"__builtin_msa_sll_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_sll_d : GCCBuiltin<"__builtin_msa_sll_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_slli_b : GCCBuiltin<"__builtin_msa_slli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_slli_h : GCCBuiltin<"__builtin_msa_slli_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_slli_w : GCCBuiltin<"__builtin_msa_slli_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_slli_d : GCCBuiltin<"__builtin_msa_slli_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_splat_b : GCCBuiltin<"__builtin_msa_splat_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_splat_h : GCCBuiltin<"__builtin_msa_splat_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_splat_w : GCCBuiltin<"__builtin_msa_splat_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_mips_splat_d : GCCBuiltin<"__builtin_msa_splat_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_mips_splati_b : GCCBuiltin<"__builtin_msa_splati_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_splati_h : GCCBuiltin<"__builtin_msa_splati_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_splati_w : GCCBuiltin<"__builtin_msa_splati_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_splati_d : GCCBuiltin<"__builtin_msa_splati_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_sra_b : GCCBuiltin<"__builtin_msa_sra_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_sra_h : GCCBuiltin<"__builtin_msa_sra_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_sra_w : GCCBuiltin<"__builtin_msa_sra_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_sra_d : GCCBuiltin<"__builtin_msa_sra_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_srai_b : GCCBuiltin<"__builtin_msa_srai_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srai_h : GCCBuiltin<"__builtin_msa_srai_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srai_w : GCCBuiltin<"__builtin_msa_srai_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srai_d : GCCBuiltin<"__builtin_msa_srai_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_srar_b : GCCBuiltin<"__builtin_msa_srar_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_srar_h : GCCBuiltin<"__builtin_msa_srar_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_srar_w : GCCBuiltin<"__builtin_msa_srar_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_srar_d : GCCBuiltin<"__builtin_msa_srar_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_srari_b : GCCBuiltin<"__builtin_msa_srari_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srari_h : GCCBuiltin<"__builtin_msa_srari_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srari_w : GCCBuiltin<"__builtin_msa_srari_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srari_d : GCCBuiltin<"__builtin_msa_srari_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_srl_b : GCCBuiltin<"__builtin_msa_srl_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_srl_h : GCCBuiltin<"__builtin_msa_srl_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_srl_w : GCCBuiltin<"__builtin_msa_srl_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_srl_d : GCCBuiltin<"__builtin_msa_srl_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_srli_b : GCCBuiltin<"__builtin_msa_srli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srli_h : GCCBuiltin<"__builtin_msa_srli_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srli_w : GCCBuiltin<"__builtin_msa_srli_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srli_d : GCCBuiltin<"__builtin_msa_srli_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_srlr_b : GCCBuiltin<"__builtin_msa_srlr_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_srlr_h : GCCBuiltin<"__builtin_msa_srlr_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_srlr_w : GCCBuiltin<"__builtin_msa_srlr_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_srlr_d : GCCBuiltin<"__builtin_msa_srlr_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_srlri_b : GCCBuiltin<"__builtin_msa_srlri_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srlri_h : GCCBuiltin<"__builtin_msa_srlri_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srlri_w : GCCBuiltin<"__builtin_msa_srlri_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">, - Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">, - Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">, - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">, - Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - -def int_mips_str_d : GCCBuiltin<"__builtin_msa_str_d">, - Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -def int_mips_str_w : GCCBuiltin<"__builtin_msa_str_w">, - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - -def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_subs_s_h : GCCBuiltin<"__builtin_msa_subs_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_subs_s_w : GCCBuiltin<"__builtin_msa_subs_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_subs_s_d : GCCBuiltin<"__builtin_msa_subs_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_subs_u_b : GCCBuiltin<"__builtin_msa_subs_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_subs_u_h : GCCBuiltin<"__builtin_msa_subs_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_subs_u_w : GCCBuiltin<"__builtin_msa_subs_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_subs_u_d : GCCBuiltin<"__builtin_msa_subs_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_subsus_u_b : GCCBuiltin<"__builtin_msa_subsus_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_subsus_u_h : GCCBuiltin<"__builtin_msa_subsus_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_subsus_u_w : GCCBuiltin<"__builtin_msa_subsus_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_subsus_u_d : GCCBuiltin<"__builtin_msa_subsus_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_subsuu_s_b : GCCBuiltin<"__builtin_msa_subsuu_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_subsuu_s_h : GCCBuiltin<"__builtin_msa_subsuu_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_subsuu_s_w : GCCBuiltin<"__builtin_msa_subsuu_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_subsuu_s_d : GCCBuiltin<"__builtin_msa_subsuu_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_subv_b : GCCBuiltin<"__builtin_msa_subv_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -def int_mips_subv_h : GCCBuiltin<"__builtin_msa_subv_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -def int_mips_subv_w : GCCBuiltin<"__builtin_msa_subv_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_mips_subv_d : GCCBuiltin<"__builtin_msa_subv_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - -def int_mips_subvi_b : GCCBuiltin<"__builtin_msa_subvi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_subvi_h : GCCBuiltin<"__builtin_msa_subvi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_subvi_w : GCCBuiltin<"__builtin_msa_subvi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_mips_subvi_d : GCCBuiltin<"__builtin_msa_subvi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -def int_mips_vshf_b : GCCBuiltin<"__builtin_msa_vshf_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_mips_vshf_h : GCCBuiltin<"__builtin_msa_vshf_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -def int_mips_vshf_w : GCCBuiltin<"__builtin_msa_vshf_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_mips_vshf_d : GCCBuiltin<"__builtin_msa_vshf_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_mips_xor_v : GCCBuiltin<"__builtin_msa_xor_v">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - -def int_mips_xori_b : GCCBuiltin<"__builtin_msa_xori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVPTX.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVPTX.h deleted file mode 100644 index 8cae0209db..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVPTX.h +++ /dev/null @@ -1,1527 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_NVVM_ENUMS_H -#define LLVM_IR_INTRINSIC_NVVM_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum NVVMIntrinsics : unsigned { -// Enum values for intrinsics - nvvm_add_rm_d = 5112, // llvm.nvvm.add.rm.d - nvvm_add_rm_f, // llvm.nvvm.add.rm.f - nvvm_add_rm_ftz_f, // llvm.nvvm.add.rm.ftz.f - nvvm_add_rn_d, // llvm.nvvm.add.rn.d - nvvm_add_rn_f, // llvm.nvvm.add.rn.f - nvvm_add_rn_ftz_f, // llvm.nvvm.add.rn.ftz.f - nvvm_add_rp_d, // llvm.nvvm.add.rp.d - nvvm_add_rp_f, // llvm.nvvm.add.rp.f - nvvm_add_rp_ftz_f, // llvm.nvvm.add.rp.ftz.f - nvvm_add_rz_d, // llvm.nvvm.add.rz.d - nvvm_add_rz_f, // llvm.nvvm.add.rz.f - nvvm_add_rz_ftz_f, // llvm.nvvm.add.rz.ftz.f - nvvm_atomic_add_gen_f_cta, // llvm.nvvm.atomic.add.gen.f.cta - nvvm_atomic_add_gen_f_sys, // llvm.nvvm.atomic.add.gen.f.sys - nvvm_atomic_add_gen_i_cta, // llvm.nvvm.atomic.add.gen.i.cta - nvvm_atomic_add_gen_i_sys, // llvm.nvvm.atomic.add.gen.i.sys - nvvm_atomic_and_gen_i_cta, // llvm.nvvm.atomic.and.gen.i.cta - nvvm_atomic_and_gen_i_sys, // llvm.nvvm.atomic.and.gen.i.sys - nvvm_atomic_cas_gen_i_cta, // llvm.nvvm.atomic.cas.gen.i.cta - nvvm_atomic_cas_gen_i_sys, // llvm.nvvm.atomic.cas.gen.i.sys - nvvm_atomic_dec_gen_i_cta, // llvm.nvvm.atomic.dec.gen.i.cta - nvvm_atomic_dec_gen_i_sys, // llvm.nvvm.atomic.dec.gen.i.sys - nvvm_atomic_exch_gen_i_cta, // llvm.nvvm.atomic.exch.gen.i.cta - nvvm_atomic_exch_gen_i_sys, // llvm.nvvm.atomic.exch.gen.i.sys - nvvm_atomic_inc_gen_i_cta, // llvm.nvvm.atomic.inc.gen.i.cta - nvvm_atomic_inc_gen_i_sys, // llvm.nvvm.atomic.inc.gen.i.sys - nvvm_atomic_load_dec_32, // llvm.nvvm.atomic.load.dec.32 - nvvm_atomic_load_inc_32, // llvm.nvvm.atomic.load.inc.32 - nvvm_atomic_max_gen_i_cta, // llvm.nvvm.atomic.max.gen.i.cta - nvvm_atomic_max_gen_i_sys, // llvm.nvvm.atomic.max.gen.i.sys - nvvm_atomic_min_gen_i_cta, // llvm.nvvm.atomic.min.gen.i.cta - nvvm_atomic_min_gen_i_sys, // llvm.nvvm.atomic.min.gen.i.sys - nvvm_atomic_or_gen_i_cta, // llvm.nvvm.atomic.or.gen.i.cta - nvvm_atomic_or_gen_i_sys, // llvm.nvvm.atomic.or.gen.i.sys - nvvm_atomic_xor_gen_i_cta, // llvm.nvvm.atomic.xor.gen.i.cta - nvvm_atomic_xor_gen_i_sys, // llvm.nvvm.atomic.xor.gen.i.sys - nvvm_bar_sync, // llvm.nvvm.bar.sync - nvvm_bar_warp_sync, // llvm.nvvm.bar.warp.sync - nvvm_barrier, // llvm.nvvm.barrier - nvvm_barrier_n, // llvm.nvvm.barrier.n - nvvm_barrier_sync, // llvm.nvvm.barrier.sync - nvvm_barrier_sync_cnt, // llvm.nvvm.barrier.sync.cnt - nvvm_barrier0, // llvm.nvvm.barrier0 - nvvm_barrier0_and, // llvm.nvvm.barrier0.and - nvvm_barrier0_or, // llvm.nvvm.barrier0.or - nvvm_barrier0_popc, // llvm.nvvm.barrier0.popc - nvvm_bitcast_d2ll, // llvm.nvvm.bitcast.d2ll - nvvm_bitcast_f2i, // llvm.nvvm.bitcast.f2i - nvvm_bitcast_i2f, // llvm.nvvm.bitcast.i2f - nvvm_bitcast_ll2d, // llvm.nvvm.bitcast.ll2d - nvvm_ceil_d, // llvm.nvvm.ceil.d - nvvm_ceil_f, // llvm.nvvm.ceil.f - nvvm_ceil_ftz_f, // llvm.nvvm.ceil.ftz.f - nvvm_compiler_error, // llvm.nvvm.compiler.error - nvvm_compiler_warn, // llvm.nvvm.compiler.warn - nvvm_cos_approx_f, // llvm.nvvm.cos.approx.f - nvvm_cos_approx_ftz_f, // llvm.nvvm.cos.approx.ftz.f - nvvm_cp_async_ca_shared_global_16, // llvm.nvvm.cp.async.ca.shared.global.16 - nvvm_cp_async_ca_shared_global_4, // llvm.nvvm.cp.async.ca.shared.global.4 - nvvm_cp_async_ca_shared_global_8, // llvm.nvvm.cp.async.ca.shared.global.8 - nvvm_cp_async_cg_shared_global_16, // llvm.nvvm.cp.async.cg.shared.global.16 - nvvm_cp_async_commit_group, // llvm.nvvm.cp.async.commit.group - nvvm_cp_async_mbarrier_arrive, // llvm.nvvm.cp.async.mbarrier.arrive - nvvm_cp_async_mbarrier_arrive_noinc, // llvm.nvvm.cp.async.mbarrier.arrive.noinc - nvvm_cp_async_mbarrier_arrive_noinc_shared, // llvm.nvvm.cp.async.mbarrier.arrive.noinc.shared - nvvm_cp_async_mbarrier_arrive_shared, // llvm.nvvm.cp.async.mbarrier.arrive.shared - nvvm_cp_async_wait_all, // llvm.nvvm.cp.async.wait.all - nvvm_cp_async_wait_group, // llvm.nvvm.cp.async.wait.group - nvvm_d2f_rm, // llvm.nvvm.d2f.rm - nvvm_d2f_rm_ftz, // llvm.nvvm.d2f.rm.ftz - nvvm_d2f_rn, // llvm.nvvm.d2f.rn - nvvm_d2f_rn_ftz, // llvm.nvvm.d2f.rn.ftz - nvvm_d2f_rp, // llvm.nvvm.d2f.rp - nvvm_d2f_rp_ftz, // llvm.nvvm.d2f.rp.ftz - nvvm_d2f_rz, // llvm.nvvm.d2f.rz - nvvm_d2f_rz_ftz, // llvm.nvvm.d2f.rz.ftz - nvvm_d2i_hi, // llvm.nvvm.d2i.hi - nvvm_d2i_lo, // llvm.nvvm.d2i.lo - nvvm_d2i_rm, // llvm.nvvm.d2i.rm - nvvm_d2i_rn, // llvm.nvvm.d2i.rn - nvvm_d2i_rp, // llvm.nvvm.d2i.rp - nvvm_d2i_rz, // llvm.nvvm.d2i.rz - nvvm_d2ll_rm, // llvm.nvvm.d2ll.rm - nvvm_d2ll_rn, // llvm.nvvm.d2ll.rn - nvvm_d2ll_rp, // llvm.nvvm.d2ll.rp - nvvm_d2ll_rz, // llvm.nvvm.d2ll.rz - nvvm_d2ui_rm, // llvm.nvvm.d2ui.rm - nvvm_d2ui_rn, // llvm.nvvm.d2ui.rn - nvvm_d2ui_rp, // llvm.nvvm.d2ui.rp - nvvm_d2ui_rz, // llvm.nvvm.d2ui.rz - nvvm_d2ull_rm, // llvm.nvvm.d2ull.rm - nvvm_d2ull_rn, // llvm.nvvm.d2ull.rn - nvvm_d2ull_rp, // llvm.nvvm.d2ull.rp - nvvm_d2ull_rz, // llvm.nvvm.d2ull.rz - nvvm_div_approx_f, // llvm.nvvm.div.approx.f - nvvm_div_approx_ftz_f, // llvm.nvvm.div.approx.ftz.f - nvvm_div_rm_d, // llvm.nvvm.div.rm.d - nvvm_div_rm_f, // llvm.nvvm.div.rm.f - nvvm_div_rm_ftz_f, // llvm.nvvm.div.rm.ftz.f - nvvm_div_rn_d, // llvm.nvvm.div.rn.d - nvvm_div_rn_f, // llvm.nvvm.div.rn.f - nvvm_div_rn_ftz_f, // llvm.nvvm.div.rn.ftz.f - nvvm_div_rp_d, // llvm.nvvm.div.rp.d - nvvm_div_rp_f, // llvm.nvvm.div.rp.f - nvvm_div_rp_ftz_f, // llvm.nvvm.div.rp.ftz.f - nvvm_div_rz_d, // llvm.nvvm.div.rz.d - nvvm_div_rz_f, // llvm.nvvm.div.rz.f - nvvm_div_rz_ftz_f, // llvm.nvvm.div.rz.ftz.f - nvvm_ex2_approx_d, // llvm.nvvm.ex2.approx.d - nvvm_ex2_approx_f, // llvm.nvvm.ex2.approx.f - nvvm_ex2_approx_ftz_f, // llvm.nvvm.ex2.approx.ftz.f - nvvm_f2bf16_rn, // llvm.nvvm.f2bf16.rn - nvvm_f2bf16_rn_relu, // llvm.nvvm.f2bf16.rn.relu - nvvm_f2bf16_rz, // llvm.nvvm.f2bf16.rz - nvvm_f2bf16_rz_relu, // llvm.nvvm.f2bf16.rz.relu - nvvm_f2h_rn, // llvm.nvvm.f2h.rn - nvvm_f2h_rn_ftz, // llvm.nvvm.f2h.rn.ftz - nvvm_f2i_rm, // llvm.nvvm.f2i.rm - nvvm_f2i_rm_ftz, // llvm.nvvm.f2i.rm.ftz - nvvm_f2i_rn, // llvm.nvvm.f2i.rn - nvvm_f2i_rn_ftz, // llvm.nvvm.f2i.rn.ftz - nvvm_f2i_rp, // llvm.nvvm.f2i.rp - nvvm_f2i_rp_ftz, // llvm.nvvm.f2i.rp.ftz - nvvm_f2i_rz, // llvm.nvvm.f2i.rz - nvvm_f2i_rz_ftz, // llvm.nvvm.f2i.rz.ftz - nvvm_f2ll_rm, // llvm.nvvm.f2ll.rm - nvvm_f2ll_rm_ftz, // llvm.nvvm.f2ll.rm.ftz - nvvm_f2ll_rn, // llvm.nvvm.f2ll.rn - nvvm_f2ll_rn_ftz, // llvm.nvvm.f2ll.rn.ftz - nvvm_f2ll_rp, // llvm.nvvm.f2ll.rp - nvvm_f2ll_rp_ftz, // llvm.nvvm.f2ll.rp.ftz - nvvm_f2ll_rz, // llvm.nvvm.f2ll.rz - nvvm_f2ll_rz_ftz, // llvm.nvvm.f2ll.rz.ftz - nvvm_f2tf32_rna, // llvm.nvvm.f2tf32.rna - nvvm_f2ui_rm, // llvm.nvvm.f2ui.rm - nvvm_f2ui_rm_ftz, // llvm.nvvm.f2ui.rm.ftz - nvvm_f2ui_rn, // llvm.nvvm.f2ui.rn - nvvm_f2ui_rn_ftz, // llvm.nvvm.f2ui.rn.ftz - nvvm_f2ui_rp, // llvm.nvvm.f2ui.rp - nvvm_f2ui_rp_ftz, // llvm.nvvm.f2ui.rp.ftz - nvvm_f2ui_rz, // llvm.nvvm.f2ui.rz - nvvm_f2ui_rz_ftz, // llvm.nvvm.f2ui.rz.ftz - nvvm_f2ull_rm, // llvm.nvvm.f2ull.rm - nvvm_f2ull_rm_ftz, // llvm.nvvm.f2ull.rm.ftz - nvvm_f2ull_rn, // llvm.nvvm.f2ull.rn - nvvm_f2ull_rn_ftz, // llvm.nvvm.f2ull.rn.ftz - nvvm_f2ull_rp, // llvm.nvvm.f2ull.rp - nvvm_f2ull_rp_ftz, // llvm.nvvm.f2ull.rp.ftz - nvvm_f2ull_rz, // llvm.nvvm.f2ull.rz - nvvm_f2ull_rz_ftz, // llvm.nvvm.f2ull.rz.ftz - nvvm_fabs_d, // llvm.nvvm.fabs.d - nvvm_fabs_f, // llvm.nvvm.fabs.f - nvvm_fabs_ftz_f, // llvm.nvvm.fabs.ftz.f - nvvm_ff2bf16x2_rn, // llvm.nvvm.ff2bf16x2.rn - nvvm_ff2bf16x2_rn_relu, // llvm.nvvm.ff2bf16x2.rn.relu - nvvm_ff2bf16x2_rz, // llvm.nvvm.ff2bf16x2.rz - nvvm_ff2bf16x2_rz_relu, // llvm.nvvm.ff2bf16x2.rz.relu - nvvm_ff2f16x2_rn, // llvm.nvvm.ff2f16x2.rn - nvvm_ff2f16x2_rn_relu, // llvm.nvvm.ff2f16x2.rn.relu - nvvm_ff2f16x2_rz, // llvm.nvvm.ff2f16x2.rz - nvvm_ff2f16x2_rz_relu, // llvm.nvvm.ff2f16x2.rz.relu - nvvm_floor_d, // llvm.nvvm.floor.d - nvvm_floor_f, // llvm.nvvm.floor.f - nvvm_floor_ftz_f, // llvm.nvvm.floor.ftz.f - nvvm_fma_rm_d, // llvm.nvvm.fma.rm.d - nvvm_fma_rm_f, // llvm.nvvm.fma.rm.f - nvvm_fma_rm_ftz_f, // llvm.nvvm.fma.rm.ftz.f - nvvm_fma_rn_d, // llvm.nvvm.fma.rn.d - nvvm_fma_rn_f, // llvm.nvvm.fma.rn.f - nvvm_fma_rn_ftz_f, // llvm.nvvm.fma.rn.ftz.f - nvvm_fma_rp_d, // llvm.nvvm.fma.rp.d - nvvm_fma_rp_f, // llvm.nvvm.fma.rp.f - nvvm_fma_rp_ftz_f, // llvm.nvvm.fma.rp.ftz.f - nvvm_fma_rz_d, // llvm.nvvm.fma.rz.d - nvvm_fma_rz_f, // llvm.nvvm.fma.rz.f - nvvm_fma_rz_ftz_f, // llvm.nvvm.fma.rz.ftz.f - nvvm_fmax_d, // llvm.nvvm.fmax.d - nvvm_fmax_f, // llvm.nvvm.fmax.f - nvvm_fmax_ftz_f, // llvm.nvvm.fmax.ftz.f - nvvm_fmin_d, // llvm.nvvm.fmin.d - nvvm_fmin_f, // llvm.nvvm.fmin.f - nvvm_fmin_ftz_f, // llvm.nvvm.fmin.ftz.f - nvvm_fns, // llvm.nvvm.fns - nvvm_i2d_rm, // llvm.nvvm.i2d.rm - nvvm_i2d_rn, // llvm.nvvm.i2d.rn - nvvm_i2d_rp, // llvm.nvvm.i2d.rp - nvvm_i2d_rz, // llvm.nvvm.i2d.rz - nvvm_i2f_rm, // llvm.nvvm.i2f.rm - nvvm_i2f_rn, // llvm.nvvm.i2f.rn - nvvm_i2f_rp, // llvm.nvvm.i2f.rp - nvvm_i2f_rz, // llvm.nvvm.i2f.rz - nvvm_isspacep_const, // llvm.nvvm.isspacep.const - nvvm_isspacep_global, // llvm.nvvm.isspacep.global - nvvm_isspacep_local, // llvm.nvvm.isspacep.local - nvvm_isspacep_shared, // llvm.nvvm.isspacep.shared - nvvm_istypep_sampler, // llvm.nvvm.istypep.sampler - nvvm_istypep_surface, // llvm.nvvm.istypep.surface - nvvm_istypep_texture, // llvm.nvvm.istypep.texture - nvvm_ldg_global_f, // llvm.nvvm.ldg.global.f - nvvm_ldg_global_i, // llvm.nvvm.ldg.global.i - nvvm_ldg_global_p, // llvm.nvvm.ldg.global.p - nvvm_ldmatrix_sync_aligned_m8n8_x1_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x1.b16 - nvvm_ldmatrix_sync_aligned_m8n8_x1_trans_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x1.trans.b16 - nvvm_ldmatrix_sync_aligned_m8n8_x2_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x2.b16 - nvvm_ldmatrix_sync_aligned_m8n8_x2_trans_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x2.trans.b16 - nvvm_ldmatrix_sync_aligned_m8n8_x4_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x4.b16 - nvvm_ldmatrix_sync_aligned_m8n8_x4_trans_b16, // llvm.nvvm.ldmatrix.sync.aligned.m8n8.x4.trans.b16 - nvvm_ldu_global_f, // llvm.nvvm.ldu.global.f - nvvm_ldu_global_i, // llvm.nvvm.ldu.global.i - nvvm_ldu_global_p, // llvm.nvvm.ldu.global.p - nvvm_lg2_approx_d, // llvm.nvvm.lg2.approx.d - nvvm_lg2_approx_f, // llvm.nvvm.lg2.approx.f - nvvm_lg2_approx_ftz_f, // llvm.nvvm.lg2.approx.ftz.f - nvvm_ll2d_rm, // llvm.nvvm.ll2d.rm - nvvm_ll2d_rn, // llvm.nvvm.ll2d.rn - nvvm_ll2d_rp, // llvm.nvvm.ll2d.rp - nvvm_ll2d_rz, // llvm.nvvm.ll2d.rz - nvvm_ll2f_rm, // llvm.nvvm.ll2f.rm - nvvm_ll2f_rn, // llvm.nvvm.ll2f.rn - nvvm_ll2f_rp, // llvm.nvvm.ll2f.rp - nvvm_ll2f_rz, // llvm.nvvm.ll2f.rz - nvvm_lohi_i2d, // llvm.nvvm.lohi.i2d - nvvm_match_all_sync_i32p, // llvm.nvvm.match.all.sync.i32p - nvvm_match_all_sync_i64p, // llvm.nvvm.match.all.sync.i64p - nvvm_match_any_sync_i32, // llvm.nvvm.match.any.sync.i32 - nvvm_match_any_sync_i64, // llvm.nvvm.match.any.sync.i64 - nvvm_mbarrier_arrive, // llvm.nvvm.mbarrier.arrive - nvvm_mbarrier_arrive_drop, // llvm.nvvm.mbarrier.arrive.drop - nvvm_mbarrier_arrive_drop_noComplete, // llvm.nvvm.mbarrier.arrive.drop.noComplete - nvvm_mbarrier_arrive_drop_noComplete_shared, // llvm.nvvm.mbarrier.arrive.drop.noComplete.shared - nvvm_mbarrier_arrive_drop_shared, // llvm.nvvm.mbarrier.arrive.drop.shared - nvvm_mbarrier_arrive_noComplete, // llvm.nvvm.mbarrier.arrive.noComplete - nvvm_mbarrier_arrive_noComplete_shared, // llvm.nvvm.mbarrier.arrive.noComplete.shared - nvvm_mbarrier_arrive_shared, // llvm.nvvm.mbarrier.arrive.shared - nvvm_mbarrier_init, // llvm.nvvm.mbarrier.init - nvvm_mbarrier_init_shared, // llvm.nvvm.mbarrier.init.shared - nvvm_mbarrier_inval, // llvm.nvvm.mbarrier.inval - nvvm_mbarrier_inval_shared, // llvm.nvvm.mbarrier.inval.shared - nvvm_mbarrier_pending_count, // llvm.nvvm.mbarrier.pending.count - nvvm_mbarrier_test_wait, // llvm.nvvm.mbarrier.test.wait - nvvm_mbarrier_test_wait_shared, // llvm.nvvm.mbarrier.test.wait.shared - nvvm_membar_cta, // llvm.nvvm.membar.cta - nvvm_membar_gl, // llvm.nvvm.membar.gl - nvvm_membar_sys, // llvm.nvvm.membar.sys - nvvm_mma_and_popc_m16n8k128_row_col_b1, // llvm.nvvm.mma.and.popc.m16n8k128.row.col.b1 - nvvm_mma_and_popc_m16n8k256_row_col_b1, // llvm.nvvm.mma.and.popc.m16n8k256.row.col.b1 - nvvm_mma_and_popc_m8n8k128_row_col_b1, // llvm.nvvm.mma.and.popc.m8n8k128.row.col.b1 - nvvm_mma_m16n8k16_row_col_bf16, // llvm.nvvm.mma.m16n8k16.row.col.bf16 - nvvm_mma_m16n8k16_row_col_f16_f16, // llvm.nvvm.mma.m16n8k16.row.col.f16.f16 - nvvm_mma_m16n8k16_row_col_f16_f32, // llvm.nvvm.mma.m16n8k16.row.col.f16.f32 - nvvm_mma_m16n8k16_row_col_f32_f16, // llvm.nvvm.mma.m16n8k16.row.col.f32.f16 - nvvm_mma_m16n8k16_row_col_f32_f32, // llvm.nvvm.mma.m16n8k16.row.col.f32.f32 - nvvm_mma_m16n8k16_row_col_s8, // llvm.nvvm.mma.m16n8k16.row.col.s8 - nvvm_mma_m16n8k16_row_col_s8_u8, // llvm.nvvm.mma.m16n8k16.row.col.s8.u8 - nvvm_mma_m16n8k16_row_col_satfinite_s8, // llvm.nvvm.mma.m16n8k16.row.col.satfinite.s8 - nvvm_mma_m16n8k16_row_col_satfinite_s8_u8, // llvm.nvvm.mma.m16n8k16.row.col.satfinite.s8.u8 - nvvm_mma_m16n8k16_row_col_satfinite_u8, // llvm.nvvm.mma.m16n8k16.row.col.satfinite.u8 - nvvm_mma_m16n8k16_row_col_satfinite_u8_s8, // llvm.nvvm.mma.m16n8k16.row.col.satfinite.u8.s8 - nvvm_mma_m16n8k16_row_col_u8, // llvm.nvvm.mma.m16n8k16.row.col.u8 - nvvm_mma_m16n8k16_row_col_u8_s8, // llvm.nvvm.mma.m16n8k16.row.col.u8.s8 - nvvm_mma_m16n8k32_row_col_s4, // llvm.nvvm.mma.m16n8k32.row.col.s4 - nvvm_mma_m16n8k32_row_col_s4_u4, // llvm.nvvm.mma.m16n8k32.row.col.s4.u4 - nvvm_mma_m16n8k32_row_col_s8, // llvm.nvvm.mma.m16n8k32.row.col.s8 - nvvm_mma_m16n8k32_row_col_s8_u8, // llvm.nvvm.mma.m16n8k32.row.col.s8.u8 - nvvm_mma_m16n8k32_row_col_satfinite_s4, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.s4 - nvvm_mma_m16n8k32_row_col_satfinite_s4_u4, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.s4.u4 - nvvm_mma_m16n8k32_row_col_satfinite_s8, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.s8 - nvvm_mma_m16n8k32_row_col_satfinite_s8_u8, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.s8.u8 - nvvm_mma_m16n8k32_row_col_satfinite_u4, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.u4 - nvvm_mma_m16n8k32_row_col_satfinite_u4_s4, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.u4.s4 - nvvm_mma_m16n8k32_row_col_satfinite_u8, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.u8 - nvvm_mma_m16n8k32_row_col_satfinite_u8_s8, // llvm.nvvm.mma.m16n8k32.row.col.satfinite.u8.s8 - nvvm_mma_m16n8k32_row_col_u4, // llvm.nvvm.mma.m16n8k32.row.col.u4 - nvvm_mma_m16n8k32_row_col_u4_s4, // llvm.nvvm.mma.m16n8k32.row.col.u4.s4 - nvvm_mma_m16n8k32_row_col_u8, // llvm.nvvm.mma.m16n8k32.row.col.u8 - nvvm_mma_m16n8k32_row_col_u8_s8, // llvm.nvvm.mma.m16n8k32.row.col.u8.s8 - nvvm_mma_m16n8k4_row_col_tf32, // llvm.nvvm.mma.m16n8k4.row.col.tf32 - nvvm_mma_m16n8k64_row_col_s4, // llvm.nvvm.mma.m16n8k64.row.col.s4 - nvvm_mma_m16n8k64_row_col_s4_u4, // llvm.nvvm.mma.m16n8k64.row.col.s4.u4 - nvvm_mma_m16n8k64_row_col_satfinite_s4, // llvm.nvvm.mma.m16n8k64.row.col.satfinite.s4 - nvvm_mma_m16n8k64_row_col_satfinite_s4_u4, // llvm.nvvm.mma.m16n8k64.row.col.satfinite.s4.u4 - nvvm_mma_m16n8k64_row_col_satfinite_u4, // llvm.nvvm.mma.m16n8k64.row.col.satfinite.u4 - nvvm_mma_m16n8k64_row_col_satfinite_u4_s4, // llvm.nvvm.mma.m16n8k64.row.col.satfinite.u4.s4 - nvvm_mma_m16n8k64_row_col_u4, // llvm.nvvm.mma.m16n8k64.row.col.u4 - nvvm_mma_m16n8k64_row_col_u4_s4, // llvm.nvvm.mma.m16n8k64.row.col.u4.s4 - nvvm_mma_m16n8k8_row_col_bf16, // llvm.nvvm.mma.m16n8k8.row.col.bf16 - nvvm_mma_m16n8k8_row_col_f16_f16, // llvm.nvvm.mma.m16n8k8.row.col.f16.f16 - nvvm_mma_m16n8k8_row_col_f32_f32, // llvm.nvvm.mma.m16n8k8.row.col.f32.f32 - nvvm_mma_m16n8k8_row_col_tf32, // llvm.nvvm.mma.m16n8k8.row.col.tf32 - nvvm_mma_m8n8k16_row_col_s8, // llvm.nvvm.mma.m8n8k16.row.col.s8 - nvvm_mma_m8n8k16_row_col_s8_u8, // llvm.nvvm.mma.m8n8k16.row.col.s8.u8 - nvvm_mma_m8n8k16_row_col_satfinite_s8, // llvm.nvvm.mma.m8n8k16.row.col.satfinite.s8 - nvvm_mma_m8n8k16_row_col_satfinite_s8_u8, // llvm.nvvm.mma.m8n8k16.row.col.satfinite.s8.u8 - nvvm_mma_m8n8k16_row_col_satfinite_u8, // llvm.nvvm.mma.m8n8k16.row.col.satfinite.u8 - nvvm_mma_m8n8k16_row_col_satfinite_u8_s8, // llvm.nvvm.mma.m8n8k16.row.col.satfinite.u8.s8 - nvvm_mma_m8n8k16_row_col_u8, // llvm.nvvm.mma.m8n8k16.row.col.u8 - nvvm_mma_m8n8k16_row_col_u8_s8, // llvm.nvvm.mma.m8n8k16.row.col.u8.s8 - nvvm_mma_m8n8k32_row_col_s4, // llvm.nvvm.mma.m8n8k32.row.col.s4 - nvvm_mma_m8n8k32_row_col_s4_u4, // llvm.nvvm.mma.m8n8k32.row.col.s4.u4 - nvvm_mma_m8n8k32_row_col_satfinite_s4, // llvm.nvvm.mma.m8n8k32.row.col.satfinite.s4 - nvvm_mma_m8n8k32_row_col_satfinite_s4_u4, // llvm.nvvm.mma.m8n8k32.row.col.satfinite.s4.u4 - nvvm_mma_m8n8k32_row_col_satfinite_u4, // llvm.nvvm.mma.m8n8k32.row.col.satfinite.u4 - nvvm_mma_m8n8k32_row_col_satfinite_u4_s4, // llvm.nvvm.mma.m8n8k32.row.col.satfinite.u4.s4 - nvvm_mma_m8n8k32_row_col_u4, // llvm.nvvm.mma.m8n8k32.row.col.u4 - nvvm_mma_m8n8k32_row_col_u4_s4, // llvm.nvvm.mma.m8n8k32.row.col.u4.s4 - nvvm_mma_m8n8k4_col_col_f16_f16, // llvm.nvvm.mma.m8n8k4.col.col.f16.f16 - nvvm_mma_m8n8k4_col_col_f32_f16, // llvm.nvvm.mma.m8n8k4.col.col.f32.f16 - nvvm_mma_m8n8k4_col_col_f32_f32, // llvm.nvvm.mma.m8n8k4.col.col.f32.f32 - nvvm_mma_m8n8k4_col_row_f16_f16, // llvm.nvvm.mma.m8n8k4.col.row.f16.f16 - nvvm_mma_m8n8k4_col_row_f32_f16, // llvm.nvvm.mma.m8n8k4.col.row.f32.f16 - nvvm_mma_m8n8k4_col_row_f32_f32, // llvm.nvvm.mma.m8n8k4.col.row.f32.f32 - nvvm_mma_m8n8k4_row_col_f16_f16, // llvm.nvvm.mma.m8n8k4.row.col.f16.f16 - nvvm_mma_m8n8k4_row_col_f32_f16, // llvm.nvvm.mma.m8n8k4.row.col.f32.f16 - nvvm_mma_m8n8k4_row_col_f32_f32, // llvm.nvvm.mma.m8n8k4.row.col.f32.f32 - nvvm_mma_m8n8k4_row_col_f64, // llvm.nvvm.mma.m8n8k4.row.col.f64 - nvvm_mma_m8n8k4_row_row_f16_f16, // llvm.nvvm.mma.m8n8k4.row.row.f16.f16 - nvvm_mma_m8n8k4_row_row_f32_f16, // llvm.nvvm.mma.m8n8k4.row.row.f32.f16 - nvvm_mma_m8n8k4_row_row_f32_f32, // llvm.nvvm.mma.m8n8k4.row.row.f32.f32 - nvvm_mma_xor_popc_m16n8k128_row_col_b1, // llvm.nvvm.mma.xor.popc.m16n8k128.row.col.b1 - nvvm_mma_xor_popc_m16n8k256_row_col_b1, // llvm.nvvm.mma.xor.popc.m16n8k256.row.col.b1 - nvvm_mma_xor_popc_m8n8k128_row_col_b1, // llvm.nvvm.mma.xor.popc.m8n8k128.row.col.b1 - nvvm_move_double, // llvm.nvvm.move.double - nvvm_move_float, // llvm.nvvm.move.float - nvvm_move_i16, // llvm.nvvm.move.i16 - nvvm_move_i32, // llvm.nvvm.move.i32 - nvvm_move_i64, // llvm.nvvm.move.i64 - nvvm_move_ptr, // llvm.nvvm.move.ptr - nvvm_mul_rm_d, // llvm.nvvm.mul.rm.d - nvvm_mul_rm_f, // llvm.nvvm.mul.rm.f - nvvm_mul_rm_ftz_f, // llvm.nvvm.mul.rm.ftz.f - nvvm_mul_rn_d, // llvm.nvvm.mul.rn.d - nvvm_mul_rn_f, // llvm.nvvm.mul.rn.f - nvvm_mul_rn_ftz_f, // llvm.nvvm.mul.rn.ftz.f - nvvm_mul_rp_d, // llvm.nvvm.mul.rp.d - nvvm_mul_rp_f, // llvm.nvvm.mul.rp.f - nvvm_mul_rp_ftz_f, // llvm.nvvm.mul.rp.ftz.f - nvvm_mul_rz_d, // llvm.nvvm.mul.rz.d - nvvm_mul_rz_f, // llvm.nvvm.mul.rz.f - nvvm_mul_rz_ftz_f, // llvm.nvvm.mul.rz.ftz.f - nvvm_mul24_i, // llvm.nvvm.mul24.i - nvvm_mul24_ui, // llvm.nvvm.mul24.ui - nvvm_mulhi_i, // llvm.nvvm.mulhi.i - nvvm_mulhi_ll, // llvm.nvvm.mulhi.ll - nvvm_mulhi_ui, // llvm.nvvm.mulhi.ui - nvvm_mulhi_ull, // llvm.nvvm.mulhi.ull - nvvm_prmt, // llvm.nvvm.prmt - nvvm_ptr_constant_to_gen, // llvm.nvvm.ptr.constant.to.gen - nvvm_ptr_gen_to_constant, // llvm.nvvm.ptr.gen.to.constant - nvvm_ptr_gen_to_global, // llvm.nvvm.ptr.gen.to.global - nvvm_ptr_gen_to_local, // llvm.nvvm.ptr.gen.to.local - nvvm_ptr_gen_to_param, // llvm.nvvm.ptr.gen.to.param - nvvm_ptr_gen_to_shared, // llvm.nvvm.ptr.gen.to.shared - nvvm_ptr_global_to_gen, // llvm.nvvm.ptr.global.to.gen - nvvm_ptr_local_to_gen, // llvm.nvvm.ptr.local.to.gen - nvvm_ptr_shared_to_gen, // llvm.nvvm.ptr.shared.to.gen - nvvm_rcp_approx_ftz_d, // llvm.nvvm.rcp.approx.ftz.d - nvvm_rcp_rm_d, // llvm.nvvm.rcp.rm.d - nvvm_rcp_rm_f, // llvm.nvvm.rcp.rm.f - nvvm_rcp_rm_ftz_f, // llvm.nvvm.rcp.rm.ftz.f - nvvm_rcp_rn_d, // llvm.nvvm.rcp.rn.d - nvvm_rcp_rn_f, // llvm.nvvm.rcp.rn.f - nvvm_rcp_rn_ftz_f, // llvm.nvvm.rcp.rn.ftz.f - nvvm_rcp_rp_d, // llvm.nvvm.rcp.rp.d - nvvm_rcp_rp_f, // llvm.nvvm.rcp.rp.f - nvvm_rcp_rp_ftz_f, // llvm.nvvm.rcp.rp.ftz.f - nvvm_rcp_rz_d, // llvm.nvvm.rcp.rz.d - nvvm_rcp_rz_f, // llvm.nvvm.rcp.rz.f - nvvm_rcp_rz_ftz_f, // llvm.nvvm.rcp.rz.ftz.f - nvvm_read_ptx_sreg_clock, // llvm.nvvm.read.ptx.sreg.clock - nvvm_read_ptx_sreg_clock64, // llvm.nvvm.read.ptx.sreg.clock64 - nvvm_read_ptx_sreg_ctaid_w, // llvm.nvvm.read.ptx.sreg.ctaid.w - nvvm_read_ptx_sreg_ctaid_x, // llvm.nvvm.read.ptx.sreg.ctaid.x - nvvm_read_ptx_sreg_ctaid_y, // llvm.nvvm.read.ptx.sreg.ctaid.y - nvvm_read_ptx_sreg_ctaid_z, // llvm.nvvm.read.ptx.sreg.ctaid.z - nvvm_read_ptx_sreg_envreg0, // llvm.nvvm.read.ptx.sreg.envreg0 - nvvm_read_ptx_sreg_envreg1, // llvm.nvvm.read.ptx.sreg.envreg1 - nvvm_read_ptx_sreg_envreg10, // llvm.nvvm.read.ptx.sreg.envreg10 - nvvm_read_ptx_sreg_envreg11, // llvm.nvvm.read.ptx.sreg.envreg11 - nvvm_read_ptx_sreg_envreg12, // llvm.nvvm.read.ptx.sreg.envreg12 - nvvm_read_ptx_sreg_envreg13, // llvm.nvvm.read.ptx.sreg.envreg13 - nvvm_read_ptx_sreg_envreg14, // llvm.nvvm.read.ptx.sreg.envreg14 - nvvm_read_ptx_sreg_envreg15, // llvm.nvvm.read.ptx.sreg.envreg15 - nvvm_read_ptx_sreg_envreg16, // llvm.nvvm.read.ptx.sreg.envreg16 - nvvm_read_ptx_sreg_envreg17, // llvm.nvvm.read.ptx.sreg.envreg17 - nvvm_read_ptx_sreg_envreg18, // llvm.nvvm.read.ptx.sreg.envreg18 - nvvm_read_ptx_sreg_envreg19, // llvm.nvvm.read.ptx.sreg.envreg19 - nvvm_read_ptx_sreg_envreg2, // llvm.nvvm.read.ptx.sreg.envreg2 - nvvm_read_ptx_sreg_envreg20, // llvm.nvvm.read.ptx.sreg.envreg20 - nvvm_read_ptx_sreg_envreg21, // llvm.nvvm.read.ptx.sreg.envreg21 - nvvm_read_ptx_sreg_envreg22, // llvm.nvvm.read.ptx.sreg.envreg22 - nvvm_read_ptx_sreg_envreg23, // llvm.nvvm.read.ptx.sreg.envreg23 - nvvm_read_ptx_sreg_envreg24, // llvm.nvvm.read.ptx.sreg.envreg24 - nvvm_read_ptx_sreg_envreg25, // llvm.nvvm.read.ptx.sreg.envreg25 - nvvm_read_ptx_sreg_envreg26, // llvm.nvvm.read.ptx.sreg.envreg26 - nvvm_read_ptx_sreg_envreg27, // llvm.nvvm.read.ptx.sreg.envreg27 - nvvm_read_ptx_sreg_envreg28, // llvm.nvvm.read.ptx.sreg.envreg28 - nvvm_read_ptx_sreg_envreg29, // llvm.nvvm.read.ptx.sreg.envreg29 - nvvm_read_ptx_sreg_envreg3, // llvm.nvvm.read.ptx.sreg.envreg3 - nvvm_read_ptx_sreg_envreg30, // llvm.nvvm.read.ptx.sreg.envreg30 - nvvm_read_ptx_sreg_envreg31, // llvm.nvvm.read.ptx.sreg.envreg31 - nvvm_read_ptx_sreg_envreg4, // llvm.nvvm.read.ptx.sreg.envreg4 - nvvm_read_ptx_sreg_envreg5, // llvm.nvvm.read.ptx.sreg.envreg5 - nvvm_read_ptx_sreg_envreg6, // llvm.nvvm.read.ptx.sreg.envreg6 - nvvm_read_ptx_sreg_envreg7, // llvm.nvvm.read.ptx.sreg.envreg7 - nvvm_read_ptx_sreg_envreg8, // llvm.nvvm.read.ptx.sreg.envreg8 - nvvm_read_ptx_sreg_envreg9, // llvm.nvvm.read.ptx.sreg.envreg9 - nvvm_read_ptx_sreg_gridid, // llvm.nvvm.read.ptx.sreg.gridid - nvvm_read_ptx_sreg_laneid, // llvm.nvvm.read.ptx.sreg.laneid - nvvm_read_ptx_sreg_lanemask_eq, // llvm.nvvm.read.ptx.sreg.lanemask.eq - nvvm_read_ptx_sreg_lanemask_ge, // llvm.nvvm.read.ptx.sreg.lanemask.ge - nvvm_read_ptx_sreg_lanemask_gt, // llvm.nvvm.read.ptx.sreg.lanemask.gt - nvvm_read_ptx_sreg_lanemask_le, // llvm.nvvm.read.ptx.sreg.lanemask.le - nvvm_read_ptx_sreg_lanemask_lt, // llvm.nvvm.read.ptx.sreg.lanemask.lt - nvvm_read_ptx_sreg_nctaid_w, // llvm.nvvm.read.ptx.sreg.nctaid.w - nvvm_read_ptx_sreg_nctaid_x, // llvm.nvvm.read.ptx.sreg.nctaid.x - nvvm_read_ptx_sreg_nctaid_y, // llvm.nvvm.read.ptx.sreg.nctaid.y - nvvm_read_ptx_sreg_nctaid_z, // llvm.nvvm.read.ptx.sreg.nctaid.z - nvvm_read_ptx_sreg_nsmid, // llvm.nvvm.read.ptx.sreg.nsmid - nvvm_read_ptx_sreg_ntid_w, // llvm.nvvm.read.ptx.sreg.ntid.w - nvvm_read_ptx_sreg_ntid_x, // llvm.nvvm.read.ptx.sreg.ntid.x - nvvm_read_ptx_sreg_ntid_y, // llvm.nvvm.read.ptx.sreg.ntid.y - nvvm_read_ptx_sreg_ntid_z, // llvm.nvvm.read.ptx.sreg.ntid.z - nvvm_read_ptx_sreg_nwarpid, // llvm.nvvm.read.ptx.sreg.nwarpid - nvvm_read_ptx_sreg_pm0, // llvm.nvvm.read.ptx.sreg.pm0 - nvvm_read_ptx_sreg_pm1, // llvm.nvvm.read.ptx.sreg.pm1 - nvvm_read_ptx_sreg_pm2, // llvm.nvvm.read.ptx.sreg.pm2 - nvvm_read_ptx_sreg_pm3, // llvm.nvvm.read.ptx.sreg.pm3 - nvvm_read_ptx_sreg_smid, // llvm.nvvm.read.ptx.sreg.smid - nvvm_read_ptx_sreg_tid_w, // llvm.nvvm.read.ptx.sreg.tid.w - nvvm_read_ptx_sreg_tid_x, // llvm.nvvm.read.ptx.sreg.tid.x - nvvm_read_ptx_sreg_tid_y, // llvm.nvvm.read.ptx.sreg.tid.y - nvvm_read_ptx_sreg_tid_z, // llvm.nvvm.read.ptx.sreg.tid.z - nvvm_read_ptx_sreg_warpid, // llvm.nvvm.read.ptx.sreg.warpid - nvvm_read_ptx_sreg_warpsize, // llvm.nvvm.read.ptx.sreg.warpsize - nvvm_redux_sync_add, // llvm.nvvm.redux.sync.add - nvvm_redux_sync_and, // llvm.nvvm.redux.sync.and - nvvm_redux_sync_max, // llvm.nvvm.redux.sync.max - nvvm_redux_sync_min, // llvm.nvvm.redux.sync.min - nvvm_redux_sync_or, // llvm.nvvm.redux.sync.or - nvvm_redux_sync_umax, // llvm.nvvm.redux.sync.umax - nvvm_redux_sync_umin, // llvm.nvvm.redux.sync.umin - nvvm_redux_sync_xor, // llvm.nvvm.redux.sync.xor - nvvm_reflect, // llvm.nvvm.reflect - nvvm_rotate_b32, // llvm.nvvm.rotate.b32 - nvvm_rotate_b64, // llvm.nvvm.rotate.b64 - nvvm_rotate_right_b64, // llvm.nvvm.rotate.right.b64 - nvvm_round_d, // llvm.nvvm.round.d - nvvm_round_f, // llvm.nvvm.round.f - nvvm_round_ftz_f, // llvm.nvvm.round.ftz.f - nvvm_rsqrt_approx_d, // llvm.nvvm.rsqrt.approx.d - nvvm_rsqrt_approx_f, // llvm.nvvm.rsqrt.approx.f - nvvm_rsqrt_approx_ftz_f, // llvm.nvvm.rsqrt.approx.ftz.f - nvvm_sad_i, // llvm.nvvm.sad.i - nvvm_sad_ui, // llvm.nvvm.sad.ui - nvvm_saturate_d, // llvm.nvvm.saturate.d - nvvm_saturate_f, // llvm.nvvm.saturate.f - nvvm_saturate_ftz_f, // llvm.nvvm.saturate.ftz.f - nvvm_shfl_bfly_f32, // llvm.nvvm.shfl.bfly.f32 - nvvm_shfl_bfly_f32p, // llvm.nvvm.shfl.bfly.f32p - nvvm_shfl_bfly_i32, // llvm.nvvm.shfl.bfly.i32 - nvvm_shfl_bfly_i32p, // llvm.nvvm.shfl.bfly.i32p - nvvm_shfl_down_f32, // llvm.nvvm.shfl.down.f32 - nvvm_shfl_down_f32p, // llvm.nvvm.shfl.down.f32p - nvvm_shfl_down_i32, // llvm.nvvm.shfl.down.i32 - nvvm_shfl_down_i32p, // llvm.nvvm.shfl.down.i32p - nvvm_shfl_idx_f32, // llvm.nvvm.shfl.idx.f32 - nvvm_shfl_idx_f32p, // llvm.nvvm.shfl.idx.f32p - nvvm_shfl_idx_i32, // llvm.nvvm.shfl.idx.i32 - nvvm_shfl_idx_i32p, // llvm.nvvm.shfl.idx.i32p - nvvm_shfl_sync_bfly_f32, // llvm.nvvm.shfl.sync.bfly.f32 - nvvm_shfl_sync_bfly_f32p, // llvm.nvvm.shfl.sync.bfly.f32p - nvvm_shfl_sync_bfly_i32, // llvm.nvvm.shfl.sync.bfly.i32 - nvvm_shfl_sync_bfly_i32p, // llvm.nvvm.shfl.sync.bfly.i32p - nvvm_shfl_sync_down_f32, // llvm.nvvm.shfl.sync.down.f32 - nvvm_shfl_sync_down_f32p, // llvm.nvvm.shfl.sync.down.f32p - nvvm_shfl_sync_down_i32, // llvm.nvvm.shfl.sync.down.i32 - nvvm_shfl_sync_down_i32p, // llvm.nvvm.shfl.sync.down.i32p - nvvm_shfl_sync_idx_f32, // llvm.nvvm.shfl.sync.idx.f32 - nvvm_shfl_sync_idx_f32p, // llvm.nvvm.shfl.sync.idx.f32p - nvvm_shfl_sync_idx_i32, // llvm.nvvm.shfl.sync.idx.i32 - nvvm_shfl_sync_idx_i32p, // llvm.nvvm.shfl.sync.idx.i32p - nvvm_shfl_sync_up_f32, // llvm.nvvm.shfl.sync.up.f32 - nvvm_shfl_sync_up_f32p, // llvm.nvvm.shfl.sync.up.f32p - nvvm_shfl_sync_up_i32, // llvm.nvvm.shfl.sync.up.i32 - nvvm_shfl_sync_up_i32p, // llvm.nvvm.shfl.sync.up.i32p - nvvm_shfl_up_f32, // llvm.nvvm.shfl.up.f32 - nvvm_shfl_up_f32p, // llvm.nvvm.shfl.up.f32p - nvvm_shfl_up_i32, // llvm.nvvm.shfl.up.i32 - nvvm_shfl_up_i32p, // llvm.nvvm.shfl.up.i32p - nvvm_sin_approx_f, // llvm.nvvm.sin.approx.f - nvvm_sin_approx_ftz_f, // llvm.nvvm.sin.approx.ftz.f - nvvm_sqrt_approx_f, // llvm.nvvm.sqrt.approx.f - nvvm_sqrt_approx_ftz_f, // llvm.nvvm.sqrt.approx.ftz.f - nvvm_sqrt_f, // llvm.nvvm.sqrt.f - nvvm_sqrt_rm_d, // llvm.nvvm.sqrt.rm.d - nvvm_sqrt_rm_f, // llvm.nvvm.sqrt.rm.f - nvvm_sqrt_rm_ftz_f, // llvm.nvvm.sqrt.rm.ftz.f - nvvm_sqrt_rn_d, // llvm.nvvm.sqrt.rn.d - nvvm_sqrt_rn_f, // llvm.nvvm.sqrt.rn.f - nvvm_sqrt_rn_ftz_f, // llvm.nvvm.sqrt.rn.ftz.f - nvvm_sqrt_rp_d, // llvm.nvvm.sqrt.rp.d - nvvm_sqrt_rp_f, // llvm.nvvm.sqrt.rp.f - nvvm_sqrt_rp_ftz_f, // llvm.nvvm.sqrt.rp.ftz.f - nvvm_sqrt_rz_d, // llvm.nvvm.sqrt.rz.d - nvvm_sqrt_rz_f, // llvm.nvvm.sqrt.rz.f - nvvm_sqrt_rz_ftz_f, // llvm.nvvm.sqrt.rz.ftz.f - nvvm_suld_1d_array_i16_clamp, // llvm.nvvm.suld.1d.array.i16.clamp - nvvm_suld_1d_array_i16_trap, // llvm.nvvm.suld.1d.array.i16.trap - nvvm_suld_1d_array_i16_zero, // llvm.nvvm.suld.1d.array.i16.zero - nvvm_suld_1d_array_i32_clamp, // llvm.nvvm.suld.1d.array.i32.clamp - nvvm_suld_1d_array_i32_trap, // llvm.nvvm.suld.1d.array.i32.trap - nvvm_suld_1d_array_i32_zero, // llvm.nvvm.suld.1d.array.i32.zero - nvvm_suld_1d_array_i64_clamp, // llvm.nvvm.suld.1d.array.i64.clamp - nvvm_suld_1d_array_i64_trap, // llvm.nvvm.suld.1d.array.i64.trap - nvvm_suld_1d_array_i64_zero, // llvm.nvvm.suld.1d.array.i64.zero - nvvm_suld_1d_array_i8_clamp, // llvm.nvvm.suld.1d.array.i8.clamp - nvvm_suld_1d_array_i8_trap, // llvm.nvvm.suld.1d.array.i8.trap - nvvm_suld_1d_array_i8_zero, // llvm.nvvm.suld.1d.array.i8.zero - nvvm_suld_1d_array_v2i16_clamp, // llvm.nvvm.suld.1d.array.v2i16.clamp - nvvm_suld_1d_array_v2i16_trap, // llvm.nvvm.suld.1d.array.v2i16.trap - nvvm_suld_1d_array_v2i16_zero, // llvm.nvvm.suld.1d.array.v2i16.zero - nvvm_suld_1d_array_v2i32_clamp, // llvm.nvvm.suld.1d.array.v2i32.clamp - nvvm_suld_1d_array_v2i32_trap, // llvm.nvvm.suld.1d.array.v2i32.trap - nvvm_suld_1d_array_v2i32_zero, // llvm.nvvm.suld.1d.array.v2i32.zero - nvvm_suld_1d_array_v2i64_clamp, // llvm.nvvm.suld.1d.array.v2i64.clamp - nvvm_suld_1d_array_v2i64_trap, // llvm.nvvm.suld.1d.array.v2i64.trap - nvvm_suld_1d_array_v2i64_zero, // llvm.nvvm.suld.1d.array.v2i64.zero - nvvm_suld_1d_array_v2i8_clamp, // llvm.nvvm.suld.1d.array.v2i8.clamp - nvvm_suld_1d_array_v2i8_trap, // llvm.nvvm.suld.1d.array.v2i8.trap - nvvm_suld_1d_array_v2i8_zero, // llvm.nvvm.suld.1d.array.v2i8.zero - nvvm_suld_1d_array_v4i16_clamp, // llvm.nvvm.suld.1d.array.v4i16.clamp - nvvm_suld_1d_array_v4i16_trap, // llvm.nvvm.suld.1d.array.v4i16.trap - nvvm_suld_1d_array_v4i16_zero, // llvm.nvvm.suld.1d.array.v4i16.zero - nvvm_suld_1d_array_v4i32_clamp, // llvm.nvvm.suld.1d.array.v4i32.clamp - nvvm_suld_1d_array_v4i32_trap, // llvm.nvvm.suld.1d.array.v4i32.trap - nvvm_suld_1d_array_v4i32_zero, // llvm.nvvm.suld.1d.array.v4i32.zero - nvvm_suld_1d_array_v4i8_clamp, // llvm.nvvm.suld.1d.array.v4i8.clamp - nvvm_suld_1d_array_v4i8_trap, // llvm.nvvm.suld.1d.array.v4i8.trap - nvvm_suld_1d_array_v4i8_zero, // llvm.nvvm.suld.1d.array.v4i8.zero - nvvm_suld_1d_i16_clamp, // llvm.nvvm.suld.1d.i16.clamp - nvvm_suld_1d_i16_trap, // llvm.nvvm.suld.1d.i16.trap - nvvm_suld_1d_i16_zero, // llvm.nvvm.suld.1d.i16.zero - nvvm_suld_1d_i32_clamp, // llvm.nvvm.suld.1d.i32.clamp - nvvm_suld_1d_i32_trap, // llvm.nvvm.suld.1d.i32.trap - nvvm_suld_1d_i32_zero, // llvm.nvvm.suld.1d.i32.zero - nvvm_suld_1d_i64_clamp, // llvm.nvvm.suld.1d.i64.clamp - nvvm_suld_1d_i64_trap, // llvm.nvvm.suld.1d.i64.trap - nvvm_suld_1d_i64_zero, // llvm.nvvm.suld.1d.i64.zero - nvvm_suld_1d_i8_clamp, // llvm.nvvm.suld.1d.i8.clamp - nvvm_suld_1d_i8_trap, // llvm.nvvm.suld.1d.i8.trap - nvvm_suld_1d_i8_zero, // llvm.nvvm.suld.1d.i8.zero - nvvm_suld_1d_v2i16_clamp, // llvm.nvvm.suld.1d.v2i16.clamp - nvvm_suld_1d_v2i16_trap, // llvm.nvvm.suld.1d.v2i16.trap - nvvm_suld_1d_v2i16_zero, // llvm.nvvm.suld.1d.v2i16.zero - nvvm_suld_1d_v2i32_clamp, // llvm.nvvm.suld.1d.v2i32.clamp - nvvm_suld_1d_v2i32_trap, // llvm.nvvm.suld.1d.v2i32.trap - nvvm_suld_1d_v2i32_zero, // llvm.nvvm.suld.1d.v2i32.zero - nvvm_suld_1d_v2i64_clamp, // llvm.nvvm.suld.1d.v2i64.clamp - nvvm_suld_1d_v2i64_trap, // llvm.nvvm.suld.1d.v2i64.trap - nvvm_suld_1d_v2i64_zero, // llvm.nvvm.suld.1d.v2i64.zero - nvvm_suld_1d_v2i8_clamp, // llvm.nvvm.suld.1d.v2i8.clamp - nvvm_suld_1d_v2i8_trap, // llvm.nvvm.suld.1d.v2i8.trap - nvvm_suld_1d_v2i8_zero, // llvm.nvvm.suld.1d.v2i8.zero - nvvm_suld_1d_v4i16_clamp, // llvm.nvvm.suld.1d.v4i16.clamp - nvvm_suld_1d_v4i16_trap, // llvm.nvvm.suld.1d.v4i16.trap - nvvm_suld_1d_v4i16_zero, // llvm.nvvm.suld.1d.v4i16.zero - nvvm_suld_1d_v4i32_clamp, // llvm.nvvm.suld.1d.v4i32.clamp - nvvm_suld_1d_v4i32_trap, // llvm.nvvm.suld.1d.v4i32.trap - nvvm_suld_1d_v4i32_zero, // llvm.nvvm.suld.1d.v4i32.zero - nvvm_suld_1d_v4i8_clamp, // llvm.nvvm.suld.1d.v4i8.clamp - nvvm_suld_1d_v4i8_trap, // llvm.nvvm.suld.1d.v4i8.trap - nvvm_suld_1d_v4i8_zero, // llvm.nvvm.suld.1d.v4i8.zero - nvvm_suld_2d_array_i16_clamp, // llvm.nvvm.suld.2d.array.i16.clamp - nvvm_suld_2d_array_i16_trap, // llvm.nvvm.suld.2d.array.i16.trap - nvvm_suld_2d_array_i16_zero, // llvm.nvvm.suld.2d.array.i16.zero - nvvm_suld_2d_array_i32_clamp, // llvm.nvvm.suld.2d.array.i32.clamp - nvvm_suld_2d_array_i32_trap, // llvm.nvvm.suld.2d.array.i32.trap - nvvm_suld_2d_array_i32_zero, // llvm.nvvm.suld.2d.array.i32.zero - nvvm_suld_2d_array_i64_clamp, // llvm.nvvm.suld.2d.array.i64.clamp - nvvm_suld_2d_array_i64_trap, // llvm.nvvm.suld.2d.array.i64.trap - nvvm_suld_2d_array_i64_zero, // llvm.nvvm.suld.2d.array.i64.zero - nvvm_suld_2d_array_i8_clamp, // llvm.nvvm.suld.2d.array.i8.clamp - nvvm_suld_2d_array_i8_trap, // llvm.nvvm.suld.2d.array.i8.trap - nvvm_suld_2d_array_i8_zero, // llvm.nvvm.suld.2d.array.i8.zero - nvvm_suld_2d_array_v2i16_clamp, // llvm.nvvm.suld.2d.array.v2i16.clamp - nvvm_suld_2d_array_v2i16_trap, // llvm.nvvm.suld.2d.array.v2i16.trap - nvvm_suld_2d_array_v2i16_zero, // llvm.nvvm.suld.2d.array.v2i16.zero - nvvm_suld_2d_array_v2i32_clamp, // llvm.nvvm.suld.2d.array.v2i32.clamp - nvvm_suld_2d_array_v2i32_trap, // llvm.nvvm.suld.2d.array.v2i32.trap - nvvm_suld_2d_array_v2i32_zero, // llvm.nvvm.suld.2d.array.v2i32.zero - nvvm_suld_2d_array_v2i64_clamp, // llvm.nvvm.suld.2d.array.v2i64.clamp - nvvm_suld_2d_array_v2i64_trap, // llvm.nvvm.suld.2d.array.v2i64.trap - nvvm_suld_2d_array_v2i64_zero, // llvm.nvvm.suld.2d.array.v2i64.zero - nvvm_suld_2d_array_v2i8_clamp, // llvm.nvvm.suld.2d.array.v2i8.clamp - nvvm_suld_2d_array_v2i8_trap, // llvm.nvvm.suld.2d.array.v2i8.trap - nvvm_suld_2d_array_v2i8_zero, // llvm.nvvm.suld.2d.array.v2i8.zero - nvvm_suld_2d_array_v4i16_clamp, // llvm.nvvm.suld.2d.array.v4i16.clamp - nvvm_suld_2d_array_v4i16_trap, // llvm.nvvm.suld.2d.array.v4i16.trap - nvvm_suld_2d_array_v4i16_zero, // llvm.nvvm.suld.2d.array.v4i16.zero - nvvm_suld_2d_array_v4i32_clamp, // llvm.nvvm.suld.2d.array.v4i32.clamp - nvvm_suld_2d_array_v4i32_trap, // llvm.nvvm.suld.2d.array.v4i32.trap - nvvm_suld_2d_array_v4i32_zero, // llvm.nvvm.suld.2d.array.v4i32.zero - nvvm_suld_2d_array_v4i8_clamp, // llvm.nvvm.suld.2d.array.v4i8.clamp - nvvm_suld_2d_array_v4i8_trap, // llvm.nvvm.suld.2d.array.v4i8.trap - nvvm_suld_2d_array_v4i8_zero, // llvm.nvvm.suld.2d.array.v4i8.zero - nvvm_suld_2d_i16_clamp, // llvm.nvvm.suld.2d.i16.clamp - nvvm_suld_2d_i16_trap, // llvm.nvvm.suld.2d.i16.trap - nvvm_suld_2d_i16_zero, // llvm.nvvm.suld.2d.i16.zero - nvvm_suld_2d_i32_clamp, // llvm.nvvm.suld.2d.i32.clamp - nvvm_suld_2d_i32_trap, // llvm.nvvm.suld.2d.i32.trap - nvvm_suld_2d_i32_zero, // llvm.nvvm.suld.2d.i32.zero - nvvm_suld_2d_i64_clamp, // llvm.nvvm.suld.2d.i64.clamp - nvvm_suld_2d_i64_trap, // llvm.nvvm.suld.2d.i64.trap - nvvm_suld_2d_i64_zero, // llvm.nvvm.suld.2d.i64.zero - nvvm_suld_2d_i8_clamp, // llvm.nvvm.suld.2d.i8.clamp - nvvm_suld_2d_i8_trap, // llvm.nvvm.suld.2d.i8.trap - nvvm_suld_2d_i8_zero, // llvm.nvvm.suld.2d.i8.zero - nvvm_suld_2d_v2i16_clamp, // llvm.nvvm.suld.2d.v2i16.clamp - nvvm_suld_2d_v2i16_trap, // llvm.nvvm.suld.2d.v2i16.trap - nvvm_suld_2d_v2i16_zero, // llvm.nvvm.suld.2d.v2i16.zero - nvvm_suld_2d_v2i32_clamp, // llvm.nvvm.suld.2d.v2i32.clamp - nvvm_suld_2d_v2i32_trap, // llvm.nvvm.suld.2d.v2i32.trap - nvvm_suld_2d_v2i32_zero, // llvm.nvvm.suld.2d.v2i32.zero - nvvm_suld_2d_v2i64_clamp, // llvm.nvvm.suld.2d.v2i64.clamp - nvvm_suld_2d_v2i64_trap, // llvm.nvvm.suld.2d.v2i64.trap - nvvm_suld_2d_v2i64_zero, // llvm.nvvm.suld.2d.v2i64.zero - nvvm_suld_2d_v2i8_clamp, // llvm.nvvm.suld.2d.v2i8.clamp - nvvm_suld_2d_v2i8_trap, // llvm.nvvm.suld.2d.v2i8.trap - nvvm_suld_2d_v2i8_zero, // llvm.nvvm.suld.2d.v2i8.zero - nvvm_suld_2d_v4i16_clamp, // llvm.nvvm.suld.2d.v4i16.clamp - nvvm_suld_2d_v4i16_trap, // llvm.nvvm.suld.2d.v4i16.trap - nvvm_suld_2d_v4i16_zero, // llvm.nvvm.suld.2d.v4i16.zero - nvvm_suld_2d_v4i32_clamp, // llvm.nvvm.suld.2d.v4i32.clamp - nvvm_suld_2d_v4i32_trap, // llvm.nvvm.suld.2d.v4i32.trap - nvvm_suld_2d_v4i32_zero, // llvm.nvvm.suld.2d.v4i32.zero - nvvm_suld_2d_v4i8_clamp, // llvm.nvvm.suld.2d.v4i8.clamp - nvvm_suld_2d_v4i8_trap, // llvm.nvvm.suld.2d.v4i8.trap - nvvm_suld_2d_v4i8_zero, // llvm.nvvm.suld.2d.v4i8.zero - nvvm_suld_3d_i16_clamp, // llvm.nvvm.suld.3d.i16.clamp - nvvm_suld_3d_i16_trap, // llvm.nvvm.suld.3d.i16.trap - nvvm_suld_3d_i16_zero, // llvm.nvvm.suld.3d.i16.zero - nvvm_suld_3d_i32_clamp, // llvm.nvvm.suld.3d.i32.clamp - nvvm_suld_3d_i32_trap, // llvm.nvvm.suld.3d.i32.trap - nvvm_suld_3d_i32_zero, // llvm.nvvm.suld.3d.i32.zero - nvvm_suld_3d_i64_clamp, // llvm.nvvm.suld.3d.i64.clamp - nvvm_suld_3d_i64_trap, // llvm.nvvm.suld.3d.i64.trap - nvvm_suld_3d_i64_zero, // llvm.nvvm.suld.3d.i64.zero - nvvm_suld_3d_i8_clamp, // llvm.nvvm.suld.3d.i8.clamp - nvvm_suld_3d_i8_trap, // llvm.nvvm.suld.3d.i8.trap - nvvm_suld_3d_i8_zero, // llvm.nvvm.suld.3d.i8.zero - nvvm_suld_3d_v2i16_clamp, // llvm.nvvm.suld.3d.v2i16.clamp - nvvm_suld_3d_v2i16_trap, // llvm.nvvm.suld.3d.v2i16.trap - nvvm_suld_3d_v2i16_zero, // llvm.nvvm.suld.3d.v2i16.zero - nvvm_suld_3d_v2i32_clamp, // llvm.nvvm.suld.3d.v2i32.clamp - nvvm_suld_3d_v2i32_trap, // llvm.nvvm.suld.3d.v2i32.trap - nvvm_suld_3d_v2i32_zero, // llvm.nvvm.suld.3d.v2i32.zero - nvvm_suld_3d_v2i64_clamp, // llvm.nvvm.suld.3d.v2i64.clamp - nvvm_suld_3d_v2i64_trap, // llvm.nvvm.suld.3d.v2i64.trap - nvvm_suld_3d_v2i64_zero, // llvm.nvvm.suld.3d.v2i64.zero - nvvm_suld_3d_v2i8_clamp, // llvm.nvvm.suld.3d.v2i8.clamp - nvvm_suld_3d_v2i8_trap, // llvm.nvvm.suld.3d.v2i8.trap - nvvm_suld_3d_v2i8_zero, // llvm.nvvm.suld.3d.v2i8.zero - nvvm_suld_3d_v4i16_clamp, // llvm.nvvm.suld.3d.v4i16.clamp - nvvm_suld_3d_v4i16_trap, // llvm.nvvm.suld.3d.v4i16.trap - nvvm_suld_3d_v4i16_zero, // llvm.nvvm.suld.3d.v4i16.zero - nvvm_suld_3d_v4i32_clamp, // llvm.nvvm.suld.3d.v4i32.clamp - nvvm_suld_3d_v4i32_trap, // llvm.nvvm.suld.3d.v4i32.trap - nvvm_suld_3d_v4i32_zero, // llvm.nvvm.suld.3d.v4i32.zero - nvvm_suld_3d_v4i8_clamp, // llvm.nvvm.suld.3d.v4i8.clamp - nvvm_suld_3d_v4i8_trap, // llvm.nvvm.suld.3d.v4i8.trap - nvvm_suld_3d_v4i8_zero, // llvm.nvvm.suld.3d.v4i8.zero - nvvm_suq_array_size, // llvm.nvvm.suq.array.size - nvvm_suq_channel_data_type, // llvm.nvvm.suq.channel.data.type - nvvm_suq_channel_order, // llvm.nvvm.suq.channel.order - nvvm_suq_depth, // llvm.nvvm.suq.depth - nvvm_suq_height, // llvm.nvvm.suq.height - nvvm_suq_width, // llvm.nvvm.suq.width - nvvm_sust_b_1d_array_i16_clamp, // llvm.nvvm.sust.b.1d.array.i16.clamp - nvvm_sust_b_1d_array_i16_trap, // llvm.nvvm.sust.b.1d.array.i16.trap - nvvm_sust_b_1d_array_i16_zero, // llvm.nvvm.sust.b.1d.array.i16.zero - nvvm_sust_b_1d_array_i32_clamp, // llvm.nvvm.sust.b.1d.array.i32.clamp - nvvm_sust_b_1d_array_i32_trap, // llvm.nvvm.sust.b.1d.array.i32.trap - nvvm_sust_b_1d_array_i32_zero, // llvm.nvvm.sust.b.1d.array.i32.zero - nvvm_sust_b_1d_array_i64_clamp, // llvm.nvvm.sust.b.1d.array.i64.clamp - nvvm_sust_b_1d_array_i64_trap, // llvm.nvvm.sust.b.1d.array.i64.trap - nvvm_sust_b_1d_array_i64_zero, // llvm.nvvm.sust.b.1d.array.i64.zero - nvvm_sust_b_1d_array_i8_clamp, // llvm.nvvm.sust.b.1d.array.i8.clamp - nvvm_sust_b_1d_array_i8_trap, // llvm.nvvm.sust.b.1d.array.i8.trap - nvvm_sust_b_1d_array_i8_zero, // llvm.nvvm.sust.b.1d.array.i8.zero - nvvm_sust_b_1d_array_v2i16_clamp, // llvm.nvvm.sust.b.1d.array.v2i16.clamp - nvvm_sust_b_1d_array_v2i16_trap, // llvm.nvvm.sust.b.1d.array.v2i16.trap - nvvm_sust_b_1d_array_v2i16_zero, // llvm.nvvm.sust.b.1d.array.v2i16.zero - nvvm_sust_b_1d_array_v2i32_clamp, // llvm.nvvm.sust.b.1d.array.v2i32.clamp - nvvm_sust_b_1d_array_v2i32_trap, // llvm.nvvm.sust.b.1d.array.v2i32.trap - nvvm_sust_b_1d_array_v2i32_zero, // llvm.nvvm.sust.b.1d.array.v2i32.zero - nvvm_sust_b_1d_array_v2i64_clamp, // llvm.nvvm.sust.b.1d.array.v2i64.clamp - nvvm_sust_b_1d_array_v2i64_trap, // llvm.nvvm.sust.b.1d.array.v2i64.trap - nvvm_sust_b_1d_array_v2i64_zero, // llvm.nvvm.sust.b.1d.array.v2i64.zero - nvvm_sust_b_1d_array_v2i8_clamp, // llvm.nvvm.sust.b.1d.array.v2i8.clamp - nvvm_sust_b_1d_array_v2i8_trap, // llvm.nvvm.sust.b.1d.array.v2i8.trap - nvvm_sust_b_1d_array_v2i8_zero, // llvm.nvvm.sust.b.1d.array.v2i8.zero - nvvm_sust_b_1d_array_v4i16_clamp, // llvm.nvvm.sust.b.1d.array.v4i16.clamp - nvvm_sust_b_1d_array_v4i16_trap, // llvm.nvvm.sust.b.1d.array.v4i16.trap - nvvm_sust_b_1d_array_v4i16_zero, // llvm.nvvm.sust.b.1d.array.v4i16.zero - nvvm_sust_b_1d_array_v4i32_clamp, // llvm.nvvm.sust.b.1d.array.v4i32.clamp - nvvm_sust_b_1d_array_v4i32_trap, // llvm.nvvm.sust.b.1d.array.v4i32.trap - nvvm_sust_b_1d_array_v4i32_zero, // llvm.nvvm.sust.b.1d.array.v4i32.zero - nvvm_sust_b_1d_array_v4i8_clamp, // llvm.nvvm.sust.b.1d.array.v4i8.clamp - nvvm_sust_b_1d_array_v4i8_trap, // llvm.nvvm.sust.b.1d.array.v4i8.trap - nvvm_sust_b_1d_array_v4i8_zero, // llvm.nvvm.sust.b.1d.array.v4i8.zero - nvvm_sust_b_1d_i16_clamp, // llvm.nvvm.sust.b.1d.i16.clamp - nvvm_sust_b_1d_i16_trap, // llvm.nvvm.sust.b.1d.i16.trap - nvvm_sust_b_1d_i16_zero, // llvm.nvvm.sust.b.1d.i16.zero - nvvm_sust_b_1d_i32_clamp, // llvm.nvvm.sust.b.1d.i32.clamp - nvvm_sust_b_1d_i32_trap, // llvm.nvvm.sust.b.1d.i32.trap - nvvm_sust_b_1d_i32_zero, // llvm.nvvm.sust.b.1d.i32.zero - nvvm_sust_b_1d_i64_clamp, // llvm.nvvm.sust.b.1d.i64.clamp - nvvm_sust_b_1d_i64_trap, // llvm.nvvm.sust.b.1d.i64.trap - nvvm_sust_b_1d_i64_zero, // llvm.nvvm.sust.b.1d.i64.zero - nvvm_sust_b_1d_i8_clamp, // llvm.nvvm.sust.b.1d.i8.clamp - nvvm_sust_b_1d_i8_trap, // llvm.nvvm.sust.b.1d.i8.trap - nvvm_sust_b_1d_i8_zero, // llvm.nvvm.sust.b.1d.i8.zero - nvvm_sust_b_1d_v2i16_clamp, // llvm.nvvm.sust.b.1d.v2i16.clamp - nvvm_sust_b_1d_v2i16_trap, // llvm.nvvm.sust.b.1d.v2i16.trap - nvvm_sust_b_1d_v2i16_zero, // llvm.nvvm.sust.b.1d.v2i16.zero - nvvm_sust_b_1d_v2i32_clamp, // llvm.nvvm.sust.b.1d.v2i32.clamp - nvvm_sust_b_1d_v2i32_trap, // llvm.nvvm.sust.b.1d.v2i32.trap - nvvm_sust_b_1d_v2i32_zero, // llvm.nvvm.sust.b.1d.v2i32.zero - nvvm_sust_b_1d_v2i64_clamp, // llvm.nvvm.sust.b.1d.v2i64.clamp - nvvm_sust_b_1d_v2i64_trap, // llvm.nvvm.sust.b.1d.v2i64.trap - nvvm_sust_b_1d_v2i64_zero, // llvm.nvvm.sust.b.1d.v2i64.zero - nvvm_sust_b_1d_v2i8_clamp, // llvm.nvvm.sust.b.1d.v2i8.clamp - nvvm_sust_b_1d_v2i8_trap, // llvm.nvvm.sust.b.1d.v2i8.trap - nvvm_sust_b_1d_v2i8_zero, // llvm.nvvm.sust.b.1d.v2i8.zero - nvvm_sust_b_1d_v4i16_clamp, // llvm.nvvm.sust.b.1d.v4i16.clamp - nvvm_sust_b_1d_v4i16_trap, // llvm.nvvm.sust.b.1d.v4i16.trap - nvvm_sust_b_1d_v4i16_zero, // llvm.nvvm.sust.b.1d.v4i16.zero - nvvm_sust_b_1d_v4i32_clamp, // llvm.nvvm.sust.b.1d.v4i32.clamp - nvvm_sust_b_1d_v4i32_trap, // llvm.nvvm.sust.b.1d.v4i32.trap - nvvm_sust_b_1d_v4i32_zero, // llvm.nvvm.sust.b.1d.v4i32.zero - nvvm_sust_b_1d_v4i8_clamp, // llvm.nvvm.sust.b.1d.v4i8.clamp - nvvm_sust_b_1d_v4i8_trap, // llvm.nvvm.sust.b.1d.v4i8.trap - nvvm_sust_b_1d_v4i8_zero, // llvm.nvvm.sust.b.1d.v4i8.zero - nvvm_sust_b_2d_array_i16_clamp, // llvm.nvvm.sust.b.2d.array.i16.clamp - nvvm_sust_b_2d_array_i16_trap, // llvm.nvvm.sust.b.2d.array.i16.trap - nvvm_sust_b_2d_array_i16_zero, // llvm.nvvm.sust.b.2d.array.i16.zero - nvvm_sust_b_2d_array_i32_clamp, // llvm.nvvm.sust.b.2d.array.i32.clamp - nvvm_sust_b_2d_array_i32_trap, // llvm.nvvm.sust.b.2d.array.i32.trap - nvvm_sust_b_2d_array_i32_zero, // llvm.nvvm.sust.b.2d.array.i32.zero - nvvm_sust_b_2d_array_i64_clamp, // llvm.nvvm.sust.b.2d.array.i64.clamp - nvvm_sust_b_2d_array_i64_trap, // llvm.nvvm.sust.b.2d.array.i64.trap - nvvm_sust_b_2d_array_i64_zero, // llvm.nvvm.sust.b.2d.array.i64.zero - nvvm_sust_b_2d_array_i8_clamp, // llvm.nvvm.sust.b.2d.array.i8.clamp - nvvm_sust_b_2d_array_i8_trap, // llvm.nvvm.sust.b.2d.array.i8.trap - nvvm_sust_b_2d_array_i8_zero, // llvm.nvvm.sust.b.2d.array.i8.zero - nvvm_sust_b_2d_array_v2i16_clamp, // llvm.nvvm.sust.b.2d.array.v2i16.clamp - nvvm_sust_b_2d_array_v2i16_trap, // llvm.nvvm.sust.b.2d.array.v2i16.trap - nvvm_sust_b_2d_array_v2i16_zero, // llvm.nvvm.sust.b.2d.array.v2i16.zero - nvvm_sust_b_2d_array_v2i32_clamp, // llvm.nvvm.sust.b.2d.array.v2i32.clamp - nvvm_sust_b_2d_array_v2i32_trap, // llvm.nvvm.sust.b.2d.array.v2i32.trap - nvvm_sust_b_2d_array_v2i32_zero, // llvm.nvvm.sust.b.2d.array.v2i32.zero - nvvm_sust_b_2d_array_v2i64_clamp, // llvm.nvvm.sust.b.2d.array.v2i64.clamp - nvvm_sust_b_2d_array_v2i64_trap, // llvm.nvvm.sust.b.2d.array.v2i64.trap - nvvm_sust_b_2d_array_v2i64_zero, // llvm.nvvm.sust.b.2d.array.v2i64.zero - nvvm_sust_b_2d_array_v2i8_clamp, // llvm.nvvm.sust.b.2d.array.v2i8.clamp - nvvm_sust_b_2d_array_v2i8_trap, // llvm.nvvm.sust.b.2d.array.v2i8.trap - nvvm_sust_b_2d_array_v2i8_zero, // llvm.nvvm.sust.b.2d.array.v2i8.zero - nvvm_sust_b_2d_array_v4i16_clamp, // llvm.nvvm.sust.b.2d.array.v4i16.clamp - nvvm_sust_b_2d_array_v4i16_trap, // llvm.nvvm.sust.b.2d.array.v4i16.trap - nvvm_sust_b_2d_array_v4i16_zero, // llvm.nvvm.sust.b.2d.array.v4i16.zero - nvvm_sust_b_2d_array_v4i32_clamp, // llvm.nvvm.sust.b.2d.array.v4i32.clamp - nvvm_sust_b_2d_array_v4i32_trap, // llvm.nvvm.sust.b.2d.array.v4i32.trap - nvvm_sust_b_2d_array_v4i32_zero, // llvm.nvvm.sust.b.2d.array.v4i32.zero - nvvm_sust_b_2d_array_v4i8_clamp, // llvm.nvvm.sust.b.2d.array.v4i8.clamp - nvvm_sust_b_2d_array_v4i8_trap, // llvm.nvvm.sust.b.2d.array.v4i8.trap - nvvm_sust_b_2d_array_v4i8_zero, // llvm.nvvm.sust.b.2d.array.v4i8.zero - nvvm_sust_b_2d_i16_clamp, // llvm.nvvm.sust.b.2d.i16.clamp - nvvm_sust_b_2d_i16_trap, // llvm.nvvm.sust.b.2d.i16.trap - nvvm_sust_b_2d_i16_zero, // llvm.nvvm.sust.b.2d.i16.zero - nvvm_sust_b_2d_i32_clamp, // llvm.nvvm.sust.b.2d.i32.clamp - nvvm_sust_b_2d_i32_trap, // llvm.nvvm.sust.b.2d.i32.trap - nvvm_sust_b_2d_i32_zero, // llvm.nvvm.sust.b.2d.i32.zero - nvvm_sust_b_2d_i64_clamp, // llvm.nvvm.sust.b.2d.i64.clamp - nvvm_sust_b_2d_i64_trap, // llvm.nvvm.sust.b.2d.i64.trap - nvvm_sust_b_2d_i64_zero, // llvm.nvvm.sust.b.2d.i64.zero - nvvm_sust_b_2d_i8_clamp, // llvm.nvvm.sust.b.2d.i8.clamp - nvvm_sust_b_2d_i8_trap, // llvm.nvvm.sust.b.2d.i8.trap - nvvm_sust_b_2d_i8_zero, // llvm.nvvm.sust.b.2d.i8.zero - nvvm_sust_b_2d_v2i16_clamp, // llvm.nvvm.sust.b.2d.v2i16.clamp - nvvm_sust_b_2d_v2i16_trap, // llvm.nvvm.sust.b.2d.v2i16.trap - nvvm_sust_b_2d_v2i16_zero, // llvm.nvvm.sust.b.2d.v2i16.zero - nvvm_sust_b_2d_v2i32_clamp, // llvm.nvvm.sust.b.2d.v2i32.clamp - nvvm_sust_b_2d_v2i32_trap, // llvm.nvvm.sust.b.2d.v2i32.trap - nvvm_sust_b_2d_v2i32_zero, // llvm.nvvm.sust.b.2d.v2i32.zero - nvvm_sust_b_2d_v2i64_clamp, // llvm.nvvm.sust.b.2d.v2i64.clamp - nvvm_sust_b_2d_v2i64_trap, // llvm.nvvm.sust.b.2d.v2i64.trap - nvvm_sust_b_2d_v2i64_zero, // llvm.nvvm.sust.b.2d.v2i64.zero - nvvm_sust_b_2d_v2i8_clamp, // llvm.nvvm.sust.b.2d.v2i8.clamp - nvvm_sust_b_2d_v2i8_trap, // llvm.nvvm.sust.b.2d.v2i8.trap - nvvm_sust_b_2d_v2i8_zero, // llvm.nvvm.sust.b.2d.v2i8.zero - nvvm_sust_b_2d_v4i16_clamp, // llvm.nvvm.sust.b.2d.v4i16.clamp - nvvm_sust_b_2d_v4i16_trap, // llvm.nvvm.sust.b.2d.v4i16.trap - nvvm_sust_b_2d_v4i16_zero, // llvm.nvvm.sust.b.2d.v4i16.zero - nvvm_sust_b_2d_v4i32_clamp, // llvm.nvvm.sust.b.2d.v4i32.clamp - nvvm_sust_b_2d_v4i32_trap, // llvm.nvvm.sust.b.2d.v4i32.trap - nvvm_sust_b_2d_v4i32_zero, // llvm.nvvm.sust.b.2d.v4i32.zero - nvvm_sust_b_2d_v4i8_clamp, // llvm.nvvm.sust.b.2d.v4i8.clamp - nvvm_sust_b_2d_v4i8_trap, // llvm.nvvm.sust.b.2d.v4i8.trap - nvvm_sust_b_2d_v4i8_zero, // llvm.nvvm.sust.b.2d.v4i8.zero - nvvm_sust_b_3d_i16_clamp, // llvm.nvvm.sust.b.3d.i16.clamp - nvvm_sust_b_3d_i16_trap, // llvm.nvvm.sust.b.3d.i16.trap - nvvm_sust_b_3d_i16_zero, // llvm.nvvm.sust.b.3d.i16.zero - nvvm_sust_b_3d_i32_clamp, // llvm.nvvm.sust.b.3d.i32.clamp - nvvm_sust_b_3d_i32_trap, // llvm.nvvm.sust.b.3d.i32.trap - nvvm_sust_b_3d_i32_zero, // llvm.nvvm.sust.b.3d.i32.zero - nvvm_sust_b_3d_i64_clamp, // llvm.nvvm.sust.b.3d.i64.clamp - nvvm_sust_b_3d_i64_trap, // llvm.nvvm.sust.b.3d.i64.trap - nvvm_sust_b_3d_i64_zero, // llvm.nvvm.sust.b.3d.i64.zero - nvvm_sust_b_3d_i8_clamp, // llvm.nvvm.sust.b.3d.i8.clamp - nvvm_sust_b_3d_i8_trap, // llvm.nvvm.sust.b.3d.i8.trap - nvvm_sust_b_3d_i8_zero, // llvm.nvvm.sust.b.3d.i8.zero - nvvm_sust_b_3d_v2i16_clamp, // llvm.nvvm.sust.b.3d.v2i16.clamp - nvvm_sust_b_3d_v2i16_trap, // llvm.nvvm.sust.b.3d.v2i16.trap - nvvm_sust_b_3d_v2i16_zero, // llvm.nvvm.sust.b.3d.v2i16.zero - nvvm_sust_b_3d_v2i32_clamp, // llvm.nvvm.sust.b.3d.v2i32.clamp - nvvm_sust_b_3d_v2i32_trap, // llvm.nvvm.sust.b.3d.v2i32.trap - nvvm_sust_b_3d_v2i32_zero, // llvm.nvvm.sust.b.3d.v2i32.zero - nvvm_sust_b_3d_v2i64_clamp, // llvm.nvvm.sust.b.3d.v2i64.clamp - nvvm_sust_b_3d_v2i64_trap, // llvm.nvvm.sust.b.3d.v2i64.trap - nvvm_sust_b_3d_v2i64_zero, // llvm.nvvm.sust.b.3d.v2i64.zero - nvvm_sust_b_3d_v2i8_clamp, // llvm.nvvm.sust.b.3d.v2i8.clamp - nvvm_sust_b_3d_v2i8_trap, // llvm.nvvm.sust.b.3d.v2i8.trap - nvvm_sust_b_3d_v2i8_zero, // llvm.nvvm.sust.b.3d.v2i8.zero - nvvm_sust_b_3d_v4i16_clamp, // llvm.nvvm.sust.b.3d.v4i16.clamp - nvvm_sust_b_3d_v4i16_trap, // llvm.nvvm.sust.b.3d.v4i16.trap - nvvm_sust_b_3d_v4i16_zero, // llvm.nvvm.sust.b.3d.v4i16.zero - nvvm_sust_b_3d_v4i32_clamp, // llvm.nvvm.sust.b.3d.v4i32.clamp - nvvm_sust_b_3d_v4i32_trap, // llvm.nvvm.sust.b.3d.v4i32.trap - nvvm_sust_b_3d_v4i32_zero, // llvm.nvvm.sust.b.3d.v4i32.zero - nvvm_sust_b_3d_v4i8_clamp, // llvm.nvvm.sust.b.3d.v4i8.clamp - nvvm_sust_b_3d_v4i8_trap, // llvm.nvvm.sust.b.3d.v4i8.trap - nvvm_sust_b_3d_v4i8_zero, // llvm.nvvm.sust.b.3d.v4i8.zero - nvvm_sust_p_1d_array_i16_trap, // llvm.nvvm.sust.p.1d.array.i16.trap - nvvm_sust_p_1d_array_i32_trap, // llvm.nvvm.sust.p.1d.array.i32.trap - nvvm_sust_p_1d_array_i8_trap, // llvm.nvvm.sust.p.1d.array.i8.trap - nvvm_sust_p_1d_array_v2i16_trap, // llvm.nvvm.sust.p.1d.array.v2i16.trap - nvvm_sust_p_1d_array_v2i32_trap, // llvm.nvvm.sust.p.1d.array.v2i32.trap - nvvm_sust_p_1d_array_v2i8_trap, // llvm.nvvm.sust.p.1d.array.v2i8.trap - nvvm_sust_p_1d_array_v4i16_trap, // llvm.nvvm.sust.p.1d.array.v4i16.trap - nvvm_sust_p_1d_array_v4i32_trap, // llvm.nvvm.sust.p.1d.array.v4i32.trap - nvvm_sust_p_1d_array_v4i8_trap, // llvm.nvvm.sust.p.1d.array.v4i8.trap - nvvm_sust_p_1d_i16_trap, // llvm.nvvm.sust.p.1d.i16.trap - nvvm_sust_p_1d_i32_trap, // llvm.nvvm.sust.p.1d.i32.trap - nvvm_sust_p_1d_i8_trap, // llvm.nvvm.sust.p.1d.i8.trap - nvvm_sust_p_1d_v2i16_trap, // llvm.nvvm.sust.p.1d.v2i16.trap - nvvm_sust_p_1d_v2i32_trap, // llvm.nvvm.sust.p.1d.v2i32.trap - nvvm_sust_p_1d_v2i8_trap, // llvm.nvvm.sust.p.1d.v2i8.trap - nvvm_sust_p_1d_v4i16_trap, // llvm.nvvm.sust.p.1d.v4i16.trap - nvvm_sust_p_1d_v4i32_trap, // llvm.nvvm.sust.p.1d.v4i32.trap - nvvm_sust_p_1d_v4i8_trap, // llvm.nvvm.sust.p.1d.v4i8.trap - nvvm_sust_p_2d_array_i16_trap, // llvm.nvvm.sust.p.2d.array.i16.trap - nvvm_sust_p_2d_array_i32_trap, // llvm.nvvm.sust.p.2d.array.i32.trap - nvvm_sust_p_2d_array_i8_trap, // llvm.nvvm.sust.p.2d.array.i8.trap - nvvm_sust_p_2d_array_v2i16_trap, // llvm.nvvm.sust.p.2d.array.v2i16.trap - nvvm_sust_p_2d_array_v2i32_trap, // llvm.nvvm.sust.p.2d.array.v2i32.trap - nvvm_sust_p_2d_array_v2i8_trap, // llvm.nvvm.sust.p.2d.array.v2i8.trap - nvvm_sust_p_2d_array_v4i16_trap, // llvm.nvvm.sust.p.2d.array.v4i16.trap - nvvm_sust_p_2d_array_v4i32_trap, // llvm.nvvm.sust.p.2d.array.v4i32.trap - nvvm_sust_p_2d_array_v4i8_trap, // llvm.nvvm.sust.p.2d.array.v4i8.trap - nvvm_sust_p_2d_i16_trap, // llvm.nvvm.sust.p.2d.i16.trap - nvvm_sust_p_2d_i32_trap, // llvm.nvvm.sust.p.2d.i32.trap - nvvm_sust_p_2d_i8_trap, // llvm.nvvm.sust.p.2d.i8.trap - nvvm_sust_p_2d_v2i16_trap, // llvm.nvvm.sust.p.2d.v2i16.trap - nvvm_sust_p_2d_v2i32_trap, // llvm.nvvm.sust.p.2d.v2i32.trap - nvvm_sust_p_2d_v2i8_trap, // llvm.nvvm.sust.p.2d.v2i8.trap - nvvm_sust_p_2d_v4i16_trap, // llvm.nvvm.sust.p.2d.v4i16.trap - nvvm_sust_p_2d_v4i32_trap, // llvm.nvvm.sust.p.2d.v4i32.trap - nvvm_sust_p_2d_v4i8_trap, // llvm.nvvm.sust.p.2d.v4i8.trap - nvvm_sust_p_3d_i16_trap, // llvm.nvvm.sust.p.3d.i16.trap - nvvm_sust_p_3d_i32_trap, // llvm.nvvm.sust.p.3d.i32.trap - nvvm_sust_p_3d_i8_trap, // llvm.nvvm.sust.p.3d.i8.trap - nvvm_sust_p_3d_v2i16_trap, // llvm.nvvm.sust.p.3d.v2i16.trap - nvvm_sust_p_3d_v2i32_trap, // llvm.nvvm.sust.p.3d.v2i32.trap - nvvm_sust_p_3d_v2i8_trap, // llvm.nvvm.sust.p.3d.v2i8.trap - nvvm_sust_p_3d_v4i16_trap, // llvm.nvvm.sust.p.3d.v4i16.trap - nvvm_sust_p_3d_v4i32_trap, // llvm.nvvm.sust.p.3d.v4i32.trap - nvvm_sust_p_3d_v4i8_trap, // llvm.nvvm.sust.p.3d.v4i8.trap - nvvm_swap_lo_hi_b64, // llvm.nvvm.swap.lo.hi.b64 - nvvm_tex_1d_array_grad_v4f32_f32, // llvm.nvvm.tex.1d.array.grad.v4f32.f32 - nvvm_tex_1d_array_grad_v4s32_f32, // llvm.nvvm.tex.1d.array.grad.v4s32.f32 - nvvm_tex_1d_array_grad_v4u32_f32, // llvm.nvvm.tex.1d.array.grad.v4u32.f32 - nvvm_tex_1d_array_level_v4f32_f32, // llvm.nvvm.tex.1d.array.level.v4f32.f32 - nvvm_tex_1d_array_level_v4s32_f32, // llvm.nvvm.tex.1d.array.level.v4s32.f32 - nvvm_tex_1d_array_level_v4u32_f32, // llvm.nvvm.tex.1d.array.level.v4u32.f32 - nvvm_tex_1d_array_v4f32_f32, // llvm.nvvm.tex.1d.array.v4f32.f32 - nvvm_tex_1d_array_v4f32_s32, // llvm.nvvm.tex.1d.array.v4f32.s32 - nvvm_tex_1d_array_v4s32_f32, // llvm.nvvm.tex.1d.array.v4s32.f32 - nvvm_tex_1d_array_v4s32_s32, // llvm.nvvm.tex.1d.array.v4s32.s32 - nvvm_tex_1d_array_v4u32_f32, // llvm.nvvm.tex.1d.array.v4u32.f32 - nvvm_tex_1d_array_v4u32_s32, // llvm.nvvm.tex.1d.array.v4u32.s32 - nvvm_tex_1d_grad_v4f32_f32, // llvm.nvvm.tex.1d.grad.v4f32.f32 - nvvm_tex_1d_grad_v4s32_f32, // llvm.nvvm.tex.1d.grad.v4s32.f32 - nvvm_tex_1d_grad_v4u32_f32, // llvm.nvvm.tex.1d.grad.v4u32.f32 - nvvm_tex_1d_level_v4f32_f32, // llvm.nvvm.tex.1d.level.v4f32.f32 - nvvm_tex_1d_level_v4s32_f32, // llvm.nvvm.tex.1d.level.v4s32.f32 - nvvm_tex_1d_level_v4u32_f32, // llvm.nvvm.tex.1d.level.v4u32.f32 - nvvm_tex_1d_v4f32_f32, // llvm.nvvm.tex.1d.v4f32.f32 - nvvm_tex_1d_v4f32_s32, // llvm.nvvm.tex.1d.v4f32.s32 - nvvm_tex_1d_v4s32_f32, // llvm.nvvm.tex.1d.v4s32.f32 - nvvm_tex_1d_v4s32_s32, // llvm.nvvm.tex.1d.v4s32.s32 - nvvm_tex_1d_v4u32_f32, // llvm.nvvm.tex.1d.v4u32.f32 - nvvm_tex_1d_v4u32_s32, // llvm.nvvm.tex.1d.v4u32.s32 - nvvm_tex_2d_array_grad_v4f32_f32, // llvm.nvvm.tex.2d.array.grad.v4f32.f32 - nvvm_tex_2d_array_grad_v4s32_f32, // llvm.nvvm.tex.2d.array.grad.v4s32.f32 - nvvm_tex_2d_array_grad_v4u32_f32, // llvm.nvvm.tex.2d.array.grad.v4u32.f32 - nvvm_tex_2d_array_level_v4f32_f32, // llvm.nvvm.tex.2d.array.level.v4f32.f32 - nvvm_tex_2d_array_level_v4s32_f32, // llvm.nvvm.tex.2d.array.level.v4s32.f32 - nvvm_tex_2d_array_level_v4u32_f32, // llvm.nvvm.tex.2d.array.level.v4u32.f32 - nvvm_tex_2d_array_v4f32_f32, // llvm.nvvm.tex.2d.array.v4f32.f32 - nvvm_tex_2d_array_v4f32_s32, // llvm.nvvm.tex.2d.array.v4f32.s32 - nvvm_tex_2d_array_v4s32_f32, // llvm.nvvm.tex.2d.array.v4s32.f32 - nvvm_tex_2d_array_v4s32_s32, // llvm.nvvm.tex.2d.array.v4s32.s32 - nvvm_tex_2d_array_v4u32_f32, // llvm.nvvm.tex.2d.array.v4u32.f32 - nvvm_tex_2d_array_v4u32_s32, // llvm.nvvm.tex.2d.array.v4u32.s32 - nvvm_tex_2d_grad_v4f32_f32, // llvm.nvvm.tex.2d.grad.v4f32.f32 - nvvm_tex_2d_grad_v4s32_f32, // llvm.nvvm.tex.2d.grad.v4s32.f32 - nvvm_tex_2d_grad_v4u32_f32, // llvm.nvvm.tex.2d.grad.v4u32.f32 - nvvm_tex_2d_level_v4f32_f32, // llvm.nvvm.tex.2d.level.v4f32.f32 - nvvm_tex_2d_level_v4s32_f32, // llvm.nvvm.tex.2d.level.v4s32.f32 - nvvm_tex_2d_level_v4u32_f32, // llvm.nvvm.tex.2d.level.v4u32.f32 - nvvm_tex_2d_v4f32_f32, // llvm.nvvm.tex.2d.v4f32.f32 - nvvm_tex_2d_v4f32_s32, // llvm.nvvm.tex.2d.v4f32.s32 - nvvm_tex_2d_v4s32_f32, // llvm.nvvm.tex.2d.v4s32.f32 - nvvm_tex_2d_v4s32_s32, // llvm.nvvm.tex.2d.v4s32.s32 - nvvm_tex_2d_v4u32_f32, // llvm.nvvm.tex.2d.v4u32.f32 - nvvm_tex_2d_v4u32_s32, // llvm.nvvm.tex.2d.v4u32.s32 - nvvm_tex_3d_grad_v4f32_f32, // llvm.nvvm.tex.3d.grad.v4f32.f32 - nvvm_tex_3d_grad_v4s32_f32, // llvm.nvvm.tex.3d.grad.v4s32.f32 - nvvm_tex_3d_grad_v4u32_f32, // llvm.nvvm.tex.3d.grad.v4u32.f32 - nvvm_tex_3d_level_v4f32_f32, // llvm.nvvm.tex.3d.level.v4f32.f32 - nvvm_tex_3d_level_v4s32_f32, // llvm.nvvm.tex.3d.level.v4s32.f32 - nvvm_tex_3d_level_v4u32_f32, // llvm.nvvm.tex.3d.level.v4u32.f32 - nvvm_tex_3d_v4f32_f32, // llvm.nvvm.tex.3d.v4f32.f32 - nvvm_tex_3d_v4f32_s32, // llvm.nvvm.tex.3d.v4f32.s32 - nvvm_tex_3d_v4s32_f32, // llvm.nvvm.tex.3d.v4s32.f32 - nvvm_tex_3d_v4s32_s32, // llvm.nvvm.tex.3d.v4s32.s32 - nvvm_tex_3d_v4u32_f32, // llvm.nvvm.tex.3d.v4u32.f32 - nvvm_tex_3d_v4u32_s32, // llvm.nvvm.tex.3d.v4u32.s32 - nvvm_tex_cube_array_level_v4f32_f32, // llvm.nvvm.tex.cube.array.level.v4f32.f32 - nvvm_tex_cube_array_level_v4s32_f32, // llvm.nvvm.tex.cube.array.level.v4s32.f32 - nvvm_tex_cube_array_level_v4u32_f32, // llvm.nvvm.tex.cube.array.level.v4u32.f32 - nvvm_tex_cube_array_v4f32_f32, // llvm.nvvm.tex.cube.array.v4f32.f32 - nvvm_tex_cube_array_v4s32_f32, // llvm.nvvm.tex.cube.array.v4s32.f32 - nvvm_tex_cube_array_v4u32_f32, // llvm.nvvm.tex.cube.array.v4u32.f32 - nvvm_tex_cube_level_v4f32_f32, // llvm.nvvm.tex.cube.level.v4f32.f32 - nvvm_tex_cube_level_v4s32_f32, // llvm.nvvm.tex.cube.level.v4s32.f32 - nvvm_tex_cube_level_v4u32_f32, // llvm.nvvm.tex.cube.level.v4u32.f32 - nvvm_tex_cube_v4f32_f32, // llvm.nvvm.tex.cube.v4f32.f32 - nvvm_tex_cube_v4s32_f32, // llvm.nvvm.tex.cube.v4s32.f32 - nvvm_tex_cube_v4u32_f32, // llvm.nvvm.tex.cube.v4u32.f32 - nvvm_tex_unified_1d_array_grad_v4f32_f32, // llvm.nvvm.tex.unified.1d.array.grad.v4f32.f32 - nvvm_tex_unified_1d_array_grad_v4s32_f32, // llvm.nvvm.tex.unified.1d.array.grad.v4s32.f32 - nvvm_tex_unified_1d_array_grad_v4u32_f32, // llvm.nvvm.tex.unified.1d.array.grad.v4u32.f32 - nvvm_tex_unified_1d_array_level_v4f32_f32, // llvm.nvvm.tex.unified.1d.array.level.v4f32.f32 - nvvm_tex_unified_1d_array_level_v4s32_f32, // llvm.nvvm.tex.unified.1d.array.level.v4s32.f32 - nvvm_tex_unified_1d_array_level_v4u32_f32, // llvm.nvvm.tex.unified.1d.array.level.v4u32.f32 - nvvm_tex_unified_1d_array_v4f32_f32, // llvm.nvvm.tex.unified.1d.array.v4f32.f32 - nvvm_tex_unified_1d_array_v4f32_s32, // llvm.nvvm.tex.unified.1d.array.v4f32.s32 - nvvm_tex_unified_1d_array_v4s32_f32, // llvm.nvvm.tex.unified.1d.array.v4s32.f32 - nvvm_tex_unified_1d_array_v4s32_s32, // llvm.nvvm.tex.unified.1d.array.v4s32.s32 - nvvm_tex_unified_1d_array_v4u32_f32, // llvm.nvvm.tex.unified.1d.array.v4u32.f32 - nvvm_tex_unified_1d_array_v4u32_s32, // llvm.nvvm.tex.unified.1d.array.v4u32.s32 - nvvm_tex_unified_1d_grad_v4f32_f32, // llvm.nvvm.tex.unified.1d.grad.v4f32.f32 - nvvm_tex_unified_1d_grad_v4s32_f32, // llvm.nvvm.tex.unified.1d.grad.v4s32.f32 - nvvm_tex_unified_1d_grad_v4u32_f32, // llvm.nvvm.tex.unified.1d.grad.v4u32.f32 - nvvm_tex_unified_1d_level_v4f32_f32, // llvm.nvvm.tex.unified.1d.level.v4f32.f32 - nvvm_tex_unified_1d_level_v4s32_f32, // llvm.nvvm.tex.unified.1d.level.v4s32.f32 - nvvm_tex_unified_1d_level_v4u32_f32, // llvm.nvvm.tex.unified.1d.level.v4u32.f32 - nvvm_tex_unified_1d_v4f32_f32, // llvm.nvvm.tex.unified.1d.v4f32.f32 - nvvm_tex_unified_1d_v4f32_s32, // llvm.nvvm.tex.unified.1d.v4f32.s32 - nvvm_tex_unified_1d_v4s32_f32, // llvm.nvvm.tex.unified.1d.v4s32.f32 - nvvm_tex_unified_1d_v4s32_s32, // llvm.nvvm.tex.unified.1d.v4s32.s32 - nvvm_tex_unified_1d_v4u32_f32, // llvm.nvvm.tex.unified.1d.v4u32.f32 - nvvm_tex_unified_1d_v4u32_s32, // llvm.nvvm.tex.unified.1d.v4u32.s32 - nvvm_tex_unified_2d_array_grad_v4f32_f32, // llvm.nvvm.tex.unified.2d.array.grad.v4f32.f32 - nvvm_tex_unified_2d_array_grad_v4s32_f32, // llvm.nvvm.tex.unified.2d.array.grad.v4s32.f32 - nvvm_tex_unified_2d_array_grad_v4u32_f32, // llvm.nvvm.tex.unified.2d.array.grad.v4u32.f32 - nvvm_tex_unified_2d_array_level_v4f32_f32, // llvm.nvvm.tex.unified.2d.array.level.v4f32.f32 - nvvm_tex_unified_2d_array_level_v4s32_f32, // llvm.nvvm.tex.unified.2d.array.level.v4s32.f32 - nvvm_tex_unified_2d_array_level_v4u32_f32, // llvm.nvvm.tex.unified.2d.array.level.v4u32.f32 - nvvm_tex_unified_2d_array_v4f32_f32, // llvm.nvvm.tex.unified.2d.array.v4f32.f32 - nvvm_tex_unified_2d_array_v4f32_s32, // llvm.nvvm.tex.unified.2d.array.v4f32.s32 - nvvm_tex_unified_2d_array_v4s32_f32, // llvm.nvvm.tex.unified.2d.array.v4s32.f32 - nvvm_tex_unified_2d_array_v4s32_s32, // llvm.nvvm.tex.unified.2d.array.v4s32.s32 - nvvm_tex_unified_2d_array_v4u32_f32, // llvm.nvvm.tex.unified.2d.array.v4u32.f32 - nvvm_tex_unified_2d_array_v4u32_s32, // llvm.nvvm.tex.unified.2d.array.v4u32.s32 - nvvm_tex_unified_2d_grad_v4f32_f32, // llvm.nvvm.tex.unified.2d.grad.v4f32.f32 - nvvm_tex_unified_2d_grad_v4s32_f32, // llvm.nvvm.tex.unified.2d.grad.v4s32.f32 - nvvm_tex_unified_2d_grad_v4u32_f32, // llvm.nvvm.tex.unified.2d.grad.v4u32.f32 - nvvm_tex_unified_2d_level_v4f32_f32, // llvm.nvvm.tex.unified.2d.level.v4f32.f32 - nvvm_tex_unified_2d_level_v4s32_f32, // llvm.nvvm.tex.unified.2d.level.v4s32.f32 - nvvm_tex_unified_2d_level_v4u32_f32, // llvm.nvvm.tex.unified.2d.level.v4u32.f32 - nvvm_tex_unified_2d_v4f32_f32, // llvm.nvvm.tex.unified.2d.v4f32.f32 - nvvm_tex_unified_2d_v4f32_s32, // llvm.nvvm.tex.unified.2d.v4f32.s32 - nvvm_tex_unified_2d_v4s32_f32, // llvm.nvvm.tex.unified.2d.v4s32.f32 - nvvm_tex_unified_2d_v4s32_s32, // llvm.nvvm.tex.unified.2d.v4s32.s32 - nvvm_tex_unified_2d_v4u32_f32, // llvm.nvvm.tex.unified.2d.v4u32.f32 - nvvm_tex_unified_2d_v4u32_s32, // llvm.nvvm.tex.unified.2d.v4u32.s32 - nvvm_tex_unified_3d_grad_v4f32_f32, // llvm.nvvm.tex.unified.3d.grad.v4f32.f32 - nvvm_tex_unified_3d_grad_v4s32_f32, // llvm.nvvm.tex.unified.3d.grad.v4s32.f32 - nvvm_tex_unified_3d_grad_v4u32_f32, // llvm.nvvm.tex.unified.3d.grad.v4u32.f32 - nvvm_tex_unified_3d_level_v4f32_f32, // llvm.nvvm.tex.unified.3d.level.v4f32.f32 - nvvm_tex_unified_3d_level_v4s32_f32, // llvm.nvvm.tex.unified.3d.level.v4s32.f32 - nvvm_tex_unified_3d_level_v4u32_f32, // llvm.nvvm.tex.unified.3d.level.v4u32.f32 - nvvm_tex_unified_3d_v4f32_f32, // llvm.nvvm.tex.unified.3d.v4f32.f32 - nvvm_tex_unified_3d_v4f32_s32, // llvm.nvvm.tex.unified.3d.v4f32.s32 - nvvm_tex_unified_3d_v4s32_f32, // llvm.nvvm.tex.unified.3d.v4s32.f32 - nvvm_tex_unified_3d_v4s32_s32, // llvm.nvvm.tex.unified.3d.v4s32.s32 - nvvm_tex_unified_3d_v4u32_f32, // llvm.nvvm.tex.unified.3d.v4u32.f32 - nvvm_tex_unified_3d_v4u32_s32, // llvm.nvvm.tex.unified.3d.v4u32.s32 - nvvm_tex_unified_cube_array_level_v4f32_f32, // llvm.nvvm.tex.unified.cube.array.level.v4f32.f32 - nvvm_tex_unified_cube_array_level_v4s32_f32, // llvm.nvvm.tex.unified.cube.array.level.v4s32.f32 - nvvm_tex_unified_cube_array_level_v4u32_f32, // llvm.nvvm.tex.unified.cube.array.level.v4u32.f32 - nvvm_tex_unified_cube_array_v4f32_f32, // llvm.nvvm.tex.unified.cube.array.v4f32.f32 - nvvm_tex_unified_cube_array_v4s32_f32, // llvm.nvvm.tex.unified.cube.array.v4s32.f32 - nvvm_tex_unified_cube_array_v4u32_f32, // llvm.nvvm.tex.unified.cube.array.v4u32.f32 - nvvm_tex_unified_cube_level_v4f32_f32, // llvm.nvvm.tex.unified.cube.level.v4f32.f32 - nvvm_tex_unified_cube_level_v4s32_f32, // llvm.nvvm.tex.unified.cube.level.v4s32.f32 - nvvm_tex_unified_cube_level_v4u32_f32, // llvm.nvvm.tex.unified.cube.level.v4u32.f32 - nvvm_tex_unified_cube_v4f32_f32, // llvm.nvvm.tex.unified.cube.v4f32.f32 - nvvm_tex_unified_cube_v4s32_f32, // llvm.nvvm.tex.unified.cube.v4s32.f32 - nvvm_tex_unified_cube_v4u32_f32, // llvm.nvvm.tex.unified.cube.v4u32.f32 - nvvm_texsurf_handle, // llvm.nvvm.texsurf.handle - nvvm_texsurf_handle_internal, // llvm.nvvm.texsurf.handle.internal - nvvm_tld4_a_2d_v4f32_f32, // llvm.nvvm.tld4.a.2d.v4f32.f32 - nvvm_tld4_a_2d_v4s32_f32, // llvm.nvvm.tld4.a.2d.v4s32.f32 - nvvm_tld4_a_2d_v4u32_f32, // llvm.nvvm.tld4.a.2d.v4u32.f32 - nvvm_tld4_b_2d_v4f32_f32, // llvm.nvvm.tld4.b.2d.v4f32.f32 - nvvm_tld4_b_2d_v4s32_f32, // llvm.nvvm.tld4.b.2d.v4s32.f32 - nvvm_tld4_b_2d_v4u32_f32, // llvm.nvvm.tld4.b.2d.v4u32.f32 - nvvm_tld4_g_2d_v4f32_f32, // llvm.nvvm.tld4.g.2d.v4f32.f32 - nvvm_tld4_g_2d_v4s32_f32, // llvm.nvvm.tld4.g.2d.v4s32.f32 - nvvm_tld4_g_2d_v4u32_f32, // llvm.nvvm.tld4.g.2d.v4u32.f32 - nvvm_tld4_r_2d_v4f32_f32, // llvm.nvvm.tld4.r.2d.v4f32.f32 - nvvm_tld4_r_2d_v4s32_f32, // llvm.nvvm.tld4.r.2d.v4s32.f32 - nvvm_tld4_r_2d_v4u32_f32, // llvm.nvvm.tld4.r.2d.v4u32.f32 - nvvm_tld4_unified_a_2d_v4f32_f32, // llvm.nvvm.tld4.unified.a.2d.v4f32.f32 - nvvm_tld4_unified_a_2d_v4s32_f32, // llvm.nvvm.tld4.unified.a.2d.v4s32.f32 - nvvm_tld4_unified_a_2d_v4u32_f32, // llvm.nvvm.tld4.unified.a.2d.v4u32.f32 - nvvm_tld4_unified_b_2d_v4f32_f32, // llvm.nvvm.tld4.unified.b.2d.v4f32.f32 - nvvm_tld4_unified_b_2d_v4s32_f32, // llvm.nvvm.tld4.unified.b.2d.v4s32.f32 - nvvm_tld4_unified_b_2d_v4u32_f32, // llvm.nvvm.tld4.unified.b.2d.v4u32.f32 - nvvm_tld4_unified_g_2d_v4f32_f32, // llvm.nvvm.tld4.unified.g.2d.v4f32.f32 - nvvm_tld4_unified_g_2d_v4s32_f32, // llvm.nvvm.tld4.unified.g.2d.v4s32.f32 - nvvm_tld4_unified_g_2d_v4u32_f32, // llvm.nvvm.tld4.unified.g.2d.v4u32.f32 - nvvm_tld4_unified_r_2d_v4f32_f32, // llvm.nvvm.tld4.unified.r.2d.v4f32.f32 - nvvm_tld4_unified_r_2d_v4s32_f32, // llvm.nvvm.tld4.unified.r.2d.v4s32.f32 - nvvm_tld4_unified_r_2d_v4u32_f32, // llvm.nvvm.tld4.unified.r.2d.v4u32.f32 - nvvm_trunc_d, // llvm.nvvm.trunc.d - nvvm_trunc_f, // llvm.nvvm.trunc.f - nvvm_trunc_ftz_f, // llvm.nvvm.trunc.ftz.f - nvvm_txq_array_size, // llvm.nvvm.txq.array.size - nvvm_txq_channel_data_type, // llvm.nvvm.txq.channel.data.type - nvvm_txq_channel_order, // llvm.nvvm.txq.channel.order - nvvm_txq_depth, // llvm.nvvm.txq.depth - nvvm_txq_height, // llvm.nvvm.txq.height - nvvm_txq_num_mipmap_levels, // llvm.nvvm.txq.num.mipmap.levels - nvvm_txq_num_samples, // llvm.nvvm.txq.num.samples - nvvm_txq_width, // llvm.nvvm.txq.width - nvvm_ui2d_rm, // llvm.nvvm.ui2d.rm - nvvm_ui2d_rn, // llvm.nvvm.ui2d.rn - nvvm_ui2d_rp, // llvm.nvvm.ui2d.rp - nvvm_ui2d_rz, // llvm.nvvm.ui2d.rz - nvvm_ui2f_rm, // llvm.nvvm.ui2f.rm - nvvm_ui2f_rn, // llvm.nvvm.ui2f.rn - nvvm_ui2f_rp, // llvm.nvvm.ui2f.rp - nvvm_ui2f_rz, // llvm.nvvm.ui2f.rz - nvvm_ull2d_rm, // llvm.nvvm.ull2d.rm - nvvm_ull2d_rn, // llvm.nvvm.ull2d.rn - nvvm_ull2d_rp, // llvm.nvvm.ull2d.rp - nvvm_ull2d_rz, // llvm.nvvm.ull2d.rz - nvvm_ull2f_rm, // llvm.nvvm.ull2f.rm - nvvm_ull2f_rn, // llvm.nvvm.ull2f.rn - nvvm_ull2f_rp, // llvm.nvvm.ull2f.rp - nvvm_ull2f_rz, // llvm.nvvm.ull2f.rz - nvvm_vote_all, // llvm.nvvm.vote.all - nvvm_vote_all_sync, // llvm.nvvm.vote.all.sync - nvvm_vote_any, // llvm.nvvm.vote.any - nvvm_vote_any_sync, // llvm.nvvm.vote.any.sync - nvvm_vote_ballot, // llvm.nvvm.vote.ballot - nvvm_vote_ballot_sync, // llvm.nvvm.vote.ballot.sync - nvvm_vote_uni, // llvm.nvvm.vote.uni - nvvm_vote_uni_sync, // llvm.nvvm.vote.uni.sync - nvvm_wmma_m16n16k16_load_a_bf16_col, // llvm.nvvm.wmma.m16n16k16.load.a.col.bf16 - nvvm_wmma_m16n16k16_load_a_f16_col, // llvm.nvvm.wmma.m16n16k16.load.a.col.f16 - nvvm_wmma_m16n16k16_load_a_s8_col, // llvm.nvvm.wmma.m16n16k16.load.a.col.s8 - nvvm_wmma_m16n16k16_load_a_bf16_col_stride, // llvm.nvvm.wmma.m16n16k16.load.a.col.stride.bf16 - nvvm_wmma_m16n16k16_load_a_f16_col_stride, // llvm.nvvm.wmma.m16n16k16.load.a.col.stride.f16 - nvvm_wmma_m16n16k16_load_a_s8_col_stride, // llvm.nvvm.wmma.m16n16k16.load.a.col.stride.s8 - nvvm_wmma_m16n16k16_load_a_u8_col_stride, // llvm.nvvm.wmma.m16n16k16.load.a.col.stride.u8 - nvvm_wmma_m16n16k16_load_a_u8_col, // llvm.nvvm.wmma.m16n16k16.load.a.col.u8 - nvvm_wmma_m16n16k16_load_a_bf16_row, // llvm.nvvm.wmma.m16n16k16.load.a.row.bf16 - nvvm_wmma_m16n16k16_load_a_f16_row, // llvm.nvvm.wmma.m16n16k16.load.a.row.f16 - nvvm_wmma_m16n16k16_load_a_s8_row, // llvm.nvvm.wmma.m16n16k16.load.a.row.s8 - nvvm_wmma_m16n16k16_load_a_bf16_row_stride, // llvm.nvvm.wmma.m16n16k16.load.a.row.stride.bf16 - nvvm_wmma_m16n16k16_load_a_f16_row_stride, // llvm.nvvm.wmma.m16n16k16.load.a.row.stride.f16 - nvvm_wmma_m16n16k16_load_a_s8_row_stride, // llvm.nvvm.wmma.m16n16k16.load.a.row.stride.s8 - nvvm_wmma_m16n16k16_load_a_u8_row_stride, // llvm.nvvm.wmma.m16n16k16.load.a.row.stride.u8 - nvvm_wmma_m16n16k16_load_a_u8_row, // llvm.nvvm.wmma.m16n16k16.load.a.row.u8 - nvvm_wmma_m16n16k16_load_b_bf16_col, // llvm.nvvm.wmma.m16n16k16.load.b.col.bf16 - nvvm_wmma_m16n16k16_load_b_f16_col, // llvm.nvvm.wmma.m16n16k16.load.b.col.f16 - nvvm_wmma_m16n16k16_load_b_s8_col, // llvm.nvvm.wmma.m16n16k16.load.b.col.s8 - nvvm_wmma_m16n16k16_load_b_bf16_col_stride, // llvm.nvvm.wmma.m16n16k16.load.b.col.stride.bf16 - nvvm_wmma_m16n16k16_load_b_f16_col_stride, // llvm.nvvm.wmma.m16n16k16.load.b.col.stride.f16 - nvvm_wmma_m16n16k16_load_b_s8_col_stride, // llvm.nvvm.wmma.m16n16k16.load.b.col.stride.s8 - nvvm_wmma_m16n16k16_load_b_u8_col_stride, // llvm.nvvm.wmma.m16n16k16.load.b.col.stride.u8 - nvvm_wmma_m16n16k16_load_b_u8_col, // llvm.nvvm.wmma.m16n16k16.load.b.col.u8 - nvvm_wmma_m16n16k16_load_b_bf16_row, // llvm.nvvm.wmma.m16n16k16.load.b.row.bf16 - nvvm_wmma_m16n16k16_load_b_f16_row, // llvm.nvvm.wmma.m16n16k16.load.b.row.f16 - nvvm_wmma_m16n16k16_load_b_s8_row, // llvm.nvvm.wmma.m16n16k16.load.b.row.s8 - nvvm_wmma_m16n16k16_load_b_bf16_row_stride, // llvm.nvvm.wmma.m16n16k16.load.b.row.stride.bf16 - nvvm_wmma_m16n16k16_load_b_f16_row_stride, // llvm.nvvm.wmma.m16n16k16.load.b.row.stride.f16 - nvvm_wmma_m16n16k16_load_b_s8_row_stride, // llvm.nvvm.wmma.m16n16k16.load.b.row.stride.s8 - nvvm_wmma_m16n16k16_load_b_u8_row_stride, // llvm.nvvm.wmma.m16n16k16.load.b.row.stride.u8 - nvvm_wmma_m16n16k16_load_b_u8_row, // llvm.nvvm.wmma.m16n16k16.load.b.row.u8 - nvvm_wmma_m16n16k16_load_c_f16_col, // llvm.nvvm.wmma.m16n16k16.load.c.col.f16 - nvvm_wmma_m16n16k16_load_c_f32_col, // llvm.nvvm.wmma.m16n16k16.load.c.col.f32 - nvvm_wmma_m16n16k16_load_c_s32_col, // llvm.nvvm.wmma.m16n16k16.load.c.col.s32 - nvvm_wmma_m16n16k16_load_c_f16_col_stride, // llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f16 - nvvm_wmma_m16n16k16_load_c_f32_col_stride, // llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f32 - nvvm_wmma_m16n16k16_load_c_s32_col_stride, // llvm.nvvm.wmma.m16n16k16.load.c.col.stride.s32 - nvvm_wmma_m16n16k16_load_c_f16_row, // llvm.nvvm.wmma.m16n16k16.load.c.row.f16 - nvvm_wmma_m16n16k16_load_c_f32_row, // llvm.nvvm.wmma.m16n16k16.load.c.row.f32 - nvvm_wmma_m16n16k16_load_c_s32_row, // llvm.nvvm.wmma.m16n16k16.load.c.row.s32 - nvvm_wmma_m16n16k16_load_c_f16_row_stride, // llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f16 - nvvm_wmma_m16n16k16_load_c_f32_row_stride, // llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f32 - nvvm_wmma_m16n16k16_load_c_s32_row_stride, // llvm.nvvm.wmma.m16n16k16.load.c.row.stride.s32 - nvvm_wmma_m16n16k16_mma_col_col_bf16, // llvm.nvvm.wmma.m16n16k16.mma.col.col.bf16 - nvvm_wmma_m16n16k16_mma_col_col_f16_f16, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16 - nvvm_wmma_m16n16k16_mma_col_col_f16_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16.satfinite - nvvm_wmma_m16n16k16_mma_col_col_f16_f32, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32 - nvvm_wmma_m16n16k16_mma_col_col_f16_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32.satfinite - nvvm_wmma_m16n16k16_mma_col_col_f32_f16, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16 - nvvm_wmma_m16n16k16_mma_col_col_f32_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16.satfinite - nvvm_wmma_m16n16k16_mma_col_col_f32_f32, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32 - nvvm_wmma_m16n16k16_mma_col_col_f32_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32.satfinite - nvvm_wmma_m16n16k16_mma_col_col_s8, // llvm.nvvm.wmma.m16n16k16.mma.col.col.s8 - nvvm_wmma_m16n16k16_mma_col_col_s8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.s8.satfinite - nvvm_wmma_m16n16k16_mma_col_col_u8, // llvm.nvvm.wmma.m16n16k16.mma.col.col.u8 - nvvm_wmma_m16n16k16_mma_col_col_u8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.col.u8.satfinite - nvvm_wmma_m16n16k16_mma_col_row_bf16, // llvm.nvvm.wmma.m16n16k16.mma.col.row.bf16 - nvvm_wmma_m16n16k16_mma_col_row_f16_f16, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16 - nvvm_wmma_m16n16k16_mma_col_row_f16_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16.satfinite - nvvm_wmma_m16n16k16_mma_col_row_f16_f32, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32 - nvvm_wmma_m16n16k16_mma_col_row_f16_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32.satfinite - nvvm_wmma_m16n16k16_mma_col_row_f32_f16, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16 - nvvm_wmma_m16n16k16_mma_col_row_f32_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16.satfinite - nvvm_wmma_m16n16k16_mma_col_row_f32_f32, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32 - nvvm_wmma_m16n16k16_mma_col_row_f32_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32.satfinite - nvvm_wmma_m16n16k16_mma_col_row_s8, // llvm.nvvm.wmma.m16n16k16.mma.col.row.s8 - nvvm_wmma_m16n16k16_mma_col_row_s8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.s8.satfinite - nvvm_wmma_m16n16k16_mma_col_row_u8, // llvm.nvvm.wmma.m16n16k16.mma.col.row.u8 - nvvm_wmma_m16n16k16_mma_col_row_u8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.col.row.u8.satfinite - nvvm_wmma_m16n16k16_mma_row_col_bf16, // llvm.nvvm.wmma.m16n16k16.mma.row.col.bf16 - nvvm_wmma_m16n16k16_mma_row_col_f16_f16, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16 - nvvm_wmma_m16n16k16_mma_row_col_f16_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16.satfinite - nvvm_wmma_m16n16k16_mma_row_col_f16_f32, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32 - nvvm_wmma_m16n16k16_mma_row_col_f16_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32.satfinite - nvvm_wmma_m16n16k16_mma_row_col_f32_f16, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16 - nvvm_wmma_m16n16k16_mma_row_col_f32_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16.satfinite - nvvm_wmma_m16n16k16_mma_row_col_f32_f32, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32 - nvvm_wmma_m16n16k16_mma_row_col_f32_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32.satfinite - nvvm_wmma_m16n16k16_mma_row_col_s8, // llvm.nvvm.wmma.m16n16k16.mma.row.col.s8 - nvvm_wmma_m16n16k16_mma_row_col_s8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.s8.satfinite - nvvm_wmma_m16n16k16_mma_row_col_u8, // llvm.nvvm.wmma.m16n16k16.mma.row.col.u8 - nvvm_wmma_m16n16k16_mma_row_col_u8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.col.u8.satfinite - nvvm_wmma_m16n16k16_mma_row_row_bf16, // llvm.nvvm.wmma.m16n16k16.mma.row.row.bf16 - nvvm_wmma_m16n16k16_mma_row_row_f16_f16, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16 - nvvm_wmma_m16n16k16_mma_row_row_f16_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16.satfinite - nvvm_wmma_m16n16k16_mma_row_row_f16_f32, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32 - nvvm_wmma_m16n16k16_mma_row_row_f16_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32.satfinite - nvvm_wmma_m16n16k16_mma_row_row_f32_f16, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16 - nvvm_wmma_m16n16k16_mma_row_row_f32_f16_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16.satfinite - nvvm_wmma_m16n16k16_mma_row_row_f32_f32, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32 - nvvm_wmma_m16n16k16_mma_row_row_f32_f32_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32.satfinite - nvvm_wmma_m16n16k16_mma_row_row_s8, // llvm.nvvm.wmma.m16n16k16.mma.row.row.s8 - nvvm_wmma_m16n16k16_mma_row_row_s8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.s8.satfinite - nvvm_wmma_m16n16k16_mma_row_row_u8, // llvm.nvvm.wmma.m16n16k16.mma.row.row.u8 - nvvm_wmma_m16n16k16_mma_row_row_u8_satfinite, // llvm.nvvm.wmma.m16n16k16.mma.row.row.u8.satfinite - nvvm_wmma_m16n16k16_store_d_f16_col, // llvm.nvvm.wmma.m16n16k16.store.d.col.f16 - nvvm_wmma_m16n16k16_store_d_f32_col, // llvm.nvvm.wmma.m16n16k16.store.d.col.f32 - nvvm_wmma_m16n16k16_store_d_s32_col, // llvm.nvvm.wmma.m16n16k16.store.d.col.s32 - nvvm_wmma_m16n16k16_store_d_f16_col_stride, // llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f16 - nvvm_wmma_m16n16k16_store_d_f32_col_stride, // llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f32 - nvvm_wmma_m16n16k16_store_d_s32_col_stride, // llvm.nvvm.wmma.m16n16k16.store.d.col.stride.s32 - nvvm_wmma_m16n16k16_store_d_f16_row, // llvm.nvvm.wmma.m16n16k16.store.d.row.f16 - nvvm_wmma_m16n16k16_store_d_f32_row, // llvm.nvvm.wmma.m16n16k16.store.d.row.f32 - nvvm_wmma_m16n16k16_store_d_s32_row, // llvm.nvvm.wmma.m16n16k16.store.d.row.s32 - nvvm_wmma_m16n16k16_store_d_f16_row_stride, // llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f16 - nvvm_wmma_m16n16k16_store_d_f32_row_stride, // llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f32 - nvvm_wmma_m16n16k16_store_d_s32_row_stride, // llvm.nvvm.wmma.m16n16k16.store.d.row.stride.s32 - nvvm_wmma_m16n16k8_load_a_tf32_col_stride, // llvm.nvvm.wmma.m16n16k8.load.a.col.stride.tf32 - nvvm_wmma_m16n16k8_load_a_tf32_col, // llvm.nvvm.wmma.m16n16k8.load.a.col.tf32 - nvvm_wmma_m16n16k8_load_a_tf32_row_stride, // llvm.nvvm.wmma.m16n16k8.load.a.row.stride.tf32 - nvvm_wmma_m16n16k8_load_a_tf32_row, // llvm.nvvm.wmma.m16n16k8.load.a.row.tf32 - nvvm_wmma_m16n16k8_load_b_tf32_col_stride, // llvm.nvvm.wmma.m16n16k8.load.b.col.stride.tf32 - nvvm_wmma_m16n16k8_load_b_tf32_col, // llvm.nvvm.wmma.m16n16k8.load.b.col.tf32 - nvvm_wmma_m16n16k8_load_b_tf32_row_stride, // llvm.nvvm.wmma.m16n16k8.load.b.row.stride.tf32 - nvvm_wmma_m16n16k8_load_b_tf32_row, // llvm.nvvm.wmma.m16n16k8.load.b.row.tf32 - nvvm_wmma_m16n16k8_load_c_f32_col, // llvm.nvvm.wmma.m16n16k8.load.c.col.f32 - nvvm_wmma_m16n16k8_load_c_f32_col_stride, // llvm.nvvm.wmma.m16n16k8.load.c.col.stride.f32 - nvvm_wmma_m16n16k8_load_c_f32_row, // llvm.nvvm.wmma.m16n16k8.load.c.row.f32 - nvvm_wmma_m16n16k8_load_c_f32_row_stride, // llvm.nvvm.wmma.m16n16k8.load.c.row.stride.f32 - nvvm_wmma_m16n16k8_mma_col_col_tf32, // llvm.nvvm.wmma.m16n16k8.mma.col.col.tf32 - nvvm_wmma_m16n16k8_mma_col_row_tf32, // llvm.nvvm.wmma.m16n16k8.mma.col.row.tf32 - nvvm_wmma_m16n16k8_mma_row_col_tf32, // llvm.nvvm.wmma.m16n16k8.mma.row.col.tf32 - nvvm_wmma_m16n16k8_mma_row_row_tf32, // llvm.nvvm.wmma.m16n16k8.mma.row.row.tf32 - nvvm_wmma_m16n16k8_store_d_f32_col, // llvm.nvvm.wmma.m16n16k8.store.d.col.f32 - nvvm_wmma_m16n16k8_store_d_f32_col_stride, // llvm.nvvm.wmma.m16n16k8.store.d.col.stride.f32 - nvvm_wmma_m16n16k8_store_d_f32_row, // llvm.nvvm.wmma.m16n16k8.store.d.row.f32 - nvvm_wmma_m16n16k8_store_d_f32_row_stride, // llvm.nvvm.wmma.m16n16k8.store.d.row.stride.f32 - nvvm_wmma_m32n8k16_load_a_bf16_col, // llvm.nvvm.wmma.m32n8k16.load.a.col.bf16 - nvvm_wmma_m32n8k16_load_a_f16_col, // llvm.nvvm.wmma.m32n8k16.load.a.col.f16 - nvvm_wmma_m32n8k16_load_a_s8_col, // llvm.nvvm.wmma.m32n8k16.load.a.col.s8 - nvvm_wmma_m32n8k16_load_a_bf16_col_stride, // llvm.nvvm.wmma.m32n8k16.load.a.col.stride.bf16 - nvvm_wmma_m32n8k16_load_a_f16_col_stride, // llvm.nvvm.wmma.m32n8k16.load.a.col.stride.f16 - nvvm_wmma_m32n8k16_load_a_s8_col_stride, // llvm.nvvm.wmma.m32n8k16.load.a.col.stride.s8 - nvvm_wmma_m32n8k16_load_a_u8_col_stride, // llvm.nvvm.wmma.m32n8k16.load.a.col.stride.u8 - nvvm_wmma_m32n8k16_load_a_u8_col, // llvm.nvvm.wmma.m32n8k16.load.a.col.u8 - nvvm_wmma_m32n8k16_load_a_bf16_row, // llvm.nvvm.wmma.m32n8k16.load.a.row.bf16 - nvvm_wmma_m32n8k16_load_a_f16_row, // llvm.nvvm.wmma.m32n8k16.load.a.row.f16 - nvvm_wmma_m32n8k16_load_a_s8_row, // llvm.nvvm.wmma.m32n8k16.load.a.row.s8 - nvvm_wmma_m32n8k16_load_a_bf16_row_stride, // llvm.nvvm.wmma.m32n8k16.load.a.row.stride.bf16 - nvvm_wmma_m32n8k16_load_a_f16_row_stride, // llvm.nvvm.wmma.m32n8k16.load.a.row.stride.f16 - nvvm_wmma_m32n8k16_load_a_s8_row_stride, // llvm.nvvm.wmma.m32n8k16.load.a.row.stride.s8 - nvvm_wmma_m32n8k16_load_a_u8_row_stride, // llvm.nvvm.wmma.m32n8k16.load.a.row.stride.u8 - nvvm_wmma_m32n8k16_load_a_u8_row, // llvm.nvvm.wmma.m32n8k16.load.a.row.u8 - nvvm_wmma_m32n8k16_load_b_bf16_col, // llvm.nvvm.wmma.m32n8k16.load.b.col.bf16 - nvvm_wmma_m32n8k16_load_b_f16_col, // llvm.nvvm.wmma.m32n8k16.load.b.col.f16 - nvvm_wmma_m32n8k16_load_b_s8_col, // llvm.nvvm.wmma.m32n8k16.load.b.col.s8 - nvvm_wmma_m32n8k16_load_b_bf16_col_stride, // llvm.nvvm.wmma.m32n8k16.load.b.col.stride.bf16 - nvvm_wmma_m32n8k16_load_b_f16_col_stride, // llvm.nvvm.wmma.m32n8k16.load.b.col.stride.f16 - nvvm_wmma_m32n8k16_load_b_s8_col_stride, // llvm.nvvm.wmma.m32n8k16.load.b.col.stride.s8 - nvvm_wmma_m32n8k16_load_b_u8_col_stride, // llvm.nvvm.wmma.m32n8k16.load.b.col.stride.u8 - nvvm_wmma_m32n8k16_load_b_u8_col, // llvm.nvvm.wmma.m32n8k16.load.b.col.u8 - nvvm_wmma_m32n8k16_load_b_bf16_row, // llvm.nvvm.wmma.m32n8k16.load.b.row.bf16 - nvvm_wmma_m32n8k16_load_b_f16_row, // llvm.nvvm.wmma.m32n8k16.load.b.row.f16 - nvvm_wmma_m32n8k16_load_b_s8_row, // llvm.nvvm.wmma.m32n8k16.load.b.row.s8 - nvvm_wmma_m32n8k16_load_b_bf16_row_stride, // llvm.nvvm.wmma.m32n8k16.load.b.row.stride.bf16 - nvvm_wmma_m32n8k16_load_b_f16_row_stride, // llvm.nvvm.wmma.m32n8k16.load.b.row.stride.f16 - nvvm_wmma_m32n8k16_load_b_s8_row_stride, // llvm.nvvm.wmma.m32n8k16.load.b.row.stride.s8 - nvvm_wmma_m32n8k16_load_b_u8_row_stride, // llvm.nvvm.wmma.m32n8k16.load.b.row.stride.u8 - nvvm_wmma_m32n8k16_load_b_u8_row, // llvm.nvvm.wmma.m32n8k16.load.b.row.u8 - nvvm_wmma_m32n8k16_load_c_f16_col, // llvm.nvvm.wmma.m32n8k16.load.c.col.f16 - nvvm_wmma_m32n8k16_load_c_f32_col, // llvm.nvvm.wmma.m32n8k16.load.c.col.f32 - nvvm_wmma_m32n8k16_load_c_s32_col, // llvm.nvvm.wmma.m32n8k16.load.c.col.s32 - nvvm_wmma_m32n8k16_load_c_f16_col_stride, // llvm.nvvm.wmma.m32n8k16.load.c.col.stride.f16 - nvvm_wmma_m32n8k16_load_c_f32_col_stride, // llvm.nvvm.wmma.m32n8k16.load.c.col.stride.f32 - nvvm_wmma_m32n8k16_load_c_s32_col_stride, // llvm.nvvm.wmma.m32n8k16.load.c.col.stride.s32 - nvvm_wmma_m32n8k16_load_c_f16_row, // llvm.nvvm.wmma.m32n8k16.load.c.row.f16 - nvvm_wmma_m32n8k16_load_c_f32_row, // llvm.nvvm.wmma.m32n8k16.load.c.row.f32 - nvvm_wmma_m32n8k16_load_c_s32_row, // llvm.nvvm.wmma.m32n8k16.load.c.row.s32 - nvvm_wmma_m32n8k16_load_c_f16_row_stride, // llvm.nvvm.wmma.m32n8k16.load.c.row.stride.f16 - nvvm_wmma_m32n8k16_load_c_f32_row_stride, // llvm.nvvm.wmma.m32n8k16.load.c.row.stride.f32 - nvvm_wmma_m32n8k16_load_c_s32_row_stride, // llvm.nvvm.wmma.m32n8k16.load.c.row.stride.s32 - nvvm_wmma_m32n8k16_mma_col_col_bf16, // llvm.nvvm.wmma.m32n8k16.mma.col.col.bf16 - nvvm_wmma_m32n8k16_mma_col_col_f16_f16, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f16 - nvvm_wmma_m32n8k16_mma_col_col_f16_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f16.satfinite - nvvm_wmma_m32n8k16_mma_col_col_f16_f32, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f32 - nvvm_wmma_m32n8k16_mma_col_col_f16_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f32.satfinite - nvvm_wmma_m32n8k16_mma_col_col_f32_f16, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f16 - nvvm_wmma_m32n8k16_mma_col_col_f32_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f16.satfinite - nvvm_wmma_m32n8k16_mma_col_col_f32_f32, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f32 - nvvm_wmma_m32n8k16_mma_col_col_f32_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f32.satfinite - nvvm_wmma_m32n8k16_mma_col_col_s8, // llvm.nvvm.wmma.m32n8k16.mma.col.col.s8 - nvvm_wmma_m32n8k16_mma_col_col_s8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.s8.satfinite - nvvm_wmma_m32n8k16_mma_col_col_u8, // llvm.nvvm.wmma.m32n8k16.mma.col.col.u8 - nvvm_wmma_m32n8k16_mma_col_col_u8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.col.u8.satfinite - nvvm_wmma_m32n8k16_mma_col_row_bf16, // llvm.nvvm.wmma.m32n8k16.mma.col.row.bf16 - nvvm_wmma_m32n8k16_mma_col_row_f16_f16, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f16 - nvvm_wmma_m32n8k16_mma_col_row_f16_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f16.satfinite - nvvm_wmma_m32n8k16_mma_col_row_f16_f32, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f32 - nvvm_wmma_m32n8k16_mma_col_row_f16_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f32.satfinite - nvvm_wmma_m32n8k16_mma_col_row_f32_f16, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f16 - nvvm_wmma_m32n8k16_mma_col_row_f32_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f16.satfinite - nvvm_wmma_m32n8k16_mma_col_row_f32_f32, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f32 - nvvm_wmma_m32n8k16_mma_col_row_f32_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f32.satfinite - nvvm_wmma_m32n8k16_mma_col_row_s8, // llvm.nvvm.wmma.m32n8k16.mma.col.row.s8 - nvvm_wmma_m32n8k16_mma_col_row_s8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.s8.satfinite - nvvm_wmma_m32n8k16_mma_col_row_u8, // llvm.nvvm.wmma.m32n8k16.mma.col.row.u8 - nvvm_wmma_m32n8k16_mma_col_row_u8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.col.row.u8.satfinite - nvvm_wmma_m32n8k16_mma_row_col_bf16, // llvm.nvvm.wmma.m32n8k16.mma.row.col.bf16 - nvvm_wmma_m32n8k16_mma_row_col_f16_f16, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f16 - nvvm_wmma_m32n8k16_mma_row_col_f16_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f16.satfinite - nvvm_wmma_m32n8k16_mma_row_col_f16_f32, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f32 - nvvm_wmma_m32n8k16_mma_row_col_f16_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f32.satfinite - nvvm_wmma_m32n8k16_mma_row_col_f32_f16, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f16 - nvvm_wmma_m32n8k16_mma_row_col_f32_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f16.satfinite - nvvm_wmma_m32n8k16_mma_row_col_f32_f32, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f32 - nvvm_wmma_m32n8k16_mma_row_col_f32_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f32.satfinite - nvvm_wmma_m32n8k16_mma_row_col_s8, // llvm.nvvm.wmma.m32n8k16.mma.row.col.s8 - nvvm_wmma_m32n8k16_mma_row_col_s8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.s8.satfinite - nvvm_wmma_m32n8k16_mma_row_col_u8, // llvm.nvvm.wmma.m32n8k16.mma.row.col.u8 - nvvm_wmma_m32n8k16_mma_row_col_u8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.col.u8.satfinite - nvvm_wmma_m32n8k16_mma_row_row_bf16, // llvm.nvvm.wmma.m32n8k16.mma.row.row.bf16 - nvvm_wmma_m32n8k16_mma_row_row_f16_f16, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f16 - nvvm_wmma_m32n8k16_mma_row_row_f16_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f16.satfinite - nvvm_wmma_m32n8k16_mma_row_row_f16_f32, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f32 - nvvm_wmma_m32n8k16_mma_row_row_f16_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f32.satfinite - nvvm_wmma_m32n8k16_mma_row_row_f32_f16, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f16 - nvvm_wmma_m32n8k16_mma_row_row_f32_f16_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f16.satfinite - nvvm_wmma_m32n8k16_mma_row_row_f32_f32, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f32 - nvvm_wmma_m32n8k16_mma_row_row_f32_f32_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f32.satfinite - nvvm_wmma_m32n8k16_mma_row_row_s8, // llvm.nvvm.wmma.m32n8k16.mma.row.row.s8 - nvvm_wmma_m32n8k16_mma_row_row_s8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.s8.satfinite - nvvm_wmma_m32n8k16_mma_row_row_u8, // llvm.nvvm.wmma.m32n8k16.mma.row.row.u8 - nvvm_wmma_m32n8k16_mma_row_row_u8_satfinite, // llvm.nvvm.wmma.m32n8k16.mma.row.row.u8.satfinite - nvvm_wmma_m32n8k16_store_d_f16_col, // llvm.nvvm.wmma.m32n8k16.store.d.col.f16 - nvvm_wmma_m32n8k16_store_d_f32_col, // llvm.nvvm.wmma.m32n8k16.store.d.col.f32 - nvvm_wmma_m32n8k16_store_d_s32_col, // llvm.nvvm.wmma.m32n8k16.store.d.col.s32 - nvvm_wmma_m32n8k16_store_d_f16_col_stride, // llvm.nvvm.wmma.m32n8k16.store.d.col.stride.f16 - nvvm_wmma_m32n8k16_store_d_f32_col_stride, // llvm.nvvm.wmma.m32n8k16.store.d.col.stride.f32 - nvvm_wmma_m32n8k16_store_d_s32_col_stride, // llvm.nvvm.wmma.m32n8k16.store.d.col.stride.s32 - nvvm_wmma_m32n8k16_store_d_f16_row, // llvm.nvvm.wmma.m32n8k16.store.d.row.f16 - nvvm_wmma_m32n8k16_store_d_f32_row, // llvm.nvvm.wmma.m32n8k16.store.d.row.f32 - nvvm_wmma_m32n8k16_store_d_s32_row, // llvm.nvvm.wmma.m32n8k16.store.d.row.s32 - nvvm_wmma_m32n8k16_store_d_f16_row_stride, // llvm.nvvm.wmma.m32n8k16.store.d.row.stride.f16 - nvvm_wmma_m32n8k16_store_d_f32_row_stride, // llvm.nvvm.wmma.m32n8k16.store.d.row.stride.f32 - nvvm_wmma_m32n8k16_store_d_s32_row_stride, // llvm.nvvm.wmma.m32n8k16.store.d.row.stride.s32 - nvvm_wmma_m8n32k16_load_a_bf16_col, // llvm.nvvm.wmma.m8n32k16.load.a.col.bf16 - nvvm_wmma_m8n32k16_load_a_f16_col, // llvm.nvvm.wmma.m8n32k16.load.a.col.f16 - nvvm_wmma_m8n32k16_load_a_s8_col, // llvm.nvvm.wmma.m8n32k16.load.a.col.s8 - nvvm_wmma_m8n32k16_load_a_bf16_col_stride, // llvm.nvvm.wmma.m8n32k16.load.a.col.stride.bf16 - nvvm_wmma_m8n32k16_load_a_f16_col_stride, // llvm.nvvm.wmma.m8n32k16.load.a.col.stride.f16 - nvvm_wmma_m8n32k16_load_a_s8_col_stride, // llvm.nvvm.wmma.m8n32k16.load.a.col.stride.s8 - nvvm_wmma_m8n32k16_load_a_u8_col_stride, // llvm.nvvm.wmma.m8n32k16.load.a.col.stride.u8 - nvvm_wmma_m8n32k16_load_a_u8_col, // llvm.nvvm.wmma.m8n32k16.load.a.col.u8 - nvvm_wmma_m8n32k16_load_a_bf16_row, // llvm.nvvm.wmma.m8n32k16.load.a.row.bf16 - nvvm_wmma_m8n32k16_load_a_f16_row, // llvm.nvvm.wmma.m8n32k16.load.a.row.f16 - nvvm_wmma_m8n32k16_load_a_s8_row, // llvm.nvvm.wmma.m8n32k16.load.a.row.s8 - nvvm_wmma_m8n32k16_load_a_bf16_row_stride, // llvm.nvvm.wmma.m8n32k16.load.a.row.stride.bf16 - nvvm_wmma_m8n32k16_load_a_f16_row_stride, // llvm.nvvm.wmma.m8n32k16.load.a.row.stride.f16 - nvvm_wmma_m8n32k16_load_a_s8_row_stride, // llvm.nvvm.wmma.m8n32k16.load.a.row.stride.s8 - nvvm_wmma_m8n32k16_load_a_u8_row_stride, // llvm.nvvm.wmma.m8n32k16.load.a.row.stride.u8 - nvvm_wmma_m8n32k16_load_a_u8_row, // llvm.nvvm.wmma.m8n32k16.load.a.row.u8 - nvvm_wmma_m8n32k16_load_b_bf16_col, // llvm.nvvm.wmma.m8n32k16.load.b.col.bf16 - nvvm_wmma_m8n32k16_load_b_f16_col, // llvm.nvvm.wmma.m8n32k16.load.b.col.f16 - nvvm_wmma_m8n32k16_load_b_s8_col, // llvm.nvvm.wmma.m8n32k16.load.b.col.s8 - nvvm_wmma_m8n32k16_load_b_bf16_col_stride, // llvm.nvvm.wmma.m8n32k16.load.b.col.stride.bf16 - nvvm_wmma_m8n32k16_load_b_f16_col_stride, // llvm.nvvm.wmma.m8n32k16.load.b.col.stride.f16 - nvvm_wmma_m8n32k16_load_b_s8_col_stride, // llvm.nvvm.wmma.m8n32k16.load.b.col.stride.s8 - nvvm_wmma_m8n32k16_load_b_u8_col_stride, // llvm.nvvm.wmma.m8n32k16.load.b.col.stride.u8 - nvvm_wmma_m8n32k16_load_b_u8_col, // llvm.nvvm.wmma.m8n32k16.load.b.col.u8 - nvvm_wmma_m8n32k16_load_b_bf16_row, // llvm.nvvm.wmma.m8n32k16.load.b.row.bf16 - nvvm_wmma_m8n32k16_load_b_f16_row, // llvm.nvvm.wmma.m8n32k16.load.b.row.f16 - nvvm_wmma_m8n32k16_load_b_s8_row, // llvm.nvvm.wmma.m8n32k16.load.b.row.s8 - nvvm_wmma_m8n32k16_load_b_bf16_row_stride, // llvm.nvvm.wmma.m8n32k16.load.b.row.stride.bf16 - nvvm_wmma_m8n32k16_load_b_f16_row_stride, // llvm.nvvm.wmma.m8n32k16.load.b.row.stride.f16 - nvvm_wmma_m8n32k16_load_b_s8_row_stride, // llvm.nvvm.wmma.m8n32k16.load.b.row.stride.s8 - nvvm_wmma_m8n32k16_load_b_u8_row_stride, // llvm.nvvm.wmma.m8n32k16.load.b.row.stride.u8 - nvvm_wmma_m8n32k16_load_b_u8_row, // llvm.nvvm.wmma.m8n32k16.load.b.row.u8 - nvvm_wmma_m8n32k16_load_c_f16_col, // llvm.nvvm.wmma.m8n32k16.load.c.col.f16 - nvvm_wmma_m8n32k16_load_c_f32_col, // llvm.nvvm.wmma.m8n32k16.load.c.col.f32 - nvvm_wmma_m8n32k16_load_c_s32_col, // llvm.nvvm.wmma.m8n32k16.load.c.col.s32 - nvvm_wmma_m8n32k16_load_c_f16_col_stride, // llvm.nvvm.wmma.m8n32k16.load.c.col.stride.f16 - nvvm_wmma_m8n32k16_load_c_f32_col_stride, // llvm.nvvm.wmma.m8n32k16.load.c.col.stride.f32 - nvvm_wmma_m8n32k16_load_c_s32_col_stride, // llvm.nvvm.wmma.m8n32k16.load.c.col.stride.s32 - nvvm_wmma_m8n32k16_load_c_f16_row, // llvm.nvvm.wmma.m8n32k16.load.c.row.f16 - nvvm_wmma_m8n32k16_load_c_f32_row, // llvm.nvvm.wmma.m8n32k16.load.c.row.f32 - nvvm_wmma_m8n32k16_load_c_s32_row, // llvm.nvvm.wmma.m8n32k16.load.c.row.s32 - nvvm_wmma_m8n32k16_load_c_f16_row_stride, // llvm.nvvm.wmma.m8n32k16.load.c.row.stride.f16 - nvvm_wmma_m8n32k16_load_c_f32_row_stride, // llvm.nvvm.wmma.m8n32k16.load.c.row.stride.f32 - nvvm_wmma_m8n32k16_load_c_s32_row_stride, // llvm.nvvm.wmma.m8n32k16.load.c.row.stride.s32 - nvvm_wmma_m8n32k16_mma_col_col_bf16, // llvm.nvvm.wmma.m8n32k16.mma.col.col.bf16 - nvvm_wmma_m8n32k16_mma_col_col_f16_f16, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f16 - nvvm_wmma_m8n32k16_mma_col_col_f16_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f16.satfinite - nvvm_wmma_m8n32k16_mma_col_col_f16_f32, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f32 - nvvm_wmma_m8n32k16_mma_col_col_f16_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f32.satfinite - nvvm_wmma_m8n32k16_mma_col_col_f32_f16, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f16 - nvvm_wmma_m8n32k16_mma_col_col_f32_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f16.satfinite - nvvm_wmma_m8n32k16_mma_col_col_f32_f32, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f32 - nvvm_wmma_m8n32k16_mma_col_col_f32_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f32.satfinite - nvvm_wmma_m8n32k16_mma_col_col_s8, // llvm.nvvm.wmma.m8n32k16.mma.col.col.s8 - nvvm_wmma_m8n32k16_mma_col_col_s8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.s8.satfinite - nvvm_wmma_m8n32k16_mma_col_col_u8, // llvm.nvvm.wmma.m8n32k16.mma.col.col.u8 - nvvm_wmma_m8n32k16_mma_col_col_u8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.col.u8.satfinite - nvvm_wmma_m8n32k16_mma_col_row_bf16, // llvm.nvvm.wmma.m8n32k16.mma.col.row.bf16 - nvvm_wmma_m8n32k16_mma_col_row_f16_f16, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f16 - nvvm_wmma_m8n32k16_mma_col_row_f16_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f16.satfinite - nvvm_wmma_m8n32k16_mma_col_row_f16_f32, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f32 - nvvm_wmma_m8n32k16_mma_col_row_f16_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f32.satfinite - nvvm_wmma_m8n32k16_mma_col_row_f32_f16, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f16 - nvvm_wmma_m8n32k16_mma_col_row_f32_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f16.satfinite - nvvm_wmma_m8n32k16_mma_col_row_f32_f32, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f32 - nvvm_wmma_m8n32k16_mma_col_row_f32_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f32.satfinite - nvvm_wmma_m8n32k16_mma_col_row_s8, // llvm.nvvm.wmma.m8n32k16.mma.col.row.s8 - nvvm_wmma_m8n32k16_mma_col_row_s8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.s8.satfinite - nvvm_wmma_m8n32k16_mma_col_row_u8, // llvm.nvvm.wmma.m8n32k16.mma.col.row.u8 - nvvm_wmma_m8n32k16_mma_col_row_u8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.col.row.u8.satfinite - nvvm_wmma_m8n32k16_mma_row_col_bf16, // llvm.nvvm.wmma.m8n32k16.mma.row.col.bf16 - nvvm_wmma_m8n32k16_mma_row_col_f16_f16, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f16 - nvvm_wmma_m8n32k16_mma_row_col_f16_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f16.satfinite - nvvm_wmma_m8n32k16_mma_row_col_f16_f32, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f32 - nvvm_wmma_m8n32k16_mma_row_col_f16_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f32.satfinite - nvvm_wmma_m8n32k16_mma_row_col_f32_f16, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f16 - nvvm_wmma_m8n32k16_mma_row_col_f32_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f16.satfinite - nvvm_wmma_m8n32k16_mma_row_col_f32_f32, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f32 - nvvm_wmma_m8n32k16_mma_row_col_f32_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f32.satfinite - nvvm_wmma_m8n32k16_mma_row_col_s8, // llvm.nvvm.wmma.m8n32k16.mma.row.col.s8 - nvvm_wmma_m8n32k16_mma_row_col_s8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.s8.satfinite - nvvm_wmma_m8n32k16_mma_row_col_u8, // llvm.nvvm.wmma.m8n32k16.mma.row.col.u8 - nvvm_wmma_m8n32k16_mma_row_col_u8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.col.u8.satfinite - nvvm_wmma_m8n32k16_mma_row_row_bf16, // llvm.nvvm.wmma.m8n32k16.mma.row.row.bf16 - nvvm_wmma_m8n32k16_mma_row_row_f16_f16, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f16 - nvvm_wmma_m8n32k16_mma_row_row_f16_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f16.satfinite - nvvm_wmma_m8n32k16_mma_row_row_f16_f32, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f32 - nvvm_wmma_m8n32k16_mma_row_row_f16_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f32.satfinite - nvvm_wmma_m8n32k16_mma_row_row_f32_f16, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f16 - nvvm_wmma_m8n32k16_mma_row_row_f32_f16_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f16.satfinite - nvvm_wmma_m8n32k16_mma_row_row_f32_f32, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f32 - nvvm_wmma_m8n32k16_mma_row_row_f32_f32_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f32.satfinite - nvvm_wmma_m8n32k16_mma_row_row_s8, // llvm.nvvm.wmma.m8n32k16.mma.row.row.s8 - nvvm_wmma_m8n32k16_mma_row_row_s8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.s8.satfinite - nvvm_wmma_m8n32k16_mma_row_row_u8, // llvm.nvvm.wmma.m8n32k16.mma.row.row.u8 - nvvm_wmma_m8n32k16_mma_row_row_u8_satfinite, // llvm.nvvm.wmma.m8n32k16.mma.row.row.u8.satfinite - nvvm_wmma_m8n32k16_store_d_f16_col, // llvm.nvvm.wmma.m8n32k16.store.d.col.f16 - nvvm_wmma_m8n32k16_store_d_f32_col, // llvm.nvvm.wmma.m8n32k16.store.d.col.f32 - nvvm_wmma_m8n32k16_store_d_s32_col, // llvm.nvvm.wmma.m8n32k16.store.d.col.s32 - nvvm_wmma_m8n32k16_store_d_f16_col_stride, // llvm.nvvm.wmma.m8n32k16.store.d.col.stride.f16 - nvvm_wmma_m8n32k16_store_d_f32_col_stride, // llvm.nvvm.wmma.m8n32k16.store.d.col.stride.f32 - nvvm_wmma_m8n32k16_store_d_s32_col_stride, // llvm.nvvm.wmma.m8n32k16.store.d.col.stride.s32 - nvvm_wmma_m8n32k16_store_d_f16_row, // llvm.nvvm.wmma.m8n32k16.store.d.row.f16 - nvvm_wmma_m8n32k16_store_d_f32_row, // llvm.nvvm.wmma.m8n32k16.store.d.row.f32 - nvvm_wmma_m8n32k16_store_d_s32_row, // llvm.nvvm.wmma.m8n32k16.store.d.row.s32 - nvvm_wmma_m8n32k16_store_d_f16_row_stride, // llvm.nvvm.wmma.m8n32k16.store.d.row.stride.f16 - nvvm_wmma_m8n32k16_store_d_f32_row_stride, // llvm.nvvm.wmma.m8n32k16.store.d.row.stride.f32 - nvvm_wmma_m8n32k16_store_d_s32_row_stride, // llvm.nvvm.wmma.m8n32k16.store.d.row.stride.s32 - nvvm_wmma_m8n8k128_load_a_b1_row, // llvm.nvvm.wmma.m8n8k128.load.a.row.b1 - nvvm_wmma_m8n8k128_load_a_b1_row_stride, // llvm.nvvm.wmma.m8n8k128.load.a.row.stride.b1 - nvvm_wmma_m8n8k128_load_b_b1_col, // llvm.nvvm.wmma.m8n8k128.load.b.col.b1 - nvvm_wmma_m8n8k128_load_b_b1_col_stride, // llvm.nvvm.wmma.m8n8k128.load.b.col.stride.b1 - nvvm_wmma_m8n8k128_load_c_s32_col, // llvm.nvvm.wmma.m8n8k128.load.c.col.s32 - nvvm_wmma_m8n8k128_load_c_s32_col_stride, // llvm.nvvm.wmma.m8n8k128.load.c.col.stride.s32 - nvvm_wmma_m8n8k128_load_c_s32_row, // llvm.nvvm.wmma.m8n8k128.load.c.row.s32 - nvvm_wmma_m8n8k128_load_c_s32_row_stride, // llvm.nvvm.wmma.m8n8k128.load.c.row.stride.s32 - nvvm_wmma_m8n8k128_mma_and_popc_row_col_b1, // llvm.nvvm.wmma.m8n8k128.mma.and.popc.row.col.b1 - nvvm_wmma_m8n8k128_mma_xor_popc_row_col_b1, // llvm.nvvm.wmma.m8n8k128.mma.xor.popc.row.col.b1 - nvvm_wmma_m8n8k128_store_d_s32_col, // llvm.nvvm.wmma.m8n8k128.store.d.col.s32 - nvvm_wmma_m8n8k128_store_d_s32_col_stride, // llvm.nvvm.wmma.m8n8k128.store.d.col.stride.s32 - nvvm_wmma_m8n8k128_store_d_s32_row, // llvm.nvvm.wmma.m8n8k128.store.d.row.s32 - nvvm_wmma_m8n8k128_store_d_s32_row_stride, // llvm.nvvm.wmma.m8n8k128.store.d.row.stride.s32 - nvvm_wmma_m8n8k32_load_a_s4_row, // llvm.nvvm.wmma.m8n8k32.load.a.row.s4 - nvvm_wmma_m8n8k32_load_a_s4_row_stride, // llvm.nvvm.wmma.m8n8k32.load.a.row.stride.s4 - nvvm_wmma_m8n8k32_load_a_u4_row_stride, // llvm.nvvm.wmma.m8n8k32.load.a.row.stride.u4 - nvvm_wmma_m8n8k32_load_a_u4_row, // llvm.nvvm.wmma.m8n8k32.load.a.row.u4 - nvvm_wmma_m8n8k32_load_b_s4_col, // llvm.nvvm.wmma.m8n8k32.load.b.col.s4 - nvvm_wmma_m8n8k32_load_b_s4_col_stride, // llvm.nvvm.wmma.m8n8k32.load.b.col.stride.s4 - nvvm_wmma_m8n8k32_load_b_u4_col_stride, // llvm.nvvm.wmma.m8n8k32.load.b.col.stride.u4 - nvvm_wmma_m8n8k32_load_b_u4_col, // llvm.nvvm.wmma.m8n8k32.load.b.col.u4 - nvvm_wmma_m8n8k32_load_c_s32_col, // llvm.nvvm.wmma.m8n8k32.load.c.col.s32 - nvvm_wmma_m8n8k32_load_c_s32_col_stride, // llvm.nvvm.wmma.m8n8k32.load.c.col.stride.s32 - nvvm_wmma_m8n8k32_load_c_s32_row, // llvm.nvvm.wmma.m8n8k32.load.c.row.s32 - nvvm_wmma_m8n8k32_load_c_s32_row_stride, // llvm.nvvm.wmma.m8n8k32.load.c.row.stride.s32 - nvvm_wmma_m8n8k32_mma_row_col_s4, // llvm.nvvm.wmma.m8n8k32.mma.row.col.s4 - nvvm_wmma_m8n8k32_mma_row_col_s4_satfinite, // llvm.nvvm.wmma.m8n8k32.mma.row.col.s4.satfinite - nvvm_wmma_m8n8k32_mma_row_col_u4, // llvm.nvvm.wmma.m8n8k32.mma.row.col.u4 - nvvm_wmma_m8n8k32_mma_row_col_u4_satfinite, // llvm.nvvm.wmma.m8n8k32.mma.row.col.u4.satfinite - nvvm_wmma_m8n8k32_store_d_s32_col, // llvm.nvvm.wmma.m8n8k32.store.d.col.s32 - nvvm_wmma_m8n8k32_store_d_s32_col_stride, // llvm.nvvm.wmma.m8n8k32.store.d.col.stride.s32 - nvvm_wmma_m8n8k32_store_d_s32_row, // llvm.nvvm.wmma.m8n8k32.store.d.row.s32 - nvvm_wmma_m8n8k32_store_d_s32_row_stride, // llvm.nvvm.wmma.m8n8k32.store.d.row.stride.s32 - nvvm_wmma_m8n8k4_load_a_f64_col, // llvm.nvvm.wmma.m8n8k4.load.a.col.f64 - nvvm_wmma_m8n8k4_load_a_f64_col_stride, // llvm.nvvm.wmma.m8n8k4.load.a.col.stride.f64 - nvvm_wmma_m8n8k4_load_a_f64_row, // llvm.nvvm.wmma.m8n8k4.load.a.row.f64 - nvvm_wmma_m8n8k4_load_a_f64_row_stride, // llvm.nvvm.wmma.m8n8k4.load.a.row.stride.f64 - nvvm_wmma_m8n8k4_load_b_f64_col, // llvm.nvvm.wmma.m8n8k4.load.b.col.f64 - nvvm_wmma_m8n8k4_load_b_f64_col_stride, // llvm.nvvm.wmma.m8n8k4.load.b.col.stride.f64 - nvvm_wmma_m8n8k4_load_b_f64_row, // llvm.nvvm.wmma.m8n8k4.load.b.row.f64 - nvvm_wmma_m8n8k4_load_b_f64_row_stride, // llvm.nvvm.wmma.m8n8k4.load.b.row.stride.f64 - nvvm_wmma_m8n8k4_load_c_f64_col, // llvm.nvvm.wmma.m8n8k4.load.c.col.f64 - nvvm_wmma_m8n8k4_load_c_f64_col_stride, // llvm.nvvm.wmma.m8n8k4.load.c.col.stride.f64 - nvvm_wmma_m8n8k4_load_c_f64_row, // llvm.nvvm.wmma.m8n8k4.load.c.row.f64 - nvvm_wmma_m8n8k4_load_c_f64_row_stride, // llvm.nvvm.wmma.m8n8k4.load.c.row.stride.f64 - nvvm_wmma_m8n8k4_mma_col_col_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.col.f64 - nvvm_wmma_m8n8k4_mma_col_col_rm_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.col.rm.f64 - nvvm_wmma_m8n8k4_mma_col_col_rn_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.col.rn.f64 - nvvm_wmma_m8n8k4_mma_col_col_rp_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.col.rp.f64 - nvvm_wmma_m8n8k4_mma_col_col_rz_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.col.rz.f64 - nvvm_wmma_m8n8k4_mma_col_row_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.row.f64 - nvvm_wmma_m8n8k4_mma_col_row_rm_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.row.rm.f64 - nvvm_wmma_m8n8k4_mma_col_row_rn_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.row.rn.f64 - nvvm_wmma_m8n8k4_mma_col_row_rp_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.row.rp.f64 - nvvm_wmma_m8n8k4_mma_col_row_rz_f64, // llvm.nvvm.wmma.m8n8k4.mma.col.row.rz.f64 - nvvm_wmma_m8n8k4_mma_row_col_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.col.f64 - nvvm_wmma_m8n8k4_mma_row_col_rm_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.col.rm.f64 - nvvm_wmma_m8n8k4_mma_row_col_rn_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.col.rn.f64 - nvvm_wmma_m8n8k4_mma_row_col_rp_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.col.rp.f64 - nvvm_wmma_m8n8k4_mma_row_col_rz_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.col.rz.f64 - nvvm_wmma_m8n8k4_mma_row_row_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.row.f64 - nvvm_wmma_m8n8k4_mma_row_row_rm_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.row.rm.f64 - nvvm_wmma_m8n8k4_mma_row_row_rn_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.row.rn.f64 - nvvm_wmma_m8n8k4_mma_row_row_rp_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.row.rp.f64 - nvvm_wmma_m8n8k4_mma_row_row_rz_f64, // llvm.nvvm.wmma.m8n8k4.mma.row.row.rz.f64 - nvvm_wmma_m8n8k4_store_d_f64_col, // llvm.nvvm.wmma.m8n8k4.store.d.col.f64 - nvvm_wmma_m8n8k4_store_d_f64_col_stride, // llvm.nvvm.wmma.m8n8k4.store.d.col.stride.f64 - nvvm_wmma_m8n8k4_store_d_f64_row, // llvm.nvvm.wmma.m8n8k4.store.d.row.f64 - nvvm_wmma_m8n8k4_store_d_f64_row_stride, // llvm.nvvm.wmma.m8n8k4.store.d.row.stride.f64 -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVVM.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVVM.td deleted file mode 100644 index 41b28db56c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsNVVM.td +++ /dev/null @@ -1,4614 +0,0 @@ -//===- IntrinsicsNVVM.td - Defines NVVM intrinsics ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the NVVM-specific intrinsics for use with NVPTX. -// -//===----------------------------------------------------------------------===// - -// The following intrinsics were once defined here, but are now auto-upgraded -// to target-generic LLVM intrinsics. -// -// * llvm.nvvm.brev32 --> llvm.bitreverse.i32 -// * llvm.nvvm.brev64 --> llvm.bitreverse.i64 -// * llvm.nvvm.clz.i --> llvm.ctlz.i32 -// * llvm.nvvm.clz.ll --> trunc i64 llvm.ctlz.i64(x) to i32 -// * llvm.nvvm.popc.i --> llvm.ctpop.i32 -// * llvm.nvvm.popc.ll --> trunc i64 llvm.ctpop.i64 to i32 -// * llvm.nvvm.abs.i --> select(x >= -x, x, -x) -// * llvm.nvvm.abs.ll --> ibid. -// * llvm.nvvm.max.i --> select(x sge y, x, y) -// * llvm.nvvm.max.ll --> ibid. -// * llvm.nvvm.max.ui --> select(x uge y, x, y) -// * llvm.nvvm.max.ull --> ibid. -// * llvm.nvvm.max.i --> select(x sle y, x, y) -// * llvm.nvvm.max.ll --> ibid. -// * llvm.nvvm.max.ui --> select(x ule y, x, y) -// * llvm.nvvm.max.ull --> ibid. -// * llvm.nvvm.h2f --> llvm.convert.to.fp16.f32 - -def llvm_global_i8ptr_ty : LLVMQualPointerType; // (global)i8* -def llvm_shared_i8ptr_ty : LLVMQualPointerType; // (shared)i8* -def llvm_i64ptr_ty : LLVMPointerType; // i64* -def llvm_any_i64ptr_ty : LLVMAnyPointerType; // (space)i64* -def llvm_shared_i64ptr_ty : LLVMQualPointerType; // (shared)i64* - -// -// MISC -// - -// Helper class that represents a 'fragment' of an NVPTX *MMA instruction. -// Geom: mnk. E.g. m8n32k16 -// Frag: [a|b|c|d] ([x1|x2|x4] for ldmatrix) -// PtxEltType: PTX type for the element. -class WMMA_REGS { - string geom = Geom; - string frag = Frag; - string ptx_elt_type = PtxEltType; - string gft = Geom#":"#Frag#":"#ptx_elt_type; - string ft = frag#":"#ptx_elt_type; - list regs = !cond( - // mma fp ops use smaller fragments than wmma fp ops - !eq(gft,"m8n8k4:a:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m8n8k4:b:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k8:a:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k8:b:f16") : [llvm_v2f16_ty], - !eq(gft,"m16n8k8:c:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k8:d:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k8:c:f32") : !listsplat(llvm_float_ty, 4), - !eq(gft,"m16n8k8:d:f32") : !listsplat(llvm_float_ty, 4), - !eq(gft,"m16n8k16:a:f16") : !listsplat(llvm_v2f16_ty, 4), - !eq(gft,"m16n8k16:b:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k16:c:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k16:d:f16") : !listsplat(llvm_v2f16_ty, 2), - !eq(gft,"m16n8k16:c:f32") : !listsplat(llvm_float_ty, 4), - !eq(gft,"m16n8k16:d:f32") : !listsplat(llvm_float_ty, 4), - !eq(gft,"m16n8k4:c:f32") : !listsplat(llvm_float_ty, 4), - !eq(gft,"m16n8k4:d:f32") : !listsplat(llvm_float_ty, 4), - - // wmma fp16 -> fp16/fp32 @ m16n16k16/m8n32k16/m32n8k16 - // All other supported geometries use the same fragment format for f32 and - // f16, so we only need to consider {fragment, type}. - !eq(ft,"a:f16") : !listsplat(llvm_v2f16_ty, 8), - !eq(ft,"b:f16") : !listsplat(llvm_v2f16_ty, 8), - !eq(ft,"c:f16") : !listsplat(llvm_v2f16_ty, 4), - !eq(ft,"d:f16") : !listsplat(llvm_v2f16_ty, 4), - !eq(ft,"c:f32") : !listsplat(llvm_float_ty, 8), - !eq(ft,"d:f32") : !listsplat(llvm_float_ty, 8), - - // wmma tf32 -> s32 @ m16n16k8 - !eq(gft,"m16n16k8:a:tf32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n16k8:b:tf32") : !listsplat(llvm_i32_ty, 4), - - // mma tf32 -> s32 @ m16n16k8/m16n8k8 - !eq(gft,"m16n8k4:a:tf32") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k4:b:tf32") : [llvm_i32_ty], - !eq(gft,"m16n8k8:a:tf32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k8:b:tf32") : !listsplat(llvm_i32_ty, 2), - - !eq(gft,"m8n8k4:a:f64") : [llvm_double_ty], - !eq(gft,"m8n8k4:b:f64") : [llvm_double_ty], - !eq(gft,"m8n8k4:c:f64") : !listsplat(llvm_double_ty, 2), - !eq(gft,"m8n8k4:d:f64") : !listsplat(llvm_double_ty, 2), - - // wmma bf16 -> s32 @ m16n16k16/m8n32k16/m32n8k16 - !eq(gft,"m16n16k16:a:bf16") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n16k16:b:bf16") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m8n32k16:a:bf16") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m8n32k16:b:bf16") : !listsplat(llvm_i32_ty, 8), - !eq(gft,"m32n8k16:a:bf16") : !listsplat(llvm_i32_ty, 8), - !eq(gft,"m32n8k16:b:bf16") : !listsplat(llvm_i32_ty, 2), - - // mma bf16 -> s32 @ m16n8k16/m16n8k8 - !eq(gft,"m16n8k16:a:bf16") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k16:b:bf16") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k8:a:bf16") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k8:b:bf16") : [llvm_i32_ty], - - // wmma u8/s8 -> s32 @ m16n16k16/m8n32k16/m32n8k16 - !eq(gft,"m16n16k16:a:u8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n16k16:a:s8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n16k16:b:u8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n16k16:b:s8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n16k16:c:s32") : !listsplat(llvm_i32_ty, 8), - !eq(gft,"m16n16k16:d:s32") : !listsplat(llvm_i32_ty, 8), - - !eq(gft,"m8n32k16:a:u8") : [llvm_i32_ty], - !eq(gft,"m8n32k16:a:s8") : [llvm_i32_ty], - !eq(gft,"m8n32k16:b:u8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m8n32k16:b:s8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m8n32k16:c:s32") : !listsplat(llvm_i32_ty, 8), - !eq(gft,"m8n32k16:d:s32") : !listsplat(llvm_i32_ty, 8), - - !eq(gft,"m32n8k16:a:u8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m32n8k16:a:s8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m32n8k16:b:u8") : [llvm_i32_ty], - !eq(gft,"m32n8k16:b:s8") : [llvm_i32_ty], - !eq(gft,"m32n8k16:c:s32") : !listsplat(llvm_i32_ty, 8), - !eq(gft,"m32n8k16:d:s32") : !listsplat(llvm_i32_ty, 8), - - // mma u8/s8 -> s32 @ m8n8k16/m16n8k16/m16n8k32 - !eq(gft,"m8n8k16:a:u8") : [llvm_i32_ty], - !eq(gft,"m8n8k16:a:s8") : [llvm_i32_ty], - !eq(gft,"m8n8k16:b:u8") : [llvm_i32_ty], - !eq(gft,"m8n8k16:b:s8") : [llvm_i32_ty], - !eq(gft,"m8n8k16:c:s32") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m8n8k16:d:s32") : !listsplat(llvm_i32_ty, 2), - - !eq(gft,"m16n8k16:a:u8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k16:a:s8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k16:b:u8") : [llvm_i32_ty], - !eq(gft,"m16n8k16:b:s8") : [llvm_i32_ty], - !eq(gft,"m16n8k16:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k16:d:s32") : !listsplat(llvm_i32_ty, 4), - - !eq(gft,"m16n8k32:a:u8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k32:a:s8") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k32:b:u8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k32:b:s8") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k32:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k32:d:s32") : !listsplat(llvm_i32_ty, 4), - - // wmma/mma u4/s4 -> s32 @ m8n8k32 (u4/s4) - !eq(gft,"m8n8k32:a:u4") : [llvm_i32_ty], - !eq(gft,"m8n8k32:a:s4") : [llvm_i32_ty], - !eq(gft,"m8n8k32:b:u4") : [llvm_i32_ty], - !eq(gft,"m8n8k32:b:s4") : [llvm_i32_ty], - !eq(gft,"m8n8k32:c:s32") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m8n8k32:d:s32") : !listsplat(llvm_i32_ty, 2), - - !eq(gft,"m16n8k32:a:u4") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k32:a:s4") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k32:b:u4") : [llvm_i32_ty], - !eq(gft,"m16n8k32:b:s4") : [llvm_i32_ty], - !eq(gft,"m16n8k32:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k32:d:s32") : !listsplat(llvm_i32_ty, 4), - - !eq(gft,"m16n8k64:a:u4") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k64:a:s4") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k64:b:u4") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k64:b:s4") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k64:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k64:d:s32") : !listsplat(llvm_i32_ty, 4), - - // wmma/mma b1 -> s32 @ m8n8k128(b1) - !eq(gft,"m8n8k128:a:b1") : [llvm_i32_ty], - !eq(gft,"m8n8k128:b:b1") : [llvm_i32_ty], - !eq(gft,"m8n8k128:c:s32") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m8n8k128:d:s32") : !listsplat(llvm_i32_ty, 2), - - !eq(gft,"m16n8k128:a:b1") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k128:b:b1") : [llvm_i32_ty], - !eq(gft,"m16n8k128:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k128:d:s32") : !listsplat(llvm_i32_ty, 4), - - !eq(gft,"m16n8k256:a:b1") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k256:b:b1") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m16n8k256:c:s32") : !listsplat(llvm_i32_ty, 4), - !eq(gft,"m16n8k256:d:s32") : !listsplat(llvm_i32_ty, 4), - - // ldmatrix b16 -> s32 @ m8n8 - !eq(gft,"m8n8:x1:b16") : !listsplat(llvm_i32_ty, 1), - !eq(gft,"m8n8:x2:b16") : !listsplat(llvm_i32_ty, 2), - !eq(gft,"m8n8:x4:b16") : !listsplat(llvm_i32_ty, 4), - ); -} - -class WMMA_NAME_LDST { - string intr = "llvm.nvvm.wmma." - # Frag.geom - # "." # Op - # "." # Frag.frag - # "." # Layout - # !if(WithStride, ".stride", "") - # "." # Frag.ptx_elt_type - ; - // TODO(tra): record name should ideally use the same field order as the intrinsic. - // E.g. string record = !subst("llvm", "int", - // !subst(".", "_", llvm)); - string record = "int_nvvm_wmma_" - # Frag.geom - # "_" # Op - # "_" # Frag.frag - # "_" # Frag.ptx_elt_type - # "_" # Layout - # !if(WithStride, "_stride", ""); -} - -class MMA_SIGNATURE { - list id_frags = !cond( - // FP16 ops are identified by accumulator & result type. - !eq(A.ptx_elt_type, "f16") : [D, C], - // other ops are identified by input types. - !ne(A.ptx_elt_type, B.ptx_elt_type): [A, B], - true: [A] - ); - string ret = !foldl("", id_frags, a, b, !strconcat(a, ".", b.ptx_elt_type)); -} - -class WMMA_NAME { - string signature = MMA_SIGNATURE.ret; - string llvm = "llvm.nvvm.wmma." - # A.geom - # ".mma" - # b1op - # "." # ALayout - # "." # BLayout - # !if(!ne(Rnd, ""), !strconcat(".", Rnd), "") - # signature - # !if(Satfinite, ".satfinite", ""); - - string record = !subst(".", "_", - !subst("llvm.", "int_", llvm)); -} - -class MMA_NAME { - string signature = MMA_SIGNATURE.ret; - string llvm = "llvm.nvvm.mma" - # b1op - # "." # A.geom - # "." # ALayout - # "." # BLayout - # !if(Satfinite, ".satfinite", "") - # signature; - string record = !subst(".", "_", - !subst("llvm.", "int_", llvm)); -} - -class LDMATRIX_NAME { - string intr = "llvm.nvvm.ldmatrix.sync.aligned" - # "." # Frag.geom - # "." # Frag.frag - # !if(Trans, ".trans", "") - # "." # Frag.ptx_elt_type - ; - string record = !subst(".", "_", - !subst("llvm.", "int_", intr)); -} - -// Generates list of 4-tuples of WMMA_REGS representing a valid MMA op. -// Geom: list of supported geometries. -// TypeN: PTX type of the corresponding fragment's element. -// TypeB and TypeD may be empty if it must match that of TypeA or TypeC. -class MMA_OPS Geom, list TypeA, list TypeB, - list TypeC, list TypeD> { - list> ret = - !foldl([]>, Geom, t1, geom, !listconcat(t1, - !foldl([]>, TypeA, t2, type_a, !listconcat(t2, - !foldl([]>, !if(!size(TypeB), TypeB, [type_a]), t3, type_b, !listconcat(t3, - !foldl([]>, TypeC, t4, type_c, !listconcat(t4, - !foldl([]>, !if(!size(TypeD), TypeD, [type_c]), t5, type_d, !listconcat(t5, - [[WMMA_REGS, - WMMA_REGS, - WMMA_REGS, - WMMA_REGS]])))))))))); - // Debugging aid for readable representation of the list above. - list> ops = !foreach(x, ret, [x[0].gft, x[1].gft, x[2].gft, x[3].gft]); -} - -class MMA_LDST_OPS Geom, list Frags, list Types> { - list ret = - !foldl([], Geom, t1, geom, !listconcat(t1, - !foldl([], Frags, t2, frag, !listconcat(t2, - !foldl([], Types, t3, type, !listconcat(t3, - [WMMA_REGS])))))); - // Debugging aid for readable representation of the list above. - list ops = !foreach(x, ret, x.gft); -} - -class LDMATRIX_OPS Geom, list Frags, list Types> { - list ret = - !foldl([], Geom, t1, geom, !listconcat(t1, - !foldl([], Frags, t2, frag, !listconcat(t2, - !foldl([], Types, t3, type, !listconcat(t3, - [WMMA_REGS])))))); - // Debugging aid for readable representation of the list above. - list ops = !foreach(x, ret, x.gft); -} - -// Creates list of valid combinations of fragments. This is the main list that -// drives generation of corresponding intrinsics and instructions. -class NVVM_MMA_OPS { - list> tf32_wmma_ops = MMA_OPS< - ["m16n16k8"], - ["tf32"], [], ["f32"], []>.ret; - list> bf16_wmma_ops = MMA_OPS< - ["m16n16k16", "m32n8k16", "m8n32k16"], - ["bf16"], [], ["f32"], []>.ret; - list> f64_wmma_ops = MMA_OPS< - ["m8n8k4"], - ["f64"], [], ["f64"], []>.ret; - list> fp_wmma_ops = MMA_OPS< - ["m16n16k16", "m32n8k16", "m8n32k16"], - ["f16"], [], ["f16", "f32"], ["f16", "f32"]>.ret; - list> int_wmma_ops = MMA_OPS< - ["m16n16k16", "m32n8k16", "m8n32k16"], - ["s8", "u8"], [], ["s32"], []>.ret; - list> subint_wmma_ops = MMA_OPS< - ["m8n8k32"], - ["s4", "u4"], [], ["s32"], []>.ret; - list> bit_wmma_ops = MMA_OPS< - ["m8n8k128"], - ["b1"], [], ["s32"], []>.ret; - list> all_wmma_ops = !listconcat( - tf32_wmma_ops, bf16_wmma_ops, f64_wmma_ops, - fp_wmma_ops, int_wmma_ops, subint_wmma_ops, bit_wmma_ops); - - list> tf32_mma_ops = MMA_OPS< - ["m16n8k4", "m16n8k8"], - ["tf32"], [], ["f32"], []>.ret; - list> bf16_mma_ops = MMA_OPS< - ["m16n8k16", "m16n8k8"], - ["bf16"], [], ["f32"], []>.ret; - list> f64_mma_ops = MMA_OPS< - ["m8n8k4"], - ["f64"], [], ["f64"], []>.ret; - list> fp_mma_ops = MMA_OPS< - ["m8n8k4", "m16n8k8", "m16n8k16"], - ["f16"], [], ["f16", "f32"], ["f16", "f32"]>.ret; - list> int_mma_ops = MMA_OPS< - ["m8n8k16", "m16n8k16", "m16n8k32"], - ["s8", "u8"], ["s8", "u8"], ["s32"], []>.ret; - list> subint_mma_ops = MMA_OPS< - ["m8n8k32", "m16n8k32", "m16n8k64"], - ["s4", "u4"], ["s4", "u4"], ["s32"], []>.ret; - list> bit_mma_ops = MMA_OPS< - ["m8n8k128", "m16n8k128", "m16n8k256"], - ["b1"], [], ["s32"], []>.ret; - list> all_mma_ops = !listconcat( - tf32_mma_ops, bf16_mma_ops, f64_mma_ops, - fp_mma_ops, int_mma_ops, subint_mma_ops, bit_mma_ops); - - list ldst_ab_ops = MMA_LDST_OPS< - ["m16n16k16", "m32n8k16", "m8n32k16"], - ["a", "b"], ["f16", "u8", "s8", "bf16"]>.ret; - list ldst_cd_ops = MMA_LDST_OPS< - ["m16n16k16", "m32n8k16", "m8n32k16"], - ["c", "d"], ["f16", "f32", "s32"]>.ret; - list ldst_tf32_ab_ops = MMA_LDST_OPS< - ["m16n16k8"], - ["a", "b"], ["tf32"]>.ret; - list ldst_tf32_cd_ops = MMA_LDST_OPS< - ["m16n16k8"], - ["c", "d"], ["f32"]>.ret; - list ldst_f64_abcd_ops = MMA_LDST_OPS< - ["m8n8k4"], - ["a", "b", "c", "d"], ["f64"]>.ret; - list ldst_subint_ab_ops = MMA_LDST_OPS< - ["m8n8k32"], ["a", "b"], ["s4","u4"]>.ret; - list ldst_bit_ab_ops = MMA_LDST_OPS< - ["m8n8k128"], ["a", "b"], ["b1"]>.ret; - list ldst_subint_cd_ops = MMA_LDST_OPS< - ["m8n8k32", "m8n8k128"], ["c", "d"], ["s32"]>.ret; - list all_ldst_ops = !listconcat(ldst_ab_ops, ldst_cd_ops, - ldst_tf32_ab_ops, - ldst_tf32_cd_ops, - ldst_f64_abcd_ops, - ldst_subint_ab_ops, - ldst_bit_ab_ops, - ldst_subint_cd_ops); - // Separate A/B/C fragments (loads) from D (stores). - list all_ld_ops = !filter(op, all_ldst_ops, !ne(op.frag, "d")); - list all_st_ops = !filter(op, all_ldst_ops, !eq(op.frag, "d")); - - list ldmatrix_b16_ops = LDMATRIX_OPS< - ["m8n8"], ["x1", "x2", "x4"], ["b16"]>.ret; - list all_ldmatrix_ops = ldmatrix_b16_ops; -} - -def NVVM_MMA_OPS : NVVM_MMA_OPS; - -// Returns true if this combination of fragment and layout for WMMA load/store -// ops is supported; false otherwise. -// E.g. -// if NVVM_WMMA_LDST_SUPPORTED<...>.ret then -// def : FOO<>; // The record will only be defined for supported ops. -// -class NVVM_WMMA_LDST_SUPPORTED { - string f = frag.frag; - string t = frag.ptx_elt_type; - - bit ret = !cond( - // Sub-int load and store requires A fragment to be of row layout and B - // fragments to be of column layout. - !and(!or(!eq(t, "b1"), - !eq(t, "u4"), - !eq(t, "s4")), - !or(!and(!eq(f, "a"), - !ne(layout, "row")), - !and(!eq(f, "b"), - !ne(layout, "col")))) : false, - true: true - ); -} - -// Returns true if this combination of layout/satf/rnd for WMMA ops is -// supported; false otherwise. -// E.g. -// if NVVM_WMMA_SUPPORTED<...>.ret then -// def : FOO<>; // The record will only be defined for supported ops. -// -class NVVM_WMMA_SUPPORTED frags, string layout_a, string layout_b, int satf, string rnd> { - // WMMA ops check both layouts. - string layout = layout_a # ":" # layout_b; - string t = frags[0].ptx_elt_type; - - bit ret = !cond( - // only f64 wmma functions support rnd options - // any non f64 type that uses a rnd value is invalid - !and(!ne(t, "f64"), !ne(rnd, "")) : false, - - // satf is only valid for select types - !and(!eq(satf, 1), - !ne(t, "s8"), - !ne(t, "u8"), - !ne(t, "s4"), - !ne(t, "u4"), - !ne(t, "f16")): false, - - // Sub-int wmma requires row/column layout - !and(!or(!eq(t, "s4"), - !eq(t, "u4"), - !eq(t, "b1")), - !ne(layout, "row:col")) : false, - true: true - ); -} - -class NVVM_MMA_B1OPS frags> { - list ret = !cond( - !eq(frags[0].ptx_elt_type, "b1") : [".xor.popc", ".and.popc"], - true: [""] - ); -} - -// Returns true if this combination of layout/satf for MMA ops is supported; -// false otherwise. -// E.g. -// if NVVM_MMA_SUPPORTED<...>.ret then -// def : FOO<>; // The record will only be defined for supported ops. -// -class NVVM_MMA_SUPPORTED frags, string layout_a, string layout_b, int satf> { - // MMA ops check both layouts. - string layout = layout_a # ":" # layout_b; - string a_type = frags[0].ptx_elt_type; - string b_type = frags[1].ptx_elt_type; - string c_type = frags[2].ptx_elt_type; - string d_type = frags[3].ptx_elt_type; - string geom = frags[0].geom; - - // gcd is a shortcut used to identify instructions that depend on - // geom+frag_c+frag_d. - string gcd = geom # ":" # c_type # d_type; - bit ret = !cond( - - // Limit satf to valid types - !and(!eq(satf, 1), - !ne(a_type, "s8"), - !ne(a_type, "u8"), - !ne(a_type, "s4"), - !ne(a_type, "u4")): false, - - // m8n8k4 has no C=f32 D=f16 variant. - !eq(gcd, "m8n8k4:f32f16"): false, - - // only m8n8k4 for f16 does not require row:col layout - !and(!ne(layout, "row:col"), - !or(!ne(geom, "m8n8k4"), - !ne(a_type, "f16"))) : false, - - // m16n8k8 requires A and B to be the same type and C and D to be the same - // type. - !and(!eq(geom, "m16n8k8"), - !or(!ne(a_type, b_type), - !ne(c_type, d_type))): false, - - // m16n8k8 requires C and D to be the same type. - !and(!eq(geom, "m16n8k8"), - !ne(c_type, d_type)): false, - - // All other are OK. - true: true - ); -} - -// Returns true if the fragment is valid for ldmatrix ops is supported; -// false otherwise. -// E.g. -// if NVVM_LDMATRIX_SUPPORTED<...>.ret then -// def : FOO<>; // The record will only be defined for supported ops. -// -class NVVM_LDMATRIX_SUPPORTED { - string g = frag.geom; - string t = frag.ptx_elt_type; - - bit ret = !cond( - // Only currently support m8n8 and b16 - !and(!eq(g, "m8n8"), !eq(t, "b16")): true, - true: false - ); -} - -class SHFL_INFO { - string Suffix = !if(sync, "sync_", "") - # mode # "_" - # type - # !if(return_pred, "p", ""); - - string Name = "int_nvvm_shfl_" # Suffix; - string Builtin = "__nvvm_shfl_" # Suffix; - string IntrName = "llvm.nvvm.shfl." # !subst("_",".", Suffix); - bit withGccBuiltin = !not(return_pred); - bit withoutGccBuiltin = return_pred; - LLVMType OpType = !cond( - !eq(type,"i32"): llvm_i32_ty, - !eq(type,"f32"): llvm_float_ty); - list RetTy = !if(return_pred, [OpType, llvm_i1_ty], [OpType]); - list ArgsTy = !if(sync, - [llvm_i32_ty, OpType, llvm_i32_ty, llvm_i32_ty], - [OpType, llvm_i32_ty, llvm_i32_ty]); -} - -let TargetPrefix = "nvvm" in { - def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - -// -// Min Max -// - - def int_nvvm_fmin_f : GCCBuiltin<"__nvvm_fmin_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_fmin_ftz_f : GCCBuiltin<"__nvvm_fmin_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_fmax_f : GCCBuiltin<"__nvvm_fmax_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty] - , [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_fmax_ftz_f : GCCBuiltin<"__nvvm_fmax_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_fmin_d : GCCBuiltin<"__nvvm_fmin_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_fmax_d : GCCBuiltin<"__nvvm_fmax_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - -// -// Multiplication -// - - def int_nvvm_mulhi_i : GCCBuiltin<"__nvvm_mulhi_i">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mulhi_ui : GCCBuiltin<"__nvvm_mulhi_ui">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_mulhi_ll : GCCBuiltin<"__nvvm_mulhi_ll">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mulhi_ull : GCCBuiltin<"__nvvm_mulhi_ull">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_mul_rn_ftz_f : GCCBuiltin<"__nvvm_mul_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rn_f : GCCBuiltin<"__nvvm_mul_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rz_ftz_f : GCCBuiltin<"__nvvm_mul_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rz_f : GCCBuiltin<"__nvvm_mul_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rm_ftz_f : GCCBuiltin<"__nvvm_mul_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rm_f : GCCBuiltin<"__nvvm_mul_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rp_ftz_f : GCCBuiltin<"__nvvm_mul_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rp_f : GCCBuiltin<"__nvvm_mul_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_mul_rn_d : GCCBuiltin<"__nvvm_mul_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rz_d : GCCBuiltin<"__nvvm_mul_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rm_d : GCCBuiltin<"__nvvm_mul_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul_rp_d : GCCBuiltin<"__nvvm_mul_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_mul24_i : GCCBuiltin<"__nvvm_mul24_i">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_mul24_ui : GCCBuiltin<"__nvvm_mul24_ui">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - -// -// Div -// - - def int_nvvm_div_approx_ftz_f : GCCBuiltin<"__nvvm_div_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_nvvm_div_approx_f : GCCBuiltin<"__nvvm_div_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - - def int_nvvm_div_rn_ftz_f : GCCBuiltin<"__nvvm_div_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_nvvm_div_rn_f : GCCBuiltin<"__nvvm_div_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - - def int_nvvm_div_rz_ftz_f : GCCBuiltin<"__nvvm_div_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_nvvm_div_rz_f : GCCBuiltin<"__nvvm_div_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - - def int_nvvm_div_rm_ftz_f : GCCBuiltin<"__nvvm_div_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_nvvm_div_rm_f : GCCBuiltin<"__nvvm_div_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - - def int_nvvm_div_rp_ftz_f : GCCBuiltin<"__nvvm_div_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_nvvm_div_rp_f : GCCBuiltin<"__nvvm_div_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - - def int_nvvm_div_rn_d : GCCBuiltin<"__nvvm_div_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_nvvm_div_rz_d : GCCBuiltin<"__nvvm_div_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_nvvm_div_rm_d : GCCBuiltin<"__nvvm_div_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_nvvm_div_rp_d : GCCBuiltin<"__nvvm_div_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - -// -// Sad -// - - def int_nvvm_sad_i : GCCBuiltin<"__nvvm_sad_i">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - def int_nvvm_sad_ui : GCCBuiltin<"__nvvm_sad_ui">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - -// -// Floor Ceil -// - - def int_nvvm_floor_ftz_f : GCCBuiltin<"__nvvm_floor_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_floor_f : GCCBuiltin<"__nvvm_floor_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_floor_d : GCCBuiltin<"__nvvm_floor_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ceil_ftz_f : GCCBuiltin<"__nvvm_ceil_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ceil_f : GCCBuiltin<"__nvvm_ceil_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ceil_d : GCCBuiltin<"__nvvm_ceil_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// -// Abs -// - - def int_nvvm_fabs_ftz_f : GCCBuiltin<"__nvvm_fabs_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fabs_f : GCCBuiltin<"__nvvm_fabs_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fabs_d : GCCBuiltin<"__nvvm_fabs_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// -// Round -// - - def int_nvvm_round_ftz_f : GCCBuiltin<"__nvvm_round_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_round_f : GCCBuiltin<"__nvvm_round_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_round_d : GCCBuiltin<"__nvvm_round_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// -// Trunc -// - - def int_nvvm_trunc_ftz_f : GCCBuiltin<"__nvvm_trunc_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_trunc_f : GCCBuiltin<"__nvvm_trunc_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_trunc_d : GCCBuiltin<"__nvvm_trunc_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// -// Saturate -// - - def int_nvvm_saturate_ftz_f : GCCBuiltin<"__nvvm_saturate_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_saturate_f : GCCBuiltin<"__nvvm_saturate_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_saturate_d : GCCBuiltin<"__nvvm_saturate_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// -// Exp2 Log2 -// - - def int_nvvm_ex2_approx_ftz_f : GCCBuiltin<"__nvvm_ex2_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ex2_approx_f : GCCBuiltin<"__nvvm_ex2_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ex2_approx_d : GCCBuiltin<"__nvvm_ex2_approx_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - - def int_nvvm_lg2_approx_ftz_f : GCCBuiltin<"__nvvm_lg2_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_lg2_approx_f : GCCBuiltin<"__nvvm_lg2_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_lg2_approx_d : GCCBuiltin<"__nvvm_lg2_approx_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - -// -// Sin Cos -// - - def int_nvvm_sin_approx_ftz_f : GCCBuiltin<"__nvvm_sin_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sin_approx_f : GCCBuiltin<"__nvvm_sin_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_cos_approx_ftz_f : GCCBuiltin<"__nvvm_cos_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_cos_approx_f : GCCBuiltin<"__nvvm_cos_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - -// -// Fma -// - - def int_nvvm_fma_rn_ftz_f : GCCBuiltin<"__nvvm_fma_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rn_f : GCCBuiltin<"__nvvm_fma_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rz_ftz_f : GCCBuiltin<"__nvvm_fma_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rz_f : GCCBuiltin<"__nvvm_fma_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rm_ftz_f : GCCBuiltin<"__nvvm_fma_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rm_f : GCCBuiltin<"__nvvm_fma_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rp_ftz_f : GCCBuiltin<"__nvvm_fma_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rp_f : GCCBuiltin<"__nvvm_fma_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_fma_rn_d : GCCBuiltin<"__nvvm_fma_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rz_d : GCCBuiltin<"__nvvm_fma_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rm_d : GCCBuiltin<"__nvvm_fma_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_fma_rp_d : GCCBuiltin<"__nvvm_fma_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable]>; - -// -// Rcp -// - - def int_nvvm_rcp_rn_ftz_f : GCCBuiltin<"__nvvm_rcp_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rn_f : GCCBuiltin<"__nvvm_rcp_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rz_ftz_f : GCCBuiltin<"__nvvm_rcp_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rz_f : GCCBuiltin<"__nvvm_rcp_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rm_ftz_f : GCCBuiltin<"__nvvm_rcp_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rm_f : GCCBuiltin<"__nvvm_rcp_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rp_ftz_f : GCCBuiltin<"__nvvm_rcp_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rcp_rp_f : GCCBuiltin<"__nvvm_rcp_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_rcp_rn_d : GCCBuiltin<"__nvvm_rcp_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_rcp_rz_d : GCCBuiltin<"__nvvm_rcp_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_rcp_rm_d : GCCBuiltin<"__nvvm_rcp_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_rcp_rp_d : GCCBuiltin<"__nvvm_rcp_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - - def int_nvvm_rcp_approx_ftz_d : GCCBuiltin<"__nvvm_rcp_approx_ftz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - -// -// Sqrt -// - - def int_nvvm_sqrt_f : GCCBuiltin<"__nvvm_sqrt_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rn_ftz_f : GCCBuiltin<"__nvvm_sqrt_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rn_f : GCCBuiltin<"__nvvm_sqrt_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rz_ftz_f : GCCBuiltin<"__nvvm_sqrt_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rz_f : GCCBuiltin<"__nvvm_sqrt_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rm_ftz_f : GCCBuiltin<"__nvvm_sqrt_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rm_f : GCCBuiltin<"__nvvm_sqrt_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rp_ftz_f : GCCBuiltin<"__nvvm_sqrt_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rp_f : GCCBuiltin<"__nvvm_sqrt_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_approx_ftz_f : GCCBuiltin<"__nvvm_sqrt_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_sqrt_approx_f : GCCBuiltin<"__nvvm_sqrt_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_sqrt_rn_d : GCCBuiltin<"__nvvm_sqrt_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rz_d : GCCBuiltin<"__nvvm_sqrt_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rm_d : GCCBuiltin<"__nvvm_sqrt_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_nvvm_sqrt_rp_d : GCCBuiltin<"__nvvm_sqrt_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - -// -// Rsqrt -// - - def int_nvvm_rsqrt_approx_ftz_f : GCCBuiltin<"__nvvm_rsqrt_approx_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rsqrt_approx_f : GCCBuiltin<"__nvvm_rsqrt_approx_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_rsqrt_approx_d : GCCBuiltin<"__nvvm_rsqrt_approx_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - -// -// Add -// - - def int_nvvm_add_rn_ftz_f : GCCBuiltin<"__nvvm_add_rn_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rn_f : GCCBuiltin<"__nvvm_add_rn_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rz_ftz_f : GCCBuiltin<"__nvvm_add_rz_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rz_f : GCCBuiltin<"__nvvm_add_rz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rm_ftz_f : GCCBuiltin<"__nvvm_add_rm_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rm_f : GCCBuiltin<"__nvvm_add_rm_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rp_ftz_f : GCCBuiltin<"__nvvm_add_rp_ftz_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rp_f : GCCBuiltin<"__nvvm_add_rp_f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_add_rn_d : GCCBuiltin<"__nvvm_add_rn_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rz_d : GCCBuiltin<"__nvvm_add_rz_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rm_d : GCCBuiltin<"__nvvm_add_rm_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - def int_nvvm_add_rp_d : GCCBuiltin<"__nvvm_add_rp_d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - -// -// Convert -// - - def int_nvvm_d2f_rn_ftz : GCCBuiltin<"__nvvm_d2f_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rn : GCCBuiltin<"__nvvm_d2f_rn">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rz_ftz : GCCBuiltin<"__nvvm_d2f_rz_ftz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rz : GCCBuiltin<"__nvvm_d2f_rz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rm_ftz : GCCBuiltin<"__nvvm_d2f_rm_ftz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rm : GCCBuiltin<"__nvvm_d2f_rm">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rp_ftz : GCCBuiltin<"__nvvm_d2f_rp_ftz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2f_rp : GCCBuiltin<"__nvvm_d2f_rp">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_d2i_rn : GCCBuiltin<"__nvvm_d2i_rn">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2i_rz : GCCBuiltin<"__nvvm_d2i_rz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2i_rm : GCCBuiltin<"__nvvm_d2i_rm">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2i_rp : GCCBuiltin<"__nvvm_d2i_rp">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_d2ui_rn : GCCBuiltin<"__nvvm_d2ui_rn">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ui_rz : GCCBuiltin<"__nvvm_d2ui_rz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ui_rm : GCCBuiltin<"__nvvm_d2ui_rm">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ui_rp : GCCBuiltin<"__nvvm_d2ui_rp">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_i2d_rn : GCCBuiltin<"__nvvm_i2d_rn">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2d_rz : GCCBuiltin<"__nvvm_i2d_rz">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2d_rm : GCCBuiltin<"__nvvm_i2d_rm">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2d_rp : GCCBuiltin<"__nvvm_i2d_rp">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ui2d_rn : GCCBuiltin<"__nvvm_ui2d_rn">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2d_rz : GCCBuiltin<"__nvvm_ui2d_rz">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2d_rm : GCCBuiltin<"__nvvm_ui2d_rm">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2d_rp : GCCBuiltin<"__nvvm_ui2d_rp">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_f2i_rn_ftz : GCCBuiltin<"__nvvm_f2i_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rn : GCCBuiltin<"__nvvm_f2i_rn">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rz_ftz : GCCBuiltin<"__nvvm_f2i_rz_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rz : GCCBuiltin<"__nvvm_f2i_rz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rm_ftz : GCCBuiltin<"__nvvm_f2i_rm_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rm : GCCBuiltin<"__nvvm_f2i_rm">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rp_ftz : GCCBuiltin<"__nvvm_f2i_rp_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2i_rp : GCCBuiltin<"__nvvm_f2i_rp">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_f2ui_rn_ftz : GCCBuiltin<"__nvvm_f2ui_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rn : GCCBuiltin<"__nvvm_f2ui_rn">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rz_ftz : GCCBuiltin<"__nvvm_f2ui_rz_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rz : GCCBuiltin<"__nvvm_f2ui_rz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rm_ftz : GCCBuiltin<"__nvvm_f2ui_rm_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rm : GCCBuiltin<"__nvvm_f2ui_rm">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rp_ftz : GCCBuiltin<"__nvvm_f2ui_rp_ftz">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ui_rp : GCCBuiltin<"__nvvm_f2ui_rp">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_i2f_rn : GCCBuiltin<"__nvvm_i2f_rn">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2f_rz : GCCBuiltin<"__nvvm_i2f_rz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2f_rm : GCCBuiltin<"__nvvm_i2f_rm">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_i2f_rp : GCCBuiltin<"__nvvm_i2f_rp">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ui2f_rn : GCCBuiltin<"__nvvm_ui2f_rn">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2f_rz : GCCBuiltin<"__nvvm_ui2f_rz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2f_rm : GCCBuiltin<"__nvvm_ui2f_rm">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ui2f_rp : GCCBuiltin<"__nvvm_ui2f_rp">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_lohi_i2d : GCCBuiltin<"__nvvm_lohi_i2d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; - - def int_nvvm_d2i_lo : GCCBuiltin<"__nvvm_d2i_lo">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2i_hi : GCCBuiltin<"__nvvm_d2i_hi">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_f2ll_rn_ftz : GCCBuiltin<"__nvvm_f2ll_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rn : GCCBuiltin<"__nvvm_f2ll_rn">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rz_ftz : GCCBuiltin<"__nvvm_f2ll_rz_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rz : GCCBuiltin<"__nvvm_f2ll_rz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rm_ftz : GCCBuiltin<"__nvvm_f2ll_rm_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rm : GCCBuiltin<"__nvvm_f2ll_rm">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rp_ftz : GCCBuiltin<"__nvvm_f2ll_rp_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ll_rp : GCCBuiltin<"__nvvm_f2ll_rp">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_f2ull_rn_ftz : GCCBuiltin<"__nvvm_f2ull_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rn : GCCBuiltin<"__nvvm_f2ull_rn">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rz_ftz : GCCBuiltin<"__nvvm_f2ull_rz_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rz : GCCBuiltin<"__nvvm_f2ull_rz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rm_ftz : GCCBuiltin<"__nvvm_f2ull_rm_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rm : GCCBuiltin<"__nvvm_f2ull_rm">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rp_ftz : GCCBuiltin<"__nvvm_f2ull_rp_ftz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2ull_rp : GCCBuiltin<"__nvvm_f2ull_rp">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_d2ll_rn : GCCBuiltin<"__nvvm_d2ll_rn">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ll_rz : GCCBuiltin<"__nvvm_d2ll_rz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ll_rm : GCCBuiltin<"__nvvm_d2ll_rm">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ll_rp : GCCBuiltin<"__nvvm_d2ll_rp">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_d2ull_rn : GCCBuiltin<"__nvvm_d2ull_rn">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ull_rz : GCCBuiltin<"__nvvm_d2ull_rz">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ull_rm : GCCBuiltin<"__nvvm_d2ull_rm">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_d2ull_rp : GCCBuiltin<"__nvvm_d2ull_rp">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ll2f_rn : GCCBuiltin<"__nvvm_ll2f_rn">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2f_rz : GCCBuiltin<"__nvvm_ll2f_rz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2f_rm : GCCBuiltin<"__nvvm_ll2f_rm">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2f_rp : GCCBuiltin<"__nvvm_ll2f_rp">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2f_rn : GCCBuiltin<"__nvvm_ull2f_rn">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2f_rz : GCCBuiltin<"__nvvm_ull2f_rz">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2f_rm : GCCBuiltin<"__nvvm_ull2f_rm">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2f_rp : GCCBuiltin<"__nvvm_ull2f_rp">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ll2d_rn : GCCBuiltin<"__nvvm_ll2d_rn">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2d_rz : GCCBuiltin<"__nvvm_ll2d_rz">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2d_rm : GCCBuiltin<"__nvvm_ll2d_rm">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ll2d_rp : GCCBuiltin<"__nvvm_ll2d_rp">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2d_rn : GCCBuiltin<"__nvvm_ull2d_rn">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2d_rz : GCCBuiltin<"__nvvm_ull2d_rz">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2d_rm : GCCBuiltin<"__nvvm_ull2d_rm">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_ull2d_rp : GCCBuiltin<"__nvvm_ull2d_rp">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_f2h_rn_ftz : GCCBuiltin<"__nvvm_f2h_rn_ftz">, - DefaultAttrsIntrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_f2h_rn : GCCBuiltin<"__nvvm_f2h_rn">, - DefaultAttrsIntrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_ff2bf16x2_rn : GCCBuiltin<"__nvvm_ff2bf16x2_rn">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2bf16x2_rn_relu : GCCBuiltin<"__nvvm_ff2bf16x2_rn_relu">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2bf16x2_rz : GCCBuiltin<"__nvvm_ff2bf16x2_rz">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2bf16x2_rz_relu : GCCBuiltin<"__nvvm_ff2bf16x2_rz_relu">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_ff2f16x2_rn : GCCBuiltin<"__nvvm_ff2f16x2_rn">, - Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2f16x2_rn_relu : GCCBuiltin<"__nvvm_ff2f16x2_rn_relu">, - Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2f16x2_rz : GCCBuiltin<"__nvvm_ff2f16x2_rz">, - Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - def int_nvvm_ff2f16x2_rz_relu : GCCBuiltin<"__nvvm_ff2f16x2_rz_relu">, - Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_f2bf16_rn : GCCBuiltin<"__nvvm_f2bf16_rn">, - Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_f2bf16_rn_relu : GCCBuiltin<"__nvvm_f2bf16_rn_relu">, - Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_f2bf16_rz : GCCBuiltin<"__nvvm_f2bf16_rz">, - Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; - def int_nvvm_f2bf16_rz_relu : GCCBuiltin<"__nvvm_f2bf16_rz_relu">, - Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; - - def int_nvvm_f2tf32_rna : GCCBuiltin<"__nvvm_f2tf32_rna">, - Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; - -// -// Bitcast -// - - def int_nvvm_bitcast_f2i : GCCBuiltin<"__nvvm_bitcast_f2i">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_bitcast_i2f : GCCBuiltin<"__nvvm_bitcast_i2f">, - DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; - - def int_nvvm_bitcast_ll2d : GCCBuiltin<"__nvvm_bitcast_ll2d">, - DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem, IntrSpeculatable]>; - def int_nvvm_bitcast_d2ll : GCCBuiltin<"__nvvm_bitcast_d2ll">, - DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem, IntrSpeculatable]>; - -// FNS - - def int_nvvm_fns : GCCBuiltin<"__nvvm_fns">, - DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - -// Atomics not available as llvm intrinsics. - def int_nvvm_atomic_load_inc_32 : Intrinsic<[llvm_i32_ty], - [LLVMAnyPointerType, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_nvvm_atomic_load_dec_32 : Intrinsic<[llvm_i32_ty], - [LLVMAnyPointerType, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>]>; - - class SCOPED_ATOMIC2_impl - : Intrinsic<[elty], - [LLVMAnyPointerType>, LLVMMatchType<0>], - [IntrArgMemOnly, NoCapture>]>; - class SCOPED_ATOMIC3_impl - : Intrinsic<[elty], - [LLVMAnyPointerType>, LLVMMatchType<0>, - LLVMMatchType<0>], - [IntrArgMemOnly, NoCapture>]>; - - multiclass PTXAtomicWithScope2 { - def _cta : SCOPED_ATOMIC2_impl; - def _sys : SCOPED_ATOMIC2_impl; - } - multiclass PTXAtomicWithScope3 { - def _cta : SCOPED_ATOMIC3_impl; - def _sys : SCOPED_ATOMIC3_impl; - } - multiclass PTXAtomicWithScope2_fi { - defm _f: PTXAtomicWithScope2; - defm _i: PTXAtomicWithScope2; - } - defm int_nvvm_atomic_add_gen : PTXAtomicWithScope2_fi; - defm int_nvvm_atomic_inc_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_dec_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_exch_gen_i: PTXAtomicWithScope2; - defm int_nvvm_atomic_xor_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_max_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_min_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_or_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_and_gen_i : PTXAtomicWithScope2; - defm int_nvvm_atomic_cas_gen_i : PTXAtomicWithScope3; - -// Bar.Sync - - // The builtin for "bar.sync 0" is called __syncthreads. Unlike most of the - // intrinsics in this file, this one is a user-facing API. - def int_nvvm_barrier0 : GCCBuiltin<"__syncthreads">, - Intrinsic<[], [], [IntrConvergent]>; - // Synchronize all threads in the CTA at barrier 'n'. - def int_nvvm_barrier_n : GCCBuiltin<"__nvvm_bar_n">, - Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>; - // Synchronize 'm', a multiple of warp size, (arg 2) threads in - // the CTA at barrier 'n' (arg 1). - def int_nvvm_barrier : GCCBuiltin<"__nvvm_bar">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [IntrConvergent]>; - def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>; - def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>; - def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>; - - def int_nvvm_bar_sync : - Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>, - GCCBuiltin<"__nvvm_bar_sync">; - def int_nvvm_bar_warp_sync : - Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>, - GCCBuiltin<"__nvvm_bar_warp_sync">; - - // barrier.sync id[, cnt] - def int_nvvm_barrier_sync : - Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>, - GCCBuiltin<"__nvvm_barrier_sync">; - def int_nvvm_barrier_sync_cnt : - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [IntrConvergent]>, - GCCBuiltin<"__nvvm_barrier_sync_cnt">; - - // Membar - def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">, - Intrinsic<[], [], []>; - def int_nvvm_membar_gl : GCCBuiltin<"__nvvm_membar_gl">, - Intrinsic<[], [], []>; - def int_nvvm_membar_sys : GCCBuiltin<"__nvvm_membar_sys">, - Intrinsic<[], [], []>; - -// Async Copy -def int_nvvm_cp_async_mbarrier_arrive : - GCCBuiltin<"__nvvm_cp_async_mbarrier_arrive">, - Intrinsic<[],[llvm_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_cp_async_mbarrier_arrive_shared : - GCCBuiltin<"__nvvm_cp_async_mbarrier_arrive_shared">, - Intrinsic<[],[llvm_shared_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_cp_async_mbarrier_arrive_noinc : - GCCBuiltin<"__nvvm_cp_async_mbarrier_arrive_noinc">, - Intrinsic<[],[llvm_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_cp_async_mbarrier_arrive_noinc_shared : - GCCBuiltin<"__nvvm_cp_async_mbarrier_arrive_noinc_shared">, - Intrinsic<[],[llvm_shared_i64ptr_ty],[IntrConvergent]>; - -def int_nvvm_cp_async_ca_shared_global_4 : - GCCBuiltin<"__nvvm_cp_async_ca_shared_global_4">, - Intrinsic<[],[llvm_shared_i8ptr_ty, llvm_global_i8ptr_ty], - [IntrArgMemOnly, NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>], - "llvm.nvvm.cp.async.ca.shared.global.4">; -def int_nvvm_cp_async_ca_shared_global_8 : - GCCBuiltin<"__nvvm_cp_async_ca_shared_global_8">, - Intrinsic<[],[llvm_shared_i8ptr_ty, llvm_global_i8ptr_ty], - [IntrArgMemOnly, NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>], - "llvm.nvvm.cp.async.ca.shared.global.8">; -def int_nvvm_cp_async_ca_shared_global_16 : - GCCBuiltin<"__nvvm_cp_async_ca_shared_global_16">, - Intrinsic<[],[llvm_shared_i8ptr_ty, llvm_global_i8ptr_ty], - [IntrArgMemOnly, NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>], - "llvm.nvvm.cp.async.ca.shared.global.16">; -def int_nvvm_cp_async_cg_shared_global_16 : - GCCBuiltin<"__nvvm_cp_async_cg_shared_global_16">, - Intrinsic<[],[llvm_shared_i8ptr_ty, llvm_global_i8ptr_ty], - [IntrArgMemOnly, NoAlias>, NoAlias>, - WriteOnly>, ReadOnly>], - "llvm.nvvm.cp.async.cg.shared.global.16">; - -def int_nvvm_cp_async_commit_group : - GCCBuiltin<"__nvvm_cp_async_commit_group">, - Intrinsic<[],[],[]>; - -def int_nvvm_cp_async_wait_group : - GCCBuiltin<"__nvvm_cp_async_wait_group">, - Intrinsic<[],[llvm_i32_ty],[ImmArg>]>; - -def int_nvvm_cp_async_wait_all : - GCCBuiltin<"__nvvm_cp_async_wait_all">, - Intrinsic<[],[],[]>; - -// mbarrier -def int_nvvm_mbarrier_init : GCCBuiltin<"__nvvm_mbarrier_init">, - Intrinsic<[],[llvm_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_init_shared : - GCCBuiltin<"__nvvm_mbarrier_init_shared">, - Intrinsic<[],[llvm_shared_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; - -def int_nvvm_mbarrier_inval : GCCBuiltin<"__nvvm_mbarrier_inval">, - Intrinsic<[],[llvm_i64ptr_ty], - [IntrConvergent, IntrWriteMem, IntrArgMemOnly, - WriteOnly>, NoCapture>]>; -def int_nvvm_mbarrier_inval_shared : - GCCBuiltin<"__nvvm_mbarrier_inval_shared">, - Intrinsic<[],[llvm_shared_i64ptr_ty], - [IntrConvergent, IntrWriteMem, IntrArgMemOnly, - WriteOnly>, NoCapture>]>; - -def int_nvvm_mbarrier_arrive : GCCBuiltin<"__nvvm_mbarrier_arrive">, - Intrinsic<[llvm_i64_ty],[llvm_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_shared : - GCCBuiltin<"__nvvm_mbarrier_arrive_shared">, - Intrinsic<[llvm_i64_ty],[llvm_shared_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_noComplete : - GCCBuiltin<"__nvvm_mbarrier_arrive_noComplete">, - Intrinsic<[llvm_i64_ty],[llvm_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_noComplete_shared : - GCCBuiltin<"__nvvm_mbarrier_arrive_noComplete_shared">, - Intrinsic<[llvm_i64_ty],[llvm_shared_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; - -def int_nvvm_mbarrier_arrive_drop : - GCCBuiltin<"__nvvm_mbarrier_arrive_drop">, - Intrinsic<[llvm_i64_ty],[llvm_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_drop_shared : - GCCBuiltin<"__nvvm_mbarrier_arrive_drop_shared">, - Intrinsic<[llvm_i64_ty],[llvm_shared_i64ptr_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_drop_noComplete : - GCCBuiltin<"__nvvm_mbarrier_arrive_drop_noComplete">, - Intrinsic<[llvm_i64_ty],[llvm_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_arrive_drop_noComplete_shared : - GCCBuiltin<"__nvvm_mbarrier_arrive_drop_noComplete_shared">, - Intrinsic<[llvm_i64_ty],[llvm_shared_i64ptr_ty, llvm_i32_ty],[IntrConvergent]>; - -def int_nvvm_mbarrier_test_wait : - GCCBuiltin<"__nvvm_mbarrier_test_wait">, - Intrinsic<[llvm_i1_ty],[llvm_i64ptr_ty, llvm_i64_ty],[IntrConvergent]>; -def int_nvvm_mbarrier_test_wait_shared : - GCCBuiltin<"__nvvm_mbarrier_test_wait_shared">, - Intrinsic<[llvm_i1_ty],[llvm_shared_i64ptr_ty, llvm_i64_ty],[IntrConvergent]>; - -def int_nvvm_mbarrier_pending_count : - GCCBuiltin<"__nvvm_mbarrier_pending_count">, - Intrinsic<[llvm_i32_ty],[llvm_i64_ty],[IntrNoMem, IntrConvergent]>; - -// Generated within nvvm. Use for ldu on sm_20 or later. Second arg is the -// pointer's alignment. -def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldu.global.i">; -def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldu.global.f">; -def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldu.global.p">; - -// Generated within nvvm. Use for ldg on sm_35 or later. Second arg is the -// pointer's alignment. -def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldg.global.i">; -def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldg.global.f">; -def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType>, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, NoCapture>], - "llvm.nvvm.ldg.global.p">; - -// Use for generic pointers -// - These intrinsics are used to convert address spaces. -// - The input pointer and output pointer must have the same type, except for -// the address-space. (This restriction is not enforced here as there is -// currently no way to describe it). -// - This complements the llvm bitcast, which can be used to cast one type -// of pointer to another type of pointer, while the address space remains -// the same. -def int_nvvm_ptr_local_to_gen: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.local.to.gen">; -def int_nvvm_ptr_shared_to_gen: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.shared.to.gen">; -def int_nvvm_ptr_global_to_gen: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.global.to.gen">; -def int_nvvm_ptr_constant_to_gen: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.constant.to.gen">; - -def int_nvvm_ptr_gen_to_global: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.gen.to.global">; -def int_nvvm_ptr_gen_to_shared: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.gen.to.shared">; -def int_nvvm_ptr_gen_to_local: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.gen.to.local">; -def int_nvvm_ptr_gen_to_constant: DefaultAttrsIntrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.gen.to.constant">; - -// Used in nvvm internally to help address space opt and ptx code generation -// This is for params that are passed to kernel functions by pointer by-val. -def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], - [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.ptr.gen.to.param">; - -// Move intrinsics, used in nvvm internally - -def int_nvvm_move_i16 : Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem], - "llvm.nvvm.move.i16">; -def int_nvvm_move_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem], - "llvm.nvvm.move.i32">; -def int_nvvm_move_i64 : Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.move.i64">; -def int_nvvm_move_float : Intrinsic<[llvm_float_ty], [llvm_float_ty], - [IntrNoMem], "llvm.nvvm.move.float">; -def int_nvvm_move_double : Intrinsic<[llvm_double_ty], [llvm_double_ty], - [IntrNoMem], "llvm.nvvm.move.double">; -def int_nvvm_move_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty], - [IntrNoMem, NoCapture>], "llvm.nvvm.move.ptr">; - - -// For getting the handle from a texture or surface variable -def int_nvvm_texsurf_handle - : Intrinsic<[llvm_i64_ty], [llvm_metadata_ty, llvm_any_i64ptr_ty], - [IntrNoMem], "llvm.nvvm.texsurf.handle">; -def int_nvvm_texsurf_handle_internal - : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty], - [IntrNoMem], "llvm.nvvm.texsurf.handle.internal">; - -/// Error / Warn -def int_nvvm_compiler_error : - Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.error">; -def int_nvvm_compiler_warn : - Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.warn">; - -def int_nvvm_reflect : - Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.reflect">; - -// isspacep.{const, global, local, shared} -def int_nvvm_isspacep_const - : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.isspacep.const">, - GCCBuiltin<"__nvvm_isspacep_const">; -def int_nvvm_isspacep_global - : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.isspacep.global">, - GCCBuiltin<"__nvvm_isspacep_global">; -def int_nvvm_isspacep_local - : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.isspacep.local">, - GCCBuiltin<"__nvvm_isspacep_local">; -def int_nvvm_isspacep_shared - : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.isspacep.shared">, - GCCBuiltin<"__nvvm_isspacep_shared">; - -// Environment register read -def int_nvvm_read_ptx_sreg_envreg0 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg0">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg0">; -def int_nvvm_read_ptx_sreg_envreg1 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg1">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg1">; -def int_nvvm_read_ptx_sreg_envreg2 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg2">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg2">; -def int_nvvm_read_ptx_sreg_envreg3 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg3">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg3">; -def int_nvvm_read_ptx_sreg_envreg4 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg4">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg4">; -def int_nvvm_read_ptx_sreg_envreg5 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg5">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg5">; -def int_nvvm_read_ptx_sreg_envreg6 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg6">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg6">; -def int_nvvm_read_ptx_sreg_envreg7 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg7">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg7">; -def int_nvvm_read_ptx_sreg_envreg8 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg8">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg8">; -def int_nvvm_read_ptx_sreg_envreg9 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg9">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg9">; -def int_nvvm_read_ptx_sreg_envreg10 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg10">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg10">; -def int_nvvm_read_ptx_sreg_envreg11 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg11">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg11">; -def int_nvvm_read_ptx_sreg_envreg12 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg12">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg12">; -def int_nvvm_read_ptx_sreg_envreg13 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg13">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg13">; -def int_nvvm_read_ptx_sreg_envreg14 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg14">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg14">; -def int_nvvm_read_ptx_sreg_envreg15 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg15">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg15">; -def int_nvvm_read_ptx_sreg_envreg16 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg16">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg16">; -def int_nvvm_read_ptx_sreg_envreg17 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg17">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg17">; -def int_nvvm_read_ptx_sreg_envreg18 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg18">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg18">; -def int_nvvm_read_ptx_sreg_envreg19 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg19">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg19">; -def int_nvvm_read_ptx_sreg_envreg20 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg20">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg20">; -def int_nvvm_read_ptx_sreg_envreg21 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg21">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg21">; -def int_nvvm_read_ptx_sreg_envreg22 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg22">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg22">; -def int_nvvm_read_ptx_sreg_envreg23 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg23">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg23">; -def int_nvvm_read_ptx_sreg_envreg24 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg24">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg24">; -def int_nvvm_read_ptx_sreg_envreg25 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg25">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg25">; -def int_nvvm_read_ptx_sreg_envreg26 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg26">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg26">; -def int_nvvm_read_ptx_sreg_envreg27 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg27">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg27">; -def int_nvvm_read_ptx_sreg_envreg28 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg28">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg28">; -def int_nvvm_read_ptx_sreg_envreg29 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg29">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg29">; -def int_nvvm_read_ptx_sreg_envreg30 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg30">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg30">; -def int_nvvm_read_ptx_sreg_envreg31 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable], - "llvm.nvvm.read.ptx.sreg.envreg31">, - GCCBuiltin<"__nvvm_read_ptx_sreg_envreg31">; - - -// Texture Fetch -// texmode_independent -def int_nvvm_tex_1d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.v4f32.s32">; -def int_nvvm_tex_1d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.v4f32.f32">; -def int_nvvm_tex_1d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.level.v4f32.f32">; -def int_nvvm_tex_1d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.grad.v4f32.f32">; -def int_nvvm_tex_1d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.v4s32.s32">; -def int_nvvm_tex_1d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.v4s32.f32">; -def int_nvvm_tex_1d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.level.v4s32.f32">; -def int_nvvm_tex_1d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.grad.v4s32.f32">; -def int_nvvm_tex_1d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.v4u32.s32">; -def int_nvvm_tex_1d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.v4u32.f32">; -def int_nvvm_tex_1d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.level.v4u32.f32">; -def int_nvvm_tex_1d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.grad.v4u32.f32">; - -def int_nvvm_tex_1d_array_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.array.v4f32.s32">; -def int_nvvm_tex_1d_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.v4f32.f32">; -def int_nvvm_tex_1d_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.level.v4f32.f32">; -def int_nvvm_tex_1d_array_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.grad.v4f32.f32">; -def int_nvvm_tex_1d_array_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.array.v4s32.s32">; -def int_nvvm_tex_1d_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.v4s32.f32">; -def int_nvvm_tex_1d_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.level.v4s32.f32">; -def int_nvvm_tex_1d_array_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.grad.v4s32.f32">; -def int_nvvm_tex_1d_array_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.1d.array.v4u32.s32">; -def int_nvvm_tex_1d_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.v4u32.f32">; -def int_nvvm_tex_1d_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.level.v4u32.f32">; -def int_nvvm_tex_1d_array_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.1d.array.grad.v4u32.f32">; - -def int_nvvm_tex_2d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.2d.v4f32.s32">; -def int_nvvm_tex_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.v4f32.f32">; -def int_nvvm_tex_2d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.level.v4f32.f32">; -def int_nvvm_tex_2d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.grad.v4f32.f32">; -def int_nvvm_tex_2d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.2d.v4s32.s32">; -def int_nvvm_tex_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.v4s32.f32">; -def int_nvvm_tex_2d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.level.v4s32.f32">; -def int_nvvm_tex_2d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.grad.v4s32.f32">; -def int_nvvm_tex_2d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.2d.v4u32.s32">; -def int_nvvm_tex_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.v4u32.f32">; -def int_nvvm_tex_2d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.level.v4u32.f32">; -def int_nvvm_tex_2d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.grad.v4u32.f32">; - -def int_nvvm_tex_2d_array_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.2d.array.v4f32.s32">; -def int_nvvm_tex_2d_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.v4f32.f32">; -def int_nvvm_tex_2d_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.level.v4f32.f32">; -def int_nvvm_tex_2d_array_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.grad.v4f32.f32">; -def int_nvvm_tex_2d_array_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.2d.array.v4s32.s32">; -def int_nvvm_tex_2d_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.v4s32.f32">; -def int_nvvm_tex_2d_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.level.v4s32.f32">; -def int_nvvm_tex_2d_array_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.grad.v4s32.f32">; -def int_nvvm_tex_2d_array_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.2d.array.v4u32.s32">; -def int_nvvm_tex_2d_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.v4u32.f32">; -def int_nvvm_tex_2d_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.level.v4u32.f32">; -def int_nvvm_tex_2d_array_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.2d.array.grad.v4u32.f32">; - -def int_nvvm_tex_3d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.3d.v4f32.s32">; -def int_nvvm_tex_3d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.3d.v4f32.f32">; -def int_nvvm_tex_3d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.level.v4f32.f32">; -def int_nvvm_tex_3d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.grad.v4f32.f32">; -def int_nvvm_tex_3d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.3d.v4s32.s32">; -def int_nvvm_tex_3d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.3d.v4s32.f32">; -def int_nvvm_tex_3d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.level.v4s32.f32">; -def int_nvvm_tex_3d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.grad.v4s32.f32">; -def int_nvvm_tex_3d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.3d.v4u32.s32">; -def int_nvvm_tex_3d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.3d.v4u32.f32">; -def int_nvvm_tex_3d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.level.v4u32.f32">; -def int_nvvm_tex_3d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.3d.grad.v4u32.f32">; - -def int_nvvm_tex_cube_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.v4f32.f32">; -def int_nvvm_tex_cube_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.level.v4f32.f32">; -def int_nvvm_tex_cube_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.v4s32.f32">; -def int_nvvm_tex_cube_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.level.v4s32.f32">; -def int_nvvm_tex_cube_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.v4u32.f32">; -def int_nvvm_tex_cube_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.level.v4u32.f32">; - -def int_nvvm_tex_cube_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.v4f32.f32">; -def int_nvvm_tex_cube_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.level.v4f32.f32">; -def int_nvvm_tex_cube_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.v4s32.f32">; -def int_nvvm_tex_cube_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.level.v4s32.f32">; -def int_nvvm_tex_cube_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.v4u32.f32">; -def int_nvvm_tex_cube_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.cube.array.level.v4u32.f32">; - -def int_nvvm_tld4_r_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.r.2d.v4f32.f32">; -def int_nvvm_tld4_g_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.g.2d.v4f32.f32">; -def int_nvvm_tld4_b_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.b.2d.v4f32.f32">; -def int_nvvm_tld4_a_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.a.2d.v4f32.f32">; -def int_nvvm_tld4_r_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.r.2d.v4s32.f32">; -def int_nvvm_tld4_g_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.g.2d.v4s32.f32">; -def int_nvvm_tld4_b_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.b.2d.v4s32.f32">; -def int_nvvm_tld4_a_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.a.2d.v4s32.f32">; -def int_nvvm_tld4_r_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.r.2d.v4u32.f32">; -def int_nvvm_tld4_g_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.g.2d.v4u32.f32">; -def int_nvvm_tld4_b_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.b.2d.v4u32.f32">; -def int_nvvm_tld4_a_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.a.2d.v4u32.f32">; - - -// texmode_unified -def int_nvvm_tex_unified_1d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.v4f32.s32">; -def int_nvvm_tex_unified_1d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.v4f32.f32">; -def int_nvvm_tex_unified_1d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.level.v4f32.f32">; -def int_nvvm_tex_unified_1d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.grad.v4f32.f32">; -def int_nvvm_tex_unified_1d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.v4s32.s32">; -def int_nvvm_tex_unified_1d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.v4s32.f32">; -def int_nvvm_tex_unified_1d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.level.v4s32.f32">; -def int_nvvm_tex_unified_1d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.grad.v4s32.f32">; -def int_nvvm_tex_unified_1d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.v4u32.s32">; -def int_nvvm_tex_unified_1d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.v4u32.f32">; -def int_nvvm_tex_unified_1d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.level.v4u32.f32">; -def int_nvvm_tex_unified_1d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.grad.v4u32.f32">; - -def int_nvvm_tex_unified_1d_array_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4f32.s32">; -def int_nvvm_tex_unified_1d_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4f32.f32">; -def int_nvvm_tex_unified_1d_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.level.v4f32.f32">; -def int_nvvm_tex_unified_1d_array_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.grad.v4f32.f32">; -def int_nvvm_tex_unified_1d_array_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4s32.s32">; -def int_nvvm_tex_unified_1d_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4s32.f32">; -def int_nvvm_tex_unified_1d_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.level.v4s32.f32">; -def int_nvvm_tex_unified_1d_array_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.grad.v4s32.f32">; -def int_nvvm_tex_unified_1d_array_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4u32.s32">; -def int_nvvm_tex_unified_1d_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.v4u32.f32">; -def int_nvvm_tex_unified_1d_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.level.v4u32.f32">; -def int_nvvm_tex_unified_1d_array_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.1d.array.grad.v4u32.f32">; - -def int_nvvm_tex_unified_2d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.v4f32.s32">; -def int_nvvm_tex_unified_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.v4f32.f32">; -def int_nvvm_tex_unified_2d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.level.v4f32.f32">; -def int_nvvm_tex_unified_2d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.grad.v4f32.f32">; -def int_nvvm_tex_unified_2d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.v4s32.s32">; -def int_nvvm_tex_unified_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.v4s32.f32">; -def int_nvvm_tex_unified_2d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.level.v4s32.f32">; -def int_nvvm_tex_unified_2d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.grad.v4s32.f32">; -def int_nvvm_tex_unified_2d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.v4u32.s32">; -def int_nvvm_tex_unified_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.v4u32.f32">; -def int_nvvm_tex_unified_2d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.level.v4u32.f32">; -def int_nvvm_tex_unified_2d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.grad.v4u32.f32">; - -def int_nvvm_tex_unified_2d_array_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4f32.s32">; -def int_nvvm_tex_unified_2d_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4f32.f32">; -def int_nvvm_tex_unified_2d_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.level.v4f32.f32">; -def int_nvvm_tex_unified_2d_array_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.grad.v4f32.f32">; -def int_nvvm_tex_unified_2d_array_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4s32.s32">; -def int_nvvm_tex_unified_2d_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4s32.f32">; -def int_nvvm_tex_unified_2d_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.level.v4s32.f32">; -def int_nvvm_tex_unified_2d_array_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.grad.v4s32.f32">; -def int_nvvm_tex_unified_2d_array_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4u32.s32">; -def int_nvvm_tex_unified_2d_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.v4u32.f32">; -def int_nvvm_tex_unified_2d_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.level.v4u32.f32">; -def int_nvvm_tex_unified_2d_array_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.2d.array.grad.v4u32.f32">; - -def int_nvvm_tex_unified_3d_v4f32_s32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.unified.3d.v4f32.s32">; -def int_nvvm_tex_unified_3d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.v4f32.f32">; -def int_nvvm_tex_unified_3d_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.level.v4f32.f32">; -def int_nvvm_tex_unified_3d_grad_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.grad.v4f32.f32">; -def int_nvvm_tex_unified_3d_v4s32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.unified.3d.v4s32.s32">; -def int_nvvm_tex_unified_3d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.v4s32.f32">; -def int_nvvm_tex_unified_3d_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.level.v4s32.f32">; -def int_nvvm_tex_unified_3d_grad_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.grad.v4s32.f32">; -def int_nvvm_tex_unified_3d_v4u32_s32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [], "llvm.nvvm.tex.unified.3d.v4u32.s32">; -def int_nvvm_tex_unified_3d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.v4u32.f32">; -def int_nvvm_tex_unified_3d_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.level.v4u32.f32">; -def int_nvvm_tex_unified_3d_grad_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.3d.grad.v4u32.f32">; - -def int_nvvm_tex_unified_cube_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.v4f32.f32">; -def int_nvvm_tex_unified_cube_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.level.v4f32.f32">; -def int_nvvm_tex_unified_cube_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.v4s32.f32">; -def int_nvvm_tex_unified_cube_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.level.v4s32.f32">; -def int_nvvm_tex_unified_cube_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.v4u32.f32">; -def int_nvvm_tex_unified_cube_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.level.v4u32.f32">; - -def int_nvvm_tex_unified_cube_array_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.v4f32.f32">; -def int_nvvm_tex_unified_cube_array_level_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.level.v4f32.f32">; -def int_nvvm_tex_unified_cube_array_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.v4s32.f32">; -def int_nvvm_tex_unified_cube_array_level_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.level.v4s32.f32">; -def int_nvvm_tex_unified_cube_array_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.v4u32.f32">; -def int_nvvm_tex_unified_cube_array_level_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tex.unified.cube.array.level.v4u32.f32">; - -def int_nvvm_tld4_unified_r_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.r.2d.v4f32.f32">; -def int_nvvm_tld4_unified_g_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.g.2d.v4f32.f32">; -def int_nvvm_tld4_unified_b_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.b.2d.v4f32.f32">; -def int_nvvm_tld4_unified_a_2d_v4f32_f32 - : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.a.2d.v4f32.f32">; -def int_nvvm_tld4_unified_r_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.r.2d.v4s32.f32">; -def int_nvvm_tld4_unified_g_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.g.2d.v4s32.f32">; -def int_nvvm_tld4_unified_b_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.b.2d.v4s32.f32">; -def int_nvvm_tld4_unified_a_2d_v4s32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.a.2d.v4s32.f32">; -def int_nvvm_tld4_unified_r_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.r.2d.v4u32.f32">; -def int_nvvm_tld4_unified_g_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.g.2d.v4u32.f32">; -def int_nvvm_tld4_unified_b_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.b.2d.v4u32.f32">; -def int_nvvm_tld4_unified_a_2d_v4u32_f32 - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], - "llvm.nvvm.tld4.unified.a.2d.v4u32.f32">; - - -//=== Surface Load -// .clamp variants -def int_nvvm_suld_1d_i8_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i8.clamp">; -def int_nvvm_suld_1d_i16_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i16.clamp">; -def int_nvvm_suld_1d_i32_clamp - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i32.clamp">; -def int_nvvm_suld_1d_i64_clamp - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i64.clamp">; -def int_nvvm_suld_1d_v2i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i8.clamp">; -def int_nvvm_suld_1d_v2i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i16.clamp">; -def int_nvvm_suld_1d_v2i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i32.clamp">; -def int_nvvm_suld_1d_v2i64_clamp - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i64.clamp">; -def int_nvvm_suld_1d_v4i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i8.clamp">; -def int_nvvm_suld_1d_v4i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i16.clamp">; -def int_nvvm_suld_1d_v4i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i32.clamp">; - -def int_nvvm_suld_1d_array_i8_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i8.clamp">; -def int_nvvm_suld_1d_array_i16_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i16.clamp">; -def int_nvvm_suld_1d_array_i32_clamp - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i32.clamp">; -def int_nvvm_suld_1d_array_i64_clamp - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i64.clamp">; -def int_nvvm_suld_1d_array_v2i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i8.clamp">; -def int_nvvm_suld_1d_array_v2i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i16.clamp">; -def int_nvvm_suld_1d_array_v2i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i32.clamp">; -def int_nvvm_suld_1d_array_v2i64_clamp - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i64.clamp">; -def int_nvvm_suld_1d_array_v4i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i8.clamp">; -def int_nvvm_suld_1d_array_v4i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i16.clamp">; -def int_nvvm_suld_1d_array_v4i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i32.clamp">; - -def int_nvvm_suld_2d_i8_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i8.clamp">; -def int_nvvm_suld_2d_i16_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i16.clamp">; -def int_nvvm_suld_2d_i32_clamp - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i32.clamp">; -def int_nvvm_suld_2d_i64_clamp - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i64.clamp">; -def int_nvvm_suld_2d_v2i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i8.clamp">; -def int_nvvm_suld_2d_v2i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i16.clamp">; -def int_nvvm_suld_2d_v2i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i32.clamp">; -def int_nvvm_suld_2d_v2i64_clamp - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i64.clamp">; -def int_nvvm_suld_2d_v4i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i8.clamp">; -def int_nvvm_suld_2d_v4i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i16.clamp">; -def int_nvvm_suld_2d_v4i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i32.clamp">; - -def int_nvvm_suld_2d_array_i8_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i8.clamp">; -def int_nvvm_suld_2d_array_i16_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i16.clamp">; -def int_nvvm_suld_2d_array_i32_clamp - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i32.clamp">; -def int_nvvm_suld_2d_array_i64_clamp - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i64.clamp">; -def int_nvvm_suld_2d_array_v2i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i8.clamp">; -def int_nvvm_suld_2d_array_v2i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i16.clamp">; -def int_nvvm_suld_2d_array_v2i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i32.clamp">; -def int_nvvm_suld_2d_array_v2i64_clamp - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i64.clamp">; -def int_nvvm_suld_2d_array_v4i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i8.clamp">; -def int_nvvm_suld_2d_array_v4i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i16.clamp">; -def int_nvvm_suld_2d_array_v4i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i32.clamp">; - -def int_nvvm_suld_3d_i8_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i8.clamp">; -def int_nvvm_suld_3d_i16_clamp - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i16.clamp">; -def int_nvvm_suld_3d_i32_clamp - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i32.clamp">; -def int_nvvm_suld_3d_i64_clamp - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i64.clamp">; -def int_nvvm_suld_3d_v2i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i8.clamp">; -def int_nvvm_suld_3d_v2i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i16.clamp">; -def int_nvvm_suld_3d_v2i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i32.clamp">; -def int_nvvm_suld_3d_v2i64_clamp - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i64.clamp">; -def int_nvvm_suld_3d_v4i8_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i8.clamp">; -def int_nvvm_suld_3d_v4i16_clamp - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i16.clamp">; -def int_nvvm_suld_3d_v4i32_clamp - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i32.clamp">; - -// .trap variants -def int_nvvm_suld_1d_i8_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i8.trap">; -def int_nvvm_suld_1d_i16_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i16.trap">; -def int_nvvm_suld_1d_i32_trap - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i32.trap">; -def int_nvvm_suld_1d_i64_trap - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i64.trap">; -def int_nvvm_suld_1d_v2i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i8.trap">; -def int_nvvm_suld_1d_v2i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i16.trap">; -def int_nvvm_suld_1d_v2i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i32.trap">; -def int_nvvm_suld_1d_v2i64_trap - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i64.trap">; -def int_nvvm_suld_1d_v4i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i8.trap">; -def int_nvvm_suld_1d_v4i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i16.trap">; -def int_nvvm_suld_1d_v4i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i32.trap">; - -def int_nvvm_suld_1d_array_i8_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i8.trap">; -def int_nvvm_suld_1d_array_i16_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i16.trap">; -def int_nvvm_suld_1d_array_i32_trap - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i32.trap">; -def int_nvvm_suld_1d_array_i64_trap - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i64.trap">; -def int_nvvm_suld_1d_array_v2i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i8.trap">; -def int_nvvm_suld_1d_array_v2i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i16.trap">; -def int_nvvm_suld_1d_array_v2i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i32.trap">; -def int_nvvm_suld_1d_array_v2i64_trap - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i64.trap">; -def int_nvvm_suld_1d_array_v4i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i8.trap">; -def int_nvvm_suld_1d_array_v4i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i16.trap">; -def int_nvvm_suld_1d_array_v4i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i32.trap">; - -def int_nvvm_suld_2d_i8_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i8.trap">; -def int_nvvm_suld_2d_i16_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i16.trap">; -def int_nvvm_suld_2d_i32_trap - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i32.trap">; -def int_nvvm_suld_2d_i64_trap - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i64.trap">; -def int_nvvm_suld_2d_v2i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i8.trap">; -def int_nvvm_suld_2d_v2i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i16.trap">; -def int_nvvm_suld_2d_v2i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i32.trap">; -def int_nvvm_suld_2d_v2i64_trap - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i64.trap">; -def int_nvvm_suld_2d_v4i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i8.trap">; -def int_nvvm_suld_2d_v4i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i16.trap">; -def int_nvvm_suld_2d_v4i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i32.trap">; - -def int_nvvm_suld_2d_array_i8_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i8.trap">; -def int_nvvm_suld_2d_array_i16_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i16.trap">; -def int_nvvm_suld_2d_array_i32_trap - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i32.trap">; -def int_nvvm_suld_2d_array_i64_trap - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i64.trap">; -def int_nvvm_suld_2d_array_v2i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i8.trap">; -def int_nvvm_suld_2d_array_v2i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i16.trap">; -def int_nvvm_suld_2d_array_v2i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i32.trap">; -def int_nvvm_suld_2d_array_v2i64_trap - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i64.trap">; -def int_nvvm_suld_2d_array_v4i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i8.trap">; -def int_nvvm_suld_2d_array_v4i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i16.trap">; -def int_nvvm_suld_2d_array_v4i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i32.trap">; - -def int_nvvm_suld_3d_i8_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i8.trap">; -def int_nvvm_suld_3d_i16_trap - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i16.trap">; -def int_nvvm_suld_3d_i32_trap - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i32.trap">; -def int_nvvm_suld_3d_i64_trap - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i64.trap">; -def int_nvvm_suld_3d_v2i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i8.trap">; -def int_nvvm_suld_3d_v2i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i16.trap">; -def int_nvvm_suld_3d_v2i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i32.trap">; -def int_nvvm_suld_3d_v2i64_trap - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i64.trap">; -def int_nvvm_suld_3d_v4i8_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i8.trap">; -def int_nvvm_suld_3d_v4i16_trap - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i16.trap">; -def int_nvvm_suld_3d_v4i32_trap - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i32.trap">; - -// .zero variants -def int_nvvm_suld_1d_i8_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i8.zero">; -def int_nvvm_suld_1d_i16_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i16.zero">; -def int_nvvm_suld_1d_i32_zero - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i32.zero">; -def int_nvvm_suld_1d_i64_zero - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.i64.zero">; -def int_nvvm_suld_1d_v2i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i8.zero">; -def int_nvvm_suld_1d_v2i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i16.zero">; -def int_nvvm_suld_1d_v2i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i32.zero">; -def int_nvvm_suld_1d_v2i64_zero - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v2i64.zero">; -def int_nvvm_suld_1d_v4i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i8.zero">; -def int_nvvm_suld_1d_v4i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i16.zero">; -def int_nvvm_suld_1d_v4i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.v4i32.zero">; - -def int_nvvm_suld_1d_array_i8_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i8.zero">; -def int_nvvm_suld_1d_array_i16_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i16.zero">; -def int_nvvm_suld_1d_array_i32_zero - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i32.zero">; -def int_nvvm_suld_1d_array_i64_zero - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.i64.zero">; -def int_nvvm_suld_1d_array_v2i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i8.zero">; -def int_nvvm_suld_1d_array_v2i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i16.zero">; -def int_nvvm_suld_1d_array_v2i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i32.zero">; -def int_nvvm_suld_1d_array_v2i64_zero - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v2i64.zero">; -def int_nvvm_suld_1d_array_v4i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i8.zero">; -def int_nvvm_suld_1d_array_v4i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i16.zero">; -def int_nvvm_suld_1d_array_v4i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.1d.array.v4i32.zero">; - -def int_nvvm_suld_2d_i8_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i8.zero">; -def int_nvvm_suld_2d_i16_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i16.zero">; -def int_nvvm_suld_2d_i32_zero - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i32.zero">; -def int_nvvm_suld_2d_i64_zero - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.i64.zero">; -def int_nvvm_suld_2d_v2i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i8.zero">; -def int_nvvm_suld_2d_v2i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i16.zero">; -def int_nvvm_suld_2d_v2i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i32.zero">; -def int_nvvm_suld_2d_v2i64_zero - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v2i64.zero">; -def int_nvvm_suld_2d_v4i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i8.zero">; -def int_nvvm_suld_2d_v4i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i16.zero">; -def int_nvvm_suld_2d_v4i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.v4i32.zero">; - -def int_nvvm_suld_2d_array_i8_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i8.zero">; -def int_nvvm_suld_2d_array_i16_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i16.zero">; -def int_nvvm_suld_2d_array_i32_zero - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i32.zero">; -def int_nvvm_suld_2d_array_i64_zero - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.i64.zero">; -def int_nvvm_suld_2d_array_v2i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i8.zero">; -def int_nvvm_suld_2d_array_v2i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i16.zero">; -def int_nvvm_suld_2d_array_v2i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i32.zero">; -def int_nvvm_suld_2d_array_v2i64_zero - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v2i64.zero">; -def int_nvvm_suld_2d_array_v4i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i8.zero">; -def int_nvvm_suld_2d_array_v4i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i16.zero">; -def int_nvvm_suld_2d_array_v4i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.2d.array.v4i32.zero">; - -def int_nvvm_suld_3d_i8_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i8.zero">; -def int_nvvm_suld_3d_i16_zero - : Intrinsic<[llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i16.zero">; -def int_nvvm_suld_3d_i32_zero - : Intrinsic<[llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i32.zero">; -def int_nvvm_suld_3d_i64_zero - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.i64.zero">; -def int_nvvm_suld_3d_v2i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i8.zero">; -def int_nvvm_suld_3d_v2i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i16.zero">; -def int_nvvm_suld_3d_v2i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i32.zero">; -def int_nvvm_suld_3d_v2i64_zero - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v2i64.zero">; -def int_nvvm_suld_3d_v4i8_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i8.zero">; -def int_nvvm_suld_3d_v4i16_zero - : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i16.zero">; -def int_nvvm_suld_3d_v4i32_zero - : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.suld.3d.v4i32.zero">; - -//===- Texture Query ------------------------------------------------------===// - -def int_nvvm_txq_channel_order - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.channel.order">, - GCCBuiltin<"__nvvm_txq_channel_order">; -def int_nvvm_txq_channel_data_type - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.channel.data.type">, - GCCBuiltin<"__nvvm_txq_channel_data_type">; -def int_nvvm_txq_width - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.width">, - GCCBuiltin<"__nvvm_txq_width">; -def int_nvvm_txq_height - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.height">, - GCCBuiltin<"__nvvm_txq_height">; -def int_nvvm_txq_depth - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.depth">, - GCCBuiltin<"__nvvm_txq_depth">; -def int_nvvm_txq_array_size - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.array.size">, - GCCBuiltin<"__nvvm_txq_array_size">; -def int_nvvm_txq_num_samples - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.num.samples">, - GCCBuiltin<"__nvvm_txq_num_samples">; -def int_nvvm_txq_num_mipmap_levels - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.txq.num.mipmap.levels">, - GCCBuiltin<"__nvvm_txq_num_mipmap_levels">; - -//===- Surface Query ------------------------------------------------------===// - -def int_nvvm_suq_channel_order - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.channel.order">, - GCCBuiltin<"__nvvm_suq_channel_order">; -def int_nvvm_suq_channel_data_type - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.channel.data.type">, - GCCBuiltin<"__nvvm_suq_channel_data_type">; -def int_nvvm_suq_width - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.width">, - GCCBuiltin<"__nvvm_suq_width">; -def int_nvvm_suq_height - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.height">, - GCCBuiltin<"__nvvm_suq_height">; -def int_nvvm_suq_depth - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.depth">, - GCCBuiltin<"__nvvm_suq_depth">; -def int_nvvm_suq_array_size - : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.suq.array.size">, - GCCBuiltin<"__nvvm_suq_array_size">; - - -//===- Handle Query -------------------------------------------------------===// - -def int_nvvm_istypep_sampler - : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.istypep.sampler">, - GCCBuiltin<"__nvvm_istypep_sampler">; -def int_nvvm_istypep_surface - : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.istypep.surface">, - GCCBuiltin<"__nvvm_istypep_surface">; -def int_nvvm_istypep_texture - : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], - "llvm.nvvm.istypep.texture">, - GCCBuiltin<"__nvvm_istypep_texture">; - - - -//===- Surface Stores -----------------------------------------------------===// - -// Unformatted -// .clamp variant -def int_nvvm_sust_b_1d_i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_i8_clamp">; -def int_nvvm_sust_b_1d_i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_i16_clamp">; -def int_nvvm_sust_b_1d_i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_i32_clamp">; -def int_nvvm_sust_b_1d_i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_i64_clamp">; -def int_nvvm_sust_b_1d_v2i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i8_clamp">; -def int_nvvm_sust_b_1d_v2i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i16_clamp">; -def int_nvvm_sust_b_1d_v2i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v2i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i32_clamp">; -def int_nvvm_sust_b_1d_v2i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.v2i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i64_clamp">; -def int_nvvm_sust_b_1d_v4i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i8_clamp">; -def int_nvvm_sust_b_1d_v4i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i16_clamp">; -def int_nvvm_sust_b_1d_v4i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v4i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i32_clamp">; - - -def int_nvvm_sust_b_1d_array_i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i8_clamp">; -def int_nvvm_sust_b_1d_array_i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i16_clamp">; -def int_nvvm_sust_b_1d_array_i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i32_clamp">; -def int_nvvm_sust_b_1d_array_i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i64_clamp">; -def int_nvvm_sust_b_1d_array_v2i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_clamp">; -def int_nvvm_sust_b_1d_array_v2i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_clamp">; -def int_nvvm_sust_b_1d_array_v2i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_clamp">; -def int_nvvm_sust_b_1d_array_v2i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_clamp">; -def int_nvvm_sust_b_1d_array_v4i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_clamp">; -def int_nvvm_sust_b_1d_array_v4i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_clamp">; -def int_nvvm_sust_b_1d_array_v4i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_clamp">; - - -def int_nvvm_sust_b_2d_i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_i8_clamp">; -def int_nvvm_sust_b_2d_i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_i16_clamp">; -def int_nvvm_sust_b_2d_i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_i32_clamp">; -def int_nvvm_sust_b_2d_i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_i64_clamp">; -def int_nvvm_sust_b_2d_v2i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i8_clamp">; -def int_nvvm_sust_b_2d_v2i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i16_clamp">; -def int_nvvm_sust_b_2d_v2i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v2i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i32_clamp">; -def int_nvvm_sust_b_2d_v2i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.v2i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i64_clamp">; -def int_nvvm_sust_b_2d_v4i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i8_clamp">; -def int_nvvm_sust_b_2d_v4i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i16_clamp">; -def int_nvvm_sust_b_2d_v4i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v4i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i32_clamp">; - - -def int_nvvm_sust_b_2d_array_i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i8_clamp">; -def int_nvvm_sust_b_2d_array_i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i16_clamp">; -def int_nvvm_sust_b_2d_array_i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i32_clamp">; -def int_nvvm_sust_b_2d_array_i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i64_clamp">; -def int_nvvm_sust_b_2d_array_v2i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_clamp">; -def int_nvvm_sust_b_2d_array_v2i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_clamp">; -def int_nvvm_sust_b_2d_array_v2i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_clamp">; -def int_nvvm_sust_b_2d_array_v2i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_clamp">; -def int_nvvm_sust_b_2d_array_v4i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_clamp">; -def int_nvvm_sust_b_2d_array_v4i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_clamp">; -def int_nvvm_sust_b_2d_array_v4i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_clamp">; - - -def int_nvvm_sust_b_3d_i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_i8_clamp">; -def int_nvvm_sust_b_3d_i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_i16_clamp">; -def int_nvvm_sust_b_3d_i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_i32_clamp">; -def int_nvvm_sust_b_3d_i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_i64_clamp">; -def int_nvvm_sust_b_3d_v2i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i8_clamp">; -def int_nvvm_sust_b_3d_v2i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i16_clamp">; -def int_nvvm_sust_b_3d_v2i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v2i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i32_clamp">; -def int_nvvm_sust_b_3d_v2i64_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.v2i64.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i64_clamp">; -def int_nvvm_sust_b_3d_v4i8_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i8.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i8_clamp">; -def int_nvvm_sust_b_3d_v4i16_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i16.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i16_clamp">; -def int_nvvm_sust_b_3d_v4i32_clamp - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v4i32.clamp">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i32_clamp">; - - -// .trap variant -def int_nvvm_sust_b_1d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_i8_trap">; -def int_nvvm_sust_b_1d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_i16_trap">; -def int_nvvm_sust_b_1d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_i32_trap">; -def int_nvvm_sust_b_1d_i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.i64.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_i64_trap">; -def int_nvvm_sust_b_1d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i8_trap">; -def int_nvvm_sust_b_1d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i16_trap">; -def int_nvvm_sust_b_1d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i32_trap">; -def int_nvvm_sust_b_1d_v2i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.v2i64.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i64_trap">; -def int_nvvm_sust_b_1d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i8_trap">; -def int_nvvm_sust_b_1d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i16_trap">; -def int_nvvm_sust_b_1d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i32_trap">; - - -def int_nvvm_sust_b_1d_array_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i8_trap">; -def int_nvvm_sust_b_1d_array_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i16_trap">; -def int_nvvm_sust_b_1d_array_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i32_trap">; -def int_nvvm_sust_b_1d_array_i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.i64.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i64_trap">; -def int_nvvm_sust_b_1d_array_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_trap">; -def int_nvvm_sust_b_1d_array_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_trap">; -def int_nvvm_sust_b_1d_array_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_trap">; -def int_nvvm_sust_b_1d_array_v2i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i64.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_trap">; -def int_nvvm_sust_b_1d_array_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_trap">; -def int_nvvm_sust_b_1d_array_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_trap">; -def int_nvvm_sust_b_1d_array_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_trap">; - - -def int_nvvm_sust_b_2d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_i8_trap">; -def int_nvvm_sust_b_2d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_i16_trap">; -def int_nvvm_sust_b_2d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_i32_trap">; -def int_nvvm_sust_b_2d_i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.i64.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_i64_trap">; -def int_nvvm_sust_b_2d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i8_trap">; -def int_nvvm_sust_b_2d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i16_trap">; -def int_nvvm_sust_b_2d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i32_trap">; -def int_nvvm_sust_b_2d_v2i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.v2i64.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i64_trap">; -def int_nvvm_sust_b_2d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i8_trap">; -def int_nvvm_sust_b_2d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i16_trap">; -def int_nvvm_sust_b_2d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i32_trap">; - - -def int_nvvm_sust_b_2d_array_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i8_trap">; -def int_nvvm_sust_b_2d_array_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i16_trap">; -def int_nvvm_sust_b_2d_array_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i32_trap">; -def int_nvvm_sust_b_2d_array_i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.i64.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i64_trap">; -def int_nvvm_sust_b_2d_array_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_trap">; -def int_nvvm_sust_b_2d_array_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_trap">; -def int_nvvm_sust_b_2d_array_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_trap">; -def int_nvvm_sust_b_2d_array_v2i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i64.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_trap">; -def int_nvvm_sust_b_2d_array_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_trap">; -def int_nvvm_sust_b_2d_array_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_trap">; -def int_nvvm_sust_b_2d_array_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_trap">; - - -def int_nvvm_sust_b_3d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i8.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_i8_trap">; -def int_nvvm_sust_b_3d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i16.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_i16_trap">; -def int_nvvm_sust_b_3d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.i32.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_i32_trap">; -def int_nvvm_sust_b_3d_i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.i64.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_i64_trap">; -def int_nvvm_sust_b_3d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i8_trap">; -def int_nvvm_sust_b_3d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i16_trap">; -def int_nvvm_sust_b_3d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i32_trap">; -def int_nvvm_sust_b_3d_v2i64_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.v2i64.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i64_trap">; -def int_nvvm_sust_b_3d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i8_trap">; -def int_nvvm_sust_b_3d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i16_trap">; -def int_nvvm_sust_b_3d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i32_trap">; - - -// .zero variant -def int_nvvm_sust_b_1d_i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_i8_zero">; -def int_nvvm_sust_b_1d_i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_i16_zero">; -def int_nvvm_sust_b_1d_i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_i32_zero">; -def int_nvvm_sust_b_1d_i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.i64.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_i64_zero">; -def int_nvvm_sust_b_1d_v2i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i8_zero">; -def int_nvvm_sust_b_1d_v2i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v2i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i16_zero">; -def int_nvvm_sust_b_1d_v2i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v2i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i32_zero">; -def int_nvvm_sust_b_1d_v2i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.v2i64.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v2i64_zero">; -def int_nvvm_sust_b_1d_v4i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i8_zero">; -def int_nvvm_sust_b_1d_v4i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.v4i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i16_zero">; -def int_nvvm_sust_b_1d_v4i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.v4i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_v4i32_zero">; - - -def int_nvvm_sust_b_1d_array_i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i8_zero">; -def int_nvvm_sust_b_1d_array_i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i16_zero">; -def int_nvvm_sust_b_1d_array_i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i32_zero">; -def int_nvvm_sust_b_1d_array_i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.i64.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_i64_zero">; -def int_nvvm_sust_b_1d_array_v2i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_zero">; -def int_nvvm_sust_b_1d_array_v2i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_zero">; -def int_nvvm_sust_b_1d_array_v2i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_zero">; -def int_nvvm_sust_b_1d_array_v2i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.1d.array.v2i64.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_zero">; -def int_nvvm_sust_b_1d_array_v4i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i8.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_zero">; -def int_nvvm_sust_b_1d_array_v4i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i16.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_zero">; -def int_nvvm_sust_b_1d_array_v4i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.1d.array.v4i32.zero">, - GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_zero">; - - -def int_nvvm_sust_b_2d_i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_i8_zero">; -def int_nvvm_sust_b_2d_i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_i16_zero">; -def int_nvvm_sust_b_2d_i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_i32_zero">; -def int_nvvm_sust_b_2d_i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.i64.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_i64_zero">; -def int_nvvm_sust_b_2d_v2i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i8_zero">; -def int_nvvm_sust_b_2d_v2i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v2i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i16_zero">; -def int_nvvm_sust_b_2d_v2i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v2i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i32_zero">; -def int_nvvm_sust_b_2d_v2i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.v2i64.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v2i64_zero">; -def int_nvvm_sust_b_2d_v4i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i8_zero">; -def int_nvvm_sust_b_2d_v4i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.v4i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i16_zero">; -def int_nvvm_sust_b_2d_v4i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.v4i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_v4i32_zero">; - - -def int_nvvm_sust_b_2d_array_i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i8_zero">; -def int_nvvm_sust_b_2d_array_i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i16_zero">; -def int_nvvm_sust_b_2d_array_i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i32_zero">; -def int_nvvm_sust_b_2d_array_i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.i64.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_i64_zero">; -def int_nvvm_sust_b_2d_array_v2i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_zero">; -def int_nvvm_sust_b_2d_array_v2i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_zero">; -def int_nvvm_sust_b_2d_array_v2i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_zero">; -def int_nvvm_sust_b_2d_array_v2i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.2d.array.v2i64.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_zero">; -def int_nvvm_sust_b_2d_array_v4i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i8.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_zero">; -def int_nvvm_sust_b_2d_array_v4i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i16.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_zero">; -def int_nvvm_sust_b_2d_array_v4i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.2d.array.v4i32.zero">, - GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_zero">; - - -def int_nvvm_sust_b_3d_i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i8.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_i8_zero">; -def int_nvvm_sust_b_3d_i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.i16.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_i16_zero">; -def int_nvvm_sust_b_3d_i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.i32.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_i32_zero">; -def int_nvvm_sust_b_3d_i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.i64.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_i64_zero">; -def int_nvvm_sust_b_3d_v2i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i8.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i8_zero">; -def int_nvvm_sust_b_3d_v2i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v2i16.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i16_zero">; -def int_nvvm_sust_b_3d_v2i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v2i32.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i32_zero">; -def int_nvvm_sust_b_3d_v2i64_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i64_ty, llvm_i64_ty], [], - "llvm.nvvm.sust.b.3d.v2i64.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v2i64_zero">; -def int_nvvm_sust_b_3d_v4i8_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i8.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i8_zero">; -def int_nvvm_sust_b_3d_v4i16_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.b.3d.v4i16.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i16_zero">; -def int_nvvm_sust_b_3d_v4i32_zero - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.b.3d.v4i32.zero">, - GCCBuiltin<"__nvvm_sust_b_3d_v4i32_zero">; - - - -// Formatted - -def int_nvvm_sust_p_1d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_i8_trap">; -def int_nvvm_sust_p_1d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_i16_trap">; -def int_nvvm_sust_p_1d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_i32_trap">; -def int_nvvm_sust_p_1d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v2i8_trap">; -def int_nvvm_sust_p_1d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v2i16_trap">; -def int_nvvm_sust_p_1d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v2i32_trap">; -def int_nvvm_sust_p_1d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v4i8_trap">; -def int_nvvm_sust_p_1d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v4i16_trap">; -def int_nvvm_sust_p_1d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_v4i32_trap">; - - -def int_nvvm_sust_p_1d_array_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_i8_trap">; -def int_nvvm_sust_p_1d_array_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_i16_trap">; -def int_nvvm_sust_p_1d_array_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.array.i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_i32_trap">; -def int_nvvm_sust_p_1d_array_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v2i8_trap">; -def int_nvvm_sust_p_1d_array_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v2i16_trap">; -def int_nvvm_sust_p_1d_array_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.array.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v2i32_trap">; -def int_nvvm_sust_p_1d_array_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v4i8_trap">; -def int_nvvm_sust_p_1d_array_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.1d.array.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v4i16_trap">; -def int_nvvm_sust_p_1d_array_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.1d.array.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_p_1d_array_v4i32_trap">; - - -def int_nvvm_sust_p_2d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_i8_trap">; -def int_nvvm_sust_p_2d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_i16_trap">; -def int_nvvm_sust_p_2d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_i32_trap">; -def int_nvvm_sust_p_2d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v2i8_trap">; -def int_nvvm_sust_p_2d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v2i16_trap">; -def int_nvvm_sust_p_2d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v2i32_trap">; -def int_nvvm_sust_p_2d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v4i8_trap">; -def int_nvvm_sust_p_2d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v4i16_trap">; -def int_nvvm_sust_p_2d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_v4i32_trap">; - - -def int_nvvm_sust_p_2d_array_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_i8_trap">; -def int_nvvm_sust_p_2d_array_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_i16_trap">; -def int_nvvm_sust_p_2d_array_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.array.i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_i32_trap">; -def int_nvvm_sust_p_2d_array_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v2i8_trap">; -def int_nvvm_sust_p_2d_array_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v2i16_trap">; -def int_nvvm_sust_p_2d_array_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.array.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v2i32_trap">; -def int_nvvm_sust_p_2d_array_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v4i8_trap">; -def int_nvvm_sust_p_2d_array_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.2d.array.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v4i16_trap">; -def int_nvvm_sust_p_2d_array_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.2d.array.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_p_2d_array_v4i32_trap">; - - -def int_nvvm_sust_p_3d_i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.i8.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_i8_trap">; -def int_nvvm_sust_p_3d_i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.i16.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_i16_trap">; -def int_nvvm_sust_p_3d_i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.3d.i32.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_i32_trap">; -def int_nvvm_sust_p_3d_v2i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.v2i8.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v2i8_trap">; -def int_nvvm_sust_p_3d_v2i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.v2i16.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v2i16_trap">; -def int_nvvm_sust_p_3d_v2i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.3d.v2i32.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v2i32_trap">; -def int_nvvm_sust_p_3d_v4i8_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.v4i8.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v4i8_trap">; -def int_nvvm_sust_p_3d_v4i16_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], - "llvm.nvvm.sust.p.3d.v4i16.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v4i16_trap">; -def int_nvvm_sust_p_3d_v4i32_trap - : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], - "llvm.nvvm.sust.p.3d.v4i32.trap">, - GCCBuiltin<"__nvvm_sust_p_3d_v4i32_trap">; - - -def int_nvvm_rotate_b32 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable], "llvm.nvvm.rotate.b32">, - GCCBuiltin<"__nvvm_rotate_b32">; - -def int_nvvm_rotate_b64 - : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable], "llvm.nvvm.rotate.b64">, - GCCBuiltin<"__nvvm_rotate_b64">; - -def int_nvvm_rotate_right_b64 - : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable], "llvm.nvvm.rotate.right.b64">, - GCCBuiltin<"__nvvm_rotate_right_b64">; - -def int_nvvm_swap_lo_hi_b64 - : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty], - [IntrNoMem, IntrSpeculatable], "llvm.nvvm.swap.lo.hi.b64">, - GCCBuiltin<"__nvvm_swap_lo_hi_b64">; - - -// Accessing special registers. -multiclass PTXReadSRegIntrinsic_v4i32 { -// FIXME: Do we need the 128-bit integer type version? -// def _r64 : Intrinsic<[llvm_i128_ty], [], [IntrNoMem, IntrSpeculatable]>; - -// FIXME: Enable this once v4i32 support is enabled in back-end. -// def _v4i16 : Intrinsic<[llvm_v4i32_ty], [], [IntrNoMem, IntrSpeculatable]>; - - def _x : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_x">; - def _y : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_y">; - def _z : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_z">; - def _w : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_w">; -} - -class PTXReadSRegIntrinsic_r32 - : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; -class PTXReadSRegIntrinsic_r64 - : DefaultAttrsIntrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrSpeculatable]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; - -// Intrinsics to read registers with non-constant values. E.g. the values that -// do change over the kernel lifetime. Such reads should not be CSE'd. -class PTXReadNCSRegIntrinsic_r32 - : Intrinsic<[llvm_i32_ty], [], [IntrInaccessibleMemOnly]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; -class PTXReadNCSRegIntrinsic_r64 - : Intrinsic<[llvm_i64_ty], [], [IntrInaccessibleMemOnly]>, - GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; - -defm int_nvvm_read_ptx_sreg_tid : PTXReadSRegIntrinsic_v4i32<"tid">; -defm int_nvvm_read_ptx_sreg_ntid : PTXReadSRegIntrinsic_v4i32<"ntid">; - -def int_nvvm_read_ptx_sreg_laneid : PTXReadSRegIntrinsic_r32<"laneid">; -def int_nvvm_read_ptx_sreg_warpid : PTXReadSRegIntrinsic_r32<"warpid">; -def int_nvvm_read_ptx_sreg_nwarpid : PTXReadSRegIntrinsic_r32<"nwarpid">; - -defm int_nvvm_read_ptx_sreg_ctaid : PTXReadSRegIntrinsic_v4i32<"ctaid">; -defm int_nvvm_read_ptx_sreg_nctaid : PTXReadSRegIntrinsic_v4i32<"nctaid">; - -def int_nvvm_read_ptx_sreg_smid : PTXReadSRegIntrinsic_r32<"smid">; -def int_nvvm_read_ptx_sreg_nsmid : PTXReadSRegIntrinsic_r32<"nsmid">; -def int_nvvm_read_ptx_sreg_gridid : PTXReadSRegIntrinsic_r32<"gridid">; - -def int_nvvm_read_ptx_sreg_lanemask_eq : - PTXReadSRegIntrinsic_r32<"lanemask_eq">; -def int_nvvm_read_ptx_sreg_lanemask_le : - PTXReadSRegIntrinsic_r32<"lanemask_le">; -def int_nvvm_read_ptx_sreg_lanemask_lt : - PTXReadSRegIntrinsic_r32<"lanemask_lt">; -def int_nvvm_read_ptx_sreg_lanemask_ge : - PTXReadSRegIntrinsic_r32<"lanemask_ge">; -def int_nvvm_read_ptx_sreg_lanemask_gt : - PTXReadSRegIntrinsic_r32<"lanemask_gt">; - -def int_nvvm_read_ptx_sreg_clock : PTXReadNCSRegIntrinsic_r32<"clock">; -def int_nvvm_read_ptx_sreg_clock64 : PTXReadNCSRegIntrinsic_r64<"clock64">; - -def int_nvvm_read_ptx_sreg_pm0 : PTXReadNCSRegIntrinsic_r32<"pm0">; -def int_nvvm_read_ptx_sreg_pm1 : PTXReadNCSRegIntrinsic_r32<"pm1">; -def int_nvvm_read_ptx_sreg_pm2 : PTXReadNCSRegIntrinsic_r32<"pm2">; -def int_nvvm_read_ptx_sreg_pm3 : PTXReadNCSRegIntrinsic_r32<"pm3">; - -def int_nvvm_read_ptx_sreg_warpsize : PTXReadSRegIntrinsic_r32<"warpsize">; - -// -// SHUFFLE -// -// Generate intrinsics for all variants of shfl instruction. -foreach sync = [false, true] in { - foreach mode = ["up", "down", "bfly", "idx"] in { - foreach type = ["i32", "f32"] in { - foreach return_pred = [false, true] in { - foreach i = [SHFL_INFO] in { - if i.withGccBuiltin then { - def i.Name : GCCBuiltin, - Intrinsic; - } - if i.withoutGccBuiltin then { - def i.Name : Intrinsic; - } - } - } - } - } -} - -// -// VOTE -// - -// vote.all pred -def int_nvvm_vote_all : - Intrinsic<[llvm_i1_ty], [llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.all">, - GCCBuiltin<"__nvvm_vote_all">; -// vote.any pred -def int_nvvm_vote_any : - Intrinsic<[llvm_i1_ty], [llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.any">, - GCCBuiltin<"__nvvm_vote_any">; -// vote.uni pred -def int_nvvm_vote_uni : - Intrinsic<[llvm_i1_ty], [llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.uni">, - GCCBuiltin<"__nvvm_vote_uni">; -// vote.ballot pred -def int_nvvm_vote_ballot : - Intrinsic<[llvm_i32_ty], [llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.ballot">, - GCCBuiltin<"__nvvm_vote_ballot">; - -// -// VOTE.SYNC -// - -// vote.sync.all mask, pred -def int_nvvm_vote_all_sync : - Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.all.sync">, - GCCBuiltin<"__nvvm_vote_all_sync">; -// vote.sync.any mask, pred -def int_nvvm_vote_any_sync : - Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.any.sync">, - GCCBuiltin<"__nvvm_vote_any_sync">; -// vote.sync.uni mask, pred -def int_nvvm_vote_uni_sync : - Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.uni.sync">, - GCCBuiltin<"__nvvm_vote_uni_sync">; -// vote.sync.ballot mask, pred -def int_nvvm_vote_ballot_sync : - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i1_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.vote.ballot.sync">, - GCCBuiltin<"__nvvm_vote_ballot_sync">; - -// -// MATCH.SYNC -// -// match.any.sync.b32 mask, value -def int_nvvm_match_any_sync_i32 : - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.match.any.sync.i32">, - GCCBuiltin<"__nvvm_match_any_sync_i32">; -// match.any.sync.b64 mask, value -def int_nvvm_match_any_sync_i64 : - Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.match.any.sync.i64">, - GCCBuiltin<"__nvvm_match_any_sync_i64">; - -// match.all instruction have two variants -- one returns a single value, another -// returns a pair {value, predicate}. We currently only implement the latter as -// that's the variant exposed by CUDA API. - -// match.all.sync.b32p mask, value -def int_nvvm_match_all_sync_i32p : - Intrinsic<[llvm_i32_ty, llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.match.all.sync.i32p">; -// match.all.sync.b64p mask, value -def int_nvvm_match_all_sync_i64p : - Intrinsic<[llvm_i64_ty, llvm_i1_ty], [llvm_i32_ty, llvm_i64_ty], - [IntrInaccessibleMemOnly, IntrConvergent], "llvm.nvvm.match.all.sync.i64p">; - -// -// REDUX.SYNC -// -// redux.sync.min.u32 dst, src, membermask; -def int_nvvm_redux_sync_umin : GCCBuiltin<"__nvvm_redux_sync_umin">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.max.u32 dst, src, membermask; -def int_nvvm_redux_sync_umax : GCCBuiltin<"__nvvm_redux_sync_umax">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.add.s32 dst, src, membermask; -def int_nvvm_redux_sync_add : GCCBuiltin<"__nvvm_redux_sync_add">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.min.s32 dst, src, membermask; -def int_nvvm_redux_sync_min : GCCBuiltin<"__nvvm_redux_sync_min">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.max.s32 dst, src, membermask; -def int_nvvm_redux_sync_max : GCCBuiltin<"__nvvm_redux_sync_max">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.and.b32 dst, src, membermask; -def int_nvvm_redux_sync_and : GCCBuiltin<"__nvvm_redux_sync_and">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.xor.b32 dst, src, membermask; -def int_nvvm_redux_sync_xor : GCCBuiltin<"__nvvm_redux_sync_xor">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// redux.sync.or.b32 dst, src, membermask; -def int_nvvm_redux_sync_or : GCCBuiltin<"__nvvm_redux_sync_or">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrConvergent, IntrInaccessibleMemOnly]>; - -// -// WMMA instructions -// -// WMMA.LOAD -class NVVM_WMMA_LD - : Intrinsic>, NoCapture>], - WMMA_NAME_LDST<"load", Frag, Layout, WithStride>.intr>; - -// WMMA.STORE.D -class NVVM_WMMA_ST - : Intrinsic<[], - !listconcat( - [llvm_anyptr_ty], - Frag.regs, - !if(WithStride, [llvm_i32_ty], [])), - [IntrWriteMem, IntrArgMemOnly, WriteOnly>, NoCapture>], - WMMA_NAME_LDST<"store", Frag, Layout, WithStride>.intr>; - -// Create all load/store variants -foreach layout = ["row", "col"] in { - foreach stride = [0, 1] in { - foreach frag = NVVM_MMA_OPS.all_ld_ops in - if NVVM_WMMA_LDST_SUPPORTED.ret then - def WMMA_NAME_LDST<"load", frag, layout, stride>.record - : NVVM_WMMA_LD; - foreach frag = NVVM_MMA_OPS.all_st_ops in - if NVVM_WMMA_LDST_SUPPORTED.ret then - def WMMA_NAME_LDST<"store", frag, layout, stride>.record - : NVVM_WMMA_ST; - } -} - -// WMMA.MMA -class NVVM_WMMA_MMA - : Intrinsic.llvm>; - -foreach layout_a = ["row", "col"] in { - foreach layout_b = ["row", "col"] in { - foreach satf = [0, 1] in { - foreach rnd = ["", "rn", "rz", "rm", "rp"] in { - foreach op = NVVM_MMA_OPS.all_wmma_ops in { - foreach b1op = NVVM_MMA_B1OPS.ret in { - if NVVM_WMMA_SUPPORTED.ret then { - def WMMA_NAME.record - : NVVM_WMMA_MMA; - } - } // b1op - } // op - } // rnd - } // satf - } // layout_b -} // layout_a - -// MMA -class NVVM_MMA - : Intrinsic.llvm>; - -foreach layout_a = ["row", "col"] in { - foreach layout_b = ["row", "col"] in { - foreach satf = [0, 1] in { - foreach op = NVVM_MMA_OPS.all_mma_ops in { - foreach b1op = NVVM_MMA_B1OPS.ret in { - if NVVM_MMA_SUPPORTED.ret then { - def MMA_NAME.record - : NVVM_MMA; - } - } // b1op - } // op - } // satf - } // layout_b -} // layout_a - -// LDMATRIX -class NVVM_LDMATRIX - : Intrinsic>, - NoCapture>], - LDMATRIX_NAME.intr>; - -foreach transposed = [0, 1] in { - foreach frag = NVVM_MMA_OPS.all_ldmatrix_ops in { - if NVVM_LDMATRIX_SUPPORTED.ret then { - def LDMATRIX_NAME.record - : NVVM_LDMATRIX; - } - } -} - -} // let TargetPrefix = "nvvm" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.h deleted file mode 100644 index 2d0a4852f5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.h +++ /dev/null @@ -1,628 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_PPC_ENUMS_H -#define LLVM_IR_INTRINSIC_PPC_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum PPCIntrinsics : unsigned { -// Enum values for intrinsics - ppc_addex = 6619, // llvm.ppc.addex - ppc_addf128_round_to_odd, // llvm.ppc.addf128.round.to.odd - ppc_altivec_crypto_vcipher, // llvm.ppc.altivec.crypto.vcipher - ppc_altivec_crypto_vcipherlast, // llvm.ppc.altivec.crypto.vcipherlast - ppc_altivec_crypto_vncipher, // llvm.ppc.altivec.crypto.vncipher - ppc_altivec_crypto_vncipherlast, // llvm.ppc.altivec.crypto.vncipherlast - ppc_altivec_crypto_vpermxor, // llvm.ppc.altivec.crypto.vpermxor - ppc_altivec_crypto_vpermxor_be, // llvm.ppc.altivec.crypto.vpermxor.be - ppc_altivec_crypto_vpmsumb, // llvm.ppc.altivec.crypto.vpmsumb - ppc_altivec_crypto_vpmsumd, // llvm.ppc.altivec.crypto.vpmsumd - ppc_altivec_crypto_vpmsumh, // llvm.ppc.altivec.crypto.vpmsumh - ppc_altivec_crypto_vpmsumw, // llvm.ppc.altivec.crypto.vpmsumw - ppc_altivec_crypto_vsbox, // llvm.ppc.altivec.crypto.vsbox - ppc_altivec_crypto_vshasigmad, // llvm.ppc.altivec.crypto.vshasigmad - ppc_altivec_crypto_vshasigmaw, // llvm.ppc.altivec.crypto.vshasigmaw - ppc_altivec_dss, // llvm.ppc.altivec.dss - ppc_altivec_dssall, // llvm.ppc.altivec.dssall - ppc_altivec_dst, // llvm.ppc.altivec.dst - ppc_altivec_dstst, // llvm.ppc.altivec.dstst - ppc_altivec_dststt, // llvm.ppc.altivec.dststt - ppc_altivec_dstt, // llvm.ppc.altivec.dstt - ppc_altivec_lvebx, // llvm.ppc.altivec.lvebx - ppc_altivec_lvehx, // llvm.ppc.altivec.lvehx - ppc_altivec_lvewx, // llvm.ppc.altivec.lvewx - ppc_altivec_lvsl, // llvm.ppc.altivec.lvsl - ppc_altivec_lvsr, // llvm.ppc.altivec.lvsr - ppc_altivec_lvx, // llvm.ppc.altivec.lvx - ppc_altivec_lvxl, // llvm.ppc.altivec.lvxl - ppc_altivec_mfvscr, // llvm.ppc.altivec.mfvscr - ppc_altivec_mtvscr, // llvm.ppc.altivec.mtvscr - ppc_altivec_mtvsrbm, // llvm.ppc.altivec.mtvsrbm - ppc_altivec_mtvsrdm, // llvm.ppc.altivec.mtvsrdm - ppc_altivec_mtvsrhm, // llvm.ppc.altivec.mtvsrhm - ppc_altivec_mtvsrqm, // llvm.ppc.altivec.mtvsrqm - ppc_altivec_mtvsrwm, // llvm.ppc.altivec.mtvsrwm - ppc_altivec_stvebx, // llvm.ppc.altivec.stvebx - ppc_altivec_stvehx, // llvm.ppc.altivec.stvehx - ppc_altivec_stvewx, // llvm.ppc.altivec.stvewx - ppc_altivec_stvx, // llvm.ppc.altivec.stvx - ppc_altivec_stvxl, // llvm.ppc.altivec.stvxl - ppc_altivec_vabsdub, // llvm.ppc.altivec.vabsdub - ppc_altivec_vabsduh, // llvm.ppc.altivec.vabsduh - ppc_altivec_vabsduw, // llvm.ppc.altivec.vabsduw - ppc_altivec_vaddcuq, // llvm.ppc.altivec.vaddcuq - ppc_altivec_vaddcuw, // llvm.ppc.altivec.vaddcuw - ppc_altivec_vaddecuq, // llvm.ppc.altivec.vaddecuq - ppc_altivec_vaddeuqm, // llvm.ppc.altivec.vaddeuqm - ppc_altivec_vaddsbs, // llvm.ppc.altivec.vaddsbs - ppc_altivec_vaddshs, // llvm.ppc.altivec.vaddshs - ppc_altivec_vaddsws, // llvm.ppc.altivec.vaddsws - ppc_altivec_vaddubs, // llvm.ppc.altivec.vaddubs - ppc_altivec_vadduhs, // llvm.ppc.altivec.vadduhs - ppc_altivec_vadduws, // llvm.ppc.altivec.vadduws - ppc_altivec_vavgsb, // llvm.ppc.altivec.vavgsb - ppc_altivec_vavgsh, // llvm.ppc.altivec.vavgsh - ppc_altivec_vavgsw, // llvm.ppc.altivec.vavgsw - ppc_altivec_vavgub, // llvm.ppc.altivec.vavgub - ppc_altivec_vavguh, // llvm.ppc.altivec.vavguh - ppc_altivec_vavguw, // llvm.ppc.altivec.vavguw - ppc_altivec_vbpermd, // llvm.ppc.altivec.vbpermd - ppc_altivec_vbpermq, // llvm.ppc.altivec.vbpermq - ppc_altivec_vcfsx, // llvm.ppc.altivec.vcfsx - ppc_altivec_vcfuged, // llvm.ppc.altivec.vcfuged - ppc_altivec_vcfux, // llvm.ppc.altivec.vcfux - ppc_altivec_vclrlb, // llvm.ppc.altivec.vclrlb - ppc_altivec_vclrrb, // llvm.ppc.altivec.vclrrb - ppc_altivec_vclzdm, // llvm.ppc.altivec.vclzdm - ppc_altivec_vclzlsbb, // llvm.ppc.altivec.vclzlsbb - ppc_altivec_vcmpbfp, // llvm.ppc.altivec.vcmpbfp - ppc_altivec_vcmpbfp_p, // llvm.ppc.altivec.vcmpbfp.p - ppc_altivec_vcmpeqfp, // llvm.ppc.altivec.vcmpeqfp - ppc_altivec_vcmpeqfp_p, // llvm.ppc.altivec.vcmpeqfp.p - ppc_altivec_vcmpequb, // llvm.ppc.altivec.vcmpequb - ppc_altivec_vcmpequb_p, // llvm.ppc.altivec.vcmpequb.p - ppc_altivec_vcmpequd, // llvm.ppc.altivec.vcmpequd - ppc_altivec_vcmpequd_p, // llvm.ppc.altivec.vcmpequd.p - ppc_altivec_vcmpequh, // llvm.ppc.altivec.vcmpequh - ppc_altivec_vcmpequh_p, // llvm.ppc.altivec.vcmpequh.p - ppc_altivec_vcmpequq, // llvm.ppc.altivec.vcmpequq - ppc_altivec_vcmpequq_p, // llvm.ppc.altivec.vcmpequq.p - ppc_altivec_vcmpequw, // llvm.ppc.altivec.vcmpequw - ppc_altivec_vcmpequw_p, // llvm.ppc.altivec.vcmpequw.p - ppc_altivec_vcmpgefp, // llvm.ppc.altivec.vcmpgefp - ppc_altivec_vcmpgefp_p, // llvm.ppc.altivec.vcmpgefp.p - ppc_altivec_vcmpgtfp, // llvm.ppc.altivec.vcmpgtfp - ppc_altivec_vcmpgtfp_p, // llvm.ppc.altivec.vcmpgtfp.p - ppc_altivec_vcmpgtsb, // llvm.ppc.altivec.vcmpgtsb - ppc_altivec_vcmpgtsb_p, // llvm.ppc.altivec.vcmpgtsb.p - ppc_altivec_vcmpgtsd, // llvm.ppc.altivec.vcmpgtsd - ppc_altivec_vcmpgtsd_p, // llvm.ppc.altivec.vcmpgtsd.p - ppc_altivec_vcmpgtsh, // llvm.ppc.altivec.vcmpgtsh - ppc_altivec_vcmpgtsh_p, // llvm.ppc.altivec.vcmpgtsh.p - ppc_altivec_vcmpgtsq, // llvm.ppc.altivec.vcmpgtsq - ppc_altivec_vcmpgtsq_p, // llvm.ppc.altivec.vcmpgtsq.p - ppc_altivec_vcmpgtsw, // llvm.ppc.altivec.vcmpgtsw - ppc_altivec_vcmpgtsw_p, // llvm.ppc.altivec.vcmpgtsw.p - ppc_altivec_vcmpgtub, // llvm.ppc.altivec.vcmpgtub - ppc_altivec_vcmpgtub_p, // llvm.ppc.altivec.vcmpgtub.p - ppc_altivec_vcmpgtud, // llvm.ppc.altivec.vcmpgtud - ppc_altivec_vcmpgtud_p, // llvm.ppc.altivec.vcmpgtud.p - ppc_altivec_vcmpgtuh, // llvm.ppc.altivec.vcmpgtuh - ppc_altivec_vcmpgtuh_p, // llvm.ppc.altivec.vcmpgtuh.p - ppc_altivec_vcmpgtuq, // llvm.ppc.altivec.vcmpgtuq - ppc_altivec_vcmpgtuq_p, // llvm.ppc.altivec.vcmpgtuq.p - ppc_altivec_vcmpgtuw, // llvm.ppc.altivec.vcmpgtuw - ppc_altivec_vcmpgtuw_p, // llvm.ppc.altivec.vcmpgtuw.p - ppc_altivec_vcmpneb, // llvm.ppc.altivec.vcmpneb - ppc_altivec_vcmpneb_p, // llvm.ppc.altivec.vcmpneb.p - ppc_altivec_vcmpneh, // llvm.ppc.altivec.vcmpneh - ppc_altivec_vcmpneh_p, // llvm.ppc.altivec.vcmpneh.p - ppc_altivec_vcmpnew, // llvm.ppc.altivec.vcmpnew - ppc_altivec_vcmpnew_p, // llvm.ppc.altivec.vcmpnew.p - ppc_altivec_vcmpnezb, // llvm.ppc.altivec.vcmpnezb - ppc_altivec_vcmpnezb_p, // llvm.ppc.altivec.vcmpnezb.p - ppc_altivec_vcmpnezh, // llvm.ppc.altivec.vcmpnezh - ppc_altivec_vcmpnezh_p, // llvm.ppc.altivec.vcmpnezh.p - ppc_altivec_vcmpnezw, // llvm.ppc.altivec.vcmpnezw - ppc_altivec_vcmpnezw_p, // llvm.ppc.altivec.vcmpnezw.p - ppc_altivec_vcntmbb, // llvm.ppc.altivec.vcntmbb - ppc_altivec_vcntmbd, // llvm.ppc.altivec.vcntmbd - ppc_altivec_vcntmbh, // llvm.ppc.altivec.vcntmbh - ppc_altivec_vcntmbw, // llvm.ppc.altivec.vcntmbw - ppc_altivec_vctsxs, // llvm.ppc.altivec.vctsxs - ppc_altivec_vctuxs, // llvm.ppc.altivec.vctuxs - ppc_altivec_vctzdm, // llvm.ppc.altivec.vctzdm - ppc_altivec_vctzlsbb, // llvm.ppc.altivec.vctzlsbb - ppc_altivec_vdivesd, // llvm.ppc.altivec.vdivesd - ppc_altivec_vdivesq, // llvm.ppc.altivec.vdivesq - ppc_altivec_vdivesw, // llvm.ppc.altivec.vdivesw - ppc_altivec_vdiveud, // llvm.ppc.altivec.vdiveud - ppc_altivec_vdiveuq, // llvm.ppc.altivec.vdiveuq - ppc_altivec_vdiveuw, // llvm.ppc.altivec.vdiveuw - ppc_altivec_vexpandbm, // llvm.ppc.altivec.vexpandbm - ppc_altivec_vexpanddm, // llvm.ppc.altivec.vexpanddm - ppc_altivec_vexpandhm, // llvm.ppc.altivec.vexpandhm - ppc_altivec_vexpandqm, // llvm.ppc.altivec.vexpandqm - ppc_altivec_vexpandwm, // llvm.ppc.altivec.vexpandwm - ppc_altivec_vexptefp, // llvm.ppc.altivec.vexptefp - ppc_altivec_vextddvlx, // llvm.ppc.altivec.vextddvlx - ppc_altivec_vextddvrx, // llvm.ppc.altivec.vextddvrx - ppc_altivec_vextdubvlx, // llvm.ppc.altivec.vextdubvlx - ppc_altivec_vextdubvrx, // llvm.ppc.altivec.vextdubvrx - ppc_altivec_vextduhvlx, // llvm.ppc.altivec.vextduhvlx - ppc_altivec_vextduhvrx, // llvm.ppc.altivec.vextduhvrx - ppc_altivec_vextduwvlx, // llvm.ppc.altivec.vextduwvlx - ppc_altivec_vextduwvrx, // llvm.ppc.altivec.vextduwvrx - ppc_altivec_vextractbm, // llvm.ppc.altivec.vextractbm - ppc_altivec_vextractdm, // llvm.ppc.altivec.vextractdm - ppc_altivec_vextracthm, // llvm.ppc.altivec.vextracthm - ppc_altivec_vextractqm, // llvm.ppc.altivec.vextractqm - ppc_altivec_vextractwm, // llvm.ppc.altivec.vextractwm - ppc_altivec_vextsb2d, // llvm.ppc.altivec.vextsb2d - ppc_altivec_vextsb2w, // llvm.ppc.altivec.vextsb2w - ppc_altivec_vextsd2q, // llvm.ppc.altivec.vextsd2q - ppc_altivec_vextsh2d, // llvm.ppc.altivec.vextsh2d - ppc_altivec_vextsh2w, // llvm.ppc.altivec.vextsh2w - ppc_altivec_vextsw2d, // llvm.ppc.altivec.vextsw2d - ppc_altivec_vgbbd, // llvm.ppc.altivec.vgbbd - ppc_altivec_vgnb, // llvm.ppc.altivec.vgnb - ppc_altivec_vinsblx, // llvm.ppc.altivec.vinsblx - ppc_altivec_vinsbrx, // llvm.ppc.altivec.vinsbrx - ppc_altivec_vinsbvlx, // llvm.ppc.altivec.vinsbvlx - ppc_altivec_vinsbvrx, // llvm.ppc.altivec.vinsbvrx - ppc_altivec_vinsd, // llvm.ppc.altivec.vinsd - ppc_altivec_vinsdlx, // llvm.ppc.altivec.vinsdlx - ppc_altivec_vinsdrx, // llvm.ppc.altivec.vinsdrx - ppc_altivec_vinshlx, // llvm.ppc.altivec.vinshlx - ppc_altivec_vinshrx, // llvm.ppc.altivec.vinshrx - ppc_altivec_vinshvlx, // llvm.ppc.altivec.vinshvlx - ppc_altivec_vinshvrx, // llvm.ppc.altivec.vinshvrx - ppc_altivec_vinsw, // llvm.ppc.altivec.vinsw - ppc_altivec_vinswlx, // llvm.ppc.altivec.vinswlx - ppc_altivec_vinswrx, // llvm.ppc.altivec.vinswrx - ppc_altivec_vinswvlx, // llvm.ppc.altivec.vinswvlx - ppc_altivec_vinswvrx, // llvm.ppc.altivec.vinswvrx - ppc_altivec_vlogefp, // llvm.ppc.altivec.vlogefp - ppc_altivec_vmaddfp, // llvm.ppc.altivec.vmaddfp - ppc_altivec_vmaxfp, // llvm.ppc.altivec.vmaxfp - ppc_altivec_vmaxsb, // llvm.ppc.altivec.vmaxsb - ppc_altivec_vmaxsd, // llvm.ppc.altivec.vmaxsd - ppc_altivec_vmaxsh, // llvm.ppc.altivec.vmaxsh - ppc_altivec_vmaxsw, // llvm.ppc.altivec.vmaxsw - ppc_altivec_vmaxub, // llvm.ppc.altivec.vmaxub - ppc_altivec_vmaxud, // llvm.ppc.altivec.vmaxud - ppc_altivec_vmaxuh, // llvm.ppc.altivec.vmaxuh - ppc_altivec_vmaxuw, // llvm.ppc.altivec.vmaxuw - ppc_altivec_vmhaddshs, // llvm.ppc.altivec.vmhaddshs - ppc_altivec_vmhraddshs, // llvm.ppc.altivec.vmhraddshs - ppc_altivec_vminfp, // llvm.ppc.altivec.vminfp - ppc_altivec_vminsb, // llvm.ppc.altivec.vminsb - ppc_altivec_vminsd, // llvm.ppc.altivec.vminsd - ppc_altivec_vminsh, // llvm.ppc.altivec.vminsh - ppc_altivec_vminsw, // llvm.ppc.altivec.vminsw - ppc_altivec_vminub, // llvm.ppc.altivec.vminub - ppc_altivec_vminud, // llvm.ppc.altivec.vminud - ppc_altivec_vminuh, // llvm.ppc.altivec.vminuh - ppc_altivec_vminuw, // llvm.ppc.altivec.vminuw - ppc_altivec_vmladduhm, // llvm.ppc.altivec.vmladduhm - ppc_altivec_vmsumcud, // llvm.ppc.altivec.vmsumcud - ppc_altivec_vmsummbm, // llvm.ppc.altivec.vmsummbm - ppc_altivec_vmsumshm, // llvm.ppc.altivec.vmsumshm - ppc_altivec_vmsumshs, // llvm.ppc.altivec.vmsumshs - ppc_altivec_vmsumubm, // llvm.ppc.altivec.vmsumubm - ppc_altivec_vmsumudm, // llvm.ppc.altivec.vmsumudm - ppc_altivec_vmsumuhm, // llvm.ppc.altivec.vmsumuhm - ppc_altivec_vmsumuhs, // llvm.ppc.altivec.vmsumuhs - ppc_altivec_vmulesb, // llvm.ppc.altivec.vmulesb - ppc_altivec_vmulesd, // llvm.ppc.altivec.vmulesd - ppc_altivec_vmulesh, // llvm.ppc.altivec.vmulesh - ppc_altivec_vmulesw, // llvm.ppc.altivec.vmulesw - ppc_altivec_vmuleub, // llvm.ppc.altivec.vmuleub - ppc_altivec_vmuleud, // llvm.ppc.altivec.vmuleud - ppc_altivec_vmuleuh, // llvm.ppc.altivec.vmuleuh - ppc_altivec_vmuleuw, // llvm.ppc.altivec.vmuleuw - ppc_altivec_vmulhsd, // llvm.ppc.altivec.vmulhsd - ppc_altivec_vmulhsw, // llvm.ppc.altivec.vmulhsw - ppc_altivec_vmulhud, // llvm.ppc.altivec.vmulhud - ppc_altivec_vmulhuw, // llvm.ppc.altivec.vmulhuw - ppc_altivec_vmulosb, // llvm.ppc.altivec.vmulosb - ppc_altivec_vmulosd, // llvm.ppc.altivec.vmulosd - ppc_altivec_vmulosh, // llvm.ppc.altivec.vmulosh - ppc_altivec_vmulosw, // llvm.ppc.altivec.vmulosw - ppc_altivec_vmuloub, // llvm.ppc.altivec.vmuloub - ppc_altivec_vmuloud, // llvm.ppc.altivec.vmuloud - ppc_altivec_vmulouh, // llvm.ppc.altivec.vmulouh - ppc_altivec_vmulouw, // llvm.ppc.altivec.vmulouw - ppc_altivec_vnmsubfp, // llvm.ppc.altivec.vnmsubfp - ppc_altivec_vpdepd, // llvm.ppc.altivec.vpdepd - ppc_altivec_vperm, // llvm.ppc.altivec.vperm - ppc_altivec_vpextd, // llvm.ppc.altivec.vpextd - ppc_altivec_vpkpx, // llvm.ppc.altivec.vpkpx - ppc_altivec_vpksdss, // llvm.ppc.altivec.vpksdss - ppc_altivec_vpksdus, // llvm.ppc.altivec.vpksdus - ppc_altivec_vpkshss, // llvm.ppc.altivec.vpkshss - ppc_altivec_vpkshus, // llvm.ppc.altivec.vpkshus - ppc_altivec_vpkswss, // llvm.ppc.altivec.vpkswss - ppc_altivec_vpkswus, // llvm.ppc.altivec.vpkswus - ppc_altivec_vpkudus, // llvm.ppc.altivec.vpkudus - ppc_altivec_vpkuhus, // llvm.ppc.altivec.vpkuhus - ppc_altivec_vpkuwus, // llvm.ppc.altivec.vpkuwus - ppc_altivec_vprtybd, // llvm.ppc.altivec.vprtybd - ppc_altivec_vprtybq, // llvm.ppc.altivec.vprtybq - ppc_altivec_vprtybw, // llvm.ppc.altivec.vprtybw - ppc_altivec_vrefp, // llvm.ppc.altivec.vrefp - ppc_altivec_vrfim, // llvm.ppc.altivec.vrfim - ppc_altivec_vrfin, // llvm.ppc.altivec.vrfin - ppc_altivec_vrfip, // llvm.ppc.altivec.vrfip - ppc_altivec_vrfiz, // llvm.ppc.altivec.vrfiz - ppc_altivec_vrlb, // llvm.ppc.altivec.vrlb - ppc_altivec_vrld, // llvm.ppc.altivec.vrld - ppc_altivec_vrldmi, // llvm.ppc.altivec.vrldmi - ppc_altivec_vrldnm, // llvm.ppc.altivec.vrldnm - ppc_altivec_vrlh, // llvm.ppc.altivec.vrlh - ppc_altivec_vrlqmi, // llvm.ppc.altivec.vrlqmi - ppc_altivec_vrlqnm, // llvm.ppc.altivec.vrlqnm - ppc_altivec_vrlw, // llvm.ppc.altivec.vrlw - ppc_altivec_vrlwmi, // llvm.ppc.altivec.vrlwmi - ppc_altivec_vrlwnm, // llvm.ppc.altivec.vrlwnm - ppc_altivec_vrsqrtefp, // llvm.ppc.altivec.vrsqrtefp - ppc_altivec_vsel, // llvm.ppc.altivec.vsel - ppc_altivec_vsl, // llvm.ppc.altivec.vsl - ppc_altivec_vslb, // llvm.ppc.altivec.vslb - ppc_altivec_vsldbi, // llvm.ppc.altivec.vsldbi - ppc_altivec_vslh, // llvm.ppc.altivec.vslh - ppc_altivec_vslo, // llvm.ppc.altivec.vslo - ppc_altivec_vslv, // llvm.ppc.altivec.vslv - ppc_altivec_vslw, // llvm.ppc.altivec.vslw - ppc_altivec_vsr, // llvm.ppc.altivec.vsr - ppc_altivec_vsrab, // llvm.ppc.altivec.vsrab - ppc_altivec_vsrah, // llvm.ppc.altivec.vsrah - ppc_altivec_vsraw, // llvm.ppc.altivec.vsraw - ppc_altivec_vsrb, // llvm.ppc.altivec.vsrb - ppc_altivec_vsrdbi, // llvm.ppc.altivec.vsrdbi - ppc_altivec_vsrh, // llvm.ppc.altivec.vsrh - ppc_altivec_vsro, // llvm.ppc.altivec.vsro - ppc_altivec_vsrv, // llvm.ppc.altivec.vsrv - ppc_altivec_vsrw, // llvm.ppc.altivec.vsrw - ppc_altivec_vstribl, // llvm.ppc.altivec.vstribl - ppc_altivec_vstribl_p, // llvm.ppc.altivec.vstribl.p - ppc_altivec_vstribr, // llvm.ppc.altivec.vstribr - ppc_altivec_vstribr_p, // llvm.ppc.altivec.vstribr.p - ppc_altivec_vstrihl, // llvm.ppc.altivec.vstrihl - ppc_altivec_vstrihl_p, // llvm.ppc.altivec.vstrihl.p - ppc_altivec_vstrihr, // llvm.ppc.altivec.vstrihr - ppc_altivec_vstrihr_p, // llvm.ppc.altivec.vstrihr.p - ppc_altivec_vsubcuq, // llvm.ppc.altivec.vsubcuq - ppc_altivec_vsubcuw, // llvm.ppc.altivec.vsubcuw - ppc_altivec_vsubecuq, // llvm.ppc.altivec.vsubecuq - ppc_altivec_vsubeuqm, // llvm.ppc.altivec.vsubeuqm - ppc_altivec_vsubsbs, // llvm.ppc.altivec.vsubsbs - ppc_altivec_vsubshs, // llvm.ppc.altivec.vsubshs - ppc_altivec_vsubsws, // llvm.ppc.altivec.vsubsws - ppc_altivec_vsububs, // llvm.ppc.altivec.vsububs - ppc_altivec_vsubuhs, // llvm.ppc.altivec.vsubuhs - ppc_altivec_vsubuws, // llvm.ppc.altivec.vsubuws - ppc_altivec_vsum2sws, // llvm.ppc.altivec.vsum2sws - ppc_altivec_vsum4sbs, // llvm.ppc.altivec.vsum4sbs - ppc_altivec_vsum4shs, // llvm.ppc.altivec.vsum4shs - ppc_altivec_vsum4ubs, // llvm.ppc.altivec.vsum4ubs - ppc_altivec_vsumsws, // llvm.ppc.altivec.vsumsws - ppc_altivec_vupkhpx, // llvm.ppc.altivec.vupkhpx - ppc_altivec_vupkhsb, // llvm.ppc.altivec.vupkhsb - ppc_altivec_vupkhsh, // llvm.ppc.altivec.vupkhsh - ppc_altivec_vupkhsw, // llvm.ppc.altivec.vupkhsw - ppc_altivec_vupklpx, // llvm.ppc.altivec.vupklpx - ppc_altivec_vupklsb, // llvm.ppc.altivec.vupklsb - ppc_altivec_vupklsh, // llvm.ppc.altivec.vupklsh - ppc_altivec_vupklsw, // llvm.ppc.altivec.vupklsw - ppc_atomic_load_i128, // llvm.ppc.atomic.load.i128 - ppc_atomic_store_i128, // llvm.ppc.atomic.store.i128 - ppc_atomicrmw_add_i128, // llvm.ppc.atomicrmw.add.i128 - ppc_atomicrmw_and_i128, // llvm.ppc.atomicrmw.and.i128 - ppc_atomicrmw_nand_i128, // llvm.ppc.atomicrmw.nand.i128 - ppc_atomicrmw_or_i128, // llvm.ppc.atomicrmw.or.i128 - ppc_atomicrmw_sub_i128, // llvm.ppc.atomicrmw.sub.i128 - ppc_atomicrmw_xchg_i128, // llvm.ppc.atomicrmw.xchg.i128 - ppc_atomicrmw_xor_i128, // llvm.ppc.atomicrmw.xor.i128 - ppc_bcdadd, // llvm.ppc.bcdadd - ppc_bcdadd_p, // llvm.ppc.bcdadd.p - ppc_bcdsub, // llvm.ppc.bcdsub - ppc_bcdsub_p, // llvm.ppc.bcdsub.p - ppc_bpermd, // llvm.ppc.bpermd - ppc_cfence, // llvm.ppc.cfence - ppc_cfuged, // llvm.ppc.cfuged - ppc_cmpb, // llvm.ppc.cmpb - ppc_cmpeqb, // llvm.ppc.cmpeqb - ppc_cmprb, // llvm.ppc.cmprb - ppc_cmpxchg_i128, // llvm.ppc.cmpxchg.i128 - ppc_cntlzdm, // llvm.ppc.cntlzdm - ppc_cnttzdm, // llvm.ppc.cnttzdm - ppc_compare_exp_eq, // llvm.ppc.compare.exp.eq - ppc_compare_exp_gt, // llvm.ppc.compare.exp.gt - ppc_compare_exp_lt, // llvm.ppc.compare.exp.lt - ppc_compare_exp_uo, // llvm.ppc.compare.exp.uo - ppc_convert_f128_to_ppcf128, // llvm.ppc.convert.f128.to.ppcf128 - ppc_convert_ppcf128_to_f128, // llvm.ppc.convert.ppcf128.to.f128 - ppc_darn, // llvm.ppc.darn - ppc_darn32, // llvm.ppc.darn32 - ppc_darnraw, // llvm.ppc.darnraw - ppc_dcba, // llvm.ppc.dcba - ppc_dcbf, // llvm.ppc.dcbf - ppc_dcbfl, // llvm.ppc.dcbfl - ppc_dcbflp, // llvm.ppc.dcbflp - ppc_dcbfps, // llvm.ppc.dcbfps - ppc_dcbi, // llvm.ppc.dcbi - ppc_dcbst, // llvm.ppc.dcbst - ppc_dcbstps, // llvm.ppc.dcbstps - ppc_dcbt, // llvm.ppc.dcbt - ppc_dcbt_with_hint, // llvm.ppc.dcbt.with.hint - ppc_dcbtst, // llvm.ppc.dcbtst - ppc_dcbtst_with_hint, // llvm.ppc.dcbtst.with.hint - ppc_dcbtstt, // llvm.ppc.dcbtstt - ppc_dcbtt, // llvm.ppc.dcbtt - ppc_dcbz, // llvm.ppc.dcbz - ppc_dcbzl, // llvm.ppc.dcbzl - ppc_divde, // llvm.ppc.divde - ppc_divdeu, // llvm.ppc.divdeu - ppc_divf128_round_to_odd, // llvm.ppc.divf128.round.to.odd - ppc_divwe, // llvm.ppc.divwe - ppc_divweu, // llvm.ppc.divweu - ppc_eieio, // llvm.ppc.eieio - ppc_extract_exp, // llvm.ppc.extract.exp - ppc_extract_sig, // llvm.ppc.extract.sig - ppc_fcfid, // llvm.ppc.fcfid - ppc_fcfud, // llvm.ppc.fcfud - ppc_fctid, // llvm.ppc.fctid - ppc_fctidz, // llvm.ppc.fctidz - ppc_fctiw, // llvm.ppc.fctiw - ppc_fctiwz, // llvm.ppc.fctiwz - ppc_fctudz, // llvm.ppc.fctudz - ppc_fctuwz, // llvm.ppc.fctuwz - ppc_fmaf128_round_to_odd, // llvm.ppc.fmaf128.round.to.odd - ppc_fmsub, // llvm.ppc.fmsub - ppc_fmsubs, // llvm.ppc.fmsubs - ppc_fnmadd, // llvm.ppc.fnmadd - ppc_fnmadds, // llvm.ppc.fnmadds - ppc_fnmsub, // llvm.ppc.fnmsub - ppc_fnmsubs, // llvm.ppc.fnmsubs - ppc_fre, // llvm.ppc.fre - ppc_fres, // llvm.ppc.fres - ppc_frsqrte, // llvm.ppc.frsqrte - ppc_frsqrtes, // llvm.ppc.frsqrtes - ppc_fsel, // llvm.ppc.fsel - ppc_fsels, // llvm.ppc.fsels - ppc_get_texasr, // llvm.ppc.get.texasr - ppc_get_texasru, // llvm.ppc.get.texasru - ppc_get_tfhar, // llvm.ppc.get.tfhar - ppc_get_tfiar, // llvm.ppc.get.tfiar - ppc_icbt, // llvm.ppc.icbt - ppc_insert_exp, // llvm.ppc.insert.exp - ppc_iospace_eieio, // llvm.ppc.iospace.eieio - ppc_iospace_lwsync, // llvm.ppc.iospace.lwsync - ppc_iospace_sync, // llvm.ppc.iospace.sync - ppc_isync, // llvm.ppc.isync - ppc_load2r, // llvm.ppc.load2r - ppc_load4r, // llvm.ppc.load4r - ppc_load8r, // llvm.ppc.load8r - ppc_lwsync, // llvm.ppc.lwsync - ppc_maddhd, // llvm.ppc.maddhd - ppc_maddhdu, // llvm.ppc.maddhdu - ppc_maddld, // llvm.ppc.maddld - ppc_mfmsr, // llvm.ppc.mfmsr - ppc_mfspr, // llvm.ppc.mfspr - ppc_mftbu, // llvm.ppc.mftbu - ppc_mma_assemble_acc, // llvm.ppc.mma.assemble.acc - ppc_mma_disassemble_acc, // llvm.ppc.mma.disassemble.acc - ppc_mma_pmxvbf16ger2, // llvm.ppc.mma.pmxvbf16ger2 - ppc_mma_pmxvbf16ger2nn, // llvm.ppc.mma.pmxvbf16ger2nn - ppc_mma_pmxvbf16ger2np, // llvm.ppc.mma.pmxvbf16ger2np - ppc_mma_pmxvbf16ger2pn, // llvm.ppc.mma.pmxvbf16ger2pn - ppc_mma_pmxvbf16ger2pp, // llvm.ppc.mma.pmxvbf16ger2pp - ppc_mma_pmxvf16ger2, // llvm.ppc.mma.pmxvf16ger2 - ppc_mma_pmxvf16ger2nn, // llvm.ppc.mma.pmxvf16ger2nn - ppc_mma_pmxvf16ger2np, // llvm.ppc.mma.pmxvf16ger2np - ppc_mma_pmxvf16ger2pn, // llvm.ppc.mma.pmxvf16ger2pn - ppc_mma_pmxvf16ger2pp, // llvm.ppc.mma.pmxvf16ger2pp - ppc_mma_pmxvf32ger, // llvm.ppc.mma.pmxvf32ger - ppc_mma_pmxvf32gernn, // llvm.ppc.mma.pmxvf32gernn - ppc_mma_pmxvf32gernp, // llvm.ppc.mma.pmxvf32gernp - ppc_mma_pmxvf32gerpn, // llvm.ppc.mma.pmxvf32gerpn - ppc_mma_pmxvf32gerpp, // llvm.ppc.mma.pmxvf32gerpp - ppc_mma_pmxvf64ger, // llvm.ppc.mma.pmxvf64ger - ppc_mma_pmxvf64gernn, // llvm.ppc.mma.pmxvf64gernn - ppc_mma_pmxvf64gernp, // llvm.ppc.mma.pmxvf64gernp - ppc_mma_pmxvf64gerpn, // llvm.ppc.mma.pmxvf64gerpn - ppc_mma_pmxvf64gerpp, // llvm.ppc.mma.pmxvf64gerpp - ppc_mma_pmxvi16ger2, // llvm.ppc.mma.pmxvi16ger2 - ppc_mma_pmxvi16ger2pp, // llvm.ppc.mma.pmxvi16ger2pp - ppc_mma_pmxvi16ger2s, // llvm.ppc.mma.pmxvi16ger2s - ppc_mma_pmxvi16ger2spp, // llvm.ppc.mma.pmxvi16ger2spp - ppc_mma_pmxvi4ger8, // llvm.ppc.mma.pmxvi4ger8 - ppc_mma_pmxvi4ger8pp, // llvm.ppc.mma.pmxvi4ger8pp - ppc_mma_pmxvi8ger4, // llvm.ppc.mma.pmxvi8ger4 - ppc_mma_pmxvi8ger4pp, // llvm.ppc.mma.pmxvi8ger4pp - ppc_mma_pmxvi8ger4spp, // llvm.ppc.mma.pmxvi8ger4spp - ppc_mma_xvbf16ger2, // llvm.ppc.mma.xvbf16ger2 - ppc_mma_xvbf16ger2nn, // llvm.ppc.mma.xvbf16ger2nn - ppc_mma_xvbf16ger2np, // llvm.ppc.mma.xvbf16ger2np - ppc_mma_xvbf16ger2pn, // llvm.ppc.mma.xvbf16ger2pn - ppc_mma_xvbf16ger2pp, // llvm.ppc.mma.xvbf16ger2pp - ppc_mma_xvf16ger2, // llvm.ppc.mma.xvf16ger2 - ppc_mma_xvf16ger2nn, // llvm.ppc.mma.xvf16ger2nn - ppc_mma_xvf16ger2np, // llvm.ppc.mma.xvf16ger2np - ppc_mma_xvf16ger2pn, // llvm.ppc.mma.xvf16ger2pn - ppc_mma_xvf16ger2pp, // llvm.ppc.mma.xvf16ger2pp - ppc_mma_xvf32ger, // llvm.ppc.mma.xvf32ger - ppc_mma_xvf32gernn, // llvm.ppc.mma.xvf32gernn - ppc_mma_xvf32gernp, // llvm.ppc.mma.xvf32gernp - ppc_mma_xvf32gerpn, // llvm.ppc.mma.xvf32gerpn - ppc_mma_xvf32gerpp, // llvm.ppc.mma.xvf32gerpp - ppc_mma_xvf64ger, // llvm.ppc.mma.xvf64ger - ppc_mma_xvf64gernn, // llvm.ppc.mma.xvf64gernn - ppc_mma_xvf64gernp, // llvm.ppc.mma.xvf64gernp - ppc_mma_xvf64gerpn, // llvm.ppc.mma.xvf64gerpn - ppc_mma_xvf64gerpp, // llvm.ppc.mma.xvf64gerpp - ppc_mma_xvi16ger2, // llvm.ppc.mma.xvi16ger2 - ppc_mma_xvi16ger2pp, // llvm.ppc.mma.xvi16ger2pp - ppc_mma_xvi16ger2s, // llvm.ppc.mma.xvi16ger2s - ppc_mma_xvi16ger2spp, // llvm.ppc.mma.xvi16ger2spp - ppc_mma_xvi4ger8, // llvm.ppc.mma.xvi4ger8 - ppc_mma_xvi4ger8pp, // llvm.ppc.mma.xvi4ger8pp - ppc_mma_xvi8ger4, // llvm.ppc.mma.xvi8ger4 - ppc_mma_xvi8ger4pp, // llvm.ppc.mma.xvi8ger4pp - ppc_mma_xvi8ger4spp, // llvm.ppc.mma.xvi8ger4spp - ppc_mma_xxmfacc, // llvm.ppc.mma.xxmfacc - ppc_mma_xxmtacc, // llvm.ppc.mma.xxmtacc - ppc_mma_xxsetaccz, // llvm.ppc.mma.xxsetaccz - ppc_mtfsb0, // llvm.ppc.mtfsb0 - ppc_mtfsb1, // llvm.ppc.mtfsb1 - ppc_mtfsf, // llvm.ppc.mtfsf - ppc_mtfsfi, // llvm.ppc.mtfsfi - ppc_mtmsr, // llvm.ppc.mtmsr - ppc_mtspr, // llvm.ppc.mtspr - ppc_mulf128_round_to_odd, // llvm.ppc.mulf128.round.to.odd - ppc_mulhd, // llvm.ppc.mulhd - ppc_mulhdu, // llvm.ppc.mulhdu - ppc_mulhw, // llvm.ppc.mulhw - ppc_mulhwu, // llvm.ppc.mulhwu - ppc_pack_longdouble, // llvm.ppc.pack.longdouble - ppc_pdepd, // llvm.ppc.pdepd - ppc_pextd, // llvm.ppc.pextd - ppc_popcntb, // llvm.ppc.popcntb - ppc_readflm, // llvm.ppc.readflm - ppc_scalar_extract_expq, // llvm.ppc.scalar.extract.expq - ppc_scalar_insert_exp_qp, // llvm.ppc.scalar.insert.exp.qp - ppc_set_texasr, // llvm.ppc.set.texasr - ppc_set_texasru, // llvm.ppc.set.texasru - ppc_set_tfhar, // llvm.ppc.set.tfhar - ppc_set_tfiar, // llvm.ppc.set.tfiar - ppc_setb, // llvm.ppc.setb - ppc_setflm, // llvm.ppc.setflm - ppc_setrnd, // llvm.ppc.setrnd - ppc_sqrtf128_round_to_odd, // llvm.ppc.sqrtf128.round.to.odd - ppc_stbcx, // llvm.ppc.stbcx - ppc_stdcx, // llvm.ppc.stdcx - ppc_stfiw, // llvm.ppc.stfiw - ppc_sthcx, // llvm.ppc.sthcx - ppc_store2r, // llvm.ppc.store2r - ppc_store4r, // llvm.ppc.store4r - ppc_store8r, // llvm.ppc.store8r - ppc_stwcx, // llvm.ppc.stwcx - ppc_subf128_round_to_odd, // llvm.ppc.subf128.round.to.odd - ppc_sync, // llvm.ppc.sync - ppc_tabort, // llvm.ppc.tabort - ppc_tabortdc, // llvm.ppc.tabortdc - ppc_tabortdci, // llvm.ppc.tabortdci - ppc_tabortwc, // llvm.ppc.tabortwc - ppc_tabortwci, // llvm.ppc.tabortwci - ppc_tbegin, // llvm.ppc.tbegin - ppc_tcheck, // llvm.ppc.tcheck - ppc_tdw, // llvm.ppc.tdw - ppc_tend, // llvm.ppc.tend - ppc_tendall, // llvm.ppc.tendall - ppc_test_data_class_d, // llvm.ppc.test.data.class.d - ppc_test_data_class_f, // llvm.ppc.test.data.class.f - ppc_trap, // llvm.ppc.trap - ppc_trapd, // llvm.ppc.trapd - ppc_trechkpt, // llvm.ppc.trechkpt - ppc_treclaim, // llvm.ppc.treclaim - ppc_tresume, // llvm.ppc.tresume - ppc_truncf128_round_to_odd, // llvm.ppc.truncf128.round.to.odd - ppc_tsr, // llvm.ppc.tsr - ppc_tsuspend, // llvm.ppc.tsuspend - ppc_ttest, // llvm.ppc.ttest - ppc_tw, // llvm.ppc.tw - ppc_unpack_longdouble, // llvm.ppc.unpack.longdouble - ppc_vsx_assemble_pair, // llvm.ppc.vsx.assemble.pair - ppc_vsx_disassemble_pair, // llvm.ppc.vsx.disassemble.pair - ppc_vsx_lxvd2x, // llvm.ppc.vsx.lxvd2x - ppc_vsx_lxvd2x_be, // llvm.ppc.vsx.lxvd2x.be - ppc_vsx_lxvl, // llvm.ppc.vsx.lxvl - ppc_vsx_lxvll, // llvm.ppc.vsx.lxvll - ppc_vsx_lxvp, // llvm.ppc.vsx.lxvp - ppc_vsx_lxvw4x, // llvm.ppc.vsx.lxvw4x - ppc_vsx_lxvw4x_be, // llvm.ppc.vsx.lxvw4x.be - ppc_vsx_stxvd2x, // llvm.ppc.vsx.stxvd2x - ppc_vsx_stxvd2x_be, // llvm.ppc.vsx.stxvd2x.be - ppc_vsx_stxvl, // llvm.ppc.vsx.stxvl - ppc_vsx_stxvll, // llvm.ppc.vsx.stxvll - ppc_vsx_stxvp, // llvm.ppc.vsx.stxvp - ppc_vsx_stxvw4x, // llvm.ppc.vsx.stxvw4x - ppc_vsx_stxvw4x_be, // llvm.ppc.vsx.stxvw4x.be - ppc_vsx_xsmaxdp, // llvm.ppc.vsx.xsmaxdp - ppc_vsx_xsmindp, // llvm.ppc.vsx.xsmindp - ppc_vsx_xvcmpeqdp, // llvm.ppc.vsx.xvcmpeqdp - ppc_vsx_xvcmpeqdp_p, // llvm.ppc.vsx.xvcmpeqdp.p - ppc_vsx_xvcmpeqsp, // llvm.ppc.vsx.xvcmpeqsp - ppc_vsx_xvcmpeqsp_p, // llvm.ppc.vsx.xvcmpeqsp.p - ppc_vsx_xvcmpgedp, // llvm.ppc.vsx.xvcmpgedp - ppc_vsx_xvcmpgedp_p, // llvm.ppc.vsx.xvcmpgedp.p - ppc_vsx_xvcmpgesp, // llvm.ppc.vsx.xvcmpgesp - ppc_vsx_xvcmpgesp_p, // llvm.ppc.vsx.xvcmpgesp.p - ppc_vsx_xvcmpgtdp, // llvm.ppc.vsx.xvcmpgtdp - ppc_vsx_xvcmpgtdp_p, // llvm.ppc.vsx.xvcmpgtdp.p - ppc_vsx_xvcmpgtsp, // llvm.ppc.vsx.xvcmpgtsp - ppc_vsx_xvcmpgtsp_p, // llvm.ppc.vsx.xvcmpgtsp.p - ppc_vsx_xvcvbf16spn, // llvm.ppc.vsx.xvcvbf16spn - ppc_vsx_xvcvdpsp, // llvm.ppc.vsx.xvcvdpsp - ppc_vsx_xvcvdpsxws, // llvm.ppc.vsx.xvcvdpsxws - ppc_vsx_xvcvdpuxws, // llvm.ppc.vsx.xvcvdpuxws - ppc_vsx_xvcvhpsp, // llvm.ppc.vsx.xvcvhpsp - ppc_vsx_xvcvspbf16, // llvm.ppc.vsx.xvcvspbf16 - ppc_vsx_xvcvspdp, // llvm.ppc.vsx.xvcvspdp - ppc_vsx_xvcvsphp, // llvm.ppc.vsx.xvcvsphp - ppc_vsx_xvcvspsxds, // llvm.ppc.vsx.xvcvspsxds - ppc_vsx_xvcvspuxds, // llvm.ppc.vsx.xvcvspuxds - ppc_vsx_xvcvsxdsp, // llvm.ppc.vsx.xvcvsxdsp - ppc_vsx_xvcvsxwdp, // llvm.ppc.vsx.xvcvsxwdp - ppc_vsx_xvcvuxdsp, // llvm.ppc.vsx.xvcvuxdsp - ppc_vsx_xvcvuxwdp, // llvm.ppc.vsx.xvcvuxwdp - ppc_vsx_xvdivdp, // llvm.ppc.vsx.xvdivdp - ppc_vsx_xvdivsp, // llvm.ppc.vsx.xvdivsp - ppc_vsx_xviexpdp, // llvm.ppc.vsx.xviexpdp - ppc_vsx_xviexpsp, // llvm.ppc.vsx.xviexpsp - ppc_vsx_xvmaxdp, // llvm.ppc.vsx.xvmaxdp - ppc_vsx_xvmaxsp, // llvm.ppc.vsx.xvmaxsp - ppc_vsx_xvmindp, // llvm.ppc.vsx.xvmindp - ppc_vsx_xvminsp, // llvm.ppc.vsx.xvminsp - ppc_vsx_xvrdpip, // llvm.ppc.vsx.xvrdpip - ppc_vsx_xvredp, // llvm.ppc.vsx.xvredp - ppc_vsx_xvresp, // llvm.ppc.vsx.xvresp - ppc_vsx_xvrspip, // llvm.ppc.vsx.xvrspip - ppc_vsx_xvrsqrtedp, // llvm.ppc.vsx.xvrsqrtedp - ppc_vsx_xvrsqrtesp, // llvm.ppc.vsx.xvrsqrtesp - ppc_vsx_xvtdivdp, // llvm.ppc.vsx.xvtdivdp - ppc_vsx_xvtdivsp, // llvm.ppc.vsx.xvtdivsp - ppc_vsx_xvtlsbb, // llvm.ppc.vsx.xvtlsbb - ppc_vsx_xvtsqrtdp, // llvm.ppc.vsx.xvtsqrtdp - ppc_vsx_xvtsqrtsp, // llvm.ppc.vsx.xvtsqrtsp - ppc_vsx_xvtstdcdp, // llvm.ppc.vsx.xvtstdcdp - ppc_vsx_xvtstdcsp, // llvm.ppc.vsx.xvtstdcsp - ppc_vsx_xvxexpdp, // llvm.ppc.vsx.xvxexpdp - ppc_vsx_xvxexpsp, // llvm.ppc.vsx.xvxexpsp - ppc_vsx_xvxsigdp, // llvm.ppc.vsx.xvxsigdp - ppc_vsx_xvxsigsp, // llvm.ppc.vsx.xvxsigsp - ppc_vsx_xxblendvb, // llvm.ppc.vsx.xxblendvb - ppc_vsx_xxblendvd, // llvm.ppc.vsx.xxblendvd - ppc_vsx_xxblendvh, // llvm.ppc.vsx.xxblendvh - ppc_vsx_xxblendvw, // llvm.ppc.vsx.xxblendvw - ppc_vsx_xxeval, // llvm.ppc.vsx.xxeval - ppc_vsx_xxextractuw, // llvm.ppc.vsx.xxextractuw - ppc_vsx_xxgenpcvbm, // llvm.ppc.vsx.xxgenpcvbm - ppc_vsx_xxgenpcvdm, // llvm.ppc.vsx.xxgenpcvdm - ppc_vsx_xxgenpcvhm, // llvm.ppc.vsx.xxgenpcvhm - ppc_vsx_xxgenpcvwm, // llvm.ppc.vsx.xxgenpcvwm - ppc_vsx_xxinsertw, // llvm.ppc.vsx.xxinsertw - ppc_vsx_xxleqv, // llvm.ppc.vsx.xxleqv - ppc_vsx_xxpermx, // llvm.ppc.vsx.xxpermx -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.td deleted file mode 100644 index b01fa10763..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsPowerPC.td +++ /dev/null @@ -1,1809 +0,0 @@ -//===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the PowerPC-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Definitions for all PowerPC intrinsics. -// - -// Non-altivec intrinsics. -let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". - // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. - def int_ppc_dcba : Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_dcbf : GCCBuiltin<"__builtin_dcbf">, - Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly]>; - def int_ppc_dcbfps : Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly]>; - def int_ppc_dcbstps : Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly]>; - def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_dcbt_with_hint: Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>, ImmArg>]>; - def int_ppc_dcbtst_with_hint: Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture>, ImmArg>]>; - def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; - - // Get content from current FPSCR register - def int_ppc_readflm : GCCBuiltin<"__builtin_readflm">, - Intrinsic<[llvm_double_ty], [], - [IntrNoMerge, IntrHasSideEffects]>; - // Set FPSCR register, and return previous content - def int_ppc_setflm : GCCBuiltin<"__builtin_setflm">, - Intrinsic<[llvm_double_ty], [llvm_double_ty], - [IntrHasSideEffects]>; - - // Intrinsics for [double]word extended forms of divide instructions - def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_divde : GCCBuiltin<"__builtin_divde">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - - def int_ppc_unpack_longdouble : GCCBuiltin<"__builtin_unpack_longdouble">, - Intrinsic<[llvm_double_ty], - [llvm_ppcf128_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_pack_longdouble : GCCBuiltin<"__builtin_pack_longdouble">, - Intrinsic<[llvm_ppcf128_ty], - [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - - // Generate a random number - def int_ppc_darn : GCCBuiltin<"__builtin_darn">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; - def int_ppc_darnraw : GCCBuiltin<"__builtin_darn_raw">, - Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; - def int_ppc_darn32 : GCCBuiltin<"__builtin_darn_32">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; - - // Bit permute doubleword - def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - - // Parallel Bits Deposit/Extract Doubleword Builtins. - def int_ppc_pdepd - : GCCBuiltin<"__builtin_pdepd">, - Intrinsic <[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_pextd - : GCCBuiltin<"__builtin_pextd">, - Intrinsic <[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - - // Centrifuge Doubleword Builtin. - def int_ppc_cfuged - : GCCBuiltin<"__builtin_cfuged">, - Intrinsic <[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - - // Count Leading / Trailing Zeroes under bit Mask Builtins. - def int_ppc_cntlzdm - : GCCBuiltin<"__builtin_cntlzdm">, - Intrinsic <[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_cnttzdm - : GCCBuiltin<"__builtin_cnttzdm">, - Intrinsic <[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - - def int_ppc_truncf128_round_to_odd - : GCCBuiltin<"__builtin_truncf128_round_to_odd">, - Intrinsic <[llvm_double_ty], [llvm_f128_ty], [IntrNoMem]>; - def int_ppc_sqrtf128_round_to_odd - : GCCBuiltin<"__builtin_sqrtf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty], [IntrNoMem]>; - def int_ppc_addf128_round_to_odd - : GCCBuiltin<"__builtin_addf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; - def int_ppc_subf128_round_to_odd - : GCCBuiltin<"__builtin_subf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; - def int_ppc_mulf128_round_to_odd - : GCCBuiltin<"__builtin_mulf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; - def int_ppc_divf128_round_to_odd - : GCCBuiltin<"__builtin_divf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; - def int_ppc_fmaf128_round_to_odd - : GCCBuiltin<"__builtin_fmaf128_round_to_odd">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; - def int_ppc_scalar_extract_expq - : GCCBuiltin<"__builtin_vsx_scalar_extract_expq">, - Intrinsic <[llvm_i64_ty], [llvm_f128_ty], [IntrNoMem]>; - def int_ppc_scalar_insert_exp_qp - : GCCBuiltin<"__builtin_vsx_scalar_insert_exp_qp">, - Intrinsic <[llvm_f128_ty], [llvm_f128_ty, llvm_i64_ty], [IntrNoMem]>; - - // Intrinsics defined to maintain XL compatibility - def int_ppc_tdw - : GCCBuiltin<"__builtin_ppc_tdw">, - Intrinsic <[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [ImmArg>]>; - def int_ppc_tw - : GCCBuiltin<"__builtin_ppc_tw">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>]>; - def int_ppc_trapd - : GCCBuiltin<"__builtin_ppc_trapd">, - Intrinsic <[], [llvm_i64_ty], []>; - def int_ppc_trap - : GCCBuiltin<"__builtin_ppc_trap">, - Intrinsic <[], [llvm_i32_ty], []>; - def int_ppc_fcfid - : GCCBuiltin<"__builtin_ppc_fcfid">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fcfud - : GCCBuiltin<"__builtin_ppc_fcfud">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctid - : GCCBuiltin<"__builtin_ppc_fctid">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctidz - : GCCBuiltin<"__builtin_ppc_fctidz">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctiw - : GCCBuiltin<"__builtin_ppc_fctiw">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctiwz - : GCCBuiltin<"__builtin_ppc_fctiwz">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctudz - : GCCBuiltin<"__builtin_ppc_fctudz">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fctuwz - : GCCBuiltin<"__builtin_ppc_fctuwz">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; -} - -let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". - /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. - class PowerPC_Vec_Intrinsic ret_types, - list param_types, - list properties> - : GCCBuiltin, - Intrinsic; - - /// PowerPC_VSX_Intrinsic - Base class for all VSX intrinsics. - class PowerPC_VSX_Intrinsic ret_types, - list param_types, - list properties> - : GCCBuiltin, - Intrinsic; -} - -//===----------------------------------------------------------------------===// -// PowerPC MMA Intrinsic Multi Class Definitions. -// - -multiclass PowerPC_MMA_ACC_Intrinsic args> { - def NAME: Intrinsic<[llvm_v512i1_ty], args, [IntrNoMem]>; - def pp : Intrinsic<[llvm_v512i1_ty], !listconcat([llvm_v512i1_ty], args), - [IntrNoMem]>; - def pn : Intrinsic<[llvm_v512i1_ty], !listconcat([llvm_v512i1_ty], args), - [IntrNoMem]>; - def np : Intrinsic<[llvm_v512i1_ty], !listconcat([llvm_v512i1_ty], args), - [IntrNoMem]>; - def nn : Intrinsic<[llvm_v512i1_ty], !listconcat([llvm_v512i1_ty], args), - [IntrNoMem]>; -} - -multiclass PowerPC_MMA_ACC_PP_Intrinsic args> { - def NAME: Intrinsic<[llvm_v512i1_ty], args, [IntrNoMem]>; - def pp : Intrinsic<[llvm_v512i1_ty], !listconcat([llvm_v512i1_ty], args), - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// PowerPC Altivec Intrinsic Class Definitions. -// - -/// PowerPC_Vec_FF_Intrinsic - A PowerPC intrinsic that takes one v4f32 -/// vector and returns one. These intrinsics have no side effects. -class PowerPC_Vec_FF_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_FFF_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16i8 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_BBB_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_HHH_Intrinsic - A PowerPC intrinsic that takes two v8i16 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_HHH_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_WWW_Intrinsic - A PowerPC intrinsic that takes two v4i32 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_WWW_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2i64 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_DDD_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_QQQ_Intrinsic - A PowerPC intrinsic that takes two v1i128 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_Vec_QQQ_Intrinsic - : PowerPC_Vec_Intrinsic; - -/// PowerPC_Vec_QDD_Intrinsic - A PowerPC intrinsic that takes two v2i64 -/// vectors and returns one v1i128. These intrinsics have no side effects. -class PowerPC_Vec_QDD_Intrinsic - : PowerPC_Vec_Intrinsic; - -//===----------------------------------------------------------------------===// -// PowerPC VSX Intrinsic Class Definitions. -// - -/// PowerPC_VSX_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2f64 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_VSX_Vec_DDD_Intrinsic - : PowerPC_VSX_Intrinsic; - -/// PowerPC_VSX_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 -/// vectors and returns one. These intrinsics have no side effects. -class PowerPC_VSX_Vec_FFF_Intrinsic - : PowerPC_VSX_Intrinsic; - -/// PowerPC_VSX_Sca_DDD_Intrinsic - A PowerPC intrinsic that takes two f64 -/// scalars and returns one. These intrinsics have no side effects. -class PowerPC_VSX_Sca_DDD_Intrinsic - : PowerPC_VSX_Intrinsic; - -//===----------------------------------------------------------------------===// -// PowerPC Altivec Intrinsic Definitions. - -let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". - // Data Stream Control. - def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">, - Intrinsic<[], [], []>; - def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">, - Intrinsic<[], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - []>; - def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">, - Intrinsic<[], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - []>; - def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">, - Intrinsic<[], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - []>; - def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">, - Intrinsic<[], - [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - []>; - - // VSCR access. - def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">, - Intrinsic<[llvm_v8i16_ty], [], [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">, - Intrinsic<[], [llvm_v4i32_ty], [IntrNoMem, IntrHasSideEffects]>; - - - // Loads. These don't map directly to GCC builtins because they represent the - // source address with a single pointer. - def int_ppc_altivec_lvx : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_altivec_lvxl : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_altivec_lvebx : - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_altivec_lvehx : - Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_altivec_lvewx : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - - // Stores. These don't map directly to GCC builtins because they represent the - // source address with a single pointer. - def int_ppc_altivec_stvx : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; - def int_ppc_altivec_stvxl : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; - def int_ppc_altivec_stvebx : - Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; - def int_ppc_altivec_stvehx : - Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; - def int_ppc_altivec_stvewx : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; - - // Comparisons setting a vector. - def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpeqfp : GCCBuiltin<"__builtin_altivec_vcmpeqfp">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgefp : GCCBuiltin<"__builtin_altivec_vcmpgefp">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequd : GCCBuiltin<"__builtin_altivec_vcmpequd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsd : GCCBuiltin<"__builtin_altivec_vcmpgtsd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtud : GCCBuiltin<"__builtin_altivec_vcmpgtud">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsw : GCCBuiltin<"__builtin_altivec_vcmpgtsw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuw : GCCBuiltin<"__builtin_altivec_vcmpgtuw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnew : GCCBuiltin<"__builtin_altivec_vcmpnew">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezw : GCCBuiltin<"__builtin_altivec_vcmpnezw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequh : GCCBuiltin<"__builtin_altivec_vcmpequh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsh : GCCBuiltin<"__builtin_altivec_vcmpgtsh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuh : GCCBuiltin<"__builtin_altivec_vcmpgtuh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpneh : GCCBuiltin<"__builtin_altivec_vcmpneh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezh : GCCBuiltin<"__builtin_altivec_vcmpnezh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequb : GCCBuiltin<"__builtin_altivec_vcmpequb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsb : GCCBuiltin<"__builtin_altivec_vcmpgtsb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtub : GCCBuiltin<"__builtin_altivec_vcmpgtub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpneb : GCCBuiltin<"__builtin_altivec_vcmpneb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezb : GCCBuiltin<"__builtin_altivec_vcmpnezb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequq : GCCBuiltin<"__builtin_altivec_vcmpequq">, - Intrinsic<[llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsq : GCCBuiltin<"__builtin_altivec_vcmpgtsq">, - Intrinsic<[llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuq : GCCBuiltin<"__builtin_altivec_vcmpgtuq">, - Intrinsic<[llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpequq_p : GCCBuiltin<"__builtin_altivec_vcmpequq_p">, - Intrinsic<[llvm_i32_ty], - [llvm_i32_ty,llvm_v1i128_ty,llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsq_p : GCCBuiltin<"__builtin_altivec_vcmpgtsq_p">, - Intrinsic<[llvm_i32_ty], - [llvm_i32_ty,llvm_v1i128_ty,llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuq_p : GCCBuiltin<"__builtin_altivec_vcmpgtuq_p">, - Intrinsic<[llvm_i32_ty], - [llvm_i32_ty,llvm_v1i128_ty,llvm_v1i128_ty], - [IntrNoMem]>; - - // Predicate Comparisons. The first operand specifies interpretation of CR6. - def int_ppc_altivec_vcmpbfp_p : GCCBuiltin<"__builtin_altivec_vcmpbfp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpeqfp_p : GCCBuiltin<"__builtin_altivec_vcmpeqfp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgefp_p : GCCBuiltin<"__builtin_altivec_vcmpgefp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequd_p : GCCBuiltin<"__builtin_altivec_vcmpequd_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsd_p : GCCBuiltin<"__builtin_altivec_vcmpgtsd_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtud_p : GCCBuiltin<"__builtin_altivec_vcmpgtud_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsw_p : GCCBuiltin<"__builtin_altivec_vcmpgtsw_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuw_p : GCCBuiltin<"__builtin_altivec_vcmpgtuw_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnew_p : GCCBuiltin<"__builtin_altivec_vcmpnew_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezw_p : GCCBuiltin<"__builtin_altivec_vcmpnezw_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequh_p : GCCBuiltin<"__builtin_altivec_vcmpequh_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsh_p : GCCBuiltin<"__builtin_altivec_vcmpgtsh_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtuh_p : GCCBuiltin<"__builtin_altivec_vcmpgtuh_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpneh_p : GCCBuiltin<"__builtin_altivec_vcmpneh_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezh_p : GCCBuiltin<"__builtin_altivec_vcmpnezh_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; - - def int_ppc_altivec_vcmpequb_p : GCCBuiltin<"__builtin_altivec_vcmpequb_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtsb_p : GCCBuiltin<"__builtin_altivec_vcmpgtsb_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpgtub_p : GCCBuiltin<"__builtin_altivec_vcmpgtub_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpneb_p : GCCBuiltin<"__builtin_altivec_vcmpneb_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vcmpnezb_p : GCCBuiltin<"__builtin_altivec_vcmpnezb_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vclzlsbb : GCCBuiltin<"__builtin_altivec_vclzlsbb">, - Intrinsic<[llvm_i32_ty],[llvm_v16i8_ty],[IntrNoMem]>; - def int_ppc_altivec_vctzlsbb : GCCBuiltin<"__builtin_altivec_vctzlsbb">, - Intrinsic<[llvm_i32_ty],[llvm_v16i8_ty],[IntrNoMem]>; - def int_ppc_altivec_vprtybw : GCCBuiltin<"__builtin_altivec_vprtybw">, - Intrinsic<[llvm_v4i32_ty],[llvm_v4i32_ty],[IntrNoMem]>; - def int_ppc_altivec_vprtybd : GCCBuiltin<"__builtin_altivec_vprtybd">, - Intrinsic<[llvm_v2i64_ty],[llvm_v2i64_ty],[IntrNoMem]>; - def int_ppc_altivec_vprtybq : GCCBuiltin<"__builtin_altivec_vprtybq">, - Intrinsic<[llvm_v1i128_ty],[llvm_v1i128_ty],[IntrNoMem]>; - - // BCD intrinsics. - def int_ppc_bcdadd : GCCBuiltin<"__builtin_ppc_bcdadd">, Intrinsic< - [llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_bcdadd_p : GCCBuiltin<"__builtin_ppc_bcdadd_p">, Intrinsic< - [llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_bcdsub : GCCBuiltin<"__builtin_ppc_bcdsub">, Intrinsic< - [llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_bcdsub_p : GCCBuiltin<"__builtin_ppc_bcdsub_p">, Intrinsic< - [llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem, ImmArg>]>; - - // P10 Vector Extract with Mask - def int_ppc_altivec_vextractbm : GCCBuiltin<"__builtin_altivec_vextractbm">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vextracthm : GCCBuiltin<"__builtin_altivec_vextracthm">, - Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vextractwm : GCCBuiltin<"__builtin_altivec_vextractwm">, - Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vextractdm : GCCBuiltin<"__builtin_altivec_vextractdm">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; - def int_ppc_altivec_vextractqm : GCCBuiltin<"__builtin_altivec_vextractqm">, - Intrinsic<[llvm_i32_ty], [llvm_v1i128_ty], [IntrNoMem]>; - - // P10 Vector Expand with Mask - def int_ppc_altivec_vexpandbm : GCCBuiltin<"__builtin_altivec_vexpandbm">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vexpandhm : GCCBuiltin<"__builtin_altivec_vexpandhm">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vexpandwm : GCCBuiltin<"__builtin_altivec_vexpandwm">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vexpanddm : GCCBuiltin<"__builtin_altivec_vexpanddm">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - def int_ppc_altivec_vexpandqm : GCCBuiltin<"__builtin_altivec_vexpandqm">, - Intrinsic<[llvm_v1i128_ty], [llvm_v1i128_ty], [IntrNoMem]>; - - // P10 Vector Count with Mask intrinsics. - def int_ppc_altivec_vcntmbb : GCCBuiltin<"__builtin_altivec_vcntmbb">, - Intrinsic<[llvm_i64_ty], [llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vcntmbh : GCCBuiltin<"__builtin_altivec_vcntmbh">, - Intrinsic<[llvm_i64_ty], [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vcntmbw : GCCBuiltin<"__builtin_altivec_vcntmbw">, - Intrinsic<[llvm_i64_ty], [llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vcntmbd : GCCBuiltin<"__builtin_altivec_vcntmbd">, - Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - // P10 Move to VSR with Mask Intrinsics. - def int_ppc_altivec_mtvsrbm : GCCBuiltin<"__builtin_altivec_mtvsrbm">, - Intrinsic<[llvm_v16i8_ty], [llvm_i64_ty], [IntrNoMem]>; - def int_ppc_altivec_mtvsrhm : GCCBuiltin<"__builtin_altivec_mtvsrhm">, - Intrinsic<[llvm_v8i16_ty], [llvm_i64_ty], [IntrNoMem]>; - def int_ppc_altivec_mtvsrwm : GCCBuiltin<"__builtin_altivec_mtvsrwm">, - Intrinsic<[llvm_v4i32_ty], [llvm_i64_ty], [IntrNoMem]>; - def int_ppc_altivec_mtvsrdm : GCCBuiltin<"__builtin_altivec_mtvsrdm">, - Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; - def int_ppc_altivec_mtvsrqm : GCCBuiltin<"__builtin_altivec_mtvsrqm">, - Intrinsic<[llvm_v1i128_ty], [llvm_i64_ty], [IntrNoMem]>; - - // P10 Vector Parallel Bits Deposit/Extract Doubleword Builtins. - def int_ppc_altivec_vpdepd : GCCBuiltin<"__builtin_altivec_vpdepd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vpextd : GCCBuiltin<"__builtin_altivec_vpextd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - - // P10 Vector String Isolate Intrinsics. - def int_ppc_altivec_vstribr : GCCBuiltin<"__builtin_altivec_vstribr">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vstribl : GCCBuiltin<"__builtin_altivec_vstribl">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vstrihr : GCCBuiltin<"__builtin_altivec_vstrihr">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vstrihl : GCCBuiltin<"__builtin_altivec_vstrihl">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; - // Predicate Intrinsics: The first operand specifies interpretation of CR6. - def int_ppc_altivec_vstribr_p : GCCBuiltin<"__builtin_altivec_vstribr_p">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vstribl_p : GCCBuiltin<"__builtin_altivec_vstribl_p">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vstrihr_p : GCCBuiltin<"__builtin_altivec_vstrihr_p">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vstrihl_p : GCCBuiltin<"__builtin_altivec_vstrihl_p">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v8i16_ty], [IntrNoMem]>; - - // P10 Vector Centrifuge Builtin. - def int_ppc_altivec_vcfuged : GCCBuiltin<"__builtin_altivec_vcfuged">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - - // P10 Vector Gather Every Nth Bit Builtin. - def int_ppc_altivec_vgnb : GCCBuiltin<"__builtin_altivec_vgnb">, - Intrinsic<[llvm_i64_ty], [llvm_v1i128_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - // P10 Vector Clear Bytes - def int_ppc_altivec_vclrlb : GCCBuiltin<"__builtin_altivec_vclrlb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vclrrb : GCCBuiltin<"__builtin_altivec_vclrrb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; - - // P10 Vector Shift Double Bit Immediate. - def int_ppc_altivec_vsldbi : GCCBuiltin<"__builtin_altivec_vsldbi">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vsrdbi : GCCBuiltin<"__builtin_altivec_vsrdbi">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - // P10 Vector Insert. - def int_ppc_altivec_vinsblx : GCCBuiltin<"__builtin_altivec_vinsblx">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinsbrx : GCCBuiltin<"__builtin_altivec_vinsbrx">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinshlx : GCCBuiltin<"__builtin_altivec_vinshlx">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinshrx : GCCBuiltin<"__builtin_altivec_vinshrx">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinswlx : GCCBuiltin<"__builtin_altivec_vinswlx">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinswrx : GCCBuiltin<"__builtin_altivec_vinswrx">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinsdlx : GCCBuiltin<"__builtin_altivec_vinsdlx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinsdrx : GCCBuiltin<"__builtin_altivec_vinsdrx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinsbvlx : GCCBuiltin<"__builtin_altivec_vinsbvlx">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinsbvrx : GCCBuiltin<"__builtin_altivec_vinsbvrx">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinshvlx : GCCBuiltin<"__builtin_altivec_vinshvlx">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinshvrx : GCCBuiltin<"__builtin_altivec_vinshvrx">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinswvlx : GCCBuiltin<"__builtin_altivec_vinswvlx">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vinswvrx : GCCBuiltin<"__builtin_altivec_vinswvrx">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - // P10 Vector Insert with immediate. - def int_ppc_altivec_vinsw : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vinsd : - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - // P10 Vector Extract. - def int_ppc_altivec_vextdubvlx : GCCBuiltin<"__builtin_altivec_vextdubvlx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextdubvrx : GCCBuiltin<"__builtin_altivec_vextdubvrx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextduhvlx : GCCBuiltin<"__builtin_altivec_vextduhvlx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextduhvrx : GCCBuiltin<"__builtin_altivec_vextduhvrx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextduwvlx : GCCBuiltin<"__builtin_altivec_vextduwvlx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextduwvrx : GCCBuiltin<"__builtin_altivec_vextduwvrx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextddvlx : GCCBuiltin<"__builtin_altivec_vextddvlx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vextddvrx : GCCBuiltin<"__builtin_altivec_vextddvrx">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; -} - -// Vector average. -def int_ppc_altivec_vavgsb : PowerPC_Vec_BBB_Intrinsic<"vavgsb">; -def int_ppc_altivec_vavgsh : PowerPC_Vec_HHH_Intrinsic<"vavgsh">; -def int_ppc_altivec_vavgsw : PowerPC_Vec_WWW_Intrinsic<"vavgsw">; -def int_ppc_altivec_vavgub : PowerPC_Vec_BBB_Intrinsic<"vavgub">; -def int_ppc_altivec_vavguh : PowerPC_Vec_HHH_Intrinsic<"vavguh">; -def int_ppc_altivec_vavguw : PowerPC_Vec_WWW_Intrinsic<"vavguw">; - -// Vector maximum. -def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; -def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; -def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; -def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; -def int_ppc_altivec_vmaxsd : PowerPC_Vec_DDD_Intrinsic<"vmaxsd">; -def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; -def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; -def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; -def int_ppc_altivec_vmaxud : PowerPC_Vec_DDD_Intrinsic<"vmaxud">; - -// Vector minimum. -def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; -def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; -def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; -def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; -def int_ppc_altivec_vminsd : PowerPC_Vec_DDD_Intrinsic<"vminsd">; -def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; -def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; -def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; -def int_ppc_altivec_vminud : PowerPC_Vec_DDD_Intrinsic<"vminud">; - -// Saturating adds. -def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; -def int_ppc_altivec_vaddsbs : PowerPC_Vec_BBB_Intrinsic<"vaddsbs">; -def int_ppc_altivec_vadduhs : PowerPC_Vec_HHH_Intrinsic<"vadduhs">; -def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; -def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; -def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; -def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; -def int_ppc_altivec_vaddcuq : PowerPC_Vec_QQQ_Intrinsic<"vaddcuq">; - -// Saturating subs. -def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; -def int_ppc_altivec_vsubsbs : PowerPC_Vec_BBB_Intrinsic<"vsubsbs">; -def int_ppc_altivec_vsubuhs : PowerPC_Vec_HHH_Intrinsic<"vsubuhs">; -def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; -def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; -def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; -def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; -def int_ppc_altivec_vsubcuq : PowerPC_Vec_QQQ_Intrinsic<"vsubcuq">; - -let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". - // Saturating multiply-adds. - def int_ppc_altivec_vmhaddshs : GCCBuiltin<"__builtin_altivec_vmhaddshs">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vmhraddshs : GCCBuiltin<"__builtin_altivec_vmhraddshs">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrHasSideEffects]>; - - def int_ppc_altivec_vmaddfp : GCCBuiltin<"__builtin_altivec_vmaddfp">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; - def int_ppc_altivec_vnmsubfp : GCCBuiltin<"__builtin_altivec_vnmsubfp">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; - - // Vector Multiply Sum Instructions. - def int_ppc_altivec_vmsummbm : GCCBuiltin<"__builtin_altivec_vmsummbm">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vmsumshm : GCCBuiltin<"__builtin_altivec_vmsumshm">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vmsumshs : GCCBuiltin<"__builtin_altivec_vmsumshs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v4i32_ty], [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vmsumubm : GCCBuiltin<"__builtin_altivec_vmsumubm">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vmsumuhm : GCCBuiltin<"__builtin_altivec_vmsumuhm">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vmsumudm : GCCBuiltin<"__builtin_altivec_vmsumudm">, - Intrinsic<[llvm_v1i128_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v1i128_ty], [IntrNoMem]>; - def int_ppc_altivec_vmsumuhs : GCCBuiltin<"__builtin_altivec_vmsumuhs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v4i32_ty], [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vmsumcud : GCCBuiltin<"__builtin_altivec_vmsumcud">, - Intrinsic<[llvm_v1i128_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v1i128_ty], [IntrNoMem]>; - - // Vector Multiply Instructions. - def int_ppc_altivec_vmulesb : GCCBuiltin<"__builtin_altivec_vmulesb">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulesw : GCCBuiltin<"__builtin_altivec_vmulesw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulesd : PowerPC_Vec_QDD_Intrinsic<"vmulesd">; - def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmuleuw : GCCBuiltin<"__builtin_altivec_vmuleuw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmuleud : PowerPC_Vec_QDD_Intrinsic<"vmuleud">; - - def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulosw : GCCBuiltin<"__builtin_altivec_vmulosw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulosd : PowerPC_Vec_QDD_Intrinsic<"vmulosd">; - def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmulouw : GCCBuiltin<"__builtin_altivec_vmulouw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vmuloud : PowerPC_Vec_QDD_Intrinsic<"vmuloud">; - - // Vector Sum Instructions. - def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vsum2sws : GCCBuiltin<"__builtin_altivec_vsum2sws">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vsum4sbs : GCCBuiltin<"__builtin_altivec_vsum4sbs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vsum4shs : GCCBuiltin<"__builtin_altivec_vsum4shs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vsum4ubs : GCCBuiltin<"__builtin_altivec_vsum4ubs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - - // Vector Sign Extension Instructions - def int_ppc_altivec_vextsb2w : GCCBuiltin<"__builtin_altivec_vextsb2w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vextsb2d : GCCBuiltin<"__builtin_altivec_vextsb2d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vextsh2w : GCCBuiltin<"__builtin_altivec_vextsh2w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vextsh2d : GCCBuiltin<"__builtin_altivec_vextsh2d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vextsw2d : GCCBuiltin<"__builtin_altivec_vextsw2d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vextsd2q : GCCBuiltin<"__builtin_altivec_vextsd2q">, - Intrinsic<[llvm_v1i128_ty], [llvm_v2i64_ty], [IntrNoMem]>; - - // Other multiplies. - def int_ppc_altivec_vmladduhm : GCCBuiltin<"__builtin_altivec_vmladduhm">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - // Packs. - def int_ppc_altivec_vpkpx : GCCBuiltin<"__builtin_altivec_vpkpx">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_ppc_altivec_vpkshss : GCCBuiltin<"__builtin_altivec_vpkshss">, - Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vpkshus : GCCBuiltin<"__builtin_altivec_vpkshus">, - Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vpksdss : GCCBuiltin<"__builtin_altivec_vpksdss">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem, IntrHasSideEffects]>; - def int_ppc_altivec_vpksdus : GCCBuiltin<"__builtin_altivec_vpksdus">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem, IntrHasSideEffects]>; - // vpkuhum is lowered to a shuffle. - def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, - Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrHasSideEffects]>; - // vpkuwum is lowered to a shuffle. - def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, IntrHasSideEffects]>; - // vpkudum is lowered to a shuffle. - def int_ppc_altivec_vpkudus : GCCBuiltin<"__builtin_altivec_vpkudus">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem, IntrHasSideEffects]>; - - // Unpacks. - def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vupkhsb : GCCBuiltin<"__builtin_altivec_vupkhsb">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vupkhsw : GCCBuiltin<"__builtin_altivec_vupkhsw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_ppc_altivec_vupklsw : GCCBuiltin<"__builtin_altivec_vupklsw">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - - - // FP <-> integer conversion. - def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_ppc_altivec_vrfin : GCCBuiltin<"__builtin_altivec_vrfin">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_ppc_altivec_vrfip : GCCBuiltin<"__builtin_altivec_vrfip">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - - // Add Extended Quadword - def int_ppc_altivec_vaddeuqm : GCCBuiltin<"__builtin_altivec_vaddeuqm">, - Intrinsic<[llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vaddecuq : GCCBuiltin<"__builtin_altivec_vaddecuq">, - Intrinsic<[llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - - // Sub Extended Quadword - def int_ppc_altivec_vsubeuqm : GCCBuiltin<"__builtin_altivec_vsubeuqm">, - Intrinsic<[llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - def int_ppc_altivec_vsubecuq : GCCBuiltin<"__builtin_altivec_vsubecuq">, - Intrinsic<[llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - - // P10 Vector Count Leading / Trailing Zeroes under bit Mask Builtins. - def int_ppc_altivec_vclzdm : GCCBuiltin<"__builtin_altivec_vclzdm">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_ppc_altivec_vctzdm : GCCBuiltin<"__builtin_altivec_vctzdm">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; -} - -def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; -def int_ppc_altivec_vslo : PowerPC_Vec_WWW_Intrinsic<"vslo">; - -def int_ppc_altivec_vslb : PowerPC_Vec_BBB_Intrinsic<"vslb">; -def int_ppc_altivec_vslv : PowerPC_Vec_BBB_Intrinsic<"vslv">; -def int_ppc_altivec_vsrv : PowerPC_Vec_BBB_Intrinsic<"vsrv">; -def int_ppc_altivec_vslh : PowerPC_Vec_HHH_Intrinsic<"vslh">; -def int_ppc_altivec_vslw : PowerPC_Vec_WWW_Intrinsic<"vslw">; - -// Right Shifts. -def int_ppc_altivec_vsr : PowerPC_Vec_WWW_Intrinsic<"vsr">; -def int_ppc_altivec_vsro : PowerPC_Vec_WWW_Intrinsic<"vsro">; - -def int_ppc_altivec_vsrb : PowerPC_Vec_BBB_Intrinsic<"vsrb">; -def int_ppc_altivec_vsrh : PowerPC_Vec_HHH_Intrinsic<"vsrh">; -def int_ppc_altivec_vsrw : PowerPC_Vec_WWW_Intrinsic<"vsrw">; -def int_ppc_altivec_vsrab : PowerPC_Vec_BBB_Intrinsic<"vsrab">; -def int_ppc_altivec_vsrah : PowerPC_Vec_HHH_Intrinsic<"vsrah">; -def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; - -// Rotates. -def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; -def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; -def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; -def int_ppc_altivec_vrld : PowerPC_Vec_DDD_Intrinsic<"vrld">; - -let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". - // Miscellaneous. - def int_ppc_altivec_lvsl : - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; - def int_ppc_altivec_lvsr : - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; - - def int_ppc_altivec_vperm : GCCBuiltin<"__builtin_altivec_vperm_4si">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_ppc_altivec_vgbbd : GCCBuiltin<"__builtin_altivec_vgbbd">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_vbpermq : GCCBuiltin<"__builtin_altivec_vbpermq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_ppc_altivec_vbpermd : GCCBuiltin<"__builtin_altivec_vbpermd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v16i8_ty], - [IntrNoMem]>; -} - -def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; -def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; -def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; -def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; - -// Power8 Intrinsics -// Crypto -let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". - def int_ppc_altivec_crypto_vsbox : - GCCBuiltin<"__builtin_altivec_crypto_vsbox">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - def int_ppc_altivec_crypto_vpermxor : - GCCBuiltin<"__builtin_altivec_crypto_vpermxor">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_altivec_crypto_vpermxor_be : - GCCBuiltin<"__builtin_altivec_crypto_vpermxor_be">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - -def int_ppc_altivec_crypto_vshasigmad : - GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; -def int_ppc_altivec_crypto_vshasigmaw : - GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; -} -def int_ppc_altivec_crypto_vcipher : - PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">; -def int_ppc_altivec_crypto_vcipherlast : - PowerPC_Vec_DDD_Intrinsic<"crypto_vcipherlast">; -def int_ppc_altivec_crypto_vncipher : - PowerPC_Vec_DDD_Intrinsic<"crypto_vncipher">; -def int_ppc_altivec_crypto_vncipherlast : - PowerPC_Vec_DDD_Intrinsic<"crypto_vncipherlast">; -def int_ppc_altivec_crypto_vpmsumb : - PowerPC_Vec_BBB_Intrinsic<"crypto_vpmsumb">; -def int_ppc_altivec_crypto_vpmsumh : - PowerPC_Vec_HHH_Intrinsic<"crypto_vpmsumh">; -def int_ppc_altivec_crypto_vpmsumw : - PowerPC_Vec_WWW_Intrinsic<"crypto_vpmsumw">; -def int_ppc_altivec_crypto_vpmsumd : - PowerPC_Vec_DDD_Intrinsic<"crypto_vpmsumd">; - -// Absolute Difference intrinsics -def int_ppc_altivec_vabsdub : PowerPC_Vec_BBB_Intrinsic<"vabsdub">; -def int_ppc_altivec_vabsduh : PowerPC_Vec_HHH_Intrinsic<"vabsduh">; -def int_ppc_altivec_vabsduw : PowerPC_Vec_WWW_Intrinsic<"vabsduw">; - -// Vector rotates -def int_ppc_altivec_vrlwnm : - PowerPC_Vec_Intrinsic<"vrlwnm", [llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_ppc_altivec_vrlwmi : - PowerPC_Vec_Intrinsic<"vrlwmi", [llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_ppc_altivec_vrldnm : - PowerPC_Vec_Intrinsic<"vrldnm", [llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -def int_ppc_altivec_vrldmi : - PowerPC_Vec_Intrinsic<"vrldmi", [llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - -def int_ppc_altivec_vrlqnm : - PowerPC_Vec_Intrinsic<"vrlqnm", [llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; -def int_ppc_altivec_vrlqmi : - PowerPC_Vec_Intrinsic<"vrlqmi", [llvm_v1i128_ty], - [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], - [IntrNoMem]>; - -// Vector Divide Extended Intrinsics. -def int_ppc_altivec_vdivesw : PowerPC_Vec_WWW_Intrinsic<"vdivesw">; -def int_ppc_altivec_vdiveuw : PowerPC_Vec_WWW_Intrinsic<"vdiveuw">; -def int_ppc_altivec_vdivesd : PowerPC_Vec_DDD_Intrinsic<"vdivesd">; -def int_ppc_altivec_vdiveud : PowerPC_Vec_DDD_Intrinsic<"vdiveud">; -def int_ppc_altivec_vdivesq : PowerPC_Vec_QQQ_Intrinsic<"vdivesq">; -def int_ppc_altivec_vdiveuq : PowerPC_Vec_QQQ_Intrinsic<"vdiveuq">; - -// Vector Multiply High Intrinsics. -def int_ppc_altivec_vmulhsw : PowerPC_Vec_WWW_Intrinsic<"vmulhsw">; -def int_ppc_altivec_vmulhuw : PowerPC_Vec_WWW_Intrinsic<"vmulhuw">; -def int_ppc_altivec_vmulhsd : PowerPC_Vec_DDD_Intrinsic<"vmulhsd">; -def int_ppc_altivec_vmulhud : PowerPC_Vec_DDD_Intrinsic<"vmulhud">; - -//===----------------------------------------------------------------------===// -// PowerPC VSX Intrinsic Definitions. - -let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". - -// Vector load. -def int_ppc_vsx_lxvw4x : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_ppc_vsx_lxvd2x : - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_ppc_vsx_lxvw4x_be : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_ppc_vsx_lxvd2x_be : - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; -def int_ppc_vsx_lxvl : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem, - IntrArgMemOnly]>; -def int_ppc_vsx_lxvll : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem, - IntrArgMemOnly]>; -def int_ppc_vsx_lxvp : - Intrinsic<[llvm_v256i1_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - -// Vector store. -def int_ppc_vsx_stxvw4x : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvd2x : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvw4x_be : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvd2x_be : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvl : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvll : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty], - [IntrWriteMem, IntrArgMemOnly]>; -def int_ppc_vsx_stxvp : - Intrinsic<[], [llvm_v256i1_ty, llvm_ptr_ty], [IntrWriteMem, - IntrArgMemOnly]>; -// Vector and scalar maximum. -def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">; -def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">; -def int_ppc_vsx_xsmaxdp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmaxdp">; - -// Vector and scalar minimum. -def int_ppc_vsx_xvmindp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmindp">; -def int_ppc_vsx_xvminsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvminsp">; -def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; - -// Vector divide. -def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; -def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; - -// Vector round-to-infinity (ceil) -def int_ppc_vsx_xvrspip : - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvrdpip : - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Vector reciprocal estimate -def int_ppc_vsx_xvresp : GCCBuiltin<"__builtin_vsx_xvresp">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvredp : GCCBuiltin<"__builtin_vsx_xvredp">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Vector rsqrte -def int_ppc_vsx_xvrsqrtesp : GCCBuiltin<"__builtin_vsx_xvrsqrtesp">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvrsqrtedp : GCCBuiltin<"__builtin_vsx_xvrsqrtedp">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Vector compare -def int_ppc_vsx_xvcmpeqdp : - PowerPC_VSX_Intrinsic<"xvcmpeqdp", [llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpeqdp_p : GCCBuiltin<"__builtin_vsx_xvcmpeqdp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2f64_ty,llvm_v2f64_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvcmpeqsp : - PowerPC_VSX_Intrinsic<"xvcmpeqsp", [llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpeqsp_p : GCCBuiltin<"__builtin_vsx_xvcmpeqsp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvcmpgedp : - PowerPC_VSX_Intrinsic<"xvcmpgedp", [llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpgedp_p : GCCBuiltin<"__builtin_vsx_xvcmpgedp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2f64_ty,llvm_v2f64_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvcmpgesp : - PowerPC_VSX_Intrinsic<"xvcmpgesp", [llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpgesp_p : GCCBuiltin<"__builtin_vsx_xvcmpgesp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvcmpgtdp : - PowerPC_VSX_Intrinsic<"xvcmpgtdp", [llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpgtdp_p : GCCBuiltin<"__builtin_vsx_xvcmpgtdp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2f64_ty,llvm_v2f64_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvcmpgtsp : - PowerPC_VSX_Intrinsic<"xvcmpgtsp", [llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcmpgtsp_p : GCCBuiltin<"__builtin_vsx_xvcmpgtsp_p">, - Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; -def int_ppc_vsx_xxleqv : - PowerPC_VSX_Intrinsic<"xxleqv", [llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xviexpdp : - PowerPC_VSX_Intrinsic<"xviexpdp",[llvm_v2f64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty],[IntrNoMem]>; -def int_ppc_vsx_xviexpsp : - PowerPC_VSX_Intrinsic<"xviexpsp",[llvm_v4f32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty],[IntrNoMem]>; -def int_ppc_vsx_xvcvdpsxws : - PowerPC_VSX_Intrinsic<"xvcvdpsxws", [llvm_v4i32_ty], - [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvdpuxws : - PowerPC_VSX_Intrinsic<"xvcvdpuxws", [llvm_v4i32_ty], - [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvspsxds : - PowerPC_VSX_Intrinsic<"xvcvspsxds", [llvm_v2i64_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvspuxds : - PowerPC_VSX_Intrinsic<"xvcvspuxds", [llvm_v2i64_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvsxwdp : - PowerPC_VSX_Intrinsic<"xvcvsxwdp", [llvm_v2f64_ty], - [llvm_v4i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvuxwdp : - PowerPC_VSX_Intrinsic<"xvcvuxwdp", [llvm_v2f64_ty], - [llvm_v4i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvspdp : - PowerPC_VSX_Intrinsic<"xvcvspdp", [llvm_v2f64_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvsxdsp : - PowerPC_VSX_Intrinsic<"xvcvsxdsp", [llvm_v4f32_ty], - [llvm_v2i64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvuxdsp : - PowerPC_VSX_Intrinsic<"xvcvuxdsp", [llvm_v4f32_ty], - [llvm_v2i64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvdpsp : - PowerPC_VSX_Intrinsic<"xvcvdpsp", [llvm_v4f32_ty], - [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvsphp : - PowerPC_VSX_Intrinsic<"xvcvsphp", [llvm_v4f32_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvxexpdp : - PowerPC_VSX_Intrinsic<"xvxexpdp", [llvm_v2i64_ty], - [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvxexpsp : - PowerPC_VSX_Intrinsic<"xvxexpsp", [llvm_v4i32_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvxsigdp : - PowerPC_VSX_Intrinsic<"xvxsigdp", [llvm_v2i64_ty], - [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvxsigsp : - PowerPC_VSX_Intrinsic<"xvxsigsp", [llvm_v4i32_ty], - [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvtstdcdp : - PowerPC_VSX_Intrinsic<"xvtstdcdp", [llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_ppc_vsx_xvtstdcsp : - PowerPC_VSX_Intrinsic<"xvtstdcsp", [llvm_v4i32_ty], - [llvm_v4f32_ty,llvm_i32_ty], [IntrNoMem, ImmArg>]>; -def int_ppc_vsx_xvcvhpsp : - PowerPC_VSX_Intrinsic<"xvcvhpsp", [llvm_v4f32_ty], - [llvm_v8i16_ty],[IntrNoMem]>; -def int_ppc_vsx_xvcvspbf16 : - PowerPC_VSX_Intrinsic<"xvcvspbf16", [llvm_v16i8_ty], - [llvm_v16i8_ty], [IntrNoMem]>; -def int_ppc_vsx_xvcvbf16spn : - PowerPC_VSX_Intrinsic<"xvcvbf16spn", [llvm_v16i8_ty], - [llvm_v16i8_ty], [IntrNoMem]>; -def int_ppc_vsx_xxextractuw : - PowerPC_VSX_Intrinsic<"xxextractuw",[llvm_v2i64_ty], - [llvm_v2i64_ty,llvm_i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xxinsertw : - PowerPC_VSX_Intrinsic<"xxinsertw",[llvm_v4i32_ty], - [llvm_v4i32_ty,llvm_v2i64_ty,llvm_i32_ty], - [IntrNoMem]>; -def int_ppc_vsx_xvtlsbb : - PowerPC_VSX_Intrinsic<"xvtlsbb", [llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvtdivdp : - PowerPC_VSX_Intrinsic<"xvtdivdp", [llvm_i32_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvtdivsp : - PowerPC_VSX_Intrinsic<"xvtdivsp", [llvm_i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xvtsqrtdp : - PowerPC_VSX_Intrinsic<"xvtsqrtdp", [llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; -def int_ppc_vsx_xvtsqrtsp : - PowerPC_VSX_Intrinsic<"xvtsqrtsp", [llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_ppc_vsx_xxeval : - PowerPC_VSX_Intrinsic<"xxeval", [llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -def int_ppc_vsx_xxgenpcvbm : - PowerPC_VSX_Intrinsic<"xxgenpcvbm", [llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xxgenpcvhm : - PowerPC_VSX_Intrinsic<"xxgenpcvhm", [llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xxgenpcvwm : - PowerPC_VSX_Intrinsic<"xxgenpcvwm", [llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_ppc_vsx_xxgenpcvdm : - PowerPC_VSX_Intrinsic<"xxgenpcvdm", [llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - -// P10 VSX Vector permute extended. -def int_ppc_vsx_xxpermx : - GCCBuiltin<"__builtin_vsx_xxpermx">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty,llvm_v16i8_ty,llvm_v16i8_ty,llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -// P10 VSX Vector Blend Variable. -def int_ppc_vsx_xxblendvb: GCCBuiltin<"__builtin_vsx_xxblendvb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; -def int_ppc_vsx_xxblendvh: GCCBuiltin<"__builtin_vsx_xxblendvh">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,llvm_v8i16_ty], - [IntrNoMem]>; -def int_ppc_vsx_xxblendvw: GCCBuiltin<"__builtin_vsx_xxblendvw">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -def int_ppc_vsx_xxblendvd: GCCBuiltin<"__builtin_vsx_xxblendvd">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// PowerPC HTM Intrinsic Definitions. - -let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". - -def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg>]>; -def int_ppc_tend : GCCBuiltin<"__builtin_tend">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg>]>; - -def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - -def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, - Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">, - Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; - -def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, - Intrinsic<[llvm_i64_ty], [], []>; -def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">, - Intrinsic<[llvm_i64_ty], [], []>; -def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">, - Intrinsic<[llvm_i64_ty], [], []>; -def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">, - Intrinsic<[llvm_i64_ty], [], []>; - -def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">, - Intrinsic<[], [llvm_i64_ty], []>; -def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">, - Intrinsic<[], [llvm_i64_ty], []>; -def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">, - Intrinsic<[], [llvm_i64_ty], []>; -def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">, - Intrinsic<[], [llvm_i64_ty], []>; - -// Extended mnemonics -def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">, - Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">, - Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">, - Intrinsic<[llvm_i32_ty], [], []>; - -def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">, - Intrinsic<[llvm_i64_ty], [], []>; - -def int_ppc_cfence : Intrinsic<[], [llvm_anyint_ty], []>; - -// PowerPC set FPSCR Intrinsic Definitions. -def int_ppc_setrnd : GCCBuiltin<"__builtin_setrnd">, - Intrinsic<[llvm_double_ty], [llvm_i32_ty], []>; -} - -let TargetPrefix = "ppc" in { - def int_ppc_vsx_assemble_pair : - Intrinsic<[llvm_v256i1_ty], - [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - - def int_ppc_vsx_disassemble_pair : - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty], - [llvm_v256i1_ty], [IntrNoMem]>; - - def int_ppc_mma_assemble_acc : - Intrinsic<[llvm_v512i1_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - - def int_ppc_mma_disassemble_acc : - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [llvm_v512i1_ty], [IntrNoMem]>; - - def int_ppc_mma_xxmtacc : - Intrinsic<[llvm_v512i1_ty], [llvm_v512i1_ty], [IntrNoMem]>; - - def int_ppc_mma_xxmfacc : - Intrinsic<[llvm_v512i1_ty], [llvm_v512i1_ty], [IntrNoMem]>; - - def int_ppc_mma_xxsetaccz : - Intrinsic<[llvm_v512i1_ty], [], [IntrNoMem]>; - - // MMA Reduced-Precision: Outer Product Intrinsic Definitions. - defm int_ppc_mma_xvi4ger8 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvi4ger8 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty]>; - - defm int_ppc_mma_xvi8ger4 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvi8ger4 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty]>; - - defm int_ppc_mma_xvi16ger2s : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvi16ger2s : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty]>; - - defm int_ppc_mma_xvf16ger2 : - PowerPC_MMA_ACC_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvf16ger2 : - PowerPC_MMA_ACC_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty]>; - defm int_ppc_mma_xvf32ger : - PowerPC_MMA_ACC_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvf32ger : - PowerPC_MMA_ACC_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty]>; - defm int_ppc_mma_xvf64ger : - PowerPC_MMA_ACC_Intrinsic<[llvm_v256i1_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvf64ger : - PowerPC_MMA_ACC_Intrinsic<[llvm_v256i1_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty]>; - - // MMA Reduced-Precision: bfloat16 Outer Product Intrinsic Definitions. - defm int_ppc_mma_xvbf16ger2 : - PowerPC_MMA_ACC_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvbf16ger2 : - PowerPC_MMA_ACC_Intrinsic< - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; - - // MMA Reduced-Precision: Missing Integer-based Outer Product Operations. - defm int_ppc_mma_xvi16ger2 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty]>; - defm int_ppc_mma_pmxvi16ger2 : - PowerPC_MMA_ACC_PP_Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty]>; - def int_ppc_mma_xvi8ger4spp : - Intrinsic<[llvm_v512i1_ty], - [llvm_v512i1_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_ppc_mma_pmxvi8ger4spp : - Intrinsic<[llvm_v512i1_ty], - [llvm_v512i1_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -} - -// XL Compat intrinsics. -let TargetPrefix = "ppc" in { - def int_ppc_dcbfl : GCCBuiltin<"__builtin_ppc_dcbfl">, - Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly]>; - def int_ppc_dcbflp : GCCBuiltin<"__builtin_ppc_dcbflp">, - Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly]>; - def int_ppc_dcbst : GCCBuiltin<"__builtin_ppc_dcbst">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_dcbt : GCCBuiltin<"__builtin_ppc_dcbt">, - Intrinsic<[], [llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_dcbtst : GCCBuiltin<"__builtin_ppc_dcbtst">, - Intrinsic<[], [llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_dcbz : GCCBuiltin<"__builtin_ppc_dcbz">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_icbt : GCCBuiltin<"__builtin_ppc_icbt">, - Intrinsic<[], [llvm_ptr_ty], []>; - - // Population Count in each Byte. - def int_ppc_popcntb : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty], [IntrNoMem]>; - - // sync instruction (i.e. sync 0, a.k.a hwsync) - def int_ppc_sync : GCCBuiltin<"__builtin_ppc_sync">, - Intrinsic<[], [], []>; - def int_ppc_iospace_sync : GCCBuiltin<"__builtin_ppc_iospace_sync">, - Intrinsic<[], [], []>; - // isync instruction - def int_ppc_isync : GCCBuiltin<"__builtin_ppc_isync">, - Intrinsic<[], [], []>; - // lwsync is sync 1 - def int_ppc_lwsync : GCCBuiltin<"__builtin_ppc_lwsync">, - Intrinsic<[], [], []>; - def int_ppc_iospace_lwsync : GCCBuiltin<"__builtin_ppc_iospace_lwsync">, - Intrinsic<[], [], []>; - // eieio instruction - def int_ppc_eieio : GCCBuiltin<"__builtin_ppc_eieio">, - Intrinsic<[],[],[]>; - def int_ppc_iospace_eieio : GCCBuiltin<"__builtin_ppc_iospace_eieio">, - Intrinsic<[],[],[]>; - def int_ppc_stdcx : GCCBuiltin<"__builtin_ppc_stdcx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty], - [IntrWriteMem]>; - def int_ppc_stwcx : GCCBuiltin<"__builtin_ppc_stwcx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrWriteMem]>; - def int_ppc_sthcx - : Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty ], [IntrWriteMem]>; - def int_ppc_stbcx : GCCBuiltin<"__builtin_ppc_stbcx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrWriteMem]>; - def int_ppc_dcbtstt : GCCBuiltin<"__builtin_ppc_dcbtstt">, - Intrinsic<[], [llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_dcbtt : GCCBuiltin<"__builtin_ppc_dcbtt">, - Intrinsic<[], [llvm_ptr_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_mftbu : GCCBuiltin<"__builtin_ppc_mftbu">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; - def int_ppc_mfmsr : GCCBuiltin<"__builtin_ppc_mfmsr">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; - def int_ppc_mfspr - : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty], [ImmArg>]>; - def int_ppc_mtmsr - : GCCBuiltin<"__builtin_ppc_mtmsr">, Intrinsic<[], [llvm_i32_ty], []>; - def int_ppc_mtspr - : Intrinsic<[], [llvm_i32_ty, llvm_anyint_ty], [ImmArg>]>; - def int_ppc_stfiw : GCCBuiltin<"__builtin_ppc_stfiw">, - Intrinsic<[], [llvm_ptr_ty, llvm_double_ty], - [IntrWriteMem]>; - // compare - def int_ppc_cmpeqb - : GCCBuiltin<"__builtin_ppc_cmpeqb">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_cmprb - : GCCBuiltin<"__builtin_ppc_cmprb">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_setb - : GCCBuiltin<"__builtin_ppc_setb">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_cmpb - : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, llvm_anyint_ty], - [IntrNoMem]>; - // multiply - def int_ppc_mulhd - : GCCBuiltin<"__builtin_ppc_mulhd">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_mulhdu - : GCCBuiltin<"__builtin_ppc_mulhdu">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_mulhw - : GCCBuiltin<"__builtin_ppc_mulhw">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_ppc_mulhwu - : GCCBuiltin<"__builtin_ppc_mulhwu">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_ppc_maddhd - : GCCBuiltin<"__builtin_ppc_maddhd">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_maddhdu - : GCCBuiltin<"__builtin_ppc_maddhdu">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_ppc_maddld - : GCCBuiltin<"__builtin_ppc_maddld">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - // load - def int_ppc_load2r - : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_load4r - : GCCBuiltin<"__builtin_ppc_load4r">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_ppc_load8r - : GCCBuiltin<"__builtin_ppc_load8r">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - // store - def int_ppc_store2r - : GCCBuiltin<"__builtin_ppc_store2r">, - Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [IntrWriteMem]>; - def int_ppc_store4r - : GCCBuiltin<"__builtin_ppc_store4r">, - Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [IntrWriteMem]>; - def int_ppc_store8r - : GCCBuiltin<"__builtin_ppc_store8r">, - Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty], [IntrWriteMem]>; - def int_ppc_insert_exp - : GCCBuiltin<"__builtin_ppc_insert_exp">, - Intrinsic <[llvm_double_ty], [llvm_double_ty, llvm_i64_ty], - [IntrNoMem]>; - def int_ppc_extract_exp - : GCCBuiltin<"__builtin_ppc_extract_exp">, - Intrinsic <[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_extract_sig - : GCCBuiltin<"__builtin_ppc_extract_sig">, - Intrinsic <[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_mtfsb0 - : GCCBuiltin<"__builtin_ppc_mtfsb0">, - Intrinsic <[], [llvm_i32_ty], - [IntrNoMem, IntrHasSideEffects, ImmArg>]>; - def int_ppc_mtfsb1 - : GCCBuiltin<"__builtin_ppc_mtfsb1">, - Intrinsic <[], [llvm_i32_ty], - [IntrNoMem, IntrHasSideEffects, ImmArg>]>; - def int_ppc_mtfsf : - Intrinsic <[], [llvm_i32_ty, llvm_double_ty], - [IntrNoMem, IntrHasSideEffects, ImmArg>]>; - def int_ppc_mtfsfi - : GCCBuiltin<"__builtin_ppc_mtfsfi">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrHasSideEffects, - ImmArg>,ImmArg>]>; - def int_ppc_fmsub - : GCCBuiltin<"__builtin_ppc_fmsub">, - Intrinsic <[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_fmsubs - : GCCBuiltin<"__builtin_ppc_fmsubs">, - Intrinsic <[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_ppc_fnmadd - : GCCBuiltin<"__builtin_ppc_fnmadd">, - Intrinsic <[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_fnmadds - : GCCBuiltin<"__builtin_ppc_fnmadds">, - Intrinsic <[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_ppc_fnmsub - : GCCBuiltin<"__builtin_ppc_fnmsub">, - Intrinsic <[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_fnmsubs - : GCCBuiltin<"__builtin_ppc_fnmsubs">, - Intrinsic <[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; - def int_ppc_fre - : GCCBuiltin<"__builtin_ppc_fre">, - Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_fres - : GCCBuiltin<"__builtin_ppc_fres">, - Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_ppc_addex - : GCCBuiltin<"__builtin_ppc_addex">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, IntrHasSideEffects, ImmArg>]>; - def int_ppc_fsel : GCCBuiltin<"__builtin_ppc_fsel">, - Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty, - llvm_double_ty], [IntrNoMem]>; - def int_ppc_fsels : GCCBuiltin<"__builtin_ppc_fsels">, - Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, - llvm_float_ty], [IntrNoMem]>; - def int_ppc_frsqrte : GCCBuiltin<"__builtin_ppc_frsqrte">, - Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; - def int_ppc_frsqrtes : GCCBuiltin<"__builtin_ppc_frsqrtes">, - Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; - def int_ppc_compare_exp_uo : GCCBuiltin<"__builtin_ppc_compare_exp_uo">, - Intrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_compare_exp_lt : GCCBuiltin<"__builtin_ppc_compare_exp_lt">, - Intrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_compare_exp_gt : GCCBuiltin<"__builtin_ppc_compare_exp_gt">, - Intrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_compare_exp_eq : GCCBuiltin<"__builtin_ppc_compare_exp_eq">, - Intrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; - def int_ppc_test_data_class_d : Intrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_test_data_class_f : Intrinsic<[llvm_i32_ty], - [llvm_float_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_ppc_convert_f128_to_ppcf128 - : Intrinsic<[llvm_ppcf128_ty], [llvm_f128_ty], [IntrNoMem]>; - def int_ppc_convert_ppcf128_to_f128 - : Intrinsic<[llvm_f128_ty], [llvm_ppcf128_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// PowerPC Atomic Intrinsic Definitions. -let TargetPrefix = "ppc" in { - class AtomicRMW128Intrinsic - : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_ptr_ty, llvm_i64_ty, llvm_i64_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_atomicrmw_xchg_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_add_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_sub_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_and_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_or_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_xor_i128 : AtomicRMW128Intrinsic; - def int_ppc_atomicrmw_nand_i128 : AtomicRMW128Intrinsic; - def int_ppc_cmpxchg_i128 : Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_ptr_ty, - llvm_i64_ty, llvm_i64_ty, - llvm_i64_ty, llvm_i64_ty], - [IntrArgMemOnly, NoCapture>]>; - def int_ppc_atomic_load_i128 : - Intrinsic<[llvm_i64_ty, llvm_i64_ty], - [llvm_ptr_ty], - [IntrArgMemOnly, IntrReadMem, NoCapture>]>; - def int_ppc_atomic_store_i128 : - Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_ptr_ty], - [IntrArgMemOnly, IntrWriteMem, NoCapture>]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsR600.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsR600.h deleted file mode 100644 index 274e8f050c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsR600.h +++ /dev/null @@ -1,55 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_R600_ENUMS_H -#define LLVM_IR_INTRINSIC_R600_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum R600Intrinsics : unsigned { -// Enum values for intrinsics - r600_cube = 7227, // llvm.r600.cube - r600_ddx, // llvm.r600.ddx - r600_ddy, // llvm.r600.ddy - r600_dot4, // llvm.r600.dot4 - r600_group_barrier, // llvm.r600.group.barrier - r600_implicitarg_ptr, // llvm.r600.implicitarg.ptr - r600_kill, // llvm.r600.kill - r600_rat_store_typed, // llvm.r600.rat.store.typed - r600_read_global_size_x, // llvm.r600.read.global.size.x - r600_read_global_size_y, // llvm.r600.read.global.size.y - r600_read_global_size_z, // llvm.r600.read.global.size.z - r600_read_local_size_x, // llvm.r600.read.local.size.x - r600_read_local_size_y, // llvm.r600.read.local.size.y - r600_read_local_size_z, // llvm.r600.read.local.size.z - r600_read_ngroups_x, // llvm.r600.read.ngroups.x - r600_read_ngroups_y, // llvm.r600.read.ngroups.y - r600_read_ngroups_z, // llvm.r600.read.ngroups.z - r600_read_tgid_x, // llvm.r600.read.tgid.x - r600_read_tgid_y, // llvm.r600.read.tgid.y - r600_read_tgid_z, // llvm.r600.read.tgid.z - r600_read_tidig_x, // llvm.r600.read.tidig.x - r600_read_tidig_y, // llvm.r600.read.tidig.y - r600_read_tidig_z, // llvm.r600.read.tidig.z - r600_recipsqrt_clamped, // llvm.r600.recipsqrt.clamped - r600_recipsqrt_ieee, // llvm.r600.recipsqrt.ieee - r600_store_stream_output, // llvm.r600.store.stream.output - r600_store_swizzle, // llvm.r600.store.swizzle - r600_tex, // llvm.r600.tex - r600_texc, // llvm.r600.texc - r600_txb, // llvm.r600.txb - r600_txbc, // llvm.r600.txbc - r600_txf, // llvm.r600.txf - r600_txl, // llvm.r600.txl - r600_txlc, // llvm.r600.txlc - r600_txq, // llvm.r600.txq -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.h deleted file mode 100644 index 8c766308a6..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.h +++ /dev/null @@ -1,591 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_RISCV_ENUMS_H -#define LLVM_IR_INTRINSIC_RISCV_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum RISCVIntrinsics : unsigned { -// Enum values for intrinsics - riscv_aes32dsi = 7262, // llvm.riscv.aes32dsi - riscv_aes32dsmi, // llvm.riscv.aes32dsmi - riscv_aes32esi, // llvm.riscv.aes32esi - riscv_aes32esmi, // llvm.riscv.aes32esmi - riscv_aes64ds, // llvm.riscv.aes64ds - riscv_aes64dsm, // llvm.riscv.aes64dsm - riscv_aes64es, // llvm.riscv.aes64es - riscv_aes64esm, // llvm.riscv.aes64esm - riscv_aes64im, // llvm.riscv.aes64im - riscv_aes64ks1i, // llvm.riscv.aes64ks1i - riscv_aes64ks2, // llvm.riscv.aes64ks2 - riscv_bcompress, // llvm.riscv.bcompress - riscv_bdecompress, // llvm.riscv.bdecompress - riscv_bfp, // llvm.riscv.bfp - riscv_brev8, // llvm.riscv.brev8 - riscv_clmul, // llvm.riscv.clmul - riscv_clmulh, // llvm.riscv.clmulh - riscv_clmulr, // llvm.riscv.clmulr - riscv_crc32_b, // llvm.riscv.crc32.b - riscv_crc32_d, // llvm.riscv.crc32.d - riscv_crc32_h, // llvm.riscv.crc32.h - riscv_crc32_w, // llvm.riscv.crc32.w - riscv_crc32c_b, // llvm.riscv.crc32c.b - riscv_crc32c_d, // llvm.riscv.crc32c.d - riscv_crc32c_h, // llvm.riscv.crc32c.h - riscv_crc32c_w, // llvm.riscv.crc32c.w - riscv_fsl, // llvm.riscv.fsl - riscv_fsr, // llvm.riscv.fsr - riscv_gorc, // llvm.riscv.gorc - riscv_grev, // llvm.riscv.grev - riscv_masked_atomicrmw_add_i32, // llvm.riscv.masked.atomicrmw.add.i32 - riscv_masked_atomicrmw_add_i64, // llvm.riscv.masked.atomicrmw.add.i64 - riscv_masked_atomicrmw_max_i32, // llvm.riscv.masked.atomicrmw.max.i32 - riscv_masked_atomicrmw_max_i64, // llvm.riscv.masked.atomicrmw.max.i64 - riscv_masked_atomicrmw_min_i32, // llvm.riscv.masked.atomicrmw.min.i32 - riscv_masked_atomicrmw_min_i64, // llvm.riscv.masked.atomicrmw.min.i64 - riscv_masked_atomicrmw_nand_i32, // llvm.riscv.masked.atomicrmw.nand.i32 - riscv_masked_atomicrmw_nand_i64, // llvm.riscv.masked.atomicrmw.nand.i64 - riscv_masked_atomicrmw_sub_i32, // llvm.riscv.masked.atomicrmw.sub.i32 - riscv_masked_atomicrmw_sub_i64, // llvm.riscv.masked.atomicrmw.sub.i64 - riscv_masked_atomicrmw_umax_i32, // llvm.riscv.masked.atomicrmw.umax.i32 - riscv_masked_atomicrmw_umax_i64, // llvm.riscv.masked.atomicrmw.umax.i64 - riscv_masked_atomicrmw_umin_i32, // llvm.riscv.masked.atomicrmw.umin.i32 - riscv_masked_atomicrmw_umin_i64, // llvm.riscv.masked.atomicrmw.umin.i64 - riscv_masked_atomicrmw_xchg_i32, // llvm.riscv.masked.atomicrmw.xchg.i32 - riscv_masked_atomicrmw_xchg_i64, // llvm.riscv.masked.atomicrmw.xchg.i64 - riscv_masked_cmpxchg_i32, // llvm.riscv.masked.cmpxchg.i32 - riscv_masked_cmpxchg_i64, // llvm.riscv.masked.cmpxchg.i64 - riscv_masked_strided_load, // llvm.riscv.masked.strided.load - riscv_masked_strided_store, // llvm.riscv.masked.strided.store - riscv_orc_b, // llvm.riscv.orc.b - riscv_sha256sig0, // llvm.riscv.sha256sig0 - riscv_sha256sig1, // llvm.riscv.sha256sig1 - riscv_sha256sum0, // llvm.riscv.sha256sum0 - riscv_sha256sum1, // llvm.riscv.sha256sum1 - riscv_sha512sig0, // llvm.riscv.sha512sig0 - riscv_sha512sig0h, // llvm.riscv.sha512sig0h - riscv_sha512sig0l, // llvm.riscv.sha512sig0l - riscv_sha512sig1, // llvm.riscv.sha512sig1 - riscv_sha512sig1h, // llvm.riscv.sha512sig1h - riscv_sha512sig1l, // llvm.riscv.sha512sig1l - riscv_sha512sum0, // llvm.riscv.sha512sum0 - riscv_sha512sum0r, // llvm.riscv.sha512sum0r - riscv_sha512sum1, // llvm.riscv.sha512sum1 - riscv_sha512sum1r, // llvm.riscv.sha512sum1r - riscv_shfl, // llvm.riscv.shfl - riscv_sm3p0, // llvm.riscv.sm3p0 - riscv_sm3p1, // llvm.riscv.sm3p1 - riscv_sm4ed, // llvm.riscv.sm4ed - riscv_sm4ks, // llvm.riscv.sm4ks - riscv_unshfl, // llvm.riscv.unshfl - riscv_unzip, // llvm.riscv.unzip - riscv_vaadd, // llvm.riscv.vaadd - riscv_vaadd_mask, // llvm.riscv.vaadd.mask - riscv_vaaddu, // llvm.riscv.vaaddu - riscv_vaaddu_mask, // llvm.riscv.vaaddu.mask - riscv_vadc, // llvm.riscv.vadc - riscv_vadd, // llvm.riscv.vadd - riscv_vadd_mask, // llvm.riscv.vadd.mask - riscv_vand, // llvm.riscv.vand - riscv_vand_mask, // llvm.riscv.vand.mask - riscv_vasub, // llvm.riscv.vasub - riscv_vasub_mask, // llvm.riscv.vasub.mask - riscv_vasubu, // llvm.riscv.vasubu - riscv_vasubu_mask, // llvm.riscv.vasubu.mask - riscv_vcompress, // llvm.riscv.vcompress - riscv_vcpop, // llvm.riscv.vcpop - riscv_vcpop_mask, // llvm.riscv.vcpop.mask - riscv_vdiv, // llvm.riscv.vdiv - riscv_vdiv_mask, // llvm.riscv.vdiv.mask - riscv_vdivu, // llvm.riscv.vdivu - riscv_vdivu_mask, // llvm.riscv.vdivu.mask - riscv_vfadd, // llvm.riscv.vfadd - riscv_vfadd_mask, // llvm.riscv.vfadd.mask - riscv_vfclass, // llvm.riscv.vfclass - riscv_vfclass_mask, // llvm.riscv.vfclass.mask - riscv_vfcvt_f_x_v, // llvm.riscv.vfcvt.f.x.v - riscv_vfcvt_f_x_v_mask, // llvm.riscv.vfcvt.f.x.v.mask - riscv_vfcvt_f_xu_v, // llvm.riscv.vfcvt.f.xu.v - riscv_vfcvt_f_xu_v_mask, // llvm.riscv.vfcvt.f.xu.v.mask - riscv_vfcvt_rtz_x_f_v, // llvm.riscv.vfcvt.rtz.x.f.v - riscv_vfcvt_rtz_x_f_v_mask, // llvm.riscv.vfcvt.rtz.x.f.v.mask - riscv_vfcvt_rtz_xu_f_v, // llvm.riscv.vfcvt.rtz.xu.f.v - riscv_vfcvt_rtz_xu_f_v_mask, // llvm.riscv.vfcvt.rtz.xu.f.v.mask - riscv_vfcvt_x_f_v, // llvm.riscv.vfcvt.x.f.v - riscv_vfcvt_x_f_v_mask, // llvm.riscv.vfcvt.x.f.v.mask - riscv_vfcvt_xu_f_v, // llvm.riscv.vfcvt.xu.f.v - riscv_vfcvt_xu_f_v_mask, // llvm.riscv.vfcvt.xu.f.v.mask - riscv_vfdiv, // llvm.riscv.vfdiv - riscv_vfdiv_mask, // llvm.riscv.vfdiv.mask - riscv_vfirst, // llvm.riscv.vfirst - riscv_vfirst_mask, // llvm.riscv.vfirst.mask - riscv_vfmacc, // llvm.riscv.vfmacc - riscv_vfmacc_mask, // llvm.riscv.vfmacc.mask - riscv_vfmadd, // llvm.riscv.vfmadd - riscv_vfmadd_mask, // llvm.riscv.vfmadd.mask - riscv_vfmax, // llvm.riscv.vfmax - riscv_vfmax_mask, // llvm.riscv.vfmax.mask - riscv_vfmerge, // llvm.riscv.vfmerge - riscv_vfmin, // llvm.riscv.vfmin - riscv_vfmin_mask, // llvm.riscv.vfmin.mask - riscv_vfmsac, // llvm.riscv.vfmsac - riscv_vfmsac_mask, // llvm.riscv.vfmsac.mask - riscv_vfmsub, // llvm.riscv.vfmsub - riscv_vfmsub_mask, // llvm.riscv.vfmsub.mask - riscv_vfmul, // llvm.riscv.vfmul - riscv_vfmul_mask, // llvm.riscv.vfmul.mask - riscv_vfmv_f_s, // llvm.riscv.vfmv.f.s - riscv_vfmv_s_f, // llvm.riscv.vfmv.s.f - riscv_vfmv_v_f, // llvm.riscv.vfmv.v.f - riscv_vfncvt_f_f_w, // llvm.riscv.vfncvt.f.f.w - riscv_vfncvt_f_f_w_mask, // llvm.riscv.vfncvt.f.f.w.mask - riscv_vfncvt_f_x_w, // llvm.riscv.vfncvt.f.x.w - riscv_vfncvt_f_x_w_mask, // llvm.riscv.vfncvt.f.x.w.mask - riscv_vfncvt_f_xu_w, // llvm.riscv.vfncvt.f.xu.w - riscv_vfncvt_f_xu_w_mask, // llvm.riscv.vfncvt.f.xu.w.mask - riscv_vfncvt_rod_f_f_w, // llvm.riscv.vfncvt.rod.f.f.w - riscv_vfncvt_rod_f_f_w_mask, // llvm.riscv.vfncvt.rod.f.f.w.mask - riscv_vfncvt_rtz_x_f_w, // llvm.riscv.vfncvt.rtz.x.f.w - riscv_vfncvt_rtz_x_f_w_mask, // llvm.riscv.vfncvt.rtz.x.f.w.mask - riscv_vfncvt_rtz_xu_f_w, // llvm.riscv.vfncvt.rtz.xu.f.w - riscv_vfncvt_rtz_xu_f_w_mask, // llvm.riscv.vfncvt.rtz.xu.f.w.mask - riscv_vfncvt_x_f_w, // llvm.riscv.vfncvt.x.f.w - riscv_vfncvt_x_f_w_mask, // llvm.riscv.vfncvt.x.f.w.mask - riscv_vfncvt_xu_f_w, // llvm.riscv.vfncvt.xu.f.w - riscv_vfncvt_xu_f_w_mask, // llvm.riscv.vfncvt.xu.f.w.mask - riscv_vfnmacc, // llvm.riscv.vfnmacc - riscv_vfnmacc_mask, // llvm.riscv.vfnmacc.mask - riscv_vfnmadd, // llvm.riscv.vfnmadd - riscv_vfnmadd_mask, // llvm.riscv.vfnmadd.mask - riscv_vfnmsac, // llvm.riscv.vfnmsac - riscv_vfnmsac_mask, // llvm.riscv.vfnmsac.mask - riscv_vfnmsub, // llvm.riscv.vfnmsub - riscv_vfnmsub_mask, // llvm.riscv.vfnmsub.mask - riscv_vfrdiv, // llvm.riscv.vfrdiv - riscv_vfrdiv_mask, // llvm.riscv.vfrdiv.mask - riscv_vfrec7, // llvm.riscv.vfrec7 - riscv_vfrec7_mask, // llvm.riscv.vfrec7.mask - riscv_vfredmax, // llvm.riscv.vfredmax - riscv_vfredmax_mask, // llvm.riscv.vfredmax.mask - riscv_vfredmin, // llvm.riscv.vfredmin - riscv_vfredmin_mask, // llvm.riscv.vfredmin.mask - riscv_vfredosum, // llvm.riscv.vfredosum - riscv_vfredosum_mask, // llvm.riscv.vfredosum.mask - riscv_vfredusum, // llvm.riscv.vfredusum - riscv_vfredusum_mask, // llvm.riscv.vfredusum.mask - riscv_vfrsqrt7, // llvm.riscv.vfrsqrt7 - riscv_vfrsqrt7_mask, // llvm.riscv.vfrsqrt7.mask - riscv_vfrsub, // llvm.riscv.vfrsub - riscv_vfrsub_mask, // llvm.riscv.vfrsub.mask - riscv_vfsgnj, // llvm.riscv.vfsgnj - riscv_vfsgnj_mask, // llvm.riscv.vfsgnj.mask - riscv_vfsgnjn, // llvm.riscv.vfsgnjn - riscv_vfsgnjn_mask, // llvm.riscv.vfsgnjn.mask - riscv_vfsgnjx, // llvm.riscv.vfsgnjx - riscv_vfsgnjx_mask, // llvm.riscv.vfsgnjx.mask - riscv_vfslide1down, // llvm.riscv.vfslide1down - riscv_vfslide1down_mask, // llvm.riscv.vfslide1down.mask - riscv_vfslide1up, // llvm.riscv.vfslide1up - riscv_vfslide1up_mask, // llvm.riscv.vfslide1up.mask - riscv_vfsqrt, // llvm.riscv.vfsqrt - riscv_vfsqrt_mask, // llvm.riscv.vfsqrt.mask - riscv_vfsub, // llvm.riscv.vfsub - riscv_vfsub_mask, // llvm.riscv.vfsub.mask - riscv_vfwadd, // llvm.riscv.vfwadd - riscv_vfwadd_mask, // llvm.riscv.vfwadd.mask - riscv_vfwadd_w, // llvm.riscv.vfwadd.w - riscv_vfwadd_w_mask, // llvm.riscv.vfwadd.w.mask - riscv_vfwcvt_f_f_v, // llvm.riscv.vfwcvt.f.f.v - riscv_vfwcvt_f_f_v_mask, // llvm.riscv.vfwcvt.f.f.v.mask - riscv_vfwcvt_f_x_v, // llvm.riscv.vfwcvt.f.x.v - riscv_vfwcvt_f_x_v_mask, // llvm.riscv.vfwcvt.f.x.v.mask - riscv_vfwcvt_f_xu_v, // llvm.riscv.vfwcvt.f.xu.v - riscv_vfwcvt_f_xu_v_mask, // llvm.riscv.vfwcvt.f.xu.v.mask - riscv_vfwcvt_rtz_x_f_v, // llvm.riscv.vfwcvt.rtz.x.f.v - riscv_vfwcvt_rtz_x_f_v_mask, // llvm.riscv.vfwcvt.rtz.x.f.v.mask - riscv_vfwcvt_rtz_xu_f_v, // llvm.riscv.vfwcvt.rtz.xu.f.v - riscv_vfwcvt_rtz_xu_f_v_mask, // llvm.riscv.vfwcvt.rtz.xu.f.v.mask - riscv_vfwcvt_x_f_v, // llvm.riscv.vfwcvt.x.f.v - riscv_vfwcvt_x_f_v_mask, // llvm.riscv.vfwcvt.x.f.v.mask - riscv_vfwcvt_xu_f_v, // llvm.riscv.vfwcvt.xu.f.v - riscv_vfwcvt_xu_f_v_mask, // llvm.riscv.vfwcvt.xu.f.v.mask - riscv_vfwmacc, // llvm.riscv.vfwmacc - riscv_vfwmacc_mask, // llvm.riscv.vfwmacc.mask - riscv_vfwmsac, // llvm.riscv.vfwmsac - riscv_vfwmsac_mask, // llvm.riscv.vfwmsac.mask - riscv_vfwmul, // llvm.riscv.vfwmul - riscv_vfwmul_mask, // llvm.riscv.vfwmul.mask - riscv_vfwnmacc, // llvm.riscv.vfwnmacc - riscv_vfwnmacc_mask, // llvm.riscv.vfwnmacc.mask - riscv_vfwnmsac, // llvm.riscv.vfwnmsac - riscv_vfwnmsac_mask, // llvm.riscv.vfwnmsac.mask - riscv_vfwredosum, // llvm.riscv.vfwredosum - riscv_vfwredosum_mask, // llvm.riscv.vfwredosum.mask - riscv_vfwredusum, // llvm.riscv.vfwredusum - riscv_vfwredusum_mask, // llvm.riscv.vfwredusum.mask - riscv_vfwsub, // llvm.riscv.vfwsub - riscv_vfwsub_mask, // llvm.riscv.vfwsub.mask - riscv_vfwsub_w, // llvm.riscv.vfwsub.w - riscv_vfwsub_w_mask, // llvm.riscv.vfwsub.w.mask - riscv_vid, // llvm.riscv.vid - riscv_vid_mask, // llvm.riscv.vid.mask - riscv_viota, // llvm.riscv.viota - riscv_viota_mask, // llvm.riscv.viota.mask - riscv_vle, // llvm.riscv.vle - riscv_vle_mask, // llvm.riscv.vle.mask - riscv_vleff, // llvm.riscv.vleff - riscv_vleff_mask, // llvm.riscv.vleff.mask - riscv_vlm, // llvm.riscv.vlm - riscv_vloxei, // llvm.riscv.vloxei - riscv_vloxei_mask, // llvm.riscv.vloxei.mask - riscv_vloxseg2, // llvm.riscv.vloxseg2 - riscv_vloxseg2_mask, // llvm.riscv.vloxseg2.mask - riscv_vloxseg3, // llvm.riscv.vloxseg3 - riscv_vloxseg3_mask, // llvm.riscv.vloxseg3.mask - riscv_vloxseg4, // llvm.riscv.vloxseg4 - riscv_vloxseg4_mask, // llvm.riscv.vloxseg4.mask - riscv_vloxseg5, // llvm.riscv.vloxseg5 - riscv_vloxseg5_mask, // llvm.riscv.vloxseg5.mask - riscv_vloxseg6, // llvm.riscv.vloxseg6 - riscv_vloxseg6_mask, // llvm.riscv.vloxseg6.mask - riscv_vloxseg7, // llvm.riscv.vloxseg7 - riscv_vloxseg7_mask, // llvm.riscv.vloxseg7.mask - riscv_vloxseg8, // llvm.riscv.vloxseg8 - riscv_vloxseg8_mask, // llvm.riscv.vloxseg8.mask - riscv_vlse, // llvm.riscv.vlse - riscv_vlse_mask, // llvm.riscv.vlse.mask - riscv_vlseg2, // llvm.riscv.vlseg2 - riscv_vlseg2_mask, // llvm.riscv.vlseg2.mask - riscv_vlseg2ff, // llvm.riscv.vlseg2ff - riscv_vlseg2ff_mask, // llvm.riscv.vlseg2ff.mask - riscv_vlseg3, // llvm.riscv.vlseg3 - riscv_vlseg3_mask, // llvm.riscv.vlseg3.mask - riscv_vlseg3ff, // llvm.riscv.vlseg3ff - riscv_vlseg3ff_mask, // llvm.riscv.vlseg3ff.mask - riscv_vlseg4, // llvm.riscv.vlseg4 - riscv_vlseg4_mask, // llvm.riscv.vlseg4.mask - riscv_vlseg4ff, // llvm.riscv.vlseg4ff - riscv_vlseg4ff_mask, // llvm.riscv.vlseg4ff.mask - riscv_vlseg5, // llvm.riscv.vlseg5 - riscv_vlseg5_mask, // llvm.riscv.vlseg5.mask - riscv_vlseg5ff, // llvm.riscv.vlseg5ff - riscv_vlseg5ff_mask, // llvm.riscv.vlseg5ff.mask - riscv_vlseg6, // llvm.riscv.vlseg6 - riscv_vlseg6_mask, // llvm.riscv.vlseg6.mask - riscv_vlseg6ff, // llvm.riscv.vlseg6ff - riscv_vlseg6ff_mask, // llvm.riscv.vlseg6ff.mask - riscv_vlseg7, // llvm.riscv.vlseg7 - riscv_vlseg7_mask, // llvm.riscv.vlseg7.mask - riscv_vlseg7ff, // llvm.riscv.vlseg7ff - riscv_vlseg7ff_mask, // llvm.riscv.vlseg7ff.mask - riscv_vlseg8, // llvm.riscv.vlseg8 - riscv_vlseg8_mask, // llvm.riscv.vlseg8.mask - riscv_vlseg8ff, // llvm.riscv.vlseg8ff - riscv_vlseg8ff_mask, // llvm.riscv.vlseg8ff.mask - riscv_vlsseg2, // llvm.riscv.vlsseg2 - riscv_vlsseg2_mask, // llvm.riscv.vlsseg2.mask - riscv_vlsseg3, // llvm.riscv.vlsseg3 - riscv_vlsseg3_mask, // llvm.riscv.vlsseg3.mask - riscv_vlsseg4, // llvm.riscv.vlsseg4 - riscv_vlsseg4_mask, // llvm.riscv.vlsseg4.mask - riscv_vlsseg5, // llvm.riscv.vlsseg5 - riscv_vlsseg5_mask, // llvm.riscv.vlsseg5.mask - riscv_vlsseg6, // llvm.riscv.vlsseg6 - riscv_vlsseg6_mask, // llvm.riscv.vlsseg6.mask - riscv_vlsseg7, // llvm.riscv.vlsseg7 - riscv_vlsseg7_mask, // llvm.riscv.vlsseg7.mask - riscv_vlsseg8, // llvm.riscv.vlsseg8 - riscv_vlsseg8_mask, // llvm.riscv.vlsseg8.mask - riscv_vluxei, // llvm.riscv.vluxei - riscv_vluxei_mask, // llvm.riscv.vluxei.mask - riscv_vluxseg2, // llvm.riscv.vluxseg2 - riscv_vluxseg2_mask, // llvm.riscv.vluxseg2.mask - riscv_vluxseg3, // llvm.riscv.vluxseg3 - riscv_vluxseg3_mask, // llvm.riscv.vluxseg3.mask - riscv_vluxseg4, // llvm.riscv.vluxseg4 - riscv_vluxseg4_mask, // llvm.riscv.vluxseg4.mask - riscv_vluxseg5, // llvm.riscv.vluxseg5 - riscv_vluxseg5_mask, // llvm.riscv.vluxseg5.mask - riscv_vluxseg6, // llvm.riscv.vluxseg6 - riscv_vluxseg6_mask, // llvm.riscv.vluxseg6.mask - riscv_vluxseg7, // llvm.riscv.vluxseg7 - riscv_vluxseg7_mask, // llvm.riscv.vluxseg7.mask - riscv_vluxseg8, // llvm.riscv.vluxseg8 - riscv_vluxseg8_mask, // llvm.riscv.vluxseg8.mask - riscv_vmacc, // llvm.riscv.vmacc - riscv_vmacc_mask, // llvm.riscv.vmacc.mask - riscv_vmadc, // llvm.riscv.vmadc - riscv_vmadc_carry_in, // llvm.riscv.vmadc.carry.in - riscv_vmadd, // llvm.riscv.vmadd - riscv_vmadd_mask, // llvm.riscv.vmadd.mask - riscv_vmand, // llvm.riscv.vmand - riscv_vmandn, // llvm.riscv.vmandn - riscv_vmax, // llvm.riscv.vmax - riscv_vmax_mask, // llvm.riscv.vmax.mask - riscv_vmaxu, // llvm.riscv.vmaxu - riscv_vmaxu_mask, // llvm.riscv.vmaxu.mask - riscv_vmclr, // llvm.riscv.vmclr - riscv_vmerge, // llvm.riscv.vmerge - riscv_vmfeq, // llvm.riscv.vmfeq - riscv_vmfeq_mask, // llvm.riscv.vmfeq.mask - riscv_vmfge, // llvm.riscv.vmfge - riscv_vmfge_mask, // llvm.riscv.vmfge.mask - riscv_vmfgt, // llvm.riscv.vmfgt - riscv_vmfgt_mask, // llvm.riscv.vmfgt.mask - riscv_vmfle, // llvm.riscv.vmfle - riscv_vmfle_mask, // llvm.riscv.vmfle.mask - riscv_vmflt, // llvm.riscv.vmflt - riscv_vmflt_mask, // llvm.riscv.vmflt.mask - riscv_vmfne, // llvm.riscv.vmfne - riscv_vmfne_mask, // llvm.riscv.vmfne.mask - riscv_vmin, // llvm.riscv.vmin - riscv_vmin_mask, // llvm.riscv.vmin.mask - riscv_vminu, // llvm.riscv.vminu - riscv_vminu_mask, // llvm.riscv.vminu.mask - riscv_vmnand, // llvm.riscv.vmnand - riscv_vmnor, // llvm.riscv.vmnor - riscv_vmor, // llvm.riscv.vmor - riscv_vmorn, // llvm.riscv.vmorn - riscv_vmsbc, // llvm.riscv.vmsbc - riscv_vmsbc_borrow_in, // llvm.riscv.vmsbc.borrow.in - riscv_vmsbf, // llvm.riscv.vmsbf - riscv_vmsbf_mask, // llvm.riscv.vmsbf.mask - riscv_vmseq, // llvm.riscv.vmseq - riscv_vmseq_mask, // llvm.riscv.vmseq.mask - riscv_vmset, // llvm.riscv.vmset - riscv_vmsge, // llvm.riscv.vmsge - riscv_vmsge_mask, // llvm.riscv.vmsge.mask - riscv_vmsgeu, // llvm.riscv.vmsgeu - riscv_vmsgeu_mask, // llvm.riscv.vmsgeu.mask - riscv_vmsgt, // llvm.riscv.vmsgt - riscv_vmsgt_mask, // llvm.riscv.vmsgt.mask - riscv_vmsgtu, // llvm.riscv.vmsgtu - riscv_vmsgtu_mask, // llvm.riscv.vmsgtu.mask - riscv_vmsif, // llvm.riscv.vmsif - riscv_vmsif_mask, // llvm.riscv.vmsif.mask - riscv_vmsle, // llvm.riscv.vmsle - riscv_vmsle_mask, // llvm.riscv.vmsle.mask - riscv_vmsleu, // llvm.riscv.vmsleu - riscv_vmsleu_mask, // llvm.riscv.vmsleu.mask - riscv_vmslt, // llvm.riscv.vmslt - riscv_vmslt_mask, // llvm.riscv.vmslt.mask - riscv_vmsltu, // llvm.riscv.vmsltu - riscv_vmsltu_mask, // llvm.riscv.vmsltu.mask - riscv_vmsne, // llvm.riscv.vmsne - riscv_vmsne_mask, // llvm.riscv.vmsne.mask - riscv_vmsof, // llvm.riscv.vmsof - riscv_vmsof_mask, // llvm.riscv.vmsof.mask - riscv_vmul, // llvm.riscv.vmul - riscv_vmul_mask, // llvm.riscv.vmul.mask - riscv_vmulh, // llvm.riscv.vmulh - riscv_vmulh_mask, // llvm.riscv.vmulh.mask - riscv_vmulhsu, // llvm.riscv.vmulhsu - riscv_vmulhsu_mask, // llvm.riscv.vmulhsu.mask - riscv_vmulhu, // llvm.riscv.vmulhu - riscv_vmulhu_mask, // llvm.riscv.vmulhu.mask - riscv_vmv_s_x, // llvm.riscv.vmv.s.x - riscv_vmv_v_v, // llvm.riscv.vmv.v.v - riscv_vmv_v_x, // llvm.riscv.vmv.v.x - riscv_vmv_x_s, // llvm.riscv.vmv.x.s - riscv_vmxnor, // llvm.riscv.vmxnor - riscv_vmxor, // llvm.riscv.vmxor - riscv_vnclip, // llvm.riscv.vnclip - riscv_vnclip_mask, // llvm.riscv.vnclip.mask - riscv_vnclipu, // llvm.riscv.vnclipu - riscv_vnclipu_mask, // llvm.riscv.vnclipu.mask - riscv_vnmsac, // llvm.riscv.vnmsac - riscv_vnmsac_mask, // llvm.riscv.vnmsac.mask - riscv_vnmsub, // llvm.riscv.vnmsub - riscv_vnmsub_mask, // llvm.riscv.vnmsub.mask - riscv_vnsra, // llvm.riscv.vnsra - riscv_vnsra_mask, // llvm.riscv.vnsra.mask - riscv_vnsrl, // llvm.riscv.vnsrl - riscv_vnsrl_mask, // llvm.riscv.vnsrl.mask - riscv_vor, // llvm.riscv.vor - riscv_vor_mask, // llvm.riscv.vor.mask - riscv_vredand, // llvm.riscv.vredand - riscv_vredand_mask, // llvm.riscv.vredand.mask - riscv_vredmax, // llvm.riscv.vredmax - riscv_vredmax_mask, // llvm.riscv.vredmax.mask - riscv_vredmaxu, // llvm.riscv.vredmaxu - riscv_vredmaxu_mask, // llvm.riscv.vredmaxu.mask - riscv_vredmin, // llvm.riscv.vredmin - riscv_vredmin_mask, // llvm.riscv.vredmin.mask - riscv_vredminu, // llvm.riscv.vredminu - riscv_vredminu_mask, // llvm.riscv.vredminu.mask - riscv_vredor, // llvm.riscv.vredor - riscv_vredor_mask, // llvm.riscv.vredor.mask - riscv_vredsum, // llvm.riscv.vredsum - riscv_vredsum_mask, // llvm.riscv.vredsum.mask - riscv_vredxor, // llvm.riscv.vredxor - riscv_vredxor_mask, // llvm.riscv.vredxor.mask - riscv_vrem, // llvm.riscv.vrem - riscv_vrem_mask, // llvm.riscv.vrem.mask - riscv_vremu, // llvm.riscv.vremu - riscv_vremu_mask, // llvm.riscv.vremu.mask - riscv_vrgather_vv, // llvm.riscv.vrgather.vv - riscv_vrgather_vv_mask, // llvm.riscv.vrgather.vv.mask - riscv_vrgather_vx, // llvm.riscv.vrgather.vx - riscv_vrgather_vx_mask, // llvm.riscv.vrgather.vx.mask - riscv_vrgatherei16_vv, // llvm.riscv.vrgatherei16.vv - riscv_vrgatherei16_vv_mask, // llvm.riscv.vrgatherei16.vv.mask - riscv_vrsub, // llvm.riscv.vrsub - riscv_vrsub_mask, // llvm.riscv.vrsub.mask - riscv_vsadd, // llvm.riscv.vsadd - riscv_vsadd_mask, // llvm.riscv.vsadd.mask - riscv_vsaddu, // llvm.riscv.vsaddu - riscv_vsaddu_mask, // llvm.riscv.vsaddu.mask - riscv_vsbc, // llvm.riscv.vsbc - riscv_vse, // llvm.riscv.vse - riscv_vse_mask, // llvm.riscv.vse.mask - riscv_vsetvli, // llvm.riscv.vsetvli - riscv_vsetvli_opt, // llvm.riscv.vsetvli.opt - riscv_vsetvlimax, // llvm.riscv.vsetvlimax - riscv_vsetvlimax_opt, // llvm.riscv.vsetvlimax.opt - riscv_vsext, // llvm.riscv.vsext - riscv_vsext_mask, // llvm.riscv.vsext.mask - riscv_vslide1down, // llvm.riscv.vslide1down - riscv_vslide1down_mask, // llvm.riscv.vslide1down.mask - riscv_vslide1up, // llvm.riscv.vslide1up - riscv_vslide1up_mask, // llvm.riscv.vslide1up.mask - riscv_vslidedown, // llvm.riscv.vslidedown - riscv_vslidedown_mask, // llvm.riscv.vslidedown.mask - riscv_vslideup, // llvm.riscv.vslideup - riscv_vslideup_mask, // llvm.riscv.vslideup.mask - riscv_vsll, // llvm.riscv.vsll - riscv_vsll_mask, // llvm.riscv.vsll.mask - riscv_vsm, // llvm.riscv.vsm - riscv_vsmul, // llvm.riscv.vsmul - riscv_vsmul_mask, // llvm.riscv.vsmul.mask - riscv_vsoxei, // llvm.riscv.vsoxei - riscv_vsoxei_mask, // llvm.riscv.vsoxei.mask - riscv_vsoxseg2, // llvm.riscv.vsoxseg2 - riscv_vsoxseg2_mask, // llvm.riscv.vsoxseg2.mask - riscv_vsoxseg3, // llvm.riscv.vsoxseg3 - riscv_vsoxseg3_mask, // llvm.riscv.vsoxseg3.mask - riscv_vsoxseg4, // llvm.riscv.vsoxseg4 - riscv_vsoxseg4_mask, // llvm.riscv.vsoxseg4.mask - riscv_vsoxseg5, // llvm.riscv.vsoxseg5 - riscv_vsoxseg5_mask, // llvm.riscv.vsoxseg5.mask - riscv_vsoxseg6, // llvm.riscv.vsoxseg6 - riscv_vsoxseg6_mask, // llvm.riscv.vsoxseg6.mask - riscv_vsoxseg7, // llvm.riscv.vsoxseg7 - riscv_vsoxseg7_mask, // llvm.riscv.vsoxseg7.mask - riscv_vsoxseg8, // llvm.riscv.vsoxseg8 - riscv_vsoxseg8_mask, // llvm.riscv.vsoxseg8.mask - riscv_vsra, // llvm.riscv.vsra - riscv_vsra_mask, // llvm.riscv.vsra.mask - riscv_vsrl, // llvm.riscv.vsrl - riscv_vsrl_mask, // llvm.riscv.vsrl.mask - riscv_vsse, // llvm.riscv.vsse - riscv_vsse_mask, // llvm.riscv.vsse.mask - riscv_vsseg2, // llvm.riscv.vsseg2 - riscv_vsseg2_mask, // llvm.riscv.vsseg2.mask - riscv_vsseg3, // llvm.riscv.vsseg3 - riscv_vsseg3_mask, // llvm.riscv.vsseg3.mask - riscv_vsseg4, // llvm.riscv.vsseg4 - riscv_vsseg4_mask, // llvm.riscv.vsseg4.mask - riscv_vsseg5, // llvm.riscv.vsseg5 - riscv_vsseg5_mask, // llvm.riscv.vsseg5.mask - riscv_vsseg6, // llvm.riscv.vsseg6 - riscv_vsseg6_mask, // llvm.riscv.vsseg6.mask - riscv_vsseg7, // llvm.riscv.vsseg7 - riscv_vsseg7_mask, // llvm.riscv.vsseg7.mask - riscv_vsseg8, // llvm.riscv.vsseg8 - riscv_vsseg8_mask, // llvm.riscv.vsseg8.mask - riscv_vssra, // llvm.riscv.vssra - riscv_vssra_mask, // llvm.riscv.vssra.mask - riscv_vssrl, // llvm.riscv.vssrl - riscv_vssrl_mask, // llvm.riscv.vssrl.mask - riscv_vssseg2, // llvm.riscv.vssseg2 - riscv_vssseg2_mask, // llvm.riscv.vssseg2.mask - riscv_vssseg3, // llvm.riscv.vssseg3 - riscv_vssseg3_mask, // llvm.riscv.vssseg3.mask - riscv_vssseg4, // llvm.riscv.vssseg4 - riscv_vssseg4_mask, // llvm.riscv.vssseg4.mask - riscv_vssseg5, // llvm.riscv.vssseg5 - riscv_vssseg5_mask, // llvm.riscv.vssseg5.mask - riscv_vssseg6, // llvm.riscv.vssseg6 - riscv_vssseg6_mask, // llvm.riscv.vssseg6.mask - riscv_vssseg7, // llvm.riscv.vssseg7 - riscv_vssseg7_mask, // llvm.riscv.vssseg7.mask - riscv_vssseg8, // llvm.riscv.vssseg8 - riscv_vssseg8_mask, // llvm.riscv.vssseg8.mask - riscv_vssub, // llvm.riscv.vssub - riscv_vssub_mask, // llvm.riscv.vssub.mask - riscv_vssubu, // llvm.riscv.vssubu - riscv_vssubu_mask, // llvm.riscv.vssubu.mask - riscv_vsub, // llvm.riscv.vsub - riscv_vsub_mask, // llvm.riscv.vsub.mask - riscv_vsuxei, // llvm.riscv.vsuxei - riscv_vsuxei_mask, // llvm.riscv.vsuxei.mask - riscv_vsuxseg2, // llvm.riscv.vsuxseg2 - riscv_vsuxseg2_mask, // llvm.riscv.vsuxseg2.mask - riscv_vsuxseg3, // llvm.riscv.vsuxseg3 - riscv_vsuxseg3_mask, // llvm.riscv.vsuxseg3.mask - riscv_vsuxseg4, // llvm.riscv.vsuxseg4 - riscv_vsuxseg4_mask, // llvm.riscv.vsuxseg4.mask - riscv_vsuxseg5, // llvm.riscv.vsuxseg5 - riscv_vsuxseg5_mask, // llvm.riscv.vsuxseg5.mask - riscv_vsuxseg6, // llvm.riscv.vsuxseg6 - riscv_vsuxseg6_mask, // llvm.riscv.vsuxseg6.mask - riscv_vsuxseg7, // llvm.riscv.vsuxseg7 - riscv_vsuxseg7_mask, // llvm.riscv.vsuxseg7.mask - riscv_vsuxseg8, // llvm.riscv.vsuxseg8 - riscv_vsuxseg8_mask, // llvm.riscv.vsuxseg8.mask - riscv_vwadd, // llvm.riscv.vwadd - riscv_vwadd_mask, // llvm.riscv.vwadd.mask - riscv_vwadd_w, // llvm.riscv.vwadd.w - riscv_vwadd_w_mask, // llvm.riscv.vwadd.w.mask - riscv_vwaddu, // llvm.riscv.vwaddu - riscv_vwaddu_mask, // llvm.riscv.vwaddu.mask - riscv_vwaddu_w, // llvm.riscv.vwaddu.w - riscv_vwaddu_w_mask, // llvm.riscv.vwaddu.w.mask - riscv_vwmacc, // llvm.riscv.vwmacc - riscv_vwmacc_mask, // llvm.riscv.vwmacc.mask - riscv_vwmaccsu, // llvm.riscv.vwmaccsu - riscv_vwmaccsu_mask, // llvm.riscv.vwmaccsu.mask - riscv_vwmaccu, // llvm.riscv.vwmaccu - riscv_vwmaccu_mask, // llvm.riscv.vwmaccu.mask - riscv_vwmaccus, // llvm.riscv.vwmaccus - riscv_vwmaccus_mask, // llvm.riscv.vwmaccus.mask - riscv_vwmul, // llvm.riscv.vwmul - riscv_vwmul_mask, // llvm.riscv.vwmul.mask - riscv_vwmulsu, // llvm.riscv.vwmulsu - riscv_vwmulsu_mask, // llvm.riscv.vwmulsu.mask - riscv_vwmulu, // llvm.riscv.vwmulu - riscv_vwmulu_mask, // llvm.riscv.vwmulu.mask - riscv_vwredsum, // llvm.riscv.vwredsum - riscv_vwredsum_mask, // llvm.riscv.vwredsum.mask - riscv_vwredsumu, // llvm.riscv.vwredsumu - riscv_vwredsumu_mask, // llvm.riscv.vwredsumu.mask - riscv_vwsub, // llvm.riscv.vwsub - riscv_vwsub_mask, // llvm.riscv.vwsub.mask - riscv_vwsub_w, // llvm.riscv.vwsub.w - riscv_vwsub_w_mask, // llvm.riscv.vwsub.w.mask - riscv_vwsubu, // llvm.riscv.vwsubu - riscv_vwsubu_mask, // llvm.riscv.vwsubu.mask - riscv_vwsubu_w, // llvm.riscv.vwsubu.w - riscv_vwsubu_w_mask, // llvm.riscv.vwsubu.w.mask - riscv_vxor, // llvm.riscv.vxor - riscv_vxor_mask, // llvm.riscv.vxor.mask - riscv_vzext, // llvm.riscv.vzext - riscv_vzext_mask, // llvm.riscv.vzext.mask - riscv_xperm_b, // llvm.riscv.xperm.b - riscv_xperm_h, // llvm.riscv.xperm.h - riscv_xperm_n, // llvm.riscv.xperm.n - riscv_xperm_w, // llvm.riscv.xperm.w - riscv_xperm4, // llvm.riscv.xperm4 - riscv_xperm8, // llvm.riscv.xperm8 - riscv_zip, // llvm.riscv.zip -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.td deleted file mode 100644 index 6780436bd7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsRISCV.td +++ /dev/null @@ -1,1555 +0,0 @@ -//===- IntrinsicsRISCV.td - Defines RISCV intrinsics -------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the RISCV-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Atomics - -// Atomic Intrinsics have multiple versions for different access widths, which -// all follow one of the following signatures (depending on how many arguments -// they require). We carefully instantiate only specific versions of these for -// specific integer widths, rather than using `llvm_anyint_ty`. -// -// In fact, as these intrinsics take `llvm_anyptr_ty`, the given names are the -// canonical names, and the intrinsics used in the code will have a name -// suffixed with the pointer type they are specialised for (denoted `

` in the -// names below), in order to avoid type conflicts. - -let TargetPrefix = "riscv" in { - - // T @llvm..T.

(any*, T, T, T imm); - class MaskedAtomicRMWFourArg - : Intrinsic<[itype], [llvm_anyptr_ty, itype, itype, itype], - [IntrArgMemOnly, NoCapture>, ImmArg>]>; - // T @llvm..T.

(any*, T, T, T, T imm); - class MaskedAtomicRMWFiveArg - : Intrinsic<[itype], [llvm_anyptr_ty, itype, itype, itype, itype], - [IntrArgMemOnly, NoCapture>, ImmArg>]>; - - // We define 32-bit and 64-bit variants of the above, where T stands for i32 - // or i64 respectively: - multiclass MaskedAtomicRMWFourArgIntrinsics { - // i32 @llvm..i32.

(any*, i32, i32, i32 imm); - def _i32 : MaskedAtomicRMWFourArg; - // i64 @llvm..i32.

(any*, i64, i64, i64 imm); - def _i64 : MaskedAtomicRMWFourArg; - } - - multiclass MaskedAtomicRMWFiveArgIntrinsics { - // i32 @llvm..i32.

(any*, i32, i32, i32, i32 imm); - def _i32 : MaskedAtomicRMWFiveArg; - // i64 @llvm..i64.

(any*, i64, i64, i64, i64 imm); - def _i64 : MaskedAtomicRMWFiveArg; - } - - // @llvm.riscv.masked.atomicrmw.*.{i32,i64}.

(...) - defm int_riscv_masked_atomicrmw_xchg : MaskedAtomicRMWFourArgIntrinsics; - defm int_riscv_masked_atomicrmw_add : MaskedAtomicRMWFourArgIntrinsics; - defm int_riscv_masked_atomicrmw_sub : MaskedAtomicRMWFourArgIntrinsics; - defm int_riscv_masked_atomicrmw_nand : MaskedAtomicRMWFourArgIntrinsics; - // Signed min and max need an extra operand to do sign extension with. - defm int_riscv_masked_atomicrmw_max : MaskedAtomicRMWFiveArgIntrinsics; - defm int_riscv_masked_atomicrmw_min : MaskedAtomicRMWFiveArgIntrinsics; - // Unsigned min and max don't need the extra operand. - defm int_riscv_masked_atomicrmw_umax : MaskedAtomicRMWFourArgIntrinsics; - defm int_riscv_masked_atomicrmw_umin : MaskedAtomicRMWFourArgIntrinsics; - - // @llvm.riscv.masked.cmpxchg.{i32,i64}.

(...) - defm int_riscv_masked_cmpxchg : MaskedAtomicRMWFiveArgIntrinsics; - -} // TargetPrefix = "riscv" - -//===----------------------------------------------------------------------===// -// Bitmanip (Bit Manipulation) Extension - -let TargetPrefix = "riscv" in { - - class BitManipGPRIntrinsics - : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - class BitManipGPRGPRIntrinsics - : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - class BitManipGPRGPRGRIntrinsics - : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; - - // Zbb - def int_riscv_orc_b : BitManipGPRIntrinsics; - - // Zbc or Zbkc - def int_riscv_clmul : BitManipGPRGPRIntrinsics; - def int_riscv_clmulh : BitManipGPRGPRIntrinsics; - - // Zbc - def int_riscv_clmulr : BitManipGPRGPRIntrinsics; - - // Zbe - def int_riscv_bcompress : BitManipGPRGPRIntrinsics; - def int_riscv_bdecompress : BitManipGPRGPRIntrinsics; - - // Zbf - def int_riscv_bfp : BitManipGPRGPRIntrinsics; - - // Zbp - def int_riscv_grev : BitManipGPRGPRIntrinsics; - def int_riscv_gorc : BitManipGPRGPRIntrinsics; - def int_riscv_shfl : BitManipGPRGPRIntrinsics; - def int_riscv_unshfl : BitManipGPRGPRIntrinsics; - def int_riscv_xperm_n : BitManipGPRGPRIntrinsics; - def int_riscv_xperm_b : BitManipGPRGPRIntrinsics; - def int_riscv_xperm_h : BitManipGPRGPRIntrinsics; - def int_riscv_xperm_w : BitManipGPRGPRIntrinsics; - - // Zbr - def int_riscv_crc32_b : BitManipGPRIntrinsics; - def int_riscv_crc32_h : BitManipGPRIntrinsics; - def int_riscv_crc32_w : BitManipGPRIntrinsics; - def int_riscv_crc32_d : BitManipGPRIntrinsics; - def int_riscv_crc32c_b : BitManipGPRIntrinsics; - def int_riscv_crc32c_h : BitManipGPRIntrinsics; - def int_riscv_crc32c_w : BitManipGPRIntrinsics; - def int_riscv_crc32c_d : BitManipGPRIntrinsics; - - // Zbt - def int_riscv_fsl : BitManipGPRGPRGRIntrinsics; - def int_riscv_fsr : BitManipGPRGPRGRIntrinsics; - - // Zbkb - def int_riscv_brev8 : BitManipGPRIntrinsics; - def int_riscv_zip : BitManipGPRIntrinsics; - def int_riscv_unzip : BitManipGPRIntrinsics; - - // Zbkx - def int_riscv_xperm4 : BitManipGPRGPRIntrinsics; - def int_riscv_xperm8 : BitManipGPRGPRIntrinsics; -} // TargetPrefix = "riscv" - -//===----------------------------------------------------------------------===// -// Vectors - -// The intrinsic does not have any operand that must be extended. -defvar NoSplatOperand = 0xF; - -// The intrinsic does not have a VL operand. -// (e.g., riscv_vmv_x_s and riscv_vfmv_f_s) -defvar NoVLOperand = 0x1F; - -class RISCVVIntrinsic { - // These intrinsics may accept illegal integer values in their llvm_any_ty - // operand, so they have to be extended. - Intrinsic IntrinsicID = !cast(NAME); - bits<4> SplatOperand = NoSplatOperand; - bits<5> VLOperand = NoVLOperand; -} - -let TargetPrefix = "riscv" in { - // We use anyint here but we only support XLen. - def int_riscv_vsetvli : Intrinsic<[llvm_anyint_ty], - /* AVL */ [LLVMMatchType<0>, - /* VSEW */ LLVMMatchType<0>, - /* VLMUL */ LLVMMatchType<0>], - [IntrNoMem, IntrHasSideEffects, - ImmArg>, - ImmArg>]>; - def int_riscv_vsetvlimax : Intrinsic<[llvm_anyint_ty], - /* VSEW */ [LLVMMatchType<0>, - /* VLMUL */ LLVMMatchType<0>], - [IntrNoMem, IntrHasSideEffects, - ImmArg>, - ImmArg>]>; - - // Versions without side effects: better optimizable and usable if only the - // returned vector length is important. - def int_riscv_vsetvli_opt : Intrinsic<[llvm_anyint_ty], - /* AVL */ [LLVMMatchType<0>, - /* VSEW */ LLVMMatchType<0>, - /* VLMUL */ LLVMMatchType<0>], - [IntrNoMem, - ImmArg>, - ImmArg>]>; - def int_riscv_vsetvlimax_opt : Intrinsic<[llvm_anyint_ty], - /* VSEW */ [LLVMMatchType<0>, - /* VLMUL */ LLVMMatchType<0>], - [IntrNoMem, - ImmArg>, - ImmArg>]>; - - // For unit stride mask load - // Input: (pointer, vl) - class RISCVUSMLoad - : Intrinsic<[llvm_anyvector_ty], - [LLVMPointerType>, - llvm_anyint_ty], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For unit stride load - // Input: (passthru, pointer, vl) - class RISCVUSLoad - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMPointerType>, - llvm_anyint_ty], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For unit stride fault-only-first load - // Input: (passthru, pointer, vl) - // Output: (data, vl) - // NOTE: We model this with default memory properties since we model writing - // VL as a side effect. IntrReadMem, IntrHasSideEffects does not work. - class RISCVUSLoadFF - : Intrinsic<[llvm_anyvector_ty, llvm_anyint_ty], - [LLVMMatchType<0>, - LLVMPointerType>, LLVMMatchType<1>], - [NoCapture>]>, - RISCVVIntrinsic { - let VLOperand = 2; - } - // For unit stride load with mask - // Input: (maskedoff, pointer, mask, vl, ta) - class RISCVUSLoadMask - : Intrinsic<[llvm_anyvector_ty ], - [LLVMMatchType<0>, - LLVMPointerType>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty, LLVMMatchType<1>], - [NoCapture>, ImmArg>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = 3; - } - // For unit stride fault-only-first load with mask - // Input: (maskedoff, pointer, mask, vl, ta) - // Output: (data, vl) - // NOTE: We model this with default memory properties since we model writing - // VL as a side effect. IntrReadMem, IntrHasSideEffects does not work. - class RISCVUSLoadFFMask - : Intrinsic<[llvm_anyvector_ty, llvm_anyint_ty], - [LLVMMatchType<0>, - LLVMPointerType>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<1>, LLVMMatchType<1>], - [NoCapture>, ImmArg>]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For strided load with passthru operand - // Input: (passthru, pointer, stride, vl) - class RISCVSLoad - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMPointerType>, - llvm_anyint_ty, LLVMMatchType<1>], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For strided load with mask - // Input: (maskedoff, pointer, stride, mask, vl, ta) - class RISCVSLoadMask - : Intrinsic<[llvm_anyvector_ty ], - [LLVMMatchType<0>, - LLVMPointerType>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>, - LLVMMatchType<1>], - [NoCapture>, ImmArg>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = 4; - } - // For indexed load with passthru operand - // Input: (passthru, pointer, index, vl) - class RISCVILoad - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMPointerType>, - llvm_anyvector_ty, llvm_anyint_ty], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For indexed load with mask - // Input: (maskedoff, pointer, index, mask, vl, ta) - class RISCVILoadMask - : Intrinsic<[llvm_anyvector_ty ], - [LLVMMatchType<0>, - LLVMPointerType>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [NoCapture>, ImmArg>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = 4; - } - // For unit stride store - // Input: (vector_in, pointer, vl) - class RISCVUSStore - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, - llvm_anyint_ty], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For unit stride store with mask - // Input: (vector_in, pointer, mask, vl) - class RISCVUSStoreMask - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For strided store - // Input: (vector_in, pointer, stride, vl) - class RISCVSStore - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, - llvm_anyint_ty, LLVMMatchType<1>], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For stride store with mask - // Input: (vector_in, pointer, stirde, mask, vl) - class RISCVSStoreMask - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For indexed store - // Input: (vector_in, pointer, index, vl) - class RISCVIStore - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, - llvm_anyint_ty, llvm_anyint_ty], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For indexed store with mask - // Input: (vector_in, pointer, index, mask, vl) - class RISCVIStoreMask - : Intrinsic<[], - [llvm_anyvector_ty, - LLVMPointerType>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For destination vector type is the same as source vector. - // Input: (vector_in, vl) - class RISCVUnaryAANoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For destination vector type is the same as first source vector (with mask). - // Input: (vector_in, mask, vl, ta) - class RISCVUnaryAAMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<1>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - class RISCVUnaryAAMaskNoTA - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For destination vector type is the same as first and second source vector. - // Input: (vector_in, vector_in, vl) - class RISCVBinaryAAANoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is the same as first and second source vector. - // Input: (vector_in, int_vector_in, vl) - class RISCVRGatherVVNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMVectorOfBitcastsToInt<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is the same as first and second source vector. - // Input: (vector_in, vector_in, int_vector_in, vl, ta) - class RISCVRGatherVVMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMVectorOfBitcastsToInt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<1>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // Input: (vector_in, int16_vector_in, vl) - class RISCVRGatherEI16VVNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i16_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is the same as first and second source vector. - // Input: (vector_in, vector_in, int16_vector_in, vl, ta) - class RISCVRGatherEI16VVMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i16_ty>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<1>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For destination vector type is the same as first source vector, and the - // second operand is XLen. - // Input: (vector_in, xlen_in, vl) - class RISCVGatherVXNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyint_ty, LLVMMatchType<1>], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is the same as first source vector (with mask). - // Second operand is XLen. - // Input: (maskedoff, vector_in, xlen_in, mask, vl, ta) - class RISCVGatherVXMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>, - LLVMMatchType<1>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For destination vector type is the same as first source vector. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVBinaryAAXNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 2; - } - // For destination vector type is the same as first source vector (with mask). - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVBinaryAAXMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 2; - let VLOperand = 4; - } - // For destination vector type is the same as first source vector. The - // second source operand must match the destination type or be an XLen scalar. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVBinaryAAShiftNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is the same as first source vector (with mask). - // The second source operand must match the destination type or be an XLen scalar. - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVBinaryAAShiftMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For destination vector type is NOT the same as first source vector. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVBinaryABXNoMask - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 2; - } - // For destination vector type is NOT the same as first source vector (with mask). - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVBinaryABXMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<3>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 2; - let VLOperand = 4; - } - // For destination vector type is NOT the same as first source vector. The - // second source operand must match the destination type or be an XLen scalar. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVBinaryABShiftNoMask - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is NOT the same as first source vector (with mask). - // The second source operand must match the destination type or be an XLen scalar. - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVBinaryABShiftMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<3>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For binary operations with V0 as input. - // Input: (vector_in, vector_in/scalar_in, V0, vl) - class RISCVBinaryWithV0 - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 3; - } - // For binary operations with mask type output and V0 as input. - // Output: (mask type output) - // Input: (vector_in, vector_in/scalar_in, V0, vl) - class RISCVBinaryMOutWithV0 - :Intrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 3; - } - // For binary operations with mask type output. - // Output: (mask type output) - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVBinaryMOut - : Intrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 2; - } - // For binary operations with mask type output without mask. - // Output: (mask type output) - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVCompareNoMask - : Intrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 2; - } - // For binary operations with mask type output with mask. - // Output: (mask type output) - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl) - class RISCVCompareMask - : Intrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 2; - let VLOperand = 4; - } - // For FP classify operations. - // Output: (bit mask type output) - // Input: (vector_in, vl) - class RISCVClassifyNoMask - : Intrinsic<[LLVMVectorOfBitcastsToInt<0>], - [llvm_anyvector_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For FP classify operations with mask. - // Output: (bit mask type output) - // Input: (maskedoff, vector_in, mask, vl) - class RISCVClassifyMask - : Intrinsic<[LLVMVectorOfBitcastsToInt<0>], - [LLVMVectorOfBitcastsToInt<0>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For Saturating binary operations. - // The destination vector type is the same as first source vector. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVSaturatingBinaryAAXNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 2; - } - // For Saturating binary operations with mask. - // The destination vector type is the same as first source vector. - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVSaturatingBinaryAAXMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [ImmArg>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let SplatOperand = 2; - let VLOperand = 4; - } - // For Saturating binary operations. - // The destination vector type is the same as first source vector. - // The second source operand matches the destination type or is an XLen scalar. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVSaturatingBinaryAAShiftNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For Saturating binary operations with mask. - // The destination vector type is the same as first source vector. - // The second source operand matches the destination type or is an XLen scalar. - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVSaturatingBinaryAAShiftMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [ImmArg>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For Saturating binary operations. - // The destination vector type is NOT the same as first source vector. - // The second source operand matches the destination type or is an XLen scalar. - // Input: (vector_in, vector_in/scalar_in, vl) - class RISCVSaturatingBinaryABShiftNoMask - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], - [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For Saturating binary operations with mask. - // The destination vector type is NOT the same as first source vector (with mask). - // The second source operand matches the destination type or is an XLen scalar. - // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) - class RISCVSaturatingBinaryABShiftMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<3>], - [ImmArg>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { - let VLOperand = 4; - } - class RISCVTernaryAAAXNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty, - LLVMMatchType<1>], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - class RISCVTernaryAAAXMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - class RISCVTernaryAAXANoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, LLVMMatchType<0>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 3; - } - class RISCVTernaryAAXAMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 4; - } - class RISCVTernaryWideNoMask - : Intrinsic< [llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyvector_ty, - llvm_anyint_ty], - [IntrNoMem] >, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 3; - } - class RISCVTernaryWideMask - : Intrinsic< [llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_any_ty, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let SplatOperand = 1; - let VLOperand = 4; - } - // For Reduction ternary operations. - // For destination vector type is the same as first and third source vector. - // Input: (vector_in, vector_in, vector_in, vl) - class RISCVReductionNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For Reduction ternary operations with mask. - // For destination vector type is the same as first and third source vector. - // The mask type come from second source vector. - // Input: (maskedoff, vector_in, vector_in, vector_in, mask, vl) - class RISCVReductionMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 4; - } - // For unary operations with scalar type output without mask - // Output: (scalar type) - // Input: (vector_in, vl) - class RISCVMaskUnarySOutNoMask - : Intrinsic<[LLVMMatchType<1>], - [llvm_anyvector_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For unary operations with scalar type output with mask - // Output: (scalar type) - // Input: (vector_in, mask, vl) - class RISCVMaskUnarySOutMask - : Intrinsic<[LLVMMatchType<1>], - [llvm_anyvector_ty, LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For destination vector type is NOT the same as source vector. - // Input: (vector_in, vl) - class RISCVUnaryABNoMask - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For destination vector type is NOT the same as source vector (with mask). - // Input: (maskedoff, vector_in, mask, vl, ta) - class RISCVUnaryABMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>, - llvm_anyint_ty, LLVMMatchType<2>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // For unary operations with the same vector type in/out without mask - // Output: (vector) - // Input: (vector_in, vl) - class RISCVUnaryNoMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For mask unary operations with mask type in/out with mask - // Output: (mask type output) - // Input: (mask type maskedoff, mask type vector_in, mask, vl) - class RISCVMaskUnaryMOutMask - : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // Output: (vector) - // Input: (vl) - class RISCVNullaryIntrinsic - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 0; - } - // For Conversion unary operations. - // Input: (vector_in, vl) - class RISCVConversionNoMask - : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For Conversion unary operations with mask. - // Input: (maskedoff, vector_in, mask, vl, ta) - class RISCVConversionMask - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, - LLVMMatchType<2>], - [ImmArg>, IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - - // For unit stride segment load - // Input: (pointer, vl) - class RISCVUSSegLoad - : Intrinsic, - !add(nf, -1))), - [LLVMPointerToElt<0>, llvm_anyint_ty], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For unit stride segment load with mask - // Input: (maskedoff, pointer, mask, vl, ta) - class RISCVUSSegLoadMask - : Intrinsic, - !add(nf, -1))), - !listconcat(!listsplat(LLVMMatchType<0>, nf), - [LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty, LLVMMatchType<1>]), - [ImmArg>, NoCapture>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = !add(nf, 2); - } - - // For unit stride fault-only-first segment load - // Input: (pointer, vl) - // Output: (data, vl) - // NOTE: We model this with default memory properties since we model writing - // VL as a side effect. IntrReadMem, IntrHasSideEffects does not work. - class RISCVUSSegLoadFF - : Intrinsic, - !add(nf, -1)), [llvm_anyint_ty]), - [LLVMPointerToElt<0>, LLVMMatchType<1>], - [NoCapture>]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // For unit stride fault-only-first segment load with mask - // Input: (maskedoff, pointer, mask, vl, ta) - // Output: (data, vl) - // NOTE: We model this with default memory properties since we model writing - // VL as a side effect. IntrReadMem, IntrHasSideEffects does not work. - class RISCVUSSegLoadFFMask - : Intrinsic, - !add(nf, -1)), [llvm_anyint_ty]), - !listconcat(!listsplat(LLVMMatchType<0>, nf), - [LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<1>, LLVMMatchType<1>]), - [ImmArg>, NoCapture>]>, - RISCVVIntrinsic { - let VLOperand = !add(nf, 2); - } - - // For stride segment load - // Input: (pointer, offset, vl) - class RISCVSSegLoad - : Intrinsic, - !add(nf, -1))), - [LLVMPointerToElt<0>, llvm_anyint_ty, LLVMMatchType<1>], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For stride segment load with mask - // Input: (maskedoff, pointer, offset, mask, vl, ta) - class RISCVSSegLoadMask - : Intrinsic, - !add(nf, -1))), - !listconcat(!listsplat(LLVMMatchType<0>, nf), - [LLVMPointerToElt<0>, - llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<1>, LLVMMatchType<1>]), - [ImmArg>, NoCapture>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = !add(nf, 3); - } - - // For indexed segment load - // Input: (pointer, index, vl) - class RISCVISegLoad - : Intrinsic, - !add(nf, -1))), - [LLVMPointerToElt<0>, llvm_anyvector_ty, llvm_anyint_ty], - [NoCapture>, IntrReadMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - // For indexed segment load with mask - // Input: (maskedoff, pointer, index, mask, vl, ta) - class RISCVISegLoadMask - : Intrinsic, - !add(nf, -1))), - !listconcat(!listsplat(LLVMMatchType<0>, nf), - [LLVMPointerToElt<0>, - llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty, LLVMMatchType<2>]), - [ImmArg>, NoCapture>, IntrReadMem]>, - RISCVVIntrinsic { - let VLOperand = !add(nf, 3); - } - - // For unit stride segment store - // Input: (value, pointer, vl) - class RISCVUSSegStore - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, llvm_anyint_ty]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 1); - } - // For unit stride segment store with mask - // Input: (value, pointer, mask, vl) - class RISCVUSSegStoreMask - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 2); - } - - // For stride segment store - // Input: (value, pointer, offset, vl) - class RISCVSSegStore - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, llvm_anyint_ty, - LLVMMatchType<1>]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 2); - } - // For stride segment store with mask - // Input: (value, pointer, offset, mask, vl) - class RISCVSSegStoreMask - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMMatchType<1>]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 3); - } - - // For indexed segment store - // Input: (value, pointer, offset, vl) - class RISCVISegStore - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, llvm_anyvector_ty, - llvm_anyint_ty]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 2); - } - // For indexed segment store with mask - // Input: (value, pointer, offset, mask, vl) - class RISCVISegStoreMask - : Intrinsic<[], - !listconcat([llvm_anyvector_ty], - !listsplat(LLVMMatchType<0>, !add(nf, -1)), - [LLVMPointerToElt<0>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty]), - [NoCapture>, IntrWriteMem]>, RISCVVIntrinsic { - let VLOperand = !add(nf, 3); - } - - multiclass RISCVUSLoad { - def "int_riscv_" # NAME : RISCVUSLoad; - def "int_riscv_" # NAME # "_mask" : RISCVUSLoadMask; - } - multiclass RISCVUSLoadFF { - def "int_riscv_" # NAME : RISCVUSLoadFF; - def "int_riscv_" # NAME # "_mask" : RISCVUSLoadFFMask; - } - multiclass RISCVSLoad { - def "int_riscv_" # NAME : RISCVSLoad; - def "int_riscv_" # NAME # "_mask" : RISCVSLoadMask; - } - multiclass RISCVILoad { - def "int_riscv_" # NAME : RISCVILoad; - def "int_riscv_" # NAME # "_mask" : RISCVILoadMask; - } - multiclass RISCVUSStore { - def "int_riscv_" # NAME : RISCVUSStore; - def "int_riscv_" # NAME # "_mask" : RISCVUSStoreMask; - } - multiclass RISCVSStore { - def "int_riscv_" # NAME : RISCVSStore; - def "int_riscv_" # NAME # "_mask" : RISCVSStoreMask; - } - - multiclass RISCVIStore { - def "int_riscv_" # NAME : RISCVIStore; - def "int_riscv_" # NAME # "_mask" : RISCVIStoreMask; - } - multiclass RISCVUnaryAA { - def "int_riscv_" # NAME : RISCVUnaryAANoMask; - def "int_riscv_" # NAME # "_mask" : RISCVUnaryAAMask; - } - multiclass RISCVUnaryAB { - def "int_riscv_" # NAME : RISCVUnaryABNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVUnaryABMask; - } - // AAX means the destination type(A) is the same as the first source - // type(A). X means any type for the second source operand. - multiclass RISCVBinaryAAX { - def "int_riscv_" # NAME : RISCVBinaryAAXNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAXMask; - } - // Like RISCVBinaryAAX, but the second operand is used a shift amount so it - // must be a vector or an XLen scalar. - multiclass RISCVBinaryAAShift { - def "int_riscv_" # NAME : RISCVBinaryAAShiftNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAShiftMask; - } - multiclass RISCVRGatherVV { - def "int_riscv_" # NAME : RISCVRGatherVVNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVRGatherVVMask; - } - multiclass RISCVRGatherVX { - def "int_riscv_" # NAME : RISCVGatherVXNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVGatherVXMask; - } - multiclass RISCVRGatherEI16VV { - def "int_riscv_" # NAME : RISCVRGatherEI16VVNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVRGatherEI16VVMask; - } - // ABX means the destination type(A) is different from the first source - // type(B). X means any type for the second source operand. - multiclass RISCVBinaryABX { - def "int_riscv_" # NAME : RISCVBinaryABXNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVBinaryABXMask; - } - // Like RISCVBinaryABX, but the second operand is used a shift amount so it - // must be a vector or an XLen scalar. - multiclass RISCVBinaryABShift { - def "int_riscv_" # NAME : RISCVBinaryABShiftNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVBinaryABShiftMask; - } - multiclass RISCVBinaryWithV0 { - def "int_riscv_" # NAME : RISCVBinaryWithV0; - } - multiclass RISCVBinaryMaskOutWithV0 { - def "int_riscv_" # NAME : RISCVBinaryMOutWithV0; - } - multiclass RISCVBinaryMaskOut { - def "int_riscv_" # NAME : RISCVBinaryMOut; - } - multiclass RISCVSaturatingBinaryAAX { - def "int_riscv_" # NAME : RISCVSaturatingBinaryAAXNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAXMask; - } - multiclass RISCVSaturatingBinaryAAShift { - def "int_riscv_" # NAME : RISCVSaturatingBinaryAAShiftNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAShiftMask; - } - multiclass RISCVSaturatingBinaryABShift { - def "int_riscv_" # NAME : RISCVSaturatingBinaryABShiftNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryABShiftMask; - } - multiclass RISCVTernaryAAAX { - def "int_riscv_" # NAME : RISCVTernaryAAAXNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVTernaryAAAXMask; - } - multiclass RISCVTernaryAAXA { - def "int_riscv_" # NAME : RISCVTernaryAAXANoMask; - def "int_riscv_" # NAME # "_mask" : RISCVTernaryAAXAMask; - } - multiclass RISCVCompare { - def "int_riscv_" # NAME : RISCVCompareNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVCompareMask; - } - multiclass RISCVClassify { - def "int_riscv_" # NAME : RISCVClassifyNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVClassifyMask; - } - multiclass RISCVTernaryWide { - def "int_riscv_" # NAME : RISCVTernaryWideNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVTernaryWideMask; - } - multiclass RISCVReduction { - def "int_riscv_" # NAME : RISCVReductionNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVReductionMask; - } - multiclass RISCVMaskUnarySOut { - def "int_riscv_" # NAME : RISCVMaskUnarySOutNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVMaskUnarySOutMask; - } - multiclass RISCVMaskUnaryMOut { - def "int_riscv_" # NAME : RISCVUnaryNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVMaskUnaryMOutMask; - } - multiclass RISCVConversion { - def "int_riscv_" #NAME :RISCVConversionNoMask; - def "int_riscv_" # NAME # "_mask" : RISCVConversionMask; - } - multiclass RISCVUSSegLoad { - def "int_riscv_" # NAME : RISCVUSSegLoad; - def "int_riscv_" # NAME # "_mask" : RISCVUSSegLoadMask; - } - multiclass RISCVUSSegLoadFF { - def "int_riscv_" # NAME : RISCVUSSegLoadFF; - def "int_riscv_" # NAME # "_mask" : RISCVUSSegLoadFFMask; - } - multiclass RISCVSSegLoad { - def "int_riscv_" # NAME : RISCVSSegLoad; - def "int_riscv_" # NAME # "_mask" : RISCVSSegLoadMask; - } - multiclass RISCVISegLoad { - def "int_riscv_" # NAME : RISCVISegLoad; - def "int_riscv_" # NAME # "_mask" : RISCVISegLoadMask; - } - multiclass RISCVUSSegStore { - def "int_riscv_" # NAME : RISCVUSSegStore; - def "int_riscv_" # NAME # "_mask" : RISCVUSSegStoreMask; - } - multiclass RISCVSSegStore { - def "int_riscv_" # NAME : RISCVSSegStore; - def "int_riscv_" # NAME # "_mask" : RISCVSSegStoreMask; - } - multiclass RISCVISegStore { - def "int_riscv_" # NAME : RISCVISegStore; - def "int_riscv_" # NAME # "_mask" : RISCVISegStoreMask; - } - - defm vle : RISCVUSLoad; - defm vleff : RISCVUSLoadFF; - defm vse : RISCVUSStore; - defm vlse: RISCVSLoad; - defm vsse: RISCVSStore; - defm vluxei : RISCVILoad; - defm vloxei : RISCVILoad; - defm vsoxei : RISCVIStore; - defm vsuxei : RISCVIStore; - - def int_riscv_vlm : RISCVUSMLoad; - def int_riscv_vsm : RISCVUSStore; - - defm vadd : RISCVBinaryAAX; - defm vsub : RISCVBinaryAAX; - defm vrsub : RISCVBinaryAAX; - - defm vwaddu : RISCVBinaryABX; - defm vwadd : RISCVBinaryABX; - defm vwaddu_w : RISCVBinaryAAX; - defm vwadd_w : RISCVBinaryAAX; - defm vwsubu : RISCVBinaryABX; - defm vwsub : RISCVBinaryABX; - defm vwsubu_w : RISCVBinaryAAX; - defm vwsub_w : RISCVBinaryAAX; - - defm vzext : RISCVUnaryAB; - defm vsext : RISCVUnaryAB; - - defm vadc : RISCVBinaryWithV0; - defm vmadc_carry_in : RISCVBinaryMaskOutWithV0; - defm vmadc : RISCVBinaryMaskOut; - - defm vsbc : RISCVBinaryWithV0; - defm vmsbc_borrow_in : RISCVBinaryMaskOutWithV0; - defm vmsbc : RISCVBinaryMaskOut; - - defm vand : RISCVBinaryAAX; - defm vor : RISCVBinaryAAX; - defm vxor : RISCVBinaryAAX; - - defm vsll : RISCVBinaryAAShift; - defm vsrl : RISCVBinaryAAShift; - defm vsra : RISCVBinaryAAShift; - - defm vnsrl : RISCVBinaryABShift; - defm vnsra : RISCVBinaryABShift; - - defm vmseq : RISCVCompare; - defm vmsne : RISCVCompare; - defm vmsltu : RISCVCompare; - defm vmslt : RISCVCompare; - defm vmsleu : RISCVCompare; - defm vmsle : RISCVCompare; - defm vmsgtu : RISCVCompare; - defm vmsgt : RISCVCompare; - defm vmsgeu : RISCVCompare; - defm vmsge : RISCVCompare; - - defm vminu : RISCVBinaryAAX; - defm vmin : RISCVBinaryAAX; - defm vmaxu : RISCVBinaryAAX; - defm vmax : RISCVBinaryAAX; - - defm vmul : RISCVBinaryAAX; - defm vmulh : RISCVBinaryAAX; - defm vmulhu : RISCVBinaryAAX; - defm vmulhsu : RISCVBinaryAAX; - - defm vdivu : RISCVBinaryAAX; - defm vdiv : RISCVBinaryAAX; - defm vremu : RISCVBinaryAAX; - defm vrem : RISCVBinaryAAX; - - defm vwmul : RISCVBinaryABX; - defm vwmulu : RISCVBinaryABX; - defm vwmulsu : RISCVBinaryABX; - - defm vmacc : RISCVTernaryAAXA; - defm vnmsac : RISCVTernaryAAXA; - defm vmadd : RISCVTernaryAAXA; - defm vnmsub : RISCVTernaryAAXA; - - defm vwmaccu : RISCVTernaryWide; - defm vwmacc : RISCVTernaryWide; - defm vwmaccus : RISCVTernaryWide; - defm vwmaccsu : RISCVTernaryWide; - - defm vfadd : RISCVBinaryAAX; - defm vfsub : RISCVBinaryAAX; - defm vfrsub : RISCVBinaryAAX; - - defm vfwadd : RISCVBinaryABX; - defm vfwsub : RISCVBinaryABX; - defm vfwadd_w : RISCVBinaryAAX; - defm vfwsub_w : RISCVBinaryAAX; - - defm vsaddu : RISCVSaturatingBinaryAAX; - defm vsadd : RISCVSaturatingBinaryAAX; - defm vssubu : RISCVSaturatingBinaryAAX; - defm vssub : RISCVSaturatingBinaryAAX; - - defm vmerge : RISCVBinaryWithV0; - - def int_riscv_vmv_v_v : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - def int_riscv_vmv_v_x : Intrinsic<[llvm_anyint_ty], - [LLVMVectorElementType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - def int_riscv_vfmv_v_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMVectorElementType<0>, llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - - def int_riscv_vmv_x_s : Intrinsic<[LLVMVectorElementType<0>], - [llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic; - def int_riscv_vmv_s_x : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMVectorElementType<0>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - - def int_riscv_vfmv_f_s : Intrinsic<[LLVMVectorElementType<0>], - [llvm_anyfloat_ty], - [IntrNoMem]>, RISCVVIntrinsic; - def int_riscv_vfmv_s_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMVectorElementType<0>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - - defm vfmul : RISCVBinaryAAX; - defm vfdiv : RISCVBinaryAAX; - defm vfrdiv : RISCVBinaryAAX; - - defm vfwmul : RISCVBinaryABX; - - defm vfmacc : RISCVTernaryAAXA; - defm vfnmacc : RISCVTernaryAAXA; - defm vfmsac : RISCVTernaryAAXA; - defm vfnmsac : RISCVTernaryAAXA; - defm vfmadd : RISCVTernaryAAXA; - defm vfnmadd : RISCVTernaryAAXA; - defm vfmsub : RISCVTernaryAAXA; - defm vfnmsub : RISCVTernaryAAXA; - - defm vfwmacc : RISCVTernaryWide; - defm vfwnmacc : RISCVTernaryWide; - defm vfwmsac : RISCVTernaryWide; - defm vfwnmsac : RISCVTernaryWide; - - defm vfsqrt : RISCVUnaryAA; - defm vfrsqrt7 : RISCVUnaryAA; - defm vfrec7 : RISCVUnaryAA; - - defm vfmin : RISCVBinaryAAX; - defm vfmax : RISCVBinaryAAX; - - defm vfsgnj : RISCVBinaryAAX; - defm vfsgnjn : RISCVBinaryAAX; - defm vfsgnjx : RISCVBinaryAAX; - - defm vfclass : RISCVClassify; - - defm vfmerge : RISCVBinaryWithV0; - - defm vslideup : RISCVTernaryAAAX; - defm vslidedown : RISCVTernaryAAAX; - - defm vslide1up : RISCVBinaryAAX; - defm vslide1down : RISCVBinaryAAX; - defm vfslide1up : RISCVBinaryAAX; - defm vfslide1down : RISCVBinaryAAX; - - defm vrgather_vv : RISCVRGatherVV; - defm vrgather_vx : RISCVRGatherVX; - defm vrgatherei16_vv : RISCVRGatherEI16VV; - - def "int_riscv_vcompress" : RISCVUnaryAAMaskNoTA; - - defm vaaddu : RISCVSaturatingBinaryAAX; - defm vaadd : RISCVSaturatingBinaryAAX; - defm vasubu : RISCVSaturatingBinaryAAX; - defm vasub : RISCVSaturatingBinaryAAX; - - defm vsmul : RISCVSaturatingBinaryAAX; - - defm vssrl : RISCVSaturatingBinaryAAShift; - defm vssra : RISCVSaturatingBinaryAAShift; - - defm vnclipu : RISCVSaturatingBinaryABShift; - defm vnclip : RISCVSaturatingBinaryABShift; - - defm vmfeq : RISCVCompare; - defm vmfne : RISCVCompare; - defm vmflt : RISCVCompare; - defm vmfle : RISCVCompare; - defm vmfgt : RISCVCompare; - defm vmfge : RISCVCompare; - - defm vredsum : RISCVReduction; - defm vredand : RISCVReduction; - defm vredor : RISCVReduction; - defm vredxor : RISCVReduction; - defm vredminu : RISCVReduction; - defm vredmin : RISCVReduction; - defm vredmaxu : RISCVReduction; - defm vredmax : RISCVReduction; - - defm vwredsumu : RISCVReduction; - defm vwredsum : RISCVReduction; - - defm vfredosum : RISCVReduction; - defm vfredusum : RISCVReduction; - defm vfredmin : RISCVReduction; - defm vfredmax : RISCVReduction; - - defm vfwredusum : RISCVReduction; - defm vfwredosum : RISCVReduction; - - def int_riscv_vmand: RISCVBinaryAAANoMask; - def int_riscv_vmnand: RISCVBinaryAAANoMask; - def int_riscv_vmandn: RISCVBinaryAAANoMask; - def int_riscv_vmxor: RISCVBinaryAAANoMask; - def int_riscv_vmor: RISCVBinaryAAANoMask; - def int_riscv_vmnor: RISCVBinaryAAANoMask; - def int_riscv_vmorn: RISCVBinaryAAANoMask; - def int_riscv_vmxnor: RISCVBinaryAAANoMask; - def int_riscv_vmclr : RISCVNullaryIntrinsic; - def int_riscv_vmset : RISCVNullaryIntrinsic; - - defm vcpop : RISCVMaskUnarySOut; - defm vfirst : RISCVMaskUnarySOut; - defm vmsbf : RISCVMaskUnaryMOut; - defm vmsof : RISCVMaskUnaryMOut; - defm vmsif : RISCVMaskUnaryMOut; - - defm vfcvt_xu_f_v : RISCVConversion; - defm vfcvt_x_f_v : RISCVConversion; - defm vfcvt_rtz_xu_f_v : RISCVConversion; - defm vfcvt_rtz_x_f_v : RISCVConversion; - defm vfcvt_f_xu_v : RISCVConversion; - defm vfcvt_f_x_v : RISCVConversion; - - defm vfwcvt_f_xu_v : RISCVConversion; - defm vfwcvt_f_x_v : RISCVConversion; - defm vfwcvt_xu_f_v : RISCVConversion; - defm vfwcvt_x_f_v : RISCVConversion; - defm vfwcvt_rtz_xu_f_v : RISCVConversion; - defm vfwcvt_rtz_x_f_v : RISCVConversion; - defm vfwcvt_f_f_v : RISCVConversion; - - defm vfncvt_f_xu_w : RISCVConversion; - defm vfncvt_f_x_w : RISCVConversion; - defm vfncvt_xu_f_w : RISCVConversion; - defm vfncvt_x_f_w : RISCVConversion; - defm vfncvt_rtz_xu_f_w : RISCVConversion; - defm vfncvt_rtz_x_f_w : RISCVConversion; - defm vfncvt_f_f_w : RISCVConversion; - defm vfncvt_rod_f_f_w : RISCVConversion; - - // Output: (vector) - // Input: (mask type input, vl) - def int_riscv_viota : Intrinsic<[llvm_anyvector_ty], - [LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 1; - } - // Output: (vector) - // Input: (maskedoff, mask type vector_in, mask, vl) - def int_riscv_viota_mask : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 3; - } - // Output: (vector) - // Input: (vl) - def int_riscv_vid : RISCVNullaryIntrinsic; - - // Output: (vector) - // Input: (maskedoff, mask, vl) - def int_riscv_vid_mask : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, - llvm_anyint_ty], - [IntrNoMem]>, RISCVVIntrinsic { - let VLOperand = 2; - } - - foreach nf = [2, 3, 4, 5, 6, 7, 8] in { - defm vlseg # nf : RISCVUSSegLoad; - defm vlseg # nf # ff : RISCVUSSegLoadFF; - defm vlsseg # nf : RISCVSSegLoad; - defm vloxseg # nf : RISCVISegLoad; - defm vluxseg # nf : RISCVISegLoad; - defm vsseg # nf : RISCVUSSegStore; - defm vssseg # nf : RISCVSSegStore; - defm vsoxseg # nf : RISCVISegStore; - defm vsuxseg # nf : RISCVISegStore; - } - - // Strided loads/stores for fixed vectors. - def int_riscv_masked_strided_load - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyptr_ty, - llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [NoCapture>, IntrReadMem]>; - def int_riscv_masked_strided_store - : Intrinsic<[], - [llvm_anyvector_ty, llvm_anyptr_ty, - llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [NoCapture>, IntrWriteMem]>; -} // TargetPrefix = "riscv" - -//===----------------------------------------------------------------------===// -// Scalar Cryptography -// -// These intrinsics will lower directly into the corresponding instructions -// added by the scalar cyptography extension, if the extension is present. - -let TargetPrefix = "riscv" in { - -class ScalarCryptoGprIntrinsicAny - : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; - -class ScalarCryptoByteSelect32 - : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, IntrWillReturn, IntrSpeculatable, - ImmArg>]>; - -class ScalarCryptoGprGprIntrinsic32 - : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; - -class ScalarCryptoGprGprIntrinsic64 - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; - -class ScalarCryptoGprIntrinsic64 - : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty], - [IntrNoMem, IntrWillReturn, IntrSpeculatable]>; - -class ScalarCryptoByteSelectAny - : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i8_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, - ImmArg>, Returned>]>; - -// Zknd -def int_riscv_aes32dsi : ScalarCryptoByteSelect32; -def int_riscv_aes32dsmi : ScalarCryptoByteSelect32; - -def int_riscv_aes64ds : ScalarCryptoGprGprIntrinsic64; -def int_riscv_aes64dsm : ScalarCryptoGprGprIntrinsic64; - -def int_riscv_aes64im : ScalarCryptoGprIntrinsic64; - -// Zkne -def int_riscv_aes32esi : ScalarCryptoByteSelect32; -def int_riscv_aes32esmi : ScalarCryptoByteSelect32; - -def int_riscv_aes64es : ScalarCryptoGprGprIntrinsic64; -def int_riscv_aes64esm : ScalarCryptoGprGprIntrinsic64; - -// Zknd & Zkne -def int_riscv_aes64ks2 : ScalarCryptoGprGprIntrinsic64; -def int_riscv_aes64ks1i : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, - IntrWillReturn, ImmArg>]>; - -// Zknh -def int_riscv_sha256sig0 : ScalarCryptoGprIntrinsicAny; -def int_riscv_sha256sig1 : ScalarCryptoGprIntrinsicAny; -def int_riscv_sha256sum0 : ScalarCryptoGprIntrinsicAny; -def int_riscv_sha256sum1 : ScalarCryptoGprIntrinsicAny; - -def int_riscv_sha512sig0l : ScalarCryptoGprGprIntrinsic32; -def int_riscv_sha512sig0h : ScalarCryptoGprGprIntrinsic32; -def int_riscv_sha512sig1l : ScalarCryptoGprGprIntrinsic32; -def int_riscv_sha512sig1h : ScalarCryptoGprGprIntrinsic32; -def int_riscv_sha512sum0r : ScalarCryptoGprGprIntrinsic32; -def int_riscv_sha512sum1r : ScalarCryptoGprGprIntrinsic32; - -def int_riscv_sha512sig0 : ScalarCryptoGprIntrinsic64; -def int_riscv_sha512sig1 : ScalarCryptoGprIntrinsic64; -def int_riscv_sha512sum0 : ScalarCryptoGprIntrinsic64; -def int_riscv_sha512sum1 : ScalarCryptoGprIntrinsic64; - -// Zksed -def int_riscv_sm4ks : ScalarCryptoByteSelectAny; -def int_riscv_sm4ed : ScalarCryptoByteSelectAny; - -// Zksh -def int_riscv_sm3p0 : ScalarCryptoGprIntrinsicAny; -def int_riscv_sm3p1 : ScalarCryptoGprIntrinsicAny; -} // TargetPrefix = "riscv" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsS390.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsS390.h deleted file mode 100644 index f8c0f905c3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsS390.h +++ /dev/null @@ -1,253 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_S390_ENUMS_H -#define LLVM_IR_INTRINSIC_S390_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum S390Intrinsics : unsigned { -// Enum values for intrinsics - s390_efpc = 7833, // llvm.s390.efpc - s390_etnd, // llvm.s390.etnd - s390_lcbb, // llvm.s390.lcbb - s390_ntstg, // llvm.s390.ntstg - s390_ppa_txassist, // llvm.s390.ppa.txassist - s390_sfpc, // llvm.s390.sfpc - s390_tabort, // llvm.s390.tabort - s390_tbegin, // llvm.s390.tbegin - s390_tbegin_nofloat, // llvm.s390.tbegin.nofloat - s390_tbeginc, // llvm.s390.tbeginc - s390_tdc, // llvm.s390.tdc - s390_tend, // llvm.s390.tend - s390_vaccb, // llvm.s390.vaccb - s390_vacccq, // llvm.s390.vacccq - s390_vaccf, // llvm.s390.vaccf - s390_vaccg, // llvm.s390.vaccg - s390_vacch, // llvm.s390.vacch - s390_vaccq, // llvm.s390.vaccq - s390_vacq, // llvm.s390.vacq - s390_vaq, // llvm.s390.vaq - s390_vavgb, // llvm.s390.vavgb - s390_vavgf, // llvm.s390.vavgf - s390_vavgg, // llvm.s390.vavgg - s390_vavgh, // llvm.s390.vavgh - s390_vavglb, // llvm.s390.vavglb - s390_vavglf, // llvm.s390.vavglf - s390_vavglg, // llvm.s390.vavglg - s390_vavglh, // llvm.s390.vavglh - s390_vbperm, // llvm.s390.vbperm - s390_vceqbs, // llvm.s390.vceqbs - s390_vceqfs, // llvm.s390.vceqfs - s390_vceqgs, // llvm.s390.vceqgs - s390_vceqhs, // llvm.s390.vceqhs - s390_vcfn, // llvm.s390.vcfn - s390_vchbs, // llvm.s390.vchbs - s390_vchfs, // llvm.s390.vchfs - s390_vchgs, // llvm.s390.vchgs - s390_vchhs, // llvm.s390.vchhs - s390_vchlbs, // llvm.s390.vchlbs - s390_vchlfs, // llvm.s390.vchlfs - s390_vchlgs, // llvm.s390.vchlgs - s390_vchlhs, // llvm.s390.vchlhs - s390_vcksm, // llvm.s390.vcksm - s390_vclfnhs, // llvm.s390.vclfnhs - s390_vclfnls, // llvm.s390.vclfnls - s390_vcnf, // llvm.s390.vcnf - s390_vcrnfs, // llvm.s390.vcrnfs - s390_verimb, // llvm.s390.verimb - s390_verimf, // llvm.s390.verimf - s390_verimg, // llvm.s390.verimg - s390_verimh, // llvm.s390.verimh - s390_verllb, // llvm.s390.verllb - s390_verllf, // llvm.s390.verllf - s390_verllg, // llvm.s390.verllg - s390_verllh, // llvm.s390.verllh - s390_verllvb, // llvm.s390.verllvb - s390_verllvf, // llvm.s390.verllvf - s390_verllvg, // llvm.s390.verllvg - s390_verllvh, // llvm.s390.verllvh - s390_vfaeb, // llvm.s390.vfaeb - s390_vfaebs, // llvm.s390.vfaebs - s390_vfaef, // llvm.s390.vfaef - s390_vfaefs, // llvm.s390.vfaefs - s390_vfaeh, // llvm.s390.vfaeh - s390_vfaehs, // llvm.s390.vfaehs - s390_vfaezb, // llvm.s390.vfaezb - s390_vfaezbs, // llvm.s390.vfaezbs - s390_vfaezf, // llvm.s390.vfaezf - s390_vfaezfs, // llvm.s390.vfaezfs - s390_vfaezh, // llvm.s390.vfaezh - s390_vfaezhs, // llvm.s390.vfaezhs - s390_vfcedbs, // llvm.s390.vfcedbs - s390_vfcesbs, // llvm.s390.vfcesbs - s390_vfchdbs, // llvm.s390.vfchdbs - s390_vfchedbs, // llvm.s390.vfchedbs - s390_vfchesbs, // llvm.s390.vfchesbs - s390_vfchsbs, // llvm.s390.vfchsbs - s390_vfeeb, // llvm.s390.vfeeb - s390_vfeebs, // llvm.s390.vfeebs - s390_vfeef, // llvm.s390.vfeef - s390_vfeefs, // llvm.s390.vfeefs - s390_vfeeh, // llvm.s390.vfeeh - s390_vfeehs, // llvm.s390.vfeehs - s390_vfeezb, // llvm.s390.vfeezb - s390_vfeezbs, // llvm.s390.vfeezbs - s390_vfeezf, // llvm.s390.vfeezf - s390_vfeezfs, // llvm.s390.vfeezfs - s390_vfeezh, // llvm.s390.vfeezh - s390_vfeezhs, // llvm.s390.vfeezhs - s390_vfeneb, // llvm.s390.vfeneb - s390_vfenebs, // llvm.s390.vfenebs - s390_vfenef, // llvm.s390.vfenef - s390_vfenefs, // llvm.s390.vfenefs - s390_vfeneh, // llvm.s390.vfeneh - s390_vfenehs, // llvm.s390.vfenehs - s390_vfenezb, // llvm.s390.vfenezb - s390_vfenezbs, // llvm.s390.vfenezbs - s390_vfenezf, // llvm.s390.vfenezf - s390_vfenezfs, // llvm.s390.vfenezfs - s390_vfenezh, // llvm.s390.vfenezh - s390_vfenezhs, // llvm.s390.vfenezhs - s390_vfidb, // llvm.s390.vfidb - s390_vfisb, // llvm.s390.vfisb - s390_vfmaxdb, // llvm.s390.vfmaxdb - s390_vfmaxsb, // llvm.s390.vfmaxsb - s390_vfmindb, // llvm.s390.vfmindb - s390_vfminsb, // llvm.s390.vfminsb - s390_vftcidb, // llvm.s390.vftcidb - s390_vftcisb, // llvm.s390.vftcisb - s390_vgfmab, // llvm.s390.vgfmab - s390_vgfmaf, // llvm.s390.vgfmaf - s390_vgfmag, // llvm.s390.vgfmag - s390_vgfmah, // llvm.s390.vgfmah - s390_vgfmb, // llvm.s390.vgfmb - s390_vgfmf, // llvm.s390.vgfmf - s390_vgfmg, // llvm.s390.vgfmg - s390_vgfmh, // llvm.s390.vgfmh - s390_vistrb, // llvm.s390.vistrb - s390_vistrbs, // llvm.s390.vistrbs - s390_vistrf, // llvm.s390.vistrf - s390_vistrfs, // llvm.s390.vistrfs - s390_vistrh, // llvm.s390.vistrh - s390_vistrhs, // llvm.s390.vistrhs - s390_vlbb, // llvm.s390.vlbb - s390_vll, // llvm.s390.vll - s390_vlrl, // llvm.s390.vlrl - s390_vmaeb, // llvm.s390.vmaeb - s390_vmaef, // llvm.s390.vmaef - s390_vmaeh, // llvm.s390.vmaeh - s390_vmahb, // llvm.s390.vmahb - s390_vmahf, // llvm.s390.vmahf - s390_vmahh, // llvm.s390.vmahh - s390_vmaleb, // llvm.s390.vmaleb - s390_vmalef, // llvm.s390.vmalef - s390_vmaleh, // llvm.s390.vmaleh - s390_vmalhb, // llvm.s390.vmalhb - s390_vmalhf, // llvm.s390.vmalhf - s390_vmalhh, // llvm.s390.vmalhh - s390_vmalob, // llvm.s390.vmalob - s390_vmalof, // llvm.s390.vmalof - s390_vmaloh, // llvm.s390.vmaloh - s390_vmaob, // llvm.s390.vmaob - s390_vmaof, // llvm.s390.vmaof - s390_vmaoh, // llvm.s390.vmaoh - s390_vmeb, // llvm.s390.vmeb - s390_vmef, // llvm.s390.vmef - s390_vmeh, // llvm.s390.vmeh - s390_vmhb, // llvm.s390.vmhb - s390_vmhf, // llvm.s390.vmhf - s390_vmhh, // llvm.s390.vmhh - s390_vmleb, // llvm.s390.vmleb - s390_vmlef, // llvm.s390.vmlef - s390_vmleh, // llvm.s390.vmleh - s390_vmlhb, // llvm.s390.vmlhb - s390_vmlhf, // llvm.s390.vmlhf - s390_vmlhh, // llvm.s390.vmlhh - s390_vmlob, // llvm.s390.vmlob - s390_vmlof, // llvm.s390.vmlof - s390_vmloh, // llvm.s390.vmloh - s390_vmob, // llvm.s390.vmob - s390_vmof, // llvm.s390.vmof - s390_vmoh, // llvm.s390.vmoh - s390_vmslg, // llvm.s390.vmslg - s390_vpdi, // llvm.s390.vpdi - s390_vperm, // llvm.s390.vperm - s390_vpklsf, // llvm.s390.vpklsf - s390_vpklsfs, // llvm.s390.vpklsfs - s390_vpklsg, // llvm.s390.vpklsg - s390_vpklsgs, // llvm.s390.vpklsgs - s390_vpklsh, // llvm.s390.vpklsh - s390_vpklshs, // llvm.s390.vpklshs - s390_vpksf, // llvm.s390.vpksf - s390_vpksfs, // llvm.s390.vpksfs - s390_vpksg, // llvm.s390.vpksg - s390_vpksgs, // llvm.s390.vpksgs - s390_vpksh, // llvm.s390.vpksh - s390_vpkshs, // llvm.s390.vpkshs - s390_vsbcbiq, // llvm.s390.vsbcbiq - s390_vsbiq, // llvm.s390.vsbiq - s390_vscbib, // llvm.s390.vscbib - s390_vscbif, // llvm.s390.vscbif - s390_vscbig, // llvm.s390.vscbig - s390_vscbih, // llvm.s390.vscbih - s390_vscbiq, // llvm.s390.vscbiq - s390_vsl, // llvm.s390.vsl - s390_vslb, // llvm.s390.vslb - s390_vsld, // llvm.s390.vsld - s390_vsldb, // llvm.s390.vsldb - s390_vsq, // llvm.s390.vsq - s390_vsra, // llvm.s390.vsra - s390_vsrab, // llvm.s390.vsrab - s390_vsrd, // llvm.s390.vsrd - s390_vsrl, // llvm.s390.vsrl - s390_vsrlb, // llvm.s390.vsrlb - s390_vstl, // llvm.s390.vstl - s390_vstrcb, // llvm.s390.vstrcb - s390_vstrcbs, // llvm.s390.vstrcbs - s390_vstrcf, // llvm.s390.vstrcf - s390_vstrcfs, // llvm.s390.vstrcfs - s390_vstrch, // llvm.s390.vstrch - s390_vstrchs, // llvm.s390.vstrchs - s390_vstrczb, // llvm.s390.vstrczb - s390_vstrczbs, // llvm.s390.vstrczbs - s390_vstrczf, // llvm.s390.vstrczf - s390_vstrczfs, // llvm.s390.vstrczfs - s390_vstrczh, // llvm.s390.vstrczh - s390_vstrczhs, // llvm.s390.vstrczhs - s390_vstrl, // llvm.s390.vstrl - s390_vstrsb, // llvm.s390.vstrsb - s390_vstrsf, // llvm.s390.vstrsf - s390_vstrsh, // llvm.s390.vstrsh - s390_vstrszb, // llvm.s390.vstrszb - s390_vstrszf, // llvm.s390.vstrszf - s390_vstrszh, // llvm.s390.vstrszh - s390_vsumb, // llvm.s390.vsumb - s390_vsumgf, // llvm.s390.vsumgf - s390_vsumgh, // llvm.s390.vsumgh - s390_vsumh, // llvm.s390.vsumh - s390_vsumqf, // llvm.s390.vsumqf - s390_vsumqg, // llvm.s390.vsumqg - s390_vtm, // llvm.s390.vtm - s390_vuphb, // llvm.s390.vuphb - s390_vuphf, // llvm.s390.vuphf - s390_vuphh, // llvm.s390.vuphh - s390_vuplb, // llvm.s390.vuplb - s390_vuplf, // llvm.s390.vuplf - s390_vuplhb, // llvm.s390.vuplhb - s390_vuplhf, // llvm.s390.vuplhf - s390_vuplhh, // llvm.s390.vuplhh - s390_vuplhw, // llvm.s390.vuplhw - s390_vupllb, // llvm.s390.vupllb - s390_vupllf, // llvm.s390.vupllf - s390_vupllh, // llvm.s390.vupllh -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsSystemZ.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsSystemZ.td deleted file mode 100644 index a149b57107..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsSystemZ.td +++ /dev/null @@ -1,477 +0,0 @@ -//===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the SystemZ-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -class SystemZUnaryConv - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[result], [arg], [IntrNoMem]>; - -class SystemZUnary - : SystemZUnaryConv; - -class SystemZUnaryConvCC - : Intrinsic<[result, llvm_i32_ty], [arg], [IntrNoMem]>; - -class SystemZUnaryCC - : SystemZUnaryConvCC; - -class SystemZBinaryConv - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[result], [arg, arg], [IntrNoMem]>; - -class SystemZBinary - : SystemZBinaryConv; - -class SystemZBinaryInt - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[type], [type, llvm_i32_ty], [IntrNoMem]>; - -class SystemZBinaryConvCC - : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>; - -class SystemZBinaryConvIntCC - : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -class SystemZBinaryCC - : SystemZBinaryConvCC; - -class SystemZTernaryConv - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[result], [arg, arg, result], [IntrNoMem]>; - -class SystemZTernaryConvCC - : Intrinsic<[result, llvm_i32_ty], [arg, arg, result], [IntrNoMem]>; - -class SystemZTernary - : SystemZTernaryConv; - -class SystemZTernaryInt - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - -class SystemZTernaryIntCC - : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -class SystemZQuaternaryInt - : GCCBuiltin<"__builtin_s390_" # name>, - Intrinsic<[type], [type, type, type, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -class SystemZQuaternaryIntCC - : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -multiclass SystemZUnaryExtBHF { - def b : SystemZUnaryConv; - def h : SystemZUnaryConv; - def f : SystemZUnaryConv; -} - -multiclass SystemZUnaryExtBHWF { - def b : SystemZUnaryConv; - def hw : SystemZUnaryConv; - def f : SystemZUnaryConv; -} - -multiclass SystemZUnaryBHF { - def b : SystemZUnary; - def h : SystemZUnary; - def f : SystemZUnary; -} - -multiclass SystemZUnaryBHFG : SystemZUnaryBHF { - def g : SystemZUnary; -} - -multiclass SystemZUnaryCCBHF { - def bs : SystemZUnaryCC; - def hs : SystemZUnaryCC; - def fs : SystemZUnaryCC; -} - -multiclass SystemZBinaryTruncHFG { - def h : SystemZBinaryConv; - def f : SystemZBinaryConv; - def g : SystemZBinaryConv; -} - -multiclass SystemZBinaryTruncCCHFG { - def hs : SystemZBinaryConvCC; - def fs : SystemZBinaryConvCC; - def gs : SystemZBinaryConvCC; -} - -multiclass SystemZBinaryExtBHF { - def b : SystemZBinaryConv; - def h : SystemZBinaryConv; - def f : SystemZBinaryConv; -} - -multiclass SystemZBinaryExtBHFG : SystemZBinaryExtBHF { - def g : SystemZBinaryConv; -} - -multiclass SystemZBinaryBHF { - def b : SystemZBinary; - def h : SystemZBinary; - def f : SystemZBinary; -} - -multiclass SystemZBinaryBHFG : SystemZBinaryBHF { - def g : SystemZBinary; -} - -multiclass SystemZBinaryIntBHFG { - def b : SystemZBinaryInt; - def h : SystemZBinaryInt; - def f : SystemZBinaryInt; - def g : SystemZBinaryInt; -} - -multiclass SystemZBinaryCCBHF { - def bs : SystemZBinaryCC; - def hs : SystemZBinaryCC; - def fs : SystemZBinaryCC; -} - -multiclass SystemZCompareBHFG { - def bs : SystemZBinaryCC; - def hs : SystemZBinaryCC; - def fs : SystemZBinaryCC; - def gs : SystemZBinaryCC; -} - -multiclass SystemZTernaryExtBHF { - def b : SystemZTernaryConv; - def h : SystemZTernaryConv; - def f : SystemZTernaryConv; -} - -multiclass SystemZTernaryExtBHFG : SystemZTernaryExtBHF { - def g : SystemZTernaryConv; -} - -multiclass SystemZTernaryBHF { - def b : SystemZTernary; - def h : SystemZTernary; - def f : SystemZTernary; -} - -multiclass SystemZTernaryIntBHF { - def b : SystemZTernaryInt; - def h : SystemZTernaryInt; - def f : SystemZTernaryInt; -} - -multiclass SystemZTernaryIntCCBHF { - def bs : SystemZTernaryIntCC; - def hs : SystemZTernaryIntCC; - def fs : SystemZTernaryIntCC; -} - -multiclass SystemZQuaternaryIntBHF { - def b : SystemZQuaternaryInt; - def h : SystemZQuaternaryInt; - def f : SystemZQuaternaryInt; -} - -multiclass SystemZQuaternaryIntBHFG : - SystemZQuaternaryIntBHF { - def g : SystemZQuaternaryInt; -} - -multiclass SystemZQuaternaryIntCCBHF { - def bs : SystemZQuaternaryIntCC; - def hs : SystemZQuaternaryIntCC; - def fs : SystemZQuaternaryIntCC; -} - -//===----------------------------------------------------------------------===// -// -// Transactional-execution intrinsics -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "s390" in { - def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrNoDuplicate, IntrWriteMem]>; - - def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], - [llvm_ptr_ty, llvm_i32_ty], - [IntrNoDuplicate, IntrWriteMem]>; - - def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], - [IntrNoDuplicate, IntrWriteMem]>; - - def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], - [IntrNoReturn, Throws, IntrWriteMem]>; - - def int_s390_tend : GCCBuiltin<"__builtin_tend">, - Intrinsic<[llvm_i32_ty], []>; - - def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; - - def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], - [IntrArgMemOnly, IntrWriteMem]>; - - def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, - Intrinsic<[], [llvm_i32_ty]>; -} - -//===----------------------------------------------------------------------===// -// -// Vector intrinsics -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "s390" in { - def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly, ImmArg>]>; - - def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">, - Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - - def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - - defm int_s390_vpks : SystemZBinaryTruncHFG<"vpks">; - defm int_s390_vpks : SystemZBinaryTruncCCHFG; - - defm int_s390_vpkls : SystemZBinaryTruncHFG<"vpkls">; - defm int_s390_vpkls : SystemZBinaryTruncCCHFG; - - def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">, - Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrArgMemOnly, IntrWriteMem]>; - - defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">; - defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">; - - defm int_s390_vuph : SystemZUnaryExtBHF<"vuph">; - defm int_s390_vuplh : SystemZUnaryExtBHF<"vuplh">; - - defm int_s390_vacc : SystemZBinaryBHFG<"vacc">; - - def int_s390_vaq : SystemZBinary<"vaq", llvm_v16i8_ty>; - def int_s390_vacq : SystemZTernary<"vacq", llvm_v16i8_ty>; - def int_s390_vaccq : SystemZBinary<"vaccq", llvm_v16i8_ty>; - def int_s390_vacccq : SystemZTernary<"vacccq", llvm_v16i8_ty>; - - defm int_s390_vavg : SystemZBinaryBHFG<"vavg">; - defm int_s390_vavgl : SystemZBinaryBHFG<"vavgl">; - - def int_s390_vcksm : SystemZBinary<"vcksm", llvm_v4i32_ty>; - - defm int_s390_vgfm : SystemZBinaryExtBHFG<"vgfm">; - defm int_s390_vgfma : SystemZTernaryExtBHFG<"vgfma">; - - defm int_s390_vmah : SystemZTernaryBHF<"vmah">; - defm int_s390_vmalh : SystemZTernaryBHF<"vmalh">; - defm int_s390_vmae : SystemZTernaryExtBHF<"vmae">; - defm int_s390_vmale : SystemZTernaryExtBHF<"vmale">; - defm int_s390_vmao : SystemZTernaryExtBHF<"vmao">; - defm int_s390_vmalo : SystemZTernaryExtBHF<"vmalo">; - - defm int_s390_vmh : SystemZBinaryBHF<"vmh">; - defm int_s390_vmlh : SystemZBinaryBHF<"vmlh">; - defm int_s390_vme : SystemZBinaryExtBHF<"vme">; - defm int_s390_vmle : SystemZBinaryExtBHF<"vmle">; - defm int_s390_vmo : SystemZBinaryExtBHF<"vmo">; - defm int_s390_vmlo : SystemZBinaryExtBHF<"vmlo">; - - defm int_s390_verllv : SystemZBinaryBHFG<"verllv">; - defm int_s390_verll : SystemZBinaryIntBHFG<"verll">; - defm int_s390_verim : SystemZQuaternaryIntBHFG<"verim">; - - def int_s390_vsl : SystemZBinary<"vsl", llvm_v16i8_ty>; - def int_s390_vslb : SystemZBinary<"vslb", llvm_v16i8_ty>; - def int_s390_vsra : SystemZBinary<"vsra", llvm_v16i8_ty>; - def int_s390_vsrab : SystemZBinary<"vsrab", llvm_v16i8_ty>; - def int_s390_vsrl : SystemZBinary<"vsrl", llvm_v16i8_ty>; - def int_s390_vsrlb : SystemZBinary<"vsrlb", llvm_v16i8_ty>; - - def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">; - - def int_s390_vsq : SystemZBinary<"vsq", llvm_v16i8_ty>; - def int_s390_vsbiq : SystemZTernary<"vsbiq", llvm_v16i8_ty>; - def int_s390_vscbiq : SystemZBinary<"vscbiq", llvm_v16i8_ty>; - def int_s390_vsbcbiq : SystemZTernary<"vsbcbiq", llvm_v16i8_ty>; - - def int_s390_vsumb : SystemZBinaryConv<"vsumb", llvm_v4i32_ty, llvm_v16i8_ty>; - def int_s390_vsumh : SystemZBinaryConv<"vsumh", llvm_v4i32_ty, llvm_v8i16_ty>; - - def int_s390_vsumgh : SystemZBinaryConv<"vsumgh", llvm_v2i64_ty, - llvm_v8i16_ty>; - def int_s390_vsumgf : SystemZBinaryConv<"vsumgf", llvm_v2i64_ty, - llvm_v4i32_ty>; - - def int_s390_vsumqf : SystemZBinaryConv<"vsumqf", llvm_v16i8_ty, - llvm_v4i32_ty>; - def int_s390_vsumqg : SystemZBinaryConv<"vsumqg", llvm_v16i8_ty, - llvm_v2i64_ty>; - - def int_s390_vtm : SystemZBinaryConv<"vtm", llvm_i32_ty, llvm_v16i8_ty>; - - defm int_s390_vceq : SystemZCompareBHFG; - defm int_s390_vch : SystemZCompareBHFG; - defm int_s390_vchl : SystemZCompareBHFG; - - defm int_s390_vfae : SystemZTernaryIntBHF<"vfae">; - defm int_s390_vfae : SystemZTernaryIntCCBHF; - defm int_s390_vfaez : SystemZTernaryIntBHF<"vfaez">; - defm int_s390_vfaez : SystemZTernaryIntCCBHF; - - defm int_s390_vfee : SystemZBinaryBHF<"vfee">; - defm int_s390_vfee : SystemZBinaryCCBHF; - defm int_s390_vfeez : SystemZBinaryBHF<"vfeez">; - defm int_s390_vfeez : SystemZBinaryCCBHF; - - defm int_s390_vfene : SystemZBinaryBHF<"vfene">; - defm int_s390_vfene : SystemZBinaryCCBHF; - defm int_s390_vfenez : SystemZBinaryBHF<"vfenez">; - defm int_s390_vfenez : SystemZBinaryCCBHF; - - defm int_s390_vistr : SystemZUnaryBHF<"vistr">; - defm int_s390_vistr : SystemZUnaryCCBHF; - - defm int_s390_vstrc : SystemZQuaternaryIntBHF<"vstrc">; - defm int_s390_vstrc : SystemZQuaternaryIntCCBHF; - defm int_s390_vstrcz : SystemZQuaternaryIntBHF<"vstrcz">; - defm int_s390_vstrcz : SystemZQuaternaryIntCCBHF; - - def int_s390_vfcedbs : SystemZBinaryConvCC; - def int_s390_vfchdbs : SystemZBinaryConvCC; - def int_s390_vfchedbs : SystemZBinaryConvCC; - - def int_s390_vftcidb : SystemZBinaryConvIntCC; - - def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - // Instructions from the Vector Enhancements Facility 1 - def int_s390_vbperm : SystemZBinaryConv<"vbperm", llvm_v2i64_ty, - llvm_v16i8_ty>; - - def int_s390_vmslg : GCCBuiltin<"__builtin_s390_vmslg">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v16i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_s390_vfmaxdb : Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vfmindb : Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vfmaxsb : Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vfminsb : Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_s390_vfcesbs : SystemZBinaryConvCC; - def int_s390_vfchsbs : SystemZBinaryConvCC; - def int_s390_vfchesbs : SystemZBinaryConvCC; - - def int_s390_vftcisb : SystemZBinaryConvIntCC; - - def int_s390_vfisb : Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - // Instructions from the Vector Packed Decimal Facility - def int_s390_vlrl : GCCBuiltin<"__builtin_s390_vlrl">, - Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], - [IntrReadMem, IntrArgMemOnly]>; - - def int_s390_vstrl : GCCBuiltin<"__builtin_s390_vstrl">, - Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], - [IntrArgMemOnly, IntrWriteMem]>; - - // Instructions from the Vector Enhancements Facility 2 - def int_s390_vsld : GCCBuiltin<"__builtin_s390_vsld">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_s390_vsrd : GCCBuiltin<"__builtin_s390_vsrd">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_s390_vstrsb : SystemZTernaryConvCC; - def int_s390_vstrsh : SystemZTernaryConvCC; - def int_s390_vstrsf : SystemZTernaryConvCC; - def int_s390_vstrszb : SystemZTernaryConvCC; - def int_s390_vstrszh : SystemZTernaryConvCC; - def int_s390_vstrszf : SystemZTernaryConvCC; - - // Instructions from the NNP-assist Facility - def int_s390_vclfnhs : GCCBuiltin<"__builtin_s390_vclfnhs">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vclfnls : GCCBuiltin<"__builtin_s390_vclfnls">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vcrnfs : GCCBuiltin<"__builtin_s390_vcrnfs">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vcfn : GCCBuiltin<"__builtin_s390_vcfn">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_s390_vcnf : GCCBuiltin<"__builtin_s390_vcnf">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// -// Misc intrinsics -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "s390" in { - def int_s390_sfpc : GCCBuiltin<"__builtin_s390_sfpc">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_s390_efpc : GCCBuiltin<"__builtin_s390_efpc">, - Intrinsic<[llvm_i32_ty], [], []>; - - def int_s390_tdc : Intrinsic<[llvm_i32_ty], [llvm_anyfloat_ty, llvm_i64_ty], - [IntrNoMem]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.h deleted file mode 100644 index a3ea48a88f..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.h +++ /dev/null @@ -1,1240 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_VE_ENUMS_H -#define LLVM_IR_INTRINSIC_VE_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum VEIntrinsics : unsigned { -// Enum values for intrinsics - ve_vl_andm_MMM = 8066, // llvm.ve.vl.andm.MMM - ve_vl_andm_mmm, // llvm.ve.vl.andm.mmm - ve_vl_eqvm_MMM, // llvm.ve.vl.eqvm.MMM - ve_vl_eqvm_mmm, // llvm.ve.vl.eqvm.mmm - ve_vl_extract_vm512l, // llvm.ve.vl.extract.vm512l - ve_vl_extract_vm512u, // llvm.ve.vl.extract.vm512u - ve_vl_insert_vm512l, // llvm.ve.vl.insert.vm512l - ve_vl_insert_vm512u, // llvm.ve.vl.insert.vm512u - ve_vl_lsv_vvss, // llvm.ve.vl.lsv.vvss - ve_vl_lvm_MMss, // llvm.ve.vl.lvm.MMss - ve_vl_lvm_mmss, // llvm.ve.vl.lvm.mmss - ve_vl_lvsd_svs, // llvm.ve.vl.lvsd.svs - ve_vl_lvsl_svs, // llvm.ve.vl.lvsl.svs - ve_vl_lvss_svs, // llvm.ve.vl.lvss.svs - ve_vl_lzvm_sml, // llvm.ve.vl.lzvm.sml - ve_vl_negm_MM, // llvm.ve.vl.negm.MM - ve_vl_negm_mm, // llvm.ve.vl.negm.mm - ve_vl_nndm_MMM, // llvm.ve.vl.nndm.MMM - ve_vl_nndm_mmm, // llvm.ve.vl.nndm.mmm - ve_vl_orm_MMM, // llvm.ve.vl.orm.MMM - ve_vl_orm_mmm, // llvm.ve.vl.orm.mmm - ve_vl_pack_f32a, // llvm.ve.vl.pack.f32a - ve_vl_pack_f32p, // llvm.ve.vl.pack.f32p - ve_vl_pcvm_sml, // llvm.ve.vl.pcvm.sml - ve_vl_pfchv_ssl, // llvm.ve.vl.pfchv.ssl - ve_vl_pfchvnc_ssl, // llvm.ve.vl.pfchvnc.ssl - ve_vl_pvadds_vsvMvl, // llvm.ve.vl.pvadds.vsvMvl - ve_vl_pvadds_vsvl, // llvm.ve.vl.pvadds.vsvl - ve_vl_pvadds_vsvvl, // llvm.ve.vl.pvadds.vsvvl - ve_vl_pvadds_vvvMvl, // llvm.ve.vl.pvadds.vvvMvl - ve_vl_pvadds_vvvl, // llvm.ve.vl.pvadds.vvvl - ve_vl_pvadds_vvvvl, // llvm.ve.vl.pvadds.vvvvl - ve_vl_pvaddu_vsvMvl, // llvm.ve.vl.pvaddu.vsvMvl - ve_vl_pvaddu_vsvl, // llvm.ve.vl.pvaddu.vsvl - ve_vl_pvaddu_vsvvl, // llvm.ve.vl.pvaddu.vsvvl - ve_vl_pvaddu_vvvMvl, // llvm.ve.vl.pvaddu.vvvMvl - ve_vl_pvaddu_vvvl, // llvm.ve.vl.pvaddu.vvvl - ve_vl_pvaddu_vvvvl, // llvm.ve.vl.pvaddu.vvvvl - ve_vl_pvand_vsvMvl, // llvm.ve.vl.pvand.vsvMvl - ve_vl_pvand_vsvl, // llvm.ve.vl.pvand.vsvl - ve_vl_pvand_vsvvl, // llvm.ve.vl.pvand.vsvvl - ve_vl_pvand_vvvMvl, // llvm.ve.vl.pvand.vvvMvl - ve_vl_pvand_vvvl, // llvm.ve.vl.pvand.vvvl - ve_vl_pvand_vvvvl, // llvm.ve.vl.pvand.vvvvl - ve_vl_pvbrd_vsMvl, // llvm.ve.vl.pvbrd.vsMvl - ve_vl_pvbrd_vsl, // llvm.ve.vl.pvbrd.vsl - ve_vl_pvbrd_vsvl, // llvm.ve.vl.pvbrd.vsvl - ve_vl_pvcmps_vsvMvl, // llvm.ve.vl.pvcmps.vsvMvl - ve_vl_pvcmps_vsvl, // llvm.ve.vl.pvcmps.vsvl - ve_vl_pvcmps_vsvvl, // llvm.ve.vl.pvcmps.vsvvl - ve_vl_pvcmps_vvvMvl, // llvm.ve.vl.pvcmps.vvvMvl - ve_vl_pvcmps_vvvl, // llvm.ve.vl.pvcmps.vvvl - ve_vl_pvcmps_vvvvl, // llvm.ve.vl.pvcmps.vvvvl - ve_vl_pvcmpu_vsvMvl, // llvm.ve.vl.pvcmpu.vsvMvl - ve_vl_pvcmpu_vsvl, // llvm.ve.vl.pvcmpu.vsvl - ve_vl_pvcmpu_vsvvl, // llvm.ve.vl.pvcmpu.vsvvl - ve_vl_pvcmpu_vvvMvl, // llvm.ve.vl.pvcmpu.vvvMvl - ve_vl_pvcmpu_vvvl, // llvm.ve.vl.pvcmpu.vvvl - ve_vl_pvcmpu_vvvvl, // llvm.ve.vl.pvcmpu.vvvvl - ve_vl_pvcvtsw_vvl, // llvm.ve.vl.pvcvtsw.vvl - ve_vl_pvcvtsw_vvvl, // llvm.ve.vl.pvcvtsw.vvvl - ve_vl_pvcvtws_vvMvl, // llvm.ve.vl.pvcvtws.vvMvl - ve_vl_pvcvtws_vvl, // llvm.ve.vl.pvcvtws.vvl - ve_vl_pvcvtws_vvvl, // llvm.ve.vl.pvcvtws.vvvl - ve_vl_pvcvtwsrz_vvMvl, // llvm.ve.vl.pvcvtwsrz.vvMvl - ve_vl_pvcvtwsrz_vvl, // llvm.ve.vl.pvcvtwsrz.vvl - ve_vl_pvcvtwsrz_vvvl, // llvm.ve.vl.pvcvtwsrz.vvvl - ve_vl_pveqv_vsvMvl, // llvm.ve.vl.pveqv.vsvMvl - ve_vl_pveqv_vsvl, // llvm.ve.vl.pveqv.vsvl - ve_vl_pveqv_vsvvl, // llvm.ve.vl.pveqv.vsvvl - ve_vl_pveqv_vvvMvl, // llvm.ve.vl.pveqv.vvvMvl - ve_vl_pveqv_vvvl, // llvm.ve.vl.pveqv.vvvl - ve_vl_pveqv_vvvvl, // llvm.ve.vl.pveqv.vvvvl - ve_vl_pvfadd_vsvMvl, // llvm.ve.vl.pvfadd.vsvMvl - ve_vl_pvfadd_vsvl, // llvm.ve.vl.pvfadd.vsvl - ve_vl_pvfadd_vsvvl, // llvm.ve.vl.pvfadd.vsvvl - ve_vl_pvfadd_vvvMvl, // llvm.ve.vl.pvfadd.vvvMvl - ve_vl_pvfadd_vvvl, // llvm.ve.vl.pvfadd.vvvl - ve_vl_pvfadd_vvvvl, // llvm.ve.vl.pvfadd.vvvvl - ve_vl_pvfcmp_vsvMvl, // llvm.ve.vl.pvfcmp.vsvMvl - ve_vl_pvfcmp_vsvl, // llvm.ve.vl.pvfcmp.vsvl - ve_vl_pvfcmp_vsvvl, // llvm.ve.vl.pvfcmp.vsvvl - ve_vl_pvfcmp_vvvMvl, // llvm.ve.vl.pvfcmp.vvvMvl - ve_vl_pvfcmp_vvvl, // llvm.ve.vl.pvfcmp.vvvl - ve_vl_pvfcmp_vvvvl, // llvm.ve.vl.pvfcmp.vvvvl - ve_vl_pvfmad_vsvvMvl, // llvm.ve.vl.pvfmad.vsvvMvl - ve_vl_pvfmad_vsvvl, // llvm.ve.vl.pvfmad.vsvvl - ve_vl_pvfmad_vsvvvl, // llvm.ve.vl.pvfmad.vsvvvl - ve_vl_pvfmad_vvsvMvl, // llvm.ve.vl.pvfmad.vvsvMvl - ve_vl_pvfmad_vvsvl, // llvm.ve.vl.pvfmad.vvsvl - ve_vl_pvfmad_vvsvvl, // llvm.ve.vl.pvfmad.vvsvvl - ve_vl_pvfmad_vvvvMvl, // llvm.ve.vl.pvfmad.vvvvMvl - ve_vl_pvfmad_vvvvl, // llvm.ve.vl.pvfmad.vvvvl - ve_vl_pvfmad_vvvvvl, // llvm.ve.vl.pvfmad.vvvvvl - ve_vl_pvfmax_vsvMvl, // llvm.ve.vl.pvfmax.vsvMvl - ve_vl_pvfmax_vsvl, // llvm.ve.vl.pvfmax.vsvl - ve_vl_pvfmax_vsvvl, // llvm.ve.vl.pvfmax.vsvvl - ve_vl_pvfmax_vvvMvl, // llvm.ve.vl.pvfmax.vvvMvl - ve_vl_pvfmax_vvvl, // llvm.ve.vl.pvfmax.vvvl - ve_vl_pvfmax_vvvvl, // llvm.ve.vl.pvfmax.vvvvl - ve_vl_pvfmin_vsvMvl, // llvm.ve.vl.pvfmin.vsvMvl - ve_vl_pvfmin_vsvl, // llvm.ve.vl.pvfmin.vsvl - ve_vl_pvfmin_vsvvl, // llvm.ve.vl.pvfmin.vsvvl - ve_vl_pvfmin_vvvMvl, // llvm.ve.vl.pvfmin.vvvMvl - ve_vl_pvfmin_vvvl, // llvm.ve.vl.pvfmin.vvvl - ve_vl_pvfmin_vvvvl, // llvm.ve.vl.pvfmin.vvvvl - ve_vl_pvfmkaf_Ml, // llvm.ve.vl.pvfmkaf.Ml - ve_vl_pvfmkat_Ml, // llvm.ve.vl.pvfmkat.Ml - ve_vl_pvfmkseq_MvMl, // llvm.ve.vl.pvfmkseq.MvMl - ve_vl_pvfmkseq_Mvl, // llvm.ve.vl.pvfmkseq.Mvl - ve_vl_pvfmkseqnan_MvMl, // llvm.ve.vl.pvfmkseqnan.MvMl - ve_vl_pvfmkseqnan_Mvl, // llvm.ve.vl.pvfmkseqnan.Mvl - ve_vl_pvfmksge_MvMl, // llvm.ve.vl.pvfmksge.MvMl - ve_vl_pvfmksge_Mvl, // llvm.ve.vl.pvfmksge.Mvl - ve_vl_pvfmksgenan_MvMl, // llvm.ve.vl.pvfmksgenan.MvMl - ve_vl_pvfmksgenan_Mvl, // llvm.ve.vl.pvfmksgenan.Mvl - ve_vl_pvfmksgt_MvMl, // llvm.ve.vl.pvfmksgt.MvMl - ve_vl_pvfmksgt_Mvl, // llvm.ve.vl.pvfmksgt.Mvl - ve_vl_pvfmksgtnan_MvMl, // llvm.ve.vl.pvfmksgtnan.MvMl - ve_vl_pvfmksgtnan_Mvl, // llvm.ve.vl.pvfmksgtnan.Mvl - ve_vl_pvfmksle_MvMl, // llvm.ve.vl.pvfmksle.MvMl - ve_vl_pvfmksle_Mvl, // llvm.ve.vl.pvfmksle.Mvl - ve_vl_pvfmkslenan_MvMl, // llvm.ve.vl.pvfmkslenan.MvMl - ve_vl_pvfmkslenan_Mvl, // llvm.ve.vl.pvfmkslenan.Mvl - ve_vl_pvfmksloeq_mvl, // llvm.ve.vl.pvfmksloeq.mvl - ve_vl_pvfmksloeq_mvml, // llvm.ve.vl.pvfmksloeq.mvml - ve_vl_pvfmksloeqnan_mvl, // llvm.ve.vl.pvfmksloeqnan.mvl - ve_vl_pvfmksloeqnan_mvml, // llvm.ve.vl.pvfmksloeqnan.mvml - ve_vl_pvfmksloge_mvl, // llvm.ve.vl.pvfmksloge.mvl - ve_vl_pvfmksloge_mvml, // llvm.ve.vl.pvfmksloge.mvml - ve_vl_pvfmkslogenan_mvl, // llvm.ve.vl.pvfmkslogenan.mvl - ve_vl_pvfmkslogenan_mvml, // llvm.ve.vl.pvfmkslogenan.mvml - ve_vl_pvfmkslogt_mvl, // llvm.ve.vl.pvfmkslogt.mvl - ve_vl_pvfmkslogt_mvml, // llvm.ve.vl.pvfmkslogt.mvml - ve_vl_pvfmkslogtnan_mvl, // llvm.ve.vl.pvfmkslogtnan.mvl - ve_vl_pvfmkslogtnan_mvml, // llvm.ve.vl.pvfmkslogtnan.mvml - ve_vl_pvfmkslole_mvl, // llvm.ve.vl.pvfmkslole.mvl - ve_vl_pvfmkslole_mvml, // llvm.ve.vl.pvfmkslole.mvml - ve_vl_pvfmkslolenan_mvl, // llvm.ve.vl.pvfmkslolenan.mvl - ve_vl_pvfmkslolenan_mvml, // llvm.ve.vl.pvfmkslolenan.mvml - ve_vl_pvfmkslolt_mvl, // llvm.ve.vl.pvfmkslolt.mvl - ve_vl_pvfmkslolt_mvml, // llvm.ve.vl.pvfmkslolt.mvml - ve_vl_pvfmksloltnan_mvl, // llvm.ve.vl.pvfmksloltnan.mvl - ve_vl_pvfmksloltnan_mvml, // llvm.ve.vl.pvfmksloltnan.mvml - ve_vl_pvfmkslonan_mvl, // llvm.ve.vl.pvfmkslonan.mvl - ve_vl_pvfmkslonan_mvml, // llvm.ve.vl.pvfmkslonan.mvml - ve_vl_pvfmkslone_mvl, // llvm.ve.vl.pvfmkslone.mvl - ve_vl_pvfmkslone_mvml, // llvm.ve.vl.pvfmkslone.mvml - ve_vl_pvfmkslonenan_mvl, // llvm.ve.vl.pvfmkslonenan.mvl - ve_vl_pvfmkslonenan_mvml, // llvm.ve.vl.pvfmkslonenan.mvml - ve_vl_pvfmkslonum_mvl, // llvm.ve.vl.pvfmkslonum.mvl - ve_vl_pvfmkslonum_mvml, // llvm.ve.vl.pvfmkslonum.mvml - ve_vl_pvfmkslt_MvMl, // llvm.ve.vl.pvfmkslt.MvMl - ve_vl_pvfmkslt_Mvl, // llvm.ve.vl.pvfmkslt.Mvl - ve_vl_pvfmksltnan_MvMl, // llvm.ve.vl.pvfmksltnan.MvMl - ve_vl_pvfmksltnan_Mvl, // llvm.ve.vl.pvfmksltnan.Mvl - ve_vl_pvfmksnan_MvMl, // llvm.ve.vl.pvfmksnan.MvMl - ve_vl_pvfmksnan_Mvl, // llvm.ve.vl.pvfmksnan.Mvl - ve_vl_pvfmksne_MvMl, // llvm.ve.vl.pvfmksne.MvMl - ve_vl_pvfmksne_Mvl, // llvm.ve.vl.pvfmksne.Mvl - ve_vl_pvfmksnenan_MvMl, // llvm.ve.vl.pvfmksnenan.MvMl - ve_vl_pvfmksnenan_Mvl, // llvm.ve.vl.pvfmksnenan.Mvl - ve_vl_pvfmksnum_MvMl, // llvm.ve.vl.pvfmksnum.MvMl - ve_vl_pvfmksnum_Mvl, // llvm.ve.vl.pvfmksnum.Mvl - ve_vl_pvfmksupeq_mvl, // llvm.ve.vl.pvfmksupeq.mvl - ve_vl_pvfmksupeq_mvml, // llvm.ve.vl.pvfmksupeq.mvml - ve_vl_pvfmksupeqnan_mvl, // llvm.ve.vl.pvfmksupeqnan.mvl - ve_vl_pvfmksupeqnan_mvml, // llvm.ve.vl.pvfmksupeqnan.mvml - ve_vl_pvfmksupge_mvl, // llvm.ve.vl.pvfmksupge.mvl - ve_vl_pvfmksupge_mvml, // llvm.ve.vl.pvfmksupge.mvml - ve_vl_pvfmksupgenan_mvl, // llvm.ve.vl.pvfmksupgenan.mvl - ve_vl_pvfmksupgenan_mvml, // llvm.ve.vl.pvfmksupgenan.mvml - ve_vl_pvfmksupgt_mvl, // llvm.ve.vl.pvfmksupgt.mvl - ve_vl_pvfmksupgt_mvml, // llvm.ve.vl.pvfmksupgt.mvml - ve_vl_pvfmksupgtnan_mvl, // llvm.ve.vl.pvfmksupgtnan.mvl - ve_vl_pvfmksupgtnan_mvml, // llvm.ve.vl.pvfmksupgtnan.mvml - ve_vl_pvfmksuple_mvl, // llvm.ve.vl.pvfmksuple.mvl - ve_vl_pvfmksuple_mvml, // llvm.ve.vl.pvfmksuple.mvml - ve_vl_pvfmksuplenan_mvl, // llvm.ve.vl.pvfmksuplenan.mvl - ve_vl_pvfmksuplenan_mvml, // llvm.ve.vl.pvfmksuplenan.mvml - ve_vl_pvfmksuplt_mvl, // llvm.ve.vl.pvfmksuplt.mvl - ve_vl_pvfmksuplt_mvml, // llvm.ve.vl.pvfmksuplt.mvml - ve_vl_pvfmksupltnan_mvl, // llvm.ve.vl.pvfmksupltnan.mvl - ve_vl_pvfmksupltnan_mvml, // llvm.ve.vl.pvfmksupltnan.mvml - ve_vl_pvfmksupnan_mvl, // llvm.ve.vl.pvfmksupnan.mvl - ve_vl_pvfmksupnan_mvml, // llvm.ve.vl.pvfmksupnan.mvml - ve_vl_pvfmksupne_mvl, // llvm.ve.vl.pvfmksupne.mvl - ve_vl_pvfmksupne_mvml, // llvm.ve.vl.pvfmksupne.mvml - ve_vl_pvfmksupnenan_mvl, // llvm.ve.vl.pvfmksupnenan.mvl - ve_vl_pvfmksupnenan_mvml, // llvm.ve.vl.pvfmksupnenan.mvml - ve_vl_pvfmksupnum_mvl, // llvm.ve.vl.pvfmksupnum.mvl - ve_vl_pvfmksupnum_mvml, // llvm.ve.vl.pvfmksupnum.mvml - ve_vl_pvfmkweq_MvMl, // llvm.ve.vl.pvfmkweq.MvMl - ve_vl_pvfmkweq_Mvl, // llvm.ve.vl.pvfmkweq.Mvl - ve_vl_pvfmkweqnan_MvMl, // llvm.ve.vl.pvfmkweqnan.MvMl - ve_vl_pvfmkweqnan_Mvl, // llvm.ve.vl.pvfmkweqnan.Mvl - ve_vl_pvfmkwge_MvMl, // llvm.ve.vl.pvfmkwge.MvMl - ve_vl_pvfmkwge_Mvl, // llvm.ve.vl.pvfmkwge.Mvl - ve_vl_pvfmkwgenan_MvMl, // llvm.ve.vl.pvfmkwgenan.MvMl - ve_vl_pvfmkwgenan_Mvl, // llvm.ve.vl.pvfmkwgenan.Mvl - ve_vl_pvfmkwgt_MvMl, // llvm.ve.vl.pvfmkwgt.MvMl - ve_vl_pvfmkwgt_Mvl, // llvm.ve.vl.pvfmkwgt.Mvl - ve_vl_pvfmkwgtnan_MvMl, // llvm.ve.vl.pvfmkwgtnan.MvMl - ve_vl_pvfmkwgtnan_Mvl, // llvm.ve.vl.pvfmkwgtnan.Mvl - ve_vl_pvfmkwle_MvMl, // llvm.ve.vl.pvfmkwle.MvMl - ve_vl_pvfmkwle_Mvl, // llvm.ve.vl.pvfmkwle.Mvl - ve_vl_pvfmkwlenan_MvMl, // llvm.ve.vl.pvfmkwlenan.MvMl - ve_vl_pvfmkwlenan_Mvl, // llvm.ve.vl.pvfmkwlenan.Mvl - ve_vl_pvfmkwloeq_mvl, // llvm.ve.vl.pvfmkwloeq.mvl - ve_vl_pvfmkwloeq_mvml, // llvm.ve.vl.pvfmkwloeq.mvml - ve_vl_pvfmkwloeqnan_mvl, // llvm.ve.vl.pvfmkwloeqnan.mvl - ve_vl_pvfmkwloeqnan_mvml, // llvm.ve.vl.pvfmkwloeqnan.mvml - ve_vl_pvfmkwloge_mvl, // llvm.ve.vl.pvfmkwloge.mvl - ve_vl_pvfmkwloge_mvml, // llvm.ve.vl.pvfmkwloge.mvml - ve_vl_pvfmkwlogenan_mvl, // llvm.ve.vl.pvfmkwlogenan.mvl - ve_vl_pvfmkwlogenan_mvml, // llvm.ve.vl.pvfmkwlogenan.mvml - ve_vl_pvfmkwlogt_mvl, // llvm.ve.vl.pvfmkwlogt.mvl - ve_vl_pvfmkwlogt_mvml, // llvm.ve.vl.pvfmkwlogt.mvml - ve_vl_pvfmkwlogtnan_mvl, // llvm.ve.vl.pvfmkwlogtnan.mvl - ve_vl_pvfmkwlogtnan_mvml, // llvm.ve.vl.pvfmkwlogtnan.mvml - ve_vl_pvfmkwlole_mvl, // llvm.ve.vl.pvfmkwlole.mvl - ve_vl_pvfmkwlole_mvml, // llvm.ve.vl.pvfmkwlole.mvml - ve_vl_pvfmkwlolenan_mvl, // llvm.ve.vl.pvfmkwlolenan.mvl - ve_vl_pvfmkwlolenan_mvml, // llvm.ve.vl.pvfmkwlolenan.mvml - ve_vl_pvfmkwlolt_mvl, // llvm.ve.vl.pvfmkwlolt.mvl - ve_vl_pvfmkwlolt_mvml, // llvm.ve.vl.pvfmkwlolt.mvml - ve_vl_pvfmkwloltnan_mvl, // llvm.ve.vl.pvfmkwloltnan.mvl - ve_vl_pvfmkwloltnan_mvml, // llvm.ve.vl.pvfmkwloltnan.mvml - ve_vl_pvfmkwlonan_mvl, // llvm.ve.vl.pvfmkwlonan.mvl - ve_vl_pvfmkwlonan_mvml, // llvm.ve.vl.pvfmkwlonan.mvml - ve_vl_pvfmkwlone_mvl, // llvm.ve.vl.pvfmkwlone.mvl - ve_vl_pvfmkwlone_mvml, // llvm.ve.vl.pvfmkwlone.mvml - ve_vl_pvfmkwlonenan_mvl, // llvm.ve.vl.pvfmkwlonenan.mvl - ve_vl_pvfmkwlonenan_mvml, // llvm.ve.vl.pvfmkwlonenan.mvml - ve_vl_pvfmkwlonum_mvl, // llvm.ve.vl.pvfmkwlonum.mvl - ve_vl_pvfmkwlonum_mvml, // llvm.ve.vl.pvfmkwlonum.mvml - ve_vl_pvfmkwlt_MvMl, // llvm.ve.vl.pvfmkwlt.MvMl - ve_vl_pvfmkwlt_Mvl, // llvm.ve.vl.pvfmkwlt.Mvl - ve_vl_pvfmkwltnan_MvMl, // llvm.ve.vl.pvfmkwltnan.MvMl - ve_vl_pvfmkwltnan_Mvl, // llvm.ve.vl.pvfmkwltnan.Mvl - ve_vl_pvfmkwnan_MvMl, // llvm.ve.vl.pvfmkwnan.MvMl - ve_vl_pvfmkwnan_Mvl, // llvm.ve.vl.pvfmkwnan.Mvl - ve_vl_pvfmkwne_MvMl, // llvm.ve.vl.pvfmkwne.MvMl - ve_vl_pvfmkwne_Mvl, // llvm.ve.vl.pvfmkwne.Mvl - ve_vl_pvfmkwnenan_MvMl, // llvm.ve.vl.pvfmkwnenan.MvMl - ve_vl_pvfmkwnenan_Mvl, // llvm.ve.vl.pvfmkwnenan.Mvl - ve_vl_pvfmkwnum_MvMl, // llvm.ve.vl.pvfmkwnum.MvMl - ve_vl_pvfmkwnum_Mvl, // llvm.ve.vl.pvfmkwnum.Mvl - ve_vl_pvfmkwupeq_mvl, // llvm.ve.vl.pvfmkwupeq.mvl - ve_vl_pvfmkwupeq_mvml, // llvm.ve.vl.pvfmkwupeq.mvml - ve_vl_pvfmkwupeqnan_mvl, // llvm.ve.vl.pvfmkwupeqnan.mvl - ve_vl_pvfmkwupeqnan_mvml, // llvm.ve.vl.pvfmkwupeqnan.mvml - ve_vl_pvfmkwupge_mvl, // llvm.ve.vl.pvfmkwupge.mvl - ve_vl_pvfmkwupge_mvml, // llvm.ve.vl.pvfmkwupge.mvml - ve_vl_pvfmkwupgenan_mvl, // llvm.ve.vl.pvfmkwupgenan.mvl - ve_vl_pvfmkwupgenan_mvml, // llvm.ve.vl.pvfmkwupgenan.mvml - ve_vl_pvfmkwupgt_mvl, // llvm.ve.vl.pvfmkwupgt.mvl - ve_vl_pvfmkwupgt_mvml, // llvm.ve.vl.pvfmkwupgt.mvml - ve_vl_pvfmkwupgtnan_mvl, // llvm.ve.vl.pvfmkwupgtnan.mvl - ve_vl_pvfmkwupgtnan_mvml, // llvm.ve.vl.pvfmkwupgtnan.mvml - ve_vl_pvfmkwuple_mvl, // llvm.ve.vl.pvfmkwuple.mvl - ve_vl_pvfmkwuple_mvml, // llvm.ve.vl.pvfmkwuple.mvml - ve_vl_pvfmkwuplenan_mvl, // llvm.ve.vl.pvfmkwuplenan.mvl - ve_vl_pvfmkwuplenan_mvml, // llvm.ve.vl.pvfmkwuplenan.mvml - ve_vl_pvfmkwuplt_mvl, // llvm.ve.vl.pvfmkwuplt.mvl - ve_vl_pvfmkwuplt_mvml, // llvm.ve.vl.pvfmkwuplt.mvml - ve_vl_pvfmkwupltnan_mvl, // llvm.ve.vl.pvfmkwupltnan.mvl - ve_vl_pvfmkwupltnan_mvml, // llvm.ve.vl.pvfmkwupltnan.mvml - ve_vl_pvfmkwupnan_mvl, // llvm.ve.vl.pvfmkwupnan.mvl - ve_vl_pvfmkwupnan_mvml, // llvm.ve.vl.pvfmkwupnan.mvml - ve_vl_pvfmkwupne_mvl, // llvm.ve.vl.pvfmkwupne.mvl - ve_vl_pvfmkwupne_mvml, // llvm.ve.vl.pvfmkwupne.mvml - ve_vl_pvfmkwupnenan_mvl, // llvm.ve.vl.pvfmkwupnenan.mvl - ve_vl_pvfmkwupnenan_mvml, // llvm.ve.vl.pvfmkwupnenan.mvml - ve_vl_pvfmkwupnum_mvl, // llvm.ve.vl.pvfmkwupnum.mvl - ve_vl_pvfmkwupnum_mvml, // llvm.ve.vl.pvfmkwupnum.mvml - ve_vl_pvfmsb_vsvvMvl, // llvm.ve.vl.pvfmsb.vsvvMvl - ve_vl_pvfmsb_vsvvl, // llvm.ve.vl.pvfmsb.vsvvl - ve_vl_pvfmsb_vsvvvl, // llvm.ve.vl.pvfmsb.vsvvvl - ve_vl_pvfmsb_vvsvMvl, // llvm.ve.vl.pvfmsb.vvsvMvl - ve_vl_pvfmsb_vvsvl, // llvm.ve.vl.pvfmsb.vvsvl - ve_vl_pvfmsb_vvsvvl, // llvm.ve.vl.pvfmsb.vvsvvl - ve_vl_pvfmsb_vvvvMvl, // llvm.ve.vl.pvfmsb.vvvvMvl - ve_vl_pvfmsb_vvvvl, // llvm.ve.vl.pvfmsb.vvvvl - ve_vl_pvfmsb_vvvvvl, // llvm.ve.vl.pvfmsb.vvvvvl - ve_vl_pvfmul_vsvMvl, // llvm.ve.vl.pvfmul.vsvMvl - ve_vl_pvfmul_vsvl, // llvm.ve.vl.pvfmul.vsvl - ve_vl_pvfmul_vsvvl, // llvm.ve.vl.pvfmul.vsvvl - ve_vl_pvfmul_vvvMvl, // llvm.ve.vl.pvfmul.vvvMvl - ve_vl_pvfmul_vvvl, // llvm.ve.vl.pvfmul.vvvl - ve_vl_pvfmul_vvvvl, // llvm.ve.vl.pvfmul.vvvvl - ve_vl_pvfnmad_vsvvMvl, // llvm.ve.vl.pvfnmad.vsvvMvl - ve_vl_pvfnmad_vsvvl, // llvm.ve.vl.pvfnmad.vsvvl - ve_vl_pvfnmad_vsvvvl, // llvm.ve.vl.pvfnmad.vsvvvl - ve_vl_pvfnmad_vvsvMvl, // llvm.ve.vl.pvfnmad.vvsvMvl - ve_vl_pvfnmad_vvsvl, // llvm.ve.vl.pvfnmad.vvsvl - ve_vl_pvfnmad_vvsvvl, // llvm.ve.vl.pvfnmad.vvsvvl - ve_vl_pvfnmad_vvvvMvl, // llvm.ve.vl.pvfnmad.vvvvMvl - ve_vl_pvfnmad_vvvvl, // llvm.ve.vl.pvfnmad.vvvvl - ve_vl_pvfnmad_vvvvvl, // llvm.ve.vl.pvfnmad.vvvvvl - ve_vl_pvfnmsb_vsvvMvl, // llvm.ve.vl.pvfnmsb.vsvvMvl - ve_vl_pvfnmsb_vsvvl, // llvm.ve.vl.pvfnmsb.vsvvl - ve_vl_pvfnmsb_vsvvvl, // llvm.ve.vl.pvfnmsb.vsvvvl - ve_vl_pvfnmsb_vvsvMvl, // llvm.ve.vl.pvfnmsb.vvsvMvl - ve_vl_pvfnmsb_vvsvl, // llvm.ve.vl.pvfnmsb.vvsvl - ve_vl_pvfnmsb_vvsvvl, // llvm.ve.vl.pvfnmsb.vvsvvl - ve_vl_pvfnmsb_vvvvMvl, // llvm.ve.vl.pvfnmsb.vvvvMvl - ve_vl_pvfnmsb_vvvvl, // llvm.ve.vl.pvfnmsb.vvvvl - ve_vl_pvfnmsb_vvvvvl, // llvm.ve.vl.pvfnmsb.vvvvvl - ve_vl_pvfsub_vsvMvl, // llvm.ve.vl.pvfsub.vsvMvl - ve_vl_pvfsub_vsvl, // llvm.ve.vl.pvfsub.vsvl - ve_vl_pvfsub_vsvvl, // llvm.ve.vl.pvfsub.vsvvl - ve_vl_pvfsub_vvvMvl, // llvm.ve.vl.pvfsub.vvvMvl - ve_vl_pvfsub_vvvl, // llvm.ve.vl.pvfsub.vvvl - ve_vl_pvfsub_vvvvl, // llvm.ve.vl.pvfsub.vvvvl - ve_vl_pvmaxs_vsvMvl, // llvm.ve.vl.pvmaxs.vsvMvl - ve_vl_pvmaxs_vsvl, // llvm.ve.vl.pvmaxs.vsvl - ve_vl_pvmaxs_vsvvl, // llvm.ve.vl.pvmaxs.vsvvl - ve_vl_pvmaxs_vvvMvl, // llvm.ve.vl.pvmaxs.vvvMvl - ve_vl_pvmaxs_vvvl, // llvm.ve.vl.pvmaxs.vvvl - ve_vl_pvmaxs_vvvvl, // llvm.ve.vl.pvmaxs.vvvvl - ve_vl_pvmins_vsvMvl, // llvm.ve.vl.pvmins.vsvMvl - ve_vl_pvmins_vsvl, // llvm.ve.vl.pvmins.vsvl - ve_vl_pvmins_vsvvl, // llvm.ve.vl.pvmins.vsvvl - ve_vl_pvmins_vvvMvl, // llvm.ve.vl.pvmins.vvvMvl - ve_vl_pvmins_vvvl, // llvm.ve.vl.pvmins.vvvl - ve_vl_pvmins_vvvvl, // llvm.ve.vl.pvmins.vvvvl - ve_vl_pvor_vsvMvl, // llvm.ve.vl.pvor.vsvMvl - ve_vl_pvor_vsvl, // llvm.ve.vl.pvor.vsvl - ve_vl_pvor_vsvvl, // llvm.ve.vl.pvor.vsvvl - ve_vl_pvor_vvvMvl, // llvm.ve.vl.pvor.vvvMvl - ve_vl_pvor_vvvl, // llvm.ve.vl.pvor.vvvl - ve_vl_pvor_vvvvl, // llvm.ve.vl.pvor.vvvvl - ve_vl_pvrcp_vvl, // llvm.ve.vl.pvrcp.vvl - ve_vl_pvrcp_vvvl, // llvm.ve.vl.pvrcp.vvvl - ve_vl_pvrsqrt_vvl, // llvm.ve.vl.pvrsqrt.vvl - ve_vl_pvrsqrt_vvvl, // llvm.ve.vl.pvrsqrt.vvvl - ve_vl_pvrsqrtnex_vvl, // llvm.ve.vl.pvrsqrtnex.vvl - ve_vl_pvrsqrtnex_vvvl, // llvm.ve.vl.pvrsqrtnex.vvvl - ve_vl_pvseq_vl, // llvm.ve.vl.pvseq.vl - ve_vl_pvseq_vvl, // llvm.ve.vl.pvseq.vvl - ve_vl_pvseqlo_vl, // llvm.ve.vl.pvseqlo.vl - ve_vl_pvseqlo_vvl, // llvm.ve.vl.pvseqlo.vvl - ve_vl_pvsequp_vl, // llvm.ve.vl.pvsequp.vl - ve_vl_pvsequp_vvl, // llvm.ve.vl.pvsequp.vvl - ve_vl_pvsla_vvsMvl, // llvm.ve.vl.pvsla.vvsMvl - ve_vl_pvsla_vvsl, // llvm.ve.vl.pvsla.vvsl - ve_vl_pvsla_vvsvl, // llvm.ve.vl.pvsla.vvsvl - ve_vl_pvsla_vvvMvl, // llvm.ve.vl.pvsla.vvvMvl - ve_vl_pvsla_vvvl, // llvm.ve.vl.pvsla.vvvl - ve_vl_pvsla_vvvvl, // llvm.ve.vl.pvsla.vvvvl - ve_vl_pvsll_vvsMvl, // llvm.ve.vl.pvsll.vvsMvl - ve_vl_pvsll_vvsl, // llvm.ve.vl.pvsll.vvsl - ve_vl_pvsll_vvsvl, // llvm.ve.vl.pvsll.vvsvl - ve_vl_pvsll_vvvMvl, // llvm.ve.vl.pvsll.vvvMvl - ve_vl_pvsll_vvvl, // llvm.ve.vl.pvsll.vvvl - ve_vl_pvsll_vvvvl, // llvm.ve.vl.pvsll.vvvvl - ve_vl_pvsra_vvsMvl, // llvm.ve.vl.pvsra.vvsMvl - ve_vl_pvsra_vvsl, // llvm.ve.vl.pvsra.vvsl - ve_vl_pvsra_vvsvl, // llvm.ve.vl.pvsra.vvsvl - ve_vl_pvsra_vvvMvl, // llvm.ve.vl.pvsra.vvvMvl - ve_vl_pvsra_vvvl, // llvm.ve.vl.pvsra.vvvl - ve_vl_pvsra_vvvvl, // llvm.ve.vl.pvsra.vvvvl - ve_vl_pvsrl_vvsMvl, // llvm.ve.vl.pvsrl.vvsMvl - ve_vl_pvsrl_vvsl, // llvm.ve.vl.pvsrl.vvsl - ve_vl_pvsrl_vvsvl, // llvm.ve.vl.pvsrl.vvsvl - ve_vl_pvsrl_vvvMvl, // llvm.ve.vl.pvsrl.vvvMvl - ve_vl_pvsrl_vvvl, // llvm.ve.vl.pvsrl.vvvl - ve_vl_pvsrl_vvvvl, // llvm.ve.vl.pvsrl.vvvvl - ve_vl_pvsubs_vsvMvl, // llvm.ve.vl.pvsubs.vsvMvl - ve_vl_pvsubs_vsvl, // llvm.ve.vl.pvsubs.vsvl - ve_vl_pvsubs_vsvvl, // llvm.ve.vl.pvsubs.vsvvl - ve_vl_pvsubs_vvvMvl, // llvm.ve.vl.pvsubs.vvvMvl - ve_vl_pvsubs_vvvl, // llvm.ve.vl.pvsubs.vvvl - ve_vl_pvsubs_vvvvl, // llvm.ve.vl.pvsubs.vvvvl - ve_vl_pvsubu_vsvMvl, // llvm.ve.vl.pvsubu.vsvMvl - ve_vl_pvsubu_vsvl, // llvm.ve.vl.pvsubu.vsvl - ve_vl_pvsubu_vsvvl, // llvm.ve.vl.pvsubu.vsvvl - ve_vl_pvsubu_vvvMvl, // llvm.ve.vl.pvsubu.vvvMvl - ve_vl_pvsubu_vvvl, // llvm.ve.vl.pvsubu.vvvl - ve_vl_pvsubu_vvvvl, // llvm.ve.vl.pvsubu.vvvvl - ve_vl_pvxor_vsvMvl, // llvm.ve.vl.pvxor.vsvMvl - ve_vl_pvxor_vsvl, // llvm.ve.vl.pvxor.vsvl - ve_vl_pvxor_vsvvl, // llvm.ve.vl.pvxor.vsvvl - ve_vl_pvxor_vvvMvl, // llvm.ve.vl.pvxor.vvvMvl - ve_vl_pvxor_vvvl, // llvm.ve.vl.pvxor.vvvl - ve_vl_pvxor_vvvvl, // llvm.ve.vl.pvxor.vvvvl - ve_vl_svm_sMs, // llvm.ve.vl.svm.sMs - ve_vl_svm_sms, // llvm.ve.vl.svm.sms - ve_vl_svob, // llvm.ve.vl.svob - ve_vl_tovm_sml, // llvm.ve.vl.tovm.sml - ve_vl_vaddsl_vsvl, // llvm.ve.vl.vaddsl.vsvl - ve_vl_vaddsl_vsvmvl, // llvm.ve.vl.vaddsl.vsvmvl - ve_vl_vaddsl_vsvvl, // llvm.ve.vl.vaddsl.vsvvl - ve_vl_vaddsl_vvvl, // llvm.ve.vl.vaddsl.vvvl - ve_vl_vaddsl_vvvmvl, // llvm.ve.vl.vaddsl.vvvmvl - ve_vl_vaddsl_vvvvl, // llvm.ve.vl.vaddsl.vvvvl - ve_vl_vaddswsx_vsvl, // llvm.ve.vl.vaddswsx.vsvl - ve_vl_vaddswsx_vsvmvl, // llvm.ve.vl.vaddswsx.vsvmvl - ve_vl_vaddswsx_vsvvl, // llvm.ve.vl.vaddswsx.vsvvl - ve_vl_vaddswsx_vvvl, // llvm.ve.vl.vaddswsx.vvvl - ve_vl_vaddswsx_vvvmvl, // llvm.ve.vl.vaddswsx.vvvmvl - ve_vl_vaddswsx_vvvvl, // llvm.ve.vl.vaddswsx.vvvvl - ve_vl_vaddswzx_vsvl, // llvm.ve.vl.vaddswzx.vsvl - ve_vl_vaddswzx_vsvmvl, // llvm.ve.vl.vaddswzx.vsvmvl - ve_vl_vaddswzx_vsvvl, // llvm.ve.vl.vaddswzx.vsvvl - ve_vl_vaddswzx_vvvl, // llvm.ve.vl.vaddswzx.vvvl - ve_vl_vaddswzx_vvvmvl, // llvm.ve.vl.vaddswzx.vvvmvl - ve_vl_vaddswzx_vvvvl, // llvm.ve.vl.vaddswzx.vvvvl - ve_vl_vaddul_vsvl, // llvm.ve.vl.vaddul.vsvl - ve_vl_vaddul_vsvmvl, // llvm.ve.vl.vaddul.vsvmvl - ve_vl_vaddul_vsvvl, // llvm.ve.vl.vaddul.vsvvl - ve_vl_vaddul_vvvl, // llvm.ve.vl.vaddul.vvvl - ve_vl_vaddul_vvvmvl, // llvm.ve.vl.vaddul.vvvmvl - ve_vl_vaddul_vvvvl, // llvm.ve.vl.vaddul.vvvvl - ve_vl_vadduw_vsvl, // llvm.ve.vl.vadduw.vsvl - ve_vl_vadduw_vsvmvl, // llvm.ve.vl.vadduw.vsvmvl - ve_vl_vadduw_vsvvl, // llvm.ve.vl.vadduw.vsvvl - ve_vl_vadduw_vvvl, // llvm.ve.vl.vadduw.vvvl - ve_vl_vadduw_vvvmvl, // llvm.ve.vl.vadduw.vvvmvl - ve_vl_vadduw_vvvvl, // llvm.ve.vl.vadduw.vvvvl - ve_vl_vand_vsvl, // llvm.ve.vl.vand.vsvl - ve_vl_vand_vsvmvl, // llvm.ve.vl.vand.vsvmvl - ve_vl_vand_vsvvl, // llvm.ve.vl.vand.vsvvl - ve_vl_vand_vvvl, // llvm.ve.vl.vand.vvvl - ve_vl_vand_vvvmvl, // llvm.ve.vl.vand.vvvmvl - ve_vl_vand_vvvvl, // llvm.ve.vl.vand.vvvvl - ve_vl_vbrdd_vsl, // llvm.ve.vl.vbrdd.vsl - ve_vl_vbrdd_vsmvl, // llvm.ve.vl.vbrdd.vsmvl - ve_vl_vbrdd_vsvl, // llvm.ve.vl.vbrdd.vsvl - ve_vl_vbrdl_vsl, // llvm.ve.vl.vbrdl.vsl - ve_vl_vbrdl_vsmvl, // llvm.ve.vl.vbrdl.vsmvl - ve_vl_vbrdl_vsvl, // llvm.ve.vl.vbrdl.vsvl - ve_vl_vbrds_vsl, // llvm.ve.vl.vbrds.vsl - ve_vl_vbrds_vsmvl, // llvm.ve.vl.vbrds.vsmvl - ve_vl_vbrds_vsvl, // llvm.ve.vl.vbrds.vsvl - ve_vl_vbrdw_vsl, // llvm.ve.vl.vbrdw.vsl - ve_vl_vbrdw_vsmvl, // llvm.ve.vl.vbrdw.vsmvl - ve_vl_vbrdw_vsvl, // llvm.ve.vl.vbrdw.vsvl - ve_vl_vcmpsl_vsvl, // llvm.ve.vl.vcmpsl.vsvl - ve_vl_vcmpsl_vsvmvl, // llvm.ve.vl.vcmpsl.vsvmvl - ve_vl_vcmpsl_vsvvl, // llvm.ve.vl.vcmpsl.vsvvl - ve_vl_vcmpsl_vvvl, // llvm.ve.vl.vcmpsl.vvvl - ve_vl_vcmpsl_vvvmvl, // llvm.ve.vl.vcmpsl.vvvmvl - ve_vl_vcmpsl_vvvvl, // llvm.ve.vl.vcmpsl.vvvvl - ve_vl_vcmpswsx_vsvl, // llvm.ve.vl.vcmpswsx.vsvl - ve_vl_vcmpswsx_vsvmvl, // llvm.ve.vl.vcmpswsx.vsvmvl - ve_vl_vcmpswsx_vsvvl, // llvm.ve.vl.vcmpswsx.vsvvl - ve_vl_vcmpswsx_vvvl, // llvm.ve.vl.vcmpswsx.vvvl - ve_vl_vcmpswsx_vvvmvl, // llvm.ve.vl.vcmpswsx.vvvmvl - ve_vl_vcmpswsx_vvvvl, // llvm.ve.vl.vcmpswsx.vvvvl - ve_vl_vcmpswzx_vsvl, // llvm.ve.vl.vcmpswzx.vsvl - ve_vl_vcmpswzx_vsvmvl, // llvm.ve.vl.vcmpswzx.vsvmvl - ve_vl_vcmpswzx_vsvvl, // llvm.ve.vl.vcmpswzx.vsvvl - ve_vl_vcmpswzx_vvvl, // llvm.ve.vl.vcmpswzx.vvvl - ve_vl_vcmpswzx_vvvmvl, // llvm.ve.vl.vcmpswzx.vvvmvl - ve_vl_vcmpswzx_vvvvl, // llvm.ve.vl.vcmpswzx.vvvvl - ve_vl_vcmpul_vsvl, // llvm.ve.vl.vcmpul.vsvl - ve_vl_vcmpul_vsvmvl, // llvm.ve.vl.vcmpul.vsvmvl - ve_vl_vcmpul_vsvvl, // llvm.ve.vl.vcmpul.vsvvl - ve_vl_vcmpul_vvvl, // llvm.ve.vl.vcmpul.vvvl - ve_vl_vcmpul_vvvmvl, // llvm.ve.vl.vcmpul.vvvmvl - ve_vl_vcmpul_vvvvl, // llvm.ve.vl.vcmpul.vvvvl - ve_vl_vcmpuw_vsvl, // llvm.ve.vl.vcmpuw.vsvl - ve_vl_vcmpuw_vsvmvl, // llvm.ve.vl.vcmpuw.vsvmvl - ve_vl_vcmpuw_vsvvl, // llvm.ve.vl.vcmpuw.vsvvl - ve_vl_vcmpuw_vvvl, // llvm.ve.vl.vcmpuw.vvvl - ve_vl_vcmpuw_vvvmvl, // llvm.ve.vl.vcmpuw.vvvmvl - ve_vl_vcmpuw_vvvvl, // llvm.ve.vl.vcmpuw.vvvvl - ve_vl_vcp_vvmvl, // llvm.ve.vl.vcp.vvmvl - ve_vl_vcvtdl_vvl, // llvm.ve.vl.vcvtdl.vvl - ve_vl_vcvtdl_vvvl, // llvm.ve.vl.vcvtdl.vvvl - ve_vl_vcvtds_vvl, // llvm.ve.vl.vcvtds.vvl - ve_vl_vcvtds_vvvl, // llvm.ve.vl.vcvtds.vvvl - ve_vl_vcvtdw_vvl, // llvm.ve.vl.vcvtdw.vvl - ve_vl_vcvtdw_vvvl, // llvm.ve.vl.vcvtdw.vvvl - ve_vl_vcvtld_vvl, // llvm.ve.vl.vcvtld.vvl - ve_vl_vcvtld_vvmvl, // llvm.ve.vl.vcvtld.vvmvl - ve_vl_vcvtld_vvvl, // llvm.ve.vl.vcvtld.vvvl - ve_vl_vcvtldrz_vvl, // llvm.ve.vl.vcvtldrz.vvl - ve_vl_vcvtldrz_vvmvl, // llvm.ve.vl.vcvtldrz.vvmvl - ve_vl_vcvtldrz_vvvl, // llvm.ve.vl.vcvtldrz.vvvl - ve_vl_vcvtsd_vvl, // llvm.ve.vl.vcvtsd.vvl - ve_vl_vcvtsd_vvvl, // llvm.ve.vl.vcvtsd.vvvl - ve_vl_vcvtsw_vvl, // llvm.ve.vl.vcvtsw.vvl - ve_vl_vcvtsw_vvvl, // llvm.ve.vl.vcvtsw.vvvl - ve_vl_vcvtwdsx_vvl, // llvm.ve.vl.vcvtwdsx.vvl - ve_vl_vcvtwdsx_vvmvl, // llvm.ve.vl.vcvtwdsx.vvmvl - ve_vl_vcvtwdsx_vvvl, // llvm.ve.vl.vcvtwdsx.vvvl - ve_vl_vcvtwdsxrz_vvl, // llvm.ve.vl.vcvtwdsxrz.vvl - ve_vl_vcvtwdsxrz_vvmvl, // llvm.ve.vl.vcvtwdsxrz.vvmvl - ve_vl_vcvtwdsxrz_vvvl, // llvm.ve.vl.vcvtwdsxrz.vvvl - ve_vl_vcvtwdzx_vvl, // llvm.ve.vl.vcvtwdzx.vvl - ve_vl_vcvtwdzx_vvmvl, // llvm.ve.vl.vcvtwdzx.vvmvl - ve_vl_vcvtwdzx_vvvl, // llvm.ve.vl.vcvtwdzx.vvvl - ve_vl_vcvtwdzxrz_vvl, // llvm.ve.vl.vcvtwdzxrz.vvl - ve_vl_vcvtwdzxrz_vvmvl, // llvm.ve.vl.vcvtwdzxrz.vvmvl - ve_vl_vcvtwdzxrz_vvvl, // llvm.ve.vl.vcvtwdzxrz.vvvl - ve_vl_vcvtwssx_vvl, // llvm.ve.vl.vcvtwssx.vvl - ve_vl_vcvtwssx_vvmvl, // llvm.ve.vl.vcvtwssx.vvmvl - ve_vl_vcvtwssx_vvvl, // llvm.ve.vl.vcvtwssx.vvvl - ve_vl_vcvtwssxrz_vvl, // llvm.ve.vl.vcvtwssxrz.vvl - ve_vl_vcvtwssxrz_vvmvl, // llvm.ve.vl.vcvtwssxrz.vvmvl - ve_vl_vcvtwssxrz_vvvl, // llvm.ve.vl.vcvtwssxrz.vvvl - ve_vl_vcvtwszx_vvl, // llvm.ve.vl.vcvtwszx.vvl - ve_vl_vcvtwszx_vvmvl, // llvm.ve.vl.vcvtwszx.vvmvl - ve_vl_vcvtwszx_vvvl, // llvm.ve.vl.vcvtwszx.vvvl - ve_vl_vcvtwszxrz_vvl, // llvm.ve.vl.vcvtwszxrz.vvl - ve_vl_vcvtwszxrz_vvmvl, // llvm.ve.vl.vcvtwszxrz.vvmvl - ve_vl_vcvtwszxrz_vvvl, // llvm.ve.vl.vcvtwszxrz.vvvl - ve_vl_vdivsl_vsvl, // llvm.ve.vl.vdivsl.vsvl - ve_vl_vdivsl_vsvmvl, // llvm.ve.vl.vdivsl.vsvmvl - ve_vl_vdivsl_vsvvl, // llvm.ve.vl.vdivsl.vsvvl - ve_vl_vdivsl_vvsl, // llvm.ve.vl.vdivsl.vvsl - ve_vl_vdivsl_vvsmvl, // llvm.ve.vl.vdivsl.vvsmvl - ve_vl_vdivsl_vvsvl, // llvm.ve.vl.vdivsl.vvsvl - ve_vl_vdivsl_vvvl, // llvm.ve.vl.vdivsl.vvvl - ve_vl_vdivsl_vvvmvl, // llvm.ve.vl.vdivsl.vvvmvl - ve_vl_vdivsl_vvvvl, // llvm.ve.vl.vdivsl.vvvvl - ve_vl_vdivswsx_vsvl, // llvm.ve.vl.vdivswsx.vsvl - ve_vl_vdivswsx_vsvmvl, // llvm.ve.vl.vdivswsx.vsvmvl - ve_vl_vdivswsx_vsvvl, // llvm.ve.vl.vdivswsx.vsvvl - ve_vl_vdivswsx_vvsl, // llvm.ve.vl.vdivswsx.vvsl - ve_vl_vdivswsx_vvsmvl, // llvm.ve.vl.vdivswsx.vvsmvl - ve_vl_vdivswsx_vvsvl, // llvm.ve.vl.vdivswsx.vvsvl - ve_vl_vdivswsx_vvvl, // llvm.ve.vl.vdivswsx.vvvl - ve_vl_vdivswsx_vvvmvl, // llvm.ve.vl.vdivswsx.vvvmvl - ve_vl_vdivswsx_vvvvl, // llvm.ve.vl.vdivswsx.vvvvl - ve_vl_vdivswzx_vsvl, // llvm.ve.vl.vdivswzx.vsvl - ve_vl_vdivswzx_vsvmvl, // llvm.ve.vl.vdivswzx.vsvmvl - ve_vl_vdivswzx_vsvvl, // llvm.ve.vl.vdivswzx.vsvvl - ve_vl_vdivswzx_vvsl, // llvm.ve.vl.vdivswzx.vvsl - ve_vl_vdivswzx_vvsmvl, // llvm.ve.vl.vdivswzx.vvsmvl - ve_vl_vdivswzx_vvsvl, // llvm.ve.vl.vdivswzx.vvsvl - ve_vl_vdivswzx_vvvl, // llvm.ve.vl.vdivswzx.vvvl - ve_vl_vdivswzx_vvvmvl, // llvm.ve.vl.vdivswzx.vvvmvl - ve_vl_vdivswzx_vvvvl, // llvm.ve.vl.vdivswzx.vvvvl - ve_vl_vdivul_vsvl, // llvm.ve.vl.vdivul.vsvl - ve_vl_vdivul_vsvmvl, // llvm.ve.vl.vdivul.vsvmvl - ve_vl_vdivul_vsvvl, // llvm.ve.vl.vdivul.vsvvl - ve_vl_vdivul_vvsl, // llvm.ve.vl.vdivul.vvsl - ve_vl_vdivul_vvsmvl, // llvm.ve.vl.vdivul.vvsmvl - ve_vl_vdivul_vvsvl, // llvm.ve.vl.vdivul.vvsvl - ve_vl_vdivul_vvvl, // llvm.ve.vl.vdivul.vvvl - ve_vl_vdivul_vvvmvl, // llvm.ve.vl.vdivul.vvvmvl - ve_vl_vdivul_vvvvl, // llvm.ve.vl.vdivul.vvvvl - ve_vl_vdivuw_vsvl, // llvm.ve.vl.vdivuw.vsvl - ve_vl_vdivuw_vsvmvl, // llvm.ve.vl.vdivuw.vsvmvl - ve_vl_vdivuw_vsvvl, // llvm.ve.vl.vdivuw.vsvvl - ve_vl_vdivuw_vvsl, // llvm.ve.vl.vdivuw.vvsl - ve_vl_vdivuw_vvsmvl, // llvm.ve.vl.vdivuw.vvsmvl - ve_vl_vdivuw_vvsvl, // llvm.ve.vl.vdivuw.vvsvl - ve_vl_vdivuw_vvvl, // llvm.ve.vl.vdivuw.vvvl - ve_vl_vdivuw_vvvmvl, // llvm.ve.vl.vdivuw.vvvmvl - ve_vl_vdivuw_vvvvl, // llvm.ve.vl.vdivuw.vvvvl - ve_vl_veqv_vsvl, // llvm.ve.vl.veqv.vsvl - ve_vl_veqv_vsvmvl, // llvm.ve.vl.veqv.vsvmvl - ve_vl_veqv_vsvvl, // llvm.ve.vl.veqv.vsvvl - ve_vl_veqv_vvvl, // llvm.ve.vl.veqv.vvvl - ve_vl_veqv_vvvmvl, // llvm.ve.vl.veqv.vvvmvl - ve_vl_veqv_vvvvl, // llvm.ve.vl.veqv.vvvvl - ve_vl_vex_vvmvl, // llvm.ve.vl.vex.vvmvl - ve_vl_vfaddd_vsvl, // llvm.ve.vl.vfaddd.vsvl - ve_vl_vfaddd_vsvmvl, // llvm.ve.vl.vfaddd.vsvmvl - ve_vl_vfaddd_vsvvl, // llvm.ve.vl.vfaddd.vsvvl - ve_vl_vfaddd_vvvl, // llvm.ve.vl.vfaddd.vvvl - ve_vl_vfaddd_vvvmvl, // llvm.ve.vl.vfaddd.vvvmvl - ve_vl_vfaddd_vvvvl, // llvm.ve.vl.vfaddd.vvvvl - ve_vl_vfadds_vsvl, // llvm.ve.vl.vfadds.vsvl - ve_vl_vfadds_vsvmvl, // llvm.ve.vl.vfadds.vsvmvl - ve_vl_vfadds_vsvvl, // llvm.ve.vl.vfadds.vsvvl - ve_vl_vfadds_vvvl, // llvm.ve.vl.vfadds.vvvl - ve_vl_vfadds_vvvmvl, // llvm.ve.vl.vfadds.vvvmvl - ve_vl_vfadds_vvvvl, // llvm.ve.vl.vfadds.vvvvl - ve_vl_vfcmpd_vsvl, // llvm.ve.vl.vfcmpd.vsvl - ve_vl_vfcmpd_vsvmvl, // llvm.ve.vl.vfcmpd.vsvmvl - ve_vl_vfcmpd_vsvvl, // llvm.ve.vl.vfcmpd.vsvvl - ve_vl_vfcmpd_vvvl, // llvm.ve.vl.vfcmpd.vvvl - ve_vl_vfcmpd_vvvmvl, // llvm.ve.vl.vfcmpd.vvvmvl - ve_vl_vfcmpd_vvvvl, // llvm.ve.vl.vfcmpd.vvvvl - ve_vl_vfcmps_vsvl, // llvm.ve.vl.vfcmps.vsvl - ve_vl_vfcmps_vsvmvl, // llvm.ve.vl.vfcmps.vsvmvl - ve_vl_vfcmps_vsvvl, // llvm.ve.vl.vfcmps.vsvvl - ve_vl_vfcmps_vvvl, // llvm.ve.vl.vfcmps.vvvl - ve_vl_vfcmps_vvvmvl, // llvm.ve.vl.vfcmps.vvvmvl - ve_vl_vfcmps_vvvvl, // llvm.ve.vl.vfcmps.vvvvl - ve_vl_vfdivd_vsvl, // llvm.ve.vl.vfdivd.vsvl - ve_vl_vfdivd_vsvmvl, // llvm.ve.vl.vfdivd.vsvmvl - ve_vl_vfdivd_vsvvl, // llvm.ve.vl.vfdivd.vsvvl - ve_vl_vfdivd_vvvl, // llvm.ve.vl.vfdivd.vvvl - ve_vl_vfdivd_vvvmvl, // llvm.ve.vl.vfdivd.vvvmvl - ve_vl_vfdivd_vvvvl, // llvm.ve.vl.vfdivd.vvvvl - ve_vl_vfdivs_vsvl, // llvm.ve.vl.vfdivs.vsvl - ve_vl_vfdivs_vsvmvl, // llvm.ve.vl.vfdivs.vsvmvl - ve_vl_vfdivs_vsvvl, // llvm.ve.vl.vfdivs.vsvvl - ve_vl_vfdivs_vvvl, // llvm.ve.vl.vfdivs.vvvl - ve_vl_vfdivs_vvvmvl, // llvm.ve.vl.vfdivs.vvvmvl - ve_vl_vfdivs_vvvvl, // llvm.ve.vl.vfdivs.vvvvl - ve_vl_vfmadd_vsvvl, // llvm.ve.vl.vfmadd.vsvvl - ve_vl_vfmadd_vsvvmvl, // llvm.ve.vl.vfmadd.vsvvmvl - ve_vl_vfmadd_vsvvvl, // llvm.ve.vl.vfmadd.vsvvvl - ve_vl_vfmadd_vvsvl, // llvm.ve.vl.vfmadd.vvsvl - ve_vl_vfmadd_vvsvmvl, // llvm.ve.vl.vfmadd.vvsvmvl - ve_vl_vfmadd_vvsvvl, // llvm.ve.vl.vfmadd.vvsvvl - ve_vl_vfmadd_vvvvl, // llvm.ve.vl.vfmadd.vvvvl - ve_vl_vfmadd_vvvvmvl, // llvm.ve.vl.vfmadd.vvvvmvl - ve_vl_vfmadd_vvvvvl, // llvm.ve.vl.vfmadd.vvvvvl - ve_vl_vfmads_vsvvl, // llvm.ve.vl.vfmads.vsvvl - ve_vl_vfmads_vsvvmvl, // llvm.ve.vl.vfmads.vsvvmvl - ve_vl_vfmads_vsvvvl, // llvm.ve.vl.vfmads.vsvvvl - ve_vl_vfmads_vvsvl, // llvm.ve.vl.vfmads.vvsvl - ve_vl_vfmads_vvsvmvl, // llvm.ve.vl.vfmads.vvsvmvl - ve_vl_vfmads_vvsvvl, // llvm.ve.vl.vfmads.vvsvvl - ve_vl_vfmads_vvvvl, // llvm.ve.vl.vfmads.vvvvl - ve_vl_vfmads_vvvvmvl, // llvm.ve.vl.vfmads.vvvvmvl - ve_vl_vfmads_vvvvvl, // llvm.ve.vl.vfmads.vvvvvl - ve_vl_vfmaxd_vsvl, // llvm.ve.vl.vfmaxd.vsvl - ve_vl_vfmaxd_vsvmvl, // llvm.ve.vl.vfmaxd.vsvmvl - ve_vl_vfmaxd_vsvvl, // llvm.ve.vl.vfmaxd.vsvvl - ve_vl_vfmaxd_vvvl, // llvm.ve.vl.vfmaxd.vvvl - ve_vl_vfmaxd_vvvmvl, // llvm.ve.vl.vfmaxd.vvvmvl - ve_vl_vfmaxd_vvvvl, // llvm.ve.vl.vfmaxd.vvvvl - ve_vl_vfmaxs_vsvl, // llvm.ve.vl.vfmaxs.vsvl - ve_vl_vfmaxs_vsvmvl, // llvm.ve.vl.vfmaxs.vsvmvl - ve_vl_vfmaxs_vsvvl, // llvm.ve.vl.vfmaxs.vsvvl - ve_vl_vfmaxs_vvvl, // llvm.ve.vl.vfmaxs.vvvl - ve_vl_vfmaxs_vvvmvl, // llvm.ve.vl.vfmaxs.vvvmvl - ve_vl_vfmaxs_vvvvl, // llvm.ve.vl.vfmaxs.vvvvl - ve_vl_vfmind_vsvl, // llvm.ve.vl.vfmind.vsvl - ve_vl_vfmind_vsvmvl, // llvm.ve.vl.vfmind.vsvmvl - ve_vl_vfmind_vsvvl, // llvm.ve.vl.vfmind.vsvvl - ve_vl_vfmind_vvvl, // llvm.ve.vl.vfmind.vvvl - ve_vl_vfmind_vvvmvl, // llvm.ve.vl.vfmind.vvvmvl - ve_vl_vfmind_vvvvl, // llvm.ve.vl.vfmind.vvvvl - ve_vl_vfmins_vsvl, // llvm.ve.vl.vfmins.vsvl - ve_vl_vfmins_vsvmvl, // llvm.ve.vl.vfmins.vsvmvl - ve_vl_vfmins_vsvvl, // llvm.ve.vl.vfmins.vsvvl - ve_vl_vfmins_vvvl, // llvm.ve.vl.vfmins.vvvl - ve_vl_vfmins_vvvmvl, // llvm.ve.vl.vfmins.vvvmvl - ve_vl_vfmins_vvvvl, // llvm.ve.vl.vfmins.vvvvl - ve_vl_vfmkdeq_mvl, // llvm.ve.vl.vfmkdeq.mvl - ve_vl_vfmkdeq_mvml, // llvm.ve.vl.vfmkdeq.mvml - ve_vl_vfmkdeqnan_mvl, // llvm.ve.vl.vfmkdeqnan.mvl - ve_vl_vfmkdeqnan_mvml, // llvm.ve.vl.vfmkdeqnan.mvml - ve_vl_vfmkdge_mvl, // llvm.ve.vl.vfmkdge.mvl - ve_vl_vfmkdge_mvml, // llvm.ve.vl.vfmkdge.mvml - ve_vl_vfmkdgenan_mvl, // llvm.ve.vl.vfmkdgenan.mvl - ve_vl_vfmkdgenan_mvml, // llvm.ve.vl.vfmkdgenan.mvml - ve_vl_vfmkdgt_mvl, // llvm.ve.vl.vfmkdgt.mvl - ve_vl_vfmkdgt_mvml, // llvm.ve.vl.vfmkdgt.mvml - ve_vl_vfmkdgtnan_mvl, // llvm.ve.vl.vfmkdgtnan.mvl - ve_vl_vfmkdgtnan_mvml, // llvm.ve.vl.vfmkdgtnan.mvml - ve_vl_vfmkdle_mvl, // llvm.ve.vl.vfmkdle.mvl - ve_vl_vfmkdle_mvml, // llvm.ve.vl.vfmkdle.mvml - ve_vl_vfmkdlenan_mvl, // llvm.ve.vl.vfmkdlenan.mvl - ve_vl_vfmkdlenan_mvml, // llvm.ve.vl.vfmkdlenan.mvml - ve_vl_vfmkdlt_mvl, // llvm.ve.vl.vfmkdlt.mvl - ve_vl_vfmkdlt_mvml, // llvm.ve.vl.vfmkdlt.mvml - ve_vl_vfmkdltnan_mvl, // llvm.ve.vl.vfmkdltnan.mvl - ve_vl_vfmkdltnan_mvml, // llvm.ve.vl.vfmkdltnan.mvml - ve_vl_vfmkdnan_mvl, // llvm.ve.vl.vfmkdnan.mvl - ve_vl_vfmkdnan_mvml, // llvm.ve.vl.vfmkdnan.mvml - ve_vl_vfmkdne_mvl, // llvm.ve.vl.vfmkdne.mvl - ve_vl_vfmkdne_mvml, // llvm.ve.vl.vfmkdne.mvml - ve_vl_vfmkdnenan_mvl, // llvm.ve.vl.vfmkdnenan.mvl - ve_vl_vfmkdnenan_mvml, // llvm.ve.vl.vfmkdnenan.mvml - ve_vl_vfmkdnum_mvl, // llvm.ve.vl.vfmkdnum.mvl - ve_vl_vfmkdnum_mvml, // llvm.ve.vl.vfmkdnum.mvml - ve_vl_vfmklaf_ml, // llvm.ve.vl.vfmklaf.ml - ve_vl_vfmklat_ml, // llvm.ve.vl.vfmklat.ml - ve_vl_vfmkleq_mvl, // llvm.ve.vl.vfmkleq.mvl - ve_vl_vfmkleq_mvml, // llvm.ve.vl.vfmkleq.mvml - ve_vl_vfmkleqnan_mvl, // llvm.ve.vl.vfmkleqnan.mvl - ve_vl_vfmkleqnan_mvml, // llvm.ve.vl.vfmkleqnan.mvml - ve_vl_vfmklge_mvl, // llvm.ve.vl.vfmklge.mvl - ve_vl_vfmklge_mvml, // llvm.ve.vl.vfmklge.mvml - ve_vl_vfmklgenan_mvl, // llvm.ve.vl.vfmklgenan.mvl - ve_vl_vfmklgenan_mvml, // llvm.ve.vl.vfmklgenan.mvml - ve_vl_vfmklgt_mvl, // llvm.ve.vl.vfmklgt.mvl - ve_vl_vfmklgt_mvml, // llvm.ve.vl.vfmklgt.mvml - ve_vl_vfmklgtnan_mvl, // llvm.ve.vl.vfmklgtnan.mvl - ve_vl_vfmklgtnan_mvml, // llvm.ve.vl.vfmklgtnan.mvml - ve_vl_vfmklle_mvl, // llvm.ve.vl.vfmklle.mvl - ve_vl_vfmklle_mvml, // llvm.ve.vl.vfmklle.mvml - ve_vl_vfmkllenan_mvl, // llvm.ve.vl.vfmkllenan.mvl - ve_vl_vfmkllenan_mvml, // llvm.ve.vl.vfmkllenan.mvml - ve_vl_vfmkllt_mvl, // llvm.ve.vl.vfmkllt.mvl - ve_vl_vfmkllt_mvml, // llvm.ve.vl.vfmkllt.mvml - ve_vl_vfmklltnan_mvl, // llvm.ve.vl.vfmklltnan.mvl - ve_vl_vfmklltnan_mvml, // llvm.ve.vl.vfmklltnan.mvml - ve_vl_vfmklnan_mvl, // llvm.ve.vl.vfmklnan.mvl - ve_vl_vfmklnan_mvml, // llvm.ve.vl.vfmklnan.mvml - ve_vl_vfmklne_mvl, // llvm.ve.vl.vfmklne.mvl - ve_vl_vfmklne_mvml, // llvm.ve.vl.vfmklne.mvml - ve_vl_vfmklnenan_mvl, // llvm.ve.vl.vfmklnenan.mvl - ve_vl_vfmklnenan_mvml, // llvm.ve.vl.vfmklnenan.mvml - ve_vl_vfmklnum_mvl, // llvm.ve.vl.vfmklnum.mvl - ve_vl_vfmklnum_mvml, // llvm.ve.vl.vfmklnum.mvml - ve_vl_vfmkseq_mvl, // llvm.ve.vl.vfmkseq.mvl - ve_vl_vfmkseq_mvml, // llvm.ve.vl.vfmkseq.mvml - ve_vl_vfmkseqnan_mvl, // llvm.ve.vl.vfmkseqnan.mvl - ve_vl_vfmkseqnan_mvml, // llvm.ve.vl.vfmkseqnan.mvml - ve_vl_vfmksge_mvl, // llvm.ve.vl.vfmksge.mvl - ve_vl_vfmksge_mvml, // llvm.ve.vl.vfmksge.mvml - ve_vl_vfmksgenan_mvl, // llvm.ve.vl.vfmksgenan.mvl - ve_vl_vfmksgenan_mvml, // llvm.ve.vl.vfmksgenan.mvml - ve_vl_vfmksgt_mvl, // llvm.ve.vl.vfmksgt.mvl - ve_vl_vfmksgt_mvml, // llvm.ve.vl.vfmksgt.mvml - ve_vl_vfmksgtnan_mvl, // llvm.ve.vl.vfmksgtnan.mvl - ve_vl_vfmksgtnan_mvml, // llvm.ve.vl.vfmksgtnan.mvml - ve_vl_vfmksle_mvl, // llvm.ve.vl.vfmksle.mvl - ve_vl_vfmksle_mvml, // llvm.ve.vl.vfmksle.mvml - ve_vl_vfmkslenan_mvl, // llvm.ve.vl.vfmkslenan.mvl - ve_vl_vfmkslenan_mvml, // llvm.ve.vl.vfmkslenan.mvml - ve_vl_vfmkslt_mvl, // llvm.ve.vl.vfmkslt.mvl - ve_vl_vfmkslt_mvml, // llvm.ve.vl.vfmkslt.mvml - ve_vl_vfmksltnan_mvl, // llvm.ve.vl.vfmksltnan.mvl - ve_vl_vfmksltnan_mvml, // llvm.ve.vl.vfmksltnan.mvml - ve_vl_vfmksnan_mvl, // llvm.ve.vl.vfmksnan.mvl - ve_vl_vfmksnan_mvml, // llvm.ve.vl.vfmksnan.mvml - ve_vl_vfmksne_mvl, // llvm.ve.vl.vfmksne.mvl - ve_vl_vfmksne_mvml, // llvm.ve.vl.vfmksne.mvml - ve_vl_vfmksnenan_mvl, // llvm.ve.vl.vfmksnenan.mvl - ve_vl_vfmksnenan_mvml, // llvm.ve.vl.vfmksnenan.mvml - ve_vl_vfmksnum_mvl, // llvm.ve.vl.vfmksnum.mvl - ve_vl_vfmksnum_mvml, // llvm.ve.vl.vfmksnum.mvml - ve_vl_vfmkweq_mvl, // llvm.ve.vl.vfmkweq.mvl - ve_vl_vfmkweq_mvml, // llvm.ve.vl.vfmkweq.mvml - ve_vl_vfmkweqnan_mvl, // llvm.ve.vl.vfmkweqnan.mvl - ve_vl_vfmkweqnan_mvml, // llvm.ve.vl.vfmkweqnan.mvml - ve_vl_vfmkwge_mvl, // llvm.ve.vl.vfmkwge.mvl - ve_vl_vfmkwge_mvml, // llvm.ve.vl.vfmkwge.mvml - ve_vl_vfmkwgenan_mvl, // llvm.ve.vl.vfmkwgenan.mvl - ve_vl_vfmkwgenan_mvml, // llvm.ve.vl.vfmkwgenan.mvml - ve_vl_vfmkwgt_mvl, // llvm.ve.vl.vfmkwgt.mvl - ve_vl_vfmkwgt_mvml, // llvm.ve.vl.vfmkwgt.mvml - ve_vl_vfmkwgtnan_mvl, // llvm.ve.vl.vfmkwgtnan.mvl - ve_vl_vfmkwgtnan_mvml, // llvm.ve.vl.vfmkwgtnan.mvml - ve_vl_vfmkwle_mvl, // llvm.ve.vl.vfmkwle.mvl - ve_vl_vfmkwle_mvml, // llvm.ve.vl.vfmkwle.mvml - ve_vl_vfmkwlenan_mvl, // llvm.ve.vl.vfmkwlenan.mvl - ve_vl_vfmkwlenan_mvml, // llvm.ve.vl.vfmkwlenan.mvml - ve_vl_vfmkwlt_mvl, // llvm.ve.vl.vfmkwlt.mvl - ve_vl_vfmkwlt_mvml, // llvm.ve.vl.vfmkwlt.mvml - ve_vl_vfmkwltnan_mvl, // llvm.ve.vl.vfmkwltnan.mvl - ve_vl_vfmkwltnan_mvml, // llvm.ve.vl.vfmkwltnan.mvml - ve_vl_vfmkwnan_mvl, // llvm.ve.vl.vfmkwnan.mvl - ve_vl_vfmkwnan_mvml, // llvm.ve.vl.vfmkwnan.mvml - ve_vl_vfmkwne_mvl, // llvm.ve.vl.vfmkwne.mvl - ve_vl_vfmkwne_mvml, // llvm.ve.vl.vfmkwne.mvml - ve_vl_vfmkwnenan_mvl, // llvm.ve.vl.vfmkwnenan.mvl - ve_vl_vfmkwnenan_mvml, // llvm.ve.vl.vfmkwnenan.mvml - ve_vl_vfmkwnum_mvl, // llvm.ve.vl.vfmkwnum.mvl - ve_vl_vfmkwnum_mvml, // llvm.ve.vl.vfmkwnum.mvml - ve_vl_vfmsbd_vsvvl, // llvm.ve.vl.vfmsbd.vsvvl - ve_vl_vfmsbd_vsvvmvl, // llvm.ve.vl.vfmsbd.vsvvmvl - ve_vl_vfmsbd_vsvvvl, // llvm.ve.vl.vfmsbd.vsvvvl - ve_vl_vfmsbd_vvsvl, // llvm.ve.vl.vfmsbd.vvsvl - ve_vl_vfmsbd_vvsvmvl, // llvm.ve.vl.vfmsbd.vvsvmvl - ve_vl_vfmsbd_vvsvvl, // llvm.ve.vl.vfmsbd.vvsvvl - ve_vl_vfmsbd_vvvvl, // llvm.ve.vl.vfmsbd.vvvvl - ve_vl_vfmsbd_vvvvmvl, // llvm.ve.vl.vfmsbd.vvvvmvl - ve_vl_vfmsbd_vvvvvl, // llvm.ve.vl.vfmsbd.vvvvvl - ve_vl_vfmsbs_vsvvl, // llvm.ve.vl.vfmsbs.vsvvl - ve_vl_vfmsbs_vsvvmvl, // llvm.ve.vl.vfmsbs.vsvvmvl - ve_vl_vfmsbs_vsvvvl, // llvm.ve.vl.vfmsbs.vsvvvl - ve_vl_vfmsbs_vvsvl, // llvm.ve.vl.vfmsbs.vvsvl - ve_vl_vfmsbs_vvsvmvl, // llvm.ve.vl.vfmsbs.vvsvmvl - ve_vl_vfmsbs_vvsvvl, // llvm.ve.vl.vfmsbs.vvsvvl - ve_vl_vfmsbs_vvvvl, // llvm.ve.vl.vfmsbs.vvvvl - ve_vl_vfmsbs_vvvvmvl, // llvm.ve.vl.vfmsbs.vvvvmvl - ve_vl_vfmsbs_vvvvvl, // llvm.ve.vl.vfmsbs.vvvvvl - ve_vl_vfmuld_vsvl, // llvm.ve.vl.vfmuld.vsvl - ve_vl_vfmuld_vsvmvl, // llvm.ve.vl.vfmuld.vsvmvl - ve_vl_vfmuld_vsvvl, // llvm.ve.vl.vfmuld.vsvvl - ve_vl_vfmuld_vvvl, // llvm.ve.vl.vfmuld.vvvl - ve_vl_vfmuld_vvvmvl, // llvm.ve.vl.vfmuld.vvvmvl - ve_vl_vfmuld_vvvvl, // llvm.ve.vl.vfmuld.vvvvl - ve_vl_vfmuls_vsvl, // llvm.ve.vl.vfmuls.vsvl - ve_vl_vfmuls_vsvmvl, // llvm.ve.vl.vfmuls.vsvmvl - ve_vl_vfmuls_vsvvl, // llvm.ve.vl.vfmuls.vsvvl - ve_vl_vfmuls_vvvl, // llvm.ve.vl.vfmuls.vvvl - ve_vl_vfmuls_vvvmvl, // llvm.ve.vl.vfmuls.vvvmvl - ve_vl_vfmuls_vvvvl, // llvm.ve.vl.vfmuls.vvvvl - ve_vl_vfnmadd_vsvvl, // llvm.ve.vl.vfnmadd.vsvvl - ve_vl_vfnmadd_vsvvmvl, // llvm.ve.vl.vfnmadd.vsvvmvl - ve_vl_vfnmadd_vsvvvl, // llvm.ve.vl.vfnmadd.vsvvvl - ve_vl_vfnmadd_vvsvl, // llvm.ve.vl.vfnmadd.vvsvl - ve_vl_vfnmadd_vvsvmvl, // llvm.ve.vl.vfnmadd.vvsvmvl - ve_vl_vfnmadd_vvsvvl, // llvm.ve.vl.vfnmadd.vvsvvl - ve_vl_vfnmadd_vvvvl, // llvm.ve.vl.vfnmadd.vvvvl - ve_vl_vfnmadd_vvvvmvl, // llvm.ve.vl.vfnmadd.vvvvmvl - ve_vl_vfnmadd_vvvvvl, // llvm.ve.vl.vfnmadd.vvvvvl - ve_vl_vfnmads_vsvvl, // llvm.ve.vl.vfnmads.vsvvl - ve_vl_vfnmads_vsvvmvl, // llvm.ve.vl.vfnmads.vsvvmvl - ve_vl_vfnmads_vsvvvl, // llvm.ve.vl.vfnmads.vsvvvl - ve_vl_vfnmads_vvsvl, // llvm.ve.vl.vfnmads.vvsvl - ve_vl_vfnmads_vvsvmvl, // llvm.ve.vl.vfnmads.vvsvmvl - ve_vl_vfnmads_vvsvvl, // llvm.ve.vl.vfnmads.vvsvvl - ve_vl_vfnmads_vvvvl, // llvm.ve.vl.vfnmads.vvvvl - ve_vl_vfnmads_vvvvmvl, // llvm.ve.vl.vfnmads.vvvvmvl - ve_vl_vfnmads_vvvvvl, // llvm.ve.vl.vfnmads.vvvvvl - ve_vl_vfnmsbd_vsvvl, // llvm.ve.vl.vfnmsbd.vsvvl - ve_vl_vfnmsbd_vsvvmvl, // llvm.ve.vl.vfnmsbd.vsvvmvl - ve_vl_vfnmsbd_vsvvvl, // llvm.ve.vl.vfnmsbd.vsvvvl - ve_vl_vfnmsbd_vvsvl, // llvm.ve.vl.vfnmsbd.vvsvl - ve_vl_vfnmsbd_vvsvmvl, // llvm.ve.vl.vfnmsbd.vvsvmvl - ve_vl_vfnmsbd_vvsvvl, // llvm.ve.vl.vfnmsbd.vvsvvl - ve_vl_vfnmsbd_vvvvl, // llvm.ve.vl.vfnmsbd.vvvvl - ve_vl_vfnmsbd_vvvvmvl, // llvm.ve.vl.vfnmsbd.vvvvmvl - ve_vl_vfnmsbd_vvvvvl, // llvm.ve.vl.vfnmsbd.vvvvvl - ve_vl_vfnmsbs_vsvvl, // llvm.ve.vl.vfnmsbs.vsvvl - ve_vl_vfnmsbs_vsvvmvl, // llvm.ve.vl.vfnmsbs.vsvvmvl - ve_vl_vfnmsbs_vsvvvl, // llvm.ve.vl.vfnmsbs.vsvvvl - ve_vl_vfnmsbs_vvsvl, // llvm.ve.vl.vfnmsbs.vvsvl - ve_vl_vfnmsbs_vvsvmvl, // llvm.ve.vl.vfnmsbs.vvsvmvl - ve_vl_vfnmsbs_vvsvvl, // llvm.ve.vl.vfnmsbs.vvsvvl - ve_vl_vfnmsbs_vvvvl, // llvm.ve.vl.vfnmsbs.vvvvl - ve_vl_vfnmsbs_vvvvmvl, // llvm.ve.vl.vfnmsbs.vvvvmvl - ve_vl_vfnmsbs_vvvvvl, // llvm.ve.vl.vfnmsbs.vvvvvl - ve_vl_vfrmaxdfst_vvl, // llvm.ve.vl.vfrmaxdfst.vvl - ve_vl_vfrmaxdfst_vvvl, // llvm.ve.vl.vfrmaxdfst.vvvl - ve_vl_vfrmaxdlst_vvl, // llvm.ve.vl.vfrmaxdlst.vvl - ve_vl_vfrmaxdlst_vvvl, // llvm.ve.vl.vfrmaxdlst.vvvl - ve_vl_vfrmaxsfst_vvl, // llvm.ve.vl.vfrmaxsfst.vvl - ve_vl_vfrmaxsfst_vvvl, // llvm.ve.vl.vfrmaxsfst.vvvl - ve_vl_vfrmaxslst_vvl, // llvm.ve.vl.vfrmaxslst.vvl - ve_vl_vfrmaxslst_vvvl, // llvm.ve.vl.vfrmaxslst.vvvl - ve_vl_vfrmindfst_vvl, // llvm.ve.vl.vfrmindfst.vvl - ve_vl_vfrmindfst_vvvl, // llvm.ve.vl.vfrmindfst.vvvl - ve_vl_vfrmindlst_vvl, // llvm.ve.vl.vfrmindlst.vvl - ve_vl_vfrmindlst_vvvl, // llvm.ve.vl.vfrmindlst.vvvl - ve_vl_vfrminsfst_vvl, // llvm.ve.vl.vfrminsfst.vvl - ve_vl_vfrminsfst_vvvl, // llvm.ve.vl.vfrminsfst.vvvl - ve_vl_vfrminslst_vvl, // llvm.ve.vl.vfrminslst.vvl - ve_vl_vfrminslst_vvvl, // llvm.ve.vl.vfrminslst.vvvl - ve_vl_vfsqrtd_vvl, // llvm.ve.vl.vfsqrtd.vvl - ve_vl_vfsqrtd_vvvl, // llvm.ve.vl.vfsqrtd.vvvl - ve_vl_vfsqrts_vvl, // llvm.ve.vl.vfsqrts.vvl - ve_vl_vfsqrts_vvvl, // llvm.ve.vl.vfsqrts.vvvl - ve_vl_vfsubd_vsvl, // llvm.ve.vl.vfsubd.vsvl - ve_vl_vfsubd_vsvmvl, // llvm.ve.vl.vfsubd.vsvmvl - ve_vl_vfsubd_vsvvl, // llvm.ve.vl.vfsubd.vsvvl - ve_vl_vfsubd_vvvl, // llvm.ve.vl.vfsubd.vvvl - ve_vl_vfsubd_vvvmvl, // llvm.ve.vl.vfsubd.vvvmvl - ve_vl_vfsubd_vvvvl, // llvm.ve.vl.vfsubd.vvvvl - ve_vl_vfsubs_vsvl, // llvm.ve.vl.vfsubs.vsvl - ve_vl_vfsubs_vsvmvl, // llvm.ve.vl.vfsubs.vsvmvl - ve_vl_vfsubs_vsvvl, // llvm.ve.vl.vfsubs.vsvvl - ve_vl_vfsubs_vvvl, // llvm.ve.vl.vfsubs.vvvl - ve_vl_vfsubs_vvvmvl, // llvm.ve.vl.vfsubs.vvvmvl - ve_vl_vfsubs_vvvvl, // llvm.ve.vl.vfsubs.vvvvl - ve_vl_vfsumd_vvl, // llvm.ve.vl.vfsumd.vvl - ve_vl_vfsumd_vvml, // llvm.ve.vl.vfsumd.vvml - ve_vl_vfsums_vvl, // llvm.ve.vl.vfsums.vvl - ve_vl_vfsums_vvml, // llvm.ve.vl.vfsums.vvml - ve_vl_vgt_vvssl, // llvm.ve.vl.vgt.vvssl - ve_vl_vgt_vvssml, // llvm.ve.vl.vgt.vvssml - ve_vl_vgt_vvssmvl, // llvm.ve.vl.vgt.vvssmvl - ve_vl_vgt_vvssvl, // llvm.ve.vl.vgt.vvssvl - ve_vl_vgtlsx_vvssl, // llvm.ve.vl.vgtlsx.vvssl - ve_vl_vgtlsx_vvssml, // llvm.ve.vl.vgtlsx.vvssml - ve_vl_vgtlsx_vvssmvl, // llvm.ve.vl.vgtlsx.vvssmvl - ve_vl_vgtlsx_vvssvl, // llvm.ve.vl.vgtlsx.vvssvl - ve_vl_vgtlsxnc_vvssl, // llvm.ve.vl.vgtlsxnc.vvssl - ve_vl_vgtlsxnc_vvssml, // llvm.ve.vl.vgtlsxnc.vvssml - ve_vl_vgtlsxnc_vvssmvl, // llvm.ve.vl.vgtlsxnc.vvssmvl - ve_vl_vgtlsxnc_vvssvl, // llvm.ve.vl.vgtlsxnc.vvssvl - ve_vl_vgtlzx_vvssl, // llvm.ve.vl.vgtlzx.vvssl - ve_vl_vgtlzx_vvssml, // llvm.ve.vl.vgtlzx.vvssml - ve_vl_vgtlzx_vvssmvl, // llvm.ve.vl.vgtlzx.vvssmvl - ve_vl_vgtlzx_vvssvl, // llvm.ve.vl.vgtlzx.vvssvl - ve_vl_vgtlzxnc_vvssl, // llvm.ve.vl.vgtlzxnc.vvssl - ve_vl_vgtlzxnc_vvssml, // llvm.ve.vl.vgtlzxnc.vvssml - ve_vl_vgtlzxnc_vvssmvl, // llvm.ve.vl.vgtlzxnc.vvssmvl - ve_vl_vgtlzxnc_vvssvl, // llvm.ve.vl.vgtlzxnc.vvssvl - ve_vl_vgtnc_vvssl, // llvm.ve.vl.vgtnc.vvssl - ve_vl_vgtnc_vvssml, // llvm.ve.vl.vgtnc.vvssml - ve_vl_vgtnc_vvssmvl, // llvm.ve.vl.vgtnc.vvssmvl - ve_vl_vgtnc_vvssvl, // llvm.ve.vl.vgtnc.vvssvl - ve_vl_vgtu_vvssl, // llvm.ve.vl.vgtu.vvssl - ve_vl_vgtu_vvssml, // llvm.ve.vl.vgtu.vvssml - ve_vl_vgtu_vvssmvl, // llvm.ve.vl.vgtu.vvssmvl - ve_vl_vgtu_vvssvl, // llvm.ve.vl.vgtu.vvssvl - ve_vl_vgtunc_vvssl, // llvm.ve.vl.vgtunc.vvssl - ve_vl_vgtunc_vvssml, // llvm.ve.vl.vgtunc.vvssml - ve_vl_vgtunc_vvssmvl, // llvm.ve.vl.vgtunc.vvssmvl - ve_vl_vgtunc_vvssvl, // llvm.ve.vl.vgtunc.vvssvl - ve_vl_vld_vssl, // llvm.ve.vl.vld.vssl - ve_vl_vld_vssvl, // llvm.ve.vl.vld.vssvl - ve_vl_vld2d_vssl, // llvm.ve.vl.vld2d.vssl - ve_vl_vld2d_vssvl, // llvm.ve.vl.vld2d.vssvl - ve_vl_vld2dnc_vssl, // llvm.ve.vl.vld2dnc.vssl - ve_vl_vld2dnc_vssvl, // llvm.ve.vl.vld2dnc.vssvl - ve_vl_vldl2dsx_vssl, // llvm.ve.vl.vldl2dsx.vssl - ve_vl_vldl2dsx_vssvl, // llvm.ve.vl.vldl2dsx.vssvl - ve_vl_vldl2dsxnc_vssl, // llvm.ve.vl.vldl2dsxnc.vssl - ve_vl_vldl2dsxnc_vssvl, // llvm.ve.vl.vldl2dsxnc.vssvl - ve_vl_vldl2dzx_vssl, // llvm.ve.vl.vldl2dzx.vssl - ve_vl_vldl2dzx_vssvl, // llvm.ve.vl.vldl2dzx.vssvl - ve_vl_vldl2dzxnc_vssl, // llvm.ve.vl.vldl2dzxnc.vssl - ve_vl_vldl2dzxnc_vssvl, // llvm.ve.vl.vldl2dzxnc.vssvl - ve_vl_vldlsx_vssl, // llvm.ve.vl.vldlsx.vssl - ve_vl_vldlsx_vssvl, // llvm.ve.vl.vldlsx.vssvl - ve_vl_vldlsxnc_vssl, // llvm.ve.vl.vldlsxnc.vssl - ve_vl_vldlsxnc_vssvl, // llvm.ve.vl.vldlsxnc.vssvl - ve_vl_vldlzx_vssl, // llvm.ve.vl.vldlzx.vssl - ve_vl_vldlzx_vssvl, // llvm.ve.vl.vldlzx.vssvl - ve_vl_vldlzxnc_vssl, // llvm.ve.vl.vldlzxnc.vssl - ve_vl_vldlzxnc_vssvl, // llvm.ve.vl.vldlzxnc.vssvl - ve_vl_vldnc_vssl, // llvm.ve.vl.vldnc.vssl - ve_vl_vldnc_vssvl, // llvm.ve.vl.vldnc.vssvl - ve_vl_vldu_vssl, // llvm.ve.vl.vldu.vssl - ve_vl_vldu_vssvl, // llvm.ve.vl.vldu.vssvl - ve_vl_vldu2d_vssl, // llvm.ve.vl.vldu2d.vssl - ve_vl_vldu2d_vssvl, // llvm.ve.vl.vldu2d.vssvl - ve_vl_vldu2dnc_vssl, // llvm.ve.vl.vldu2dnc.vssl - ve_vl_vldu2dnc_vssvl, // llvm.ve.vl.vldu2dnc.vssvl - ve_vl_vldunc_vssl, // llvm.ve.vl.vldunc.vssl - ve_vl_vldunc_vssvl, // llvm.ve.vl.vldunc.vssvl - ve_vl_vmaxsl_vsvl, // llvm.ve.vl.vmaxsl.vsvl - ve_vl_vmaxsl_vsvmvl, // llvm.ve.vl.vmaxsl.vsvmvl - ve_vl_vmaxsl_vsvvl, // llvm.ve.vl.vmaxsl.vsvvl - ve_vl_vmaxsl_vvvl, // llvm.ve.vl.vmaxsl.vvvl - ve_vl_vmaxsl_vvvmvl, // llvm.ve.vl.vmaxsl.vvvmvl - ve_vl_vmaxsl_vvvvl, // llvm.ve.vl.vmaxsl.vvvvl - ve_vl_vmaxswsx_vsvl, // llvm.ve.vl.vmaxswsx.vsvl - ve_vl_vmaxswsx_vsvmvl, // llvm.ve.vl.vmaxswsx.vsvmvl - ve_vl_vmaxswsx_vsvvl, // llvm.ve.vl.vmaxswsx.vsvvl - ve_vl_vmaxswsx_vvvl, // llvm.ve.vl.vmaxswsx.vvvl - ve_vl_vmaxswsx_vvvmvl, // llvm.ve.vl.vmaxswsx.vvvmvl - ve_vl_vmaxswsx_vvvvl, // llvm.ve.vl.vmaxswsx.vvvvl - ve_vl_vmaxswzx_vsvl, // llvm.ve.vl.vmaxswzx.vsvl - ve_vl_vmaxswzx_vsvmvl, // llvm.ve.vl.vmaxswzx.vsvmvl - ve_vl_vmaxswzx_vsvvl, // llvm.ve.vl.vmaxswzx.vsvvl - ve_vl_vmaxswzx_vvvl, // llvm.ve.vl.vmaxswzx.vvvl - ve_vl_vmaxswzx_vvvmvl, // llvm.ve.vl.vmaxswzx.vvvmvl - ve_vl_vmaxswzx_vvvvl, // llvm.ve.vl.vmaxswzx.vvvvl - ve_vl_vminsl_vsvl, // llvm.ve.vl.vminsl.vsvl - ve_vl_vminsl_vsvmvl, // llvm.ve.vl.vminsl.vsvmvl - ve_vl_vminsl_vsvvl, // llvm.ve.vl.vminsl.vsvvl - ve_vl_vminsl_vvvl, // llvm.ve.vl.vminsl.vvvl - ve_vl_vminsl_vvvmvl, // llvm.ve.vl.vminsl.vvvmvl - ve_vl_vminsl_vvvvl, // llvm.ve.vl.vminsl.vvvvl - ve_vl_vminswsx_vsvl, // llvm.ve.vl.vminswsx.vsvl - ve_vl_vminswsx_vsvmvl, // llvm.ve.vl.vminswsx.vsvmvl - ve_vl_vminswsx_vsvvl, // llvm.ve.vl.vminswsx.vsvvl - ve_vl_vminswsx_vvvl, // llvm.ve.vl.vminswsx.vvvl - ve_vl_vminswsx_vvvmvl, // llvm.ve.vl.vminswsx.vvvmvl - ve_vl_vminswsx_vvvvl, // llvm.ve.vl.vminswsx.vvvvl - ve_vl_vminswzx_vsvl, // llvm.ve.vl.vminswzx.vsvl - ve_vl_vminswzx_vsvmvl, // llvm.ve.vl.vminswzx.vsvmvl - ve_vl_vminswzx_vsvvl, // llvm.ve.vl.vminswzx.vsvvl - ve_vl_vminswzx_vvvl, // llvm.ve.vl.vminswzx.vvvl - ve_vl_vminswzx_vvvmvl, // llvm.ve.vl.vminswzx.vvvmvl - ve_vl_vminswzx_vvvvl, // llvm.ve.vl.vminswzx.vvvvl - ve_vl_vmrg_vsvml, // llvm.ve.vl.vmrg.vsvml - ve_vl_vmrg_vsvmvl, // llvm.ve.vl.vmrg.vsvmvl - ve_vl_vmrg_vvvml, // llvm.ve.vl.vmrg.vvvml - ve_vl_vmrg_vvvmvl, // llvm.ve.vl.vmrg.vvvmvl - ve_vl_vmrgw_vsvMl, // llvm.ve.vl.vmrgw.vsvMl - ve_vl_vmrgw_vsvMvl, // llvm.ve.vl.vmrgw.vsvMvl - ve_vl_vmrgw_vvvMl, // llvm.ve.vl.vmrgw.vvvMl - ve_vl_vmrgw_vvvMvl, // llvm.ve.vl.vmrgw.vvvMvl - ve_vl_vmulsl_vsvl, // llvm.ve.vl.vmulsl.vsvl - ve_vl_vmulsl_vsvmvl, // llvm.ve.vl.vmulsl.vsvmvl - ve_vl_vmulsl_vsvvl, // llvm.ve.vl.vmulsl.vsvvl - ve_vl_vmulsl_vvvl, // llvm.ve.vl.vmulsl.vvvl - ve_vl_vmulsl_vvvmvl, // llvm.ve.vl.vmulsl.vvvmvl - ve_vl_vmulsl_vvvvl, // llvm.ve.vl.vmulsl.vvvvl - ve_vl_vmulslw_vsvl, // llvm.ve.vl.vmulslw.vsvl - ve_vl_vmulslw_vsvvl, // llvm.ve.vl.vmulslw.vsvvl - ve_vl_vmulslw_vvvl, // llvm.ve.vl.vmulslw.vvvl - ve_vl_vmulslw_vvvvl, // llvm.ve.vl.vmulslw.vvvvl - ve_vl_vmulswsx_vsvl, // llvm.ve.vl.vmulswsx.vsvl - ve_vl_vmulswsx_vsvmvl, // llvm.ve.vl.vmulswsx.vsvmvl - ve_vl_vmulswsx_vsvvl, // llvm.ve.vl.vmulswsx.vsvvl - ve_vl_vmulswsx_vvvl, // llvm.ve.vl.vmulswsx.vvvl - ve_vl_vmulswsx_vvvmvl, // llvm.ve.vl.vmulswsx.vvvmvl - ve_vl_vmulswsx_vvvvl, // llvm.ve.vl.vmulswsx.vvvvl - ve_vl_vmulswzx_vsvl, // llvm.ve.vl.vmulswzx.vsvl - ve_vl_vmulswzx_vsvmvl, // llvm.ve.vl.vmulswzx.vsvmvl - ve_vl_vmulswzx_vsvvl, // llvm.ve.vl.vmulswzx.vsvvl - ve_vl_vmulswzx_vvvl, // llvm.ve.vl.vmulswzx.vvvl - ve_vl_vmulswzx_vvvmvl, // llvm.ve.vl.vmulswzx.vvvmvl - ve_vl_vmulswzx_vvvvl, // llvm.ve.vl.vmulswzx.vvvvl - ve_vl_vmulul_vsvl, // llvm.ve.vl.vmulul.vsvl - ve_vl_vmulul_vsvmvl, // llvm.ve.vl.vmulul.vsvmvl - ve_vl_vmulul_vsvvl, // llvm.ve.vl.vmulul.vsvvl - ve_vl_vmulul_vvvl, // llvm.ve.vl.vmulul.vvvl - ve_vl_vmulul_vvvmvl, // llvm.ve.vl.vmulul.vvvmvl - ve_vl_vmulul_vvvvl, // llvm.ve.vl.vmulul.vvvvl - ve_vl_vmuluw_vsvl, // llvm.ve.vl.vmuluw.vsvl - ve_vl_vmuluw_vsvmvl, // llvm.ve.vl.vmuluw.vsvmvl - ve_vl_vmuluw_vsvvl, // llvm.ve.vl.vmuluw.vsvvl - ve_vl_vmuluw_vvvl, // llvm.ve.vl.vmuluw.vvvl - ve_vl_vmuluw_vvvmvl, // llvm.ve.vl.vmuluw.vvvmvl - ve_vl_vmuluw_vvvvl, // llvm.ve.vl.vmuluw.vvvvl - ve_vl_vmv_vsvl, // llvm.ve.vl.vmv.vsvl - ve_vl_vmv_vsvmvl, // llvm.ve.vl.vmv.vsvmvl - ve_vl_vmv_vsvvl, // llvm.ve.vl.vmv.vsvvl - ve_vl_vor_vsvl, // llvm.ve.vl.vor.vsvl - ve_vl_vor_vsvmvl, // llvm.ve.vl.vor.vsvmvl - ve_vl_vor_vsvvl, // llvm.ve.vl.vor.vsvvl - ve_vl_vor_vvvl, // llvm.ve.vl.vor.vvvl - ve_vl_vor_vvvmvl, // llvm.ve.vl.vor.vvvmvl - ve_vl_vor_vvvvl, // llvm.ve.vl.vor.vvvvl - ve_vl_vrand_vvl, // llvm.ve.vl.vrand.vvl - ve_vl_vrand_vvml, // llvm.ve.vl.vrand.vvml - ve_vl_vrcpd_vvl, // llvm.ve.vl.vrcpd.vvl - ve_vl_vrcpd_vvvl, // llvm.ve.vl.vrcpd.vvvl - ve_vl_vrcps_vvl, // llvm.ve.vl.vrcps.vvl - ve_vl_vrcps_vvvl, // llvm.ve.vl.vrcps.vvvl - ve_vl_vrmaxslfst_vvl, // llvm.ve.vl.vrmaxslfst.vvl - ve_vl_vrmaxslfst_vvvl, // llvm.ve.vl.vrmaxslfst.vvvl - ve_vl_vrmaxsllst_vvl, // llvm.ve.vl.vrmaxsllst.vvl - ve_vl_vrmaxsllst_vvvl, // llvm.ve.vl.vrmaxsllst.vvvl - ve_vl_vrmaxswfstsx_vvl, // llvm.ve.vl.vrmaxswfstsx.vvl - ve_vl_vrmaxswfstsx_vvvl, // llvm.ve.vl.vrmaxswfstsx.vvvl - ve_vl_vrmaxswfstzx_vvl, // llvm.ve.vl.vrmaxswfstzx.vvl - ve_vl_vrmaxswfstzx_vvvl, // llvm.ve.vl.vrmaxswfstzx.vvvl - ve_vl_vrmaxswlstsx_vvl, // llvm.ve.vl.vrmaxswlstsx.vvl - ve_vl_vrmaxswlstsx_vvvl, // llvm.ve.vl.vrmaxswlstsx.vvvl - ve_vl_vrmaxswlstzx_vvl, // llvm.ve.vl.vrmaxswlstzx.vvl - ve_vl_vrmaxswlstzx_vvvl, // llvm.ve.vl.vrmaxswlstzx.vvvl - ve_vl_vrminslfst_vvl, // llvm.ve.vl.vrminslfst.vvl - ve_vl_vrminslfst_vvvl, // llvm.ve.vl.vrminslfst.vvvl - ve_vl_vrminsllst_vvl, // llvm.ve.vl.vrminsllst.vvl - ve_vl_vrminsllst_vvvl, // llvm.ve.vl.vrminsllst.vvvl - ve_vl_vrminswfstsx_vvl, // llvm.ve.vl.vrminswfstsx.vvl - ve_vl_vrminswfstsx_vvvl, // llvm.ve.vl.vrminswfstsx.vvvl - ve_vl_vrminswfstzx_vvl, // llvm.ve.vl.vrminswfstzx.vvl - ve_vl_vrminswfstzx_vvvl, // llvm.ve.vl.vrminswfstzx.vvvl - ve_vl_vrminswlstsx_vvl, // llvm.ve.vl.vrminswlstsx.vvl - ve_vl_vrminswlstsx_vvvl, // llvm.ve.vl.vrminswlstsx.vvvl - ve_vl_vrminswlstzx_vvl, // llvm.ve.vl.vrminswlstzx.vvl - ve_vl_vrminswlstzx_vvvl, // llvm.ve.vl.vrminswlstzx.vvvl - ve_vl_vror_vvl, // llvm.ve.vl.vror.vvl - ve_vl_vror_vvml, // llvm.ve.vl.vror.vvml - ve_vl_vrsqrtd_vvl, // llvm.ve.vl.vrsqrtd.vvl - ve_vl_vrsqrtd_vvvl, // llvm.ve.vl.vrsqrtd.vvvl - ve_vl_vrsqrtdnex_vvl, // llvm.ve.vl.vrsqrtdnex.vvl - ve_vl_vrsqrtdnex_vvvl, // llvm.ve.vl.vrsqrtdnex.vvvl - ve_vl_vrsqrts_vvl, // llvm.ve.vl.vrsqrts.vvl - ve_vl_vrsqrts_vvvl, // llvm.ve.vl.vrsqrts.vvvl - ve_vl_vrsqrtsnex_vvl, // llvm.ve.vl.vrsqrtsnex.vvl - ve_vl_vrsqrtsnex_vvvl, // llvm.ve.vl.vrsqrtsnex.vvvl - ve_vl_vrxor_vvl, // llvm.ve.vl.vrxor.vvl - ve_vl_vrxor_vvml, // llvm.ve.vl.vrxor.vvml - ve_vl_vsc_vvssl, // llvm.ve.vl.vsc.vvssl - ve_vl_vsc_vvssml, // llvm.ve.vl.vsc.vvssml - ve_vl_vscl_vvssl, // llvm.ve.vl.vscl.vvssl - ve_vl_vscl_vvssml, // llvm.ve.vl.vscl.vvssml - ve_vl_vsclnc_vvssl, // llvm.ve.vl.vsclnc.vvssl - ve_vl_vsclnc_vvssml, // llvm.ve.vl.vsclnc.vvssml - ve_vl_vsclncot_vvssl, // llvm.ve.vl.vsclncot.vvssl - ve_vl_vsclncot_vvssml, // llvm.ve.vl.vsclncot.vvssml - ve_vl_vsclot_vvssl, // llvm.ve.vl.vsclot.vvssl - ve_vl_vsclot_vvssml, // llvm.ve.vl.vsclot.vvssml - ve_vl_vscnc_vvssl, // llvm.ve.vl.vscnc.vvssl - ve_vl_vscnc_vvssml, // llvm.ve.vl.vscnc.vvssml - ve_vl_vscncot_vvssl, // llvm.ve.vl.vscncot.vvssl - ve_vl_vscncot_vvssml, // llvm.ve.vl.vscncot.vvssml - ve_vl_vscot_vvssl, // llvm.ve.vl.vscot.vvssl - ve_vl_vscot_vvssml, // llvm.ve.vl.vscot.vvssml - ve_vl_vscu_vvssl, // llvm.ve.vl.vscu.vvssl - ve_vl_vscu_vvssml, // llvm.ve.vl.vscu.vvssml - ve_vl_vscunc_vvssl, // llvm.ve.vl.vscunc.vvssl - ve_vl_vscunc_vvssml, // llvm.ve.vl.vscunc.vvssml - ve_vl_vscuncot_vvssl, // llvm.ve.vl.vscuncot.vvssl - ve_vl_vscuncot_vvssml, // llvm.ve.vl.vscuncot.vvssml - ve_vl_vscuot_vvssl, // llvm.ve.vl.vscuot.vvssl - ve_vl_vscuot_vvssml, // llvm.ve.vl.vscuot.vvssml - ve_vl_vseq_vl, // llvm.ve.vl.vseq.vl - ve_vl_vseq_vvl, // llvm.ve.vl.vseq.vvl - ve_vl_vsfa_vvssl, // llvm.ve.vl.vsfa.vvssl - ve_vl_vsfa_vvssmvl, // llvm.ve.vl.vsfa.vvssmvl - ve_vl_vsfa_vvssvl, // llvm.ve.vl.vsfa.vvssvl - ve_vl_vshf_vvvsl, // llvm.ve.vl.vshf.vvvsl - ve_vl_vshf_vvvsvl, // llvm.ve.vl.vshf.vvvsvl - ve_vl_vslal_vvsl, // llvm.ve.vl.vslal.vvsl - ve_vl_vslal_vvsmvl, // llvm.ve.vl.vslal.vvsmvl - ve_vl_vslal_vvsvl, // llvm.ve.vl.vslal.vvsvl - ve_vl_vslal_vvvl, // llvm.ve.vl.vslal.vvvl - ve_vl_vslal_vvvmvl, // llvm.ve.vl.vslal.vvvmvl - ve_vl_vslal_vvvvl, // llvm.ve.vl.vslal.vvvvl - ve_vl_vslawsx_vvsl, // llvm.ve.vl.vslawsx.vvsl - ve_vl_vslawsx_vvsmvl, // llvm.ve.vl.vslawsx.vvsmvl - ve_vl_vslawsx_vvsvl, // llvm.ve.vl.vslawsx.vvsvl - ve_vl_vslawsx_vvvl, // llvm.ve.vl.vslawsx.vvvl - ve_vl_vslawsx_vvvmvl, // llvm.ve.vl.vslawsx.vvvmvl - ve_vl_vslawsx_vvvvl, // llvm.ve.vl.vslawsx.vvvvl - ve_vl_vslawzx_vvsl, // llvm.ve.vl.vslawzx.vvsl - ve_vl_vslawzx_vvsmvl, // llvm.ve.vl.vslawzx.vvsmvl - ve_vl_vslawzx_vvsvl, // llvm.ve.vl.vslawzx.vvsvl - ve_vl_vslawzx_vvvl, // llvm.ve.vl.vslawzx.vvvl - ve_vl_vslawzx_vvvmvl, // llvm.ve.vl.vslawzx.vvvmvl - ve_vl_vslawzx_vvvvl, // llvm.ve.vl.vslawzx.vvvvl - ve_vl_vsll_vvsl, // llvm.ve.vl.vsll.vvsl - ve_vl_vsll_vvsmvl, // llvm.ve.vl.vsll.vvsmvl - ve_vl_vsll_vvsvl, // llvm.ve.vl.vsll.vvsvl - ve_vl_vsll_vvvl, // llvm.ve.vl.vsll.vvvl - ve_vl_vsll_vvvmvl, // llvm.ve.vl.vsll.vvvmvl - ve_vl_vsll_vvvvl, // llvm.ve.vl.vsll.vvvvl - ve_vl_vsral_vvsl, // llvm.ve.vl.vsral.vvsl - ve_vl_vsral_vvsmvl, // llvm.ve.vl.vsral.vvsmvl - ve_vl_vsral_vvsvl, // llvm.ve.vl.vsral.vvsvl - ve_vl_vsral_vvvl, // llvm.ve.vl.vsral.vvvl - ve_vl_vsral_vvvmvl, // llvm.ve.vl.vsral.vvvmvl - ve_vl_vsral_vvvvl, // llvm.ve.vl.vsral.vvvvl - ve_vl_vsrawsx_vvsl, // llvm.ve.vl.vsrawsx.vvsl - ve_vl_vsrawsx_vvsmvl, // llvm.ve.vl.vsrawsx.vvsmvl - ve_vl_vsrawsx_vvsvl, // llvm.ve.vl.vsrawsx.vvsvl - ve_vl_vsrawsx_vvvl, // llvm.ve.vl.vsrawsx.vvvl - ve_vl_vsrawsx_vvvmvl, // llvm.ve.vl.vsrawsx.vvvmvl - ve_vl_vsrawsx_vvvvl, // llvm.ve.vl.vsrawsx.vvvvl - ve_vl_vsrawzx_vvsl, // llvm.ve.vl.vsrawzx.vvsl - ve_vl_vsrawzx_vvsmvl, // llvm.ve.vl.vsrawzx.vvsmvl - ve_vl_vsrawzx_vvsvl, // llvm.ve.vl.vsrawzx.vvsvl - ve_vl_vsrawzx_vvvl, // llvm.ve.vl.vsrawzx.vvvl - ve_vl_vsrawzx_vvvmvl, // llvm.ve.vl.vsrawzx.vvvmvl - ve_vl_vsrawzx_vvvvl, // llvm.ve.vl.vsrawzx.vvvvl - ve_vl_vsrl_vvsl, // llvm.ve.vl.vsrl.vvsl - ve_vl_vsrl_vvsmvl, // llvm.ve.vl.vsrl.vvsmvl - ve_vl_vsrl_vvsvl, // llvm.ve.vl.vsrl.vvsvl - ve_vl_vsrl_vvvl, // llvm.ve.vl.vsrl.vvvl - ve_vl_vsrl_vvvmvl, // llvm.ve.vl.vsrl.vvvmvl - ve_vl_vsrl_vvvvl, // llvm.ve.vl.vsrl.vvvvl - ve_vl_vst_vssl, // llvm.ve.vl.vst.vssl - ve_vl_vst_vssml, // llvm.ve.vl.vst.vssml - ve_vl_vst2d_vssl, // llvm.ve.vl.vst2d.vssl - ve_vl_vst2d_vssml, // llvm.ve.vl.vst2d.vssml - ve_vl_vst2dnc_vssl, // llvm.ve.vl.vst2dnc.vssl - ve_vl_vst2dnc_vssml, // llvm.ve.vl.vst2dnc.vssml - ve_vl_vst2dncot_vssl, // llvm.ve.vl.vst2dncot.vssl - ve_vl_vst2dncot_vssml, // llvm.ve.vl.vst2dncot.vssml - ve_vl_vst2dot_vssl, // llvm.ve.vl.vst2dot.vssl - ve_vl_vst2dot_vssml, // llvm.ve.vl.vst2dot.vssml - ve_vl_vstl_vssl, // llvm.ve.vl.vstl.vssl - ve_vl_vstl_vssml, // llvm.ve.vl.vstl.vssml - ve_vl_vstl2d_vssl, // llvm.ve.vl.vstl2d.vssl - ve_vl_vstl2d_vssml, // llvm.ve.vl.vstl2d.vssml - ve_vl_vstl2dnc_vssl, // llvm.ve.vl.vstl2dnc.vssl - ve_vl_vstl2dnc_vssml, // llvm.ve.vl.vstl2dnc.vssml - ve_vl_vstl2dncot_vssl, // llvm.ve.vl.vstl2dncot.vssl - ve_vl_vstl2dncot_vssml, // llvm.ve.vl.vstl2dncot.vssml - ve_vl_vstl2dot_vssl, // llvm.ve.vl.vstl2dot.vssl - ve_vl_vstl2dot_vssml, // llvm.ve.vl.vstl2dot.vssml - ve_vl_vstlnc_vssl, // llvm.ve.vl.vstlnc.vssl - ve_vl_vstlnc_vssml, // llvm.ve.vl.vstlnc.vssml - ve_vl_vstlncot_vssl, // llvm.ve.vl.vstlncot.vssl - ve_vl_vstlncot_vssml, // llvm.ve.vl.vstlncot.vssml - ve_vl_vstlot_vssl, // llvm.ve.vl.vstlot.vssl - ve_vl_vstlot_vssml, // llvm.ve.vl.vstlot.vssml - ve_vl_vstnc_vssl, // llvm.ve.vl.vstnc.vssl - ve_vl_vstnc_vssml, // llvm.ve.vl.vstnc.vssml - ve_vl_vstncot_vssl, // llvm.ve.vl.vstncot.vssl - ve_vl_vstncot_vssml, // llvm.ve.vl.vstncot.vssml - ve_vl_vstot_vssl, // llvm.ve.vl.vstot.vssl - ve_vl_vstot_vssml, // llvm.ve.vl.vstot.vssml - ve_vl_vstu_vssl, // llvm.ve.vl.vstu.vssl - ve_vl_vstu_vssml, // llvm.ve.vl.vstu.vssml - ve_vl_vstu2d_vssl, // llvm.ve.vl.vstu2d.vssl - ve_vl_vstu2d_vssml, // llvm.ve.vl.vstu2d.vssml - ve_vl_vstu2dnc_vssl, // llvm.ve.vl.vstu2dnc.vssl - ve_vl_vstu2dnc_vssml, // llvm.ve.vl.vstu2dnc.vssml - ve_vl_vstu2dncot_vssl, // llvm.ve.vl.vstu2dncot.vssl - ve_vl_vstu2dncot_vssml, // llvm.ve.vl.vstu2dncot.vssml - ve_vl_vstu2dot_vssl, // llvm.ve.vl.vstu2dot.vssl - ve_vl_vstu2dot_vssml, // llvm.ve.vl.vstu2dot.vssml - ve_vl_vstunc_vssl, // llvm.ve.vl.vstunc.vssl - ve_vl_vstunc_vssml, // llvm.ve.vl.vstunc.vssml - ve_vl_vstuncot_vssl, // llvm.ve.vl.vstuncot.vssl - ve_vl_vstuncot_vssml, // llvm.ve.vl.vstuncot.vssml - ve_vl_vstuot_vssl, // llvm.ve.vl.vstuot.vssl - ve_vl_vstuot_vssml, // llvm.ve.vl.vstuot.vssml - ve_vl_vsubsl_vsvl, // llvm.ve.vl.vsubsl.vsvl - ve_vl_vsubsl_vsvmvl, // llvm.ve.vl.vsubsl.vsvmvl - ve_vl_vsubsl_vsvvl, // llvm.ve.vl.vsubsl.vsvvl - ve_vl_vsubsl_vvvl, // llvm.ve.vl.vsubsl.vvvl - ve_vl_vsubsl_vvvmvl, // llvm.ve.vl.vsubsl.vvvmvl - ve_vl_vsubsl_vvvvl, // llvm.ve.vl.vsubsl.vvvvl - ve_vl_vsubswsx_vsvl, // llvm.ve.vl.vsubswsx.vsvl - ve_vl_vsubswsx_vsvmvl, // llvm.ve.vl.vsubswsx.vsvmvl - ve_vl_vsubswsx_vsvvl, // llvm.ve.vl.vsubswsx.vsvvl - ve_vl_vsubswsx_vvvl, // llvm.ve.vl.vsubswsx.vvvl - ve_vl_vsubswsx_vvvmvl, // llvm.ve.vl.vsubswsx.vvvmvl - ve_vl_vsubswsx_vvvvl, // llvm.ve.vl.vsubswsx.vvvvl - ve_vl_vsubswzx_vsvl, // llvm.ve.vl.vsubswzx.vsvl - ve_vl_vsubswzx_vsvmvl, // llvm.ve.vl.vsubswzx.vsvmvl - ve_vl_vsubswzx_vsvvl, // llvm.ve.vl.vsubswzx.vsvvl - ve_vl_vsubswzx_vvvl, // llvm.ve.vl.vsubswzx.vvvl - ve_vl_vsubswzx_vvvmvl, // llvm.ve.vl.vsubswzx.vvvmvl - ve_vl_vsubswzx_vvvvl, // llvm.ve.vl.vsubswzx.vvvvl - ve_vl_vsubul_vsvl, // llvm.ve.vl.vsubul.vsvl - ve_vl_vsubul_vsvmvl, // llvm.ve.vl.vsubul.vsvmvl - ve_vl_vsubul_vsvvl, // llvm.ve.vl.vsubul.vsvvl - ve_vl_vsubul_vvvl, // llvm.ve.vl.vsubul.vvvl - ve_vl_vsubul_vvvmvl, // llvm.ve.vl.vsubul.vvvmvl - ve_vl_vsubul_vvvvl, // llvm.ve.vl.vsubul.vvvvl - ve_vl_vsubuw_vsvl, // llvm.ve.vl.vsubuw.vsvl - ve_vl_vsubuw_vsvmvl, // llvm.ve.vl.vsubuw.vsvmvl - ve_vl_vsubuw_vsvvl, // llvm.ve.vl.vsubuw.vsvvl - ve_vl_vsubuw_vvvl, // llvm.ve.vl.vsubuw.vvvl - ve_vl_vsubuw_vvvmvl, // llvm.ve.vl.vsubuw.vvvmvl - ve_vl_vsubuw_vvvvl, // llvm.ve.vl.vsubuw.vvvvl - ve_vl_vsuml_vvl, // llvm.ve.vl.vsuml.vvl - ve_vl_vsuml_vvml, // llvm.ve.vl.vsuml.vvml - ve_vl_vsumwsx_vvl, // llvm.ve.vl.vsumwsx.vvl - ve_vl_vsumwsx_vvml, // llvm.ve.vl.vsumwsx.vvml - ve_vl_vsumwzx_vvl, // llvm.ve.vl.vsumwzx.vvl - ve_vl_vsumwzx_vvml, // llvm.ve.vl.vsumwzx.vvml - ve_vl_vxor_vsvl, // llvm.ve.vl.vxor.vsvl - ve_vl_vxor_vsvmvl, // llvm.ve.vl.vxor.vsvmvl - ve_vl_vxor_vsvvl, // llvm.ve.vl.vxor.vsvvl - ve_vl_vxor_vvvl, // llvm.ve.vl.vxor.vvvl - ve_vl_vxor_vvvmvl, // llvm.ve.vl.vxor.vvvmvl - ve_vl_vxor_vvvvl, // llvm.ve.vl.vxor.vvvvl - ve_vl_xorm_MMM, // llvm.ve.vl.xorm.MMM - ve_vl_xorm_mmm, // llvm.ve.vl.xorm.mmm -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.td deleted file mode 100644 index be4bccef0c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVE.td +++ /dev/null @@ -1,35 +0,0 @@ -// Define intrinsics written by hand - -// VEL Intrinsic instructions. -let TargetPrefix = "ve" in { - def int_ve_vl_svob : GCCBuiltin<"__builtin_ve_vl_svob">, - Intrinsic<[], [], [IntrHasSideEffects]>; - - def int_ve_vl_pack_f32p : GCCBuiltin<"__builtin_ve_vl_pack_f32p">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_ptr_ty], - [IntrReadMem]>; - def int_ve_vl_pack_f32a : GCCBuiltin<"__builtin_ve_vl_pack_f32a">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], - [IntrReadMem]>; - - def int_ve_vl_extract_vm512u : - GCCBuiltin<"__builtin_ve_vl_extract_vm512u">, - Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; - - def int_ve_vl_extract_vm512l : - GCCBuiltin<"__builtin_ve_vl_extract_vm512l">, - Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; - - def int_ve_vl_insert_vm512u : - GCCBuiltin<"__builtin_ve_vl_insert_vm512u">, - Intrinsic<[LLVMType], [LLVMType, LLVMType], - [IntrNoMem]>; - - def int_ve_vl_insert_vm512l : - GCCBuiltin<"__builtin_ve_vl_insert_vm512l">, - Intrinsic<[LLVMType], [LLVMType, LLVMType], - [IntrNoMem]>; -} - -// Define intrinsics automatically generated -include "llvm/IR/IntrinsicsVEVL.gen.td" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVEVL.gen.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVEVL.gen.td deleted file mode 100644 index 67cbd30790..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsVEVL.gen.td +++ /dev/null @@ -1,1213 +0,0 @@ -let TargetPrefix = "ve" in def int_ve_vl_vld_vssl : GCCBuiltin<"__builtin_ve_vl_vld_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vld_vssvl : GCCBuiltin<"__builtin_ve_vl_vld_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu_vssl : GCCBuiltin<"__builtin_ve_vl_vldu_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu_vssvl : GCCBuiltin<"__builtin_ve_vl_vldu_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldunc_vssl : GCCBuiltin<"__builtin_ve_vl_vldunc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldunc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldunc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlsx_vssl : GCCBuiltin<"__builtin_ve_vl_vldlsx_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlsx_vssvl : GCCBuiltin<"__builtin_ve_vl_vldlsx_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlsxnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldlsxnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlsxnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldlsxnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlzx_vssl : GCCBuiltin<"__builtin_ve_vl_vldlzx_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlzx_vssvl : GCCBuiltin<"__builtin_ve_vl_vldlzx_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlzxnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldlzxnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldlzxnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldlzxnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vld2d_vssl : GCCBuiltin<"__builtin_ve_vl_vld2d_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vld2d_vssvl : GCCBuiltin<"__builtin_ve_vl_vld2d_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vld2dnc_vssl : GCCBuiltin<"__builtin_ve_vl_vld2dnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vld2dnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vld2dnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu2d_vssl : GCCBuiltin<"__builtin_ve_vl_vldu2d_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu2d_vssvl : GCCBuiltin<"__builtin_ve_vl_vldu2d_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu2dnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldu2dnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldu2dnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldu2dnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dsx_vssl : GCCBuiltin<"__builtin_ve_vl_vldl2dsx_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dsx_vssvl : GCCBuiltin<"__builtin_ve_vl_vldl2dsx_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dsxnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldl2dsxnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dsxnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldl2dsxnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dzx_vssl : GCCBuiltin<"__builtin_ve_vl_vldl2dzx_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dzx_vssvl : GCCBuiltin<"__builtin_ve_vl_vldl2dzx_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dzxnc_vssl : GCCBuiltin<"__builtin_ve_vl_vldl2dzxnc_vssl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vldl2dzxnc_vssvl : GCCBuiltin<"__builtin_ve_vl_vldl2dzxnc_vssvl">, Intrinsic<[LLVMType], [LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst_vssl : GCCBuiltin<"__builtin_ve_vl_vst_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst_vssml : GCCBuiltin<"__builtin_ve_vl_vst_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstnc_vssl : GCCBuiltin<"__builtin_ve_vl_vstnc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstnc_vssml : GCCBuiltin<"__builtin_ve_vl_vstnc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstot_vssl : GCCBuiltin<"__builtin_ve_vl_vstot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstot_vssml : GCCBuiltin<"__builtin_ve_vl_vstot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstncot_vssl : GCCBuiltin<"__builtin_ve_vl_vstncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstncot_vssml : GCCBuiltin<"__builtin_ve_vl_vstncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu_vssl : GCCBuiltin<"__builtin_ve_vl_vstu_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu_vssml : GCCBuiltin<"__builtin_ve_vl_vstu_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstunc_vssl : GCCBuiltin<"__builtin_ve_vl_vstunc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstunc_vssml : GCCBuiltin<"__builtin_ve_vl_vstunc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstuot_vssl : GCCBuiltin<"__builtin_ve_vl_vstuot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstuot_vssml : GCCBuiltin<"__builtin_ve_vl_vstuot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstuncot_vssl : GCCBuiltin<"__builtin_ve_vl_vstuncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstuncot_vssml : GCCBuiltin<"__builtin_ve_vl_vstuncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl_vssl : GCCBuiltin<"__builtin_ve_vl_vstl_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl_vssml : GCCBuiltin<"__builtin_ve_vl_vstl_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlnc_vssl : GCCBuiltin<"__builtin_ve_vl_vstlnc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlnc_vssml : GCCBuiltin<"__builtin_ve_vl_vstlnc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlot_vssl : GCCBuiltin<"__builtin_ve_vl_vstlot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlot_vssml : GCCBuiltin<"__builtin_ve_vl_vstlot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlncot_vssl : GCCBuiltin<"__builtin_ve_vl_vstlncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstlncot_vssml : GCCBuiltin<"__builtin_ve_vl_vstlncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2d_vssl : GCCBuiltin<"__builtin_ve_vl_vst2d_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2d_vssml : GCCBuiltin<"__builtin_ve_vl_vst2d_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dnc_vssl : GCCBuiltin<"__builtin_ve_vl_vst2dnc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dnc_vssml : GCCBuiltin<"__builtin_ve_vl_vst2dnc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dot_vssl : GCCBuiltin<"__builtin_ve_vl_vst2dot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dot_vssml : GCCBuiltin<"__builtin_ve_vl_vst2dot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dncot_vssl : GCCBuiltin<"__builtin_ve_vl_vst2dncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vst2dncot_vssml : GCCBuiltin<"__builtin_ve_vl_vst2dncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2d_vssl : GCCBuiltin<"__builtin_ve_vl_vstu2d_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2d_vssml : GCCBuiltin<"__builtin_ve_vl_vstu2d_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dnc_vssl : GCCBuiltin<"__builtin_ve_vl_vstu2dnc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dnc_vssml : GCCBuiltin<"__builtin_ve_vl_vstu2dnc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dot_vssl : GCCBuiltin<"__builtin_ve_vl_vstu2dot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dot_vssml : GCCBuiltin<"__builtin_ve_vl_vstu2dot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dncot_vssl : GCCBuiltin<"__builtin_ve_vl_vstu2dncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstu2dncot_vssml : GCCBuiltin<"__builtin_ve_vl_vstu2dncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2d_vssl : GCCBuiltin<"__builtin_ve_vl_vstl2d_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2d_vssml : GCCBuiltin<"__builtin_ve_vl_vstl2d_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dnc_vssl : GCCBuiltin<"__builtin_ve_vl_vstl2dnc_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dnc_vssml : GCCBuiltin<"__builtin_ve_vl_vstl2dnc_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dot_vssl : GCCBuiltin<"__builtin_ve_vl_vstl2dot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dot_vssml : GCCBuiltin<"__builtin_ve_vl_vstl2dot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dncot_vssl : GCCBuiltin<"__builtin_ve_vl_vstl2dncot_vssl">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vstl2dncot_vssml : GCCBuiltin<"__builtin_ve_vl_vstl2dncot_vssml">, Intrinsic<[], [LLVMType, LLVMType, llvm_ptr_ty, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pfchv_ssl : GCCBuiltin<"__builtin_ve_vl_pfchv_ssl">, Intrinsic<[], [LLVMType, llvm_ptr_ty, LLVMType], [IntrInaccessibleMemOrArgMemOnly]>; -let TargetPrefix = "ve" in def int_ve_vl_pfchvnc_ssl : GCCBuiltin<"__builtin_ve_vl_pfchvnc_ssl">, Intrinsic<[], [LLVMType, llvm_ptr_ty, LLVMType], [IntrInaccessibleMemOrArgMemOnly]>; -let TargetPrefix = "ve" in def int_ve_vl_lsv_vvss : GCCBuiltin<"__builtin_ve_vl_lsv_vvss">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lvsl_svs : GCCBuiltin<"__builtin_ve_vl_lvsl_svs">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lvsd_svs : GCCBuiltin<"__builtin_ve_vl_lvsd_svs">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lvss_svs : GCCBuiltin<"__builtin_ve_vl_lvss_svs">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lvm_mmss : GCCBuiltin<"__builtin_ve_vl_lvm_mmss">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lvm_MMss : GCCBuiltin<"__builtin_ve_vl_lvm_MMss">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_svm_sms : GCCBuiltin<"__builtin_ve_vl_svm_sms">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_svm_sMs : GCCBuiltin<"__builtin_ve_vl_svm_sMs">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdd_vsl : GCCBuiltin<"__builtin_ve_vl_vbrdd_vsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdd_vsvl : GCCBuiltin<"__builtin_ve_vl_vbrdd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdd_vsmvl : GCCBuiltin<"__builtin_ve_vl_vbrdd_vsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdl_vsl : GCCBuiltin<"__builtin_ve_vl_vbrdl_vsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdl_vsvl : GCCBuiltin<"__builtin_ve_vl_vbrdl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdl_vsmvl : GCCBuiltin<"__builtin_ve_vl_vbrdl_vsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrds_vsl : GCCBuiltin<"__builtin_ve_vl_vbrds_vsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrds_vsvl : GCCBuiltin<"__builtin_ve_vl_vbrds_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrds_vsmvl : GCCBuiltin<"__builtin_ve_vl_vbrds_vsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdw_vsl : GCCBuiltin<"__builtin_ve_vl_vbrdw_vsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdw_vsvl : GCCBuiltin<"__builtin_ve_vl_vbrdw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vbrdw_vsmvl : GCCBuiltin<"__builtin_ve_vl_vbrdw_vsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvbrd_vsl : GCCBuiltin<"__builtin_ve_vl_pvbrd_vsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvbrd_vsvl : GCCBuiltin<"__builtin_ve_vl_pvbrd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvbrd_vsMvl : GCCBuiltin<"__builtin_ve_vl_pvbrd_vsMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmv_vsvl : GCCBuiltin<"__builtin_ve_vl_vmv_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmv_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmv_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmv_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmv_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vvvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vvvvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vsvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vsvvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddul_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vaddul_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vvvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vsvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vadduw_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vadduw_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vvvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vsvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvaddu_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvaddu_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vaddswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vaddswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vvvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vsvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvadds_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvadds_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vaddsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vaddsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vvvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vsvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vsvvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubul_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vsubul_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vvvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vsvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubuw_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vsubuw_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vsvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubu_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvsubu_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vsubswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vsubswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vsvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsubs_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvsubs_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsubsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vsubsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vvvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vsvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulul_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmulul_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vvvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vsvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmuluw_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmuluw_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmulswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmulswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmulsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulslw_vvvl : GCCBuiltin<"__builtin_ve_vl_vmulslw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulslw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmulslw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulslw_vsvl : GCCBuiltin<"__builtin_ve_vl_vmulslw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmulslw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmulslw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvvvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vsvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vsvvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vsvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvsl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvsvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivul_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vdivul_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvsl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvsvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivuw_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vdivuw_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvsl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswsx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vdivswsx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvsl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivswzx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vdivswzx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvsl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvsvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vdivsl_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vdivsl_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vvvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vvvvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vsvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vsvvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpul_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpul_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vvvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vvvvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vsvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vsvvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpuw_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpuw_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vvvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vsvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmpu_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvcmpu_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vvvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vsvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcmps_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvcmps_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcmpsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vcmpsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vvvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vsvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmaxs_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvmaxs_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vsvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswsx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vminswsx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vsvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vsvvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminswzx_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vminswzx_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vvvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vsvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvmins_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvmins_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmaxsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmaxsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vvvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vsvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vsvvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vminsl_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vminsl_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vvvl : GCCBuiltin<"__builtin_ve_vl_vand_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vvvvl : GCCBuiltin<"__builtin_ve_vl_vand_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vsvl : GCCBuiltin<"__builtin_ve_vl_vand_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vsvvl : GCCBuiltin<"__builtin_ve_vl_vand_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vand_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vand_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vand_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vvvl : GCCBuiltin<"__builtin_ve_vl_pvand_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvand_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vsvl : GCCBuiltin<"__builtin_ve_vl_pvand_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvand_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvand_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvand_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvand_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vvvl : GCCBuiltin<"__builtin_ve_vl_vor_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vvvvl : GCCBuiltin<"__builtin_ve_vl_vor_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vsvl : GCCBuiltin<"__builtin_ve_vl_vor_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vsvvl : GCCBuiltin<"__builtin_ve_vl_vor_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vor_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vor_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vor_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vvvl : GCCBuiltin<"__builtin_ve_vl_pvor_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvor_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vsvl : GCCBuiltin<"__builtin_ve_vl_pvor_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvor_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvor_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvor_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvor_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vvvl : GCCBuiltin<"__builtin_ve_vl_vxor_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vvvvl : GCCBuiltin<"__builtin_ve_vl_vxor_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vsvl : GCCBuiltin<"__builtin_ve_vl_vxor_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vsvvl : GCCBuiltin<"__builtin_ve_vl_vxor_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vxor_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vxor_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vxor_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vvvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vsvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvxor_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvxor_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vvvl : GCCBuiltin<"__builtin_ve_vl_veqv_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vvvvl : GCCBuiltin<"__builtin_ve_vl_veqv_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vsvl : GCCBuiltin<"__builtin_ve_vl_veqv_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vsvvl : GCCBuiltin<"__builtin_ve_vl_veqv_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vvvmvl : GCCBuiltin<"__builtin_ve_vl_veqv_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_veqv_vsvmvl : GCCBuiltin<"__builtin_ve_vl_veqv_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vvvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vvvvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vsvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vsvvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pveqv_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pveqv_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vseq_vl : GCCBuiltin<"__builtin_ve_vl_vseq_vl">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vseq_vvl : GCCBuiltin<"__builtin_ve_vl_vseq_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvseqlo_vl : GCCBuiltin<"__builtin_ve_vl_pvseqlo_vl">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvseqlo_vvl : GCCBuiltin<"__builtin_ve_vl_pvseqlo_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsequp_vl : GCCBuiltin<"__builtin_ve_vl_pvsequp_vl">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsequp_vvl : GCCBuiltin<"__builtin_ve_vl_pvsequp_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvseq_vl : GCCBuiltin<"__builtin_ve_vl_pvseq_vl">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvseq_vvl : GCCBuiltin<"__builtin_ve_vl_pvseq_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvvl : GCCBuiltin<"__builtin_ve_vl_vsll_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsll_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvsl : GCCBuiltin<"__builtin_ve_vl_vsll_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvsvl : GCCBuiltin<"__builtin_ve_vl_vsll_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsll_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsll_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vsll_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvsl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsll_vvsMvl : GCCBuiltin<"__builtin_ve_vl_pvsll_vvsMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvvl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvsl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvsvl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrl_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vsrl_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvsl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsrl_vvsMvl : GCCBuiltin<"__builtin_ve_vl_pvsrl_vvsMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvsl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawsx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vslawsx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvsl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslawzx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vslawzx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvsl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsla_vvsMvl : GCCBuiltin<"__builtin_ve_vl_pvsla_vvsMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvvl : GCCBuiltin<"__builtin_ve_vl_vslal_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvvvl : GCCBuiltin<"__builtin_ve_vl_vslal_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvsl : GCCBuiltin<"__builtin_ve_vl_vslal_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvsvl : GCCBuiltin<"__builtin_ve_vl_vslal_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vslal_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vslal_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vslal_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvsl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawsx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vsrawsx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvsl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvsvl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsrawzx_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vsrawzx_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvvl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvsl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvsra_vvsMvl : GCCBuiltin<"__builtin_ve_vl_pvsra_vvsMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvvl : GCCBuiltin<"__builtin_ve_vl_vsral_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvvvl : GCCBuiltin<"__builtin_ve_vl_vsral_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvsl : GCCBuiltin<"__builtin_ve_vl_vsral_vvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvsvl : GCCBuiltin<"__builtin_ve_vl_vsral_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vsral_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsral_vvsmvl : GCCBuiltin<"__builtin_ve_vl_vsral_vvsmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsfa_vvssl : GCCBuiltin<"__builtin_ve_vl_vsfa_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsfa_vvssvl : GCCBuiltin<"__builtin_ve_vl_vsfa_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsfa_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vsfa_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vsvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfaddd_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfaddd_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vvvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vsvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfadds_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfadds_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfadd_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfadd_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vsvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubd_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfsubd_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vvvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vsvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsubs_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfsubs_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfsub_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfsub_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuld_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmuld_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmuls_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmuls_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmul_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmul_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vsvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivd_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfdivd_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vvvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vsvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfdivs_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfdivs_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsqrtd_vvl : GCCBuiltin<"__builtin_ve_vl_vfsqrtd_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsqrtd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfsqrtd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsqrts_vvl : GCCBuiltin<"__builtin_ve_vl_vfsqrts_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsqrts_vvvl : GCCBuiltin<"__builtin_ve_vl_vfsqrts_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vsvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmpd_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfcmpd_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vvvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vsvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfcmps_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfcmps_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfcmp_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfcmp_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxd_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmaxd_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmaxs_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmaxs_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmax_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmax_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmind_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmind_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vvvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vsvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmins_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmins_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vvvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vsvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmin_vsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmin_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmadd_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmadd_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmads_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmads_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vsvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vsvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vsvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmad_vvsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmad_vvsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbd_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbd_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmsbs_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfmsbs_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vsvvvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvsvvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vsvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vsvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmsb_vvsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfmsb_vvsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmadd_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmadd_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmads_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmads_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vsvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvsvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vsvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vsvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmad_vvsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmad_vvsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbd_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbd_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vsvvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvsvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvsvvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vsvvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vsvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfnmsbs_vvsvmvl : GCCBuiltin<"__builtin_ve_vl_vfnmsbs_vvsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vsvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vsvvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vsvvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvsvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvsvvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvsvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vsvvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vsvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfnmsb_vvsvMvl : GCCBuiltin<"__builtin_ve_vl_pvfnmsb_vvsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrcpd_vvl : GCCBuiltin<"__builtin_ve_vl_vrcpd_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrcpd_vvvl : GCCBuiltin<"__builtin_ve_vl_vrcpd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrcps_vvl : GCCBuiltin<"__builtin_ve_vl_vrcps_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrcps_vvvl : GCCBuiltin<"__builtin_ve_vl_vrcps_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrcp_vvl : GCCBuiltin<"__builtin_ve_vl_pvrcp_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrcp_vvvl : GCCBuiltin<"__builtin_ve_vl_pvrcp_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtd_vvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtd_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtd_vvvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrts_vvl : GCCBuiltin<"__builtin_ve_vl_vrsqrts_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrts_vvvl : GCCBuiltin<"__builtin_ve_vl_vrsqrts_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrsqrt_vvl : GCCBuiltin<"__builtin_ve_vl_pvrsqrt_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrsqrt_vvvl : GCCBuiltin<"__builtin_ve_vl_pvrsqrt_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtdnex_vvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtdnex_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtdnex_vvvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtdnex_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtsnex_vvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtsnex_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrsqrtsnex_vvvl : GCCBuiltin<"__builtin_ve_vl_vrsqrtsnex_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrsqrtnex_vvl : GCCBuiltin<"__builtin_ve_vl_pvrsqrtnex_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvrsqrtnex_vvvl : GCCBuiltin<"__builtin_ve_vl_pvrsqrtnex_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsx_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsx_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsx_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsxrz_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsxrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsxrz_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsxrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdsxrz_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdsxrz_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzx_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzx_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzx_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzxrz_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzxrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzxrz_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzxrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwdzxrz_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwdzxrz_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssx_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssx_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssx_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssxrz_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssxrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssxrz_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssxrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwssxrz_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwssxrz_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszx_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszx_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszx_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszx_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszxrz_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszxrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszxrz_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszxrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtwszxrz_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtwszxrz_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtws_vvl : GCCBuiltin<"__builtin_ve_vl_pvcvtws_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtws_vvvl : GCCBuiltin<"__builtin_ve_vl_pvcvtws_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtws_vvMvl : GCCBuiltin<"__builtin_ve_vl_pvcvtws_vvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtwsrz_vvl : GCCBuiltin<"__builtin_ve_vl_pvcvtwsrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtwsrz_vvvl : GCCBuiltin<"__builtin_ve_vl_pvcvtwsrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtwsrz_vvMvl : GCCBuiltin<"__builtin_ve_vl_pvcvtwsrz_vvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtld_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtld_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtld_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtld_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtld_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtld_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtldrz_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtldrz_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtldrz_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtldrz_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtldrz_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcvtldrz_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtdw_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtdw_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtdw_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtdw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtsw_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtsw_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtsw_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtsw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtsw_vvl : GCCBuiltin<"__builtin_ve_vl_pvcvtsw_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvcvtsw_vvvl : GCCBuiltin<"__builtin_ve_vl_pvcvtsw_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtdl_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtdl_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtdl_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtdl_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtds_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtds_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtds_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtds_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtsd_vvl : GCCBuiltin<"__builtin_ve_vl_vcvtsd_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcvtsd_vvvl : GCCBuiltin<"__builtin_ve_vl_vcvtsd_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrg_vvvml : GCCBuiltin<"__builtin_ve_vl_vmrg_vvvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrg_vvvmvl : GCCBuiltin<"__builtin_ve_vl_vmrg_vvvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrg_vsvml : GCCBuiltin<"__builtin_ve_vl_vmrg_vsvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrg_vsvmvl : GCCBuiltin<"__builtin_ve_vl_vmrg_vsvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrgw_vvvMl : GCCBuiltin<"__builtin_ve_vl_vmrgw_vvvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrgw_vvvMvl : GCCBuiltin<"__builtin_ve_vl_vmrgw_vvvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrgw_vsvMl : GCCBuiltin<"__builtin_ve_vl_vmrgw_vsvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vmrgw_vsvMvl : GCCBuiltin<"__builtin_ve_vl_vmrgw_vsvMvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vshf_vvvsl : GCCBuiltin<"__builtin_ve_vl_vshf_vvvsl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vshf_vvvsvl : GCCBuiltin<"__builtin_ve_vl_vshf_vvvsvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vcp_vvmvl : GCCBuiltin<"__builtin_ve_vl_vcp_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vex_vvmvl : GCCBuiltin<"__builtin_ve_vl_vex_vvmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklat_ml : GCCBuiltin<"__builtin_ve_vl_vfmklat_ml">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklaf_ml : GCCBuiltin<"__builtin_ve_vl_vfmklaf_ml">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkat_Ml : GCCBuiltin<"__builtin_ve_vl_pvfmkat_Ml">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkaf_Ml : GCCBuiltin<"__builtin_ve_vl_pvfmkaf_Ml">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkllt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkllt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkllt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkllt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklne_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklne_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkleq_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkleq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkleq_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkleq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklge_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklge_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklle_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklle_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklle_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklle_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnum_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnum_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklltnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklltnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklnenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkleqnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkleqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkleqnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkleqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmklgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmklgenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmklgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkllenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkllenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkllenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkllenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwlt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwlt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwlt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwlt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwne_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwne_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkweq_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkweq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkweq_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkweq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwge_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwge_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwle_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwle_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwle_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwle_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnum_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnum_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwltnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwltnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwnenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkweqnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkweqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkweqnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkweqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwgenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwlenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkwlenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkwlenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkwlenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlolt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlolt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuplt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwuplt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlolt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlolt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuplt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwuplt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlone_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlone_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupne_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlone_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlone_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupne_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloeq_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwloeq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupeq_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupeq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloeq_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwloeq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupeq_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupeq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloge_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwloge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupge_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloge_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwloge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupge_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlole_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlole_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuple_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwuple_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlole_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlole_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuple_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwuple_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonum_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnum_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonum_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnum_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogtnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogtnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloltnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwloltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupltnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloltnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwloltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupltnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlonenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlonenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupnenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloeqnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwloeqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupeqnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupeqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwloeqnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwloeqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupeqnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupeqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlogenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlogenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwupgenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwupgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlolenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlolenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuplenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwuplenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlolenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwlolenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwuplenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkwuplenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgt_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgt_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgt_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgt_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlt_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlt_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlt_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlt_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwne_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwne_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwne_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwne_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkweq_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkweq_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkweq_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkweq_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwge_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwge_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwge_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwge_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwle_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwle_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwle_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwle_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnum_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnum_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnum_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnum_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgtnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgtnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgtnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgtnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwltnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwltnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwltnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwltnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwnenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwnenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkweqnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkweqnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkweqnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkweqnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwgenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwgenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkwlenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkwlenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdlt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdlt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdlt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdlt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdne_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdne_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdeq_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdeq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdeq_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdeq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdge_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdge_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdle_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdle_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdle_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdle_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnum_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnum_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdltnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdltnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdnenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdeqnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdeqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdeqnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdeqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdgenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdlenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkdlenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkdlenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkdlenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkslt_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkslt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkslt_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkslt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksne_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksne_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkseq_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkseq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkseq_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkseq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksge_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksge_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksle_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksle_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksle_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksle_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnum_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnum_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksltnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksltnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksnenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkseqnan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkseqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkseqnan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkseqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmksgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmksgenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmksgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkslenan_mvl : GCCBuiltin<"__builtin_ve_vl_vfmkslenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfmkslenan_mvml : GCCBuiltin<"__builtin_ve_vl_vfmkslenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslogt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupgt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslogt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupgt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslolt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslolt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuplt_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksuplt_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslolt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslolt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuplt_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksuplt_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslone_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslone_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupne_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupne_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslone_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslone_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupne_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupne_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloeq_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksloeq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupeq_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupeq_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloeq_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksloeq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupeq_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupeq_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloge_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksloge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupge_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupge_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloge_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksloge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupge_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupge_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslole_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslole_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuple_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksuple_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslole_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslole_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuple_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksuple_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonum_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslonum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnum_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupnum_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonum_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslonum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnum_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupnum_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslonan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslonan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogtnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslogtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgtnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupgtnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogtnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslogtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgtnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupgtnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloltnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksloltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupltnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupltnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloltnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksloltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupltnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupltnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslonenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupnenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslonenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslonenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupnenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupnenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloeqnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksloeqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupeqnan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupeqnan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksloeqnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksloeqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupeqnan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupeqnan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslogenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksupgenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslogenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslogenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksupgenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksupgenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslolenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslolenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuplenan_mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksuplenan_mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslolenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmkslolenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksuplenan_mvml : GCCBuiltin<"__builtin_ve_vl_pvfmksuplenan_mvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgt_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksgt_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgt_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksgt_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslt_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslt_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslt_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkslt_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksne_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksne_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksne_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksne_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkseq_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkseq_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkseq_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkseq_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksge_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksge_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksge_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksge_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksle_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksle_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksle_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksle_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnum_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksnum_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnum_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksnum_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgtnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksgtnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgtnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksgtnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksltnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksltnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksltnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksltnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksnenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksnenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksnenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkseqnan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkseqnan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkseqnan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkseqnan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmksgenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmksgenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmksgenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslenan_Mvl : GCCBuiltin<"__builtin_ve_vl_pvfmkslenan_Mvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pvfmkslenan_MvMl : GCCBuiltin<"__builtin_ve_vl_pvfmkslenan_MvMl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsumwsx_vvl : GCCBuiltin<"__builtin_ve_vl_vsumwsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsumwsx_vvml : GCCBuiltin<"__builtin_ve_vl_vsumwsx_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsumwzx_vvl : GCCBuiltin<"__builtin_ve_vl_vsumwzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsumwzx_vvml : GCCBuiltin<"__builtin_ve_vl_vsumwzx_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsuml_vvl : GCCBuiltin<"__builtin_ve_vl_vsuml_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsuml_vvml : GCCBuiltin<"__builtin_ve_vl_vsuml_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsumd_vvl : GCCBuiltin<"__builtin_ve_vl_vfsumd_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsumd_vvml : GCCBuiltin<"__builtin_ve_vl_vfsumd_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsums_vvl : GCCBuiltin<"__builtin_ve_vl_vfsums_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfsums_vvml : GCCBuiltin<"__builtin_ve_vl_vfsums_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswfstsx_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswfstsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswfstsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswfstsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswlstsx_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswlstsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswlstsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswlstsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswfstzx_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswfstzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswfstzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswfstzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswlstzx_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswlstzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxswlstzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxswlstzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswfstsx_vvl : GCCBuiltin<"__builtin_ve_vl_vrminswfstsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswfstsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminswfstsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswlstsx_vvl : GCCBuiltin<"__builtin_ve_vl_vrminswlstsx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswlstsx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminswlstsx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswfstzx_vvl : GCCBuiltin<"__builtin_ve_vl_vrminswfstzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswfstzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminswfstzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswlstzx_vvl : GCCBuiltin<"__builtin_ve_vl_vrminswlstzx_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminswlstzx_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminswlstzx_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxslfst_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxslfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxslfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxslfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxsllst_vvl : GCCBuiltin<"__builtin_ve_vl_vrmaxsllst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrmaxsllst_vvvl : GCCBuiltin<"__builtin_ve_vl_vrmaxsllst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminslfst_vvl : GCCBuiltin<"__builtin_ve_vl_vrminslfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminslfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminslfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminsllst_vvl : GCCBuiltin<"__builtin_ve_vl_vrminsllst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrminsllst_vvvl : GCCBuiltin<"__builtin_ve_vl_vrminsllst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxdfst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxdfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxdfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxdfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxdlst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxdlst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxdlst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxdlst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxsfst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxsfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxsfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxsfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxslst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxslst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmaxslst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmaxslst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmindfst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmindfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmindfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmindfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmindlst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrmindlst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrmindlst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrmindlst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrminsfst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrminsfst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrminsfst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrminsfst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrminslst_vvl : GCCBuiltin<"__builtin_ve_vl_vfrminslst_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vfrminslst_vvvl : GCCBuiltin<"__builtin_ve_vl_vfrminslst_vvvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrand_vvl : GCCBuiltin<"__builtin_ve_vl_vrand_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrand_vvml : GCCBuiltin<"__builtin_ve_vl_vrand_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vror_vvl : GCCBuiltin<"__builtin_ve_vl_vror_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vror_vvml : GCCBuiltin<"__builtin_ve_vl_vror_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrxor_vvl : GCCBuiltin<"__builtin_ve_vl_vrxor_vvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vrxor_vvml : GCCBuiltin<"__builtin_ve_vl_vrxor_vvml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgt_vvssl : GCCBuiltin<"__builtin_ve_vl_vgt_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgt_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgt_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgt_vvssml : GCCBuiltin<"__builtin_ve_vl_vgt_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgt_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgt_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtnc_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtnc_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtnc_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtnc_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtnc_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtnc_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtnc_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtnc_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtu_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtu_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtu_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtu_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtu_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtu_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtu_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtu_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtunc_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtunc_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtunc_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtunc_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtunc_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtunc_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtunc_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtunc_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsx_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtlsx_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsx_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtlsx_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsx_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtlsx_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsx_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtlsx_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsxnc_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtlsxnc_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsxnc_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtlsxnc_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsxnc_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtlsxnc_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlsxnc_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtlsxnc_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzx_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtlzx_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzx_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtlzx_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzx_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtlzx_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzx_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtlzx_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzxnc_vvssl : GCCBuiltin<"__builtin_ve_vl_vgtlzxnc_vvssl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzxnc_vvssvl : GCCBuiltin<"__builtin_ve_vl_vgtlzxnc_vvssvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzxnc_vvssml : GCCBuiltin<"__builtin_ve_vl_vgtlzxnc_vvssml">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vgtlzxnc_vvssmvl : GCCBuiltin<"__builtin_ve_vl_vgtlzxnc_vvssmvl">, Intrinsic<[LLVMType], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrReadMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsc_vvssl : GCCBuiltin<"__builtin_ve_vl_vsc_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsc_vvssml : GCCBuiltin<"__builtin_ve_vl_vsc_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscnc_vvssl : GCCBuiltin<"__builtin_ve_vl_vscnc_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscnc_vvssml : GCCBuiltin<"__builtin_ve_vl_vscnc_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscot_vvssl : GCCBuiltin<"__builtin_ve_vl_vscot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscot_vvssml : GCCBuiltin<"__builtin_ve_vl_vscot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscncot_vvssl : GCCBuiltin<"__builtin_ve_vl_vscncot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscncot_vvssml : GCCBuiltin<"__builtin_ve_vl_vscncot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscu_vvssl : GCCBuiltin<"__builtin_ve_vl_vscu_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscu_vvssml : GCCBuiltin<"__builtin_ve_vl_vscu_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscunc_vvssl : GCCBuiltin<"__builtin_ve_vl_vscunc_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscunc_vvssml : GCCBuiltin<"__builtin_ve_vl_vscunc_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscuot_vvssl : GCCBuiltin<"__builtin_ve_vl_vscuot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscuot_vvssml : GCCBuiltin<"__builtin_ve_vl_vscuot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscuncot_vvssl : GCCBuiltin<"__builtin_ve_vl_vscuncot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscuncot_vvssml : GCCBuiltin<"__builtin_ve_vl_vscuncot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscl_vvssl : GCCBuiltin<"__builtin_ve_vl_vscl_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vscl_vvssml : GCCBuiltin<"__builtin_ve_vl_vscl_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclnc_vvssl : GCCBuiltin<"__builtin_ve_vl_vsclnc_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclnc_vvssml : GCCBuiltin<"__builtin_ve_vl_vsclnc_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclot_vvssl : GCCBuiltin<"__builtin_ve_vl_vsclot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclot_vvssml : GCCBuiltin<"__builtin_ve_vl_vsclot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclncot_vvssl : GCCBuiltin<"__builtin_ve_vl_vsclncot_vvssl">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_vsclncot_vvssml : GCCBuiltin<"__builtin_ve_vl_vsclncot_vvssml">, Intrinsic<[], [LLVMType, LLVMType, LLVMType, LLVMType, LLVMType, LLVMType], [IntrWriteMem]>; -let TargetPrefix = "ve" in def int_ve_vl_andm_mmm : GCCBuiltin<"__builtin_ve_vl_andm_mmm">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_andm_MMM : GCCBuiltin<"__builtin_ve_vl_andm_MMM">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_orm_mmm : GCCBuiltin<"__builtin_ve_vl_orm_mmm">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_orm_MMM : GCCBuiltin<"__builtin_ve_vl_orm_MMM">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_xorm_mmm : GCCBuiltin<"__builtin_ve_vl_xorm_mmm">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_xorm_MMM : GCCBuiltin<"__builtin_ve_vl_xorm_MMM">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_eqvm_mmm : GCCBuiltin<"__builtin_ve_vl_eqvm_mmm">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_eqvm_MMM : GCCBuiltin<"__builtin_ve_vl_eqvm_MMM">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_nndm_mmm : GCCBuiltin<"__builtin_ve_vl_nndm_mmm">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_nndm_MMM : GCCBuiltin<"__builtin_ve_vl_nndm_MMM">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_negm_mm : GCCBuiltin<"__builtin_ve_vl_negm_mm">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_negm_MM : GCCBuiltin<"__builtin_ve_vl_negm_MM">, Intrinsic<[LLVMType], [LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_pcvm_sml : GCCBuiltin<"__builtin_ve_vl_pcvm_sml">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_lzvm_sml : GCCBuiltin<"__builtin_ve_vl_lzvm_sml">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; -let TargetPrefix = "ve" in def int_ve_vl_tovm_sml : GCCBuiltin<"__builtin_ve_vl_tovm_sml">, Intrinsic<[LLVMType], [LLVMType, LLVMType], [IntrNoMem]>; diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.h deleted file mode 100644 index 72581b1feb..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.h +++ /dev/null @@ -1,74 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_WASM_ENUMS_H -#define LLVM_IR_INTRINSIC_WASM_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum WASMIntrinsics : unsigned { -// Enum values for intrinsics - wasm_alltrue = 9286, // llvm.wasm.alltrue - wasm_anytrue, // llvm.wasm.anytrue - wasm_avgr_unsigned, // llvm.wasm.avgr.unsigned - wasm_bitmask, // llvm.wasm.bitmask - wasm_bitselect, // llvm.wasm.bitselect - wasm_catch, // llvm.wasm.catch - wasm_dot, // llvm.wasm.dot - wasm_extadd_pairwise_signed, // llvm.wasm.extadd.pairwise.signed - wasm_extadd_pairwise_unsigned, // llvm.wasm.extadd.pairwise.unsigned - wasm_fma, // llvm.wasm.fma - wasm_fms, // llvm.wasm.fms - wasm_get_ehselector, // llvm.wasm.get.ehselector - wasm_get_exception, // llvm.wasm.get.exception - wasm_landingpad_index, // llvm.wasm.landingpad.index - wasm_laneselect, // llvm.wasm.laneselect - wasm_lsda, // llvm.wasm.lsda - wasm_memory_atomic_notify, // llvm.wasm.memory.atomic.notify - wasm_memory_atomic_wait32, // llvm.wasm.memory.atomic.wait32 - wasm_memory_atomic_wait64, // llvm.wasm.memory.atomic.wait64 - wasm_memory_grow, // llvm.wasm.memory.grow - wasm_memory_size, // llvm.wasm.memory.size - wasm_narrow_signed, // llvm.wasm.narrow.signed - wasm_narrow_unsigned, // llvm.wasm.narrow.unsigned - wasm_pmax, // llvm.wasm.pmax - wasm_pmin, // llvm.wasm.pmin - wasm_q15mulr_sat_signed, // llvm.wasm.q15mulr.sat.signed - wasm_ref_null_extern, // llvm.wasm.ref.null.extern - wasm_ref_null_func, // llvm.wasm.ref.null.func - wasm_relaxed_max, // llvm.wasm.relaxed.max - wasm_relaxed_min, // llvm.wasm.relaxed.min - wasm_relaxed_swizzle, // llvm.wasm.relaxed.swizzle - wasm_relaxed_trunc_signed, // llvm.wasm.relaxed.trunc.signed - wasm_relaxed_trunc_unsigned, // llvm.wasm.relaxed.trunc.unsigned - wasm_relaxed_trunc_zero_signed, // llvm.wasm.relaxed.trunc.zero.signed - wasm_relaxed_trunc_zero_unsigned, // llvm.wasm.relaxed.trunc.zero.unsigned - wasm_rethrow, // llvm.wasm.rethrow - wasm_shuffle, // llvm.wasm.shuffle - wasm_sub_sat_signed, // llvm.wasm.sub.sat.signed - wasm_sub_sat_unsigned, // llvm.wasm.sub.sat.unsigned - wasm_swizzle, // llvm.wasm.swizzle - wasm_table_copy, // llvm.wasm.table.copy - wasm_table_fill_externref, // llvm.wasm.table.fill.externref - wasm_table_fill_funcref, // llvm.wasm.table.fill.funcref - wasm_table_grow_externref, // llvm.wasm.table.grow.externref - wasm_table_grow_funcref, // llvm.wasm.table.grow.funcref - wasm_table_size, // llvm.wasm.table.size - wasm_throw, // llvm.wasm.throw - wasm_tls_align, // llvm.wasm.tls.align - wasm_tls_base, // llvm.wasm.tls.base - wasm_tls_size, // llvm.wasm.tls.size - wasm_trunc_saturate_signed, // llvm.wasm.trunc.saturate.signed - wasm_trunc_saturate_unsigned, // llvm.wasm.trunc.saturate.unsigned - wasm_trunc_signed, // llvm.wasm.trunc.signed - wasm_trunc_unsigned, // llvm.wasm.trunc.unsigned -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.td deleted file mode 100644 index aecc3d91fa..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsWebAssembly.td +++ /dev/null @@ -1,289 +0,0 @@ -//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines all of the WebAssembly-specific intrinsics. -/// -//===----------------------------------------------------------------------===// - -// Type definition for a table in an intrinsic -def llvm_table_ty : LLVMQualPointerType; - -let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.". - -// Query the current memory size, and increase the current memory size. -// Note that memory.size is not IntrNoMem because it must be sequenced with -// respect to memory.grow calls. -def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty], - [llvm_i32_ty], - [IntrReadMem]>; -def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty], - [llvm_i32_ty, LLVMMatchType<0>], - []>; - -//===----------------------------------------------------------------------===// -// ref.null intrinsics -//===----------------------------------------------------------------------===// -def int_wasm_ref_null_extern : Intrinsic<[llvm_externref_ty], [], [IntrNoMem]>; -def int_wasm_ref_null_func : Intrinsic<[llvm_funcref_ty], [], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Table intrinsics -//===----------------------------------------------------------------------===// -// Query the current table size, and increase the current table size. -def int_wasm_table_size : Intrinsic<[llvm_i32_ty], - [llvm_table_ty], - [IntrReadMem]>; -def int_wasm_table_copy : Intrinsic<[], - [llvm_table_ty, llvm_table_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - []>; -def int_wasm_table_grow_externref : Intrinsic<[llvm_i32_ty], - [llvm_table_ty, llvm_externref_ty, llvm_i32_ty], - []>; -def int_wasm_table_grow_funcref : Intrinsic<[llvm_i32_ty], - [llvm_table_ty, llvm_funcref_ty, llvm_i32_ty], - []>; -def int_wasm_table_fill_externref : Intrinsic<[], - [llvm_table_ty, llvm_i32_ty, llvm_externref_ty, llvm_i32_ty], - []>; -def int_wasm_table_fill_funcref : Intrinsic<[], - [llvm_table_ty, llvm_i32_ty, llvm_funcref_ty, llvm_i32_ty], - []>; - -//===----------------------------------------------------------------------===// -// Trapping float-to-int conversions -//===----------------------------------------------------------------------===// - -def int_wasm_trunc_signed : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty], - [IntrNoMem]>; -def int_wasm_trunc_unsigned : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty], - [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Saturating float-to-int conversions -//===----------------------------------------------------------------------===// - -def int_wasm_trunc_saturate_signed : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty], - [IntrNoMem, IntrSpeculatable]>; - -//===----------------------------------------------------------------------===// -// Exception handling intrinsics -//===----------------------------------------------------------------------===// - -// throw / rethrow -// The first immediate argument is an index to a tag, which is 0 for C++ -// exception. The second argument is the thrown exception pointer. -def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], - [Throws, IntrNoReturn, ImmArg>]>; -def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>; - -// Since wasm does not use landingpad instructions, these instructions return -// exception pointer and selector values until we lower them in WasmEHPrepare. -def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], - [IntrHasSideEffects]>; -def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty], - [IntrHasSideEffects]>; - -// wasm.catch returns the pointer to the exception object caught by wasm 'catch' -// instruction. This returns a single pointer, which is the case for C++ -// exceptions. The immediate argument is an index to for a tag, which is 0 for -// C++ exceptions. -def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], - [IntrHasSideEffects, ImmArg>]>; - -// WebAssembly EH must maintain the landingpads in the order assigned to them -// by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is -// used in order to give them the indices in WasmEHPrepare. -def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - -// Returns LSDA address of the current function. -def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// -// Atomic intrinsics -//===----------------------------------------------------------------------===// - -// wait / notify -def int_wasm_memory_atomic_wait32 : - Intrinsic<[llvm_i32_ty], - [LLVMPointerType, llvm_i32_ty, llvm_i64_ty], - [IntrInaccessibleMemOrArgMemOnly, ReadOnly>, - NoCapture>, IntrHasSideEffects], - "", [SDNPMemOperand]>; -def int_wasm_memory_atomic_wait64 : - Intrinsic<[llvm_i32_ty], - [LLVMPointerType, llvm_i64_ty, llvm_i64_ty], - [IntrInaccessibleMemOrArgMemOnly, ReadOnly>, - NoCapture>, IntrHasSideEffects], - "", [SDNPMemOperand]>; -def int_wasm_memory_atomic_notify: - Intrinsic<[llvm_i32_ty], [LLVMPointerType, llvm_i32_ty], - [IntrInaccessibleMemOnly, NoCapture>, - IntrHasSideEffects], - "", [SDNPMemOperand]>; - -//===----------------------------------------------------------------------===// -// SIMD intrinsics -//===----------------------------------------------------------------------===// - -def int_wasm_swizzle : - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_shuffle : - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_sub_sat_signed : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_sub_sat_unsigned : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_avgr_unsigned : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_bitselect : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_anytrue : - Intrinsic<[llvm_i32_ty], - [llvm_anyvector_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_alltrue : - Intrinsic<[llvm_i32_ty], - [llvm_anyvector_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_bitmask : - Intrinsic<[llvm_i32_ty], - [llvm_anyvector_ty], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_dot : - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_narrow_signed : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_narrow_unsigned : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_q15mulr_sat_signed : - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_pmin : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_pmax : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_extadd_pairwise_signed : - Intrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_extadd_pairwise_unsigned : - Intrinsic<[llvm_anyvector_ty], - [LLVMSubdivide2VectorType<0>], - [IntrNoMem, IntrSpeculatable]>; - -//===----------------------------------------------------------------------===// -// Relaxed SIMD intrinsics (experimental) -//===----------------------------------------------------------------------===// - -def int_wasm_fma : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_fms : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_laneselect : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_swizzle : - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_min : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; -def int_wasm_relaxed_max : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_trunc_signed: - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_trunc_unsigned: - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_trunc_zero_signed: - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_relaxed_trunc_zero_unsigned: - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty], - [IntrNoMem, IntrSpeculatable]>; - - -//===----------------------------------------------------------------------===// -// Thread-local storage intrinsics -//===----------------------------------------------------------------------===// - -def int_wasm_tls_size : - Intrinsic<[llvm_anyint_ty], - [], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_tls_align : - Intrinsic<[llvm_anyint_ty], - [], - [IntrNoMem, IntrSpeculatable]>; - -def int_wasm_tls_base : - Intrinsic<[llvm_ptr_ty], - [], - [IntrReadMem]>; - -} // TargetPrefix = "wasm" diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.h deleted file mode 100644 index 8e8325b7b1..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.h +++ /dev/null @@ -1,1388 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_X86_ENUMS_H -#define LLVM_IR_INTRINSIC_X86_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum X86Intrinsics : unsigned { -// Enum values for intrinsics - x86_3dnow_pavgusb = 9340, // llvm.x86.3dnow.pavgusb - x86_3dnow_pf2id, // llvm.x86.3dnow.pf2id - x86_3dnow_pfacc, // llvm.x86.3dnow.pfacc - x86_3dnow_pfadd, // llvm.x86.3dnow.pfadd - x86_3dnow_pfcmpeq, // llvm.x86.3dnow.pfcmpeq - x86_3dnow_pfcmpge, // llvm.x86.3dnow.pfcmpge - x86_3dnow_pfcmpgt, // llvm.x86.3dnow.pfcmpgt - x86_3dnow_pfmax, // llvm.x86.3dnow.pfmax - x86_3dnow_pfmin, // llvm.x86.3dnow.pfmin - x86_3dnow_pfmul, // llvm.x86.3dnow.pfmul - x86_3dnow_pfrcp, // llvm.x86.3dnow.pfrcp - x86_3dnow_pfrcpit1, // llvm.x86.3dnow.pfrcpit1 - x86_3dnow_pfrcpit2, // llvm.x86.3dnow.pfrcpit2 - x86_3dnow_pfrsqit1, // llvm.x86.3dnow.pfrsqit1 - x86_3dnow_pfrsqrt, // llvm.x86.3dnow.pfrsqrt - x86_3dnow_pfsub, // llvm.x86.3dnow.pfsub - x86_3dnow_pfsubr, // llvm.x86.3dnow.pfsubr - x86_3dnow_pi2fd, // llvm.x86.3dnow.pi2fd - x86_3dnow_pmulhrw, // llvm.x86.3dnow.pmulhrw - x86_3dnowa_pf2iw, // llvm.x86.3dnowa.pf2iw - x86_3dnowa_pfnacc, // llvm.x86.3dnowa.pfnacc - x86_3dnowa_pfpnacc, // llvm.x86.3dnowa.pfpnacc - x86_3dnowa_pi2fw, // llvm.x86.3dnowa.pi2fw - x86_3dnowa_pswapd, // llvm.x86.3dnowa.pswapd - x86_addcarry_32, // llvm.x86.addcarry.32 - x86_addcarry_64, // llvm.x86.addcarry.64 - x86_aesdec128kl, // llvm.x86.aesdec128kl - x86_aesdec256kl, // llvm.x86.aesdec256kl - x86_aesdecwide128kl, // llvm.x86.aesdecwide128kl - x86_aesdecwide256kl, // llvm.x86.aesdecwide256kl - x86_aesenc128kl, // llvm.x86.aesenc128kl - x86_aesenc256kl, // llvm.x86.aesenc256kl - x86_aesencwide128kl, // llvm.x86.aesencwide128kl - x86_aesencwide256kl, // llvm.x86.aesencwide256kl - x86_aesni_aesdec, // llvm.x86.aesni.aesdec - x86_aesni_aesdec_256, // llvm.x86.aesni.aesdec.256 - x86_aesni_aesdec_512, // llvm.x86.aesni.aesdec.512 - x86_aesni_aesdeclast, // llvm.x86.aesni.aesdeclast - x86_aesni_aesdeclast_256, // llvm.x86.aesni.aesdeclast.256 - x86_aesni_aesdeclast_512, // llvm.x86.aesni.aesdeclast.512 - x86_aesni_aesenc, // llvm.x86.aesni.aesenc - x86_aesni_aesenc_256, // llvm.x86.aesni.aesenc.256 - x86_aesni_aesenc_512, // llvm.x86.aesni.aesenc.512 - x86_aesni_aesenclast, // llvm.x86.aesni.aesenclast - x86_aesni_aesenclast_256, // llvm.x86.aesni.aesenclast.256 - x86_aesni_aesenclast_512, // llvm.x86.aesni.aesenclast.512 - x86_aesni_aesimc, // llvm.x86.aesni.aesimc - x86_aesni_aeskeygenassist, // llvm.x86.aesni.aeskeygenassist - x86_avx_addsub_pd_256, // llvm.x86.avx.addsub.pd.256 - x86_avx_addsub_ps_256, // llvm.x86.avx.addsub.ps.256 - x86_avx_blendv_pd_256, // llvm.x86.avx.blendv.pd.256 - x86_avx_blendv_ps_256, // llvm.x86.avx.blendv.ps.256 - x86_avx_cmp_pd_256, // llvm.x86.avx.cmp.pd.256 - x86_avx_cmp_ps_256, // llvm.x86.avx.cmp.ps.256 - x86_avx_cvt_pd2_ps_256, // llvm.x86.avx.cvt.pd2.ps.256 - x86_avx_cvt_pd2dq_256, // llvm.x86.avx.cvt.pd2dq.256 - x86_avx_cvt_ps2dq_256, // llvm.x86.avx.cvt.ps2dq.256 - x86_avx_cvtt_pd2dq_256, // llvm.x86.avx.cvtt.pd2dq.256 - x86_avx_cvtt_ps2dq_256, // llvm.x86.avx.cvtt.ps2dq.256 - x86_avx_dp_ps_256, // llvm.x86.avx.dp.ps.256 - x86_avx_hadd_pd_256, // llvm.x86.avx.hadd.pd.256 - x86_avx_hadd_ps_256, // llvm.x86.avx.hadd.ps.256 - x86_avx_hsub_pd_256, // llvm.x86.avx.hsub.pd.256 - x86_avx_hsub_ps_256, // llvm.x86.avx.hsub.ps.256 - x86_avx_ldu_dq_256, // llvm.x86.avx.ldu.dq.256 - x86_avx_maskload_pd, // llvm.x86.avx.maskload.pd - x86_avx_maskload_pd_256, // llvm.x86.avx.maskload.pd.256 - x86_avx_maskload_ps, // llvm.x86.avx.maskload.ps - x86_avx_maskload_ps_256, // llvm.x86.avx.maskload.ps.256 - x86_avx_maskstore_pd, // llvm.x86.avx.maskstore.pd - x86_avx_maskstore_pd_256, // llvm.x86.avx.maskstore.pd.256 - x86_avx_maskstore_ps, // llvm.x86.avx.maskstore.ps - x86_avx_maskstore_ps_256, // llvm.x86.avx.maskstore.ps.256 - x86_avx_max_pd_256, // llvm.x86.avx.max.pd.256 - x86_avx_max_ps_256, // llvm.x86.avx.max.ps.256 - x86_avx_min_pd_256, // llvm.x86.avx.min.pd.256 - x86_avx_min_ps_256, // llvm.x86.avx.min.ps.256 - x86_avx_movmsk_pd_256, // llvm.x86.avx.movmsk.pd.256 - x86_avx_movmsk_ps_256, // llvm.x86.avx.movmsk.ps.256 - x86_avx_ptestc_256, // llvm.x86.avx.ptestc.256 - x86_avx_ptestnzc_256, // llvm.x86.avx.ptestnzc.256 - x86_avx_ptestz_256, // llvm.x86.avx.ptestz.256 - x86_avx_rcp_ps_256, // llvm.x86.avx.rcp.ps.256 - x86_avx_round_pd_256, // llvm.x86.avx.round.pd.256 - x86_avx_round_ps_256, // llvm.x86.avx.round.ps.256 - x86_avx_rsqrt_ps_256, // llvm.x86.avx.rsqrt.ps.256 - x86_avx_vpermilvar_pd, // llvm.x86.avx.vpermilvar.pd - x86_avx_vpermilvar_pd_256, // llvm.x86.avx.vpermilvar.pd.256 - x86_avx_vpermilvar_ps, // llvm.x86.avx.vpermilvar.ps - x86_avx_vpermilvar_ps_256, // llvm.x86.avx.vpermilvar.ps.256 - x86_avx_vtestc_pd, // llvm.x86.avx.vtestc.pd - x86_avx_vtestc_pd_256, // llvm.x86.avx.vtestc.pd.256 - x86_avx_vtestc_ps, // llvm.x86.avx.vtestc.ps - x86_avx_vtestc_ps_256, // llvm.x86.avx.vtestc.ps.256 - x86_avx_vtestnzc_pd, // llvm.x86.avx.vtestnzc.pd - x86_avx_vtestnzc_pd_256, // llvm.x86.avx.vtestnzc.pd.256 - x86_avx_vtestnzc_ps, // llvm.x86.avx.vtestnzc.ps - x86_avx_vtestnzc_ps_256, // llvm.x86.avx.vtestnzc.ps.256 - x86_avx_vtestz_pd, // llvm.x86.avx.vtestz.pd - x86_avx_vtestz_pd_256, // llvm.x86.avx.vtestz.pd.256 - x86_avx_vtestz_ps, // llvm.x86.avx.vtestz.ps - x86_avx_vtestz_ps_256, // llvm.x86.avx.vtestz.ps.256 - x86_avx_vzeroall, // llvm.x86.avx.vzeroall - x86_avx_vzeroupper, // llvm.x86.avx.vzeroupper - x86_avx2_gather_d_d, // llvm.x86.avx2.gather.d.d - x86_avx2_gather_d_d_256, // llvm.x86.avx2.gather.d.d.256 - x86_avx2_gather_d_pd, // llvm.x86.avx2.gather.d.pd - x86_avx2_gather_d_pd_256, // llvm.x86.avx2.gather.d.pd.256 - x86_avx2_gather_d_ps, // llvm.x86.avx2.gather.d.ps - x86_avx2_gather_d_ps_256, // llvm.x86.avx2.gather.d.ps.256 - x86_avx2_gather_d_q, // llvm.x86.avx2.gather.d.q - x86_avx2_gather_d_q_256, // llvm.x86.avx2.gather.d.q.256 - x86_avx2_gather_q_d, // llvm.x86.avx2.gather.q.d - x86_avx2_gather_q_d_256, // llvm.x86.avx2.gather.q.d.256 - x86_avx2_gather_q_pd, // llvm.x86.avx2.gather.q.pd - x86_avx2_gather_q_pd_256, // llvm.x86.avx2.gather.q.pd.256 - x86_avx2_gather_q_ps, // llvm.x86.avx2.gather.q.ps - x86_avx2_gather_q_ps_256, // llvm.x86.avx2.gather.q.ps.256 - x86_avx2_gather_q_q, // llvm.x86.avx2.gather.q.q - x86_avx2_gather_q_q_256, // llvm.x86.avx2.gather.q.q.256 - x86_avx2_maskload_d, // llvm.x86.avx2.maskload.d - x86_avx2_maskload_d_256, // llvm.x86.avx2.maskload.d.256 - x86_avx2_maskload_q, // llvm.x86.avx2.maskload.q - x86_avx2_maskload_q_256, // llvm.x86.avx2.maskload.q.256 - x86_avx2_maskstore_d, // llvm.x86.avx2.maskstore.d - x86_avx2_maskstore_d_256, // llvm.x86.avx2.maskstore.d.256 - x86_avx2_maskstore_q, // llvm.x86.avx2.maskstore.q - x86_avx2_maskstore_q_256, // llvm.x86.avx2.maskstore.q.256 - x86_avx2_mpsadbw, // llvm.x86.avx2.mpsadbw - x86_avx2_packssdw, // llvm.x86.avx2.packssdw - x86_avx2_packsswb, // llvm.x86.avx2.packsswb - x86_avx2_packusdw, // llvm.x86.avx2.packusdw - x86_avx2_packuswb, // llvm.x86.avx2.packuswb - x86_avx2_pavg_b, // llvm.x86.avx2.pavg.b - x86_avx2_pavg_w, // llvm.x86.avx2.pavg.w - x86_avx2_pblendvb, // llvm.x86.avx2.pblendvb - x86_avx2_permd, // llvm.x86.avx2.permd - x86_avx2_permps, // llvm.x86.avx2.permps - x86_avx2_phadd_d, // llvm.x86.avx2.phadd.d - x86_avx2_phadd_sw, // llvm.x86.avx2.phadd.sw - x86_avx2_phadd_w, // llvm.x86.avx2.phadd.w - x86_avx2_phsub_d, // llvm.x86.avx2.phsub.d - x86_avx2_phsub_sw, // llvm.x86.avx2.phsub.sw - x86_avx2_phsub_w, // llvm.x86.avx2.phsub.w - x86_avx2_pmadd_ub_sw, // llvm.x86.avx2.pmadd.ub.sw - x86_avx2_pmadd_wd, // llvm.x86.avx2.pmadd.wd - x86_avx2_pmovmskb, // llvm.x86.avx2.pmovmskb - x86_avx2_pmul_hr_sw, // llvm.x86.avx2.pmul.hr.sw - x86_avx2_pmulh_w, // llvm.x86.avx2.pmulh.w - x86_avx2_pmulhu_w, // llvm.x86.avx2.pmulhu.w - x86_avx2_psad_bw, // llvm.x86.avx2.psad.bw - x86_avx2_pshuf_b, // llvm.x86.avx2.pshuf.b - x86_avx2_psign_b, // llvm.x86.avx2.psign.b - x86_avx2_psign_d, // llvm.x86.avx2.psign.d - x86_avx2_psign_w, // llvm.x86.avx2.psign.w - x86_avx2_psll_d, // llvm.x86.avx2.psll.d - x86_avx2_psll_q, // llvm.x86.avx2.psll.q - x86_avx2_psll_w, // llvm.x86.avx2.psll.w - x86_avx2_pslli_d, // llvm.x86.avx2.pslli.d - x86_avx2_pslli_q, // llvm.x86.avx2.pslli.q - x86_avx2_pslli_w, // llvm.x86.avx2.pslli.w - x86_avx2_psllv_d, // llvm.x86.avx2.psllv.d - x86_avx2_psllv_d_256, // llvm.x86.avx2.psllv.d.256 - x86_avx2_psllv_q, // llvm.x86.avx2.psllv.q - x86_avx2_psllv_q_256, // llvm.x86.avx2.psllv.q.256 - x86_avx2_psra_d, // llvm.x86.avx2.psra.d - x86_avx2_psra_w, // llvm.x86.avx2.psra.w - x86_avx2_psrai_d, // llvm.x86.avx2.psrai.d - x86_avx2_psrai_w, // llvm.x86.avx2.psrai.w - x86_avx2_psrav_d, // llvm.x86.avx2.psrav.d - x86_avx2_psrav_d_256, // llvm.x86.avx2.psrav.d.256 - x86_avx2_psrl_d, // llvm.x86.avx2.psrl.d - x86_avx2_psrl_q, // llvm.x86.avx2.psrl.q - x86_avx2_psrl_w, // llvm.x86.avx2.psrl.w - x86_avx2_psrli_d, // llvm.x86.avx2.psrli.d - x86_avx2_psrli_q, // llvm.x86.avx2.psrli.q - x86_avx2_psrli_w, // llvm.x86.avx2.psrli.w - x86_avx2_psrlv_d, // llvm.x86.avx2.psrlv.d - x86_avx2_psrlv_d_256, // llvm.x86.avx2.psrlv.d.256 - x86_avx2_psrlv_q, // llvm.x86.avx2.psrlv.q - x86_avx2_psrlv_q_256, // llvm.x86.avx2.psrlv.q.256 - x86_avx512_add_pd_512, // llvm.x86.avx512.add.pd.512 - x86_avx512_add_ps_512, // llvm.x86.avx512.add.ps.512 - x86_avx512_broadcastmb_128, // llvm.x86.avx512.broadcastmb.128 - x86_avx512_broadcastmb_256, // llvm.x86.avx512.broadcastmb.256 - x86_avx512_broadcastmb_512, // llvm.x86.avx512.broadcastmb.512 - x86_avx512_broadcastmw_128, // llvm.x86.avx512.broadcastmw.128 - x86_avx512_broadcastmw_256, // llvm.x86.avx512.broadcastmw.256 - x86_avx512_broadcastmw_512, // llvm.x86.avx512.broadcastmw.512 - x86_avx512_conflict_d_128, // llvm.x86.avx512.conflict.d.128 - x86_avx512_conflict_d_256, // llvm.x86.avx512.conflict.d.256 - x86_avx512_conflict_d_512, // llvm.x86.avx512.conflict.d.512 - x86_avx512_conflict_q_128, // llvm.x86.avx512.conflict.q.128 - x86_avx512_conflict_q_256, // llvm.x86.avx512.conflict.q.256 - x86_avx512_conflict_q_512, // llvm.x86.avx512.conflict.q.512 - x86_avx512_cvtsi2sd64, // llvm.x86.avx512.cvtsi2sd64 - x86_avx512_cvtsi2ss32, // llvm.x86.avx512.cvtsi2ss32 - x86_avx512_cvtsi2ss64, // llvm.x86.avx512.cvtsi2ss64 - x86_avx512_cvttsd2si, // llvm.x86.avx512.cvttsd2si - x86_avx512_cvttsd2si64, // llvm.x86.avx512.cvttsd2si64 - x86_avx512_cvttsd2usi, // llvm.x86.avx512.cvttsd2usi - x86_avx512_cvttsd2usi64, // llvm.x86.avx512.cvttsd2usi64 - x86_avx512_cvttss2si, // llvm.x86.avx512.cvttss2si - x86_avx512_cvttss2si64, // llvm.x86.avx512.cvttss2si64 - x86_avx512_cvttss2usi, // llvm.x86.avx512.cvttss2usi - x86_avx512_cvttss2usi64, // llvm.x86.avx512.cvttss2usi64 - x86_avx512_cvtusi2ss, // llvm.x86.avx512.cvtusi2ss - x86_avx512_cvtusi642sd, // llvm.x86.avx512.cvtusi642sd - x86_avx512_cvtusi642ss, // llvm.x86.avx512.cvtusi642ss - x86_avx512_dbpsadbw_128, // llvm.x86.avx512.dbpsadbw.128 - x86_avx512_dbpsadbw_256, // llvm.x86.avx512.dbpsadbw.256 - x86_avx512_dbpsadbw_512, // llvm.x86.avx512.dbpsadbw.512 - x86_avx512_div_pd_512, // llvm.x86.avx512.div.pd.512 - x86_avx512_div_ps_512, // llvm.x86.avx512.div.ps.512 - x86_avx512_exp2_pd, // llvm.x86.avx512.exp2.pd - x86_avx512_exp2_ps, // llvm.x86.avx512.exp2.ps - x86_avx512_fpclass_pd_128, // llvm.x86.avx512.fpclass.pd.128 - x86_avx512_fpclass_pd_256, // llvm.x86.avx512.fpclass.pd.256 - x86_avx512_fpclass_pd_512, // llvm.x86.avx512.fpclass.pd.512 - x86_avx512_fpclass_ps_128, // llvm.x86.avx512.fpclass.ps.128 - x86_avx512_fpclass_ps_256, // llvm.x86.avx512.fpclass.ps.256 - x86_avx512_fpclass_ps_512, // llvm.x86.avx512.fpclass.ps.512 - x86_avx512_gather_dpd_512, // llvm.x86.avx512.gather.dpd.512 - x86_avx512_gather_dpi_512, // llvm.x86.avx512.gather.dpi.512 - x86_avx512_gather_dpq_512, // llvm.x86.avx512.gather.dpq.512 - x86_avx512_gather_dps_512, // llvm.x86.avx512.gather.dps.512 - x86_avx512_gather_qpd_512, // llvm.x86.avx512.gather.qpd.512 - x86_avx512_gather_qpi_512, // llvm.x86.avx512.gather.qpi.512 - x86_avx512_gather_qpq_512, // llvm.x86.avx512.gather.qpq.512 - x86_avx512_gather_qps_512, // llvm.x86.avx512.gather.qps.512 - x86_avx512_gather3div2_df, // llvm.x86.avx512.gather3div2.df - x86_avx512_gather3div2_di, // llvm.x86.avx512.gather3div2.di - x86_avx512_gather3div4_df, // llvm.x86.avx512.gather3div4.df - x86_avx512_gather3div4_di, // llvm.x86.avx512.gather3div4.di - x86_avx512_gather3div4_sf, // llvm.x86.avx512.gather3div4.sf - x86_avx512_gather3div4_si, // llvm.x86.avx512.gather3div4.si - x86_avx512_gather3div8_sf, // llvm.x86.avx512.gather3div8.sf - x86_avx512_gather3div8_si, // llvm.x86.avx512.gather3div8.si - x86_avx512_gather3siv2_df, // llvm.x86.avx512.gather3siv2.df - x86_avx512_gather3siv2_di, // llvm.x86.avx512.gather3siv2.di - x86_avx512_gather3siv4_df, // llvm.x86.avx512.gather3siv4.df - x86_avx512_gather3siv4_di, // llvm.x86.avx512.gather3siv4.di - x86_avx512_gather3siv4_sf, // llvm.x86.avx512.gather3siv4.sf - x86_avx512_gather3siv4_si, // llvm.x86.avx512.gather3siv4.si - x86_avx512_gather3siv8_sf, // llvm.x86.avx512.gather3siv8.sf - x86_avx512_gather3siv8_si, // llvm.x86.avx512.gather3siv8.si - x86_avx512_gatherpf_dpd_512, // llvm.x86.avx512.gatherpf.dpd.512 - x86_avx512_gatherpf_dps_512, // llvm.x86.avx512.gatherpf.dps.512 - x86_avx512_gatherpf_qpd_512, // llvm.x86.avx512.gatherpf.qpd.512 - x86_avx512_gatherpf_qps_512, // llvm.x86.avx512.gatherpf.qps.512 - x86_avx512_kadd_b, // llvm.x86.avx512.kadd.b - x86_avx512_kadd_d, // llvm.x86.avx512.kadd.d - x86_avx512_kadd_q, // llvm.x86.avx512.kadd.q - x86_avx512_kadd_w, // llvm.x86.avx512.kadd.w - x86_avx512_ktestc_b, // llvm.x86.avx512.ktestc.b - x86_avx512_ktestc_d, // llvm.x86.avx512.ktestc.d - x86_avx512_ktestc_q, // llvm.x86.avx512.ktestc.q - x86_avx512_ktestc_w, // llvm.x86.avx512.ktestc.w - x86_avx512_ktestz_b, // llvm.x86.avx512.ktestz.b - x86_avx512_ktestz_d, // llvm.x86.avx512.ktestz.d - x86_avx512_ktestz_q, // llvm.x86.avx512.ktestz.q - x86_avx512_ktestz_w, // llvm.x86.avx512.ktestz.w - x86_avx512_mask_add_sd_round, // llvm.x86.avx512.mask.add.sd.round - x86_avx512_mask_add_ss_round, // llvm.x86.avx512.mask.add.ss.round - x86_avx512_mask_cmp_pd_128, // llvm.x86.avx512.mask.cmp.pd.128 - x86_avx512_mask_cmp_pd_256, // llvm.x86.avx512.mask.cmp.pd.256 - x86_avx512_mask_cmp_pd_512, // llvm.x86.avx512.mask.cmp.pd.512 - x86_avx512_mask_cmp_ps_128, // llvm.x86.avx512.mask.cmp.ps.128 - x86_avx512_mask_cmp_ps_256, // llvm.x86.avx512.mask.cmp.ps.256 - x86_avx512_mask_cmp_ps_512, // llvm.x86.avx512.mask.cmp.ps.512 - x86_avx512_mask_cmp_sd, // llvm.x86.avx512.mask.cmp.sd - x86_avx512_mask_cmp_ss, // llvm.x86.avx512.mask.cmp.ss - x86_avx512_mask_compress, // llvm.x86.avx512.mask.compress - x86_avx512_mask_cvtpd2dq_128, // llvm.x86.avx512.mask.cvtpd2dq.128 - x86_avx512_mask_cvtpd2dq_512, // llvm.x86.avx512.mask.cvtpd2dq.512 - x86_avx512_mask_cvtpd2ps, // llvm.x86.avx512.mask.cvtpd2ps - x86_avx512_mask_cvtpd2ps_512, // llvm.x86.avx512.mask.cvtpd2ps.512 - x86_avx512_mask_cvtpd2qq_128, // llvm.x86.avx512.mask.cvtpd2qq.128 - x86_avx512_mask_cvtpd2qq_256, // llvm.x86.avx512.mask.cvtpd2qq.256 - x86_avx512_mask_cvtpd2qq_512, // llvm.x86.avx512.mask.cvtpd2qq.512 - x86_avx512_mask_cvtpd2udq_128, // llvm.x86.avx512.mask.cvtpd2udq.128 - x86_avx512_mask_cvtpd2udq_256, // llvm.x86.avx512.mask.cvtpd2udq.256 - x86_avx512_mask_cvtpd2udq_512, // llvm.x86.avx512.mask.cvtpd2udq.512 - x86_avx512_mask_cvtpd2uqq_128, // llvm.x86.avx512.mask.cvtpd2uqq.128 - x86_avx512_mask_cvtpd2uqq_256, // llvm.x86.avx512.mask.cvtpd2uqq.256 - x86_avx512_mask_cvtpd2uqq_512, // llvm.x86.avx512.mask.cvtpd2uqq.512 - x86_avx512_mask_cvtps2dq_128, // llvm.x86.avx512.mask.cvtps2dq.128 - x86_avx512_mask_cvtps2dq_256, // llvm.x86.avx512.mask.cvtps2dq.256 - x86_avx512_mask_cvtps2dq_512, // llvm.x86.avx512.mask.cvtps2dq.512 - x86_avx512_mask_cvtps2pd_512, // llvm.x86.avx512.mask.cvtps2pd.512 - x86_avx512_mask_cvtps2qq_128, // llvm.x86.avx512.mask.cvtps2qq.128 - x86_avx512_mask_cvtps2qq_256, // llvm.x86.avx512.mask.cvtps2qq.256 - x86_avx512_mask_cvtps2qq_512, // llvm.x86.avx512.mask.cvtps2qq.512 - x86_avx512_mask_cvtps2udq_128, // llvm.x86.avx512.mask.cvtps2udq.128 - x86_avx512_mask_cvtps2udq_256, // llvm.x86.avx512.mask.cvtps2udq.256 - x86_avx512_mask_cvtps2udq_512, // llvm.x86.avx512.mask.cvtps2udq.512 - x86_avx512_mask_cvtps2uqq_128, // llvm.x86.avx512.mask.cvtps2uqq.128 - x86_avx512_mask_cvtps2uqq_256, // llvm.x86.avx512.mask.cvtps2uqq.256 - x86_avx512_mask_cvtps2uqq_512, // llvm.x86.avx512.mask.cvtps2uqq.512 - x86_avx512_mask_cvtqq2ps_128, // llvm.x86.avx512.mask.cvtqq2ps.128 - x86_avx512_mask_cvtsd2ss_round, // llvm.x86.avx512.mask.cvtsd2ss.round - x86_avx512_mask_cvtss2sd_round, // llvm.x86.avx512.mask.cvtss2sd.round - x86_avx512_mask_cvttpd2dq_128, // llvm.x86.avx512.mask.cvttpd2dq.128 - x86_avx512_mask_cvttpd2dq_512, // llvm.x86.avx512.mask.cvttpd2dq.512 - x86_avx512_mask_cvttpd2qq_128, // llvm.x86.avx512.mask.cvttpd2qq.128 - x86_avx512_mask_cvttpd2qq_256, // llvm.x86.avx512.mask.cvttpd2qq.256 - x86_avx512_mask_cvttpd2qq_512, // llvm.x86.avx512.mask.cvttpd2qq.512 - x86_avx512_mask_cvttpd2udq_128, // llvm.x86.avx512.mask.cvttpd2udq.128 - x86_avx512_mask_cvttpd2udq_256, // llvm.x86.avx512.mask.cvttpd2udq.256 - x86_avx512_mask_cvttpd2udq_512, // llvm.x86.avx512.mask.cvttpd2udq.512 - x86_avx512_mask_cvttpd2uqq_128, // llvm.x86.avx512.mask.cvttpd2uqq.128 - x86_avx512_mask_cvttpd2uqq_256, // llvm.x86.avx512.mask.cvttpd2uqq.256 - x86_avx512_mask_cvttpd2uqq_512, // llvm.x86.avx512.mask.cvttpd2uqq.512 - x86_avx512_mask_cvttps2dq_512, // llvm.x86.avx512.mask.cvttps2dq.512 - x86_avx512_mask_cvttps2qq_128, // llvm.x86.avx512.mask.cvttps2qq.128 - x86_avx512_mask_cvttps2qq_256, // llvm.x86.avx512.mask.cvttps2qq.256 - x86_avx512_mask_cvttps2qq_512, // llvm.x86.avx512.mask.cvttps2qq.512 - x86_avx512_mask_cvttps2udq_128, // llvm.x86.avx512.mask.cvttps2udq.128 - x86_avx512_mask_cvttps2udq_256, // llvm.x86.avx512.mask.cvttps2udq.256 - x86_avx512_mask_cvttps2udq_512, // llvm.x86.avx512.mask.cvttps2udq.512 - x86_avx512_mask_cvttps2uqq_128, // llvm.x86.avx512.mask.cvttps2uqq.128 - x86_avx512_mask_cvttps2uqq_256, // llvm.x86.avx512.mask.cvttps2uqq.256 - x86_avx512_mask_cvttps2uqq_512, // llvm.x86.avx512.mask.cvttps2uqq.512 - x86_avx512_mask_cvtuqq2ps_128, // llvm.x86.avx512.mask.cvtuqq2ps.128 - x86_avx512_mask_div_sd_round, // llvm.x86.avx512.mask.div.sd.round - x86_avx512_mask_div_ss_round, // llvm.x86.avx512.mask.div.ss.round - x86_avx512_mask_expand, // llvm.x86.avx512.mask.expand - x86_avx512_mask_fixupimm_pd_128, // llvm.x86.avx512.mask.fixupimm.pd.128 - x86_avx512_mask_fixupimm_pd_256, // llvm.x86.avx512.mask.fixupimm.pd.256 - x86_avx512_mask_fixupimm_pd_512, // llvm.x86.avx512.mask.fixupimm.pd.512 - x86_avx512_mask_fixupimm_ps_128, // llvm.x86.avx512.mask.fixupimm.ps.128 - x86_avx512_mask_fixupimm_ps_256, // llvm.x86.avx512.mask.fixupimm.ps.256 - x86_avx512_mask_fixupimm_ps_512, // llvm.x86.avx512.mask.fixupimm.ps.512 - x86_avx512_mask_fixupimm_sd, // llvm.x86.avx512.mask.fixupimm.sd - x86_avx512_mask_fixupimm_ss, // llvm.x86.avx512.mask.fixupimm.ss - x86_avx512_mask_fpclass_sd, // llvm.x86.avx512.mask.fpclass.sd - x86_avx512_mask_fpclass_ss, // llvm.x86.avx512.mask.fpclass.ss - x86_avx512_mask_gather_dpd_512, // llvm.x86.avx512.mask.gather.dpd.512 - x86_avx512_mask_gather_dpi_512, // llvm.x86.avx512.mask.gather.dpi.512 - x86_avx512_mask_gather_dpq_512, // llvm.x86.avx512.mask.gather.dpq.512 - x86_avx512_mask_gather_dps_512, // llvm.x86.avx512.mask.gather.dps.512 - x86_avx512_mask_gather_qpd_512, // llvm.x86.avx512.mask.gather.qpd.512 - x86_avx512_mask_gather_qpi_512, // llvm.x86.avx512.mask.gather.qpi.512 - x86_avx512_mask_gather_qpq_512, // llvm.x86.avx512.mask.gather.qpq.512 - x86_avx512_mask_gather_qps_512, // llvm.x86.avx512.mask.gather.qps.512 - x86_avx512_mask_gather3div2_df, // llvm.x86.avx512.mask.gather3div2.df - x86_avx512_mask_gather3div2_di, // llvm.x86.avx512.mask.gather3div2.di - x86_avx512_mask_gather3div4_df, // llvm.x86.avx512.mask.gather3div4.df - x86_avx512_mask_gather3div4_di, // llvm.x86.avx512.mask.gather3div4.di - x86_avx512_mask_gather3div4_sf, // llvm.x86.avx512.mask.gather3div4.sf - x86_avx512_mask_gather3div4_si, // llvm.x86.avx512.mask.gather3div4.si - x86_avx512_mask_gather3div8_sf, // llvm.x86.avx512.mask.gather3div8.sf - x86_avx512_mask_gather3div8_si, // llvm.x86.avx512.mask.gather3div8.si - x86_avx512_mask_gather3siv2_df, // llvm.x86.avx512.mask.gather3siv2.df - x86_avx512_mask_gather3siv2_di, // llvm.x86.avx512.mask.gather3siv2.di - x86_avx512_mask_gather3siv4_df, // llvm.x86.avx512.mask.gather3siv4.df - x86_avx512_mask_gather3siv4_di, // llvm.x86.avx512.mask.gather3siv4.di - x86_avx512_mask_gather3siv4_sf, // llvm.x86.avx512.mask.gather3siv4.sf - x86_avx512_mask_gather3siv4_si, // llvm.x86.avx512.mask.gather3siv4.si - x86_avx512_mask_gather3siv8_sf, // llvm.x86.avx512.mask.gather3siv8.sf - x86_avx512_mask_gather3siv8_si, // llvm.x86.avx512.mask.gather3siv8.si - x86_avx512_mask_getexp_pd_128, // llvm.x86.avx512.mask.getexp.pd.128 - x86_avx512_mask_getexp_pd_256, // llvm.x86.avx512.mask.getexp.pd.256 - x86_avx512_mask_getexp_pd_512, // llvm.x86.avx512.mask.getexp.pd.512 - x86_avx512_mask_getexp_ps_128, // llvm.x86.avx512.mask.getexp.ps.128 - x86_avx512_mask_getexp_ps_256, // llvm.x86.avx512.mask.getexp.ps.256 - x86_avx512_mask_getexp_ps_512, // llvm.x86.avx512.mask.getexp.ps.512 - x86_avx512_mask_getexp_sd, // llvm.x86.avx512.mask.getexp.sd - x86_avx512_mask_getexp_ss, // llvm.x86.avx512.mask.getexp.ss - x86_avx512_mask_getmant_pd_128, // llvm.x86.avx512.mask.getmant.pd.128 - x86_avx512_mask_getmant_pd_256, // llvm.x86.avx512.mask.getmant.pd.256 - x86_avx512_mask_getmant_pd_512, // llvm.x86.avx512.mask.getmant.pd.512 - x86_avx512_mask_getmant_ps_128, // llvm.x86.avx512.mask.getmant.ps.128 - x86_avx512_mask_getmant_ps_256, // llvm.x86.avx512.mask.getmant.ps.256 - x86_avx512_mask_getmant_ps_512, // llvm.x86.avx512.mask.getmant.ps.512 - x86_avx512_mask_getmant_sd, // llvm.x86.avx512.mask.getmant.sd - x86_avx512_mask_getmant_ss, // llvm.x86.avx512.mask.getmant.ss - x86_avx512_mask_max_sd_round, // llvm.x86.avx512.mask.max.sd.round - x86_avx512_mask_max_ss_round, // llvm.x86.avx512.mask.max.ss.round - x86_avx512_mask_min_sd_round, // llvm.x86.avx512.mask.min.sd.round - x86_avx512_mask_min_ss_round, // llvm.x86.avx512.mask.min.ss.round - x86_avx512_mask_mul_sd_round, // llvm.x86.avx512.mask.mul.sd.round - x86_avx512_mask_mul_ss_round, // llvm.x86.avx512.mask.mul.ss.round - x86_avx512_mask_pmov_db_128, // llvm.x86.avx512.mask.pmov.db.128 - x86_avx512_mask_pmov_db_256, // llvm.x86.avx512.mask.pmov.db.256 - x86_avx512_mask_pmov_db_512, // llvm.x86.avx512.mask.pmov.db.512 - x86_avx512_mask_pmov_db_mem_128, // llvm.x86.avx512.mask.pmov.db.mem.128 - x86_avx512_mask_pmov_db_mem_256, // llvm.x86.avx512.mask.pmov.db.mem.256 - x86_avx512_mask_pmov_db_mem_512, // llvm.x86.avx512.mask.pmov.db.mem.512 - x86_avx512_mask_pmov_dw_128, // llvm.x86.avx512.mask.pmov.dw.128 - x86_avx512_mask_pmov_dw_256, // llvm.x86.avx512.mask.pmov.dw.256 - x86_avx512_mask_pmov_dw_512, // llvm.x86.avx512.mask.pmov.dw.512 - x86_avx512_mask_pmov_dw_mem_128, // llvm.x86.avx512.mask.pmov.dw.mem.128 - x86_avx512_mask_pmov_dw_mem_256, // llvm.x86.avx512.mask.pmov.dw.mem.256 - x86_avx512_mask_pmov_dw_mem_512, // llvm.x86.avx512.mask.pmov.dw.mem.512 - x86_avx512_mask_pmov_qb_128, // llvm.x86.avx512.mask.pmov.qb.128 - x86_avx512_mask_pmov_qb_256, // llvm.x86.avx512.mask.pmov.qb.256 - x86_avx512_mask_pmov_qb_512, // llvm.x86.avx512.mask.pmov.qb.512 - x86_avx512_mask_pmov_qb_mem_128, // llvm.x86.avx512.mask.pmov.qb.mem.128 - x86_avx512_mask_pmov_qb_mem_256, // llvm.x86.avx512.mask.pmov.qb.mem.256 - x86_avx512_mask_pmov_qb_mem_512, // llvm.x86.avx512.mask.pmov.qb.mem.512 - x86_avx512_mask_pmov_qd_128, // llvm.x86.avx512.mask.pmov.qd.128 - x86_avx512_mask_pmov_qd_mem_128, // llvm.x86.avx512.mask.pmov.qd.mem.128 - x86_avx512_mask_pmov_qd_mem_256, // llvm.x86.avx512.mask.pmov.qd.mem.256 - x86_avx512_mask_pmov_qd_mem_512, // llvm.x86.avx512.mask.pmov.qd.mem.512 - x86_avx512_mask_pmov_qw_128, // llvm.x86.avx512.mask.pmov.qw.128 - x86_avx512_mask_pmov_qw_256, // llvm.x86.avx512.mask.pmov.qw.256 - x86_avx512_mask_pmov_qw_512, // llvm.x86.avx512.mask.pmov.qw.512 - x86_avx512_mask_pmov_qw_mem_128, // llvm.x86.avx512.mask.pmov.qw.mem.128 - x86_avx512_mask_pmov_qw_mem_256, // llvm.x86.avx512.mask.pmov.qw.mem.256 - x86_avx512_mask_pmov_qw_mem_512, // llvm.x86.avx512.mask.pmov.qw.mem.512 - x86_avx512_mask_pmov_wb_128, // llvm.x86.avx512.mask.pmov.wb.128 - x86_avx512_mask_pmov_wb_mem_128, // llvm.x86.avx512.mask.pmov.wb.mem.128 - x86_avx512_mask_pmov_wb_mem_256, // llvm.x86.avx512.mask.pmov.wb.mem.256 - x86_avx512_mask_pmov_wb_mem_512, // llvm.x86.avx512.mask.pmov.wb.mem.512 - x86_avx512_mask_pmovs_db_128, // llvm.x86.avx512.mask.pmovs.db.128 - x86_avx512_mask_pmovs_db_256, // llvm.x86.avx512.mask.pmovs.db.256 - x86_avx512_mask_pmovs_db_512, // llvm.x86.avx512.mask.pmovs.db.512 - x86_avx512_mask_pmovs_db_mem_128, // llvm.x86.avx512.mask.pmovs.db.mem.128 - x86_avx512_mask_pmovs_db_mem_256, // llvm.x86.avx512.mask.pmovs.db.mem.256 - x86_avx512_mask_pmovs_db_mem_512, // llvm.x86.avx512.mask.pmovs.db.mem.512 - x86_avx512_mask_pmovs_dw_128, // llvm.x86.avx512.mask.pmovs.dw.128 - x86_avx512_mask_pmovs_dw_256, // llvm.x86.avx512.mask.pmovs.dw.256 - x86_avx512_mask_pmovs_dw_512, // llvm.x86.avx512.mask.pmovs.dw.512 - x86_avx512_mask_pmovs_dw_mem_128, // llvm.x86.avx512.mask.pmovs.dw.mem.128 - x86_avx512_mask_pmovs_dw_mem_256, // llvm.x86.avx512.mask.pmovs.dw.mem.256 - x86_avx512_mask_pmovs_dw_mem_512, // llvm.x86.avx512.mask.pmovs.dw.mem.512 - x86_avx512_mask_pmovs_qb_128, // llvm.x86.avx512.mask.pmovs.qb.128 - x86_avx512_mask_pmovs_qb_256, // llvm.x86.avx512.mask.pmovs.qb.256 - x86_avx512_mask_pmovs_qb_512, // llvm.x86.avx512.mask.pmovs.qb.512 - x86_avx512_mask_pmovs_qb_mem_128, // llvm.x86.avx512.mask.pmovs.qb.mem.128 - x86_avx512_mask_pmovs_qb_mem_256, // llvm.x86.avx512.mask.pmovs.qb.mem.256 - x86_avx512_mask_pmovs_qb_mem_512, // llvm.x86.avx512.mask.pmovs.qb.mem.512 - x86_avx512_mask_pmovs_qd_128, // llvm.x86.avx512.mask.pmovs.qd.128 - x86_avx512_mask_pmovs_qd_256, // llvm.x86.avx512.mask.pmovs.qd.256 - x86_avx512_mask_pmovs_qd_512, // llvm.x86.avx512.mask.pmovs.qd.512 - x86_avx512_mask_pmovs_qd_mem_128, // llvm.x86.avx512.mask.pmovs.qd.mem.128 - x86_avx512_mask_pmovs_qd_mem_256, // llvm.x86.avx512.mask.pmovs.qd.mem.256 - x86_avx512_mask_pmovs_qd_mem_512, // llvm.x86.avx512.mask.pmovs.qd.mem.512 - x86_avx512_mask_pmovs_qw_128, // llvm.x86.avx512.mask.pmovs.qw.128 - x86_avx512_mask_pmovs_qw_256, // llvm.x86.avx512.mask.pmovs.qw.256 - x86_avx512_mask_pmovs_qw_512, // llvm.x86.avx512.mask.pmovs.qw.512 - x86_avx512_mask_pmovs_qw_mem_128, // llvm.x86.avx512.mask.pmovs.qw.mem.128 - x86_avx512_mask_pmovs_qw_mem_256, // llvm.x86.avx512.mask.pmovs.qw.mem.256 - x86_avx512_mask_pmovs_qw_mem_512, // llvm.x86.avx512.mask.pmovs.qw.mem.512 - x86_avx512_mask_pmovs_wb_128, // llvm.x86.avx512.mask.pmovs.wb.128 - x86_avx512_mask_pmovs_wb_256, // llvm.x86.avx512.mask.pmovs.wb.256 - x86_avx512_mask_pmovs_wb_512, // llvm.x86.avx512.mask.pmovs.wb.512 - x86_avx512_mask_pmovs_wb_mem_128, // llvm.x86.avx512.mask.pmovs.wb.mem.128 - x86_avx512_mask_pmovs_wb_mem_256, // llvm.x86.avx512.mask.pmovs.wb.mem.256 - x86_avx512_mask_pmovs_wb_mem_512, // llvm.x86.avx512.mask.pmovs.wb.mem.512 - x86_avx512_mask_pmovus_db_128, // llvm.x86.avx512.mask.pmovus.db.128 - x86_avx512_mask_pmovus_db_256, // llvm.x86.avx512.mask.pmovus.db.256 - x86_avx512_mask_pmovus_db_512, // llvm.x86.avx512.mask.pmovus.db.512 - x86_avx512_mask_pmovus_db_mem_128, // llvm.x86.avx512.mask.pmovus.db.mem.128 - x86_avx512_mask_pmovus_db_mem_256, // llvm.x86.avx512.mask.pmovus.db.mem.256 - x86_avx512_mask_pmovus_db_mem_512, // llvm.x86.avx512.mask.pmovus.db.mem.512 - x86_avx512_mask_pmovus_dw_128, // llvm.x86.avx512.mask.pmovus.dw.128 - x86_avx512_mask_pmovus_dw_256, // llvm.x86.avx512.mask.pmovus.dw.256 - x86_avx512_mask_pmovus_dw_512, // llvm.x86.avx512.mask.pmovus.dw.512 - x86_avx512_mask_pmovus_dw_mem_128, // llvm.x86.avx512.mask.pmovus.dw.mem.128 - x86_avx512_mask_pmovus_dw_mem_256, // llvm.x86.avx512.mask.pmovus.dw.mem.256 - x86_avx512_mask_pmovus_dw_mem_512, // llvm.x86.avx512.mask.pmovus.dw.mem.512 - x86_avx512_mask_pmovus_qb_128, // llvm.x86.avx512.mask.pmovus.qb.128 - x86_avx512_mask_pmovus_qb_256, // llvm.x86.avx512.mask.pmovus.qb.256 - x86_avx512_mask_pmovus_qb_512, // llvm.x86.avx512.mask.pmovus.qb.512 - x86_avx512_mask_pmovus_qb_mem_128, // llvm.x86.avx512.mask.pmovus.qb.mem.128 - x86_avx512_mask_pmovus_qb_mem_256, // llvm.x86.avx512.mask.pmovus.qb.mem.256 - x86_avx512_mask_pmovus_qb_mem_512, // llvm.x86.avx512.mask.pmovus.qb.mem.512 - x86_avx512_mask_pmovus_qd_128, // llvm.x86.avx512.mask.pmovus.qd.128 - x86_avx512_mask_pmovus_qd_256, // llvm.x86.avx512.mask.pmovus.qd.256 - x86_avx512_mask_pmovus_qd_512, // llvm.x86.avx512.mask.pmovus.qd.512 - x86_avx512_mask_pmovus_qd_mem_128, // llvm.x86.avx512.mask.pmovus.qd.mem.128 - x86_avx512_mask_pmovus_qd_mem_256, // llvm.x86.avx512.mask.pmovus.qd.mem.256 - x86_avx512_mask_pmovus_qd_mem_512, // llvm.x86.avx512.mask.pmovus.qd.mem.512 - x86_avx512_mask_pmovus_qw_128, // llvm.x86.avx512.mask.pmovus.qw.128 - x86_avx512_mask_pmovus_qw_256, // llvm.x86.avx512.mask.pmovus.qw.256 - x86_avx512_mask_pmovus_qw_512, // llvm.x86.avx512.mask.pmovus.qw.512 - x86_avx512_mask_pmovus_qw_mem_128, // llvm.x86.avx512.mask.pmovus.qw.mem.128 - x86_avx512_mask_pmovus_qw_mem_256, // llvm.x86.avx512.mask.pmovus.qw.mem.256 - x86_avx512_mask_pmovus_qw_mem_512, // llvm.x86.avx512.mask.pmovus.qw.mem.512 - x86_avx512_mask_pmovus_wb_128, // llvm.x86.avx512.mask.pmovus.wb.128 - x86_avx512_mask_pmovus_wb_256, // llvm.x86.avx512.mask.pmovus.wb.256 - x86_avx512_mask_pmovus_wb_512, // llvm.x86.avx512.mask.pmovus.wb.512 - x86_avx512_mask_pmovus_wb_mem_128, // llvm.x86.avx512.mask.pmovus.wb.mem.128 - x86_avx512_mask_pmovus_wb_mem_256, // llvm.x86.avx512.mask.pmovus.wb.mem.256 - x86_avx512_mask_pmovus_wb_mem_512, // llvm.x86.avx512.mask.pmovus.wb.mem.512 - x86_avx512_mask_range_pd_128, // llvm.x86.avx512.mask.range.pd.128 - x86_avx512_mask_range_pd_256, // llvm.x86.avx512.mask.range.pd.256 - x86_avx512_mask_range_pd_512, // llvm.x86.avx512.mask.range.pd.512 - x86_avx512_mask_range_ps_128, // llvm.x86.avx512.mask.range.ps.128 - x86_avx512_mask_range_ps_256, // llvm.x86.avx512.mask.range.ps.256 - x86_avx512_mask_range_ps_512, // llvm.x86.avx512.mask.range.ps.512 - x86_avx512_mask_range_sd, // llvm.x86.avx512.mask.range.sd - x86_avx512_mask_range_ss, // llvm.x86.avx512.mask.range.ss - x86_avx512_mask_reduce_pd_128, // llvm.x86.avx512.mask.reduce.pd.128 - x86_avx512_mask_reduce_pd_256, // llvm.x86.avx512.mask.reduce.pd.256 - x86_avx512_mask_reduce_pd_512, // llvm.x86.avx512.mask.reduce.pd.512 - x86_avx512_mask_reduce_ps_128, // llvm.x86.avx512.mask.reduce.ps.128 - x86_avx512_mask_reduce_ps_256, // llvm.x86.avx512.mask.reduce.ps.256 - x86_avx512_mask_reduce_ps_512, // llvm.x86.avx512.mask.reduce.ps.512 - x86_avx512_mask_reduce_sd, // llvm.x86.avx512.mask.reduce.sd - x86_avx512_mask_reduce_ss, // llvm.x86.avx512.mask.reduce.ss - x86_avx512_mask_rndscale_pd_128, // llvm.x86.avx512.mask.rndscale.pd.128 - x86_avx512_mask_rndscale_pd_256, // llvm.x86.avx512.mask.rndscale.pd.256 - x86_avx512_mask_rndscale_pd_512, // llvm.x86.avx512.mask.rndscale.pd.512 - x86_avx512_mask_rndscale_ps_128, // llvm.x86.avx512.mask.rndscale.ps.128 - x86_avx512_mask_rndscale_ps_256, // llvm.x86.avx512.mask.rndscale.ps.256 - x86_avx512_mask_rndscale_ps_512, // llvm.x86.avx512.mask.rndscale.ps.512 - x86_avx512_mask_rndscale_sd, // llvm.x86.avx512.mask.rndscale.sd - x86_avx512_mask_rndscale_ss, // llvm.x86.avx512.mask.rndscale.ss - x86_avx512_mask_scalef_pd_128, // llvm.x86.avx512.mask.scalef.pd.128 - x86_avx512_mask_scalef_pd_256, // llvm.x86.avx512.mask.scalef.pd.256 - x86_avx512_mask_scalef_pd_512, // llvm.x86.avx512.mask.scalef.pd.512 - x86_avx512_mask_scalef_ps_128, // llvm.x86.avx512.mask.scalef.ps.128 - x86_avx512_mask_scalef_ps_256, // llvm.x86.avx512.mask.scalef.ps.256 - x86_avx512_mask_scalef_ps_512, // llvm.x86.avx512.mask.scalef.ps.512 - x86_avx512_mask_scalef_sd, // llvm.x86.avx512.mask.scalef.sd - x86_avx512_mask_scalef_ss, // llvm.x86.avx512.mask.scalef.ss - x86_avx512_mask_scatter_dpd_512, // llvm.x86.avx512.mask.scatter.dpd.512 - x86_avx512_mask_scatter_dpi_512, // llvm.x86.avx512.mask.scatter.dpi.512 - x86_avx512_mask_scatter_dpq_512, // llvm.x86.avx512.mask.scatter.dpq.512 - x86_avx512_mask_scatter_dps_512, // llvm.x86.avx512.mask.scatter.dps.512 - x86_avx512_mask_scatter_qpd_512, // llvm.x86.avx512.mask.scatter.qpd.512 - x86_avx512_mask_scatter_qpi_512, // llvm.x86.avx512.mask.scatter.qpi.512 - x86_avx512_mask_scatter_qpq_512, // llvm.x86.avx512.mask.scatter.qpq.512 - x86_avx512_mask_scatter_qps_512, // llvm.x86.avx512.mask.scatter.qps.512 - x86_avx512_mask_scatterdiv2_df, // llvm.x86.avx512.mask.scatterdiv2.df - x86_avx512_mask_scatterdiv2_di, // llvm.x86.avx512.mask.scatterdiv2.di - x86_avx512_mask_scatterdiv4_df, // llvm.x86.avx512.mask.scatterdiv4.df - x86_avx512_mask_scatterdiv4_di, // llvm.x86.avx512.mask.scatterdiv4.di - x86_avx512_mask_scatterdiv4_sf, // llvm.x86.avx512.mask.scatterdiv4.sf - x86_avx512_mask_scatterdiv4_si, // llvm.x86.avx512.mask.scatterdiv4.si - x86_avx512_mask_scatterdiv8_sf, // llvm.x86.avx512.mask.scatterdiv8.sf - x86_avx512_mask_scatterdiv8_si, // llvm.x86.avx512.mask.scatterdiv8.si - x86_avx512_mask_scattersiv2_df, // llvm.x86.avx512.mask.scattersiv2.df - x86_avx512_mask_scattersiv2_di, // llvm.x86.avx512.mask.scattersiv2.di - x86_avx512_mask_scattersiv4_df, // llvm.x86.avx512.mask.scattersiv4.df - x86_avx512_mask_scattersiv4_di, // llvm.x86.avx512.mask.scattersiv4.di - x86_avx512_mask_scattersiv4_sf, // llvm.x86.avx512.mask.scattersiv4.sf - x86_avx512_mask_scattersiv4_si, // llvm.x86.avx512.mask.scattersiv4.si - x86_avx512_mask_scattersiv8_sf, // llvm.x86.avx512.mask.scattersiv8.sf - x86_avx512_mask_scattersiv8_si, // llvm.x86.avx512.mask.scattersiv8.si - x86_avx512_mask_sqrt_sd, // llvm.x86.avx512.mask.sqrt.sd - x86_avx512_mask_sqrt_ss, // llvm.x86.avx512.mask.sqrt.ss - x86_avx512_mask_sub_sd_round, // llvm.x86.avx512.mask.sub.sd.round - x86_avx512_mask_sub_ss_round, // llvm.x86.avx512.mask.sub.ss.round - x86_avx512_mask_vcvtph2ps_512, // llvm.x86.avx512.mask.vcvtph2ps.512 - x86_avx512_mask_vcvtps2ph_128, // llvm.x86.avx512.mask.vcvtps2ph.128 - x86_avx512_mask_vcvtps2ph_256, // llvm.x86.avx512.mask.vcvtps2ph.256 - x86_avx512_mask_vcvtps2ph_512, // llvm.x86.avx512.mask.vcvtps2ph.512 - x86_avx512_maskz_fixupimm_pd_128, // llvm.x86.avx512.maskz.fixupimm.pd.128 - x86_avx512_maskz_fixupimm_pd_256, // llvm.x86.avx512.maskz.fixupimm.pd.256 - x86_avx512_maskz_fixupimm_pd_512, // llvm.x86.avx512.maskz.fixupimm.pd.512 - x86_avx512_maskz_fixupimm_ps_128, // llvm.x86.avx512.maskz.fixupimm.ps.128 - x86_avx512_maskz_fixupimm_ps_256, // llvm.x86.avx512.maskz.fixupimm.ps.256 - x86_avx512_maskz_fixupimm_ps_512, // llvm.x86.avx512.maskz.fixupimm.ps.512 - x86_avx512_maskz_fixupimm_sd, // llvm.x86.avx512.maskz.fixupimm.sd - x86_avx512_maskz_fixupimm_ss, // llvm.x86.avx512.maskz.fixupimm.ss - x86_avx512_max_pd_512, // llvm.x86.avx512.max.pd.512 - x86_avx512_max_ps_512, // llvm.x86.avx512.max.ps.512 - x86_avx512_min_pd_512, // llvm.x86.avx512.min.pd.512 - x86_avx512_min_ps_512, // llvm.x86.avx512.min.ps.512 - x86_avx512_mul_pd_512, // llvm.x86.avx512.mul.pd.512 - x86_avx512_mul_ps_512, // llvm.x86.avx512.mul.ps.512 - x86_avx512_packssdw_512, // llvm.x86.avx512.packssdw.512 - x86_avx512_packsswb_512, // llvm.x86.avx512.packsswb.512 - x86_avx512_packusdw_512, // llvm.x86.avx512.packusdw.512 - x86_avx512_packuswb_512, // llvm.x86.avx512.packuswb.512 - x86_avx512_pavg_b_512, // llvm.x86.avx512.pavg.b.512 - x86_avx512_pavg_w_512, // llvm.x86.avx512.pavg.w.512 - x86_avx512_permvar_df_256, // llvm.x86.avx512.permvar.df.256 - x86_avx512_permvar_df_512, // llvm.x86.avx512.permvar.df.512 - x86_avx512_permvar_di_256, // llvm.x86.avx512.permvar.di.256 - x86_avx512_permvar_di_512, // llvm.x86.avx512.permvar.di.512 - x86_avx512_permvar_hi_128, // llvm.x86.avx512.permvar.hi.128 - x86_avx512_permvar_hi_256, // llvm.x86.avx512.permvar.hi.256 - x86_avx512_permvar_hi_512, // llvm.x86.avx512.permvar.hi.512 - x86_avx512_permvar_qi_128, // llvm.x86.avx512.permvar.qi.128 - x86_avx512_permvar_qi_256, // llvm.x86.avx512.permvar.qi.256 - x86_avx512_permvar_qi_512, // llvm.x86.avx512.permvar.qi.512 - x86_avx512_permvar_sf_512, // llvm.x86.avx512.permvar.sf.512 - x86_avx512_permvar_si_512, // llvm.x86.avx512.permvar.si.512 - x86_avx512_pmaddubs_w_512, // llvm.x86.avx512.pmaddubs.w.512 - x86_avx512_pmaddw_d_512, // llvm.x86.avx512.pmaddw.d.512 - x86_avx512_pmul_hr_sw_512, // llvm.x86.avx512.pmul.hr.sw.512 - x86_avx512_pmulh_w_512, // llvm.x86.avx512.pmulh.w.512 - x86_avx512_pmulhu_w_512, // llvm.x86.avx512.pmulhu.w.512 - x86_avx512_pmultishift_qb_128, // llvm.x86.avx512.pmultishift.qb.128 - x86_avx512_pmultishift_qb_256, // llvm.x86.avx512.pmultishift.qb.256 - x86_avx512_pmultishift_qb_512, // llvm.x86.avx512.pmultishift.qb.512 - x86_avx512_psad_bw_512, // llvm.x86.avx512.psad.bw.512 - x86_avx512_pshuf_b_512, // llvm.x86.avx512.pshuf.b.512 - x86_avx512_psll_d_512, // llvm.x86.avx512.psll.d.512 - x86_avx512_psll_q_512, // llvm.x86.avx512.psll.q.512 - x86_avx512_psll_w_512, // llvm.x86.avx512.psll.w.512 - x86_avx512_pslli_d_512, // llvm.x86.avx512.pslli.d.512 - x86_avx512_pslli_q_512, // llvm.x86.avx512.pslli.q.512 - x86_avx512_pslli_w_512, // llvm.x86.avx512.pslli.w.512 - x86_avx512_psllv_d_512, // llvm.x86.avx512.psllv.d.512 - x86_avx512_psllv_q_512, // llvm.x86.avx512.psllv.q.512 - x86_avx512_psllv_w_128, // llvm.x86.avx512.psllv.w.128 - x86_avx512_psllv_w_256, // llvm.x86.avx512.psllv.w.256 - x86_avx512_psllv_w_512, // llvm.x86.avx512.psllv.w.512 - x86_avx512_psra_d_512, // llvm.x86.avx512.psra.d.512 - x86_avx512_psra_q_128, // llvm.x86.avx512.psra.q.128 - x86_avx512_psra_q_256, // llvm.x86.avx512.psra.q.256 - x86_avx512_psra_q_512, // llvm.x86.avx512.psra.q.512 - x86_avx512_psra_w_512, // llvm.x86.avx512.psra.w.512 - x86_avx512_psrai_d_512, // llvm.x86.avx512.psrai.d.512 - x86_avx512_psrai_q_128, // llvm.x86.avx512.psrai.q.128 - x86_avx512_psrai_q_256, // llvm.x86.avx512.psrai.q.256 - x86_avx512_psrai_q_512, // llvm.x86.avx512.psrai.q.512 - x86_avx512_psrai_w_512, // llvm.x86.avx512.psrai.w.512 - x86_avx512_psrav_d_512, // llvm.x86.avx512.psrav.d.512 - x86_avx512_psrav_q_128, // llvm.x86.avx512.psrav.q.128 - x86_avx512_psrav_q_256, // llvm.x86.avx512.psrav.q.256 - x86_avx512_psrav_q_512, // llvm.x86.avx512.psrav.q.512 - x86_avx512_psrav_w_128, // llvm.x86.avx512.psrav.w.128 - x86_avx512_psrav_w_256, // llvm.x86.avx512.psrav.w.256 - x86_avx512_psrav_w_512, // llvm.x86.avx512.psrav.w.512 - x86_avx512_psrl_d_512, // llvm.x86.avx512.psrl.d.512 - x86_avx512_psrl_q_512, // llvm.x86.avx512.psrl.q.512 - x86_avx512_psrl_w_512, // llvm.x86.avx512.psrl.w.512 - x86_avx512_psrli_d_512, // llvm.x86.avx512.psrli.d.512 - x86_avx512_psrli_q_512, // llvm.x86.avx512.psrli.q.512 - x86_avx512_psrli_w_512, // llvm.x86.avx512.psrli.w.512 - x86_avx512_psrlv_d_512, // llvm.x86.avx512.psrlv.d.512 - x86_avx512_psrlv_q_512, // llvm.x86.avx512.psrlv.q.512 - x86_avx512_psrlv_w_128, // llvm.x86.avx512.psrlv.w.128 - x86_avx512_psrlv_w_256, // llvm.x86.avx512.psrlv.w.256 - x86_avx512_psrlv_w_512, // llvm.x86.avx512.psrlv.w.512 - x86_avx512_pternlog_d_128, // llvm.x86.avx512.pternlog.d.128 - x86_avx512_pternlog_d_256, // llvm.x86.avx512.pternlog.d.256 - x86_avx512_pternlog_d_512, // llvm.x86.avx512.pternlog.d.512 - x86_avx512_pternlog_q_128, // llvm.x86.avx512.pternlog.q.128 - x86_avx512_pternlog_q_256, // llvm.x86.avx512.pternlog.q.256 - x86_avx512_pternlog_q_512, // llvm.x86.avx512.pternlog.q.512 - x86_avx512_rcp14_pd_128, // llvm.x86.avx512.rcp14.pd.128 - x86_avx512_rcp14_pd_256, // llvm.x86.avx512.rcp14.pd.256 - x86_avx512_rcp14_pd_512, // llvm.x86.avx512.rcp14.pd.512 - x86_avx512_rcp14_ps_128, // llvm.x86.avx512.rcp14.ps.128 - x86_avx512_rcp14_ps_256, // llvm.x86.avx512.rcp14.ps.256 - x86_avx512_rcp14_ps_512, // llvm.x86.avx512.rcp14.ps.512 - x86_avx512_rcp14_sd, // llvm.x86.avx512.rcp14.sd - x86_avx512_rcp14_ss, // llvm.x86.avx512.rcp14.ss - x86_avx512_rcp28_pd, // llvm.x86.avx512.rcp28.pd - x86_avx512_rcp28_ps, // llvm.x86.avx512.rcp28.ps - x86_avx512_rcp28_sd, // llvm.x86.avx512.rcp28.sd - x86_avx512_rcp28_ss, // llvm.x86.avx512.rcp28.ss - x86_avx512_rsqrt14_pd_128, // llvm.x86.avx512.rsqrt14.pd.128 - x86_avx512_rsqrt14_pd_256, // llvm.x86.avx512.rsqrt14.pd.256 - x86_avx512_rsqrt14_pd_512, // llvm.x86.avx512.rsqrt14.pd.512 - x86_avx512_rsqrt14_ps_128, // llvm.x86.avx512.rsqrt14.ps.128 - x86_avx512_rsqrt14_ps_256, // llvm.x86.avx512.rsqrt14.ps.256 - x86_avx512_rsqrt14_ps_512, // llvm.x86.avx512.rsqrt14.ps.512 - x86_avx512_rsqrt14_sd, // llvm.x86.avx512.rsqrt14.sd - x86_avx512_rsqrt14_ss, // llvm.x86.avx512.rsqrt14.ss - x86_avx512_rsqrt28_pd, // llvm.x86.avx512.rsqrt28.pd - x86_avx512_rsqrt28_ps, // llvm.x86.avx512.rsqrt28.ps - x86_avx512_rsqrt28_sd, // llvm.x86.avx512.rsqrt28.sd - x86_avx512_rsqrt28_ss, // llvm.x86.avx512.rsqrt28.ss - x86_avx512_scatter_dpd_512, // llvm.x86.avx512.scatter.dpd.512 - x86_avx512_scatter_dpi_512, // llvm.x86.avx512.scatter.dpi.512 - x86_avx512_scatter_dpq_512, // llvm.x86.avx512.scatter.dpq.512 - x86_avx512_scatter_dps_512, // llvm.x86.avx512.scatter.dps.512 - x86_avx512_scatter_qpd_512, // llvm.x86.avx512.scatter.qpd.512 - x86_avx512_scatter_qpi_512, // llvm.x86.avx512.scatter.qpi.512 - x86_avx512_scatter_qpq_512, // llvm.x86.avx512.scatter.qpq.512 - x86_avx512_scatter_qps_512, // llvm.x86.avx512.scatter.qps.512 - x86_avx512_scatterdiv2_df, // llvm.x86.avx512.scatterdiv2.df - x86_avx512_scatterdiv2_di, // llvm.x86.avx512.scatterdiv2.di - x86_avx512_scatterdiv4_df, // llvm.x86.avx512.scatterdiv4.df - x86_avx512_scatterdiv4_di, // llvm.x86.avx512.scatterdiv4.di - x86_avx512_scatterdiv4_sf, // llvm.x86.avx512.scatterdiv4.sf - x86_avx512_scatterdiv4_si, // llvm.x86.avx512.scatterdiv4.si - x86_avx512_scatterdiv8_sf, // llvm.x86.avx512.scatterdiv8.sf - x86_avx512_scatterdiv8_si, // llvm.x86.avx512.scatterdiv8.si - x86_avx512_scatterpf_dpd_512, // llvm.x86.avx512.scatterpf.dpd.512 - x86_avx512_scatterpf_dps_512, // llvm.x86.avx512.scatterpf.dps.512 - x86_avx512_scatterpf_qpd_512, // llvm.x86.avx512.scatterpf.qpd.512 - x86_avx512_scatterpf_qps_512, // llvm.x86.avx512.scatterpf.qps.512 - x86_avx512_scattersiv2_df, // llvm.x86.avx512.scattersiv2.df - x86_avx512_scattersiv2_di, // llvm.x86.avx512.scattersiv2.di - x86_avx512_scattersiv4_df, // llvm.x86.avx512.scattersiv4.df - x86_avx512_scattersiv4_di, // llvm.x86.avx512.scattersiv4.di - x86_avx512_scattersiv4_sf, // llvm.x86.avx512.scattersiv4.sf - x86_avx512_scattersiv4_si, // llvm.x86.avx512.scattersiv4.si - x86_avx512_scattersiv8_sf, // llvm.x86.avx512.scattersiv8.sf - x86_avx512_scattersiv8_si, // llvm.x86.avx512.scattersiv8.si - x86_avx512_sitofp_round, // llvm.x86.avx512.sitofp.round - x86_avx512_sqrt_pd_512, // llvm.x86.avx512.sqrt.pd.512 - x86_avx512_sqrt_ps_512, // llvm.x86.avx512.sqrt.ps.512 - x86_avx512_sub_pd_512, // llvm.x86.avx512.sub.pd.512 - x86_avx512_sub_ps_512, // llvm.x86.avx512.sub.ps.512 - x86_avx512_uitofp_round, // llvm.x86.avx512.uitofp.round - x86_avx512_vcomi_sd, // llvm.x86.avx512.vcomi.sd - x86_avx512_vcomi_ss, // llvm.x86.avx512.vcomi.ss - x86_avx512_vcvtsd2si32, // llvm.x86.avx512.vcvtsd2si32 - x86_avx512_vcvtsd2si64, // llvm.x86.avx512.vcvtsd2si64 - x86_avx512_vcvtsd2usi32, // llvm.x86.avx512.vcvtsd2usi32 - x86_avx512_vcvtsd2usi64, // llvm.x86.avx512.vcvtsd2usi64 - x86_avx512_vcvtss2si32, // llvm.x86.avx512.vcvtss2si32 - x86_avx512_vcvtss2si64, // llvm.x86.avx512.vcvtss2si64 - x86_avx512_vcvtss2usi32, // llvm.x86.avx512.vcvtss2usi32 - x86_avx512_vcvtss2usi64, // llvm.x86.avx512.vcvtss2usi64 - x86_avx512_vfmadd_f32, // llvm.x86.avx512.vfmadd.f32 - x86_avx512_vfmadd_f64, // llvm.x86.avx512.vfmadd.f64 - x86_avx512_vfmadd_pd_512, // llvm.x86.avx512.vfmadd.pd.512 - x86_avx512_vfmadd_ps_512, // llvm.x86.avx512.vfmadd.ps.512 - x86_avx512_vfmaddsub_pd_512, // llvm.x86.avx512.vfmaddsub.pd.512 - x86_avx512_vfmaddsub_ps_512, // llvm.x86.avx512.vfmaddsub.ps.512 - x86_avx512_vp2intersect_d_128, // llvm.x86.avx512.vp2intersect.d.128 - x86_avx512_vp2intersect_d_256, // llvm.x86.avx512.vp2intersect.d.256 - x86_avx512_vp2intersect_d_512, // llvm.x86.avx512.vp2intersect.d.512 - x86_avx512_vp2intersect_q_128, // llvm.x86.avx512.vp2intersect.q.128 - x86_avx512_vp2intersect_q_256, // llvm.x86.avx512.vp2intersect.q.256 - x86_avx512_vp2intersect_q_512, // llvm.x86.avx512.vp2intersect.q.512 - x86_avx512_vpdpbusd_128, // llvm.x86.avx512.vpdpbusd.128 - x86_avx512_vpdpbusd_256, // llvm.x86.avx512.vpdpbusd.256 - x86_avx512_vpdpbusd_512, // llvm.x86.avx512.vpdpbusd.512 - x86_avx512_vpdpbusds_128, // llvm.x86.avx512.vpdpbusds.128 - x86_avx512_vpdpbusds_256, // llvm.x86.avx512.vpdpbusds.256 - x86_avx512_vpdpbusds_512, // llvm.x86.avx512.vpdpbusds.512 - x86_avx512_vpdpwssd_128, // llvm.x86.avx512.vpdpwssd.128 - x86_avx512_vpdpwssd_256, // llvm.x86.avx512.vpdpwssd.256 - x86_avx512_vpdpwssd_512, // llvm.x86.avx512.vpdpwssd.512 - x86_avx512_vpdpwssds_128, // llvm.x86.avx512.vpdpwssds.128 - x86_avx512_vpdpwssds_256, // llvm.x86.avx512.vpdpwssds.256 - x86_avx512_vpdpwssds_512, // llvm.x86.avx512.vpdpwssds.512 - x86_avx512_vpermi2var_d_128, // llvm.x86.avx512.vpermi2var.d.128 - x86_avx512_vpermi2var_d_256, // llvm.x86.avx512.vpermi2var.d.256 - x86_avx512_vpermi2var_d_512, // llvm.x86.avx512.vpermi2var.d.512 - x86_avx512_vpermi2var_hi_128, // llvm.x86.avx512.vpermi2var.hi.128 - x86_avx512_vpermi2var_hi_256, // llvm.x86.avx512.vpermi2var.hi.256 - x86_avx512_vpermi2var_hi_512, // llvm.x86.avx512.vpermi2var.hi.512 - x86_avx512_vpermi2var_pd_128, // llvm.x86.avx512.vpermi2var.pd.128 - x86_avx512_vpermi2var_pd_256, // llvm.x86.avx512.vpermi2var.pd.256 - x86_avx512_vpermi2var_pd_512, // llvm.x86.avx512.vpermi2var.pd.512 - x86_avx512_vpermi2var_ps_128, // llvm.x86.avx512.vpermi2var.ps.128 - x86_avx512_vpermi2var_ps_256, // llvm.x86.avx512.vpermi2var.ps.256 - x86_avx512_vpermi2var_ps_512, // llvm.x86.avx512.vpermi2var.ps.512 - x86_avx512_vpermi2var_q_128, // llvm.x86.avx512.vpermi2var.q.128 - x86_avx512_vpermi2var_q_256, // llvm.x86.avx512.vpermi2var.q.256 - x86_avx512_vpermi2var_q_512, // llvm.x86.avx512.vpermi2var.q.512 - x86_avx512_vpermi2var_qi_128, // llvm.x86.avx512.vpermi2var.qi.128 - x86_avx512_vpermi2var_qi_256, // llvm.x86.avx512.vpermi2var.qi.256 - x86_avx512_vpermi2var_qi_512, // llvm.x86.avx512.vpermi2var.qi.512 - x86_avx512_vpermilvar_pd_512, // llvm.x86.avx512.vpermilvar.pd.512 - x86_avx512_vpermilvar_ps_512, // llvm.x86.avx512.vpermilvar.ps.512 - x86_avx512_vpmadd52h_uq_128, // llvm.x86.avx512.vpmadd52h.uq.128 - x86_avx512_vpmadd52h_uq_256, // llvm.x86.avx512.vpmadd52h.uq.256 - x86_avx512_vpmadd52h_uq_512, // llvm.x86.avx512.vpmadd52h.uq.512 - x86_avx512_vpmadd52l_uq_128, // llvm.x86.avx512.vpmadd52l.uq.128 - x86_avx512_vpmadd52l_uq_256, // llvm.x86.avx512.vpmadd52l.uq.256 - x86_avx512_vpmadd52l_uq_512, // llvm.x86.avx512.vpmadd52l.uq.512 - x86_avx512_vpshufbitqmb_128, // llvm.x86.avx512.vpshufbitqmb.128 - x86_avx512_vpshufbitqmb_256, // llvm.x86.avx512.vpshufbitqmb.256 - x86_avx512_vpshufbitqmb_512, // llvm.x86.avx512.vpshufbitqmb.512 - x86_avx512bf16_cvtne2ps2bf16_128, // llvm.x86.avx512bf16.cvtne2ps2bf16.128 - x86_avx512bf16_cvtne2ps2bf16_256, // llvm.x86.avx512bf16.cvtne2ps2bf16.256 - x86_avx512bf16_cvtne2ps2bf16_512, // llvm.x86.avx512bf16.cvtne2ps2bf16.512 - x86_avx512bf16_cvtneps2bf16_256, // llvm.x86.avx512bf16.cvtneps2bf16.256 - x86_avx512bf16_cvtneps2bf16_512, // llvm.x86.avx512bf16.cvtneps2bf16.512 - x86_avx512bf16_dpbf16ps_128, // llvm.x86.avx512bf16.dpbf16ps.128 - x86_avx512bf16_dpbf16ps_256, // llvm.x86.avx512bf16.dpbf16ps.256 - x86_avx512bf16_dpbf16ps_512, // llvm.x86.avx512bf16.dpbf16ps.512 - x86_avx512bf16_mask_cvtneps2bf16_128, // llvm.x86.avx512bf16.mask.cvtneps2bf16.128 - x86_avx512fp16_add_ph_512, // llvm.x86.avx512fp16.add.ph.512 - x86_avx512fp16_div_ph_512, // llvm.x86.avx512fp16.div.ph.512 - x86_avx512fp16_fpclass_ph_128, // llvm.x86.avx512fp16.fpclass.ph.128 - x86_avx512fp16_fpclass_ph_256, // llvm.x86.avx512fp16.fpclass.ph.256 - x86_avx512fp16_fpclass_ph_512, // llvm.x86.avx512fp16.fpclass.ph.512 - x86_avx512fp16_mask_add_sh_round, // llvm.x86.avx512fp16.mask.add.sh.round - x86_avx512fp16_mask_cmp_ph_128, // llvm.x86.avx512fp16.mask.cmp.ph.128 - x86_avx512fp16_mask_cmp_ph_256, // llvm.x86.avx512fp16.mask.cmp.ph.256 - x86_avx512fp16_mask_cmp_ph_512, // llvm.x86.avx512fp16.mask.cmp.ph.512 - x86_avx512fp16_mask_cmp_sh, // llvm.x86.avx512fp16.mask.cmp.sh - x86_avx512fp16_mask_div_sh_round, // llvm.x86.avx512fp16.mask.div.sh.round - x86_avx512fp16_mask_fpclass_sh, // llvm.x86.avx512fp16.mask.fpclass.sh - x86_avx512fp16_mask_getexp_ph_128, // llvm.x86.avx512fp16.mask.getexp.ph.128 - x86_avx512fp16_mask_getexp_ph_256, // llvm.x86.avx512fp16.mask.getexp.ph.256 - x86_avx512fp16_mask_getexp_ph_512, // llvm.x86.avx512fp16.mask.getexp.ph.512 - x86_avx512fp16_mask_getexp_sh, // llvm.x86.avx512fp16.mask.getexp.sh - x86_avx512fp16_mask_getmant_ph_128, // llvm.x86.avx512fp16.mask.getmant.ph.128 - x86_avx512fp16_mask_getmant_ph_256, // llvm.x86.avx512fp16.mask.getmant.ph.256 - x86_avx512fp16_mask_getmant_ph_512, // llvm.x86.avx512fp16.mask.getmant.ph.512 - x86_avx512fp16_mask_getmant_sh, // llvm.x86.avx512fp16.mask.getmant.sh - x86_avx512fp16_mask_max_sh_round, // llvm.x86.avx512fp16.mask.max.sh.round - x86_avx512fp16_mask_min_sh_round, // llvm.x86.avx512fp16.mask.min.sh.round - x86_avx512fp16_mask_mul_sh_round, // llvm.x86.avx512fp16.mask.mul.sh.round - x86_avx512fp16_mask_rcp_ph_128, // llvm.x86.avx512fp16.mask.rcp.ph.128 - x86_avx512fp16_mask_rcp_ph_256, // llvm.x86.avx512fp16.mask.rcp.ph.256 - x86_avx512fp16_mask_rcp_ph_512, // llvm.x86.avx512fp16.mask.rcp.ph.512 - x86_avx512fp16_mask_rcp_sh, // llvm.x86.avx512fp16.mask.rcp.sh - x86_avx512fp16_mask_reduce_ph_128, // llvm.x86.avx512fp16.mask.reduce.ph.128 - x86_avx512fp16_mask_reduce_ph_256, // llvm.x86.avx512fp16.mask.reduce.ph.256 - x86_avx512fp16_mask_reduce_ph_512, // llvm.x86.avx512fp16.mask.reduce.ph.512 - x86_avx512fp16_mask_reduce_sh, // llvm.x86.avx512fp16.mask.reduce.sh - x86_avx512fp16_mask_rndscale_ph_128, // llvm.x86.avx512fp16.mask.rndscale.ph.128 - x86_avx512fp16_mask_rndscale_ph_256, // llvm.x86.avx512fp16.mask.rndscale.ph.256 - x86_avx512fp16_mask_rndscale_ph_512, // llvm.x86.avx512fp16.mask.rndscale.ph.512 - x86_avx512fp16_mask_rndscale_sh, // llvm.x86.avx512fp16.mask.rndscale.sh - x86_avx512fp16_mask_rsqrt_ph_128, // llvm.x86.avx512fp16.mask.rsqrt.ph.128 - x86_avx512fp16_mask_rsqrt_ph_256, // llvm.x86.avx512fp16.mask.rsqrt.ph.256 - x86_avx512fp16_mask_rsqrt_ph_512, // llvm.x86.avx512fp16.mask.rsqrt.ph.512 - x86_avx512fp16_mask_rsqrt_sh, // llvm.x86.avx512fp16.mask.rsqrt.sh - x86_avx512fp16_mask_scalef_ph_128, // llvm.x86.avx512fp16.mask.scalef.ph.128 - x86_avx512fp16_mask_scalef_ph_256, // llvm.x86.avx512fp16.mask.scalef.ph.256 - x86_avx512fp16_mask_scalef_ph_512, // llvm.x86.avx512fp16.mask.scalef.ph.512 - x86_avx512fp16_mask_scalef_sh, // llvm.x86.avx512fp16.mask.scalef.sh - x86_avx512fp16_mask_sqrt_sh, // llvm.x86.avx512fp16.mask.sqrt.sh - x86_avx512fp16_mask_sub_sh_round, // llvm.x86.avx512fp16.mask.sub.sh.round - x86_avx512fp16_mask_vcvtdq2ph_128, // llvm.x86.avx512fp16.mask.vcvtdq2ph.128 - x86_avx512fp16_mask_vcvtpd2ph_128, // llvm.x86.avx512fp16.mask.vcvtpd2ph.128 - x86_avx512fp16_mask_vcvtpd2ph_256, // llvm.x86.avx512fp16.mask.vcvtpd2ph.256 - x86_avx512fp16_mask_vcvtpd2ph_512, // llvm.x86.avx512fp16.mask.vcvtpd2ph.512 - x86_avx512fp16_mask_vcvtph2dq_128, // llvm.x86.avx512fp16.mask.vcvtph2dq.128 - x86_avx512fp16_mask_vcvtph2dq_256, // llvm.x86.avx512fp16.mask.vcvtph2dq.256 - x86_avx512fp16_mask_vcvtph2dq_512, // llvm.x86.avx512fp16.mask.vcvtph2dq.512 - x86_avx512fp16_mask_vcvtph2pd_128, // llvm.x86.avx512fp16.mask.vcvtph2pd.128 - x86_avx512fp16_mask_vcvtph2pd_256, // llvm.x86.avx512fp16.mask.vcvtph2pd.256 - x86_avx512fp16_mask_vcvtph2pd_512, // llvm.x86.avx512fp16.mask.vcvtph2pd.512 - x86_avx512fp16_mask_vcvtph2psx_128, // llvm.x86.avx512fp16.mask.vcvtph2psx.128 - x86_avx512fp16_mask_vcvtph2psx_256, // llvm.x86.avx512fp16.mask.vcvtph2psx.256 - x86_avx512fp16_mask_vcvtph2psx_512, // llvm.x86.avx512fp16.mask.vcvtph2psx.512 - x86_avx512fp16_mask_vcvtph2qq_128, // llvm.x86.avx512fp16.mask.vcvtph2qq.128 - x86_avx512fp16_mask_vcvtph2qq_256, // llvm.x86.avx512fp16.mask.vcvtph2qq.256 - x86_avx512fp16_mask_vcvtph2qq_512, // llvm.x86.avx512fp16.mask.vcvtph2qq.512 - x86_avx512fp16_mask_vcvtph2udq_128, // llvm.x86.avx512fp16.mask.vcvtph2udq.128 - x86_avx512fp16_mask_vcvtph2udq_256, // llvm.x86.avx512fp16.mask.vcvtph2udq.256 - x86_avx512fp16_mask_vcvtph2udq_512, // llvm.x86.avx512fp16.mask.vcvtph2udq.512 - x86_avx512fp16_mask_vcvtph2uqq_128, // llvm.x86.avx512fp16.mask.vcvtph2uqq.128 - x86_avx512fp16_mask_vcvtph2uqq_256, // llvm.x86.avx512fp16.mask.vcvtph2uqq.256 - x86_avx512fp16_mask_vcvtph2uqq_512, // llvm.x86.avx512fp16.mask.vcvtph2uqq.512 - x86_avx512fp16_mask_vcvtph2uw_128, // llvm.x86.avx512fp16.mask.vcvtph2uw.128 - x86_avx512fp16_mask_vcvtph2uw_256, // llvm.x86.avx512fp16.mask.vcvtph2uw.256 - x86_avx512fp16_mask_vcvtph2uw_512, // llvm.x86.avx512fp16.mask.vcvtph2uw.512 - x86_avx512fp16_mask_vcvtph2w_128, // llvm.x86.avx512fp16.mask.vcvtph2w.128 - x86_avx512fp16_mask_vcvtph2w_256, // llvm.x86.avx512fp16.mask.vcvtph2w.256 - x86_avx512fp16_mask_vcvtph2w_512, // llvm.x86.avx512fp16.mask.vcvtph2w.512 - x86_avx512fp16_mask_vcvtps2phx_128, // llvm.x86.avx512fp16.mask.vcvtps2phx.128 - x86_avx512fp16_mask_vcvtps2phx_256, // llvm.x86.avx512fp16.mask.vcvtps2phx.256 - x86_avx512fp16_mask_vcvtps2phx_512, // llvm.x86.avx512fp16.mask.vcvtps2phx.512 - x86_avx512fp16_mask_vcvtqq2ph_128, // llvm.x86.avx512fp16.mask.vcvtqq2ph.128 - x86_avx512fp16_mask_vcvtqq2ph_256, // llvm.x86.avx512fp16.mask.vcvtqq2ph.256 - x86_avx512fp16_mask_vcvtsd2sh_round, // llvm.x86.avx512fp16.mask.vcvtsd2sh.round - x86_avx512fp16_mask_vcvtsh2sd_round, // llvm.x86.avx512fp16.mask.vcvtsh2sd.round - x86_avx512fp16_mask_vcvtsh2ss_round, // llvm.x86.avx512fp16.mask.vcvtsh2ss.round - x86_avx512fp16_mask_vcvtss2sh_round, // llvm.x86.avx512fp16.mask.vcvtss2sh.round - x86_avx512fp16_mask_vcvttph2dq_128, // llvm.x86.avx512fp16.mask.vcvttph2dq.128 - x86_avx512fp16_mask_vcvttph2dq_256, // llvm.x86.avx512fp16.mask.vcvttph2dq.256 - x86_avx512fp16_mask_vcvttph2dq_512, // llvm.x86.avx512fp16.mask.vcvttph2dq.512 - x86_avx512fp16_mask_vcvttph2qq_128, // llvm.x86.avx512fp16.mask.vcvttph2qq.128 - x86_avx512fp16_mask_vcvttph2qq_256, // llvm.x86.avx512fp16.mask.vcvttph2qq.256 - x86_avx512fp16_mask_vcvttph2qq_512, // llvm.x86.avx512fp16.mask.vcvttph2qq.512 - x86_avx512fp16_mask_vcvttph2udq_128, // llvm.x86.avx512fp16.mask.vcvttph2udq.128 - x86_avx512fp16_mask_vcvttph2udq_256, // llvm.x86.avx512fp16.mask.vcvttph2udq.256 - x86_avx512fp16_mask_vcvttph2udq_512, // llvm.x86.avx512fp16.mask.vcvttph2udq.512 - x86_avx512fp16_mask_vcvttph2uqq_128, // llvm.x86.avx512fp16.mask.vcvttph2uqq.128 - x86_avx512fp16_mask_vcvttph2uqq_256, // llvm.x86.avx512fp16.mask.vcvttph2uqq.256 - x86_avx512fp16_mask_vcvttph2uqq_512, // llvm.x86.avx512fp16.mask.vcvttph2uqq.512 - x86_avx512fp16_mask_vcvttph2uw_128, // llvm.x86.avx512fp16.mask.vcvttph2uw.128 - x86_avx512fp16_mask_vcvttph2uw_256, // llvm.x86.avx512fp16.mask.vcvttph2uw.256 - x86_avx512fp16_mask_vcvttph2uw_512, // llvm.x86.avx512fp16.mask.vcvttph2uw.512 - x86_avx512fp16_mask_vcvttph2w_128, // llvm.x86.avx512fp16.mask.vcvttph2w.128 - x86_avx512fp16_mask_vcvttph2w_256, // llvm.x86.avx512fp16.mask.vcvttph2w.256 - x86_avx512fp16_mask_vcvttph2w_512, // llvm.x86.avx512fp16.mask.vcvttph2w.512 - x86_avx512fp16_mask_vcvtudq2ph_128, // llvm.x86.avx512fp16.mask.vcvtudq2ph.128 - x86_avx512fp16_mask_vcvtuqq2ph_128, // llvm.x86.avx512fp16.mask.vcvtuqq2ph.128 - x86_avx512fp16_mask_vcvtuqq2ph_256, // llvm.x86.avx512fp16.mask.vcvtuqq2ph.256 - x86_avx512fp16_mask_vfcmadd_cph_128, // llvm.x86.avx512fp16.mask.vfcmadd.cph.128 - x86_avx512fp16_mask_vfcmadd_cph_256, // llvm.x86.avx512fp16.mask.vfcmadd.cph.256 - x86_avx512fp16_mask_vfcmadd_cph_512, // llvm.x86.avx512fp16.mask.vfcmadd.cph.512 - x86_avx512fp16_mask_vfcmadd_csh, // llvm.x86.avx512fp16.mask.vfcmadd.csh - x86_avx512fp16_mask_vfcmul_cph_128, // llvm.x86.avx512fp16.mask.vfcmul.cph.128 - x86_avx512fp16_mask_vfcmul_cph_256, // llvm.x86.avx512fp16.mask.vfcmul.cph.256 - x86_avx512fp16_mask_vfcmul_cph_512, // llvm.x86.avx512fp16.mask.vfcmul.cph.512 - x86_avx512fp16_mask_vfcmul_csh, // llvm.x86.avx512fp16.mask.vfcmul.csh - x86_avx512fp16_mask_vfmadd_cph_128, // llvm.x86.avx512fp16.mask.vfmadd.cph.128 - x86_avx512fp16_mask_vfmadd_cph_256, // llvm.x86.avx512fp16.mask.vfmadd.cph.256 - x86_avx512fp16_mask_vfmadd_cph_512, // llvm.x86.avx512fp16.mask.vfmadd.cph.512 - x86_avx512fp16_mask_vfmadd_csh, // llvm.x86.avx512fp16.mask.vfmadd.csh - x86_avx512fp16_mask_vfmul_cph_128, // llvm.x86.avx512fp16.mask.vfmul.cph.128 - x86_avx512fp16_mask_vfmul_cph_256, // llvm.x86.avx512fp16.mask.vfmul.cph.256 - x86_avx512fp16_mask_vfmul_cph_512, // llvm.x86.avx512fp16.mask.vfmul.cph.512 - x86_avx512fp16_mask_vfmul_csh, // llvm.x86.avx512fp16.mask.vfmul.csh - x86_avx512fp16_maskz_vfcmadd_cph_128, // llvm.x86.avx512fp16.maskz.vfcmadd.cph.128 - x86_avx512fp16_maskz_vfcmadd_cph_256, // llvm.x86.avx512fp16.maskz.vfcmadd.cph.256 - x86_avx512fp16_maskz_vfcmadd_cph_512, // llvm.x86.avx512fp16.maskz.vfcmadd.cph.512 - x86_avx512fp16_maskz_vfcmadd_csh, // llvm.x86.avx512fp16.maskz.vfcmadd.csh - x86_avx512fp16_maskz_vfmadd_cph_128, // llvm.x86.avx512fp16.maskz.vfmadd.cph.128 - x86_avx512fp16_maskz_vfmadd_cph_256, // llvm.x86.avx512fp16.maskz.vfmadd.cph.256 - x86_avx512fp16_maskz_vfmadd_cph_512, // llvm.x86.avx512fp16.maskz.vfmadd.cph.512 - x86_avx512fp16_maskz_vfmadd_csh, // llvm.x86.avx512fp16.maskz.vfmadd.csh - x86_avx512fp16_max_ph_128, // llvm.x86.avx512fp16.max.ph.128 - x86_avx512fp16_max_ph_256, // llvm.x86.avx512fp16.max.ph.256 - x86_avx512fp16_max_ph_512, // llvm.x86.avx512fp16.max.ph.512 - x86_avx512fp16_min_ph_128, // llvm.x86.avx512fp16.min.ph.128 - x86_avx512fp16_min_ph_256, // llvm.x86.avx512fp16.min.ph.256 - x86_avx512fp16_min_ph_512, // llvm.x86.avx512fp16.min.ph.512 - x86_avx512fp16_mul_ph_512, // llvm.x86.avx512fp16.mul.ph.512 - x86_avx512fp16_sqrt_ph_512, // llvm.x86.avx512fp16.sqrt.ph.512 - x86_avx512fp16_sub_ph_512, // llvm.x86.avx512fp16.sub.ph.512 - x86_avx512fp16_vcomi_sh, // llvm.x86.avx512fp16.vcomi.sh - x86_avx512fp16_vcvtsh2si32, // llvm.x86.avx512fp16.vcvtsh2si32 - x86_avx512fp16_vcvtsh2si64, // llvm.x86.avx512fp16.vcvtsh2si64 - x86_avx512fp16_vcvtsh2usi32, // llvm.x86.avx512fp16.vcvtsh2usi32 - x86_avx512fp16_vcvtsh2usi64, // llvm.x86.avx512fp16.vcvtsh2usi64 - x86_avx512fp16_vcvtsi2sh, // llvm.x86.avx512fp16.vcvtsi2sh - x86_avx512fp16_vcvtsi642sh, // llvm.x86.avx512fp16.vcvtsi642sh - x86_avx512fp16_vcvttsh2si32, // llvm.x86.avx512fp16.vcvttsh2si32 - x86_avx512fp16_vcvttsh2si64, // llvm.x86.avx512fp16.vcvttsh2si64 - x86_avx512fp16_vcvttsh2usi32, // llvm.x86.avx512fp16.vcvttsh2usi32 - x86_avx512fp16_vcvttsh2usi64, // llvm.x86.avx512fp16.vcvttsh2usi64 - x86_avx512fp16_vcvtusi2sh, // llvm.x86.avx512fp16.vcvtusi2sh - x86_avx512fp16_vcvtusi642sh, // llvm.x86.avx512fp16.vcvtusi642sh - x86_avx512fp16_vfmadd_f16, // llvm.x86.avx512fp16.vfmadd.f16 - x86_avx512fp16_vfmadd_ph_512, // llvm.x86.avx512fp16.vfmadd.ph.512 - x86_avx512fp16_vfmaddsub_ph_128, // llvm.x86.avx512fp16.vfmaddsub.ph.128 - x86_avx512fp16_vfmaddsub_ph_256, // llvm.x86.avx512fp16.vfmaddsub.ph.256 - x86_avx512fp16_vfmaddsub_ph_512, // llvm.x86.avx512fp16.vfmaddsub.ph.512 - x86_bmi_bextr_32, // llvm.x86.bmi.bextr.32 - x86_bmi_bextr_64, // llvm.x86.bmi.bextr.64 - x86_bmi_bzhi_32, // llvm.x86.bmi.bzhi.32 - x86_bmi_bzhi_64, // llvm.x86.bmi.bzhi.64 - x86_bmi_pdep_32, // llvm.x86.bmi.pdep.32 - x86_bmi_pdep_64, // llvm.x86.bmi.pdep.64 - x86_bmi_pext_32, // llvm.x86.bmi.pext.32 - x86_bmi_pext_64, // llvm.x86.bmi.pext.64 - x86_cast_tile_to_vector, // llvm.x86.cast.tile.to.vector - x86_cast_vector_to_tile, // llvm.x86.cast.vector.to.tile - x86_cldemote, // llvm.x86.cldemote - x86_clflushopt, // llvm.x86.clflushopt - x86_clrssbsy, // llvm.x86.clrssbsy - x86_clui, // llvm.x86.clui - x86_clwb, // llvm.x86.clwb - x86_clzero, // llvm.x86.clzero - x86_directstore32, // llvm.x86.directstore32 - x86_directstore64, // llvm.x86.directstore64 - x86_encodekey128, // llvm.x86.encodekey128 - x86_encodekey256, // llvm.x86.encodekey256 - x86_enqcmd, // llvm.x86.enqcmd - x86_enqcmds, // llvm.x86.enqcmds - x86_flags_read_u32, // llvm.x86.flags.read.u32 - x86_flags_read_u64, // llvm.x86.flags.read.u64 - x86_flags_write_u32, // llvm.x86.flags.write.u32 - x86_flags_write_u64, // llvm.x86.flags.write.u64 - x86_fma_vfmaddsub_pd, // llvm.x86.fma.vfmaddsub.pd - x86_fma_vfmaddsub_pd_256, // llvm.x86.fma.vfmaddsub.pd.256 - x86_fma_vfmaddsub_ps, // llvm.x86.fma.vfmaddsub.ps - x86_fma_vfmaddsub_ps_256, // llvm.x86.fma.vfmaddsub.ps.256 - x86_fxrstor, // llvm.x86.fxrstor - x86_fxrstor64, // llvm.x86.fxrstor64 - x86_fxsave, // llvm.x86.fxsave - x86_fxsave64, // llvm.x86.fxsave64 - x86_incsspd, // llvm.x86.incsspd - x86_incsspq, // llvm.x86.incsspq - x86_int, // llvm.x86.int - x86_invpcid, // llvm.x86.invpcid - x86_ldtilecfg, // llvm.x86.ldtilecfg - x86_ldtilecfg_internal, // llvm.x86.ldtilecfg.internal - x86_llwpcb, // llvm.x86.llwpcb - x86_loadiwkey, // llvm.x86.loadiwkey - x86_lwpins32, // llvm.x86.lwpins32 - x86_lwpins64, // llvm.x86.lwpins64 - x86_lwpval32, // llvm.x86.lwpval32 - x86_lwpval64, // llvm.x86.lwpval64 - x86_mmx_emms, // llvm.x86.mmx.emms - x86_mmx_femms, // llvm.x86.mmx.femms - x86_mmx_maskmovq, // llvm.x86.mmx.maskmovq - x86_mmx_movnt_dq, // llvm.x86.mmx.movnt.dq - x86_mmx_packssdw, // llvm.x86.mmx.packssdw - x86_mmx_packsswb, // llvm.x86.mmx.packsswb - x86_mmx_packuswb, // llvm.x86.mmx.packuswb - x86_mmx_padd_b, // llvm.x86.mmx.padd.b - x86_mmx_padd_d, // llvm.x86.mmx.padd.d - x86_mmx_padd_q, // llvm.x86.mmx.padd.q - x86_mmx_padd_w, // llvm.x86.mmx.padd.w - x86_mmx_padds_b, // llvm.x86.mmx.padds.b - x86_mmx_padds_w, // llvm.x86.mmx.padds.w - x86_mmx_paddus_b, // llvm.x86.mmx.paddus.b - x86_mmx_paddus_w, // llvm.x86.mmx.paddus.w - x86_mmx_palignr_b, // llvm.x86.mmx.palignr.b - x86_mmx_pand, // llvm.x86.mmx.pand - x86_mmx_pandn, // llvm.x86.mmx.pandn - x86_mmx_pavg_b, // llvm.x86.mmx.pavg.b - x86_mmx_pavg_w, // llvm.x86.mmx.pavg.w - x86_mmx_pcmpeq_b, // llvm.x86.mmx.pcmpeq.b - x86_mmx_pcmpeq_d, // llvm.x86.mmx.pcmpeq.d - x86_mmx_pcmpeq_w, // llvm.x86.mmx.pcmpeq.w - x86_mmx_pcmpgt_b, // llvm.x86.mmx.pcmpgt.b - x86_mmx_pcmpgt_d, // llvm.x86.mmx.pcmpgt.d - x86_mmx_pcmpgt_w, // llvm.x86.mmx.pcmpgt.w - x86_mmx_pextr_w, // llvm.x86.mmx.pextr.w - x86_mmx_pinsr_w, // llvm.x86.mmx.pinsr.w - x86_mmx_pmadd_wd, // llvm.x86.mmx.pmadd.wd - x86_mmx_pmaxs_w, // llvm.x86.mmx.pmaxs.w - x86_mmx_pmaxu_b, // llvm.x86.mmx.pmaxu.b - x86_mmx_pmins_w, // llvm.x86.mmx.pmins.w - x86_mmx_pminu_b, // llvm.x86.mmx.pminu.b - x86_mmx_pmovmskb, // llvm.x86.mmx.pmovmskb - x86_mmx_pmulh_w, // llvm.x86.mmx.pmulh.w - x86_mmx_pmulhu_w, // llvm.x86.mmx.pmulhu.w - x86_mmx_pmull_w, // llvm.x86.mmx.pmull.w - x86_mmx_pmulu_dq, // llvm.x86.mmx.pmulu.dq - x86_mmx_por, // llvm.x86.mmx.por - x86_mmx_psad_bw, // llvm.x86.mmx.psad.bw - x86_mmx_psll_d, // llvm.x86.mmx.psll.d - x86_mmx_psll_q, // llvm.x86.mmx.psll.q - x86_mmx_psll_w, // llvm.x86.mmx.psll.w - x86_mmx_pslli_d, // llvm.x86.mmx.pslli.d - x86_mmx_pslli_q, // llvm.x86.mmx.pslli.q - x86_mmx_pslli_w, // llvm.x86.mmx.pslli.w - x86_mmx_psra_d, // llvm.x86.mmx.psra.d - x86_mmx_psra_w, // llvm.x86.mmx.psra.w - x86_mmx_psrai_d, // llvm.x86.mmx.psrai.d - x86_mmx_psrai_w, // llvm.x86.mmx.psrai.w - x86_mmx_psrl_d, // llvm.x86.mmx.psrl.d - x86_mmx_psrl_q, // llvm.x86.mmx.psrl.q - x86_mmx_psrl_w, // llvm.x86.mmx.psrl.w - x86_mmx_psrli_d, // llvm.x86.mmx.psrli.d - x86_mmx_psrli_q, // llvm.x86.mmx.psrli.q - x86_mmx_psrli_w, // llvm.x86.mmx.psrli.w - x86_mmx_psub_b, // llvm.x86.mmx.psub.b - x86_mmx_psub_d, // llvm.x86.mmx.psub.d - x86_mmx_psub_q, // llvm.x86.mmx.psub.q - x86_mmx_psub_w, // llvm.x86.mmx.psub.w - x86_mmx_psubs_b, // llvm.x86.mmx.psubs.b - x86_mmx_psubs_w, // llvm.x86.mmx.psubs.w - x86_mmx_psubus_b, // llvm.x86.mmx.psubus.b - x86_mmx_psubus_w, // llvm.x86.mmx.psubus.w - x86_mmx_punpckhbw, // llvm.x86.mmx.punpckhbw - x86_mmx_punpckhdq, // llvm.x86.mmx.punpckhdq - x86_mmx_punpckhwd, // llvm.x86.mmx.punpckhwd - x86_mmx_punpcklbw, // llvm.x86.mmx.punpcklbw - x86_mmx_punpckldq, // llvm.x86.mmx.punpckldq - x86_mmx_punpcklwd, // llvm.x86.mmx.punpcklwd - x86_mmx_pxor, // llvm.x86.mmx.pxor - x86_monitorx, // llvm.x86.monitorx - x86_movdir64b, // llvm.x86.movdir64b - x86_mwaitx, // llvm.x86.mwaitx - x86_pclmulqdq, // llvm.x86.pclmulqdq - x86_pclmulqdq_256, // llvm.x86.pclmulqdq.256 - x86_pclmulqdq_512, // llvm.x86.pclmulqdq.512 - x86_ptwrite32, // llvm.x86.ptwrite32 - x86_ptwrite64, // llvm.x86.ptwrite64 - x86_rdfsbase_32, // llvm.x86.rdfsbase.32 - x86_rdfsbase_64, // llvm.x86.rdfsbase.64 - x86_rdgsbase_32, // llvm.x86.rdgsbase.32 - x86_rdgsbase_64, // llvm.x86.rdgsbase.64 - x86_rdpid, // llvm.x86.rdpid - x86_rdpkru, // llvm.x86.rdpkru - x86_rdpmc, // llvm.x86.rdpmc - x86_rdrand_16, // llvm.x86.rdrand.16 - x86_rdrand_32, // llvm.x86.rdrand.32 - x86_rdrand_64, // llvm.x86.rdrand.64 - x86_rdseed_16, // llvm.x86.rdseed.16 - x86_rdseed_32, // llvm.x86.rdseed.32 - x86_rdseed_64, // llvm.x86.rdseed.64 - x86_rdsspd, // llvm.x86.rdsspd - x86_rdsspq, // llvm.x86.rdsspq - x86_rdtsc, // llvm.x86.rdtsc - x86_rdtscp, // llvm.x86.rdtscp - x86_rstorssp, // llvm.x86.rstorssp - x86_saveprevssp, // llvm.x86.saveprevssp - x86_seh_ehguard, // llvm.x86.seh.ehguard - x86_seh_ehregnode, // llvm.x86.seh.ehregnode - x86_seh_lsda, // llvm.x86.seh.lsda - x86_senduipi, // llvm.x86.senduipi - x86_serialize, // llvm.x86.serialize - x86_setssbsy, // llvm.x86.setssbsy - x86_sha1msg1, // llvm.x86.sha1msg1 - x86_sha1msg2, // llvm.x86.sha1msg2 - x86_sha1nexte, // llvm.x86.sha1nexte - x86_sha1rnds4, // llvm.x86.sha1rnds4 - x86_sha256msg1, // llvm.x86.sha256msg1 - x86_sha256msg2, // llvm.x86.sha256msg2 - x86_sha256rnds2, // llvm.x86.sha256rnds2 - x86_slwpcb, // llvm.x86.slwpcb - x86_sse_cmp_ps, // llvm.x86.sse.cmp.ps - x86_sse_cmp_ss, // llvm.x86.sse.cmp.ss - x86_sse_comieq_ss, // llvm.x86.sse.comieq.ss - x86_sse_comige_ss, // llvm.x86.sse.comige.ss - x86_sse_comigt_ss, // llvm.x86.sse.comigt.ss - x86_sse_comile_ss, // llvm.x86.sse.comile.ss - x86_sse_comilt_ss, // llvm.x86.sse.comilt.ss - x86_sse_comineq_ss, // llvm.x86.sse.comineq.ss - x86_sse_cvtpd2pi, // llvm.x86.sse.cvtpd2pi - x86_sse_cvtpi2pd, // llvm.x86.sse.cvtpi2pd - x86_sse_cvtpi2ps, // llvm.x86.sse.cvtpi2ps - x86_sse_cvtps2pi, // llvm.x86.sse.cvtps2pi - x86_sse_cvtss2si, // llvm.x86.sse.cvtss2si - x86_sse_cvtss2si64, // llvm.x86.sse.cvtss2si64 - x86_sse_cvttpd2pi, // llvm.x86.sse.cvttpd2pi - x86_sse_cvttps2pi, // llvm.x86.sse.cvttps2pi - x86_sse_cvttss2si, // llvm.x86.sse.cvttss2si - x86_sse_cvttss2si64, // llvm.x86.sse.cvttss2si64 - x86_sse_ldmxcsr, // llvm.x86.sse.ldmxcsr - x86_sse_max_ps, // llvm.x86.sse.max.ps - x86_sse_max_ss, // llvm.x86.sse.max.ss - x86_sse_min_ps, // llvm.x86.sse.min.ps - x86_sse_min_ss, // llvm.x86.sse.min.ss - x86_sse_movmsk_ps, // llvm.x86.sse.movmsk.ps - x86_sse_pshuf_w, // llvm.x86.sse.pshuf.w - x86_sse_rcp_ps, // llvm.x86.sse.rcp.ps - x86_sse_rcp_ss, // llvm.x86.sse.rcp.ss - x86_sse_rsqrt_ps, // llvm.x86.sse.rsqrt.ps - x86_sse_rsqrt_ss, // llvm.x86.sse.rsqrt.ss - x86_sse_sfence, // llvm.x86.sse.sfence - x86_sse_stmxcsr, // llvm.x86.sse.stmxcsr - x86_sse_ucomieq_ss, // llvm.x86.sse.ucomieq.ss - x86_sse_ucomige_ss, // llvm.x86.sse.ucomige.ss - x86_sse_ucomigt_ss, // llvm.x86.sse.ucomigt.ss - x86_sse_ucomile_ss, // llvm.x86.sse.ucomile.ss - x86_sse_ucomilt_ss, // llvm.x86.sse.ucomilt.ss - x86_sse_ucomineq_ss, // llvm.x86.sse.ucomineq.ss - x86_sse2_clflush, // llvm.x86.sse2.clflush - x86_sse2_cmp_pd, // llvm.x86.sse2.cmp.pd - x86_sse2_cmp_sd, // llvm.x86.sse2.cmp.sd - x86_sse2_comieq_sd, // llvm.x86.sse2.comieq.sd - x86_sse2_comige_sd, // llvm.x86.sse2.comige.sd - x86_sse2_comigt_sd, // llvm.x86.sse2.comigt.sd - x86_sse2_comile_sd, // llvm.x86.sse2.comile.sd - x86_sse2_comilt_sd, // llvm.x86.sse2.comilt.sd - x86_sse2_comineq_sd, // llvm.x86.sse2.comineq.sd - x86_sse2_cvtpd2dq, // llvm.x86.sse2.cvtpd2dq - x86_sse2_cvtpd2ps, // llvm.x86.sse2.cvtpd2ps - x86_sse2_cvtps2dq, // llvm.x86.sse2.cvtps2dq - x86_sse2_cvtsd2si, // llvm.x86.sse2.cvtsd2si - x86_sse2_cvtsd2si64, // llvm.x86.sse2.cvtsd2si64 - x86_sse2_cvtsd2ss, // llvm.x86.sse2.cvtsd2ss - x86_sse2_cvttpd2dq, // llvm.x86.sse2.cvttpd2dq - x86_sse2_cvttps2dq, // llvm.x86.sse2.cvttps2dq - x86_sse2_cvttsd2si, // llvm.x86.sse2.cvttsd2si - x86_sse2_cvttsd2si64, // llvm.x86.sse2.cvttsd2si64 - x86_sse2_lfence, // llvm.x86.sse2.lfence - x86_sse2_maskmov_dqu, // llvm.x86.sse2.maskmov.dqu - x86_sse2_max_pd, // llvm.x86.sse2.max.pd - x86_sse2_max_sd, // llvm.x86.sse2.max.sd - x86_sse2_mfence, // llvm.x86.sse2.mfence - x86_sse2_min_pd, // llvm.x86.sse2.min.pd - x86_sse2_min_sd, // llvm.x86.sse2.min.sd - x86_sse2_movmsk_pd, // llvm.x86.sse2.movmsk.pd - x86_sse2_packssdw_128, // llvm.x86.sse2.packssdw.128 - x86_sse2_packsswb_128, // llvm.x86.sse2.packsswb.128 - x86_sse2_packuswb_128, // llvm.x86.sse2.packuswb.128 - x86_sse2_pause, // llvm.x86.sse2.pause - x86_sse2_pavg_b, // llvm.x86.sse2.pavg.b - x86_sse2_pavg_w, // llvm.x86.sse2.pavg.w - x86_sse2_pmadd_wd, // llvm.x86.sse2.pmadd.wd - x86_sse2_pmovmskb_128, // llvm.x86.sse2.pmovmskb.128 - x86_sse2_pmulh_w, // llvm.x86.sse2.pmulh.w - x86_sse2_pmulhu_w, // llvm.x86.sse2.pmulhu.w - x86_sse2_psad_bw, // llvm.x86.sse2.psad.bw - x86_sse2_psll_d, // llvm.x86.sse2.psll.d - x86_sse2_psll_q, // llvm.x86.sse2.psll.q - x86_sse2_psll_w, // llvm.x86.sse2.psll.w - x86_sse2_pslli_d, // llvm.x86.sse2.pslli.d - x86_sse2_pslli_q, // llvm.x86.sse2.pslli.q - x86_sse2_pslli_w, // llvm.x86.sse2.pslli.w - x86_sse2_psra_d, // llvm.x86.sse2.psra.d - x86_sse2_psra_w, // llvm.x86.sse2.psra.w - x86_sse2_psrai_d, // llvm.x86.sse2.psrai.d - x86_sse2_psrai_w, // llvm.x86.sse2.psrai.w - x86_sse2_psrl_d, // llvm.x86.sse2.psrl.d - x86_sse2_psrl_q, // llvm.x86.sse2.psrl.q - x86_sse2_psrl_w, // llvm.x86.sse2.psrl.w - x86_sse2_psrli_d, // llvm.x86.sse2.psrli.d - x86_sse2_psrli_q, // llvm.x86.sse2.psrli.q - x86_sse2_psrli_w, // llvm.x86.sse2.psrli.w - x86_sse2_ucomieq_sd, // llvm.x86.sse2.ucomieq.sd - x86_sse2_ucomige_sd, // llvm.x86.sse2.ucomige.sd - x86_sse2_ucomigt_sd, // llvm.x86.sse2.ucomigt.sd - x86_sse2_ucomile_sd, // llvm.x86.sse2.ucomile.sd - x86_sse2_ucomilt_sd, // llvm.x86.sse2.ucomilt.sd - x86_sse2_ucomineq_sd, // llvm.x86.sse2.ucomineq.sd - x86_sse3_addsub_pd, // llvm.x86.sse3.addsub.pd - x86_sse3_addsub_ps, // llvm.x86.sse3.addsub.ps - x86_sse3_hadd_pd, // llvm.x86.sse3.hadd.pd - x86_sse3_hadd_ps, // llvm.x86.sse3.hadd.ps - x86_sse3_hsub_pd, // llvm.x86.sse3.hsub.pd - x86_sse3_hsub_ps, // llvm.x86.sse3.hsub.ps - x86_sse3_ldu_dq, // llvm.x86.sse3.ldu.dq - x86_sse3_monitor, // llvm.x86.sse3.monitor - x86_sse3_mwait, // llvm.x86.sse3.mwait - x86_sse41_blendvpd, // llvm.x86.sse41.blendvpd - x86_sse41_blendvps, // llvm.x86.sse41.blendvps - x86_sse41_dppd, // llvm.x86.sse41.dppd - x86_sse41_dpps, // llvm.x86.sse41.dpps - x86_sse41_insertps, // llvm.x86.sse41.insertps - x86_sse41_mpsadbw, // llvm.x86.sse41.mpsadbw - x86_sse41_packusdw, // llvm.x86.sse41.packusdw - x86_sse41_pblendvb, // llvm.x86.sse41.pblendvb - x86_sse41_phminposuw, // llvm.x86.sse41.phminposuw - x86_sse41_ptestc, // llvm.x86.sse41.ptestc - x86_sse41_ptestnzc, // llvm.x86.sse41.ptestnzc - x86_sse41_ptestz, // llvm.x86.sse41.ptestz - x86_sse41_round_pd, // llvm.x86.sse41.round.pd - x86_sse41_round_ps, // llvm.x86.sse41.round.ps - x86_sse41_round_sd, // llvm.x86.sse41.round.sd - x86_sse41_round_ss, // llvm.x86.sse41.round.ss - x86_sse42_crc32_32_16, // llvm.x86.sse42.crc32.32.16 - x86_sse42_crc32_32_32, // llvm.x86.sse42.crc32.32.32 - x86_sse42_crc32_32_8, // llvm.x86.sse42.crc32.32.8 - x86_sse42_crc32_64_64, // llvm.x86.sse42.crc32.64.64 - x86_sse42_pcmpestri128, // llvm.x86.sse42.pcmpestri128 - x86_sse42_pcmpestria128, // llvm.x86.sse42.pcmpestria128 - x86_sse42_pcmpestric128, // llvm.x86.sse42.pcmpestric128 - x86_sse42_pcmpestrio128, // llvm.x86.sse42.pcmpestrio128 - x86_sse42_pcmpestris128, // llvm.x86.sse42.pcmpestris128 - x86_sse42_pcmpestriz128, // llvm.x86.sse42.pcmpestriz128 - x86_sse42_pcmpestrm128, // llvm.x86.sse42.pcmpestrm128 - x86_sse42_pcmpistri128, // llvm.x86.sse42.pcmpistri128 - x86_sse42_pcmpistria128, // llvm.x86.sse42.pcmpistria128 - x86_sse42_pcmpistric128, // llvm.x86.sse42.pcmpistric128 - x86_sse42_pcmpistrio128, // llvm.x86.sse42.pcmpistrio128 - x86_sse42_pcmpistris128, // llvm.x86.sse42.pcmpistris128 - x86_sse42_pcmpistriz128, // llvm.x86.sse42.pcmpistriz128 - x86_sse42_pcmpistrm128, // llvm.x86.sse42.pcmpistrm128 - x86_sse4a_extrq, // llvm.x86.sse4a.extrq - x86_sse4a_extrqi, // llvm.x86.sse4a.extrqi - x86_sse4a_insertq, // llvm.x86.sse4a.insertq - x86_sse4a_insertqi, // llvm.x86.sse4a.insertqi - x86_ssse3_pabs_b, // llvm.x86.ssse3.pabs.b - x86_ssse3_pabs_d, // llvm.x86.ssse3.pabs.d - x86_ssse3_pabs_w, // llvm.x86.ssse3.pabs.w - x86_ssse3_phadd_d, // llvm.x86.ssse3.phadd.d - x86_ssse3_phadd_d_128, // llvm.x86.ssse3.phadd.d.128 - x86_ssse3_phadd_sw, // llvm.x86.ssse3.phadd.sw - x86_ssse3_phadd_sw_128, // llvm.x86.ssse3.phadd.sw.128 - x86_ssse3_phadd_w, // llvm.x86.ssse3.phadd.w - x86_ssse3_phadd_w_128, // llvm.x86.ssse3.phadd.w.128 - x86_ssse3_phsub_d, // llvm.x86.ssse3.phsub.d - x86_ssse3_phsub_d_128, // llvm.x86.ssse3.phsub.d.128 - x86_ssse3_phsub_sw, // llvm.x86.ssse3.phsub.sw - x86_ssse3_phsub_sw_128, // llvm.x86.ssse3.phsub.sw.128 - x86_ssse3_phsub_w, // llvm.x86.ssse3.phsub.w - x86_ssse3_phsub_w_128, // llvm.x86.ssse3.phsub.w.128 - x86_ssse3_pmadd_ub_sw, // llvm.x86.ssse3.pmadd.ub.sw - x86_ssse3_pmadd_ub_sw_128, // llvm.x86.ssse3.pmadd.ub.sw.128 - x86_ssse3_pmul_hr_sw, // llvm.x86.ssse3.pmul.hr.sw - x86_ssse3_pmul_hr_sw_128, // llvm.x86.ssse3.pmul.hr.sw.128 - x86_ssse3_pshuf_b, // llvm.x86.ssse3.pshuf.b - x86_ssse3_pshuf_b_128, // llvm.x86.ssse3.pshuf.b.128 - x86_ssse3_psign_b, // llvm.x86.ssse3.psign.b - x86_ssse3_psign_b_128, // llvm.x86.ssse3.psign.b.128 - x86_ssse3_psign_d, // llvm.x86.ssse3.psign.d - x86_ssse3_psign_d_128, // llvm.x86.ssse3.psign.d.128 - x86_ssse3_psign_w, // llvm.x86.ssse3.psign.w - x86_ssse3_psign_w_128, // llvm.x86.ssse3.psign.w.128 - x86_sttilecfg, // llvm.x86.sttilecfg - x86_stui, // llvm.x86.stui - x86_subborrow_32, // llvm.x86.subborrow.32 - x86_subborrow_64, // llvm.x86.subborrow.64 - x86_tbm_bextri_u32, // llvm.x86.tbm.bextri.u32 - x86_tbm_bextri_u64, // llvm.x86.tbm.bextri.u64 - x86_tdpbf16ps, // llvm.x86.tdpbf16ps - x86_tdpbf16ps_internal, // llvm.x86.tdpbf16ps.internal - x86_tdpbssd, // llvm.x86.tdpbssd - x86_tdpbssd_internal, // llvm.x86.tdpbssd.internal - x86_tdpbsud, // llvm.x86.tdpbsud - x86_tdpbsud_internal, // llvm.x86.tdpbsud.internal - x86_tdpbusd, // llvm.x86.tdpbusd - x86_tdpbusd_internal, // llvm.x86.tdpbusd.internal - x86_tdpbuud, // llvm.x86.tdpbuud - x86_tdpbuud_internal, // llvm.x86.tdpbuud.internal - x86_testui, // llvm.x86.testui - x86_tileloadd64, // llvm.x86.tileloadd64 - x86_tileloadd64_internal, // llvm.x86.tileloadd64.internal - x86_tileloaddt164, // llvm.x86.tileloaddt164 - x86_tileloaddt164_internal, // llvm.x86.tileloaddt164.internal - x86_tilerelease, // llvm.x86.tilerelease - x86_tilestored64, // llvm.x86.tilestored64 - x86_tilestored64_internal, // llvm.x86.tilestored64.internal - x86_tilezero, // llvm.x86.tilezero - x86_tilezero_internal, // llvm.x86.tilezero.internal - x86_tpause, // llvm.x86.tpause - x86_umonitor, // llvm.x86.umonitor - x86_umwait, // llvm.x86.umwait - x86_vcvtps2ph_128, // llvm.x86.vcvtps2ph.128 - x86_vcvtps2ph_256, // llvm.x86.vcvtps2ph.256 - x86_vgf2p8affineinvqb_128, // llvm.x86.vgf2p8affineinvqb.128 - x86_vgf2p8affineinvqb_256, // llvm.x86.vgf2p8affineinvqb.256 - x86_vgf2p8affineinvqb_512, // llvm.x86.vgf2p8affineinvqb.512 - x86_vgf2p8affineqb_128, // llvm.x86.vgf2p8affineqb.128 - x86_vgf2p8affineqb_256, // llvm.x86.vgf2p8affineqb.256 - x86_vgf2p8affineqb_512, // llvm.x86.vgf2p8affineqb.512 - x86_vgf2p8mulb_128, // llvm.x86.vgf2p8mulb.128 - x86_vgf2p8mulb_256, // llvm.x86.vgf2p8mulb.256 - x86_vgf2p8mulb_512, // llvm.x86.vgf2p8mulb.512 - x86_wbinvd, // llvm.x86.wbinvd - x86_wbnoinvd, // llvm.x86.wbnoinvd - x86_wrfsbase_32, // llvm.x86.wrfsbase.32 - x86_wrfsbase_64, // llvm.x86.wrfsbase.64 - x86_wrgsbase_32, // llvm.x86.wrgsbase.32 - x86_wrgsbase_64, // llvm.x86.wrgsbase.64 - x86_wrpkru, // llvm.x86.wrpkru - x86_wrssd, // llvm.x86.wrssd - x86_wrssq, // llvm.x86.wrssq - x86_wrussd, // llvm.x86.wrussd - x86_wrussq, // llvm.x86.wrussq - x86_xabort, // llvm.x86.xabort - x86_xbegin, // llvm.x86.xbegin - x86_xend, // llvm.x86.xend - x86_xgetbv, // llvm.x86.xgetbv - x86_xop_vfrcz_pd, // llvm.x86.xop.vfrcz.pd - x86_xop_vfrcz_pd_256, // llvm.x86.xop.vfrcz.pd.256 - x86_xop_vfrcz_ps, // llvm.x86.xop.vfrcz.ps - x86_xop_vfrcz_ps_256, // llvm.x86.xop.vfrcz.ps.256 - x86_xop_vfrcz_sd, // llvm.x86.xop.vfrcz.sd - x86_xop_vfrcz_ss, // llvm.x86.xop.vfrcz.ss - x86_xop_vpermil2pd, // llvm.x86.xop.vpermil2pd - x86_xop_vpermil2pd_256, // llvm.x86.xop.vpermil2pd.256 - x86_xop_vpermil2ps, // llvm.x86.xop.vpermil2ps - x86_xop_vpermil2ps_256, // llvm.x86.xop.vpermil2ps.256 - x86_xop_vphaddbd, // llvm.x86.xop.vphaddbd - x86_xop_vphaddbq, // llvm.x86.xop.vphaddbq - x86_xop_vphaddbw, // llvm.x86.xop.vphaddbw - x86_xop_vphadddq, // llvm.x86.xop.vphadddq - x86_xop_vphaddubd, // llvm.x86.xop.vphaddubd - x86_xop_vphaddubq, // llvm.x86.xop.vphaddubq - x86_xop_vphaddubw, // llvm.x86.xop.vphaddubw - x86_xop_vphaddudq, // llvm.x86.xop.vphaddudq - x86_xop_vphadduwd, // llvm.x86.xop.vphadduwd - x86_xop_vphadduwq, // llvm.x86.xop.vphadduwq - x86_xop_vphaddwd, // llvm.x86.xop.vphaddwd - x86_xop_vphaddwq, // llvm.x86.xop.vphaddwq - x86_xop_vphsubbw, // llvm.x86.xop.vphsubbw - x86_xop_vphsubdq, // llvm.x86.xop.vphsubdq - x86_xop_vphsubwd, // llvm.x86.xop.vphsubwd - x86_xop_vpmacsdd, // llvm.x86.xop.vpmacsdd - x86_xop_vpmacsdqh, // llvm.x86.xop.vpmacsdqh - x86_xop_vpmacsdql, // llvm.x86.xop.vpmacsdql - x86_xop_vpmacssdd, // llvm.x86.xop.vpmacssdd - x86_xop_vpmacssdqh, // llvm.x86.xop.vpmacssdqh - x86_xop_vpmacssdql, // llvm.x86.xop.vpmacssdql - x86_xop_vpmacsswd, // llvm.x86.xop.vpmacsswd - x86_xop_vpmacssww, // llvm.x86.xop.vpmacssww - x86_xop_vpmacswd, // llvm.x86.xop.vpmacswd - x86_xop_vpmacsww, // llvm.x86.xop.vpmacsww - x86_xop_vpmadcsswd, // llvm.x86.xop.vpmadcsswd - x86_xop_vpmadcswd, // llvm.x86.xop.vpmadcswd - x86_xop_vpperm, // llvm.x86.xop.vpperm - x86_xop_vpshab, // llvm.x86.xop.vpshab - x86_xop_vpshad, // llvm.x86.xop.vpshad - x86_xop_vpshaq, // llvm.x86.xop.vpshaq - x86_xop_vpshaw, // llvm.x86.xop.vpshaw - x86_xop_vpshlb, // llvm.x86.xop.vpshlb - x86_xop_vpshld, // llvm.x86.xop.vpshld - x86_xop_vpshlq, // llvm.x86.xop.vpshlq - x86_xop_vpshlw, // llvm.x86.xop.vpshlw - x86_xresldtrk, // llvm.x86.xresldtrk - x86_xrstor, // llvm.x86.xrstor - x86_xrstor64, // llvm.x86.xrstor64 - x86_xrstors, // llvm.x86.xrstors - x86_xrstors64, // llvm.x86.xrstors64 - x86_xsave, // llvm.x86.xsave - x86_xsave64, // llvm.x86.xsave64 - x86_xsavec, // llvm.x86.xsavec - x86_xsavec64, // llvm.x86.xsavec64 - x86_xsaveopt, // llvm.x86.xsaveopt - x86_xsaveopt64, // llvm.x86.xsaveopt64 - x86_xsaves, // llvm.x86.xsaves - x86_xsaves64, // llvm.x86.xsaves64 - x86_xsetbv, // llvm.x86.xsetbv - x86_xsusldtrk, // llvm.x86.xsusldtrk - x86_xtest, // llvm.x86.xtest -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.td deleted file mode 100644 index 8de737a1c7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsX86.td +++ /dev/null @@ -1,5868 +0,0 @@ -//===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the X86-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Interrupt traps -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_int : Intrinsic<[], [llvm_i8_ty], [ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// SEH intrinsics for Windows -let TargetPrefix = "x86" in { - def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; - - // Marks the EH registration node created in LLVM IR prior to code generation. - def int_x86_seh_ehregnode : Intrinsic<[], [llvm_ptr_ty], []>; - - // Marks the EH guard slot node created in LLVM IR prior to code generation. - def int_x86_seh_ehguard : Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// FLAGS. -let TargetPrefix = "x86" in { - def int_x86_flags_read_u32 : GCCBuiltin<"__builtin_ia32_readeflags_u32">, - Intrinsic<[llvm_i32_ty], [], []>; - def int_x86_flags_read_u64 : GCCBuiltin<"__builtin_ia32_readeflags_u64">, - Intrinsic<[llvm_i64_ty], [], []>; - def int_x86_flags_write_u32 : GCCBuiltin<"__builtin_ia32_writeeflags_u32">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_x86_flags_write_u64 : GCCBuiltin<"__builtin_ia32_writeeflags_u64">, - Intrinsic<[], [llvm_i64_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Read Time Stamp Counter. -let TargetPrefix = "x86" in { - def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">, - Intrinsic<[llvm_i64_ty], [], []>; - def int_x86_rdtscp : - Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; -} - -// Read Performance-Monitoring Counter. -let TargetPrefix = "x86" in { - def int_x86_rdpmc : GCCBuiltin<"__builtin_ia32_rdpmc">, - Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; -} - -// Read processor ID. -let TargetPrefix = "x86" in { - def int_x86_rdpid : GCCBuiltin<"__builtin_ia32_rdpid">, - Intrinsic<[llvm_i32_ty], [], []>; -} - -//===----------------------------------------------------------------------===// -// CET SS -let TargetPrefix = "x86" in { - def int_x86_incsspd : GCCBuiltin<"__builtin_ia32_incsspd">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_x86_incsspq : GCCBuiltin<"__builtin_ia32_incsspq">, - Intrinsic<[], [llvm_i64_ty], []>; - def int_x86_rdsspd : GCCBuiltin<"__builtin_ia32_rdsspd">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; - def int_x86_rdsspq : GCCBuiltin<"__builtin_ia32_rdsspq">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty], []>; - def int_x86_saveprevssp : GCCBuiltin<"__builtin_ia32_saveprevssp">, - Intrinsic<[], [], []>; - def int_x86_rstorssp : GCCBuiltin<"__builtin_ia32_rstorssp">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_wrssd : GCCBuiltin<"__builtin_ia32_wrssd">, - Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>; - def int_x86_wrssq : GCCBuiltin<"__builtin_ia32_wrssq">, - Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty], []>; - def int_x86_wrussd : GCCBuiltin<"__builtin_ia32_wrussd">, - Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>; - def int_x86_wrussq : GCCBuiltin<"__builtin_ia32_wrussq">, - Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty], []>; - def int_x86_setssbsy : GCCBuiltin<"__builtin_ia32_setssbsy">, - Intrinsic<[], [], []>; - def int_x86_clrssbsy : GCCBuiltin<"__builtin_ia32_clrssbsy">, - Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// 3DNow! - -let TargetPrefix = "x86" in { - def int_x86_3dnow_pavgusb : GCCBuiltin<"__builtin_ia32_pavgusb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pf2id : GCCBuiltin<"__builtin_ia32_pf2id">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnow_pfacc : GCCBuiltin<"__builtin_ia32_pfacc">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfadd : GCCBuiltin<"__builtin_ia32_pfadd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfcmpeq : GCCBuiltin<"__builtin_ia32_pfcmpeq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfcmpge : GCCBuiltin<"__builtin_ia32_pfcmpge">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfcmpgt : GCCBuiltin<"__builtin_ia32_pfcmpgt">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfmax : GCCBuiltin<"__builtin_ia32_pfmax">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfmin : GCCBuiltin<"__builtin_ia32_pfmin">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfmul : GCCBuiltin<"__builtin_ia32_pfmul">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfrcp : GCCBuiltin<"__builtin_ia32_pfrcp">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnow_pfrcpit1 : GCCBuiltin<"__builtin_ia32_pfrcpit1">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfrcpit2 : GCCBuiltin<"__builtin_ia32_pfrcpit2">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfrsqrt : GCCBuiltin<"__builtin_ia32_pfrsqrt">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnow_pfrsqit1 : GCCBuiltin<"__builtin_ia32_pfrsqit1">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfsub : GCCBuiltin<"__builtin_ia32_pfsub">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pfsubr : GCCBuiltin<"__builtin_ia32_pfsubr">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnow_pi2fd : GCCBuiltin<"__builtin_ia32_pi2fd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnow_pmulhrw : GCCBuiltin<"__builtin_ia32_pmulhrw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// 3DNow! extensions - -let TargetPrefix = "x86" in { - def int_x86_3dnowa_pf2iw : GCCBuiltin<"__builtin_ia32_pf2iw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnowa_pfnacc : GCCBuiltin<"__builtin_ia32_pfnacc">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnowa_pfpnacc : GCCBuiltin<"__builtin_ia32_pfpnacc">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_3dnowa_pi2fw : GCCBuiltin<"__builtin_ia32_pi2fw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_3dnowa_pswapd : - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// SSE1 - -// Arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_sse_rcp_ps : GCCBuiltin<"__builtin_ia32_rcpps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_sse_rsqrt_ss : GCCBuiltin<"__builtin_ia32_rsqrtss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_sse_rsqrt_ps : GCCBuiltin<"__builtin_ia32_rsqrtps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_sse_min_ss : GCCBuiltin<"__builtin_ia32_minss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_min_ps : GCCBuiltin<"__builtin_ia32_minps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_max_ss : GCCBuiltin<"__builtin_ia32_maxss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_max_ps : GCCBuiltin<"__builtin_ia32_maxps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; -} - -// Comparison ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - // NOTE: This comparison intrinsic is not used by clang as long as the - // distinction in signaling behaviour is not implemented. - def int_x86_sse_cmp_ps : - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_comilt_ss : GCCBuiltin<"__builtin_ia32_comilt">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_comile_ss : GCCBuiltin<"__builtin_ia32_comile">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_comigt_ss : GCCBuiltin<"__builtin_ia32_comigt">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_comige_ss : GCCBuiltin<"__builtin_ia32_comige">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_comineq_ss : GCCBuiltin<"__builtin_ia32_comineq">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomieq_ss : GCCBuiltin<"__builtin_ia32_ucomieq">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomilt_ss : GCCBuiltin<"__builtin_ia32_ucomilt">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomile_ss : GCCBuiltin<"__builtin_ia32_ucomile">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomigt_ss : GCCBuiltin<"__builtin_ia32_ucomigt">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomige_ss : GCCBuiltin<"__builtin_ia32_ucomige">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_ucomineq_ss : GCCBuiltin<"__builtin_ia32_ucomineq">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; -} - - -// Conversion ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_cvtss2si : GCCBuiltin<"__builtin_ia32_cvtss2si">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvtss2si64 : GCCBuiltin<"__builtin_ia32_cvtss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvttss2si : GCCBuiltin<"__builtin_ia32_cvttss2si">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - - def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvtpi2ps : GCCBuiltin<"__builtin_ia32_cvtpi2ps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_x86mmx_ty], [IntrNoMem]>; -} - -// Cacheability support ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">, - Intrinsic<[], [], []>; -} - -// Control register. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_stmxcsr : - Intrinsic<[], [llvm_ptr_ty], - [IntrWriteMem, IntrArgMemOnly, - // This prevents reordering with ldmxcsr - IntrHasSideEffects]>; - def int_x86_sse_ldmxcsr : - Intrinsic<[], [llvm_ptr_ty], - // FIXME: LDMXCSR does not actually write to memory, - // but intrinsic properties are generated incorrectly - // for IntrReadMem+IntrHasSideEffects. - [/*IntrReadMem, IntrArgMemOnly,*/ IntrHasSideEffects]>; -} - -// Misc. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_movmsk_ps : GCCBuiltin<"__builtin_ia32_movmskps">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// SSE2 - -// FP arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_min_pd : GCCBuiltin<"__builtin_ia32_minpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_max_sd : GCCBuiltin<"__builtin_ia32_maxsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_max_pd : GCCBuiltin<"__builtin_ia32_maxpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; -} - -// FP comparison ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - // NOTE: This comparison intrinsic is not used by clang as long as the - // distinction in signaling behaviour is not implemented. - def int_x86_sse2_cmp_pd : - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_comilt_sd : GCCBuiltin<"__builtin_ia32_comisdlt">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_comile_sd : GCCBuiltin<"__builtin_ia32_comisdle">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_comigt_sd : GCCBuiltin<"__builtin_ia32_comisdgt">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_comige_sd : GCCBuiltin<"__builtin_ia32_comisdge">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_comineq_sd : GCCBuiltin<"__builtin_ia32_comisdneq">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomieq_sd : GCCBuiltin<"__builtin_ia32_ucomisdeq">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomilt_sd : GCCBuiltin<"__builtin_ia32_ucomisdlt">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomile_sd : GCCBuiltin<"__builtin_ia32_ucomisdle">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomigt_sd : GCCBuiltin<"__builtin_ia32_ucomisdgt">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomige_sd : GCCBuiltin<"__builtin_ia32_ucomisdge">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_ucomineq_sd : GCCBuiltin<"__builtin_ia32_ucomisdneq">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; -} - -// Integer arithmetic ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem, Commutative]>; -} - -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_psll_w : GCCBuiltin<"__builtin_ia32_psllw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_sse2_psll_d : GCCBuiltin<"__builtin_ia32_pslld128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_q : GCCBuiltin<"__builtin_ia32_psllq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_sse2_psra_w : GCCBuiltin<"__builtin_ia32_psraw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_sse2_psra_d : GCCBuiltin<"__builtin_ia32_psrad128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - - // Oddly these don't require an immediate due to a gcc compatibility issue. - def int_x86_sse2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty], [IntrNoMem]>; -} - -// Conversion ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, - Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtsd2si64 : GCCBuiltin<"__builtin_ia32_cvtsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvttsd2si : GCCBuiltin<"__builtin_ia32_cvttsd2si">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse_cvtpi2pd : GCCBuiltin<"__builtin_ia32_cvtpi2pd">, - Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; -} - -// Misc. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_sse2_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, - Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">, - Intrinsic<[], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_ptr_ty], []>; - def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">, - Intrinsic<[], [], []>; - def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, - Intrinsic<[], [], []>; - def int_x86_sse2_pause : GCCBuiltin<"__builtin_ia32_pause">, - Intrinsic<[], [], []>; -} - -//===----------------------------------------------------------------------===// -// SSE3 - -// Addition / subtraction ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse3_addsub_ps : GCCBuiltin<"__builtin_ia32_addsubps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse3_addsub_pd : GCCBuiltin<"__builtin_ia32_addsubpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; -} - -// Horizontal ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse3_hadd_ps : GCCBuiltin<"__builtin_ia32_haddps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse3_hadd_pd : GCCBuiltin<"__builtin_ia32_haddpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse3_hsub_ps : GCCBuiltin<"__builtin_ia32_hsubps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse3_hsub_pd : GCCBuiltin<"__builtin_ia32_hsubpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; -} - -// Specialized unaligned load. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse3_ldu_dq : GCCBuiltin<"__builtin_ia32_lddqu">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - -// Thread synchronization ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">, - Intrinsic<[], [llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">, - Intrinsic<[], [llvm_i32_ty, - llvm_i32_ty], []>; -} - -//===----------------------------------------------------------------------===// -// SSSE3 - -// Horizontal arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - - def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phsub_w_128 : GCCBuiltin<"__builtin_ia32_phsubw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_ssse3_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phsub_d_128 : GCCBuiltin<"__builtin_ia32_phsubd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - - def int_x86_ssse3_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_phsub_sw_128 : GCCBuiltin<"__builtin_ia32_phsubsw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; -} - -// Packed multiply high with round and scale -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; -} - -// Shuffle ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_ssse3_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// Sign ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_ssse3_psign_b : GCCBuiltin<"__builtin_ia32_psignb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_psign_b_128 : GCCBuiltin<"__builtin_ia32_psignb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; - - def int_x86_ssse3_psign_w : GCCBuiltin<"__builtin_ia32_psignw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_psign_w_128 : GCCBuiltin<"__builtin_ia32_psignw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_ssse3_psign_d : GCCBuiltin<"__builtin_ia32_psignd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_ssse3_psign_d_128 : GCCBuiltin<"__builtin_ia32_psignd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; -} - -// Absolute value ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_ssse3_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_ssse3_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_ssse3_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// SSE4.1 - -// FP rounding ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_round_ss : GCCBuiltin<"__builtin_ia32_roundss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_sse41_round_ps : GCCBuiltin<"__builtin_ia32_roundps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_sse41_round_sd : GCCBuiltin<"__builtin_ia32_roundsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_sse41_round_pd : GCCBuiltin<"__builtin_ia32_roundpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; -} - -// Vector min element -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], - [IntrNoMem]>; -} - -// Advanced Encryption Standard (AES) Instructions -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_aesni_aesimc : GCCBuiltin<"__builtin_ia32_aesimc128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], - [IntrNoMem]>; - - def int_x86_aesni_aesenc : GCCBuiltin<"__builtin_ia32_aesenc128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesenc_256 : GCCBuiltin<"__builtin_ia32_aesenc256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesenc_512 : GCCBuiltin<"__builtin_ia32_aesenc512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_aesni_aesenclast : GCCBuiltin<"__builtin_ia32_aesenclast128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesenclast_256 : - GCCBuiltin<"__builtin_ia32_aesenclast256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesenclast_512 : - GCCBuiltin<"__builtin_ia32_aesenclast512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_aesni_aesdec : GCCBuiltin<"__builtin_ia32_aesdec128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesdec_256 : GCCBuiltin<"__builtin_ia32_aesdec256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesdec_512 : GCCBuiltin<"__builtin_ia32_aesdec512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_aesni_aesdeclast : GCCBuiltin<"__builtin_ia32_aesdeclast128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesdeclast_256 : - GCCBuiltin<"__builtin_ia32_aesdeclast256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_aesni_aesdeclast_512 : - GCCBuiltin<"__builtin_ia32_aesdeclast512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_aesni_aeskeygenassist : - GCCBuiltin<"__builtin_ia32_aeskeygenassist128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// PCLMUL instructions -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_pclmulqdq : GCCBuiltin<"__builtin_ia32_pclmulqdq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_pclmulqdq_256 : GCCBuiltin<"__builtin_ia32_pclmulqdq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_pclmulqdq_512 : GCCBuiltin<"__builtin_ia32_pclmulqdq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// Vector pack -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -} - -// Vector insert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// Vector blend -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_sse41_blendvps : GCCBuiltin<"__builtin_ia32_blendvps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_v4f32_ty], - [IntrNoMem]>; -} - -// Vector dot product -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, Commutative, ImmArg>]>; - def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, Commutative, ImmArg>]>; -} - -// Vector sum of absolute differences -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// Test instruction with bitwise comparison. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_sse41_ptestc : GCCBuiltin<"__builtin_ia32_ptestc128">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_sse41_ptestnzc : GCCBuiltin<"__builtin_ia32_ptestnzc128">, - Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// SSE4.2 - -// Miscellaneous -// CRC Instruction -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse42_crc32_32_8 : GCCBuiltin<"__builtin_ia32_crc32qi">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse42_crc32_32_16 : GCCBuiltin<"__builtin_ia32_crc32hi">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_sse42_crc32_32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_sse42_crc32_64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; -} - -// String/text processing ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// SSE4A - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse4a_extrqi : GCCBuiltin<"__builtin_ia32_extrqi">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_sse4a_extrq : GCCBuiltin<"__builtin_ia32_extrq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v16i8_ty], [IntrNoMem]>; - - def int_x86_sse4a_insertqi : GCCBuiltin<"__builtin_ia32_insertqi">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_sse4a_insertq : GCCBuiltin<"__builtin_ia32_insertq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// AVX - -// Arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_addsub_pd_256 : GCCBuiltin<"__builtin_ia32_addsubpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_addsub_ps_256 : GCCBuiltin<"__builtin_ia32_addsubps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - - def int_x86_avx_rsqrt_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrtps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - - def int_x86_avx_rcp_ps_256 : GCCBuiltin<"__builtin_ia32_rcpps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - - def int_x86_avx_round_pd_256 : GCCBuiltin<"__builtin_ia32_roundpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx_round_ps_256 : GCCBuiltin<"__builtin_ia32_roundps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; -} - -// Horizontal ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_hadd_pd_256 : GCCBuiltin<"__builtin_ia32_haddpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_hsub_ps_256 : GCCBuiltin<"__builtin_ia32_hsubps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_hsub_pd_256 : GCCBuiltin<"__builtin_ia32_hsubpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_hadd_ps_256 : GCCBuiltin<"__builtin_ia32_haddps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; -} - -// Vector permutation -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vpermilvar_pd : GCCBuiltin<"__builtin_ia32_vpermilvarpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx_vpermilvar_ps : GCCBuiltin<"__builtin_ia32_vpermilvarps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - - def int_x86_avx_vpermilvar_pd_256 : - GCCBuiltin<"__builtin_ia32_vpermilvarpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx_vpermilvar_ps_256 : - GCCBuiltin<"__builtin_ia32_vpermilvarps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_d_128 : - GCCBuiltin<"__builtin_ia32_vpermi2vard128">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_d_256 : - GCCBuiltin<"__builtin_ia32_vpermi2vard256">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_d_512 : - GCCBuiltin<"__builtin_ia32_vpermi2vard512">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_hi_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi128">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_hi_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi256">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_hi_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi512">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_pd_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd128">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_pd_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_pd_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd512">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_ps_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varps128">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_ps_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varps256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_ps_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varps512">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty], - [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_q_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varq128">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_q_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varq256">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_q_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varq512">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_qi_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_qi_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi256">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermi2var_qi_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi512">, - Intrinsic<[llvm_v64i8_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem]>; - - def int_x86_avx512_vpermilvar_pd_512 : - GCCBuiltin<"__builtin_ia32_vpermilvarpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_avx512_vpermilvar_ps_512 : - GCCBuiltin<"__builtin_ia32_vpermilvarps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_pshuf_b_512 : - GCCBuiltin<"__builtin_ia32_pshufb512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty], - [IntrNoMem]>; - -} - -// GFNI Instructions -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_vgf2p8affineinvqb_128 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v16qi">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_vgf2p8affineinvqb_256 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v32qi">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_vgf2p8affineinvqb_512 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v64qi">, - Intrinsic<[llvm_v64i8_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_vgf2p8affineqb_128 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v16qi">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_vgf2p8affineqb_256 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v32qi">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_vgf2p8affineqb_512 : - GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v64qi">, - Intrinsic<[llvm_v64i8_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_vgf2p8mulb_128 : - GCCBuiltin<"__builtin_ia32_vgf2p8mulb_v16qi">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_vgf2p8mulb_256 : - GCCBuiltin<"__builtin_ia32_vgf2p8mulb_v32qi">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i8_ty, llvm_v32i8_ty], - [IntrNoMem]>; - def int_x86_vgf2p8mulb_512 : - GCCBuiltin<"__builtin_ia32_vgf2p8mulb_v64qi">, - Intrinsic<[llvm_v64i8_ty], - [llvm_v64i8_ty, llvm_v64i8_ty], - [IntrNoMem]>; -} - -// Vector blend -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_blendv_ps_256 : GCCBuiltin<"__builtin_ia32_blendvps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -} - -// Vector dot product -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem, Commutative, ImmArg>]>; -} - -// Vector compare -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_cmp_pd_256 : - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx_cmp_ps_256 : - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; -} - -// Vector convert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_cvtt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvttpd2dq256">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_cvt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvtpd2dq256">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_cvtt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvttps2dq256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -} - -// Vector bit test -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vtestz_pd : GCCBuiltin<"__builtin_ia32_vtestzpd">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestc_pd : GCCBuiltin<"__builtin_ia32_vtestcpd">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestnzc_pd : GCCBuiltin<"__builtin_ia32_vtestnzcpd">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestz_ps : GCCBuiltin<"__builtin_ia32_vtestzps">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx_vtestc_ps : GCCBuiltin<"__builtin_ia32_vtestcps">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx_vtestnzc_ps : GCCBuiltin<"__builtin_ia32_vtestnzcps">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx_vtestz_pd_256 : GCCBuiltin<"__builtin_ia32_vtestzpd256">, - Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestcpd256">, - Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestnzc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestnzcpd256">, - Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, - llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_vtestz_ps_256 : GCCBuiltin<"__builtin_ia32_vtestzps256">, - Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_vtestc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestcps256">, - Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_vtestnzc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestnzcps256">, - Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_ptestz_256 : GCCBuiltin<"__builtin_ia32_ptestz256">, - Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx_ptestc_256 : GCCBuiltin<"__builtin_ia32_ptestc256">, - Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx_ptestnzc_256 : GCCBuiltin<"__builtin_ia32_ptestnzc256">, - Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - - def int_x86_avx512_fpclass_pd_128 : - Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_fpclass_pd_256 : - Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_fpclass_pd_512 : - Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_fpclass_ps_128 : - Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_fpclass_ps_256 : - Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_fpclass_ps_512 : - Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fpclass_sd : - GCCBuiltin<"__builtin_ia32_fpclasssd_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fpclass_ss : - GCCBuiltin<"__builtin_ia32_fpclassss_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -// Vector extract sign mask -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_movmsk_pd_256 : GCCBuiltin<"__builtin_ia32_movmskpd256">, - Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_movmsk_ps_256 : GCCBuiltin<"__builtin_ia32_movmskps256">, - Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -} - -// Vector zero -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vzeroall : GCCBuiltin<"__builtin_ia32_vzeroall">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects]>; - def int_x86_avx_vzeroupper : GCCBuiltin<"__builtin_ia32_vzeroupper">, - Intrinsic<[], [], [IntrNoMem, IntrHasSideEffects]>; -} - -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_ldu_dq_256 : GCCBuiltin<"__builtin_ia32_lddqu256">, - Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - -// Conditional load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_maskload_pd : GCCBuiltin<"__builtin_ia32_maskloadpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2i64_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx_maskload_ps : GCCBuiltin<"__builtin_ia32_maskloadps">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx_maskload_pd_256 : GCCBuiltin<"__builtin_ia32_maskloadpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4i64_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx_maskload_ps_256 : GCCBuiltin<"__builtin_ia32_maskloadps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8i32_ty], - [IntrReadMem, IntrArgMemOnly]>; -} - -// Conditional store ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_maskstore_pd : GCCBuiltin<"__builtin_ia32_maskstorepd">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v2i64_ty, llvm_v2f64_ty], [IntrArgMemOnly]>; - def int_x86_avx_maskstore_ps : GCCBuiltin<"__builtin_ia32_maskstoreps">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v4i32_ty, llvm_v4f32_ty], [IntrArgMemOnly]>; - def int_x86_avx_maskstore_pd_256 : - GCCBuiltin<"__builtin_ia32_maskstorepd256">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v4i64_ty, llvm_v4f64_ty], [IntrArgMemOnly]>; - def int_x86_avx_maskstore_ps_256 : - GCCBuiltin<"__builtin_ia32_maskstoreps256">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v8i32_ty, llvm_v8f32_ty], [IntrArgMemOnly]>; -} - -// BITALG bits shuffle -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_vpshufbitqmb_128 : - Intrinsic<[llvm_v16i1_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_avx512_vpshufbitqmb_256 : - Intrinsic<[llvm_v32i1_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx512_vpshufbitqmb_512 : - Intrinsic<[llvm_v64i1_ty], [llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// AVX2 - -// Integer arithmetic ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem, Commutative]>; -} - -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_psll_w : GCCBuiltin<"__builtin_ia32_psllw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx2_psll_d : GCCBuiltin<"__builtin_ia32_pslld256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_q : GCCBuiltin<"__builtin_ia32_psllq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx2_psra_w : GCCBuiltin<"__builtin_ia32_psraw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx2_psra_d : GCCBuiltin<"__builtin_ia32_psrad256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - - // Oddly these don't require an immediate due to a gcc compatibility issue. - def int_x86_avx2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_psra_q_128 : GCCBuiltin<"__builtin_ia32_psraq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_psra_q_256 : GCCBuiltin<"__builtin_ia32_psraq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - - // Oddly these don't require an immediate due to a gcc compatibility issue. - def int_x86_avx512_psrai_q_128 : GCCBuiltin<"__builtin_ia32_psraqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrai_q_256 : GCCBuiltin<"__builtin_ia32_psraqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_psll_w_512 : GCCBuiltin<"__builtin_ia32_psllw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_psll_d_512 : GCCBuiltin<"__builtin_ia32_pslld512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_psll_q_512 : GCCBuiltin<"__builtin_ia32_psllq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_w_512 : GCCBuiltin<"__builtin_ia32_psrlw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_d_512 : GCCBuiltin<"__builtin_ia32_psrld512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_q_512 : GCCBuiltin<"__builtin_ia32_psrlq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_psra_w_512 : GCCBuiltin<"__builtin_ia32_psraw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_psra_d_512 : GCCBuiltin<"__builtin_ia32_psrad512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_psra_q_512 : GCCBuiltin<"__builtin_ia32_psraq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - - // Oddly these don't require an immediate due to a gcc compatibility issue. - def int_x86_avx512_pslli_w_512 : GCCBuiltin<"__builtin_ia32_psllwi512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_pslli_d_512 : GCCBuiltin<"__builtin_ia32_pslldi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_pslli_q_512 : GCCBuiltin<"__builtin_ia32_psllqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrli_w_512 : GCCBuiltin<"__builtin_ia32_psrlwi512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrli_d_512 : GCCBuiltin<"__builtin_ia32_psrldi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrli_q_512 : GCCBuiltin<"__builtin_ia32_psrlqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrai_w_512 : GCCBuiltin<"__builtin_ia32_psrawi512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrai_d_512 : GCCBuiltin<"__builtin_ia32_psradi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrai_q_512 : GCCBuiltin<"__builtin_ia32_psraqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_pmultishift_qb_128: - GCCBuiltin<"__builtin_ia32_vpmultishiftqb128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_avx512_pmultishift_qb_256: - GCCBuiltin<"__builtin_ia32_vpmultishiftqb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx512_pmultishift_qb_512: - GCCBuiltin<"__builtin_ia32_vpmultishiftqb512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem]>; -} - -// Pack ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_packsswb : GCCBuiltin<"__builtin_ia32_packsswb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_packssdw : GCCBuiltin<"__builtin_ia32_packssdw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx2_packuswb : GCCBuiltin<"__builtin_ia32_packuswb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_packusdw : GCCBuiltin<"__builtin_ia32_packusdw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; -} - -// Horizontal arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx2_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx2_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem]>; -} - -// Sign ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_psign_b : GCCBuiltin<"__builtin_ia32_psignb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_psign_w : GCCBuiltin<"__builtin_ia32_psignw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx2_psign_d : GCCBuiltin<"__builtin_ia32_psignd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; -} - -// Packed multiply high with round and scale -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v32i16_ty], [IntrNoMem, Commutative]>; -} - -// Vector blend -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem]>; -} - - -// Vector permutation -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_permd : GCCBuiltin<"__builtin_ia32_permvarsi256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], - [IntrNoMem]>; - def int_x86_avx2_permps : GCCBuiltin<"__builtin_ia32_permvarsf256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], - [IntrNoMem]>; -} - -// Conditional load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_maskload_d : GCCBuiltin<"__builtin_ia32_maskloadd">, - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx2_maskload_q : GCCBuiltin<"__builtin_ia32_maskloadq">, - Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx2_maskload_d_256 : GCCBuiltin<"__builtin_ia32_maskloadd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx2_maskload_q_256 : GCCBuiltin<"__builtin_ia32_maskloadq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty], - [IntrReadMem, IntrArgMemOnly]>; -} - -// Conditional store ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_maskstore_d : GCCBuiltin<"__builtin_ia32_maskstored">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx2_maskstore_q : GCCBuiltin<"__builtin_ia32_maskstoreq">, - Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [IntrArgMemOnly]>; - def int_x86_avx2_maskstore_d_256 : - GCCBuiltin<"__builtin_ia32_maskstored256">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx2_maskstore_q_256 : - GCCBuiltin<"__builtin_ia32_maskstoreq256">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty], - [IntrArgMemOnly]>; -} - -// Variable bit shift ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_psllv_d : GCCBuiltin<"__builtin_ia32_psllv4si">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_avx2_psllv_d_256 : GCCBuiltin<"__builtin_ia32_psllv8si">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], - [IntrNoMem]>; - def int_x86_avx2_psllv_q : GCCBuiltin<"__builtin_ia32_psllv2di">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_avx2_psllv_q_256 : GCCBuiltin<"__builtin_ia32_psllv4di">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - - def int_x86_avx512_psllv_d_512 : GCCBuiltin<"__builtin_ia32_psllv16si">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - def int_x86_avx512_psllv_q_512 : GCCBuiltin<"__builtin_ia32_psllv8di">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_avx2_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv4si">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_avx2_psrlv_d_256 : GCCBuiltin<"__builtin_ia32_psrlv8si">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], - [IntrNoMem]>; - def int_x86_avx2_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv2di">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_avx2_psrlv_q_256 : GCCBuiltin<"__builtin_ia32_psrlv4di">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - - def int_x86_avx512_psrlv_d_512 : GCCBuiltin<"__builtin_ia32_psrlv16si">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - def int_x86_avx512_psrlv_q_512 : GCCBuiltin<"__builtin_ia32_psrlv8di">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_avx2_psrav_d : GCCBuiltin<"__builtin_ia32_psrav4si">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_psrav_d_512 : GCCBuiltin<"__builtin_ia32_psrav16si">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - def int_x86_avx512_psrav_q_128 : GCCBuiltin<"__builtin_ia32_psravq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_avx512_psrav_q_256 : GCCBuiltin<"__builtin_ia32_psravq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_avx512_psrav_q_512 : GCCBuiltin<"__builtin_ia32_psrav8di">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - - def int_x86_avx512_psllv_w_128 : GCCBuiltin<"__builtin_ia32_psllv8hi">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psllv_w_256 : GCCBuiltin<"__builtin_ia32_psllv16hi">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psllv_w_512 : GCCBuiltin<"__builtin_ia32_psllv32hi">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_psrlv_w_128 : GCCBuiltin<"__builtin_ia32_psrlv8hi">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psrlv_w_256 : GCCBuiltin<"__builtin_ia32_psrlv16hi">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psrlv_w_512 : GCCBuiltin<"__builtin_ia32_psrlv32hi">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_psrav_w_128 : GCCBuiltin<"__builtin_ia32_psrav8hi">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psrav_w_256 : GCCBuiltin<"__builtin_ia32_psrav16hi">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], - [IntrNoMem]>; - def int_x86_avx512_psrav_w_512 : GCCBuiltin<"__builtin_ia32_psrav32hi">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], - [IntrNoMem]>; -} - -// Gather ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, ImmArg>]>; -} - -// Misc. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb256">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i8_ty], [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// FMA3 and FMA4 - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd : GCCBuiltin<"__builtin_ia32_vfmaddsubpd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - - def int_x86_avx512_vfmadd_pd_512 : - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_vfmadd_ps_512 : - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_vfmaddsub_pd_512 : - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_vfmaddsub_ps_512 : - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_vfmadd_f64 : - Intrinsic<[llvm_double_ty], - [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vfmadd_f32 : - Intrinsic<[llvm_float_ty], - [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_vpmadd52h_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_vpmadd52l_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_vpmadd52h_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_vpmadd52l_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_vpmadd52h_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_vpmadd52l_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; -} - -// VNNI -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_vpdpbusd_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpbusd_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpbusd_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpdpbusds_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusds128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpbusds_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusds256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpbusds_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusds512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpdpwssd_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpwssd_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpwssd_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - - def int_x86_avx512_vpdpwssds_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssds128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpwssds_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssds256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_vpdpwssds_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssds512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// XOP - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_xop_vpermil2pd : GCCBuiltin<"__builtin_ia32_vpermil2pd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_xop_vpermil2pd_256 : - GCCBuiltin<"__builtin_ia32_vpermil2pd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_xop_vpermil2ps : GCCBuiltin<"__builtin_ia32_vpermil2ps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_xop_vpermil2ps_256 : - GCCBuiltin<"__builtin_ia32_vpermil2ps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_xop_vfrcz_pd : GCCBuiltin<"__builtin_ia32_vfrczpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_ps : GCCBuiltin<"__builtin_ia32_vfrczps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_sd : GCCBuiltin<"__builtin_ia32_vfrczsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_ss : GCCBuiltin<"__builtin_ia32_vfrczss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_pd_256 : GCCBuiltin<"__builtin_ia32_vfrczpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_ps_256 : GCCBuiltin<"__builtin_ia32_vfrczps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - - def int_x86_xop_vphaddbd : - GCCBuiltin<"__builtin_ia32_vphaddbd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddbq : - GCCBuiltin<"__builtin_ia32_vphaddbq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddbw : - GCCBuiltin<"__builtin_ia32_vphaddbw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphadddq : - GCCBuiltin<"__builtin_ia32_vphadddq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_xop_vphaddubd : - GCCBuiltin<"__builtin_ia32_vphaddubd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddubq : - GCCBuiltin<"__builtin_ia32_vphaddubq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddubw : - GCCBuiltin<"__builtin_ia32_vphaddubw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddudq : - GCCBuiltin<"__builtin_ia32_vphaddudq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_xop_vphadduwd : - GCCBuiltin<"__builtin_ia32_vphadduwd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_xop_vphadduwq : - GCCBuiltin<"__builtin_ia32_vphadduwq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_xop_vphaddwd : - GCCBuiltin<"__builtin_ia32_vphaddwd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_xop_vphaddwq : - GCCBuiltin<"__builtin_ia32_vphaddwq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_xop_vphsubbw : - GCCBuiltin<"__builtin_ia32_vphsubbw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vphsubdq : - GCCBuiltin<"__builtin_ia32_vphsubdq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_xop_vphsubwd : - GCCBuiltin<"__builtin_ia32_vphsubwd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_xop_vpmacsdd : - GCCBuiltin<"__builtin_ia32_vpmacsdd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacsdqh : - GCCBuiltin<"__builtin_ia32_vpmacsdqh">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacsdql : - GCCBuiltin<"__builtin_ia32_vpmacsdql">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacssdd : - GCCBuiltin<"__builtin_ia32_vpmacssdd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacssdqh : - GCCBuiltin<"__builtin_ia32_vpmacssdqh">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacssdql : - GCCBuiltin<"__builtin_ia32_vpmacssdql">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacsswd : - GCCBuiltin<"__builtin_ia32_vpmacsswd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacssww : - GCCBuiltin<"__builtin_ia32_vpmacssww">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacswd : - GCCBuiltin<"__builtin_ia32_vpmacswd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmacsww : - GCCBuiltin<"__builtin_ia32_vpmacsww">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmadcsswd : - GCCBuiltin<"__builtin_ia32_vpmadcsswd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpmadcswd : - GCCBuiltin<"__builtin_ia32_vpmadcswd">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; - def int_x86_xop_vpperm : - GCCBuiltin<"__builtin_ia32_vpperm">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpshab : - GCCBuiltin<"__builtin_ia32_vpshab">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpshad : - GCCBuiltin<"__builtin_ia32_vpshad">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpshaq : - GCCBuiltin<"__builtin_ia32_vpshaq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpshaw : - GCCBuiltin<"__builtin_ia32_vpshaw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpshlb : - GCCBuiltin<"__builtin_ia32_vpshlb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpshld : - GCCBuiltin<"__builtin_ia32_vpshld">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpshlq : - GCCBuiltin<"__builtin_ia32_vpshlq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpshlw : - GCCBuiltin<"__builtin_ia32_vpshlw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// LWP -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_llwpcb : - GCCBuiltin<"__builtin_ia32_llwpcb">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_slwpcb : - GCCBuiltin<"__builtin_ia32_slwpcb">, - Intrinsic<[llvm_ptr_ty], [], []>; - def int_x86_lwpins32 : - GCCBuiltin<"__builtin_ia32_lwpins32">, - Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_lwpins64 : - GCCBuiltin<"__builtin_ia32_lwpins64">, - Intrinsic<[llvm_i8_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_lwpval32 : - GCCBuiltin<"__builtin_ia32_lwpval32">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_lwpval64 : - GCCBuiltin<"__builtin_ia32_lwpval64">, - Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// MMX - -// Empty MMX state op. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">, - Intrinsic<[], [], []>; - def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">, - Intrinsic<[], [], []>; -} - -// Integer arithmetic ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // Addition - def int_x86_mmx_padd_b : GCCBuiltin<"__builtin_ia32_paddb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - def int_x86_mmx_padd_w : GCCBuiltin<"__builtin_ia32_paddw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - def int_x86_mmx_padd_d : GCCBuiltin<"__builtin_ia32_paddd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - def int_x86_mmx_padd_q : GCCBuiltin<"__builtin_ia32_paddq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - - def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - // Subtraction - def int_x86_mmx_psub_b : GCCBuiltin<"__builtin_ia32_psubb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_psub_w : GCCBuiltin<"__builtin_ia32_psubw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_psub_d : GCCBuiltin<"__builtin_ia32_psubd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_psub_q : GCCBuiltin<"__builtin_ia32_psubq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - - def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - - // Multiplication - def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmull_w : GCCBuiltin<"__builtin_ia32_pmullw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - // Bitwise operations - def int_x86_mmx_pand : GCCBuiltin<"__builtin_ia32_pand">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - def int_x86_mmx_pandn : GCCBuiltin<"__builtin_ia32_pandn">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_por : GCCBuiltin<"__builtin_ia32_por">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - def int_x86_mmx_pxor : GCCBuiltin<"__builtin_ia32_pxor">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem, Commutative]>; - - // Averages - def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - // Maximum - def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - // Minimum - def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - // Packed sum of absolute differences - def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; -} - -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // Shift left logical - def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - - // Oddly these don't require an immediate due to a gcc compatibility issue. - def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_mmx_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_mmx_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_psrai_d : GCCBuiltin<"__builtin_ia32_psradi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty], [IntrNoMem]>; -} -// Permute -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v32i16_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, - llvm_v64i8_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; -} -// Pack ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; -} - -// Unpacking ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_mmx_punpckhbw : GCCBuiltin<"__builtin_ia32_punpckhbw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_punpckhwd : GCCBuiltin<"__builtin_ia32_punpckhwd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_punpckhdq : GCCBuiltin<"__builtin_ia32_punpckhdq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_punpcklbw : GCCBuiltin<"__builtin_ia32_punpcklbw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_punpcklwd : GCCBuiltin<"__builtin_ia32_punpcklwd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; - def int_x86_mmx_punpckldq : GCCBuiltin<"__builtin_ia32_punpckldq">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], - [IntrNoMem]>; -} - -// Integer comparison ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem, Commutative]>; - - def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; - def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty], [IntrNoMem]>; -} - -// Misc. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, - Intrinsic<[], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_ptr_ty], []>; - - def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, - Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty], [IntrNoMem]>; - - def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, - Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; - - def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, - Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// BMI - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_bmi_bextr_32 : GCCBuiltin<"__builtin_ia32_bextr_u32">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_bmi_bextr_64 : GCCBuiltin<"__builtin_ia32_bextr_u64">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_bmi_bzhi_32 : GCCBuiltin<"__builtin_ia32_bzhi_si">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_bmi_bzhi_64 : GCCBuiltin<"__builtin_ia32_bzhi_di">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_bmi_pdep_32 : GCCBuiltin<"__builtin_ia32_pdep_si">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_bmi_pdep_64 : GCCBuiltin<"__builtin_ia32_pdep_di">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_bmi_pext_32 : GCCBuiltin<"__builtin_ia32_pext_si">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_bmi_pext_64 : GCCBuiltin<"__builtin_ia32_pext_di">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// FS/GS Base - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_rdfsbase_32 : GCCBuiltin<"__builtin_ia32_rdfsbase32">, - Intrinsic<[llvm_i32_ty], []>; - def int_x86_rdgsbase_32 : GCCBuiltin<"__builtin_ia32_rdgsbase32">, - Intrinsic<[llvm_i32_ty], []>; - def int_x86_rdfsbase_64 : GCCBuiltin<"__builtin_ia32_rdfsbase64">, - Intrinsic<[llvm_i64_ty], []>; - def int_x86_rdgsbase_64 : GCCBuiltin<"__builtin_ia32_rdgsbase64">, - Intrinsic<[llvm_i64_ty], []>; - def int_x86_wrfsbase_32 : GCCBuiltin<"__builtin_ia32_wrfsbase32">, - Intrinsic<[], [llvm_i32_ty]>; - def int_x86_wrgsbase_32 : GCCBuiltin<"__builtin_ia32_wrgsbase32">, - Intrinsic<[], [llvm_i32_ty]>; - def int_x86_wrfsbase_64 : GCCBuiltin<"__builtin_ia32_wrfsbase64">, - Intrinsic<[], [llvm_i64_ty]>; - def int_x86_wrgsbase_64 : GCCBuiltin<"__builtin_ia32_wrgsbase64">, - Intrinsic<[], [llvm_i64_ty]>; -} - -//===----------------------------------------------------------------------===// -// FXSR -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_fxrstor : GCCBuiltin<"__builtin_ia32_fxrstor">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_fxrstor64 : GCCBuiltin<"__builtin_ia32_fxrstor64">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_fxsave : GCCBuiltin<"__builtin_ia32_fxsave">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_fxsave64 : GCCBuiltin<"__builtin_ia32_fxsave64">, - Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// XSAVE -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_xsave : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsave64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xrstor : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xrstor64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsaveopt : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsaveopt64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xrstors : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xrstors64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsavec : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsavec64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsaves : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xsaves64 : - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_xgetbv : - Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; - def int_x86_xsetbv : - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -} - -//===----------------------------------------------------------------------===// -// CLFLUSHOPT and CLWB -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_clflushopt : GCCBuiltin<"__builtin_ia32_clflushopt">, - Intrinsic<[], [llvm_ptr_ty], []>; - - def int_x86_clwb : GCCBuiltin<"__builtin_ia32_clwb">, - Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Support protection key -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_rdpkru : GCCBuiltin <"__builtin_ia32_rdpkru">, - Intrinsic<[llvm_i32_ty], [], []>; - def int_x86_wrpkru : GCCBuiltin<"__builtin_ia32_wrpkru">, - Intrinsic<[], [llvm_i32_ty], []>; -} -//===----------------------------------------------------------------------===// -// Half float conversion - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_vcvtps2ph_128 : GCCBuiltin<"__builtin_ia32_vcvtps2ph">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_vcvtph2ps_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty, - llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_vcvtps2ph_128 : GCCBuiltin<"__builtin_ia32_vcvtps2ph_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// TBM - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_tbm_bextri_u32 : GCCBuiltin<"__builtin_ia32_bextri_u32">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_tbm_bextri_u64 : GCCBuiltin<"__builtin_ia32_bextri_u64">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// RDRAND intrinsics - Return a random value and whether it is valid. -// RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and -// whether it is valid. - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // These are declared side-effecting so they don't get eliminated by CSE or - // LICM. - def int_x86_rdrand_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; - def int_x86_rdrand_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; - def int_x86_rdrand_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; - def int_x86_rdseed_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; - def int_x86_rdseed_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; - def int_x86_rdseed_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; -} - -//===----------------------------------------------------------------------===// -// ADX - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_addcarry_32: - Intrinsic<[llvm_i8_ty, llvm_i32_ty], - [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_addcarry_64: - Intrinsic<[llvm_i8_ty, llvm_i64_ty], - [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_subborrow_32: - Intrinsic<[llvm_i8_ty, llvm_i32_ty], - [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_subborrow_64: - Intrinsic<[llvm_i8_ty, llvm_i64_ty], - [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// RTM intrinsics. Transactional Memory support. - -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_xbegin : GCCBuiltin<"__builtin_ia32_xbegin">, - Intrinsic<[llvm_i32_ty], [], []>; - def int_x86_xend : GCCBuiltin<"__builtin_ia32_xend">, - Intrinsic<[], [], []>; - def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">, - Intrinsic<[], [llvm_i8_ty], [ImmArg>]>; - def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, - Intrinsic<[llvm_i32_ty], [], []>; -} - -//===----------------------------------------------------------------------===// -// AVX512 - -// Mask ops -let TargetPrefix = "x86" in { - def int_x86_avx512_kadd_b : - Intrinsic<[llvm_v8i1_ty], [llvm_v8i1_ty, llvm_v8i1_ty], [IntrNoMem]>; - def int_x86_avx512_kadd_w : - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], [IntrNoMem]>; - def int_x86_avx512_kadd_d : - Intrinsic<[llvm_v32i1_ty], [llvm_v32i1_ty, llvm_v32i1_ty], [IntrNoMem]>; - def int_x86_avx512_kadd_q : - Intrinsic<[llvm_v64i1_ty], [llvm_v64i1_ty, llvm_v64i1_ty], [IntrNoMem]>; - - def int_x86_avx512_ktestc_b : - Intrinsic<[llvm_i32_ty], [llvm_v8i1_ty, llvm_v8i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestc_w : - Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty, llvm_v16i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestc_d : - Intrinsic<[llvm_i32_ty], [llvm_v32i1_ty, llvm_v32i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestc_q : - Intrinsic<[llvm_i32_ty], [llvm_v64i1_ty, llvm_v64i1_ty], [IntrNoMem]>; - - def int_x86_avx512_ktestz_b : - Intrinsic<[llvm_i32_ty], [llvm_v8i1_ty, llvm_v8i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestz_w : - Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty, llvm_v16i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestz_d : - Intrinsic<[llvm_i32_ty], [llvm_v32i1_ty, llvm_v32i1_ty], [IntrNoMem]>; - def int_x86_avx512_ktestz_q : - Intrinsic<[llvm_i32_ty], [llvm_v64i1_ty, llvm_v64i1_ty], [IntrNoMem]>; -} - -// Conversion ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_cvttss2si : GCCBuiltin<"__builtin_ia32_vcvttss2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttss2si64 : GCCBuiltin<"__builtin_ia32_vcvttss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttss2usi : GCCBuiltin<"__builtin_ia32_vcvttss2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_vcvttss2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss32">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss64">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttsd2si : GCCBuiltin<"__builtin_ia32_vcvttsd2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_vcvttsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttsd2usi : GCCBuiltin<"__builtin_ia32_vcvttsd2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvttsd2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtss2usi32 : GCCBuiltin<"__builtin_ia32_vcvtss2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtss2usi64 : GCCBuiltin<"__builtin_ia32_vcvtss2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtss2si32 : GCCBuiltin<"__builtin_ia32_vcvtss2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtss2si64 : GCCBuiltin<"__builtin_ia32_vcvtss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtsd2usi32 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtsd2si32 : GCCBuiltin<"__builtin_ia32_vcvtsd2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_vcvtsd2si64 : GCCBuiltin<"__builtin_ia32_vcvtsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtsi2ss32 : GCCBuiltin<"__builtin_ia32_cvtsi2ss32">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtsi2ss64 : GCCBuiltin<"__builtin_ia32_cvtsi2ss64">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; -} - -// Pack ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty], - [IntrNoMem]>; - def int_x86_avx512_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - def int_x86_avx512_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty], - [IntrNoMem]>; - def int_x86_avx512_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; -} - -// Vector convert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_sitofp_round : - Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_uitofp_round : - Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtpd2dq_128 : - GCCBuiltin<"__builtin_ia32_cvtpd2dq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2dq_512 : - GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtpd2ps_512 : - GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtsd2ss_round : - GCCBuiltin<"__builtin_ia32_cvtsd2ss_round_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtss2sd_round : - GCCBuiltin<"__builtin_ia32_cvtss2sd_round_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtpd2ps : - GCCBuiltin<"__builtin_ia32_cvtpd2ps_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2qq_128 : - GCCBuiltin<"__builtin_ia32_cvtpd2qq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2qq_256 : - GCCBuiltin<"__builtin_ia32_cvtpd2qq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2qq_512 : - GCCBuiltin<"__builtin_ia32_cvtpd2qq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtpd2udq_128 : - GCCBuiltin<"__builtin_ia32_cvtpd2udq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2udq_256 : - GCCBuiltin<"__builtin_ia32_cvtpd2udq256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2udq_512 : - GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtpd2uqq_128 : - GCCBuiltin<"__builtin_ia32_cvtpd2uqq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2uqq_256 : - GCCBuiltin<"__builtin_ia32_cvtpd2uqq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtpd2uqq_512 : - GCCBuiltin<"__builtin_ia32_cvtpd2uqq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtps2dq_128 : - GCCBuiltin<"__builtin_ia32_cvtps2dq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2dq_256 : - GCCBuiltin<"__builtin_ia32_cvtps2dq256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2dq_512 : - GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtps2pd_512 : - GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f32_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtps2qq_128 : - GCCBuiltin<"__builtin_ia32_cvtps2qq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2qq_256 : - GCCBuiltin<"__builtin_ia32_cvtps2qq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2qq_512 : - GCCBuiltin<"__builtin_ia32_cvtps2qq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtps2udq_128 : - GCCBuiltin<"__builtin_ia32_cvtps2udq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2udq_256 : - GCCBuiltin<"__builtin_ia32_cvtps2udq256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2udq_512 : - GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtps2uqq_128 : - GCCBuiltin<"__builtin_ia32_cvtps2uqq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2uqq_256 : - GCCBuiltin<"__builtin_ia32_cvtps2uqq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2uqq_512 : - GCCBuiltin<"__builtin_ia32_cvtps2uqq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtqq2ps_128 : - GCCBuiltin<"__builtin_ia32_cvtqq2ps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2dq_128 : - GCCBuiltin<"__builtin_ia32_cvttpd2dq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2dq_512 : - GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttpd2qq_128 : - GCCBuiltin<"__builtin_ia32_cvttpd2qq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2qq_256 : - GCCBuiltin<"__builtin_ia32_cvttpd2qq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2qq_512 : - GCCBuiltin<"__builtin_ia32_cvttpd2qq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttpd2udq_128 : - GCCBuiltin<"__builtin_ia32_cvttpd2udq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2udq_256 : - GCCBuiltin<"__builtin_ia32_cvttpd2udq256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2udq_512 : - GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttpd2uqq_128 : - GCCBuiltin<"__builtin_ia32_cvttpd2uqq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2uqq_256 : - GCCBuiltin<"__builtin_ia32_cvttpd2uqq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttpd2uqq_512 : - GCCBuiltin<"__builtin_ia32_cvttpd2uqq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttps2dq_512 : - GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttps2qq_128 : - GCCBuiltin<"__builtin_ia32_cvttps2qq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2qq_256 : - GCCBuiltin<"__builtin_ia32_cvttps2qq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2qq_512 : - GCCBuiltin<"__builtin_ia32_cvttps2qq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttps2udq_128 : - GCCBuiltin<"__builtin_ia32_cvttps2udq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2udq_256 : - GCCBuiltin<"__builtin_ia32_cvttps2udq256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2udq_512 : - GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvttps2uqq_128 : - GCCBuiltin<"__builtin_ia32_cvttps2uqq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2uqq_256 : - GCCBuiltin<"__builtin_ia32_cvttps2uqq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2uqq_512 : - GCCBuiltin<"__builtin_ia32_cvttps2uqq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cvtuqq2ps_128 : - GCCBuiltin<"__builtin_ia32_cvtuqq2ps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_rndscale_pd_128 : GCCBuiltin<"__builtin_ia32_rndscalepd_128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_rndscale_pd_256 : GCCBuiltin<"__builtin_ia32_rndscalepd_256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_rndscale_ps_128 : GCCBuiltin<"__builtin_ia32_rndscaleps_128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_rndscale_ps_256 : GCCBuiltin<"__builtin_ia32_rndscaleps_256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_reduce_pd_128 : GCCBuiltin<"__builtin_ia32_reducepd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_reduce_pd_256 : GCCBuiltin<"__builtin_ia32_reducepd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_reduce_pd_512 : GCCBuiltin<"__builtin_ia32_reducepd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_reduce_ps_128 : GCCBuiltin<"__builtin_ia32_reduceps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_reduce_ps_256 : GCCBuiltin<"__builtin_ia32_reduceps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_reduce_ps_512 : GCCBuiltin<"__builtin_ia32_reduceps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; -def int_x86_avx512_mask_range_pd_128 : GCCBuiltin<"__builtin_ia32_rangepd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -def int_x86_avx512_mask_range_pd_256 : GCCBuiltin<"__builtin_ia32_rangepd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -def int_x86_avx512_mask_range_pd_512 : GCCBuiltin<"__builtin_ia32_rangepd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, - llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; -def int_x86_avx512_mask_range_ps_128 : GCCBuiltin<"__builtin_ia32_rangeps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -def int_x86_avx512_mask_range_ps_256 : GCCBuiltin<"__builtin_ia32_rangeps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; -def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, - llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -// Vector load with broadcast -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_broadcastmw_512 : - GCCBuiltin<"__builtin_ia32_broadcastmw512">, - Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_broadcastmw_256 : - GCCBuiltin<"__builtin_ia32_broadcastmw256">, - Intrinsic<[llvm_v8i32_ty], [llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_broadcastmw_128 : - GCCBuiltin<"__builtin_ia32_broadcastmw128">, - Intrinsic<[llvm_v4i32_ty], [llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_broadcastmb_512 : - GCCBuiltin<"__builtin_ia32_broadcastmb512">, - Intrinsic<[llvm_v8i64_ty], [llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_broadcastmb_256 : - GCCBuiltin<"__builtin_ia32_broadcastmb256">, - Intrinsic<[llvm_v4i64_ty], [llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_broadcastmb_128 : - GCCBuiltin<"__builtin_ia32_broadcastmb128">, - Intrinsic<[llvm_v2i64_ty], [llvm_i8_ty], [IntrNoMem]>; -} - -// Arithmetic ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - - def int_x86_avx512_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_range_ss : GCCBuiltin<"__builtin_ia32_rangess128_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_range_sd : GCCBuiltin<"__builtin_ia32_rangesd128_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_reduce_ss : GCCBuiltin<"__builtin_ia32_reducess_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_reduce_sd : GCCBuiltin<"__builtin_ia32_reducesd_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_scalef_sd : GCCBuiltin<"__builtin_ia32_scalefsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_scalef_ss : GCCBuiltin<"__builtin_ia32_scalefss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_scalef_pd_128 : GCCBuiltin<"__builtin_ia32_scalefpd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_scalef_pd_256 : GCCBuiltin<"__builtin_ia32_scalefpd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty],[IntrNoMem]>; - def int_x86_avx512_mask_scalef_pd_512 : GCCBuiltin<"__builtin_ia32_scalefpd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_scalef_ps_128 : GCCBuiltin<"__builtin_ia32_scalefps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_scalef_ps_256 : GCCBuiltin<"__builtin_ia32_scalefps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_scalef_ps_512 : GCCBuiltin<"__builtin_ia32_scalefps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_sqrt_ss : - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_sqrt_sd : - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_sqrt_pd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_sqrt_ps_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_pd_128 : - GCCBuiltin<"__builtin_ia32_fixupimmpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_pd_128 : - GCCBuiltin<"__builtin_ia32_fixupimmpd128_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_pd_256 : - GCCBuiltin<"__builtin_ia32_fixupimmpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_pd_256 : - GCCBuiltin<"__builtin_ia32_fixupimmpd256_maskz">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_pd_512 : - GCCBuiltin<"__builtin_ia32_fixupimmpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_pd_512 : - GCCBuiltin<"__builtin_ia32_fixupimmpd512_maskz">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_ps_128 : - GCCBuiltin<"__builtin_ia32_fixupimmps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_ps_128 : - GCCBuiltin<"__builtin_ia32_fixupimmps128_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_ps_256 : - GCCBuiltin<"__builtin_ia32_fixupimmps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_ps_256 : - GCCBuiltin<"__builtin_ia32_fixupimmps256_maskz">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_ps_512 : - GCCBuiltin<"__builtin_ia32_fixupimmps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_ps_512 : - GCCBuiltin<"__builtin_ia32_fixupimmps512_maskz">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_sd : - GCCBuiltin<"__builtin_ia32_fixupimmsd_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_sd : - GCCBuiltin<"__builtin_ia32_fixupimmsd_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_fixupimm_ss : - GCCBuiltin<"__builtin_ia32_fixupimmss_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_maskz_fixupimm_ss : - GCCBuiltin<"__builtin_ia32_fixupimmss_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_getexp_pd_128 : GCCBuiltin<"__builtin_ia32_getexppd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_getexp_pd_256 : GCCBuiltin<"__builtin_ia32_getexppd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_getexp_pd_512 : GCCBuiltin<"__builtin_ia32_getexppd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_getexp_ps_128 : GCCBuiltin<"__builtin_ia32_getexpps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_getexp_ps_256 : GCCBuiltin<"__builtin_ia32_getexpps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_getexp_ps_512 : GCCBuiltin<"__builtin_ia32_getexpps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getexp_ss : GCCBuiltin<"__builtin_ia32_getexpss128_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_getexp_sd : GCCBuiltin<"__builtin_ia32_getexpsd128_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getmant_pd_128 : - GCCBuiltin<"__builtin_ia32_getmantpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty,llvm_i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getmant_pd_256 : - GCCBuiltin<"__builtin_ia32_getmantpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty,llvm_i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getmant_pd_512 : - GCCBuiltin<"__builtin_ia32_getmantpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty,llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty,llvm_i32_ty ], - [IntrNoMem, ImmArg>, ImmArg>]>; - - def int_x86_avx512_mask_getmant_ps_128 : - GCCBuiltin<"__builtin_ia32_getmantps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getmant_ps_256 : - GCCBuiltin<"__builtin_ia32_getmantps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_getmant_ps_512 : - GCCBuiltin<"__builtin_ia32_getmantps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty,llvm_i32_ty, llvm_v16f32_ty,llvm_i16_ty,llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - - def int_x86_avx512_mask_getmant_ss : - GCCBuiltin<"__builtin_ia32_getmantss_round_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - - def int_x86_avx512_mask_getmant_sd : - GCCBuiltin<"__builtin_ia32_getmantsd_round_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; - - def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_rsqrt14_pd_128 : GCCBuiltin<"__builtin_ia32_rsqrt14pd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_pd_256 : GCCBuiltin<"__builtin_ia32_rsqrt14pd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_ps_128 : GCCBuiltin<"__builtin_ia32_rsqrt14ps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrt14ps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_rcp14_pd_128 : GCCBuiltin<"__builtin_ia32_rcp14pd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_pd_256 : GCCBuiltin<"__builtin_ia32_rcp14pd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_ps_128 : GCCBuiltin<"__builtin_ia32_rcp14ps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_ps_256 : GCCBuiltin<"__builtin_ia32_rcp14ps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrNoMem]>; - - def int_x86_avx512_rcp28_ps : GCCBuiltin<"__builtin_ia32_rcp28ps_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rsqrt28_ps : GCCBuiltin<"__builtin_ia32_rsqrt28ps_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rsqrt28_pd : GCCBuiltin<"__builtin_ia32_rsqrt28pd_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss_round_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd_round_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_avx512_psad_bw_512 : GCCBuiltin<"__builtin_ia32_psadbw512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty], - [IntrNoMem, Commutative]>; -} -// Integer arithmetic ops -let TargetPrefix = "x86" in { - def int_x86_avx512_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v32i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v32i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_pavg_b_512 : GCCBuiltin<"__builtin_ia32_pavgb512">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty], - [IntrNoMem]>; - def int_x86_avx512_pavg_w_512 : GCCBuiltin<"__builtin_ia32_pavgw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], - [IntrNoMem]>; - def int_x86_avx512_pmaddw_d_512 : GCCBuiltin<"__builtin_ia32_pmaddwd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v32i16_ty, - llvm_v32i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_pmaddubs_w_512 : GCCBuiltin<"__builtin_ia32_pmaddubsw512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v64i8_ty, - llvm_v64i8_ty], [IntrNoMem]>; - - def int_x86_avx512_dbpsadbw_128 : - GCCBuiltin<"__builtin_ia32_dbpsadbw128">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_dbpsadbw_256 : - GCCBuiltin<"__builtin_ia32_dbpsadbw256">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_dbpsadbw_512 : - GCCBuiltin<"__builtin_ia32_dbpsadbw512">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -} - -// Gather and Scatter ops -let TargetPrefix = "x86" in { - // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_gather_dpd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, - llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_dps_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, - llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_qpd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_qps_512 : - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - - def int_x86_avx512_gather_dpq_512 : - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_dpi_512 : - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, - llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_qpq_512 : - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_gather_qpi_512 : - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div2_df : - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div2_di : - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div4_df : - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div4_di : - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div4_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div4_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div8_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3div8_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv2_df : - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv2_di : - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv4_df : - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv4_di : - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv4_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv4_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv8_sf : - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_gather3siv8_si : - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - -// scatter - // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_scatter_dpd_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_dps_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, - llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_qpd_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_qps_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [ImmArg>]>; - - - def int_x86_avx512_scatter_dpq_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_dpi_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_qpq_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_scatter_qpi_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty, - llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv2_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv2_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv4_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv4_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv4_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv4_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv8_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scatterdiv8_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv2_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv2_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv4_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv4_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv4_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv4_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv8_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_scattersiv8_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [ImmArg>]>; - - // gather prefetch - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_gatherpf_dps_512 : GCCBuiltin<"__builtin_ia32_gatherpfdps">, - Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_gatherpf_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfqpd">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_gatherpf_qps_512 : GCCBuiltin<"__builtin_ia32_gatherpfqps">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - - // scatter prefetch - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_scatterpf_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfdpd">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_scatterpf_dps_512 : GCCBuiltin<"__builtin_ia32_scatterpfdps">, - Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_scatterpf_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfqpd">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; - def int_x86_avx512_scatterpf_qps_512 : GCCBuiltin<"__builtin_ia32_scatterpfqps">, - Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [ImmArg>, ImmArg>]>; -} - -// AVX512 gather/scatter intrinsics that use vXi1 masks. -let TargetPrefix = "x86" in { - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_mask_gather_dpd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, - llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_dps_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, - llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_qpd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_qps_512 : - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - - def int_x86_avx512_mask_gather_dpq_512 : - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_dpi_512 : - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, - llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_qpq_512 : - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - def int_x86_avx512_mask_gather_qpi_512 : - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, - llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div2_df : - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div2_di : - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div4_df : - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div4_di : - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div4_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div4_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div8_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3div8_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv2_df : - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv2_di : - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv4_df : - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv4_di : - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv4_sf : - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv4_si : - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv8_sf : - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_gather3siv8_si : - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, ImmArg>]>; - - def int_x86_avx512_mask_scatter_dpd_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, - llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_dps_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, - llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_qpd_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, - llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_qps_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, - llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [ImmArg>]>; - - - // NOTE: These can't be ArgMemOnly because you can put the address completely - // in the index register. - def int_x86_avx512_mask_scatter_dpq_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, - llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_dpi_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_qpq_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty,llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i32_ty], - [ImmArg>]>; - def int_x86_avx512_mask_scatter_qpi_512 : - Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i32_ty, - llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv2_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv2_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv4_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv4_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv4_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv4_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv8_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scatterdiv8_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv2_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv2_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv4_df : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv4_di : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv4_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv4_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv8_sf : - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [ImmArg>]>; - - def int_x86_avx512_mask_scattersiv8_si : - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [ImmArg>]>; -} - -// AVX-512 conflict detection instruction -// Instructions that count the number of leading zero bits -let TargetPrefix = "x86" in { - def int_x86_avx512_conflict_d_128 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_conflict_d_256 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_conflict_d_512 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], [IntrNoMem]>; - - def int_x86_avx512_conflict_q_128 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_conflict_q_256 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_conflict_q_512 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], [IntrNoMem]>; -} - -// Compares -let TargetPrefix = "x86" in { - // 512-bit - def int_x86_avx512_vcomi_sd : GCCBuiltin<"__builtin_ia32_vcomisd">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_vcomi_ss : GCCBuiltin<"__builtin_ia32_vcomiss">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -// Compress, Expand -let TargetPrefix = "x86" in { - def int_x86_avx512_mask_compress : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrNoMem]>; - def int_x86_avx512_mask_expand : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrNoMem]>; -} - -// truncate -let TargetPrefix = "x86" in { - def int_x86_avx512_mask_pmov_qb_128 : - GCCBuiltin<"__builtin_ia32_pmovqb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovqb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qb_128 : - GCCBuiltin<"__builtin_ia32_pmovsqb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovsqb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qb_128 : - GCCBuiltin<"__builtin_ia32_pmovusqb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovusqb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qb_256 : - GCCBuiltin<"__builtin_ia32_pmovqb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovqb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qb_256 : - GCCBuiltin<"__builtin_ia32_pmovsqb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovsqb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qb_256 : - GCCBuiltin<"__builtin_ia32_pmovusqb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovusqb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qb_512 : - GCCBuiltin<"__builtin_ia32_pmovqb512_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovqb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qb_512 : - GCCBuiltin<"__builtin_ia32_pmovsqb512_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovsqb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qb_512 : - GCCBuiltin<"__builtin_ia32_pmovusqb512_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovusqb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qw_128 : - GCCBuiltin<"__builtin_ia32_pmovqw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovqw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qw_128 : - GCCBuiltin<"__builtin_ia32_pmovsqw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovsqw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qw_128 : - GCCBuiltin<"__builtin_ia32_pmovusqw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovusqw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qw_256 : - GCCBuiltin<"__builtin_ia32_pmovqw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovqw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qw_256 : - GCCBuiltin<"__builtin_ia32_pmovsqw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovsqw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qw_256 : - GCCBuiltin<"__builtin_ia32_pmovusqw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovusqw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qw_512 : - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovqw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qw_512 : - GCCBuiltin<"__builtin_ia32_pmovsqw512_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovsqw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qw_512 : - GCCBuiltin<"__builtin_ia32_pmovusqw512_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovusqw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_128 : - GCCBuiltin<"__builtin_ia32_pmovqd128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_qd_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovqd128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qd_128 : - GCCBuiltin<"__builtin_ia32_pmovsqd128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qd_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovsqd128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qd_128 : - GCCBuiltin<"__builtin_ia32_pmovusqd128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qd_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovusqd128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovqd256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qd_256 : - GCCBuiltin<"__builtin_ia32_pmovsqd256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qd_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovsqd256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qd_256 : - GCCBuiltin<"__builtin_ia32_pmovusqd256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qd_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovusqd256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovqd512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_qd_512 : - GCCBuiltin<"__builtin_ia32_pmovsqd512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_qd_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovsqd512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_qd_512 : - GCCBuiltin<"__builtin_ia32_pmovusqd512_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_qd_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovusqd512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_db_128 : - GCCBuiltin<"__builtin_ia32_pmovdb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_db_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovdb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_db_128 : - GCCBuiltin<"__builtin_ia32_pmovsdb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_db_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovsdb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_db_128 : - GCCBuiltin<"__builtin_ia32_pmovusdb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_db_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovusdb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_db_256 : - GCCBuiltin<"__builtin_ia32_pmovdb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_db_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovdb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_db_256 : - GCCBuiltin<"__builtin_ia32_pmovsdb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_db_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovsdb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_db_256 : - GCCBuiltin<"__builtin_ia32_pmovusdb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_db_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovusdb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_db_512 : - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_db_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovdb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_db_512 : - GCCBuiltin<"__builtin_ia32_pmovsdb512_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_db_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovsdb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_db_512 : - GCCBuiltin<"__builtin_ia32_pmovusdb512_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_db_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovusdb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_dw_128 : - GCCBuiltin<"__builtin_ia32_pmovdw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_dw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovdw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_dw_128 : - GCCBuiltin<"__builtin_ia32_pmovsdw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_dw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovsdw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_dw_128 : - GCCBuiltin<"__builtin_ia32_pmovusdw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_dw_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovusdw128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_dw_256 : - GCCBuiltin<"__builtin_ia32_pmovdw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_dw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovdw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_dw_256 : - GCCBuiltin<"__builtin_ia32_pmovsdw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_dw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovsdw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_dw_256 : - GCCBuiltin<"__builtin_ia32_pmovusdw256_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_dw_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovusdw256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_dw_512 : - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_dw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovdw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_dw_512 : - GCCBuiltin<"__builtin_ia32_pmovsdw512_mask">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_dw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovsdw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_dw_512 : - GCCBuiltin<"__builtin_ia32_pmovusdw512_mask">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_dw_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovusdw512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_128 : - GCCBuiltin<"__builtin_ia32_pmovwb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmov_wb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovwb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_wb_128 : - GCCBuiltin<"__builtin_ia32_pmovswb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_wb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovswb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_wb_128 : - GCCBuiltin<"__builtin_ia32_pmovuswb128_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_wb_mem_128 : - GCCBuiltin<"__builtin_ia32_pmovuswb128mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovwb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_wb_256 : - GCCBuiltin<"__builtin_ia32_pmovswb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_wb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovswb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_wb_256 : - GCCBuiltin<"__builtin_ia32_pmovuswb256_mask">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_wb_mem_256 : - GCCBuiltin<"__builtin_ia32_pmovuswb256mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovwb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovs_wb_512 : - GCCBuiltin<"__builtin_ia32_pmovswb512_mask">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovs_wb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovswb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmovus_wb_512 : - GCCBuiltin<"__builtin_ia32_pmovuswb512_mask">, - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmovus_wb_mem_512 : - GCCBuiltin<"__builtin_ia32_pmovuswb512mem_mask">, - Intrinsic<[], - [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrArgMemOnly]>; -} - -// Bitwise ternary logic -let TargetPrefix = "x86" in { - def int_x86_avx512_pternlog_d_128 : - GCCBuiltin<"__builtin_ia32_pternlogd128">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_pternlog_d_256 : - GCCBuiltin<"__builtin_ia32_pternlogd256">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_pternlog_d_512 : - GCCBuiltin<"__builtin_ia32_pternlogd512">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, - llvm_i32_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_pternlog_q_128 : - GCCBuiltin<"__builtin_ia32_pternlogq128">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_pternlog_q_256 : - GCCBuiltin<"__builtin_ia32_pternlogq256">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_pternlog_q_512 : - GCCBuiltin<"__builtin_ia32_pternlogq512">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; -} - -// vp2intersect -let TargetPrefix = "x86" in { - def int_x86_avx512_vp2intersect_q_512 : - Intrinsic<[llvm_v8i1_ty, llvm_v8i1_ty], - [llvm_v8i64_ty, llvm_v8i64_ty], - [IntrNoMem]>; - def int_x86_avx512_vp2intersect_q_256 : - Intrinsic<[llvm_v4i1_ty, llvm_v4i1_ty], - [llvm_v4i64_ty, llvm_v4i64_ty], - [IntrNoMem]>; - def int_x86_avx512_vp2intersect_q_128 : - Intrinsic<[llvm_v2i1_ty, llvm_v2i1_ty], - [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_avx512_vp2intersect_d_512 : - Intrinsic<[llvm_v16i1_ty, llvm_v16i1_ty], - [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; - def int_x86_avx512_vp2intersect_d_256 : - Intrinsic<[llvm_v8i1_ty, llvm_v8i1_ty], - [llvm_v8i32_ty, llvm_v8i32_ty], - [IntrNoMem]>; - def int_x86_avx512_vp2intersect_d_128 : - Intrinsic<[llvm_v4i1_ty, llvm_v4i1_ty], - [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; -} - -// Misc. -let TargetPrefix = "x86" in { - // NOTE: These comparison intrinsics are not used by clang as long as the - // distinction in signaling behaviour is not implemented. - def int_x86_avx512_mask_cmp_ps_512 : - Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_cmp_pd_512 : - Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_cmp_ps_256 : - Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i32_ty, llvm_v8i1_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_cmp_pd_256 : - Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i32_ty, llvm_v4i1_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_cmp_ps_128 : - Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty, llvm_v4i1_ty], [IntrNoMem, ImmArg>]>; - def int_x86_avx512_mask_cmp_pd_128 : - Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty, llvm_v2i1_ty], [IntrNoMem, ImmArg>]>; - - def int_x86_avx512_mask_cmp_ss : - GCCBuiltin<"__builtin_ia32_cmpss_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; - def int_x86_avx512_mask_cmp_sd : - GCCBuiltin<"__builtin_ia32_cmpsd_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>, ImmArg>]>; -} - -//===----------------------------------------------------------------------===// -// SHA intrinsics -let TargetPrefix = "x86" in { - def int_x86_sha1rnds4 : GCCBuiltin<"__builtin_ia32_sha1rnds4">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem, ImmArg>]>; - def int_x86_sha1nexte : GCCBuiltin<"__builtin_ia32_sha1nexte">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sha1msg1 : GCCBuiltin<"__builtin_ia32_sha1msg1">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sha1msg2 : GCCBuiltin<"__builtin_ia32_sha1msg2">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sha256rnds2 : GCCBuiltin<"__builtin_ia32_sha256rnds2">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_sha256msg1 : GCCBuiltin<"__builtin_ia32_sha256msg1">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// Thread synchronization ops with timer. -let TargetPrefix = "x86" in { - def int_x86_monitorx - : GCCBuiltin<"__builtin_ia32_monitorx">, - Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty ], []>; - def int_x86_mwaitx - : GCCBuiltin<"__builtin_ia32_mwaitx">, - Intrinsic<[], [ llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], []>; -} - -//===----------------------------------------------------------------------===// -// Cache-line zero -let TargetPrefix = "x86" in { - def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">, - Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Cache write back intrinsics - -let TargetPrefix = "x86" in { - // Write back and invalidate - def int_x86_wbinvd : GCCBuiltin<"__builtin_ia32_wbinvd">, - Intrinsic<[], [], []>; - - // Write back no-invalidate - def int_x86_wbnoinvd : GCCBuiltin<"__builtin_ia32_wbnoinvd">, - Intrinsic<[], [], []>; -} - -//===----------------------------------------------------------------------===// -// Cache-line demote - -let TargetPrefix = "x86" in { - def int_x86_cldemote : GCCBuiltin<"__builtin_ia32_cldemote">, - Intrinsic<[], [llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Wait and pause enhancements -let TargetPrefix = "x86" in { - def int_x86_umonitor : GCCBuiltin<"__builtin_ia32_umonitor">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_umwait : GCCBuiltin<"__builtin_ia32_umwait">, - Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_x86_tpause : GCCBuiltin<"__builtin_ia32_tpause">, - Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Direct Move Instructions - -let TargetPrefix = "x86" in { - def int_x86_directstore32 : GCCBuiltin<"__builtin_ia32_directstore_u32">, - Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], []>; - def int_x86_directstore64 : GCCBuiltin<"__builtin_ia32_directstore_u64">, - Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], []>; - def int_x86_movdir64b : GCCBuiltin<"__builtin_ia32_movdir64b">, - Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// PTWrite - Write data to processor trace pocket - -let TargetPrefix = "x86" in { - def int_x86_ptwrite32 : GCCBuiltin<"__builtin_ia32_ptwrite32">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_x86_ptwrite64 : GCCBuiltin<"__builtin_ia32_ptwrite64">, - Intrinsic<[], [llvm_i64_ty], []>; -} - -//===----------------------------------------------------------------------===// -// INVPCID - Invalidate Process-Context Identifier - -let TargetPrefix = "x86" in { - def int_x86_invpcid : GCCBuiltin<"__builtin_ia32_invpcid">, - Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>; -} - -let TargetPrefix = "x86" in { - def int_x86_avx512bf16_cvtne2ps2bf16_128: - GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_avx512bf16_cvtne2ps2bf16_256: - GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_avx512bf16_cvtne2ps2bf16_512: - GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_512">, - Intrinsic<[llvm_v32i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty], - [IntrNoMem]>; - // Intrinsic must be masked due to it producing less than 128 bits of results. - def int_x86_avx512bf16_mask_cvtneps2bf16_128: - Intrinsic<[llvm_v8i16_ty], - [llvm_v4f32_ty, llvm_v8i16_ty, llvm_v4i1_ty], - [IntrNoMem]>; - def int_x86_avx512bf16_cvtneps2bf16_256: - GCCBuiltin<"__builtin_ia32_cvtneps2bf16_256">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx512bf16_cvtneps2bf16_512: - GCCBuiltin<"__builtin_ia32_cvtneps2bf16_512">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty], [IntrNoMem]>; - def int_x86_avx512bf16_dpbf16ps_128: - GCCBuiltin<"__builtin_ia32_dpbf16ps_128">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512bf16_dpbf16ps_256: - GCCBuiltin<"__builtin_ia32_dpbf16ps_256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512bf16_dpbf16ps_512: - GCCBuiltin<"__builtin_ia32_dpbf16ps_512">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// ENQCMD - Enqueue Stores Instructions - -let TargetPrefix = "x86" in { - def int_x86_enqcmd : GCCBuiltin<"__builtin_ia32_enqcmd">, - Intrinsic<[llvm_i8_ty], [llvm_ptr_ty, llvm_ptr_ty], []>; - def int_x86_enqcmds : GCCBuiltin<"__builtin_ia32_enqcmds">, - Intrinsic<[llvm_i8_ty], [llvm_ptr_ty, llvm_ptr_ty], []>; -} - -//===----------------------------------------------------------------------===// -// SERIALIZE - Serialize instruction fetch and execution - -let TargetPrefix = "x86" in { - def int_x86_serialize : GCCBuiltin<"__builtin_ia32_serialize">, - Intrinsic<[], [], []>; -} - -//===----------------------------------------------------------------------===// -// TSXLDTRK - TSX Suspend Load Address Tracking - -let TargetPrefix = "x86" in { - def int_x86_xsusldtrk : GCCBuiltin<"__builtin_ia32_xsusldtrk">, - Intrinsic<[], [], []>; - def int_x86_xresldtrk : GCCBuiltin<"__builtin_ia32_xresldtrk">, - Intrinsic<[], [], []>; -} - -//===----------------------------------------------------------------------===// -// Key Locker -let TargetPrefix = "x86" in { - def int_x86_loadiwkey : GCCBuiltin<"__builtin_ia32_loadiwkey">, - Intrinsic<[], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - []>; - def int_x86_encodekey128 : - Intrinsic<[llvm_i32_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_i32_ty, llvm_v2i64_ty], []>; - def int_x86_encodekey256 : - Intrinsic<[llvm_i32_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_i32_ty, llvm_v2i64_ty, llvm_v2i64_ty], []>; - def int_x86_aesenc128kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty], []>; - def int_x86_aesdec128kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty], []>; - def int_x86_aesenc256kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty], []>; - def int_x86_aesdec256kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty], []>; - def int_x86_aesencwide128kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], []>; - def int_x86_aesdecwide128kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], []>; - def int_x86_aesencwide256kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], []>; - def int_x86_aesdecwide256kl : - Intrinsic<[llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], - [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], []>; -} - -//===----------------------------------------------------------------------===// -// AMX - Intel AMX extensions - -let TargetPrefix = "x86" in { - def int_x86_ldtilecfg : GCCBuiltin<"__builtin_ia32_tile_loadconfig">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_sttilecfg : GCCBuiltin<"__builtin_ia32_tile_storeconfig">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_tilerelease : GCCBuiltin<"__builtin_ia32_tilerelease">, - Intrinsic<[], [], []>; - def int_x86_tilezero : GCCBuiltin<"__builtin_ia32_tilezero">, - Intrinsic<[], [llvm_i8_ty], [ImmArg>]>; - def int_x86_tileloadd64 : GCCBuiltin<"__builtin_ia32_tileloadd64">, - Intrinsic<[], [llvm_i8_ty, llvm_ptr_ty, llvm_i64_ty], - [ImmArg>]>; - def int_x86_tileloaddt164 : GCCBuiltin<"__builtin_ia32_tileloaddt164">, - Intrinsic<[], [llvm_i8_ty, llvm_ptr_ty, llvm_i64_ty], - [ImmArg>]>; - def int_x86_tilestored64 : GCCBuiltin<"__builtin_ia32_tilestored64">, - Intrinsic<[], [llvm_i8_ty, llvm_ptr_ty, llvm_i64_ty], - [ImmArg>]>; - def int_x86_tdpbssd : GCCBuiltin<"__builtin_ia32_tdpbssd">, - Intrinsic<[], [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [ImmArg>, ImmArg>, - ImmArg>]>; - def int_x86_tdpbsud : GCCBuiltin<"__builtin_ia32_tdpbsud">, - Intrinsic<[], [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [ImmArg>, ImmArg>, - ImmArg>]>; - def int_x86_tdpbusd : GCCBuiltin<"__builtin_ia32_tdpbusd">, - Intrinsic<[], [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [ImmArg>, ImmArg>, - ImmArg>]>; - def int_x86_tdpbuud : GCCBuiltin<"__builtin_ia32_tdpbuud">, - Intrinsic<[], [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [ImmArg>, ImmArg>, - ImmArg>]>; - def int_x86_tdpbf16ps : GCCBuiltin<"__builtin_ia32_tdpbf16ps">, - Intrinsic<[], [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [ImmArg>, ImmArg>, - ImmArg>]>; - // AMX - internal intrinsics - def int_x86_ldtilecfg_internal : - GCCBuiltin<"__builtin_ia32_tile_loadconfig_internal">, - Intrinsic<[], [llvm_ptr_ty], []>; - def int_x86_tileloadd64_internal : - GCCBuiltin<"__builtin_ia32_tileloadd64_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_ptr_ty, llvm_i64_ty], - []>; - def int_x86_tileloaddt164_internal : - GCCBuiltin<"__builtin_ia32_tileloaddt164_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_ptr_ty, llvm_i64_ty], - []>; - def int_x86_tdpbssd_internal : - GCCBuiltin<"__builtin_ia32_tdpbssd_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, - llvm_x86amx_ty, llvm_x86amx_ty, - llvm_x86amx_ty], []>; - def int_x86_tdpbsud_internal : - GCCBuiltin<"__builtin_ia32_tdpbsud_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, - llvm_x86amx_ty, llvm_x86amx_ty, - llvm_x86amx_ty], []>; - def int_x86_tdpbusd_internal : - GCCBuiltin<"__builtin_ia32_tdpbusd_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, - llvm_x86amx_ty, llvm_x86amx_ty, - llvm_x86amx_ty], []>; - def int_x86_tdpbuud_internal : - GCCBuiltin<"__builtin_ia32_tdpbuud_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, - llvm_x86amx_ty, llvm_x86amx_ty, - llvm_x86amx_ty], []>; - def int_x86_tilestored64_internal : - GCCBuiltin<"__builtin_ia32_tilestored64_internal">, - Intrinsic<[], [llvm_i16_ty, llvm_i16_ty, llvm_ptr_ty, - llvm_i64_ty, llvm_x86amx_ty], []>; - def int_x86_tilezero_internal : - GCCBuiltin<"__builtin_ia32_tilezero_internal">, - Intrinsic<[llvm_x86amx_ty], [llvm_i16_ty, llvm_i16_ty], - []>; - def int_x86_tdpbf16ps_internal : - GCCBuiltin<"__builtin_ia32_tdpbf16ps_internal">, - Intrinsic<[llvm_x86amx_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, - llvm_x86amx_ty, llvm_x86amx_ty, - llvm_x86amx_ty], []>; - def int_x86_cast_vector_to_tile: - Intrinsic<[llvm_x86amx_ty], [llvm_anyvector_ty], [IntrNoMem]>; - def int_x86_cast_tile_to_vector: - Intrinsic<[llvm_anyvector_ty], [llvm_x86amx_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// UINTR - User Level Interrupt - -let TargetPrefix = "x86" in { - def int_x86_clui : GCCBuiltin<"__builtin_ia32_clui">, - Intrinsic<[], [], []>; - def int_x86_stui : GCCBuiltin<"__builtin_ia32_stui">, - Intrinsic<[], [], []>; - def int_x86_testui : GCCBuiltin<"__builtin_ia32_testui">, - Intrinsic<[llvm_i8_ty], [], []>; - def int_x86_senduipi : GCCBuiltin<"__builtin_ia32_senduipi">, - Intrinsic<[], [llvm_i64_ty], []>; -} - -//===----------------------------------------------------------------------===// -// avx512_fp16: vaddph -let TargetPrefix = "x86" in { - def int_x86_avx512fp16_add_ph_512 - : GCCBuiltin<"__builtin_ia32_addph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_sub_ph_512 - : GCCBuiltin<"__builtin_ia32_subph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mul_ph_512 - : GCCBuiltin<"__builtin_ia32_mulph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_div_ph_512 - : GCCBuiltin<"__builtin_ia32_divph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_max_ph_128 - : GCCBuiltin<"__builtin_ia32_maxph128">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_max_ph_256 - : GCCBuiltin<"__builtin_ia32_maxph256">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_max_ph_512 - : GCCBuiltin<"__builtin_ia32_maxph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_min_ph_128 - : GCCBuiltin<"__builtin_ia32_minph128">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_min_ph_256 - : GCCBuiltin<"__builtin_ia32_minph256">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_min_ph_512 - : GCCBuiltin<"__builtin_ia32_minph512">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_cmp_ph_512 - : Intrinsic<[ llvm_v32i1_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty, llvm_v32i1_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_cmp_ph_256 - : Intrinsic<[ llvm_v16i1_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_i32_ty, llvm_v16i1_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_cmp_ph_128 - : Intrinsic<[ llvm_v8i1_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i32_ty, llvm_v8i1_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_add_sh_round - : GCCBuiltin<"__builtin_ia32_addsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_sub_sh_round - : GCCBuiltin<"__builtin_ia32_subsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_mul_sh_round - : GCCBuiltin<"__builtin_ia32_mulsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_div_sh_round - : GCCBuiltin<"__builtin_ia32_divsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_min_sh_round - : GCCBuiltin<"__builtin_ia32_minsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_max_sh_round - : GCCBuiltin<"__builtin_ia32_maxsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_cmp_sh - : GCCBuiltin<"__builtin_ia32_cmpsh_mask">, - Intrinsic<[ llvm_i8_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_vcomi_sh - : GCCBuiltin<"__builtin_ia32_vcomish">, - Intrinsic<[ llvm_i32_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - - def int_x86_avx512fp16_mask_vcvtph2psx_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2psx128_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v8f16_ty, llvm_v4f32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2psx_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2psx256_mask">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f16_ty, llvm_v8f32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2psx_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2psx512_mask">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f16_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtps2phx_128 - : GCCBuiltin<"__builtin_ia32_vcvtps2phx128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4f32_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtps2phx_256 - : GCCBuiltin<"__builtin_ia32_vcvtps2phx256_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f32_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtps2phx_512 - : GCCBuiltin<"__builtin_ia32_vcvtps2phx512_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f32_ty, llvm_v16f16_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtpd2ph_128 - : GCCBuiltin<"__builtin_ia32_vcvtpd2ph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v2f64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtpd2ph_256 - : GCCBuiltin<"__builtin_ia32_vcvtpd2ph256_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4f64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtpd2ph_512 - : GCCBuiltin<"__builtin_ia32_vcvtpd2ph512_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f64_ty, llvm_v8f16_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtph2pd_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2pd128_mask">, - Intrinsic<[ llvm_v2f64_ty ], - [ llvm_v8f16_ty, llvm_v2f64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2pd_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2pd256_mask">, - Intrinsic<[ llvm_v4f64_ty ], - [ llvm_v8f16_ty, llvm_v4f64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2pd_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2pd512_mask">, - Intrinsic<[ llvm_v8f64_ty ], - [ llvm_v8f16_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtsh2ss_round - : GCCBuiltin<"__builtin_ia32_vcvtsh2ss_round_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v8f16_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtss2sh_round - : GCCBuiltin<"__builtin_ia32_vcvtss2sh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v4f32_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtsd2sh_round - : GCCBuiltin<"__builtin_ia32_vcvtsd2sh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v2f64_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtsh2sd_round - : GCCBuiltin<"__builtin_ia32_vcvtsh2sd_round_mask">, - Intrinsic<[ llvm_v2f64_ty ], - [ llvm_v2f64_ty, llvm_v8f16_ty, llvm_v2f64_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_vcvtph2w_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2w128_mask">, - Intrinsic<[ llvm_v8i16_ty ], - [ llvm_v8f16_ty, llvm_v8i16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2w_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2w256_mask">, - Intrinsic<[ llvm_v16i16_ty ], - [ llvm_v16f16_ty, llvm_v16i16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2w_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2w512_mask">, - Intrinsic<[ llvm_v32i16_ty ], - [ llvm_v32f16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvttph2w_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2w128_mask">, - Intrinsic<[ llvm_v8i16_ty ], - [ llvm_v8f16_ty, llvm_v8i16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2w_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2w256_mask">, - Intrinsic<[ llvm_v16i16_ty ], - [ llvm_v16f16_ty, llvm_v16i16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2w_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2w512_mask">, - Intrinsic<[ llvm_v32i16_ty ], - [ llvm_v32f16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtph2uw_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2uw128_mask">, - Intrinsic<[ llvm_v8i16_ty ], - [ llvm_v8f16_ty, llvm_v8i16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2uw_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2uw256_mask">, - Intrinsic<[ llvm_v16i16_ty ], - [ llvm_v16f16_ty, llvm_v16i16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2uw_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2uw512_mask">, - Intrinsic<[ llvm_v32i16_ty ], - [ llvm_v32f16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvttph2uw_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2uw128_mask">, - Intrinsic<[ llvm_v8i16_ty ], - [ llvm_v8f16_ty, llvm_v8i16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2uw_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2uw256_mask">, - Intrinsic<[ llvm_v16i16_ty ], - [ llvm_v16f16_ty, llvm_v16i16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2uw_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2uw512_mask">, - Intrinsic<[ llvm_v32i16_ty ], - [ llvm_v32f16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_vcvtph2dq_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2dq128_mask">, - Intrinsic<[ llvm_v4i32_ty ], - [ llvm_v8f16_ty, llvm_v4i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2dq_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2dq256_mask">, - Intrinsic<[ llvm_v8i32_ty ], - [ llvm_v8f16_ty, llvm_v8i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2dq_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2dq512_mask">, - Intrinsic<[ llvm_v16i32_ty ], - [ llvm_v16f16_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtph2udq_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2udq128_mask">, - Intrinsic<[ llvm_v4i32_ty ], - [ llvm_v8f16_ty, llvm_v4i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2udq_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2udq256_mask">, - Intrinsic<[ llvm_v8i32_ty ], - [ llvm_v8f16_ty, llvm_v8i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2udq_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2udq512_mask">, - Intrinsic<[ llvm_v16i32_ty ], - [ llvm_v16f16_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtdq2ph_128 - : GCCBuiltin<"__builtin_ia32_vcvtdq2ph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4i32_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtudq2ph_128 - : GCCBuiltin<"__builtin_ia32_vcvtudq2ph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4i32_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2dq_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2dq128_mask">, - Intrinsic<[ llvm_v4i32_ty ], - [ llvm_v8f16_ty, llvm_v4i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2dq_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2dq256_mask">, - Intrinsic<[ llvm_v8i32_ty ], - [ llvm_v8f16_ty, llvm_v8i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2dq_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2dq512_mask">, - Intrinsic<[ llvm_v16i32_ty ], - [ llvm_v16f16_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvttph2udq_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2udq128_mask">, - Intrinsic<[ llvm_v4i32_ty ], - [ llvm_v8f16_ty, llvm_v4i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2udq_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2udq256_mask">, - Intrinsic<[ llvm_v8i32_ty ], - [ llvm_v8f16_ty, llvm_v8i32_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2udq_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2udq512_mask">, - Intrinsic<[ llvm_v16i32_ty ], - [ llvm_v16f16_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_vcvtqq2ph_128 - : GCCBuiltin<"__builtin_ia32_vcvtqq2ph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v2i64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtqq2ph_256 - : GCCBuiltin<"__builtin_ia32_vcvtqq2ph256_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4i64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2qq_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2qq128_mask">, - Intrinsic<[ llvm_v2i64_ty ], - [ llvm_v8f16_ty, llvm_v2i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2qq_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2qq256_mask">, - Intrinsic<[ llvm_v4i64_ty ], - [ llvm_v8f16_ty, llvm_v4i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2qq_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2qq512_mask">, - Intrinsic<[ llvm_v8i64_ty ], - [ llvm_v8f16_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvtuqq2ph_128 - : GCCBuiltin<"__builtin_ia32_vcvtuqq2ph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v2i64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtuqq2ph_256 - : GCCBuiltin<"__builtin_ia32_vcvtuqq2ph256_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v4i64_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2uqq_128 - : GCCBuiltin<"__builtin_ia32_vcvtph2uqq128_mask">, - Intrinsic<[ llvm_v2i64_ty ], - [ llvm_v8f16_ty, llvm_v2i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2uqq_256 - : GCCBuiltin<"__builtin_ia32_vcvtph2uqq256_mask">, - Intrinsic<[ llvm_v4i64_ty ], - [ llvm_v8f16_ty, llvm_v4i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvtph2uqq_512 - : GCCBuiltin<"__builtin_ia32_vcvtph2uqq512_mask">, - Intrinsic<[ llvm_v8i64_ty ], - [ llvm_v8f16_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvttph2qq_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2qq128_mask">, - Intrinsic<[ llvm_v2i64_ty ], - [ llvm_v8f16_ty, llvm_v2i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2qq_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2qq256_mask">, - Intrinsic<[ llvm_v4i64_ty ], - [ llvm_v8f16_ty, llvm_v4i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2qq_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2qq512_mask">, - Intrinsic<[ llvm_v8i64_ty ], - [ llvm_v8f16_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vcvttph2uqq_128 - : GCCBuiltin<"__builtin_ia32_vcvttph2uqq128_mask">, - Intrinsic<[ llvm_v2i64_ty ], - [ llvm_v8f16_ty, llvm_v2i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2uqq_256 - : GCCBuiltin<"__builtin_ia32_vcvttph2uqq256_mask">, - Intrinsic<[ llvm_v4i64_ty ], - [ llvm_v8f16_ty, llvm_v4i64_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vcvttph2uqq_512 - : GCCBuiltin<"__builtin_ia32_vcvttph2uqq512_mask">, - Intrinsic<[ llvm_v8i64_ty ], - [ llvm_v8f16_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_vcvtsh2si32 - : GCCBuiltin<"__builtin_ia32_vcvtsh2si32">, - Intrinsic<[ llvm_i32_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtsh2usi32 - : GCCBuiltin<"__builtin_ia32_vcvtsh2usi32">, - Intrinsic<[ llvm_i32_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtsh2si64 - : GCCBuiltin<"__builtin_ia32_vcvtsh2si64">, - Intrinsic<[ llvm_i64_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtsh2usi64 - : GCCBuiltin<"__builtin_ia32_vcvtsh2usi64">, - Intrinsic<[ llvm_i64_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtusi2sh - : GCCBuiltin<"__builtin_ia32_vcvtusi2sh">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtusi642sh - : GCCBuiltin<"__builtin_ia32_vcvtusi642sh">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i64_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtsi2sh - : GCCBuiltin<"__builtin_ia32_vcvtsi2sh">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvtsi642sh - : GCCBuiltin<"__builtin_ia32_vcvtsi642sh">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i64_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvttsh2si32 - : GCCBuiltin<"__builtin_ia32_vcvttsh2si32">, - Intrinsic<[ llvm_i32_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvttsh2si64 - : GCCBuiltin<"__builtin_ia32_vcvttsh2si64">, - Intrinsic<[ llvm_i64_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvttsh2usi32 - : GCCBuiltin<"__builtin_ia32_vcvttsh2usi32">, - Intrinsic<[ llvm_i32_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vcvttsh2usi64 - : GCCBuiltin<"__builtin_ia32_vcvttsh2usi64">, - Intrinsic<[ llvm_i64_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_sqrt_ph_512 - : Intrinsic<[ llvm_v32f16_ty ], [ llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_sqrt_sh - : Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_rsqrt_ph_128 - : GCCBuiltin<"__builtin_ia32_rsqrtph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rsqrt_ph_256 - : GCCBuiltin<"__builtin_ia32_rsqrtph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rsqrt_ph_512 - : GCCBuiltin<"__builtin_ia32_rsqrtph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rsqrt_sh - : GCCBuiltin<"__builtin_ia32_rsqrtsh_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rcp_ph_128 - : GCCBuiltin<"__builtin_ia32_rcpph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rcp_ph_256 - : GCCBuiltin<"__builtin_ia32_rcpph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rcp_ph_512 - : GCCBuiltin<"__builtin_ia32_rcpph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_rcp_sh - : GCCBuiltin<"__builtin_ia32_rcpsh_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_reduce_ph_128 - : GCCBuiltin<"__builtin_ia32_reduceph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i32_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_reduce_ph_256 - : GCCBuiltin<"__builtin_ia32_reduceph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_i32_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_reduce_ph_512 - : GCCBuiltin<"__builtin_ia32_reduceph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_i32_ty, llvm_v32f16_ty, llvm_i32_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_reduce_sh - : GCCBuiltin<"__builtin_ia32_reducesh_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_fpclass_ph_128 - : Intrinsic<[ llvm_v8i1_ty ], [ llvm_v8f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_fpclass_ph_256 - : Intrinsic<[ llvm_v16i1_ty ], [ llvm_v16f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_fpclass_ph_512 - : Intrinsic<[ llvm_v32i1_ty ], [ llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_fpclass_sh - : GCCBuiltin<"__builtin_ia32_fpclasssh_mask">, - Intrinsic<[ llvm_i8_ty ], [ llvm_v8f16_ty, llvm_i32_ty, llvm_i8_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_getexp_ph_128 - : GCCBuiltin<"__builtin_ia32_getexpph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_getexp_ph_256 - : GCCBuiltin<"__builtin_ia32_getexpph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_getexp_ph_512 - : GCCBuiltin<"__builtin_ia32_getexpph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_getexp_sh - : GCCBuiltin<"__builtin_ia32_getexpsh128_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_getmant_ph_128 - : GCCBuiltin<"__builtin_ia32_getmantph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i32_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_getmant_ph_256 - : GCCBuiltin<"__builtin_ia32_getmantph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_i32_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_getmant_ph_512 - : GCCBuiltin<"__builtin_ia32_getmantph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_i32_ty, llvm_v32f16_ty, llvm_i32_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_getmant_sh - : GCCBuiltin<"__builtin_ia32_getmantsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_i32_ty, llvm_v8f16_ty, - llvm_i8_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_rndscale_ph_128 - : GCCBuiltin<"__builtin_ia32_rndscaleph_128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_i32_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_rndscale_ph_256 - : GCCBuiltin<"__builtin_ia32_rndscaleph_256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_i32_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_rndscale_ph_512 - : GCCBuiltin<"__builtin_ia32_rndscaleph_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_i32_ty, llvm_v32f16_ty, llvm_i32_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_rndscale_sh - : GCCBuiltin<"__builtin_ia32_rndscalesh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg>, ImmArg> ]>; - def int_x86_avx512fp16_mask_scalef_ph_128 - : GCCBuiltin<"__builtin_ia32_scalefph128_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_scalef_ph_256 - : GCCBuiltin<"__builtin_ia32_scalefph256_mask">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_v16f16_ty, llvm_i16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_scalef_ph_512 - : GCCBuiltin<"__builtin_ia32_scalefph512_mask">, - Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_scalef_sh - : GCCBuiltin<"__builtin_ia32_scalefsh_round_mask">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_vfmadd_ph_512 - : Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vfmaddsub_ph_128 - : GCCBuiltin<"__builtin_ia32_vfmaddsubph">, - Intrinsic<[ llvm_v8f16_ty ], - [ llvm_v8f16_ty, llvm_v8f16_ty, llvm_v8f16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_vfmaddsub_ph_256 - : GCCBuiltin<"__builtin_ia32_vfmaddsubph256">, - Intrinsic<[ llvm_v16f16_ty ], - [ llvm_v16f16_ty, llvm_v16f16_ty, llvm_v16f16_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_vfmaddsub_ph_512 - : Intrinsic<[ llvm_v32f16_ty ], - [ llvm_v32f16_ty, llvm_v32f16_ty, llvm_v32f16_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_vfmadd_f16 - : Intrinsic<[ llvm_half_ty ], - [ llvm_half_ty, llvm_half_ty, llvm_half_ty, llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - - def int_x86_avx512fp16_mask_vfcmadd_cph_128 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph128_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_maskz_vfcmadd_cph_128 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph128_maskz">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfcmadd_cph_256 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph256_mask">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_maskz_vfcmadd_cph_256 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph256_maskz">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfcmadd_cph_512 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph512_mask3">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_maskz_vfcmadd_cph_512 - : GCCBuiltin<"__builtin_ia32_vfcmaddcph512_maskz">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfmadd_cph_128 - : GCCBuiltin<"__builtin_ia32_vfmaddcph128_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_maskz_vfmadd_cph_128 - : GCCBuiltin<"__builtin_ia32_vfmaddcph128_maskz">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfmadd_cph_256 - : GCCBuiltin<"__builtin_ia32_vfmaddcph256_mask">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_maskz_vfmadd_cph_256 - : GCCBuiltin<"__builtin_ia32_vfmaddcph256_maskz">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfmadd_cph_512 - : GCCBuiltin<"__builtin_ia32_vfmaddcph512_mask3">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_maskz_vfmadd_cph_512 - : GCCBuiltin<"__builtin_ia32_vfmaddcph512_maskz">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfmadd_csh - : GCCBuiltin<"__builtin_ia32_vfmaddcsh_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_maskz_vfmadd_csh - : GCCBuiltin<"__builtin_ia32_vfmaddcsh_maskz">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfcmadd_csh - : GCCBuiltin<"__builtin_ia32_vfcmaddcsh_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_maskz_vfcmadd_csh - : GCCBuiltin<"__builtin_ia32_vfcmaddcsh_maskz">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfmul_cph_128 - : GCCBuiltin<"__builtin_ia32_vfmulcph128_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfcmul_cph_128 - : GCCBuiltin<"__builtin_ia32_vfcmulcph128_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfmul_cph_256 - : GCCBuiltin<"__builtin_ia32_vfmulcph256_mask">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfcmul_cph_256 - : GCCBuiltin<"__builtin_ia32_vfcmulcph256_mask">, - Intrinsic<[ llvm_v8f32_ty ], - [ llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty ], - [ IntrNoMem ]>; - def int_x86_avx512fp16_mask_vfmul_cph_512 - : GCCBuiltin<"__builtin_ia32_vfmulcph512_mask">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfcmul_cph_512 - : GCCBuiltin<"__builtin_ia32_vfcmulcph512_mask">, - Intrinsic<[ llvm_v16f32_ty ], - [ llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfmul_csh - : GCCBuiltin<"__builtin_ia32_vfmulcsh_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; - def int_x86_avx512fp16_mask_vfcmul_csh - : GCCBuiltin<"__builtin_ia32_vfcmulcsh_mask">, - Intrinsic<[ llvm_v4f32_ty ], - [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty ], - [ IntrNoMem, ImmArg> ]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.h b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.h deleted file mode 100644 index 580f6a414d..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.h +++ /dev/null @@ -1,73 +0,0 @@ -/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ -|* *| -|* Intrinsic Function Source Fragment *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_IR_INTRINSIC_XCORE_ENUMS_H -#define LLVM_IR_INTRINSIC_XCORE_ENUMS_H - -namespace llvm { -namespace Intrinsic { -enum XCOREIntrinsics : unsigned { -// Enum values for intrinsics - xcore_bitrev = 10708, // llvm.xcore.bitrev - xcore_checkevent, // llvm.xcore.checkevent - xcore_chkct, // llvm.xcore.chkct - xcore_clre, // llvm.xcore.clre - xcore_clrpt, // llvm.xcore.clrpt - xcore_clrsr, // llvm.xcore.clrsr - xcore_crc32, // llvm.xcore.crc32 - xcore_crc8, // llvm.xcore.crc8 - xcore_edu, // llvm.xcore.edu - xcore_eeu, // llvm.xcore.eeu - xcore_endin, // llvm.xcore.endin - xcore_freer, // llvm.xcore.freer - xcore_geted, // llvm.xcore.geted - xcore_getet, // llvm.xcore.getet - xcore_getid, // llvm.xcore.getid - xcore_getps, // llvm.xcore.getps - xcore_getr, // llvm.xcore.getr - xcore_getst, // llvm.xcore.getst - xcore_getts, // llvm.xcore.getts - xcore_in, // llvm.xcore.in - xcore_inct, // llvm.xcore.inct - xcore_initcp, // llvm.xcore.initcp - xcore_initdp, // llvm.xcore.initdp - xcore_initlr, // llvm.xcore.initlr - xcore_initpc, // llvm.xcore.initpc - xcore_initsp, // llvm.xcore.initsp - xcore_inshr, // llvm.xcore.inshr - xcore_int, // llvm.xcore.int - xcore_mjoin, // llvm.xcore.mjoin - xcore_msync, // llvm.xcore.msync - xcore_out, // llvm.xcore.out - xcore_outct, // llvm.xcore.outct - xcore_outshr, // llvm.xcore.outshr - xcore_outt, // llvm.xcore.outt - xcore_peek, // llvm.xcore.peek - xcore_setc, // llvm.xcore.setc - xcore_setclk, // llvm.xcore.setclk - xcore_setd, // llvm.xcore.setd - xcore_setev, // llvm.xcore.setev - xcore_setps, // llvm.xcore.setps - xcore_setpsc, // llvm.xcore.setpsc - xcore_setpt, // llvm.xcore.setpt - xcore_setrdy, // llvm.xcore.setrdy - xcore_setsr, // llvm.xcore.setsr - xcore_settw, // llvm.xcore.settw - xcore_setv, // llvm.xcore.setv - xcore_sext, // llvm.xcore.sext - xcore_ssync, // llvm.xcore.ssync - xcore_syncr, // llvm.xcore.syncr - xcore_testct, // llvm.xcore.testct - xcore_testwct, // llvm.xcore.testwct - xcore_waitevent, // llvm.xcore.waitevent - xcore_zext, // llvm.xcore.zext -}; // enum -} // namespace Intrinsic -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.td b/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.td deleted file mode 100644 index 89dbc65fea..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/IntrinsicsXCore.td +++ /dev/null @@ -1,120 +0,0 @@ -//==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the XCore-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". - // Miscellaneous instructions. - def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>, - GCCBuiltin<"__builtin_bitrev">; - def int_xcore_crc8 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], - [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; - def int_xcore_crc32 : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; - def int_xcore_sext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_xcore_zext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>, - GCCBuiltin<"__builtin_getid">; - def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>, - GCCBuiltin<"__builtin_getps">; - def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>, - GCCBuiltin<"__builtin_setps">; - def int_xcore_geted : Intrinsic<[llvm_i32_ty],[]>; - def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; - def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; - def int_xcore_clrsr : Intrinsic<[],[llvm_i32_ty]>; - - // Resource instructions. - def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; - def int_xcore_freer : Intrinsic<[],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_in : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],[NoCapture>]>; - def int_xcore_int : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_inct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_out : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_outt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_outct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_testct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_testwct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_clrpt : Intrinsic<[],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_setev : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture>]>; - def int_xcore_edu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture>]>; - def int_xcore_setclk : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], - [NoCapture>, NoCapture>]>; - def int_xcore_setrdy : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], - [NoCapture>, NoCapture>]>; - def int_xcore_setpsc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], - [NoCapture>]>; - def int_xcore_peek : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_endin : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], - [NoCapture>]>; - - // Intrinsics for events. - def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; - - // If any of the resources owned by the thread are ready this returns the - // vector of one of the ready resources. If no resources owned by the thread - // are ready then the operand passed to the intrinsic is returned. - def int_xcore_checkevent : Intrinsic<[llvm_ptr_ty],[llvm_ptr_ty]>; - - def int_xcore_clre : Intrinsic<[],[],[]>; - - // Intrinsics for threads. - def int_xcore_getst : Intrinsic <[llvm_anyptr_ty],[llvm_anyptr_ty], - [NoCapture>]>; - def int_xcore_msync : Intrinsic <[],[llvm_anyptr_ty], [NoCapture>]>; - def int_xcore_ssync : Intrinsic <[],[]>; - def int_xcore_mjoin : Intrinsic <[],[llvm_anyptr_ty], [NoCapture>]>; - def int_xcore_initsp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_initpc : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_initlr : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_initcp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; - def int_xcore_initdp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], - [NoCapture>]>; -} diff --git a/suite/synctools/tablegen/include/llvm/IR/LLVMContext.h b/suite/synctools/tablegen/include/llvm/IR/LLVMContext.h deleted file mode 100644 index 4250c94ef5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/LLVMContext.h +++ /dev/null @@ -1,341 +0,0 @@ -//===- llvm/LLVMContext.h - Class for managing "global" state ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares LLVMContext, a container of "global" state in LLVM, such -// as the global type and constant uniquing tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LLVMCONTEXT_H -#define LLVM_IR_LLVMCONTEXT_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/DiagnosticHandler.h" -#include "llvm/Support/CBindingWrapping.h" -#include -#include -#include - -namespace llvm { - -class DiagnosticInfo; -enum DiagnosticSeverity : char; -class Function; -class Instruction; -class LLVMContextImpl; -class Module; -class OptPassGate; -template class SmallVectorImpl; -template class StringMapEntry; -class StringRef; -class Twine; -class LLVMRemarkStreamer; - -namespace remarks { -class RemarkStreamer; -} - -namespace SyncScope { - -typedef uint8_t ID; - -/// Known synchronization scope IDs, which always have the same value. All -/// synchronization scope IDs that LLVM has special knowledge of are listed -/// here. Additionally, this scheme allows LLVM to efficiently check for -/// specific synchronization scope ID without comparing strings. -enum { - /// Synchronized with respect to signal handlers executing in the same thread. - SingleThread = 0, - - /// Synchronized with respect to all concurrently executing threads. - System = 1 -}; - -} // end namespace SyncScope - -/// This is an important class for using LLVM in a threaded context. It -/// (opaquely) owns and manages the core "global" data of LLVM's core -/// infrastructure, including the type and constant uniquing tables. -/// LLVMContext itself provides no locking guarantees, so you should be careful -/// to have one context per thread. -class LLVMContext { -public: - LLVMContextImpl *const pImpl; - LLVMContext(); - LLVMContext(LLVMContext &) = delete; - LLVMContext &operator=(const LLVMContext &) = delete; - ~LLVMContext(); - - // Pinned metadata names, which always have the same value. This is a - // compile-time performance optimization, not a correctness optimization. - enum : unsigned { -#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) EnumID = Value, -#include "llvm/IR/FixedMetadataKinds.def" -#undef LLVM_FIXED_MD_KIND - }; - - /// Known operand bundle tag IDs, which always have the same value. All - /// operand bundle tags that LLVM has special knowledge of are listed here. - /// Additionally, this scheme allows LLVM to efficiently check for specific - /// operand bundle tags without comparing strings. Keep this in sync with - /// LLVMContext::LLVMContext(). - enum : unsigned { - OB_deopt = 0, // "deopt" - OB_funclet = 1, // "funclet" - OB_gc_transition = 2, // "gc-transition" - OB_cfguardtarget = 3, // "cfguardtarget" - OB_preallocated = 4, // "preallocated" - OB_gc_live = 5, // "gc-live" - OB_clang_arc_attachedcall = 6, // "clang.arc.attachedcall" - }; - - /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. - /// This ID is uniqued across modules in the current LLVMContext. - unsigned getMDKindID(StringRef Name) const; - - /// getMDKindNames - Populate client supplied SmallVector with the name for - /// custom metadata IDs registered in this LLVMContext. - void getMDKindNames(SmallVectorImpl &Result) const; - - /// getOperandBundleTags - Populate client supplied SmallVector with the - /// bundle tags registered in this LLVMContext. The bundle tags are ordered - /// by increasing bundle IDs. - /// \see LLVMContext::getOperandBundleTagID - void getOperandBundleTags(SmallVectorImpl &Result) const; - - /// getOrInsertBundleTag - Returns the Tag to use for an operand bundle of - /// name TagName. - StringMapEntry *getOrInsertBundleTag(StringRef TagName) const; - - /// getOperandBundleTagID - Maps a bundle tag to an integer ID. Every bundle - /// tag registered with an LLVMContext has an unique ID. - uint32_t getOperandBundleTagID(StringRef Tag) const; - - /// getOrInsertSyncScopeID - Maps synchronization scope name to - /// synchronization scope ID. Every synchronization scope registered with - /// LLVMContext has unique ID except pre-defined ones. - SyncScope::ID getOrInsertSyncScopeID(StringRef SSN); - - /// getSyncScopeNames - Populates client supplied SmallVector with - /// synchronization scope names registered with LLVMContext. Synchronization - /// scope names are ordered by increasing synchronization scope IDs. - void getSyncScopeNames(SmallVectorImpl &SSNs) const; - - /// Define the GC for a function - void setGC(const Function &Fn, std::string GCName); - - /// Return the GC for a function - const std::string &getGC(const Function &Fn); - - /// Remove the GC for a function - void deleteGC(const Function &Fn); - - /// Return true if the Context runtime configuration is set to discard all - /// value names. When true, only GlobalValue names will be available in the - /// IR. - bool shouldDiscardValueNames() const; - - /// Set the Context runtime configuration to discard all value name (but - /// GlobalValue). Clients can use this flag to save memory and runtime, - /// especially in release mode. - void setDiscardValueNames(bool Discard); - - /// Whether there is a string map for uniquing debug info - /// identifiers across the context. Off by default. - bool isODRUniquingDebugTypes() const; - void enableDebugTypeODRUniquing(); - void disableDebugTypeODRUniquing(); - - /// Defines the type of a yield callback. - /// \see LLVMContext::setYieldCallback. - using YieldCallbackTy = void (*)(LLVMContext *Context, void *OpaqueHandle); - - /// setDiagnosticHandlerCallBack - This method sets a handler call back - /// that is invoked when the backend needs to report anything to the user. - /// The first argument is a function pointer and the second is a context pointer - /// that gets passed into the DiagHandler. The third argument should be set to - /// true if the handler only expects enabled diagnostics. - /// - /// LLVMContext doesn't take ownership or interpret either of these - /// pointers. - void setDiagnosticHandlerCallBack( - DiagnosticHandler::DiagnosticHandlerTy DiagHandler, - void *DiagContext = nullptr, bool RespectFilters = false); - - /// setDiagnosticHandler - This method sets unique_ptr to object of - /// DiagnosticHandler to provide custom diagnostic handling. The first - /// argument is unique_ptr of object of type DiagnosticHandler or a derived - /// of that. The second argument should be set to true if the handler only - /// expects enabled diagnostics. - /// - /// Ownership of this pointer is moved to LLVMContextImpl. - void setDiagnosticHandler(std::unique_ptr &&DH, - bool RespectFilters = false); - - /// getDiagnosticHandlerCallBack - Return the diagnostic handler call back set by - /// setDiagnosticHandlerCallBack. - DiagnosticHandler::DiagnosticHandlerTy getDiagnosticHandlerCallBack() const; - - /// getDiagnosticContext - Return the diagnostic context set by - /// setDiagnosticContext. - void *getDiagnosticContext() const; - - /// getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by - /// setDiagnosticHandler. - const DiagnosticHandler *getDiagHandlerPtr() const; - - /// getDiagnosticHandler - transfers ownership of DiagnosticHandler unique_ptr - /// to caller. - std::unique_ptr getDiagnosticHandler(); - - /// Return if a code hotness metric should be included in optimization - /// diagnostics. - bool getDiagnosticsHotnessRequested() const; - /// Set if a code hotness metric should be included in optimization - /// diagnostics. - void setDiagnosticsHotnessRequested(bool Requested); - - /// Return the minimum hotness value a diagnostic would need in order - /// to be included in optimization diagnostics. - /// - /// Three possible return values: - /// 0 - threshold is disabled. Everything will be printed out. - /// positive int - threshold is set. - /// UINT64_MAX - threshold is not yet set, and needs to be synced from - /// profile summary. Note that in case of missing profile - /// summary, threshold will be kept at "MAX", effectively - /// suppresses all remarks output. - uint64_t getDiagnosticsHotnessThreshold() const; - - /// Set the minimum hotness value a diagnostic needs in order to be - /// included in optimization diagnostics. - void setDiagnosticsHotnessThreshold(Optional Threshold); - - /// Return if hotness threshold is requested from PSI. - bool isDiagnosticsHotnessThresholdSetFromPSI() const; - - /// The "main remark streamer" used by all the specialized remark streamers. - /// This streamer keeps generic remark metadata in memory throughout the life - /// of the LLVMContext. This metadata may be emitted in a section in object - /// files depending on the format requirements. - /// - /// All specialized remark streamers should convert remarks to - /// llvm::remarks::Remark and emit them through this streamer. - remarks::RemarkStreamer *getMainRemarkStreamer(); - const remarks::RemarkStreamer *getMainRemarkStreamer() const; - void setMainRemarkStreamer( - std::unique_ptr MainRemarkStreamer); - - /// The "LLVM remark streamer" used by LLVM to serialize remark diagnostics - /// coming from IR and MIR passes. - /// - /// If it does not exist, diagnostics are not saved in a file but only emitted - /// via the diagnostic handler. - LLVMRemarkStreamer *getLLVMRemarkStreamer(); - const LLVMRemarkStreamer *getLLVMRemarkStreamer() const; - void - setLLVMRemarkStreamer(std::unique_ptr RemarkStreamer); - - /// Get the prefix that should be printed in front of a diagnostic of - /// the given \p Severity - static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity); - - /// Report a message to the currently installed diagnostic handler. - /// - /// This function returns, in particular in the case of error reporting - /// (DI.Severity == \a DS_Error), so the caller should leave the compilation - /// process in a self-consistent state, even though the generated code - /// need not be correct. - /// - /// The diagnostic message will be implicitly prefixed with a severity keyword - /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error, - /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note. - void diagnose(const DiagnosticInfo &DI); - - /// Registers a yield callback with the given context. - /// - /// The yield callback function may be called by LLVM to transfer control back - /// to the client that invoked the LLVM compilation. This can be used to yield - /// control of the thread, or perform periodic work needed by the client. - /// There is no guaranteed frequency at which callbacks must occur; in fact, - /// the client is not guaranteed to ever receive this callback. It is at the - /// sole discretion of LLVM to do so and only if it can guarantee that - /// suspending the thread won't block any forward progress in other LLVM - /// contexts in the same process. - /// - /// At a suspend point, the state of the current LLVM context is intentionally - /// undefined. No assumptions about it can or should be made. Only LLVM - /// context API calls that explicitly state that they can be used during a - /// yield callback are allowed to be used. Any other API calls into the - /// context are not supported until the yield callback function returns - /// control to LLVM. Other LLVM contexts are unaffected by this restriction. - void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle); - - /// Calls the yield callback (if applicable). - /// - /// This transfers control of the current thread back to the client, which may - /// suspend the current thread. Only call this method when LLVM doesn't hold - /// any global mutex or cannot block the execution in another LLVM context. - void yield(); - - /// emitError - Emit an error message to the currently installed error handler - /// with optional location information. This function returns, so code should - /// be prepared to drop the erroneous construct on the floor and "not crash". - /// The generated code need not be correct. The error message will be - /// implicitly prefixed with "error: " and should not end with a ".". - void emitError(uint64_t LocCookie, const Twine &ErrorStr); - void emitError(const Instruction *I, const Twine &ErrorStr); - void emitError(const Twine &ErrorStr); - - /// Access the object which can disable optional passes and individual - /// optimizations at compile time. - OptPassGate &getOptPassGate() const; - - /// Set the object which can disable optional passes and individual - /// optimizations at compile time. - /// - /// The lifetime of the object must be guaranteed to extend as long as the - /// LLVMContext is used by compilation. - void setOptPassGate(OptPassGate&); - - /// Enable opaque pointers. Can only be called before creating the first - /// pointer type. - void enableOpaquePointers() const; - - /// Whether typed pointers are supported. If false, all pointers are opaque. - bool supportsTypedPointers() const; - -private: - // Module needs access to the add/removeModule methods. - friend class Module; - - /// addModule - Register a module as being instantiated in this context. If - /// the context is deleted, the module will be deleted as well. - void addModule(Module*); - - /// removeModule - Unregister a module from this context. - void removeModule(Module*); -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef) - -/* Specialized opaque context conversions. - */ -inline LLVMContext **unwrap(LLVMContextRef* Tys) { - return reinterpret_cast(Tys); -} - -inline LLVMContextRef *wrap(const LLVMContext **Tys) { - return reinterpret_cast(const_cast(Tys)); -} - -} // end namespace llvm - -#endif // LLVM_IR_LLVMCONTEXT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/LLVMRemarkStreamer.h b/suite/synctools/tablegen/include/llvm/IR/LLVMRemarkStreamer.h deleted file mode 100644 index 094ead273e..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/LLVMRemarkStreamer.h +++ /dev/null @@ -1,100 +0,0 @@ -//===- llvm/IR/LLVMRemarkStreamer.h - Streamer for LLVM remarks--*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the conversion between IR Diagnostics and -// serializable remarks::Remark objects. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LLVMREMARKSTREAMER_H -#define LLVM_IR_LLVMREMARKSTREAMER_H - -#include "llvm/Remarks/Remark.h" -#include "llvm/Support/Error.h" -#include -#include - -namespace llvm { - -class DiagnosticInfoOptimizationBase; -class LLVMContext; -class ToolOutputFile; -namespace remarks { -class RemarkStreamer; -} - -/// Streamer for LLVM remarks which has logic for dealing with DiagnosticInfo -/// objects. -class LLVMRemarkStreamer { - remarks::RemarkStreamer &RS; - /// Convert diagnostics into remark objects. - /// The lifetime of the members of the result is bound to the lifetime of - /// the LLVM diagnostics. - remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag) const; - -public: - LLVMRemarkStreamer(remarks::RemarkStreamer &RS) : RS(RS) {} - /// Emit a diagnostic through the streamer. - void emit(const DiagnosticInfoOptimizationBase &Diag); -}; - -template -struct LLVMRemarkSetupErrorInfo : public ErrorInfo { - std::string Msg; - std::error_code EC; - - LLVMRemarkSetupErrorInfo(Error E) { - handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) { - Msg = EIB.message(); - EC = EIB.convertToErrorCode(); - }); - } - - void log(raw_ostream &OS) const override { OS << Msg; } - std::error_code convertToErrorCode() const override { return EC; } -}; - -struct LLVMRemarkSetupFileError - : LLVMRemarkSetupErrorInfo { - static char ID; - using LLVMRemarkSetupErrorInfo< - LLVMRemarkSetupFileError>::LLVMRemarkSetupErrorInfo; -}; - -struct LLVMRemarkSetupPatternError - : LLVMRemarkSetupErrorInfo { - static char ID; - using LLVMRemarkSetupErrorInfo< - LLVMRemarkSetupPatternError>::LLVMRemarkSetupErrorInfo; -}; - -struct LLVMRemarkSetupFormatError - : LLVMRemarkSetupErrorInfo { - static char ID; - using LLVMRemarkSetupErrorInfo< - LLVMRemarkSetupFormatError>::LLVMRemarkSetupErrorInfo; -}; - -/// Setup optimization remarks that output to a file. -Expected> -setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, - StringRef RemarksPasses, StringRef RemarksFormat, - bool RemarksWithHotness, - Optional RemarksHotnessThreshold = 0); - -/// Setup optimization remarks that output directly to a raw_ostream. -/// \p OS is managed by the caller and should be open for writing as long as \p -/// Context is streaming remarks to it. -Error setupLLVMOptimizationRemarks( - LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses, - StringRef RemarksFormat, bool RemarksWithHotness, - Optional RemarksHotnessThreshold = 0); - -} // end namespace llvm - -#endif // LLVM_IR_LLVMREMARKSTREAMER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/LegacyPassManager.h b/suite/synctools/tablegen/include/llvm/IR/LegacyPassManager.h deleted file mode 100644 index 70c9e418d7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/LegacyPassManager.h +++ /dev/null @@ -1,106 +0,0 @@ -//===- LegacyPassManager.h - Legacy Container for Passes --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the legacy PassManager class. This class is used to hold, -// maintain, and optimize execution of Passes. The PassManager class ensures -// that analysis results are available before a pass runs, and that Pass's are -// destroyed when the PassManager is destroyed. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEGACYPASSMANAGER_H -#define LLVM_IR_LEGACYPASSMANAGER_H - -#include "llvm/Support/CBindingWrapping.h" - -namespace llvm { - -class Function; -class Pass; -class Module; - -namespace legacy { - -// Whether or not -debug-pass has been specified. For use to check if it's -// specified alongside the new PM. -bool debugPassSpecified(); - -class PassManagerImpl; -class FunctionPassManagerImpl; - -/// PassManagerBase - An abstract interface to allow code to add passes to -/// a pass manager without having to hard-code what kind of pass manager -/// it is. -class PassManagerBase { -public: - virtual ~PassManagerBase(); - - /// Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// may even destroy the pass right away if it is found to be redundant. This - /// implies that all passes MUST be allocated with 'new'. - virtual void add(Pass *P) = 0; -}; - -/// PassManager manages ModulePassManagers -class PassManager : public PassManagerBase { -public: - - PassManager(); - ~PassManager() override; - - void add(Pass *P) override; - - /// run - Execute all of the passes scheduled for execution. Keep track of - /// whether any of the passes modifies the module, and if so, return true. - bool run(Module &M); - -private: - /// PassManagerImpl_New is the actual class. PassManager is just the - /// wrapper to publish simple pass manager interface - PassManagerImpl *PM; -}; - -/// FunctionPassManager manages FunctionPasses. -class FunctionPassManager : public PassManagerBase { -public: - /// FunctionPassManager ctor - This initializes the pass manager. It needs, - /// but does not take ownership of, the specified Module. - explicit FunctionPassManager(Module *M); - ~FunctionPassManager() override; - - void add(Pass *P) override; - - /// run - Execute all of the passes scheduled for execution. Keep - /// track of whether any of the passes modifies the function, and if - /// so, return true. - /// - bool run(Function &F); - - /// doInitialization - Run all of the initializers for the function passes. - /// - bool doInitialization(); - - /// doFinalization - Run all of the finalizers for the function passes. - /// - bool doFinalization(); - -private: - FunctionPassManagerImpl *FPM; - Module *M; -}; - -} // End legacy namespace - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_STDCXX_CONVERSION_FUNCTIONS(legacy::PassManagerBase, LLVMPassManagerRef) - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/LegacyPassManagers.h b/suite/synctools/tablegen/include/llvm/IR/LegacyPassManagers.h deleted file mode 100644 index 62351e34ed..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/LegacyPassManagers.h +++ /dev/null @@ -1,516 +0,0 @@ -//===- LegacyPassManagers.h - Legacy Pass Infrastructure --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the LLVM Pass Manager infrastructure. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEGACYPASSMANAGERS_H -#define LLVM_IR_LEGACYPASSMANAGERS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Pass.h" -#include - -//===----------------------------------------------------------------------===// -// Overview: -// The Pass Manager Infrastructure manages passes. It's responsibilities are: -// -// o Manage optimization pass execution order -// o Make required Analysis information available before pass P is run -// o Release memory occupied by dead passes -// o If Analysis information is dirtied by a pass then regenerate Analysis -// information before it is consumed by another pass. -// -// Pass Manager Infrastructure uses multiple pass managers. They are -// PassManager, FunctionPassManager, MPPassManager, FPPassManager, BBPassManager. -// This class hierarchy uses multiple inheritance but pass managers do not -// derive from another pass manager. -// -// PassManager and FunctionPassManager are two top-level pass manager that -// represents the external interface of this entire pass manager infrastructure. -// -// Important classes : -// -// [o] class PMTopLevelManager; -// -// Two top level managers, PassManager and FunctionPassManager, derive from -// PMTopLevelManager. PMTopLevelManager manages information used by top level -// managers such as last user info. -// -// [o] class PMDataManager; -// -// PMDataManager manages information, e.g. list of available analysis info, -// used by a pass manager to manage execution order of passes. It also provides -// a place to implement common pass manager APIs. All pass managers derive from -// PMDataManager. -// -// [o] class FunctionPassManager; -// -// This is a external interface used to manage FunctionPasses. This -// interface relies on FunctionPassManagerImpl to do all the tasks. -// -// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, -// public PMTopLevelManager; -// -// FunctionPassManagerImpl is a top level manager. It manages FPPassManagers -// -// [o] class FPPassManager : public ModulePass, public PMDataManager; -// -// FPPassManager manages FunctionPasses and BBPassManagers -// -// [o] class MPPassManager : public Pass, public PMDataManager; -// -// MPPassManager manages ModulePasses and FPPassManagers -// -// [o] class PassManager; -// -// This is a external interface used by various tools to manages passes. It -// relies on PassManagerImpl to do all the tasks. -// -// [o] class PassManagerImpl : public Pass, public PMDataManager, -// public PMTopLevelManager -// -// PassManagerImpl is a top level pass manager responsible for managing -// MPPassManagers. -//===----------------------------------------------------------------------===// - -#include "llvm/Support/PrettyStackTrace.h" - -namespace llvm { -template class ArrayRef; -class Module; -class StringRef; -class Value; -class PMDataManager; - -// enums for debugging strings -enum PassDebuggingString { - EXECUTION_MSG, // "Executing Pass '" + PassName - MODIFICATION_MSG, // "Made Modification '" + PassName - FREEING_MSG, // " Freeing Pass '" + PassName - ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" - ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" - ON_REGION_MSG, // "' on Region '" + Msg + "'...\n'" - ON_LOOP_MSG, // "' on Loop '" + Msg + "'...\n'" - ON_CG_MSG // "' on Call Graph Nodes '" + Msg + "'...\n'" -}; - -/// PassManagerPrettyStackEntry - This is used to print informative information -/// about what pass is running when/if a stack trace is generated. -class PassManagerPrettyStackEntry : public PrettyStackTraceEntry { - Pass *P; - Value *V; - Module *M; - -public: - explicit PassManagerPrettyStackEntry(Pass *p) - : P(p), V(nullptr), M(nullptr) {} // When P is releaseMemory'd. - PassManagerPrettyStackEntry(Pass *p, Value &v) - : P(p), V(&v), M(nullptr) {} // When P is run on V - PassManagerPrettyStackEntry(Pass *p, Module &m) - : P(p), V(nullptr), M(&m) {} // When P is run on M - - /// print - Emit information about this stack frame to OS. - void print(raw_ostream &OS) const override; -}; - -//===----------------------------------------------------------------------===// -// PMStack -// -/// PMStack - This class implements a stack data structure of PMDataManager -/// pointers. -/// -/// Top level pass managers (see PassManager.cpp) maintain active Pass Managers -/// using PMStack. Each Pass implements assignPassManager() to connect itself -/// with appropriate manager. assignPassManager() walks PMStack to find -/// suitable manager. -class PMStack { -public: - typedef std::vector::const_reverse_iterator iterator; - iterator begin() const { return S.rbegin(); } - iterator end() const { return S.rend(); } - - void pop(); - PMDataManager *top() const { return S.back(); } - void push(PMDataManager *PM); - bool empty() const { return S.empty(); } - - void dump() const; - -private: - std::vector S; -}; - -//===----------------------------------------------------------------------===// -// PMTopLevelManager -// -/// PMTopLevelManager manages LastUser info and collects common APIs used by -/// top level pass managers. -class PMTopLevelManager { -protected: - explicit PMTopLevelManager(PMDataManager *PMDM); - - unsigned getNumContainedManagers() const { - return (unsigned)PassManagers.size(); - } - - void initializeAllAnalysisInfo(); - -private: - virtual PMDataManager *getAsPMDataManager() = 0; - virtual PassManagerType getTopLevelPassManagerType() = 0; - -public: - /// Schedule pass P for execution. Make sure that passes required by - /// P are run before P is run. Update analysis info maintained by - /// the manager. Remove dead passes. This is a recursive function. - void schedulePass(Pass *P); - - /// Set pass P as the last user of the given analysis passes. - void setLastUser(ArrayRef AnalysisPasses, Pass *P); - - /// Collect passes whose last user is P - void collectLastUses(SmallVectorImpl &LastUses, Pass *P); - - /// Find the pass that implements Analysis AID. Search immutable - /// passes and all pass managers. If desired pass is not found - /// then return NULL. - Pass *findAnalysisPass(AnalysisID AID); - - /// Retrieve the PassInfo for an analysis. - const PassInfo *findAnalysisPassInfo(AnalysisID AID) const; - - /// Find analysis usage information for the pass P. - AnalysisUsage *findAnalysisUsage(Pass *P); - - virtual ~PMTopLevelManager(); - - /// Add immutable pass and initialize it. - void addImmutablePass(ImmutablePass *P); - - inline SmallVectorImpl& getImmutablePasses() { - return ImmutablePasses; - } - - void addPassManager(PMDataManager *Manager) { - PassManagers.push_back(Manager); - } - - // Add Manager into the list of managers that are not directly - // maintained by this top level pass manager - inline void addIndirectPassManager(PMDataManager *Manager) { - IndirectPassManagers.push_back(Manager); - } - - // Print passes managed by this top level manager. - void dumpPasses() const; - void dumpArguments() const; - - // Active Pass Managers - PMStack activeStack; - -protected: - /// Collection of pass managers - SmallVector PassManagers; - -private: - /// Collection of pass managers that are not directly maintained - /// by this pass manager - SmallVector IndirectPassManagers; - - // Map to keep track of last user of the analysis pass. - // LastUser->second is the last user of Lastuser->first. - // This is kept in sync with InversedLastUser. - DenseMap LastUser; - - // Map to keep track of passes that are last used by a pass. - // This is kept in sync with LastUser. - DenseMap > InversedLastUser; - - /// Immutable passes are managed by top level manager. - SmallVector ImmutablePasses; - - /// Map from ID to immutable passes. - SmallDenseMap ImmutablePassMap; - - - /// A wrapper around AnalysisUsage for the purpose of uniqueing. The wrapper - /// is used to avoid needing to make AnalysisUsage itself a folding set node. - struct AUFoldingSetNode : public FoldingSetNode { - AnalysisUsage AU; - AUFoldingSetNode(const AnalysisUsage &AU) : AU(AU) {} - void Profile(FoldingSetNodeID &ID) const { - Profile(ID, AU); - } - static void Profile(FoldingSetNodeID &ID, const AnalysisUsage &AU) { - // TODO: We could consider sorting the dependency arrays within the - // AnalysisUsage (since they are conceptually unordered). - ID.AddBoolean(AU.getPreservesAll()); - auto ProfileVec = [&](const SmallVectorImpl& Vec) { - ID.AddInteger(Vec.size()); - for(AnalysisID AID : Vec) - ID.AddPointer(AID); - }; - ProfileVec(AU.getRequiredSet()); - ProfileVec(AU.getRequiredTransitiveSet()); - ProfileVec(AU.getPreservedSet()); - ProfileVec(AU.getUsedSet()); - } - }; - - // Contains all of the unique combinations of AnalysisUsage. This is helpful - // when we have multiple instances of the same pass since they'll usually - // have the same analysis usage and can share storage. - FoldingSet UniqueAnalysisUsages; - - // Allocator used for allocating UAFoldingSetNodes. This handles deletion of - // all allocated nodes in one fell swoop. - SpecificBumpPtrAllocator AUFoldingSetNodeAllocator; - - // Maps from a pass to its associated entry in UniqueAnalysisUsages. Does - // not own the storage associated with either key or value.. - DenseMap AnUsageMap; - - /// Collection of PassInfo objects found via analysis IDs and in this top - /// level manager. This is used to memoize queries to the pass registry. - /// FIXME: This is an egregious hack because querying the pass registry is - /// either slow or racy. - mutable DenseMap AnalysisPassInfos; -}; - -//===----------------------------------------------------------------------===// -// PMDataManager - -/// PMDataManager provides the common place to manage the analysis data -/// used by pass managers. -class PMDataManager { -public: - explicit PMDataManager() : TPM(nullptr), Depth(0) { - initializeAnalysisInfo(); - } - - virtual ~PMDataManager(); - - virtual Pass *getAsPass() = 0; - - /// Augment AvailableAnalysis by adding analysis made available by pass P. - void recordAvailableAnalysis(Pass *P); - - /// verifyPreservedAnalysis -- Verify analysis preserved by pass P. - void verifyPreservedAnalysis(Pass *P); - - /// Remove Analysis that is not preserved by the pass - void removeNotPreservedAnalysis(Pass *P); - - /// Remove dead passes used by P. - void removeDeadPasses(Pass *P, StringRef Msg, - enum PassDebuggingString); - - /// Remove P. - void freePass(Pass *P, StringRef Msg, - enum PassDebuggingString); - - /// Add pass P into the PassVector. Update - /// AvailableAnalysis appropriately if ProcessAnalysis is true. - void add(Pass *P, bool ProcessAnalysis = true); - - /// Add RequiredPass into list of lower level passes required by pass P. - /// RequiredPass is run on the fly by Pass Manager when P requests it - /// through getAnalysis interface. - virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass); - - virtual std::tuple getOnTheFlyPass(Pass *P, AnalysisID PI, - Function &F); - - /// Initialize available analysis information. - void initializeAnalysisInfo() { - AvailableAnalysis.clear(); - for (auto &IA : InheritedAnalysis) - IA = nullptr; - } - - // Return true if P preserves high level analysis used by other - // passes that are managed by this manager. - bool preserveHigherLevelAnalysis(Pass *P); - - /// Populate UsedPasses with analysis pass that are used or required by pass - /// P and are available. Populate ReqPassNotAvailable with analysis pass that - /// are required by pass P but are not available. - void collectRequiredAndUsedAnalyses( - SmallVectorImpl &UsedPasses, - SmallVectorImpl &ReqPassNotAvailable, Pass *P); - - /// All Required analyses should be available to the pass as it runs! Here - /// we fill in the AnalysisImpls member of the pass so that it can - /// successfully use the getAnalysis() method to retrieve the - /// implementations it needs. - void initializeAnalysisImpl(Pass *P); - - /// Find the pass that implements Analysis AID. If desired pass is not found - /// then return NULL. - Pass *findAnalysisPass(AnalysisID AID, bool Direction); - - // Access toplevel manager - PMTopLevelManager *getTopLevelManager() { return TPM; } - void setTopLevelManager(PMTopLevelManager *T) { TPM = T; } - - unsigned getDepth() const { return Depth; } - void setDepth(unsigned newDepth) { Depth = newDepth; } - - // Print routines used by debug-pass - void dumpLastUses(Pass *P, unsigned Offset) const; - void dumpPassArguments() const; - void dumpPassInfo(Pass *P, enum PassDebuggingString S1, - enum PassDebuggingString S2, StringRef Msg); - void dumpRequiredSet(const Pass *P) const; - void dumpPreservedSet(const Pass *P) const; - void dumpUsedSet(const Pass *P) const; - - unsigned getNumContainedPasses() const { - return (unsigned)PassVector.size(); - } - - virtual PassManagerType getPassManagerType() const { - assert ( 0 && "Invalid use of getPassManagerType"); - return PMT_Unknown; - } - - DenseMap *getAvailableAnalysis() { - return &AvailableAnalysis; - } - - // Collect AvailableAnalysis from all the active Pass Managers. - void populateInheritedAnalysis(PMStack &PMS) { - unsigned Index = 0; - for (PMDataManager *PMDM : PMS) - InheritedAnalysis[Index++] = PMDM->getAvailableAnalysis(); - } - - /// Set the initial size of the module if the user has specified that they - /// want remarks for size. - /// Returns 0 if the remark was not requested. - unsigned initSizeRemarkInfo( - Module &M, - StringMap> &FunctionToInstrCount); - - /// Emit a remark signifying that the number of IR instructions in the module - /// changed. - /// \p F is optionally passed by passes which run on Functions, and thus - /// always know whether or not a non-empty function is available. - /// - /// \p FunctionToInstrCount maps the name of a \p Function to a pair. The - /// first member of the pair is the IR count of the \p Function before running - /// \p P, and the second member is the IR count of the \p Function after - /// running \p P. - void emitInstrCountChangedRemark( - Pass *P, Module &M, int64_t Delta, unsigned CountBefore, - StringMap> &FunctionToInstrCount, - Function *F = nullptr); - -protected: - // Top level manager. - PMTopLevelManager *TPM; - - // Collection of pass that are managed by this manager - SmallVector PassVector; - - // Collection of Analysis provided by Parent pass manager and - // used by current pass manager. At time there can not be more - // then PMT_Last active pass mangers. - DenseMap *InheritedAnalysis[PMT_Last]; - - /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions - /// or higher is specified. - bool isPassDebuggingExecutionsOrMore() const; - -private: - void dumpAnalysisUsage(StringRef Msg, const Pass *P, - const AnalysisUsage::VectorType &Set) const; - - // Set of available Analysis. This information is used while scheduling - // pass. If a pass requires an analysis which is not available then - // the required analysis pass is scheduled to run before the pass itself is - // scheduled to run. - DenseMap AvailableAnalysis; - - // Collection of higher level analysis used by the pass managed by - // this manager. - SmallVector HigherLevelAnalysis; - - unsigned Depth; -}; - -//===----------------------------------------------------------------------===// -// FPPassManager -// -/// FPPassManager manages BBPassManagers and FunctionPasses. -/// It batches all function passes and basic block pass managers together and -/// sequence them to process one function at a time before processing next -/// function. -class FPPassManager : public ModulePass, public PMDataManager { -public: - static char ID; - explicit FPPassManager() : ModulePass(ID) {} - - /// run - Execute all of the passes scheduled for execution. Keep track of - /// whether any of the passes modifies the module, and if so, return true. - bool runOnFunction(Function &F); - bool runOnModule(Module &M) override; - - /// cleanup - After running all passes, clean up pass manager cache. - void cleanup(); - - /// doInitialization - Overrides ModulePass doInitialization for global - /// initialization tasks - /// - using ModulePass::doInitialization; - - /// doInitialization - Run all of the initializers for the function passes. - /// - bool doInitialization(Module &M) override; - - /// doFinalization - Overrides ModulePass doFinalization for global - /// finalization tasks - /// - using ModulePass::doFinalization; - - /// doFinalization - Run all of the finalizers for the function passes. - /// - bool doFinalization(Module &M) override; - - PMDataManager *getAsPMDataManager() override { return this; } - Pass *getAsPass() override { return this; } - - /// Pass Manager itself does not invalidate any analysis info. - void getAnalysisUsage(AnalysisUsage &Info) const override { - Info.setPreservesAll(); - } - - // Print passes managed by this manager - void dumpPassStructure(unsigned Offset) override; - - StringRef getPassName() const override { return "Function Pass Manager"; } - - FunctionPass *getContainedPass(unsigned N) { - assert ( N < PassVector.size() && "Pass number out of range!"); - FunctionPass *FP = static_cast(PassVector[N]); - return FP; - } - - PassManagerType getPassManagerType() const override { - return PMT_FunctionPassManager; - } -}; - -} - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/LegacyPassNameParser.h b/suite/synctools/tablegen/include/llvm/IR/LegacyPassNameParser.h deleted file mode 100644 index 103bfab74c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/LegacyPassNameParser.h +++ /dev/null @@ -1,97 +0,0 @@ -//===- LegacyPassNameParser.h -----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the PassNameParser and FilteredPassNameParser<> classes, -// which are used to add command line arguments to a utility for all of the -// passes that have been registered into the system. -// -// The PassNameParser class adds ALL passes linked into the system (that are -// creatable) as command line arguments to the tool (when instantiated with the -// appropriate command line option template). The FilteredPassNameParser<> -// template is used for the same purposes as PassNameParser, except that it only -// includes passes that have a PassType that are compatible with the filter -// (which is the template argument). -// -// Note that this is part of the legacy pass manager infrastructure and will be -// (eventually) going away. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEGACYPASSNAMEPARSER_H -#define LLVM_IR_LEGACYPASSNAMEPARSER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { - -//===----------------------------------------------------------------------===// -// PassNameParser class - Make use of the pass registration mechanism to -// automatically add a command line argument to opt for each pass. -// -class PassNameParser : public PassRegistrationListener, - public cl::parser { -public: - PassNameParser(cl::Option &O); - ~PassNameParser() override; - - void initialize() { - cl::parser::initialize(); - - // Add all of the passes to the map that got initialized before 'this' did. - enumeratePasses(); - } - - // ignorablePassImpl - Can be overridden in subclasses to refine the list of - // which passes we want to include. - // - virtual bool ignorablePassImpl(const PassInfo *P) const { return false; } - - inline bool ignorablePass(const PassInfo *P) const { - // Ignore non-selectable and non-constructible passes! Ignore - // non-optimizations. - return P->getPassArgument().empty() || P->getNormalCtor() == nullptr || - ignorablePassImpl(P); - } - - // Implement the PassRegistrationListener callbacks used to populate our map - // - void passRegistered(const PassInfo *P) override { - if (ignorablePass(P)) return; - if (findOption(P->getPassArgument().data()) != getNumOptions()) { - errs() << "Two passes with the same argument (-" - << P->getPassArgument() << ") attempted to be registered!\n"; - llvm_unreachable(nullptr); - } - addLiteralOption(P->getPassArgument().data(), P, P->getPassName().data()); - } - void passEnumerate(const PassInfo *P) override { passRegistered(P); } - - // printOptionInfo - Print out information about this option. Override the - // default implementation to sort the table before we print... - void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const override { - PassNameParser *PNP = const_cast(this); - array_pod_sort(PNP->Values.begin(), PNP->Values.end(), ValCompare); - cl::parser::printOptionInfo(O, GlobalWidth); - } - -private: - // ValCompare - Provide a sorting comparator for Values elements... - static int ValCompare(const PassNameParser::OptionInfo *VT1, - const PassNameParser::OptionInfo *VT2) { - return VT1->Name.compare(VT2->Name); - } -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/MDBuilder.h b/suite/synctools/tablegen/include/llvm/IR/MDBuilder.h deleted file mode 100644 index 42829388b7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/MDBuilder.h +++ /dev/null @@ -1,217 +0,0 @@ -//===---- llvm/MDBuilder.h - Builder for LLVM metadata ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MDBuilder class, which is used as a convenient way to -// create LLVM metadata with a consistent and simplified interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MDBUILDER_H -#define LLVM_IR_MDBUILDER_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - -class APInt; -template class ArrayRef; -class LLVMContext; -class Constant; -class ConstantAsMetadata; -class Function; -class MDNode; -class MDString; -class Metadata; - -class MDBuilder { - LLVMContext &Context; - -public: - MDBuilder(LLVMContext &context) : Context(context) {} - - /// Return the given string as metadata. - MDString *createString(StringRef Str); - - /// Return the given constant as metadata. - ConstantAsMetadata *createConstant(Constant *C); - - //===------------------------------------------------------------------===// - // FPMath metadata. - //===------------------------------------------------------------------===// - - /// Return metadata with the given settings. The special value 0.0 - /// for the Accuracy parameter indicates the default (maximal precision) - /// setting. - MDNode *createFPMath(float Accuracy); - - //===------------------------------------------------------------------===// - // Prof metadata. - //===------------------------------------------------------------------===// - - /// Return metadata containing two branch weights. - MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight); - - /// Return metadata containing a number of branch weights. - MDNode *createBranchWeights(ArrayRef Weights); - - /// Return metadata specifying that a branch or switch is unpredictable. - MDNode *createUnpredictable(); - - /// Return metadata containing the entry \p Count for a function, a boolean - /// \Synthetic indicating whether the counts were synthetized, and the - /// GUIDs stored in \p Imports that need to be imported for sample PGO, to - /// enable the same inlines as the profiled optimized binary - MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic, - const DenseSet *Imports); - - /// Return metadata containing the section prefix for a function. - MDNode *createFunctionSectionPrefix(StringRef Prefix); - - /// Return metadata containing the pseudo probe descriptor for a function. - MDNode *createPseudoProbeDesc(uint64_t GUID, uint64_t Hash, Function *F); - - //===------------------------------------------------------------------===// - // Range metadata. - //===------------------------------------------------------------------===// - - /// Return metadata describing the range [Lo, Hi). - MDNode *createRange(const APInt &Lo, const APInt &Hi); - - /// Return metadata describing the range [Lo, Hi). - MDNode *createRange(Constant *Lo, Constant *Hi); - - //===------------------------------------------------------------------===// - // Callees metadata. - //===------------------------------------------------------------------===// - - /// Return metadata indicating the possible callees of indirect - /// calls. - MDNode *createCallees(ArrayRef Callees); - - //===------------------------------------------------------------------===// - // Callback metadata. - //===------------------------------------------------------------------===// - - /// Return metadata describing a callback (see llvm::AbstractCallSite). - MDNode *createCallbackEncoding(unsigned CalleeArgNo, ArrayRef Arguments, - bool VarArgsArePassed); - - /// Merge the new callback encoding \p NewCB into \p ExistingCallbacks. - MDNode *mergeCallbackEncodings(MDNode *ExistingCallbacks, MDNode *NewCB); - - //===------------------------------------------------------------------===// - // AA metadata. - //===------------------------------------------------------------------===// - -protected: - /// Return metadata appropriate for a AA root node (scope or TBAA). - /// Each returned node is distinct from all other metadata and will never - /// be identified (uniqued) with anything else. - MDNode *createAnonymousAARoot(StringRef Name = StringRef(), - MDNode *Extra = nullptr); - -public: - /// Return metadata appropriate for a TBAA root node. Each returned - /// node is distinct from all other metadata and will never be identified - /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot() { - return createAnonymousAARoot(); - } - - /// Return metadata appropriate for an alias scope domain node. - /// Each returned node is distinct from all other metadata and will never - /// be identified (uniqued) with anything else. - MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) { - return createAnonymousAARoot(Name); - } - - /// Return metadata appropriate for an alias scope root node. - /// Each returned node is distinct from all other metadata and will never - /// be identified (uniqued) with anything else. - MDNode *createAnonymousAliasScope(MDNode *Domain, - StringRef Name = StringRef()) { - return createAnonymousAARoot(Name, Domain); - } - - /// Return metadata appropriate for a TBAA root node with the given - /// name. This may be identified (uniqued) with other roots with the same - /// name. - MDNode *createTBAARoot(StringRef Name); - - /// Return metadata appropriate for an alias scope domain node with - /// the given name. This may be identified (uniqued) with other roots with - /// the same name. - MDNode *createAliasScopeDomain(StringRef Name); - - /// Return metadata appropriate for an alias scope node with - /// the given name. This may be identified (uniqued) with other scopes with - /// the same name and domain. - MDNode *createAliasScope(StringRef Name, MDNode *Domain); - - /// Return metadata for a non-root TBAA node with the given name, - /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. - MDNode *createTBAANode(StringRef Name, MDNode *Parent, - bool isConstant = false); - - struct TBAAStructField { - uint64_t Offset; - uint64_t Size; - MDNode *Type; - TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *Type) : - Offset(Offset), Size(Size), Type(Type) {} - }; - - /// Return metadata for a tbaa.struct node with the given - /// struct field descriptions. - MDNode *createTBAAStructNode(ArrayRef Fields); - - /// Return metadata for a TBAA struct node in the type DAG - /// with the given name, a list of pairs (offset, field type in the type DAG). - MDNode * - createTBAAStructTypeNode(StringRef Name, - ArrayRef> Fields); - - /// Return metadata for a TBAA scalar type node with the - /// given name, an offset and a parent in the TBAA type DAG. - MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, - uint64_t Offset = 0); - - /// Return metadata for a TBAA tag node with the given - /// base type, access type and offset relative to the base type. - MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, - uint64_t Offset, bool IsConstant = false); - - /// Return metadata for a TBAA type node in the TBAA type DAG with the - /// given parent type, size in bytes, type identifier and a list of fields. - MDNode *createTBAATypeNode(MDNode *Parent, uint64_t Size, Metadata *Id, - ArrayRef Fields = - ArrayRef()); - - /// Return metadata for a TBAA access tag with the given base type, - /// final access type, offset of the access relative to the base type, size of - /// the access and flag indicating whether the accessed object can be - /// considered immutable for the purposes of the TBAA analysis. - MDNode *createTBAAAccessTag(MDNode *BaseType, MDNode *AccessType, - uint64_t Offset, uint64_t Size, - bool IsImmutable = false); - - /// Return mutable version of the given mutable or immutable TBAA - /// access tag. - MDNode *createMutableTBAAAccessTag(MDNode *Tag); - - /// Return metadata containing an irreducible loop header weight. - MDNode *createIrrLoopHeaderWeight(uint64_t Weight); -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Mangler.h b/suite/synctools/tablegen/include/llvm/IR/Mangler.h deleted file mode 100644 index 747a408523..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Mangler.h +++ /dev/null @@ -1,57 +0,0 @@ -//===-- llvm/IR/Mangler.h - Self-contained name mangler ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Unified name mangler for various backends. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MANGLER_H -#define LLVM_IR_MANGLER_H - -#include "llvm/ADT/DenseMap.h" - -namespace llvm { - -class DataLayout; -class GlobalValue; -template class SmallVectorImpl; -class Triple; -class Twine; -class raw_ostream; - -class Mangler { - /// We need to give global values the same name every time they are mangled. - /// This keeps track of the number we give to anonymous ones. - mutable DenseMap AnonGlobalIDs; - -public: - /// Print the appropriate prefix and the specified global variable's name. - /// If the global variable doesn't have a name, this fills in a unique name - /// for the global. - void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, - bool CannotUsePrivateLabel) const; - void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, - bool CannotUsePrivateLabel) const; - - /// Print the appropriate prefix and the specified name as the global variable - /// name. GVName must not be empty. - static void getNameWithPrefix(raw_ostream &OS, const Twine &GVName, - const DataLayout &DL); - static void getNameWithPrefix(SmallVectorImpl &OutName, - const Twine &GVName, const DataLayout &DL); -}; - -void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, - const Triple &TT, Mangler &Mangler); - -void emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, - const Triple &T, Mangler &M); - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/MatrixBuilder.h b/suite/synctools/tablegen/include/llvm/IR/MatrixBuilder.h deleted file mode 100644 index 4c8286692e..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/MatrixBuilder.h +++ /dev/null @@ -1,264 +0,0 @@ -//===- llvm/MatrixBuilder.h - Builder to lower matrix ops -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MatrixBuilder class, which is used as a convenient way -// to lower matrix operations to LLVM IR. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MATRIXBUILDER_H -#define LLVM_IR_MATRIXBUILDER_H - -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Alignment.h" - -namespace llvm { - -class Function; -class Twine; -class Module; - -template class MatrixBuilder { - IRBuilderTy &B; - Module *getModule() { return B.GetInsertBlock()->getParent()->getParent(); } - - std::pair splatScalarOperandIfNeeded(Value *LHS, - Value *RHS) { - assert((LHS->getType()->isVectorTy() || RHS->getType()->isVectorTy()) && - "One of the operands must be a matrix (embedded in a vector)"); - if (LHS->getType()->isVectorTy() && !RHS->getType()->isVectorTy()) { - assert(!isa(LHS->getType()) && - "LHS Assumed to be fixed width"); - RHS = B.CreateVectorSplat( - cast(LHS->getType())->getElementCount(), RHS, - "scalar.splat"); - } else if (!LHS->getType()->isVectorTy() && RHS->getType()->isVectorTy()) { - assert(!isa(RHS->getType()) && - "RHS Assumed to be fixed width"); - LHS = B.CreateVectorSplat( - cast(RHS->getType())->getElementCount(), LHS, - "scalar.splat"); - } - return {LHS, RHS}; - } - -public: - MatrixBuilder(IRBuilderTy &Builder) : B(Builder) {} - - /// Create a column major, strided matrix load. - /// \p DataPtr - Start address of the matrix read - /// \p Rows - Number of rows in matrix (must be a constant) - /// \p Columns - Number of columns in matrix (must be a constant) - /// \p Stride - Space between columns - CallInst *CreateColumnMajorLoad(Value *DataPtr, Align Alignment, - Value *Stride, bool IsVolatile, unsigned Rows, - unsigned Columns, const Twine &Name = "") { - - // Deal with the pointer - PointerType *PtrTy = cast(DataPtr->getType()); - Type *EltTy = PtrTy->getPointerElementType(); - - auto *RetType = FixedVectorType::get(EltTy, Rows * Columns); - - Value *Ops[] = {DataPtr, Stride, B.getInt1(IsVolatile), B.getInt32(Rows), - B.getInt32(Columns)}; - Type *OverloadedTypes[] = {RetType, Stride->getType()}; - - Function *TheFn = Intrinsic::getDeclaration( - getModule(), Intrinsic::matrix_column_major_load, OverloadedTypes); - - CallInst *Call = B.CreateCall(TheFn->getFunctionType(), TheFn, Ops, Name); - Attribute AlignAttr = - Attribute::getWithAlignment(Call->getContext(), Alignment); - Call->addParamAttr(0, AlignAttr); - return Call; - } - - /// Create a column major, strided matrix store. - /// \p Matrix - Matrix to store - /// \p Ptr - Pointer to write back to - /// \p Stride - Space between columns - CallInst *CreateColumnMajorStore(Value *Matrix, Value *Ptr, Align Alignment, - Value *Stride, bool IsVolatile, - unsigned Rows, unsigned Columns, - const Twine &Name = "") { - Value *Ops[] = {Matrix, Ptr, - Stride, B.getInt1(IsVolatile), - B.getInt32(Rows), B.getInt32(Columns)}; - Type *OverloadedTypes[] = {Matrix->getType(), Stride->getType()}; - - Function *TheFn = Intrinsic::getDeclaration( - getModule(), Intrinsic::matrix_column_major_store, OverloadedTypes); - - CallInst *Call = B.CreateCall(TheFn->getFunctionType(), TheFn, Ops, Name); - Attribute AlignAttr = - Attribute::getWithAlignment(Call->getContext(), Alignment); - Call->addParamAttr(1, AlignAttr); - return Call; - } - - /// Create a llvm.matrix.transpose call, transposing \p Matrix with \p Rows - /// rows and \p Columns columns. - CallInst *CreateMatrixTranspose(Value *Matrix, unsigned Rows, - unsigned Columns, const Twine &Name = "") { - auto *OpType = cast(Matrix->getType()); - auto *ReturnType = - FixedVectorType::get(OpType->getElementType(), Rows * Columns); - - Type *OverloadedTypes[] = {ReturnType}; - Value *Ops[] = {Matrix, B.getInt32(Rows), B.getInt32(Columns)}; - Function *TheFn = Intrinsic::getDeclaration( - getModule(), Intrinsic::matrix_transpose, OverloadedTypes); - - return B.CreateCall(TheFn->getFunctionType(), TheFn, Ops, Name); - } - - /// Create a llvm.matrix.multiply call, multiplying matrixes \p LHS and \p - /// RHS. - CallInst *CreateMatrixMultiply(Value *LHS, Value *RHS, unsigned LHSRows, - unsigned LHSColumns, unsigned RHSColumns, - const Twine &Name = "") { - auto *LHSType = cast(LHS->getType()); - auto *RHSType = cast(RHS->getType()); - - auto *ReturnType = - FixedVectorType::get(LHSType->getElementType(), LHSRows * RHSColumns); - - Value *Ops[] = {LHS, RHS, B.getInt32(LHSRows), B.getInt32(LHSColumns), - B.getInt32(RHSColumns)}; - Type *OverloadedTypes[] = {ReturnType, LHSType, RHSType}; - - Function *TheFn = Intrinsic::getDeclaration( - getModule(), Intrinsic::matrix_multiply, OverloadedTypes); - return B.CreateCall(TheFn->getFunctionType(), TheFn, Ops, Name); - } - - /// Insert a single element \p NewVal into \p Matrix at indices (\p RowIdx, \p - /// ColumnIdx). - Value *CreateMatrixInsert(Value *Matrix, Value *NewVal, Value *RowIdx, - Value *ColumnIdx, unsigned NumRows) { - return B.CreateInsertElement( - Matrix, NewVal, - B.CreateAdd(B.CreateMul(ColumnIdx, ConstantInt::get( - ColumnIdx->getType(), NumRows)), - RowIdx)); - } - - /// Add matrixes \p LHS and \p RHS. Support both integer and floating point - /// matrixes. - Value *CreateAdd(Value *LHS, Value *RHS) { - assert(LHS->getType()->isVectorTy() || RHS->getType()->isVectorTy()); - if (LHS->getType()->isVectorTy() && !RHS->getType()->isVectorTy()) { - assert(!isa(LHS->getType()) && - "LHS Assumed to be fixed width"); - RHS = B.CreateVectorSplat( - cast(LHS->getType())->getElementCount(), RHS, - "scalar.splat"); - } else if (!LHS->getType()->isVectorTy() && RHS->getType()->isVectorTy()) { - assert(!isa(RHS->getType()) && - "RHS Assumed to be fixed width"); - LHS = B.CreateVectorSplat( - cast(RHS->getType())->getElementCount(), LHS, - "scalar.splat"); - } - - return cast(LHS->getType()) - ->getElementType() - ->isFloatingPointTy() - ? B.CreateFAdd(LHS, RHS) - : B.CreateAdd(LHS, RHS); - } - - /// Subtract matrixes \p LHS and \p RHS. Support both integer and floating - /// point matrixes. - Value *CreateSub(Value *LHS, Value *RHS) { - assert(LHS->getType()->isVectorTy() || RHS->getType()->isVectorTy()); - if (LHS->getType()->isVectorTy() && !RHS->getType()->isVectorTy()) { - assert(!isa(LHS->getType()) && - "LHS Assumed to be fixed width"); - RHS = B.CreateVectorSplat( - cast(LHS->getType())->getElementCount(), RHS, - "scalar.splat"); - } else if (!LHS->getType()->isVectorTy() && RHS->getType()->isVectorTy()) { - assert(!isa(RHS->getType()) && - "RHS Assumed to be fixed width"); - LHS = B.CreateVectorSplat( - cast(RHS->getType())->getElementCount(), LHS, - "scalar.splat"); - } - - return cast(LHS->getType()) - ->getElementType() - ->isFloatingPointTy() - ? B.CreateFSub(LHS, RHS) - : B.CreateSub(LHS, RHS); - } - - /// Multiply matrix \p LHS with scalar \p RHS or scalar \p LHS with matrix \p - /// RHS. - Value *CreateScalarMultiply(Value *LHS, Value *RHS) { - std::tie(LHS, RHS) = splatScalarOperandIfNeeded(LHS, RHS); - if (LHS->getType()->getScalarType()->isFloatingPointTy()) - return B.CreateFMul(LHS, RHS); - return B.CreateMul(LHS, RHS); - } - - /// Divide matrix \p LHS by scalar \p RHS. If the operands are integers, \p - /// IsUnsigned indicates whether UDiv or SDiv should be used. - Value *CreateScalarDiv(Value *LHS, Value *RHS, bool IsUnsigned) { - assert(LHS->getType()->isVectorTy() && !RHS->getType()->isVectorTy()); - assert(!isa(LHS->getType()) && - "LHS Assumed to be fixed width"); - RHS = - B.CreateVectorSplat(cast(LHS->getType())->getElementCount(), - RHS, "scalar.splat"); - return cast(LHS->getType()) - ->getElementType() - ->isFloatingPointTy() - ? B.CreateFDiv(LHS, RHS) - : (IsUnsigned ? B.CreateUDiv(LHS, RHS) : B.CreateSDiv(LHS, RHS)); - } - - /// Create an assumption that \p Idx is less than \p NumElements. - void CreateIndexAssumption(Value *Idx, unsigned NumElements, - Twine const &Name = "") { - - Value *NumElts = - B.getIntN(Idx->getType()->getScalarSizeInBits(), NumElements); - auto *Cmp = B.CreateICmpULT(Idx, NumElts); - if (auto *ConstCond = dyn_cast(Cmp)) - assert(ConstCond->isOne() && "Index must be valid!"); - else - B.CreateAssumption(Cmp); - } - - /// Compute the index to access the element at (\p RowIdx, \p ColumnIdx) from - /// a matrix with \p NumRows embedded in a vector. - Value *CreateIndex(Value *RowIdx, Value *ColumnIdx, unsigned NumRows, - Twine const &Name = "") { - - unsigned MaxWidth = std::max(RowIdx->getType()->getScalarSizeInBits(), - ColumnIdx->getType()->getScalarSizeInBits()); - Type *IntTy = IntegerType::get(RowIdx->getType()->getContext(), MaxWidth); - RowIdx = B.CreateZExt(RowIdx, IntTy); - ColumnIdx = B.CreateZExt(ColumnIdx, IntTy); - Value *NumRowsV = B.getIntN(MaxWidth, NumRows); - return B.CreateAdd(B.CreateMul(ColumnIdx, NumRowsV), RowIdx); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_MATRIXBUILDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Metadata.def b/suite/synctools/tablegen/include/llvm/IR/Metadata.def deleted file mode 100644 index bbf349e6b5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Metadata.def +++ /dev/null @@ -1,129 +0,0 @@ -//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Macros for running through all types of metadata. -// -//===----------------------------------------------------------------------===// - -#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ - defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ - defined HANDLE_MDNODE_LEAF_UNIQUABLE || defined HANDLE_MDNODE_BRANCH || \ - defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE || \ - defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ - defined HANDLE_SPECIALIZED_MDNODE_BRANCH) -#error "Missing macro definition of HANDLE_METADATA*" -#endif - -// Handler for all types of metadata. -#ifndef HANDLE_METADATA -#define HANDLE_METADATA(CLASS) -#endif - -// Handler for leaf nodes in the class hierarchy. -#ifndef HANDLE_METADATA_LEAF -#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) -#endif - -// Handler for non-leaf nodes in the class hierarchy. -#ifndef HANDLE_METADATA_BRANCH -#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) -#endif - -// Handler for specialized and uniquable leaf nodes under MDNode. Defers to -// HANDLE_MDNODE_LEAF_UNIQUABLE if it's defined, otherwise to -// HANDLE_SPECIALIZED_MDNODE_LEAF. -#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE -#ifdef HANDLE_MDNODE_LEAF_UNIQUABLE -#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ - HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) -#else -#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ - HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) -#endif -#endif - -// Handler for leaf nodes under MDNode. -#ifndef HANDLE_MDNODE_LEAF_UNIQUABLE -#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) HANDLE_MDNODE_LEAF(CLASS) -#endif - -// Handler for leaf nodes under MDNode. -#ifndef HANDLE_MDNODE_LEAF -#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) -#endif - -// Handler for non-leaf nodes under MDNode. -#ifndef HANDLE_MDNODE_BRANCH -#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) -#endif - -// Handler for specialized leaf nodes under MDNode. -#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF -#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) -#endif - -// Handler for specialized non-leaf nodes under MDNode. -#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH -#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) -#endif - -HANDLE_METADATA_LEAF(MDString) -HANDLE_METADATA_BRANCH(ValueAsMetadata) -HANDLE_METADATA_LEAF(ConstantAsMetadata) -HANDLE_METADATA_LEAF(LocalAsMetadata) -HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder) -HANDLE_MDNODE_BRANCH(MDNode) -HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrange) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIEnumerator) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIBasicType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIDerivedType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile) -HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlock) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlockFile) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DINamespace) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIModule) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateTypeParameter) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIArgList) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange) - -#undef HANDLE_METADATA -#undef HANDLE_METADATA_LEAF -#undef HANDLE_METADATA_BRANCH -#undef HANDLE_MDNODE_LEAF -#undef HANDLE_MDNODE_LEAF_UNIQUABLE -#undef HANDLE_MDNODE_BRANCH -#undef HANDLE_SPECIALIZED_MDNODE_LEAF -#undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE -#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/suite/synctools/tablegen/include/llvm/IR/Metadata.h b/suite/synctools/tablegen/include/llvm/IR/Metadata.h deleted file mode 100644 index eeeeb90550..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Metadata.h +++ /dev/null @@ -1,1549 +0,0 @@ -//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains the declarations for metadata subclasses. -/// They represent the different flavors of metadata that live in LLVM. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_METADATA_H -#define LLVM_IR_METADATA_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class Module; -class ModuleSlotTracker; -class raw_ostream; -template class StringMapEntry; -template class StringMapEntryStorage; -class Type; - -enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 3 // Current debug info version number. -}; - -/// Magic number in the value profile metadata showing a target has been -/// promoted for the instruction and shouldn't be promoted again. -const uint64_t NOMORE_ICP_MAGICNUM = -1; - -/// Root of the metadata hierarchy. -/// -/// This is a root class for typeless data in the IR. -class Metadata { - friend class ReplaceableMetadataImpl; - - /// RTTI. - const unsigned char SubclassID; - -protected: - /// Active type of storage. - enum StorageType { Uniqued, Distinct, Temporary }; - - /// Storage flag for non-uniqued, otherwise unowned, metadata. - unsigned char Storage : 7; - - unsigned char SubclassData1 : 1; - unsigned short SubclassData16 = 0; - unsigned SubclassData32 = 0; - -public: - enum MetadataKind { -#define HANDLE_METADATA_LEAF(CLASS) CLASS##Kind, -#include "llvm/IR/Metadata.def" - }; - -protected: - Metadata(unsigned ID, StorageType Storage) - : SubclassID(ID), Storage(Storage), SubclassData1(false) { - static_assert(sizeof(*this) == 8, "Metadata fields poorly packed"); - } - - ~Metadata() = default; - - /// Default handling of a changed operand, which asserts. - /// - /// If subclasses pass themselves in as owners to a tracking node reference, - /// they must provide an implementation of this method. - void handleChangedOperand(void *, Metadata *) { - llvm_unreachable("Unimplemented in Metadata subclass"); - } - -public: - unsigned getMetadataID() const { return SubclassID; } - - /// User-friendly dump. - /// - /// If \c M is provided, metadata nodes will be numbered canonically; - /// otherwise, pointer addresses are substituted. - /// - /// Note: this uses an explicit overload instead of default arguments so that - /// the nullptr version is easy to call from a debugger. - /// - /// @{ - void dump() const; - void dump(const Module *M) const; - /// @} - - /// Print. - /// - /// Prints definition of \c this. - /// - /// If \c M is provided, metadata nodes will be numbered canonically; - /// otherwise, pointer addresses are substituted. - /// @{ - void print(raw_ostream &OS, const Module *M = nullptr, - bool IsForDebug = false) const; - void print(raw_ostream &OS, ModuleSlotTracker &MST, const Module *M = nullptr, - bool IsForDebug = false) const; - /// @} - - /// Print as operand. - /// - /// Prints reference of \c this. - /// - /// If \c M is provided, metadata nodes will be numbered canonically; - /// otherwise, pointer addresses are substituted. - /// @{ - void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; - void printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST, - const Module *M = nullptr) const; - /// @} -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) - -// Specialized opaque metadata conversions. -inline Metadata **unwrap(LLVMMetadataRef *MDs) { - return reinterpret_cast(MDs); -} - -#define HANDLE_METADATA(CLASS) class CLASS; -#include "llvm/IR/Metadata.def" - -// Provide specializations of isa so that we don't need definitions of -// subclasses to see if the metadata is a subclass. -#define HANDLE_METADATA_LEAF(CLASS) \ - template <> struct isa_impl { \ - static inline bool doit(const Metadata &MD) { \ - return MD.getMetadataID() == Metadata::CLASS##Kind; \ - } \ - }; -#include "llvm/IR/Metadata.def" - -inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { - MD.print(OS); - return OS; -} - -/// Metadata wrapper in the Value hierarchy. -/// -/// A member of the \a Value hierarchy to represent a reference to metadata. -/// This allows, e.g., intrinsics to have metadata as operands. -/// -/// Notably, this is the only thing in either hierarchy that is allowed to -/// reference \a LocalAsMetadata. -class MetadataAsValue : public Value { - friend class ReplaceableMetadataImpl; - friend class LLVMContextImpl; - - Metadata *MD; - - MetadataAsValue(Type *Ty, Metadata *MD); - - /// Drop use of metadata (during teardown). - void dropUse() { MD = nullptr; } - -public: - ~MetadataAsValue(); - - static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); - static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); - - Metadata *getMetadata() const { return MD; } - - static bool classof(const Value *V) { - return V->getValueID() == MetadataAsValueVal; - } - -private: - void handleChangedMetadata(Metadata *MD); - void track(); - void untrack(); -}; - -/// API for tracking metadata references through RAUW and deletion. -/// -/// Shared API for updating \a Metadata pointers in subclasses that support -/// RAUW. -/// -/// This API is not meant to be used directly. See \a TrackingMDRef for a -/// user-friendly tracking reference. -class MetadataTracking { -public: - /// Track the reference to metadata. - /// - /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD - /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets - /// deleted, \c MD will be set to \c nullptr. - /// - /// If tracking isn't supported, \c *MD will not change. - /// - /// \return true iff tracking is supported by \c MD. - static bool track(Metadata *&MD) { - return track(&MD, *MD, static_cast(nullptr)); - } - - /// Track the reference to metadata for \a Metadata. - /// - /// As \a track(Metadata*&), but with support for calling back to \c Owner to - /// tell it that its operand changed. This could trigger \c Owner being - /// re-uniqued. - static bool track(void *Ref, Metadata &MD, Metadata &Owner) { - return track(Ref, MD, &Owner); - } - - /// Track the reference to metadata for \a MetadataAsValue. - /// - /// As \a track(Metadata*&), but with support for calling back to \c Owner to - /// tell it that its operand changed. This could trigger \c Owner being - /// re-uniqued. - static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { - return track(Ref, MD, &Owner); - } - - /// Stop tracking a reference to metadata. - /// - /// Stops \c *MD from tracking \c MD. - static void untrack(Metadata *&MD) { untrack(&MD, *MD); } - static void untrack(void *Ref, Metadata &MD); - - /// Move tracking from one reference to another. - /// - /// Semantically equivalent to \c untrack(MD) followed by \c track(New), - /// except that ownership callbacks are maintained. - /// - /// Note: it is an error if \c *MD does not equal \c New. - /// - /// \return true iff tracking is supported by \c MD. - static bool retrack(Metadata *&MD, Metadata *&New) { - return retrack(&MD, *MD, &New); - } - static bool retrack(void *Ref, Metadata &MD, void *New); - - /// Check whether metadata is replaceable. - static bool isReplaceable(const Metadata &MD); - - using OwnerTy = PointerUnion; - -private: - /// Track a reference to metadata for an owner. - /// - /// Generalized version of tracking. - static bool track(void *Ref, Metadata &MD, OwnerTy Owner); -}; - -/// Shared implementation of use-lists for replaceable metadata. -/// -/// Most metadata cannot be RAUW'ed. This is a shared implementation of -/// use-lists and associated API for the two that support it (\a ValueAsMetadata -/// and \a TempMDNode). -class ReplaceableMetadataImpl { - friend class MetadataTracking; - -public: - using OwnerTy = MetadataTracking::OwnerTy; - -private: - LLVMContext &Context; - uint64_t NextIndex = 0; - SmallDenseMap, 4> UseMap; - -public: - ReplaceableMetadataImpl(LLVMContext &Context) : Context(Context) {} - - ~ReplaceableMetadataImpl() { - assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); - } - - LLVMContext &getContext() const { return Context; } - - /// Replace all uses of this with MD. - /// - /// Replace all uses of this with \c MD, which is allowed to be null. - void replaceAllUsesWith(Metadata *MD); - - /// Returns the list of all DIArgList users of this. - SmallVector getAllArgListUsers(); - - /// Resolve all uses of this. - /// - /// Resolve all uses of this, turning off RAUW permanently. If \c - /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand - /// is resolved. - void resolveAllUses(bool ResolveUsers = true); - -private: - void addRef(void *Ref, OwnerTy Owner); - void dropRef(void *Ref); - void moveRef(void *Ref, void *New, const Metadata &MD); - - /// Lazily construct RAUW support on MD. - /// - /// If this is an unresolved MDNode, RAUW support will be created on-demand. - /// ValueAsMetadata always has RAUW support. - static ReplaceableMetadataImpl *getOrCreate(Metadata &MD); - - /// Get RAUW support on MD, if it exists. - static ReplaceableMetadataImpl *getIfExists(Metadata &MD); - - /// Check whether this node will support RAUW. - /// - /// Returns \c true unless getOrCreate() would return null. - static bool isReplaceable(const Metadata &MD); -}; - -/// Value wrapper in the Metadata hierarchy. -/// -/// This is a custom value handle that allows other metadata to refer to -/// classes in the Value hierarchy. -/// -/// Because of full uniquing support, each value is only wrapped by a single \a -/// ValueAsMetadata object, so the lookup maps are far more efficient than -/// those using ValueHandleBase. -class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { - friend class ReplaceableMetadataImpl; - friend class LLVMContextImpl; - - Value *V; - - /// Drop users without RAUW (during teardown). - void dropUsers() { - ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); - } - -protected: - ValueAsMetadata(unsigned ID, Value *V) - : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { - assert(V && "Expected valid value"); - } - - ~ValueAsMetadata() = default; - -public: - static ValueAsMetadata *get(Value *V); - - static ConstantAsMetadata *getConstant(Value *C) { - return cast(get(C)); - } - - static LocalAsMetadata *getLocal(Value *Local) { - return cast(get(Local)); - } - - static ValueAsMetadata *getIfExists(Value *V); - - static ConstantAsMetadata *getConstantIfExists(Value *C) { - return cast_or_null(getIfExists(C)); - } - - static LocalAsMetadata *getLocalIfExists(Value *Local) { - return cast_or_null(getIfExists(Local)); - } - - Value *getValue() const { return V; } - Type *getType() const { return V->getType(); } - LLVMContext &getContext() const { return V->getContext(); } - - SmallVector getAllArgListUsers() { - return ReplaceableMetadataImpl::getAllArgListUsers(); - } - - static void handleDeletion(Value *V); - static void handleRAUW(Value *From, Value *To); - -protected: - /// Handle collisions after \a Value::replaceAllUsesWith(). - /// - /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped - /// \a Value gets RAUW'ed and the target already exists, this is used to - /// merge the two metadata nodes. - void replaceAllUsesWith(Metadata *MD) { - ReplaceableMetadataImpl::replaceAllUsesWith(MD); - } - -public: - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == LocalAsMetadataKind || - MD->getMetadataID() == ConstantAsMetadataKind; - } -}; - -class ConstantAsMetadata : public ValueAsMetadata { - friend class ValueAsMetadata; - - ConstantAsMetadata(Constant *C) - : ValueAsMetadata(ConstantAsMetadataKind, C) {} - -public: - static ConstantAsMetadata *get(Constant *C) { - return ValueAsMetadata::getConstant(C); - } - - static ConstantAsMetadata *getIfExists(Constant *C) { - return ValueAsMetadata::getConstantIfExists(C); - } - - Constant *getValue() const { - return cast(ValueAsMetadata::getValue()); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == ConstantAsMetadataKind; - } -}; - -class LocalAsMetadata : public ValueAsMetadata { - friend class ValueAsMetadata; - - LocalAsMetadata(Value *Local) - : ValueAsMetadata(LocalAsMetadataKind, Local) { - assert(!isa(Local) && "Expected local value"); - } - -public: - static LocalAsMetadata *get(Value *Local) { - return ValueAsMetadata::getLocal(Local); - } - - static LocalAsMetadata *getIfExists(Value *Local) { - return ValueAsMetadata::getLocalIfExists(Local); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == LocalAsMetadataKind; - } -}; - -/// Transitional API for extracting constants from Metadata. -/// -/// This namespace contains transitional functions for metadata that points to -/// \a Constants. -/// -/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode -/// operands could refer to any \a Value. There's was a lot of code like this: -/// -/// \code -/// MDNode *N = ...; -/// auto *CI = dyn_cast(N->getOperand(2)); -/// \endcode -/// -/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining -/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three -/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and -/// cast in the \a Value hierarchy. Besides creating boiler-plate, this -/// requires subtle control flow changes. -/// -/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, -/// so that metadata can refer to numbers without traversing a bridge to the \a -/// Value hierarchy. In this final state, the code above would look like this: -/// -/// \code -/// MDNode *N = ...; -/// auto *MI = dyn_cast(N->getOperand(2)); -/// \endcode -/// -/// The API in this namespace supports the transition. \a MDInt doesn't exist -/// yet, and even once it does, changing each metadata schema to use it is its -/// own mini-project. In the meantime this API prevents us from introducing -/// complex and bug-prone control flow that will disappear in the end. In -/// particular, the above code looks like this: -/// -/// \code -/// MDNode *N = ...; -/// auto *CI = mdconst::dyn_extract(N->getOperand(2)); -/// \endcode -/// -/// The full set of provided functions includes: -/// -/// mdconst::hasa <=> isa -/// mdconst::extract <=> cast -/// mdconst::extract_or_null <=> cast_or_null -/// mdconst::dyn_extract <=> dyn_cast -/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null -/// -/// The target of the cast must be a subclass of \a Constant. -namespace mdconst { - -namespace detail { - -template T &make(); -template struct HasDereference { - using Yes = char[1]; - using No = char[2]; - template struct SFINAE {}; - - template - static Yes &hasDereference(SFINAE(*make()))> * = 0); - template static No &hasDereference(...); - - static const bool value = - sizeof(hasDereference(nullptr)) == sizeof(Yes); -}; -template struct IsValidPointer { - static const bool value = std::is_base_of::value && - HasDereference::value; -}; -template struct IsValidReference { - static const bool value = std::is_base_of::value && - std::is_convertible::value; -}; - -} // end namespace detail - -/// Check whether Metadata has a Value. -/// -/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of -/// type \c X. -template -inline std::enable_if_t::value, bool> -hasa(Y &&MD) { - assert(MD && "Null pointer sent into hasa"); - if (auto *V = dyn_cast(MD)) - return isa(V->getValue()); - return false; -} -template -inline std::enable_if_t::value, bool> -hasa(Y &MD) { - return hasa(&MD); -} - -/// Extract a Value from Metadata. -/// -/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. -template -inline std::enable_if_t::value, X *> -extract(Y &&MD) { - return cast(cast(MD)->getValue()); -} -template -inline std::enable_if_t::value, X *> -extract(Y &MD) { - return extract(&MD); -} - -/// Extract a Value from Metadata, allowing null. -/// -/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X -/// from \c MD, allowing \c MD to be null. -template -inline std::enable_if_t::value, X *> -extract_or_null(Y &&MD) { - if (auto *V = cast_or_null(MD)) - return cast(V->getValue()); - return nullptr; -} - -/// Extract a Value from Metadata, if any. -/// -/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X -/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a -/// Value it does contain is of the wrong subclass. -template -inline std::enable_if_t::value, X *> -dyn_extract(Y &&MD) { - if (auto *V = dyn_cast(MD)) - return dyn_cast(V->getValue()); - return nullptr; -} - -/// Extract a Value from Metadata, if any, allowing null. -/// -/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X -/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a -/// Value it does contain is of the wrong subclass, allowing \c MD to be null. -template -inline std::enable_if_t::value, X *> -dyn_extract_or_null(Y &&MD) { - if (auto *V = dyn_cast_or_null(MD)) - return dyn_cast(V->getValue()); - return nullptr; -} - -} // end namespace mdconst - -//===----------------------------------------------------------------------===// -/// A single uniqued string. -/// -/// These are used to efficiently contain a byte sequence for metadata. -/// MDString is always unnamed. -class MDString : public Metadata { - friend class StringMapEntryStorage; - - StringMapEntry *Entry = nullptr; - - MDString() : Metadata(MDStringKind, Uniqued) {} - -public: - MDString(const MDString &) = delete; - MDString &operator=(MDString &&) = delete; - MDString &operator=(const MDString &) = delete; - - static MDString *get(LLVMContext &Context, StringRef Str); - static MDString *get(LLVMContext &Context, const char *Str) { - return get(Context, Str ? StringRef(Str) : StringRef()); - } - - StringRef getString() const; - - unsigned getLength() const { return (unsigned)getString().size(); } - - using iterator = StringRef::iterator; - - /// Pointer to the first byte of the string. - iterator begin() const { return getString().begin(); } - - /// Pointer to one byte past the end of the string. - iterator end() const { return getString().end(); } - - const unsigned char *bytes_begin() const { return getString().bytes_begin(); } - const unsigned char *bytes_end() const { return getString().bytes_end(); } - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDStringKind; - } -}; - -/// A collection of metadata nodes that might be associated with a -/// memory access used by the alias-analysis infrastructure. -struct AAMDNodes { - explicit AAMDNodes() = default; - explicit AAMDNodes(MDNode *T, MDNode *TS, MDNode *S, MDNode *N) - : TBAA(T), TBAAStruct(TS), Scope(S), NoAlias(N) {} - - bool operator==(const AAMDNodes &A) const { - return TBAA == A.TBAA && TBAAStruct == A.TBAAStruct && Scope == A.Scope && - NoAlias == A.NoAlias; - } - - bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - - explicit operator bool() const { - return TBAA || TBAAStruct || Scope || NoAlias; - } - - /// The tag for type-based alias analysis. - MDNode *TBAA = nullptr; - - /// The tag for type-based alias analysis (tbaa struct). - MDNode *TBAAStruct = nullptr; - - /// The tag for alias scope specification (used with noalias). - MDNode *Scope = nullptr; - - /// The tag specifying the noalias scope. - MDNode *NoAlias = nullptr; - - // Shift tbaa Metadata node to start off bytes later - static MDNode *shiftTBAA(MDNode *M, size_t off); - - // Shift tbaa.struct Metadata node to start off bytes later - static MDNode *shiftTBAAStruct(MDNode *M, size_t off); - - // Extend tbaa Metadata node to apply to a series of bytes of length len. - // A size of -1 denotes an unknown size. - static MDNode *extendToTBAA(MDNode *TBAA, ssize_t len); - - /// Given two sets of AAMDNodes that apply to the same pointer, - /// give the best AAMDNodes that are compatible with both (i.e. a set of - /// nodes whose allowable aliasing conclusions are a subset of those - /// allowable by both of the inputs). However, for efficiency - /// reasons, do not create any new MDNodes. - AAMDNodes intersect(const AAMDNodes &Other) const { - AAMDNodes Result; - Result.TBAA = Other.TBAA == TBAA ? TBAA : nullptr; - Result.TBAAStruct = Other.TBAAStruct == TBAAStruct ? TBAAStruct : nullptr; - Result.Scope = Other.Scope == Scope ? Scope : nullptr; - Result.NoAlias = Other.NoAlias == NoAlias ? NoAlias : nullptr; - return Result; - } - - /// Create a new AAMDNode that describes this AAMDNode after applying a - /// constant offset to the start of the pointer. - AAMDNodes shift(size_t Offset) const { - AAMDNodes Result; - Result.TBAA = TBAA ? shiftTBAA(TBAA, Offset) : nullptr; - Result.TBAAStruct = - TBAAStruct ? shiftTBAAStruct(TBAAStruct, Offset) : nullptr; - Result.Scope = Scope; - Result.NoAlias = NoAlias; - return Result; - } - - /// Create a new AAMDNode that describes this AAMDNode after extending it to - /// apply to a series of bytes of length Len. A size of -1 denotes an unknown - /// size. - AAMDNodes extendTo(ssize_t Len) const { - AAMDNodes Result; - Result.TBAA = TBAA ? extendToTBAA(TBAA, Len) : nullptr; - // tbaa.struct contains (offset, size, type) triples. Extending the length - // of the tbaa.struct doesn't require changing this (though more information - // could be provided by adding more triples at subsequent lengths). - Result.TBAAStruct = TBAAStruct; - Result.Scope = Scope; - Result.NoAlias = NoAlias; - return Result; - } - - /// Given two sets of AAMDNodes applying to potentially different locations, - /// determine the best AAMDNodes that apply to both. - AAMDNodes merge(const AAMDNodes &Other) const; - - /// Determine the best AAMDNodes after concatenating two different locations - /// together. Different from `merge`, where different locations should - /// overlap each other, `concat` puts non-overlapping locations together. - AAMDNodes concat(const AAMDNodes &Other) const; -}; - -// Specialize DenseMapInfo for AAMDNodes. -template<> -struct DenseMapInfo { - static inline AAMDNodes getEmptyKey() { - return AAMDNodes(DenseMapInfo::getEmptyKey(), - nullptr, nullptr, nullptr); - } - - static inline AAMDNodes getTombstoneKey() { - return AAMDNodes(DenseMapInfo::getTombstoneKey(), - nullptr, nullptr, nullptr); - } - - static unsigned getHashValue(const AAMDNodes &Val) { - return DenseMapInfo::getHashValue(Val.TBAA) ^ - DenseMapInfo::getHashValue(Val.TBAAStruct) ^ - DenseMapInfo::getHashValue(Val.Scope) ^ - DenseMapInfo::getHashValue(Val.NoAlias); - } - - static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) { - return LHS == RHS; - } -}; - -/// Tracking metadata reference owned by Metadata. -/// -/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance -/// of \a Metadata, which has the option of registering itself for callbacks to -/// re-unique itself. -/// -/// In particular, this is used by \a MDNode. -class MDOperand { - Metadata *MD = nullptr; - -public: - MDOperand() = default; - MDOperand(MDOperand &&) = delete; - MDOperand(const MDOperand &) = delete; - MDOperand &operator=(MDOperand &&) = delete; - MDOperand &operator=(const MDOperand &) = delete; - ~MDOperand() { untrack(); } - - Metadata *get() const { return MD; } - operator Metadata *() const { return get(); } - Metadata *operator->() const { return get(); } - Metadata &operator*() const { return *get(); } - - void reset() { - untrack(); - MD = nullptr; - } - void reset(Metadata *MD, Metadata *Owner) { - untrack(); - this->MD = MD; - track(Owner); - } - -private: - void track(Metadata *Owner) { - if (MD) { - if (Owner) - MetadataTracking::track(this, *MD, *Owner); - else - MetadataTracking::track(MD); - } - } - - void untrack() { - assert(static_cast(this) == &MD && "Expected same address"); - if (MD) - MetadataTracking::untrack(MD); - } -}; - -template <> struct simplify_type { - using SimpleType = Metadata *; - - static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } -}; - -template <> struct simplify_type { - using SimpleType = Metadata *; - - static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } -}; - -/// Pointer to the context, with optional RAUW support. -/// -/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer -/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). -class ContextAndReplaceableUses { - PointerUnion Ptr; - -public: - ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} - ContextAndReplaceableUses( - std::unique_ptr ReplaceableUses) - : Ptr(ReplaceableUses.release()) { - assert(getReplaceableUses() && "Expected non-null replaceable uses"); - } - ContextAndReplaceableUses() = delete; - ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; - ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; - ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; - ContextAndReplaceableUses & - operator=(const ContextAndReplaceableUses &) = delete; - ~ContextAndReplaceableUses() { delete getReplaceableUses(); } - - operator LLVMContext &() { return getContext(); } - - /// Whether this contains RAUW support. - bool hasReplaceableUses() const { - return Ptr.is(); - } - - LLVMContext &getContext() const { - if (hasReplaceableUses()) - return getReplaceableUses()->getContext(); - return *Ptr.get(); - } - - ReplaceableMetadataImpl *getReplaceableUses() const { - if (hasReplaceableUses()) - return Ptr.get(); - return nullptr; - } - - /// Ensure that this has RAUW support, and then return it. - ReplaceableMetadataImpl *getOrCreateReplaceableUses() { - if (!hasReplaceableUses()) - makeReplaceable(std::make_unique(getContext())); - return getReplaceableUses(); - } - - /// Assign RAUW support to this. - /// - /// Make this replaceable, taking ownership of \c ReplaceableUses (which must - /// not be null). - void - makeReplaceable(std::unique_ptr ReplaceableUses) { - assert(ReplaceableUses && "Expected non-null replaceable uses"); - assert(&ReplaceableUses->getContext() == &getContext() && - "Expected same context"); - delete getReplaceableUses(); - Ptr = ReplaceableUses.release(); - } - - /// Drop RAUW support. - /// - /// Cede ownership of RAUW support, returning it. - std::unique_ptr takeReplaceableUses() { - assert(hasReplaceableUses() && "Expected to own replaceable uses"); - std::unique_ptr ReplaceableUses( - getReplaceableUses()); - Ptr = &ReplaceableUses->getContext(); - return ReplaceableUses; - } -}; - -struct TempMDNodeDeleter { - inline void operator()(MDNode *Node) const; -}; - -#define HANDLE_MDNODE_LEAF(CLASS) \ - using Temp##CLASS = std::unique_ptr; -#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) -#include "llvm/IR/Metadata.def" - -/// Metadata node. -/// -/// Metadata nodes can be uniqued, like constants, or distinct. Temporary -/// metadata nodes (with full support for RAUW) can be used to delay uniquing -/// until forward references are known. The basic metadata node is an \a -/// MDTuple. -/// -/// There is limited support for RAUW at construction time. At construction -/// time, if any operand is a temporary node (or an unresolved uniqued node, -/// which indicates a transitive temporary operand), the node itself will be -/// unresolved. As soon as all operands become resolved, it will drop RAUW -/// support permanently. -/// -/// If an unresolved node is part of a cycle, \a resolveCycles() needs -/// to be called on some member of the cycle once all temporary nodes have been -/// replaced. -class MDNode : public Metadata { - friend class ReplaceableMetadataImpl; - friend class LLVMContextImpl; - friend class DIArgList; - - unsigned NumOperands; - unsigned NumUnresolved; - - ContextAndReplaceableUses Context; - -protected: - MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, - ArrayRef Ops1, ArrayRef Ops2 = None); - ~MDNode() = default; - - void *operator new(size_t Size, unsigned NumOps); - void operator delete(void *Mem); - - /// Required by std, but never called. - void operator delete(void *, unsigned) { - llvm_unreachable("Constructor throws?"); - } - - /// Required by std, but never called. - void operator delete(void *, unsigned, bool) { - llvm_unreachable("Constructor throws?"); - } - - void dropAllReferences(); - - MDOperand *mutable_begin() { return mutable_end() - NumOperands; } - MDOperand *mutable_end() { return reinterpret_cast(this); } - - using mutable_op_range = iterator_range; - - mutable_op_range mutable_operands() { - return mutable_op_range(mutable_begin(), mutable_end()); - } - -public: - MDNode(const MDNode &) = delete; - void operator=(const MDNode &) = delete; - void *operator new(size_t) = delete; - - static inline MDTuple *get(LLVMContext &Context, ArrayRef MDs); - static inline MDTuple *getIfExists(LLVMContext &Context, - ArrayRef MDs); - static inline MDTuple *getDistinct(LLVMContext &Context, - ArrayRef MDs); - static inline TempMDTuple getTemporary(LLVMContext &Context, - ArrayRef MDs); - - /// Create a (temporary) clone of this. - TempMDNode clone() const; - - /// Deallocate a node created by getTemporary. - /// - /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining - /// references will be reset. - static void deleteTemporary(MDNode *N); - - LLVMContext &getContext() const { return Context.getContext(); } - - /// Replace a specific operand. - void replaceOperandWith(unsigned I, Metadata *New); - - /// Check if node is fully resolved. - /// - /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), - /// this always returns \c true. - /// - /// If \a isUniqued(), returns \c true if this has already dropped RAUW - /// support (because all operands are resolved). - /// - /// As forward declarations are resolved, their containers should get - /// resolved automatically. However, if this (or one of its operands) is - /// involved in a cycle, \a resolveCycles() needs to be called explicitly. - bool isResolved() const { return !isTemporary() && !NumUnresolved; } - - bool isUniqued() const { return Storage == Uniqued; } - bool isDistinct() const { return Storage == Distinct; } - bool isTemporary() const { return Storage == Temporary; } - - /// RAUW a temporary. - /// - /// \pre \a isTemporary() must be \c true. - void replaceAllUsesWith(Metadata *MD) { - assert(isTemporary() && "Expected temporary node"); - if (Context.hasReplaceableUses()) - Context.getReplaceableUses()->replaceAllUsesWith(MD); - } - - /// Resolve cycles. - /// - /// Once all forward declarations have been resolved, force cycles to be - /// resolved. - /// - /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). - void resolveCycles(); - - /// Resolve a unique, unresolved node. - void resolve(); - - /// Replace a temporary node with a permanent one. - /// - /// Try to create a uniqued version of \c N -- in place, if possible -- and - /// return it. If \c N cannot be uniqued, return a distinct node instead. - template - static std::enable_if_t::value, T *> - replaceWithPermanent(std::unique_ptr N) { - return cast(N.release()->replaceWithPermanentImpl()); - } - - /// Replace a temporary node with a uniqued one. - /// - /// Create a uniqued version of \c N -- in place, if possible -- and return - /// it. Takes ownership of the temporary node. - /// - /// \pre N does not self-reference. - template - static std::enable_if_t::value, T *> - replaceWithUniqued(std::unique_ptr N) { - return cast(N.release()->replaceWithUniquedImpl()); - } - - /// Replace a temporary node with a distinct one. - /// - /// Create a distinct version of \c N -- in place, if possible -- and return - /// it. Takes ownership of the temporary node. - template - static std::enable_if_t::value, T *> - replaceWithDistinct(std::unique_ptr N) { - return cast(N.release()->replaceWithDistinctImpl()); - } - - /// Print in tree shape. - /// - /// Prints definition of \c this in tree shape. - /// - /// If \c M is provided, metadata nodes will be numbered canonically; - /// otherwise, pointer addresses are substituted. - /// @{ - void printTree(raw_ostream &OS, const Module *M = nullptr) const; - void printTree(raw_ostream &OS, ModuleSlotTracker &MST, - const Module *M = nullptr) const; - /// @} - - /// User-friendly dump in tree shape. - /// - /// If \c M is provided, metadata nodes will be numbered canonically; - /// otherwise, pointer addresses are substituted. - /// - /// Note: this uses an explicit overload instead of default arguments so that - /// the nullptr version is easy to call from a debugger. - /// - /// @{ - void dumpTree() const; - void dumpTree(const Module *M) const; - /// @} - -private: - MDNode *replaceWithPermanentImpl(); - MDNode *replaceWithUniquedImpl(); - MDNode *replaceWithDistinctImpl(); - -protected: - /// Set an operand. - /// - /// Sets the operand directly, without worrying about uniquing. - void setOperand(unsigned I, Metadata *New); - - void storeDistinctInContext(); - template - static T *storeImpl(T *N, StorageType Storage, StoreT &Store); - template static T *storeImpl(T *N, StorageType Storage); - -private: - void handleChangedOperand(void *Ref, Metadata *New); - - /// Drop RAUW support, if any. - void dropReplaceableUses(); - - void resolveAfterOperandChange(Metadata *Old, Metadata *New); - void decrementUnresolvedOperandCount(); - void countUnresolvedOperands(); - - /// Mutate this to be "uniqued". - /// - /// Mutate this so that \a isUniqued(). - /// \pre \a isTemporary(). - /// \pre already added to uniquing set. - void makeUniqued(); - - /// Mutate this to be "distinct". - /// - /// Mutate this so that \a isDistinct(). - /// \pre \a isTemporary(). - void makeDistinct(); - - void deleteAsSubclass(); - MDNode *uniquify(); - void eraseFromStore(); - - template struct HasCachedHash; - template - static void dispatchRecalculateHash(NodeTy *N, std::true_type) { - N->recalculateHash(); - } - template - static void dispatchRecalculateHash(NodeTy *, std::false_type) {} - template - static void dispatchResetHash(NodeTy *N, std::true_type) { - N->setHash(0); - } - template - static void dispatchResetHash(NodeTy *, std::false_type) {} - -public: - using op_iterator = const MDOperand *; - using op_range = iterator_range; - - op_iterator op_begin() const { - return const_cast(this)->mutable_begin(); - } - - op_iterator op_end() const { - return const_cast(this)->mutable_end(); - } - - op_range operands() const { return op_range(op_begin(), op_end()); } - - const MDOperand &getOperand(unsigned I) const { - assert(I < NumOperands && "Out of range"); - return op_begin()[I]; - } - - /// Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Metadata *MD) { - switch (MD->getMetadataID()) { - default: - return false; -#define HANDLE_MDNODE_LEAF(CLASS) \ - case CLASS##Kind: \ - return true; -#include "llvm/IR/Metadata.def" - } - } - - /// Check whether MDNode is a vtable access. - bool isTBAAVtableAccess() const; - - /// Methods for metadata merging. - static MDNode *concatenate(MDNode *A, MDNode *B); - static MDNode *intersect(MDNode *A, MDNode *B); - static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); - static MDNode *getMostGenericRange(MDNode *A, MDNode *B); - static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); - static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B); -}; - -/// Tuple of metadata. -/// -/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by -/// default based on their operands. -class MDTuple : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - - MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, - ArrayRef Vals) - : MDNode(C, MDTupleKind, Storage, Vals) { - setHash(Hash); - } - - ~MDTuple() { dropAllReferences(); } - - void setHash(unsigned Hash) { SubclassData32 = Hash; } - void recalculateHash(); - - static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, - StorageType Storage, bool ShouldCreate = true); - - TempMDTuple cloneImpl() const { - return getTemporary(getContext(), SmallVector(operands())); - } - -public: - /// Get the hash, if any. - unsigned getHash() const { return SubclassData32; } - - static MDTuple *get(LLVMContext &Context, ArrayRef MDs) { - return getImpl(Context, MDs, Uniqued); - } - - static MDTuple *getIfExists(LLVMContext &Context, ArrayRef MDs) { - return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); - } - - /// Return a distinct node. - /// - /// Return a distinct node -- i.e., a node that is not uniqued. - static MDTuple *getDistinct(LLVMContext &Context, ArrayRef MDs) { - return getImpl(Context, MDs, Distinct); - } - - /// Return a temporary node. - /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static TempMDTuple getTemporary(LLVMContext &Context, - ArrayRef MDs) { - return TempMDTuple(getImpl(Context, MDs, Temporary)); - } - - /// Return a (temporary) clone of this. - TempMDTuple clone() const { return cloneImpl(); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTupleKind; - } -}; - -MDTuple *MDNode::get(LLVMContext &Context, ArrayRef MDs) { - return MDTuple::get(Context, MDs); -} - -MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef MDs) { - return MDTuple::getIfExists(Context, MDs); -} - -MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { - return MDTuple::getDistinct(Context, MDs); -} - -TempMDTuple MDNode::getTemporary(LLVMContext &Context, - ArrayRef MDs) { - return MDTuple::getTemporary(Context, MDs); -} - -void TempMDNodeDeleter::operator()(MDNode *Node) const { - MDNode::deleteTemporary(Node); -} - -/// This is a simple wrapper around an MDNode which provides a higher-level -/// interface by hiding the details of how alias analysis information is encoded -/// in its operands. -class AliasScopeNode { - const MDNode *Node = nullptr; - -public: - AliasScopeNode() = default; - explicit AliasScopeNode(const MDNode *N) : Node(N) {} - - /// Get the MDNode for this AliasScopeNode. - const MDNode *getNode() const { return Node; } - - /// Get the MDNode for this AliasScopeNode's domain. - const MDNode *getDomain() const { - if (Node->getNumOperands() < 2) - return nullptr; - return dyn_cast_or_null(Node->getOperand(1)); - } - StringRef getName() const { - if (Node->getNumOperands() > 2) - if (MDString *N = dyn_cast_or_null(Node->getOperand(2))) - return N->getString(); - return StringRef(); - } -}; - -/// Typed iterator through MDNode operands. -/// -/// An iterator that transforms an \a MDNode::iterator into an iterator over a -/// particular Metadata subclass. -template class TypedMDOperandIterator { - MDNode::op_iterator I = nullptr; - -public: - using iterator_category = std::input_iterator_tag; - using value_type = T *; - using difference_type = std::ptrdiff_t; - using pointer = void; - using reference = T *; - - TypedMDOperandIterator() = default; - explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} - - T *operator*() const { return cast_or_null(*I); } - - TypedMDOperandIterator &operator++() { - ++I; - return *this; - } - - TypedMDOperandIterator operator++(int) { - TypedMDOperandIterator Temp(*this); - ++I; - return Temp; - } - - bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } - bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } -}; - -/// Typed, array-like tuple of metadata. -/// -/// This is a wrapper for \a MDTuple that makes it act like an array holding a -/// particular type of metadata. -template class MDTupleTypedArrayWrapper { - const MDTuple *N = nullptr; - -public: - MDTupleTypedArrayWrapper() = default; - MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} - - template - MDTupleTypedArrayWrapper( - const MDTupleTypedArrayWrapper &Other, - std::enable_if_t::value> * = nullptr) - : N(Other.get()) {} - - template - explicit MDTupleTypedArrayWrapper( - const MDTupleTypedArrayWrapper &Other, - std::enable_if_t::value> * = nullptr) - : N(Other.get()) {} - - explicit operator bool() const { return get(); } - explicit operator MDTuple *() const { return get(); } - - MDTuple *get() const { return const_cast(N); } - MDTuple *operator->() const { return get(); } - MDTuple &operator*() const { return *get(); } - - // FIXME: Fix callers and remove condition on N. - unsigned size() const { return N ? N->getNumOperands() : 0u; } - bool empty() const { return N ? N->getNumOperands() == 0 : true; } - T *operator[](unsigned I) const { return cast_or_null(N->getOperand(I)); } - - // FIXME: Fix callers and remove condition on N. - using iterator = TypedMDOperandIterator; - - iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } - iterator end() const { return N ? iterator(N->op_end()) : iterator(); } -}; - -#define HANDLE_METADATA(CLASS) \ - using CLASS##Array = MDTupleTypedArrayWrapper; -#include "llvm/IR/Metadata.def" - -/// Placeholder metadata for operands of distinct MDNodes. -/// -/// This is a lightweight placeholder for an operand of a distinct node. It's -/// purpose is to help track forward references when creating a distinct node. -/// This allows distinct nodes involved in a cycle to be constructed before -/// their operands without requiring a heavyweight temporary node with -/// full-blown RAUW support. -/// -/// Each placeholder supports only a single MDNode user. Clients should pass -/// an ID, retrieved via \a getID(), to indicate the "real" operand that this -/// should be replaced with. -/// -/// While it would be possible to implement move operators, they would be -/// fairly expensive. Leave them unimplemented to discourage their use -/// (clients can use std::deque, std::list, BumpPtrAllocator, etc.). -class DistinctMDOperandPlaceholder : public Metadata { - friend class MetadataTracking; - - Metadata **Use = nullptr; - -public: - explicit DistinctMDOperandPlaceholder(unsigned ID) - : Metadata(DistinctMDOperandPlaceholderKind, Distinct) { - SubclassData32 = ID; - } - - DistinctMDOperandPlaceholder() = delete; - DistinctMDOperandPlaceholder(DistinctMDOperandPlaceholder &&) = delete; - DistinctMDOperandPlaceholder(const DistinctMDOperandPlaceholder &) = delete; - - ~DistinctMDOperandPlaceholder() { - if (Use) - *Use = nullptr; - } - - unsigned getID() const { return SubclassData32; } - - /// Replace the use of this with MD. - void replaceUseWith(Metadata *MD) { - if (!Use) - return; - *Use = MD; - - if (*Use) - MetadataTracking::track(*Use); - - Metadata *T = cast(this); - MetadataTracking::untrack(T); - assert(!Use && "Use is still being tracked despite being untracked!"); - } -}; - -//===----------------------------------------------------------------------===// -/// A tuple of MDNodes. -/// -/// Despite its name, a NamedMDNode isn't itself an MDNode. -/// -/// NamedMDNodes are named module-level entities that contain lists of MDNodes. -/// -/// It is illegal for a NamedMDNode to appear as an operand of an MDNode. -class NamedMDNode : public ilist_node { - friend class LLVMContextImpl; - friend class Module; - - std::string Name; - Module *Parent = nullptr; - void *Operands; // SmallVector - - void setParent(Module *M) { Parent = M; } - - explicit NamedMDNode(const Twine &N); - - template class op_iterator_impl { - friend class NamedMDNode; - - const NamedMDNode *Node = nullptr; - unsigned Idx = 0; - - op_iterator_impl(const NamedMDNode *N, unsigned i) : Node(N), Idx(i) {} - - public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = T2; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - op_iterator_impl() = default; - - bool operator==(const op_iterator_impl &o) const { return Idx == o.Idx; } - bool operator!=(const op_iterator_impl &o) const { return Idx != o.Idx; } - - op_iterator_impl &operator++() { - ++Idx; - return *this; - } - - op_iterator_impl operator++(int) { - op_iterator_impl tmp(*this); - operator++(); - return tmp; - } - - op_iterator_impl &operator--() { - --Idx; - return *this; - } - - op_iterator_impl operator--(int) { - op_iterator_impl tmp(*this); - operator--(); - return tmp; - } - - T1 operator*() const { return Node->getOperand(Idx); } - }; - -public: - NamedMDNode(const NamedMDNode &) = delete; - ~NamedMDNode(); - - /// Drop all references and remove the node from parent module. - void eraseFromParent(); - - /// Remove all uses and clear node vector. - void dropAllReferences() { clearOperands(); } - /// Drop all references to this node's operands. - void clearOperands(); - - /// Get the module that holds this named metadata collection. - inline Module *getParent() { return Parent; } - inline const Module *getParent() const { return Parent; } - - MDNode *getOperand(unsigned i) const; - unsigned getNumOperands() const; - void addOperand(MDNode *M); - void setOperand(unsigned I, MDNode *New); - StringRef getName() const; - void print(raw_ostream &ROS, bool IsForDebug = false) const; - void print(raw_ostream &ROS, ModuleSlotTracker &MST, - bool IsForDebug = false) const; - void dump() const; - - // --------------------------------------------------------------------------- - // Operand Iterator interface... - // - using op_iterator = op_iterator_impl; - - op_iterator op_begin() { return op_iterator(this, 0); } - op_iterator op_end() { return op_iterator(this, getNumOperands()); } - - using const_op_iterator = op_iterator_impl; - - const_op_iterator op_begin() const { return const_op_iterator(this, 0); } - const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); } - - inline iterator_range operands() { - return make_range(op_begin(), op_end()); - } - inline iterator_range operands() const { - return make_range(op_begin(), op_end()); - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_ISA_CONVERSION_FUNCTIONS(NamedMDNode, LLVMNamedMDNodeRef) - -} // end namespace llvm - -#endif // LLVM_IR_METADATA_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Module.h b/suite/synctools/tablegen/include/llvm/IR/Module.h deleted file mode 100644 index 7b834fbeee..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Module.h +++ /dev/null @@ -1,973 +0,0 @@ -//===- llvm/Module.h - C++ class to represent a VM module -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// Module.h This file contains the declarations for the Module class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MODULE_H -#define LLVM_IR_MODULE_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Comdat.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalAlias.h" -#include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/CodeGen.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class Error; -class FunctionType; -class GVMaterializer; -class LLVMContext; -class MemoryBuffer; -class ModuleSummaryIndex; -class RandomNumberGenerator; -class StructType; -class VersionTuple; - -/// A Module instance is used to store all the information related to an -/// LLVM module. Modules are the top level container of all other LLVM -/// Intermediate Representation (IR) objects. Each module directly contains a -/// list of globals variables, a list of functions, a list of libraries (or -/// other modules) this module depends on, a symbol table, and various data -/// about the target's characteristics. -/// -/// A module maintains a GlobalValRefMap object that is used to hold all -/// constant references to global variables in the module. When a global -/// variable is destroyed, it should have no entries in the GlobalValueRefMap. -/// The main container class for the LLVM Intermediate Representation. -class LLVM_EXTERNAL_VISIBILITY Module { - /// @name Types And Enumerations - /// @{ -public: - /// The type for the list of global variables. - using GlobalListType = SymbolTableList; - /// The type for the list of functions. - using FunctionListType = SymbolTableList; - /// The type for the list of aliases. - using AliasListType = SymbolTableList; - /// The type for the list of ifuncs. - using IFuncListType = SymbolTableList; - /// The type for the list of named metadata. - using NamedMDListType = ilist; - /// The type of the comdat "symbol" table. - using ComdatSymTabType = StringMap; - /// The type for mapping names to named metadata. - using NamedMDSymTabType = StringMap; - - /// The Global Variable iterator. - using global_iterator = GlobalListType::iterator; - /// The Global Variable constant iterator. - using const_global_iterator = GlobalListType::const_iterator; - - /// The Function iterators. - using iterator = FunctionListType::iterator; - /// The Function constant iterator - using const_iterator = FunctionListType::const_iterator; - - /// The Function reverse iterator. - using reverse_iterator = FunctionListType::reverse_iterator; - /// The Function constant reverse iterator. - using const_reverse_iterator = FunctionListType::const_reverse_iterator; - - /// The Global Alias iterators. - using alias_iterator = AliasListType::iterator; - /// The Global Alias constant iterator - using const_alias_iterator = AliasListType::const_iterator; - - /// The Global IFunc iterators. - using ifunc_iterator = IFuncListType::iterator; - /// The Global IFunc constant iterator - using const_ifunc_iterator = IFuncListType::const_iterator; - - /// The named metadata iterators. - using named_metadata_iterator = NamedMDListType::iterator; - /// The named metadata constant iterators. - using const_named_metadata_iterator = NamedMDListType::const_iterator; - - /// This enumeration defines the supported behaviors of module flags. - enum ModFlagBehavior { - /// Emits an error if two values disagree, otherwise the resulting value is - /// that of the operands. - Error = 1, - - /// Emits a warning if two values disagree. The result value will be the - /// operand for the flag from the first module being linked. - Warning = 2, - - /// Adds a requirement that another module flag be present and have a - /// specified value after linking is performed. The value must be a metadata - /// pair, where the first element of the pair is the ID of the module flag - /// to be restricted, and the second element of the pair is the value the - /// module flag should be restricted to. This behavior can be used to - /// restrict the allowable results (via triggering of an error) of linking - /// IDs with the **Override** behavior. - Require = 3, - - /// Uses the specified value, regardless of the behavior or value of the - /// other module. If both modules specify **Override**, but the values - /// differ, an error will be emitted. - Override = 4, - - /// Appends the two values, which are required to be metadata nodes. - Append = 5, - - /// Appends the two values, which are required to be metadata - /// nodes. However, duplicate entries in the second list are dropped - /// during the append operation. - AppendUnique = 6, - - /// Takes the max of the two values, which are required to be integers. - Max = 7, - - // Markers: - ModFlagBehaviorFirstVal = Error, - ModFlagBehaviorLastVal = Max - }; - - /// Checks if Metadata represents a valid ModFlagBehavior, and stores the - /// converted result in MFB. - static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); - - /// Check if the given module flag metadata represents a valid module flag, - /// and store the flag behavior, the key string and the value metadata. - static bool isValidModuleFlag(const MDNode &ModFlag, ModFlagBehavior &MFB, - MDString *&Key, Metadata *&Val); - - struct ModuleFlagEntry { - ModFlagBehavior Behavior; - MDString *Key; - Metadata *Val; - - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) - : Behavior(B), Key(K), Val(V) {} - }; - -/// @} -/// @name Member Variables -/// @{ -private: - LLVMContext &Context; ///< The LLVMContext from which types and - ///< constants are allocated. - GlobalListType GlobalList; ///< The Global Variables in the module - FunctionListType FunctionList; ///< The Functions in the module - AliasListType AliasList; ///< The Aliases in the module - IFuncListType IFuncList; ///< The IFuncs in the module - NamedMDListType NamedMDList; ///< The named metadata in the module - std::string GlobalScopeAsm; ///< Inline Asm at global scope. - std::unique_ptr ValSymTab; ///< Symbol table for values - ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs - std::unique_ptr - OwnedMemoryBuffer; ///< Memory buffer directly owned by this - ///< module, for legacy clients only. - std::unique_ptr - Materializer; ///< Used to materialize GlobalValues - std::string ModuleID; ///< Human readable identifier for the module - std::string SourceFileName; ///< Original source file name for module, - ///< recorded in bitcode. - std::string TargetTriple; ///< Platform target triple Module compiled on - ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) - NamedMDSymTabType NamedMDSymTab; ///< NamedMDNode names. - DataLayout DL; ///< DataLayout associated with the module - StringMap - CurrentIntrinsicIds; ///< Keep track of the current unique id count for - ///< the specified intrinsic basename. - DenseMap, unsigned> - UniquedIntrinsicNames; ///< Keep track of uniqued names of intrinsics - ///< based on unnamed types. The combination of - ///< ID and FunctionType maps to the extension that - ///< is used to make the intrinsic name unique. - - friend class Constant; - -/// @} -/// @name Constructors -/// @{ -public: - /// The Module constructor. Note that there is no default constructor. You - /// must provide a name for the module upon construction. - explicit Module(StringRef ModuleID, LLVMContext& C); - /// The module destructor. This will dropAllReferences. - ~Module(); - -/// @} -/// @name Module Level Accessors -/// @{ - - /// Get the module identifier which is, essentially, the name of the module. - /// @returns the module identifier as a string - const std::string &getModuleIdentifier() const { return ModuleID; } - - /// Returns the number of non-debug IR instructions in the module. - /// This is equivalent to the sum of the IR instruction counts of each - /// function contained in the module. - unsigned getInstructionCount() const; - - /// Get the module's original source file name. When compiling from - /// bitcode, this is taken from a bitcode record where it was recorded. - /// For other compiles it is the same as the ModuleID, which would - /// contain the source file name. - const std::string &getSourceFileName() const { return SourceFileName; } - - /// Get a short "name" for the module. - /// - /// This is useful for debugging or logging. It is essentially a convenience - /// wrapper around getModuleIdentifier(). - StringRef getName() const { return ModuleID; } - - /// Get the data layout string for the module's target platform. This is - /// equivalent to getDataLayout()->getStringRepresentation(). - const std::string &getDataLayoutStr() const { - return DL.getStringRepresentation(); - } - - /// Get the data layout for the module's target platform. - const DataLayout &getDataLayout() const; - - /// Get the target triple which is a string describing the target host. - /// @returns a string containing the target triple. - const std::string &getTargetTriple() const { return TargetTriple; } - - /// Get the global data context. - /// @returns LLVMContext - a container for LLVM's global information - LLVMContext &getContext() const { return Context; } - - /// Get any module-scope inline assembly blocks. - /// @returns a string containing the module-scope inline assembly blocks. - const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - - /// Get a RandomNumberGenerator salted for use with this module. The - /// RNG can be seeded via -rng-seed= and is salted with the - /// ModuleID and the provided pass salt. The returned RNG should not - /// be shared across threads or passes. - /// - /// A unique RNG per pass ensures a reproducible random stream even - /// when other randomness consuming passes are added or removed. In - /// addition, the random stream will be reproducible across LLVM - /// versions when the pass does not change. - std::unique_ptr createRNG(const StringRef Name) const; - - /// Return true if size-info optimization remark is enabled, false - /// otherwise. - bool shouldEmitInstrCountChangedRemark() { - return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled( - "size-info"); - } - - /// @} - /// @name Module Level Mutators - /// @{ - - /// Set the module identifier. - void setModuleIdentifier(StringRef ID) { ModuleID = std::string(ID); } - - /// Set the module's original source file name. - void setSourceFileName(StringRef Name) { SourceFileName = std::string(Name); } - - /// Set the data layout - void setDataLayout(StringRef Desc); - void setDataLayout(const DataLayout &Other); - - /// Set the target triple. - void setTargetTriple(StringRef T) { TargetTriple = std::string(T); } - - /// Set the module-scope inline assembly blocks. - /// A trailing newline is added if the input doesn't have one. - void setModuleInlineAsm(StringRef Asm) { - GlobalScopeAsm = std::string(Asm); - if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n') - GlobalScopeAsm += '\n'; - } - - /// Append to the module-scope inline assembly blocks. - /// A trailing newline is added if the input doesn't have one. - void appendModuleInlineAsm(StringRef Asm) { - GlobalScopeAsm += Asm; - if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n') - GlobalScopeAsm += '\n'; - } - -/// @} -/// @name Generic Value Accessors -/// @{ - - /// Return the global value in the module with the specified name, of - /// arbitrary type. This method returns null if a global with the specified - /// name is not found. - GlobalValue *getNamedValue(StringRef Name) const; - - /// Return the number of global values in the module. - unsigned getNumNamedValues() const; - - /// Return a unique non-zero ID for the specified metadata kind. This ID is - /// uniqued across modules in the current LLVMContext. - unsigned getMDKindID(StringRef Name) const; - - /// Populate client supplied SmallVector with the name for custom metadata IDs - /// registered in this LLVMContext. - void getMDKindNames(SmallVectorImpl &Result) const; - - /// Populate client supplied SmallVector with the bundle tags registered in - /// this LLVMContext. The bundle tags are ordered by increasing bundle IDs. - /// \see LLVMContext::getOperandBundleTagID - void getOperandBundleTags(SmallVectorImpl &Result) const; - - std::vector getIdentifiedStructTypes() const; - - /// Return a unique name for an intrinsic whose mangling is based on an - /// unnamed type. The Proto represents the function prototype. - std::string getUniqueIntrinsicName(StringRef BaseName, Intrinsic::ID Id, - const FunctionType *Proto); - -/// @} -/// @name Function Accessors -/// @{ - - /// Look up the specified function in the module symbol table. Four - /// possibilities: - /// 1. If it does not exist, add a prototype for the function and return it. - /// 2. Otherwise, if the existing function has the correct prototype, return - /// the existing function. - /// 3. Finally, the function exists but has the wrong prototype: return the - /// function with a constantexpr cast to the right prototype. - /// - /// In all cases, the returned value is a FunctionCallee wrapper around the - /// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or - /// the bitcast to the function. - FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, - AttributeList AttributeList); - - FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T); - - /// Look up the specified function in the module symbol table. If it does not - /// exist, add a prototype for the function and return it. This function - /// guarantees to return a constant of pointer to the specified function type - /// or a ConstantExpr BitCast of that type if the named function has a - /// different type. This version of the method takes a list of - /// function arguments, which makes it easier for clients to use. - template - FunctionCallee getOrInsertFunction(StringRef Name, - AttributeList AttributeList, Type *RetTy, - ArgsTy... Args) { - SmallVector ArgTys{Args...}; - return getOrInsertFunction(Name, - FunctionType::get(RetTy, ArgTys, false), - AttributeList); - } - - /// Same as above, but without the attributes. - template - FunctionCallee getOrInsertFunction(StringRef Name, Type *RetTy, - ArgsTy... Args) { - return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...); - } - - // Avoid an incorrect ordering that'd otherwise compile incorrectly. - template - FunctionCallee - getOrInsertFunction(StringRef Name, AttributeList AttributeList, - FunctionType *Invalid, ArgsTy... Args) = delete; - - /// Look up the specified function in the module symbol table. If it does not - /// exist, return null. - Function *getFunction(StringRef Name) const; - -/// @} -/// @name Global Variable Accessors -/// @{ - - /// Look up the specified global variable in the module symbol table. If it - /// does not exist, return null. If AllowInternal is set to true, this - /// function will return types that have InternalLinkage. By default, these - /// types are not returned. - GlobalVariable *getGlobalVariable(StringRef Name) const { - return getGlobalVariable(Name, false); - } - - GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const; - - GlobalVariable *getGlobalVariable(StringRef Name, - bool AllowInternal = false) { - return static_cast(this)->getGlobalVariable(Name, - AllowInternal); - } - - /// Return the global variable in the module with the specified name, of - /// arbitrary type. This method returns null if a global with the specified - /// name is not found. - const GlobalVariable *getNamedGlobal(StringRef Name) const { - return getGlobalVariable(Name, true); - } - GlobalVariable *getNamedGlobal(StringRef Name) { - return const_cast( - static_cast(this)->getNamedGlobal(Name)); - } - - /// Look up the specified global in the module symbol table. - /// If it does not exist, invoke a callback to create a declaration of the - /// global and return it. The global is constantexpr casted to the expected - /// type if necessary. - Constant * - getOrInsertGlobal(StringRef Name, Type *Ty, - function_ref CreateGlobalCallback); - - /// Look up the specified global in the module symbol table. If required, this - /// overload constructs the global variable using its constructor's defaults. - Constant *getOrInsertGlobal(StringRef Name, Type *Ty); - -/// @} -/// @name Global Alias Accessors -/// @{ - - /// Return the global alias in the module with the specified name, of - /// arbitrary type. This method returns null if a global with the specified - /// name is not found. - GlobalAlias *getNamedAlias(StringRef Name) const; - -/// @} -/// @name Global IFunc Accessors -/// @{ - - /// Return the global ifunc in the module with the specified name, of - /// arbitrary type. This method returns null if a global with the specified - /// name is not found. - GlobalIFunc *getNamedIFunc(StringRef Name) const; - -/// @} -/// @name Named Metadata Accessors -/// @{ - - /// Return the first NamedMDNode in the module with the specified name. This - /// method returns null if a NamedMDNode with the specified name is not found. - NamedMDNode *getNamedMetadata(const Twine &Name) const; - - /// Return the named MDNode in the module with the specified name. This method - /// returns a new NamedMDNode if a NamedMDNode with the specified name is not - /// found. - NamedMDNode *getOrInsertNamedMetadata(StringRef Name); - - /// Remove the given NamedMDNode from this module and delete it. - void eraseNamedMetadata(NamedMDNode *NMD); - -/// @} -/// @name Comdat Accessors -/// @{ - - /// Return the Comdat in the module with the specified name. It is created - /// if it didn't already exist. - Comdat *getOrInsertComdat(StringRef Name); - -/// @} -/// @name Module Flags Accessors -/// @{ - - /// Returns the module flags in the provided vector. - void getModuleFlagsMetadata(SmallVectorImpl &Flags) const; - - /// Return the corresponding value if Key appears in module flags, otherwise - /// return null. - Metadata *getModuleFlag(StringRef Key) const; - - /// Returns the NamedMDNode in the module that represents module-level flags. - /// This method returns null if there are no module-level flags. - NamedMDNode *getModuleFlagsMetadata() const; - - /// Returns the NamedMDNode in the module that represents module-level flags. - /// If module-level flags aren't found, it creates the named metadata that - /// contains them. - NamedMDNode *getOrInsertModuleFlagsMetadata(); - - /// Add a module-level flag to the module-level flags metadata. It will create - /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); - void addModuleFlag(MDNode *Node); - /// Like addModuleFlag but replaces the old module flag if it already exists. - void setModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); - - /// @} - /// @name Materialization - /// @{ - - /// Sets the GVMaterializer to GVM. This module must not yet have a - /// Materializer. To reset the materializer for a module that already has one, - /// call materializeAll first. Destroying this module will destroy - /// its materializer without materializing any more GlobalValues. Without - /// destroying the Module, there is no way to detach or destroy a materializer - /// without materializing all the GVs it controls, to avoid leaving orphan - /// unmaterialized GVs. - void setMaterializer(GVMaterializer *GVM); - /// Retrieves the GVMaterializer, if any, for this Module. - GVMaterializer *getMaterializer() const { return Materializer.get(); } - bool isMaterialized() const { return !getMaterializer(); } - - /// Make sure the GlobalValue is fully read. - llvm::Error materialize(GlobalValue *GV); - - /// Make sure all GlobalValues in this Module are fully read and clear the - /// Materializer. - llvm::Error materializeAll(); - - llvm::Error materializeMetadata(); - -/// @} -/// @name Direct access to the globals list, functions list, and symbol table -/// @{ - - /// Get the Module's list of global variables (constant). - const GlobalListType &getGlobalList() const { return GlobalList; } - /// Get the Module's list of global variables. - GlobalListType &getGlobalList() { return GlobalList; } - - static GlobalListType Module::*getSublistAccess(GlobalVariable*) { - return &Module::GlobalList; - } - - /// Get the Module's list of functions (constant). - const FunctionListType &getFunctionList() const { return FunctionList; } - /// Get the Module's list of functions. - FunctionListType &getFunctionList() { return FunctionList; } - static FunctionListType Module::*getSublistAccess(Function*) { - return &Module::FunctionList; - } - - /// Get the Module's list of aliases (constant). - const AliasListType &getAliasList() const { return AliasList; } - /// Get the Module's list of aliases. - AliasListType &getAliasList() { return AliasList; } - - static AliasListType Module::*getSublistAccess(GlobalAlias*) { - return &Module::AliasList; - } - - /// Get the Module's list of ifuncs (constant). - const IFuncListType &getIFuncList() const { return IFuncList; } - /// Get the Module's list of ifuncs. - IFuncListType &getIFuncList() { return IFuncList; } - - static IFuncListType Module::*getSublistAccess(GlobalIFunc*) { - return &Module::IFuncList; - } - - /// Get the Module's list of named metadata (constant). - const NamedMDListType &getNamedMDList() const { return NamedMDList; } - /// Get the Module's list of named metadata. - NamedMDListType &getNamedMDList() { return NamedMDList; } - - static NamedMDListType Module::*getSublistAccess(NamedMDNode*) { - return &Module::NamedMDList; - } - - /// Get the symbol table of global variable and function identifiers - const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } - /// Get the Module's symbol table of global variable and function identifiers. - ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } - - /// Get the Module's symbol table for COMDATs (constant). - const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; } - /// Get the Module's symbol table for COMDATs. - ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; } - -/// @} -/// @name Global Variable Iteration -/// @{ - - global_iterator global_begin() { return GlobalList.begin(); } - const_global_iterator global_begin() const { return GlobalList.begin(); } - global_iterator global_end () { return GlobalList.end(); } - const_global_iterator global_end () const { return GlobalList.end(); } - size_t global_size () const { return GlobalList.size(); } - bool global_empty() const { return GlobalList.empty(); } - - iterator_range globals() { - return make_range(global_begin(), global_end()); - } - iterator_range globals() const { - return make_range(global_begin(), global_end()); - } - -/// @} -/// @name Function Iteration -/// @{ - - iterator begin() { return FunctionList.begin(); } - const_iterator begin() const { return FunctionList.begin(); } - iterator end () { return FunctionList.end(); } - const_iterator end () const { return FunctionList.end(); } - reverse_iterator rbegin() { return FunctionList.rbegin(); } - const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); } - reverse_iterator rend() { return FunctionList.rend(); } - const_reverse_iterator rend() const { return FunctionList.rend(); } - size_t size() const { return FunctionList.size(); } - bool empty() const { return FunctionList.empty(); } - - iterator_range functions() { - return make_range(begin(), end()); - } - iterator_range functions() const { - return make_range(begin(), end()); - } - -/// @} -/// @name Alias Iteration -/// @{ - - alias_iterator alias_begin() { return AliasList.begin(); } - const_alias_iterator alias_begin() const { return AliasList.begin(); } - alias_iterator alias_end () { return AliasList.end(); } - const_alias_iterator alias_end () const { return AliasList.end(); } - size_t alias_size () const { return AliasList.size(); } - bool alias_empty() const { return AliasList.empty(); } - - iterator_range aliases() { - return make_range(alias_begin(), alias_end()); - } - iterator_range aliases() const { - return make_range(alias_begin(), alias_end()); - } - -/// @} -/// @name IFunc Iteration -/// @{ - - ifunc_iterator ifunc_begin() { return IFuncList.begin(); } - const_ifunc_iterator ifunc_begin() const { return IFuncList.begin(); } - ifunc_iterator ifunc_end () { return IFuncList.end(); } - const_ifunc_iterator ifunc_end () const { return IFuncList.end(); } - size_t ifunc_size () const { return IFuncList.size(); } - bool ifunc_empty() const { return IFuncList.empty(); } - - iterator_range ifuncs() { - return make_range(ifunc_begin(), ifunc_end()); - } - iterator_range ifuncs() const { - return make_range(ifunc_begin(), ifunc_end()); - } - - /// @} - /// @name Convenience iterators - /// @{ - - using global_object_iterator = - concat_iterator; - using const_global_object_iterator = - concat_iterator; - - iterator_range global_objects(); - iterator_range global_objects() const; - - using global_value_iterator = - concat_iterator; - using const_global_value_iterator = - concat_iterator; - - iterator_range global_values(); - iterator_range global_values() const; - - /// @} - /// @name Named Metadata Iteration - /// @{ - - named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); } - const_named_metadata_iterator named_metadata_begin() const { - return NamedMDList.begin(); - } - - named_metadata_iterator named_metadata_end() { return NamedMDList.end(); } - const_named_metadata_iterator named_metadata_end() const { - return NamedMDList.end(); - } - - size_t named_metadata_size() const { return NamedMDList.size(); } - bool named_metadata_empty() const { return NamedMDList.empty(); } - - iterator_range named_metadata() { - return make_range(named_metadata_begin(), named_metadata_end()); - } - iterator_range named_metadata() const { - return make_range(named_metadata_begin(), named_metadata_end()); - } - - /// An iterator for DICompileUnits that skips those marked NoDebug. - class debug_compile_units_iterator { - NamedMDNode *CUs; - unsigned Idx; - - void SkipNoDebugCUs(); - - public: - using iterator_category = std::input_iterator_tag; - using value_type = DICompileUnit *; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - explicit debug_compile_units_iterator(NamedMDNode *CUs, unsigned Idx) - : CUs(CUs), Idx(Idx) { - SkipNoDebugCUs(); - } - - debug_compile_units_iterator &operator++() { - ++Idx; - SkipNoDebugCUs(); - return *this; - } - - debug_compile_units_iterator operator++(int) { - debug_compile_units_iterator T(*this); - ++Idx; - return T; - } - - bool operator==(const debug_compile_units_iterator &I) const { - return Idx == I.Idx; - } - - bool operator!=(const debug_compile_units_iterator &I) const { - return Idx != I.Idx; - } - - DICompileUnit *operator*() const; - DICompileUnit *operator->() const; - }; - - debug_compile_units_iterator debug_compile_units_begin() const { - auto *CUs = getNamedMetadata("llvm.dbg.cu"); - return debug_compile_units_iterator(CUs, 0); - } - - debug_compile_units_iterator debug_compile_units_end() const { - auto *CUs = getNamedMetadata("llvm.dbg.cu"); - return debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0); - } - - /// Return an iterator for all DICompileUnits listed in this Module's - /// llvm.dbg.cu named metadata node and aren't explicitly marked as - /// NoDebug. - iterator_range debug_compile_units() const { - auto *CUs = getNamedMetadata("llvm.dbg.cu"); - return make_range( - debug_compile_units_iterator(CUs, 0), - debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0)); - } -/// @} - - /// Destroy ConstantArrays in LLVMContext if they are not used. - /// ConstantArrays constructed during linking can cause quadratic memory - /// explosion. Releasing all unused constants can cause a 20% LTO compile-time - /// slowdown for a large application. - /// - /// NOTE: Constants are currently owned by LLVMContext. This can then only - /// be called where all uses of the LLVMContext are understood. - void dropTriviallyDeadConstantArrays(); - -/// @name Utility functions for printing and dumping Module objects -/// @{ - - /// Print the module to an output stream with an optional - /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include - /// uselistorder directives so that use-lists can be recreated when reading - /// the assembly. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, - bool ShouldPreserveUseListOrder = false, - bool IsForDebug = false) const; - - /// Dump the module to stderr (for debugging). - void dump() const; - - /// This function causes all the subinstructions to "let go" of all references - /// that they are maintaining. This allows one to 'delete' a whole class at - /// a time, even though there may be circular references... first all - /// references are dropped, and all use counts go to zero. Then everything - /// is delete'd for real. Note that no operations are valid on an object - /// that has "dropped all references", except operator delete. - void dropAllReferences(); - -/// @} -/// @name Utility functions for querying Debug information. -/// @{ - - /// Returns the Number of Register ParametersDwarf Version by checking - /// module flags. - unsigned getNumberRegisterParameters() const; - - /// Returns the Dwarf Version by checking module flags. - unsigned getDwarfVersion() const; - - /// Returns the DWARF format by checking module flags. - bool isDwarf64() const; - - /// Returns the CodeView Version by checking module flags. - /// Returns zero if not present in module. - unsigned getCodeViewFlag() const; - -/// @} -/// @name Utility functions for querying and setting PIC level -/// @{ - - /// Returns the PIC level (small or large model) - PICLevel::Level getPICLevel() const; - - /// Set the PIC level (small or large model) - void setPICLevel(PICLevel::Level PL); -/// @} - -/// @} -/// @name Utility functions for querying and setting PIE level -/// @{ - - /// Returns the PIE level (small or large model) - PIELevel::Level getPIELevel() const; - - /// Set the PIE level (small or large model) - void setPIELevel(PIELevel::Level PL); -/// @} - - /// @} - /// @name Utility function for querying and setting code model - /// @{ - - /// Returns the code model (tiny, small, kernel, medium or large model) - Optional getCodeModel() const; - - /// Set the code model (tiny, small, kernel, medium or large) - void setCodeModel(CodeModel::Model CL); - /// @} - - /// @name Utility functions for querying and setting PGO summary - /// @{ - - /// Attach profile summary metadata to this module. - void setProfileSummary(Metadata *M, ProfileSummary::Kind Kind); - - /// Returns profile summary metadata. When IsCS is true, use the context - /// sensitive profile summary. - Metadata *getProfileSummary(bool IsCS) const; - /// @} - - /// Returns whether semantic interposition is to be respected. - bool getSemanticInterposition() const; - - /// Set whether semantic interposition is to be respected. - void setSemanticInterposition(bool); - - /// Returns true if PLT should be avoided for RTLib calls. - bool getRtLibUseGOT() const; - - /// Set that PLT should be avoid for RTLib calls. - void setRtLibUseGOT(); - - /// Get/set whether synthesized functions should get the uwtable attribute. - bool getUwtable() const; - void setUwtable(); - - /// Get/set whether synthesized functions should get the "frame-pointer" - /// attribute. - FramePointerKind getFramePointer() const; - void setFramePointer(FramePointerKind Kind); - - /// Get/set what kind of stack protector guard to use. - StringRef getStackProtectorGuard() const; - void setStackProtectorGuard(StringRef Kind); - - /// Get/set which register to use as the stack protector guard register. The - /// empty string is equivalent to "global". Other values may be "tls" or - /// "sysreg". - StringRef getStackProtectorGuardReg() const; - void setStackProtectorGuardReg(StringRef Reg); - - /// Get/set what offset from the stack protector to use. - int getStackProtectorGuardOffset() const; - void setStackProtectorGuardOffset(int Offset); - - /// Get/set the stack alignment overridden from the default. - unsigned getOverrideStackAlignment() const; - void setOverrideStackAlignment(unsigned Align); - - /// @name Utility functions for querying and setting the build SDK version - /// @{ - - /// Attach a build SDK version metadata to this module. - void setSDKVersion(const VersionTuple &V); - - /// Get the build SDK version metadata. - /// - /// An empty version is returned if no such metadata is attached. - VersionTuple getSDKVersion() const; - /// @} - - /// Take ownership of the given memory buffer. - void setOwnedMemoryBuffer(std::unique_ptr MB); - - /// Set the partial sample profile ratio in the profile summary module flag, - /// if applicable. - void setPartialSampleProfileRatio(const ModuleSummaryIndex &Index); - - /// Get the target variant triple which is a string describing a variant of - /// the target host platform. For example, Mac Catalyst can be a variant - /// target triple for a macOS target. - /// @returns a string containing the target variant triple. - StringRef getDarwinTargetVariantTriple() const; - - /// Get the target variant version build SDK version metadata. - /// - /// An empty version is returned if no such metadata is attached. - VersionTuple getDarwinTargetVariantSDKVersion() const; -}; - -/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the -/// initializer elements of that global in a SmallVector and return the global -/// itself. -GlobalVariable *collectUsedGlobalVariables(const Module &M, - SmallVectorImpl &Vec, - bool CompilerUsed); - -/// An raw_ostream inserter for modules. -inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { - M.print(O, nullptr); - return O; -} - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef) - -/* LLVMModuleProviderRef exists for historical reasons, but now just holds a - * Module. - */ -inline Module *unwrap(LLVMModuleProviderRef MP) { - return reinterpret_cast(MP); -} - -} // end namespace llvm - -#endif // LLVM_IR_MODULE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ModuleSlotTracker.h b/suite/synctools/tablegen/include/llvm/IR/ModuleSlotTracker.h deleted file mode 100644 index 37cfc0f072..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ModuleSlotTracker.h +++ /dev/null @@ -1,109 +0,0 @@ -//===-- llvm/IR/ModuleSlotTracker.h -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MODULESLOTTRACKER_H -#define LLVM_IR_MODULESLOTTRACKER_H - -#include -#include -#include -#include - -namespace llvm { - -class Module; -class Function; -class SlotTracker; -class Value; -class MDNode; - -/// Abstract interface of slot tracker storage. -class AbstractSlotTrackerStorage { -public: - virtual ~AbstractSlotTrackerStorage(); - - virtual unsigned getNextMetadataSlot() = 0; - - virtual void createMetadataSlot(const MDNode *) = 0; - virtual int getMetadataSlot(const MDNode *) = 0; -}; - -/// Manage lifetime of a slot tracker for printing IR. -/// -/// Wrapper around the \a SlotTracker used internally by \a AsmWriter. This -/// class allows callers to share the cost of incorporating the metadata in a -/// module or a function. -/// -/// If the IR changes from underneath \a ModuleSlotTracker, strings like -/// "" will be printed, or, worse, the wrong slots entirely. -class ModuleSlotTracker { - /// Storage for a slot tracker. - std::unique_ptr MachineStorage; - bool ShouldCreateStorage = false; - bool ShouldInitializeAllMetadata = false; - - const Module *M = nullptr; - const Function *F = nullptr; - SlotTracker *Machine = nullptr; - - std::function - ProcessModuleHookFn; - std::function - ProcessFunctionHookFn; - -public: - /// Wrap a preinitialized SlotTracker. - ModuleSlotTracker(SlotTracker &Machine, const Module *M, - const Function *F = nullptr); - - /// Construct a slot tracker from a module. - /// - /// If \a M is \c nullptr, uses a null slot tracker. Otherwise, initializes - /// a slot tracker, and initializes all metadata slots. \c - /// ShouldInitializeAllMetadata defaults to true because this is expected to - /// be shared between multiple callers, and otherwise MDNode references will - /// not match up. - explicit ModuleSlotTracker(const Module *M, - bool ShouldInitializeAllMetadata = true); - - /// Destructor to clean up storage. - virtual ~ModuleSlotTracker(); - - /// Lazily creates a slot tracker. - SlotTracker *getMachine(); - - const Module *getModule() const { return M; } - const Function *getCurrentFunction() const { return F; } - - /// Incorporate the given function. - /// - /// Purge the currently incorporated function and incorporate \c F. If \c F - /// is currently incorporated, this is a no-op. - void incorporateFunction(const Function &F); - - /// Return the slot number of the specified local value. - /// - /// A function that defines this value should be incorporated prior to calling - /// this method. - /// Return -1 if the value is not in the function's SlotTracker. - int getLocalSlot(const Value *V); - - void setProcessHook( - std::function); - void setProcessHook(std::function); - - using MachineMDNodeListType = - std::vector>; - - void collectMDNodes(MachineMDNodeListType &L, unsigned LB, unsigned UB) const; -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndex.h b/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndex.h deleted file mode 100644 index b76bc879fb..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndex.h +++ /dev/null @@ -1,1664 +0,0 @@ -//===- llvm/ModuleSummaryIndex.h - Module Summary Index ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// @file -/// ModuleSummaryIndex.h This file contains the declarations the classes that -/// hold the module index and summary for function importing. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MODULESUMMARYINDEX_H -#define LLVM_IR_MODULESUMMARYINDEX_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/ConstantRange.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/ScaledNumber.h" -#include "llvm/Support/StringSaver.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -template struct GraphTraits; - -namespace yaml { - -template struct MappingTraits; - -} // end namespace yaml - -/// Class to accumulate and hold information about a callee. -struct CalleeInfo { - enum class HotnessType : uint8_t { - Unknown = 0, - Cold = 1, - None = 2, - Hot = 3, - Critical = 4 - }; - - // The size of the bit-field might need to be adjusted if more values are - // added to HotnessType enum. - uint32_t Hotness : 3; - - /// The value stored in RelBlockFreq has to be interpreted as the digits of - /// a scaled number with a scale of \p -ScaleShift. - uint32_t RelBlockFreq : 29; - static constexpr int32_t ScaleShift = 8; - static constexpr uint64_t MaxRelBlockFreq = (1 << 29) - 1; - - CalleeInfo() - : Hotness(static_cast(HotnessType::Unknown)), RelBlockFreq(0) {} - explicit CalleeInfo(HotnessType Hotness, uint64_t RelBF) - : Hotness(static_cast(Hotness)), RelBlockFreq(RelBF) {} - - void updateHotness(const HotnessType OtherHotness) { - Hotness = std::max(Hotness, static_cast(OtherHotness)); - } - - HotnessType getHotness() const { return HotnessType(Hotness); } - - /// Update \p RelBlockFreq from \p BlockFreq and \p EntryFreq - /// - /// BlockFreq is divided by EntryFreq and added to RelBlockFreq. To represent - /// fractional values, the result is represented as a fixed point number with - /// scale of -ScaleShift. - void updateRelBlockFreq(uint64_t BlockFreq, uint64_t EntryFreq) { - if (EntryFreq == 0) - return; - using Scaled64 = ScaledNumber; - Scaled64 Temp(BlockFreq, ScaleShift); - Temp /= Scaled64::get(EntryFreq); - - uint64_t Sum = - SaturatingAdd(Temp.toInt(), RelBlockFreq); - Sum = std::min(Sum, uint64_t(MaxRelBlockFreq)); - RelBlockFreq = static_cast(Sum); - } -}; - -inline const char *getHotnessName(CalleeInfo::HotnessType HT) { - switch (HT) { - case CalleeInfo::HotnessType::Unknown: - return "unknown"; - case CalleeInfo::HotnessType::Cold: - return "cold"; - case CalleeInfo::HotnessType::None: - return "none"; - case CalleeInfo::HotnessType::Hot: - return "hot"; - case CalleeInfo::HotnessType::Critical: - return "critical"; - } - llvm_unreachable("invalid hotness"); -} - -class GlobalValueSummary; - -using GlobalValueSummaryList = std::vector>; - -struct alignas(8) GlobalValueSummaryInfo { - union NameOrGV { - NameOrGV(bool HaveGVs) { - if (HaveGVs) - GV = nullptr; - else - Name = ""; - } - - /// The GlobalValue corresponding to this summary. This is only used in - /// per-module summaries and when the IR is available. E.g. when module - /// analysis is being run, or when parsing both the IR and the summary - /// from assembly. - const GlobalValue *GV; - - /// Summary string representation. This StringRef points to BC module - /// string table and is valid until module data is stored in memory. - /// This is guaranteed to happen until runThinLTOBackend function is - /// called, so it is safe to use this field during thin link. This field - /// is only valid if summary index was loaded from BC file. - StringRef Name; - } U; - - GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {} - - /// List of global value summary structures for a particular value held - /// in the GlobalValueMap. Requires a vector in the case of multiple - /// COMDAT values of the same name. - GlobalValueSummaryList SummaryList; -}; - -/// Map from global value GUID to corresponding summary structures. Use a -/// std::map rather than a DenseMap so that pointers to the map's value_type -/// (which are used by ValueInfo) are not invalidated by insertion. Also it will -/// likely incur less overhead, as the value type is not very small and the size -/// of the map is unknown, resulting in inefficiencies due to repeated -/// insertions and resizing. -using GlobalValueSummaryMapTy = - std::map; - -/// Struct that holds a reference to a particular GUID in a global value -/// summary. -struct ValueInfo { - enum Flags { HaveGV = 1, ReadOnly = 2, WriteOnly = 4 }; - PointerIntPair - RefAndFlags; - - ValueInfo() = default; - ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) { - RefAndFlags.setPointer(R); - RefAndFlags.setInt(HaveGVs); - } - - explicit operator bool() const { return getRef(); } - - GlobalValue::GUID getGUID() const { return getRef()->first; } - const GlobalValue *getValue() const { - assert(haveGVs()); - return getRef()->second.U.GV; - } - - ArrayRef> getSummaryList() const { - return getRef()->second.SummaryList; - } - - StringRef name() const { - return haveGVs() ? getRef()->second.U.GV->getName() - : getRef()->second.U.Name; - } - - bool haveGVs() const { return RefAndFlags.getInt() & HaveGV; } - bool isReadOnly() const { - assert(isValidAccessSpecifier()); - return RefAndFlags.getInt() & ReadOnly; - } - bool isWriteOnly() const { - assert(isValidAccessSpecifier()); - return RefAndFlags.getInt() & WriteOnly; - } - unsigned getAccessSpecifier() const { - assert(isValidAccessSpecifier()); - return RefAndFlags.getInt() & (ReadOnly | WriteOnly); - } - bool isValidAccessSpecifier() const { - unsigned BadAccessMask = ReadOnly | WriteOnly; - return (RefAndFlags.getInt() & BadAccessMask) != BadAccessMask; - } - void setReadOnly() { - // We expect ro/wo attribute to set only once during - // ValueInfo lifetime. - assert(getAccessSpecifier() == 0); - RefAndFlags.setInt(RefAndFlags.getInt() | ReadOnly); - } - void setWriteOnly() { - assert(getAccessSpecifier() == 0); - RefAndFlags.setInt(RefAndFlags.getInt() | WriteOnly); - } - - const GlobalValueSummaryMapTy::value_type *getRef() const { - return RefAndFlags.getPointer(); - } - - /// Returns the most constraining visibility among summaries. The - /// visibilities, ordered from least to most constraining, are: default, - /// protected and hidden. - GlobalValue::VisibilityTypes getELFVisibility() const; - - /// Checks if all summaries are DSO local (have the flag set). When DSOLocal - /// propagation has been done, set the parameter to enable fast check. - bool isDSOLocal(bool WithDSOLocalPropagation = false) const; - - /// Checks if all copies are eligible for auto-hiding (have flag set). - bool canAutoHide() const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) { - OS << VI.getGUID(); - if (!VI.name().empty()) - OS << " (" << VI.name() << ")"; - return OS; -} - -inline bool operator==(const ValueInfo &A, const ValueInfo &B) { - assert(A.getRef() && B.getRef() && - "Need ValueInfo with non-null Ref for comparison"); - return A.getRef() == B.getRef(); -} - -inline bool operator!=(const ValueInfo &A, const ValueInfo &B) { - assert(A.getRef() && B.getRef() && - "Need ValueInfo with non-null Ref for comparison"); - return A.getRef() != B.getRef(); -} - -inline bool operator<(const ValueInfo &A, const ValueInfo &B) { - assert(A.getRef() && B.getRef() && - "Need ValueInfo with non-null Ref to compare GUIDs"); - return A.getGUID() < B.getGUID(); -} - -template <> struct DenseMapInfo { - static inline ValueInfo getEmptyKey() { - return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); - } - - static inline ValueInfo getTombstoneKey() { - return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16); - } - - static inline bool isSpecialKey(ValueInfo V) { - return V == getTombstoneKey() || V == getEmptyKey(); - } - - static bool isEqual(ValueInfo L, ValueInfo R) { - // We are not supposed to mix ValueInfo(s) with different HaveGVs flag - // in a same container. - assert(isSpecialKey(L) || isSpecialKey(R) || (L.haveGVs() == R.haveGVs())); - return L.getRef() == R.getRef(); - } - static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); } -}; - -/// Function and variable summary information to aid decisions and -/// implementation of importing. -class GlobalValueSummary { -public: - /// Sububclass discriminator (for dyn_cast<> et al.) - enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind }; - - /// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield. - struct GVFlags { - /// The linkage type of the associated global value. - /// - /// One use is to flag values that have local linkage types and need to - /// have module identifier appended before placing into the combined - /// index, to disambiguate from other values with the same name. - /// In the future this will be used to update and optimize linkage - /// types based on global summary-based analysis. - unsigned Linkage : 4; - - /// Indicates the visibility. - unsigned Visibility : 2; - - /// Indicate if the global value cannot be imported (e.g. it cannot - /// be renamed or references something that can't be renamed). - unsigned NotEligibleToImport : 1; - - /// In per-module summary, indicate that the global value must be considered - /// a live root for index-based liveness analysis. Used for special LLVM - /// values such as llvm.global_ctors that the linker does not know about. - /// - /// In combined summary, indicate that the global value is live. - unsigned Live : 1; - - /// Indicates that the linker resolved the symbol to a definition from - /// within the same linkage unit. - unsigned DSOLocal : 1; - - /// In the per-module summary, indicates that the global value is - /// linkonce_odr and global unnamed addr (so eligible for auto-hiding - /// via hidden visibility). In the combined summary, indicates that the - /// prevailing linkonce_odr copy can be auto-hidden via hidden visibility - /// when it is upgraded to weak_odr in the backend. This is legal when - /// all copies are eligible for auto-hiding (i.e. all copies were - /// linkonce_odr global unnamed addr. If any copy is not (e.g. it was - /// originally weak_odr, we cannot auto-hide the prevailing copy as it - /// means the symbol was externally visible. - unsigned CanAutoHide : 1; - - /// Convenience Constructors - explicit GVFlags(GlobalValue::LinkageTypes Linkage, - GlobalValue::VisibilityTypes Visibility, - bool NotEligibleToImport, bool Live, bool IsLocal, - bool CanAutoHide) - : Linkage(Linkage), Visibility(Visibility), - NotEligibleToImport(NotEligibleToImport), Live(Live), - DSOLocal(IsLocal), CanAutoHide(CanAutoHide) {} - }; - -private: - /// Kind of summary for use in dyn_cast<> et al. - SummaryKind Kind; - - GVFlags Flags; - - /// This is the hash of the name of the symbol in the original file. It is - /// identical to the GUID for global symbols, but differs for local since the - /// GUID includes the module level id in the hash. - GlobalValue::GUID OriginalName = 0; - - /// Path of module IR containing value's definition, used to locate - /// module during importing. - /// - /// This is only used during parsing of the combined index, or when - /// parsing the per-module index for creation of the combined summary index, - /// not during writing of the per-module index which doesn't contain a - /// module path string table. - StringRef ModulePath; - - /// List of values referenced by this global value's definition - /// (either by the initializer of a global variable, or referenced - /// from within a function). This does not include functions called, which - /// are listed in the derived FunctionSummary object. - std::vector RefEdgeList; - -protected: - GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector Refs) - : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) { - assert((K != AliasKind || Refs.empty()) && - "Expect no references for AliasSummary"); - } - -public: - virtual ~GlobalValueSummary() = default; - - /// Returns the hash of the original name, it is identical to the GUID for - /// externally visible symbols, but not for local ones. - GlobalValue::GUID getOriginalName() const { return OriginalName; } - - /// Initialize the original name hash in this summary. - void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; } - - /// Which kind of summary subclass this is. - SummaryKind getSummaryKind() const { return Kind; } - - /// Set the path to the module containing this function, for use in - /// the combined index. - void setModulePath(StringRef ModPath) { ModulePath = ModPath; } - - /// Get the path to the module containing this function. - StringRef modulePath() const { return ModulePath; } - - /// Get the flags for this GlobalValue (see \p struct GVFlags). - GVFlags flags() const { return Flags; } - - /// Return linkage type recorded for this global value. - GlobalValue::LinkageTypes linkage() const { - return static_cast(Flags.Linkage); - } - - /// Sets the linkage to the value determined by global summary-based - /// optimization. Will be applied in the ThinLTO backends. - void setLinkage(GlobalValue::LinkageTypes Linkage) { - Flags.Linkage = Linkage; - } - - /// Return true if this global value can't be imported. - bool notEligibleToImport() const { return Flags.NotEligibleToImport; } - - bool isLive() const { return Flags.Live; } - - void setLive(bool Live) { Flags.Live = Live; } - - void setDSOLocal(bool Local) { Flags.DSOLocal = Local; } - - bool isDSOLocal() const { return Flags.DSOLocal; } - - void setCanAutoHide(bool CanAutoHide) { Flags.CanAutoHide = CanAutoHide; } - - bool canAutoHide() const { return Flags.CanAutoHide; } - - GlobalValue::VisibilityTypes getVisibility() const { - return (GlobalValue::VisibilityTypes)Flags.Visibility; - } - void setVisibility(GlobalValue::VisibilityTypes Vis) { - Flags.Visibility = (unsigned)Vis; - } - - /// Flag that this global value cannot be imported. - void setNotEligibleToImport() { Flags.NotEligibleToImport = true; } - - /// Return the list of values referenced by this global value definition. - ArrayRef refs() const { return RefEdgeList; } - - /// If this is an alias summary, returns the summary of the aliased object (a - /// global variable or function), otherwise returns itself. - GlobalValueSummary *getBaseObject(); - const GlobalValueSummary *getBaseObject() const; - - friend class ModuleSummaryIndex; -}; - -/// Alias summary information. -class AliasSummary : public GlobalValueSummary { - ValueInfo AliaseeValueInfo; - - /// This is the Aliasee in the same module as alias (could get from VI, trades - /// memory for time). Note that this pointer may be null (and the value info - /// empty) when we have a distributed index where the alias is being imported - /// (as a copy of the aliasee), but the aliasee is not. - GlobalValueSummary *AliaseeSummary; - -public: - AliasSummary(GVFlags Flags) - : GlobalValueSummary(AliasKind, Flags, ArrayRef{}), - AliaseeSummary(nullptr) {} - - /// Check if this is an alias summary. - static bool classof(const GlobalValueSummary *GVS) { - return GVS->getSummaryKind() == AliasKind; - } - - void setAliasee(ValueInfo &AliaseeVI, GlobalValueSummary *Aliasee) { - AliaseeValueInfo = AliaseeVI; - AliaseeSummary = Aliasee; - } - - bool hasAliasee() const { - assert(!!AliaseeSummary == (AliaseeValueInfo && - !AliaseeValueInfo.getSummaryList().empty()) && - "Expect to have both aliasee summary and summary list or neither"); - return !!AliaseeSummary; - } - - const GlobalValueSummary &getAliasee() const { - assert(AliaseeSummary && "Unexpected missing aliasee summary"); - return *AliaseeSummary; - } - - GlobalValueSummary &getAliasee() { - return const_cast( - static_cast(this)->getAliasee()); - } - ValueInfo getAliaseeVI() const { - assert(AliaseeValueInfo && "Unexpected missing aliasee"); - return AliaseeValueInfo; - } - GlobalValue::GUID getAliaseeGUID() const { - assert(AliaseeValueInfo && "Unexpected missing aliasee"); - return AliaseeValueInfo.getGUID(); - } -}; - -const inline GlobalValueSummary *GlobalValueSummary::getBaseObject() const { - if (auto *AS = dyn_cast(this)) - return &AS->getAliasee(); - return this; -} - -inline GlobalValueSummary *GlobalValueSummary::getBaseObject() { - if (auto *AS = dyn_cast(this)) - return &AS->getAliasee(); - return this; -} - -/// Function summary information to aid decisions and implementation of -/// importing. -class FunctionSummary : public GlobalValueSummary { -public: - /// call edge pair. - using EdgeTy = std::pair; - - /// Types for -force-summary-edges-cold debugging option. - enum ForceSummaryHotnessType : unsigned { - FSHT_None, - FSHT_AllNonCritical, - FSHT_All - }; - - /// An "identifier" for a virtual function. This contains the type identifier - /// represented as a GUID and the offset from the address point to the virtual - /// function pointer, where "address point" is as defined in the Itanium ABI: - /// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general - struct VFuncId { - GlobalValue::GUID GUID; - uint64_t Offset; - }; - - /// A specification for a virtual function call with all constant integer - /// arguments. This is used to perform virtual constant propagation on the - /// summary. - struct ConstVCall { - VFuncId VFunc; - std::vector Args; - }; - - /// All type identifier related information. Because these fields are - /// relatively uncommon we only allocate space for them if necessary. - struct TypeIdInfo { - /// List of type identifiers used by this function in llvm.type.test - /// intrinsics referenced by something other than an llvm.assume intrinsic, - /// represented as GUIDs. - std::vector TypeTests; - - /// List of virtual calls made by this function using (respectively) - /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do - /// not have all constant integer arguments. - std::vector TypeTestAssumeVCalls, TypeCheckedLoadVCalls; - - /// List of virtual calls made by this function using (respectively) - /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with - /// all constant integer arguments. - std::vector TypeTestAssumeConstVCalls, - TypeCheckedLoadConstVCalls; - }; - - /// Flags specific to function summaries. - struct FFlags { - // Function attribute flags. Used to track if a function accesses memory, - // recurses or aliases. - unsigned ReadNone : 1; - unsigned ReadOnly : 1; - unsigned NoRecurse : 1; - unsigned ReturnDoesNotAlias : 1; - - // Indicate if the global value cannot be inlined. - unsigned NoInline : 1; - // Indicate if function should be always inlined. - unsigned AlwaysInline : 1; - // Indicate if function never raises an exception. Can be modified during - // thinlink function attribute propagation - unsigned NoUnwind : 1; - // Indicate if function contains instructions that mayThrow - unsigned MayThrow : 1; - - // If there are calls to unknown targets (e.g. indirect) - unsigned HasUnknownCall : 1; - - // Indicate if a function must be an unreachable function. - // - // This bit is sufficient but not necessary; - // if this bit is on, the function must be regarded as unreachable; - // if this bit is off, the function might be reachable or unreachable. - unsigned MustBeUnreachable : 1; - - FFlags &operator&=(const FFlags &RHS) { - this->ReadNone &= RHS.ReadNone; - this->ReadOnly &= RHS.ReadOnly; - this->NoRecurse &= RHS.NoRecurse; - this->ReturnDoesNotAlias &= RHS.ReturnDoesNotAlias; - this->NoInline &= RHS.NoInline; - this->AlwaysInline &= RHS.AlwaysInline; - this->NoUnwind &= RHS.NoUnwind; - this->MayThrow &= RHS.MayThrow; - this->HasUnknownCall &= RHS.HasUnknownCall; - this->MustBeUnreachable &= RHS.MustBeUnreachable; - return *this; - } - - bool anyFlagSet() { - return this->ReadNone | this->ReadOnly | this->NoRecurse | - this->ReturnDoesNotAlias | this->NoInline | this->AlwaysInline | - this->NoUnwind | this->MayThrow | this->HasUnknownCall | - this->MustBeUnreachable; - } - - operator std::string() { - std::string Output; - raw_string_ostream OS(Output); - OS << "funcFlags: ("; - OS << "readNone: " << this->ReadNone; - OS << ", readOnly: " << this->ReadOnly; - OS << ", noRecurse: " << this->NoRecurse; - OS << ", returnDoesNotAlias: " << this->ReturnDoesNotAlias; - OS << ", noInline: " << this->NoInline; - OS << ", alwaysInline: " << this->AlwaysInline; - OS << ", noUnwind: " << this->NoUnwind; - OS << ", mayThrow: " << this->MayThrow; - OS << ", hasUnknownCall: " << this->HasUnknownCall; - OS << ", mustBeUnreachable: " << this->MustBeUnreachable; - OS << ")"; - return OS.str(); - } - }; - - /// Describes the uses of a parameter by the function. - struct ParamAccess { - static constexpr uint32_t RangeWidth = 64; - - /// Describes the use of a value in a call instruction, specifying the - /// call's target, the value's parameter number, and the possible range of - /// offsets from the beginning of the value that are passed. - struct Call { - uint64_t ParamNo = 0; - ValueInfo Callee; - ConstantRange Offsets{/*BitWidth=*/RangeWidth, /*isFullSet=*/true}; - - Call() = default; - Call(uint64_t ParamNo, ValueInfo Callee, const ConstantRange &Offsets) - : ParamNo(ParamNo), Callee(Callee), Offsets(Offsets) {} - }; - - uint64_t ParamNo = 0; - /// The range contains byte offsets from the parameter pointer which - /// accessed by the function. In the per-module summary, it only includes - /// accesses made by the function instructions. In the combined summary, it - /// also includes accesses by nested function calls. - ConstantRange Use{/*BitWidth=*/RangeWidth, /*isFullSet=*/true}; - /// In the per-module summary, it summarizes the byte offset applied to each - /// pointer parameter before passing to each corresponding callee. - /// In the combined summary, it's empty and information is propagated by - /// inter-procedural analysis and applied to the Use field. - std::vector Calls; - - ParamAccess() = default; - ParamAccess(uint64_t ParamNo, const ConstantRange &Use) - : ParamNo(ParamNo), Use(Use) {} - }; - - /// Create an empty FunctionSummary (with specified call edges). - /// Used to represent external nodes and the dummy root node. - static FunctionSummary - makeDummyFunctionSummary(std::vector Edges) { - return FunctionSummary( - FunctionSummary::GVFlags( - GlobalValue::LinkageTypes::AvailableExternallyLinkage, - GlobalValue::DefaultVisibility, - /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false, - /*CanAutoHide=*/false), - /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, - std::vector(), std::move(Edges), - std::vector(), - std::vector(), - std::vector(), - std::vector(), - std::vector(), - std::vector()); - } - - /// A dummy node to reference external functions that aren't in the index - static FunctionSummary ExternalNode; - -private: - /// Number of instructions (ignoring debug instructions, e.g.) computed - /// during the initial compile step when the summary index is first built. - unsigned InstCount; - - /// Function summary specific flags. - FFlags FunFlags; - - /// The synthesized entry count of the function. - /// This is only populated during ThinLink phase and remains unused while - /// generating per-module summaries. - uint64_t EntryCount = 0; - - /// List of call edge pairs from this function. - std::vector CallGraphEdgeList; - - std::unique_ptr TIdInfo; - - /// Uses for every parameter to this function. - using ParamAccessesTy = std::vector; - std::unique_ptr ParamAccesses; - -public: - FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags, - uint64_t EntryCount, std::vector Refs, - std::vector CGEdges, - std::vector TypeTests, - std::vector TypeTestAssumeVCalls, - std::vector TypeCheckedLoadVCalls, - std::vector TypeTestAssumeConstVCalls, - std::vector TypeCheckedLoadConstVCalls, - std::vector Params) - : GlobalValueSummary(FunctionKind, Flags, std::move(Refs)), - InstCount(NumInsts), FunFlags(FunFlags), EntryCount(EntryCount), - CallGraphEdgeList(std::move(CGEdges)) { - if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() || - !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() || - !TypeCheckedLoadConstVCalls.empty()) - TIdInfo = std::make_unique( - TypeIdInfo{std::move(TypeTests), std::move(TypeTestAssumeVCalls), - std::move(TypeCheckedLoadVCalls), - std::move(TypeTestAssumeConstVCalls), - std::move(TypeCheckedLoadConstVCalls)}); - if (!Params.empty()) - ParamAccesses = std::make_unique(std::move(Params)); - } - // Gets the number of readonly and writeonly refs in RefEdgeList - std::pair specialRefCounts() const; - - /// Check if this is a function summary. - static bool classof(const GlobalValueSummary *GVS) { - return GVS->getSummaryKind() == FunctionKind; - } - - /// Get function summary flags. - FFlags fflags() const { return FunFlags; } - - void setNoRecurse() { FunFlags.NoRecurse = true; } - - void setNoUnwind() { FunFlags.NoUnwind = true; } - - /// Get the instruction count recorded for this function. - unsigned instCount() const { return InstCount; } - - /// Get the synthetic entry count for this function. - uint64_t entryCount() const { return EntryCount; } - - /// Set the synthetic entry count for this function. - void setEntryCount(uint64_t EC) { EntryCount = EC; } - - /// Return the list of pairs. - ArrayRef calls() const { return CallGraphEdgeList; } - - std::vector &mutableCalls() { return CallGraphEdgeList; } - - void addCall(EdgeTy E) { CallGraphEdgeList.push_back(E); } - - /// Returns the list of type identifiers used by this function in - /// llvm.type.test intrinsics other than by an llvm.assume intrinsic, - /// represented as GUIDs. - ArrayRef type_tests() const { - if (TIdInfo) - return TIdInfo->TypeTests; - return {}; - } - - /// Returns the list of virtual calls made by this function using - /// llvm.assume(llvm.type.test) intrinsics that do not have all constant - /// integer arguments. - ArrayRef type_test_assume_vcalls() const { - if (TIdInfo) - return TIdInfo->TypeTestAssumeVCalls; - return {}; - } - - /// Returns the list of virtual calls made by this function using - /// llvm.type.checked.load intrinsics that do not have all constant integer - /// arguments. - ArrayRef type_checked_load_vcalls() const { - if (TIdInfo) - return TIdInfo->TypeCheckedLoadVCalls; - return {}; - } - - /// Returns the list of virtual calls made by this function using - /// llvm.assume(llvm.type.test) intrinsics with all constant integer - /// arguments. - ArrayRef type_test_assume_const_vcalls() const { - if (TIdInfo) - return TIdInfo->TypeTestAssumeConstVCalls; - return {}; - } - - /// Returns the list of virtual calls made by this function using - /// llvm.type.checked.load intrinsics with all constant integer arguments. - ArrayRef type_checked_load_const_vcalls() const { - if (TIdInfo) - return TIdInfo->TypeCheckedLoadConstVCalls; - return {}; - } - - /// Returns the list of known uses of pointer parameters. - ArrayRef paramAccesses() const { - if (ParamAccesses) - return *ParamAccesses; - return {}; - } - - /// Sets the list of known uses of pointer parameters. - void setParamAccesses(std::vector NewParams) { - if (NewParams.empty()) - ParamAccesses.reset(); - else if (ParamAccesses) - *ParamAccesses = std::move(NewParams); - else - ParamAccesses = std::make_unique(std::move(NewParams)); - } - - /// Add a type test to the summary. This is used by WholeProgramDevirt if we - /// were unable to devirtualize a checked call. - void addTypeTest(GlobalValue::GUID Guid) { - if (!TIdInfo) - TIdInfo = std::make_unique(); - TIdInfo->TypeTests.push_back(Guid); - } - - const TypeIdInfo *getTypeIdInfo() const { return TIdInfo.get(); }; - - friend struct GraphTraits; -}; - -template <> struct DenseMapInfo { - static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; } - - static FunctionSummary::VFuncId getTombstoneKey() { - return {0, uint64_t(-2)}; - } - - static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) { - return L.GUID == R.GUID && L.Offset == R.Offset; - } - - static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; } -}; - -template <> struct DenseMapInfo { - static FunctionSummary::ConstVCall getEmptyKey() { - return {{0, uint64_t(-1)}, {}}; - } - - static FunctionSummary::ConstVCall getTombstoneKey() { - return {{0, uint64_t(-2)}, {}}; - } - - static bool isEqual(FunctionSummary::ConstVCall L, - FunctionSummary::ConstVCall R) { - return DenseMapInfo::isEqual(L.VFunc, R.VFunc) && - L.Args == R.Args; - } - - static unsigned getHashValue(FunctionSummary::ConstVCall I) { - return I.VFunc.GUID; - } -}; - -/// The ValueInfo and offset for a function within a vtable definition -/// initializer array. -struct VirtFuncOffset { - VirtFuncOffset(ValueInfo VI, uint64_t Offset) - : FuncVI(VI), VTableOffset(Offset) {} - - ValueInfo FuncVI; - uint64_t VTableOffset; -}; -/// List of functions referenced by a particular vtable definition. -using VTableFuncList = std::vector; - -/// Global variable summary information to aid decisions and -/// implementation of importing. -/// -/// Global variable summary has two extra flag, telling if it is -/// readonly or writeonly. Both readonly and writeonly variables -/// can be optimized in the backed: readonly variables can be -/// const-folded, while writeonly vars can be completely eliminated -/// together with corresponding stores. We let both things happen -/// by means of internalizing such variables after ThinLTO import. -class GlobalVarSummary : public GlobalValueSummary { -private: - /// For vtable definitions this holds the list of functions and - /// their corresponding offsets within the initializer array. - std::unique_ptr VTableFuncs; - -public: - struct GVarFlags { - GVarFlags(bool ReadOnly, bool WriteOnly, bool Constant, - GlobalObject::VCallVisibility Vis) - : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly), - Constant(Constant), VCallVisibility(Vis) {} - - // If true indicates that this global variable might be accessed - // purely by non-volatile load instructions. This in turn means - // it can be internalized in source and destination modules during - // thin LTO import because it neither modified nor its address - // is taken. - unsigned MaybeReadOnly : 1; - // If true indicates that variable is possibly only written to, so - // its value isn't loaded and its address isn't taken anywhere. - // False, when 'Constant' attribute is set. - unsigned MaybeWriteOnly : 1; - // Indicates that value is a compile-time constant. Global variable - // can be 'Constant' while not being 'ReadOnly' on several occasions: - // - it is volatile, (e.g mapped device address) - // - its address is taken, meaning that unlike 'ReadOnly' vars we can't - // internalize it. - // Constant variables are always imported thus giving compiler an - // opportunity to make some extra optimizations. Readonly constants - // are also internalized. - unsigned Constant : 1; - // Set from metadata on vtable definitions during the module summary - // analysis. - unsigned VCallVisibility : 2; - } VarFlags; - - GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags, - std::vector Refs) - : GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)), - VarFlags(VarFlags) {} - - /// Check if this is a global variable summary. - static bool classof(const GlobalValueSummary *GVS) { - return GVS->getSummaryKind() == GlobalVarKind; - } - - GVarFlags varflags() const { return VarFlags; } - void setReadOnly(bool RO) { VarFlags.MaybeReadOnly = RO; } - void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; } - bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; } - bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; } - bool isConstant() const { return VarFlags.Constant; } - void setVCallVisibility(GlobalObject::VCallVisibility Vis) { - VarFlags.VCallVisibility = Vis; - } - GlobalObject::VCallVisibility getVCallVisibility() const { - return (GlobalObject::VCallVisibility)VarFlags.VCallVisibility; - } - - void setVTableFuncs(VTableFuncList Funcs) { - assert(!VTableFuncs); - VTableFuncs = std::make_unique(std::move(Funcs)); - } - - ArrayRef vTableFuncs() const { - if (VTableFuncs) - return *VTableFuncs; - return {}; - } -}; - -struct TypeTestResolution { - /// Specifies which kind of type check we should emit for this byte array. - /// See http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html for full - /// details on each kind of check; the enumerators are described with - /// reference to that document. - enum Kind { - Unsat, ///< Unsatisfiable type (i.e. no global has this type metadata) - ByteArray, ///< Test a byte array (first example) - Inline, ///< Inlined bit vector ("Short Inline Bit Vectors") - Single, ///< Single element (last example in "Short Inline Bit Vectors") - AllOnes, ///< All-ones bit vector ("Eliminating Bit Vector Checks for - /// All-Ones Bit Vectors") - Unknown, ///< Unknown (analysis not performed, don't lower) - } TheKind = Unknown; - - /// Range of size-1 expressed as a bit width. For example, if the size is in - /// range [1,256], this number will be 8. This helps generate the most compact - /// instruction sequences. - unsigned SizeM1BitWidth = 0; - - // The following fields are only used if the target does not support the use - // of absolute symbols to store constants. Their meanings are the same as the - // corresponding fields in LowerTypeTestsModule::TypeIdLowering in - // LowerTypeTests.cpp. - - uint64_t AlignLog2 = 0; - uint64_t SizeM1 = 0; - uint8_t BitMask = 0; - uint64_t InlineBits = 0; -}; - -struct WholeProgramDevirtResolution { - enum Kind { - Indir, ///< Just do a regular virtual call - SingleImpl, ///< Single implementation devirtualization - BranchFunnel, ///< When retpoline mitigation is enabled, use a branch funnel - ///< that is defined in the merged module. Otherwise same as - ///< Indir. - } TheKind = Indir; - - std::string SingleImplName; - - struct ByArg { - enum Kind { - Indir, ///< Just do a regular virtual call - UniformRetVal, ///< Uniform return value optimization - UniqueRetVal, ///< Unique return value optimization - VirtualConstProp, ///< Virtual constant propagation - } TheKind = Indir; - - /// Additional information for the resolution: - /// - UniformRetVal: the uniform return value. - /// - UniqueRetVal: the return value associated with the unique vtable (0 or - /// 1). - uint64_t Info = 0; - - // The following fields are only used if the target does not support the use - // of absolute symbols to store constants. - - uint32_t Byte = 0; - uint32_t Bit = 0; - }; - - /// Resolutions for calls with all constant integer arguments (excluding the - /// first argument, "this"), where the key is the argument vector. - std::map, ByArg> ResByArg; -}; - -struct TypeIdSummary { - TypeTestResolution TTRes; - - /// Mapping from byte offset to whole-program devirt resolution for that - /// (typeid, byte offset) pair. - std::map WPDRes; -}; - -/// 160 bits SHA1 -using ModuleHash = std::array; - -/// Type used for iterating through the global value summary map. -using const_gvsummary_iterator = GlobalValueSummaryMapTy::const_iterator; -using gvsummary_iterator = GlobalValueSummaryMapTy::iterator; - -/// String table to hold/own module path strings, which additionally holds the -/// module ID assigned to each module during the plugin step, as well as a hash -/// of the module. The StringMap makes a copy of and owns inserted strings. -using ModulePathStringTableTy = StringMap>; - -/// Map of global value GUID to its summary, used to identify values defined in -/// a particular module, and provide efficient access to their summary. -using GVSummaryMapTy = DenseMap; - -/// Map of a type GUID to type id string and summary (multimap used -/// in case of GUID conflicts). -using TypeIdSummaryMapTy = - std::multimap>; - -/// The following data structures summarize type metadata information. -/// For type metadata overview see https://llvm.org/docs/TypeMetadata.html. -/// Each type metadata includes both the type identifier and the offset of -/// the address point of the type (the address held by objects of that type -/// which may not be the beginning of the virtual table). Vtable definitions -/// are decorated with type metadata for the types they are compatible with. -/// -/// Holds information about vtable definitions decorated with type metadata: -/// the vtable definition value and its address point offset in a type -/// identifier metadata it is decorated (compatible) with. -struct TypeIdOffsetVtableInfo { - TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI) - : AddressPointOffset(Offset), VTableVI(VI) {} - - uint64_t AddressPointOffset; - ValueInfo VTableVI; -}; -/// List of vtable definitions decorated by a particular type identifier, -/// and their corresponding offsets in that type identifier's metadata. -/// Note that each type identifier may be compatible with multiple vtables, due -/// to inheritance, which is why this is a vector. -using TypeIdCompatibleVtableInfo = std::vector; - -/// Class to hold module path string table and global value map, -/// and encapsulate methods for operating on them. -class ModuleSummaryIndex { -private: - /// Map from value name to list of summary instances for values of that - /// name (may be duplicates in the COMDAT case, e.g.). - GlobalValueSummaryMapTy GlobalValueMap; - - /// Holds strings for combined index, mapping to the corresponding module ID. - ModulePathStringTableTy ModulePathStringTable; - - /// Mapping from type identifier GUIDs to type identifier and its summary - /// information. Produced by thin link. - TypeIdSummaryMapTy TypeIdMap; - - /// Mapping from type identifier to information about vtables decorated - /// with that type identifier's metadata. Produced by per module summary - /// analysis and consumed by thin link. For more information, see description - /// above where TypeIdCompatibleVtableInfo is defined. - std::map> - TypeIdCompatibleVtableMap; - - /// Mapping from original ID to GUID. If original ID can map to multiple - /// GUIDs, it will be mapped to 0. - std::map OidGuidMap; - - /// Indicates that summary-based GlobalValue GC has run, and values with - /// GVFlags::Live==false are really dead. Otherwise, all values must be - /// considered live. - bool WithGlobalValueDeadStripping = false; - - /// Indicates that summary-based attribute propagation has run and - /// GVarFlags::MaybeReadonly / GVarFlags::MaybeWriteonly are really - /// read/write only. - bool WithAttributePropagation = false; - - /// Indicates that summary-based DSOLocal propagation has run and the flag in - /// every summary of a GV is synchronized. - bool WithDSOLocalPropagation = false; - - /// Indicates that summary-based synthetic entry count propagation has run - bool HasSyntheticEntryCounts = false; - - /// Indicates that distributed backend should skip compilation of the - /// module. Flag is suppose to be set by distributed ThinLTO indexing - /// when it detected that the module is not needed during the final - /// linking. As result distributed backend should just output a minimal - /// valid object file. - bool SkipModuleByDistributedBackend = false; - - /// If true then we're performing analysis of IR module, or parsing along with - /// the IR from assembly. The value of 'false' means we're reading summary - /// from BC or YAML source. Affects the type of value stored in NameOrGV - /// union. - bool HaveGVs; - - // True if the index was created for a module compiled with -fsplit-lto-unit. - bool EnableSplitLTOUnit; - - // True if some of the modules were compiled with -fsplit-lto-unit and - // some were not. Set when the combined index is created during the thin link. - bool PartiallySplitLTOUnits = false; - - /// True if some of the FunctionSummary contains a ParamAccess. - bool HasParamAccess = false; - - std::set CfiFunctionDefs; - std::set CfiFunctionDecls; - - // Used in cases where we want to record the name of a global, but - // don't have the string owned elsewhere (e.g. the Strtab on a module). - StringSaver Saver; - BumpPtrAllocator Alloc; - - // The total number of basic blocks in the module in the per-module summary or - // the total number of basic blocks in the LTO unit in the combined index. - uint64_t BlockCount; - - // YAML I/O support. - friend yaml::MappingTraits; - - GlobalValueSummaryMapTy::value_type * - getOrInsertValuePtr(GlobalValue::GUID GUID) { - return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(HaveGVs)) - .first; - } - -public: - // See HaveGVs variable comment. - ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false) - : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc), - BlockCount(0) {} - - // Current version for the module summary in bitcode files. - // The BitcodeSummaryVersion should be bumped whenever we introduce changes - // in the way some record are interpreted, like flags for instance. - // Note that incrementing this may require changes in both BitcodeReader.cpp - // and BitcodeWriter.cpp. - static constexpr uint64_t BitcodeSummaryVersion = 9; - - // Regular LTO module name for ASM writer - static constexpr const char *getRegularLTOModuleName() { - return "[Regular LTO]"; - } - - bool haveGVs() const { return HaveGVs; } - - uint64_t getFlags() const; - void setFlags(uint64_t Flags); - - uint64_t getBlockCount() const { return BlockCount; } - void addBlockCount(uint64_t C) { BlockCount += C; } - void setBlockCount(uint64_t C) { BlockCount = C; } - - gvsummary_iterator begin() { return GlobalValueMap.begin(); } - const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } - gvsummary_iterator end() { return GlobalValueMap.end(); } - const_gvsummary_iterator end() const { return GlobalValueMap.end(); } - size_t size() const { return GlobalValueMap.size(); } - - /// Convenience function for doing a DFS on a ValueInfo. Marks the function in - /// the FunctionHasParent map. - static void discoverNodes(ValueInfo V, - std::map &FunctionHasParent) { - if (!V.getSummaryList().size()) - return; // skip external functions that don't have summaries - - // Mark discovered if we haven't yet - auto S = FunctionHasParent.emplace(V, false); - - // Stop if we've already discovered this node - if (!S.second) - return; - - FunctionSummary *F = - dyn_cast(V.getSummaryList().front().get()); - assert(F != nullptr && "Expected FunctionSummary node"); - - for (auto &C : F->calls()) { - // Insert node if necessary - auto S = FunctionHasParent.emplace(C.first, true); - - // Skip nodes that we're sure have parents - if (!S.second && S.first->second) - continue; - - if (S.second) - discoverNodes(C.first, FunctionHasParent); - else - S.first->second = true; - } - } - - // Calculate the callgraph root - FunctionSummary calculateCallGraphRoot() { - // Functions that have a parent will be marked in FunctionHasParent pair. - // Once we've marked all functions, the functions in the map that are false - // have no parent (so they're the roots) - std::map FunctionHasParent; - - for (auto &S : *this) { - // Skip external functions - if (!S.second.SummaryList.size() || - !isa(S.second.SummaryList.front().get())) - continue; - discoverNodes(ValueInfo(HaveGVs, &S), FunctionHasParent); - } - - std::vector Edges; - // create edges to all roots in the Index - for (auto &P : FunctionHasParent) { - if (P.second) - continue; // skip over non-root nodes - Edges.push_back(std::make_pair(P.first, CalleeInfo{})); - } - if (Edges.empty()) { - // Failed to find root - return an empty node - return FunctionSummary::makeDummyFunctionSummary({}); - } - auto CallGraphRoot = FunctionSummary::makeDummyFunctionSummary(Edges); - return CallGraphRoot; - } - - bool withGlobalValueDeadStripping() const { - return WithGlobalValueDeadStripping; - } - void setWithGlobalValueDeadStripping() { - WithGlobalValueDeadStripping = true; - } - - bool withAttributePropagation() const { return WithAttributePropagation; } - void setWithAttributePropagation() { - WithAttributePropagation = true; - } - - bool withDSOLocalPropagation() const { return WithDSOLocalPropagation; } - void setWithDSOLocalPropagation() { WithDSOLocalPropagation = true; } - - bool isReadOnly(const GlobalVarSummary *GVS) const { - return WithAttributePropagation && GVS->maybeReadOnly(); - } - bool isWriteOnly(const GlobalVarSummary *GVS) const { - return WithAttributePropagation && GVS->maybeWriteOnly(); - } - - bool hasSyntheticEntryCounts() const { return HasSyntheticEntryCounts; } - void setHasSyntheticEntryCounts() { HasSyntheticEntryCounts = true; } - - bool skipModuleByDistributedBackend() const { - return SkipModuleByDistributedBackend; - } - void setSkipModuleByDistributedBackend() { - SkipModuleByDistributedBackend = true; - } - - bool enableSplitLTOUnit() const { return EnableSplitLTOUnit; } - void setEnableSplitLTOUnit() { EnableSplitLTOUnit = true; } - - bool partiallySplitLTOUnits() const { return PartiallySplitLTOUnits; } - void setPartiallySplitLTOUnits() { PartiallySplitLTOUnits = true; } - - bool hasParamAccess() const { return HasParamAccess; } - - bool isGlobalValueLive(const GlobalValueSummary *GVS) const { - return !WithGlobalValueDeadStripping || GVS->isLive(); - } - bool isGUIDLive(GlobalValue::GUID GUID) const; - - /// Return a ValueInfo for the index value_type (convenient when iterating - /// index). - ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const { - return ValueInfo(HaveGVs, &R); - } - - /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo(). - ValueInfo getValueInfo(GlobalValue::GUID GUID) const { - auto I = GlobalValueMap.find(GUID); - return ValueInfo(HaveGVs, I == GlobalValueMap.end() ? nullptr : &*I); - } - - /// Return a ValueInfo for \p GUID. - ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) { - return ValueInfo(HaveGVs, getOrInsertValuePtr(GUID)); - } - - // Save a string in the Index. Use before passing Name to - // getOrInsertValueInfo when the string isn't owned elsewhere (e.g. on the - // module's Strtab). - StringRef saveString(StringRef String) { return Saver.save(String); } - - /// Return a ValueInfo for \p GUID setting value \p Name. - ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) { - assert(!HaveGVs); - auto VP = getOrInsertValuePtr(GUID); - VP->second.U.Name = Name; - return ValueInfo(HaveGVs, VP); - } - - /// Return a ValueInfo for \p GV and mark it as belonging to GV. - ValueInfo getOrInsertValueInfo(const GlobalValue *GV) { - assert(HaveGVs); - auto VP = getOrInsertValuePtr(GV->getGUID()); - VP->second.U.GV = GV; - return ValueInfo(HaveGVs, VP); - } - - /// Return the GUID for \p OriginalId in the OidGuidMap. - GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const { - const auto I = OidGuidMap.find(OriginalID); - return I == OidGuidMap.end() ? 0 : I->second; - } - - std::set &cfiFunctionDefs() { return CfiFunctionDefs; } - const std::set &cfiFunctionDefs() const { return CfiFunctionDefs; } - - std::set &cfiFunctionDecls() { return CfiFunctionDecls; } - const std::set &cfiFunctionDecls() const { return CfiFunctionDecls; } - - /// Add a global value summary for a value. - void addGlobalValueSummary(const GlobalValue &GV, - std::unique_ptr Summary) { - addGlobalValueSummary(getOrInsertValueInfo(&GV), std::move(Summary)); - } - - /// Add a global value summary for a value of the given name. - void addGlobalValueSummary(StringRef ValueName, - std::unique_ptr Summary) { - addGlobalValueSummary(getOrInsertValueInfo(GlobalValue::getGUID(ValueName)), - std::move(Summary)); - } - - /// Add a global value summary for the given ValueInfo. - void addGlobalValueSummary(ValueInfo VI, - std::unique_ptr Summary) { - if (const FunctionSummary *FS = dyn_cast(Summary.get())) - HasParamAccess |= !FS->paramAccesses().empty(); - addOriginalName(VI.getGUID(), Summary->getOriginalName()); - // Here we have a notionally const VI, but the value it points to is owned - // by the non-const *this. - const_cast(VI.getRef()) - ->second.SummaryList.push_back(std::move(Summary)); - } - - /// Add an original name for the value of the given GUID. - void addOriginalName(GlobalValue::GUID ValueGUID, - GlobalValue::GUID OrigGUID) { - if (OrigGUID == 0 || ValueGUID == OrigGUID) - return; - if (OidGuidMap.count(OrigGUID) && OidGuidMap[OrigGUID] != ValueGUID) - OidGuidMap[OrigGUID] = 0; - else - OidGuidMap[OrigGUID] = ValueGUID; - } - - /// Find the summary for ValueInfo \p VI in module \p ModuleId, or nullptr if - /// not found. - GlobalValueSummary *findSummaryInModule(ValueInfo VI, StringRef ModuleId) const { - auto SummaryList = VI.getSummaryList(); - auto Summary = - llvm::find_if(SummaryList, - [&](const std::unique_ptr &Summary) { - return Summary->modulePath() == ModuleId; - }); - if (Summary == SummaryList.end()) - return nullptr; - return Summary->get(); - } - - /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if - /// not found. - GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID, - StringRef ModuleId) const { - auto CalleeInfo = getValueInfo(ValueGUID); - if (!CalleeInfo) - return nullptr; // This function does not have a summary - return findSummaryInModule(CalleeInfo, ModuleId); - } - - /// Returns the first GlobalValueSummary for \p GV, asserting that there - /// is only one if \p PerModuleIndex. - GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV, - bool PerModuleIndex = true) const { - assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name"); - return getGlobalValueSummary(GV.getGUID(), PerModuleIndex); - } - - /// Returns the first GlobalValueSummary for \p ValueGUID, asserting that - /// there - /// is only one if \p PerModuleIndex. - GlobalValueSummary *getGlobalValueSummary(GlobalValue::GUID ValueGUID, - bool PerModuleIndex = true) const; - - /// Table of modules, containing module hash and id. - const StringMap> &modulePaths() const { - return ModulePathStringTable; - } - - /// Table of modules, containing hash and id. - StringMap> &modulePaths() { - return ModulePathStringTable; - } - - /// Get the module ID recorded for the given module path. - uint64_t getModuleId(const StringRef ModPath) const { - return ModulePathStringTable.lookup(ModPath).first; - } - - /// Get the module SHA1 hash recorded for the given module path. - const ModuleHash &getModuleHash(const StringRef ModPath) const { - auto It = ModulePathStringTable.find(ModPath); - assert(It != ModulePathStringTable.end() && "Module not registered"); - return It->second.second; - } - - /// Convenience method for creating a promoted global name - /// for the given value name of a local, and its original module's ID. - static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash) { - SmallString<256> NewName(Name); - NewName += ".llvm."; - NewName += utostr((uint64_t(ModHash[0]) << 32) | - ModHash[1]); // Take the first 64 bits - return std::string(NewName.str()); - } - - /// Helper to obtain the unpromoted name for a global value (or the original - /// name if not promoted). Split off the rightmost ".llvm.${hash}" suffix, - /// because it is possible in certain clients (not clang at the moment) for - /// two rounds of ThinLTO optimization and therefore promotion to occur. - static StringRef getOriginalNameBeforePromote(StringRef Name) { - std::pair Pair = Name.rsplit(".llvm."); - return Pair.first; - } - - typedef ModulePathStringTableTy::value_type ModuleInfo; - - /// Add a new module with the given \p Hash, mapped to the given \p - /// ModID, and return a reference to the module. - ModuleInfo *addModule(StringRef ModPath, uint64_t ModId, - ModuleHash Hash = ModuleHash{{0}}) { - return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first; - } - - /// Return module entry for module with the given \p ModPath. - ModuleInfo *getModule(StringRef ModPath) { - auto It = ModulePathStringTable.find(ModPath); - assert(It != ModulePathStringTable.end() && "Module not registered"); - return &*It; - } - - /// Check if the given Module has any functions available for exporting - /// in the index. We consider any module present in the ModulePathStringTable - /// to have exported functions. - bool hasExportedFunctions(const Module &M) const { - return ModulePathStringTable.count(M.getModuleIdentifier()); - } - - const TypeIdSummaryMapTy &typeIds() const { return TypeIdMap; } - - /// Return an existing or new TypeIdSummary entry for \p TypeId. - /// This accessor can mutate the map and therefore should not be used in - /// the ThinLTO backends. - TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) { - auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId)); - for (auto It = TidIter.first; It != TidIter.second; ++It) - if (It->second.first == TypeId) - return It->second.second; - auto It = TypeIdMap.insert( - {GlobalValue::getGUID(TypeId), {std::string(TypeId), TypeIdSummary()}}); - return It->second.second; - } - - /// This returns either a pointer to the type id summary (if present in the - /// summary map) or null (if not present). This may be used when importing. - const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const { - auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId)); - for (auto It = TidIter.first; It != TidIter.second; ++It) - if (It->second.first == TypeId) - return &It->second.second; - return nullptr; - } - - TypeIdSummary *getTypeIdSummary(StringRef TypeId) { - return const_cast( - static_cast(this)->getTypeIdSummary( - TypeId)); - } - - const auto &typeIdCompatibleVtableMap() const { - return TypeIdCompatibleVtableMap; - } - - /// Return an existing or new TypeIdCompatibleVtableMap entry for \p TypeId. - /// This accessor can mutate the map and therefore should not be used in - /// the ThinLTO backends. - TypeIdCompatibleVtableInfo & - getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) { - return TypeIdCompatibleVtableMap[std::string(TypeId)]; - } - - /// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap - /// entry if present in the summary map. This may be used when importing. - Optional - getTypeIdCompatibleVtableSummary(StringRef TypeId) const { - auto I = TypeIdCompatibleVtableMap.find(TypeId); - if (I == TypeIdCompatibleVtableMap.end()) - return None; - return I->second; - } - - /// Collect for the given module the list of functions it defines - /// (GUID -> Summary). - void collectDefinedFunctionsForModule(StringRef ModulePath, - GVSummaryMapTy &GVSummaryMap) const; - - /// Collect for each module the list of Summaries it defines (GUID -> - /// Summary). - template - void - collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const { - for (auto &GlobalList : *this) { - auto GUID = GlobalList.first; - for (auto &Summary : GlobalList.second.SummaryList) { - ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); - } - } - } - - /// Print to an output stream. - void print(raw_ostream &OS, bool IsForDebug = false) const; - - /// Dump to stderr (for debugging). - void dump() const; - - /// Export summary to dot file for GraphViz. - void - exportToDot(raw_ostream &OS, - const DenseSet &GUIDPreservedSymbols) const; - - /// Print out strongly connected components for debugging. - void dumpSCCs(raw_ostream &OS); - - /// Do the access attribute and DSOLocal propagation in combined index. - void propagateAttributes(const DenseSet &PreservedSymbols); - - /// Checks if we can import global variable from another module. - bool canImportGlobalVar(GlobalValueSummary *S, bool AnalyzeRefs) const; -}; - -/// GraphTraits definition to build SCC for the index -template <> struct GraphTraits { - typedef ValueInfo NodeRef; - using EdgeRef = FunctionSummary::EdgeTy &; - - static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) { - return P.first; - } - using ChildIteratorType = - mapped_iterator::iterator, - decltype(&valueInfoFromEdge)>; - - using ChildEdgeIteratorType = std::vector::iterator; - - static NodeRef getEntryNode(ValueInfo V) { return V; } - - static ChildIteratorType child_begin(NodeRef N) { - if (!N.getSummaryList().size()) // handle external function - return ChildIteratorType( - FunctionSummary::ExternalNode.CallGraphEdgeList.begin(), - &valueInfoFromEdge); - FunctionSummary *F = - cast(N.getSummaryList().front()->getBaseObject()); - return ChildIteratorType(F->CallGraphEdgeList.begin(), &valueInfoFromEdge); - } - - static ChildIteratorType child_end(NodeRef N) { - if (!N.getSummaryList().size()) // handle external function - return ChildIteratorType( - FunctionSummary::ExternalNode.CallGraphEdgeList.end(), - &valueInfoFromEdge); - FunctionSummary *F = - cast(N.getSummaryList().front()->getBaseObject()); - return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge); - } - - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - if (!N.getSummaryList().size()) // handle external function - return FunctionSummary::ExternalNode.CallGraphEdgeList.begin(); - - FunctionSummary *F = - cast(N.getSummaryList().front()->getBaseObject()); - return F->CallGraphEdgeList.begin(); - } - - static ChildEdgeIteratorType child_edge_end(NodeRef N) { - if (!N.getSummaryList().size()) // handle external function - return FunctionSummary::ExternalNode.CallGraphEdgeList.end(); - - FunctionSummary *F = - cast(N.getSummaryList().front()->getBaseObject()); - return F->CallGraphEdgeList.end(); - } - - static NodeRef edge_dest(EdgeRef E) { return E.first; } -}; - -template <> -struct GraphTraits : public GraphTraits { - static NodeRef getEntryNode(ModuleSummaryIndex *I) { - std::unique_ptr Root = - std::make_unique(I->calculateCallGraphRoot()); - GlobalValueSummaryInfo G(I->haveGVs()); - G.SummaryList.push_back(std::move(Root)); - static auto P = - GlobalValueSummaryMapTy::value_type(GlobalValue::GUID(0), std::move(G)); - return ValueInfo(I->haveGVs(), &P); - } -}; -} // end namespace llvm - -#endif // LLVM_IR_MODULESUMMARYINDEX_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndexYAML.h b/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndexYAML.h deleted file mode 100644 index f09ee0efa5..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ModuleSummaryIndexYAML.h +++ /dev/null @@ -1,307 +0,0 @@ -//===-- llvm/ModuleSummaryIndexYAML.h - YAML I/O for summary ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_MODULESUMMARYINDEXYAML_H -#define LLVM_IR_MODULESUMMARYINDEXYAML_H - -#include "llvm/IR/ModuleSummaryIndex.h" -#include "llvm/Support/YAMLTraits.h" - -namespace llvm { -namespace yaml { - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, TypeTestResolution::Kind &value) { - io.enumCase(value, "Unknown", TypeTestResolution::Unknown); - io.enumCase(value, "Unsat", TypeTestResolution::Unsat); - io.enumCase(value, "ByteArray", TypeTestResolution::ByteArray); - io.enumCase(value, "Inline", TypeTestResolution::Inline); - io.enumCase(value, "Single", TypeTestResolution::Single); - io.enumCase(value, "AllOnes", TypeTestResolution::AllOnes); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, TypeTestResolution &res) { - io.mapOptional("Kind", res.TheKind); - io.mapOptional("SizeM1BitWidth", res.SizeM1BitWidth); - io.mapOptional("AlignLog2", res.AlignLog2); - io.mapOptional("SizeM1", res.SizeM1); - io.mapOptional("BitMask", res.BitMask); - io.mapOptional("InlineBits", res.InlineBits); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &io, - WholeProgramDevirtResolution::ByArg::Kind &value) { - io.enumCase(value, "Indir", WholeProgramDevirtResolution::ByArg::Indir); - io.enumCase(value, "UniformRetVal", - WholeProgramDevirtResolution::ByArg::UniformRetVal); - io.enumCase(value, "UniqueRetVal", - WholeProgramDevirtResolution::ByArg::UniqueRetVal); - io.enumCase(value, "VirtualConstProp", - WholeProgramDevirtResolution::ByArg::VirtualConstProp); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) { - io.mapOptional("Kind", res.TheKind); - io.mapOptional("Info", res.Info); - io.mapOptional("Byte", res.Byte); - io.mapOptional("Bit", res.Bit); - } -}; - -template <> -struct CustomMappingTraits< - std::map, WholeProgramDevirtResolution::ByArg>> { - static void inputOne( - IO &io, StringRef Key, - std::map, WholeProgramDevirtResolution::ByArg> &V) { - std::vector Args; - std::pair P = {"", Key}; - while (!P.second.empty()) { - P = P.second.split(','); - uint64_t Arg; - if (P.first.getAsInteger(0, Arg)) { - io.setError("key not an integer"); - return; - } - Args.push_back(Arg); - } - io.mapRequired(Key.str().c_str(), V[Args]); - } - static void output( - IO &io, - std::map, WholeProgramDevirtResolution::ByArg> &V) { - for (auto &P : V) { - std::string Key; - for (uint64_t Arg : P.first) { - if (!Key.empty()) - Key += ','; - Key += llvm::utostr(Arg); - } - io.mapRequired(Key.c_str(), P.second); - } - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) { - io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir); - io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl); - io.enumCase(value, "BranchFunnel", - WholeProgramDevirtResolution::BranchFunnel); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, WholeProgramDevirtResolution &res) { - io.mapOptional("Kind", res.TheKind); - io.mapOptional("SingleImplName", res.SingleImplName); - io.mapOptional("ResByArg", res.ResByArg); - } -}; - -template <> -struct CustomMappingTraits> { - static void inputOne(IO &io, StringRef Key, - std::map &V) { - uint64_t KeyInt; - if (Key.getAsInteger(0, KeyInt)) { - io.setError("key not an integer"); - return; - } - io.mapRequired(Key.str().c_str(), V[KeyInt]); - } - static void output(IO &io, std::map &V) { - for (auto &P : V) - io.mapRequired(llvm::utostr(P.first).c_str(), P.second); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, TypeIdSummary& summary) { - io.mapOptional("TTRes", summary.TTRes); - io.mapOptional("WPDRes", summary.WPDRes); - } -}; - -struct FunctionSummaryYaml { - unsigned Linkage, Visibility; - bool NotEligibleToImport, Live, IsLocal, CanAutoHide; - std::vector Refs; - std::vector TypeTests; - std::vector TypeTestAssumeVCalls, - TypeCheckedLoadVCalls; - std::vector TypeTestAssumeConstVCalls, - TypeCheckedLoadConstVCalls; -}; - -} // End yaml namespace -} // End llvm namespace - -namespace llvm { -namespace yaml { - -template <> struct MappingTraits { - static void mapping(IO &io, FunctionSummary::VFuncId& id) { - io.mapOptional("GUID", id.GUID); - io.mapOptional("Offset", id.Offset); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, FunctionSummary::ConstVCall& id) { - io.mapOptional("VFunc", id.VFunc); - io.mapOptional("Args", id.Args); - } -}; - -} // End yaml namespace -} // End llvm namespace - -LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId) -LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall) - -namespace llvm { -namespace yaml { - -template <> struct MappingTraits { - static void mapping(IO &io, FunctionSummaryYaml& summary) { - io.mapOptional("Linkage", summary.Linkage); - io.mapOptional("Visibility", summary.Visibility); - io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); - io.mapOptional("Live", summary.Live); - io.mapOptional("Local", summary.IsLocal); - io.mapOptional("CanAutoHide", summary.CanAutoHide); - io.mapOptional("Refs", summary.Refs); - io.mapOptional("TypeTests", summary.TypeTests); - io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); - io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls); - io.mapOptional("TypeTestAssumeConstVCalls", - summary.TypeTestAssumeConstVCalls); - io.mapOptional("TypeCheckedLoadConstVCalls", - summary.TypeCheckedLoadConstVCalls); - } -}; - -} // End yaml namespace -} // End llvm namespace - -LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml) - -namespace llvm { -namespace yaml { - -// FIXME: Add YAML mappings for the rest of the module summary. -template <> struct CustomMappingTraits { - static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) { - std::vector FSums; - io.mapRequired(Key.str().c_str(), FSums); - uint64_t KeyInt; - if (Key.getAsInteger(0, KeyInt)) { - io.setError("key not an integer"); - return; - } - if (!V.count(KeyInt)) - V.emplace(KeyInt, /*IsAnalysis=*/false); - auto &Elem = V.find(KeyInt)->second; - for (auto &FSum : FSums) { - std::vector Refs; - for (auto &RefGUID : FSum.Refs) { - if (!V.count(RefGUID)) - V.emplace(RefGUID, /*IsAnalysis=*/false); - Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID))); - } - Elem.SummaryList.push_back(std::make_unique( - GlobalValueSummary::GVFlags( - static_cast(FSum.Linkage), - static_cast(FSum.Visibility), - FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal, - FSum.CanAutoHide), - /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, Refs, - ArrayRef{}, std::move(FSum.TypeTests), - std::move(FSum.TypeTestAssumeVCalls), - std::move(FSum.TypeCheckedLoadVCalls), - std::move(FSum.TypeTestAssumeConstVCalls), - std::move(FSum.TypeCheckedLoadConstVCalls), - ArrayRef{})); - } - } - static void output(IO &io, GlobalValueSummaryMapTy &V) { - for (auto &P : V) { - std::vector FSums; - for (auto &Sum : P.second.SummaryList) { - if (auto *FSum = dyn_cast(Sum.get())) { - std::vector Refs; - for (auto &VI : FSum->refs()) - Refs.push_back(VI.getGUID()); - FSums.push_back(FunctionSummaryYaml{ - FSum->flags().Linkage, FSum->flags().Visibility, - static_cast(FSum->flags().NotEligibleToImport), - static_cast(FSum->flags().Live), - static_cast(FSum->flags().DSOLocal), - static_cast(FSum->flags().CanAutoHide), Refs, - FSum->type_tests(), FSum->type_test_assume_vcalls(), - FSum->type_checked_load_vcalls(), - FSum->type_test_assume_const_vcalls(), - FSum->type_checked_load_const_vcalls()}); - } - } - if (!FSums.empty()) - io.mapRequired(llvm::utostr(P.first).c_str(), FSums); - } - } -}; - -template <> struct CustomMappingTraits { - static void inputOne(IO &io, StringRef Key, TypeIdSummaryMapTy &V) { - TypeIdSummary TId; - io.mapRequired(Key.str().c_str(), TId); - V.insert({GlobalValue::getGUID(Key), {std::string(Key), TId}}); - } - static void output(IO &io, TypeIdSummaryMapTy &V) { - for (auto TidIter = V.begin(); TidIter != V.end(); TidIter++) - io.mapRequired(TidIter->second.first.c_str(), TidIter->second.second); - } -}; - -template <> struct MappingTraits { - static void mapping(IO &io, ModuleSummaryIndex& index) { - io.mapOptional("GlobalValueMap", index.GlobalValueMap); - io.mapOptional("TypeIdMap", index.TypeIdMap); - io.mapOptional("WithGlobalValueDeadStripping", - index.WithGlobalValueDeadStripping); - - if (io.outputting()) { - std::vector CfiFunctionDefs(index.CfiFunctionDefs.begin(), - index.CfiFunctionDefs.end()); - io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); - std::vector CfiFunctionDecls(index.CfiFunctionDecls.begin(), - index.CfiFunctionDecls.end()); - io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); - } else { - std::vector CfiFunctionDefs; - io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); - index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()}; - std::vector CfiFunctionDecls; - io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); - index.CfiFunctionDecls = {CfiFunctionDecls.begin(), - CfiFunctionDecls.end()}; - } - } -}; - -} // End yaml namespace -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/NoFolder.h b/suite/synctools/tablegen/include/llvm/IR/NoFolder.h deleted file mode 100644 index ec149747e3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/NoFolder.h +++ /dev/null @@ -1,281 +0,0 @@ -//===- NoFolder.h - Constant folding helper ---------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the NoFolder class, a helper for IRBuilder. It provides -// IRBuilder with a set of methods for creating unfolded constants. This is -// useful for learners trying to understand how LLVM IR works, and who don't -// want details to be hidden by the constant folder. For general constant -// creation and folding, use ConstantExpr and the routines in -// llvm/Analysis/ConstantFolding.h. -// -// Note: since it is not actually possible to create unfolded constants, this -// class returns instructions rather than constants. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_NOFOLDER_H -#define LLVM_IR_NOFOLDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IRBuilderFolder.h" - -namespace llvm { - -/// NoFolder - Create "constants" (actually, instructions) with no folding. -class NoFolder final : public IRBuilderFolder { - virtual void anchor(); - -public: - explicit NoFolder() = default; - - //===--------------------------------------------------------------------===// - // Value-based folders. - // - // Return an existing value or a constant if the operation can be simplified. - // Otherwise return nullptr. - //===--------------------------------------------------------------------===// - Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, - bool HasNSW = false) const override { - return nullptr; - } - - Value *FoldAnd(Value *LHS, Value *RHS) const override { return nullptr; } - - Value *FoldOr(Value *LHS, Value *RHS) const override { return nullptr; } - - Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { - return nullptr; - } - - Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, - bool IsInBounds = false) const override { - return nullptr; - } - - Value *FoldSelect(Value *C, Value *True, Value *False) const override { - return nullptr; - } - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateFAdd(LHS, RHS); - } - - Instruction *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, - bool HasNSW = false) const override { - BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *CreateFSub(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateFSub(LHS, RHS); - } - - Instruction *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, - bool HasNSW = false) const override { - BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *CreateFMul(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateFMul(LHS, RHS); - } - - Instruction *CreateUDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - if (!isExact) - return BinaryOperator::CreateUDiv(LHS, RHS); - return BinaryOperator::CreateExactUDiv(LHS, RHS); - } - - Instruction *CreateSDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - if (!isExact) - return BinaryOperator::CreateSDiv(LHS, RHS); - return BinaryOperator::CreateExactSDiv(LHS, RHS); - } - - Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateFDiv(LHS, RHS); - } - - Instruction *CreateURem(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateURem(LHS, RHS); - } - - Instruction *CreateSRem(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateSRem(LHS, RHS); - } - - Instruction *CreateFRem(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateFRem(LHS, RHS); - } - - Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, - bool HasNSW = false) const override { - BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *CreateLShr(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - if (!isExact) - return BinaryOperator::CreateLShr(LHS, RHS); - return BinaryOperator::CreateExactLShr(LHS, RHS); - } - - Instruction *CreateAShr(Constant *LHS, Constant *RHS, - bool isExact = false) const override { - if (!isExact) - return BinaryOperator::CreateAShr(LHS, RHS); - return BinaryOperator::CreateExactAShr(LHS, RHS); - } - - Instruction *CreateXor(Constant *LHS, Constant *RHS) const override { - return BinaryOperator::CreateXor(LHS, RHS); - } - - Instruction *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const override { - return BinaryOperator::Create(Opc, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateNeg(Constant *C, - bool HasNUW = false, - bool HasNSW = false) const override { - BinaryOperator *BO = BinaryOperator::CreateNeg(C); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *CreateFNeg(Constant *C) const override { - return UnaryOperator::CreateFNeg(C); - } - - Instruction *CreateNot(Constant *C) const override { - return BinaryOperator::CreateNot(C); - } - - Instruction *CreateUnOp(Instruction::UnaryOps Opc, - Constant *C) const override { - return UnaryOperator::Create(Opc, C); - } - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const override { - return CastInst::Create(Op, C, DestTy); - } - - Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override { - return CastInst::CreatePointerCast(C, DestTy); - } - - Instruction *CreatePointerBitCastOrAddrSpaceCast( - Constant *C, Type *DestTy) const override { - return CastInst::CreatePointerBitCastOrAddrSpaceCast(C, DestTy); - } - - Instruction *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const override { - return CastInst::CreateIntegerCast(C, DestTy, isSigned); - } - - Instruction *CreateFPCast(Constant *C, Type *DestTy) const override { - return CastInst::CreateFPCast(C, DestTy); - } - - Instruction *CreateBitCast(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::BitCast, C, DestTy); - } - - Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::IntToPtr, C, DestTy); - } - - Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const override { - return CreateCast(Instruction::PtrToInt, C, DestTy); - } - - Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { - return CastInst::CreateZExtOrBitCast(C, DestTy); - } - - Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { - return CastInst::CreateSExtOrBitCast(C, DestTy); - } - - Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { - return CastInst::CreateTruncOrBitCast(C, DestTy); - } - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - Instruction *CreateFCmp(CmpInst::Predicate P, - Constant *LHS, Constant *RHS) const override { - return new FCmpInst(P, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - Instruction *CreateExtractElement(Constant *Vec, - Constant *Idx) const override { - return ExtractElementInst::Create(Vec, Idx); - } - - Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const override { - return InsertElementInst::Create(Vec, NewElt, Idx); - } - - Instruction *CreateShuffleVector(Constant *V1, Constant *V2, - ArrayRef Mask) const override { - return new ShuffleVectorInst(V1, V2, Mask); - } - - Instruction *CreateExtractValue(Constant *Agg, - ArrayRef IdxList) const override { - return ExtractValueInst::Create(Agg, IdxList); - } - - Instruction *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef IdxList) const override { - return InsertValueInst::Create(Agg, Val, IdxList); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_NOFOLDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/OperandTraits.h b/suite/synctools/tablegen/include/llvm/IR/OperandTraits.h deleted file mode 100644 index 979ad35019..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/OperandTraits.h +++ /dev/null @@ -1,162 +0,0 @@ -//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the traits classes that are handy for enforcing the correct -// layout of various User subclasses. It also provides the means for accessing -// the operands in the most efficient manner. -// - -#ifndef LLVM_IR_OPERANDTRAITS_H -#define LLVM_IR_OPERANDTRAITS_H - -#include "llvm/IR/User.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -// FixedNumOperand Trait Class -//===----------------------------------------------------------------------===// - -/// FixedNumOperandTraits - determine the allocation regime of the Use array -/// when it is a prefix to the User object, and the number of Use objects is -/// known at compile time. - -template -struct FixedNumOperandTraits { - static Use *op_begin(SubClass* U) { - static_assert( - !std::is_polymorphic::value, - "adding virtual methods to subclasses of User breaks use lists"); - return reinterpret_cast(U) - ARITY; - } - static Use *op_end(SubClass* U) { - return reinterpret_cast(U); - } - static unsigned operands(const User*) { - return ARITY; - } -}; - -//===----------------------------------------------------------------------===// -// OptionalOperand Trait Class -//===----------------------------------------------------------------------===// - -/// OptionalOperandTraits - when the number of operands may change at runtime. -/// Naturally it may only decrease, because the allocations may not change. - -template -struct OptionalOperandTraits : public FixedNumOperandTraits { - static unsigned operands(const User *U) { - return U->getNumOperands(); - } -}; - -//===----------------------------------------------------------------------===// -// VariadicOperand Trait Class -//===----------------------------------------------------------------------===// - -/// VariadicOperandTraits - determine the allocation regime of the Use array -/// when it is a prefix to the User object, and the number of Use objects is -/// only known at allocation time. - -template -struct VariadicOperandTraits { - static Use *op_begin(SubClass* U) { - static_assert( - !std::is_polymorphic::value, - "adding virtual methods to subclasses of User breaks use lists"); - return reinterpret_cast(U) - static_cast(U)->getNumOperands(); - } - static Use *op_end(SubClass* U) { - return reinterpret_cast(U); - } - static unsigned operands(const User *U) { - return U->getNumOperands(); - } -}; - -//===----------------------------------------------------------------------===// -// HungoffOperand Trait Class -//===----------------------------------------------------------------------===// - -/// HungoffOperandTraits - determine the allocation regime of the Use array -/// when it is not a prefix to the User object, but allocated at an unrelated -/// heap address. -/// -/// This is the traits class that is needed when the Use array must be -/// resizable. - -template -struct HungoffOperandTraits { - static Use *op_begin(User* U) { - return U->getOperandList(); - } - static Use *op_end(User* U) { - return U->getOperandList() + U->getNumOperands(); - } - static unsigned operands(const User *U) { - return U->getNumOperands(); - } -}; - -/// Macro for generating in-class operand accessor declarations. -/// It should only be called in the public section of the interface. -/// -#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ - public: \ - inline VALUECLASS *getOperand(unsigned) const; \ - inline void setOperand(unsigned, VALUECLASS*); \ - inline op_iterator op_begin(); \ - inline const_op_iterator op_begin() const; \ - inline op_iterator op_end(); \ - inline const_op_iterator op_end() const; \ - protected: \ - template inline Use &Op(); \ - template inline const Use &Op() const; \ - public: \ - inline unsigned getNumOperands() const - -/// Macro for generating out-of-class operand accessor definitions -#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ -CLASS::op_iterator CLASS::op_begin() { \ - return OperandTraits::op_begin(this); \ -} \ -CLASS::const_op_iterator CLASS::op_begin() const { \ - return OperandTraits::op_begin(const_cast(this)); \ -} \ -CLASS::op_iterator CLASS::op_end() { \ - return OperandTraits::op_end(this); \ -} \ -CLASS::const_op_iterator CLASS::op_end() const { \ - return OperandTraits::op_end(const_cast(this)); \ -} \ -VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ - assert(i_nocapture < OperandTraits::operands(this) \ - && "getOperand() out of range!"); \ - return cast_or_null( \ - OperandTraits::op_begin(const_cast(this))[i_nocapture].get()); \ -} \ -void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ - assert(i_nocapture < OperandTraits::operands(this) \ - && "setOperand() out of range!"); \ - OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ -} \ -unsigned CLASS::getNumOperands() const { \ - return OperandTraits::operands(this); \ -} \ -template Use &CLASS::Op() { \ - return this->OpFrom(this); \ -} \ -template const Use &CLASS::Op() const { \ - return this->OpFrom(this); \ -} - - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/Operator.h b/suite/synctools/tablegen/include/llvm/IR/Operator.h deleted file mode 100644 index 7d232bba08..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Operator.h +++ /dev/null @@ -1,675 +0,0 @@ -//===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines various classes for working with Instructions and -// ConstantExprs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_OPERATOR_H -#define LLVM_IR_OPERATOR_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include - -namespace llvm { - -/// This is a utility class that provides an abstraction for the common -/// functionality between Instructions and ConstantExprs. -class Operator : public User { -public: - // The Operator class is intended to be used as a utility, and is never itself - // instantiated. - Operator() = delete; - ~Operator() = delete; - - void *operator new(size_t s) = delete; - - /// Return the opcode for this Instruction or ConstantExpr. - unsigned getOpcode() const { - if (const Instruction *I = dyn_cast(this)) - return I->getOpcode(); - return cast(this)->getOpcode(); - } - - /// If V is an Instruction or ConstantExpr, return its opcode. - /// Otherwise return UserOp1. - static unsigned getOpcode(const Value *V) { - if (const Instruction *I = dyn_cast(V)) - return I->getOpcode(); - if (const ConstantExpr *CE = dyn_cast(V)) - return CE->getOpcode(); - return Instruction::UserOp1; - } - - static bool classof(const Instruction *) { return true; } - static bool classof(const ConstantExpr *) { return true; } - static bool classof(const Value *V) { - return isa(V) || isa(V); - } - - /// Return true if this operator has flags which may cause this operator - /// to evaluate to poison despite having non-poison inputs. - bool hasPoisonGeneratingFlags() const; -}; - -/// Utility class for integer operators which may exhibit overflow - Add, Sub, -/// Mul, and Shl. It does not include SDiv, despite that operator having the -/// potential for overflow. -class OverflowingBinaryOperator : public Operator { -public: - enum { - AnyWrap = 0, - NoUnsignedWrap = (1 << 0), - NoSignedWrap = (1 << 1) - }; - -private: - friend class Instruction; - friend class ConstantExpr; - - void setHasNoUnsignedWrap(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); - } - void setHasNoSignedWrap(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); - } - -public: - /// Test whether this operation is known to never - /// undergo unsigned overflow, aka the nuw property. - bool hasNoUnsignedWrap() const { - return SubclassOptionalData & NoUnsignedWrap; - } - - /// Test whether this operation is known to never - /// undergo signed overflow, aka the nsw property. - bool hasNoSignedWrap() const { - return (SubclassOptionalData & NoSignedWrap) != 0; - } - - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Add || - I->getOpcode() == Instruction::Sub || - I->getOpcode() == Instruction::Mul || - I->getOpcode() == Instruction::Shl; - } - static bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Add || - CE->getOpcode() == Instruction::Sub || - CE->getOpcode() == Instruction::Mul || - CE->getOpcode() == Instruction::Shl; - } - static bool classof(const Value *V) { - return (isa(V) && classof(cast(V))) || - (isa(V) && classof(cast(V))); - } -}; - -/// A udiv or sdiv instruction, which can be marked as "exact", -/// indicating that no bits are destroyed. -class PossiblyExactOperator : public Operator { -public: - enum { - IsExact = (1 << 0) - }; - -private: - friend class Instruction; - friend class ConstantExpr; - - void setIsExact(bool B) { - SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); - } - -public: - /// Test whether this division is known to be exact, with zero remainder. - bool isExact() const { - return SubclassOptionalData & IsExact; - } - - static bool isPossiblyExactOpcode(unsigned OpC) { - return OpC == Instruction::SDiv || - OpC == Instruction::UDiv || - OpC == Instruction::AShr || - OpC == Instruction::LShr; - } - - static bool classof(const ConstantExpr *CE) { - return isPossiblyExactOpcode(CE->getOpcode()); - } - static bool classof(const Instruction *I) { - return isPossiblyExactOpcode(I->getOpcode()); - } - static bool classof(const Value *V) { - return (isa(V) && classof(cast(V))) || - (isa(V) && classof(cast(V))); - } -}; - -/// Convenience struct for specifying and reasoning about fast-math flags. -class FastMathFlags { -private: - friend class FPMathOperator; - - unsigned Flags = 0; - - FastMathFlags(unsigned F) { - // If all 7 bits are set, turn this into -1. If the number of bits grows, - // this must be updated. This is intended to provide some forward binary - // compatibility insurance for the meaning of 'fast' in case bits are added. - if (F == 0x7F) Flags = ~0U; - else Flags = F; - } - -public: - // This is how the bits are used in Value::SubclassOptionalData so they - // should fit there too. - // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New - // functionality will require a change in how this information is stored. - enum { - AllowReassoc = (1 << 0), - NoNaNs = (1 << 1), - NoInfs = (1 << 2), - NoSignedZeros = (1 << 3), - AllowReciprocal = (1 << 4), - AllowContract = (1 << 5), - ApproxFunc = (1 << 6) - }; - - FastMathFlags() = default; - - static FastMathFlags getFast() { - FastMathFlags FMF; - FMF.setFast(); - return FMF; - } - - bool any() const { return Flags != 0; } - bool none() const { return Flags == 0; } - bool all() const { return Flags == ~0U; } - - void clear() { Flags = 0; } - void set() { Flags = ~0U; } - - /// Flag queries - bool allowReassoc() const { return 0 != (Flags & AllowReassoc); } - bool noNaNs() const { return 0 != (Flags & NoNaNs); } - bool noInfs() const { return 0 != (Flags & NoInfs); } - bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } - bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } - bool allowContract() const { return 0 != (Flags & AllowContract); } - bool approxFunc() const { return 0 != (Flags & ApproxFunc); } - /// 'Fast' means all bits are set. - bool isFast() const { return all(); } - - /// Flag setters - void setAllowReassoc(bool B = true) { - Flags = (Flags & ~AllowReassoc) | B * AllowReassoc; - } - void setNoNaNs(bool B = true) { - Flags = (Flags & ~NoNaNs) | B * NoNaNs; - } - void setNoInfs(bool B = true) { - Flags = (Flags & ~NoInfs) | B * NoInfs; - } - void setNoSignedZeros(bool B = true) { - Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros; - } - void setAllowReciprocal(bool B = true) { - Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal; - } - void setAllowContract(bool B = true) { - Flags = (Flags & ~AllowContract) | B * AllowContract; - } - void setApproxFunc(bool B = true) { - Flags = (Flags & ~ApproxFunc) | B * ApproxFunc; - } - void setFast(bool B = true) { B ? set() : clear(); } - - void operator&=(const FastMathFlags &OtherFlags) { - Flags &= OtherFlags.Flags; - } - void operator|=(const FastMathFlags &OtherFlags) { - Flags |= OtherFlags.Flags; - } - bool operator!=(const FastMathFlags &OtherFlags) const { - return Flags != OtherFlags.Flags; - } - - /// Print fast-math flags to \p O. - void print(raw_ostream &O) const; -}; - -inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) { - FMF.print(O); - return O; -} - -/// Utility class for floating point operations which can have -/// information about relaxed accuracy requirements attached to them. -class FPMathOperator : public Operator { -private: - friend class Instruction; - - /// 'Fast' means all bits are set. - void setFast(bool B) { - setHasAllowReassoc(B); - setHasNoNaNs(B); - setHasNoInfs(B); - setHasNoSignedZeros(B); - setHasAllowReciprocal(B); - setHasAllowContract(B); - setHasApproxFunc(B); - } - - void setHasAllowReassoc(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | - (B * FastMathFlags::AllowReassoc); - } - - void setHasNoNaNs(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::NoNaNs) | - (B * FastMathFlags::NoNaNs); - } - - void setHasNoInfs(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::NoInfs) | - (B * FastMathFlags::NoInfs); - } - - void setHasNoSignedZeros(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | - (B * FastMathFlags::NoSignedZeros); - } - - void setHasAllowReciprocal(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | - (B * FastMathFlags::AllowReciprocal); - } - - void setHasAllowContract(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::AllowContract) | - (B * FastMathFlags::AllowContract); - } - - void setHasApproxFunc(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | - (B * FastMathFlags::ApproxFunc); - } - - /// Convenience function for setting multiple fast-math flags. - /// FMF is a mask of the bits to set. - void setFastMathFlags(FastMathFlags FMF) { - SubclassOptionalData |= FMF.Flags; - } - - /// Convenience function for copying all fast-math flags. - /// All values in FMF are transferred to this operator. - void copyFastMathFlags(FastMathFlags FMF) { - SubclassOptionalData = FMF.Flags; - } - -public: - /// Test if this operation allows all non-strict floating-point transforms. - bool isFast() const { - return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && - (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && - (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && - (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && - (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && - (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && - (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); - } - - /// Test if this operation may be simplified with reassociative transforms. - bool hasAllowReassoc() const { - return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; - } - - /// Test if this operation's arguments and results are assumed not-NaN. - bool hasNoNaNs() const { - return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; - } - - /// Test if this operation's arguments and results are assumed not-infinite. - bool hasNoInfs() const { - return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; - } - - /// Test if this operation can ignore the sign of zero. - bool hasNoSignedZeros() const { - return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; - } - - /// Test if this operation can use reciprocal multiply instead of division. - bool hasAllowReciprocal() const { - return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; - } - - /// Test if this operation can be floating-point contracted (FMA). - bool hasAllowContract() const { - return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; - } - - /// Test if this operation allows approximations of math library functions or - /// intrinsics. - bool hasApproxFunc() const { - return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; - } - - /// Convenience function for getting all the fast-math flags - FastMathFlags getFastMathFlags() const { - return FastMathFlags(SubclassOptionalData); - } - - /// Get the maximum error permitted by this operation in ULPs. An accuracy of - /// 0.0 means that the operation should be performed with the default - /// precision. - float getFPAccuracy() const; - - static bool classof(const Value *V) { - unsigned Opcode; - if (auto *I = dyn_cast(V)) - Opcode = I->getOpcode(); - else if (auto *CE = dyn_cast(V)) - Opcode = CE->getOpcode(); - else - return false; - - switch (Opcode) { - case Instruction::FNeg: - case Instruction::FAdd: - case Instruction::FSub: - case Instruction::FMul: - case Instruction::FDiv: - case Instruction::FRem: - // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp - // should not be treated as a math op, but the other opcodes should. - // This would make things consistent with Select/PHI (FP value type - // determines whether they are math ops and, therefore, capable of - // having fast-math-flags). - case Instruction::FCmp: - return true; - case Instruction::PHI: - case Instruction::Select: - case Instruction::Call: { - Type *Ty = V->getType(); - while (ArrayType *ArrTy = dyn_cast(Ty)) - Ty = ArrTy->getElementType(); - return Ty->isFPOrFPVectorTy(); - } - default: - return false; - } - } -}; - -/// A helper template for defining operators for individual opcodes. -template -class ConcreteOperator : public SuperClass { -public: - static bool classof(const Instruction *I) { - return I->getOpcode() == Opc; - } - static bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Opc; - } - static bool classof(const Value *V) { - return (isa(V) && classof(cast(V))) || - (isa(V) && classof(cast(V))); - } -}; - -class AddOperator - : public ConcreteOperator { -}; -class SubOperator - : public ConcreteOperator { -}; -class MulOperator - : public ConcreteOperator { -}; -class ShlOperator - : public ConcreteOperator { -}; - -class SDivOperator - : public ConcreteOperator { -}; -class UDivOperator - : public ConcreteOperator { -}; -class AShrOperator - : public ConcreteOperator { -}; -class LShrOperator - : public ConcreteOperator { -}; - -class ZExtOperator : public ConcreteOperator {}; - -class GEPOperator - : public ConcreteOperator { - friend class GetElementPtrInst; - friend class ConstantExpr; - - enum { - IsInBounds = (1 << 0), - // InRangeIndex: bits 1-6 - }; - - void setIsInBounds(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); - } - -public: - /// Test whether this is an inbounds GEP, as defined by LangRef.html. - bool isInBounds() const { - return SubclassOptionalData & IsInBounds; - } - - /// Returns the offset of the index with an inrange attachment, or None if - /// none. - Optional getInRangeIndex() const { - if (SubclassOptionalData >> 1 == 0) return None; - return (SubclassOptionalData >> 1) - 1; - } - - inline op_iterator idx_begin() { return op_begin()+1; } - inline const_op_iterator idx_begin() const { return op_begin()+1; } - inline op_iterator idx_end() { return op_end(); } - inline const_op_iterator idx_end() const { return op_end(); } - - inline iterator_range indices() { - return make_range(idx_begin(), idx_end()); - } - - inline iterator_range indices() const { - return make_range(idx_begin(), idx_end()); - } - - Value *getPointerOperand() { - return getOperand(0); - } - const Value *getPointerOperand() const { - return getOperand(0); - } - static unsigned getPointerOperandIndex() { - return 0U; // get index for modifying correct operand - } - - /// Method to return the pointer operand as a PointerType. - Type *getPointerOperandType() const { - return getPointerOperand()->getType(); - } - - Type *getSourceElementType() const; - Type *getResultElementType() const; - - /// Method to return the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return getPointerOperandType()->getPointerAddressSpace(); - } - - unsigned getNumIndices() const { // Note: always non-negative - return getNumOperands() - 1; - } - - bool hasIndices() const { - return getNumOperands() > 1; - } - - /// Return true if all of the indices of this GEP are zeros. - /// If so, the result pointer and the first operand have the same - /// value, just potentially different types. - bool hasAllZeroIndices() const { - for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { - if (ConstantInt *C = dyn_cast(I)) - if (C->isZero()) - continue; - return false; - } - return true; - } - - /// Return true if all of the indices of this GEP are constant integers. - /// If so, the result pointer and the first operand have - /// a constant offset between them. - bool hasAllConstantIndices() const { - for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { - if (!isa(I)) - return false; - } - return true; - } - - unsigned countNonConstantIndices() const { - return count_if(indices(), [](const Use& use) { - return !isa(*use); - }); - } - - /// Compute the maximum alignment that this GEP is garranteed to preserve. - Align getMaxPreservedAlignment(const DataLayout &DL) const; - - /// Accumulate the constant address offset of this GEP if possible. - /// - /// This routine accepts an APInt into which it will try to accumulate the - /// constant offset of this GEP. - /// - /// If \p ExternalAnalysis is provided it will be used to calculate a offset - /// when a operand of GEP is not constant. - /// For example, for a value \p ExternalAnalysis might try to calculate a - /// lower bound. If \p ExternalAnalysis is successful, it should return true. - /// - /// If the \p ExternalAnalysis returns false or the value returned by \p - /// ExternalAnalysis results in a overflow/underflow, this routine returns - /// false and the value of the offset APInt is undefined (it is *not* - /// preserved!). - /// - /// The APInt passed into this routine must be at exactly as wide as the - /// IntPtr type for the address space of the base GEP pointer. - bool accumulateConstantOffset( - const DataLayout &DL, APInt &Offset, - function_ref ExternalAnalysis = nullptr) const; - - static bool accumulateConstantOffset( - Type *SourceType, ArrayRef Index, const DataLayout &DL, - APInt &Offset, - function_ref ExternalAnalysis = nullptr); - - /// Collect the offset of this GEP as a map of Values to their associated - /// APInt multipliers, as well as a total Constant Offset. - bool collectOffset(const DataLayout &DL, unsigned BitWidth, - MapVector &VariableOffsets, - APInt &ConstantOffset) const; -}; - -class PtrToIntOperator - : public ConcreteOperator { - friend class PtrToInt; - friend class ConstantExpr; - -public: - Value *getPointerOperand() { - return getOperand(0); - } - const Value *getPointerOperand() const { - return getOperand(0); - } - - static unsigned getPointerOperandIndex() { - return 0U; // get index for modifying correct operand - } - - /// Method to return the pointer operand as a PointerType. - Type *getPointerOperandType() const { - return getPointerOperand()->getType(); - } - - /// Method to return the address space of the pointer operand. - unsigned getPointerAddressSpace() const { - return cast(getPointerOperandType())->getAddressSpace(); - } -}; - -class BitCastOperator - : public ConcreteOperator { - friend class BitCastInst; - friend class ConstantExpr; - -public: - Type *getSrcTy() const { - return getOperand(0)->getType(); - } - - Type *getDestTy() const { - return getType(); - } -}; - -class AddrSpaceCastOperator - : public ConcreteOperator { - friend class AddrSpaceCastInst; - friend class ConstantExpr; - -public: - Value *getPointerOperand() { return getOperand(0); } - - const Value *getPointerOperand() const { return getOperand(0); } - - unsigned getSrcAddressSpace() const { - return getPointerOperand()->getType()->getPointerAddressSpace(); - } - - unsigned getDestAddressSpace() const { - return getType()->getPointerAddressSpace(); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_OPERATOR_H diff --git a/suite/synctools/tablegen/include/llvm/IR/OptBisect.h b/suite/synctools/tablegen/include/llvm/IR/OptBisect.h deleted file mode 100644 index 63fd98073b..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/OptBisect.h +++ /dev/null @@ -1,96 +0,0 @@ -//===- llvm/IR/OptBisect.h - LLVM Bisect support ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file declares the interface for bisecting optimizations. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_OPTBISECT_H -#define LLVM_IR_OPTBISECT_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ManagedStatic.h" -#include - -namespace llvm { - -class Pass; - -/// Extensions to this class implement mechanisms to disable passes and -/// individual optimizations at compile time. -class OptPassGate { -public: - virtual ~OptPassGate() = default; - - /// IRDescription is a textual description of the IR unit the pass is running - /// over. - virtual bool shouldRunPass(const Pass *P, StringRef IRDescription) { - return true; - } - - /// isEnabled() should return true before calling shouldRunPass(). - virtual bool isEnabled() const { return false; } -}; - -/// This class implements a mechanism to disable passes and individual -/// optimizations at compile time based on a command line option -/// (-opt-bisect-limit) in order to perform a bisecting search for -/// optimization-related problems. -class OptBisect : public OptPassGate { -public: - /// Default constructor. Initializes the state to "disabled". The bisection - /// will be enabled by the cl::opt call-back when the command line option - /// is processed. - /// Clients should not instantiate this class directly. All access should go - /// through LLVMContext. - OptBisect() = default; - - virtual ~OptBisect() = default; - - /// Checks the bisect limit to determine if the specified pass should run. - /// - /// This forwards to checkPass(). - bool shouldRunPass(const Pass *P, StringRef IRDescription) override; - - /// isEnabled() should return true before calling shouldRunPass(). - bool isEnabled() const override { return BisectLimit != Disabled; } - - /// Set the new optimization limit and reset the counter. Passing - /// OptBisect::Disabled disables the limiting. - void setLimit(int Limit) { - BisectLimit = Limit; - LastBisectNum = 0; - } - - /// Checks the bisect limit to determine if the specified pass should run. - /// - /// If the bisect limit is set to -1, the function prints a message describing - /// the pass and the bisect number assigned to it and return true. Otherwise, - /// the function prints a message with the bisect number assigned to the - /// pass and indicating whether or not the pass will be run and return true if - /// the bisect limit has not yet been exceeded or false if it has. - /// - /// Most passes should not call this routine directly. Instead, they are - /// called through helper routines provided by the pass base classes. For - /// instance, function passes should call FunctionPass::skipFunction(). - bool checkPass(const StringRef PassName, const StringRef TargetDesc); - - static const int Disabled = std::numeric_limits::max(); - -private: - int BisectLimit = Disabled; - int LastBisectNum = 0; -}; - -/// Singleton instance of the OptBisect class, so multiple pass managers don't -/// need to coordinate their uses of OptBisect. -extern ManagedStatic OptBisector; -} // end namespace llvm - -#endif // LLVM_IR_OPTBISECT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PassInstrumentation.h b/suite/synctools/tablegen/include/llvm/IR/PassInstrumentation.h deleted file mode 100644 index 27dd075bbd..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PassInstrumentation.h +++ /dev/null @@ -1,322 +0,0 @@ -//===- llvm/IR/PassInstrumentation.h ----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file defines the Pass Instrumentation classes that provide -/// instrumentation points into the pass execution by PassManager. -/// -/// There are two main classes: -/// - PassInstrumentation provides a set of instrumentation points for -/// pass managers to call on. -/// -/// - PassInstrumentationCallbacks registers callbacks and provides access -/// to them for PassInstrumentation. -/// -/// PassInstrumentation object is being used as a result of -/// PassInstrumentationAnalysis (so it is intended to be easily copyable). -/// -/// Intended scheme of use for Pass Instrumentation is as follows: -/// - register instrumentation callbacks in PassInstrumentationCallbacks -/// instance. PassBuilder provides helper for that. -/// -/// - register PassInstrumentationAnalysis with all the PassManagers. -/// PassBuilder handles that automatically when registering analyses. -/// -/// - Pass Manager requests PassInstrumentationAnalysis from analysis manager -/// and gets PassInstrumentation as its result. -/// -/// - Pass Manager invokes PassInstrumentation entry points appropriately, -/// passing StringRef identification ("name") of the pass currently being -/// executed and IRUnit it works on. There can be different schemes of -/// providing names in future, currently it is just a name() of the pass. -/// -/// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes -/// control to all the registered callbacks. Note that we specifically wrap -/// 'const IRUnitT*' so as to avoid any accidental changes to IR in -/// instrumenting callbacks. -/// -/// - Some instrumentation points (BeforePass) allow to control execution -/// of a pass. For those callbacks returning false means pass will not be -/// executed. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PASSINSTRUMENTATION_H -#define LLVM_IR_PASSINSTRUMENTATION_H - -#include "llvm/ADT/Any.h" -#include "llvm/ADT/FunctionExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include -#include - -namespace llvm { - -class PreservedAnalyses; -class StringRef; - -/// This class manages callbacks registration, as well as provides a way for -/// PassInstrumentation to pass control to the registered callbacks. -class PassInstrumentationCallbacks { -public: - // Before/After callbacks accept IRUnits whenever appropriate, so they need - // to take them as constant pointers, wrapped with llvm::Any. - // For the case when IRUnit has been invalidated there is a different - // callback to use - AfterPassInvalidated. - // We call all BeforePassFuncs to determine if a pass should run or not. - // BeforeNonSkippedPassFuncs are called only if the pass should run. - // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing - // already invalidated IRUnit is unsafe. There are ways to handle invalidated - // IRUnits in a safe way, and we might pursue that as soon as there is a - // useful instrumentation that needs it. - using BeforePassFunc = bool(StringRef, Any); - using BeforeSkippedPassFunc = void(StringRef, Any); - using BeforeNonSkippedPassFunc = void(StringRef, Any); - using AfterPassFunc = void(StringRef, Any, const PreservedAnalyses &); - using AfterPassInvalidatedFunc = void(StringRef, const PreservedAnalyses &); - using BeforeAnalysisFunc = void(StringRef, Any); - using AfterAnalysisFunc = void(StringRef, Any); - using AnalysisInvalidatedFunc = void(StringRef, Any); - using AnalysesClearedFunc = void(StringRef); - -public: - PassInstrumentationCallbacks() = default; - - /// Copying PassInstrumentationCallbacks is not intended. - PassInstrumentationCallbacks(const PassInstrumentationCallbacks &) = delete; - void operator=(const PassInstrumentationCallbacks &) = delete; - - template - void registerShouldRunOptionalPassCallback(CallableT C) { - ShouldRunOptionalPassCallbacks.emplace_back(std::move(C)); - } - - template - void registerBeforeSkippedPassCallback(CallableT C) { - BeforeSkippedPassCallbacks.emplace_back(std::move(C)); - } - - template - void registerBeforeNonSkippedPassCallback(CallableT C) { - BeforeNonSkippedPassCallbacks.emplace_back(std::move(C)); - } - - template void registerAfterPassCallback(CallableT C) { - AfterPassCallbacks.emplace_back(std::move(C)); - } - - template - void registerAfterPassInvalidatedCallback(CallableT C) { - AfterPassInvalidatedCallbacks.emplace_back(std::move(C)); - } - - template - void registerBeforeAnalysisCallback(CallableT C) { - BeforeAnalysisCallbacks.emplace_back(std::move(C)); - } - - template - void registerAfterAnalysisCallback(CallableT C) { - AfterAnalysisCallbacks.emplace_back(std::move(C)); - } - - template - void registerAnalysisInvalidatedCallback(CallableT C) { - AnalysisInvalidatedCallbacks.emplace_back(std::move(C)); - } - - template - void registerAnalysesClearedCallback(CallableT C) { - AnalysesClearedCallbacks.emplace_back(std::move(C)); - } - - /// Add a class name to pass name mapping for use by pass instrumentation. - void addClassToPassName(StringRef ClassName, StringRef PassName); - /// Get the pass name for a given pass class name. - StringRef getPassNameForClassName(StringRef ClassName); - -private: - friend class PassInstrumentation; - - /// These are only run on passes that are not required. They return false when - /// an optional pass should be skipped. - SmallVector, 4> - ShouldRunOptionalPassCallbacks; - /// These are run on passes that are skipped. - SmallVector, 4> - BeforeSkippedPassCallbacks; - /// These are run on passes that are about to be run. - SmallVector, 4> - BeforeNonSkippedPassCallbacks; - /// These are run on passes that have just run. - SmallVector, 4> AfterPassCallbacks; - /// These are run passes that have just run on invalidated IR. - SmallVector, 4> - AfterPassInvalidatedCallbacks; - /// These are run on analyses that are about to be run. - SmallVector, 4> - BeforeAnalysisCallbacks; - /// These are run on analyses that have been run. - SmallVector, 4> - AfterAnalysisCallbacks; - /// These are run on analyses that have been invalidated. - SmallVector, 4> - AnalysisInvalidatedCallbacks; - /// These are run on analyses that have been cleared. - SmallVector, 4> - AnalysesClearedCallbacks; - - StringMap ClassToPassName; -}; - -/// This class provides instrumentation entry points for the Pass Manager, -/// doing calls to callbacks registered in PassInstrumentationCallbacks. -class PassInstrumentation { - PassInstrumentationCallbacks *Callbacks; - - // Template argument PassT of PassInstrumentation::runBeforePass could be two - // kinds: (1) a regular pass inherited from PassInfoMixin (happen when - // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept - // created from (1). Here we want to make case (1) skippable unconditionally - // since they are regular passes. We call PassConcept::isRequired to decide - // for case (2). - template - using has_required_t = decltype(std::declval().isRequired()); - - template - static std::enable_if_t::value, bool> - isRequired(const PassT &Pass) { - return Pass.isRequired(); - } - template - static std::enable_if_t::value, bool> - isRequired(const PassT &Pass) { - return false; - } - -public: - /// Callbacks object is not owned by PassInstrumentation, its life-time - /// should at least match the life-time of corresponding - /// PassInstrumentationAnalysis (which usually is till the end of current - /// compilation). - PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr) - : Callbacks(CB) {} - - /// BeforePass instrumentation point - takes \p Pass instance to be executed - /// and constant reference to IR it operates on. \Returns true if pass is - /// allowed to be executed. These are only run on optional pass since required - /// passes must always be run. This allows these callbacks to print info when - /// they want to skip a pass. - template - bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const { - if (!Callbacks) - return true; - - bool ShouldRun = true; - if (!isRequired(Pass)) { - for (auto &C : Callbacks->ShouldRunOptionalPassCallbacks) - ShouldRun &= C(Pass.name(), llvm::Any(&IR)); - } - - if (ShouldRun) { - for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks) - C(Pass.name(), llvm::Any(&IR)); - } else { - for (auto &C : Callbacks->BeforeSkippedPassCallbacks) - C(Pass.name(), llvm::Any(&IR)); - } - - return ShouldRun; - } - - /// AfterPass instrumentation point - takes \p Pass instance that has - /// just been executed and constant reference to \p IR it operates on. - /// \p IR is guaranteed to be valid at this point. - template - void runAfterPass(const PassT &Pass, const IRUnitT &IR, - const PreservedAnalyses &PA) const { - if (Callbacks) - for (auto &C : Callbacks->AfterPassCallbacks) - C(Pass.name(), llvm::Any(&IR), PA); - } - - /// AfterPassInvalidated instrumentation point - takes \p Pass instance - /// that has just been executed. For use when IR has been invalidated - /// by \p Pass execution. - template - void runAfterPassInvalidated(const PassT &Pass, - const PreservedAnalyses &PA) const { - if (Callbacks) - for (auto &C : Callbacks->AfterPassInvalidatedCallbacks) - C(Pass.name(), PA); - } - - /// BeforeAnalysis instrumentation point - takes \p Analysis instance - /// to be executed and constant reference to IR it operates on. - template - void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const { - if (Callbacks) - for (auto &C : Callbacks->BeforeAnalysisCallbacks) - C(Analysis.name(), llvm::Any(&IR)); - } - - /// AfterAnalysis instrumentation point - takes \p Analysis instance - /// that has just been executed and constant reference to IR it operated on. - template - void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const { - if (Callbacks) - for (auto &C : Callbacks->AfterAnalysisCallbacks) - C(Analysis.name(), llvm::Any(&IR)); - } - - /// AnalysisInvalidated instrumentation point - takes \p Analysis instance - /// that has just been invalidated and constant reference to IR it operated - /// on. - template - void runAnalysisInvalidated(const PassT &Analysis, const IRUnitT &IR) const { - if (Callbacks) - for (auto &C : Callbacks->AnalysisInvalidatedCallbacks) - C(Analysis.name(), llvm::Any(&IR)); - } - - /// AnalysesCleared instrumentation point - takes name of IR that analyses - /// operated on. - void runAnalysesCleared(StringRef Name) const { - if (Callbacks) - for (auto &C : Callbacks->AnalysesClearedCallbacks) - C(Name); - } - - /// Handle invalidation from the pass manager when PassInstrumentation - /// is used as the result of PassInstrumentationAnalysis. - /// - /// On attempt to invalidate just return false. There is nothing to become - /// invalid here. - template - bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &, - ExtraArgsT...) { - return false; - } - - template - void pushBeforeNonSkippedPassCallback(CallableT C) { - if (Callbacks) - Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C)); - } - void popBeforeNonSkippedPassCallback() { - if (Callbacks) - Callbacks->BeforeNonSkippedPassCallbacks.pop_back(); - } -}; - -bool isSpecialPass(StringRef PassID, const std::vector &Specials); - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/PassManager.h b/suite/synctools/tablegen/include/llvm/IR/PassManager.h deleted file mode 100644 index 6c5e8f3616..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PassManager.h +++ /dev/null @@ -1,1365 +0,0 @@ -//===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This header defines various interfaces for pass management in LLVM. There -/// is no "pass" interface in LLVM per se. Instead, an instance of any class -/// which supports a method to 'run' it over a unit of IR can be used as -/// a pass. A pass manager is generally a tool to collect a sequence of passes -/// which run over a particular IR construct, and run each of them in sequence -/// over each such construct in the containing IR construct. As there is no -/// containing IR construct for a Module, a manager for passes over modules -/// forms the base case which runs its managed passes in sequence over the -/// single module provided. -/// -/// The core IR library provides managers for running passes over -/// modules and functions. -/// -/// * FunctionPassManager can run over a Module, runs each pass over -/// a Function. -/// * ModulePassManager must be directly run, runs each pass over the Module. -/// -/// Note that the implementations of the pass managers use concept-based -/// polymorphism as outlined in the "Value Semantics and Concept-based -/// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base -/// Class of Evil") by Sean Parent: -/// * http://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations -/// * http://www.youtube.com/watch?v=_BpMYeUFXv8 -/// * http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PASSMANAGER_H -#define LLVM_IR_PASSMANAGER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/PassInstrumentation.h" -#include "llvm/IR/PassManagerInternal.h" -#include "llvm/Support/TimeProfiler.h" -#include "llvm/Support/TypeName.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -/// A special type used by analysis passes to provide an address that -/// identifies that particular analysis pass type. -/// -/// Analysis passes should have a static data member of this type and derive -/// from the \c AnalysisInfoMixin to get a static ID method used to identify -/// the analysis in the pass management infrastructure. -struct alignas(8) AnalysisKey {}; - -/// A special type used to provide an address that identifies a set of related -/// analyses. These sets are primarily used below to mark sets of analyses as -/// preserved. -/// -/// For example, a transformation can indicate that it preserves the CFG of a -/// function by preserving the appropriate AnalysisSetKey. An analysis that -/// depends only on the CFG can then check if that AnalysisSetKey is preserved; -/// if it is, the analysis knows that it itself is preserved. -struct alignas(8) AnalysisSetKey {}; - -/// This templated class represents "all analyses that operate over \" (e.g. a Function or a Module) in instances of -/// PreservedAnalysis. -/// -/// This lets a transformation say e.g. "I preserved all function analyses". -/// -/// Note that you must provide an explicit instantiation declaration and -/// definition for this template in order to get the correct behavior on -/// Windows. Otherwise, the address of SetKey will not be stable. -template class AllAnalysesOn { -public: - static AnalysisSetKey *ID() { return &SetKey; } - -private: - static AnalysisSetKey SetKey; -}; - -template AnalysisSetKey AllAnalysesOn::SetKey; - -extern template class AllAnalysesOn; -extern template class AllAnalysesOn; - -/// Represents analyses that only rely on functions' control flow. -/// -/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and -/// to query whether it has been preserved. -/// -/// The CFG of a function is defined as the set of basic blocks and the edges -/// between them. Changing the set of basic blocks in a function is enough to -/// mutate the CFG. Mutating the condition of a branch or argument of an -/// invoked function does not mutate the CFG, but changing the successor labels -/// of those instructions does. -class CFGAnalyses { -public: - static AnalysisSetKey *ID() { return &SetKey; } - -private: - static AnalysisSetKey SetKey; -}; - -/// A set of analyses that are preserved following a run of a transformation -/// pass. -/// -/// Transformation passes build and return these objects to communicate which -/// analyses are still valid after the transformation. For most passes this is -/// fairly simple: if they don't change anything all analyses are preserved, -/// otherwise only a short list of analyses that have been explicitly updated -/// are preserved. -/// -/// This class also lets transformation passes mark abstract *sets* of analyses -/// as preserved. A transformation that (say) does not alter the CFG can -/// indicate such by marking a particular AnalysisSetKey as preserved, and -/// then analyses can query whether that AnalysisSetKey is preserved. -/// -/// Finally, this class can represent an "abandoned" analysis, which is -/// not preserved even if it would be covered by some abstract set of analyses. -/// -/// Given a `PreservedAnalyses` object, an analysis will typically want to -/// figure out whether it is preserved. In the example below, MyAnalysisType is -/// preserved if it's not abandoned, and (a) it's explicitly marked as -/// preserved, (b), the set AllAnalysesOn is preserved, or (c) both -/// AnalysisSetA and AnalysisSetB are preserved. -/// -/// ``` -/// auto PAC = PA.getChecker(); -/// if (PAC.preserved() || PAC.preservedSet>() || -/// (PAC.preservedSet() && -/// PAC.preservedSet())) { -/// // The analysis has been successfully preserved ... -/// } -/// ``` -class PreservedAnalyses { -public: - /// Convenience factory function for the empty preserved set. - static PreservedAnalyses none() { return PreservedAnalyses(); } - - /// Construct a special preserved set that preserves all passes. - static PreservedAnalyses all() { - PreservedAnalyses PA; - PA.PreservedIDs.insert(&AllAnalysesKey); - return PA; - } - - /// Construct a preserved analyses object with a single preserved set. - template - static PreservedAnalyses allInSet() { - PreservedAnalyses PA; - PA.preserveSet(); - return PA; - } - - /// Mark an analysis as preserved. - template void preserve() { preserve(AnalysisT::ID()); } - - /// Given an analysis's ID, mark the analysis as preserved, adding it - /// to the set. - void preserve(AnalysisKey *ID) { - // Clear this ID from the explicit not-preserved set if present. - NotPreservedAnalysisIDs.erase(ID); - - // If we're not already preserving all analyses (other than those in - // NotPreservedAnalysisIDs). - if (!areAllPreserved()) - PreservedIDs.insert(ID); - } - - /// Mark an analysis set as preserved. - template void preserveSet() { - preserveSet(AnalysisSetT::ID()); - } - - /// Mark an analysis set as preserved using its ID. - void preserveSet(AnalysisSetKey *ID) { - // If we're not already in the saturated 'all' state, add this set. - if (!areAllPreserved()) - PreservedIDs.insert(ID); - } - - /// Mark an analysis as abandoned. - /// - /// An abandoned analysis is not preserved, even if it is nominally covered - /// by some other set or was previously explicitly marked as preserved. - /// - /// Note that you can only abandon a specific analysis, not a *set* of - /// analyses. - template void abandon() { abandon(AnalysisT::ID()); } - - /// Mark an analysis as abandoned using its ID. - /// - /// An abandoned analysis is not preserved, even if it is nominally covered - /// by some other set or was previously explicitly marked as preserved. - /// - /// Note that you can only abandon a specific analysis, not a *set* of - /// analyses. - void abandon(AnalysisKey *ID) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - - /// Intersect this set with another in place. - /// - /// This is a mutating operation on this preserved set, removing all - /// preserved passes which are not also preserved in the argument. - void intersect(const PreservedAnalyses &Arg) { - if (Arg.areAllPreserved()) - return; - if (areAllPreserved()) { - *this = Arg; - return; - } - // The intersection requires the *union* of the explicitly not-preserved - // IDs and the *intersection* of the preserved IDs. - for (auto ID : Arg.NotPreservedAnalysisIDs) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - for (auto ID : PreservedIDs) - if (!Arg.PreservedIDs.count(ID)) - PreservedIDs.erase(ID); - } - - /// Intersect this set with a temporary other set in place. - /// - /// This is a mutating operation on this preserved set, removing all - /// preserved passes which are not also preserved in the argument. - void intersect(PreservedAnalyses &&Arg) { - if (Arg.areAllPreserved()) - return; - if (areAllPreserved()) { - *this = std::move(Arg); - return; - } - // The intersection requires the *union* of the explicitly not-preserved - // IDs and the *intersection* of the preserved IDs. - for (auto ID : Arg.NotPreservedAnalysisIDs) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - for (auto ID : PreservedIDs) - if (!Arg.PreservedIDs.count(ID)) - PreservedIDs.erase(ID); - } - - /// A checker object that makes it easy to query for whether an analysis or - /// some set covering it is preserved. - class PreservedAnalysisChecker { - friend class PreservedAnalyses; - - const PreservedAnalyses &PA; - AnalysisKey *const ID; - const bool IsAbandoned; - - /// A PreservedAnalysisChecker is tied to a particular Analysis because - /// `preserved()` and `preservedSet()` both return false if the Analysis - /// was abandoned. - PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID) - : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} - - public: - /// Returns true if the checker's analysis was not abandoned and either - /// - the analysis is explicitly preserved or - /// - all analyses are preserved. - bool preserved() { - return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || - PA.PreservedIDs.count(ID)); - } - - /// Return true if the checker's analysis was not abandoned, i.e. it was not - /// explicitly invalidated. Even if the analysis is not explicitly - /// preserved, if the analysis is known stateless, then it is preserved. - bool preservedWhenStateless() { - return !IsAbandoned; - } - - /// Returns true if the checker's analysis was not abandoned and either - /// - \p AnalysisSetT is explicitly preserved or - /// - all analyses are preserved. - template bool preservedSet() { - AnalysisSetKey *SetID = AnalysisSetT::ID(); - return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || - PA.PreservedIDs.count(SetID)); - } - }; - - /// Build a checker for this `PreservedAnalyses` and the specified analysis - /// type. - /// - /// You can use the returned object to query whether an analysis was - /// preserved. See the example in the comment on `PreservedAnalysis`. - template PreservedAnalysisChecker getChecker() const { - return PreservedAnalysisChecker(*this, AnalysisT::ID()); - } - - /// Build a checker for this `PreservedAnalyses` and the specified analysis - /// ID. - /// - /// You can use the returned object to query whether an analysis was - /// preserved. See the example in the comment on `PreservedAnalysis`. - PreservedAnalysisChecker getChecker(AnalysisKey *ID) const { - return PreservedAnalysisChecker(*this, ID); - } - - /// Test whether all analyses are preserved (and none are abandoned). - /// - /// This is used primarily to optimize for the common case of a transformation - /// which makes no changes to the IR. - bool areAllPreserved() const { - return NotPreservedAnalysisIDs.empty() && - PreservedIDs.count(&AllAnalysesKey); - } - - /// Directly test whether a set of analyses is preserved. - /// - /// This is only true when no analyses have been explicitly abandoned. - template bool allAnalysesInSetPreserved() const { - return allAnalysesInSetPreserved(AnalysisSetT::ID()); - } - - /// Directly test whether a set of analyses is preserved. - /// - /// This is only true when no analyses have been explicitly abandoned. - bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const { - return NotPreservedAnalysisIDs.empty() && - (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID)); - } - -private: - /// A special key used to indicate all analyses. - static AnalysisSetKey AllAnalysesKey; - - /// The IDs of analyses and analysis sets that are preserved. - SmallPtrSet PreservedIDs; - - /// The IDs of explicitly not-preserved analyses. - /// - /// If an analysis in this set is covered by a set in `PreservedIDs`, we - /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always - /// "wins" over analysis sets in `PreservedIDs`. - /// - /// Also, a given ID should never occur both here and in `PreservedIDs`. - SmallPtrSet NotPreservedAnalysisIDs; -}; - -// Forward declare the analysis manager template. -template class AnalysisManager; - -/// A CRTP mix-in to automatically provide informational APIs needed for -/// passes. -/// -/// This provides some boilerplate for types that are passes. -template struct PassInfoMixin { - /// Gets the name of the pass we are mixed into. - static StringRef name() { - static_assert(std::is_base_of::value, - "Must pass the derived type as the template argument!"); - StringRef Name = getTypeName(); - Name.consume_front("llvm::"); - return Name; - } - - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) { - StringRef ClassName = DerivedT::name(); - auto PassName = MapClassName2PassName(ClassName); - OS << PassName; - } -}; - -/// A CRTP mix-in that provides informational APIs needed for analysis passes. -/// -/// This provides some boilerplate for types that are analysis passes. It -/// automatically mixes in \c PassInfoMixin. -template -struct AnalysisInfoMixin : PassInfoMixin { - /// Returns an opaque, unique ID for this analysis type. - /// - /// This ID is a pointer type that is guaranteed to be 8-byte aligned and thus - /// suitable for use in sets, maps, and other data structures that use the low - /// bits of pointers. - /// - /// Note that this requires the derived type provide a static \c AnalysisKey - /// member called \c Key. - /// - /// FIXME: The only reason the mixin type itself can't declare the Key value - /// is that some compilers cannot correctly unique a templated static variable - /// so it has the same addresses in each instantiation. The only currently - /// known platform with this limitation is Windows DLL builds, specifically - /// building each part of LLVM as a DLL. If we ever remove that build - /// configuration, this mixin can provide the static key as well. - static AnalysisKey *ID() { - static_assert(std::is_base_of::value, - "Must pass the derived type as the template argument!"); - return &DerivedT::Key; - } -}; - -namespace detail { - -/// Actual unpacker of extra arguments in getAnalysisResult, -/// passes only those tuple arguments that are mentioned in index_sequence. -template -typename PassT::Result -getAnalysisResultUnpackTuple(AnalysisManagerT &AM, IRUnitT &IR, - std::tuple Args, - std::index_sequence) { - (void)Args; - return AM.template getResult(IR, std::get(Args)...); -} - -/// Helper for *partial* unpacking of extra arguments in getAnalysisResult. -/// -/// Arguments passed in tuple come from PassManager, so they might have extra -/// arguments after those AnalysisManager's ExtraArgTs ones that we need to -/// pass to getResult. -template -typename PassT::Result -getAnalysisResult(AnalysisManager &AM, IRUnitT &IR, - std::tuple Args) { - return (getAnalysisResultUnpackTuple< - PassT, IRUnitT>)(AM, IR, Args, - std::index_sequence_for{}); -} - -} // namespace detail - -// Forward declare the pass instrumentation analysis explicitly queried in -// generic PassManager code. -// FIXME: figure out a way to move PassInstrumentationAnalysis into its own -// header. -class PassInstrumentationAnalysis; - -/// Manages a sequence of passes over a particular unit of IR. -/// -/// A pass manager contains a sequence of passes to run over a particular unit -/// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of -/// IR, and when run over some given IR will run each of its contained passes in -/// sequence. Pass managers are the primary and most basic building block of a -/// pass pipeline. -/// -/// When you run a pass manager, you provide an \c AnalysisManager -/// argument. The pass manager will propagate that analysis manager to each -/// pass it runs, and will call the analysis manager's invalidation routine with -/// the PreservedAnalyses of each pass it runs. -template , - typename... ExtraArgTs> -class PassManager : public PassInfoMixin< - PassManager> { -public: - /// Construct a pass manager. - explicit PassManager() = default; - - // FIXME: These are equivalent to the default move constructor/move - // assignment. However, using = default triggers linker errors due to the - // explicit instantiations below. Find away to use the default and remove the - // duplicated code here. - PassManager(PassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - - PassManager &operator=(PassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) { - for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { - auto *P = Passes[Idx].get(); - P->printPipeline(OS, MapClassName2PassName); - if (Idx + 1 < Size) - OS << ","; - } - } - - /// Run all of the passes in this manager over the given unit of IR. - /// ExtraArgs are passed to each pass. - PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) { - PreservedAnalyses PA = PreservedAnalyses::all(); - - // Request PassInstrumentation from analysis manager, will use it to run - // instrumenting callbacks for the passes later. - // Here we use std::tuple wrapper over getResult which helps to extract - // AnalysisManager's arguments out of the whole ExtraArgs set. - PassInstrumentation PI = - detail::getAnalysisResult( - AM, IR, std::tuple(ExtraArgs...)); - - for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { - auto *P = Passes[Idx].get(); - - // Check the PassInstrumentation's BeforePass callbacks before running the - // pass, skip its execution completely if asked to (callback returns - // false). - if (!PI.runBeforePass(*P, IR)) - continue; - - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(P->name(), IR.getName()); - PassPA = P->run(IR, AM, ExtraArgs...); - } - - // Call onto PassInstrumentation's AfterPass callbacks immediately after - // running the pass. - PI.runAfterPass(*P, IR, PassPA); - - // Update the analysis manager as each pass runs and potentially - // invalidates analyses. - AM.invalidate(IR, PassPA); - - // Finally, intersect the preserved analyses to compute the aggregate - // preserved set for this pass manager. - PA.intersect(std::move(PassPA)); - } - - // Invalidation was handled after each pass in the above loop for the - // current unit of IR. Therefore, the remaining analysis results in the - // AnalysisManager are preserved. We mark this with a set so that we don't - // need to inspect each one individually. - PA.preserveSet>(); - - return PA; - } - - template - LLVM_ATTRIBUTE_MINSIZE - std::enable_if_t::value> - addPass(PassT &&Pass) { - using PassModelT = - detail::PassModel; - // Do not use make_unique or emplace_back, they cause too many template - // instantiations, causing terrible compile times. - Passes.push_back(std::unique_ptr( - new PassModelT(std::forward(Pass)))); - } - - /// When adding a pass manager pass that has the same type as this pass - /// manager, simply move the passes over. This is because we don't have use - /// cases rely on executing nested pass managers. Doing this could reduce - /// implementation complexity and avoid potential invalidation issues that may - /// happen with nested pass managers of the same type. - template - LLVM_ATTRIBUTE_MINSIZE - std::enable_if_t::value> - addPass(PassT &&Pass) { - for (auto &P : Pass.Passes) - Passes.push_back(std::move(P)); - } - - /// Returns if the pass manager contains any passes. - bool isEmpty() const { return Passes.empty(); } - - static bool isRequired() { return true; } - -protected: - using PassConceptT = - detail::PassConcept; - - std::vector> Passes; -}; - -extern template class PassManager; - -/// Convenience typedef for a pass manager over modules. -using ModulePassManager = PassManager; - -extern template class PassManager; - -/// Convenience typedef for a pass manager over functions. -using FunctionPassManager = PassManager; - -/// Pseudo-analysis pass that exposes the \c PassInstrumentation to pass -/// managers. Goes before AnalysisManager definition to provide its -/// internals (e.g PassInstrumentationAnalysis::ID) for use there if needed. -/// FIXME: figure out a way to move PassInstrumentationAnalysis into its own -/// header. -class PassInstrumentationAnalysis - : public AnalysisInfoMixin { - friend AnalysisInfoMixin; - static AnalysisKey Key; - - PassInstrumentationCallbacks *Callbacks; - -public: - /// PassInstrumentationCallbacks object is shared, owned by something else, - /// not this analysis. - PassInstrumentationAnalysis(PassInstrumentationCallbacks *Callbacks = nullptr) - : Callbacks(Callbacks) {} - - using Result = PassInstrumentation; - - template - Result run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) { - return PassInstrumentation(Callbacks); - } -}; - -/// A container for analyses that lazily runs them and caches their -/// results. -/// -/// This class can manage analyses for any IR unit where the address of the IR -/// unit sufficies as its identity. -template class AnalysisManager { -public: - class Invalidator; - -private: - // Now that we've defined our invalidator, we can define the concept types. - using ResultConceptT = - detail::AnalysisResultConcept; - using PassConceptT = - detail::AnalysisPassConcept; - - /// List of analysis pass IDs and associated concept pointers. - /// - /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides the analysis ID to enable finding iterators to a given - /// entry in maps below, and provides the storage for the actual result - /// concept. - using AnalysisResultListT = - std::list>>; - - /// Map type from IRUnitT pointer to our custom list type. - using AnalysisResultListMapT = DenseMap; - - /// Map type from a pair of analysis ID and IRUnitT pointer to an - /// iterator into a particular result list (which is where the actual analysis - /// result is stored). - using AnalysisResultMapT = - DenseMap, - typename AnalysisResultListT::iterator>; - -public: - /// API to communicate dependencies between analyses during invalidation. - /// - /// When an analysis result embeds handles to other analysis results, it - /// needs to be invalidated both when its own information isn't preserved and - /// when any of its embedded analysis results end up invalidated. We pass an - /// \c Invalidator object as an argument to \c invalidate() in order to let - /// the analysis results themselves define the dependency graph on the fly. - /// This lets us avoid building an explicit representation of the - /// dependencies between analysis results. - class Invalidator { - public: - /// Trigger the invalidation of some other analysis pass if not already - /// handled and return whether it was in fact invalidated. - /// - /// This is expected to be called from within a given analysis result's \c - /// invalidate method to trigger a depth-first walk of all inter-analysis - /// dependencies. The same \p IR unit and \p PA passed to that result's \c - /// invalidate method should in turn be provided to this routine. - /// - /// The first time this is called for a given analysis pass, it will call - /// the corresponding result's \c invalidate method. Subsequent calls will - /// use a cache of the results of that initial call. It is an error to form - /// cyclic dependencies between analysis results. - /// - /// This returns true if the given analysis's result is invalid. Any - /// dependencies on it will become invalid as a result. - template - bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) { - using ResultModelT = - detail::AnalysisResultModel; - - return invalidateImpl(PassT::ID(), IR, PA); - } - - /// A type-erased variant of the above invalidate method with the same core - /// API other than passing an analysis ID rather than an analysis type - /// parameter. - /// - /// This is sadly less efficient than the above routine, which leverages - /// the type parameter to avoid the type erasure overhead. - bool invalidate(AnalysisKey *ID, IRUnitT &IR, const PreservedAnalyses &PA) { - return invalidateImpl<>(ID, IR, PA); - } - - private: - friend class AnalysisManager; - - template - bool invalidateImpl(AnalysisKey *ID, IRUnitT &IR, - const PreservedAnalyses &PA) { - // If we've already visited this pass, return true if it was invalidated - // and false otherwise. - auto IMapI = IsResultInvalidated.find(ID); - if (IMapI != IsResultInvalidated.end()) - return IMapI->second; - - // Otherwise look up the result object. - auto RI = Results.find({ID, &IR}); - assert(RI != Results.end() && - "Trying to invalidate a dependent result that isn't in the " - "manager's cache is always an error, likely due to a stale result " - "handle!"); - - auto &Result = static_cast(*RI->second->second); - - // Insert into the map whether the result should be invalidated and return - // that. Note that we cannot reuse IMapI and must do a fresh insert here, - // as calling invalidate could (recursively) insert things into the map, - // making any iterator or reference invalid. - bool Inserted; - std::tie(IMapI, Inserted) = - IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, *this)}); - (void)Inserted; - assert(Inserted && "Should not have already inserted this ID, likely " - "indicates a dependency cycle!"); - return IMapI->second; - } - - Invalidator(SmallDenseMap &IsResultInvalidated, - const AnalysisResultMapT &Results) - : IsResultInvalidated(IsResultInvalidated), Results(Results) {} - - SmallDenseMap &IsResultInvalidated; - const AnalysisResultMapT &Results; - }; - - /// Construct an empty analysis manager. - AnalysisManager(); - AnalysisManager(AnalysisManager &&); - AnalysisManager &operator=(AnalysisManager &&); - - /// Returns true if the analysis manager has an empty results cache. - bool empty() const { - assert(AnalysisResults.empty() == AnalysisResultLists.empty() && - "The storage and index of analysis results disagree on how many " - "there are!"); - return AnalysisResults.empty(); - } - - /// Clear any cached analysis results for a single unit of IR. - /// - /// This doesn't invalidate, but instead simply deletes, the relevant results. - /// It is useful when the IR is being removed and we want to clear out all the - /// memory pinned for it. - void clear(IRUnitT &IR, llvm::StringRef Name); - - /// Clear all analysis results cached by this AnalysisManager. - /// - /// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply - /// deletes them. This lets you clean up the AnalysisManager when the set of - /// IR units itself has potentially changed, and thus we can't even look up a - /// a result and invalidate/clear it directly. - void clear() { - AnalysisResults.clear(); - AnalysisResultLists.clear(); - } - - /// Get the result of an analysis pass for a given IR unit. - /// - /// Runs the analysis if a cached result is not available. - template - typename PassT::Result &getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) { - assert(AnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - ResultConceptT &ResultConcept = - getResultImpl(PassT::ID(), IR, ExtraArgs...); - - using ResultModelT = - detail::AnalysisResultModel; - - return static_cast(ResultConcept).Result; - } - - /// Get the cached result of an analysis pass for a given IR unit. - /// - /// This method never runs the analysis. - /// - /// \returns null if there is no cached result. - template - typename PassT::Result *getCachedResult(IRUnitT &IR) const { - assert(AnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - - ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(), IR); - if (!ResultConcept) - return nullptr; - - using ResultModelT = - detail::AnalysisResultModel; - - return &static_cast(ResultConcept)->Result; - } - - /// Verify that the given Result cannot be invalidated, assert otherwise. - template - void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const { - PreservedAnalyses PA = PreservedAnalyses::none(); - SmallDenseMap IsResultInvalidated; - Invalidator Inv(IsResultInvalidated, AnalysisResults); - assert(!Result->invalidate(IR, PA, Inv) && - "Cached result cannot be invalidated"); - } - - /// Register an analysis pass with the manager. - /// - /// The parameter is a callable whose result is an analysis pass. This allows - /// passing in a lambda to construct the analysis. - /// - /// The analysis type to register is the type returned by calling the \c - /// PassBuilder argument. If that type has already been registered, then the - /// argument will not be called and this function will return false. - /// Otherwise, we register the analysis returned by calling \c PassBuilder(), - /// and this function returns true. - /// - /// (Note: Although the return value of this function indicates whether or not - /// an analysis was previously registered, there intentionally isn't a way to - /// query this directly. Instead, you should just register all the analyses - /// you might want and let this class run them lazily. This idiom lets us - /// minimize the number of times we have to look up analyses in our - /// hashtable.) - template - bool registerPass(PassBuilderT &&PassBuilder) { - using PassT = decltype(PassBuilder()); - using PassModelT = - detail::AnalysisPassModel; - - auto &PassPtr = AnalysisPasses[PassT::ID()]; - if (PassPtr) - // Already registered this pass type! - return false; - - // Construct a new model around the instance returned by the builder. - PassPtr.reset(new PassModelT(PassBuilder())); - return true; - } - - /// Invalidate cached analyses for an IR unit. - /// - /// Walk through all of the analyses pertaining to this unit of IR and - /// invalidate them, unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT &IR, const PreservedAnalyses &PA); - -private: - /// Look up a registered analysis pass. - PassConceptT &lookUpPass(AnalysisKey *ID) { - typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID); - assert(PI != AnalysisPasses.end() && - "Analysis passes must be registered prior to being queried!"); - return *PI->second; - } - - /// Look up a registered analysis pass. - const PassConceptT &lookUpPass(AnalysisKey *ID) const { - typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID); - assert(PI != AnalysisPasses.end() && - "Analysis passes must be registered prior to being queried!"); - return *PI->second; - } - - /// Get an analysis result, running the pass if necessary. - ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR, - ExtraArgTs... ExtraArgs); - - /// Get a cached analysis result or return null. - ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR) const { - typename AnalysisResultMapT::const_iterator RI = - AnalysisResults.find({ID, &IR}); - return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; - } - - /// Map type from analysis pass ID to pass concept pointer. - using AnalysisPassMapT = - DenseMap>; - - /// Collection of analysis passes, indexed by ID. - AnalysisPassMapT AnalysisPasses; - - /// Map from IR unit to a list of analysis results. - /// - /// Provides linear time removal of all analysis results for a IR unit and - /// the ultimate storage for a particular cached analysis result. - AnalysisResultListMapT AnalysisResultLists; - - /// Map from an analysis ID and IR unit to a particular cached - /// analysis result. - AnalysisResultMapT AnalysisResults; -}; - -extern template class AnalysisManager; - -/// Convenience typedef for the Module analysis manager. -using ModuleAnalysisManager = AnalysisManager; - -extern template class AnalysisManager; - -/// Convenience typedef for the Function analysis manager. -using FunctionAnalysisManager = AnalysisManager; - -/// An analysis over an "outer" IR unit that provides access to an -/// analysis manager over an "inner" IR unit. The inner unit must be contained -/// in the outer unit. -/// -/// For example, InnerAnalysisManagerProxy is -/// an analysis over Modules (the "outer" unit) that provides access to a -/// Function analysis manager. The FunctionAnalysisManager is the "inner" -/// manager being proxied, and Functions are the "inner" unit. The inner/outer -/// relationship is valid because each Function is contained in one Module. -/// -/// If you're (transitively) within a pass manager for an IR unit U that -/// contains IR unit V, you should never use an analysis manager over V, except -/// via one of these proxies. -/// -/// Note that the proxy's result is a move-only RAII object. The validity of -/// the analyses in the inner analysis manager is tied to its lifetime. -template -class InnerAnalysisManagerProxy - : public AnalysisInfoMixin< - InnerAnalysisManagerProxy> { -public: - class Result { - public: - explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {} - - Result(Result &&Arg) : InnerAM(std::move(Arg.InnerAM)) { - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibility to clear the - // analysis state. - Arg.InnerAM = nullptr; - } - - ~Result() { - // InnerAM is cleared in a moved from state where there is nothing to do. - if (!InnerAM) - return; - - // Clear out the analysis manager if we're being destroyed -- it means we - // didn't even see an invalidate call when we got invalidated. - InnerAM->clear(); - } - - Result &operator=(Result &&RHS) { - InnerAM = RHS.InnerAM; - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibility to clear the - // analysis state. - RHS.InnerAM = nullptr; - return *this; - } - - /// Accessor for the analysis manager. - AnalysisManagerT &getManager() { return *InnerAM; } - - /// Handler for invalidation of the outer IR unit, \c IRUnitT. - /// - /// If the proxy analysis itself is not preserved, we assume that the set of - /// inner IR objects contained in IRUnit may have changed. In this case, - /// we have to call \c clear() on the inner analysis manager, as it may now - /// have stale pointers to its inner IR objects. - /// - /// Regardless of whether the proxy analysis is marked as preserved, all of - /// the analyses in the inner analysis manager are potentially invalidated - /// based on the set of preserved analyses. - bool invalidate( - IRUnitT &IR, const PreservedAnalyses &PA, - typename AnalysisManager::Invalidator &Inv); - - private: - AnalysisManagerT *InnerAM; - }; - - explicit InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM) - : InnerAM(&InnerAM) {} - - /// Run the analysis pass and create our proxy result object. - /// - /// This doesn't do any interesting work; it is primarily used to insert our - /// proxy result object into the outer analysis cache so that we can proxy - /// invalidation to the inner analysis manager. - Result run(IRUnitT &IR, AnalysisManager &AM, - ExtraArgTs...) { - return Result(*InnerAM); - } - -private: - friend AnalysisInfoMixin< - InnerAnalysisManagerProxy>; - - static AnalysisKey Key; - - AnalysisManagerT *InnerAM; -}; - -template -AnalysisKey - InnerAnalysisManagerProxy::Key; - -/// Provide the \c FunctionAnalysisManager to \c Module proxy. -using FunctionAnalysisManagerModuleProxy = - InnerAnalysisManagerProxy; - -/// Specialization of the invalidate method for the \c -/// FunctionAnalysisManagerModuleProxy's result. -template <> -bool FunctionAnalysisManagerModuleProxy::Result::invalidate( - Module &M, const PreservedAnalyses &PA, - ModuleAnalysisManager::Invalidator &Inv); - -// Ensure the \c FunctionAnalysisManagerModuleProxy is provided as an extern -// template. -extern template class InnerAnalysisManagerProxy; - -/// An analysis over an "inner" IR unit that provides access to an -/// analysis manager over a "outer" IR unit. The inner unit must be contained -/// in the outer unit. -/// -/// For example OuterAnalysisManagerProxy is an -/// analysis over Functions (the "inner" unit) which provides access to a Module -/// analysis manager. The ModuleAnalysisManager is the "outer" manager being -/// proxied, and Modules are the "outer" IR unit. The inner/outer relationship -/// is valid because each Function is contained in one Module. -/// -/// This proxy only exposes the const interface of the outer analysis manager, -/// to indicate that you cannot cause an outer analysis to run from within an -/// inner pass. Instead, you must rely on the \c getCachedResult API. This is -/// due to keeping potential future concurrency in mind. To give an example, -/// running a module analysis before any function passes may give a different -/// result than running it in a function pass. Both may be valid, but it would -/// produce non-deterministic results. GlobalsAA is a good analysis example, -/// because the cached information has the mod/ref info for all memory for each -/// function at the time the analysis was computed. The information is still -/// valid after a function transformation, but it may be *different* if -/// recomputed after that transform. GlobalsAA is never invalidated. - -/// -/// This proxy doesn't manage invalidation in any way -- that is handled by the -/// recursive return path of each layer of the pass manager. A consequence of -/// this is the outer analyses may be stale. We invalidate the outer analyses -/// only when we're done running passes over the inner IR units. -template -class OuterAnalysisManagerProxy - : public AnalysisInfoMixin< - OuterAnalysisManagerProxy> { -public: - /// Result proxy object for \c OuterAnalysisManagerProxy. - class Result { - public: - explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {} - - /// Get a cached analysis. If the analysis can be invalidated, this will - /// assert. - template - typename PassT::Result *getCachedResult(IRUnitTParam &IR) const { - typename PassT::Result *Res = - OuterAM->template getCachedResult(IR); - if (Res) - OuterAM->template verifyNotInvalidated(IR, Res); - return Res; - } - - /// Method provided for unit testing, not intended for general use. - template - bool cachedResultExists(IRUnitTParam &IR) const { - typename PassT::Result *Res = - OuterAM->template getCachedResult(IR); - return Res != nullptr; - } - - /// When invalidation occurs, remove any registered invalidation events. - bool invalidate( - IRUnitT &IRUnit, const PreservedAnalyses &PA, - typename AnalysisManager::Invalidator &Inv) { - // Loop over the set of registered outer invalidation mappings and if any - // of them map to an analysis that is now invalid, clear it out. - SmallVector DeadKeys; - for (auto &KeyValuePair : OuterAnalysisInvalidationMap) { - AnalysisKey *OuterID = KeyValuePair.first; - auto &InnerIDs = KeyValuePair.second; - llvm::erase_if(InnerIDs, [&](AnalysisKey *InnerID) { - return Inv.invalidate(InnerID, IRUnit, PA); - }); - if (InnerIDs.empty()) - DeadKeys.push_back(OuterID); - } - - for (auto OuterID : DeadKeys) - OuterAnalysisInvalidationMap.erase(OuterID); - - // The proxy itself remains valid regardless of anything else. - return false; - } - - /// Register a deferred invalidation event for when the outer analysis - /// manager processes its invalidations. - template - void registerOuterAnalysisInvalidation() { - AnalysisKey *OuterID = OuterAnalysisT::ID(); - AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID(); - - auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID]; - // Note, this is a linear scan. If we end up with large numbers of - // analyses that all trigger invalidation on the same outer analysis, - // this entire system should be changed to some other deterministic - // data structure such as a `SetVector` of a pair of pointers. - if (!llvm::is_contained(InvalidatedIDList, InvalidatedID)) - InvalidatedIDList.push_back(InvalidatedID); - } - - /// Access the map from outer analyses to deferred invalidation requiring - /// analyses. - const SmallDenseMap, 2> & - getOuterInvalidations() const { - return OuterAnalysisInvalidationMap; - } - - private: - const AnalysisManagerT *OuterAM; - - /// A map from an outer analysis ID to the set of this IR-unit's analyses - /// which need to be invalidated. - SmallDenseMap, 2> - OuterAnalysisInvalidationMap; - }; - - OuterAnalysisManagerProxy(const AnalysisManagerT &OuterAM) - : OuterAM(&OuterAM) {} - - /// Run the analysis pass and create our proxy result object. - /// Nothing to see here, it just forwards the \c OuterAM reference into the - /// result. - Result run(IRUnitT &, AnalysisManager &, - ExtraArgTs...) { - return Result(*OuterAM); - } - -private: - friend AnalysisInfoMixin< - OuterAnalysisManagerProxy>; - - static AnalysisKey Key; - - const AnalysisManagerT *OuterAM; -}; - -template -AnalysisKey - OuterAnalysisManagerProxy::Key; - -extern template class OuterAnalysisManagerProxy; -/// Provide the \c ModuleAnalysisManager to \c Function proxy. -using ModuleAnalysisManagerFunctionProxy = - OuterAnalysisManagerProxy; - -/// Trivial adaptor that maps from a module to its functions. -/// -/// Designed to allow composition of a FunctionPass(Manager) and -/// a ModulePassManager, by running the FunctionPass(Manager) over every -/// function in the module. -/// -/// Function passes run within this adaptor can rely on having exclusive access -/// to the function they are run over. They should not read or modify any other -/// functions! Other threads or systems may be manipulating other functions in -/// the module, and so their state should never be relied on. -/// FIXME: Make the above true for all of LLVM's actual passes, some still -/// violate this principle. -/// -/// Function passes can also read the module containing the function, but they -/// should not modify that module outside of the use lists of various globals. -/// For example, a function pass is not permitted to add functions to the -/// module. -/// FIXME: Make the above true for all of LLVM's actual passes, some still -/// violate this principle. -/// -/// Note that although function passes can access module analyses, module -/// analyses are not invalidated while the function passes are running, so they -/// may be stale. Function analyses will not be stale. -class ModuleToFunctionPassAdaptor - : public PassInfoMixin { -public: - using PassConceptT = detail::PassConcept; - - explicit ModuleToFunctionPassAdaptor(std::unique_ptr Pass, - bool EagerlyInvalidate) - : Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {} - - /// Runs the function pass across every function in the module. - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName); - - static bool isRequired() { return true; } - -private: - std::unique_ptr Pass; - bool EagerlyInvalidate; -}; - -/// A function to deduce a function pass type and wrap it in the -/// templated adaptor. -template -ModuleToFunctionPassAdaptor -createModuleToFunctionPassAdaptor(FunctionPassT &&Pass, - bool EagerlyInvalidate = false) { - using PassModelT = - detail::PassModel; - // Do not use make_unique, it causes too many template instantiations, - // causing terrible compile times. - return ModuleToFunctionPassAdaptor( - std::unique_ptr( - new PassModelT(std::forward(Pass))), - EagerlyInvalidate); -} - -/// A utility pass template to force an analysis result to be available. -/// -/// If there are extra arguments at the pass's run level there may also be -/// extra arguments to the analysis manager's \c getResult routine. We can't -/// guess how to effectively map the arguments from one to the other, and so -/// this specialization just ignores them. -/// -/// Specific patterns of run-method extra arguments and analysis manager extra -/// arguments will have to be defined as appropriate specializations. -template , - typename... ExtraArgTs> -struct RequireAnalysisPass - : PassInfoMixin> { - /// Run this pass over some unit of IR. - /// - /// This pass can be run over any unit of IR and use any analysis manager - /// provided they satisfy the basic API requirements. When this pass is - /// created, these methods can be instantiated to satisfy whatever the - /// context requires. - PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, - ExtraArgTs &&... Args) { - (void)AM.template getResult(Arg, - std::forward(Args)...); - - return PreservedAnalyses::all(); - } - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) { - auto ClassName = AnalysisT::name(); - auto PassName = MapClassName2PassName(ClassName); - OS << "require<" << PassName << ">"; - } - static bool isRequired() { return true; } -}; - -/// A no-op pass template which simply forces a specific analysis result -/// to be invalidated. -template -struct InvalidateAnalysisPass - : PassInfoMixin> { - /// Run this pass over some unit of IR. - /// - /// This pass can be run over any unit of IR and use any analysis manager, - /// provided they satisfy the basic API requirements. When this pass is - /// created, these methods can be instantiated to satisfy whatever the - /// context requires. - template - PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...) { - auto PA = PreservedAnalyses::all(); - PA.abandon(); - return PA; - } - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) { - auto ClassName = AnalysisT::name(); - auto PassName = MapClassName2PassName(ClassName); - OS << "invalidate<" << PassName << ">"; - } -}; - -/// A utility pass that does nothing, but preserves no analyses. -/// -/// Because this preserves no analyses, any analysis passes queried after this -/// pass runs will recompute fresh results. -struct InvalidateAllAnalysesPass : PassInfoMixin { - /// Run this pass over some unit of IR. - template - PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) { - return PreservedAnalyses::none(); - } -}; - -/// A utility pass template that simply runs another pass multiple times. -/// -/// This can be useful when debugging or testing passes. It also serves as an -/// example of how to extend the pass manager in ways beyond composition. -template -class RepeatedPass : public PassInfoMixin> { -public: - RepeatedPass(int Count, PassT &&P) - : Count(Count), P(std::forward(P)) {} - - template - PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, Ts &&... Args) { - - // Request PassInstrumentation from analysis manager, will use it to run - // instrumenting callbacks for the passes later. - // Here we use std::tuple wrapper over getResult which helps to extract - // AnalysisManager's arguments out of the whole Args set. - PassInstrumentation PI = - detail::getAnalysisResult( - AM, IR, std::tuple(Args...)); - - auto PA = PreservedAnalyses::all(); - for (int i = 0; i < Count; ++i) { - // Check the PassInstrumentation's BeforePass callbacks before running the - // pass, skip its execution completely if asked to (callback returns - // false). - if (!PI.runBeforePass(P, IR)) - continue; - PreservedAnalyses IterPA = P.run(IR, AM, std::forward(Args)...); - PA.intersect(IterPA); - PI.runAfterPass(P, IR, IterPA); - } - return PA; - } - - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) { - OS << "repeat<" << Count << ">("; - P.printPipeline(OS, MapClassName2PassName); - OS << ")"; - } - -private: - int Count; - PassT P; -}; - -template -RepeatedPass createRepeatedPass(int Count, PassT &&P) { - return RepeatedPass(Count, std::forward(P)); -} - -} // end namespace llvm - -#endif // LLVM_IR_PASSMANAGER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PassManagerImpl.h b/suite/synctools/tablegen/include/llvm/IR/PassManagerImpl.h deleted file mode 100644 index 3c94cf2811..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PassManagerImpl.h +++ /dev/null @@ -1,147 +0,0 @@ -//===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// Provides implementations for PassManager and AnalysisManager template -/// methods. These classes should be explicitly instantiated for any IR unit, -/// and files doing the explicit instantiation should include this header. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PASSMANAGERIMPL_H -#define LLVM_IR_PASSMANAGERIMPL_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -template -inline AnalysisManager::AnalysisManager() = default; - -template -inline AnalysisManager::AnalysisManager( - AnalysisManager &&) = default; - -template -inline AnalysisManager & -AnalysisManager::operator=(AnalysisManager &&) = - default; - -template -inline void -AnalysisManager::clear(IRUnitT &IR, - llvm::StringRef Name) { - if (auto *PI = getCachedResult(IR)) - PI->runAnalysesCleared(Name); - - auto ResultsListI = AnalysisResultLists.find(&IR); - if (ResultsListI == AnalysisResultLists.end()) - return; - // Delete the map entries that point into the results list. - for (auto &IDAndResult : ResultsListI->second) - AnalysisResults.erase({IDAndResult.first, &IR}); - - // And actually destroy and erase the results associated with this IR. - AnalysisResultLists.erase(ResultsListI); -} - -template -inline typename AnalysisManager::ResultConceptT & -AnalysisManager::getResultImpl( - AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) { - typename AnalysisResultMapT::iterator RI; - bool Inserted; - std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( - std::make_pair(ID, &IR), typename AnalysisResultListT::iterator())); - - // If we don't have a cached result for this function, look up the pass and - // run it to produce a result, which we then add to the cache. - if (Inserted) { - auto &P = this->lookUpPass(ID); - - PassInstrumentation PI; - if (ID != PassInstrumentationAnalysis::ID()) { - PI = getResult(IR, ExtraArgs...); - PI.runBeforeAnalysis(P, IR); - } - - AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; - ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); - - PI.runAfterAnalysis(P, IR); - - // P.run may have inserted elements into AnalysisResults and invalidated - // RI. - RI = AnalysisResults.find({ID, &IR}); - assert(RI != AnalysisResults.end() && "we just inserted it!"); - - RI->second = std::prev(ResultList.end()); - } - - return *RI->second->second; -} - -template -inline void AnalysisManager::invalidate( - IRUnitT &IR, const PreservedAnalyses &PA) { - // We're done if all analyses on this IR unit are preserved. - if (PA.allAnalysesInSetPreserved>()) - return; - - // Track whether each analysis's result is invalidated in - // IsResultInvalidated. - SmallDenseMap IsResultInvalidated; - Invalidator Inv(IsResultInvalidated, AnalysisResults); - AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; - for (auto &AnalysisResultPair : ResultsList) { - // This is basically the same thing as Invalidator::invalidate, but we - // can't call it here because we're operating on the type-erased result. - // Moreover if we instead called invalidate() directly, it would do an - // unnecessary look up in ResultsList. - AnalysisKey *ID = AnalysisResultPair.first; - auto &Result = *AnalysisResultPair.second; - - auto IMapI = IsResultInvalidated.find(ID); - if (IMapI != IsResultInvalidated.end()) - // This result was already handled via the Invalidator. - continue; - - // Try to invalidate the result, giving it the Invalidator so it can - // recursively query for any dependencies it has and record the result. - // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as - // Result.invalidate may insert things into the map, invalidating our - // iterator. - bool Inserted = - IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second; - (void)Inserted; - assert(Inserted && "Should never have already inserted this ID, likely " - "indicates a cycle!"); - } - - // Now erase the results that were marked above as invalidated. - if (!IsResultInvalidated.empty()) { - for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) { - AnalysisKey *ID = I->first; - if (!IsResultInvalidated.lookup(ID)) { - ++I; - continue; - } - - if (auto *PI = getCachedResult(IR)) - PI->runAnalysisInvalidated(this->lookUpPass(ID), IR); - - I = ResultsList.erase(I); - AnalysisResults.erase({ID, &IR}); - } - } - - if (ResultsList.empty()) - AnalysisResultLists.erase(&IR); -} -} // end namespace llvm - -#endif // LLVM_IR_PASSMANAGERIMPL_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PassManagerInternal.h b/suite/synctools/tablegen/include/llvm/IR/PassManagerInternal.h deleted file mode 100644 index e2b1fea407..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PassManagerInternal.h +++ /dev/null @@ -1,339 +0,0 @@ -//===- PassManager internal APIs and implementation details -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This header provides internal APIs and implementation details used by the -/// pass management interfaces exposed in PassManager.h. To understand more -/// context of why these particular interfaces are needed, see that header -/// file. None of these APIs should be used elsewhere. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PASSMANAGERINTERNAL_H -#define LLVM_IR_PASSMANAGERINTERNAL_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include -#include - -namespace llvm { - -template class AllAnalysesOn; -template class AnalysisManager; -class PreservedAnalyses; - -// Implementation details of the pass manager interfaces. -namespace detail { - -/// Template for the abstract base class used to dispatch -/// polymorphically over pass objects. -template -struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() = default; - - /// The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) = 0; - - virtual void - printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName) = 0; - /// Polymorphic method to access the name of a pass. - virtual StringRef name() const = 0; - - /// Polymorphic method to let a pass optionally exempted from skipping by - /// PassInstrumentation. - /// To opt-in, pass should implement `static bool isRequired()`. It's no-op - /// to have `isRequired` always return false since that is the default. - virtual bool isRequired() const = 0; -}; - -/// A template wrapper used to implement the polymorphic API. -/// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT& and an \c AnalysisManager&. It requires the pass to -/// be a copyable object. -template -struct PassModel : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) override { - return Pass.run(IR, AM, ExtraArgs...); - } - - void printPipeline( - raw_ostream &OS, - function_ref MapClassName2PassName) override { - Pass.printPipeline(OS, MapClassName2PassName); - } - - StringRef name() const override { return PassT::name(); } - - template - using has_required_t = decltype(std::declval().isRequired()); - - template - static std::enable_if_t::value, bool> - passIsRequiredImpl() { - return T::isRequired(); - } - template - static std::enable_if_t::value, bool> - passIsRequiredImpl() { - return false; - } - - bool isRequired() const override { return passIsRequiredImpl(); } - - PassT Pass; -}; - -/// Abstract concept of an analysis result. -/// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template -struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() = default; - - /// Method to try to mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// \p PA is a set of preserved analyses which can be used to avoid - /// invalidation because the pass which changed the underlying IR took care - /// to update or preserve the analysis result in some way. - /// - /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be - /// used by a particular analysis result to discover if other analyses - /// results are also invalidated in the event that this result depends on - /// them. See the documentation in the \c AnalysisManager for more details. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, - InvalidatorT &Inv) = 0; -}; - -/// SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template class ResultHasInvalidateMethod { - using EnabledType = char; - struct DisabledType { - char a, b; - }; - - // Purely to help out MSVC which fails to disable the below specialization, - // explicitly enable using the result type's invalidate routine if we can - // successfully call that routine. - template struct Nonce { using Type = EnabledType; }; - template - static typename Nonce().invalidate( - std::declval(), std::declval()))>::Type - check(rank<2>); - - // First we define an overload that can only be taken if there is no - // invalidate member. We do this by taking the address of an invalidate - // member in an adjacent base class of a derived class. This would be - // ambiguous if there were an invalidate member in the result type. - template static DisabledType NonceFunction(T U::*); - struct CheckerBase { int invalidate; }; - template struct Checker : CheckerBase, T {}; - template - static decltype(NonceFunction(&Checker::invalidate)) check(rank<1>); - - // Now we have the fallback that will only be reached when there is an - // invalidate member, and enables the trait. - template - static EnabledType check(rank<0>); - -public: - enum { Value = sizeof(check(rank<2>())) == sizeof(EnabledType) }; -}; - -/// Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template ::Value> -struct AnalysisResultModel; - -/// Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT &, const PreservedAnalysesT &PA, - InvalidatorT &) override { - auto PAC = PA.template getChecker(); - return !PAC.preserved() && - !PAC.template preservedSet>(); - } - - ResultT Result; -}; - -/// Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// The model delegates to the \c ResultT method. - bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, - InvalidatorT &Inv) override { - return Result.invalidate(IR, PA, Inv); - } - - ResultT Result; -}; - -/// Abstract concept of an analysis pass. -/// -/// This concept is parameterized over the IR unit that it can run over and -/// produce an analysis result. -template -struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() = default; - - /// Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr< - AnalysisResultConcept> - run(IRUnitT &IR, AnalysisManager &AM, - ExtraArgTs... ExtraArgs) = 0; - - /// Polymorphic method to access the name of a pass. - virtual StringRef name() const = 0; -}; - -/// Wrapper to model the analysis pass concept. -/// -/// Can wrap any type which implements a suitable \c run method. The method -/// must accept an \c IRUnitT& and an \c AnalysisManager& as arguments -/// and produce an object which can be wrapped in a \c AnalysisResultModel. -template -struct AnalysisPassModel : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - using ResultModelT = - AnalysisResultModel; - - /// The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr< - AnalysisResultConcept> - run(IRUnitT &IR, AnalysisManager &AM, - ExtraArgTs... ExtraArgs) override { - return std::make_unique( - Pass.run(IR, AM, std::forward(ExtraArgs)...)); - } - - /// The model delegates to a static \c PassT::name method. - /// - /// The returned string ref must point to constant immutable data! - StringRef name() const override { return PassT::name(); } - - PassT Pass; -}; - -} // end namespace detail - -} // end namespace llvm - -#endif // LLVM_IR_PASSMANAGERINTERNAL_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PassTimingInfo.h b/suite/synctools/tablegen/include/llvm/IR/PassTimingInfo.h deleted file mode 100644 index 49a83605c4..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PassTimingInfo.h +++ /dev/null @@ -1,104 +0,0 @@ -//===- PassTimingInfo.h - pass execution timing -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This header defines classes/functions to handle pass execution timing -/// information with interfaces for both pass managers. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PASSTIMINGINFO_H -#define LLVM_IR_PASSTIMINGINFO_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Timer.h" -#include -#include - -namespace llvm { - -class Pass; -class PassInstrumentationCallbacks; -class raw_ostream; - -/// If -time-passes has been specified, report the timings immediately and then -/// reset the timers to zero. By default it uses the stream created by -/// CreateInfoOutputFile(). -void reportAndResetTimings(raw_ostream *OutStream = nullptr); - -/// Request the timer for this legacy-pass-manager's pass instance. -Timer *getPassTimer(Pass *); - -/// This class implements -time-passes functionality for new pass manager. -/// It provides the pass-instrumentation callbacks that measure the pass -/// execution time. They collect timing info into individual timers as -/// passes are being run. At the end of its life-time it prints the resulting -/// timing report. -class TimePassesHandler { - /// Value of this type is capable of uniquely identifying pass invocations. - /// It is a pair of string Pass-Identifier (which for now is common - /// to all the instance of a given pass) + sequential invocation counter. - using PassInvocationID = std::pair; - - /// A group of all pass-timing timers. - TimerGroup TG; - - using TimerVector = llvm::SmallVector, 4>; - /// Map of timers for pass invocations - StringMap TimingData; - - /// Stack of currently active timers. - SmallVector TimerStack; - - /// Custom output stream to print timing information into. - /// By default (== nullptr) we emit time report into the stream created by - /// CreateInfoOutputFile(). - raw_ostream *OutStream = nullptr; - - bool Enabled; - bool PerRun; - -public: - TimePassesHandler(); - TimePassesHandler(bool Enabled, bool PerRun = false); - - /// Destructor handles the print action if it has not been handled before. - ~TimePassesHandler() { print(); } - - /// Prints out timing information and then resets the timers. - void print(); - - // We intend this to be unique per-compilation, thus no copies. - TimePassesHandler(const TimePassesHandler &) = delete; - void operator=(const TimePassesHandler &) = delete; - - void registerCallbacks(PassInstrumentationCallbacks &PIC); - - /// Set a custom output stream for subsequent reporting. - void setOutStream(raw_ostream &OutStream); - -private: - /// Dumps information for running/triggered timers, useful for debugging - LLVM_DUMP_METHOD void dump() const; - - /// Returns the new timer for each new run of the pass. - Timer &getPassTimer(StringRef PassID); - - void startTimer(StringRef PassID); - void stopTimer(StringRef PassID); - - // Implementation of pass instrumentation callbacks. - void runBeforePass(StringRef PassID); - void runAfterPass(StringRef PassID); -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/PatternMatch.h b/suite/synctools/tablegen/include/llvm/IR/PatternMatch.h deleted file mode 100644 index f9f4f16038..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PatternMatch.h +++ /dev/null @@ -1,2571 +0,0 @@ -//===- PatternMatch.h - Match on the LLVM IR --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides a simple and efficient mechanism for performing general -// tree-based pattern matches on the LLVM IR. The power of these routines is -// that it allows you to write concise patterns that are expressive and easy to -// understand. The other major advantage of this is that it allows you to -// trivially capture/bind elements in the pattern to variables. For example, -// you can do something like this: -// -// Value *Exp = ... -// Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) -// if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), -// m_And(m_Value(Y), m_ConstantInt(C2))))) { -// ... Pattern is matched and variables are bound ... -// } -// -// This is primarily useful to things like the instruction combiner, but can -// also be useful for static analysis tools or code generators. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PATTERNMATCH_H -#define LLVM_IR_PATTERNMATCH_H - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include - -namespace llvm { -namespace PatternMatch { - -template bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); -} - -template bool match(ArrayRef Mask, const Pattern &P) { - return const_cast(P).match(Mask); -} - -template struct OneUse_match { - SubPattern_t SubPattern; - - OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - - template bool match(OpTy *V) { - return V->hasOneUse() && SubPattern.match(V); - } -}; - -template inline OneUse_match m_OneUse(const T &SubPattern) { - return SubPattern; -} - -template struct class_match { - template bool match(ITy *V) { return isa(V); } -}; - -/// Match an arbitrary value and ignore it. -inline class_match m_Value() { return class_match(); } - -/// Match an arbitrary unary operation and ignore it. -inline class_match m_UnOp() { - return class_match(); -} - -/// Match an arbitrary binary operation and ignore it. -inline class_match m_BinOp() { - return class_match(); -} - -/// Matches any compare instruction and ignore it. -inline class_match m_Cmp() { return class_match(); } - -struct undef_match { - static bool check(const Value *V) { - if (isa(V)) - return true; - - const auto *CA = dyn_cast(V); - if (!CA) - return false; - - SmallPtrSet Seen; - SmallVector Worklist; - - // Either UndefValue, PoisonValue, or an aggregate that only contains - // these is accepted by matcher. - // CheckValue returns false if CA cannot satisfy this constraint. - auto CheckValue = [&](const ConstantAggregate *CA) { - for (const Value *Op : CA->operand_values()) { - if (isa(Op)) - continue; - - const auto *CA = dyn_cast(Op); - if (!CA) - return false; - if (Seen.insert(CA).second) - Worklist.emplace_back(CA); - } - - return true; - }; - - if (!CheckValue(CA)) - return false; - - while (!Worklist.empty()) { - if (!CheckValue(Worklist.pop_back_val())) - return false; - } - return true; - } - template bool match(ITy *V) { return check(V); } -}; - -/// Match an arbitrary undef constant. This matches poison as well. -/// If this is an aggregate and contains a non-aggregate element that is -/// neither undef nor poison, the aggregate is not matched. -inline auto m_Undef() { return undef_match(); } - -/// Match an arbitrary poison constant. -inline class_match m_Poison() { return class_match(); } - -/// Match an arbitrary Constant and ignore it. -inline class_match m_Constant() { return class_match(); } - -/// Match an arbitrary ConstantInt and ignore it. -inline class_match m_ConstantInt() { - return class_match(); -} - -/// Match an arbitrary ConstantFP and ignore it. -inline class_match m_ConstantFP() { - return class_match(); -} - -/// Match an arbitrary ConstantExpr and ignore it. -inline class_match m_ConstantExpr() { - return class_match(); -} - -/// Match an arbitrary basic block value and ignore it. -inline class_match m_BasicBlock() { - return class_match(); -} - -/// Inverting matcher -template struct match_unless { - Ty M; - - match_unless(const Ty &Matcher) : M(Matcher) {} - - template bool match(ITy *V) { return !M.match(V); } -}; - -/// Match if the inner matcher does *NOT* match. -template inline match_unless m_Unless(const Ty &M) { - return match_unless(M); -} - -/// Matching combinators -template struct match_combine_or { - LTy L; - RTy R; - - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - - template bool match(ITy *V) { - if (L.match(V)) - return true; - if (R.match(V)) - return true; - return false; - } -}; - -template struct match_combine_and { - LTy L; - RTy R; - - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - - template bool match(ITy *V) { - if (L.match(V)) - if (R.match(V)) - return true; - return false; - } -}; - -/// Combine two pattern matchers matching L || R -template -inline match_combine_or m_CombineOr(const LTy &L, const RTy &R) { - return match_combine_or(L, R); -} - -/// Combine two pattern matchers matching L && R -template -inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { - return match_combine_and(L, R); -} - -struct apint_match { - const APInt *&Res; - bool AllowUndef; - - apint_match(const APInt *&Res, bool AllowUndef) - : Res(Res), AllowUndef(AllowUndef) {} - - template bool match(ITy *V) { - if (auto *CI = dyn_cast(V)) { - Res = &CI->getValue(); - return true; - } - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - if (auto *CI = dyn_cast_or_null( - C->getSplatValue(AllowUndef))) { - Res = &CI->getValue(); - return true; - } - return false; - } -}; -// Either constexpr if or renaming ConstantFP::getValueAPF to -// ConstantFP::getValue is needed to do it via single template -// function for both apint/apfloat. -struct apfloat_match { - const APFloat *&Res; - bool AllowUndef; - - apfloat_match(const APFloat *&Res, bool AllowUndef) - : Res(Res), AllowUndef(AllowUndef) {} - - template bool match(ITy *V) { - if (auto *CI = dyn_cast(V)) { - Res = &CI->getValueAPF(); - return true; - } - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - if (auto *CI = dyn_cast_or_null( - C->getSplatValue(AllowUndef))) { - Res = &CI->getValueAPF(); - return true; - } - return false; - } -}; - -/// Match a ConstantInt or splatted ConstantVector, binding the -/// specified pointer to the contained APInt. -inline apint_match m_APInt(const APInt *&Res) { - // Forbid undefs by default to maintain previous behavior. - return apint_match(Res, /* AllowUndef */ false); -} - -/// Match APInt while allowing undefs in splat vector constants. -inline apint_match m_APIntAllowUndef(const APInt *&Res) { - return apint_match(Res, /* AllowUndef */ true); -} - -/// Match APInt while forbidding undefs in splat vector constants. -inline apint_match m_APIntForbidUndef(const APInt *&Res) { - return apint_match(Res, /* AllowUndef */ false); -} - -/// Match a ConstantFP or splatted ConstantVector, binding the -/// specified pointer to the contained APFloat. -inline apfloat_match m_APFloat(const APFloat *&Res) { - // Forbid undefs by default to maintain previous behavior. - return apfloat_match(Res, /* AllowUndef */ false); -} - -/// Match APFloat while allowing undefs in splat vector constants. -inline apfloat_match m_APFloatAllowUndef(const APFloat *&Res) { - return apfloat_match(Res, /* AllowUndef */ true); -} - -/// Match APFloat while forbidding undefs in splat vector constants. -inline apfloat_match m_APFloatForbidUndef(const APFloat *&Res) { - return apfloat_match(Res, /* AllowUndef */ false); -} - -template struct constantint_match { - template bool match(ITy *V) { - if (const auto *CI = dyn_cast(V)) { - const APInt &CIV = CI->getValue(); - if (Val >= 0) - return CIV == static_cast(Val); - // If Val is negative, and CI is shorter than it, truncate to the right - // number of bits. If it is larger, then we have to sign extend. Just - // compare their negated values. - return -CIV == -Val; - } - return false; - } -}; - -/// Match a ConstantInt with a specific value. -template inline constantint_match m_ConstantInt() { - return constantint_match(); -} - -/// This helper class is used to match constant scalars, vector splats, -/// and fixed width vectors that satisfy a specified predicate. -/// For fixed width vector constants, undefined elements are ignored. -template -struct cstval_pred_ty : public Predicate { - template bool match(ITy *V) { - if (const auto *CV = dyn_cast(V)) - return this->isValue(CV->getValue()); - if (const auto *VTy = dyn_cast(V->getType())) { - if (const auto *C = dyn_cast(V)) { - if (const auto *CV = dyn_cast_or_null(C->getSplatValue())) - return this->isValue(CV->getValue()); - - // Number of elements of a scalable vector unknown at compile time - auto *FVTy = dyn_cast(VTy); - if (!FVTy) - return false; - - // Non-splat vector constant: check each element for a match. - unsigned NumElts = FVTy->getNumElements(); - assert(NumElts != 0 && "Constant vector with no elements?"); - bool HasNonUndefElements = false; - for (unsigned i = 0; i != NumElts; ++i) { - Constant *Elt = C->getAggregateElement(i); - if (!Elt) - return false; - if (isa(Elt)) - continue; - auto *CV = dyn_cast(Elt); - if (!CV || !this->isValue(CV->getValue())) - return false; - HasNonUndefElements = true; - } - return HasNonUndefElements; - } - } - return false; - } -}; - -/// specialization of cstval_pred_ty for ConstantInt -template -using cst_pred_ty = cstval_pred_ty; - -/// specialization of cstval_pred_ty for ConstantFP -template -using cstfp_pred_ty = cstval_pred_ty; - -/// This helper class is used to match scalar and vector constants that -/// satisfy a specified predicate, and bind them to an APInt. -template struct api_pred_ty : public Predicate { - const APInt *&Res; - - api_pred_ty(const APInt *&R) : Res(R) {} - - template bool match(ITy *V) { - if (const auto *CI = dyn_cast(V)) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - if (auto *CI = dyn_cast_or_null(C->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - - return false; - } -}; - -/// This helper class is used to match scalar and vector constants that -/// satisfy a specified predicate, and bind them to an APFloat. -/// Undefs are allowed in splat vector constants. -template struct apf_pred_ty : public Predicate { - const APFloat *&Res; - - apf_pred_ty(const APFloat *&R) : Res(R) {} - - template bool match(ITy *V) { - if (const auto *CI = dyn_cast(V)) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - if (auto *CI = dyn_cast_or_null( - C->getSplatValue(/* AllowUndef */ true))) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - - return false; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// Encapsulate constant value queries for use in templated predicate matchers. -// This allows checking if constants match using compound predicates and works -// with vector constants, possibly with relaxed constraints. For example, ignore -// undef values. -// -/////////////////////////////////////////////////////////////////////////////// - -struct is_any_apint { - bool isValue(const APInt &C) { return true; } -}; -/// Match an integer or vector with any integral constant. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_AnyIntegralConstant() { - return cst_pred_ty(); -} - -struct is_all_ones { - bool isValue(const APInt &C) { return C.isAllOnes(); } -}; -/// Match an integer or vector with all bits set. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_AllOnes() { - return cst_pred_ty(); -} - -struct is_maxsignedvalue { - bool isValue(const APInt &C) { return C.isMaxSignedValue(); } -}; -/// Match an integer or vector with values having all bits except for the high -/// bit set (0x7f...). -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_MaxSignedValue() { - return cst_pred_ty(); -} -inline api_pred_ty m_MaxSignedValue(const APInt *&V) { - return V; -} - -struct is_negative { - bool isValue(const APInt &C) { return C.isNegative(); } -}; -/// Match an integer or vector of negative values. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_Negative() { - return cst_pred_ty(); -} -inline api_pred_ty m_Negative(const APInt *&V) { - return V; -} - -struct is_nonnegative { - bool isValue(const APInt &C) { return C.isNonNegative(); } -}; -/// Match an integer or vector of non-negative values. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_NonNegative() { - return cst_pred_ty(); -} -inline api_pred_ty m_NonNegative(const APInt *&V) { - return V; -} - -struct is_strictlypositive { - bool isValue(const APInt &C) { return C.isStrictlyPositive(); } -}; -/// Match an integer or vector of strictly positive values. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_StrictlyPositive() { - return cst_pred_ty(); -} -inline api_pred_ty m_StrictlyPositive(const APInt *&V) { - return V; -} - -struct is_nonpositive { - bool isValue(const APInt &C) { return C.isNonPositive(); } -}; -/// Match an integer or vector of non-positive values. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_NonPositive() { - return cst_pred_ty(); -} -inline api_pred_ty m_NonPositive(const APInt *&V) { return V; } - -struct is_one { - bool isValue(const APInt &C) { return C.isOne(); } -}; -/// Match an integer 1 or a vector with all elements equal to 1. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_One() { - return cst_pred_ty(); -} - -struct is_zero_int { - bool isValue(const APInt &C) { return C.isZero(); } -}; -/// Match an integer 0 or a vector with all elements equal to 0. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_ZeroInt() { - return cst_pred_ty(); -} - -struct is_zero { - template bool match(ITy *V) { - auto *C = dyn_cast(V); - // FIXME: this should be able to do something for scalable vectors - return C && (C->isNullValue() || cst_pred_ty().match(C)); - } -}; -/// Match any null constant or a vector with all elements equal to 0. -/// For vectors, this includes constants with undefined elements. -inline is_zero m_Zero() { - return is_zero(); -} - -struct is_power2 { - bool isValue(const APInt &C) { return C.isPowerOf2(); } -}; -/// Match an integer or vector power-of-2. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_Power2() { - return cst_pred_ty(); -} -inline api_pred_ty m_Power2(const APInt *&V) { - return V; -} - -struct is_negated_power2 { - bool isValue(const APInt &C) { return C.isNegatedPowerOf2(); } -}; -/// Match a integer or vector negated power-of-2. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_NegatedPower2() { - return cst_pred_ty(); -} -inline api_pred_ty m_NegatedPower2(const APInt *&V) { - return V; -} - -struct is_power2_or_zero { - bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } -}; -/// Match an integer or vector of 0 or power-of-2 values. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_Power2OrZero() { - return cst_pred_ty(); -} -inline api_pred_ty m_Power2OrZero(const APInt *&V) { - return V; -} - -struct is_sign_mask { - bool isValue(const APInt &C) { return C.isSignMask(); } -}; -/// Match an integer or vector with only the sign bit(s) set. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_SignMask() { - return cst_pred_ty(); -} - -struct is_lowbit_mask { - bool isValue(const APInt &C) { return C.isMask(); } -}; -/// Match an integer or vector with only the low bit(s) set. -/// For vectors, this includes constants with undefined elements. -inline cst_pred_ty m_LowBitMask() { - return cst_pred_ty(); -} -inline api_pred_ty m_LowBitMask(const APInt *&V) { - return V; -} - -struct icmp_pred_with_threshold { - ICmpInst::Predicate Pred; - const APInt *Thr; - bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); } -}; -/// Match an integer or vector with every element comparing 'pred' (eg/ne/...) -/// to Threshold. For vectors, this includes constants with undefined elements. -inline cst_pred_ty -m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) { - cst_pred_ty P; - P.Pred = Predicate; - P.Thr = &Threshold; - return P; -} - -struct is_nan { - bool isValue(const APFloat &C) { return C.isNaN(); } -}; -/// Match an arbitrary NaN constant. This includes quiet and signalling nans. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_NaN() { - return cstfp_pred_ty(); -} - -struct is_nonnan { - bool isValue(const APFloat &C) { return !C.isNaN(); } -}; -/// Match a non-NaN FP constant. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_NonNaN() { - return cstfp_pred_ty(); -} - -struct is_inf { - bool isValue(const APFloat &C) { return C.isInfinity(); } -}; -/// Match a positive or negative infinity FP constant. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_Inf() { - return cstfp_pred_ty(); -} - -struct is_noninf { - bool isValue(const APFloat &C) { return !C.isInfinity(); } -}; -/// Match a non-infinity FP constant, i.e. finite or NaN. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_NonInf() { - return cstfp_pred_ty(); -} - -struct is_finite { - bool isValue(const APFloat &C) { return C.isFinite(); } -}; -/// Match a finite FP constant, i.e. not infinity or NaN. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_Finite() { - return cstfp_pred_ty(); -} -inline apf_pred_ty m_Finite(const APFloat *&V) { return V; } - -struct is_finitenonzero { - bool isValue(const APFloat &C) { return C.isFiniteNonZero(); } -}; -/// Match a finite non-zero FP constant. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_FiniteNonZero() { - return cstfp_pred_ty(); -} -inline apf_pred_ty m_FiniteNonZero(const APFloat *&V) { - return V; -} - -struct is_any_zero_fp { - bool isValue(const APFloat &C) { return C.isZero(); } -}; -/// Match a floating-point negative zero or positive zero. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_AnyZeroFP() { - return cstfp_pred_ty(); -} - -struct is_pos_zero_fp { - bool isValue(const APFloat &C) { return C.isPosZero(); } -}; -/// Match a floating-point positive zero. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_PosZeroFP() { - return cstfp_pred_ty(); -} - -struct is_neg_zero_fp { - bool isValue(const APFloat &C) { return C.isNegZero(); } -}; -/// Match a floating-point negative zero. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_NegZeroFP() { - return cstfp_pred_ty(); -} - -struct is_non_zero_fp { - bool isValue(const APFloat &C) { return C.isNonZero(); } -}; -/// Match a floating-point non-zero. -/// For vectors, this includes constants with undefined elements. -inline cstfp_pred_ty m_NonZeroFP() { - return cstfp_pred_ty(); -} - -/////////////////////////////////////////////////////////////////////////////// - -template struct bind_ty { - Class *&VR; - - bind_ty(Class *&V) : VR(V) {} - - template bool match(ITy *V) { - if (auto *CV = dyn_cast(V)) { - VR = CV; - return true; - } - return false; - } -}; - -/// Match a value, capturing it if we match. -inline bind_ty m_Value(Value *&V) { return V; } -inline bind_ty m_Value(const Value *&V) { return V; } - -/// Match an instruction, capturing it if we match. -inline bind_ty m_Instruction(Instruction *&I) { return I; } -/// Match a unary operator, capturing it if we match. -inline bind_ty m_UnOp(UnaryOperator *&I) { return I; } -/// Match a binary operator, capturing it if we match. -inline bind_ty m_BinOp(BinaryOperator *&I) { return I; } -/// Match a with overflow intrinsic, capturing it if we match. -inline bind_ty m_WithOverflowInst(WithOverflowInst *&I) { return I; } -inline bind_ty -m_WithOverflowInst(const WithOverflowInst *&I) { - return I; -} - -/// Match a Constant, capturing the value if we match. -inline bind_ty m_Constant(Constant *&C) { return C; } - -/// Match a ConstantInt, capturing the value if we match. -inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } - -/// Match a ConstantFP, capturing the value if we match. -inline bind_ty m_ConstantFP(ConstantFP *&C) { return C; } - -/// Match a ConstantExpr, capturing the value if we match. -inline bind_ty m_ConstantExpr(ConstantExpr *&C) { return C; } - -/// Match a basic block value, capturing it if we match. -inline bind_ty m_BasicBlock(BasicBlock *&V) { return V; } -inline bind_ty m_BasicBlock(const BasicBlock *&V) { - return V; -} - -/// Match an arbitrary immediate Constant and ignore it. -inline match_combine_and, - match_unless>> -m_ImmConstant() { - return m_CombineAnd(m_Constant(), m_Unless(m_ConstantExpr())); -} - -/// Match an immediate Constant, capturing the value if we match. -inline match_combine_and, - match_unless>> -m_ImmConstant(Constant *&C) { - return m_CombineAnd(m_Constant(C), m_Unless(m_ConstantExpr())); -} - -/// Match a specified Value*. -struct specificval_ty { - const Value *Val; - - specificval_ty(const Value *V) : Val(V) {} - - template bool match(ITy *V) { return V == Val; } -}; - -/// Match if we have a specific specified value. -inline specificval_ty m_Specific(const Value *V) { return V; } - -/// Stores a reference to the Value *, not the Value * itself, -/// thus can be used in commutative matchers. -template struct deferredval_ty { - Class *const &Val; - - deferredval_ty(Class *const &V) : Val(V) {} - - template bool match(ITy *const V) { return V == Val; } -}; - -/// Like m_Specific(), but works if the specific value to match is determined -/// as part of the same match() expression. For example: -/// m_Add(m_Value(X), m_Specific(X)) is incorrect, because m_Specific() will -/// bind X before the pattern match starts. -/// m_Add(m_Value(X), m_Deferred(X)) is correct, and will check against -/// whichever value m_Value(X) populated. -inline deferredval_ty m_Deferred(Value *const &V) { return V; } -inline deferredval_ty m_Deferred(const Value *const &V) { - return V; -} - -/// Match a specified floating point value or vector of all elements of -/// that value. -struct specific_fpval { - double Val; - - specific_fpval(double V) : Val(V) {} - - template bool match(ITy *V) { - if (const auto *CFP = dyn_cast(V)) - return CFP->isExactlyValue(Val); - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - if (auto *CFP = dyn_cast_or_null(C->getSplatValue())) - return CFP->isExactlyValue(Val); - return false; - } -}; - -/// Match a specific floating point value or vector with all elements -/// equal to the value. -inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } - -/// Match a float 1.0 or vector with all elements equal to 1.0. -inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } - -struct bind_const_intval_ty { - uint64_t &VR; - - bind_const_intval_ty(uint64_t &V) : VR(V) {} - - template bool match(ITy *V) { - if (const auto *CV = dyn_cast(V)) - if (CV->getValue().ule(UINT64_MAX)) { - VR = CV->getZExtValue(); - return true; - } - return false; - } -}; - -/// Match a specified integer value or vector of all elements of that -/// value. -template -struct specific_intval { - APInt Val; - - specific_intval(APInt V) : Val(std::move(V)) {} - - template bool match(ITy *V) { - const auto *CI = dyn_cast(V); - if (!CI && V->getType()->isVectorTy()) - if (const auto *C = dyn_cast(V)) - CI = dyn_cast_or_null(C->getSplatValue(AllowUndefs)); - - return CI && APInt::isSameValue(CI->getValue(), Val); - } -}; - -/// Match a specific integer value or vector with all elements equal to -/// the value. -inline specific_intval m_SpecificInt(APInt V) { - return specific_intval(std::move(V)); -} - -inline specific_intval m_SpecificInt(uint64_t V) { - return m_SpecificInt(APInt(64, V)); -} - -inline specific_intval m_SpecificIntAllowUndef(APInt V) { - return specific_intval(std::move(V)); -} - -inline specific_intval m_SpecificIntAllowUndef(uint64_t V) { - return m_SpecificIntAllowUndef(APInt(64, V)); -} - -/// Match a ConstantInt and bind to its value. This does not match -/// ConstantInts wider than 64-bits. -inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } - -/// Match a specified basic block value. -struct specific_bbval { - BasicBlock *Val; - - specific_bbval(BasicBlock *Val) : Val(Val) {} - - template bool match(ITy *V) { - const auto *BB = dyn_cast(V); - return BB && BB == Val; - } -}; - -/// Match a specific basic block value. -inline specific_bbval m_SpecificBB(BasicBlock *BB) { - return specific_bbval(BB); -} - -/// A commutative-friendly version of m_Specific(). -inline deferredval_ty m_Deferred(BasicBlock *const &BB) { - return BB; -} -inline deferredval_ty -m_Deferred(const BasicBlock *const &BB) { - return BB; -} - -//===----------------------------------------------------------------------===// -// Matcher for any binary operator. -// -template -struct AnyBinaryOp_match { - LHS_t L; - RHS_t R; - - // The evaluation order is always stable, regardless of Commutability. - // The LHS is always matched first. - AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) - return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || - (Commutable && L.match(I->getOperand(1)) && - R.match(I->getOperand(0))); - return false; - } -}; - -template -inline AnyBinaryOp_match m_BinOp(const LHS &L, const RHS &R) { - return AnyBinaryOp_match(L, R); -} - -//===----------------------------------------------------------------------===// -// Matcher for any unary operator. -// TODO fuse unary, binary matcher into n-ary matcher -// -template struct AnyUnaryOp_match { - OP_t X; - - AnyUnaryOp_match(const OP_t &X) : X(X) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) - return X.match(I->getOperand(0)); - return false; - } -}; - -template inline AnyUnaryOp_match m_UnOp(const OP_t &X) { - return AnyUnaryOp_match(X); -} - -//===----------------------------------------------------------------------===// -// Matchers for specific binary operators. -// - -template -struct BinaryOp_match { - LHS_t L; - RHS_t R; - - // The evaluation order is always stable, regardless of Commutability. - // The LHS is always matched first. - BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template inline bool match(unsigned Opc, OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opc) { - auto *I = cast(V); - return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || - (Commutable && L.match(I->getOperand(1)) && - R.match(I->getOperand(0))); - } - if (auto *CE = dyn_cast(V)) - return CE->getOpcode() == Opc && - ((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) || - (Commutable && L.match(CE->getOperand(1)) && - R.match(CE->getOperand(0)))); - return false; - } - - template bool match(OpTy *V) { return match(Opcode, V); } -}; - -template -inline BinaryOp_match m_Add(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_FAdd(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_Sub(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_FSub(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template struct FNeg_match { - Op_t X; - - FNeg_match(const Op_t &Op) : X(Op) {} - template bool match(OpTy *V) { - auto *FPMO = dyn_cast(V); - if (!FPMO) return false; - - if (FPMO->getOpcode() == Instruction::FNeg) - return X.match(FPMO->getOperand(0)); - - if (FPMO->getOpcode() == Instruction::FSub) { - if (FPMO->hasNoSignedZeros()) { - // With 'nsz', any zero goes. - if (!cstfp_pred_ty().match(FPMO->getOperand(0))) - return false; - } else { - // Without 'nsz', we need fsub -0.0, X exactly. - if (!cstfp_pred_ty().match(FPMO->getOperand(0))) - return false; - } - - return X.match(FPMO->getOperand(1)); - } - - return false; - } -}; - -/// Match 'fneg X' as 'fsub -0.0, X'. -template -inline FNeg_match -m_FNeg(const OpTy &X) { - return FNeg_match(X); -} - -/// Match 'fneg X' as 'fsub +-0.0, X'. -template -inline BinaryOp_match, RHS, Instruction::FSub> -m_FNegNSZ(const RHS &X) { - return m_FSub(m_AnyZeroFP(), X); -} - -template -inline BinaryOp_match m_Mul(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_FMul(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_UDiv(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_SDiv(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_FDiv(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_URem(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_SRem(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_FRem(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_And(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_Or(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_Xor(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_Shl(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_LShr(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -inline BinaryOp_match m_AShr(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -template -struct OverflowingBinaryOp_match { - LHS_t L; - RHS_t R; - - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} - - template bool match(OpTy *V) { - if (auto *Op = dyn_cast(V)) { - if (Op->getOpcode() != Opcode) - return false; - if ((WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap) && - !Op->hasNoUnsignedWrap()) - return false; - if ((WrapFlags & OverflowingBinaryOperator::NoSignedWrap) && - !Op->hasNoSignedWrap()) - return false; - return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); - } - return false; - } -}; - -template -inline OverflowingBinaryOp_match -m_NSWAdd(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NSWSub(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NSWMul(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NSWShl(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} - -template -inline OverflowingBinaryOp_match -m_NUWAdd(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NUWSub(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NUWMul(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} -template -inline OverflowingBinaryOp_match -m_NUWShl(const LHS &L, const RHS &R) { - return OverflowingBinaryOp_match( - L, R); -} - -template -struct SpecificBinaryOp_match - : public BinaryOp_match { - unsigned Opcode; - - SpecificBinaryOp_match(unsigned Opcode, const LHS_t &LHS, const RHS_t &RHS) - : BinaryOp_match(LHS, RHS), Opcode(Opcode) {} - - template bool match(OpTy *V) { - return BinaryOp_match::match(Opcode, V); - } -}; - -/// Matches a specific opcode. -template -inline SpecificBinaryOp_match m_BinOp(unsigned Opcode, const LHS &L, - const RHS &R) { - return SpecificBinaryOp_match(Opcode, L, R); -} - -//===----------------------------------------------------------------------===// -// Class that matches a group of binary opcodes. -// -template -struct BinOpPred_match : Predicate { - LHS_t L; - RHS_t R; - - BinOpPred_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) - return this->isOpType(I->getOpcode()) && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); - if (auto *CE = dyn_cast(V)) - return this->isOpType(CE->getOpcode()) && L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); - return false; - } -}; - -struct is_shift_op { - bool isOpType(unsigned Opcode) { return Instruction::isShift(Opcode); } -}; - -struct is_right_shift_op { - bool isOpType(unsigned Opcode) { - return Opcode == Instruction::LShr || Opcode == Instruction::AShr; - } -}; - -struct is_logical_shift_op { - bool isOpType(unsigned Opcode) { - return Opcode == Instruction::LShr || Opcode == Instruction::Shl; - } -}; - -struct is_bitwiselogic_op { - bool isOpType(unsigned Opcode) { - return Instruction::isBitwiseLogicOp(Opcode); - } -}; - -struct is_idiv_op { - bool isOpType(unsigned Opcode) { - return Opcode == Instruction::SDiv || Opcode == Instruction::UDiv; - } -}; - -struct is_irem_op { - bool isOpType(unsigned Opcode) { - return Opcode == Instruction::SRem || Opcode == Instruction::URem; - } -}; - -/// Matches shift operations. -template -inline BinOpPred_match m_Shift(const LHS &L, - const RHS &R) { - return BinOpPred_match(L, R); -} - -/// Matches logical shift operations. -template -inline BinOpPred_match m_Shr(const LHS &L, - const RHS &R) { - return BinOpPred_match(L, R); -} - -/// Matches logical shift operations. -template -inline BinOpPred_match -m_LogicalShift(const LHS &L, const RHS &R) { - return BinOpPred_match(L, R); -} - -/// Matches bitwise logic operations. -template -inline BinOpPred_match -m_BitwiseLogic(const LHS &L, const RHS &R) { - return BinOpPred_match(L, R); -} - -/// Matches integer division operations. -template -inline BinOpPred_match m_IDiv(const LHS &L, - const RHS &R) { - return BinOpPred_match(L, R); -} - -/// Matches integer remainder operations. -template -inline BinOpPred_match m_IRem(const LHS &L, - const RHS &R) { - return BinOpPred_match(L, R); -} - -//===----------------------------------------------------------------------===// -// Class that matches exact binary ops. -// -template struct Exact_match { - SubPattern_t SubPattern; - - Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - - template bool match(OpTy *V) { - if (auto *PEO = dyn_cast(V)) - return PEO->isExact() && SubPattern.match(V); - return false; - } -}; - -template inline Exact_match m_Exact(const T &SubPattern) { - return SubPattern; -} - -//===----------------------------------------------------------------------===// -// Matchers for CmpInst classes -// - -template -struct CmpClass_match { - PredicateTy &Predicate; - LHS_t L; - RHS_t R; - - // The evaluation order is always stable, regardless of Commutability. - // The LHS is always matched first. - CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) { - if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { - Predicate = I->getPredicate(); - return true; - } else if (Commutable && L.match(I->getOperand(1)) && - R.match(I->getOperand(0))) { - Predicate = I->getSwappedPredicate(); - return true; - } - } - return false; - } -}; - -template -inline CmpClass_match -m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); -} - -template -inline CmpClass_match -m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); -} - -template -inline CmpClass_match -m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); -} - -//===----------------------------------------------------------------------===// -// Matchers for instructions with a given opcode and number of operands. -// - -/// Matches instructions with Opcode and three operands. -template struct OneOps_match { - T0 Op1; - - OneOps_match(const T0 &Op1) : Op1(Op1) {} - - template bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opcode) { - auto *I = cast(V); - return Op1.match(I->getOperand(0)); - } - return false; - } -}; - -/// Matches instructions with Opcode and three operands. -template struct TwoOps_match { - T0 Op1; - T1 Op2; - - TwoOps_match(const T0 &Op1, const T1 &Op2) : Op1(Op1), Op2(Op2) {} - - template bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opcode) { - auto *I = cast(V); - return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)); - } - return false; - } -}; - -/// Matches instructions with Opcode and three operands. -template -struct ThreeOps_match { - T0 Op1; - T1 Op2; - T2 Op3; - - ThreeOps_match(const T0 &Op1, const T1 &Op2, const T2 &Op3) - : Op1(Op1), Op2(Op2), Op3(Op3) {} - - template bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opcode) { - auto *I = cast(V); - return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) && - Op3.match(I->getOperand(2)); - } - return false; - } -}; - -/// Matches SelectInst. -template -inline ThreeOps_match -m_Select(const Cond &C, const LHS &L, const RHS &R) { - return ThreeOps_match(C, L, R); -} - -/// This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template -inline ThreeOps_match, constantint_match, - Instruction::Select> -m_SelectCst(const Cond &C) { - return m_Select(C, m_ConstantInt(), m_ConstantInt()); -} - -/// Matches FreezeInst. -template -inline OneOps_match m_Freeze(const OpTy &Op) { - return OneOps_match(Op); -} - -/// Matches InsertElementInst. -template -inline ThreeOps_match -m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx) { - return ThreeOps_match( - Val, Elt, Idx); -} - -/// Matches ExtractElementInst. -template -inline TwoOps_match -m_ExtractElt(const Val_t &Val, const Idx_t &Idx) { - return TwoOps_match(Val, Idx); -} - -/// Matches shuffle. -template struct Shuffle_match { - T0 Op1; - T1 Op2; - T2 Mask; - - Shuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask) - : Op1(Op1), Op2(Op2), Mask(Mask) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) { - return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) && - Mask.match(I->getShuffleMask()); - } - return false; - } -}; - -struct m_Mask { - ArrayRef &MaskRef; - m_Mask(ArrayRef &MaskRef) : MaskRef(MaskRef) {} - bool match(ArrayRef Mask) { - MaskRef = Mask; - return true; - } -}; - -struct m_ZeroMask { - bool match(ArrayRef Mask) { - return all_of(Mask, [](int Elem) { return Elem == 0 || Elem == -1; }); - } -}; - -struct m_SpecificMask { - ArrayRef &MaskRef; - m_SpecificMask(ArrayRef &MaskRef) : MaskRef(MaskRef) {} - bool match(ArrayRef Mask) { return MaskRef == Mask; } -}; - -struct m_SplatOrUndefMask { - int &SplatIndex; - m_SplatOrUndefMask(int &SplatIndex) : SplatIndex(SplatIndex) {} - bool match(ArrayRef Mask) { - auto First = find_if(Mask, [](int Elem) { return Elem != -1; }); - if (First == Mask.end()) - return false; - SplatIndex = *First; - return all_of(Mask, - [First](int Elem) { return Elem == *First || Elem == -1; }); - } -}; - -/// Matches ShuffleVectorInst independently of mask value. -template -inline TwoOps_match -m_Shuffle(const V1_t &v1, const V2_t &v2) { - return TwoOps_match(v1, v2); -} - -template -inline Shuffle_match -m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) { - return Shuffle_match(v1, v2, mask); -} - -/// Matches LoadInst. -template -inline OneOps_match m_Load(const OpTy &Op) { - return OneOps_match(Op); -} - -/// Matches StoreInst. -template -inline TwoOps_match -m_Store(const ValueOpTy &ValueOp, const PointerOpTy &PointerOp) { - return TwoOps_match(ValueOp, - PointerOp); -} - -//===----------------------------------------------------------------------===// -// Matchers for CastInst classes -// - -template struct CastClass_match { - Op_t Op; - - CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - - template bool match(OpTy *V) { - if (auto *O = dyn_cast(V)) - return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); - return false; - } -}; - -/// Matches BitCast. -template -inline CastClass_match m_BitCast(const OpTy &Op) { - return CastClass_match(Op); -} - -/// Matches PtrToInt. -template -inline CastClass_match m_PtrToInt(const OpTy &Op) { - return CastClass_match(Op); -} - -/// Matches IntToPtr. -template -inline CastClass_match m_IntToPtr(const OpTy &Op) { - return CastClass_match(Op); -} - -/// Matches Trunc. -template -inline CastClass_match m_Trunc(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline match_combine_or, OpTy> -m_TruncOrSelf(const OpTy &Op) { - return m_CombineOr(m_Trunc(Op), Op); -} - -/// Matches SExt. -template -inline CastClass_match m_SExt(const OpTy &Op) { - return CastClass_match(Op); -} - -/// Matches ZExt. -template -inline CastClass_match m_ZExt(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline match_combine_or, OpTy> -m_ZExtOrSelf(const OpTy &Op) { - return m_CombineOr(m_ZExt(Op), Op); -} - -template -inline match_combine_or, OpTy> -m_SExtOrSelf(const OpTy &Op) { - return m_CombineOr(m_SExt(Op), Op); -} - -template -inline match_combine_or, - CastClass_match> -m_ZExtOrSExt(const OpTy &Op) { - return m_CombineOr(m_ZExt(Op), m_SExt(Op)); -} - -template -inline match_combine_or< - match_combine_or, - CastClass_match>, - OpTy> -m_ZExtOrSExtOrSelf(const OpTy &Op) { - return m_CombineOr(m_ZExtOrSExt(Op), Op); -} - -template -inline CastClass_match m_UIToFP(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline CastClass_match m_SIToFP(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline CastClass_match m_FPToUI(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline CastClass_match m_FPToSI(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline CastClass_match m_FPTrunc(const OpTy &Op) { - return CastClass_match(Op); -} - -template -inline CastClass_match m_FPExt(const OpTy &Op) { - return CastClass_match(Op); -} - -//===----------------------------------------------------------------------===// -// Matchers for control flow. -// - -struct br_match { - BasicBlock *&Succ; - - br_match(BasicBlock *&Succ) : Succ(Succ) {} - - template bool match(OpTy *V) { - if (auto *BI = dyn_cast(V)) - if (BI->isUnconditional()) { - Succ = BI->getSuccessor(0); - return true; - } - return false; - } -}; - -inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } - -template -struct brc_match { - Cond_t Cond; - TrueBlock_t T; - FalseBlock_t F; - - brc_match(const Cond_t &C, const TrueBlock_t &t, const FalseBlock_t &f) - : Cond(C), T(t), F(f) {} - - template bool match(OpTy *V) { - if (auto *BI = dyn_cast(V)) - if (BI->isConditional() && Cond.match(BI->getCondition())) - return T.match(BI->getSuccessor(0)) && F.match(BI->getSuccessor(1)); - return false; - } -}; - -template -inline brc_match, bind_ty> -m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { - return brc_match, bind_ty>( - C, m_BasicBlock(T), m_BasicBlock(F)); -} - -template -inline brc_match -m_Br(const Cond_t &C, const TrueBlock_t &T, const FalseBlock_t &F) { - return brc_match(C, T, F); -} - -//===----------------------------------------------------------------------===// -// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). -// - -template -struct MaxMin_match { - using PredType = Pred_t; - LHS_t L; - RHS_t R; - - // The evaluation order is always stable, regardless of Commutability. - // The LHS is always matched first. - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template bool match(OpTy *V) { - if (auto *II = dyn_cast(V)) { - Intrinsic::ID IID = II->getIntrinsicID(); - if ((IID == Intrinsic::smax && Pred_t::match(ICmpInst::ICMP_SGT)) || - (IID == Intrinsic::smin && Pred_t::match(ICmpInst::ICMP_SLT)) || - (IID == Intrinsic::umax && Pred_t::match(ICmpInst::ICMP_UGT)) || - (IID == Intrinsic::umin && Pred_t::match(ICmpInst::ICMP_ULT))) { - Value *LHS = II->getOperand(0), *RHS = II->getOperand(1); - return (L.match(LHS) && R.match(RHS)) || - (Commutable && L.match(RHS) && R.match(LHS)); - } - } - // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - auto *SI = dyn_cast(V); - if (!SI) - return false; - auto *Cmp = dyn_cast(SI->getCondition()); - if (!Cmp) - return false; - // At this point we have a select conditioned on a comparison. Check that - // it is the values returned by the select that are being compared. - auto *TrueVal = SI->getTrueValue(); - auto *FalseVal = SI->getFalseValue(); - auto *LHS = Cmp->getOperand(0); - auto *RHS = Cmp->getOperand(1); - if ((TrueVal != LHS || FalseVal != RHS) && - (TrueVal != RHS || FalseVal != LHS)) - return false; - typename CmpInst_t::Predicate Pred = - LHS == TrueVal ? Cmp->getPredicate() : Cmp->getInversePredicate(); - // Does "(x pred y) ? x : y" represent the desired max/min operation? - if (!Pred_t::match(Pred)) - return false; - // It does! Bind the operands. - return (L.match(LHS) && R.match(RHS)) || - (Commutable && L.match(RHS) && R.match(LHS)); - } -}; - -/// Helper class for identifying signed max predicates. -struct smax_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; - } -}; - -/// Helper class for identifying signed min predicates. -struct smin_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; - } -}; - -/// Helper class for identifying unsigned max predicates. -struct umax_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; - } -}; - -/// Helper class for identifying unsigned min predicates. -struct umin_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; - } -}; - -/// Helper class for identifying ordered max predicates. -struct ofmax_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; - } -}; - -/// Helper class for identifying ordered min predicates. -struct ofmin_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; - } -}; - -/// Helper class for identifying unordered max predicates. -struct ufmax_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; - } -}; - -/// Helper class for identifying unordered min predicates. -struct ufmin_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; - } -}; - -template -inline MaxMin_match m_SMax(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -template -inline MaxMin_match m_SMin(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -template -inline MaxMin_match m_UMax(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -template -inline MaxMin_match m_UMin(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -template -inline match_combine_or< - match_combine_or, - MaxMin_match>, - match_combine_or, - MaxMin_match>> -m_MaxOrMin(const LHS &L, const RHS &R) { - return m_CombineOr(m_CombineOr(m_SMax(L, R), m_SMin(L, R)), - m_CombineOr(m_UMax(L, R), m_UMin(L, R))); -} - -/// Match an 'ordered' floating point maximum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ogt/ge, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_OrdFMax(L, R) = R iff L or R are NaN -template -inline MaxMin_match m_OrdFMax(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -/// Match an 'ordered' floating point minimum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(olt/le, L, R), L, R) semantics matched by this predicate. -/// -/// min(L, R) iff L and R are not NaN -/// m_OrdFMin(L, R) = R iff L or R are NaN -template -inline MaxMin_match m_OrdFMin(const LHS &L, - const RHS &R) { - return MaxMin_match(L, R); -} - -/// Match an 'unordered' floating point maximum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ugt/ge, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_UnordFMax(L, R) = L iff L or R are NaN -template -inline MaxMin_match -m_UnordFMax(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} - -/// Match an 'unordered' floating point minimum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate. -/// -/// min(L, R) iff L and R are not NaN -/// m_UnordFMin(L, R) = L iff L or R are NaN -template -inline MaxMin_match -m_UnordFMin(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} - -//===----------------------------------------------------------------------===// -// Matchers for overflow check patterns: e.g. (a + b) u< a, (a ^ -1) -struct UAddWithOverflow_match { - LHS_t L; - RHS_t R; - Sum_t S; - - UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) - : L(L), R(R), S(S) {} - - template bool match(OpTy *V) { - Value *ICmpLHS, *ICmpRHS; - ICmpInst::Predicate Pred; - if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) - return false; - - Value *AddLHS, *AddRHS; - auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); - - // (a + b) u< a, (a + b) u< b - if (Pred == ICmpInst::ICMP_ULT) - if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS)) - return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); - - // a >u (a + b), b >u (a + b) - if (Pred == ICmpInst::ICMP_UGT) - if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) - return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); - - Value *Op1; - auto XorExpr = m_OneUse(m_Xor(m_Value(Op1), m_AllOnes())); - // (a ^ -1) u (a ^ -1) - if (Pred == ICmpInst::ICMP_UGT) { - if (XorExpr.match(ICmpRHS)) - return L.match(Op1) && R.match(ICmpLHS) && S.match(ICmpRHS); - } - - // Match special-case for increment-by-1. - if (Pred == ICmpInst::ICMP_EQ) { - // (a + 1) == 0 - // (1 + a) == 0 - if (AddExpr.match(ICmpLHS) && m_ZeroInt().match(ICmpRHS) && - (m_One().match(AddLHS) || m_One().match(AddRHS))) - return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); - // 0 == (a + 1) - // 0 == (1 + a) - if (m_ZeroInt().match(ICmpLHS) && AddExpr.match(ICmpRHS) && - (m_One().match(AddLHS) || m_One().match(AddRHS))) - return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); - } - - return false; - } -}; - -/// Match an icmp instruction checking for unsigned overflow on addition. -/// -/// S is matched to the addition whose result is being checked for overflow, and -/// L and R are matched to the LHS and RHS of S. -template -UAddWithOverflow_match -m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { - return UAddWithOverflow_match(L, R, S); -} - -template struct Argument_match { - unsigned OpI; - Opnd_t Val; - - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - - template bool match(OpTy *V) { - // FIXME: Should likely be switched to use `CallBase`. - if (const auto *CI = dyn_cast(V)) - return Val.match(CI->getArgOperand(OpI)); - return false; - } -}; - -/// Match an argument. -template -inline Argument_match m_Argument(const Opnd_t &Op) { - return Argument_match(OpI, Op); -} - -/// Intrinsic matchers. -struct IntrinsicID_match { - unsigned ID; - - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - - template bool match(OpTy *V) { - if (const auto *CI = dyn_cast(V)) - if (const auto *F = CI->getCalledFunction()) - return F->getIntrinsicID() == ID; - return false; - } -}; - -/// Intrinsic matches are combinations of ID matchers, and argument -/// matchers. Higher arity matcher are defined recursively in terms of and-ing -/// them with lower arity matchers. Here's some convenient typedefs for up to -/// several arguments, and more can be added as needed -template -struct m_Intrinsic_Ty; -template struct m_Intrinsic_Ty { - using Ty = match_combine_and>; -}; -template struct m_Intrinsic_Ty { - using Ty = - match_combine_and::Ty, Argument_match>; -}; -template -struct m_Intrinsic_Ty { - using Ty = - match_combine_and::Ty, - Argument_match>; -}; -template -struct m_Intrinsic_Ty { - using Ty = - match_combine_and::Ty, - Argument_match>; -}; - -template -struct m_Intrinsic_Ty { - using Ty = match_combine_and::Ty, - Argument_match>; -}; - -template -struct m_Intrinsic_Ty { - using Ty = match_combine_and::Ty, - Argument_match>; -}; - -/// Match intrinsic calls like this: -/// m_Intrinsic(m_Value(X)) -template inline IntrinsicID_match m_Intrinsic() { - return IntrinsicID_match(IntrID); -} - -/// Matches MaskedLoad Intrinsic. -template -inline typename m_Intrinsic_Ty::Ty -m_MaskedLoad(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2, - const Opnd3 &Op3) { - return m_Intrinsic(Op0, Op1, Op2, Op3); -} - -template -inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0) { - return m_CombineAnd(m_Intrinsic(), m_Argument<0>(Op0)); -} - -template -inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, - const T1 &Op1) { - return m_CombineAnd(m_Intrinsic(Op0), m_Argument<1>(Op1)); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { - return m_CombineAnd(m_Intrinsic(Op0, Op1), m_Argument<2>(Op2)); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { - return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2), m_Argument<3>(Op3)); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3, - const T4 &Op4) { - return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2, Op3), - m_Argument<4>(Op4)); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3, - const T4 &Op4, const T5 &Op5) { - return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2, Op3, Op4), - m_Argument<5>(Op5)); -} - -// Helper intrinsic matching specializations. -template -inline typename m_Intrinsic_Ty::Ty m_BitReverse(const Opnd0 &Op0) { - return m_Intrinsic(Op0); -} - -template -inline typename m_Intrinsic_Ty::Ty m_BSwap(const Opnd0 &Op0) { - return m_Intrinsic(Op0); -} - -template -inline typename m_Intrinsic_Ty::Ty m_FAbs(const Opnd0 &Op0) { - return m_Intrinsic(Op0); -} - -template -inline typename m_Intrinsic_Ty::Ty m_FCanonicalize(const Opnd0 &Op0) { - return m_Intrinsic(Op0); -} - -template -inline typename m_Intrinsic_Ty::Ty m_FMin(const Opnd0 &Op0, - const Opnd1 &Op1) { - return m_Intrinsic(Op0, Op1); -} - -template -inline typename m_Intrinsic_Ty::Ty m_FMax(const Opnd0 &Op0, - const Opnd1 &Op1) { - return m_Intrinsic(Op0, Op1); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_FShl(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2) { - return m_Intrinsic(Op0, Op1, Op2); -} - -template -inline typename m_Intrinsic_Ty::Ty -m_FShr(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2) { - return m_Intrinsic(Op0, Op1, Op2); -} - -//===----------------------------------------------------------------------===// -// Matchers for two-operands operators with the operators in either order -// - -/// Matches a BinaryOperator with LHS and RHS in either order. -template -inline AnyBinaryOp_match m_c_BinOp(const LHS &L, const RHS &R) { - return AnyBinaryOp_match(L, R); -} - -/// Matches an ICmp with a predicate over LHS and RHS in either order. -/// Swaps the predicate if operands are commuted. -template -inline CmpClass_match -m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, - R); -} - -/// Matches a specific opcode with LHS and RHS in either order. -template -inline SpecificBinaryOp_match -m_c_BinOp(unsigned Opcode, const LHS &L, const RHS &R) { - return SpecificBinaryOp_match(Opcode, L, R); -} - -/// Matches a Add with LHS and RHS in either order. -template -inline BinaryOp_match m_c_Add(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches a Mul with LHS and RHS in either order. -template -inline BinaryOp_match m_c_Mul(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches an And with LHS and RHS in either order. -template -inline BinaryOp_match m_c_And(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches an Or with LHS and RHS in either order. -template -inline BinaryOp_match m_c_Or(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches an Xor with LHS and RHS in either order. -template -inline BinaryOp_match m_c_Xor(const LHS &L, - const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches a 'Neg' as 'sub 0, V'. -template -inline BinaryOp_match, ValTy, Instruction::Sub> -m_Neg(const ValTy &V) { - return m_Sub(m_ZeroInt(), V); -} - -/// Matches a 'Neg' as 'sub nsw 0, V'. -template -inline OverflowingBinaryOp_match, ValTy, - Instruction::Sub, - OverflowingBinaryOperator::NoSignedWrap> -m_NSWNeg(const ValTy &V) { - return m_NSWSub(m_ZeroInt(), V); -} - -/// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'. -template -inline BinaryOp_match, Instruction::Xor, true> -m_Not(const ValTy &V) { - return m_c_Xor(V, m_AllOnes()); -} - -template struct NotForbidUndef_match { - ValTy Val; - NotForbidUndef_match(const ValTy &V) : Val(V) {} - - template bool match(OpTy *V) { - // We do not use m_c_Xor because that could match an arbitrary APInt that is - // not -1 as C and then fail to match the other operand if it is -1. - // This code should still work even when both operands are constants. - Value *X; - const APInt *C; - if (m_Xor(m_Value(X), m_APIntForbidUndef(C)).match(V) && C->isAllOnes()) - return Val.match(X); - if (m_Xor(m_APIntForbidUndef(C), m_Value(X)).match(V) && C->isAllOnes()) - return Val.match(X); - return false; - } -}; - -/// Matches a bitwise 'not' as 'xor V, -1' or 'xor -1, V'. For vectors, the -/// constant value must be composed of only -1 scalar elements. -template -inline NotForbidUndef_match m_NotForbidUndef(const ValTy &V) { - return NotForbidUndef_match(V); -} - -/// Matches an SMin with LHS and RHS in either order. -template -inline MaxMin_match -m_c_SMin(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} -/// Matches an SMax with LHS and RHS in either order. -template -inline MaxMin_match -m_c_SMax(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} -/// Matches a UMin with LHS and RHS in either order. -template -inline MaxMin_match -m_c_UMin(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} -/// Matches a UMax with LHS and RHS in either order. -template -inline MaxMin_match -m_c_UMax(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} - -template -inline match_combine_or< - match_combine_or, - MaxMin_match>, - match_combine_or, - MaxMin_match>> -m_c_MaxOrMin(const LHS &L, const RHS &R) { - return m_CombineOr(m_CombineOr(m_c_SMax(L, R), m_c_SMin(L, R)), - m_CombineOr(m_c_UMax(L, R), m_c_UMin(L, R))); -} - -/// Matches FAdd with LHS and RHS in either order. -template -inline BinaryOp_match -m_c_FAdd(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -/// Matches FMul with LHS and RHS in either order. -template -inline BinaryOp_match -m_c_FMul(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); -} - -template struct Signum_match { - Opnd_t Val; - Signum_match(const Opnd_t &V) : Val(V) {} - - template bool match(OpTy *V) { - unsigned TypeSize = V->getType()->getScalarSizeInBits(); - if (TypeSize == 0) - return false; - - unsigned ShiftWidth = TypeSize - 1; - Value *OpL = nullptr, *OpR = nullptr; - - // This is the representation of signum we match: - // - // signum(x) == (x >> 63) | (-x >>u 63) - // - // An i1 value is its own signum, so it's correct to match - // - // signum(x) == (x >> 0) | (-x >>u 0) - // - // for i1 values. - - auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth)); - auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth)); - auto Signum = m_Or(LHS, RHS); - - return Signum.match(V) && OpL == OpR && Val.match(OpL); - } -}; - -/// Matches a signum pattern. -/// -/// signum(x) = -/// x > 0 -> 1 -/// x == 0 -> 0 -/// x < 0 -> -1 -template inline Signum_match m_Signum(const Val_t &V) { - return Signum_match(V); -} - -template struct ExtractValue_match { - Opnd_t Val; - ExtractValue_match(const Opnd_t &V) : Val(V) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) { - // If Ind is -1, don't inspect indices - if (Ind != -1 && - !(I->getNumIndices() == 1 && I->getIndices()[0] == (unsigned)Ind)) - return false; - return Val.match(I->getAggregateOperand()); - } - return false; - } -}; - -/// Match a single index ExtractValue instruction. -/// For example m_ExtractValue<1>(...) -template -inline ExtractValue_match m_ExtractValue(const Val_t &V) { - return ExtractValue_match(V); -} - -/// Match an ExtractValue instruction with any index. -/// For example m_ExtractValue(...) -template -inline ExtractValue_match<-1, Val_t> m_ExtractValue(const Val_t &V) { - return ExtractValue_match<-1, Val_t>(V); -} - -/// Matcher for a single index InsertValue instruction. -template struct InsertValue_match { - T0 Op0; - T1 Op1; - - InsertValue_match(const T0 &Op0, const T1 &Op1) : Op0(Op0), Op1(Op1) {} - - template bool match(OpTy *V) { - if (auto *I = dyn_cast(V)) { - return Op0.match(I->getOperand(0)) && Op1.match(I->getOperand(1)) && - I->getNumIndices() == 1 && Ind == I->getIndices()[0]; - } - return false; - } -}; - -/// Matches a single index InsertValue instruction. -template -inline InsertValue_match m_InsertValue(const Val_t &Val, - const Elt_t &Elt) { - return InsertValue_match(Val, Elt); -} - -/// Matches patterns for `vscale`. This can either be a call to `llvm.vscale` or -/// the constant expression -/// `ptrtoint(gep , * null, i32 1>` -/// under the right conditions determined by DataLayout. -struct VScaleVal_match { - const DataLayout &DL; - VScaleVal_match(const DataLayout &DL) : DL(DL) {} - - template bool match(ITy *V) { - if (m_Intrinsic().match(V)) - return true; - - Value *Ptr; - if (m_PtrToInt(m_Value(Ptr)).match(V)) { - if (auto *GEP = dyn_cast(Ptr)) { - auto *DerefTy = GEP->getSourceElementType(); - if (GEP->getNumIndices() == 1 && isa(DerefTy) && - m_Zero().match(GEP->getPointerOperand()) && - m_SpecificInt(1).match(GEP->idx_begin()->get()) && - DL.getTypeAllocSizeInBits(DerefTy).getKnownMinSize() == 8) - return true; - } - } - - return false; - } -}; - -inline VScaleVal_match m_VScale(const DataLayout &DL) { - return VScaleVal_match(DL); -} - -template -struct LogicalOp_match { - LHS L; - RHS R; - - LogicalOp_match(const LHS &L, const RHS &R) : L(L), R(R) {} - - template bool match(T *V) { - auto *I = dyn_cast(V); - if (!I || !I->getType()->isIntOrIntVectorTy(1)) - return false; - - if (I->getOpcode() == Opcode) { - auto *Op0 = I->getOperand(0); - auto *Op1 = I->getOperand(1); - return (L.match(Op0) && R.match(Op1)) || - (Commutable && L.match(Op1) && R.match(Op0)); - } - - if (auto *Select = dyn_cast(I)) { - auto *Cond = Select->getCondition(); - auto *TVal = Select->getTrueValue(); - auto *FVal = Select->getFalseValue(); - if (Opcode == Instruction::And) { - auto *C = dyn_cast(FVal); - if (C && C->isNullValue()) - return (L.match(Cond) && R.match(TVal)) || - (Commutable && L.match(TVal) && R.match(Cond)); - } else { - assert(Opcode == Instruction::Or); - auto *C = dyn_cast(TVal); - if (C && C->isOneValue()) - return (L.match(Cond) && R.match(FVal)) || - (Commutable && L.match(FVal) && R.match(Cond)); - } - } - - return false; - } -}; - -/// Matches L && R either in the form of L & R or L ? R : false. -/// Note that the latter form is poison-blocking. -template -inline LogicalOp_match -m_LogicalAnd(const LHS &L, const RHS &R) { - return LogicalOp_match(L, R); -} - -/// Matches L && R where L and R are arbitrary values. -inline auto m_LogicalAnd() { return m_LogicalAnd(m_Value(), m_Value()); } - -/// Matches L && R with LHS and RHS in either order. -template -inline LogicalOp_match -m_c_LogicalAnd(const LHS &L, const RHS &R) { - return LogicalOp_match(L, R); -} - -/// Matches L || R either in the form of L | R or L ? true : R. -/// Note that the latter form is poison-blocking. -template -inline LogicalOp_match -m_LogicalOr(const LHS &L, const RHS &R) { - return LogicalOp_match(L, R); -} - -/// Matches L || R where L and R are arbitrary values. -inline auto m_LogicalOr() { return m_LogicalOr(m_Value(), m_Value()); } - -/// Matches L || R with LHS and RHS in either order. -template -inline LogicalOp_match -m_c_LogicalOr(const LHS &L, const RHS &R) { - return LogicalOp_match(L, R); -} - -} // end namespace PatternMatch -} // end namespace llvm - -#endif // LLVM_IR_PATTERNMATCH_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PredIteratorCache.h b/suite/synctools/tablegen/include/llvm/IR/PredIteratorCache.h deleted file mode 100644 index 6bbd7e5e87..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PredIteratorCache.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- PredIteratorCache.h - pred_iterator Cache ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the PredIteratorCache class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PREDITERATORCACHE_H -#define LLVM_IR_PREDITERATORCACHE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/CFG.h" -#include "llvm/Support/Allocator.h" - -namespace llvm { - -/// PredIteratorCache - This class is an extremely trivial cache for -/// predecessor iterator queries. This is useful for code that repeatedly -/// wants the predecessor list for the same blocks. -class PredIteratorCache { - /// BlockToPredsMap - Pointer to null-terminated list. - mutable DenseMap BlockToPredsMap; - mutable DenseMap BlockToPredCountMap; - - /// Memory - This is the space that holds cached preds. - BumpPtrAllocator Memory; - -private: - /// GetPreds - Get a cached list for the null-terminated predecessor list of - /// the specified block. This can be used in a loop like this: - /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) - /// use(*PI); - /// instead of: - /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - BasicBlock **GetPreds(BasicBlock *BB) { - BasicBlock **&Entry = BlockToPredsMap[BB]; - if (Entry) - return Entry; - - SmallVector PredCache(predecessors(BB)); - PredCache.push_back(nullptr); // null terminator. - - BlockToPredCountMap[BB] = PredCache.size() - 1; - - Entry = Memory.Allocate(PredCache.size()); - std::copy(PredCache.begin(), PredCache.end(), Entry); - return Entry; - } - - unsigned GetNumPreds(BasicBlock *BB) const { - auto Result = BlockToPredCountMap.find(BB); - if (Result != BlockToPredCountMap.end()) - return Result->second; - return BlockToPredCountMap[BB] = pred_size(BB); - } - -public: - size_t size(BasicBlock *BB) const { return GetNumPreds(BB); } - ArrayRef get(BasicBlock *BB) { - return makeArrayRef(GetPreds(BB), GetNumPreds(BB)); - } - - /// clear - Remove all information. - void clear() { - BlockToPredsMap.clear(); - BlockToPredCountMap.clear(); - Memory.Reset(); - } -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/IR/PrintPasses.h b/suite/synctools/tablegen/include/llvm/IR/PrintPasses.h deleted file mode 100644 index 1fa7c1893e..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PrintPasses.h +++ /dev/null @@ -1,44 +0,0 @@ -//===- PrintPasses.h - Determining whether/when to print IR ---------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PRINTPASSES_H -#define LLVM_IR_PRINTPASSES_H - -#include "llvm/ADT/StringRef.h" -#include - -namespace llvm { - -// Returns true if printing before/after some pass is enabled, whether all -// passes or a specific pass. -bool shouldPrintBeforeSomePass(); -bool shouldPrintAfterSomePass(); - -// Returns true if we should print before/after a specific pass. The argument -// should be the pass ID, e.g. "instcombine". -bool shouldPrintBeforePass(StringRef PassID); -bool shouldPrintAfterPass(StringRef PassID); - -// Returns true if we should print before/after all passes. -bool shouldPrintBeforeAll(); -bool shouldPrintAfterAll(); - -// The list of passes to print before/after, if we only want to print -// before/after specific passes. -std::vector printBeforePasses(); -std::vector printAfterPasses(); - -// Returns true if we should always print the entire module. -bool forcePrintModuleIR(); - -// Returns true if we should print the function. -bool isFunctionInPrintList(StringRef FunctionName); - -} // namespace llvm - -#endif // LLVM_IR_PRINTPASSES_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ProfileSummary.h b/suite/synctools/tablegen/include/llvm/IR/ProfileSummary.h deleted file mode 100644 index dfd61e8fba..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ProfileSummary.h +++ /dev/null @@ -1,108 +0,0 @@ -//===- ProfileSummary.h - Profile summary data structure. -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the profile summary data structure. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PROFILESUMMARY_H -#define LLVM_IR_PROFILESUMMARY_H - -#include -#include -#include -#include - -namespace llvm { - -class LLVMContext; -class Metadata; -class raw_ostream; - -// The profile summary is one or more (Cutoff, MinCount, NumCounts) triplets. -// The semantics of counts depend on the type of profile. For instrumentation -// profile, counts are block counts and for sample profile, counts are -// per-line samples. Given a target counts percentile, we compute the minimum -// number of counts needed to reach this target and the minimum among these -// counts. -struct ProfileSummaryEntry { - const uint32_t Cutoff; ///< The required percentile of counts. - const uint64_t MinCount; ///< The minimum count for this percentile. - const uint64_t NumCounts; ///< Number of counts >= the minimum count. - - ProfileSummaryEntry(uint32_t TheCutoff, uint64_t TheMinCount, - uint64_t TheNumCounts) - : Cutoff(TheCutoff), MinCount(TheMinCount), NumCounts(TheNumCounts) {} -}; - -using SummaryEntryVector = std::vector; - -class ProfileSummary { -public: - enum Kind { PSK_Instr, PSK_CSInstr, PSK_Sample }; - -private: - const Kind PSK; - const SummaryEntryVector DetailedSummary; - const uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount; - const uint32_t NumCounts, NumFunctions; - /// If 'Partial' is false, it means the profile being used to optimize - /// a target is collected from the same target. - /// If 'Partial' is true, it means the profile is for common/shared - /// code. The common profile is usually merged from profiles collected - /// from running other targets. - bool Partial = false; - /// This approximately represents the ratio of the number of profile counters - /// of the program being built to the number of profile counters in the - /// partial sample profile. When 'Partial' is false, it is undefined. This is - /// currently only available under thin LTO mode. - double PartialProfileRatio = 0.0; - /// Return detailed summary as metadata. - Metadata *getDetailedSummaryMD(LLVMContext &Context); - -public: - static const int Scale = 1000000; - - ProfileSummary(Kind K, const SummaryEntryVector &DetailedSummary, - uint64_t TotalCount, uint64_t MaxCount, - uint64_t MaxInternalCount, uint64_t MaxFunctionCount, - uint32_t NumCounts, uint32_t NumFunctions, - bool Partial = false, double PartialProfileRatio = 0) - : PSK(K), DetailedSummary(std::move(DetailedSummary)), - TotalCount(TotalCount), MaxCount(MaxCount), - MaxInternalCount(MaxInternalCount), MaxFunctionCount(MaxFunctionCount), - NumCounts(NumCounts), NumFunctions(NumFunctions), Partial(Partial), - PartialProfileRatio(PartialProfileRatio) {} - - Kind getKind() const { return PSK; } - /// Return summary information as metadata. - Metadata *getMD(LLVMContext &Context, bool AddPartialField = true, - bool AddPartialProfileRatioField = true); - /// Construct profile summary from metadata. - static ProfileSummary *getFromMD(Metadata *MD); - const SummaryEntryVector &getDetailedSummary() { return DetailedSummary; } - uint32_t getNumFunctions() const { return NumFunctions; } - uint64_t getMaxFunctionCount() const { return MaxFunctionCount; } - uint32_t getNumCounts() const { return NumCounts; } - uint64_t getTotalCount() const { return TotalCount; } - uint64_t getMaxCount() const { return MaxCount; } - uint64_t getMaxInternalCount() const { return MaxInternalCount; } - void setPartialProfile(bool PP) { Partial = PP; } - bool isPartialProfile() const { return Partial; } - double getPartialProfileRatio() const { return PartialProfileRatio; } - void setPartialProfileRatio(double R) { - assert(isPartialProfile() && "Unexpected when not partial profile"); - PartialProfileRatio = R; - } - void printSummary(raw_ostream &OS) const; - void printDetailedSummary(raw_ostream &OS) const; -}; - -} // end namespace llvm - -#endif // LLVM_IR_PROFILESUMMARY_H diff --git a/suite/synctools/tablegen/include/llvm/IR/PseudoProbe.h b/suite/synctools/tablegen/include/llvm/IR/PseudoProbe.h deleted file mode 100644 index 7d14213143..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/PseudoProbe.h +++ /dev/null @@ -1,88 +0,0 @@ -//===- PseudoProbe.h - Pseudo Probe IR Helpers ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Pseudo probe IR intrinsic and dwarf discriminator manipulation routines. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_PSEUDOPROBE_H -#define LLVM_IR_PSEUDOPROBE_H - -#include "llvm/ADT/Optional.h" -#include -#include -#include - -namespace llvm { - -class Instruction; - -constexpr const char *PseudoProbeDescMetadataName = "llvm.pseudo_probe_desc"; - -enum class PseudoProbeType { Block = 0, IndirectCall, DirectCall }; - -// The saturated distrution factor representing 100% for block probes. -constexpr static uint64_t PseudoProbeFullDistributionFactor = - std::numeric_limits::max(); - -struct PseudoProbeDwarfDiscriminator { -public: - // The following APIs encodes/decodes per-probe information to/from a - // 32-bit integer which is organized as: - // [2:0] - 0x7, this is reserved for regular discriminator, - // see DWARF discriminator encoding rule - // [18:3] - probe id - // [25:19] - probe distribution factor - // [28:26] - probe type, see PseudoProbeType - // [31:29] - reserved for probe attributes - static uint32_t packProbeData(uint32_t Index, uint32_t Type, uint32_t Flags, - uint32_t Factor) { - assert(Index <= 0xFFFF && "Probe index too big to encode, exceeding 2^16"); - assert(Type <= 0x7 && "Probe type too big to encode, exceeding 7"); - assert(Flags <= 0x7); - assert(Factor <= 100 && - "Probe distribution factor too big to encode, exceeding 100"); - return (Index << 3) | (Factor << 19) | (Type << 26) | 0x7; - } - - static uint32_t extractProbeIndex(uint32_t Value) { - return (Value >> 3) & 0xFFFF; - } - - static uint32_t extractProbeType(uint32_t Value) { - return (Value >> 26) & 0x7; - } - - static uint32_t extractProbeAttributes(uint32_t Value) { - return (Value >> 29) & 0x7; - } - - static uint32_t extractProbeFactor(uint32_t Value) { - return (Value >> 19) & 0x7F; - } - - // The saturated distrution factor representing 100% for callsites. - constexpr static uint8_t FullDistributionFactor = 100; -}; - -struct PseudoProbe { - uint32_t Id; - uint32_t Type; - uint32_t Attr; - // Distribution factor that estimates the portion of the real execution count. - // A saturated distribution factor stands for 1.0 or 100%. A pesudo probe has - // a factor with the value ranged from 0.0 to 1.0. - float Factor; -}; - -Optional extractProbe(const Instruction &Inst); - -void setProbeDistributionFactor(Instruction &Inst, float Factor); -} // end namespace llvm - -#endif // LLVM_IR_PSEUDOPROBE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ReplaceConstant.h b/suite/synctools/tablegen/include/llvm/IR/ReplaceConstant.h deleted file mode 100644 index 02c57239e8..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ReplaceConstant.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- ReplaceConstant.h - Replacing LLVM constant expressions --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the utility function for replacing LLVM constant -// expressions by instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_REPLACECONSTANT_H -#define LLVM_IR_REPLACECONSTANT_H - -#include -#include - -namespace llvm { - -class ConstantExpr; -class Instruction; -class Use; -template class SmallPtrSetImpl; - -/// The given instruction \p I contains given constant expression \p CE as one -/// of its operands, possibly nested within constant expression trees. Convert -/// all reachable paths from constant expression operands of \p I to \p CE into -/// corresponding instructions, insert them before \p I, update operands of \p I -/// accordingly, and if required, return all such converted instructions at -/// \p Insts. -void convertConstantExprsToInstructions( - Instruction *I, ConstantExpr *CE, - SmallPtrSetImpl *Insts = nullptr); - -/// The given instruction \p I contains constant expression CE within the -/// constant expression trees of it`s constant expression operands, and -/// \p CEPaths holds all the reachable paths (to CE) from such constant -/// expression trees of \p I. Convert constant expressions within these paths -/// into corresponding instructions, insert them before \p I, update operands of -/// \p I accordingly, and if required, return all such converted instructions at -/// \p Insts. -void convertConstantExprsToInstructions( - Instruction *I, - std::map>> &CEPaths, - SmallPtrSetImpl *Insts = nullptr); - -/// Given an instruction \p I which uses given constant expression \p CE as -/// operand, either directly or nested within other constant expressions, return -/// all reachable paths from the constant expression operands of \p I to \p CE, -/// and return collected paths at \p CEPaths. -void collectConstantExprPaths( - Instruction *I, ConstantExpr *CE, - std::map>> &CEPaths); - -} // end namespace llvm - -#endif // LLVM_IR_REPLACECONSTANT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/RuntimeLibcalls.def b/suite/synctools/tablegen/include/llvm/IR/RuntimeLibcalls.def deleted file mode 100644 index 62d6730811..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/RuntimeLibcalls.def +++ /dev/null @@ -1,592 +0,0 @@ -//===-- llvm/RuntimeLibcalls.def - File that describes libcalls -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the runtime library calls the backend can emit. -// The various long double types cannot be merged, because 80-bit library -// functions use "xf" and 128-bit use "tf". -// -// When adding PPCF128 functions here, note that their names generally need -// to be overridden for Darwin with the xxx$LDBL128 form. See -// PPCISelLowering.cpp. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -// Provide definitions of macros so that users of this file do not have to -// define everything to use it... - -// Declare the enumerator for each libcall, along with its default name. Some -// libcalls have different names on particular OSes or architectures. These -// are set in InitLibcalls() in TargetLoweringBase.cpp and/or by targets -// using TargetLoweringBase::setLibcallName() -#ifndef HANDLE_LIBCALL -#error "HANDLE_LIBCALL must be defined" -#endif - -// Integer -HANDLE_LIBCALL(SHL_I16, "__ashlhi3") -HANDLE_LIBCALL(SHL_I32, "__ashlsi3") -HANDLE_LIBCALL(SHL_I64, "__ashldi3") -HANDLE_LIBCALL(SHL_I128, "__ashlti3") -HANDLE_LIBCALL(SRL_I16, "__lshrhi3") -HANDLE_LIBCALL(SRL_I32, "__lshrsi3") -HANDLE_LIBCALL(SRL_I64, "__lshrdi3") -HANDLE_LIBCALL(SRL_I128, "__lshrti3") -HANDLE_LIBCALL(SRA_I16, "__ashrhi3") -HANDLE_LIBCALL(SRA_I32, "__ashrsi3") -HANDLE_LIBCALL(SRA_I64, "__ashrdi3") -HANDLE_LIBCALL(SRA_I128, "__ashrti3") -HANDLE_LIBCALL(MUL_I8, "__mulqi3") -HANDLE_LIBCALL(MUL_I16, "__mulhi3") -HANDLE_LIBCALL(MUL_I32, "__mulsi3") -HANDLE_LIBCALL(MUL_I64, "__muldi3") -HANDLE_LIBCALL(MUL_I128, "__multi3") -HANDLE_LIBCALL(MULO_I32, "__mulosi4") -HANDLE_LIBCALL(MULO_I64, "__mulodi4") -HANDLE_LIBCALL(MULO_I128, "__muloti4") -HANDLE_LIBCALL(SDIV_I8, "__divqi3") -HANDLE_LIBCALL(SDIV_I16, "__divhi3") -HANDLE_LIBCALL(SDIV_I32, "__divsi3") -HANDLE_LIBCALL(SDIV_I64, "__divdi3") -HANDLE_LIBCALL(SDIV_I128, "__divti3") -HANDLE_LIBCALL(UDIV_I8, "__udivqi3") -HANDLE_LIBCALL(UDIV_I16, "__udivhi3") -HANDLE_LIBCALL(UDIV_I32, "__udivsi3") -HANDLE_LIBCALL(UDIV_I64, "__udivdi3") -HANDLE_LIBCALL(UDIV_I128, "__udivti3") -HANDLE_LIBCALL(SREM_I8, "__modqi3") -HANDLE_LIBCALL(SREM_I16, "__modhi3") -HANDLE_LIBCALL(SREM_I32, "__modsi3") -HANDLE_LIBCALL(SREM_I64, "__moddi3") -HANDLE_LIBCALL(SREM_I128, "__modti3") -HANDLE_LIBCALL(UREM_I8, "__umodqi3") -HANDLE_LIBCALL(UREM_I16, "__umodhi3") -HANDLE_LIBCALL(UREM_I32, "__umodsi3") -HANDLE_LIBCALL(UREM_I64, "__umoddi3") -HANDLE_LIBCALL(UREM_I128, "__umodti3") -HANDLE_LIBCALL(SDIVREM_I8, nullptr) -HANDLE_LIBCALL(SDIVREM_I16, nullptr) -HANDLE_LIBCALL(SDIVREM_I32, nullptr) -HANDLE_LIBCALL(SDIVREM_I64, nullptr) -HANDLE_LIBCALL(SDIVREM_I128, nullptr) -HANDLE_LIBCALL(UDIVREM_I8, nullptr) -HANDLE_LIBCALL(UDIVREM_I16, nullptr) -HANDLE_LIBCALL(UDIVREM_I32, nullptr) -HANDLE_LIBCALL(UDIVREM_I64, nullptr) -HANDLE_LIBCALL(UDIVREM_I128, nullptr) -HANDLE_LIBCALL(NEG_I32, "__negsi2") -HANDLE_LIBCALL(NEG_I64, "__negdi2") -HANDLE_LIBCALL(CTLZ_I32, "__clzsi2") -HANDLE_LIBCALL(CTLZ_I64, "__clzdi2") -HANDLE_LIBCALL(CTLZ_I128, "__clzti2") - -// Floating-point -HANDLE_LIBCALL(ADD_F32, "__addsf3") -HANDLE_LIBCALL(ADD_F64, "__adddf3") -HANDLE_LIBCALL(ADD_F80, "__addxf3") -HANDLE_LIBCALL(ADD_F128, "__addtf3") -HANDLE_LIBCALL(ADD_PPCF128, "__gcc_qadd") -HANDLE_LIBCALL(SUB_F32, "__subsf3") -HANDLE_LIBCALL(SUB_F64, "__subdf3") -HANDLE_LIBCALL(SUB_F80, "__subxf3") -HANDLE_LIBCALL(SUB_F128, "__subtf3") -HANDLE_LIBCALL(SUB_PPCF128, "__gcc_qsub") -HANDLE_LIBCALL(MUL_F32, "__mulsf3") -HANDLE_LIBCALL(MUL_F64, "__muldf3") -HANDLE_LIBCALL(MUL_F80, "__mulxf3") -HANDLE_LIBCALL(MUL_F128, "__multf3") -HANDLE_LIBCALL(MUL_PPCF128, "__gcc_qmul") -HANDLE_LIBCALL(DIV_F32, "__divsf3") -HANDLE_LIBCALL(DIV_F64, "__divdf3") -HANDLE_LIBCALL(DIV_F80, "__divxf3") -HANDLE_LIBCALL(DIV_F128, "__divtf3") -HANDLE_LIBCALL(DIV_PPCF128, "__gcc_qdiv") -HANDLE_LIBCALL(REM_F32, "fmodf") -HANDLE_LIBCALL(REM_F64, "fmod") -HANDLE_LIBCALL(REM_F80, "fmodl") -HANDLE_LIBCALL(REM_F128, "fmodl") -HANDLE_LIBCALL(REM_PPCF128, "fmodl") -HANDLE_LIBCALL(FMA_F32, "fmaf") -HANDLE_LIBCALL(FMA_F64, "fma") -HANDLE_LIBCALL(FMA_F80, "fmal") -HANDLE_LIBCALL(FMA_F128, "fmal") -HANDLE_LIBCALL(FMA_PPCF128, "fmal") -HANDLE_LIBCALL(POWI_F32, "__powisf2") -HANDLE_LIBCALL(POWI_F64, "__powidf2") -HANDLE_LIBCALL(POWI_F80, "__powixf2") -HANDLE_LIBCALL(POWI_F128, "__powitf2") -HANDLE_LIBCALL(POWI_PPCF128, "__powitf2") -HANDLE_LIBCALL(SQRT_F32, "sqrtf") -HANDLE_LIBCALL(SQRT_F64, "sqrt") -HANDLE_LIBCALL(SQRT_F80, "sqrtl") -HANDLE_LIBCALL(SQRT_F128, "sqrtl") -HANDLE_LIBCALL(SQRT_PPCF128, "sqrtl") -HANDLE_LIBCALL(CBRT_F32, "cbrtf") -HANDLE_LIBCALL(CBRT_F64, "cbrt") -HANDLE_LIBCALL(CBRT_F80, "cbrtl") -HANDLE_LIBCALL(CBRT_F128, "cbrtl") -HANDLE_LIBCALL(CBRT_PPCF128, "cbrtl") -HANDLE_LIBCALL(LOG_F32, "logf") -HANDLE_LIBCALL(LOG_F64, "log") -HANDLE_LIBCALL(LOG_F80, "logl") -HANDLE_LIBCALL(LOG_F128, "logl") -HANDLE_LIBCALL(LOG_PPCF128, "logl") -HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite") -HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite") -HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite") -HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite") -HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite") -HANDLE_LIBCALL(LOG2_F32, "log2f") -HANDLE_LIBCALL(LOG2_F64, "log2") -HANDLE_LIBCALL(LOG2_F80, "log2l") -HANDLE_LIBCALL(LOG2_F128, "log2l") -HANDLE_LIBCALL(LOG2_PPCF128, "log2l") -HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite") -HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite") -HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite") -HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite") -HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite") -HANDLE_LIBCALL(LOG10_F32, "log10f") -HANDLE_LIBCALL(LOG10_F64, "log10") -HANDLE_LIBCALL(LOG10_F80, "log10l") -HANDLE_LIBCALL(LOG10_F128, "log10l") -HANDLE_LIBCALL(LOG10_PPCF128, "log10l") -HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite") -HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite") -HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite") -HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite") -HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite") -HANDLE_LIBCALL(EXP_F32, "expf") -HANDLE_LIBCALL(EXP_F64, "exp") -HANDLE_LIBCALL(EXP_F80, "expl") -HANDLE_LIBCALL(EXP_F128, "expl") -HANDLE_LIBCALL(EXP_PPCF128, "expl") -HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite") -HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite") -HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite") -HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite") -HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite") -HANDLE_LIBCALL(EXP2_F32, "exp2f") -HANDLE_LIBCALL(EXP2_F64, "exp2") -HANDLE_LIBCALL(EXP2_F80, "exp2l") -HANDLE_LIBCALL(EXP2_F128, "exp2l") -HANDLE_LIBCALL(EXP2_PPCF128, "exp2l") -HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite") -HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite") -HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite") -HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite") -HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite") -HANDLE_LIBCALL(SIN_F32, "sinf") -HANDLE_LIBCALL(SIN_F64, "sin") -HANDLE_LIBCALL(SIN_F80, "sinl") -HANDLE_LIBCALL(SIN_F128, "sinl") -HANDLE_LIBCALL(SIN_PPCF128, "sinl") -HANDLE_LIBCALL(COS_F32, "cosf") -HANDLE_LIBCALL(COS_F64, "cos") -HANDLE_LIBCALL(COS_F80, "cosl") -HANDLE_LIBCALL(COS_F128, "cosl") -HANDLE_LIBCALL(COS_PPCF128, "cosl") -HANDLE_LIBCALL(SINCOS_F32, nullptr) -HANDLE_LIBCALL(SINCOS_F64, nullptr) -HANDLE_LIBCALL(SINCOS_F80, nullptr) -HANDLE_LIBCALL(SINCOS_F128, nullptr) -HANDLE_LIBCALL(SINCOS_PPCF128, nullptr) -HANDLE_LIBCALL(SINCOS_STRET_F32, nullptr) -HANDLE_LIBCALL(SINCOS_STRET_F64, nullptr) -HANDLE_LIBCALL(POW_F32, "powf") -HANDLE_LIBCALL(POW_F64, "pow") -HANDLE_LIBCALL(POW_F80, "powl") -HANDLE_LIBCALL(POW_F128, "powl") -HANDLE_LIBCALL(POW_PPCF128, "powl") -HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite") -HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite") -HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite") -HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite") -HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite") -HANDLE_LIBCALL(CEIL_F32, "ceilf") -HANDLE_LIBCALL(CEIL_F64, "ceil") -HANDLE_LIBCALL(CEIL_F80, "ceill") -HANDLE_LIBCALL(CEIL_F128, "ceill") -HANDLE_LIBCALL(CEIL_PPCF128, "ceill") -HANDLE_LIBCALL(TRUNC_F32, "truncf") -HANDLE_LIBCALL(TRUNC_F64, "trunc") -HANDLE_LIBCALL(TRUNC_F80, "truncl") -HANDLE_LIBCALL(TRUNC_F128, "truncl") -HANDLE_LIBCALL(TRUNC_PPCF128, "truncl") -HANDLE_LIBCALL(RINT_F32, "rintf") -HANDLE_LIBCALL(RINT_F64, "rint") -HANDLE_LIBCALL(RINT_F80, "rintl") -HANDLE_LIBCALL(RINT_F128, "rintl") -HANDLE_LIBCALL(RINT_PPCF128, "rintl") -HANDLE_LIBCALL(NEARBYINT_F32, "nearbyintf") -HANDLE_LIBCALL(NEARBYINT_F64, "nearbyint") -HANDLE_LIBCALL(NEARBYINT_F80, "nearbyintl") -HANDLE_LIBCALL(NEARBYINT_F128, "nearbyintl") -HANDLE_LIBCALL(NEARBYINT_PPCF128, "nearbyintl") -HANDLE_LIBCALL(ROUND_F32, "roundf") -HANDLE_LIBCALL(ROUND_F64, "round") -HANDLE_LIBCALL(ROUND_F80, "roundl") -HANDLE_LIBCALL(ROUND_F128, "roundl") -HANDLE_LIBCALL(ROUND_PPCF128, "roundl") -HANDLE_LIBCALL(ROUNDEVEN_F32, "roundevenf") -HANDLE_LIBCALL(ROUNDEVEN_F64, "roundeven") -HANDLE_LIBCALL(ROUNDEVEN_F80, "roundevenl") -HANDLE_LIBCALL(ROUNDEVEN_F128, "roundevenl") -HANDLE_LIBCALL(ROUNDEVEN_PPCF128, "roundevenl") -HANDLE_LIBCALL(FLOOR_F32, "floorf") -HANDLE_LIBCALL(FLOOR_F64, "floor") -HANDLE_LIBCALL(FLOOR_F80, "floorl") -HANDLE_LIBCALL(FLOOR_F128, "floorl") -HANDLE_LIBCALL(FLOOR_PPCF128, "floorl") -HANDLE_LIBCALL(COPYSIGN_F32, "copysignf") -HANDLE_LIBCALL(COPYSIGN_F64, "copysign") -HANDLE_LIBCALL(COPYSIGN_F80, "copysignl") -HANDLE_LIBCALL(COPYSIGN_F128, "copysignl") -HANDLE_LIBCALL(COPYSIGN_PPCF128, "copysignl") -HANDLE_LIBCALL(FMIN_F32, "fminf") -HANDLE_LIBCALL(FMIN_F64, "fmin") -HANDLE_LIBCALL(FMIN_F80, "fminl") -HANDLE_LIBCALL(FMIN_F128, "fminl") -HANDLE_LIBCALL(FMIN_PPCF128, "fminl") -HANDLE_LIBCALL(FMAX_F32, "fmaxf") -HANDLE_LIBCALL(FMAX_F64, "fmax") -HANDLE_LIBCALL(FMAX_F80, "fmaxl") -HANDLE_LIBCALL(FMAX_F128, "fmaxl") -HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl") -HANDLE_LIBCALL(LROUND_F32, "lroundf") -HANDLE_LIBCALL(LROUND_F64, "lround") -HANDLE_LIBCALL(LROUND_F80, "lroundl") -HANDLE_LIBCALL(LROUND_F128, "lroundl") -HANDLE_LIBCALL(LROUND_PPCF128, "lroundl") -HANDLE_LIBCALL(LLROUND_F32, "llroundf") -HANDLE_LIBCALL(LLROUND_F64, "llround") -HANDLE_LIBCALL(LLROUND_F80, "llroundl") -HANDLE_LIBCALL(LLROUND_F128, "llroundl") -HANDLE_LIBCALL(LLROUND_PPCF128, "llroundl") -HANDLE_LIBCALL(LRINT_F32, "lrintf") -HANDLE_LIBCALL(LRINT_F64, "lrint") -HANDLE_LIBCALL(LRINT_F80, "lrintl") -HANDLE_LIBCALL(LRINT_F128, "lrintl") -HANDLE_LIBCALL(LRINT_PPCF128, "lrintl") -HANDLE_LIBCALL(LLRINT_F32, "llrintf") -HANDLE_LIBCALL(LLRINT_F64, "llrint") -HANDLE_LIBCALL(LLRINT_F80, "llrintl") -HANDLE_LIBCALL(LLRINT_F128, "llrintl") -HANDLE_LIBCALL(LLRINT_PPCF128, "llrintl") - -// Conversion -HANDLE_LIBCALL(FPEXT_F32_PPCF128, "__gcc_stoq") -HANDLE_LIBCALL(FPEXT_F64_PPCF128, "__gcc_dtoq") -HANDLE_LIBCALL(FPEXT_F80_F128, "__extendxftf2") -HANDLE_LIBCALL(FPEXT_F64_F128, "__extenddftf2") -HANDLE_LIBCALL(FPEXT_F32_F128, "__extendsftf2") -HANDLE_LIBCALL(FPEXT_F16_F128, "__extendhftf2") -HANDLE_LIBCALL(FPEXT_F16_F80, "__extendhfxf2") -HANDLE_LIBCALL(FPEXT_F32_F64, "__extendsfdf2") -HANDLE_LIBCALL(FPEXT_F16_F64, "__extendhfdf2") -HANDLE_LIBCALL(FPEXT_F16_F32, "__gnu_h2f_ieee") -HANDLE_LIBCALL(FPROUND_F32_F16, "__gnu_f2h_ieee") -HANDLE_LIBCALL(FPROUND_F64_F16, "__truncdfhf2") -HANDLE_LIBCALL(FPROUND_F80_F16, "__truncxfhf2") -HANDLE_LIBCALL(FPROUND_F128_F16, "__trunctfhf2") -HANDLE_LIBCALL(FPROUND_PPCF128_F16, "__trunctfhf2") -HANDLE_LIBCALL(FPROUND_F64_F32, "__truncdfsf2") -HANDLE_LIBCALL(FPROUND_F80_F32, "__truncxfsf2") -HANDLE_LIBCALL(FPROUND_F128_F32, "__trunctfsf2") -HANDLE_LIBCALL(FPROUND_PPCF128_F32, "__gcc_qtos") -HANDLE_LIBCALL(FPROUND_F80_F64, "__truncxfdf2") -HANDLE_LIBCALL(FPROUND_F128_F64, "__trunctfdf2") -HANDLE_LIBCALL(FPROUND_PPCF128_F64, "__gcc_qtod") -HANDLE_LIBCALL(FPROUND_F128_F80, "__trunctfxf2") -HANDLE_LIBCALL(FPTOSINT_F16_I32, "__fixhfsi") -HANDLE_LIBCALL(FPTOSINT_F16_I64, "__fixhfdi") -HANDLE_LIBCALL(FPTOSINT_F16_I128, "__fixhfti") -HANDLE_LIBCALL(FPTOSINT_F32_I32, "__fixsfsi") -HANDLE_LIBCALL(FPTOSINT_F32_I64, "__fixsfdi") -HANDLE_LIBCALL(FPTOSINT_F32_I128, "__fixsfti") -HANDLE_LIBCALL(FPTOSINT_F64_I32, "__fixdfsi") -HANDLE_LIBCALL(FPTOSINT_F64_I64, "__fixdfdi") -HANDLE_LIBCALL(FPTOSINT_F64_I128, "__fixdfti") -HANDLE_LIBCALL(FPTOSINT_F80_I32, "__fixxfsi") -HANDLE_LIBCALL(FPTOSINT_F80_I64, "__fixxfdi") -HANDLE_LIBCALL(FPTOSINT_F80_I128, "__fixxfti") -HANDLE_LIBCALL(FPTOSINT_F128_I32, "__fixtfsi") -HANDLE_LIBCALL(FPTOSINT_F128_I64, "__fixtfdi") -HANDLE_LIBCALL(FPTOSINT_F128_I128, "__fixtfti") -HANDLE_LIBCALL(FPTOSINT_PPCF128_I32, "__gcc_qtou") -HANDLE_LIBCALL(FPTOSINT_PPCF128_I64, "__fixtfdi") -HANDLE_LIBCALL(FPTOSINT_PPCF128_I128, "__fixtfti") -HANDLE_LIBCALL(FPTOUINT_F16_I32, "__fixunshfsi") -HANDLE_LIBCALL(FPTOUINT_F16_I64, "__fixunshfdi") -HANDLE_LIBCALL(FPTOUINT_F16_I128, "__fixunshfti") -HANDLE_LIBCALL(FPTOUINT_F32_I32, "__fixunssfsi") -HANDLE_LIBCALL(FPTOUINT_F32_I64, "__fixunssfdi") -HANDLE_LIBCALL(FPTOUINT_F32_I128, "__fixunssfti") -HANDLE_LIBCALL(FPTOUINT_F64_I32, "__fixunsdfsi") -HANDLE_LIBCALL(FPTOUINT_F64_I64, "__fixunsdfdi") -HANDLE_LIBCALL(FPTOUINT_F64_I128, "__fixunsdfti") -HANDLE_LIBCALL(FPTOUINT_F80_I32, "__fixunsxfsi") -HANDLE_LIBCALL(FPTOUINT_F80_I64, "__fixunsxfdi") -HANDLE_LIBCALL(FPTOUINT_F80_I128, "__fixunsxfti") -HANDLE_LIBCALL(FPTOUINT_F128_I32, "__fixunstfsi") -HANDLE_LIBCALL(FPTOUINT_F128_I64, "__fixunstfdi") -HANDLE_LIBCALL(FPTOUINT_F128_I128, "__fixunstfti") -HANDLE_LIBCALL(FPTOUINT_PPCF128_I32, "__fixunstfsi") -HANDLE_LIBCALL(FPTOUINT_PPCF128_I64, "__fixunstfdi") -HANDLE_LIBCALL(FPTOUINT_PPCF128_I128, "__fixunstfti") -HANDLE_LIBCALL(SINTTOFP_I32_F16, "__floatsihf") -HANDLE_LIBCALL(SINTTOFP_I32_F32, "__floatsisf") -HANDLE_LIBCALL(SINTTOFP_I32_F64, "__floatsidf") -HANDLE_LIBCALL(SINTTOFP_I32_F80, "__floatsixf") -HANDLE_LIBCALL(SINTTOFP_I32_F128, "__floatsitf") -HANDLE_LIBCALL(SINTTOFP_I32_PPCF128, "__gcc_itoq") -HANDLE_LIBCALL(SINTTOFP_I64_F16, "__floatdihf") -HANDLE_LIBCALL(SINTTOFP_I64_F32, "__floatdisf") -HANDLE_LIBCALL(SINTTOFP_I64_F64, "__floatdidf") -HANDLE_LIBCALL(SINTTOFP_I64_F80, "__floatdixf") -HANDLE_LIBCALL(SINTTOFP_I64_F128, "__floatditf") -HANDLE_LIBCALL(SINTTOFP_I64_PPCF128, "__floatditf") -HANDLE_LIBCALL(SINTTOFP_I128_F16, "__floattihf") -HANDLE_LIBCALL(SINTTOFP_I128_F32, "__floattisf") -HANDLE_LIBCALL(SINTTOFP_I128_F64, "__floattidf") -HANDLE_LIBCALL(SINTTOFP_I128_F80, "__floattixf") -HANDLE_LIBCALL(SINTTOFP_I128_F128, "__floattitf") -HANDLE_LIBCALL(SINTTOFP_I128_PPCF128, "__floattitf") -HANDLE_LIBCALL(UINTTOFP_I32_F16, "__floatunsihf") -HANDLE_LIBCALL(UINTTOFP_I32_F32, "__floatunsisf") -HANDLE_LIBCALL(UINTTOFP_I32_F64, "__floatunsidf") -HANDLE_LIBCALL(UINTTOFP_I32_F80, "__floatunsixf") -HANDLE_LIBCALL(UINTTOFP_I32_F128, "__floatunsitf") -HANDLE_LIBCALL(UINTTOFP_I32_PPCF128, "__gcc_utoq") -HANDLE_LIBCALL(UINTTOFP_I64_F16, "__floatundihf") -HANDLE_LIBCALL(UINTTOFP_I64_F32, "__floatundisf") -HANDLE_LIBCALL(UINTTOFP_I64_F64, "__floatundidf") -HANDLE_LIBCALL(UINTTOFP_I64_F80, "__floatundixf") -HANDLE_LIBCALL(UINTTOFP_I64_F128, "__floatunditf") -HANDLE_LIBCALL(UINTTOFP_I64_PPCF128, "__floatunditf") -HANDLE_LIBCALL(UINTTOFP_I128_F16, "__floatuntihf") -HANDLE_LIBCALL(UINTTOFP_I128_F32, "__floatuntisf") -HANDLE_LIBCALL(UINTTOFP_I128_F64, "__floatuntidf") -HANDLE_LIBCALL(UINTTOFP_I128_F80, "__floatuntixf") -HANDLE_LIBCALL(UINTTOFP_I128_F128, "__floatuntitf") -HANDLE_LIBCALL(UINTTOFP_I128_PPCF128, "__floatuntitf") -HANDLE_LIBCALL(CONVERT_F128_PPCF128, "__extendkftf2") -HANDLE_LIBCALL(CONVERT_PPCF128_F128, "__trunctfkf2") - -// Comparison -HANDLE_LIBCALL(OEQ_F32, "__eqsf2") -HANDLE_LIBCALL(OEQ_F64, "__eqdf2") -HANDLE_LIBCALL(OEQ_F128, "__eqtf2") -HANDLE_LIBCALL(OEQ_PPCF128, "__gcc_qeq") -HANDLE_LIBCALL(UNE_F32, "__nesf2") -HANDLE_LIBCALL(UNE_F64, "__nedf2") -HANDLE_LIBCALL(UNE_F128, "__netf2") -HANDLE_LIBCALL(UNE_PPCF128, "__gcc_qne") -HANDLE_LIBCALL(OGE_F32, "__gesf2") -HANDLE_LIBCALL(OGE_F64, "__gedf2") -HANDLE_LIBCALL(OGE_F128, "__getf2") -HANDLE_LIBCALL(OGE_PPCF128, "__gcc_qge") -HANDLE_LIBCALL(OLT_F32, "__ltsf2") -HANDLE_LIBCALL(OLT_F64, "__ltdf2") -HANDLE_LIBCALL(OLT_F128, "__lttf2") -HANDLE_LIBCALL(OLT_PPCF128, "__gcc_qlt") -HANDLE_LIBCALL(OLE_F32, "__lesf2") -HANDLE_LIBCALL(OLE_F64, "__ledf2") -HANDLE_LIBCALL(OLE_F128, "__letf2") -HANDLE_LIBCALL(OLE_PPCF128, "__gcc_qle") -HANDLE_LIBCALL(OGT_F32, "__gtsf2") -HANDLE_LIBCALL(OGT_F64, "__gtdf2") -HANDLE_LIBCALL(OGT_F128, "__gttf2") -HANDLE_LIBCALL(OGT_PPCF128, "__gcc_qgt") -HANDLE_LIBCALL(UO_F32, "__unordsf2") -HANDLE_LIBCALL(UO_F64, "__unorddf2") -HANDLE_LIBCALL(UO_F128, "__unordtf2") -HANDLE_LIBCALL(UO_PPCF128, "__gcc_qunord") - -// Memory -HANDLE_LIBCALL(MEMCPY, "memcpy") -HANDLE_LIBCALL(MEMMOVE, "memmove") -HANDLE_LIBCALL(MEMSET, "memset") -HANDLE_LIBCALL(BZERO, nullptr) - -// Element-wise unordered-atomic memory of different sizes -HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_1, "__llvm_memcpy_element_unordered_atomic_1") -HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_2, "__llvm_memcpy_element_unordered_atomic_2") -HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_4, "__llvm_memcpy_element_unordered_atomic_4") -HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_8, "__llvm_memcpy_element_unordered_atomic_8") -HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_16, "__llvm_memcpy_element_unordered_atomic_16") -HANDLE_LIBCALL(MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1, "__llvm_memmove_element_unordered_atomic_1") -HANDLE_LIBCALL(MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2, "__llvm_memmove_element_unordered_atomic_2") -HANDLE_LIBCALL(MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4, "__llvm_memmove_element_unordered_atomic_4") -HANDLE_LIBCALL(MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8, "__llvm_memmove_element_unordered_atomic_8") -HANDLE_LIBCALL(MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16, "__llvm_memmove_element_unordered_atomic_16") -HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_1, "__llvm_memset_element_unordered_atomic_1") -HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_2, "__llvm_memset_element_unordered_atomic_2") -HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_4, "__llvm_memset_element_unordered_atomic_4") -HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_8, "__llvm_memset_element_unordered_atomic_8") -HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_16, "__llvm_memset_element_unordered_atomic_16") - -// Exception handling -HANDLE_LIBCALL(UNWIND_RESUME, "_Unwind_Resume") -HANDLE_LIBCALL(CXA_END_CLEANUP, "__cxa_end_cleanup") - -// Note: there are two sets of atomics libcalls; see -// for more info on the -// difference between them. - -// Atomic '__sync_*' libcalls. -HANDLE_LIBCALL(SYNC_VAL_COMPARE_AND_SWAP_1, "__sync_val_compare_and_swap_1") -HANDLE_LIBCALL(SYNC_VAL_COMPARE_AND_SWAP_2, "__sync_val_compare_and_swap_2") -HANDLE_LIBCALL(SYNC_VAL_COMPARE_AND_SWAP_4, "__sync_val_compare_and_swap_4") -HANDLE_LIBCALL(SYNC_VAL_COMPARE_AND_SWAP_8, "__sync_val_compare_and_swap_8") -HANDLE_LIBCALL(SYNC_VAL_COMPARE_AND_SWAP_16, "__sync_val_compare_and_swap_16") -HANDLE_LIBCALL(SYNC_LOCK_TEST_AND_SET_1, "__sync_lock_test_and_set_1") -HANDLE_LIBCALL(SYNC_LOCK_TEST_AND_SET_2, "__sync_lock_test_and_set_2") -HANDLE_LIBCALL(SYNC_LOCK_TEST_AND_SET_4, "__sync_lock_test_and_set_4") -HANDLE_LIBCALL(SYNC_LOCK_TEST_AND_SET_8, "__sync_lock_test_and_set_8") -HANDLE_LIBCALL(SYNC_LOCK_TEST_AND_SET_16, "__sync_lock_test_and_set_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_ADD_1, "__sync_fetch_and_add_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_ADD_2, "__sync_fetch_and_add_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_ADD_4, "__sync_fetch_and_add_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_ADD_8, "__sync_fetch_and_add_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_ADD_16, "__sync_fetch_and_add_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_SUB_1, "__sync_fetch_and_sub_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_SUB_2, "__sync_fetch_and_sub_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_SUB_4, "__sync_fetch_and_sub_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_SUB_8, "__sync_fetch_and_sub_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_SUB_16, "__sync_fetch_and_sub_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_AND_1, "__sync_fetch_and_and_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_AND_2, "__sync_fetch_and_and_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_AND_4, "__sync_fetch_and_and_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_AND_8, "__sync_fetch_and_and_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_AND_16, "__sync_fetch_and_and_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_OR_1, "__sync_fetch_and_or_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_OR_2, "__sync_fetch_and_or_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_OR_4, "__sync_fetch_and_or_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_OR_8, "__sync_fetch_and_or_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_OR_16, "__sync_fetch_and_or_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_XOR_1, "__sync_fetch_and_xor_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_XOR_2, "__sync_fetch_and_xor_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_XOR_4, "__sync_fetch_and_xor_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_XOR_8, "__sync_fetch_and_xor_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_XOR_16, "__sync_fetch_and_xor_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_NAND_1, "__sync_fetch_and_nand_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_NAND_2, "__sync_fetch_and_nand_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_NAND_4, "__sync_fetch_and_nand_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_NAND_8, "__sync_fetch_and_nand_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_NAND_16, "__sync_fetch_and_nand_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_MAX_1, "__sync_fetch_and_max_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_MAX_2, "__sync_fetch_and_max_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_MAX_4, "__sync_fetch_and_max_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_MAX_8, "__sync_fetch_and_max_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_MAX_16, "__sync_fetch_and_max_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMAX_1, "__sync_fetch_and_umax_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMAX_2, "__sync_fetch_and_umax_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMAX_4, "__sync_fetch_and_umax_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMAX_8, "__sync_fetch_and_umax_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMAX_16, "__sync_fetch_and_umax_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_MIN_1, "__sync_fetch_and_min_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_MIN_2, "__sync_fetch_and_min_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_MIN_4, "__sync_fetch_and_min_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_MIN_8, "__sync_fetch_and_min_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_MIN_16, "__sync_fetch_and_min_16") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMIN_1, "__sync_fetch_and_umin_1") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMIN_2, "__sync_fetch_and_umin_2") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMIN_4, "__sync_fetch_and_umin_4") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMIN_8, "__sync_fetch_and_umin_8") -HANDLE_LIBCALL(SYNC_FETCH_AND_UMIN_16, "__sync_fetch_and_umin_16") - -// Atomic `__atomic_*' libcalls. -HANDLE_LIBCALL(ATOMIC_LOAD, "__atomic_load") -HANDLE_LIBCALL(ATOMIC_LOAD_1, "__atomic_load_1") -HANDLE_LIBCALL(ATOMIC_LOAD_2, "__atomic_load_2") -HANDLE_LIBCALL(ATOMIC_LOAD_4, "__atomic_load_4") -HANDLE_LIBCALL(ATOMIC_LOAD_8, "__atomic_load_8") -HANDLE_LIBCALL(ATOMIC_LOAD_16, "__atomic_load_16") - -HANDLE_LIBCALL(ATOMIC_STORE, "__atomic_store") -HANDLE_LIBCALL(ATOMIC_STORE_1, "__atomic_store_1") -HANDLE_LIBCALL(ATOMIC_STORE_2, "__atomic_store_2") -HANDLE_LIBCALL(ATOMIC_STORE_4, "__atomic_store_4") -HANDLE_LIBCALL(ATOMIC_STORE_8, "__atomic_store_8") -HANDLE_LIBCALL(ATOMIC_STORE_16, "__atomic_store_16") - -HANDLE_LIBCALL(ATOMIC_EXCHANGE, "__atomic_exchange") -HANDLE_LIBCALL(ATOMIC_EXCHANGE_1, "__atomic_exchange_1") -HANDLE_LIBCALL(ATOMIC_EXCHANGE_2, "__atomic_exchange_2") -HANDLE_LIBCALL(ATOMIC_EXCHANGE_4, "__atomic_exchange_4") -HANDLE_LIBCALL(ATOMIC_EXCHANGE_8, "__atomic_exchange_8") -HANDLE_LIBCALL(ATOMIC_EXCHANGE_16, "__atomic_exchange_16") - -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE, "__atomic_compare_exchange") -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE_1, "__atomic_compare_exchange_1") -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE_2, "__atomic_compare_exchange_2") -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE_4, "__atomic_compare_exchange_4") -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE_8, "__atomic_compare_exchange_8") -HANDLE_LIBCALL(ATOMIC_COMPARE_EXCHANGE_16, "__atomic_compare_exchange_16") - -HANDLE_LIBCALL(ATOMIC_FETCH_ADD_1, "__atomic_fetch_add_1") -HANDLE_LIBCALL(ATOMIC_FETCH_ADD_2, "__atomic_fetch_add_2") -HANDLE_LIBCALL(ATOMIC_FETCH_ADD_4, "__atomic_fetch_add_4") -HANDLE_LIBCALL(ATOMIC_FETCH_ADD_8, "__atomic_fetch_add_8") -HANDLE_LIBCALL(ATOMIC_FETCH_ADD_16, "__atomic_fetch_add_16") -HANDLE_LIBCALL(ATOMIC_FETCH_SUB_1, "__atomic_fetch_sub_1") -HANDLE_LIBCALL(ATOMIC_FETCH_SUB_2, "__atomic_fetch_sub_2") -HANDLE_LIBCALL(ATOMIC_FETCH_SUB_4, "__atomic_fetch_sub_4") -HANDLE_LIBCALL(ATOMIC_FETCH_SUB_8, "__atomic_fetch_sub_8") -HANDLE_LIBCALL(ATOMIC_FETCH_SUB_16, "__atomic_fetch_sub_16") -HANDLE_LIBCALL(ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1") -HANDLE_LIBCALL(ATOMIC_FETCH_AND_2, "__atomic_fetch_and_2") -HANDLE_LIBCALL(ATOMIC_FETCH_AND_4, "__atomic_fetch_and_4") -HANDLE_LIBCALL(ATOMIC_FETCH_AND_8, "__atomic_fetch_and_8") -HANDLE_LIBCALL(ATOMIC_FETCH_AND_16, "__atomic_fetch_and_16") -HANDLE_LIBCALL(ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1") -HANDLE_LIBCALL(ATOMIC_FETCH_OR_2, "__atomic_fetch_or_2") -HANDLE_LIBCALL(ATOMIC_FETCH_OR_4, "__atomic_fetch_or_4") -HANDLE_LIBCALL(ATOMIC_FETCH_OR_8, "__atomic_fetch_or_8") -HANDLE_LIBCALL(ATOMIC_FETCH_OR_16, "__atomic_fetch_or_16") -HANDLE_LIBCALL(ATOMIC_FETCH_XOR_1, "__atomic_fetch_xor_1") -HANDLE_LIBCALL(ATOMIC_FETCH_XOR_2, "__atomic_fetch_xor_2") -HANDLE_LIBCALL(ATOMIC_FETCH_XOR_4, "__atomic_fetch_xor_4") -HANDLE_LIBCALL(ATOMIC_FETCH_XOR_8, "__atomic_fetch_xor_8") -HANDLE_LIBCALL(ATOMIC_FETCH_XOR_16, "__atomic_fetch_xor_16") -HANDLE_LIBCALL(ATOMIC_FETCH_NAND_1, "__atomic_fetch_nand_1") -HANDLE_LIBCALL(ATOMIC_FETCH_NAND_2, "__atomic_fetch_nand_2") -HANDLE_LIBCALL(ATOMIC_FETCH_NAND_4, "__atomic_fetch_nand_4") -HANDLE_LIBCALL(ATOMIC_FETCH_NAND_8, "__atomic_fetch_nand_8") -HANDLE_LIBCALL(ATOMIC_FETCH_NAND_16, "__atomic_fetch_nand_16") - -// Out-of-line atomics libcalls -#define HLCALLS(A, N) \ - HANDLE_LIBCALL(A##N##_RELAX, nullptr) \ - HANDLE_LIBCALL(A##N##_ACQ, nullptr) \ - HANDLE_LIBCALL(A##N##_REL, nullptr) \ - HANDLE_LIBCALL(A##N##_ACQ_REL, nullptr) -#define HLCALL5(A) \ - HLCALLS(A, 1) HLCALLS(A, 2) HLCALLS(A, 4) HLCALLS(A, 8) HLCALLS(A, 16) -HLCALL5(OUTLINE_ATOMIC_CAS) -HLCALL5(OUTLINE_ATOMIC_SWP) -HLCALL5(OUTLINE_ATOMIC_LDADD) -HLCALL5(OUTLINE_ATOMIC_LDSET) -HLCALL5(OUTLINE_ATOMIC_LDCLR) -HLCALL5(OUTLINE_ATOMIC_LDEOR) -#undef HLCALLS -#undef HLCALL5 - -// Stack Protector Fail -HANDLE_LIBCALL(STACKPROTECTOR_CHECK_FAIL, "__stack_chk_fail") - -// Deoptimization -HANDLE_LIBCALL(DEOPTIMIZE, "__llvm_deoptimize") - -// Return address -HANDLE_LIBCALL(RETURN_ADDRESS, nullptr) - -HANDLE_LIBCALL(UNKNOWN_LIBCALL, nullptr) - diff --git a/suite/synctools/tablegen/include/llvm/IR/SSAContext.h b/suite/synctools/tablegen/include/llvm/IR/SSAContext.h deleted file mode 100644 index 8ca23e3ee0..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/SSAContext.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- SSAContext.h ---------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file declares a specialization of the GenericSSAContext -/// class template for LLVM IR. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_SSACONTEXT_H -#define LLVM_IR_SSACONTEXT_H - -#include "llvm/Support/Printable.h" - -namespace llvm { -class BasicBlock; -class Function; -class Instruction; -class Value; -template class DominatorTreeBase; -template class GenericSSAContext; - -template <> class GenericSSAContext { - Function *F; - -public: - using BlockT = BasicBlock; - using FunctionT = Function; - using InstructionT = Instruction; - using ValueRefT = Value *; - using DominatorTreeT = DominatorTreeBase; - - static BasicBlock *getEntryBlock(Function &F); - - void setFunction(Function &Fn); - Function *getFunction() const { return F; } - - Printable print(BasicBlock *Block) const; - Printable print(Instruction *Inst) const; - Printable print(Value *Value) const; -}; - -using SSAContext = GenericSSAContext; - -} // namespace llvm - -#endif // LLVM_IR_SSACONTEXT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/SafepointIRVerifier.h b/suite/synctools/tablegen/include/llvm/IR/SafepointIRVerifier.h deleted file mode 100644 index 246d236adb..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/SafepointIRVerifier.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- SafepointIRVerifier.h - Checks for GC relocation problems *- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a verifier which is useful for enforcing the relocation -// properties required by a relocating GC. Specifically, it looks for uses of -// the unrelocated value of pointer SSA values after a possible safepoint. It -// attempts to report no false negatives, but may end up reporting false -// positives in rare cases (see the note at the top of the corresponding cpp -// file.) -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_SAFEPOINTIRVERIFIER_H -#define LLVM_IR_SAFEPOINTIRVERIFIER_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class Function; -class FunctionPass; - -/// Run the safepoint verifier over a single function. Crashes on failure. -void verifySafepointIR(Function &F); - -/// Create an instance of the safepoint verifier pass which can be added to -/// a pass pipeline to check for relocation bugs. -FunctionPass *createSafepointIRVerifierPass(); - -/// Create an instance of the safepoint verifier pass which can be added to -/// a pass pipeline to check for relocation bugs. -class SafepointIRVerifierPass : public PassInfoMixin { - -public: - explicit SafepointIRVerifierPass() = default; - - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; -} - -#endif // LLVM_IR_SAFEPOINTIRVERIFIER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Statepoint.h b/suite/synctools/tablegen/include/llvm/IR/Statepoint.h deleted file mode 100644 index 61f3f748b7..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Statepoint.h +++ /dev/null @@ -1,255 +0,0 @@ -//===- llvm/IR/Statepoint.h - gc.statepoint utilities -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains utility functions and a wrapper class analogous to -// CallBase for accessing the fields of gc.statepoint, gc.relocate, -// gc.result intrinsics; and some general utilities helpful when dealing with -// gc.statepoint. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_STATEPOINT_H -#define LLVM_IR_STATEPOINT_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/MathExtras.h" -#include -#include -#include -#include - -namespace llvm { - -/// The statepoint intrinsic accepts a set of flags as its third argument. -/// Valid values come out of this set. -enum class StatepointFlags { - None = 0, - GCTransition = 1, ///< Indicates that this statepoint is a transition from - ///< GC-aware code to code that is not GC-aware. - /// Mark the deopt arguments associated with the statepoint as only being - /// "live-in". By default, deopt arguments are "live-through". "live-through" - /// requires that they the value be live on entry, on exit, and at any point - /// during the call. "live-in" only requires the value be available at the - /// start of the call. In particular, "live-in" values can be placed in - /// unused argument registers or other non-callee saved registers. - DeoptLiveIn = 2, - - MaskAll = 3 ///< A bitmask that includes all valid flags. -}; - -// These two are defined in IntrinsicInst since they're part of the -// IntrinsicInst class hierarchy. -class GCRelocateInst; -class GCResultInst; - -/// Represents a gc.statepoint intrinsic call. This extends directly from -/// CallBase as the IntrinsicInst only supports calls and gc.statepoint is -/// invokable. -class GCStatepointInst : public CallBase { -public: - GCStatepointInst() = delete; - GCStatepointInst(const GCStatepointInst &) = delete; - GCStatepointInst &operator=(const GCStatepointInst &) = delete; - - static bool classof(const CallBase *I) { - if (const Function *CF = I->getCalledFunction()) - return CF->getIntrinsicID() == Intrinsic::experimental_gc_statepoint; - return false; - } - - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - - enum { - IDPos = 0, - NumPatchBytesPos = 1, - CalledFunctionPos = 2, - NumCallArgsPos = 3, - FlagsPos = 4, - CallArgsBeginPos = 5, - }; - - /// Return the ID associated with this statepoint. - uint64_t getID() const { - return cast(getArgOperand(IDPos))->getZExtValue(); - } - - /// Return the number of patchable bytes associated with this statepoint. - uint32_t getNumPatchBytes() const { - const Value *NumPatchBytesVal = getArgOperand(NumPatchBytesPos); - uint64_t NumPatchBytes = - cast(NumPatchBytesVal)->getZExtValue(); - assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); - return NumPatchBytes; - } - - /// Number of arguments to be passed to the actual callee. - int getNumCallArgs() const { - return cast(getArgOperand(NumCallArgsPos))->getZExtValue(); - } - - uint64_t getFlags() const { - return cast(getArgOperand(FlagsPos))->getZExtValue(); - } - - /// Return the value actually being called or invoked. - Value *getActualCalledOperand() const { - return getArgOperand(CalledFunctionPos); - } - - /// Returns the function called if this is a wrapping a direct call, and null - /// otherwise. - Function *getActualCalledFunction() const { - return dyn_cast_or_null(getActualCalledOperand()); - } - - /// Return the type of the value returned by the call underlying the - /// statepoint. - Type *getActualReturnType() const { - auto *CalleeTy = - getActualCalledOperand()->getType()->getPointerElementType(); - return cast(CalleeTy)->getReturnType(); - } - - - /// Return the number of arguments to the underlying call. - size_t actual_arg_size() const { return getNumCallArgs(); } - /// Return an iterator to the beginning of the arguments to the underlying call - const_op_iterator actual_arg_begin() const { - assert(CallArgsBeginPos <= (int)arg_size()); - return arg_begin() + CallArgsBeginPos; - } - /// Return an end iterator of the arguments to the underlying call - const_op_iterator actual_arg_end() const { - auto I = actual_arg_begin() + actual_arg_size(); - assert((arg_end() - I) == 2); - return I; - } - /// range adapter for actual call arguments - iterator_range actual_args() const { - return make_range(actual_arg_begin(), actual_arg_end()); - } - - const_op_iterator gc_transition_args_begin() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) - return Opt->Inputs.begin(); - return arg_end(); - } - const_op_iterator gc_transition_args_end() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) - return Opt->Inputs.end(); - return arg_end(); - } - - /// range adapter for GC transition arguments - iterator_range gc_transition_args() const { - return make_range(gc_transition_args_begin(), gc_transition_args_end()); - } - - const_op_iterator deopt_begin() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) - return Opt->Inputs.begin(); - return arg_end(); - } - const_op_iterator deopt_end() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) - return Opt->Inputs.end(); - return arg_end(); - } - - /// range adapter for vm state arguments - iterator_range deopt_operands() const { - return make_range(deopt_begin(), deopt_end()); - } - - /// Returns an iterator to the beginning of the argument range describing gc - /// values for the statepoint. - const_op_iterator gc_args_begin() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) - return Opt->Inputs.begin(); - return arg_end(); - } - - /// Return an end iterator for the gc argument range - const_op_iterator gc_args_end() const { - if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) - return Opt->Inputs.end(); - return arg_end(); - } - - /// range adapter for gc arguments - iterator_range gc_args() const { - return make_range(gc_args_begin(), gc_args_end()); - } - - - /// Get list of all gc reloactes linked to this statepoint - /// May contain several relocations for the same base/derived pair. - /// For example this could happen due to relocations on unwinding - /// path of invoke. - inline std::vector getGCRelocates() const; -}; - -std::vector GCStatepointInst::getGCRelocates() const { - std::vector Result; - - // Search for relocated pointers. Note that working backwards from the - // gc_relocates ensures that we only get pairs which are actually relocated - // and used after the statepoint. - for (const User *U : users()) - if (auto *Relocate = dyn_cast(U)) - Result.push_back(Relocate); - - auto *StatepointInvoke = dyn_cast(this); - if (!StatepointInvoke) - return Result; - - // We need to scan thorough exceptional relocations if it is invoke statepoint - LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); - - // Search for gc relocates that are attached to this landingpad. - for (const User *LandingPadUser : LandingPad->users()) { - if (auto *Relocate = dyn_cast(LandingPadUser)) - Result.push_back(Relocate); - } - return Result; -} - -/// Call sites that get wrapped by a gc.statepoint (currently only in -/// RewriteStatepointsForGC and potentially in other passes in the future) can -/// have attributes that describe properties of gc.statepoint call they will be -/// eventually be wrapped in. This struct is used represent such directives. -struct StatepointDirectives { - Optional NumPatchBytes; - Optional StatepointID; - - static const uint64_t DefaultStatepointID = 0xABCDEF00; - static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F; -}; - -/// Parse out statepoint directives from the function attributes present in \p -/// AS. -StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS); - -/// Return \c true if the \p Attr is an attribute that is a statepoint -/// directive. -bool isStatepointDirectiveAttr(Attribute Attr); - -} // end namespace llvm - -#endif // LLVM_IR_STATEPOINT_H diff --git a/suite/synctools/tablegen/include/llvm/IR/StructuralHash.h b/suite/synctools/tablegen/include/llvm/IR/StructuralHash.h deleted file mode 100644 index eb63a21403..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/StructuralHash.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- llvm/IR/StructuralHash.h - IR Hash for expensive checks --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides hashing of the LLVM IR structure to be used to check -// Passes modification status. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_STRUCTURALHASH_H -#define LLVM_IR_STRUCTURALHASH_H - -#ifdef EXPENSIVE_CHECKS - -#include - -// This header is only meant to be used when -DEXPENSIVE_CHECKS is set -namespace llvm { - -class Function; -class Module; - -uint64_t StructuralHash(const Function &F); -uint64_t StructuralHash(const Module &M); - -} // end namespace llvm - -#endif - -#endif // LLVM_IR_STRUCTURALHASH_H diff --git a/suite/synctools/tablegen/include/llvm/IR/SymbolTableListTraits.h b/suite/synctools/tablegen/include/llvm/IR/SymbolTableListTraits.h deleted file mode 100644 index 8af712374b..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/SymbolTableListTraits.h +++ /dev/null @@ -1,119 +0,0 @@ -//===- llvm/SymbolTableListTraits.h - Traits for iplist ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a generic class that is used to implement the automatic -// symbol table manipulation that occurs when you put (for example) a named -// instruction into a basic block. -// -// The way that this is implemented is by using a special traits class with the -// intrusive list that makes up the list of instructions in a basic block. When -// a new element is added to the list of instructions, the traits class is -// notified, allowing the symbol table to be updated. -// -// This generic class implements the traits class. It must be generic so that -// it can work for all uses it, which include lists of instructions, basic -// blocks, arguments, functions, global variables, etc... -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H -#define LLVM_IR_SYMBOLTABLELISTTRAITS_H - -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/simple_ilist.h" -#include - -namespace llvm { - -class Argument; -class BasicBlock; -class Function; -class GlobalAlias; -class GlobalIFunc; -class GlobalVariable; -class Instruction; -class Module; -class ValueSymbolTable; - -/// Template metafunction to get the parent type for a symbol table list. -/// -/// Implementations create a typedef called \c type so that we only need a -/// single template parameter for the list and traits. -template struct SymbolTableListParentType {}; - -#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \ - template <> struct SymbolTableListParentType { using type = PARENT; }; -DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module) -DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module) -#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE - -template class SymbolTableList; - -// ValueSubClass - The type of objects that I hold, e.g. Instruction. -// ItemParentClass - The type of object that owns the list, e.g. BasicBlock. -// -template -class SymbolTableListTraits : public ilist_alloc_traits { - using ListTy = SymbolTableList; - using iterator = typename simple_ilist::iterator; - using ItemParentClass = - typename SymbolTableListParentType::type; - -public: - SymbolTableListTraits() = default; - -private: - /// getListOwner - Return the object that owns this list. If this is a list - /// of instructions, it returns the BasicBlock that owns them. - ItemParentClass *getListOwner() { - size_t Offset = reinterpret_cast( - &((ItemParentClass *)nullptr->*ItemParentClass::getSublistAccess( - static_cast( - nullptr)))); - ListTy *Anchor = static_cast(this); - return reinterpret_cast(reinterpret_cast(Anchor)- - Offset); - } - - static ListTy &getList(ItemParentClass *Par) { - return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr)); - } - - static ValueSymbolTable *getSymTab(ItemParentClass *Par) { - return Par ? toPtr(Par->getValueSymbolTable()) : nullptr; - } - -public: - void addNodeToList(ValueSubClass *V); - void removeNodeFromList(ValueSubClass *V); - void transferNodesFromList(SymbolTableListTraits &L2, iterator first, - iterator last); - // private: - template - void setSymTabObject(TPtr *, TPtr); - static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; } - static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; } -}; - -/// List that automatically updates parent links and symbol tables. -/// -/// When nodes are inserted into and removed from this list, the associated -/// symbol table will be automatically updated. Similarly, parent links get -/// updated automatically. -template -class SymbolTableList - : public iplist_impl, SymbolTableListTraits> {}; - -} // end namespace llvm - -#endif // LLVM_IR_SYMBOLTABLELISTTRAITS_H diff --git a/suite/synctools/tablegen/include/llvm/IR/TrackingMDRef.h b/suite/synctools/tablegen/include/llvm/IR/TrackingMDRef.h deleted file mode 100644 index 229dc73357..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/TrackingMDRef.h +++ /dev/null @@ -1,177 +0,0 @@ -//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// References to metadata that track RAUW. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_TRACKINGMDREF_H -#define LLVM_IR_TRACKINGMDREF_H - -#include "llvm/IR/Metadata.h" -#include -#include - -namespace llvm { - -/// Tracking metadata reference. -/// -/// This class behaves like \a TrackingVH, but for metadata. -class TrackingMDRef { - Metadata *MD = nullptr; - -public: - TrackingMDRef() = default; - explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } - - TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } - TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } - - TrackingMDRef &operator=(TrackingMDRef &&X) { - if (&X == this) - return *this; - - untrack(); - MD = X.MD; - retrack(X); - return *this; - } - - TrackingMDRef &operator=(const TrackingMDRef &X) { - if (&X == this) - return *this; - - untrack(); - MD = X.MD; - track(); - return *this; - } - - ~TrackingMDRef() { untrack(); } - - Metadata *get() const { return MD; } - operator Metadata *() const { return get(); } - Metadata *operator->() const { return get(); } - Metadata &operator*() const { return *get(); } - - void reset() { - untrack(); - MD = nullptr; - } - void reset(Metadata *MD) { - untrack(); - this->MD = MD; - track(); - } - - /// Check whether this has a trivial destructor. - /// - /// If \c MD isn't replaceable, the destructor will be a no-op. - bool hasTrivialDestructor() const { - return !MD || !MetadataTracking::isReplaceable(*MD); - } - - bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } - bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } - -private: - void track() { - if (MD) - MetadataTracking::track(MD); - } - - void untrack() { - if (MD) - MetadataTracking::untrack(MD); - } - - void retrack(TrackingMDRef &X) { - assert(MD == X.MD && "Expected values to match"); - if (X.MD) { - MetadataTracking::retrack(X.MD, MD); - X.MD = nullptr; - } - } -}; - -/// Typed tracking ref. -/// -/// Track references of a particular type. It's useful to use this for \a -/// MDNode and \a ValueAsMetadata. -template class TypedTrackingMDRef { - TrackingMDRef Ref; - -public: - TypedTrackingMDRef() = default; - explicit TypedTrackingMDRef(T *MD) : Ref(static_cast(MD)) {} - - TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} - TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} - - TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { - Ref = std::move(X.Ref); - return *this; - } - - TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { - Ref = X.Ref; - return *this; - } - - T *get() const { return (T *)Ref.get(); } - operator T *() const { return get(); } - T *operator->() const { return get(); } - T &operator*() const { return *get(); } - - bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } - bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } - - void reset() { Ref.reset(); } - void reset(T *MD) { Ref.reset(static_cast(MD)); } - - /// Check whether this has a trivial destructor. - bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } -}; - -using TrackingMDNodeRef = TypedTrackingMDRef; -using TrackingValueAsMetadataRef = TypedTrackingMDRef; - -// Expose the underlying metadata to casting. -template <> struct simplify_type { - using SimpleType = Metadata *; - - static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } -}; - -template <> struct simplify_type { - using SimpleType = Metadata *; - - static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { - return MD.get(); - } -}; - -template struct simplify_type> { - using SimpleType = T *; - - static SimpleType getSimplifiedValue(TypedTrackingMDRef &MD) { - return MD.get(); - } -}; - -template struct simplify_type> { - using SimpleType = T *; - - static SimpleType getSimplifiedValue(const TypedTrackingMDRef &MD) { - return MD.get(); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_TRACKINGMDREF_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Type.h b/suite/synctools/tablegen/include/llvm/IR/Type.h deleted file mode 100644 index e4e8a5529c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Type.h +++ /dev/null @@ -1,508 +0,0 @@ -//===- llvm/Type.h - Classes for handling data types ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the Type class. For more "Type" -// stuff, look in DerivedTypes.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_TYPE_H -#define LLVM_IR_TYPE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TypeSize.h" -#include -#include -#include - -namespace llvm { - -class IntegerType; -struct fltSemantics; -class LLVMContext; -class PointerType; -class raw_ostream; -class StringRef; -template class SmallPtrSetImpl; - -/// The instances of the Type class are immutable: once they are created, -/// they are never changed. Also note that only one instance of a particular -/// type is ever created. Thus seeing if two types are equal is a matter of -/// doing a trivial pointer comparison. To enforce that no two equal instances -/// are created, Type instances can only be created via static factory methods -/// in class Type and in derived classes. Once allocated, Types are never -/// free'd. -/// -class Type { -public: - //===--------------------------------------------------------------------===// - /// Definitions of all of the base types for the Type system. Based on this - /// value, you can cast to a class defined in DerivedTypes.h. - /// Note: If you add an element to this, you need to add an element to the - /// Type::getPrimitiveType function, or else things will break! - /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. - /// - enum TypeID { - // PrimitiveTypes - HalfTyID = 0, ///< 16-bit floating point type - BFloatTyID, ///< 16-bit floating point type (7-bit significand) - FloatTyID, ///< 32-bit floating point type - DoubleTyID, ///< 64-bit floating point type - X86_FP80TyID, ///< 80-bit floating point type (X87) - FP128TyID, ///< 128-bit floating point type (112-bit significand) - PPC_FP128TyID, ///< 128-bit floating point type (two 64-bits, PowerPC) - VoidTyID, ///< type with no size - LabelTyID, ///< Labels - MetadataTyID, ///< Metadata - X86_MMXTyID, ///< MMX vectors (64 bits, X86 specific) - X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific) - TokenTyID, ///< Tokens - - // Derived types... see DerivedTypes.h file. - IntegerTyID, ///< Arbitrary bit width integers - FunctionTyID, ///< Functions - PointerTyID, ///< Pointers - StructTyID, ///< Structures - ArrayTyID, ///< Arrays - FixedVectorTyID, ///< Fixed width SIMD vector type - ScalableVectorTyID ///< Scalable SIMD vector type - }; - -private: - /// This refers to the LLVMContext in which this type was uniqued. - LLVMContext &Context; - - TypeID ID : 8; // The current base type of this type. - unsigned SubclassData : 24; // Space for subclasses to store data. - // Note that this should be synchronized with - // MAX_INT_BITS value in IntegerType class. - -protected: - friend class LLVMContextImpl; - - explicit Type(LLVMContext &C, TypeID tid) - : Context(C), ID(tid), SubclassData(0) {} - ~Type() = default; - - unsigned getSubclassData() const { return SubclassData; } - - void setSubclassData(unsigned val) { - SubclassData = val; - // Ensure we don't have any accidental truncation. - assert(getSubclassData() == val && "Subclass data too large for field"); - } - - /// Keeps track of how many Type*'s there are in the ContainedTys list. - unsigned NumContainedTys = 0; - - /// A pointer to the array of Types contained by this Type. For example, this - /// includes the arguments of a function type, the elements of a structure, - /// the pointee of a pointer, the element type of an array, etc. This pointer - /// may be 0 for types that don't contain other types (Integer, Double, - /// Float). - Type * const *ContainedTys = nullptr; - -public: - /// Print the current type. - /// Omit the type details if \p NoDetails == true. - /// E.g., let %st = type { i32, i16 } - /// When \p NoDetails is true, we only print %st. - /// Put differently, \p NoDetails prints the type as if - /// inlined with the operands when printing an instruction. - void print(raw_ostream &O, bool IsForDebug = false, - bool NoDetails = false) const; - - void dump() const; - - /// Return the LLVMContext in which this type was uniqued. - LLVMContext &getContext() const { return Context; } - - //===--------------------------------------------------------------------===// - // Accessors for working with types. - // - - /// Return the type id for the type. This will return one of the TypeID enum - /// elements defined above. - TypeID getTypeID() const { return ID; } - - /// Return true if this is 'void'. - bool isVoidTy() const { return getTypeID() == VoidTyID; } - - /// Return true if this is 'half', a 16-bit IEEE fp type. - bool isHalfTy() const { return getTypeID() == HalfTyID; } - - /// Return true if this is 'bfloat', a 16-bit bfloat type. - bool isBFloatTy() const { return getTypeID() == BFloatTyID; } - - /// Return true if this is 'float', a 32-bit IEEE fp type. - bool isFloatTy() const { return getTypeID() == FloatTyID; } - - /// Return true if this is 'double', a 64-bit IEEE fp type. - bool isDoubleTy() const { return getTypeID() == DoubleTyID; } - - /// Return true if this is x86 long double. - bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; } - - /// Return true if this is 'fp128'. - bool isFP128Ty() const { return getTypeID() == FP128TyID; } - - /// Return true if this is powerpc long double. - bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; } - - /// Return true if this is one of the six floating-point types - bool isFloatingPointTy() const { - return getTypeID() == HalfTyID || getTypeID() == BFloatTyID || - getTypeID() == FloatTyID || getTypeID() == DoubleTyID || - getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID || - getTypeID() == PPC_FP128TyID; - } - - const fltSemantics &getFltSemantics() const; - - /// Return true if this is X86 MMX. - bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; } - - /// Return true if this is X86 AMX. - bool isX86_AMXTy() const { return getTypeID() == X86_AMXTyID; } - - /// Return true if this is a FP type or a vector of FP. - bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); } - - /// Return true if this is 'label'. - bool isLabelTy() const { return getTypeID() == LabelTyID; } - - /// Return true if this is 'metadata'. - bool isMetadataTy() const { return getTypeID() == MetadataTyID; } - - /// Return true if this is 'token'. - bool isTokenTy() const { return getTypeID() == TokenTyID; } - - /// True if this is an instance of IntegerType. - bool isIntegerTy() const { return getTypeID() == IntegerTyID; } - - /// Return true if this is an IntegerType of the given width. - bool isIntegerTy(unsigned Bitwidth) const; - - /// Return true if this is an integer type or a vector of integer types. - bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } - - /// Return true if this is an integer type or a vector of integer types of - /// the given width. - bool isIntOrIntVectorTy(unsigned BitWidth) const { - return getScalarType()->isIntegerTy(BitWidth); - } - - /// Return true if this is an integer type or a pointer type. - bool isIntOrPtrTy() const { return isIntegerTy() || isPointerTy(); } - - /// True if this is an instance of FunctionType. - bool isFunctionTy() const { return getTypeID() == FunctionTyID; } - - /// True if this is an instance of StructType. - bool isStructTy() const { return getTypeID() == StructTyID; } - - /// True if this is an instance of ArrayType. - bool isArrayTy() const { return getTypeID() == ArrayTyID; } - - /// True if this is an instance of PointerType. - bool isPointerTy() const { return getTypeID() == PointerTyID; } - - /// True if this is an instance of an opaque PointerType. - bool isOpaquePointerTy() const; - - /// Return true if this is a pointer type or a vector of pointer types. - bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } - - /// True if this is an instance of VectorType. - inline bool isVectorTy() const { - return getTypeID() == ScalableVectorTyID || getTypeID() == FixedVectorTyID; - } - - /// Return true if this type could be converted with a lossless BitCast to - /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the - /// same size only where no re-interpretation of the bits is done. - /// Determine if this type could be losslessly bitcast to Ty - bool canLosslesslyBitCastTo(Type *Ty) const; - - /// Return true if this type is empty, that is, it has no elements or all of - /// its elements are empty. - bool isEmptyTy() const; - - /// Return true if the type is "first class", meaning it is a valid type for a - /// Value. - bool isFirstClassType() const { - return getTypeID() != FunctionTyID && getTypeID() != VoidTyID; - } - - /// Return true if the type is a valid type for a register in codegen. This - /// includes all first-class types except struct and array types. - bool isSingleValueType() const { - return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() || - isPointerTy() || isVectorTy() || isX86_AMXTy(); - } - - /// Return true if the type is an aggregate type. This means it is valid as - /// the first operand of an insertvalue or extractvalue instruction. This - /// includes struct and array types, but does not include vector types. - bool isAggregateType() const { - return getTypeID() == StructTyID || getTypeID() == ArrayTyID; - } - - /// Return true if it makes sense to take the size of this type. To get the - /// actual size for a particular target, it is reasonable to use the - /// DataLayout subsystem to do this. - bool isSized(SmallPtrSetImpl *Visited = nullptr) const { - // If it's a primitive, it is always sized. - if (getTypeID() == IntegerTyID || isFloatingPointTy() || - getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID || - getTypeID() == X86_AMXTyID) - return true; - // If it is not something that can have a size (e.g. a function or label), - // it doesn't have a size. - if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && !isVectorTy()) - return false; - // Otherwise we have to try harder to decide. - return isSizedDerivedType(Visited); - } - - /// Return the basic size of this type if it is a primitive type. These are - /// fixed by LLVM and are not target-dependent. - /// This will return zero if the type does not have a size or is not a - /// primitive type. - /// - /// If this is a scalable vector type, the scalable property will be set and - /// the runtime size will be a positive integer multiple of the base size. - /// - /// Note that this may not reflect the size of memory allocated for an - /// instance of the type or the number of bytes that are written when an - /// instance of the type is stored to memory. The DataLayout class provides - /// additional query functions to provide this information. - /// - TypeSize getPrimitiveSizeInBits() const LLVM_READONLY; - - /// If this is a vector type, return the getPrimitiveSizeInBits value for the - /// element type. Otherwise return the getPrimitiveSizeInBits value for this - /// type. - unsigned getScalarSizeInBits() const LLVM_READONLY; - - /// Return the width of the mantissa of this type. This is only valid on - /// floating-point types. If the FP type does not have a stable mantissa (e.g. - /// ppc long double), this method returns -1. - int getFPMantissaWidth() const; - - /// Return whether the type is IEEE compatible, as defined by the eponymous - /// method in APFloat. - bool isIEEE() const; - - /// If this is a vector type, return the element type, otherwise return - /// 'this'. - inline Type *getScalarType() const { - if (isVectorTy()) - return getContainedType(0); - return const_cast(this); - } - - //===--------------------------------------------------------------------===// - // Type Iteration support. - // - using subtype_iterator = Type * const *; - - subtype_iterator subtype_begin() const { return ContainedTys; } - subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} - ArrayRef subtypes() const { - return makeArrayRef(subtype_begin(), subtype_end()); - } - - using subtype_reverse_iterator = std::reverse_iterator; - - subtype_reverse_iterator subtype_rbegin() const { - return subtype_reverse_iterator(subtype_end()); - } - subtype_reverse_iterator subtype_rend() const { - return subtype_reverse_iterator(subtype_begin()); - } - - /// This method is used to implement the type iterator (defined at the end of - /// the file). For derived types, this returns the types 'contained' in the - /// derived type. - Type *getContainedType(unsigned i) const { - assert(i < NumContainedTys && "Index out of range!"); - return ContainedTys[i]; - } - - /// Return the number of types in the derived type. - unsigned getNumContainedTypes() const { return NumContainedTys; } - - //===--------------------------------------------------------------------===// - // Helper methods corresponding to subclass methods. This forces a cast to - // the specified subclass and calls its accessor. "getArrayNumElements" (for - // example) is shorthand for cast(Ty)->getNumElements(). This is - // only intended to cover the core methods that are frequently used, helper - // methods should not be added here. - - inline unsigned getIntegerBitWidth() const; - - inline Type *getFunctionParamType(unsigned i) const; - inline unsigned getFunctionNumParams() const; - inline bool isFunctionVarArg() const; - - inline StringRef getStructName() const; - inline unsigned getStructNumElements() const; - inline Type *getStructElementType(unsigned N) const; - - inline uint64_t getArrayNumElements() const; - - Type *getArrayElementType() const { - assert(getTypeID() == ArrayTyID); - return ContainedTys[0]; - } - - /// This method is deprecated without replacement. Pointer element types are - /// not available with opaque pointers. - Type *getPointerElementType() const { - return getNonOpaquePointerElementType(); - } - - /// Only use this method in code that is not reachable with opaque pointers, - /// or part of deprecated methods that will be removed as part of the opaque - /// pointers transition. - Type *getNonOpaquePointerElementType() const { - assert(getTypeID() == PointerTyID); - assert(NumContainedTys && - "Attempting to get element type of opaque pointer"); - return ContainedTys[0]; - } - - /// Given vector type, change the element type, - /// whilst keeping the old number of elements. - /// For non-vectors simply returns \p EltTy. - inline Type *getWithNewType(Type *EltTy) const; - - /// Given an integer or vector type, change the lane bitwidth to NewBitwidth, - /// whilst keeping the old number of lanes. - inline Type *getWithNewBitWidth(unsigned NewBitWidth) const; - - /// Given scalar/vector integer type, returns a type with elements twice as - /// wide as in the original type. For vectors, preserves element count. - inline Type *getExtendedType() const; - - /// Get the address space of this pointer or pointer vector type. - inline unsigned getPointerAddressSpace() const; - - //===--------------------------------------------------------------------===// - // Static members exported by the Type class itself. Useful for getting - // instances of Type. - // - - /// Return a type based on an identifier. - static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); - - //===--------------------------------------------------------------------===// - // These are the builtin types that are always available. - // - static Type *getVoidTy(LLVMContext &C); - static Type *getLabelTy(LLVMContext &C); - static Type *getHalfTy(LLVMContext &C); - static Type *getBFloatTy(LLVMContext &C); - static Type *getFloatTy(LLVMContext &C); - static Type *getDoubleTy(LLVMContext &C); - static Type *getMetadataTy(LLVMContext &C); - static Type *getX86_FP80Ty(LLVMContext &C); - static Type *getFP128Ty(LLVMContext &C); - static Type *getPPC_FP128Ty(LLVMContext &C); - static Type *getX86_MMXTy(LLVMContext &C); - static Type *getX86_AMXTy(LLVMContext &C); - static Type *getTokenTy(LLVMContext &C); - static IntegerType *getIntNTy(LLVMContext &C, unsigned N); - static IntegerType *getInt1Ty(LLVMContext &C); - static IntegerType *getInt8Ty(LLVMContext &C); - static IntegerType *getInt16Ty(LLVMContext &C); - static IntegerType *getInt32Ty(LLVMContext &C); - static IntegerType *getInt64Ty(LLVMContext &C); - static IntegerType *getInt128Ty(LLVMContext &C); - template static Type *getScalarTy(LLVMContext &C) { - int noOfBits = sizeof(ScalarTy) * CHAR_BIT; - if (std::is_integral::value) { - return (Type*) Type::getIntNTy(C, noOfBits); - } else if (std::is_floating_point::value) { - switch (noOfBits) { - case 32: - return Type::getFloatTy(C); - case 64: - return Type::getDoubleTy(C); - } - } - llvm_unreachable("Unsupported type in Type::getScalarTy"); - } - static Type *getFloatingPointTy(LLVMContext &C, const fltSemantics &S); - - //===--------------------------------------------------------------------===// - // Convenience methods for getting pointer types with one of the above builtin - // types as pointee. - // - static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getBFloatPtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getX86_AMXPtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0); - static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); - static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); - - /// Return a pointer to the current type. This is equivalent to - /// PointerType::get(Foo, AddrSpace). - /// TODO: Remove this after opaque pointer transition is complete. - PointerType *getPointerTo(unsigned AddrSpace = 0) const; - -private: - /// Derived types like structures and arrays are sized iff all of the members - /// of the type are sized as well. Since asking for their size is relatively - /// uncommon, move this operation out-of-line. - bool isSizedDerivedType(SmallPtrSetImpl *Visited = nullptr) const; -}; - -// Printing of types. -inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) { - T.print(OS); - return OS; -} - -// allow isa(x) to work without DerivedTypes.h included. -template <> struct isa_impl { - static inline bool doit(const Type &Ty) { - return Ty.getTypeID() == Type::PointerTyID; - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef) - -/* Specialized opaque type conversions. - */ -inline Type **unwrap(LLVMTypeRef* Tys) { - return reinterpret_cast(Tys); -} - -inline LLVMTypeRef *wrap(Type **Tys) { - return reinterpret_cast(const_cast(Tys)); -} - -} // end namespace llvm - -#endif // LLVM_IR_TYPE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/TypeFinder.h b/suite/synctools/tablegen/include/llvm/IR/TypeFinder.h deleted file mode 100644 index dd2b70c65c..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/TypeFinder.h +++ /dev/null @@ -1,86 +0,0 @@ -//===- llvm/IR/TypeFinder.h - Class to find used struct types ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the TypeFinder class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_TYPEFINDER_H -#define LLVM_IR_TYPEFINDER_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/IR/Attributes.h" -#include -#include - -namespace llvm { - -class MDNode; -class Module; -class StructType; -class Type; -class Value; - -/// TypeFinder - Walk over a module, identifying all of the types that are -/// used by the module. -class TypeFinder { - // To avoid walking constant expressions multiple times and other IR - // objects, we keep several helper maps. - DenseSet VisitedConstants; - DenseSet VisitedMetadata; - DenseSet VisitedAttributes; - DenseSet VisitedTypes; - - std::vector StructTypes; - bool OnlyNamed = false; - -public: - TypeFinder() = default; - - void run(const Module &M, bool onlyNamed); - void clear(); - - using iterator = std::vector::iterator; - using const_iterator = std::vector::const_iterator; - - iterator begin() { return StructTypes.begin(); } - iterator end() { return StructTypes.end(); } - - const_iterator begin() const { return StructTypes.begin(); } - const_iterator end() const { return StructTypes.end(); } - - bool empty() const { return StructTypes.empty(); } - size_t size() const { return StructTypes.size(); } - iterator erase(iterator I, iterator E) { return StructTypes.erase(I, E); } - - StructType *&operator[](unsigned Idx) { return StructTypes[Idx]; } - - DenseSet &getVisitedMetadata() { return VisitedMetadata; } - -private: - /// incorporateType - This method adds the type to the list of used - /// structures if it's not in there already. - void incorporateType(Type *Ty); - - /// incorporateValue - This method is used to walk operand lists finding types - /// hiding in constant expressions and other operands that won't be walked in - /// other ways. GlobalValues, basic blocks, instructions, and inst operands - /// are all explicitly enumerated. - void incorporateValue(const Value *V); - - /// incorporateMDNode - This method is used to walk the operands of an MDNode - /// to find types hiding within. - void incorporateMDNode(const MDNode *V); - - /// Incorporate types referenced by attributes. - void incorporateAttributes(AttributeList AL); -}; - -} // end namespace llvm - -#endif // LLVM_IR_TYPEFINDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Use.h b/suite/synctools/tablegen/include/llvm/IR/Use.h deleted file mode 100644 index 64b86f3a43..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Use.h +++ /dev/null @@ -1,131 +0,0 @@ -//===- llvm/Use.h - Definition of the Use class -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This defines the Use class. The Use class represents the operand of an -/// instruction or some other User instance which refers to a Value. The Use -/// class keeps the "use list" of the referenced value up to date. -/// -/// Pointer tagging is used to efficiently find the User corresponding to a Use -/// without having to store a User pointer in every Use. A User is preceded in -/// memory by all the Uses corresponding to its operands, and the low bits of -/// one of the fields (Prev) of the Use class are used to encode offsets to be -/// able to find that User given a pointer to any Use. For details, see: -/// -/// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_USE_H -#define LLVM_IR_USE_H - -#include "llvm-c/Types.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { - -template struct simplify_type; -class User; -class Value; - -/// A Use represents the edge between a Value definition and its users. -/// -/// This is notionally a two-dimensional linked list. It supports traversing -/// all of the uses for a particular value definition. It also supports jumping -/// directly to the used value when we arrive from the User's operands, and -/// jumping directly to the User when we arrive from the Value's uses. -class Use { -public: - Use(const Use &U) = delete; - - /// Provide a fast substitute to std::swap - /// that also works with less standard-compliant compilers - void swap(Use &RHS); - -private: - /// Destructor - Only for zap() - ~Use() { - if (Val) - removeFromList(); - } - - /// Constructor - Use(User *Parent) : Parent(Parent) {} - -public: - friend class Value; - friend class User; - - operator Value *() const { return Val; } - Value *get() const { return Val; } - - /// Returns the User that contains this Use. - /// - /// For an instruction operand, for example, this will return the - /// instruction. - User *getUser() const { return Parent; }; - - inline void set(Value *Val); - - inline Value *operator=(Value *RHS); - inline const Use &operator=(const Use &RHS); - - Value *operator->() { return Val; } - const Value *operator->() const { return Val; } - - Use *getNext() const { return Next; } - - /// Return the operand # of this use in its User. - unsigned getOperandNo() const; - - /// Destroys Use operands when the number of operands of - /// a User changes. - static void zap(Use *Start, const Use *Stop, bool del = false); - -private: - - Value *Val = nullptr; - Use *Next = nullptr; - Use **Prev = nullptr; - User *Parent = nullptr; - - void addToList(Use **List) { - Next = *List; - if (Next) - Next->Prev = &Next; - Prev = List; - *Prev = this; - } - - void removeFromList() { - *Prev = Next; - if (Next) - Next->Prev = Prev; - } -}; - -/// Allow clients to treat uses just like values when using -/// casting operators. -template <> struct simplify_type { - using SimpleType = Value *; - - static SimpleType getSimplifiedValue(Use &Val) { return Val.get(); } -}; -template <> struct simplify_type { - using SimpleType = /*const*/ Value *; - - static SimpleType getSimplifiedValue(const Use &Val) { return Val.get(); } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef) - -} // end namespace llvm - -#endif // LLVM_IR_USE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/UseListOrder.h b/suite/synctools/tablegen/include/llvm/IR/UseListOrder.h deleted file mode 100644 index a1f313e269..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/UseListOrder.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file has structures and command-line options for preserving use-list -// order. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_USELISTORDER_H -#define LLVM_IR_USELISTORDER_H - -#include -#include - -namespace llvm { - -class Function; -class Value; - -/// Structure to hold a use-list order. -struct UseListOrder { - const Value *V = nullptr; - const Function *F = nullptr; - std::vector Shuffle; - - UseListOrder(const Value *V, const Function *F, size_t ShuffleSize) - : V(V), F(F), Shuffle(ShuffleSize) {} - - UseListOrder() = default; - UseListOrder(UseListOrder &&) = default; - UseListOrder &operator=(UseListOrder &&) = default; -}; - -using UseListOrderStack = std::vector; - -} // end namespace llvm - -#endif // LLVM_IR_USELISTORDER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/User.h b/suite/synctools/tablegen/include/llvm/IR/User.h deleted file mode 100644 index 221bb5b2cb..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/User.h +++ /dev/null @@ -1,339 +0,0 @@ -//===- llvm/User.h - User class definition ----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class defines the interface that one who uses a Value must implement. -// Each instance of the Value class keeps track of what User's have handles -// to it. -// -// * Instructions are the largest class of Users. -// * Constants may be users of other constants (think arrays and stuff) -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_USER_H -#define LLVM_IR_USER_H - -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Use.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include - -namespace llvm { - -template class ArrayRef; -template class MutableArrayRef; - -/// Compile-time customization of User operands. -/// -/// Customizes operand-related allocators and accessors. -template -struct OperandTraits; - -class User : public Value { - template - friend struct HungoffOperandTraits; - - LLVM_ATTRIBUTE_ALWAYS_INLINE static void * - allocateFixedOperandUser(size_t, unsigned, unsigned); - -protected: - /// Allocate a User with an operand pointer co-allocated. - /// - /// This is used for subclasses which need to allocate a variable number - /// of operands, ie, 'hung off uses'. - void *operator new(size_t Size); - - /// Allocate a User with the operands co-allocated. - /// - /// This is used for subclasses which have a fixed number of operands. - void *operator new(size_t Size, unsigned Us); - - /// Allocate a User with the operands co-allocated. If DescBytes is non-zero - /// then allocate an additional DescBytes bytes before the operands. These - /// bytes can be accessed by calling getDescriptor. - /// - /// DescBytes needs to be divisible by sizeof(void *). The allocated - /// descriptor, if any, is aligned to sizeof(void *) bytes. - /// - /// This is used for subclasses which have a fixed number of operands. - void *operator new(size_t Size, unsigned Us, unsigned DescBytes); - - User(Type *ty, unsigned vty, Use *, unsigned NumOps) - : Value(ty, vty) { - assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands"); - NumUserOperands = NumOps; - // If we have hung off uses, then the operand list should initially be - // null. - assert((!HasHungOffUses || !getOperandList()) && - "Error in initializing hung off uses for User"); - } - - /// Allocate the array of Uses, followed by a pointer - /// (with bottom bit set) to the User. - /// \param IsPhi identifies callers which are phi nodes and which need - /// N BasicBlock* allocated along with N - void allocHungoffUses(unsigned N, bool IsPhi = false); - - /// Grow the number of hung off uses. Note that allocHungoffUses - /// should be called if there are no uses. - void growHungoffUses(unsigned N, bool IsPhi = false); - -protected: - ~User() = default; // Use deleteValue() to delete a generic Instruction. - -public: - User(const User &) = delete; - - /// Free memory allocated for User and Use objects. - void operator delete(void *Usr); - /// Placement delete - required by std, called if the ctor throws. - void operator delete(void *Usr, unsigned) { - // Note: If a subclass manipulates the information which is required to calculate the - // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has - // to restore the changed information to the original value, since the dtor of that class - // is not called if the ctor fails. - User::operator delete(Usr); - -#ifndef LLVM_ENABLE_EXCEPTIONS - llvm_unreachable("Constructor throws?"); -#endif - } - /// Placement delete - required by std, called if the ctor throws. - void operator delete(void *Usr, unsigned, unsigned) { - // Note: If a subclass manipulates the information which is required to calculate the - // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has - // to restore the changed information to the original value, since the dtor of that class - // is not called if the ctor fails. - User::operator delete(Usr); - -#ifndef LLVM_ENABLE_EXCEPTIONS - llvm_unreachable("Constructor throws?"); -#endif - } - -protected: - template static Use &OpFrom(const U *that) { - return Idx < 0 - ? OperandTraits::op_end(const_cast(that))[Idx] - : OperandTraits::op_begin(const_cast(that))[Idx]; - } - - template Use &Op() { - return OpFrom(this); - } - template const Use &Op() const { - return OpFrom(this); - } - -private: - const Use *getHungOffOperands() const { - return *(reinterpret_cast(this) - 1); - } - - Use *&getHungOffOperands() { return *(reinterpret_cast(this) - 1); } - - const Use *getIntrusiveOperands() const { - return reinterpret_cast(this) - NumUserOperands; - } - - Use *getIntrusiveOperands() { - return reinterpret_cast(this) - NumUserOperands; - } - - void setOperandList(Use *NewList) { - assert(HasHungOffUses && - "Setting operand list only required for hung off uses"); - getHungOffOperands() = NewList; - } - -public: - const Use *getOperandList() const { - return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands(); - } - Use *getOperandList() { - return const_cast(static_cast(this)->getOperandList()); - } - - Value *getOperand(unsigned i) const { - assert(i < NumUserOperands && "getOperand() out of range!"); - return getOperandList()[i]; - } - - void setOperand(unsigned i, Value *Val) { - assert(i < NumUserOperands && "setOperand() out of range!"); - assert((!isa((const Value*)this) || - isa((const Value*)this)) && - "Cannot mutate a constant with setOperand!"); - getOperandList()[i] = Val; - } - - const Use &getOperandUse(unsigned i) const { - assert(i < NumUserOperands && "getOperandUse() out of range!"); - return getOperandList()[i]; - } - Use &getOperandUse(unsigned i) { - assert(i < NumUserOperands && "getOperandUse() out of range!"); - return getOperandList()[i]; - } - - unsigned getNumOperands() const { return NumUserOperands; } - - /// Returns the descriptor co-allocated with this User instance. - ArrayRef getDescriptor() const; - - /// Returns the descriptor co-allocated with this User instance. - MutableArrayRef getDescriptor(); - - /// Set the number of operands on a GlobalVariable. - /// - /// GlobalVariable always allocates space for a single operands, but - /// doesn't always use it. - /// - /// FIXME: As that the number of operands is used to find the start of - /// the allocated memory in operator delete, we need to always think we have - /// 1 operand before delete. - void setGlobalVariableNumOperands(unsigned NumOps) { - assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands"); - NumUserOperands = NumOps; - } - - /// Subclasses with hung off uses need to manage the operand count - /// themselves. In these instances, the operand count isn't used to find the - /// OperandList, so there's no issue in having the operand count change. - void setNumHungOffUseOperands(unsigned NumOps) { - assert(HasHungOffUses && "Must have hung off uses to use this method"); - assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands"); - NumUserOperands = NumOps; - } - - /// A droppable user is a user for which uses can be dropped without affecting - /// correctness and should be dropped rather than preventing a transformation - /// from happening. - bool isDroppable() const; - - // --------------------------------------------------------------------------- - // Operand Iterator interface... - // - using op_iterator = Use*; - using const_op_iterator = const Use*; - using op_range = iterator_range; - using const_op_range = iterator_range; - - op_iterator op_begin() { return getOperandList(); } - const_op_iterator op_begin() const { return getOperandList(); } - op_iterator op_end() { - return getOperandList() + NumUserOperands; - } - const_op_iterator op_end() const { - return getOperandList() + NumUserOperands; - } - op_range operands() { - return op_range(op_begin(), op_end()); - } - const_op_range operands() const { - return const_op_range(op_begin(), op_end()); - } - - /// Iterator for directly iterating over the operand Values. - struct value_op_iterator - : iterator_adaptor_base { - explicit value_op_iterator(Use *U = nullptr) : iterator_adaptor_base(U) {} - - Value *operator*() const { return *I; } - Value *operator->() const { return operator*(); } - }; - - value_op_iterator value_op_begin() { - return value_op_iterator(op_begin()); - } - value_op_iterator value_op_end() { - return value_op_iterator(op_end()); - } - iterator_range operand_values() { - return make_range(value_op_begin(), value_op_end()); - } - - struct const_value_op_iterator - : iterator_adaptor_base { - explicit const_value_op_iterator(const Use *U = nullptr) : - iterator_adaptor_base(U) {} - - const Value *operator*() const { return *I; } - const Value *operator->() const { return operator*(); } - }; - - const_value_op_iterator value_op_begin() const { - return const_value_op_iterator(op_begin()); - } - const_value_op_iterator value_op_end() const { - return const_value_op_iterator(op_end()); - } - iterator_range operand_values() const { - return make_range(value_op_begin(), value_op_end()); - } - - /// Drop all references to operands. - /// - /// This function is in charge of "letting go" of all objects that this User - /// refers to. This allows one to 'delete' a whole class at a time, even - /// though there may be circular references... First all references are - /// dropped, and all use counts go to zero. Then everything is deleted for - /// real. Note that no operations are valid on an object that has "dropped - /// all references", except operator delete. - void dropAllReferences() { - for (Use &U : operands()) - U.set(nullptr); - } - - /// Replace uses of one Value with another. - /// - /// Replaces all references to the "From" definition with references to the - /// "To" definition. - void replaceUsesOfWith(Value *From, Value *To); - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return isa(V) || isa(V); - } -}; - -// Either Use objects, or a Use pointer can be prepended to User. -static_assert(alignof(Use) >= alignof(User), - "Alignment is insufficient after objects prepended to User"); -static_assert(alignof(Use *) >= alignof(User), - "Alignment is insufficient after objects prepended to User"); - -template<> struct simplify_type { - using SimpleType = Value*; - - static SimpleType getSimplifiedValue(User::op_iterator &Val) { - return Val->get(); - } -}; -template<> struct simplify_type { - using SimpleType = /*const*/ Value*; - - static SimpleType getSimplifiedValue(User::const_op_iterator &Val) { - return Val->get(); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_USER_H diff --git a/suite/synctools/tablegen/include/llvm/IR/VPIntrinsics.def b/suite/synctools/tablegen/include/llvm/IR/VPIntrinsics.def deleted file mode 100644 index 1abcbb874a..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/VPIntrinsics.def +++ /dev/null @@ -1,372 +0,0 @@ -//===-- IR/VPIntrinsics.def - Describes llvm.vp.* Intrinsics -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains descriptions of the various Vector Predication intrinsics. -// This is used as a central place for enumerating the different instructions -// and should eventually be the place to put comments about the instructions. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -// Provide definitions of macros so that users of this file do not have to -// define everything to use it... -// -// Register a VP intrinsic and begin its property scope. -// All VP intrinsic scopes are top level, ie it is illegal to place a -// BEGIN_REGISTER_VP_INTRINSIC within a VP intrinsic scope. -// \p VPID The VP intrinsic id. -// \p MASKPOS The mask operand position. -// \p EVLPOS The explicit vector length operand position. -#ifndef BEGIN_REGISTER_VP_INTRINSIC -#define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, EVLPOS) -#endif - -// End the property scope of a VP intrinsic. -#ifndef END_REGISTER_VP_INTRINSIC -#define END_REGISTER_VP_INTRINSIC(VPID) -#endif - -// Register a new VP SDNode and begin its property scope. -// When the SDNode scope is nested within a VP intrinsic scope, it is -// implicitly registered as the canonical SDNode for this VP intrinsic. There -// is one VP intrinsic that maps directly to one SDNode that goes by the -// same name. Since the operands are also the same, we open the property -// scopes for both the VPIntrinsic and the SDNode at once. -// \p VPSD The SelectionDAG Node id (eg VP_ADD). -// \p LEGALPOS The operand position of the SDNode that is used for legalizing. -// If LEGALPOS < 0, then the return type given by -// TheNode->getValueType(-1-LEGALPOS) is used. -// \p TDNAME The name of the TableGen definition of this SDNode. -// \p MASKPOS The mask operand position. -// \p EVLPOS The explicit vector length operand position. -#ifndef BEGIN_REGISTER_VP_SDNODE -#define BEGIN_REGISTER_VP_SDNODE(VPSD, LEGALPOS, TDNAME, MASKPOS, EVLPOS) -#endif - -// End the property scope of a new VP SDNode. -#ifndef END_REGISTER_VP_SDNODE -#define END_REGISTER_VP_SDNODE(VPSD) -#endif - -// Helper macros for the common "1:1 - Intrinsic : SDNode" case. -// -// There is one VP intrinsic that maps directly to one SDNode that goes by the -// same name. Since the operands are also the same, we open the property -// scopes for both the VPIntrinsic and the SDNode at once. -// -// \p VPID The canonical name (eg `vp_add`, which at the same time is the -// name of the intrinsic and the TableGen def of the SDNode). -// \p MASKPOS The mask operand position. -// \p EVLPOS The explicit vector length operand position. -// \p VPSD The SelectionDAG Node id (eg VP_ADD). -// \p LEGALPOS The operand position of the SDNode that is used for legalizing -// this SDNode. This can be `-1`, in which case the return type of -// the SDNode is used. -#define BEGIN_REGISTER_VP(VPID, MASKPOS, EVLPOS, VPSD, LEGALPOS) \ - BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, EVLPOS) \ - BEGIN_REGISTER_VP_SDNODE(VPSD, LEGALPOS, VPID, MASKPOS, EVLPOS) - -#define END_REGISTER_VP(VPID, VPSD) \ - END_REGISTER_VP_INTRINSIC(VPID) \ - END_REGISTER_VP_SDNODE(VPSD) - -// The following macros attach properties to the scope they are placed in. This -// assigns the property to the VP Intrinsic and/or SDNode that belongs to the -// scope. -// -// Property Macros { - -// The intrinsic and/or SDNode has the same function as this LLVM IR Opcode. -// \p OPC The opcode of the instruction with the same function. -#ifndef VP_PROPERTY_FUNCTIONAL_OPC -#define VP_PROPERTY_FUNCTIONAL_OPC(OPC) -#endif - -// Whether the intrinsic may have a rounding mode or exception behavior operand -// bundle. -// \p HASROUND '1' if the intrinsic can have a rounding mode operand bundle, -// '0' otherwise. -// \p HASEXCEPT '1' if the intrinsic can have an exception behavior operand -// bundle, '0' otherwise. -// \p INTRINID The constrained fp intrinsic this VP intrinsic corresponds to. -#ifndef VP_PROPERTY_CONSTRAINEDFP -#define VP_PROPERTY_CONSTRAINEDFP(HASROUND, HASEXCEPT, INTRINID) -#endif - -// Map this VP intrinsic to its canonical functional intrinsic. -// \p INTRIN The non-VP intrinsics with the same function. -#ifndef VP_PROPERTY_FUNCTIONAL_INTRINSIC -#define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) -#endif - -// This VP Intrinsic is a memory operation -// The pointer arg is at POINTERPOS and the data arg is at DATAPOS. -#ifndef VP_PROPERTY_MEMOP -#define VP_PROPERTY_MEMOP(POINTERPOS, DATAPOS) -#endif - -// Map this VP reduction intrinsic to its reduction operand positions. -#ifndef VP_PROPERTY_REDUCTION -#define VP_PROPERTY_REDUCTION(STARTPOS, VECTORPOS) -#endif - -// A property to infer VP binary-op SDNode opcodes automatically. -#ifndef VP_PROPERTY_BINARYOP -#define VP_PROPERTY_BINARYOP -#endif - -/// } Property Macros - -///// Integer Arithmetic { - -// Specialized helper macro for integer binary operators (%x, %y, %mask, %evl). -#ifdef HELPER_REGISTER_BINARY_INT_VP -#error \ - "The internal helper macro HELPER_REGISTER_BINARY_INT_VP is already defined!" -#endif -#define HELPER_REGISTER_BINARY_INT_VP(VPID, VPSD, IROPC) \ - BEGIN_REGISTER_VP(VPID, 2, 3, VPSD, -1) \ - VP_PROPERTY_FUNCTIONAL_OPC(IROPC) \ - VP_PROPERTY_BINARYOP \ - END_REGISTER_VP(VPID, VPSD) - -// llvm.vp.add(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_add, VP_ADD, Add) - -// llvm.vp.and(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_and, VP_AND, And) - -// llvm.vp.ashr(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_ashr, VP_ASHR, AShr) - -// llvm.vp.lshr(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_lshr, VP_LSHR, LShr) - -// llvm.vp.mul(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_mul, VP_MUL, Mul) - -// llvm.vp.or(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_or, VP_OR, Or) - -// llvm.vp.sdiv(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_sdiv, VP_SDIV, SDiv) - -// llvm.vp.shl(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_shl, VP_SHL, Shl) - -// llvm.vp.srem(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_srem, VP_SREM, SRem) - -// llvm.vp.sub(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_sub, VP_SUB, Sub) - -// llvm.vp.udiv(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_udiv, VP_UDIV, UDiv) - -// llvm.vp.urem(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_urem, VP_UREM, URem) - -// llvm.vp.xor(x,y,mask,vlen) -HELPER_REGISTER_BINARY_INT_VP(vp_xor, VP_XOR, Xor) - -#undef HELPER_REGISTER_BINARY_INT_VP - -///// } Integer Arithmetic - -///// Floating-Point Arithmetic { - -// Specialized helper macro for floating-point binary operators -// (%x, %y, %mask, %evl). -#ifdef HELPER_REGISTER_BINARY_FP_VP -#error \ - "The internal helper macro HELPER_REGISTER_BINARY_FP_VP is already defined!" -#endif -#define HELPER_REGISTER_BINARY_FP_VP(OPSUFFIX, VPSD, IROPC) \ - BEGIN_REGISTER_VP(vp_##OPSUFFIX, 2, 3, VPSD, -1) \ - VP_PROPERTY_FUNCTIONAL_OPC(IROPC) \ - VP_PROPERTY_CONSTRAINEDFP(1, 1, experimental_constrained_##OPSUFFIX) \ - VP_PROPERTY_BINARYOP \ - END_REGISTER_VP(vp_##OPSUFFIX, VPSD) - -// llvm.vp.fadd(x,y,mask,vlen) -HELPER_REGISTER_BINARY_FP_VP(fadd, VP_FADD, FAdd) - -// llvm.vp.fsub(x,y,mask,vlen) -HELPER_REGISTER_BINARY_FP_VP(fsub, VP_FSUB, FSub) - -// llvm.vp.fmul(x,y,mask,vlen) -HELPER_REGISTER_BINARY_FP_VP(fmul, VP_FMUL, FMul) - -// llvm.vp.fdiv(x,y,mask,vlen) -HELPER_REGISTER_BINARY_FP_VP(fdiv, VP_FDIV, FDiv) - -// llvm.vp.frem(x,y,mask,vlen) -HELPER_REGISTER_BINARY_FP_VP(frem, VP_FREM, FRem) - -#undef HELPER_REGISTER_BINARY_FP_VP - -///// } Floating-Point Arithmetic - -///// Memory Operations { -// llvm.vp.store(val,ptr,mask,vlen) -BEGIN_REGISTER_VP_INTRINSIC(vp_store, 2, 3) -// chain = VP_STORE chain,val,base,offset,mask,evl -BEGIN_REGISTER_VP_SDNODE(VP_STORE, 0, vp_store, 4, 5) -VP_PROPERTY_FUNCTIONAL_OPC(Store) -VP_PROPERTY_FUNCTIONAL_INTRINSIC(masked_store) -VP_PROPERTY_MEMOP(1, 0) -END_REGISTER_VP(vp_store, VP_STORE) - -// llvm.vp.scatter(ptr,val,mask,vlen) -BEGIN_REGISTER_VP_INTRINSIC(vp_scatter, 2, 3) -// chain = VP_SCATTER chain,val,base,indices,scale,mask,evl -BEGIN_REGISTER_VP_SDNODE(VP_SCATTER, -1, vp_scatter, 5, 6) -VP_PROPERTY_FUNCTIONAL_INTRINSIC(masked_scatter) -VP_PROPERTY_MEMOP(1, 0) -END_REGISTER_VP(vp_scatter, VP_SCATTER) - -// llvm.vp.load(ptr,mask,vlen) -BEGIN_REGISTER_VP_INTRINSIC(vp_load, 1, 2) -// val,chain = VP_LOAD chain,base,offset,mask,evl -BEGIN_REGISTER_VP_SDNODE(VP_LOAD, -1, vp_load, 3, 4) -VP_PROPERTY_FUNCTIONAL_OPC(Load) -VP_PROPERTY_FUNCTIONAL_INTRINSIC(masked_load) -VP_PROPERTY_MEMOP(0, None) -END_REGISTER_VP(vp_load, VP_LOAD) - -// llvm.vp.gather(ptr,mask,vlen) -BEGIN_REGISTER_VP_INTRINSIC(vp_gather, 1, 2) -// val,chain = VP_GATHER chain,base,indices,scale,mask,evl -BEGIN_REGISTER_VP_SDNODE(VP_GATHER, -1, vp_gather, 4, 5) -VP_PROPERTY_FUNCTIONAL_INTRINSIC(masked_gather) -VP_PROPERTY_MEMOP(0, None) -END_REGISTER_VP(vp_gather, VP_GATHER) - -///// } Memory Operations - -///// Reductions { - -// Specialized helper macro for VP reductions (%start, %x, %mask, %evl). -#ifdef HELPER_REGISTER_REDUCTION_VP -#error \ - "The internal helper macro HELPER_REGISTER_REDUCTION_VP is already defined!" -#endif -#define HELPER_REGISTER_REDUCTION_VP(VPID, VPSD, INTRIN) \ - BEGIN_REGISTER_VP(VPID, 2, 3, VPSD, -1) \ - VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) \ - VP_PROPERTY_REDUCTION(0, 1) \ - END_REGISTER_VP(VPID, VPSD) - -// llvm.vp.reduce.add(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_add, VP_REDUCE_ADD, - experimental_vector_reduce_add) - -// llvm.vp.reduce.mul(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_mul, VP_REDUCE_MUL, - experimental_vector_reduce_mul) - -// llvm.vp.reduce.and(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_and, VP_REDUCE_AND, - experimental_vector_reduce_and) - -// llvm.vp.reduce.or(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_or, VP_REDUCE_OR, - experimental_vector_reduce_or) - -// llvm.vp.reduce.xor(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_xor, VP_REDUCE_XOR, - experimental_vector_reduce_xor) - -// llvm.vp.reduce.smax(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_smax, VP_REDUCE_SMAX, - experimental_vector_reduce_smax) - -// llvm.vp.reduce.smin(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_smin, VP_REDUCE_SMIN, - experimental_vector_reduce_smin) - -// llvm.vp.reduce.umax(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_umax, VP_REDUCE_UMAX, - experimental_vector_reduce_umax) - -// llvm.vp.reduce.umin(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_umin, VP_REDUCE_UMIN, - experimental_vector_reduce_umin) - -// llvm.vp.reduce.fmax(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_fmax, VP_REDUCE_FMAX, - experimental_vector_reduce_fmax) - -// llvm.vp.reduce.fmin(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_VP(vp_reduce_fmin, VP_REDUCE_FMIN, - experimental_vector_reduce_fmin) - -#undef HELPER_REGISTER_REDUCTION_VP - -// Specialized helper macro for VP reductions as above but with two forms: -// sequential and reassociative. These manifest as the presence of 'reassoc' -// fast-math flags in the IR and as two distinct ISD opcodes in the -// SelectionDAG. -#ifdef HELPER_REGISTER_REDUCTION_SEQ_VP -#error \ - "The internal helper macro HELPER_REGISTER_REDUCTION_SEQ_VP is already defined!" -#endif -#define HELPER_REGISTER_REDUCTION_SEQ_VP(VPID, VPSD, SEQ_VPSD, INTRIN) \ - BEGIN_REGISTER_VP_INTRINSIC(VPID, 2, 3) \ - BEGIN_REGISTER_VP_SDNODE(VPSD, -1, VPID, 2, 3) \ - VP_PROPERTY_REDUCTION(0, 1) \ - END_REGISTER_VP_SDNODE(VPSD) \ - BEGIN_REGISTER_VP_SDNODE(SEQ_VPSD, -1, VPID, 2, 3) \ - VP_PROPERTY_REDUCTION(0, 1) \ - END_REGISTER_VP_SDNODE(SEQ_VPSD) \ - VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) \ - END_REGISTER_VP_INTRINSIC(VPID) - -// llvm.vp.reduce.fadd(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_SEQ_VP(vp_reduce_fadd, VP_REDUCE_FADD, - VP_REDUCE_SEQ_FADD, - experimental_vector_reduce_fadd) - -// llvm.vp.reduce.fmul(start,x,mask,vlen) -HELPER_REGISTER_REDUCTION_SEQ_VP(vp_reduce_fmul, VP_REDUCE_FMUL, - VP_REDUCE_SEQ_FMUL, - experimental_vector_reduce_fmul) - -#undef HELPER_REGISTER_REDUCTION_SEQ_VP - -///// } Reduction - -///// Shuffles { - -// llvm.vp.select(mask,on_true,on_false,vlen) -BEGIN_REGISTER_VP(vp_select, 0, 3, VP_SELECT, -1) -VP_PROPERTY_FUNCTIONAL_OPC(Select) -END_REGISTER_VP(vp_select, VP_SELECT) - -// llvm.vp.merge(mask,on_true,on_false,pivot) -BEGIN_REGISTER_VP(vp_merge, 0, 3, VP_MERGE, -1) -END_REGISTER_VP(vp_merge, VP_MERGE) - -BEGIN_REGISTER_VP(experimental_vp_splice, 3, 5, EXPERIMENTAL_VP_SPLICE, -1) -END_REGISTER_VP(experimental_vp_splice, EXPERIMENTAL_VP_SPLICE) - -///// } Shuffles - -#undef BEGIN_REGISTER_VP -#undef BEGIN_REGISTER_VP_INTRINSIC -#undef BEGIN_REGISTER_VP_SDNODE -#undef END_REGISTER_VP -#undef END_REGISTER_VP_INTRINSIC -#undef END_REGISTER_VP_SDNODE -#undef VP_PROPERTY_BINARYOP -#undef VP_PROPERTY_CONSTRAINEDFP -#undef VP_PROPERTY_FUNCTIONAL_INTRINSIC -#undef VP_PROPERTY_FUNCTIONAL_OPC -#undef VP_PROPERTY_MEMOP -#undef VP_PROPERTY_REDUCTION diff --git a/suite/synctools/tablegen/include/llvm/IR/Value.def b/suite/synctools/tablegen/include/llvm/IR/Value.def deleted file mode 100644 index 97d15260f3..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Value.def +++ /dev/null @@ -1,135 +0,0 @@ -//===-------- llvm/IR/Value.def - File that describes Values ---v-*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains descriptions of the various LLVM values. This is -// used as a central place for enumerating the different values. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -// Provide definitions of macros so that users of this file do not have to -// define everything to use it... -// -#if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT || \ - defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE || \ - defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE || \ - defined HANDLE_CONSTANT_MARKER || defined HANDLE_MEMORY_VALUE) -#error "Missing macro definition of HANDLE_VALUE*" -#endif - -// If the LLVM_C_API macro is set, then values handled via HANDLE_*_EXCLUDE_LLVM_C_API will not be expanded in areas the HANDLE_* macro is used. If it is not set, then HANDLE_*_EXCLUDE_LLVM_C_API values are handled normally as their HANDLE_* counterparts. -#ifndef LLVM_C_API -#define LLVM_C_API 0 -#endif - -#ifndef HANDLE_MEMORY_VALUE -#define HANDLE_MEMORY_VALUE(ValueName) HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_GLOBAL_VALUE -#define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName) -#endif - -#ifndef HANDLE_CONSTANT -#define HANDLE_CONSTANT(ValueName) HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_INSTRUCTION -#define HANDLE_INSTRUCTION(ValueName) HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_INLINE_ASM_VALUE -#define HANDLE_INLINE_ASM_VALUE(ValueName) HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_METADATA_VALUE -#define HANDLE_METADATA_VALUE(ValueName) HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_VALUE -#define HANDLE_VALUE(ValueName) -#endif - -#ifndef HANDLE_CONSTANT_MARKER -#define HANDLE_CONSTANT_MARKER(MarkerName, ValueName) -#endif - -#ifndef HANDLE_CONSTANT_EXCLUDE_LLVM_C_API -#define HANDLE_CONSTANT_EXCLUDE_LLVM_C_API(ValueName) HANDLE_CONSTANT(ValueName) -#endif - -#if LLVM_C_API -#undef HANDLE_CONSTANT_EXCLUDE_LLVM_C_API -#define HANDLE_CONSTANT_EXCLUDE_LLVM_C_API(ValueName) -#endif - -// Having constant first makes the range check for isa faster -// and smaller by one operation. - -// Constant -HANDLE_GLOBAL_VALUE(Function) -HANDLE_GLOBAL_VALUE(GlobalAlias) -HANDLE_GLOBAL_VALUE(GlobalIFunc) -HANDLE_GLOBAL_VALUE(GlobalVariable) -HANDLE_CONSTANT(BlockAddress) -HANDLE_CONSTANT(ConstantExpr) -HANDLE_CONSTANT_EXCLUDE_LLVM_C_API(DSOLocalEquivalent) -HANDLE_CONSTANT_EXCLUDE_LLVM_C_API(NoCFIValue) - -// ConstantAggregate. -HANDLE_CONSTANT(ConstantArray) -HANDLE_CONSTANT(ConstantStruct) -HANDLE_CONSTANT(ConstantVector) - -// ConstantData. -HANDLE_CONSTANT(UndefValue) -HANDLE_CONSTANT(PoisonValue) -HANDLE_CONSTANT(ConstantAggregateZero) -HANDLE_CONSTANT(ConstantDataArray) -HANDLE_CONSTANT(ConstantDataVector) -HANDLE_CONSTANT(ConstantInt) -HANDLE_CONSTANT(ConstantFP) -HANDLE_CONSTANT(ConstantPointerNull) -HANDLE_CONSTANT(ConstantTokenNone) - -HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function) -HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone) -HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue) -HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone) -HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray) -HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector) - -HANDLE_VALUE(Argument) -HANDLE_VALUE(BasicBlock) - - -HANDLE_METADATA_VALUE(MetadataAsValue) -HANDLE_INLINE_ASM_VALUE(InlineAsm) - -// FIXME: It's awkward that Value.def knows about classes in Analysis. While -// this doesn't introduce a strict link or include dependency, we should remove -// the circular dependency eventually. -HANDLE_MEMORY_VALUE(MemoryUse) -HANDLE_MEMORY_VALUE(MemoryDef) -HANDLE_MEMORY_VALUE(MemoryPhi) - -HANDLE_INSTRUCTION(Instruction) -// Enum values starting at InstructionVal are used for Instructions; -// don't add new values here! - -#undef HANDLE_MEMORY_VALUE -#undef HANDLE_GLOBAL_VALUE -#undef HANDLE_CONSTANT -#undef HANDLE_INSTRUCTION -#undef HANDLE_METADATA_VALUE -#undef HANDLE_INLINE_ASM_VALUE -#undef HANDLE_VALUE -#undef HANDLE_CONSTANT_MARKER -#undef HANDLE_CONSTANT_EXCLUDE_LLVM_C_API -#undef LLVM_C_API diff --git a/suite/synctools/tablegen/include/llvm/IR/Value.h b/suite/synctools/tablegen/include/llvm/IR/Value.h deleted file mode 100644 index bab3149870..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Value.h +++ /dev/null @@ -1,1060 +0,0 @@ -//===- llvm/Value.h - Definition of the Value class -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the Value class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_VALUE_H -#define LLVM_IR_VALUE_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Use.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Casting.h" -#include -#include -#include - -namespace llvm { - -class APInt; -class Argument; -class BasicBlock; -class Constant; -class ConstantData; -class ConstantAggregate; -class DataLayout; -class Function; -class GlobalAlias; -class GlobalIFunc; -class GlobalObject; -class GlobalValue; -class GlobalVariable; -class InlineAsm; -class Instruction; -class LLVMContext; -class MDNode; -class Module; -class ModuleSlotTracker; -class raw_ostream; -template class StringMapEntry; -class Twine; -class Type; -class User; - -using ValueName = StringMapEntry; - -//===----------------------------------------------------------------------===// -// Value Class -//===----------------------------------------------------------------------===// - -/// LLVM Value Representation -/// -/// This is a very important LLVM class. It is the base class of all values -/// computed by a program that may be used as operands to other values. Value is -/// the super class of other important classes such as Instruction and Function. -/// All Values have a Type. Type is not a subclass of Value. Some values can -/// have a name and they belong to some Module. Setting the name on the Value -/// automatically updates the module's symbol table. -/// -/// Every value has a "use list" that keeps track of which other Values are -/// using this Value. A Value can also have an arbitrary number of ValueHandle -/// objects that watch it and listen to RAUW and Destroy events. See -/// llvm/IR/ValueHandle.h for details. -class Value { - Type *VTy; - Use *UseList; - - friend class ValueAsMetadata; // Allow access to IsUsedByMD. - friend class ValueHandleBase; - - const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) - unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? - -protected: - /// Hold subclass data that can be dropped. - /// - /// This member is similar to SubclassData, however it is for holding - /// information which may be used to aid optimization, but which may be - /// cleared to zero without affecting conservative interpretation. - unsigned char SubclassOptionalData : 7; - -private: - /// Hold arbitrary subclass data. - /// - /// This member is defined by this class, but is not used for anything. - /// Subclasses can use it to hold whatever state they find useful. This - /// field is initialized to zero by the ctor. - unsigned short SubclassData; - -protected: - /// The number of operands in the subclass. - /// - /// This member is defined by this class, but not used for anything. - /// Subclasses can use it to store their number of operands, if they have - /// any. - /// - /// This is stored here to save space in User on 64-bit hosts. Since most - /// instances of Value have operands, 32-bit hosts aren't significantly - /// affected. - /// - /// Note, this should *NOT* be used directly by any class other than User. - /// User uses this value to find the Use list. - enum : unsigned { NumUserOperandsBits = 27 }; - unsigned NumUserOperands : NumUserOperandsBits; - - // Use the same type as the bitfield above so that MSVC will pack them. - unsigned IsUsedByMD : 1; - unsigned HasName : 1; - unsigned HasMetadata : 1; // Has metadata attached to this? - unsigned HasHungOffUses : 1; - unsigned HasDescriptor : 1; - -private: - template // UseT == 'Use' or 'const Use' - class use_iterator_impl { - friend class Value; - - UseT *U; - - explicit use_iterator_impl(UseT *u) : U(u) {} - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = UseT *; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - use_iterator_impl() : U() {} - - bool operator==(const use_iterator_impl &x) const { return U == x.U; } - bool operator!=(const use_iterator_impl &x) const { return !operator==(x); } - - use_iterator_impl &operator++() { // Preincrement - assert(U && "Cannot increment end iterator!"); - U = U->getNext(); - return *this; - } - - use_iterator_impl operator++(int) { // Postincrement - auto tmp = *this; - ++*this; - return tmp; - } - - UseT &operator*() const { - assert(U && "Cannot dereference end iterator!"); - return *U; - } - - UseT *operator->() const { return &operator*(); } - - operator use_iterator_impl() const { - return use_iterator_impl(U); - } - }; - - template // UserTy == 'User' or 'const User' - class user_iterator_impl { - use_iterator_impl UI; - explicit user_iterator_impl(Use *U) : UI(U) {} - friend class Value; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = UserTy *; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - user_iterator_impl() = default; - - bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } - bool operator!=(const user_iterator_impl &x) const { return !operator==(x); } - - /// Returns true if this iterator is equal to user_end() on the value. - bool atEnd() const { return *this == user_iterator_impl(); } - - user_iterator_impl &operator++() { // Preincrement - ++UI; - return *this; - } - - user_iterator_impl operator++(int) { // Postincrement - auto tmp = *this; - ++*this; - return tmp; - } - - // Retrieve a pointer to the current User. - UserTy *operator*() const { - return UI->getUser(); - } - - UserTy *operator->() const { return operator*(); } - - operator user_iterator_impl() const { - return user_iterator_impl(*UI); - } - - Use &getUse() const { return *UI; } - }; - -protected: - Value(Type *Ty, unsigned scid); - - /// Value's destructor should be virtual by design, but that would require - /// that Value and all of its subclasses have a vtable that effectively - /// duplicates the information in the value ID. As a size optimization, the - /// destructor has been protected, and the caller should manually call - /// deleteValue. - ~Value(); // Use deleteValue() to delete a generic Value. - -public: - Value(const Value &) = delete; - Value &operator=(const Value &) = delete; - - /// Delete a pointer to a generic Value. - void deleteValue(); - - /// Support for debugging, callable in GDB: V->dump() - void dump() const; - - /// Implement operator<< on Value. - /// @{ - void print(raw_ostream &O, bool IsForDebug = false) const; - void print(raw_ostream &O, ModuleSlotTracker &MST, - bool IsForDebug = false) const; - /// @} - - /// Print the name of this Value out to the specified raw_ostream. - /// - /// This is useful when you just want to print 'int %reg126', not the - /// instruction that generated it. If you specify a Module for context, then - /// even constants get pretty-printed; for example, the type of a null - /// pointer is printed symbolically. - /// @{ - void printAsOperand(raw_ostream &O, bool PrintType = true, - const Module *M = nullptr) const; - void printAsOperand(raw_ostream &O, bool PrintType, - ModuleSlotTracker &MST) const; - /// @} - - /// All values are typed, get the type of this value. - Type *getType() const { return VTy; } - - /// All values hold a context through their type. - LLVMContext &getContext() const; - - // All values can potentially be named. - bool hasName() const { return HasName; } - ValueName *getValueName() const; - void setValueName(ValueName *VN); - -private: - void destroyValueName(); - enum class ReplaceMetadataUses { No, Yes }; - void doRAUW(Value *New, ReplaceMetadataUses); - void setNameImpl(const Twine &Name); - -public: - /// Return a constant reference to the value's name. - /// - /// This guaranteed to return the same reference as long as the value is not - /// modified. If the value has a name, this does a hashtable lookup, so it's - /// not free. - StringRef getName() const; - - /// Change the name of the value. - /// - /// Choose a new unique name if the provided name is taken. - /// - /// \param Name The new name; or "" if the value's name should be removed. - void setName(const Twine &Name); - - /// Transfer the name from V to this value. - /// - /// After taking V's name, sets V's name to empty. - /// - /// \note It is an error to call V->takeName(V). - void takeName(Value *V); - -#ifndef NDEBUG - std::string getNameOrAsOperand() const; -#endif - - /// Change all uses of this to point to a new Value. - /// - /// Go through the uses list for this definition and make each use point to - /// "V" instead of "this". After this completes, 'this's use list is - /// guaranteed to be empty. - void replaceAllUsesWith(Value *V); - - /// Change non-metadata uses of this to point to a new Value. - /// - /// Go through the uses list for this definition and make each use point to - /// "V" instead of "this". This function skips metadata entries in the list. - void replaceNonMetadataUsesWith(Value *V); - - /// Go through the uses list for this definition and make each use point - /// to "V" if the callback ShouldReplace returns true for the given Use. - /// Unlike replaceAllUsesWith() this function does not support basic block - /// values. - void replaceUsesWithIf(Value *New, - llvm::function_ref ShouldReplace); - - /// replaceUsesOutsideBlock - Go through the uses list for this definition and - /// make each use point to "V" instead of "this" when the use is outside the - /// block. 'This's use list is expected to have at least one element. - /// Unlike replaceAllUsesWith() this function does not support basic block - /// values. - void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); - - //---------------------------------------------------------------------- - // Methods for handling the chain of uses of this Value. - // - // Materializing a function can introduce new uses, so these methods come in - // two variants: - // The methods that start with materialized_ check the uses that are - // currently known given which functions are materialized. Be very careful - // when using them since you might not get all uses. - // The methods that don't start with materialized_ assert that modules is - // fully materialized. - void assertModuleIsMaterializedImpl() const; - // This indirection exists so we can keep assertModuleIsMaterializedImpl() - // around in release builds of Value.cpp to be linked with other code built - // in debug mode. But this avoids calling it in any of the release built code. - void assertModuleIsMaterialized() const { -#ifndef NDEBUG - assertModuleIsMaterializedImpl(); -#endif - } - - bool use_empty() const { - assertModuleIsMaterialized(); - return UseList == nullptr; - } - - bool materialized_use_empty() const { - return UseList == nullptr; - } - - using use_iterator = use_iterator_impl; - using const_use_iterator = use_iterator_impl; - - use_iterator materialized_use_begin() { return use_iterator(UseList); } - const_use_iterator materialized_use_begin() const { - return const_use_iterator(UseList); - } - use_iterator use_begin() { - assertModuleIsMaterialized(); - return materialized_use_begin(); - } - const_use_iterator use_begin() const { - assertModuleIsMaterialized(); - return materialized_use_begin(); - } - use_iterator use_end() { return use_iterator(); } - const_use_iterator use_end() const { return const_use_iterator(); } - iterator_range materialized_uses() { - return make_range(materialized_use_begin(), use_end()); - } - iterator_range materialized_uses() const { - return make_range(materialized_use_begin(), use_end()); - } - iterator_range uses() { - assertModuleIsMaterialized(); - return materialized_uses(); - } - iterator_range uses() const { - assertModuleIsMaterialized(); - return materialized_uses(); - } - - bool user_empty() const { - assertModuleIsMaterialized(); - return UseList == nullptr; - } - - using user_iterator = user_iterator_impl; - using const_user_iterator = user_iterator_impl; - - user_iterator materialized_user_begin() { return user_iterator(UseList); } - const_user_iterator materialized_user_begin() const { - return const_user_iterator(UseList); - } - user_iterator user_begin() { - assertModuleIsMaterialized(); - return materialized_user_begin(); - } - const_user_iterator user_begin() const { - assertModuleIsMaterialized(); - return materialized_user_begin(); - } - user_iterator user_end() { return user_iterator(); } - const_user_iterator user_end() const { return const_user_iterator(); } - User *user_back() { - assertModuleIsMaterialized(); - return *materialized_user_begin(); - } - const User *user_back() const { - assertModuleIsMaterialized(); - return *materialized_user_begin(); - } - iterator_range materialized_users() { - return make_range(materialized_user_begin(), user_end()); - } - iterator_range materialized_users() const { - return make_range(materialized_user_begin(), user_end()); - } - iterator_range users() { - assertModuleIsMaterialized(); - return materialized_users(); - } - iterator_range users() const { - assertModuleIsMaterialized(); - return materialized_users(); - } - - /// Return true if there is exactly one use of this value. - /// - /// This is specialized because it is a common request and does not require - /// traversing the whole use list. - bool hasOneUse() const { return hasSingleElement(uses()); } - - /// Return true if this Value has exactly N uses. - bool hasNUses(unsigned N) const; - - /// Return true if this value has N uses or more. - /// - /// This is logically equivalent to getNumUses() >= N. - bool hasNUsesOrMore(unsigned N) const; - - /// Return true if there is exactly one user of this value. - /// - /// Note that this is not the same as "has one use". If a value has one use, - /// then there certainly is a single user. But if value has several uses, - /// it is possible that all uses are in a single user, or not. - /// - /// This check is potentially costly, since it requires traversing, - /// in the worst case, the whole use list of a value. - bool hasOneUser() const; - - /// Return true if there is exactly one use of this value that cannot be - /// dropped. - Use *getSingleUndroppableUse(); - const Use *getSingleUndroppableUse() const { - return const_cast(this)->getSingleUndroppableUse(); - } - - /// Return true if there is exactly one unique user of this value that cannot be - /// dropped (that user can have multiple uses of this value). - User *getUniqueUndroppableUser(); - const User *getUniqueUndroppableUser() const { - return const_cast(this)->getUniqueUndroppableUser(); - } - - /// Return true if there this value. - /// - /// This is specialized because it is a common request and does not require - /// traversing the whole use list. - bool hasNUndroppableUses(unsigned N) const; - - /// Return true if this value has N uses or more. - /// - /// This is logically equivalent to getNumUses() >= N. - bool hasNUndroppableUsesOrMore(unsigned N) const; - - /// Remove every uses that can safely be removed. - /// - /// This will remove for example uses in llvm.assume. - /// This should be used when performing want to perform a transformation but - /// some Droppable uses prevent it. - /// This function optionally takes a filter to only remove some droppable - /// uses. - void dropDroppableUses(llvm::function_ref ShouldDrop = - [](const Use *) { return true; }); - - /// Remove every use of this value in \p User that can safely be removed. - void dropDroppableUsesIn(User &Usr); - - /// Remove the droppable use \p U. - static void dropDroppableUse(Use &U); - - /// Check if this value is used in the specified basic block. - bool isUsedInBasicBlock(const BasicBlock *BB) const; - - /// This method computes the number of uses of this Value. - /// - /// This is a linear time operation. Use hasOneUse, hasNUses, or - /// hasNUsesOrMore to check for specific values. - unsigned getNumUses() const; - - /// This method should only be used by the Use class. - void addUse(Use &U) { U.addToList(&UseList); } - - /// Concrete subclass of this. - /// - /// An enumeration for keeping track of the concrete subclass of Value that - /// is actually instantiated. Values of this enumeration are kept in the - /// Value classes SubclassID field. They are used for concrete type - /// identification. - enum ValueTy { -#define HANDLE_VALUE(Name) Name##Val, -#include "llvm/IR/Value.def" - - // Markers: -#define HANDLE_CONSTANT_MARKER(Marker, Constant) Marker = Constant##Val, -#include "llvm/IR/Value.def" - }; - - /// Return an ID for the concrete type of this object. - /// - /// This is used to implement the classof checks. This should not be used - /// for any other purpose, as the values may change as LLVM evolves. Also, - /// note that for instructions, the Instruction's opcode is added to - /// InstructionVal. So this means three things: - /// # there is no value with code InstructionVal (no opcode==0). - /// # there are more possible values for the value type than in ValueTy enum. - /// # the InstructionVal enumerator must be the highest valued enumerator in - /// the ValueTy enum. - unsigned getValueID() const { - return SubclassID; - } - - /// Return the raw optional flags value contained in this value. - /// - /// This should only be used when testing two Values for equivalence. - unsigned getRawSubclassOptionalData() const { - return SubclassOptionalData; - } - - /// Clear the optional flags contained in this value. - void clearSubclassOptionalData() { - SubclassOptionalData = 0; - } - - /// Check the optional flags for equality. - bool hasSameSubclassOptionalData(const Value *V) const { - return SubclassOptionalData == V->SubclassOptionalData; - } - - /// Return true if there is a value handle associated with this value. - bool hasValueHandle() const { return HasValueHandle; } - - /// Return true if there is metadata referencing this value. - bool isUsedByMetadata() const { return IsUsedByMD; } - - // Return true if this value is only transitively referenced by metadata. - bool isTransitiveUsedByMetadataOnly() const; - -protected: - /// Get the current metadata attachments for the given kind, if any. - /// - /// These functions require that the value have at most a single attachment - /// of the given kind, and return \c nullptr if such an attachment is missing. - /// @{ - MDNode *getMetadata(unsigned KindID) const; - MDNode *getMetadata(StringRef Kind) const; - /// @} - - /// Appends all attachments with the given ID to \c MDs in insertion order. - /// If the Value has no attachments with the given ID, or if ID is invalid, - /// leaves MDs unchanged. - /// @{ - void getMetadata(unsigned KindID, SmallVectorImpl &MDs) const; - void getMetadata(StringRef Kind, SmallVectorImpl &MDs) const; - /// @} - - /// Appends all metadata attached to this value to \c MDs, sorting by - /// KindID. The first element of each pair returned is the KindID, the second - /// element is the metadata value. Attachments with the same ID appear in - /// insertion order. - void - getAllMetadata(SmallVectorImpl> &MDs) const; - - /// Return true if this value has any metadata attached to it. - bool hasMetadata() const { return (bool)HasMetadata; } - - /// Return true if this value has the given type of metadata attached. - /// @{ - bool hasMetadata(unsigned KindID) const { - return getMetadata(KindID) != nullptr; - } - bool hasMetadata(StringRef Kind) const { - return getMetadata(Kind) != nullptr; - } - /// @} - - /// Set a particular kind of metadata attachment. - /// - /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or - /// replacing it if it already exists. - /// @{ - void setMetadata(unsigned KindID, MDNode *Node); - void setMetadata(StringRef Kind, MDNode *Node); - /// @} - - /// Add a metadata attachment. - /// @{ - void addMetadata(unsigned KindID, MDNode &MD); - void addMetadata(StringRef Kind, MDNode &MD); - /// @} - - /// Erase all metadata attachments with the given kind. - /// - /// \returns true if any metadata was removed. - bool eraseMetadata(unsigned KindID); - - /// Erase all metadata attached to this Value. - void clearMetadata(); - -public: - /// Return true if this value is a swifterror value. - /// - /// swifterror values can be either a function argument or an alloca with a - /// swifterror attribute. - bool isSwiftError() const; - - /// Strip off pointer casts, all-zero GEPs and address space casts. - /// - /// Returns the original uncasted value. If this is called on a non-pointer - /// value, it returns 'this'. - const Value *stripPointerCasts() const; - Value *stripPointerCasts() { - return const_cast( - static_cast(this)->stripPointerCasts()); - } - - /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases. - /// - /// Returns the original uncasted value. If this is called on a non-pointer - /// value, it returns 'this'. - const Value *stripPointerCastsAndAliases() const; - Value *stripPointerCastsAndAliases() { - return const_cast( - static_cast(this)->stripPointerCastsAndAliases()); - } - - /// Strip off pointer casts, all-zero GEPs and address space casts - /// but ensures the representation of the result stays the same. - /// - /// Returns the original uncasted value with the same representation. If this - /// is called on a non-pointer value, it returns 'this'. - const Value *stripPointerCastsSameRepresentation() const; - Value *stripPointerCastsSameRepresentation() { - return const_cast(static_cast(this) - ->stripPointerCastsSameRepresentation()); - } - - /// Strip off pointer casts, all-zero GEPs, single-argument phi nodes and - /// invariant group info. - /// - /// Returns the original uncasted value. If this is called on a non-pointer - /// value, it returns 'this'. This function should be used only in - /// Alias analysis. - const Value *stripPointerCastsForAliasAnalysis() const; - Value *stripPointerCastsForAliasAnalysis() { - return const_cast(static_cast(this) - ->stripPointerCastsForAliasAnalysis()); - } - - /// Strip off pointer casts and all-constant inbounds GEPs. - /// - /// Returns the original pointer value. If this is called on a non-pointer - /// value, it returns 'this'. - const Value *stripInBoundsConstantOffsets() const; - Value *stripInBoundsConstantOffsets() { - return const_cast( - static_cast(this)->stripInBoundsConstantOffsets()); - } - - /// Accumulate the constant offset this value has compared to a base pointer. - /// Only 'getelementptr' instructions (GEPs) are accumulated but other - /// instructions, e.g., casts, are stripped away as well. - /// The accumulated constant offset is added to \p Offset and the base - /// pointer is returned. - /// - /// The APInt \p Offset has to have a bit-width equal to the IntPtr type for - /// the address space of 'this' pointer value, e.g., use - /// DataLayout::getIndexTypeSizeInBits(Ty). - /// - /// If \p AllowNonInbounds is true, offsets in GEPs are stripped and - /// accumulated even if the GEP is not "inbounds". - /// - /// If \p AllowInvariantGroup is true then this method also looks through - /// strip.invariant.group and launder.invariant.group intrinsics. - /// - /// If \p ExternalAnalysis is provided it will be used to calculate a offset - /// when a operand of GEP is not constant. - /// For example, for a value \p ExternalAnalysis might try to calculate a - /// lower bound. If \p ExternalAnalysis is successful, it should return true. - /// - /// If this is called on a non-pointer value, it returns 'this' and the - /// \p Offset is not modified. - /// - /// Note that this function will never return a nullptr. It will also never - /// manipulate the \p Offset in a way that would not match the difference - /// between the underlying value and the returned one. Thus, if no constant - /// offset was found, the returned value is the underlying one and \p Offset - /// is unchanged. - const Value *stripAndAccumulateConstantOffsets( - const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, - bool AllowInvariantGroup = false, - function_ref ExternalAnalysis = - nullptr) const; - Value *stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, - bool AllowNonInbounds, - bool AllowInvariantGroup = false) { - return const_cast( - static_cast(this)->stripAndAccumulateConstantOffsets( - DL, Offset, AllowNonInbounds, AllowInvariantGroup)); - } - - /// This is a wrapper around stripAndAccumulateConstantOffsets with the - /// in-bounds requirement set to false. - const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, - APInt &Offset) const { - return stripAndAccumulateConstantOffsets(DL, Offset, - /* AllowNonInbounds */ false); - } - Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, - APInt &Offset) { - return stripAndAccumulateConstantOffsets(DL, Offset, - /* AllowNonInbounds */ false); - } - - /// Strip off pointer casts and inbounds GEPs. - /// - /// Returns the original pointer value. If this is called on a non-pointer - /// value, it returns 'this'. - const Value *stripInBoundsOffsets(function_ref Func = - [](const Value *) {}) const; - inline Value *stripInBoundsOffsets(function_ref Func = - [](const Value *) {}) { - return const_cast( - static_cast(this)->stripInBoundsOffsets(Func)); - } - - /// Return true if the memory object referred to by V can by freed in the - /// scope for which the SSA value defining the allocation is statically - /// defined. E.g. deallocation after the static scope of a value does not - /// count, but a deallocation before that does. - bool canBeFreed() const; - - /// Returns the number of bytes known to be dereferenceable for the - /// pointer value. - /// - /// If CanBeNull is set by this function the pointer can either be null or be - /// dereferenceable up to the returned number of bytes. - /// - /// IF CanBeFreed is true, the pointer is known to be dereferenceable at - /// point of definition only. Caller must prove that allocation is not - /// deallocated between point of definition and use. - uint64_t getPointerDereferenceableBytes(const DataLayout &DL, - bool &CanBeNull, - bool &CanBeFreed) const; - - /// Returns an alignment of the pointer value. - /// - /// Returns an alignment which is either specified explicitly, e.g. via - /// align attribute of a function argument, or guaranteed by DataLayout. - Align getPointerAlignment(const DataLayout &DL) const; - - /// Translate PHI node to its predecessor from the given basic block. - /// - /// If this value is a PHI node with CurBB as its parent, return the value in - /// the PHI node corresponding to PredBB. If not, return ourself. This is - /// useful if you want to know the value something has in a predecessor - /// block. - const Value *DoPHITranslation(const BasicBlock *CurBB, - const BasicBlock *PredBB) const; - Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) { - return const_cast( - static_cast(this)->DoPHITranslation(CurBB, PredBB)); - } - - /// The maximum alignment for instructions. - /// - /// This is the greatest alignment value supported by load, store, and alloca - /// instructions, and global values. - static constexpr unsigned MaxAlignmentExponent = 32; - static constexpr uint64_t MaximumAlignment = 1ULL << MaxAlignmentExponent; - - /// Mutate the type of this Value to be of the specified type. - /// - /// Note that this is an extremely dangerous operation which can create - /// completely invalid IR very easily. It is strongly recommended that you - /// recreate IR objects with the right types instead of mutating them in - /// place. - void mutateType(Type *Ty) { - VTy = Ty; - } - - /// Sort the use-list. - /// - /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is - /// expected to compare two \a Use references. - template void sortUseList(Compare Cmp); - - /// Reverse the use-list. - void reverseUseList(); - -private: - /// Merge two lists together. - /// - /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes - /// "equal" items from L before items from R. - /// - /// \return the first element in the list. - /// - /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update). - template - static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) { - Use *Merged; - Use **Next = &Merged; - - while (true) { - if (!L) { - *Next = R; - break; - } - if (!R) { - *Next = L; - break; - } - if (Cmp(*R, *L)) { - *Next = R; - Next = &R->Next; - R = R->Next; - } else { - *Next = L; - Next = &L->Next; - L = L->Next; - } - } - - return Merged; - } - -protected: - unsigned short getSubclassDataFromValue() const { return SubclassData; } - void setValueSubclassData(unsigned short D) { SubclassData = D; } -}; - -struct ValueDeleter { void operator()(Value *V) { V->deleteValue(); } }; - -/// Use this instead of std::unique_ptr or std::unique_ptr. -/// Those don't work because Value and Instruction's destructors are protected, -/// aren't virtual, and won't destroy the complete object. -using unique_value = std::unique_ptr; - -inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { - V.print(OS); - return OS; -} - -void Use::set(Value *V) { - if (Val) removeFromList(); - Val = V; - if (V) V->addUse(*this); -} - -Value *Use::operator=(Value *RHS) { - set(RHS); - return RHS; -} - -const Use &Use::operator=(const Use &RHS) { - set(RHS.Val); - return *this; -} - -template void Value::sortUseList(Compare Cmp) { - if (!UseList || !UseList->Next) - // No need to sort 0 or 1 uses. - return; - - // Note: this function completely ignores Prev pointers until the end when - // they're fixed en masse. - - // Create a binomial vector of sorted lists, visiting uses one at a time and - // merging lists as necessary. - const unsigned MaxSlots = 32; - Use *Slots[MaxSlots]; - - // Collect the first use, turning it into a single-item list. - Use *Next = UseList->Next; - UseList->Next = nullptr; - unsigned NumSlots = 1; - Slots[0] = UseList; - - // Collect all but the last use. - while (Next->Next) { - Use *Current = Next; - Next = Current->Next; - - // Turn Current into a single-item list. - Current->Next = nullptr; - - // Save Current in the first available slot, merging on collisions. - unsigned I; - for (I = 0; I < NumSlots; ++I) { - if (!Slots[I]) - break; - - // Merge two lists, doubling the size of Current and emptying slot I. - // - // Since the uses in Slots[I] originally preceded those in Current, send - // Slots[I] in as the left parameter to maintain a stable sort. - Current = mergeUseLists(Slots[I], Current, Cmp); - Slots[I] = nullptr; - } - // Check if this is a new slot. - if (I == NumSlots) { - ++NumSlots; - assert(NumSlots <= MaxSlots && "Use list bigger than 2^32"); - } - - // Found an open slot. - Slots[I] = Current; - } - - // Merge all the lists together. - assert(Next && "Expected one more Use"); - assert(!Next->Next && "Expected only one Use"); - UseList = Next; - for (unsigned I = 0; I < NumSlots; ++I) - if (Slots[I]) - // Since the uses in Slots[I] originally preceded those in UseList, send - // Slots[I] in as the left parameter to maintain a stable sort. - UseList = mergeUseLists(Slots[I], UseList, Cmp); - - // Fix the Prev pointers. - for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) { - I->Prev = Prev; - Prev = &I->Next; - } -} - -// isa - Provide some specializations of isa so that we don't have to include -// the subtype header files to test to see if the value is a subclass... -// -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - static_assert(Value::ConstantFirstVal == 0, "Val.getValueID() >= Value::ConstantFirstVal"); - return Val.getValueID() <= Value::ConstantLastVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() >= Value::ConstantDataFirstVal && - Val.getValueID() <= Value::ConstantDataLastVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() >= Value::ConstantAggregateFirstVal && - Val.getValueID() <= Value::ConstantAggregateLastVal; - } -}; - -template <> struct isa_impl { - static inline bool doit (const Value &Val) { - return Val.getValueID() == Value::ArgumentVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::InlineAsmVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() >= Value::InstructionVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::BasicBlockVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::FunctionVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GlobalVariableVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GlobalAliasVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GlobalIFuncVal; - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return isa(Val) || isa(Val); - } -}; - -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return isa(Val) || isa(Val) || - isa(Val); - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef) - -// Specialized opaque value conversions. -inline Value **unwrap(LLVMValueRef *Vals) { - return reinterpret_cast(Vals); -} - -template -inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { -#ifndef NDEBUG - for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) - unwrap(*I); // For side effect of calling assert on invalid usage. -#endif - (void)Length; - return reinterpret_cast(Vals); -} - -inline LLVMValueRef *wrap(const Value **Vals) { - return reinterpret_cast(const_cast(Vals)); -} - -} // end namespace llvm - -#endif // LLVM_IR_VALUE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ValueHandle.h b/suite/synctools/tablegen/include/llvm/IR/ValueHandle.h deleted file mode 100644 index 29560815ea..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ValueHandle.h +++ /dev/null @@ -1,562 +0,0 @@ -//===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the ValueHandle class and its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_VALUEHANDLE_H -#define LLVM_IR_VALUEHANDLE_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include - -namespace llvm { - -/// This is the common base class of value handles. -/// -/// ValueHandle's are smart pointers to Value's that have special behavior when -/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles -/// below for details. -class ValueHandleBase { - friend class Value; - -protected: - /// This indicates what sub class the handle actually is. - /// - /// This is to avoid having a vtable for the light-weight handle pointers. The - /// fully general Callback version does have a vtable. - enum HandleBaseKind { Assert, Callback, Weak, WeakTracking }; - - ValueHandleBase(const ValueHandleBase &RHS) - : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {} - - ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Val(RHS.getValPtr()) { - if (isValid(getValPtr())) - AddToExistingUseList(RHS.getPrevPtr()); - } - -private: - PointerIntPair PrevPair; - ValueHandleBase *Next = nullptr; - Value *Val = nullptr; - - void setValPtr(Value *V) { Val = V; } - -public: - explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind) {} - ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Val(V) { - if (isValid(getValPtr())) - AddToUseList(); - } - - ~ValueHandleBase() { - if (isValid(getValPtr())) - RemoveFromUseList(); - } - - Value *operator=(Value *RHS) { - if (getValPtr() == RHS) - return RHS; - if (isValid(getValPtr())) - RemoveFromUseList(); - setValPtr(RHS); - if (isValid(getValPtr())) - AddToUseList(); - return RHS; - } - - Value *operator=(const ValueHandleBase &RHS) { - if (getValPtr() == RHS.getValPtr()) - return RHS.getValPtr(); - if (isValid(getValPtr())) - RemoveFromUseList(); - setValPtr(RHS.getValPtr()); - if (isValid(getValPtr())) - AddToExistingUseList(RHS.getPrevPtr()); - return getValPtr(); - } - - Value *operator->() const { return getValPtr(); } - Value &operator*() const { - Value *V = getValPtr(); - assert(V && "Dereferencing deleted ValueHandle"); - return *V; - } - -protected: - Value *getValPtr() const { return Val; } - - static bool isValid(Value *V) { - return V && - V != DenseMapInfo::getEmptyKey() && - V != DenseMapInfo::getTombstoneKey(); - } - - /// Remove this ValueHandle from its current use list. - void RemoveFromUseList(); - - /// Clear the underlying pointer without clearing the use list. - /// - /// This should only be used if a derived class has manually removed the - /// handle from the use list. - void clearValPtr() { setValPtr(nullptr); } - -public: - // Callbacks made from Value. - static void ValueIsDeleted(Value *V); - static void ValueIsRAUWd(Value *Old, Value *New); - -private: - // Internal implementation details. - ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } - HandleBaseKind getKind() const { return PrevPair.getInt(); } - void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - - /// Add this ValueHandle to the use list for V. - /// - /// List is the address of either the head of the list or a Next node within - /// the existing use list. - void AddToExistingUseList(ValueHandleBase **List); - - /// Add this ValueHandle to the use list after Node. - void AddToExistingUseListAfter(ValueHandleBase *Node); - - /// Add this ValueHandle to the use list for V. - void AddToUseList(); -}; - -/// A nullable Value handle that is nullable. -/// -/// This is a value handle that points to a value, and nulls itself -/// out if that value is deleted. -class WeakVH : public ValueHandleBase { -public: - WeakVH() : ValueHandleBase(Weak) {} - WeakVH(Value *P) : ValueHandleBase(Weak, P) {} - WeakVH(const WeakVH &RHS) - : ValueHandleBase(Weak, RHS) {} - - WeakVH &operator=(const WeakVH &RHS) = default; - - Value *operator=(Value *RHS) { - return ValueHandleBase::operator=(RHS); - } - Value *operator=(const ValueHandleBase &RHS) { - return ValueHandleBase::operator=(RHS); - } - - operator Value*() const { - return getValPtr(); - } -}; - -// Specialize simplify_type to allow WeakVH to participate in -// dyn_cast, isa, etc. -template <> struct simplify_type { - using SimpleType = Value *; - - static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } -}; -template <> struct simplify_type { - using SimpleType = Value *; - - static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } -}; - -// Specialize DenseMapInfo to allow WeakVH to participate in DenseMap. -template <> struct DenseMapInfo { - static inline WeakVH getEmptyKey() { - return WeakVH(DenseMapInfo::getEmptyKey()); - } - - static inline WeakVH getTombstoneKey() { - return WeakVH(DenseMapInfo::getTombstoneKey()); - } - - static unsigned getHashValue(const WeakVH &Val) { - return DenseMapInfo::getHashValue(Val); - } - - static bool isEqual(const WeakVH &LHS, const WeakVH &RHS) { - return DenseMapInfo::isEqual(LHS, RHS); - } -}; - -/// Value handle that is nullable, but tries to track the Value. -/// -/// This is a value handle that tries hard to point to a Value, even across -/// RAUW operations, but will null itself out if the value is destroyed. this -/// is useful for advisory sorts of information, but should not be used as the -/// key of a map (since the map would have to rearrange itself when the pointer -/// changes). -class WeakTrackingVH : public ValueHandleBase { -public: - WeakTrackingVH() : ValueHandleBase(WeakTracking) {} - WeakTrackingVH(Value *P) : ValueHandleBase(WeakTracking, P) {} - WeakTrackingVH(const WeakTrackingVH &RHS) - : ValueHandleBase(WeakTracking, RHS) {} - - WeakTrackingVH &operator=(const WeakTrackingVH &RHS) = default; - - Value *operator=(Value *RHS) { - return ValueHandleBase::operator=(RHS); - } - Value *operator=(const ValueHandleBase &RHS) { - return ValueHandleBase::operator=(RHS); - } - - operator Value*() const { - return getValPtr(); - } - - bool pointsToAliveValue() const { - return ValueHandleBase::isValid(getValPtr()); - } -}; - -// Specialize simplify_type to allow WeakTrackingVH to participate in -// dyn_cast, isa, etc. -template <> struct simplify_type { - using SimpleType = Value *; - - static SimpleType getSimplifiedValue(WeakTrackingVH &WVH) { return WVH; } -}; -template <> struct simplify_type { - using SimpleType = Value *; - - static SimpleType getSimplifiedValue(const WeakTrackingVH &WVH) { - return WVH; - } -}; - -/// Value handle that asserts if the Value is deleted. -/// -/// This is a Value Handle that points to a value and asserts out if the value -/// is destroyed while the handle is still live. This is very useful for -/// catching dangling pointer bugs and other things which can be non-obvious. -/// One particularly useful place to use this is as the Key of a map. Dangling -/// pointer bugs often lead to really subtle bugs that only occur if another -/// object happens to get allocated to the same address as the old one. Using -/// an AssertingVH ensures that an assert is triggered as soon as the bad -/// delete occurs. -/// -/// Note that an AssertingVH handle does *not* follow values across RAUW -/// operations. This means that RAUW's need to explicitly update the -/// AssertingVH's as it moves. This is required because in non-assert mode this -/// class turns into a trivial wrapper around a pointer. -template -class AssertingVH -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - : public ValueHandleBase -#endif -{ - friend struct DenseMapInfo>; - -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } - void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } -#else - Value *ThePtr; - Value *getRawValPtr() const { return ThePtr; } - void setRawValPtr(Value *P) { ThePtr = P; } -#endif - // Convert a ValueTy*, which may be const, to the raw Value*. - static Value *GetAsValue(Value *V) { return V; } - static Value *GetAsValue(const Value *V) { return const_cast(V); } - - ValueTy *getValPtr() const { return static_cast(getRawValPtr()); } - void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } - -public: -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - AssertingVH() : ValueHandleBase(Assert) {} - AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} - AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} -#else - AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} - AssertingVH(const AssertingVH &) = default; -#endif - - operator ValueTy*() const { - return getValPtr(); - } - - ValueTy *operator=(ValueTy *RHS) { - setValPtr(RHS); - return getValPtr(); - } - ValueTy *operator=(const AssertingVH &RHS) { - setValPtr(RHS.getValPtr()); - return getValPtr(); - } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -// Treat AssertingVH like T* inside maps. This also allows using find_as() -// to look up a value without constructing a value handle. -template -struct DenseMapInfo> : DenseMapInfo {}; - -/// Value handle that tracks a Value across RAUW. -/// -/// TrackingVH is designed for situations where a client needs to hold a handle -/// to a Value (or subclass) across some operations which may move that value, -/// but should never destroy it or replace it with some unacceptable type. -/// -/// It is an error to attempt to replace a value with one of a type which is -/// incompatible with any of its outstanding TrackingVHs. -/// -/// It is an error to read from a TrackingVH that does not point to a valid -/// value. A TrackingVH is said to not point to a valid value if either it -/// hasn't yet been assigned a value yet or because the value it was tracking -/// has since been deleted. -/// -/// Assigning a value to a TrackingVH is always allowed, even if said TrackingVH -/// no longer points to a valid value. -template class TrackingVH { - WeakTrackingVH InnerHandle; - -public: - ValueTy *getValPtr() const { - assert(InnerHandle.pointsToAliveValue() && - "TrackingVH must be non-null and valid on dereference!"); - - // Check that the value is a member of the correct subclass. We would like - // to check this property on assignment for better debugging, but we don't - // want to require a virtual interface on this VH. Instead we allow RAUW to - // replace this value with a value of an invalid type, and check it here. - assert(isa(InnerHandle) && - "Tracked Value was replaced by one with an invalid type!"); - return cast(InnerHandle); - } - - void setValPtr(ValueTy *P) { - // Assigning to non-valid TrackingVH's are fine so we just unconditionally - // assign here. - InnerHandle = GetAsValue(P); - } - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. - static Value *GetAsValue(Value *V) { return V; } - static Value *GetAsValue(const Value *V) { return const_cast(V); } - -public: - TrackingVH() = default; - TrackingVH(ValueTy *P) { setValPtr(P); } - - operator ValueTy*() const { - return getValPtr(); - } - - ValueTy *operator=(ValueTy *RHS) { - setValPtr(RHS); - return getValPtr(); - } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -/// Value handle with callbacks on RAUW and destruction. -/// -/// This is a value handle that allows subclasses to define callbacks that run -/// when the underlying Value has RAUW called on it or is destroyed. This -/// class can be used as the key of a map, as long as the user takes it out of -/// the map before calling setValPtr() (since the map has to rearrange itself -/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable. -class CallbackVH : public ValueHandleBase { - virtual void anchor(); -protected: - ~CallbackVH() = default; - CallbackVH(const CallbackVH &) = default; - CallbackVH &operator=(const CallbackVH &) = default; - - void setValPtr(Value *P) { - ValueHandleBase::operator=(P); - } - -public: - CallbackVH() : ValueHandleBase(Callback) {} - CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} - CallbackVH(const Value *P) : CallbackVH(const_cast(P)) {} - - operator Value*() const { - return getValPtr(); - } - - /// Callback for Value destruction. - /// - /// Called when this->getValPtr() is destroyed, inside ~Value(), so you - /// may call any non-virtual Value method on getValPtr(), but no subclass - /// methods. If WeakTrackingVH were implemented as a CallbackVH, it would use - /// this - /// method to call setValPtr(NULL). AssertingVH would use this method to - /// cause an assertion failure. - /// - /// All implementations must remove the reference from this object to the - /// Value that's being destroyed. - virtual void deleted() { setValPtr(nullptr); } - - /// Callback for Value RAUW. - /// - /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, - /// _before_ any of the uses have actually been replaced. If WeakTrackingVH - /// were - /// implemented as a CallbackVH, it would use this method to call - /// setValPtr(new_value). AssertingVH would do nothing in this method. - virtual void allUsesReplacedWith(Value *) {} -}; - -/// Value handle that poisons itself if the Value is deleted. -/// -/// This is a Value Handle that points to a value and poisons itself if the -/// value is destroyed while the handle is still live. This is very useful for -/// catching dangling pointer bugs where an \c AssertingVH cannot be used -/// because the dangling handle needs to outlive the value without ever being -/// used. -/// -/// One particularly useful place to use this is as the Key of a map. Dangling -/// pointer bugs often lead to really subtle bugs that only occur if another -/// object happens to get allocated to the same address as the old one. Using -/// a PoisoningVH ensures that an assert is triggered if looking up a new value -/// in the map finds a handle from the old value. -/// -/// Note that a PoisoningVH handle does *not* follow values across RAUW -/// operations. This means that RAUW's need to explicitly update the -/// PoisoningVH's as it moves. This is required because in non-assert mode this -/// class turns into a trivial wrapper around a pointer. -template -class PoisoningVH final -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - : public CallbackVH -#endif -{ - friend struct DenseMapInfo>; - - // Convert a ValueTy*, which may be const, to the raw Value*. - static Value *GetAsValue(Value *V) { return V; } - static Value *GetAsValue(const Value *V) { return const_cast(V); } - -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - /// A flag tracking whether this value has been poisoned. - /// - /// On delete and RAUW, we leave the value pointer alone so that as a raw - /// pointer it produces the same value (and we fit into the same key of - /// a hash table, etc), but we poison the handle so that any top-level usage - /// will fail. - bool Poisoned = false; - - Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } - void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } - - /// Handle deletion by poisoning the handle. - void deleted() override { - assert(!Poisoned && "Tried to delete an already poisoned handle!"); - Poisoned = true; - RemoveFromUseList(); - } - - /// Handle RAUW by poisoning the handle. - void allUsesReplacedWith(Value *) override { - assert(!Poisoned && "Tried to RAUW an already poisoned handle!"); - Poisoned = true; - RemoveFromUseList(); - } -#else // LLVM_ENABLE_ABI_BREAKING_CHECKS - Value *ThePtr = nullptr; - - Value *getRawValPtr() const { return ThePtr; } - void setRawValPtr(Value *P) { ThePtr = P; } -#endif - - ValueTy *getValPtr() const { -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - assert(!Poisoned && "Accessed a poisoned value handle!"); -#endif - return static_cast(getRawValPtr()); - } - void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } - -public: - PoisoningVH() = default; -#if LLVM_ENABLE_ABI_BREAKING_CHECKS - PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {} - PoisoningVH(const PoisoningVH &RHS) - : CallbackVH(RHS), Poisoned(RHS.Poisoned) {} - - ~PoisoningVH() { - if (Poisoned) - clearValPtr(); - } - - PoisoningVH &operator=(const PoisoningVH &RHS) { - if (Poisoned) - clearValPtr(); - CallbackVH::operator=(RHS); - Poisoned = RHS.Poisoned; - return *this; - } -#else - PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} -#endif - - operator ValueTy *() const { return getValPtr(); } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -// Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap. -template struct DenseMapInfo> { - static inline PoisoningVH getEmptyKey() { - PoisoningVH Res; - Res.setRawValPtr(DenseMapInfo::getEmptyKey()); - return Res; - } - - static inline PoisoningVH getTombstoneKey() { - PoisoningVH Res; - Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); - return Res; - } - - static unsigned getHashValue(const PoisoningVH &Val) { - return DenseMapInfo::getHashValue(Val.getRawValPtr()); - } - - static bool isEqual(const PoisoningVH &LHS, const PoisoningVH &RHS) { - return DenseMapInfo::isEqual(LHS.getRawValPtr(), - RHS.getRawValPtr()); - } - - // Allow lookup by T* via find_as(), without constructing a temporary - // value handle. - - static unsigned getHashValue(const T *Val) { - return DenseMapInfo::getHashValue(Val); - } - - static bool isEqual(const T *LHS, const PoisoningVH &RHS) { - return DenseMapInfo::isEqual(LHS, RHS.getRawValPtr()); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_VALUEHANDLE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ValueMap.h b/suite/synctools/tablegen/include/llvm/IR/ValueMap.h deleted file mode 100644 index fb3f002b00..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ValueMap.h +++ /dev/null @@ -1,436 +0,0 @@ -//===- ValueMap.h - Safe map from Values to data ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the ValueMap class. ValueMap maps Value* or any subclass -// to an arbitrary other type. It provides the DenseMap interface but updates -// itself to remain safe when keys are RAUWed or deleted. By default, when a -// key is RAUWed from V1 to V2, the old mapping V1->target is removed, and a new -// mapping V2->target is added. If V2 already existed, its old target is -// overwritten. When a key is deleted, its mapping is removed. -// -// You can override a ValueMap's Config parameter to control exactly what -// happens on RAUW and destruction and to get called back on each event. It's -// legal to call back into the ValueMap from a Config's callbacks. Config -// parameters should inherit from ValueMapConfig to get default -// implementations of all the methods ValueMap uses. See ValueMapConfig for -// documentation of the functions you can override. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_VALUEMAP_H -#define LLVM_IR_VALUEMAP_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/TrackingMDRef.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Mutex.h" -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -template -class ValueMapCallbackVH; -template -class ValueMapIterator; -template -class ValueMapConstIterator; - -/// This class defines the default behavior for configurable aspects of -/// ValueMap<>. User Configs should inherit from this class to be as compatible -/// as possible with future versions of ValueMap. -template -struct ValueMapConfig { - using mutex_type = MutexT; - - /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's - /// false, the ValueMap will leave the original mapping in place. - enum { FollowRAUW = true }; - - // All methods will be called with a first argument of type ExtraData. The - // default implementations in this class take a templated first argument so - // that users' subclasses can use any type they want without having to - // override all the defaults. - struct ExtraData {}; - - template - static void onRAUW(const ExtraDataT & /*Data*/, KeyT /*Old*/, KeyT /*New*/) {} - template - static void onDelete(const ExtraDataT &/*Data*/, KeyT /*Old*/) {} - - /// Returns a mutex that should be acquired around any changes to the map. - /// This is only acquired from the CallbackVH (and held around calls to onRAUW - /// and onDelete) and not inside other ValueMap methods. NULL means that no - /// mutex is necessary. - template - static mutex_type *getMutex(const ExtraDataT &/*Data*/) { return nullptr; } -}; - -/// See the file comment. -template> -class ValueMap { - friend class ValueMapCallbackVH; - - using ValueMapCVH = ValueMapCallbackVH; - using MapT = DenseMap>; - using MDMapT = DenseMap; - using ExtraData = typename Config::ExtraData; - - MapT Map; - Optional MDMap; - ExtraData Data; - -public: - using key_type = KeyT; - using mapped_type = ValueT; - using value_type = std::pair; - using size_type = unsigned; - - explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} - explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} - // ValueMap can't be copied nor moved, because the callbacks store pointer - // to it. - ValueMap(const ValueMap &) = delete; - ValueMap(ValueMap &&) = delete; - ValueMap &operator=(const ValueMap &) = delete; - ValueMap &operator=(ValueMap &&) = delete; - - bool hasMD() const { return bool(MDMap); } - MDMapT &MD() { - if (!MDMap) - MDMap.emplace(); - return *MDMap; - } - Optional &getMDMap() { return MDMap; } - - /// Get the mapped metadata, if it's in the map. - Optional getMappedMD(const Metadata *MD) const { - if (!MDMap) - return None; - auto Where = MDMap->find(MD); - if (Where == MDMap->end()) - return None; - return Where->second.get(); - } - - using iterator = ValueMapIterator; - using const_iterator = ValueMapConstIterator; - - inline iterator begin() { return iterator(Map.begin()); } - inline iterator end() { return iterator(Map.end()); } - inline const_iterator begin() const { return const_iterator(Map.begin()); } - inline const_iterator end() const { return const_iterator(Map.end()); } - - bool empty() const { return Map.empty(); } - size_type size() const { return Map.size(); } - - /// Grow the map so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { Map.resize(Size); } - - void clear() { - Map.clear(); - MDMap.reset(); - } - - /// Return 1 if the specified key is in the map, 0 otherwise. - size_type count(const KeyT &Val) const { - return Map.find_as(Val) == Map.end() ? 0 : 1; - } - - iterator find(const KeyT &Val) { - return iterator(Map.find_as(Val)); - } - const_iterator find(const KeyT &Val) const { - return const_iterator(Map.find_as(Val)); - } - - /// lookup - Return the entry for the specified key, or a default - /// constructed value if no such entry exists. - ValueT lookup(const KeyT &Val) const { - typename MapT::const_iterator I = Map.find_as(Val); - return I != Map.end() ? I->second : ValueT(); - } - - // Inserts key,value pair into the map if the key isn't already in the map. - // If the key is already in the map, it returns false and doesn't update the - // value. - std::pair insert(const std::pair &KV) { - auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(MapResult.first), MapResult.second); - } - - std::pair insert(std::pair &&KV) { - auto MapResult = - Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second))); - return std::make_pair(iterator(MapResult.first), MapResult.second); - } - - /// insert - Range insertion of pairs. - template - void insert(InputIt I, InputIt E) { - for (; I != E; ++I) - insert(*I); - } - - bool erase(const KeyT &Val) { - typename MapT::iterator I = Map.find_as(Val); - if (I == Map.end()) - return false; - - Map.erase(I); - return true; - } - void erase(iterator I) { - return Map.erase(I.base()); - } - - value_type& FindAndConstruct(const KeyT &Key) { - return Map.FindAndConstruct(Wrap(Key)); - } - - ValueT &operator[](const KeyT &Key) { - return Map[Wrap(Key)]; - } - - /// isPointerIntoBucketsArray - Return true if the specified pointer points - /// somewhere into the ValueMap's array of buckets (i.e. either to a key or - /// value in the ValueMap). - bool isPointerIntoBucketsArray(const void *Ptr) const { - return Map.isPointerIntoBucketsArray(Ptr); - } - - /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets - /// array. In conjunction with the previous method, this can be used to - /// determine whether an insertion caused the ValueMap to reallocate. - const void *getPointerIntoBucketsArray() const { - return Map.getPointerIntoBucketsArray(); - } - -private: - // Takes a key being looked up in the map and wraps it into a - // ValueMapCallbackVH, the actual key type of the map. We use a helper - // function because ValueMapCVH is constructed with a second parameter. - ValueMapCVH Wrap(KeyT key) const { - // The only way the resulting CallbackVH could try to modify *this (making - // the const_cast incorrect) is if it gets inserted into the map. But then - // this function must have been called from a non-const method, making the - // const_cast ok. - return ValueMapCVH(key, const_cast(this)); - } -}; - -// This CallbackVH updates its ValueMap when the contained Value changes, -// according to the user's preferences expressed through the Config object. -template -class ValueMapCallbackVH final : public CallbackVH { - friend class ValueMap; - friend struct DenseMapInfo; - - using ValueMapT = ValueMap; - using KeySansPointerT = std::remove_pointer_t; - - ValueMapT *Map; - - ValueMapCallbackVH(KeyT Key, ValueMapT *Map) - : CallbackVH(const_cast(static_cast(Key))), - Map(Map) {} - - // Private constructor used to create empty/tombstone DenseMap keys. - ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} - -public: - KeyT Unwrap() const { return cast_or_null(getValPtr()); } - - void deleted() override { - // Make a copy that won't get changed even when *this is destroyed. - ValueMapCallbackVH Copy(*this); - typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); - std::unique_lock Guard; - if (M) - Guard = std::unique_lock(*M); - Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. - Copy.Map->Map.erase(Copy); // Definitely destroys *this. - } - - void allUsesReplacedWith(Value *new_key) override { - assert(isa(new_key) && - "Invalid RAUW on key of ValueMap<>"); - // Make a copy that won't get changed even when *this is destroyed. - ValueMapCallbackVH Copy(*this); - typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); - std::unique_lock Guard; - if (M) - Guard = std::unique_lock(*M); - - KeyT typed_new_key = cast(new_key); - // Can destroy *this: - Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key); - if (Config::FollowRAUW) { - typename ValueMapT::MapT::iterator I = Copy.Map->Map.find(Copy); - // I could == Copy.Map->Map.end() if the onRAUW callback already - // removed the old mapping. - if (I != Copy.Map->Map.end()) { - ValueT Target(std::move(I->second)); - Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target))); - } - } - } -}; - -template -struct DenseMapInfo> { - using VH = ValueMapCallbackVH; - - static inline VH getEmptyKey() { - return VH(DenseMapInfo::getEmptyKey()); - } - - static inline VH getTombstoneKey() { - return VH(DenseMapInfo::getTombstoneKey()); - } - - static unsigned getHashValue(const VH &Val) { - return DenseMapInfo::getHashValue(Val.Unwrap()); - } - - static unsigned getHashValue(const KeyT &Val) { - return DenseMapInfo::getHashValue(Val); - } - - static bool isEqual(const VH &LHS, const VH &RHS) { - return LHS == RHS; - } - - static bool isEqual(const KeyT &LHS, const VH &RHS) { - return LHS == RHS.getValPtr(); - } -}; - -template class ValueMapIterator { - using BaseT = typename DenseMapT::iterator; - using ValueT = typename DenseMapT::mapped_type; - - BaseT I; - -public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::pair; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - ValueMapIterator() : I() {} - ValueMapIterator(BaseT I) : I(I) {} - - BaseT base() const { return I; } - - struct ValueTypeProxy { - const KeyT first; - ValueT& second; - - ValueTypeProxy *operator->() { return this; } - - operator std::pair() const { - return std::make_pair(first, second); - } - }; - - ValueTypeProxy operator*() const { - ValueTypeProxy Result = {I->first.Unwrap(), I->second}; - return Result; - } - - ValueTypeProxy operator->() const { - return operator*(); - } - - bool operator==(const ValueMapIterator &RHS) const { - return I == RHS.I; - } - bool operator!=(const ValueMapIterator &RHS) const { - return I != RHS.I; - } - - inline ValueMapIterator& operator++() { // Preincrement - ++I; - return *this; - } - ValueMapIterator operator++(int) { // Postincrement - ValueMapIterator tmp = *this; ++*this; return tmp; - } -}; - -template class ValueMapConstIterator { - using BaseT = typename DenseMapT::const_iterator; - using ValueT = typename DenseMapT::mapped_type; - - BaseT I; - -public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::pair; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - ValueMapConstIterator() : I() {} - ValueMapConstIterator(BaseT I) : I(I) {} - ValueMapConstIterator(ValueMapIterator Other) - : I(Other.base()) {} - - BaseT base() const { return I; } - - struct ValueTypeProxy { - const KeyT first; - const ValueT& second; - ValueTypeProxy *operator->() { return this; } - operator std::pair() const { - return std::make_pair(first, second); - } - }; - - ValueTypeProxy operator*() const { - ValueTypeProxy Result = {I->first.Unwrap(), I->second}; - return Result; - } - - ValueTypeProxy operator->() const { - return operator*(); - } - - bool operator==(const ValueMapConstIterator &RHS) const { - return I == RHS.I; - } - bool operator!=(const ValueMapConstIterator &RHS) const { - return I != RHS.I; - } - - inline ValueMapConstIterator& operator++() { // Preincrement - ++I; - return *this; - } - ValueMapConstIterator operator++(int) { // Postincrement - ValueMapConstIterator tmp = *this; ++*this; return tmp; - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_VALUEMAP_H diff --git a/suite/synctools/tablegen/include/llvm/IR/ValueSymbolTable.h b/suite/synctools/tablegen/include/llvm/IR/ValueSymbolTable.h deleted file mode 100644 index 43d00268f4..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/ValueSymbolTable.h +++ /dev/null @@ -1,145 +0,0 @@ -//===- llvm/ValueSymbolTable.h - Implement a Value Symtab -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the name/Value symbol table for LLVM. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_VALUESYMBOLTABLE_H -#define LLVM_IR_VALUESYMBOLTABLE_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Value.h" -#include - -namespace llvm { - -class Argument; -class BasicBlock; -class Function; -class GlobalAlias; -class GlobalIFunc; -class GlobalVariable; -class Instruction; -template class SmallString; -template class SymbolTableListTraits; - -/// This class provides a symbol table of name/value pairs. It is essentially -/// a std::map but has a controlled interface provided by -/// LLVM as well as ensuring uniqueness of names. -/// -class ValueSymbolTable { - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class SymbolTableListTraits; - friend class Value; - -/// @name Types -/// @{ -public: - /// A mapping of names to values. - using ValueMap = StringMap; - - /// An iterator over a ValueMap. - using iterator = ValueMap::iterator; - - /// A const_iterator over a ValueMap. - using const_iterator = ValueMap::const_iterator; - -/// @} -/// @name Constructors -/// @{ - - ValueSymbolTable(int MaxNameSize = -1) : vmap(0), MaxNameSize(MaxNameSize) {} - ~ValueSymbolTable(); - - /// @} - /// @name Accessors - /// @{ - - /// This method finds the value with the given \p Name in the - /// the symbol table. - /// @returns the value associated with the \p Name - /// Lookup a named Value. - Value *lookup(StringRef Name) const { - if (MaxNameSize > -1 && Name.size() > (unsigned)MaxNameSize) - Name = Name.substr(0, std::max(1u, (unsigned)MaxNameSize)); - - return vmap.lookup(Name); - } - - /// @returns true iff the symbol table is empty - /// Determine if the symbol table is empty - inline bool empty() const { return vmap.empty(); } - - /// The number of name/type pairs is returned. - inline unsigned size() const { return unsigned(vmap.size()); } - - /// This function can be used from the debugger to display the - /// content of the symbol table while debugging. - /// Print out symbol table on stderr - void dump() const; - -/// @} -/// @name Iteration -/// @{ - - /// Get an iterator that from the beginning of the symbol table. - inline iterator begin() { return vmap.begin(); } - - /// Get a const_iterator that from the beginning of the symbol table. - inline const_iterator begin() const { return vmap.begin(); } - - /// Get an iterator to the end of the symbol table. - inline iterator end() { return vmap.end(); } - - /// Get a const_iterator to the end of the symbol table. - inline const_iterator end() const { return vmap.end(); } - - /// @} - /// @name Mutators - /// @{ -private: - ValueName *makeUniqueName(Value *V, SmallString<256> &UniqueName); - - /// This method adds the provided value \p N to the symbol table. The Value - /// must have a name which is used to place the value in the symbol table. - /// If the inserted name conflicts, this renames the value. - /// Add a named value to the symbol table - void reinsertValue(Value *V); - - /// createValueName - This method attempts to create a value name and insert - /// it into the symbol table with the specified name. If it conflicts, it - /// auto-renames the name and returns that instead. - ValueName *createValueName(StringRef Name, Value *V); - - /// This method removes a value from the symbol table. It leaves the - /// ValueName attached to the value, but it is no longer inserted in the - /// symtab. - void removeValueName(ValueName *V); - - /// @} - /// @name Internal Data - /// @{ - - ValueMap vmap; ///< The map that holds the symbol table. - int MaxNameSize; ///< The maximum size for each name. If the limit is - ///< exceeded, the name is capped. - mutable uint32_t LastUnique = 0; ///< Counter for tracking unique names - -/// @} -}; - -} // end namespace llvm - -#endif // LLVM_IR_VALUESYMBOLTABLE_H diff --git a/suite/synctools/tablegen/include/llvm/IR/Verifier.h b/suite/synctools/tablegen/include/llvm/IR/Verifier.h deleted file mode 100644 index 52a4c7b430..0000000000 --- a/suite/synctools/tablegen/include/llvm/IR/Verifier.h +++ /dev/null @@ -1,150 +0,0 @@ -//===- Verifier.h - LLVM IR Verifier ----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the function verifier interface, that can be used for -// validation checking of input to the system, and for checking that -// transformations haven't done something bad. -// -// Note that this does not provide full 'java style' security and verifications, -// instead it just tries to ensure that code is well formed. -// -// To see what specifically is checked, look at the top of Verifier.cpp -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_VERIFIER_H -#define LLVM_IR_VERIFIER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/PassManager.h" -#include - -namespace llvm { - -class APInt; -class Function; -class FunctionPass; -class Instruction; -class MDNode; -class Module; -class raw_ostream; -struct VerifierSupport; - -/// Verify that the TBAA Metadatas are valid. -class TBAAVerifier { - VerifierSupport *Diagnostic = nullptr; - - /// Helper to diagnose a failure - template void CheckFailed(Tys &&... Args); - - /// Cache of TBAA base nodes that have already been visited. This cachce maps - /// a node that has been visited to a pair (IsInvalid, BitWidth) where - /// - /// \c IsInvalid is true iff the node is invalid. - /// \c BitWidth, if non-zero, is the bitwidth of the integer used to denoting - /// the offset of the access. If zero, only a zero offset is allowed. - /// - /// \c BitWidth has no meaning if \c IsInvalid is true. - using TBAABaseNodeSummary = std::pair; - DenseMap TBAABaseNodes; - - /// Maps an alleged scalar TBAA node to a boolean that is true if the said - /// TBAA node is a valid scalar TBAA node or false otherwise. - DenseMap TBAAScalarNodes; - - /// \name Helper functions used by \c visitTBAAMetadata. - /// @{ - MDNode *getFieldNodeFromTBAABaseNode(Instruction &I, const MDNode *BaseNode, - APInt &Offset, bool IsNewFormat); - TBAAVerifier::TBAABaseNodeSummary verifyTBAABaseNode(Instruction &I, - const MDNode *BaseNode, - bool IsNewFormat); - TBAABaseNodeSummary verifyTBAABaseNodeImpl(Instruction &I, - const MDNode *BaseNode, - bool IsNewFormat); - - bool isValidScalarTBAANode(const MDNode *MD); - /// @} - -public: - TBAAVerifier(VerifierSupport *Diagnostic = nullptr) - : Diagnostic(Diagnostic) {} - /// Visit an instruction and return true if it is valid, return false if an - /// invalid TBAA is attached. - bool visitTBAAMetadata(Instruction &I, const MDNode *MD); -}; - -/// Check a function for errors, useful for use when debugging a -/// pass. -/// -/// If there are no errors, the function returns false. If an error is found, -/// a message describing the error is written to OS (if non-null) and true is -/// returned. -bool verifyFunction(const Function &F, raw_ostream *OS = nullptr); - -/// Check a module for errors. -/// -/// If there are no errors, the function returns false. If an error is -/// found, a message describing the error is written to OS (if -/// non-null) and true is returned. -/// -/// \return true if the module is broken. If BrokenDebugInfo is -/// supplied, DebugInfo verification failures won't be considered as -/// error and instead *BrokenDebugInfo will be set to true. Debug -/// info errors can be "recovered" from by stripping the debug info. -bool verifyModule(const Module &M, raw_ostream *OS = nullptr, - bool *BrokenDebugInfo = nullptr); - -FunctionPass *createVerifierPass(bool FatalErrors = true); - -/// Check a module for errors, and report separate error states for IR -/// and debug info errors. -class VerifierAnalysis : public AnalysisInfoMixin { - friend AnalysisInfoMixin; - - static AnalysisKey Key; - -public: - struct Result { - bool IRBroken, DebugInfoBroken; - }; - - Result run(Module &M, ModuleAnalysisManager &); - Result run(Function &F, FunctionAnalysisManager &); - static bool isRequired() { return true; } -}; - -/// Check a module for errors, but report debug info errors separately. -/// Otherwise behaves as the normal verifyModule. Debug info errors can be -/// "recovered" from by stripping the debug info. -bool verifyModule(bool &BrokenDebugInfo, const Module &M, raw_ostream *OS); - -/// Create a verifier pass. -/// -/// Check a module or function for validity. This is essentially a pass wrapped -/// around the above verifyFunction and verifyModule routines and -/// functionality. When the pass detects a verification error it is always -/// printed to stderr, and by default they are fatal. You can override that by -/// passing \c false to \p FatalErrors. -/// -/// Note that this creates a pass suitable for the legacy pass manager. It has -/// nothing to do with \c VerifierPass. -class VerifierPass : public PassInfoMixin { - bool FatalErrors; - -public: - explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); - static bool isRequired() { return true; } -}; - -} // end namespace llvm - -#endif // LLVM_IR_VERIFIER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMapping.h b/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMapping.h deleted file mode 100644 index dd3ab73e6b..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ /dev/null @@ -1,1066 +0,0 @@ -//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Code coverage mapping data is generated by clang and read by -// llvm-cov to show code coverage statistics for a file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H -#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Alignment.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class IndexedInstrProfReader; - -namespace coverage { - -class CoverageMappingReader; -struct CoverageMappingRecord; - -enum class coveragemap_error { - success = 0, - eof, - no_data_found, - unsupported_version, - truncated, - malformed, - decompression_failed, - invalid_or_missing_arch_specifier -}; - -const std::error_category &coveragemap_category(); - -inline std::error_code make_error_code(coveragemap_error E) { - return std::error_code(static_cast(E), coveragemap_category()); -} - -class CoverageMapError : public ErrorInfo { -public: - CoverageMapError(coveragemap_error Err) : Err(Err) { - assert(Err != coveragemap_error::success && "Not an error"); - } - - std::string message() const override; - - void log(raw_ostream &OS) const override { OS << message(); } - - std::error_code convertToErrorCode() const override { - return make_error_code(Err); - } - - coveragemap_error get() const { return Err; } - - static char ID; - -private: - coveragemap_error Err; -}; - -/// A Counter is an abstract value that describes how to compute the -/// execution count for a region of code using the collected profile count data. -struct Counter { - /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to - /// the CounterKind. This means CounterKind has to leave bit 0 free. - enum CounterKind { Zero, CounterValueReference, Expression }; - static const unsigned EncodingTagBits = 2; - static const unsigned EncodingTagMask = 0x3; - static const unsigned EncodingCounterTagAndExpansionRegionTagBits = - EncodingTagBits + 1; - -private: - CounterKind Kind = Zero; - unsigned ID = 0; - - Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} - -public: - Counter() = default; - - CounterKind getKind() const { return Kind; } - - bool isZero() const { return Kind == Zero; } - - bool isExpression() const { return Kind == Expression; } - - unsigned getCounterID() const { return ID; } - - unsigned getExpressionID() const { return ID; } - - friend bool operator==(const Counter &LHS, const Counter &RHS) { - return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; - } - - friend bool operator!=(const Counter &LHS, const Counter &RHS) { - return !(LHS == RHS); - } - - friend bool operator<(const Counter &LHS, const Counter &RHS) { - return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); - } - - /// Return the counter that represents the number zero. - static Counter getZero() { return Counter(); } - - /// Return the counter that corresponds to a specific profile counter. - static Counter getCounter(unsigned CounterId) { - return Counter(CounterValueReference, CounterId); - } - - /// Return the counter that corresponds to a specific addition counter - /// expression. - static Counter getExpression(unsigned ExpressionId) { - return Counter(Expression, ExpressionId); - } -}; - -/// A Counter expression is a value that represents an arithmetic operation -/// with two counters. -struct CounterExpression { - enum ExprKind { Subtract, Add }; - ExprKind Kind; - Counter LHS, RHS; - - CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) - : Kind(Kind), LHS(LHS), RHS(RHS) {} -}; - -/// A Counter expression builder is used to construct the counter expressions. -/// It avoids unnecessary duplication and simplifies algebraic expressions. -class CounterExpressionBuilder { - /// A list of all the counter expressions - std::vector Expressions; - - /// A lookup table for the index of a given expression. - DenseMap ExpressionIndices; - - /// Return the counter which corresponds to the given expression. - /// - /// If the given expression is already stored in the builder, a counter - /// that references that expression is returned. Otherwise, the given - /// expression is added to the builder's collection of expressions. - Counter get(const CounterExpression &E); - - /// Represents a term in a counter expression tree. - struct Term { - unsigned CounterID; - int Factor; - - Term(unsigned CounterID, int Factor) - : CounterID(CounterID), Factor(Factor) {} - }; - - /// Gather the terms of the expression tree for processing. - /// - /// This collects each addition and subtraction referenced by the counter into - /// a sequence that can be sorted and combined to build a simplified counter - /// expression. - void extractTerms(Counter C, int Sign, SmallVectorImpl &Terms); - - /// Simplifies the given expression tree - /// by getting rid of algebraically redundant operations. - Counter simplify(Counter ExpressionTree); - -public: - ArrayRef getExpressions() const { return Expressions; } - - /// Return a counter that represents the expression that adds LHS and RHS. - Counter add(Counter LHS, Counter RHS); - - /// Return a counter that represents the expression that subtracts RHS from - /// LHS. - Counter subtract(Counter LHS, Counter RHS); -}; - -using LineColPair = std::pair; - -/// A Counter mapping region associates a source range with a specific counter. -struct CounterMappingRegion { - enum RegionKind { - /// A CodeRegion associates some code with a counter - CodeRegion, - - /// An ExpansionRegion represents a file expansion region that associates - /// a source range with the expansion of a virtual source file, such as - /// for a macro instantiation or #include file. - ExpansionRegion, - - /// A SkippedRegion represents a source range with code that was skipped - /// by a preprocessor or similar means. - SkippedRegion, - - /// A GapRegion is like a CodeRegion, but its count is only set as the - /// line execution count when it's the only region in the line. - GapRegion, - - /// A BranchRegion represents leaf-level boolean expressions and is - /// associated with two counters, each representing the number of times the - /// expression evaluates to true or false. - BranchRegion - }; - - /// Primary Counter that is also used for Branch Regions (TrueCount). - Counter Count; - - /// Secondary Counter used for Branch Regions (FalseCount). - Counter FalseCount; - - unsigned FileID, ExpandedFileID; - unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; - RegionKind Kind; - - CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, - unsigned LineStart, unsigned ColumnStart, - unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) - : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), - LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), - ColumnEnd(ColumnEnd), Kind(Kind) {} - - CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, - unsigned ExpandedFileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd, RegionKind Kind) - : Count(Count), FalseCount(FalseCount), FileID(FileID), - ExpandedFileID(ExpandedFileID), LineStart(LineStart), - ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), - Kind(Kind) {} - - static CounterMappingRegion - makeRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { - return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, - LineEnd, ColumnEnd, CodeRegion); - } - - static CounterMappingRegion - makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { - return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, - ColumnStart, LineEnd, ColumnEnd, - ExpansionRegion); - } - - static CounterMappingRegion - makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, - unsigned LineEnd, unsigned ColumnEnd) { - return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, - LineEnd, ColumnEnd, SkippedRegion); - } - - static CounterMappingRegion - makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { - return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, - LineEnd, (1U << 31) | ColumnEnd, GapRegion); - } - - static CounterMappingRegion - makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, - unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd) { - return CounterMappingRegion(Count, FalseCount, FileID, 0, LineStart, - ColumnStart, LineEnd, ColumnEnd, BranchRegion); - } - - inline LineColPair startLoc() const { - return LineColPair(LineStart, ColumnStart); - } - - inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } -}; - -/// Associates a source range with an execution count. -struct CountedRegion : public CounterMappingRegion { - uint64_t ExecutionCount; - uint64_t FalseExecutionCount; - bool Folded; - - CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) - : CounterMappingRegion(R), ExecutionCount(ExecutionCount), - FalseExecutionCount(0), Folded(false) {} - - CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, - uint64_t FalseExecutionCount) - : CounterMappingRegion(R), ExecutionCount(ExecutionCount), - FalseExecutionCount(FalseExecutionCount), Folded(false) {} -}; - -/// A Counter mapping context is used to connect the counters, expressions -/// and the obtained counter values. -class CounterMappingContext { - ArrayRef Expressions; - ArrayRef CounterValues; - -public: - CounterMappingContext(ArrayRef Expressions, - ArrayRef CounterValues = None) - : Expressions(Expressions), CounterValues(CounterValues) {} - - void setCounts(ArrayRef Counts) { CounterValues = Counts; } - - void dump(const Counter &C, raw_ostream &OS) const; - void dump(const Counter &C) const { dump(C, dbgs()); } - - /// Return the number of times that a region of code associated with this - /// counter was executed. - Expected evaluate(const Counter &C) const; - - unsigned getMaxCounterID(const Counter &C) const; -}; - -/// Code coverage information for a single function. -struct FunctionRecord { - /// Raw function name. - std::string Name; - /// Mapping from FileID (i.e. vector index) to filename. Used to support - /// macro expansions within a function in which the macro and function are - /// defined in separate files. - /// - /// TODO: Uniquing filenames across all function records may be a performance - /// optimization. - std::vector Filenames; - /// Regions in the function along with their counts. - std::vector CountedRegions; - /// Branch Regions in the function along with their counts. - std::vector CountedBranchRegions; - /// The number of times this function was executed. - uint64_t ExecutionCount = 0; - - FunctionRecord(StringRef Name, ArrayRef Filenames) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} - - FunctionRecord(FunctionRecord &&FR) = default; - FunctionRecord &operator=(FunctionRecord &&) = default; - - void pushRegion(CounterMappingRegion Region, uint64_t Count, - uint64_t FalseCount) { - if (Region.Kind == CounterMappingRegion::BranchRegion) { - CountedBranchRegions.emplace_back(Region, Count, FalseCount); - // If both counters are hard-coded to zero, then this region represents a - // constant-folded branch. - if (Region.Count.isZero() && Region.FalseCount.isZero()) - CountedBranchRegions.back().Folded = true; - return; - } - if (CountedRegions.empty()) - ExecutionCount = Count; - CountedRegions.emplace_back(Region, Count, FalseCount); - } -}; - -/// Iterator over Functions, optionally filtered to a single file. -class FunctionRecordIterator - : public iterator_facade_base { - ArrayRef Records; - ArrayRef::iterator Current; - StringRef Filename; - - /// Skip records whose primary file is not \c Filename. - void skipOtherFiles(); - -public: - FunctionRecordIterator(ArrayRef Records_, - StringRef Filename = "") - : Records(Records_), Current(Records.begin()), Filename(Filename) { - skipOtherFiles(); - } - - FunctionRecordIterator() : Current(Records.begin()) {} - - bool operator==(const FunctionRecordIterator &RHS) const { - return Current == RHS.Current && Filename == RHS.Filename; - } - - const FunctionRecord &operator*() const { return *Current; } - - FunctionRecordIterator &operator++() { - assert(Current != Records.end() && "incremented past end"); - ++Current; - skipOtherFiles(); - return *this; - } -}; - -/// Coverage information for a macro expansion or #included file. -/// -/// When covered code has pieces that can be expanded for more detail, such as a -/// preprocessor macro use and its definition, these are represented as -/// expansions whose coverage can be looked up independently. -struct ExpansionRecord { - /// The abstract file this expansion covers. - unsigned FileID; - /// The region that expands to this record. - const CountedRegion &Region; - /// Coverage for the expansion. - const FunctionRecord &Function; - - ExpansionRecord(const CountedRegion &Region, - const FunctionRecord &Function) - : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} -}; - -/// The execution count information starting at a point in a file. -/// -/// A sequence of CoverageSegments gives execution counts for a file in format -/// that's simple to iterate through for processing. -struct CoverageSegment { - /// The line where this segment begins. - unsigned Line; - /// The column where this segment begins. - unsigned Col; - /// The execution count, or zero if no count was recorded. - uint64_t Count; - /// When false, the segment was uninstrumented or skipped. - bool HasCount; - /// Whether this enters a new region or returns to a previous count. - bool IsRegionEntry; - /// Whether this enters a gap region. - bool IsGapRegion; - - CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) - : Line(Line), Col(Col), Count(0), HasCount(false), - IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} - - CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, - bool IsRegionEntry, bool IsGapRegion = false, - bool IsBranchRegion = false) - : Line(Line), Col(Col), Count(Count), HasCount(true), - IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} - - friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { - return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, - L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, - R.HasCount, R.IsRegionEntry, - R.IsGapRegion); - } -}; - -/// An instantiation group contains a \c FunctionRecord list, such that each -/// record corresponds to a distinct instantiation of the same function. -/// -/// Note that it's possible for a function to have more than one instantiation -/// (consider C++ template specializations or static inline functions). -class InstantiationGroup { - friend class CoverageMapping; - - unsigned Line; - unsigned Col; - std::vector Instantiations; - - InstantiationGroup(unsigned Line, unsigned Col, - std::vector Instantiations) - : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} - -public: - InstantiationGroup(const InstantiationGroup &) = delete; - InstantiationGroup(InstantiationGroup &&) = default; - - /// Get the number of instantiations in this group. - size_t size() const { return Instantiations.size(); } - - /// Get the line where the common function was defined. - unsigned getLine() const { return Line; } - - /// Get the column where the common function was defined. - unsigned getColumn() const { return Col; } - - /// Check if the instantiations in this group have a common mangled name. - bool hasName() const { - for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) - if (Instantiations[I]->Name != Instantiations[0]->Name) - return false; - return true; - } - - /// Get the common mangled name for instantiations in this group. - StringRef getName() const { - assert(hasName() && "Instantiations don't have a shared name"); - return Instantiations[0]->Name; - } - - /// Get the total execution count of all instantiations in this group. - uint64_t getTotalExecutionCount() const { - uint64_t Count = 0; - for (const FunctionRecord *F : Instantiations) - Count += F->ExecutionCount; - return Count; - } - - /// Get the instantiations in this group. - ArrayRef getInstantiations() const { - return Instantiations; - } -}; - -/// Coverage information to be processed or displayed. -/// -/// This represents the coverage of an entire file, expansion, or function. It -/// provides a sequence of CoverageSegments to iterate through, as well as the -/// list of expansions that can be further processed. -class CoverageData { - friend class CoverageMapping; - - std::string Filename; - std::vector Segments; - std::vector Expansions; - std::vector BranchRegions; - -public: - CoverageData() = default; - - CoverageData(StringRef Filename) : Filename(Filename) {} - - /// Get the name of the file this data covers. - StringRef getFilename() const { return Filename; } - - /// Get an iterator over the coverage segments for this object. The segments - /// are guaranteed to be uniqued and sorted by location. - std::vector::const_iterator begin() const { - return Segments.begin(); - } - - std::vector::const_iterator end() const { - return Segments.end(); - } - - bool empty() const { return Segments.empty(); } - - /// Expansions that can be further processed. - ArrayRef getExpansions() const { return Expansions; } - - /// Branches that can be further processed. - ArrayRef getBranches() const { return BranchRegions; } -}; - -/// The mapping of profile information to coverage data. -/// -/// This is the main interface to get coverage information, using a profile to -/// fill out execution counts. -class CoverageMapping { - DenseMap> RecordProvenance; - std::vector Functions; - DenseMap> FilenameHash2RecordIndices; - std::vector> FuncHashMismatches; - - CoverageMapping() = default; - - // Load coverage records from readers. - static Error loadFromReaders( - ArrayRef> CoverageReaders, - IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage); - - /// Add a function record corresponding to \p Record. - Error loadFunctionRecord(const CoverageMappingRecord &Record, - IndexedInstrProfReader &ProfileReader); - - /// Look up the indices for function records which are at least partially - /// defined in the specified file. This is guaranteed to return a superset of - /// such records: extra records not in the file may be included if there is - /// a hash collision on the filename. Clients must be robust to collisions. - ArrayRef - getImpreciseRecordIndicesForFilename(StringRef Filename) const; - -public: - CoverageMapping(const CoverageMapping &) = delete; - CoverageMapping &operator=(const CoverageMapping &) = delete; - - /// Load the coverage mapping using the given readers. - static Expected> - load(ArrayRef> CoverageReaders, - IndexedInstrProfReader &ProfileReader); - - /// Load the coverage mapping from the given object files and profile. If - /// \p Arches is non-empty, it must specify an architecture for each object. - /// Ignores non-instrumented object files unless all are not instrumented. - static Expected> - load(ArrayRef ObjectFilenames, StringRef ProfileFilename, - ArrayRef Arches = None, StringRef CompilationDir = ""); - - /// The number of functions that couldn't have their profiles mapped. - /// - /// This is a count of functions whose profile is out of date or otherwise - /// can't be associated with any coverage information. - unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } - - /// A hash mismatch occurs when a profile record for a symbol does not have - /// the same hash as a coverage mapping record for the same symbol. This - /// returns a list of hash mismatches, where each mismatch is a pair of the - /// symbol name and its coverage mapping hash. - ArrayRef> getHashMismatches() const { - return FuncHashMismatches; - } - - /// Returns a lexicographically sorted, unique list of files that are - /// covered. - std::vector getUniqueSourceFiles() const; - - /// Get the coverage for a particular file. - /// - /// The given filename must be the name as recorded in the coverage - /// information. That is, only names returned from getUniqueSourceFiles will - /// yield a result. - CoverageData getCoverageForFile(StringRef Filename) const; - - /// Get the coverage for a particular function. - CoverageData getCoverageForFunction(const FunctionRecord &Function) const; - - /// Get the coverage for an expansion within a coverage set. - CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; - - /// Gets all of the functions covered by this profile. - iterator_range getCoveredFunctions() const { - return make_range(FunctionRecordIterator(Functions), - FunctionRecordIterator()); - } - - /// Gets all of the functions in a particular file. - iterator_range - getCoveredFunctions(StringRef Filename) const { - return make_range(FunctionRecordIterator(Functions, Filename), - FunctionRecordIterator()); - } - - /// Get the list of function instantiation groups in a particular file. - /// - /// Every instantiation group in a program is attributed to exactly one file: - /// the file in which the definition for the common function begins. - std::vector - getInstantiationGroups(StringRef Filename) const; -}; - -/// Coverage statistics for a single line. -class LineCoverageStats { - uint64_t ExecutionCount; - bool HasMultipleRegions; - bool Mapped; - unsigned Line; - ArrayRef LineSegments; - const CoverageSegment *WrappedSegment; - - friend class LineCoverageIterator; - LineCoverageStats() = default; - -public: - LineCoverageStats(ArrayRef LineSegments, - const CoverageSegment *WrappedSegment, unsigned Line); - - uint64_t getExecutionCount() const { return ExecutionCount; } - - bool hasMultipleRegions() const { return HasMultipleRegions; } - - bool isMapped() const { return Mapped; } - - unsigned getLine() const { return Line; } - - ArrayRef getLineSegments() const { - return LineSegments; - } - - const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } -}; - -/// An iterator over the \c LineCoverageStats objects for lines described by -/// a \c CoverageData instance. -class LineCoverageIterator - : public iterator_facade_base { -public: - LineCoverageIterator(const CoverageData &CD) - : LineCoverageIterator(CD, CD.begin()->Line) {} - - LineCoverageIterator(const CoverageData &CD, unsigned Line) - : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), - Line(Line) { - this->operator++(); - } - - bool operator==(const LineCoverageIterator &R) const { - return &CD == &R.CD && Next == R.Next && Ended == R.Ended; - } - - const LineCoverageStats &operator*() const { return Stats; } - - LineCoverageIterator &operator++(); - - LineCoverageIterator getEnd() const { - auto EndIt = *this; - EndIt.Next = CD.end(); - EndIt.Ended = true; - return EndIt; - } - -private: - const CoverageData &CD; - const CoverageSegment *WrappedSegment; - std::vector::const_iterator Next; - bool Ended; - unsigned Line; - SmallVector Segments; - LineCoverageStats Stats; -}; - -/// Get a \c LineCoverageIterator range for the lines described by \p CD. -static inline iterator_range -getLineCoverageStats(const coverage::CoverageData &CD) { - auto Begin = LineCoverageIterator(CD); - auto End = Begin.getEnd(); - return make_range(Begin, End); -} - -// Coverage mapping data (V2) has the following layout: -// IPSK_covmap: -// [CoverageMapFileHeader] -// [ArrayStart] -// [CovMapFunctionRecordV2] -// [CovMapFunctionRecordV2] -// ... -// [ArrayEnd] -// [Encoded Filenames and Region Mapping Data] -// -// Coverage mapping data (V3) has the following layout: -// IPSK_covmap: -// [CoverageMapFileHeader] -// [Encoded Filenames] -// IPSK_covfun: -// [ArrayStart] -// odr_name_1: [CovMapFunctionRecordV3] -// odr_name_2: [CovMapFunctionRecordV3] -// ... -// [ArrayEnd] -// -// Both versions of the coverage mapping format encode the same information, -// but the V3 format does so more compactly by taking advantage of linkonce_odr -// semantics (it allows exactly 1 function record per name reference). - -/// This namespace defines accessors shared by different versions of coverage -/// mapping records. -namespace accessors { - -/// Return the structural hash associated with the function. -template -uint64_t getFuncHash(const FuncRecordTy *Record) { - return support::endian::byte_swap(Record->FuncHash); -} - -/// Return the coverage map data size for the function. -template -uint64_t getDataSize(const FuncRecordTy *Record) { - return support::endian::byte_swap(Record->DataSize); -} - -/// Return the function lookup key. The value is considered opaque. -template -uint64_t getFuncNameRef(const FuncRecordTy *Record) { - return support::endian::byte_swap(Record->NameRef); -} - -/// Return the PGO name of the function. Used for formats in which the name is -/// a hash. -template -Error getFuncNameViaRef(const FuncRecordTy *Record, - InstrProfSymtab &ProfileNames, StringRef &FuncName) { - uint64_t NameRef = getFuncNameRef(Record); - FuncName = ProfileNames.getFuncName(NameRef); - return Error::success(); -} - -/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the -/// coverage mapping is attached to the file header, instead of to the function -/// record. -template -StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record, - const char *MappingBuf) { - return {MappingBuf, size_t(getDataSize(Record))}; -} - -/// Advance to the next out-of-line coverage mapping and its associated -/// function record. -template -std::pair -advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) { - return {MappingBuf + getDataSize(Record), Record + 1}; -} - -} // end namespace accessors - -LLVM_PACKED_START -template -struct CovMapFunctionRecordV1 { - using ThisT = CovMapFunctionRecordV1; - -#define COVMAP_V1 -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; -#include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_V1 - CovMapFunctionRecordV1() = delete; - - template uint64_t getFuncHash() const { - return accessors::getFuncHash(this); - } - - template uint64_t getDataSize() const { - return accessors::getDataSize(this); - } - - /// Return function lookup key. The value is consider opaque. - template IntPtrT getFuncNameRef() const { - return support::endian::byte_swap(NamePtr); - } - - /// Return the PGO name of the function. - template - Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { - IntPtrT NameRef = getFuncNameRef(); - uint32_t NameS = support::endian::byte_swap(NameSize); - FuncName = ProfileNames.getFuncName(NameRef, NameS); - if (NameS && FuncName.empty()) - return make_error(coveragemap_error::malformed); - return Error::success(); - } - - template - std::pair - advanceByOne(const char *MappingBuf) const { - return accessors::advanceByOneOutOfLine(this, MappingBuf); - } - - template uint64_t getFilenamesRef() const { - llvm_unreachable("V1 function format does not contain a filenames ref"); - } - - template - StringRef getCoverageMapping(const char *MappingBuf) const { - return accessors::getCoverageMappingOutOfLine(this, - MappingBuf); - } -}; - -struct CovMapFunctionRecordV2 { - using ThisT = CovMapFunctionRecordV2; - -#define COVMAP_V2 -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; -#include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_V2 - CovMapFunctionRecordV2() = delete; - - template uint64_t getFuncHash() const { - return accessors::getFuncHash(this); - } - - template uint64_t getDataSize() const { - return accessors::getDataSize(this); - } - - template uint64_t getFuncNameRef() const { - return accessors::getFuncNameRef(this); - } - - template - Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { - return accessors::getFuncNameViaRef(this, ProfileNames, - FuncName); - } - - template - std::pair - advanceByOne(const char *MappingBuf) const { - return accessors::advanceByOneOutOfLine(this, MappingBuf); - } - - template uint64_t getFilenamesRef() const { - llvm_unreachable("V2 function format does not contain a filenames ref"); - } - - template - StringRef getCoverageMapping(const char *MappingBuf) const { - return accessors::getCoverageMappingOutOfLine(this, - MappingBuf); - } -}; - -struct CovMapFunctionRecordV3 { - using ThisT = CovMapFunctionRecordV3; - -#define COVMAP_V3 -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; -#include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_V3 - CovMapFunctionRecordV3() = delete; - - template uint64_t getFuncHash() const { - return accessors::getFuncHash(this); - } - - template uint64_t getDataSize() const { - return accessors::getDataSize(this); - } - - template uint64_t getFuncNameRef() const { - return accessors::getFuncNameRef(this); - } - - template - Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { - return accessors::getFuncNameViaRef(this, ProfileNames, - FuncName); - } - - /// Get the filename set reference. - template uint64_t getFilenamesRef() const { - return support::endian::byte_swap(FilenamesRef); - } - - /// Read the inline coverage mapping. Ignore the buffer parameter, it is for - /// out-of-line coverage mapping data only. - template - StringRef getCoverageMapping(const char *) const { - return StringRef(&CoverageMapping, getDataSize()); - } - - // Advance to the next inline coverage mapping and its associated function - // record. Ignore the out-of-line coverage mapping buffer. - template - std::pair - advanceByOne(const char *) const { - assert(isAddrAligned(Align(8), this) && "Function record not aligned"); - const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) - - sizeof(char) + getDataSize(); - // Each function record has an alignment of 8, so we need to adjust - // alignment before reading the next record. - Next += offsetToAlignedAddr(Next, Align(8)); - return {nullptr, reinterpret_cast(Next)}; - } -}; - -// Per module coverage mapping data header, i.e. CoverageMapFileHeader -// documented above. -struct CovMapHeader { -#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; -#include "llvm/ProfileData/InstrProfData.inc" - template uint32_t getNRecords() const { - return support::endian::byte_swap(NRecords); - } - - template uint32_t getFilenamesSize() const { - return support::endian::byte_swap(FilenamesSize); - } - - template uint32_t getCoverageSize() const { - return support::endian::byte_swap(CoverageSize); - } - - template uint32_t getVersion() const { - return support::endian::byte_swap(Version); - } -}; - -LLVM_PACKED_END - -enum CovMapVersion { - Version1 = 0, - // Function's name reference from CovMapFuncRecord is changed from raw - // name string pointer to MD5 to support name section compression. Name - // section is also compressed. - Version2 = 1, - // A new interpretation of the columnEnd field is added in order to mark - // regions as gap areas. - Version3 = 2, - // Function records are named, uniqued, and moved to a dedicated section. - Version4 = 3, - // Branch regions referring to two counters are added - Version5 = 4, - // Compilation directory is stored separately and combined with relative - // filenames to produce an absolute file path. - Version6 = 5, - // The current version is Version6. - CurrentVersion = INSTR_PROF_COVMAP_VERSION -}; - -template struct CovMapTraits { - using CovMapFuncRecordType = CovMapFunctionRecordV3; - using NameRefType = uint64_t; -}; - -template struct CovMapTraits { - using CovMapFuncRecordType = CovMapFunctionRecordV2; - using NameRefType = uint64_t; -}; - -template struct CovMapTraits { - using CovMapFuncRecordType = CovMapFunctionRecordV2; - using NameRefType = uint64_t; -}; - -template struct CovMapTraits { - using CovMapFuncRecordType = CovMapFunctionRecordV1; - using NameRefType = IntPtrT; -}; - -} // end namespace coverage - -/// Provide DenseMapInfo for CounterExpression -template<> struct DenseMapInfo { - static inline coverage::CounterExpression getEmptyKey() { - using namespace coverage; - - return CounterExpression(CounterExpression::ExprKind::Subtract, - Counter::getCounter(~0U), - Counter::getCounter(~0U)); - } - - static inline coverage::CounterExpression getTombstoneKey() { - using namespace coverage; - - return CounterExpression(CounterExpression::ExprKind::Add, - Counter::getCounter(~0U), - Counter::getCounter(~0U)); - } - - static unsigned getHashValue(const coverage::CounterExpression &V) { - return static_cast( - hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), - V.RHS.getKind(), V.RHS.getCounterID())); - } - - static bool isEqual(const coverage::CounterExpression &LHS, - const coverage::CounterExpression &RHS) { - return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; - } -}; - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingReader.h deleted file mode 100644 index 39c0045369..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ /dev/null @@ -1,245 +0,0 @@ -//===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains support for reading coverage mapping data for -// instrumentation based coverage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H -#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include -#include -#include -#include -#include - -namespace llvm { -namespace coverage { - -class CoverageMappingReader; - -/// Coverage mapping information for a single function. -struct CoverageMappingRecord { - StringRef FunctionName; - uint64_t FunctionHash; - ArrayRef Filenames; - ArrayRef Expressions; - ArrayRef MappingRegions; -}; - -/// A file format agnostic iterator over coverage mapping data. -class CoverageMappingIterator { - CoverageMappingReader *Reader; - CoverageMappingRecord Record; - coveragemap_error ReadErr; - - void increment(); - -public: - using iterator_category = std::input_iterator_tag; - using value_type = CoverageMappingRecord; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - CoverageMappingIterator() - : Reader(nullptr), ReadErr(coveragemap_error::success) {} - - CoverageMappingIterator(CoverageMappingReader *Reader) - : Reader(Reader), ReadErr(coveragemap_error::success) { - increment(); - } - - ~CoverageMappingIterator() { - if (ReadErr != coveragemap_error::success) - llvm_unreachable("Unexpected error in coverage mapping iterator"); - } - - CoverageMappingIterator &operator++() { - increment(); - return *this; - } - bool operator==(const CoverageMappingIterator &RHS) const { - return Reader == RHS.Reader; - } - bool operator!=(const CoverageMappingIterator &RHS) const { - return Reader != RHS.Reader; - } - Expected operator*() { - if (ReadErr != coveragemap_error::success) { - auto E = make_error(ReadErr); - ReadErr = coveragemap_error::success; - return std::move(E); - } - return Record; - } - Expected operator->() { - if (ReadErr != coveragemap_error::success) { - auto E = make_error(ReadErr); - ReadErr = coveragemap_error::success; - return std::move(E); - } - return &Record; - } -}; - -class CoverageMappingReader { -public: - virtual ~CoverageMappingReader() = default; - - virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; - CoverageMappingIterator begin() { return CoverageMappingIterator(this); } - CoverageMappingIterator end() { return CoverageMappingIterator(); } -}; - -/// Base class for the raw coverage mapping and filenames data readers. -class RawCoverageReader { -protected: - StringRef Data; - - RawCoverageReader(StringRef Data) : Data(Data) {} - - Error readULEB128(uint64_t &Result); - Error readIntMax(uint64_t &Result, uint64_t MaxPlus1); - Error readSize(uint64_t &Result); - Error readString(StringRef &Result); -}; - -/// Checks if the given coverage mapping data is exported for -/// an unused function. -class RawCoverageMappingDummyChecker : public RawCoverageReader { -public: - RawCoverageMappingDummyChecker(StringRef MappingData) - : RawCoverageReader(MappingData) {} - - Expected isDummy(); -}; - -/// Reader for the raw coverage mapping data. -class RawCoverageMappingReader : public RawCoverageReader { - ArrayRef &TranslationUnitFilenames; - std::vector &Filenames; - std::vector &Expressions; - std::vector &MappingRegions; - -public: - RawCoverageMappingReader(StringRef MappingData, - ArrayRef &TranslationUnitFilenames, - std::vector &Filenames, - std::vector &Expressions, - std::vector &MappingRegions) - : RawCoverageReader(MappingData), - TranslationUnitFilenames(TranslationUnitFilenames), - Filenames(Filenames), Expressions(Expressions), - MappingRegions(MappingRegions) {} - RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; - RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) = delete; - - Error read(); - -private: - Error decodeCounter(unsigned Value, Counter &C); - Error readCounter(Counter &C); - Error - readMappingRegionsSubArray(std::vector &MappingRegions, - unsigned InferredFileID, size_t NumFileIDs); -}; - -/// Reader for the coverage mapping data that is emitted by the -/// frontend and stored in an object file. -class BinaryCoverageReader : public CoverageMappingReader { -public: - struct ProfileMappingRecord { - CovMapVersion Version; - StringRef FunctionName; - uint64_t FunctionHash; - StringRef CoverageMapping; - size_t FilenamesBegin; - size_t FilenamesSize; - - ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName, - uint64_t FunctionHash, StringRef CoverageMapping, - size_t FilenamesBegin, size_t FilenamesSize) - : Version(Version), FunctionName(FunctionName), - FunctionHash(FunctionHash), CoverageMapping(CoverageMapping), - FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} - }; - - using FuncRecordsStorage = std::unique_ptr; - -private: - std::vector Filenames; - std::vector MappingRecords; - InstrProfSymtab ProfileNames; - size_t CurrentRecord = 0; - std::vector FunctionsFilenames; - std::vector Expressions; - std::vector MappingRegions; - - // Used to tie the lifetimes of coverage function records to the lifetime of - // this BinaryCoverageReader instance. Needed to support the format change in - // D69471, which can split up function records into multiple sections on ELF. - FuncRecordsStorage FuncRecords; - - BinaryCoverageReader(FuncRecordsStorage &&FuncRecords) - : FuncRecords(std::move(FuncRecords)) {} - -public: - BinaryCoverageReader(const BinaryCoverageReader &) = delete; - BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - - static Expected>> - create(MemoryBufferRef ObjectBuffer, StringRef Arch, - SmallVectorImpl> &ObjectFileBuffers, - StringRef CompilationDir = ""); - - static Expected> - createCoverageReaderFromBuffer(StringRef Coverage, - FuncRecordsStorage &&FuncRecords, - InstrProfSymtab &&ProfileNames, - uint8_t BytesInAddress, - support::endianness Endian, - StringRef CompilationDir = ""); - - Error readNextRecord(CoverageMappingRecord &Record) override; -}; - -/// Reader for the raw coverage filenames. -class RawCoverageFilenamesReader : public RawCoverageReader { - std::vector &Filenames; - StringRef CompilationDir; - - // Read an uncompressed sequence of filenames. - Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames); - -public: - RawCoverageFilenamesReader(StringRef Data, - std::vector &Filenames, - StringRef CompilationDir = "") - : RawCoverageReader(Data), Filenames(Filenames), - CompilationDir(CompilationDir) {} - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; - RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) = delete; - - Error read(CovMapVersion Version); -}; - -} // end namespace coverage -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h deleted file mode 100644 index 1420675588..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h +++ /dev/null @@ -1,61 +0,0 @@ -//===- CoverageMappingWriter.h - Code coverage mapping writer ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing coverage mapping data for -// instrumentation based coverage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H -#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" - -namespace llvm { - -class raw_ostream; - -namespace coverage { - -/// Writer of the filenames section for the instrumentation -/// based code coverage. -class CoverageFilenamesSectionWriter { - ArrayRef Filenames; - -public: - CoverageFilenamesSectionWriter(ArrayRef Filenames); - - /// Write encoded filenames to the given output stream. If \p Compress is - /// true, attempt to compress the filenames. - void write(raw_ostream &OS, bool Compress = true); -}; - -/// Writer for instrumentation based coverage mapping data. -class CoverageMappingWriter { - ArrayRef VirtualFileMapping; - ArrayRef Expressions; - MutableArrayRef MappingRegions; - -public: - CoverageMappingWriter(ArrayRef VirtualFileMapping, - ArrayRef Expressions, - MutableArrayRef MappingRegions) - : VirtualFileMapping(VirtualFileMapping), Expressions(Expressions), - MappingRegions(MappingRegions) {} - - /// Write encoded coverage mapping data to the given output stream. - void write(raw_ostream &OS); -}; - -} // end namespace coverage - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/GCOV.h b/suite/synctools/tablegen/include/llvm/ProfileData/GCOV.h deleted file mode 100644 index ef6515d391..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/GCOV.h +++ /dev/null @@ -1,323 +0,0 @@ -//===- GCOV.h - LLVM coverage tool ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header provides the interface to read and write coverage files that -// use 'gcov' format. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_GCOV_H -#define LLVM_PROFILEDATA_GCOV_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/DataExtractor.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class GCOVFunction; -class GCOVBlock; - -namespace GCOV { - -enum GCOVVersion { V304, V407, V408, V800, V900, V1200 }; - -/// A struct for passing gcov options between functions. -struct Options { - Options(bool A, bool B, bool C, bool F, bool P, bool U, bool I, bool L, - bool M, bool N, bool R, bool T, bool X, std::string SourcePrefix) - : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), - PreservePaths(P), UncondBranch(U), Intermediate(I), LongFileNames(L), - Demangle(M), NoOutput(N), RelativeOnly(R), UseStdout(T), - HashFilenames(X), SourcePrefix(std::move(SourcePrefix)) {} - - bool AllBlocks; - bool BranchInfo; - bool BranchCount; - bool FuncCoverage; - bool PreservePaths; - bool UncondBranch; - bool Intermediate; - bool LongFileNames; - bool Demangle; - bool NoOutput; - bool RelativeOnly; - bool UseStdout; - bool HashFilenames; - std::string SourcePrefix; -}; - -} // end namespace GCOV - -/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific -/// read operations. -class GCOVBuffer { -public: - GCOVBuffer(MemoryBuffer *B) : Buffer(B) {} - ~GCOVBuffer() { consumeError(cursor.takeError()); } - - /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. - bool readGCNOFormat() { - StringRef buf = Buffer->getBuffer(); - StringRef magic = buf.substr(0, 4); - if (magic == "gcno") { - de = DataExtractor(buf.substr(4), false, 0); - } else if (magic == "oncg") { - de = DataExtractor(buf.substr(4), true, 0); - } else { - errs() << "unexpected magic: " << magic << "\n"; - return false; - } - return true; - } - - /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. - bool readGCDAFormat() { - StringRef buf = Buffer->getBuffer(); - StringRef magic = buf.substr(0, 4); - if (magic == "gcda") { - de = DataExtractor(buf.substr(4), false, 0); - } else if (magic == "adcg") { - de = DataExtractor(buf.substr(4), true, 0); - } else { - return false; - } - return true; - } - - /// readGCOVVersion - Read GCOV version. - bool readGCOVVersion(GCOV::GCOVVersion &version) { - std::string str(de.getBytes(cursor, 4)); - if (str.size() != 4) - return false; - if (de.isLittleEndian()) - std::reverse(str.begin(), str.end()); - int ver = str[0] >= 'A' - ? (str[0] - 'A') * 100 + (str[1] - '0') * 10 + str[2] - '0' - : (str[0] - '0') * 10 + str[2] - '0'; - if (ver >= 120) { - this->version = version = GCOV::V1200; - return true; - } else if (ver >= 90) { - // PR gcov-profile/84846, r269678 - this->version = version = GCOV::V900; - return true; - } else if (ver >= 80) { - // PR gcov-profile/48463 - this->version = version = GCOV::V800; - return true; - } else if (ver >= 48) { - // r189778: the exit block moved from the last to the second. - this->version = version = GCOV::V408; - return true; - } else if (ver >= 47) { - // r173147: split checksum into cfg checksum and line checksum. - this->version = version = GCOV::V407; - return true; - } else if (ver >= 34) { - this->version = version = GCOV::V304; - return true; - } - errs() << "unexpected version: " << str << "\n"; - return false; - } - - uint32_t getWord() { return de.getU32(cursor); } - StringRef getString() { - uint32_t len; - if (!readInt(len) || len == 0) - return {}; - return de.getBytes(cursor, len * 4).split('\0').first; - } - - bool readInt(uint32_t &Val) { - if (cursor.tell() + 4 > de.size()) { - Val = 0; - errs() << "unexpected end of memory buffer: " << cursor.tell() << "\n"; - return false; - } - Val = de.getU32(cursor); - return true; - } - - bool readInt64(uint64_t &Val) { - uint32_t Lo, Hi; - if (!readInt(Lo) || !readInt(Hi)) - return false; - Val = ((uint64_t)Hi << 32) | Lo; - return true; - } - - bool readString(StringRef &str) { - uint32_t len; - if (!readInt(len) || len == 0) - return false; - if (version >= GCOV::V1200) - str = de.getBytes(cursor, len).drop_back(); - else - str = de.getBytes(cursor, len * 4).split('\0').first; - return bool(cursor); - } - - DataExtractor de{ArrayRef{}, false, 0}; - DataExtractor::Cursor cursor{0}; - -private: - MemoryBuffer *Buffer; - GCOV::GCOVVersion version{}; -}; - -/// GCOVFile - Collects coverage information for one pair of coverage file -/// (.gcno and .gcda). -class GCOVFile { -public: - GCOVFile() = default; - - bool readGCNO(GCOVBuffer &Buffer); - bool readGCDA(GCOVBuffer &Buffer); - GCOV::GCOVVersion getVersion() const { return version; } - void print(raw_ostream &OS) const; - void dump() const; - - std::vector filenames; - StringMap filenameToIdx; - -public: - bool GCNOInitialized = false; - GCOV::GCOVVersion version{}; - uint32_t checksum = 0; - StringRef cwd; - SmallVector, 16> functions; - std::map identToFunction; - uint32_t runCount = 0; - uint32_t programCount = 0; - - using iterator = pointee_iterator< - SmallVectorImpl>::const_iterator>; - iterator begin() const { return iterator(functions.begin()); } - iterator end() const { return iterator(functions.end()); } -}; - -struct GCOVArc { - GCOVArc(GCOVBlock &src, GCOVBlock &dst, uint32_t flags) - : src(src), dst(dst), flags(flags) {} - bool onTree() const; - - GCOVBlock &src; - GCOVBlock &dst; - uint32_t flags; - uint64_t count = 0; - uint64_t cycleCount = 0; -}; - -/// GCOVFunction - Collects function information. -class GCOVFunction { -public: - using BlockIterator = pointee_iterator< - SmallVectorImpl>::const_iterator>; - - GCOVFunction(GCOVFile &file) : file(file) {} - - StringRef getName(bool demangle) const; - StringRef getFilename() const; - uint64_t getEntryCount() const; - GCOVBlock &getExitBlock() const; - - iterator_range blocksRange() const { - return make_range(blocks.begin(), blocks.end()); - } - - uint64_t propagateCounts(const GCOVBlock &v, GCOVArc *pred); - void print(raw_ostream &OS) const; - void dump() const; - - GCOVFile &file; - uint32_t ident = 0; - uint32_t linenoChecksum; - uint32_t cfgChecksum = 0; - uint32_t startLine = 0; - uint32_t startColumn = 0; - uint32_t endLine = 0; - uint32_t endColumn = 0; - uint8_t artificial = 0; - StringRef Name; - mutable SmallString<0> demangled; - unsigned srcIdx; - SmallVector, 0> blocks; - SmallVector, 0> arcs, treeArcs; - DenseSet visited; -}; - -/// GCOVBlock - Collects block information. -class GCOVBlock { -public: - using EdgeIterator = SmallVectorImpl::const_iterator; - using BlockVector = SmallVector; - using BlockVectorLists = SmallVector; - using Edges = SmallVector; - - GCOVBlock(uint32_t N) : number(N) {} - - void addLine(uint32_t N) { lines.push_back(N); } - uint32_t getLastLine() const { return lines.back(); } - uint64_t getCount() const { return count; } - - void addSrcEdge(GCOVArc *Edge) { pred.push_back(Edge); } - - void addDstEdge(GCOVArc *Edge) { succ.push_back(Edge); } - - iterator_range srcs() const { - return make_range(pred.begin(), pred.end()); - } - - iterator_range dsts() const { - return make_range(succ.begin(), succ.end()); - } - - void print(raw_ostream &OS) const; - void dump() const; - - static uint64_t - augmentOneCycle(GCOVBlock *src, - std::vector> &stack); - static uint64_t getCyclesCount(const BlockVector &blocks); - static uint64_t getLineCount(const BlockVector &Blocks); - -public: - uint32_t number; - uint64_t count = 0; - SmallVector pred; - SmallVector succ; - SmallVector lines; - bool traversable = false; - GCOVArc *incoming = nullptr; -}; - -void gcovOneInput(const GCOV::Options &options, StringRef filename, - StringRef gcno, StringRef gcda, GCOVFile &file); - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_GCOV_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProf.h b/suite/synctools/tablegen/include/llvm/ProfileData/InstrProf.h deleted file mode 100644 index 746a7875aa..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProf.h +++ /dev/null @@ -1,1179 +0,0 @@ -//===- InstrProf.h - Instrumented profiling format support ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Instrumentation-based profiling data is generated by instrumented -// binaries through library functions in compiler-rt, and read by the clang -// frontend to feed PGO. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_INSTRPROF_H -#define LLVM_PROFILEDATA_INSTRPROF_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitmaskEnum.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/ADT/Triple.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/ProfileData/InstrProfData.inc" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/MD5.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class Function; -class GlobalVariable; -struct InstrProfRecord; -class InstrProfSymtab; -class Instruction; -class MDNode; -class Module; - -enum InstrProfSectKind { -#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind, -#include "llvm/ProfileData/InstrProfData.inc" -}; - -/// Return the name of the profile section corresponding to \p IPSK. -/// -/// The name of the section depends on the object format type \p OF. If -/// \p AddSegmentInfo is true, a segment prefix and additional linker hints may -/// be added to the section name (this is the default). -std::string getInstrProfSectionName(InstrProfSectKind IPSK, - Triple::ObjectFormatType OF, - bool AddSegmentInfo = true); - -/// Return the name profile runtime entry point to do value profiling -/// for a given site. -inline StringRef getInstrProfValueProfFuncName() { - return INSTR_PROF_VALUE_PROF_FUNC_STR; -} - -/// Return the name profile runtime entry point to do memop size value -/// profiling. -inline StringRef getInstrProfValueProfMemOpFuncName() { - return INSTR_PROF_VALUE_PROF_MEMOP_FUNC_STR; -} - -/// Return the name prefix of variables containing instrumented function names. -inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; } - -/// Return the name prefix of variables containing per-function control data. -inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; } - -/// Return the name prefix of profile counter variables. -inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; } - -/// Return the name prefix of value profile variables. -inline StringRef getInstrProfValuesVarPrefix() { return "__profvp_"; } - -/// Return the name of value profile node array variables: -inline StringRef getInstrProfVNodesVarName() { return "__llvm_prf_vnodes"; } - -/// Return the name of the variable holding the strings (possibly compressed) -/// of all function's PGO names. -inline StringRef getInstrProfNamesVarName() { - return "__llvm_prf_nm"; -} - -/// Return the name of a coverage mapping variable (internal linkage) -/// for each instrumented source module. Such variables are allocated -/// in the __llvm_covmap section. -inline StringRef getCoverageMappingVarName() { - return "__llvm_coverage_mapping"; -} - -/// Return the name of the internal variable recording the array -/// of PGO name vars referenced by the coverage mapping. The owning -/// functions of those names are not emitted by FE (e.g, unused inline -/// functions.) -inline StringRef getCoverageUnusedNamesVarName() { - return "__llvm_coverage_names"; -} - -/// Return the name of function that registers all the per-function control -/// data at program startup time by calling __llvm_register_function. This -/// function has internal linkage and is called by __llvm_profile_init -/// runtime method. This function is not generated for these platforms: -/// Darwin, Linux, and FreeBSD. -inline StringRef getInstrProfRegFuncsName() { - return "__llvm_profile_register_functions"; -} - -/// Return the name of the runtime interface that registers per-function control -/// data for one instrumented function. -inline StringRef getInstrProfRegFuncName() { - return "__llvm_profile_register_function"; -} - -/// Return the name of the runtime interface that registers the PGO name strings. -inline StringRef getInstrProfNamesRegFuncName() { - return "__llvm_profile_register_names_function"; -} - -/// Return the name of the runtime initialization method that is generated by -/// the compiler. The function calls __llvm_profile_register_functions and -/// __llvm_profile_override_default_filename functions if needed. This function -/// has internal linkage and invoked at startup time via init_array. -inline StringRef getInstrProfInitFuncName() { return "__llvm_profile_init"; } - -/// Return the name of the hook variable defined in profile runtime library. -/// A reference to the variable causes the linker to link in the runtime -/// initialization module (which defines the hook variable). -inline StringRef getInstrProfRuntimeHookVarName() { - return INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_RUNTIME_VAR); -} - -/// Return the name of the compiler generated function that references the -/// runtime hook variable. The function is a weak global. -inline StringRef getInstrProfRuntimeHookVarUseFuncName() { - return "__llvm_profile_runtime_user"; -} - -inline StringRef getInstrProfCounterBiasVarName() { - return INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR); -} - -/// Return the marker used to separate PGO names during serialization. -inline StringRef getInstrProfNameSeparator() { return "\01"; } - -/// Return the modified name for function \c F suitable to be -/// used the key for profile lookup. Variable \c InLTO indicates if this -/// is called in LTO optimization passes. -std::string getPGOFuncName(const Function &F, bool InLTO = false, - uint64_t Version = INSTR_PROF_INDEX_VERSION); - -/// Return the modified name for a function suitable to be -/// used the key for profile lookup. The function's original -/// name is \c RawFuncName and has linkage of type \c Linkage. -/// The function is defined in module \c FileName. -std::string getPGOFuncName(StringRef RawFuncName, - GlobalValue::LinkageTypes Linkage, - StringRef FileName, - uint64_t Version = INSTR_PROF_INDEX_VERSION); - -/// Return the name of the global variable used to store a function -/// name in PGO instrumentation. \c FuncName is the name of the function -/// returned by the \c getPGOFuncName call. -std::string getPGOFuncNameVarName(StringRef FuncName, - GlobalValue::LinkageTypes Linkage); - -/// Create and return the global variable for function name used in PGO -/// instrumentation. \c FuncName is the name of the function returned -/// by \c getPGOFuncName call. -GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName); - -/// Create and return the global variable for function name used in PGO -/// instrumentation. /// \c FuncName is the name of the function -/// returned by \c getPGOFuncName call, \c M is the owning module, -/// and \c Linkage is the linkage of the instrumented function. -GlobalVariable *createPGOFuncNameVar(Module &M, - GlobalValue::LinkageTypes Linkage, - StringRef PGOFuncName); - -/// Return the initializer in string of the PGO name var \c NameVar. -StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar); - -/// Given a PGO function name, remove the filename prefix and return -/// the original (static) function name. -StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, - StringRef FileName = ""); - -/// Given a vector of strings (function PGO names) \c NameStrs, the -/// method generates a combined string \c Result that is ready to be -/// serialized. The \c Result string is comprised of three fields: -/// The first field is the length of the uncompressed strings, and the -/// the second field is the length of the zlib-compressed string. -/// Both fields are encoded in ULEB128. If \c doCompress is false, the -/// third field is the uncompressed strings; otherwise it is the -/// compressed string. When the string compression is off, the -/// second field will have value zero. -Error collectPGOFuncNameStrings(ArrayRef NameStrs, - bool doCompression, std::string &Result); - -/// Produce \c Result string with the same format described above. The input -/// is vector of PGO function name variables that are referenced. -Error collectPGOFuncNameStrings(ArrayRef NameVars, - std::string &Result, bool doCompression = true); - -/// \c NameStrings is a string composed of one of more sub-strings encoded in -/// the format described above. The substrings are separated by 0 or more zero -/// bytes. This method decodes the string and populates the \c Symtab. -Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab); - -/// Check if INSTR_PROF_RAW_VERSION_VAR is defined. This global is only being -/// set in IR PGO compilation. -bool isIRPGOFlagSet(const Module *M); - -/// Check if we can safely rename this Comdat function. Instances of the same -/// comdat function may have different control flows thus can not share the -/// same counter variable. -bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false); - -enum InstrProfValueKind : uint32_t { -#define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value, -#include "llvm/ProfileData/InstrProfData.inc" -}; - -/// Get the value profile data for value site \p SiteIdx from \p InstrProfR -/// and annotate the instruction \p Inst with the value profile meta data. -/// Annotate up to \p MaxMDCount (default 3) number of records per value site. -void annotateValueSite(Module &M, Instruction &Inst, - const InstrProfRecord &InstrProfR, - InstrProfValueKind ValueKind, uint32_t SiteIndx, - uint32_t MaxMDCount = 3); - -/// Same as the above interface but using an ArrayRef, as well as \p Sum. -void annotateValueSite(Module &M, Instruction &Inst, - ArrayRef VDs, uint64_t Sum, - InstrProfValueKind ValueKind, uint32_t MaxMDCount); - -/// Extract the value profile data from \p Inst which is annotated with -/// value profile meta data. Return false if there is no value data annotated, -/// otherwise return true. -bool getValueProfDataFromInst(const Instruction &Inst, - InstrProfValueKind ValueKind, - uint32_t MaxNumValueData, - InstrProfValueData ValueData[], - uint32_t &ActualNumValueData, uint64_t &TotalC, - bool GetNoICPValue = false); - -inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; } - -/// Return the PGOFuncName meta data associated with a function. -MDNode *getPGOFuncNameMetadata(const Function &F); - -/// Create the PGOFuncName meta data if PGOFuncName is different from -/// function's raw name. This should only apply to internal linkage functions -/// declared by users only. -void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName); - -/// Check if we can use Comdat for profile variables. This will eliminate -/// the duplicated profile variables for Comdat functions. -bool needsComdatForCounter(const Function &F, const Module &M); - -/// An enum describing the attributes of an instrumented profile. -enum class InstrProfKind { - Unknown = 0x0, - FE = 0x1, // A frontend clang profile, incompatible with other attrs. - IR = 0x2, // An IR-level profile (default when -fprofile-generate is used). - BB = 0x4, // A profile with entry basic block instrumentation. - CS = 0x8, // A context sensitive IR-level profile. - SingleByteCoverage = 0x10, // Use single byte probes for coverage. - FunctionEntryOnly = 0x20, // Only instrument the function entry basic block. - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/FunctionEntryOnly) -}; - -const std::error_category &instrprof_category(); - -enum class instrprof_error { - success = 0, - eof, - unrecognized_format, - bad_magic, - bad_header, - unsupported_version, - unsupported_hash_type, - too_large, - truncated, - malformed, - missing_debug_info_for_correlation, - unexpected_debug_info_for_correlation, - unable_to_correlate_profile, - unknown_function, - invalid_prof, - hash_mismatch, - count_mismatch, - counter_overflow, - value_site_count_mismatch, - compress_failed, - uncompress_failed, - empty_raw_profile, - zlib_unavailable -}; - -inline std::error_code make_error_code(instrprof_error E) { - return std::error_code(static_cast(E), instrprof_category()); -} - -class InstrProfError : public ErrorInfo { -public: - InstrProfError(instrprof_error Err, const Twine &ErrStr = Twine()) - : Err(Err), Msg(ErrStr.str()) { - assert(Err != instrprof_error::success && "Not an error"); - } - - std::string message() const override; - - void log(raw_ostream &OS) const override { OS << message(); } - - std::error_code convertToErrorCode() const override { - return make_error_code(Err); - } - - instrprof_error get() const { return Err; } - const std::string &getMessage() const { return Msg; } - - /// Consume an Error and return the raw enum value contained within it. The - /// Error must either be a success value, or contain a single InstrProfError. - static instrprof_error take(Error E) { - auto Err = instrprof_error::success; - handleAllErrors(std::move(E), [&Err](const InstrProfError &IPE) { - assert(Err == instrprof_error::success && "Multiple errors encountered"); - Err = IPE.get(); - }); - return Err; - } - - static char ID; - -private: - instrprof_error Err; - std::string Msg; -}; - -class SoftInstrProfErrors { - /// Count the number of soft instrprof_errors encountered and keep track of - /// the first such error for reporting purposes. - - /// The first soft error encountered. - instrprof_error FirstError = instrprof_error::success; - - /// The number of hash mismatches. - unsigned NumHashMismatches = 0; - - /// The number of count mismatches. - unsigned NumCountMismatches = 0; - - /// The number of counter overflows. - unsigned NumCounterOverflows = 0; - - /// The number of value site count mismatches. - unsigned NumValueSiteCountMismatches = 0; - -public: - SoftInstrProfErrors() = default; - - ~SoftInstrProfErrors() { - assert(FirstError == instrprof_error::success && - "Unchecked soft error encountered"); - } - - /// Track a soft error (\p IE) and increment its associated counter. - void addError(instrprof_error IE); - - /// Get the number of hash mismatches. - unsigned getNumHashMismatches() const { return NumHashMismatches; } - - /// Get the number of count mismatches. - unsigned getNumCountMismatches() const { return NumCountMismatches; } - - /// Get the number of counter overflows. - unsigned getNumCounterOverflows() const { return NumCounterOverflows; } - - /// Get the number of value site count mismatches. - unsigned getNumValueSiteCountMismatches() const { - return NumValueSiteCountMismatches; - } - - /// Return the first encountered error and reset FirstError to a success - /// value. - Error takeError() { - if (FirstError == instrprof_error::success) - return Error::success(); - auto E = make_error(FirstError); - FirstError = instrprof_error::success; - return E; - } -}; - -namespace object { - -class SectionRef; - -} // end namespace object - -namespace IndexedInstrProf { - -uint64_t ComputeHash(StringRef K); - -} // end namespace IndexedInstrProf - -/// A symbol table used for function PGO name look-up with keys -/// (such as pointers, md5hash values) to the function. A function's -/// PGO name or name's md5hash are used in retrieving the profile -/// data of the function. See \c getPGOFuncName() method for details -/// on how PGO name is formed. -class InstrProfSymtab { -public: - using AddrHashMap = std::vector>; - -private: - StringRef Data; - uint64_t Address = 0; - // Unique name strings. - StringSet<> NameTab; - // A map from MD5 keys to function name strings. - std::vector> MD5NameMap; - // A map from MD5 keys to function define. We only populate this map - // when build the Symtab from a Module. - std::vector> MD5FuncMap; - // A map from function runtime address to function name MD5 hash. - // This map is only populated and used by raw instr profile reader. - AddrHashMap AddrToMD5Map; - bool Sorted = false; - - static StringRef getExternalSymbol() { - return "** External Symbol **"; - } - - // If the symtab is created by a series of calls to \c addFuncName, \c - // finalizeSymtab needs to be called before looking up function names. - // This is required because the underlying map is a vector (for space - // efficiency) which needs to be sorted. - inline void finalizeSymtab(); - -public: - InstrProfSymtab() = default; - - /// Create InstrProfSymtab from an object file section which - /// contains function PGO names. When section may contain raw - /// string data or string data in compressed form. This method - /// only initialize the symtab with reference to the data and - /// the section base address. The decompression will be delayed - /// until before it is used. See also \c create(StringRef) method. - Error create(object::SectionRef &Section); - - /// This interface is used by reader of CoverageMapping test - /// format. - inline Error create(StringRef D, uint64_t BaseAddr); - - /// \c NameStrings is a string composed of one of more sub-strings - /// encoded in the format described in \c collectPGOFuncNameStrings. - /// This method is a wrapper to \c readPGOFuncNameStrings method. - inline Error create(StringRef NameStrings); - - /// A wrapper interface to populate the PGO symtab with functions - /// decls from module \c M. This interface is used by transformation - /// passes such as indirect function call promotion. Variable \c InLTO - /// indicates if this is called from LTO optimization passes. - Error create(Module &M, bool InLTO = false); - - /// Create InstrProfSymtab from a set of names iterable from - /// \p IterRange. This interface is used by IndexedProfReader. - template Error create(const NameIterRange &IterRange); - - /// Update the symtab by adding \p FuncName to the table. This interface - /// is used by the raw and text profile readers. - Error addFuncName(StringRef FuncName) { - if (FuncName.empty()) - return make_error(instrprof_error::malformed, - "function name is empty"); - auto Ins = NameTab.insert(FuncName); - if (Ins.second) { - MD5NameMap.push_back(std::make_pair( - IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey())); - Sorted = false; - } - return Error::success(); - } - - /// Map a function address to its name's MD5 hash. This interface - /// is only used by the raw profiler reader. - void mapAddress(uint64_t Addr, uint64_t MD5Val) { - AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); - } - - /// Return a function's hash, or 0, if the function isn't in this SymTab. - uint64_t getFunctionHashFromAddress(uint64_t Address); - - /// Return function's PGO name from the function name's symbol - /// address in the object file. If an error occurs, return - /// an empty string. - StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); - - /// Return function's PGO name from the name's md5 hash value. - /// If not found, return an empty string. - inline StringRef getFuncName(uint64_t FuncMD5Hash); - - /// Just like getFuncName, except that it will return a non-empty StringRef - /// if the function is external to this symbol table. All such cases - /// will be represented using the same StringRef value. - inline StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash); - - /// True if Symbol is the value used to represent external symbols. - static bool isExternalSymbol(const StringRef &Symbol) { - return Symbol == InstrProfSymtab::getExternalSymbol(); - } - - /// Return function from the name's md5 hash. Return nullptr if not found. - inline Function *getFunction(uint64_t FuncMD5Hash); - - /// Return the function's original assembly name by stripping off - /// the prefix attached (to symbols with private linkage). For - /// global functions, it returns the same string as getFuncName. - inline StringRef getOrigFuncName(uint64_t FuncMD5Hash); - - /// Return the name section data. - inline StringRef getNameData() const { return Data; } - - /// Dump the symbols in this table. - void dumpNames(raw_ostream &OS) const { - for (StringRef S : NameTab.keys()) - OS << S << "\n"; - } -}; - -Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) { - Data = D; - Address = BaseAddr; - return Error::success(); -} - -Error InstrProfSymtab::create(StringRef NameStrings) { - return readPGOFuncNameStrings(NameStrings, *this); -} - -template -Error InstrProfSymtab::create(const NameIterRange &IterRange) { - for (auto Name : IterRange) - if (Error E = addFuncName(Name)) - return E; - - finalizeSymtab(); - return Error::success(); -} - -void InstrProfSymtab::finalizeSymtab() { - if (Sorted) - return; - llvm::sort(MD5NameMap, less_first()); - llvm::sort(MD5FuncMap, less_first()); - llvm::sort(AddrToMD5Map, less_first()); - AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()), - AddrToMD5Map.end()); - Sorted = true; -} - -StringRef InstrProfSymtab::getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash) { - StringRef ret = getFuncName(FuncMD5Hash); - if (ret.empty()) - return InstrProfSymtab::getExternalSymbol(); - return ret; -} - -StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) { - finalizeSymtab(); - auto Result = llvm::lower_bound(MD5NameMap, FuncMD5Hash, - [](const std::pair &LHS, - uint64_t RHS) { return LHS.first < RHS; }); - if (Result != MD5NameMap.end() && Result->first == FuncMD5Hash) - return Result->second; - return StringRef(); -} - -Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) { - finalizeSymtab(); - auto Result = llvm::lower_bound(MD5FuncMap, FuncMD5Hash, - [](const std::pair &LHS, - uint64_t RHS) { return LHS.first < RHS; }); - if (Result != MD5FuncMap.end() && Result->first == FuncMD5Hash) - return Result->second; - return nullptr; -} - -// See also getPGOFuncName implementation. These two need to be -// matched. -StringRef InstrProfSymtab::getOrigFuncName(uint64_t FuncMD5Hash) { - StringRef PGOName = getFuncName(FuncMD5Hash); - size_t S = PGOName.find_first_of(':'); - if (S == StringRef::npos) - return PGOName; - return PGOName.drop_front(S + 1); -} - -// To store the sums of profile count values, or the percentage of -// the sums of the total count values. -struct CountSumOrPercent { - uint64_t NumEntries; - double CountSum; - double ValueCounts[IPVK_Last - IPVK_First + 1]; - CountSumOrPercent() : NumEntries(0), CountSum(0.0f), ValueCounts() {} - void reset() { - NumEntries = 0; - CountSum = 0.0f; - for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) - ValueCounts[I] = 0.0f; - } -}; - -// Function level or program level overlap information. -struct OverlapStats { - enum OverlapStatsLevel { ProgramLevel, FunctionLevel }; - // Sum of the total count values for the base profile. - CountSumOrPercent Base; - // Sum of the total count values for the test profile. - CountSumOrPercent Test; - // Overlap lap score. Should be in range of [0.0f to 1.0f]. - CountSumOrPercent Overlap; - CountSumOrPercent Mismatch; - CountSumOrPercent Unique; - OverlapStatsLevel Level; - const std::string *BaseFilename; - const std::string *TestFilename; - StringRef FuncName; - uint64_t FuncHash; - bool Valid; - - OverlapStats(OverlapStatsLevel L = ProgramLevel) - : Level(L), BaseFilename(nullptr), TestFilename(nullptr), FuncHash(0), - Valid(false) {} - - void dump(raw_fd_ostream &OS) const; - - void setFuncInfo(StringRef Name, uint64_t Hash) { - FuncName = Name; - FuncHash = Hash; - } - - Error accumulateCounts(const std::string &BaseFilename, - const std::string &TestFilename, bool IsCS); - void addOneMismatch(const CountSumOrPercent &MismatchFunc); - void addOneUnique(const CountSumOrPercent &UniqueFunc); - - static inline double score(uint64_t Val1, uint64_t Val2, double Sum1, - double Sum2) { - if (Sum1 < 1.0f || Sum2 < 1.0f) - return 0.0f; - return std::min(Val1 / Sum1, Val2 / Sum2); - } -}; - -// This is used to filter the functions whose overlap information -// to be output. -struct OverlapFuncFilters { - uint64_t ValueCutoff; - const std::string NameFilter; -}; - -struct InstrProfValueSiteRecord { - /// Value profiling data pairs at a given value site. - std::list ValueData; - - InstrProfValueSiteRecord() { ValueData.clear(); } - template - InstrProfValueSiteRecord(InputIterator F, InputIterator L) - : ValueData(F, L) {} - - /// Sort ValueData ascending by Value - void sortByTargetValues() { - ValueData.sort( - [](const InstrProfValueData &left, const InstrProfValueData &right) { - return left.Value < right.Value; - }); - } - /// Sort ValueData Descending by Count - inline void sortByCount(); - - /// Merge data from another InstrProfValueSiteRecord - /// Optionally scale merged counts by \p Weight. - void merge(InstrProfValueSiteRecord &Input, uint64_t Weight, - function_ref Warn); - /// Scale up value profile data counts by N (Numerator) / D (Denominator). - void scale(uint64_t N, uint64_t D, function_ref Warn); - - /// Compute the overlap b/w this record and Input record. - void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind, - OverlapStats &Overlap, OverlapStats &FuncLevelOverlap); -}; - -/// Profiling information for a single function. -struct InstrProfRecord { - std::vector Counts; - - InstrProfRecord() = default; - InstrProfRecord(std::vector Counts) : Counts(std::move(Counts)) {} - InstrProfRecord(InstrProfRecord &&) = default; - InstrProfRecord(const InstrProfRecord &RHS) - : Counts(RHS.Counts), - ValueData(RHS.ValueData - ? std::make_unique(*RHS.ValueData) - : nullptr) {} - InstrProfRecord &operator=(InstrProfRecord &&) = default; - InstrProfRecord &operator=(const InstrProfRecord &RHS) { - Counts = RHS.Counts; - if (!RHS.ValueData) { - ValueData = nullptr; - return *this; - } - if (!ValueData) - ValueData = std::make_unique(*RHS.ValueData); - else - *ValueData = *RHS.ValueData; - return *this; - } - - /// Return the number of value profile kinds with non-zero number - /// of profile sites. - inline uint32_t getNumValueKinds() const; - /// Return the number of instrumented sites for ValueKind. - inline uint32_t getNumValueSites(uint32_t ValueKind) const; - - /// Return the total number of ValueData for ValueKind. - inline uint32_t getNumValueData(uint32_t ValueKind) const; - - /// Return the number of value data collected for ValueKind at profiling - /// site: Site. - inline uint32_t getNumValueDataForSite(uint32_t ValueKind, - uint32_t Site) const; - - /// Return the array of profiled values at \p Site. If \p TotalC - /// is not null, the total count of all target values at this site - /// will be stored in \c *TotalC. - inline std::unique_ptr - getValueForSite(uint32_t ValueKind, uint32_t Site, - uint64_t *TotalC = nullptr) const; - - /// Get the target value/counts of kind \p ValueKind collected at site - /// \p Site and store the result in array \p Dest. Return the total - /// counts of all target values at this site. - inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, - uint32_t Site) const; - - /// Reserve space for NumValueSites sites. - inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites); - - /// Add ValueData for ValueKind at value Site. - void addValueData(uint32_t ValueKind, uint32_t Site, - InstrProfValueData *VData, uint32_t N, - InstrProfSymtab *SymTab); - - /// Merge the counts in \p Other into this one. - /// Optionally scale merged counts by \p Weight. - void merge(InstrProfRecord &Other, uint64_t Weight, - function_ref Warn); - - /// Scale up profile counts (including value profile data) by - /// a factor of (N / D). - void scale(uint64_t N, uint64_t D, function_ref Warn); - - /// Sort value profile data (per site) by count. - void sortValueData() { - for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) - for (auto &SR : getValueSitesForKind(Kind)) - SR.sortByCount(); - } - - /// Clear value data entries and edge counters. - void Clear() { - Counts.clear(); - clearValueData(); - } - - /// Clear value data entries - void clearValueData() { ValueData = nullptr; } - - /// Compute the sums of all counts and store in Sum. - void accumulateCounts(CountSumOrPercent &Sum) const; - - /// Compute the overlap b/w this IntrprofRecord and Other. - void overlap(InstrProfRecord &Other, OverlapStats &Overlap, - OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff); - - /// Compute the overlap of value profile counts. - void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src, - OverlapStats &Overlap, - OverlapStats &FuncLevelOverlap); - -private: - struct ValueProfData { - std::vector IndirectCallSites; - std::vector MemOPSizes; - }; - std::unique_ptr ValueData; - - MutableArrayRef - getValueSitesForKind(uint32_t ValueKind) { - // Cast to /add/ const (should be an implicit_cast, ideally, if that's ever - // implemented in LLVM) to call the const overload of this function, then - // cast away the constness from the result. - auto AR = const_cast(this)->getValueSitesForKind( - ValueKind); - return makeMutableArrayRef( - const_cast(AR.data()), AR.size()); - } - ArrayRef - getValueSitesForKind(uint32_t ValueKind) const { - if (!ValueData) - return None; - switch (ValueKind) { - case IPVK_IndirectCallTarget: - return ValueData->IndirectCallSites; - case IPVK_MemOPSize: - return ValueData->MemOPSizes; - default: - llvm_unreachable("Unknown value kind!"); - } - } - - std::vector & - getOrCreateValueSitesForKind(uint32_t ValueKind) { - if (!ValueData) - ValueData = std::make_unique(); - switch (ValueKind) { - case IPVK_IndirectCallTarget: - return ValueData->IndirectCallSites; - case IPVK_MemOPSize: - return ValueData->MemOPSizes; - default: - llvm_unreachable("Unknown value kind!"); - } - } - - // Map indirect call target name hash to name string. - uint64_t remapValue(uint64_t Value, uint32_t ValueKind, - InstrProfSymtab *SymTab); - - // Merge Value Profile data from Src record to this record for ValueKind. - // Scale merged value counts by \p Weight. - void mergeValueProfData(uint32_t ValkeKind, InstrProfRecord &Src, - uint64_t Weight, - function_ref Warn); - - // Scale up value profile data count by N (Numerator) / D (Denominator). - void scaleValueProfData(uint32_t ValueKind, uint64_t N, uint64_t D, - function_ref Warn); -}; - -struct NamedInstrProfRecord : InstrProfRecord { - StringRef Name; - uint64_t Hash; - - // We reserve this bit as the flag for context sensitive profile record. - static const int CS_FLAG_IN_FUNC_HASH = 60; - - NamedInstrProfRecord() = default; - NamedInstrProfRecord(StringRef Name, uint64_t Hash, - std::vector Counts) - : InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {} - - static bool hasCSFlagInHash(uint64_t FuncHash) { - return ((FuncHash >> CS_FLAG_IN_FUNC_HASH) & 1); - } - static void setCSFlagInHash(uint64_t &FuncHash) { - FuncHash |= ((uint64_t)1 << CS_FLAG_IN_FUNC_HASH); - } -}; - -uint32_t InstrProfRecord::getNumValueKinds() const { - uint32_t NumValueKinds = 0; - for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) - NumValueKinds += !(getValueSitesForKind(Kind).empty()); - return NumValueKinds; -} - -uint32_t InstrProfRecord::getNumValueData(uint32_t ValueKind) const { - uint32_t N = 0; - for (auto &SR : getValueSitesForKind(ValueKind)) - N += SR.ValueData.size(); - return N; -} - -uint32_t InstrProfRecord::getNumValueSites(uint32_t ValueKind) const { - return getValueSitesForKind(ValueKind).size(); -} - -uint32_t InstrProfRecord::getNumValueDataForSite(uint32_t ValueKind, - uint32_t Site) const { - return getValueSitesForKind(ValueKind)[Site].ValueData.size(); -} - -std::unique_ptr -InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site, - uint64_t *TotalC) const { - uint64_t Dummy = 0; - uint64_t &TotalCount = (TotalC == nullptr ? Dummy : *TotalC); - uint32_t N = getNumValueDataForSite(ValueKind, Site); - if (N == 0) { - TotalCount = 0; - return std::unique_ptr(nullptr); - } - - auto VD = std::make_unique(N); - TotalCount = getValueForSite(VD.get(), ValueKind, Site); - - return VD; -} - -uint64_t InstrProfRecord::getValueForSite(InstrProfValueData Dest[], - uint32_t ValueKind, - uint32_t Site) const { - uint32_t I = 0; - uint64_t TotalCount = 0; - for (auto V : getValueSitesForKind(ValueKind)[Site].ValueData) { - Dest[I].Value = V.Value; - Dest[I].Count = V.Count; - TotalCount = SaturatingAdd(TotalCount, V.Count); - I++; - } - return TotalCount; -} - -void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) { - if (!NumValueSites) - return; - getOrCreateValueSitesForKind(ValueKind).reserve(NumValueSites); -} - -inline support::endianness getHostEndianness() { - return sys::IsLittleEndianHost ? support::little : support::big; -} - -// Include definitions for value profile data -#define INSTR_PROF_VALUE_PROF_DATA -#include "llvm/ProfileData/InstrProfData.inc" - -void InstrProfValueSiteRecord::sortByCount() { - ValueData.sort( - [](const InstrProfValueData &left, const InstrProfValueData &right) { - return left.Count > right.Count; - }); - // Now truncate - size_t max_s = INSTR_PROF_MAX_NUM_VAL_PER_SITE; - if (ValueData.size() > max_s) - ValueData.resize(max_s); -} - -namespace IndexedInstrProf { - -enum class HashT : uint32_t { - MD5, - Last = MD5 -}; - -inline uint64_t ComputeHash(HashT Type, StringRef K) { - switch (Type) { - case HashT::MD5: - return MD5Hash(K); - } - llvm_unreachable("Unhandled hash type"); -} - -const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81" - -enum ProfVersion { - // Version 1 is the first version. In this version, the value of - // a key/value pair can only include profile data of a single function. - // Due to this restriction, the number of block counters for a given - // function is not recorded but derived from the length of the value. - Version1 = 1, - // The version 2 format supports recording profile data of multiple - // functions which share the same key in one value field. To support this, - // the number block counters is recorded as an uint64_t field right after the - // function structural hash. - Version2 = 2, - // Version 3 supports value profile data. The value profile data is expected - // to follow the block counter profile data. - Version3 = 3, - // In this version, profile summary data \c IndexedInstrProf::Summary is - // stored after the profile header. - Version4 = 4, - // In this version, the frontend PGO stable hash algorithm defaults to V2. - Version5 = 5, - // In this version, the frontend PGO stable hash algorithm got fixed and - // may produce hashes different from Version5. - Version6 = 6, - // An additional counter is added around logical operators. - Version7 = 7, - // The current version is 7. - CurrentVersion = INSTR_PROF_INDEX_VERSION -}; -const uint64_t Version = ProfVersion::CurrentVersion; - -const HashT HashType = HashT::MD5; - -inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); } - -// This structure defines the file header of the LLVM profile -// data file in indexed-format. -struct Header { - uint64_t Magic; - uint64_t Version; - uint64_t Unused; // Becomes unused since version 4 - uint64_t HashType; - uint64_t HashOffset; -}; - -// Profile summary data recorded in the profile data file in indexed -// format. It is introduced in version 4. The summary data follows -// right after the profile file header. -struct Summary { - struct Entry { - uint64_t Cutoff; ///< The required percentile of total execution count. - uint64_t - MinBlockCount; ///< The minimum execution count for this percentile. - uint64_t NumBlocks; ///< Number of blocks >= the minimum execution count. - }; - // The field kind enumerator to assigned value mapping should remain - // unchanged when a new kind is added or an old kind gets deleted in - // the future. - enum SummaryFieldKind { - /// The total number of functions instrumented. - TotalNumFunctions = 0, - /// Total number of instrumented blocks/edges. - TotalNumBlocks = 1, - /// The maximal execution count among all functions. - /// This field does not exist for profile data from IR based - /// instrumentation. - MaxFunctionCount = 2, - /// Max block count of the program. - MaxBlockCount = 3, - /// Max internal block count of the program (excluding entry blocks). - MaxInternalBlockCount = 4, - /// The sum of all instrumented block counts. - TotalBlockCount = 5, - NumKinds = TotalBlockCount + 1 - }; - - // The number of summary fields following the summary header. - uint64_t NumSummaryFields; - // The number of Cutoff Entries (Summary::Entry) following summary fields. - uint64_t NumCutoffEntries; - - Summary() = delete; - Summary(uint32_t Size) { memset(this, 0, Size); } - - void operator delete(void *ptr) { ::operator delete(ptr); } - - static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries) { - return sizeof(Summary) + NumCutoffEntries * sizeof(Entry) + - NumSumFields * sizeof(uint64_t); - } - - const uint64_t *getSummaryDataBase() const { - return reinterpret_cast(this + 1); - } - - uint64_t *getSummaryDataBase() { - return reinterpret_cast(this + 1); - } - - const Entry *getCutoffEntryBase() const { - return reinterpret_cast( - &getSummaryDataBase()[NumSummaryFields]); - } - - Entry *getCutoffEntryBase() { - return reinterpret_cast(&getSummaryDataBase()[NumSummaryFields]); - } - - uint64_t get(SummaryFieldKind K) const { - return getSummaryDataBase()[K]; - } - - void set(SummaryFieldKind K, uint64_t V) { - getSummaryDataBase()[K] = V; - } - - const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; } - - void setEntry(uint32_t I, const ProfileSummaryEntry &E) { - Entry &ER = getCutoffEntryBase()[I]; - ER.Cutoff = E.Cutoff; - ER.MinBlockCount = E.MinCount; - ER.NumBlocks = E.NumCounts; - } -}; - -inline std::unique_ptr

allocSummary(uint32_t TotalSize) { - return std::unique_ptr(new (::operator new(TotalSize)) - Summary(TotalSize)); -} - -} // end namespace IndexedInstrProf - -namespace RawInstrProf { - -// Version 1: First version -// Version 2: Added value profile data section. Per-function control data -// struct has more fields to describe value profile information. -// Version 3: Compressed name section support. Function PGO name reference -// from control data struct is changed from raw pointer to Name's MD5 value. -// Version 4: ValueDataBegin and ValueDataSizes fields are removed from the -// raw header. -// Version 5: Bit 60 of FuncHash is reserved for the flag for the context -// sensitive records. -// Version 6: Added binary id. -// Version 7: Reorder binary id and include version in signature. -// Version 8: Use relative counter pointer. -const uint64_t Version = INSTR_PROF_RAW_VERSION; - -template inline uint64_t getMagic(); -template <> inline uint64_t getMagic() { - return INSTR_PROF_RAW_MAGIC_64; -} - -template <> inline uint64_t getMagic() { - return INSTR_PROF_RAW_MAGIC_32; -} - -// Per-function profile data header/control structure. -// The definition should match the structure defined in -// compiler-rt/lib/profile/InstrProfiling.h. -// It should also match the synthesized type in -// Transforms/Instrumentation/InstrProfiling.cpp:getOrCreateRegionCounters. -template struct alignas(8) ProfileData { - #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name; - #include "llvm/ProfileData/InstrProfData.inc" -}; - -// File header structure of the LLVM profile data in raw format. -// The definition should match the header referenced in -// compiler-rt/lib/profile/InstrProfilingFile.c and -// InstrProfilingBuffer.c. -struct Header { -#define INSTR_PROF_RAW_HEADER(Type, Name, Init) const Type Name; -#include "llvm/ProfileData/InstrProfData.inc" -}; - -} // end namespace RawInstrProf - -// Parse MemOP Size range option. -void getMemOPSizeRangeFromOption(StringRef Str, int64_t &RangeStart, - int64_t &RangeLast); - -// Create the variable for the profile file name. -void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput); - -// Whether to compress function names in profile records, and filenames in -// code coverage mappings. Used by the Instrumentation library and unit tests. -extern cl::opt DoInstrProfNameCompression; - -} // end namespace llvm -#endif // LLVM_PROFILEDATA_INSTRPROF_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfCorrelator.h b/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfCorrelator.h deleted file mode 100644 index 3d0076fd90..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfCorrelator.h +++ /dev/null @@ -1,178 +0,0 @@ -//===- InstrProfCorrelator.h ------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This file defines InstrProfCorrelator used to generate PGO profiles from -// raw profile data and debug info. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H -#define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include - -namespace llvm { - -/// InstrProfCorrelator - A base class used to create raw instrumentation data -/// to their functions. -class InstrProfCorrelator { -public: - static llvm::Expected> - get(StringRef DebugInfoFilename); - - /// Construct a ProfileData vector used to correlate raw instrumentation data - /// to their functions. - virtual Error correlateProfileData() = 0; - - /// Return the number of ProfileData elements. - llvm::Optional getDataSize() const; - - /// Return a pointer to the names string that this class constructs. - const char *getNamesPointer() const { return Names.c_str(); } - - /// Return the number of bytes in the names string. - size_t getNamesSize() const { return Names.size(); } - - /// Return the size of the counters section in bytes. - uint64_t getCountersSectionSize() const { - return Ctx->CountersSectionEnd - Ctx->CountersSectionStart; - } - - static const char *FunctionNameAttributeName; - static const char *CFGHashAttributeName; - static const char *NumCountersAttributeName; - - enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit }; - InstrProfCorrelatorKind getKind() const { return Kind; } - virtual ~InstrProfCorrelator() = default; - -protected: - struct Context { - static llvm::Expected> - get(std::unique_ptr Buffer, const object::ObjectFile &Obj); - std::unique_ptr Buffer; - /// The address range of the __llvm_prf_cnts section. - uint64_t CountersSectionStart; - uint64_t CountersSectionEnd; - /// True if target and host have different endian orders. - bool ShouldSwapBytes; - }; - const std::unique_ptr Ctx; - - InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr Ctx) - : Ctx(std::move(Ctx)), Kind(K) {} - - std::string Names; - std::vector NamesVec; - -private: - static llvm::Expected> - get(std::unique_ptr Buffer); - - const InstrProfCorrelatorKind Kind; -}; - -/// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template -/// pointer type so that the ProfileData vector can be materialized. -template -class InstrProfCorrelatorImpl : public InstrProfCorrelator { -public: - InstrProfCorrelatorImpl(std::unique_ptr Ctx); - static bool classof(const InstrProfCorrelator *C); - - /// Return a pointer to the underlying ProfileData vector that this class - /// constructs. - const RawInstrProf::ProfileData *getDataPointer() const { - return Data.empty() ? nullptr : Data.data(); - } - - /// Return the number of ProfileData elements. - size_t getDataSize() const { return Data.size(); } - - static llvm::Expected>> - get(std::unique_ptr Ctx, - const object::ObjectFile &Obj); - -protected: - std::vector> Data; - - Error correlateProfileData() override; - virtual void correlateProfileDataImpl() = 0; - - void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, - IntPtrT FunctionPtr, uint32_t NumCounters); - -private: - InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind, - std::unique_ptr Ctx) - : InstrProfCorrelator(Kind, std::move(Ctx)){}; - llvm::DenseSet CounterOffsets; - - // Byte-swap the value if necessary. - template T maybeSwap(T Value) const { - return Ctx->ShouldSwapBytes ? sys::getSwappedBytes(Value) : Value; - } -}; - -/// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes -/// DWARF debug info as input to correlate profiles. -template -class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl { -public: - DwarfInstrProfCorrelator(std::unique_ptr DICtx, - std::unique_ptr Ctx) - : InstrProfCorrelatorImpl(std::move(Ctx)), - DICtx(std::move(DICtx)) {} - -private: - std::unique_ptr DICtx; - - /// Return the address of the object that the provided DIE symbolizes. - llvm::Optional getLocation(const DWARFDie &Die) const; - - /// Returns true if the provided DIE symbolizes an instrumentation probe - /// symbol. - static bool isDIEOfProbe(const DWARFDie &Die); - - /// Iterate over DWARF DIEs to find those that symbolize instrumentation - /// probes and construct the ProfileData vector and Names string. - /// - /// Here is some example DWARF for an instrumentation probe we are looking - /// for: - /// \code - /// DW_TAG_subprogram - /// DW_AT_low_pc (0x0000000000000000) - /// DW_AT_high_pc (0x0000000000000014) - /// DW_AT_name ("foo") - /// DW_TAG_variable - /// DW_AT_name ("__profc_foo") - /// DW_AT_location (DW_OP_addr 0x0) - /// DW_TAG_LLVM_annotation - /// DW_AT_name ("Function Name") - /// DW_AT_const_value ("foo") - /// DW_TAG_LLVM_annotation - /// DW_AT_name ("CFG Hash") - /// DW_AT_const_value (12345678) - /// DW_TAG_LLVM_annotation - /// DW_AT_name ("Num Counters") - /// DW_AT_const_value (2) - /// NULL - /// NULL - /// \endcode - void correlateProfileDataImpl() override; -}; - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfReader.h b/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfReader.h deleted file mode 100644 index e9dd19a697..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfReader.h +++ /dev/null @@ -1,650 +0,0 @@ -//===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains support for reading profiling data for instrumentation -// based PGO and coverage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H -#define LLVM_PROFILEDATA_INSTRPROFREADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/InstrProfCorrelator.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/LineIterator.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/OnDiskHashTable.h" -#include "llvm/Support/SwapByteOrder.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class InstrProfReader; - -/// A file format agnostic iterator over profiling data. -class InstrProfIterator { -public: - using iterator_category = std::input_iterator_tag; - using value_type = NamedInstrProfRecord; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - -private: - InstrProfReader *Reader = nullptr; - value_type Record; - - void Increment(); - -public: - InstrProfIterator() = default; - InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } - - InstrProfIterator &operator++() { Increment(); return *this; } - bool operator==(const InstrProfIterator &RHS) const { - return Reader == RHS.Reader; - } - bool operator!=(const InstrProfIterator &RHS) const { - return Reader != RHS.Reader; - } - value_type &operator*() { return Record; } - value_type *operator->() { return &Record; } -}; - -/// Base class and interface for reading profiling data of any known instrprof -/// format. Provides an iterator over NamedInstrProfRecords. -class InstrProfReader { - instrprof_error LastError = instrprof_error::success; - std::string LastErrorMsg; - -public: - InstrProfReader() = default; - virtual ~InstrProfReader() = default; - - /// Read the header. Required before reading first record. - virtual Error readHeader() = 0; - - /// Read a single record. - virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0; - - /// Print binary ids on stream OS. - virtual Error printBinaryIds(raw_ostream &OS) { return success(); }; - - /// Iterator over profile data. - InstrProfIterator begin() { return InstrProfIterator(this); } - InstrProfIterator end() { return InstrProfIterator(); } - - virtual bool isIRLevelProfile() const = 0; - - virtual bool hasCSIRLevelProfile() const = 0; - - virtual bool instrEntryBBEnabled() const = 0; - - /// Return true if we must provide debug info to create PGO profiles. - virtual bool useDebugInfoCorrelate() const { return false; } - - /// Return true if the profile has single byte counters representing coverage. - virtual bool hasSingleByteCoverage() const = 0; - - /// Return true if the profile only instruments function entries. - virtual bool functionEntryOnly() const = 0; - - /// Returns a BitsetEnum describing the attributes of the profile. To check - /// individual attributes prefer using the helpers above. - virtual InstrProfKind getProfileKind() const = 0; - - /// Return the PGO symtab. There are three different readers: - /// Raw, Text, and Indexed profile readers. The first two types - /// of readers are used only by llvm-profdata tool, while the indexed - /// profile reader is also used by llvm-cov tool and the compiler ( - /// backend or frontend). Since creating PGO symtab can create - /// significant runtime and memory overhead (as it touches data - /// for the whole program), InstrProfSymtab for the indexed profile - /// reader should be created on demand and it is recommended to be - /// only used for dumping purpose with llvm-proftool, not with the - /// compiler. - virtual InstrProfSymtab &getSymtab() = 0; - - /// Compute the sum of counts and return in Sum. - void accumulateCounts(CountSumOrPercent &Sum, bool IsCS); - -protected: - std::unique_ptr Symtab; - - /// Set the current error and return same. - Error error(instrprof_error Err, const std::string &ErrMsg = "") { - LastError = Err; - LastErrorMsg = ErrMsg; - if (Err == instrprof_error::success) - return Error::success(); - return make_error(Err, ErrMsg); - } - - Error error(Error &&E) { - handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { - LastError = IPE.get(); - LastErrorMsg = IPE.getMessage(); - }); - return make_error(LastError, LastErrorMsg); - } - - /// Clear the current error and return a successful one. - Error success() { return error(instrprof_error::success); } - -public: - /// Return true if the reader has finished reading the profile data. - bool isEOF() { return LastError == instrprof_error::eof; } - - /// Return true if the reader encountered an error reading profiling data. - bool hasError() { return LastError != instrprof_error::success && !isEOF(); } - - /// Get the current error. - Error getError() { - if (hasError()) - return make_error(LastError, LastErrorMsg); - return Error::success(); - } - - /// Factory method to create an appropriately typed reader for the given - /// instrprof file. - static Expected> - create(const Twine &Path, const InstrProfCorrelator *Correlator = nullptr); - - static Expected> - create(std::unique_ptr Buffer, - const InstrProfCorrelator *Correlator = nullptr); -}; - -/// Reader for the simple text based instrprof format. -/// -/// This format is a simple text format that's suitable for test data. Records -/// are separated by one or more blank lines, and record fields are separated by -/// new lines. -/// -/// Each record consists of a function name, a function hash, a number of -/// counters, and then each counter value, in that order. -class TextInstrProfReader : public InstrProfReader { -private: - /// The profile data file contents. - std::unique_ptr DataBuffer; - /// Iterator over the profile data. - line_iterator Line; - /// The attributes of the current profile. - InstrProfKind ProfileKind = InstrProfKind::Unknown; - - Error readValueProfileData(InstrProfRecord &Record); - -public: - TextInstrProfReader(std::unique_ptr DataBuffer_) - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} - TextInstrProfReader(const TextInstrProfReader &) = delete; - TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; - - /// Return true if the given buffer is in text instrprof format. - static bool hasFormat(const MemoryBuffer &Buffer); - - bool isIRLevelProfile() const override { - return static_cast(ProfileKind & InstrProfKind::IR); - } - - bool hasCSIRLevelProfile() const override { - return static_cast(ProfileKind & InstrProfKind::CS); - } - - bool instrEntryBBEnabled() const override { - return static_cast(ProfileKind & InstrProfKind::BB); - } - - bool hasSingleByteCoverage() const override { - return static_cast(ProfileKind & InstrProfKind::SingleByteCoverage); - } - - bool functionEntryOnly() const override { - return static_cast(ProfileKind & InstrProfKind::FunctionEntryOnly); - } - - InstrProfKind getProfileKind() const override { return ProfileKind; } - - /// Read the header. - Error readHeader() override; - - /// Read a single record. - Error readNextRecord(NamedInstrProfRecord &Record) override; - - InstrProfSymtab &getSymtab() override { - assert(Symtab.get()); - return *Symtab.get(); - } -}; - -/// Reader for the raw instrprof binary format from runtime. -/// -/// This format is a raw memory dump of the instrumentation-based profiling data -/// from the runtime. It has no index. -/// -/// Templated on the unsigned type whose size matches pointers on the platform -/// that wrote the profile. -template -class RawInstrProfReader : public InstrProfReader { -private: - /// The profile data file contents. - std::unique_ptr DataBuffer; - /// If available, this hold the ProfileData array used to correlate raw - /// instrumentation data to their functions. - const InstrProfCorrelatorImpl *Correlator; - bool ShouldSwapBytes; - // The value of the version field of the raw profile data header. The lower 56 - // bits specifies the format version and the most significant 8 bits specify - // the variant types of the profile. - uint64_t Version; - uint64_t CountersDelta; - uint64_t NamesDelta; - const RawInstrProf::ProfileData *Data; - const RawInstrProf::ProfileData *DataEnd; - const char *CountersStart; - const char *CountersEnd; - const char *NamesStart; - const char *NamesEnd; - // After value profile is all read, this pointer points to - // the header of next profile data (if exists) - const uint8_t *ValueDataStart; - uint32_t ValueKindLast; - uint32_t CurValueDataSize; - - uint64_t BinaryIdsSize; - const uint8_t *BinaryIdsStart; - -public: - RawInstrProfReader(std::unique_ptr DataBuffer, - const InstrProfCorrelator *Correlator) - : DataBuffer(std::move(DataBuffer)), - Correlator(dyn_cast_or_null>( - Correlator)) {} - RawInstrProfReader(const RawInstrProfReader &) = delete; - RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; - - static bool hasFormat(const MemoryBuffer &DataBuffer); - Error readHeader() override; - Error readNextRecord(NamedInstrProfRecord &Record) override; - Error printBinaryIds(raw_ostream &OS) override; - - bool isIRLevelProfile() const override { - return (Version & VARIANT_MASK_IR_PROF) != 0; - } - - bool hasCSIRLevelProfile() const override { - return (Version & VARIANT_MASK_CSIR_PROF) != 0; - } - - bool instrEntryBBEnabled() const override { - return (Version & VARIANT_MASK_INSTR_ENTRY) != 0; - } - - bool useDebugInfoCorrelate() const override { - return (Version & VARIANT_MASK_DBG_CORRELATE) != 0; - } - - bool hasSingleByteCoverage() const override { - return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0; - } - - bool functionEntryOnly() const override { - return (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0; - } - - /// Returns a BitsetEnum describing the attributes of the raw instr profile. - InstrProfKind getProfileKind() const override; - - InstrProfSymtab &getSymtab() override { - assert(Symtab.get()); - return *Symtab.get(); - } - -private: - Error createSymtab(InstrProfSymtab &Symtab); - Error readNextHeader(const char *CurrentPos); - Error readHeader(const RawInstrProf::Header &Header); - - template IntT swap(IntT Int) const { - return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; - } - - support::endianness getDataEndianness() const { - support::endianness HostEndian = getHostEndianness(); - if (!ShouldSwapBytes) - return HostEndian; - if (HostEndian == support::little) - return support::big; - else - return support::little; - } - - inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { - return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); - } - - Error readName(NamedInstrProfRecord &Record); - Error readFuncHash(NamedInstrProfRecord &Record); - Error readRawCounts(InstrProfRecord &Record); - Error readValueProfilingData(InstrProfRecord &Record); - bool atEnd() const { return Data == DataEnd; } - - void advanceData() { - // `CountersDelta` is a constant zero when using debug info correlation. - if (!Correlator) { - // The initial CountersDelta is the in-memory address difference between - // the data and counts sections: - // start(__llvm_prf_cnts) - start(__llvm_prf_data) - // As we advance to the next record, we maintain the correct CountersDelta - // with respect to the next record. - CountersDelta -= sizeof(*Data); - } - Data++; - ValueDataStart += CurValueDataSize; - } - - const char *getNextHeaderPos() const { - assert(atEnd()); - return (const char *)ValueDataStart; - } - - StringRef getName(uint64_t NameRef) const { - return Symtab->getFuncName(swap(NameRef)); - } - - int getCounterTypeSize() const { - return hasSingleByteCoverage() ? sizeof(uint8_t) : sizeof(uint64_t); - } -}; - -using RawInstrProfReader32 = RawInstrProfReader; -using RawInstrProfReader64 = RawInstrProfReader; - -namespace IndexedInstrProf { - -enum class HashT : uint32_t; - -} // end namespace IndexedInstrProf - -/// Trait for lookups into the on-disk hash table for the binary instrprof -/// format. -class InstrProfLookupTrait { - std::vector DataBuffer; - IndexedInstrProf::HashT HashType; - unsigned FormatVersion; - // Endianness of the input value profile data. - // It should be LE by default, but can be changed - // for testing purpose. - support::endianness ValueProfDataEndianness = support::little; - -public: - InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) - : HashType(HashType), FormatVersion(FormatVersion) {} - - using data_type = ArrayRef; - - using internal_key_type = StringRef; - using external_key_type = StringRef; - using hash_value_type = uint64_t; - using offset_type = uint64_t; - - static bool EqualKey(StringRef A, StringRef B) { return A == B; } - static StringRef GetInternalKey(StringRef K) { return K; } - static StringRef GetExternalKey(StringRef K) { return K; } - - hash_value_type ComputeHash(StringRef K); - - static std::pair - ReadKeyDataLength(const unsigned char *&D) { - using namespace support; - - offset_type KeyLen = endian::readNext(D); - offset_type DataLen = endian::readNext(D); - return std::make_pair(KeyLen, DataLen); - } - - StringRef ReadKey(const unsigned char *D, offset_type N) { - return StringRef((const char *)D, N); - } - - bool readValueProfilingData(const unsigned char *&D, - const unsigned char *const End); - data_type ReadData(StringRef K, const unsigned char *D, offset_type N); - - // Used for testing purpose only. - void setValueProfDataEndianness(support::endianness Endianness) { - ValueProfDataEndianness = Endianness; - } -}; - -struct InstrProfReaderIndexBase { - virtual ~InstrProfReaderIndexBase() = default; - - // Read all the profile records with the same key pointed to the current - // iterator. - virtual Error getRecords(ArrayRef &Data) = 0; - - // Read all the profile records with the key equal to FuncName - virtual Error getRecords(StringRef FuncName, - ArrayRef &Data) = 0; - virtual void advanceToNextKey() = 0; - virtual bool atEnd() const = 0; - virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; - virtual uint64_t getVersion() const = 0; - virtual bool isIRLevelProfile() const = 0; - virtual bool hasCSIRLevelProfile() const = 0; - virtual bool instrEntryBBEnabled() const = 0; - virtual bool hasSingleByteCoverage() const = 0; - virtual bool functionEntryOnly() const = 0; - virtual InstrProfKind getProfileKind() const = 0; - virtual Error populateSymtab(InstrProfSymtab &) = 0; -}; - -using OnDiskHashTableImplV3 = - OnDiskIterableChainedHashTable; - -template -class InstrProfReaderItaniumRemapper; - -template -class InstrProfReaderIndex : public InstrProfReaderIndexBase { -private: - std::unique_ptr HashTable; - typename HashTableImpl::data_iterator RecordIterator; - uint64_t FormatVersion; - - friend class InstrProfReaderItaniumRemapper; - -public: - InstrProfReaderIndex(const unsigned char *Buckets, - const unsigned char *const Payload, - const unsigned char *const Base, - IndexedInstrProf::HashT HashType, uint64_t Version); - ~InstrProfReaderIndex() override = default; - - Error getRecords(ArrayRef &Data) override; - Error getRecords(StringRef FuncName, - ArrayRef &Data) override; - void advanceToNextKey() override { RecordIterator++; } - - bool atEnd() const override { - return RecordIterator == HashTable->data_end(); - } - - void setValueProfDataEndianness(support::endianness Endianness) override { - HashTable->getInfoObj().setValueProfDataEndianness(Endianness); - } - - uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } - - bool isIRLevelProfile() const override { - return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; - } - - bool hasCSIRLevelProfile() const override { - return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0; - } - - bool instrEntryBBEnabled() const override { - return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0; - } - - bool hasSingleByteCoverage() const override { - return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0; - } - - bool functionEntryOnly() const override { - return (FormatVersion & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0; - } - - InstrProfKind getProfileKind() const override; - - Error populateSymtab(InstrProfSymtab &Symtab) override { - return Symtab.create(HashTable->keys()); - } -}; - -/// Name matcher supporting fuzzy matching of symbol names to names in profiles. -class InstrProfReaderRemapper { -public: - virtual ~InstrProfReaderRemapper() = default; - virtual Error populateRemappings() { return Error::success(); } - virtual Error getRecords(StringRef FuncName, - ArrayRef &Data) = 0; -}; - -/// Reader for the indexed binary instrprof format. -class IndexedInstrProfReader : public InstrProfReader { -private: - /// The profile data file contents. - std::unique_ptr DataBuffer; - /// The profile remapping file contents. - std::unique_ptr RemappingBuffer; - /// The index into the profile data. - std::unique_ptr Index; - /// The profile remapping file contents. - std::unique_ptr Remapper; - /// Profile summary data. - std::unique_ptr Summary; - /// Context sensitive profile summary data. - std::unique_ptr CS_Summary; - // Index to the current record in the record array. - unsigned RecordIndex; - - // Read the profile summary. Return a pointer pointing to one byte past the - // end of the summary data if it exists or the input \c Cur. - // \c UseCS indicates whether to use the context-sensitive profile summary. - const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, - const unsigned char *Cur, bool UseCS); - -public: - IndexedInstrProfReader( - std::unique_ptr DataBuffer, - std::unique_ptr RemappingBuffer = nullptr) - : DataBuffer(std::move(DataBuffer)), - RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {} - IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; - - /// Return the profile version. - uint64_t getVersion() const { return Index->getVersion(); } - bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } - bool hasCSIRLevelProfile() const override { - return Index->hasCSIRLevelProfile(); - } - - bool instrEntryBBEnabled() const override { - return Index->instrEntryBBEnabled(); - } - - bool hasSingleByteCoverage() const override { - return Index->hasSingleByteCoverage(); - } - - bool functionEntryOnly() const override { return Index->functionEntryOnly(); } - - /// Returns a BitsetEnum describing the attributes of the indexed instr - /// profile. - InstrProfKind getProfileKind() const override { - return Index->getProfileKind(); - } - - /// Return true if the given buffer is in an indexed instrprof format. - static bool hasFormat(const MemoryBuffer &DataBuffer); - - /// Read the file header. - Error readHeader() override; - /// Read a single record. - Error readNextRecord(NamedInstrProfRecord &Record) override; - - /// Return the NamedInstrProfRecord associated with FuncName and FuncHash - Expected getInstrProfRecord(StringRef FuncName, - uint64_t FuncHash); - - /// Fill Counts with the profile data for the given function name. - Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, - std::vector &Counts); - - /// Return the maximum of all known function counts. - /// \c UseCS indicates whether to use the context-sensitive count. - uint64_t getMaximumFunctionCount(bool UseCS) { - if (UseCS) { - assert(CS_Summary && "No context sensitive profile summary"); - return CS_Summary->getMaxFunctionCount(); - } else { - assert(Summary && "No profile summary"); - return Summary->getMaxFunctionCount(); - } - } - - /// Factory method to create an indexed reader. - static Expected> - create(const Twine &Path, const Twine &RemappingPath = ""); - - static Expected> - create(std::unique_ptr Buffer, - std::unique_ptr RemappingBuffer = nullptr); - - // Used for testing purpose only. - void setValueProfDataEndianness(support::endianness Endianness) { - Index->setValueProfDataEndianness(Endianness); - } - - // See description in the base class. This interface is designed - // to be used by llvm-profdata (for dumping). Avoid using this when - // the client is the compiler. - InstrProfSymtab &getSymtab() override; - - /// Return the profile summary. - /// \c UseCS indicates whether to use the context-sensitive summary. - ProfileSummary &getSummary(bool UseCS) { - if (UseCS) { - assert(CS_Summary && "No context sensitive summary"); - return *(CS_Summary.get()); - } else { - assert(Summary && "No profile summary"); - return *(Summary.get()); - } - } -}; - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_INSTRPROFREADER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfWriter.h b/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfWriter.h deleted file mode 100644 index 2412a40f72..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/InstrProfWriter.h +++ /dev/null @@ -1,134 +0,0 @@ -//===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing profiling data for instrumentation -// based PGO and coverage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H -#define LLVM_PROFILEDATA_INSTRPROFWRITER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include -#include - -namespace llvm { - -/// Writer for instrumentation based profile data. -class InstrProfRecordWriterTrait; -class ProfOStream; -class raw_fd_ostream; - -class InstrProfWriter { -public: - using ProfilingData = SmallDenseMap; - -private: - bool Sparse; - StringMap FunctionData; - // An enum describing the attributes of the profile. - InstrProfKind ProfileKind = InstrProfKind::Unknown; - // Use raw pointer here for the incomplete type object. - InstrProfRecordWriterTrait *InfoObj; - -public: - InstrProfWriter(bool Sparse = false); - ~InstrProfWriter(); - - StringMap &getProfileData() { return FunctionData; } - - /// Add function counts for the given function. If there are already counts - /// for this function and the hash and number of counts match, each counter is - /// summed. Optionally scale counts by \p Weight. - void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, - function_ref Warn); - void addRecord(NamedInstrProfRecord &&I, function_ref Warn) { - addRecord(std::move(I), 1, Warn); - } - - /// Merge existing function counts from the given writer. - void mergeRecordsFromWriter(InstrProfWriter &&IPW, - function_ref Warn); - - /// Write the profile to \c OS - Error write(raw_fd_ostream &OS); - - /// Write the profile in text format to \c OS - Error writeText(raw_fd_ostream &OS); - - Error validateRecord(const InstrProfRecord &Func); - - /// Write \c Record in text format to \c OS - static void writeRecordInText(StringRef Name, uint64_t Hash, - const InstrProfRecord &Counters, - InstrProfSymtab &Symtab, raw_fd_ostream &OS); - - /// Write the profile, returning the raw data. For testing. - std::unique_ptr writeBuffer(); - - /// Update the attributes of the current profile from the attributes - /// specified. An error is returned if IR and FE profiles are mixed. - Error mergeProfileKind(const InstrProfKind Other) { - // If the kind is unset, this is the first profile we are merging so just - // set it to the given type. - if (ProfileKind == InstrProfKind::Unknown) { - ProfileKind = Other; - return Error::success(); - } - - // Returns true if merging should fail assuming A and B are incompatible. - auto testIncompatible = [&](InstrProfKind A, InstrProfKind B) { - return (static_cast(ProfileKind & A) && - static_cast(Other & B)) || - (static_cast(ProfileKind & B) && - static_cast(Other & A)); - }; - - // Check if the profiles are in-compatible. Clang frontend profiles can't be - // merged with other profile types. - if (static_cast((ProfileKind & InstrProfKind::FE) ^ - (Other & InstrProfKind::FE))) { - return make_error(instrprof_error::unsupported_version); - } - if (testIncompatible(InstrProfKind::FunctionEntryOnly, InstrProfKind::BB)) { - return make_error( - instrprof_error::unsupported_version, - "cannot merge FunctionEntryOnly profiles and BB profiles together"); - } - - // Now we update the profile type with the bits that are set. - ProfileKind |= Other; - return Error::success(); - } - - // Internal interface for testing purpose only. - void setValueProfDataEndianness(support::endianness Endianness); - void setOutputSparse(bool Sparse); - // Compute the overlap b/w this object and Other. Program level result is - // stored in Overlap and function level result is stored in FuncLevelOverlap. - void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap, - OverlapStats &FuncLevelOverlap, - const OverlapFuncFilters &FuncFilter); - -private: - void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I, - uint64_t Weight, function_ref Warn); - bool shouldEncodeData(const ProfilingData &PD); - - Error writeImpl(ProfOStream &OS); -}; - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/ProfileCommon.h b/suite/synctools/tablegen/include/llvm/ProfileData/ProfileCommon.h deleted file mode 100644 index ad92af22d9..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/ProfileCommon.h +++ /dev/null @@ -1,111 +0,0 @@ -//===- ProfileCommon.h - Common profiling APIs. -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains data structures and functions common to both instrumented -// and sample profiling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_PROFILECOMMON_H -#define LLVM_PROFILEDATA_PROFILECOMMON_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/Support/Error.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -namespace sampleprof { - -class FunctionSamples; - -} // end namespace sampleprof - -inline const char *getHotSectionPrefix() { return "hot"; } -inline const char *getUnlikelySectionPrefix() { return "unlikely"; } - -class ProfileSummaryBuilder { -private: - /// We keep track of the number of times a count (block count or samples) - /// appears in the profile. The map is kept sorted in the descending order of - /// counts. - std::map> CountFrequencies; - std::vector DetailedSummaryCutoffs; - -protected: - SummaryEntryVector DetailedSummary; - uint64_t TotalCount = 0; - uint64_t MaxCount = 0; - uint64_t MaxFunctionCount = 0; - uint32_t NumCounts = 0; - uint32_t NumFunctions = 0; - - ProfileSummaryBuilder(std::vector Cutoffs) - : DetailedSummaryCutoffs(std::move(Cutoffs)) {} - ~ProfileSummaryBuilder() = default; - - inline void addCount(uint64_t Count); - void computeDetailedSummary(); - -public: - /// A vector of useful cutoff values for detailed summary. - static const ArrayRef DefaultCutoffs; - - /// Find the summary entry for a desired percentile of counts. - static const ProfileSummaryEntry & - getEntryForPercentile(const SummaryEntryVector &DS, uint64_t Percentile); - static uint64_t getHotCountThreshold(const SummaryEntryVector &DS); - static uint64_t getColdCountThreshold(const SummaryEntryVector &DS); -}; - -class InstrProfSummaryBuilder final : public ProfileSummaryBuilder { - uint64_t MaxInternalBlockCount = 0; - - inline void addEntryCount(uint64_t Count); - inline void addInternalCount(uint64_t Count); - -public: - InstrProfSummaryBuilder(std::vector Cutoffs) - : ProfileSummaryBuilder(std::move(Cutoffs)) {} - - void addRecord(const InstrProfRecord &); - std::unique_ptr getSummary(); -}; - -class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder { -public: - SampleProfileSummaryBuilder(std::vector Cutoffs) - : ProfileSummaryBuilder(std::move(Cutoffs)) {} - - void addRecord(const sampleprof::FunctionSamples &FS, - bool isCallsiteSample = false); - std::unique_ptr - computeSummaryForProfiles(const sampleprof::SampleProfileMap &Profiles); - std::unique_ptr getSummary(); -}; - -/// This is called when a count is seen in the profile. -void ProfileSummaryBuilder::addCount(uint64_t Count) { - TotalCount += Count; - if (Count > MaxCount) - MaxCount = Count; - NumCounts++; - CountFrequencies[Count]++; -} - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_PROFILECOMMON_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/RawMemProfReader.h b/suite/synctools/tablegen/include/llvm/ProfileData/RawMemProfReader.h deleted file mode 100644 index 45544927a8..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/RawMemProfReader.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ -#define LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ -//===- MemProfReader.h - Instrumented memory profiling reader ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains support for reading MemProf profiling data. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" - -namespace llvm { -namespace memprof { - -class RawMemProfReader { -public: - RawMemProfReader(std::unique_ptr DataBuffer) - : DataBuffer(std::move(DataBuffer)) {} - // Prints aggregate counts for each raw profile parsed from the DataBuffer. - void printSummaries(raw_ostream &OS) const; - - // Return true if the \p DataBuffer starts with magic bytes indicating it is - // a raw binary memprof profile. - static bool hasFormat(const MemoryBuffer &DataBuffer); - - // Create a RawMemProfReader after sanity checking the contents of the file at - // \p Path. - static Expected> create(const Twine &Path); - -private: - std::unique_ptr DataBuffer; -}; - -} // namespace memprof -} // namespace llvm - -#endif // LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProf.h b/suite/synctools/tablegen/include/llvm/ProfileData/SampleProf.h deleted file mode 100644 index 33071a2609..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProf.h +++ /dev/null @@ -1,1279 +0,0 @@ -//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains common definitions used in the reading and writing of -// sample profile data. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H -#define LLVM_PROFILEDATA_SAMPLEPROF_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -const std::error_category &sampleprof_category(); - -enum class sampleprof_error { - success = 0, - bad_magic, - unsupported_version, - too_large, - truncated, - malformed, - unrecognized_format, - unsupported_writing_format, - truncated_name_table, - not_implemented, - counter_overflow, - ostream_seek_unsupported, - compress_failed, - uncompress_failed, - zlib_unavailable, - hash_mismatch -}; - -inline std::error_code make_error_code(sampleprof_error E) { - return std::error_code(static_cast(E), sampleprof_category()); -} - -inline sampleprof_error MergeResult(sampleprof_error &Accumulator, - sampleprof_error Result) { - // Prefer first error encountered as later errors may be secondary effects of - // the initial problem. - if (Accumulator == sampleprof_error::success && - Result != sampleprof_error::success) - Accumulator = Result; - return Accumulator; -} - -} // end namespace llvm - -namespace std { - -template <> -struct is_error_code_enum : std::true_type {}; - -} // end namespace std - -namespace llvm { -namespace sampleprof { - -enum SampleProfileFormat { - SPF_None = 0, - SPF_Text = 0x1, - SPF_Compact_Binary = 0x2, - SPF_GCC = 0x3, - SPF_Ext_Binary = 0x4, - SPF_Binary = 0xff -}; - -static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) { - return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) | - uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) | - uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) | - uint64_t('2') << (64 - 56) | uint64_t(Format); -} - -/// Get the proper representation of a string according to whether the -/// current Format uses MD5 to represent the string. -static inline StringRef getRepInFormat(StringRef Name, bool UseMD5, - std::string &GUIDBuf) { - if (Name.empty() || !UseMD5) - return Name; - GUIDBuf = std::to_string(Function::getGUID(Name)); - return GUIDBuf; -} - -static inline uint64_t SPVersion() { return 103; } - -// Section Type used by SampleProfileExtBinaryBaseReader and -// SampleProfileExtBinaryBaseWriter. Never change the existing -// value of enum. Only append new ones. -enum SecType { - SecInValid = 0, - SecProfSummary = 1, - SecNameTable = 2, - SecProfileSymbolList = 3, - SecFuncOffsetTable = 4, - SecFuncMetadata = 5, - SecCSNameTable = 6, - // marker for the first type of profile. - SecFuncProfileFirst = 32, - SecLBRProfile = SecFuncProfileFirst -}; - -static inline std::string getSecName(SecType Type) { - switch ((int)Type) { // Avoid -Wcovered-switch-default - case SecInValid: - return "InvalidSection"; - case SecProfSummary: - return "ProfileSummarySection"; - case SecNameTable: - return "NameTableSection"; - case SecProfileSymbolList: - return "ProfileSymbolListSection"; - case SecFuncOffsetTable: - return "FuncOffsetTableSection"; - case SecFuncMetadata: - return "FunctionMetadata"; - case SecCSNameTable: - return "CSNameTableSection"; - case SecLBRProfile: - return "LBRProfileSection"; - default: - return "UnknownSection"; - } -} - -// Entry type of section header table used by SampleProfileExtBinaryBaseReader -// and SampleProfileExtBinaryBaseWriter. -struct SecHdrTableEntry { - SecType Type; - uint64_t Flags; - uint64_t Offset; - uint64_t Size; - // The index indicating the location of the current entry in - // SectionHdrLayout table. - uint32_t LayoutIndex; -}; - -// Flags common for all sections are defined here. In SecHdrTableEntry::Flags, -// common flags will be saved in the lower 32bits and section specific flags -// will be saved in the higher 32 bits. -enum class SecCommonFlags : uint32_t { - SecFlagInValid = 0, - SecFlagCompress = (1 << 0), - // Indicate the section contains only profile without context. - SecFlagFlat = (1 << 1) -}; - -// Section specific flags are defined here. -// !!!Note: Every time a new enum class is created here, please add -// a new check in verifySecFlag. -enum class SecNameTableFlags : uint32_t { - SecFlagInValid = 0, - SecFlagMD5Name = (1 << 0), - // Store MD5 in fixed length instead of ULEB128 so NameTable can be - // accessed like an array. - SecFlagFixedLengthMD5 = (1 << 1), - // Profile contains ".__uniq." suffix name. Compiler shouldn't strip - // the suffix when doing profile matching when seeing the flag. - SecFlagUniqSuffix = (1 << 2) -}; -enum class SecProfSummaryFlags : uint32_t { - SecFlagInValid = 0, - /// SecFlagPartial means the profile is for common/shared code. - /// The common profile is usually merged from profiles collected - /// from running other targets. - SecFlagPartial = (1 << 0), - /// SecFlagContext means this is context-sensitive flat profile for - /// CSSPGO - SecFlagFullContext = (1 << 1), - /// SecFlagFSDiscriminator means this profile uses flow-sensitive - /// discriminators. - SecFlagFSDiscriminator = (1 << 2), - /// SecFlagIsCSNested means this is context-sensitive nested profile for - /// CSSPGO - SecFlagIsCSNested = (1 << 4), -}; - -enum class SecFuncMetadataFlags : uint32_t { - SecFlagInvalid = 0, - SecFlagIsProbeBased = (1 << 0), - SecFlagHasAttribute = (1 << 1), -}; - -enum class SecFuncOffsetFlags : uint32_t { - SecFlagInvalid = 0, - // Store function offsets in an order of contexts. The order ensures that - // callee contexts of a given context laid out next to it. - SecFlagOrdered = (1 << 0), -}; - -// Verify section specific flag is used for the correct section. -template -static inline void verifySecFlag(SecType Type, SecFlagType Flag) { - // No verification is needed for common flags. - if (std::is_same()) - return; - - // Verification starts here for section specific flag. - bool IsFlagLegal = false; - switch (Type) { - case SecNameTable: - IsFlagLegal = std::is_same(); - break; - case SecProfSummary: - IsFlagLegal = std::is_same(); - break; - case SecFuncMetadata: - IsFlagLegal = std::is_same(); - break; - default: - case SecFuncOffsetTable: - IsFlagLegal = std::is_same(); - break; - } - if (!IsFlagLegal) - llvm_unreachable("Misuse of a flag in an incompatible section"); -} - -template -static inline void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) { - verifySecFlag(Entry.Type, Flag); - auto FVal = static_cast(Flag); - bool IsCommon = std::is_same(); - Entry.Flags |= IsCommon ? FVal : (FVal << 32); -} - -template -static inline void removeSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) { - verifySecFlag(Entry.Type, Flag); - auto FVal = static_cast(Flag); - bool IsCommon = std::is_same(); - Entry.Flags &= ~(IsCommon ? FVal : (FVal << 32)); -} - -template -static inline bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag) { - verifySecFlag(Entry.Type, Flag); - auto FVal = static_cast(Flag); - bool IsCommon = std::is_same(); - return Entry.Flags & (IsCommon ? FVal : (FVal << 32)); -} - -/// Represents the relative location of an instruction. -/// -/// Instruction locations are specified by the line offset from the -/// beginning of the function (marked by the line where the function -/// header is) and the discriminator value within that line. -/// -/// The discriminator value is useful to distinguish instructions -/// that are on the same line but belong to different basic blocks -/// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). -struct LineLocation { - LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} - - void print(raw_ostream &OS) const; - void dump() const; - - bool operator<(const LineLocation &O) const { - return LineOffset < O.LineOffset || - (LineOffset == O.LineOffset && Discriminator < O.Discriminator); - } - - bool operator==(const LineLocation &O) const { - return LineOffset == O.LineOffset && Discriminator == O.Discriminator; - } - - bool operator!=(const LineLocation &O) const { - return LineOffset != O.LineOffset || Discriminator != O.Discriminator; - } - - uint32_t LineOffset; - uint32_t Discriminator; -}; - -raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc); - -/// Representation of a single sample record. -/// -/// A sample record is represented by a positive integer value, which -/// indicates how frequently was the associated line location executed. -/// -/// Additionally, if the associated location contains a function call, -/// the record will hold a list of all the possible called targets. For -/// direct calls, this will be the exact function being invoked. For -/// indirect calls (function pointers, virtual table dispatch), this -/// will be a list of one or more functions. -class SampleRecord { -public: - using CallTarget = std::pair; - struct CallTargetComparator { - bool operator()(const CallTarget &LHS, const CallTarget &RHS) const { - if (LHS.second != RHS.second) - return LHS.second > RHS.second; - - return LHS.first < RHS.first; - } - }; - - using SortedCallTargetSet = std::set; - using CallTargetMap = StringMap; - SampleRecord() = default; - - /// Increment the number of samples for this record by \p S. - /// Optionally scale sample count \p S by \p Weight. - /// - /// Sample counts accumulate using saturating arithmetic, to avoid wrapping - /// around unsigned integers. - sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) { - bool Overflowed; - NumSamples = SaturatingMultiplyAdd(S, Weight, NumSamples, &Overflowed); - return Overflowed ? sampleprof_error::counter_overflow - : sampleprof_error::success; - } - - /// Add called function \p F with samples \p S. - /// Optionally scale sample count \p S by \p Weight. - /// - /// Sample counts accumulate using saturating arithmetic, to avoid wrapping - /// around unsigned integers. - sampleprof_error addCalledTarget(StringRef F, uint64_t S, - uint64_t Weight = 1) { - uint64_t &TargetSamples = CallTargets[F]; - bool Overflowed; - TargetSamples = - SaturatingMultiplyAdd(S, Weight, TargetSamples, &Overflowed); - return Overflowed ? sampleprof_error::counter_overflow - : sampleprof_error::success; - } - - /// Return true if this sample record contains function calls. - bool hasCalls() const { return !CallTargets.empty(); } - - uint64_t getSamples() const { return NumSamples; } - const CallTargetMap &getCallTargets() const { return CallTargets; } - const SortedCallTargetSet getSortedCallTargets() const { - return SortCallTargets(CallTargets); - } - - /// Sort call targets in descending order of call frequency. - static const SortedCallTargetSet SortCallTargets(const CallTargetMap &Targets) { - SortedCallTargetSet SortedTargets; - for (const auto &I : Targets) { - SortedTargets.emplace(I.first(), I.second); - } - return SortedTargets; - } - - /// Prorate call targets by a distribution factor. - static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, - float DistributionFactor) { - CallTargetMap AdjustedTargets; - for (const auto &I : Targets) { - AdjustedTargets[I.first()] = I.second * DistributionFactor; - } - return AdjustedTargets; - } - - /// Merge the samples in \p Other into this record. - /// Optionally scale sample counts by \p Weight. - sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1); - void print(raw_ostream &OS, unsigned Indent) const; - void dump() const; - -private: - uint64_t NumSamples = 0; - CallTargetMap CallTargets; -}; - -raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); - -// State of context associated with FunctionSamples -enum ContextStateMask { - UnknownContext = 0x0, // Profile without context - RawContext = 0x1, // Full context profile from input profile - SyntheticContext = 0x2, // Synthetic context created for context promotion - InlinedContext = 0x4, // Profile for context that is inlined into caller - MergedContext = 0x8 // Profile for context merged into base profile -}; - -// Attribute of context associated with FunctionSamples -enum ContextAttributeMask { - ContextNone = 0x0, - ContextWasInlined = 0x1, // Leaf of context was inlined in previous build - ContextShouldBeInlined = 0x2, // Leaf of context should be inlined -}; - -// Represents a context frame with function name and line location -struct SampleContextFrame { - StringRef FuncName; - LineLocation Location; - - SampleContextFrame() : Location(0, 0) {} - - SampleContextFrame(StringRef FuncName, LineLocation Location) - : FuncName(FuncName), Location(Location) {} - - bool operator==(const SampleContextFrame &That) const { - return Location == That.Location && FuncName == That.FuncName; - } - - bool operator!=(const SampleContextFrame &That) const { - return !(*this == That); - } - - std::string toString(bool OutputLineLocation) const { - std::ostringstream OContextStr; - OContextStr << FuncName.str(); - if (OutputLineLocation) { - OContextStr << ":" << Location.LineOffset; - if (Location.Discriminator) - OContextStr << "." << Location.Discriminator; - } - return OContextStr.str(); - } -}; - -static inline hash_code hash_value(const SampleContextFrame &arg) { - return hash_combine(arg.FuncName, arg.Location.LineOffset, - arg.Location.Discriminator); -} - -using SampleContextFrameVector = SmallVector; -using SampleContextFrames = ArrayRef; - -struct SampleContextFrameHash { - uint64_t operator()(const SampleContextFrameVector &S) const { - return hash_combine_range(S.begin(), S.end()); - } -}; - -// Sample context for FunctionSamples. It consists of the calling context, -// the function name and context state. Internally sample context is represented -// using ArrayRef, which is also the input for constructing a `SampleContext`. -// It can accept and represent both full context string as well as context-less -// function name. -// For a CS profile, a full context vector can look like: -// `main:3 _Z5funcAi:1 _Z8funcLeafi` -// For a base CS profile without calling context, the context vector should only -// contain the leaf frame name. -// For a non-CS profile, the context vector should be empty. -class SampleContext { -public: - SampleContext() : State(UnknownContext), Attributes(ContextNone) {} - - SampleContext(StringRef Name) - : Name(Name), State(UnknownContext), Attributes(ContextNone) {} - - SampleContext(SampleContextFrames Context, - ContextStateMask CState = RawContext) - : Attributes(ContextNone) { - assert(!Context.empty() && "Context is empty"); - setContext(Context, CState); - } - - // Give a context string, decode and populate internal states like - // Function name, Calling context and context state. Example of input - // `ContextStr`: `[main:3 @ _Z5funcAi:1 @ _Z8funcLeafi]` - SampleContext(StringRef ContextStr, - std::list &CSNameTable, - ContextStateMask CState = RawContext) - : Attributes(ContextNone) { - assert(!ContextStr.empty()); - // Note that `[]` wrapped input indicates a full context string, otherwise - // it's treated as context-less function name only. - bool HasContext = ContextStr.startswith("["); - if (!HasContext) { - State = UnknownContext; - Name = ContextStr; - } else { - CSNameTable.emplace_back(); - SampleContextFrameVector &Context = CSNameTable.back(); - createCtxVectorFromStr(ContextStr, Context); - setContext(Context, CState); - } - } - - /// Create a context vector from a given context string and save it in - /// `Context`. - static void createCtxVectorFromStr(StringRef ContextStr, - SampleContextFrameVector &Context) { - // Remove encapsulating '[' and ']' if any - ContextStr = ContextStr.substr(1, ContextStr.size() - 2); - StringRef ContextRemain = ContextStr; - StringRef ChildContext; - StringRef CalleeName; - while (!ContextRemain.empty()) { - auto ContextSplit = ContextRemain.split(" @ "); - ChildContext = ContextSplit.first; - ContextRemain = ContextSplit.second; - LineLocation CallSiteLoc(0, 0); - decodeContextString(ChildContext, CalleeName, CallSiteLoc); - Context.emplace_back(CalleeName, CallSiteLoc); - } - } - - // Promote context by removing top frames with the length of - // `ContextFramesToRemove`. Note that with array representation of context, - // the promotion is effectively a slice operation with first - // `ContextFramesToRemove` elements removed from left. - void promoteOnPath(uint32_t ContextFramesToRemove) { - assert(ContextFramesToRemove <= FullContext.size() && - "Cannot remove more than the whole context"); - FullContext = FullContext.drop_front(ContextFramesToRemove); - } - - // Decode context string for a frame to get function name and location. - // `ContextStr` is in the form of `FuncName:StartLine.Discriminator`. - static void decodeContextString(StringRef ContextStr, StringRef &FName, - LineLocation &LineLoc) { - // Get function name - auto EntrySplit = ContextStr.split(':'); - FName = EntrySplit.first; - - LineLoc = {0, 0}; - if (!EntrySplit.second.empty()) { - // Get line offset, use signed int for getAsInteger so string will - // be parsed as signed. - int LineOffset = 0; - auto LocSplit = EntrySplit.second.split('.'); - LocSplit.first.getAsInteger(10, LineOffset); - LineLoc.LineOffset = LineOffset; - - // Get discriminator - if (!LocSplit.second.empty()) - LocSplit.second.getAsInteger(10, LineLoc.Discriminator); - } - } - - operator SampleContextFrames() const { return FullContext; } - bool hasAttribute(ContextAttributeMask A) { return Attributes & (uint32_t)A; } - void setAttribute(ContextAttributeMask A) { Attributes |= (uint32_t)A; } - uint32_t getAllAttributes() { return Attributes; } - void setAllAttributes(uint32_t A) { Attributes = A; } - bool hasState(ContextStateMask S) { return State & (uint32_t)S; } - void setState(ContextStateMask S) { State |= (uint32_t)S; } - void clearState(ContextStateMask S) { State &= (uint32_t)~S; } - bool hasContext() const { return State != UnknownContext; } - bool isBaseContext() const { return FullContext.size() == 1; } - StringRef getName() const { return Name; } - SampleContextFrames getContextFrames() const { return FullContext; } - - static std::string getContextString(SampleContextFrames Context, - bool IncludeLeafLineLocation = false) { - std::ostringstream OContextStr; - for (uint32_t I = 0; I < Context.size(); I++) { - if (OContextStr.str().size()) { - OContextStr << " @ "; - } - OContextStr << Context[I].toString(I != Context.size() - 1 || - IncludeLeafLineLocation); - } - return OContextStr.str(); - } - - std::string toString() const { - if (!hasContext()) - return Name.str(); - return getContextString(FullContext, false); - } - - uint64_t getHashCode() const { - return hasContext() ? hash_value(getContextFrames()) - : hash_value(getName()); - } - - /// Set the name of the function and clear the current context. - void setName(StringRef FunctionName) { - Name = FunctionName; - FullContext = SampleContextFrames(); - State = UnknownContext; - } - - void setContext(SampleContextFrames Context, - ContextStateMask CState = RawContext) { - assert(CState != UnknownContext); - FullContext = Context; - Name = Context.back().FuncName; - State = CState; - } - - bool operator==(const SampleContext &That) const { - return State == That.State && Name == That.Name && - FullContext == That.FullContext; - } - - bool operator!=(const SampleContext &That) const { return !(*this == That); } - - bool operator<(const SampleContext &That) const { - if (State != That.State) - return State < That.State; - - if (!hasContext()) { - return (Name.compare(That.Name)) == -1; - } - - uint64_t I = 0; - while (I < std::min(FullContext.size(), That.FullContext.size())) { - auto &Context1 = FullContext[I]; - auto &Context2 = That.FullContext[I]; - auto V = Context1.FuncName.compare(Context2.FuncName); - if (V) - return V == -1; - if (Context1.Location != Context2.Location) - return Context1.Location < Context2.Location; - I++; - } - - return FullContext.size() < That.FullContext.size(); - } - - struct Hash { - uint64_t operator()(const SampleContext &Context) const { - return Context.getHashCode(); - } - }; - - bool IsPrefixOf(const SampleContext &That) const { - auto ThisContext = FullContext; - auto ThatContext = That.FullContext; - if (ThatContext.size() < ThisContext.size()) - return false; - ThatContext = ThatContext.take_front(ThisContext.size()); - // Compare Leaf frame first - if (ThisContext.back().FuncName != ThatContext.back().FuncName) - return false; - // Compare leading context - return ThisContext.drop_back() == ThatContext.drop_back(); - } - -private: - /// Mangled name of the function. - StringRef Name; - // Full context including calling context and leaf function name - SampleContextFrames FullContext; - // State of the associated sample profile - uint32_t State; - // Attribute of the associated sample profile - uint32_t Attributes; -}; - -static inline hash_code hash_value(const SampleContext &arg) { - return arg.hasContext() ? hash_value(arg.getContextFrames()) - : hash_value(arg.getName()); -} - -class FunctionSamples; -class SampleProfileReaderItaniumRemapper; - -using BodySampleMap = std::map; -// NOTE: Using a StringMap here makes parsed profiles consume around 17% more -// memory, which is *very* significant for large profiles. -using FunctionSamplesMap = std::map>; -using CallsiteSampleMap = std::map; - -/// Representation of the samples collected for a function. -/// -/// This data structure contains all the collected samples for the body -/// of a function. Each sample corresponds to a LineLocation instance -/// within the body of the function. -class FunctionSamples { -public: - FunctionSamples() = default; - - void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; - void dump() const; - - sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { - bool Overflowed; - TotalSamples = - SaturatingMultiplyAdd(Num, Weight, TotalSamples, &Overflowed); - return Overflowed ? sampleprof_error::counter_overflow - : sampleprof_error::success; - } - - void setTotalSamples(uint64_t Num) { TotalSamples = Num; } - - sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) { - bool Overflowed; - TotalHeadSamples = - SaturatingMultiplyAdd(Num, Weight, TotalHeadSamples, &Overflowed); - return Overflowed ? sampleprof_error::counter_overflow - : sampleprof_error::success; - } - - sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, - uint64_t Num, uint64_t Weight = 1) { - return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples( - Num, Weight); - } - - sampleprof_error addCalledTargetSamples(uint32_t LineOffset, - uint32_t Discriminator, - StringRef FName, uint64_t Num, - uint64_t Weight = 1) { - return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget( - FName, Num, Weight); - } - - sampleprof_error addBodySamplesForProbe(uint32_t Index, uint64_t Num, - uint64_t Weight = 1) { - SampleRecord S; - S.addSamples(Num, Weight); - return BodySamples[LineLocation(Index, 0)].merge(S, Weight); - } - - // Accumulate all body samples to set total samples. - void updateTotalSamples() { - setTotalSamples(0); - for (const auto &I : BodySamples) - addTotalSamples(I.second.getSamples()); - - for (auto &I : CallsiteSamples) { - for (auto &CS : I.second) { - CS.second.updateTotalSamples(); - addTotalSamples(CS.second.getTotalSamples()); - } - } - } - - // Set current context and all callee contexts to be synthetic. - void SetContextSynthetic() { - Context.setState(SyntheticContext); - for (auto &I : CallsiteSamples) { - for (auto &CS : I.second) { - CS.second.SetContextSynthetic(); - } - } - } - - /// Return the number of samples collected at the given location. - /// Each location is specified by \p LineOffset and \p Discriminator. - /// If the location is not found in profile, return error. - ErrorOr findSamplesAt(uint32_t LineOffset, - uint32_t Discriminator) const { - const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator)); - if (ret == BodySamples.end()) - return std::error_code(); - return ret->second.getSamples(); - } - - /// Returns the call target map collected at a given location. - /// Each location is specified by \p LineOffset and \p Discriminator. - /// If the location is not found in profile, return error. - ErrorOr - findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const { - const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator)); - if (ret == BodySamples.end()) - return std::error_code(); - return ret->second.getCallTargets(); - } - - /// Returns the call target map collected at a given location specified by \p - /// CallSite. If the location is not found in profile, return error. - ErrorOr - findCallTargetMapAt(const LineLocation &CallSite) const { - const auto &Ret = BodySamples.find(CallSite); - if (Ret == BodySamples.end()) - return std::error_code(); - return Ret->second.getCallTargets(); - } - - /// Return the function samples at the given callsite location. - FunctionSamplesMap &functionSamplesAt(const LineLocation &Loc) { - return CallsiteSamples[Loc]; - } - - /// Returns the FunctionSamplesMap at the given \p Loc. - const FunctionSamplesMap * - findFunctionSamplesMapAt(const LineLocation &Loc) const { - auto iter = CallsiteSamples.find(Loc); - if (iter == CallsiteSamples.end()) - return nullptr; - return &iter->second; - } - - /// Returns a pointer to FunctionSamples at the given callsite location - /// \p Loc with callee \p CalleeName. If no callsite can be found, relax - /// the restriction to return the FunctionSamples at callsite location - /// \p Loc with the maximum total sample count. If \p Remapper is not - /// nullptr, use \p Remapper to find FunctionSamples with equivalent name - /// as \p CalleeName. - const FunctionSamples * - findFunctionSamplesAt(const LineLocation &Loc, StringRef CalleeName, - SampleProfileReaderItaniumRemapper *Remapper) const; - - bool empty() const { return TotalSamples == 0; } - - /// Return the total number of samples collected inside the function. - uint64_t getTotalSamples() const { return TotalSamples; } - - /// Return the total number of branch samples that have the function as the - /// branch target. This should be equivalent to the sample of the first - /// instruction of the symbol. But as we directly get this info for raw - /// profile without referring to potentially inaccurate debug info, this - /// gives more accurate profile data and is preferred for standalone symbols. - uint64_t getHeadSamples() const { return TotalHeadSamples; } - - /// Return the sample count of the first instruction of the function. - /// The function can be either a standalone symbol or an inlined function. - uint64_t getEntrySamples() const { - if (FunctionSamples::ProfileIsCSFlat && getHeadSamples()) { - // For CS profile, if we already have more accurate head samples - // counted by branch sample from caller, use them as entry samples. - return getHeadSamples(); - } - uint64_t Count = 0; - // Use either BodySamples or CallsiteSamples which ever has the smaller - // lineno. - if (!BodySamples.empty() && - (CallsiteSamples.empty() || - BodySamples.begin()->first < CallsiteSamples.begin()->first)) - Count = BodySamples.begin()->second.getSamples(); - else if (!CallsiteSamples.empty()) { - // An indirect callsite may be promoted to several inlined direct calls. - // We need to get the sum of them. - for (const auto &N_FS : CallsiteSamples.begin()->second) - Count += N_FS.second.getEntrySamples(); - } - // Return at least 1 if total sample is not 0. - return Count ? Count : TotalSamples > 0; - } - - /// Return all the samples collected in the body of the function. - const BodySampleMap &getBodySamples() const { return BodySamples; } - - /// Return all the callsite samples collected in the body of the function. - const CallsiteSampleMap &getCallsiteSamples() const { - return CallsiteSamples; - } - - /// Return the maximum of sample counts in a function body including functions - /// inlined in it. - uint64_t getMaxCountInside() const { - uint64_t MaxCount = 0; - for (const auto &L : getBodySamples()) - MaxCount = std::max(MaxCount, L.second.getSamples()); - for (const auto &C : getCallsiteSamples()) - for (const FunctionSamplesMap::value_type &F : C.second) - MaxCount = std::max(MaxCount, F.second.getMaxCountInside()); - return MaxCount; - } - - /// Merge the samples in \p Other into this one. - /// Optionally scale samples by \p Weight. - sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) { - sampleprof_error Result = sampleprof_error::success; - if (!GUIDToFuncNameMap) - GUIDToFuncNameMap = Other.GUIDToFuncNameMap; - if (Context.getName().empty()) - Context = Other.getContext(); - if (FunctionHash == 0) { - // Set the function hash code for the target profile. - FunctionHash = Other.getFunctionHash(); - } else if (FunctionHash != Other.getFunctionHash()) { - // The two profiles coming with different valid hash codes indicates - // either: - // 1. They are same-named static functions from different compilation - // units (without using -unique-internal-linkage-names), or - // 2. They are really the same function but from different compilations. - // Let's bail out in either case for now, which means one profile is - // dropped. - return sampleprof_error::hash_mismatch; - } - - MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight)); - MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight)); - for (const auto &I : Other.getBodySamples()) { - const LineLocation &Loc = I.first; - const SampleRecord &Rec = I.second; - MergeResult(Result, BodySamples[Loc].merge(Rec, Weight)); - } - for (const auto &I : Other.getCallsiteSamples()) { - const LineLocation &Loc = I.first; - FunctionSamplesMap &FSMap = functionSamplesAt(Loc); - for (const auto &Rec : I.second) - MergeResult(Result, FSMap[Rec.first].merge(Rec.second, Weight)); - } - return Result; - } - - /// Recursively traverses all children, if the total sample count of the - /// corresponding function is no less than \p Threshold, add its corresponding - /// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID - /// to \p S. - void findInlinedFunctions(DenseSet &S, - const StringMap &SymbolMap, - uint64_t Threshold) const { - if (TotalSamples <= Threshold) - return; - auto isDeclaration = [](const Function *F) { - return !F || F->isDeclaration(); - }; - if (isDeclaration(SymbolMap.lookup(getFuncName()))) { - // Add to the import list only when it's defined out of module. - S.insert(getGUID(getName())); - } - // Import hot CallTargets, which may not be available in IR because full - // profile annotation cannot be done until backend compilation in ThinLTO. - for (const auto &BS : BodySamples) - for (const auto &TS : BS.second.getCallTargets()) - if (TS.getValue() > Threshold) { - const Function *Callee = SymbolMap.lookup(getFuncName(TS.getKey())); - if (isDeclaration(Callee)) - S.insert(getGUID(TS.getKey())); - } - for (const auto &CS : CallsiteSamples) - for (const auto &NameFS : CS.second) - NameFS.second.findInlinedFunctions(S, SymbolMap, Threshold); - } - - /// Set the name of the function. - void setName(StringRef FunctionName) { Context.setName(FunctionName); } - - /// Return the function name. - StringRef getName() const { return Context.getName(); } - - /// Return the original function name. - StringRef getFuncName() const { return getFuncName(getName()); } - - void setFunctionHash(uint64_t Hash) { FunctionHash = Hash; } - - uint64_t getFunctionHash() const { return FunctionHash; } - - /// Return the canonical name for a function, taking into account - /// suffix elision policy attributes. - static StringRef getCanonicalFnName(const Function &F) { - auto AttrName = "sample-profile-suffix-elision-policy"; - auto Attr = F.getFnAttribute(AttrName).getValueAsString(); - return getCanonicalFnName(F.getName(), Attr); - } - - /// Name suffixes which canonicalization should handle to avoid - /// profile mismatch. - static constexpr const char *LLVMSuffix = ".llvm."; - static constexpr const char *PartSuffix = ".part."; - static constexpr const char *UniqSuffix = ".__uniq."; - - static StringRef getCanonicalFnName(StringRef FnName, - StringRef Attr = "selected") { - // Note the sequence of the suffixes in the knownSuffixes array matters. - // If suffix "A" is appended after the suffix "B", "A" should be in front - // of "B" in knownSuffixes. - const char *knownSuffixes[] = {LLVMSuffix, PartSuffix, UniqSuffix}; - if (Attr == "" || Attr == "all") { - return FnName.split('.').first; - } else if (Attr == "selected") { - StringRef Cand(FnName); - for (const auto &Suf : knownSuffixes) { - StringRef Suffix(Suf); - // If the profile contains ".__uniq." suffix, don't strip the - // suffix for names in the IR. - if (Suffix == UniqSuffix && FunctionSamples::HasUniqSuffix) - continue; - auto It = Cand.rfind(Suffix); - if (It == StringRef::npos) - continue; - auto Dit = Cand.rfind('.'); - if (Dit == It + Suffix.size() - 1) - Cand = Cand.substr(0, It); - } - return Cand; - } else if (Attr == "none") { - return FnName; - } else { - assert(false && "internal error: unknown suffix elision policy"); - } - return FnName; - } - - /// Translate \p Name into its original name. - /// When profile doesn't use MD5, \p Name needs no translation. - /// When profile uses MD5, \p Name in current FunctionSamples - /// is actually GUID of the original function name. getFuncName will - /// translate \p Name in current FunctionSamples into its original name - /// by looking up in the function map GUIDToFuncNameMap. - /// If the original name doesn't exist in the map, return empty StringRef. - StringRef getFuncName(StringRef Name) const { - if (!UseMD5) - return Name; - - assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first"); - return GUIDToFuncNameMap->lookup(std::stoull(Name.data())); - } - - /// Returns the line offset to the start line of the subprogram. - /// We assume that a single function will not exceed 65535 LOC. - static unsigned getOffset(const DILocation *DIL); - - /// Returns a unique call site identifier for a given debug location of a call - /// instruction. This is wrapper of two scenarios, the probe-based profile and - /// regular profile, to hide implementation details from the sample loader and - /// the context tracker. - static LineLocation getCallSiteIdentifier(const DILocation *DIL, - bool ProfileIsFS = false); - - /// Returns a unique hash code for a combination of a callsite location and - /// the callee function name. - static uint64_t getCallSiteHash(StringRef CalleeName, - const LineLocation &Callsite); - - /// Get the FunctionSamples of the inline instance where DIL originates - /// from. - /// - /// The FunctionSamples of the instruction (Machine or IR) associated to - /// \p DIL is the inlined instance in which that instruction is coming from. - /// We traverse the inline stack of that instruction, and match it with the - /// tree nodes in the profile. - /// - /// \returns the FunctionSamples pointer to the inlined instance. - /// If \p Remapper is not nullptr, it will be used to find matching - /// FunctionSamples with not exactly the same but equivalent name. - const FunctionSamples *findFunctionSamples( - const DILocation *DIL, - SampleProfileReaderItaniumRemapper *Remapper = nullptr) const; - - static bool ProfileIsProbeBased; - - static bool ProfileIsCSFlat; - - static bool ProfileIsCSNested; - - SampleContext &getContext() const { return Context; } - - void setContext(const SampleContext &FContext) { Context = FContext; } - - static SampleProfileFormat Format; - - /// Whether the profile uses MD5 to represent string. - static bool UseMD5; - - /// Whether the profile contains any ".__uniq." suffix in a name. - static bool HasUniqSuffix; - - /// If this profile uses flow sensitive discriminators. - static bool ProfileIsFS; - - /// GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for - /// all the function symbols defined or declared in current module. - DenseMap *GUIDToFuncNameMap = nullptr; - - // Assume the input \p Name is a name coming from FunctionSamples itself. - // If UseMD5 is true, the name is already a GUID and we - // don't want to return the GUID of GUID. - static uint64_t getGUID(StringRef Name) { - return UseMD5 ? std::stoull(Name.data()) : Function::getGUID(Name); - } - - // Find all the names in the current FunctionSamples including names in - // all the inline instances and names of call targets. - void findAllNames(DenseSet &NameSet) const; - -private: - /// CFG hash value for the function. - uint64_t FunctionHash = 0; - - /// Calling context for function profile - mutable SampleContext Context; - - /// Total number of samples collected inside this function. - /// - /// Samples are cumulative, they include all the samples collected - /// inside this function and all its inlined callees. - uint64_t TotalSamples = 0; - - /// Total number of samples collected at the head of the function. - /// This is an approximation of the number of calls made to this function - /// at runtime. - uint64_t TotalHeadSamples = 0; - - /// Map instruction locations to collected samples. - /// - /// Each entry in this map contains the number of samples - /// collected at the corresponding line offset. All line locations - /// are an offset from the start of the function. - BodySampleMap BodySamples; - - /// Map call sites to collected samples for the called function. - /// - /// Each entry in this map corresponds to all the samples - /// collected for the inlined function call at the given - /// location. For example, given: - /// - /// void foo() { - /// 1 bar(); - /// ... - /// 8 baz(); - /// } - /// - /// If the bar() and baz() calls were inlined inside foo(), this - /// map will contain two entries. One for all the samples collected - /// in the call to bar() at line offset 1, the other for all the samples - /// collected in the call to baz() at line offset 8. - CallsiteSampleMap CallsiteSamples; -}; - -raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS); - -using SampleProfileMap = - std::unordered_map; - -using NameFunctionSamples = std::pair; - -void sortFuncProfiles(const SampleProfileMap &ProfileMap, - std::vector &SortedProfiles); - -/// Sort a LocationT->SampleT map by LocationT. -/// -/// It produces a sorted list of records by ascending -/// order of LocationT. -template class SampleSorter { -public: - using SamplesWithLoc = std::pair; - using SamplesWithLocList = SmallVector; - - SampleSorter(const std::map &Samples) { - for (const auto &I : Samples) - V.push_back(&I); - llvm::stable_sort(V, [](const SamplesWithLoc *A, const SamplesWithLoc *B) { - return A->first < B->first; - }); - } - - const SamplesWithLocList &get() const { return V; } - -private: - SamplesWithLocList V; -}; - -/// SampleContextTrimmer implements helper functions to trim, merge cold -/// context profiles. It also supports context profile canonicalization to make -/// sure ProfileMap's key is consistent with FunctionSample's name/context. -class SampleContextTrimmer { -public: - SampleContextTrimmer(SampleProfileMap &Profiles) : ProfileMap(Profiles){}; - // Trim and merge cold context profile when requested. TrimBaseProfileOnly - // should only be effective when TrimColdContext is true. On top of - // TrimColdContext, TrimBaseProfileOnly can be used to specify to trim all - // cold profiles or only cold base profiles. Trimming base profiles only is - // mainly to honor the preinliner decision. Note that when MergeColdContext is - // true, preinliner decision is not honored anyway so TrimBaseProfileOnly will - // be ignored. - void trimAndMergeColdContextProfiles(uint64_t ColdCountThreshold, - bool TrimColdContext, - bool MergeColdContext, - uint32_t ColdContextFrameLength, - bool TrimBaseProfileOnly); - // Canonicalize context profile name and attributes. - void canonicalizeContextProfiles(); - -private: - SampleProfileMap &ProfileMap; -}; - -// CSProfileConverter converts a full context-sensitive flat sample profile into -// a nested context-sensitive sample profile. -class CSProfileConverter { -public: - CSProfileConverter(SampleProfileMap &Profiles); - void convertProfiles(); - struct FrameNode { - FrameNode(StringRef FName = StringRef(), - FunctionSamples *FSamples = nullptr, - LineLocation CallLoc = {0, 0}) - : FuncName(FName), FuncSamples(FSamples), CallSiteLoc(CallLoc){}; - - // Map line+discriminator location to child frame - std::map AllChildFrames; - // Function name for current frame - StringRef FuncName; - // Function Samples for current frame - FunctionSamples *FuncSamples; - // Callsite location in parent context - LineLocation CallSiteLoc; - - FrameNode *getOrCreateChildFrame(const LineLocation &CallSite, - StringRef CalleeName); - }; - -private: - // Nest all children profiles into the profile of Node. - void convertProfiles(FrameNode &Node); - FrameNode *getOrCreateContextPath(const SampleContext &Context); - - SampleProfileMap &ProfileMap; - FrameNode RootFrame; -}; - -/// ProfileSymbolList records the list of function symbols shown up -/// in the binary used to generate the profile. It is useful to -/// to discriminate a function being so cold as not to shown up -/// in the profile and a function newly added. -class ProfileSymbolList { -public: - /// copy indicates whether we need to copy the underlying memory - /// for the input Name. - void add(StringRef Name, bool copy = false) { - if (!copy) { - Syms.insert(Name); - return; - } - Syms.insert(Name.copy(Allocator)); - } - - bool contains(StringRef Name) { return Syms.count(Name); } - - void merge(const ProfileSymbolList &List) { - for (auto Sym : List.Syms) - add(Sym, true); - } - - unsigned size() { return Syms.size(); } - - void setToCompress(bool TC) { ToCompress = TC; } - bool toCompress() { return ToCompress; } - - std::error_code read(const uint8_t *Data, uint64_t ListSize); - std::error_code write(raw_ostream &OS); - void dump(raw_ostream &OS = dbgs()) const; - -private: - // Determine whether or not to compress the symbol list when - // writing it into profile. The variable is unused when the symbol - // list is read from an existing profile. - bool ToCompress = false; - DenseSet Syms; - BumpPtrAllocator Allocator; -}; - -} // end namespace sampleprof - -using namespace sampleprof; -// Provide DenseMapInfo for SampleContext. -template <> struct DenseMapInfo { - static inline SampleContext getEmptyKey() { return SampleContext(); } - - static inline SampleContext getTombstoneKey() { return SampleContext("@"); } - - static unsigned getHashValue(const SampleContext &Val) { - return Val.getHashCode(); - } - - static bool isEqual(const SampleContext &LHS, const SampleContext &RHS) { - return LHS == RHS; - } -}; -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_SAMPLEPROF_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfReader.h b/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfReader.h deleted file mode 100644 index 959754bad4..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfReader.h +++ /dev/null @@ -1,903 +0,0 @@ -//===- SampleProfReader.h - Read LLVM sample profile data -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains definitions needed for reading sample profiles. -// -// NOTE: If you are making changes to this file format, please remember -// to document them in the Clang documentation at -// tools/clang/docs/UsersManual.rst. -// -// Text format -// ----------- -// -// Sample profiles are written as ASCII text. The file is divided into -// sections, which correspond to each of the functions executed at runtime. -// Each section has the following format -// -// function1:total_samples:total_head_samples -// offset1[.discriminator]: number_of_samples [fn1:num fn2:num ... ] -// offset2[.discriminator]: number_of_samples [fn3:num fn4:num ... ] -// ... -// offsetN[.discriminator]: number_of_samples [fn5:num fn6:num ... ] -// offsetA[.discriminator]: fnA:num_of_total_samples -// offsetA1[.discriminator]: number_of_samples [fn7:num fn8:num ... ] -// ... -// !CFGChecksum: num -// !Attribute: flags -// -// This is a nested tree in which the indentation represents the nesting level -// of the inline stack. There are no blank lines in the file. And the spacing -// within a single line is fixed. Additional spaces will result in an error -// while reading the file. -// -// Any line starting with the '#' character is completely ignored. -// -// Inlined calls are represented with indentation. The Inline stack is a -// stack of source locations in which the top of the stack represents the -// leaf function, and the bottom of the stack represents the actual -// symbol to which the instruction belongs. -// -// Function names must be mangled in order for the profile loader to -// match them in the current translation unit. The two numbers in the -// function header specify how many total samples were accumulated in the -// function (first number), and the total number of samples accumulated -// in the prologue of the function (second number). This head sample -// count provides an indicator of how frequently the function is invoked. -// -// There are three types of lines in the function body. -// -// * Sampled line represents the profile information of a source location. -// * Callsite line represents the profile information of a callsite. -// * Metadata line represents extra metadata of the function. -// -// Each sampled line may contain several items. Some are optional (marked -// below): -// -// a. Source line offset. This number represents the line number -// in the function where the sample was collected. The line number is -// always relative to the line where symbol of the function is -// defined. So, if the function has its header at line 280, the offset -// 13 is at line 293 in the file. -// -// Note that this offset should never be a negative number. This could -// happen in cases like macros. The debug machinery will register the -// line number at the point of macro expansion. So, if the macro was -// expanded in a line before the start of the function, the profile -// converter should emit a 0 as the offset (this means that the optimizers -// will not be able to associate a meaningful weight to the instructions -// in the macro). -// -// b. [OPTIONAL] Discriminator. This is used if the sampled program -// was compiled with DWARF discriminator support -// (http://wiki.dwarfstd.org/index.php?title=Path_Discriminators). -// DWARF discriminators are unsigned integer values that allow the -// compiler to distinguish between multiple execution paths on the -// same source line location. -// -// For example, consider the line of code ``if (cond) foo(); else bar();``. -// If the predicate ``cond`` is true 80% of the time, then the edge -// into function ``foo`` should be considered to be taken most of the -// time. But both calls to ``foo`` and ``bar`` are at the same source -// line, so a sample count at that line is not sufficient. The -// compiler needs to know which part of that line is taken more -// frequently. -// -// This is what discriminators provide. In this case, the calls to -// ``foo`` and ``bar`` will be at the same line, but will have -// different discriminator values. This allows the compiler to correctly -// set edge weights into ``foo`` and ``bar``. -// -// c. Number of samples. This is an integer quantity representing the -// number of samples collected by the profiler at this source -// location. -// -// d. [OPTIONAL] Potential call targets and samples. If present, this -// line contains a call instruction. This models both direct and -// number of samples. For example, -// -// 130: 7 foo:3 bar:2 baz:7 -// -// The above means that at relative line offset 130 there is a call -// instruction that calls one of ``foo()``, ``bar()`` and ``baz()``, -// with ``baz()`` being the relatively more frequently called target. -// -// Each callsite line may contain several items. Some are optional. -// -// a. Source line offset. This number represents the line number of the -// callsite that is inlined in the profiled binary. -// -// b. [OPTIONAL] Discriminator. Same as the discriminator for sampled line. -// -// c. Number of samples. This is an integer quantity representing the -// total number of samples collected for the inlined instance at this -// callsite -// -// Metadata line can occur in lines with one indent only, containing extra -// information for the top-level function. Furthermore, metadata can only -// occur after all the body samples and callsite samples. -// Each metadata line may contain a particular type of metadata, marked by -// the starting characters annotated with !. We process each metadata line -// independently, hence each metadata line has to form an independent piece -// of information that does not require cross-line reference. -// We support the following types of metadata: -// -// a. CFG Checksum (a.k.a. function hash): -// !CFGChecksum: 12345 -// b. CFG Checksum (see ContextAttributeMask): -// !Attribute: 1 -// -// -// Binary format -// ------------- -// -// This is a more compact encoding. Numbers are encoded as ULEB128 values -// and all strings are encoded in a name table. The file is organized in -// the following sections: -// -// MAGIC (uint64_t) -// File identifier computed by function SPMagic() (0x5350524f463432ff) -// -// VERSION (uint32_t) -// File format version number computed by SPVersion() -// -// SUMMARY -// TOTAL_COUNT (uint64_t) -// Total number of samples in the profile. -// MAX_COUNT (uint64_t) -// Maximum value of samples on a line. -// MAX_FUNCTION_COUNT (uint64_t) -// Maximum number of samples at function entry (head samples). -// NUM_COUNTS (uint64_t) -// Number of lines with samples. -// NUM_FUNCTIONS (uint64_t) -// Number of functions with samples. -// NUM_DETAILED_SUMMARY_ENTRIES (size_t) -// Number of entries in detailed summary -// DETAILED_SUMMARY -// A list of detailed summary entry. Each entry consists of -// CUTOFF (uint32_t) -// Required percentile of total sample count expressed as a fraction -// multiplied by 1000000. -// MIN_COUNT (uint64_t) -// The minimum number of samples required to reach the target -// CUTOFF. -// NUM_COUNTS (uint64_t) -// Number of samples to get to the desired percentile. -// -// NAME TABLE -// SIZE (uint32_t) -// Number of entries in the name table. -// NAMES -// A NUL-separated list of SIZE strings. -// -// FUNCTION BODY (one for each uninlined function body present in the profile) -// HEAD_SAMPLES (uint64_t) [only for top-level functions] -// Total number of samples collected at the head (prologue) of the -// function. -// NOTE: This field should only be present for top-level functions -// (i.e., not inlined into any caller). Inlined function calls -// have no prologue, so they don't need this. -// NAME_IDX (uint32_t) -// Index into the name table indicating the function name. -// SAMPLES (uint64_t) -// Total number of samples collected in this function. -// NRECS (uint32_t) -// Total number of sampling records this function's profile. -// BODY RECORDS -// A list of NRECS entries. Each entry contains: -// OFFSET (uint32_t) -// Line offset from the start of the function. -// DISCRIMINATOR (uint32_t) -// Discriminator value (see description of discriminators -// in the text format documentation above). -// SAMPLES (uint64_t) -// Number of samples collected at this location. -// NUM_CALLS (uint32_t) -// Number of non-inlined function calls made at this location. In the -// case of direct calls, this number will always be 1. For indirect -// calls (virtual functions and function pointers) this will -// represent all the actual functions called at runtime. -// CALL_TARGETS -// A list of NUM_CALLS entries for each called function: -// NAME_IDX (uint32_t) -// Index into the name table with the callee name. -// SAMPLES (uint64_t) -// Number of samples collected at the call site. -// NUM_INLINED_FUNCTIONS (uint32_t) -// Number of callees inlined into this function. -// INLINED FUNCTION RECORDS -// A list of NUM_INLINED_FUNCTIONS entries describing each of the inlined -// callees. -// OFFSET (uint32_t) -// Line offset from the start of the function. -// DISCRIMINATOR (uint32_t) -// Discriminator value (see description of discriminators -// in the text format documentation above). -// FUNCTION BODY -// A FUNCTION BODY entry describing the inlined function. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H -#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/ProfileData/GCOV.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Discriminator.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SymbolRemappingReader.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class raw_ostream; -class Twine; - -namespace sampleprof { - -class SampleProfileReader; - -/// SampleProfileReaderItaniumRemapper remaps the profile data from a -/// sample profile data reader, by applying a provided set of equivalences -/// between components of the symbol names in the profile. -class SampleProfileReaderItaniumRemapper { -public: - SampleProfileReaderItaniumRemapper(std::unique_ptr B, - std::unique_ptr SRR, - SampleProfileReader &R) - : Buffer(std::move(B)), Remappings(std::move(SRR)), Reader(R) { - assert(Remappings && "Remappings cannot be nullptr"); - } - - /// Create a remapper from the given remapping file. The remapper will - /// be used for profile read in by Reader. - static ErrorOr> - create(const std::string Filename, SampleProfileReader &Reader, - LLVMContext &C); - - /// Create a remapper from the given Buffer. The remapper will - /// be used for profile read in by Reader. - static ErrorOr> - create(std::unique_ptr &B, SampleProfileReader &Reader, - LLVMContext &C); - - /// Apply remappings to the profile read by Reader. - void applyRemapping(LLVMContext &Ctx); - - bool hasApplied() { return RemappingApplied; } - - /// Insert function name into remapper. - void insert(StringRef FunctionName) { Remappings->insert(FunctionName); } - - /// Query whether there is equivalent in the remapper which has been - /// inserted. - bool exist(StringRef FunctionName) { - return Remappings->lookup(FunctionName); - } - - /// Return the equivalent name in the profile for \p FunctionName if - /// it exists. - Optional lookUpNameInProfile(StringRef FunctionName); - -private: - // The buffer holding the content read from remapping file. - std::unique_ptr Buffer; - std::unique_ptr Remappings; - // Map remapping key to the name in the profile. By looking up the - // key in the remapper, a given new name can be mapped to the - // canonical name using the NameMap. - DenseMap NameMap; - // The Reader the remapper is servicing. - SampleProfileReader &Reader; - // Indicate whether remapping has been applied to the profile read - // by Reader -- by calling applyRemapping. - bool RemappingApplied = false; -}; - -/// Sample-based profile reader. -/// -/// Each profile contains sample counts for all the functions -/// executed. Inside each function, statements are annotated with the -/// collected samples on all the instructions associated with that -/// statement. -/// -/// For this to produce meaningful data, the program needs to be -/// compiled with some debug information (at minimum, line numbers: -/// -gline-tables-only). Otherwise, it will be impossible to match IR -/// instructions to the line numbers collected by the profiler. -/// -/// From the profile file, we are interested in collecting the -/// following information: -/// -/// * A list of functions included in the profile (mangled names). -/// -/// * For each function F: -/// 1. The total number of samples collected in F. -/// -/// 2. The samples collected at each line in F. To provide some -/// protection against source code shuffling, line numbers should -/// be relative to the start of the function. -/// -/// The reader supports two file formats: text and binary. The text format -/// is useful for debugging and testing, while the binary format is more -/// compact and I/O efficient. They can both be used interchangeably. -class SampleProfileReader { -public: - SampleProfileReader(std::unique_ptr B, LLVMContext &C, - SampleProfileFormat Format = SPF_None) - : Profiles(0), Ctx(C), Buffer(std::move(B)), Format(Format) {} - - virtual ~SampleProfileReader() = default; - - /// Read and validate the file header. - virtual std::error_code readHeader() = 0; - - /// Set the bits for FS discriminators. Parameter Pass specify the sequence - /// number, Pass == i is for the i-th round of adding FS discriminators. - /// Pass == 0 is for using base discriminators. - void setDiscriminatorMaskedBitFrom(FSDiscriminatorPass P) { - MaskedBitFrom = getFSPassBitEnd(P); - } - - /// Get the bitmask the discriminators: For FS profiles, return the bit - /// mask for this pass. For non FS profiles, return (unsigned) -1. - uint32_t getDiscriminatorMask() const { - if (!ProfileIsFS) - return 0xFFFFFFFF; - assert((MaskedBitFrom != 0) && "MaskedBitFrom is not set properly"); - return getN1Bits(MaskedBitFrom); - } - - /// The interface to read sample profiles from the associated file. - std::error_code read() { - if (std::error_code EC = readImpl()) - return EC; - if (Remapper) - Remapper->applyRemapping(Ctx); - FunctionSamples::UseMD5 = useMD5(); - return sampleprof_error::success; - } - - /// The implementation to read sample profiles from the associated file. - virtual std::error_code readImpl() = 0; - - /// Print the profile for \p FContext on stream \p OS. - void dumpFunctionProfile(SampleContext FContext, raw_ostream &OS = dbgs()); - - /// Collect functions with definitions in Module M. For reader which - /// support loading function profiles on demand, return true when the - /// reader has been given a module. Always return false for reader - /// which doesn't support loading function profiles on demand. - virtual bool collectFuncsFromModule() { return false; } - - /// Print all the profiles on stream \p OS. - void dump(raw_ostream &OS = dbgs()); - - /// Return the samples collected for function \p F. - FunctionSamples *getSamplesFor(const Function &F) { - // The function name may have been updated by adding suffix. Call - // a helper to (optionally) strip off suffixes so that we can - // match against the original function name in the profile. - StringRef CanonName = FunctionSamples::getCanonicalFnName(F); - return getSamplesFor(CanonName); - } - - /// Return the samples collected for function \p F, create empty - /// FunctionSamples if it doesn't exist. - FunctionSamples *getOrCreateSamplesFor(const Function &F) { - std::string FGUID; - StringRef CanonName = FunctionSamples::getCanonicalFnName(F); - CanonName = getRepInFormat(CanonName, useMD5(), FGUID); - auto It = Profiles.find(CanonName); - if (It != Profiles.end()) - return &It->second; - if (!FGUID.empty()) { - assert(useMD5() && "New name should only be generated for md5 profile"); - CanonName = *MD5NameBuffer.insert(FGUID).first; - } - return &Profiles[CanonName]; - } - - /// Return the samples collected for function \p F. - virtual FunctionSamples *getSamplesFor(StringRef Fname) { - std::string FGUID; - Fname = getRepInFormat(Fname, useMD5(), FGUID); - auto It = Profiles.find(Fname); - if (It != Profiles.end()) - return &It->second; - - if (Remapper) { - if (auto NameInProfile = Remapper->lookUpNameInProfile(Fname)) { - auto It = Profiles.find(*NameInProfile); - if (It != Profiles.end()) - return &It->second; - } - } - return nullptr; - } - - /// Return all the profiles. - SampleProfileMap &getProfiles() { return Profiles; } - - /// Report a parse error message. - void reportError(int64_t LineNumber, const Twine &Msg) const { - Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(), - LineNumber, Msg)); - } - - /// Create a sample profile reader appropriate to the file format. - /// Create a remapper underlying if RemapFilename is not empty. - /// Parameter P specifies the FSDiscriminatorPass. - static ErrorOr> - create(const std::string Filename, LLVMContext &C, - FSDiscriminatorPass P = FSDiscriminatorPass::Base, - const std::string RemapFilename = ""); - - /// Create a sample profile reader from the supplied memory buffer. - /// Create a remapper underlying if RemapFilename is not empty. - /// Parameter P specifies the FSDiscriminatorPass. - static ErrorOr> - create(std::unique_ptr &B, LLVMContext &C, - FSDiscriminatorPass P = FSDiscriminatorPass::Base, - const std::string RemapFilename = ""); - - /// Return the profile summary. - ProfileSummary &getSummary() const { return *(Summary.get()); } - - MemoryBuffer *getBuffer() const { return Buffer.get(); } - - /// \brief Return the profile format. - SampleProfileFormat getFormat() const { return Format; } - - /// Whether input profile is based on pseudo probes. - bool profileIsProbeBased() const { return ProfileIsProbeBased; } - - /// Whether input profile is fully context-sensitive and flat. - bool profileIsCSFlat() const { return ProfileIsCSFlat; } - - /// Whether input profile is fully context-sensitive and nested. - bool profileIsCSNested() const { return ProfileIsCSNested; } - - virtual std::unique_ptr getProfileSymbolList() { - return nullptr; - }; - - /// It includes all the names that have samples either in outline instance - /// or inline instance. - virtual std::vector *getNameTable() { return nullptr; } - virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) { return false; }; - - /// Return whether names in the profile are all MD5 numbers. - virtual bool useMD5() { return false; } - - /// Don't read profile without context if the flag is set. This is only meaningful - /// for ExtBinary format. - virtual void setSkipFlatProf(bool Skip) {} - /// Return whether any name in the profile contains ".__uniq." suffix. - virtual bool hasUniqSuffix() { return false; } - - SampleProfileReaderItaniumRemapper *getRemapper() { return Remapper.get(); } - - void setModule(const Module *Mod) { M = Mod; } - -protected: - /// Map every function to its associated profile. - /// - /// The profile of every function executed at runtime is collected - /// in the structure FunctionSamples. This maps function objects - /// to their corresponding profiles. - SampleProfileMap Profiles; - - /// LLVM context used to emit diagnostics. - LLVMContext &Ctx; - - /// Memory buffer holding the profile file. - std::unique_ptr Buffer; - - /// Extra name buffer holding names created on demand. - /// This should only be needed for md5 profiles. - std::unordered_set MD5NameBuffer; - - /// Profile summary information. - std::unique_ptr Summary; - - /// Take ownership of the summary of this reader. - static std::unique_ptr - takeSummary(SampleProfileReader &Reader) { - return std::move(Reader.Summary); - } - - /// Compute summary for this profile. - void computeSummary(); - - std::unique_ptr Remapper; - - /// \brief Whether samples are collected based on pseudo probes. - bool ProfileIsProbeBased = false; - - /// Whether function profiles are context-sensitive flat profiles. - bool ProfileIsCSFlat = false; - - /// Whether function profiles are context-sensitive nested profiles. - bool ProfileIsCSNested = false; - - /// Number of context-sensitive profiles. - uint32_t CSProfileCount = 0; - - /// Whether the function profiles use FS discriminators. - bool ProfileIsFS = false; - - /// \brief The format of sample. - SampleProfileFormat Format = SPF_None; - - /// \brief The current module being compiled if SampleProfileReader - /// is used by compiler. If SampleProfileReader is used by other - /// tools which are not compiler, M is usually nullptr. - const Module *M = nullptr; - - /// Zero out the discriminator bits higher than bit MaskedBitFrom (0 based). - /// The default is to keep all the bits. - uint32_t MaskedBitFrom = 31; -}; - -class SampleProfileReaderText : public SampleProfileReader { -public: - SampleProfileReaderText(std::unique_ptr B, LLVMContext &C) - : SampleProfileReader(std::move(B), C, SPF_Text) {} - - /// Read and validate the file header. - std::error_code readHeader() override { return sampleprof_error::success; } - - /// Read sample profiles from the associated file. - std::error_code readImpl() override; - - /// Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); - -private: - /// CSNameTable is used to save full context vectors. This serves as an - /// underlying immutable buffer for all clients. - std::list CSNameTable; -}; - -class SampleProfileReaderBinary : public SampleProfileReader { -public: - SampleProfileReaderBinary(std::unique_ptr B, LLVMContext &C, - SampleProfileFormat Format = SPF_None) - : SampleProfileReader(std::move(B), C, Format) {} - - /// Read and validate the file header. - virtual std::error_code readHeader() override; - - /// Read sample profiles from the associated file. - std::error_code readImpl() override; - - /// It includes all the names that have samples either in outline instance - /// or inline instance. - virtual std::vector *getNameTable() override { return &NameTable; } - -protected: - /// Read a numeric value of type T from the profile. - /// - /// If an error occurs during decoding, a diagnostic message is emitted and - /// EC is set. - /// - /// \returns the read value. - template ErrorOr readNumber(); - - /// Read a numeric value of type T from the profile. The value is saved - /// without encoded. - template ErrorOr readUnencodedNumber(); - - /// Read a string from the profile. - /// - /// If an error occurs during decoding, a diagnostic message is emitted and - /// EC is set. - /// - /// \returns the read value. - ErrorOr readString(); - - /// Read the string index and check whether it overflows the table. - template inline ErrorOr readStringIndex(T &Table); - - /// Return true if we've reached the end of file. - bool at_eof() const { return Data >= End; } - - /// Read the next function profile instance. - std::error_code readFuncProfile(const uint8_t *Start); - - /// Read the contents of the given profile instance. - std::error_code readProfile(FunctionSamples &FProfile); - - /// Read the contents of Magic number and Version number. - std::error_code readMagicIdent(); - - /// Read profile summary. - std::error_code readSummary(); - - /// Read the whole name table. - virtual std::error_code readNameTable(); - - /// Points to the current location in the buffer. - const uint8_t *Data = nullptr; - - /// Points to the end of the buffer. - const uint8_t *End = nullptr; - - /// Function name table. - std::vector NameTable; - - /// Read a string indirectly via the name table. - virtual ErrorOr readStringFromTable(); - virtual ErrorOr readSampleContextFromTable(); - -private: - std::error_code readSummaryEntry(std::vector &Entries); - virtual std::error_code verifySPMagic(uint64_t Magic) = 0; -}; - -class SampleProfileReaderRawBinary : public SampleProfileReaderBinary { -private: - virtual std::error_code verifySPMagic(uint64_t Magic) override; - -public: - SampleProfileReaderRawBinary(std::unique_ptr B, LLVMContext &C, - SampleProfileFormat Format = SPF_Binary) - : SampleProfileReaderBinary(std::move(B), C, Format) {} - - /// \brief Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); -}; - -/// SampleProfileReaderExtBinaryBase/SampleProfileWriterExtBinaryBase defines -/// the basic structure of the extensible binary format. -/// The format is organized in sections except the magic and version number -/// at the beginning. There is a section table before all the sections, and -/// each entry in the table describes the entry type, start, size and -/// attributes. The format in each section is defined by the section itself. -/// -/// It is easy to add a new section while maintaining the backward -/// compatibility of the profile. Nothing extra needs to be done. If we want -/// to extend an existing section, like add cache misses information in -/// addition to the sample count in the profile body, we can add a new section -/// with the extension and retire the existing section, and we could choose -/// to keep the parser of the old section if we want the reader to be able -/// to read both new and old format profile. -/// -/// SampleProfileReaderExtBinary/SampleProfileWriterExtBinary define the -/// commonly used sections of a profile in extensible binary format. It is -/// possible to define other types of profile inherited from -/// SampleProfileReaderExtBinaryBase/SampleProfileWriterExtBinaryBase. -class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary { -private: - std::error_code decompressSection(const uint8_t *SecStart, - const uint64_t SecSize, - const uint8_t *&DecompressBuf, - uint64_t &DecompressBufSize); - - BumpPtrAllocator Allocator; - -protected: - std::vector SecHdrTable; - std::error_code readSecHdrTableEntry(uint32_t Idx); - std::error_code readSecHdrTable(); - - std::error_code readFuncMetadata(bool ProfileHasAttribute); - std::error_code readFuncMetadata(bool ProfileHasAttribute, - FunctionSamples *FProfile); - std::error_code readFuncOffsetTable(); - std::error_code readFuncProfiles(); - std::error_code readMD5NameTable(); - std::error_code readNameTableSec(bool IsMD5); - std::error_code readCSNameTableSec(); - std::error_code readProfileSymbolList(); - - virtual std::error_code readHeader() override; - virtual std::error_code verifySPMagic(uint64_t Magic) override = 0; - virtual std::error_code readOneSection(const uint8_t *Start, uint64_t Size, - const SecHdrTableEntry &Entry); - // placeholder for subclasses to dispatch their own section readers. - virtual std::error_code readCustomSection(const SecHdrTableEntry &Entry) = 0; - virtual ErrorOr readStringFromTable() override; - virtual ErrorOr readSampleContextFromTable() override; - ErrorOr readContextFromTable(); - - std::unique_ptr ProfSymList; - - /// The table mapping from function context to the offset of its - /// FunctionSample towards file start. - DenseMap FuncOffsetTable; - - /// Function offset mapping ordered by contexts. - std::unique_ptr>> - OrderedFuncOffsets; - - /// The set containing the functions to use when compiling a module. - DenseSet FuncsToUse; - - /// Use fixed length MD5 instead of ULEB128 encoding so NameTable doesn't - /// need to be read in up front and can be directly accessed using index. - bool FixedLengthMD5 = false; - /// The starting address of NameTable containing fixed length MD5. - const uint8_t *MD5NameMemStart = nullptr; - - /// If MD5 is used in NameTable section, the section saves uint64_t data. - /// The uint64_t data has to be converted to a string and then the string - /// will be used to initialize StringRef in NameTable. - /// Note NameTable contains StringRef so it needs another buffer to own - /// the string data. MD5StringBuf serves as the string buffer that is - /// referenced by NameTable (vector of StringRef). We make sure - /// the lifetime of MD5StringBuf is not shorter than that of NameTable. - std::unique_ptr> MD5StringBuf; - - /// CSNameTable is used to save full context vectors. This serves as an - /// underlying immutable buffer for all clients. - std::unique_ptr> CSNameTable; - - /// If SkipFlatProf is true, skip the sections with - /// SecFlagFlat flag. - bool SkipFlatProf = false; - - bool FuncOffsetsOrdered = false; - -public: - SampleProfileReaderExtBinaryBase(std::unique_ptr B, - LLVMContext &C, SampleProfileFormat Format) - : SampleProfileReaderBinary(std::move(B), C, Format) {} - - /// Read sample profiles in extensible format from the associated file. - std::error_code readImpl() override; - - /// Get the total size of all \p Type sections. - uint64_t getSectionSize(SecType Type); - /// Get the total size of header and all sections. - uint64_t getFileSize(); - virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) override; - - /// Collect functions with definitions in Module M. Return true if - /// the reader has been given a module. - bool collectFuncsFromModule() override; - - /// Return whether names in the profile are all MD5 numbers. - virtual bool useMD5() override { return MD5StringBuf.get(); } - - virtual std::unique_ptr getProfileSymbolList() override { - return std::move(ProfSymList); - }; - - virtual void setSkipFlatProf(bool Skip) override { SkipFlatProf = Skip; } -}; - -class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase { -private: - virtual std::error_code verifySPMagic(uint64_t Magic) override; - virtual std::error_code - readCustomSection(const SecHdrTableEntry &Entry) override { - // Update the data reader pointer to the end of the section. - Data = End; - return sampleprof_error::success; - }; - -public: - SampleProfileReaderExtBinary(std::unique_ptr B, LLVMContext &C, - SampleProfileFormat Format = SPF_Ext_Binary) - : SampleProfileReaderExtBinaryBase(std::move(B), C, Format) {} - - /// \brief Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); -}; - -class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary { -private: - /// Function name table. - std::vector NameTable; - /// The table mapping from function name to the offset of its FunctionSample - /// towards file start. - DenseMap FuncOffsetTable; - /// The set containing the functions to use when compiling a module. - DenseSet FuncsToUse; - virtual std::error_code verifySPMagic(uint64_t Magic) override; - virtual std::error_code readNameTable() override; - /// Read a string indirectly via the name table. - virtual ErrorOr readStringFromTable() override; - virtual std::error_code readHeader() override; - std::error_code readFuncOffsetTable(); - -public: - SampleProfileReaderCompactBinary(std::unique_ptr B, - LLVMContext &C) - : SampleProfileReaderBinary(std::move(B), C, SPF_Compact_Binary) {} - - /// \brief Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); - - /// Read samples only for functions to use. - std::error_code readImpl() override; - - /// Collect functions with definitions in Module M. Return true if - /// the reader has been given a module. - bool collectFuncsFromModule() override; - - /// Return whether names in the profile are all MD5 numbers. - virtual bool useMD5() override { return true; } -}; - -using InlineCallStack = SmallVector; - -// Supported histogram types in GCC. Currently, we only need support for -// call target histograms. -enum HistType { - HIST_TYPE_INTERVAL, - HIST_TYPE_POW2, - HIST_TYPE_SINGLE_VALUE, - HIST_TYPE_CONST_DELTA, - HIST_TYPE_INDIR_CALL, - HIST_TYPE_AVERAGE, - HIST_TYPE_IOR, - HIST_TYPE_INDIR_CALL_TOPN -}; - -class SampleProfileReaderGCC : public SampleProfileReader { -public: - SampleProfileReaderGCC(std::unique_ptr B, LLVMContext &C) - : SampleProfileReader(std::move(B), C, SPF_GCC), - GcovBuffer(Buffer.get()) {} - - /// Read and validate the file header. - std::error_code readHeader() override; - - /// Read sample profiles from the associated file. - std::error_code readImpl() override; - - /// Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); - -protected: - std::error_code readNameTable(); - std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack, - bool Update, uint32_t Offset); - std::error_code readFunctionProfiles(); - std::error_code skipNextWord(); - template ErrorOr readNumber(); - ErrorOr readString(); - - /// Read the section tag and check that it's the same as \p Expected. - std::error_code readSectionTag(uint32_t Expected); - - /// GCOV buffer containing the profile. - GCOVBuffer GcovBuffer; - - /// Function names in this profile. - std::vector Names; - - /// GCOV tags used to separate sections in the profile file. - static const uint32_t GCOVTagAFDOFileNames = 0xaa000000; - static const uint32_t GCOVTagAFDOFunction = 0xac000000; -}; - -} // end namespace sampleprof - -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H diff --git a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfWriter.h b/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfWriter.h deleted file mode 100644 index b4a2da3a7b..0000000000 --- a/suite/synctools/tablegen/include/llvm/ProfileData/SampleProfWriter.h +++ /dev/null @@ -1,407 +0,0 @@ -//===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains definitions needed for writing sample profiles. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H -#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/IR/ProfileSummary.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { -namespace sampleprof { - -enum SectionLayout { - DefaultLayout, - // The layout splits profile with context information from profile without - // context information. When Thinlto is enabled, ThinLTO postlink phase only - // has to load profile with context information and can skip the other part. - CtxSplitLayout, - NumOfLayout, -}; - -/// Sample-based profile writer. Base class. -class SampleProfileWriter { -public: - virtual ~SampleProfileWriter() = default; - - /// Write sample profiles in \p S. - /// - /// \returns status code of the file update operation. - virtual std::error_code writeSample(const FunctionSamples &S) = 0; - - /// Write all the sample profiles in the given map of samples. - /// - /// \returns status code of the file update operation. - virtual std::error_code write(const SampleProfileMap &ProfileMap); - - raw_ostream &getOutputStream() { return *OutputStream; } - - /// Profile writer factory. - /// - /// Create a new file writer based on the value of \p Format. - static ErrorOr> - create(StringRef Filename, SampleProfileFormat Format); - - /// Create a new stream writer based on the value of \p Format. - /// For testing. - static ErrorOr> - create(std::unique_ptr &OS, SampleProfileFormat Format); - - virtual void setProfileSymbolList(ProfileSymbolList *PSL) {} - virtual void setToCompressAllSections() {} - virtual void setUseMD5() {} - virtual void setPartialProfile() {} - virtual void resetSecLayout(SectionLayout SL) {} - -protected: - SampleProfileWriter(std::unique_ptr &OS) - : OutputStream(std::move(OS)) {} - - /// Write a file header for the profile file. - virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0; - - // Write function profiles to the profile file. - virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap); - - /// Output stream where to emit the profile to. - std::unique_ptr OutputStream; - - /// Profile summary. - std::unique_ptr Summary; - - /// Compute summary for this profile. - void computeSummary(const SampleProfileMap &ProfileMap); - - /// Profile format. - SampleProfileFormat Format = SPF_None; -}; - -/// Sample-based profile writer (text format). -class SampleProfileWriterText : public SampleProfileWriter { -public: - std::error_code writeSample(const FunctionSamples &S) override; - -protected: - SampleProfileWriterText(std::unique_ptr &OS) - : SampleProfileWriter(OS), Indent(0) {} - - std::error_code writeHeader(const SampleProfileMap &ProfileMap) override { - return sampleprof_error::success; - } - -private: - /// Indent level to use when writing. - /// - /// This is used when printing inlined callees. - unsigned Indent; - - friend ErrorOr> - SampleProfileWriter::create(std::unique_ptr &OS, - SampleProfileFormat Format); -}; - -/// Sample-based profile writer (binary format). -class SampleProfileWriterBinary : public SampleProfileWriter { -public: - SampleProfileWriterBinary(std::unique_ptr &OS) - : SampleProfileWriter(OS) {} - - virtual std::error_code writeSample(const FunctionSamples &S) override; - -protected: - virtual MapVector &getNameTable() { return NameTable; } - virtual std::error_code writeMagicIdent(SampleProfileFormat Format); - virtual std::error_code writeNameTable(); - virtual std::error_code - writeHeader(const SampleProfileMap &ProfileMap) override; - std::error_code writeSummary(); - virtual std::error_code writeContextIdx(const SampleContext &Context); - std::error_code writeNameIdx(StringRef FName); - std::error_code writeBody(const FunctionSamples &S); - inline void stablizeNameTable(MapVector &NameTable, - std::set &V); - - MapVector NameTable; - - void addName(StringRef FName); - virtual void addContext(const SampleContext &Context); - void addNames(const FunctionSamples &S); - -private: - friend ErrorOr> - SampleProfileWriter::create(std::unique_ptr &OS, - SampleProfileFormat Format); -}; - -class SampleProfileWriterRawBinary : public SampleProfileWriterBinary { - using SampleProfileWriterBinary::SampleProfileWriterBinary; -}; - -const std::array, NumOfLayout> - ExtBinaryHdrLayoutTable = { - // Note that SecFuncOffsetTable section is written after SecLBRProfile - // in the profile, but is put before SecLBRProfile in SectionHdrLayout. - // This is because sample reader follows the order in SectionHdrLayout - // to read each section. To read function profiles on demand, sample - // reader need to get the offset of each function profile first. - // - // DefaultLayout - SmallVector({{SecProfSummary, 0, 0, 0, 0}, - {SecNameTable, 0, 0, 0, 0}, - {SecCSNameTable, 0, 0, 0, 0}, - {SecFuncOffsetTable, 0, 0, 0, 0}, - {SecLBRProfile, 0, 0, 0, 0}, - {SecProfileSymbolList, 0, 0, 0, 0}, - {SecFuncMetadata, 0, 0, 0, 0}}), - // CtxSplitLayout - SmallVector({{SecProfSummary, 0, 0, 0, 0}, - {SecNameTable, 0, 0, 0, 0}, - // profile with context - // for next two sections - {SecFuncOffsetTable, 0, 0, 0, 0}, - {SecLBRProfile, 0, 0, 0, 0}, - // profile without context - // for next two sections - {SecFuncOffsetTable, 0, 0, 0, 0}, - {SecLBRProfile, 0, 0, 0, 0}, - {SecProfileSymbolList, 0, 0, 0, 0}, - {SecFuncMetadata, 0, 0, 0, 0}}), -}; - -class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary { - using SampleProfileWriterBinary::SampleProfileWriterBinary; -public: - virtual std::error_code write(const SampleProfileMap &ProfileMap) override; - - virtual void setToCompressAllSections() override; - void setToCompressSection(SecType Type); - virtual std::error_code writeSample(const FunctionSamples &S) override; - - // Set to use MD5 to represent string in NameTable. - virtual void setUseMD5() override { - UseMD5 = true; - addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name); - // MD5 will be stored as plain uint64_t instead of variable-length - // quantity format in NameTable section. - addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagFixedLengthMD5); - } - - // Set the profile to be partial. It means the profile is for - // common/shared code. The common profile is usually merged from - // profiles collected from running other targets. - virtual void setPartialProfile() override { - addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagPartial); - } - - virtual void setProfileSymbolList(ProfileSymbolList *PSL) override { - ProfSymList = PSL; - }; - - virtual void resetSecLayout(SectionLayout SL) override { - verifySecLayout(SL); -#ifndef NDEBUG - // Make sure resetSecLayout is called before any flag setting. - for (auto &Entry : SectionHdrLayout) { - assert(Entry.Flags == 0 && - "resetSecLayout has to be called before any flag setting"); - } -#endif - SecLayout = SL; - SectionHdrLayout = ExtBinaryHdrLayoutTable[SL]; - } - -protected: - uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx); - std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx, - uint64_t SectionStart); - template - void addSectionFlag(SecType Type, SecFlagType Flag) { - for (auto &Entry : SectionHdrLayout) { - if (Entry.Type == Type) - addSecFlag(Entry, Flag); - } - } - template - void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag) { - addSecFlag(SectionHdrLayout[SectionIdx], Flag); - } - - virtual void addContext(const SampleContext &Context) override; - - // placeholder for subclasses to dispatch their own section writers. - virtual std::error_code writeCustomSection(SecType Type) = 0; - // Verify the SecLayout is supported by the format. - virtual void verifySecLayout(SectionLayout SL) = 0; - - // specify the order to write sections. - virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0; - - // Dispatch section writer for each section. \p LayoutIdx is the sequence - // number indicating where the section is located in SectionHdrLayout. - virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx, - const SampleProfileMap &ProfileMap); - - // Helper function to write name table. - virtual std::error_code writeNameTable() override; - virtual std::error_code - writeContextIdx(const SampleContext &Context) override; - std::error_code writeCSNameIdx(const SampleContext &Context); - std::error_code writeCSNameTableSection(); - - std::error_code writeFuncMetadata(const SampleProfileMap &Profiles); - std::error_code writeFuncMetadata(const FunctionSamples &Profile); - - // Functions to write various kinds of sections. - std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap); - std::error_code writeFuncOffsetTable(); - std::error_code writeProfileSymbolListSection(); - - SectionLayout SecLayout = DefaultLayout; - // Specify the order of sections in section header table. Note - // the order of sections in SecHdrTable may be different that the - // order in SectionHdrLayout. sample Reader will follow the order - // in SectionHdrLayout to read each section. - SmallVector SectionHdrLayout = - ExtBinaryHdrLayoutTable[DefaultLayout]; - - // Save the start of SecLBRProfile so we can compute the offset to the - // start of SecLBRProfile for each Function's Profile and will keep it - // in FuncOffsetTable. - uint64_t SecLBRProfileStart = 0; - -private: - void allocSecHdrTable(); - std::error_code writeSecHdrTable(); - virtual std::error_code - writeHeader(const SampleProfileMap &ProfileMap) override; - std::error_code compressAndOutput(); - - // We will swap the raw_ostream held by LocalBufStream and that - // held by OutputStream if we try to add a section which needs - // compression. After the swap, all the data written to output - // will be temporarily buffered into the underlying raw_string_ostream - // originally held by LocalBufStream. After the data writing for the - // section is completed, compress the data in the local buffer, - // swap the raw_ostream back and write the compressed data to the - // real output. - std::unique_ptr LocalBufStream; - // The location where the output stream starts. - uint64_t FileStart; - // The location in the output stream where the SecHdrTable should be - // written to. - uint64_t SecHdrTableOffset; - // The table contains SecHdrTableEntry entries in order of how they are - // populated in the writer. It may be different from the order in - // SectionHdrLayout which specifies the sequence in which sections will - // be read. - std::vector SecHdrTable; - - // FuncOffsetTable maps function context to its profile offset in - // SecLBRProfile section. It is used to load function profile on demand. - MapVector FuncOffsetTable; - // Whether to use MD5 to represent string. - bool UseMD5 = false; - - /// CSNameTable maps function context to its offset in SecCSNameTable section. - /// The offset will be used everywhere where the context is referenced. - MapVector CSNameTable; - - ProfileSymbolList *ProfSymList = nullptr; -}; - -class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase { -public: - SampleProfileWriterExtBinary(std::unique_ptr &OS) - : SampleProfileWriterExtBinaryBase(OS) {} - -private: - std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap); - std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap); - - virtual std::error_code - writeSections(const SampleProfileMap &ProfileMap) override; - - virtual std::error_code writeCustomSection(SecType Type) override { - return sampleprof_error::success; - }; - - virtual void verifySecLayout(SectionLayout SL) override { - assert((SL == DefaultLayout || SL == CtxSplitLayout) && - "Unsupported layout"); - } -}; - -// CompactBinary is a compact format of binary profile which both reduces -// the profile size and the load time needed when compiling. It has two -// major difference with Binary format. -// 1. It represents all the strings in name table using md5 hash. -// 2. It saves a function offset table which maps function name index to -// the offset of its function profile to the start of the binary profile, -// so by using the function offset table, for those function profiles which -// will not be needed when compiling a module, the profile reader does't -// have to read them and it saves compile time if the profile size is huge. -// The layout of the compact format is shown as follows: -// -// Part1: Profile header, the same as binary format, containing magic -// number, version, summary, name table... -// Part2: Function Offset Table Offset, which saves the position of -// Part4. -// Part3: Function profile collection -// function1 profile start -// .... -// function2 profile start -// .... -// function3 profile start -// .... -// ...... -// Part4: Function Offset Table -// function1 name index --> function1 profile start -// function2 name index --> function2 profile start -// function3 name index --> function3 profile start -// -// We need Part2 because profile reader can use it to find out and read -// function offset table without reading Part3 first. -class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary { - using SampleProfileWriterBinary::SampleProfileWriterBinary; - -public: - virtual std::error_code writeSample(const FunctionSamples &S) override; - virtual std::error_code write(const SampleProfileMap &ProfileMap) override; - -protected: - /// The table mapping from function name to the offset of its FunctionSample - /// towards profile start. - MapVector FuncOffsetTable; - /// The offset of the slot to be filled with the offset of FuncOffsetTable - /// towards profile start. - uint64_t TableOffset; - virtual std::error_code writeNameTable() override; - virtual std::error_code - writeHeader(const SampleProfileMap &ProfileMap) override; - std::error_code writeFuncOffsetTable(); -}; - -} // end namespace sampleprof -} // end namespace llvm - -#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H diff --git a/suite/synctools/tablegen/include/llvm/TableGen/Automaton.td b/suite/synctools/tablegen/include/llvm/TableGen/Automaton.td deleted file mode 100644 index 13ced2a0e7..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/Automaton.td +++ /dev/null @@ -1,95 +0,0 @@ -//===- Automaton.td ----------------------------------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the key top-level classes needed to produce a reasonably -// generic finite-state automaton. -// -//===----------------------------------------------------------------------===// - -// Define a record inheriting from GenericAutomaton to generate a reasonably -// generic finite-state automaton over a set of actions and states. -// -// This automaton is defined by: -// 1) a state space (explicit, always bits<32>). -// 2) a set of input symbols (actions, explicit) and -// 3) a transition function from state + action -> state. -// -// A theoretical automaton is defined by : -// Q: A set of possible states. -// S: (sigma) The input alphabet. -// d: (delta) The transition function f(q in Q, s in S) -> q' in Q. -// F: The set of final (accepting) states. -// -// Because generating all possible states is tedious, we instead define the -// transition function only and crawl all reachable states starting from the -// initial state with all inputs under all transitions until termination. -// -// We define F = S, that is, all valid states are accepting. -// -// To ensure the generation of the automaton terminates, the state transitions -// are defined as a lattice (meaning every transitioned-to state is more -// specific than the transitioned-from state, for some definition of specificity). -// Concretely a transition may set one or more bits in the state that were -// previously zero to one. If any bit was not zero, the transition is invalid. -// -// Instead of defining all possible states (which would be cumbersome), the user -// provides a set of possible Transitions from state A, consuming an input -// symbol A to state B. The Transition object transforms state A to state B and -// acts as a predicate. This means the state space can be discovered by crawling -// all the possible transitions until none are valid. -// -// This automaton is considered to be nondeterministic, meaning that multiple -// transitions can occur from any (state, action) pair. The generated automaton -// is determinized, meaning that is executes in O(k) time where k is the input -// sequence length. -// -// In addition to a generated automaton that determines if a sequence of inputs -// is accepted or not, a table is emitted that allows determining a plausible -// sequence of states traversed to accept that input. -class GenericAutomaton { - // Name of a class that inherits from Transition. All records inheriting from - // this class will be considered when constructing the automaton. - string TransitionClass; - - // Names of fields within TransitionClass that define the action symbol. This - // defines the action as an N-tuple. - // - // Each symbol field can be of class, int, string or code type. - // If the type of a field is a class, the Record's name is used verbatim - // in C++ and the class name is used as the C++ type name. - // If the type of a field is a string, code or int, that is also used - // verbatim in C++. - // - // To override the C++ type name for field F, define a field called TypeOf_F. - // This should be a string that will be used verbatim in C++. - // - // As an example, to define a 2-tuple with an enum and a string, one might: - // def MyTransition : Transition { - // MyEnum S1; - // int S2; - // } - // def MyAutomaton : GenericAutomaton }{ - // let TransitionClass = "Transition"; - // let SymbolFields = ["S1", "S2"]; - // let TypeOf_S1 = "MyEnumInCxxKind"; - // } - list SymbolFields; -} - -// All transitions inherit from Transition. -class Transition { - // A transition S' = T(S) is valid if, for every set bit in NewState, the - // corresponding bit in S is clear. That is: - // def T(S): - // S' = S | NewState - // return S' if S' != S else Failure - // - // The automaton generator uses this property to crawl the set of possible - // transitions from a starting state of 0b0. - bits<32> NewState; -} diff --git a/suite/synctools/tablegen/include/llvm/TableGen/DirectiveEmitter.h b/suite/synctools/tablegen/include/llvm/TableGen/DirectiveEmitter.h deleted file mode 100644 index d73b9ae492..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/DirectiveEmitter.h +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef LLVM_TABLEGEN_DIRECTIVEEMITTER_H -#define LLVM_TABLEGEN_DIRECTIVEEMITTER_H - -#include "llvm/ADT/StringExtras.h" -#include "llvm/TableGen/Record.h" - -namespace llvm { - -// Wrapper class that contains DirectiveLanguage's information defined in -// DirectiveBase.td and provides helper methods for accessing it. -class DirectiveLanguage { -public: - explicit DirectiveLanguage(const llvm::RecordKeeper &Records) - : Records(Records) { - const auto &DirectiveLanguages = getDirectiveLanguages(); - Def = DirectiveLanguages[0]; - } - - StringRef getName() const { return Def->getValueAsString("name"); } - - StringRef getCppNamespace() const { - return Def->getValueAsString("cppNamespace"); - } - - StringRef getDirectivePrefix() const { - return Def->getValueAsString("directivePrefix"); - } - - StringRef getClausePrefix() const { - return Def->getValueAsString("clausePrefix"); - } - - StringRef getClauseEnumSetClass() const { - return Def->getValueAsString("clauseEnumSetClass"); - } - - StringRef getFlangClauseBaseClass() const { - return Def->getValueAsString("flangClauseBaseClass"); - } - - bool hasMakeEnumAvailableInNamespace() const { - return Def->getValueAsBit("makeEnumAvailableInNamespace"); - } - - bool hasEnableBitmaskEnumInNamespace() const { - return Def->getValueAsBit("enableBitmaskEnumInNamespace"); - } - - std::vector getDirectives() const { - return Records.getAllDerivedDefinitions("Directive"); - } - - std::vector getClauses() const { - return Records.getAllDerivedDefinitions("Clause"); - } - - bool HasValidityErrors() const; - -private: - const llvm::Record *Def; - const llvm::RecordKeeper &Records; - - std::vector getDirectiveLanguages() const { - return Records.getAllDerivedDefinitions("DirectiveLanguage"); - } -}; - -// Base record class used for Directive and Clause class defined in -// DirectiveBase.td. -class BaseRecord { -public: - explicit BaseRecord(const llvm::Record *Def) : Def(Def) {} - - StringRef getName() const { return Def->getValueAsString("name"); } - - StringRef getAlternativeName() const { - return Def->getValueAsString("alternativeName"); - } - - // Returns the name of the directive formatted for output. Whitespace are - // replaced with underscores. - std::string getFormattedName() { - StringRef Name = Def->getValueAsString("name"); - std::string N = Name.str(); - std::replace(N.begin(), N.end(), ' ', '_'); - return N; - } - - bool isDefault() const { return Def->getValueAsBit("isDefault"); } - - // Returns the record name. - StringRef getRecordName() const { return Def->getName(); } - -protected: - const llvm::Record *Def; -}; - -// Wrapper class that contains a Directive's information defined in -// DirectiveBase.td and provides helper methods for accessing it. -class Directive : public BaseRecord { -public: - explicit Directive(const llvm::Record *Def) : BaseRecord(Def) {} - - std::vector getAllowedClauses() const { - return Def->getValueAsListOfDefs("allowedClauses"); - } - - std::vector getAllowedOnceClauses() const { - return Def->getValueAsListOfDefs("allowedOnceClauses"); - } - - std::vector getAllowedExclusiveClauses() const { - return Def->getValueAsListOfDefs("allowedExclusiveClauses"); - } - - std::vector getRequiredClauses() const { - return Def->getValueAsListOfDefs("requiredClauses"); - } -}; - -// Wrapper class that contains Clause's information defined in DirectiveBase.td -// and provides helper methods for accessing it. -class Clause : public BaseRecord { -public: - explicit Clause(const llvm::Record *Def) : BaseRecord(Def) {} - - // Optional field. - StringRef getClangClass() const { - return Def->getValueAsString("clangClass"); - } - - // Optional field. - StringRef getFlangClass() const { - return Def->getValueAsString("flangClass"); - } - - // Get the formatted name for Flang parser class. The generic formatted class - // name is constructed from the name were the first letter of each word is - // captitalized and the underscores are removed. - // ex: async -> Async - // num_threads -> NumThreads - std::string getFormattedParserClassName() { - StringRef Name = Def->getValueAsString("name"); - std::string N = Name.str(); - bool Cap = true; - std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) { - if (Cap == true) { - C = llvm::toUpper(C); - Cap = false; - } else if (C == '_') { - Cap = true; - } - return C; - }); - llvm::erase_value(N, '_'); - return N; - } - - // Optional field. - StringRef getEnumName() const { - return Def->getValueAsString("enumClauseValue"); - } - - std::vector getClauseVals() const { - return Def->getValueAsListOfDefs("allowedClauseValues"); - } - - bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); } - - bool isValueList() const { return Def->getValueAsBit("isValueList"); } - - StringRef getDefaultValue() const { - return Def->getValueAsString("defaultValue"); - } - - bool isImplicit() const { return Def->getValueAsBit("isImplicit"); } -}; - -// Wrapper class that contains VersionedClause's information defined in -// DirectiveBase.td and provides helper methods for accessing it. -class VersionedClause { -public: - explicit VersionedClause(const llvm::Record *Def) : Def(Def) {} - - // Return the specific clause record wrapped in the Clause class. - Clause getClause() const { return Clause{Def->getValueAsDef("clause")}; } - - int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); } - - int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); } - -private: - const llvm::Record *Def; -}; - -class ClauseVal : public BaseRecord { -public: - explicit ClauseVal(const llvm::Record *Def) : BaseRecord(Def) {} - - int getValue() const { return Def->getValueAsInt("value"); } - - bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); } -}; - -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/TableGen/Error.h b/suite/synctools/tablegen/include/llvm/TableGen/Error.h deleted file mode 100644 index da0132b10f..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/Error.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains error handling helper routines to pretty-print diagnostic -// messages from tblgen. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_ERROR_H -#define LLVM_TABLEGEN_ERROR_H - -#include "llvm/Support/SourceMgr.h" -#include "llvm/TableGen/Record.h" - -namespace llvm { - -void PrintNote(const Twine &Msg); -void PrintNote(ArrayRef NoteLoc, const Twine &Msg); - -[[noreturn]] void PrintFatalNote(const Twine &Msg); -[[noreturn]] void PrintFatalNote(ArrayRef ErrorLoc, const Twine &Msg); -[[noreturn]] void PrintFatalNote(const Record *Rec, const Twine &Msg); -[[noreturn]] void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg); - -void PrintWarning(const Twine &Msg); -void PrintWarning(ArrayRef WarningLoc, const Twine &Msg); -void PrintWarning(const char *Loc, const Twine &Msg); - -void PrintError(const Twine &Msg); -void PrintError(ArrayRef ErrorLoc, const Twine &Msg); -void PrintError(const char *Loc, const Twine &Msg); -void PrintError(const Record *Rec, const Twine &Msg); -void PrintError(const RecordVal *RecVal, const Twine &Msg); - -[[noreturn]] void PrintFatalError(const Twine &Msg); -[[noreturn]] void PrintFatalError(ArrayRef ErrorLoc, const Twine &Msg); -[[noreturn]] void PrintFatalError(const Record *Rec, const Twine &Msg); -[[noreturn]] void PrintFatalError(const RecordVal *RecVal, const Twine &Msg); - -void CheckAssert(SMLoc Loc, Init *Condition, Init *Message); - -extern SourceMgr SrcMgr; -extern unsigned ErrorsPrinted; - -} // end namespace "llvm" - -#endif diff --git a/suite/synctools/tablegen/include/llvm/TableGen/Main.h b/suite/synctools/tablegen/include/llvm/TableGen/Main.h deleted file mode 100644 index 4e05da3616..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/Main.h +++ /dev/null @@ -1,29 +0,0 @@ -//===- llvm/TableGen/Main.h - tblgen entry point ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the common entry point for tblgen tools. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_MAIN_H -#define LLVM_TABLEGEN_MAIN_H - -namespace llvm { - -class raw_ostream; -class RecordKeeper; - -/// Perform the action using Records, and write output to OS. -/// Returns true on error, false otherwise. -using TableGenMainFn = bool (raw_ostream &OS, RecordKeeper &Records); - -int TableGenMain(const char *argv0, TableGenMainFn *MainFn); - -} // end namespace llvm - -#endif // LLVM_TABLEGEN_MAIN_H diff --git a/suite/synctools/tablegen/include/llvm/TableGen/Record.h b/suite/synctools/tablegen/include/llvm/TableGen/Record.h deleted file mode 100644 index 1157487ece..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/Record.h +++ /dev/null @@ -1,2136 +0,0 @@ -//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the main TableGen data structures, including the TableGen -// types, values, and high-level data structures. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_RECORD_H -#define LLVM_TABLEGEN_RECORD_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/TrailingObjects.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llvm { -namespace detail { -struct RecordContext; -} // namespace detail - -class ListRecTy; -class Record; -class RecordKeeper; -class RecordVal; -class Resolver; -class StringInit; -class TypedInit; - -//===----------------------------------------------------------------------===// -// Type Classes -//===----------------------------------------------------------------------===// - -class RecTy { -public: - /// Subclass discriminator (for dyn_cast<> et al.) - enum RecTyKind { - BitRecTyKind, - BitsRecTyKind, - IntRecTyKind, - StringRecTyKind, - ListRecTyKind, - DagRecTyKind, - RecordRecTyKind - }; - -private: - RecTyKind Kind; - /// ListRecTy of the list that has elements of this type. - ListRecTy *ListTy = nullptr; - -public: - RecTy(RecTyKind K) : Kind(K) {} - virtual ~RecTy() = default; - - RecTyKind getRecTyKind() const { return Kind; } - - virtual std::string getAsString() const = 0; - void print(raw_ostream &OS) const { OS << getAsString(); } - void dump() const; - - /// Return true if all values of 'this' type can be converted to the specified - /// type. - virtual bool typeIsConvertibleTo(const RecTy *RHS) const; - - /// Return true if 'this' type is equal to or a subtype of RHS. For example, - /// a bit set is not an int, but they are convertible. - virtual bool typeIsA(const RecTy *RHS) const; - - /// Returns the type representing list. - ListRecTy *getListTy(); -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { - Ty.print(OS); - return OS; -} - -/// 'bit' - Represent a single bit -class BitRecTy : public RecTy { - friend detail::RecordContext; - - BitRecTy() : RecTy(BitRecTyKind) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == BitRecTyKind; - } - - static BitRecTy *get(); - - std::string getAsString() const override { return "bit"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const override; -}; - -/// 'bits' - Represent a fixed number of bits -class BitsRecTy : public RecTy { - unsigned Size; - - explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == BitsRecTyKind; - } - - static BitsRecTy *get(unsigned Sz); - - unsigned getNumBits() const { return Size; } - - std::string getAsString() const override; - - bool typeIsConvertibleTo(const RecTy *RHS) const override; - - bool typeIsA(const RecTy *RHS) const override; -}; - -/// 'int' - Represent an integer value of no particular size -class IntRecTy : public RecTy { - friend detail::RecordContext; - - IntRecTy() : RecTy(IntRecTyKind) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == IntRecTyKind; - } - - static IntRecTy *get(); - - std::string getAsString() const override { return "int"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const override; -}; - -/// 'string' - Represent an string value -class StringRecTy : public RecTy { - friend detail::RecordContext; - - StringRecTy() : RecTy(StringRecTyKind) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == StringRecTyKind; - } - - static StringRecTy *get(); - - std::string getAsString() const override; - - bool typeIsConvertibleTo(const RecTy *RHS) const override; -}; - -/// 'list' - Represent a list of element values, all of which must be of -/// the specified type. The type is stored in ElementTy. -class ListRecTy : public RecTy { - friend ListRecTy *RecTy::getListTy(); - - RecTy *ElementTy; - - explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), ElementTy(T) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == ListRecTyKind; - } - - static ListRecTy *get(RecTy *T) { return T->getListTy(); } - RecTy *getElementType() const { return ElementTy; } - - std::string getAsString() const override; - - bool typeIsConvertibleTo(const RecTy *RHS) const override; - - bool typeIsA(const RecTy *RHS) const override; -}; - -/// 'dag' - Represent a dag fragment -class DagRecTy : public RecTy { - friend detail::RecordContext; - - DagRecTy() : RecTy(DagRecTyKind) {} - -public: - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == DagRecTyKind; - } - - static DagRecTy *get(); - - std::string getAsString() const override; -}; - -/// '[classname]' - Type of record values that have zero or more superclasses. -/// -/// The list of superclasses is non-redundant, i.e. only contains classes that -/// are not the superclass of some other listed class. -class RecordRecTy final : public RecTy, public FoldingSetNode, - public TrailingObjects { - friend class Record; - friend detail::RecordContext; - - unsigned NumClasses; - - explicit RecordRecTy(unsigned Num) - : RecTy(RecordRecTyKind), NumClasses(Num) {} - -public: - RecordRecTy(const RecordRecTy &) = delete; - RecordRecTy &operator=(const RecordRecTy &) = delete; - - // Do not use sized deallocation due to trailing objects. - void operator delete(void *p) { ::operator delete(p); } - - static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == RecordRecTyKind; - } - - /// Get the record type with the given non-redundant list of superclasses. - static RecordRecTy *get(ArrayRef Classes); - - void Profile(FoldingSetNodeID &ID) const; - - ArrayRef getClasses() const { - return makeArrayRef(getTrailingObjects(), NumClasses); - } - - using const_record_iterator = Record * const *; - - const_record_iterator classes_begin() const { return getClasses().begin(); } - const_record_iterator classes_end() const { return getClasses().end(); } - - std::string getAsString() const override; - - bool isSubClassOf(Record *Class) const; - bool typeIsConvertibleTo(const RecTy *RHS) const override; - - bool typeIsA(const RecTy *RHS) const override; -}; - -/// Find a common type that T1 and T2 convert to. -/// Return 0 if no such type exists. -RecTy *resolveTypes(RecTy *T1, RecTy *T2); - -//===----------------------------------------------------------------------===// -// Initializer Classes -//===----------------------------------------------------------------------===// - -class Init { -protected: - /// Discriminator enum (for isa<>, dyn_cast<>, et al.) - /// - /// This enum is laid out by a preorder traversal of the inheritance - /// hierarchy, and does not contain an entry for abstract classes, as per - /// the recommendation in docs/HowToSetUpLLVMStyleRTTI.rst. - /// - /// We also explicitly include "first" and "last" values for each - /// interior node of the inheritance tree, to make it easier to read the - /// corresponding classof(). - /// - /// We could pack these a bit tighter by not having the IK_FirstXXXInit - /// and IK_LastXXXInit be their own values, but that would degrade - /// readability for really no benefit. - enum InitKind : uint8_t { - IK_First, // unused; silence a spurious warning - IK_FirstTypedInit, - IK_BitInit, - IK_BitsInit, - IK_DagInit, - IK_DefInit, - IK_FieldInit, - IK_IntInit, - IK_ListInit, - IK_FirstOpInit, - IK_BinOpInit, - IK_TernOpInit, - IK_UnOpInit, - IK_LastOpInit, - IK_CondOpInit, - IK_FoldOpInit, - IK_IsAOpInit, - IK_AnonymousNameInit, - IK_StringInit, - IK_VarInit, - IK_VarListElementInit, - IK_VarBitInit, - IK_VarDefInit, - IK_LastTypedInit, - IK_UnsetInit - }; - -private: - const InitKind Kind; - -protected: - uint8_t Opc; // Used by UnOpInit, BinOpInit, and TernOpInit - -private: - virtual void anchor(); - -public: - /// Get the kind (type) of the value. - InitKind getKind() const { return Kind; } - -protected: - explicit Init(InitKind K, uint8_t Opc = 0) : Kind(K), Opc(Opc) {} - -public: - Init(const Init &) = delete; - Init &operator=(const Init &) = delete; - virtual ~Init() = default; - - /// Is this a complete value with no unset (uninitialized) subvalues? - virtual bool isComplete() const { return true; } - - /// Is this a concrete and fully resolved value without any references or - /// stuck operations? Unset values are concrete. - virtual bool isConcrete() const { return false; } - - /// Print this value. - void print(raw_ostream &OS) const { OS << getAsString(); } - - /// Convert this value to a literal form. - virtual std::string getAsString() const = 0; - - /// Convert this value to a literal form, - /// without adding quotes around a string. - virtual std::string getAsUnquotedString() const { return getAsString(); } - - /// Debugging method that may be called through a debugger; just - /// invokes print on stderr. - void dump() const; - - /// If this value is convertible to type \p Ty, return a value whose - /// type is \p Ty, generating a !cast operation if required. - /// Otherwise, return null. - virtual Init *getCastTo(RecTy *Ty) const = 0; - - /// Convert to a value whose type is \p Ty, or return null if this - /// is not possible. This can happen if the value's type is convertible - /// to \p Ty, but there are unresolved references. - virtual Init *convertInitializerTo(RecTy *Ty) const = 0; - - /// This function is used to implement the bit range - /// selection operator. Given a value, it selects the specified bits, - /// returning them as a new \p Init of type \p bits. If it is not legal - /// to use the bit selection operator on this value, null is returned. - virtual Init *convertInitializerBitRange(ArrayRef Bits) const { - return nullptr; - } - - /// This function is used to implement the list slice - /// selection operator. Given a value, it selects the specified list - /// elements, returning them as a new \p Init of type \p list. If it - /// is not legal to use the slice operator, null is returned. - virtual Init *convertInitListSlice(ArrayRef Elements) const { - return nullptr; - } - - /// This function is used to implement the FieldInit class. - /// Implementors of this method should return the type of the named - /// field if they are of type record. - virtual RecTy *getFieldType(StringInit *FieldName) const { - return nullptr; - } - - /// This function is used by classes that refer to other - /// variables which may not be defined at the time the expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - virtual Init *resolveReferences(Resolver &R) const { - return const_cast(this); - } - - /// Get the \p Init value of the specified bit. - virtual Init *getBit(unsigned Bit) const = 0; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { - I.print(OS); return OS; -} - -/// This is the common superclass of types that have a specific, -/// explicit type, stored in ValueTy. -class TypedInit : public Init { - RecTy *ValueTy; - -protected: - explicit TypedInit(InitKind K, RecTy *T, uint8_t Opc = 0) - : Init(K, Opc), ValueTy(T) {} - -public: - TypedInit(const TypedInit &) = delete; - TypedInit &operator=(const TypedInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() >= IK_FirstTypedInit && - I->getKind() <= IK_LastTypedInit; - } - - /// Get the type of the Init as a RecTy. - RecTy *getType() const { return ValueTy; } - - Init *getCastTo(RecTy *Ty) const override; - Init *convertInitializerTo(RecTy *Ty) const override; - - Init *convertInitializerBitRange(ArrayRef Bits) const override; - Init *convertInitListSlice(ArrayRef Elements) const override; - - /// This method is used to implement the FieldInit class. - /// Implementors of this method should return the type of the named field if - /// they are of type record. - RecTy *getFieldType(StringInit *FieldName) const override; -}; - -/// '?' - Represents an uninitialized value. -class UnsetInit : public Init { - friend detail::RecordContext; - - UnsetInit() : Init(IK_UnsetInit) {} - -public: - UnsetInit(const UnsetInit &) = delete; - UnsetInit &operator=(const UnsetInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_UnsetInit; - } - - /// Get the singleton unset Init. - static UnsetInit *get(); - - Init *getCastTo(RecTy *Ty) const override; - Init *convertInitializerTo(RecTy *Ty) const override; - - Init *getBit(unsigned Bit) const override { - return const_cast(this); - } - - /// Is this a complete value with no unset (uninitialized) subvalues? - bool isComplete() const override { return false; } - - bool isConcrete() const override { return true; } - - /// Get the string representation of the Init. - std::string getAsString() const override { return "?"; } -}; - -/// 'true'/'false' - Represent a concrete initializer for a bit. -class BitInit final : public TypedInit { - friend detail::RecordContext; - - bool Value; - - explicit BitInit(bool V, RecTy *T) : TypedInit(IK_BitInit, T), Value(V) {} - -public: - BitInit(const BitInit &) = delete; - BitInit &operator=(BitInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_BitInit; - } - - static BitInit *get(bool V); - - bool getValue() const { return Value; } - - Init *convertInitializerTo(RecTy *Ty) const override; - - Init *getBit(unsigned Bit) const override { - assert(Bit < 1 && "Bit index out of range!"); - return const_cast(this); - } - - bool isConcrete() const override { return true; } - std::string getAsString() const override { return Value ? "1" : "0"; } -}; - -/// '{ a, b, c }' - Represents an initializer for a BitsRecTy value. -/// It contains a vector of bits, whose size is determined by the type. -class BitsInit final : public TypedInit, public FoldingSetNode, - public TrailingObjects { - unsigned NumBits; - - BitsInit(unsigned N) - : TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {} - -public: - BitsInit(const BitsInit &) = delete; - BitsInit &operator=(const BitsInit &) = delete; - - // Do not use sized deallocation due to trailing objects. - void operator delete(void *p) { ::operator delete(p); } - - static bool classof(const Init *I) { - return I->getKind() == IK_BitsInit; - } - - static BitsInit *get(ArrayRef Range); - - void Profile(FoldingSetNodeID &ID) const; - - unsigned getNumBits() const { return NumBits; } - - Init *convertInitializerTo(RecTy *Ty) const override; - Init *convertInitializerBitRange(ArrayRef Bits) const override; - - bool isComplete() const override { - for (unsigned i = 0; i != getNumBits(); ++i) - if (!getBit(i)->isComplete()) return false; - return true; - } - - bool allInComplete() const { - for (unsigned i = 0; i != getNumBits(); ++i) - if (getBit(i)->isComplete()) return false; - return true; - } - - bool isConcrete() const override; - std::string getAsString() const override; - - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override { - assert(Bit < NumBits && "Bit index out of range!"); - return getTrailingObjects()[Bit]; - } -}; - -/// '7' - Represent an initialization by a literal integer value. -class IntInit : public TypedInit { - int64_t Value; - - explicit IntInit(int64_t V) - : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {} - -public: - IntInit(const IntInit &) = delete; - IntInit &operator=(const IntInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_IntInit; - } - - static IntInit *get(int64_t V); - - int64_t getValue() const { return Value; } - - Init *convertInitializerTo(RecTy *Ty) const override; - Init *convertInitializerBitRange(ArrayRef Bits) const override; - - bool isConcrete() const override { return true; } - std::string getAsString() const override; - - Init *getBit(unsigned Bit) const override { - return BitInit::get((Value & (1ULL << Bit)) != 0); - } -}; - -/// "anonymous_n" - Represent an anonymous record name -class AnonymousNameInit : public TypedInit { - unsigned Value; - - explicit AnonymousNameInit(unsigned V) - : TypedInit(IK_AnonymousNameInit, StringRecTy::get()), Value(V) {} - -public: - AnonymousNameInit(const AnonymousNameInit &) = delete; - AnonymousNameInit &operator=(const AnonymousNameInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_AnonymousNameInit; - } - - static AnonymousNameInit *get(unsigned); - - unsigned getValue() const { return Value; } - - StringInit *getNameInit() const; - - std::string getAsString() const override; - - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off string"); - } -}; - -/// "foo" - Represent an initialization by a string value. -class StringInit : public TypedInit { -public: - enum StringFormat { - SF_String, // Format as "text" - SF_Code, // Format as [{text}] - }; - -private: - StringRef Value; - StringFormat Format; - - explicit StringInit(StringRef V, StringFormat Fmt) - : TypedInit(IK_StringInit, StringRecTy::get()), Value(V), Format(Fmt) {} - -public: - StringInit(const StringInit &) = delete; - StringInit &operator=(const StringInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_StringInit; - } - - static StringInit *get(StringRef, StringFormat Fmt = SF_String); - - static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2) { - return (Fmt1 == SF_Code || Fmt2 == SF_Code) ? SF_Code : SF_String; - } - - StringRef getValue() const { return Value; } - StringFormat getFormat() const { return Format; } - bool hasCodeFormat() const { return Format == SF_Code; } - - Init *convertInitializerTo(RecTy *Ty) const override; - - bool isConcrete() const override { return true; } - - std::string getAsString() const override { - if (Format == SF_String) - return "\"" + Value.str() + "\""; - else - return "[{" + Value.str() + "}]"; - } - - std::string getAsUnquotedString() const override { - return std::string(Value); - } - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off string"); - } -}; - -/// [AL, AH, CL] - Represent a list of defs -/// -class ListInit final : public TypedInit, public FoldingSetNode, - public TrailingObjects { - unsigned NumValues; - -public: - using const_iterator = Init *const *; - -private: - explicit ListInit(unsigned N, RecTy *EltTy) - : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {} - -public: - ListInit(const ListInit &) = delete; - ListInit &operator=(const ListInit &) = delete; - - // Do not use sized deallocation due to trailing objects. - void operator delete(void *p) { ::operator delete(p); } - - static bool classof(const Init *I) { - return I->getKind() == IK_ListInit; - } - static ListInit *get(ArrayRef Range, RecTy *EltTy); - - void Profile(FoldingSetNodeID &ID) const; - - Init *getElement(unsigned i) const { - assert(i < NumValues && "List element index out of range!"); - return getTrailingObjects()[i]; - } - RecTy *getElementType() const { - return cast(getType())->getElementType(); - } - - Record *getElementAsRecord(unsigned i) const; - - Init *convertInitListSlice(ArrayRef Elements) const override; - - Init *convertInitializerTo(RecTy *Ty) const override; - - /// This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - Init *resolveReferences(Resolver &R) const override; - - bool isComplete() const override; - bool isConcrete() const override; - std::string getAsString() const override; - - ArrayRef getValues() const { - return makeArrayRef(getTrailingObjects(), NumValues); - } - - const_iterator begin() const { return getTrailingObjects(); } - const_iterator end () const { return begin() + NumValues; } - - size_t size () const { return NumValues; } - bool empty() const { return NumValues == 0; } - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off list"); - } -}; - -/// Base class for operators -/// -class OpInit : public TypedInit { -protected: - explicit OpInit(InitKind K, RecTy *Type, uint8_t Opc) - : TypedInit(K, Type, Opc) {} - -public: - OpInit(const OpInit &) = delete; - OpInit &operator=(OpInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() >= IK_FirstOpInit && - I->getKind() <= IK_LastOpInit; - } - - // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(ArrayRef Operands) const = 0; - - virtual unsigned getNumOperands() const = 0; - virtual Init *getOperand(unsigned i) const = 0; - - Init *getBit(unsigned Bit) const override; -}; - -/// !op (X) - Transform an init. -/// -class UnOpInit : public OpInit, public FoldingSetNode { -public: - enum UnaryOp : uint8_t { CAST, NOT, HEAD, TAIL, SIZE, EMPTY, GETDAGOP }; - -private: - Init *LHS; - - UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) - : OpInit(IK_UnOpInit, Type, opc), LHS(lhs) {} - -public: - UnOpInit(const UnOpInit &) = delete; - UnOpInit &operator=(const UnOpInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_UnOpInit; - } - - static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); - - void Profile(FoldingSetNodeID &ID) const; - - // Clone - Clone this operator, replacing arguments with the new list - OpInit *clone(ArrayRef Operands) const override { - assert(Operands.size() == 1 && - "Wrong number of operands for unary operation"); - return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); - } - - unsigned getNumOperands() const override { return 1; } - - Init *getOperand(unsigned i) const override { - assert(i == 0 && "Invalid operand id for unary operator"); - return getOperand(); - } - - UnaryOp getOpcode() const { return (UnaryOp)Opc; } - Init *getOperand() const { return LHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec, bool IsFinal = false) const; - - Init *resolveReferences(Resolver &R) const override; - - std::string getAsString() const override; -}; - -/// !op (X, Y) - Combine two inits. -class BinOpInit : public OpInit, public FoldingSetNode { -public: - enum BinaryOp : uint8_t { ADD, SUB, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT, - LISTSPLAT, STRCONCAT, INTERLEAVE, CONCAT, EQ, - NE, LE, LT, GE, GT, SETDAGOP }; - -private: - Init *LHS, *RHS; - - BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : - OpInit(IK_BinOpInit, Type, opc), LHS(lhs), RHS(rhs) {} - -public: - BinOpInit(const BinOpInit &) = delete; - BinOpInit &operator=(const BinOpInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_BinOpInit; - } - - static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, - RecTy *Type); - static Init *getStrConcat(Init *lhs, Init *rhs); - static Init *getListConcat(TypedInit *lhs, Init *rhs); - - void Profile(FoldingSetNodeID &ID) const; - - // Clone - Clone this operator, replacing arguments with the new list - OpInit *clone(ArrayRef Operands) const override { - assert(Operands.size() == 2 && - "Wrong number of operands for binary operation"); - return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); - } - - unsigned getNumOperands() const override { return 2; } - Init *getOperand(unsigned i) const override { - switch (i) { - default: llvm_unreachable("Invalid operand id for binary operator"); - case 0: return getLHS(); - case 1: return getRHS(); - } - } - - BinaryOp getOpcode() const { return (BinaryOp)Opc; } - Init *getLHS() const { return LHS; } - Init *getRHS() const { return RHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec) const; - - Init *resolveReferences(Resolver &R) const override; - - std::string getAsString() const override; -}; - -/// !op (X, Y, Z) - Combine two inits. -class TernOpInit : public OpInit, public FoldingSetNode { -public: - enum TernaryOp : uint8_t { SUBST, FOREACH, FILTER, IF, DAG, SUBSTR, FIND }; - -private: - Init *LHS, *MHS, *RHS; - - TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, - RecTy *Type) : - OpInit(IK_TernOpInit, Type, opc), LHS(lhs), MHS(mhs), RHS(rhs) {} - -public: - TernOpInit(const TernOpInit &) = delete; - TernOpInit &operator=(const TernOpInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_TernOpInit; - } - - static TernOpInit *get(TernaryOp opc, Init *lhs, - Init *mhs, Init *rhs, - RecTy *Type); - - void Profile(FoldingSetNodeID &ID) const; - - // Clone - Clone this operator, replacing arguments with the new list - OpInit *clone(ArrayRef Operands) const override { - assert(Operands.size() == 3 && - "Wrong number of operands for ternary operation"); - return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2], - getType()); - } - - unsigned getNumOperands() const override { return 3; } - Init *getOperand(unsigned i) const override { - switch (i) { - default: llvm_unreachable("Invalid operand id for ternary operator"); - case 0: return getLHS(); - case 1: return getMHS(); - case 2: return getRHS(); - } - } - - TernaryOp getOpcode() const { return (TernaryOp)Opc; } - Init *getLHS() const { return LHS; } - Init *getMHS() const { return MHS; } - Init *getRHS() const { return RHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec) const; - - bool isComplete() const override { - return LHS->isComplete() && MHS->isComplete() && RHS->isComplete(); - } - - Init *resolveReferences(Resolver &R) const override; - - std::string getAsString() const override; -}; - -/// !cond(condition_1: value1, ... , condition_n: value) -/// Selects the first value for which condition is true. -/// Otherwise reports an error. -class CondOpInit final : public TypedInit, public FoldingSetNode, - public TrailingObjects { - unsigned NumConds; - RecTy *ValType; - - CondOpInit(unsigned NC, RecTy *Type) - : TypedInit(IK_CondOpInit, Type), - NumConds(NC), ValType(Type) {} - - size_t numTrailingObjects(OverloadToken) const { - return 2*NumConds; - } - -public: - CondOpInit(const CondOpInit &) = delete; - CondOpInit &operator=(const CondOpInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_CondOpInit; - } - - static CondOpInit *get(ArrayRef C, ArrayRef V, - RecTy *Type); - - void Profile(FoldingSetNodeID &ID) const; - - RecTy *getValType() const { return ValType; } - - unsigned getNumConds() const { return NumConds; } - - Init *getCond(unsigned Num) const { - assert(Num < NumConds && "Condition number out of range!"); - return getTrailingObjects()[Num]; - } - - Init *getVal(unsigned Num) const { - assert(Num < NumConds && "Val number out of range!"); - return getTrailingObjects()[Num+NumConds]; - } - - ArrayRef getConds() const { - return makeArrayRef(getTrailingObjects(), NumConds); - } - - ArrayRef getVals() const { - return makeArrayRef(getTrailingObjects()+NumConds, NumConds); - } - - Init *Fold(Record *CurRec) const; - - Init *resolveReferences(Resolver &R) const override; - - bool isConcrete() const override; - bool isComplete() const override; - std::string getAsString() const override; - - using const_case_iterator = SmallVectorImpl::const_iterator; - using const_val_iterator = SmallVectorImpl::const_iterator; - - inline const_case_iterator arg_begin() const { return getConds().begin(); } - inline const_case_iterator arg_end () const { return getConds().end(); } - - inline size_t case_size () const { return NumConds; } - inline bool case_empty() const { return NumConds == 0; } - - inline const_val_iterator name_begin() const { return getVals().begin();} - inline const_val_iterator name_end () const { return getVals().end(); } - - inline size_t val_size () const { return NumConds; } - inline bool val_empty() const { return NumConds == 0; } - - Init *getBit(unsigned Bit) const override; -}; - -/// !foldl (a, b, expr, start, lst) - Fold over a list. -class FoldOpInit : public TypedInit, public FoldingSetNode { -private: - Init *Start; - Init *List; - Init *A; - Init *B; - Init *Expr; - - FoldOpInit(Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type) - : TypedInit(IK_FoldOpInit, Type), Start(Start), List(List), A(A), B(B), - Expr(Expr) {} - -public: - FoldOpInit(const FoldOpInit &) = delete; - FoldOpInit &operator=(const FoldOpInit &) = delete; - - static bool classof(const Init *I) { return I->getKind() == IK_FoldOpInit; } - - static FoldOpInit *get(Init *Start, Init *List, Init *A, Init *B, Init *Expr, - RecTy *Type); - - void Profile(FoldingSetNodeID &ID) const; - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec) const; - - bool isComplete() const override { return false; } - - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override; - - std::string getAsString() const override; -}; - -/// !isa(expr) - Dynamically determine the type of an expression. -class IsAOpInit : public TypedInit, public FoldingSetNode { -private: - RecTy *CheckType; - Init *Expr; - - IsAOpInit(RecTy *CheckType, Init *Expr) - : TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType), - Expr(Expr) {} - -public: - IsAOpInit(const IsAOpInit &) = delete; - IsAOpInit &operator=(const IsAOpInit &) = delete; - - static bool classof(const Init *I) { return I->getKind() == IK_IsAOpInit; } - - static IsAOpInit *get(RecTy *CheckType, Init *Expr); - - void Profile(FoldingSetNodeID &ID) const; - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold() const; - - bool isComplete() const override { return false; } - - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override; - - std::string getAsString() const override; -}; - -/// 'Opcode' - Represent a reference to an entire variable object. -class VarInit : public TypedInit { - Init *VarName; - - explicit VarInit(Init *VN, RecTy *T) - : TypedInit(IK_VarInit, T), VarName(VN) {} - -public: - VarInit(const VarInit &) = delete; - VarInit &operator=(const VarInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_VarInit; - } - - static VarInit *get(StringRef VN, RecTy *T); - static VarInit *get(Init *VN, RecTy *T); - - StringRef getName() const; - Init *getNameInit() const { return VarName; } - - std::string getNameInitAsString() const { - return getNameInit()->getAsUnquotedString(); - } - - /// This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override; - - std::string getAsString() const override { return std::string(getName()); } -}; - -/// Opcode{0} - Represent access to one bit of a variable or field. -class VarBitInit final : public TypedInit { - TypedInit *TI; - unsigned Bit; - - VarBitInit(TypedInit *T, unsigned B) - : TypedInit(IK_VarBitInit, BitRecTy::get()), TI(T), Bit(B) { - assert(T->getType() && - (isa(T->getType()) || - (isa(T->getType()) && - cast(T->getType())->getNumBits() > B)) && - "Illegal VarBitInit expression!"); - } - -public: - VarBitInit(const VarBitInit &) = delete; - VarBitInit &operator=(const VarBitInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_VarBitInit; - } - - static VarBitInit *get(TypedInit *T, unsigned B); - - Init *getBitVar() const { return TI; } - unsigned getBitNum() const { return Bit; } - - std::string getAsString() const override; - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned B) const override { - assert(B < 1 && "Bit index out of range!"); - return const_cast(this); - } -}; - -/// List[4] - Represent access to one element of a var or -/// field. -class VarListElementInit : public TypedInit { - TypedInit *TI; - unsigned Element; - - VarListElementInit(TypedInit *T, unsigned E) - : TypedInit(IK_VarListElementInit, - cast(T->getType())->getElementType()), - TI(T), Element(E) { - assert(T->getType() && isa(T->getType()) && - "Illegal VarBitInit expression!"); - } - -public: - VarListElementInit(const VarListElementInit &) = delete; - VarListElementInit &operator=(const VarListElementInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_VarListElementInit; - } - - static VarListElementInit *get(TypedInit *T, unsigned E); - - TypedInit *getVariable() const { return TI; } - unsigned getElementNum() const { return Element; } - - std::string getAsString() const override; - Init *resolveReferences(Resolver &R) const override; - - Init *getBit(unsigned Bit) const override; -}; - -/// AL - Represent a reference to a 'def' in the description -class DefInit : public TypedInit { - friend class Record; - - Record *Def; - - explicit DefInit(Record *D); - -public: - DefInit(const DefInit &) = delete; - DefInit &operator=(const DefInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_DefInit; - } - - static DefInit *get(Record*); - - Init *convertInitializerTo(RecTy *Ty) const override; - - Record *getDef() const { return Def; } - - //virtual Init *convertInitializerBitRange(ArrayRef Bits); - - RecTy *getFieldType(StringInit *FieldName) const override; - - bool isConcrete() const override { return true; } - std::string getAsString() const override; - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off def"); - } -}; - -/// classname - Represent an uninstantiated anonymous class -/// instantiation. -class VarDefInit final : public TypedInit, public FoldingSetNode, - public TrailingObjects { - Record *Class; - DefInit *Def = nullptr; // after instantiation - unsigned NumArgs; - - explicit VarDefInit(Record *Class, unsigned N) - : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {} - - DefInit *instantiate(); - -public: - VarDefInit(const VarDefInit &) = delete; - VarDefInit &operator=(const VarDefInit &) = delete; - - // Do not use sized deallocation due to trailing objects. - void operator delete(void *p) { ::operator delete(p); } - - static bool classof(const Init *I) { - return I->getKind() == IK_VarDefInit; - } - static VarDefInit *get(Record *Class, ArrayRef Args); - - void Profile(FoldingSetNodeID &ID) const; - - Init *resolveReferences(Resolver &R) const override; - Init *Fold() const; - - std::string getAsString() const override; - - Init *getArg(unsigned i) const { - assert(i < NumArgs && "Argument index out of range!"); - return getTrailingObjects()[i]; - } - - using const_iterator = Init *const *; - - const_iterator args_begin() const { return getTrailingObjects(); } - const_iterator args_end () const { return args_begin() + NumArgs; } - - size_t args_size () const { return NumArgs; } - bool args_empty() const { return NumArgs == 0; } - - ArrayRef args() const { return makeArrayRef(args_begin(), NumArgs); } - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off anonymous def"); - } -}; - -/// X.Y - Represent a reference to a subfield of a variable -class FieldInit : public TypedInit { - Init *Rec; // Record we are referring to - StringInit *FieldName; // Field we are accessing - - FieldInit(Init *R, StringInit *FN) - : TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) { -#ifndef NDEBUG - if (!getType()) { - llvm::errs() << "In Record = " << Rec->getAsString() - << ", got FieldName = " << *FieldName - << " with non-record type!\n"; - llvm_unreachable("FieldInit with non-record type!"); - } -#endif - } - -public: - FieldInit(const FieldInit &) = delete; - FieldInit &operator=(const FieldInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_FieldInit; - } - - static FieldInit *get(Init *R, StringInit *FN); - - Init *getRecord() const { return Rec; } - StringInit *getFieldName() const { return FieldName; } - - Init *getBit(unsigned Bit) const override; - - Init *resolveReferences(Resolver &R) const override; - Init *Fold(Record *CurRec) const; - - bool isConcrete() const override; - std::string getAsString() const override { - return Rec->getAsString() + "." + FieldName->getValue().str(); - } -}; - -/// (v a, b) - Represent a DAG tree value. DAG inits are required -/// to have at least one value then a (possibly empty) list of arguments. Each -/// argument can have a name associated with it. -class DagInit final : public TypedInit, public FoldingSetNode, - public TrailingObjects { - friend TrailingObjects; - - Init *Val; - StringInit *ValName; - unsigned NumArgs; - unsigned NumArgNames; - - DagInit(Init *V, StringInit *VN, unsigned NumArgs, unsigned NumArgNames) - : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN), - NumArgs(NumArgs), NumArgNames(NumArgNames) {} - - size_t numTrailingObjects(OverloadToken) const { return NumArgs; } - -public: - DagInit(const DagInit &) = delete; - DagInit &operator=(const DagInit &) = delete; - - static bool classof(const Init *I) { - return I->getKind() == IK_DagInit; - } - - static DagInit *get(Init *V, StringInit *VN, ArrayRef ArgRange, - ArrayRef NameRange); - static DagInit *get(Init *V, StringInit *VN, - ArrayRef> Args); - - void Profile(FoldingSetNodeID &ID) const; - - Init *getOperator() const { return Val; } - Record *getOperatorAsDef(ArrayRef Loc) const; - - StringInit *getName() const { return ValName; } - - StringRef getNameStr() const { - return ValName ? ValName->getValue() : StringRef(); - } - - unsigned getNumArgs() const { return NumArgs; } - - Init *getArg(unsigned Num) const { - assert(Num < NumArgs && "Arg number out of range!"); - return getTrailingObjects()[Num]; - } - - StringInit *getArgName(unsigned Num) const { - assert(Num < NumArgNames && "Arg number out of range!"); - return getTrailingObjects()[Num]; - } - - StringRef getArgNameStr(unsigned Num) const { - StringInit *Init = getArgName(Num); - return Init ? Init->getValue() : StringRef(); - } - - ArrayRef getArgs() const { - return makeArrayRef(getTrailingObjects(), NumArgs); - } - - ArrayRef getArgNames() const { - return makeArrayRef(getTrailingObjects(), NumArgNames); - } - - Init *resolveReferences(Resolver &R) const override; - - bool isConcrete() const override; - std::string getAsString() const override; - - using const_arg_iterator = SmallVectorImpl::const_iterator; - using const_name_iterator = SmallVectorImpl::const_iterator; - - inline const_arg_iterator arg_begin() const { return getArgs().begin(); } - inline const_arg_iterator arg_end () const { return getArgs().end(); } - - inline size_t arg_size () const { return NumArgs; } - inline bool arg_empty() const { return NumArgs == 0; } - - inline const_name_iterator name_begin() const { return getArgNames().begin();} - inline const_name_iterator name_end () const { return getArgNames().end(); } - - inline size_t name_size () const { return NumArgNames; } - inline bool name_empty() const { return NumArgNames == 0; } - - Init *getBit(unsigned Bit) const override { - llvm_unreachable("Illegal bit reference off dag"); - } -}; - -//===----------------------------------------------------------------------===// -// High-Level Classes -//===----------------------------------------------------------------------===// - -/// This class represents a field in a record, including its name, type, -/// value, and source location. -class RecordVal { - friend class Record; - -public: - enum FieldKind { - FK_Normal, // A normal record field. - FK_NonconcreteOK, // A field that can be nonconcrete ('field' keyword). - FK_TemplateArg, // A template argument. - }; - -private: - Init *Name; - SMLoc Loc; // Source location of definition of name. - PointerIntPair TyAndKind; - Init *Value; - bool IsUsed = false; - -public: - RecordVal(Init *N, RecTy *T, FieldKind K); - RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K); - - /// Get the name of the field as a StringRef. - StringRef getName() const; - - /// Get the name of the field as an Init. - Init *getNameInit() const { return Name; } - - /// Get the name of the field as a std::string. - std::string getNameInitAsString() const { - return getNameInit()->getAsUnquotedString(); - } - - /// Get the source location of the point where the field was defined. - const SMLoc &getLoc() const { return Loc; } - - /// Is this a field where nonconcrete values are okay? - bool isNonconcreteOK() const { - return TyAndKind.getInt() == FK_NonconcreteOK; - } - - /// Is this a template argument? - bool isTemplateArg() const { - return TyAndKind.getInt() == FK_TemplateArg; - } - - /// Get the type of the field value as a RecTy. - RecTy *getType() const { return TyAndKind.getPointer(); } - - /// Get the type of the field for printing purposes. - std::string getPrintType() const; - - /// Get the value of the field as an Init. - Init *getValue() const { return Value; } - - /// Set the value of the field from an Init. - bool setValue(Init *V); - - /// Set the value and source location of the field. - bool setValue(Init *V, SMLoc NewLoc); - - /// Whether this value is used. Useful for reporting warnings, for example - /// when a template argument is unused. - void setUsed(bool Used) { IsUsed = Used; } - bool isUsed() const { return IsUsed; } - - void dump() const; - - /// Print the value to an output stream, possibly with a semicolon. - void print(raw_ostream &OS, bool PrintSem = true) const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) { - RV.print(OS << " "); - return OS; -} - -class Record { -public: - struct AssertionInfo { - SMLoc Loc; - Init *Condition; - Init *Message; - - // User-defined constructor to support std::make_unique(). It can be - // removed in C++20 when braced initialization is supported. - AssertionInfo(SMLoc Loc, Init *Condition, Init *Message) - : Loc(Loc), Condition(Condition), Message(Message) {} - }; - -private: - Init *Name; - // Location where record was instantiated, followed by the location of - // multiclass prototypes used. - SmallVector Locs; - SmallVector TemplateArgs; - SmallVector Values; - SmallVector Assertions; - - // All superclasses in the inheritance forest in post-order (yes, it - // must be a forest; diamond-shaped inheritance is not allowed). - SmallVector, 0> SuperClasses; - - // Tracks Record instances. Not owned by Record. - RecordKeeper &TrackedRecords; - - // The DefInit corresponding to this record. - DefInit *CorrespondingDefInit = nullptr; - - // Unique record ID. - unsigned ID; - - bool IsAnonymous; - bool IsClass; - - void checkName(); - -public: - // Constructs a record. - explicit Record(Init *N, ArrayRef locs, RecordKeeper &records, - bool Anonymous = false, bool Class = false) - : Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records), - ID(getNewUID()), IsAnonymous(Anonymous), IsClass(Class) { - checkName(); - } - - explicit Record(StringRef N, ArrayRef locs, RecordKeeper &records, - bool Class = false) - : Record(StringInit::get(N), locs, records, false, Class) {} - - // When copy-constructing a Record, we must still guarantee a globally unique - // ID number. Don't copy CorrespondingDefInit either, since it's owned by the - // original record. All other fields can be copied normally. - Record(const Record &O) - : Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), - Values(O.Values), Assertions(O.Assertions), - SuperClasses(O.SuperClasses), TrackedRecords(O.TrackedRecords), - ID(getNewUID()), IsAnonymous(O.IsAnonymous), IsClass(O.IsClass) {} - - static unsigned getNewUID(); - - unsigned getID() const { return ID; } - - StringRef getName() const { return cast(Name)->getValue(); } - - Init *getNameInit() const { - return Name; - } - - const std::string getNameInitAsString() const { - return getNameInit()->getAsUnquotedString(); - } - - void setName(Init *Name); // Also updates RecordKeeper. - - ArrayRef getLoc() const { return Locs; } - void appendLoc(SMLoc Loc) { Locs.push_back(Loc); } - - // Make the type that this record should have based on its superclasses. - RecordRecTy *getType(); - - /// get the corresponding DefInit. - DefInit *getDefInit(); - - bool isClass() const { return IsClass; } - - ArrayRef getTemplateArgs() const { - return TemplateArgs; - } - - ArrayRef getValues() const { return Values; } - - ArrayRef getAssertions() const { return Assertions; } - - ArrayRef> getSuperClasses() const { - return SuperClasses; - } - - /// Determine whether this record has the specified direct superclass. - bool hasDirectSuperClass(const Record *SuperClass) const; - - /// Append the direct superclasses of this record to Classes. - void getDirectSuperClasses(SmallVectorImpl &Classes) const; - - bool isTemplateArg(Init *Name) const { - return llvm::is_contained(TemplateArgs, Name); - } - - const RecordVal *getValue(const Init *Name) const { - for (const RecordVal &Val : Values) - if (Val.Name == Name) return &Val; - return nullptr; - } - - const RecordVal *getValue(StringRef Name) const { - return getValue(StringInit::get(Name)); - } - - RecordVal *getValue(const Init *Name) { - return const_cast(static_cast(this)->getValue(Name)); - } - - RecordVal *getValue(StringRef Name) { - return const_cast(static_cast(this)->getValue(Name)); - } - - void addTemplateArg(Init *Name) { - assert(!isTemplateArg(Name) && "Template arg already defined!"); - TemplateArgs.push_back(Name); - } - - void addValue(const RecordVal &RV) { - assert(getValue(RV.getNameInit()) == nullptr && "Value already added!"); - Values.push_back(RV); - } - - void removeValue(Init *Name) { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getNameInit() == Name) { - Values.erase(Values.begin()+i); - return; - } - llvm_unreachable("Cannot remove an entry that does not exist!"); - } - - void removeValue(StringRef Name) { - removeValue(StringInit::get(Name)); - } - - void addAssertion(SMLoc Loc, Init *Condition, Init *Message) { - Assertions.push_back(AssertionInfo(Loc, Condition, Message)); - } - - void appendAssertions(const Record *Rec) { - Assertions.append(Rec->Assertions); - } - - void checkRecordAssertions(); - void checkUnusedTemplateArgs(); - - bool isSubClassOf(const Record *R) const { - for (const auto &SCPair : SuperClasses) - if (SCPair.first == R) - return true; - return false; - } - - bool isSubClassOf(StringRef Name) const { - for (const auto &SCPair : SuperClasses) { - if (const auto *SI = dyn_cast(SCPair.first->getNameInit())) { - if (SI->getValue() == Name) - return true; - } else if (SCPair.first->getNameInitAsString() == Name) { - return true; - } - } - return false; - } - - void addSuperClass(Record *R, SMRange Range) { - assert(!CorrespondingDefInit && - "changing type of record after it has been referenced"); - assert(!isSubClassOf(R) && "Already subclassing record!"); - SuperClasses.push_back(std::make_pair(R, Range)); - } - - /// If there are any field references that refer to fields - /// that have been filled in, we can propagate the values now. - /// - /// This is a final resolve: any error messages, e.g. due to undefined - /// !cast references, are generated now. - void resolveReferences(Init *NewName = nullptr); - - /// Apply the resolver to the name of the record as well as to the - /// initializers of all fields of the record except SkipVal. - /// - /// The resolver should not resolve any of the fields itself, to avoid - /// recursion / infinite loops. - void resolveReferences(Resolver &R, const RecordVal *SkipVal = nullptr); - - RecordKeeper &getRecords() const { - return TrackedRecords; - } - - bool isAnonymous() const { - return IsAnonymous; - } - - void dump() const; - - //===--------------------------------------------------------------------===// - // High-level methods useful to tablegen back-ends - // - - ///Return the source location for the named field. - SMLoc getFieldLoc(StringRef FieldName) const; - - /// Return the initializer for a value with the specified name, - /// or throw an exception if the field does not exist. - Init *getValueInit(StringRef FieldName) const; - - /// Return true if the named field is unset. - bool isValueUnset(StringRef FieldName) const { - return isa(getValueInit(FieldName)); - } - - /// This method looks up the specified field and returns - /// its value as a string, throwing an exception if the field does not exist - /// or if the value is not a string. - StringRef getValueAsString(StringRef FieldName) const; - - /// This method looks up the specified field and returns - /// its value as a string, throwing an exception if the field if the value is - /// not a string and llvm::Optional() if the field does not exist. - llvm::Optional getValueAsOptionalString(StringRef FieldName) const; - - /// This method looks up the specified field and returns - /// its value as a BitsInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - BitsInit *getValueAsBitsInit(StringRef FieldName) const; - - /// This method looks up the specified field and returns - /// its value as a ListInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - ListInit *getValueAsListInit(StringRef FieldName) const; - - /// This method looks up the specified field and - /// returns its value as a vector of records, throwing an exception if the - /// field does not exist or if the value is not the right type. - std::vector getValueAsListOfDefs(StringRef FieldName) const; - - /// This method looks up the specified field and - /// returns its value as a vector of integers, throwing an exception if the - /// field does not exist or if the value is not the right type. - std::vector getValueAsListOfInts(StringRef FieldName) const; - - /// This method looks up the specified field and - /// returns its value as a vector of strings, throwing an exception if the - /// field does not exist or if the value is not the right type. - std::vector getValueAsListOfStrings(StringRef FieldName) const; - - /// This method looks up the specified field and returns its - /// value as a Record, throwing an exception if the field does not exist or if - /// the value is not the right type. - Record *getValueAsDef(StringRef FieldName) const; - - /// This method looks up the specified field and returns its value as a - /// Record, returning null if the field exists but is "uninitialized" - /// (i.e. set to `?`), and throwing an exception if the field does not - /// exist or if its value is not the right type. - Record *getValueAsOptionalDef(StringRef FieldName) const; - - /// This method looks up the specified field and returns its - /// value as a bit, throwing an exception if the field does not exist or if - /// the value is not the right type. - bool getValueAsBit(StringRef FieldName) const; - - /// This method looks up the specified field and - /// returns its value as a bit. If the field is unset, sets Unset to true and - /// returns false. - bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const; - - /// This method looks up the specified field and returns its - /// value as an int64_t, throwing an exception if the field does not exist or - /// if the value is not the right type. - int64_t getValueAsInt(StringRef FieldName) const; - - /// This method looks up the specified field and returns its - /// value as an Dag, throwing an exception if the field does not exist or if - /// the value is not the right type. - DagInit *getValueAsDag(StringRef FieldName) const; -}; - -raw_ostream &operator<<(raw_ostream &OS, const Record &R); - -class RecordKeeper { - friend class RecordRecTy; - - using RecordMap = std::map, std::less<>>; - using GlobalMap = std::map>; - - std::string InputFilename; - RecordMap Classes, Defs; - mutable StringMap> ClassRecordsMap; - FoldingSet RecordTypePool; - std::map> ExtraGlobals; - unsigned AnonCounter = 0; - - // These members are for the phase timing feature. We need a timer group, - // the last timer started, and a flag to say whether the last timer - // is the special "backend overall timer." - TimerGroup *TimingGroup = nullptr; - Timer *LastTimer = nullptr; - bool BackendTimer = false; - -public: - /// Get the main TableGen input file's name. - const std::string getInputFilename() const { return InputFilename; } - - /// Get the map of classes. - const RecordMap &getClasses() const { return Classes; } - - /// Get the map of records (defs). - const RecordMap &getDefs() const { return Defs; } - - /// Get the map of global variables. - const GlobalMap &getGlobals() const { return ExtraGlobals; } - - /// Get the class with the specified name. - Record *getClass(StringRef Name) const { - auto I = Classes.find(Name); - return I == Classes.end() ? nullptr : I->second.get(); - } - - /// Get the concrete record with the specified name. - Record *getDef(StringRef Name) const { - auto I = Defs.find(Name); - return I == Defs.end() ? nullptr : I->second.get(); - } - - /// Get the \p Init value of the specified global variable. - Init *getGlobal(StringRef Name) const { - if (Record *R = getDef(Name)) - return R->getDefInit(); - auto It = ExtraGlobals.find(Name); - return It == ExtraGlobals.end() ? nullptr : It->second; - } - - void saveInputFilename(std::string Filename) { - InputFilename = Filename; - } - - void addClass(std::unique_ptr R) { - bool Ins = Classes.insert(std::make_pair(std::string(R->getName()), - std::move(R))).second; - (void)Ins; - assert(Ins && "Class already exists"); - } - - void addDef(std::unique_ptr R) { - bool Ins = Defs.insert(std::make_pair(std::string(R->getName()), - std::move(R))).second; - (void)Ins; - assert(Ins && "Record already exists"); - } - - void addExtraGlobal(StringRef Name, Init *I) { - bool Ins = ExtraGlobals.insert(std::make_pair(std::string(Name), I)).second; - (void)Ins; - assert(!getDef(Name)); - assert(Ins && "Global already exists"); - } - - Init *getNewAnonymousName(); - - /// Start phase timing; called if the --time-phases option is specified. - void startPhaseTiming() { - TimingGroup = new TimerGroup("TableGen", "TableGen Phase Timing"); - } - - /// Start timing a phase. Automatically stops any previous phase timer. - void startTimer(StringRef Name); - - /// Stop timing a phase. - void stopTimer(); - - /// Start timing the overall backend. If the backend itself starts a timer, - /// then this timer is cleared. - void startBackendTimer(StringRef Name); - - /// Stop timing the overall backend. - void stopBackendTimer(); - - /// Stop phase timing and print the report. - void stopPhaseTiming() { - if (TimingGroup) - delete TimingGroup; - } - - //===--------------------------------------------------------------------===// - // High-level helper methods, useful for tablegen backends. - - /// Get all the concrete records that inherit from the one specified - /// class. The class must be defined. - std::vector getAllDerivedDefinitions(StringRef ClassName) const; - - /// Get all the concrete records that inherit from all the specified - /// classes. The classes must be defined. - std::vector getAllDerivedDefinitions( - ArrayRef ClassNames) const; - - void dump() const; -}; - -/// Sorting predicate to sort record pointers by name. -struct LessRecord { - bool operator()(const Record *Rec1, const Record *Rec2) const { - return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0; - } -}; - -/// Sorting predicate to sort record pointers by their -/// unique ID. If you just need a deterministic order, use this, since it -/// just compares two `unsigned`; the other sorting predicates require -/// string manipulation. -struct LessRecordByID { - bool operator()(const Record *LHS, const Record *RHS) const { - return LHS->getID() < RHS->getID(); - } -}; - -/// Sorting predicate to sort record pointers by their -/// name field. -struct LessRecordFieldName { - bool operator()(const Record *Rec1, const Record *Rec2) const { - return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name"); - } -}; - -struct LessRecordRegister { - struct RecordParts { - SmallVector, 4> Parts; - - RecordParts(StringRef Rec) { - if (Rec.empty()) - return; - - size_t Len = 0; - const char *Start = Rec.data(); - const char *Curr = Start; - bool IsDigitPart = isDigit(Curr[0]); - for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) { - bool IsDigit = isDigit(Curr[I]); - if (IsDigit != IsDigitPart) { - Parts.push_back(std::make_pair(IsDigitPart, StringRef(Start, Len))); - Len = 0; - Start = &Curr[I]; - IsDigitPart = isDigit(Curr[I]); - } - } - // Push the last part. - Parts.push_back(std::make_pair(IsDigitPart, StringRef(Start, Len))); - } - - size_t size() { return Parts.size(); } - - std::pair getPart(size_t i) { - assert (i < Parts.size() && "Invalid idx!"); - return Parts[i]; - } - }; - - bool operator()(const Record *Rec1, const Record *Rec2) const { - RecordParts LHSParts(StringRef(Rec1->getName())); - RecordParts RHSParts(StringRef(Rec2->getName())); - - size_t LHSNumParts = LHSParts.size(); - size_t RHSNumParts = RHSParts.size(); - assert (LHSNumParts && RHSNumParts && "Expected at least one part!"); - - if (LHSNumParts != RHSNumParts) - return LHSNumParts < RHSNumParts; - - // We expect the registers to be of the form [_a-zA-Z]+([0-9]*[_a-zA-Z]*)*. - for (size_t I = 0, E = LHSNumParts; I < E; I+=2) { - std::pair LHSPart = LHSParts.getPart(I); - std::pair RHSPart = RHSParts.getPart(I); - // Expect even part to always be alpha. - assert (LHSPart.first == false && RHSPart.first == false && - "Expected both parts to be alpha."); - if (int Res = LHSPart.second.compare(RHSPart.second)) - return Res < 0; - } - for (size_t I = 1, E = LHSNumParts; I < E; I+=2) { - std::pair LHSPart = LHSParts.getPart(I); - std::pair RHSPart = RHSParts.getPart(I); - // Expect odd part to always be numeric. - assert (LHSPart.first == true && RHSPart.first == true && - "Expected both parts to be numeric."); - if (LHSPart.second.size() != RHSPart.second.size()) - return LHSPart.second.size() < RHSPart.second.size(); - - unsigned LHSVal, RHSVal; - - bool LHSFailed = LHSPart.second.getAsInteger(10, LHSVal); (void)LHSFailed; - assert(!LHSFailed && "Unable to convert LHS to integer."); - bool RHSFailed = RHSPart.second.getAsInteger(10, RHSVal); (void)RHSFailed; - assert(!RHSFailed && "Unable to convert RHS to integer."); - - if (LHSVal != RHSVal) - return LHSVal < RHSVal; - } - return LHSNumParts < RHSNumParts; - } -}; - -raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); - -//===----------------------------------------------------------------------===// -// Resolvers -//===----------------------------------------------------------------------===// - -/// Interface for looking up the initializer for a variable name, used by -/// Init::resolveReferences. -class Resolver { - Record *CurRec; - bool IsFinal = false; - -public: - explicit Resolver(Record *CurRec) : CurRec(CurRec) {} - virtual ~Resolver() = default; - - Record *getCurrentRecord() const { return CurRec; } - - /// Return the initializer for the given variable name (should normally be a - /// StringInit), or nullptr if the name could not be resolved. - virtual Init *resolve(Init *VarName) = 0; - - // Whether bits in a BitsInit should stay unresolved if resolving them would - // result in a ? (UnsetInit). This behavior is used to represent instruction - // encodings by keeping references to unset variables within a record. - virtual bool keepUnsetBits() const { return false; } - - // Whether this is the final resolve step before adding a record to the - // RecordKeeper. Error reporting during resolve and related constant folding - // should only happen when this is true. - bool isFinal() const { return IsFinal; } - - void setFinal(bool Final) { IsFinal = Final; } -}; - -/// Resolve arbitrary mappings. -class MapResolver final : public Resolver { - struct MappedValue { - Init *V; - bool Resolved; - - MappedValue() : V(nullptr), Resolved(false) {} - MappedValue(Init *V, bool Resolved) : V(V), Resolved(Resolved) {} - }; - - DenseMap Map; - -public: - explicit MapResolver(Record *CurRec = nullptr) : Resolver(CurRec) {} - - void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; } - - bool isComplete(Init *VarName) const { - auto It = Map.find(VarName); - assert(It != Map.end() && "key must be present in map"); - return It->second.V->isComplete(); - } - - Init *resolve(Init *VarName) override; -}; - -/// Resolve all variables from a record except for unset variables. -class RecordResolver final : public Resolver { - DenseMap Cache; - SmallVector Stack; - Init *Name = nullptr; - -public: - explicit RecordResolver(Record &R) : Resolver(&R) {} - - void setName(Init *NewName) { Name = NewName; } - - Init *resolve(Init *VarName) override; - - bool keepUnsetBits() const override { return true; } -}; - -/// Delegate resolving to a sub-resolver, but shadow some variable names. -class ShadowResolver final : public Resolver { - Resolver &R; - DenseSet Shadowed; - -public: - explicit ShadowResolver(Resolver &R) - : Resolver(R.getCurrentRecord()), R(R) { - setFinal(R.isFinal()); - } - - void addShadow(Init *Key) { Shadowed.insert(Key); } - - Init *resolve(Init *VarName) override { - if (Shadowed.count(VarName)) - return nullptr; - return R.resolve(VarName); - } -}; - -/// (Optionally) delegate resolving to a sub-resolver, and keep track whether -/// there were unresolved references. -class TrackUnresolvedResolver final : public Resolver { - Resolver *R; - bool FoundUnresolved = false; - -public: - explicit TrackUnresolvedResolver(Resolver *R = nullptr) - : Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {} - - bool foundUnresolved() const { return FoundUnresolved; } - - Init *resolve(Init *VarName) override; -}; - -/// Do not resolve anything, but keep track of whether a given variable was -/// referenced. -class HasReferenceResolver final : public Resolver { - Init *VarNameToTrack; - bool Found = false; - -public: - explicit HasReferenceResolver(Init *VarNameToTrack) - : Resolver(nullptr), VarNameToTrack(VarNameToTrack) {} - - bool found() const { return Found; } - - Init *resolve(Init *VarName) override; -}; - -void EmitDetailedRecords(RecordKeeper &RK, raw_ostream &OS); -void EmitJSON(RecordKeeper &RK, raw_ostream &OS); - -} // end namespace llvm - -#endif // LLVM_TABLEGEN_RECORD_H diff --git a/suite/synctools/tablegen/include/llvm/TableGen/SearchableTable.td b/suite/synctools/tablegen/include/llvm/TableGen/SearchableTable.td deleted file mode 100644 index 61dfa5c707..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/SearchableTable.td +++ /dev/null @@ -1,139 +0,0 @@ -//===- SearchableTable.td ----------------------------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the key top-level classes needed to produce a reasonably -// generic table that can be binary-searched. Three types of objects can be -// defined using the classes in this file: -// -// 1. (Generic) Enums. By instantiating the GenericEnum class once, an enum with -// the name of the def is generated. It is guarded by the preprocessor define -// GET_name_DECL, where name is the name of the def. -// -// 2. (Generic) Tables and search indices. By instantiating the GenericTable -// class once, a table with the name of the instantiating def is generated and -// guarded by the GET_name_IMPL preprocessor guard. -// -// Both a primary key and additional secondary keys / search indices can also -// be defined, which result in the generation of lookup functions. Their -// declarations and definitions are all guarded by GET_name_DECL and -// GET_name_IMPL, respectively, where name is the name of the underlying table. -// -// See AArch64SystemOperands.td and its generated header for example uses. -// -//===----------------------------------------------------------------------===// - -// Define a record derived from this class to generate a generic enum. -// -// The name of the record is used as the type name of the C++ enum. -class GenericEnum { - // Name of a TableGen class. The enum will have one entry for each record - // that derives from that class. - string FilterClass; - - // (Optional) Name of a field that is present in all collected records and - // contains the name of enum entries. - // - // If NameField is not set, the record names will be used instead. - string NameField; - - // (Optional) Name of a field that is present in all collected records and - // contains the numerical value of enum entries. - // - // If ValueField is not set, enum values will be assigned automatically, - // starting at 0, according to a lexicographical sort of the entry names. - string ValueField; -} - -// Define a record derived from this class to generate a generic table. This -// table can have a searchable primary key, and it can also be referenced by -// external search indices. -// -// The name of the record is used as the name of the global primary array of -// entries of the table in C++. -class GenericTable { - // Name of a class. The table will have one entry for each record that - // derives from that class. - string FilterClass; - - // Name of the C++ struct/class type that holds table entries. The - // declaration of this type is not generated automatically. - string CppTypeName = FilterClass; - - // List of the names of fields of collected records that contain the data for - // table entries, in the order that is used for initialization in C++. - // - // TableGen needs to know the type of the fields so that it can format - // the initializers correctly. It can infer the type of bit, bits, string, - // Intrinsic, and Instruction values. - // - // For each field of the table named xxx, TableGen will look for a field - // named TypeOf_xxx and use that as a more detailed description of the - // type of the field. This is required for fields whose type - // cannot be deduced automatically, such as enum fields. For example: - // - // def MyEnum : GenericEnum { - // let FilterClass = "MyEnum"; - // ... - // } - // - // class MyTableEntry { - // MyEnum V; - // ... - // } - // - // def MyTable : GenericTable { - // let FilterClass = "MyTableEntry"; - // let Fields = ["V", ...]; - // string TypeOf_V = "MyEnum"; - // } - // - // If a string field was initialized with a code literal, TableGen will - // emit the code verbatim. However, if a string field was initialized - // in some other way, but should be interpreted as code, then a TypeOf_xxx - // field is necessary, with a value of "code": - // - // string TypeOf_Predicate = "code"; - list Fields; - - // (Optional) List of fields that make up the primary key. - list PrimaryKey; - - // (Optional) Name of the primary key search function. - string PrimaryKeyName; - - // See SearchIndex.EarlyOut - bit PrimaryKeyEarlyOut = false; -} - -// Define a record derived from this class to generate an additional search -// index for a generic table that has been defined earlier. -// -// The name of the record will be used as the name of the C++ lookup function. -class SearchIndex { - // Table that this search index refers to. - GenericTable Table; - - // List of fields that make up the key. - list Key; - - // If true, the lookup function will check the first field of the key against - // the minimum and maximum values in the index before entering the binary - // search. This is convenient for tables that add extended data for a subset - // of a larger enum-based space, e.g. extended data about a subset of - // instructions. - // - // Can only be used when the first field is an integral (non-string) type. - bit EarlyOut = false; -} - -// Legacy table type with integrated enum. -class SearchableTable { - list SearchableFields; - string EnumNameField = "Name"; - string EnumValueField; -} diff --git a/suite/synctools/tablegen/include/llvm/TableGen/SetTheory.h b/suite/synctools/tablegen/include/llvm/TableGen/SetTheory.h deleted file mode 100644 index 35156424b0..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/SetTheory.h +++ /dev/null @@ -1,144 +0,0 @@ -//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the SetTheory class that computes ordered sets of -// Records from DAG expressions. Operators for standard set operations are -// predefined, and it is possible to add special purpose set operators as well. -// -// The user may define named sets as Records of predefined classes. Set -// expanders can be added to a SetTheory instance to teach it how to find the -// elements of such a named set. -// -// These are the predefined operators. The argument lists can be individual -// elements (defs), other sets (defs of expandable classes), lists, or DAG -// expressions that are evaluated recursively. -// -// - (add S1, S2 ...) Union sets. This is also how sets are created from element -// lists. -// -// - (sub S1, S2, ...) Set difference. Every element in S1 except for the -// elements in S2, ... -// -// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. -// -// - (shl S, N) Shift left. Remove the first N elements from S. -// -// - (trunc S, N) Truncate. The first N elements of S. -// -// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). -// -// - (rotr S, N) Rotate right. -// -// - (decimate S, N) Decimate S by picking every N'th element, starting with -// the first one. For instance, (decimate S, 2) returns the even elements of -// S. -// -// - (sequence "Format", From, To) Generate a sequence of defs with printf. -// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_SETTHEORY_H -#define LLVM_TABLEGEN_SETTHEORY_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/SMLoc.h" -#include -#include -#include - -namespace llvm { - -class DagInit; -class Init; -class Record; - -class SetTheory { -public: - using RecVec = std::vector; - using RecSet = SmallSetVector; - - /// Operator - A callback representing a DAG operator. - class Operator { - virtual void anchor(); - - public: - virtual ~Operator() = default; - - /// apply - Apply this operator to Expr's arguments and insert the result - /// in Elts. - virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) = 0; - }; - - /// Expander - A callback function that can transform a Record representing a - /// set into a fully expanded list of elements. Expanders provide a way for - /// users to define named sets that can be used in DAG expressions. - class Expander { - virtual void anchor(); - - public: - virtual ~Expander() = default; - - virtual void expand(SetTheory&, Record*, RecSet &Elts) = 0; - }; - -private: - // Map set defs to their fully expanded contents. This serves as a memoization - // cache and it makes it possible to return const references on queries. - using ExpandMap = std::map; - ExpandMap Expansions; - - // Known DAG operators by name. - StringMap> Operators; - - // Typed expanders by class name. - StringMap> Expanders; - -public: - /// Create a SetTheory instance with only the standard operators. - SetTheory(); - - /// addExpander - Add an expander for Records with the named super class. - void addExpander(StringRef ClassName, std::unique_ptr); - - /// addFieldExpander - Add an expander for ClassName that simply evaluates - /// FieldName in the Record to get the set elements. That is all that is - /// needed for a class like: - /// - /// class Set { - /// dag Elts = d; - /// } - /// - void addFieldExpander(StringRef ClassName, StringRef FieldName); - - /// addOperator - Add a DAG operator. - void addOperator(StringRef Name, std::unique_ptr); - - /// evaluate - Evaluate Expr and append the resulting set to Elts. - void evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc); - - /// evaluate - Evaluate a sequence of Inits and append to Elts. - template - void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef Loc) { - while (begin != end) - evaluate(*begin++, Elts, Loc); - } - - /// expand - Expand a record into a set of elements if possible. Return a - /// pointer to the expanded elements, or NULL if Set cannot be expanded - /// further. - const RecVec *expand(Record *Set); -}; - -} // end namespace llvm - -#endif // LLVM_TABLEGEN_SETTHEORY_H diff --git a/suite/synctools/tablegen/include/llvm/TableGen/StringMatcher.h b/suite/synctools/tablegen/include/llvm/TableGen/StringMatcher.h deleted file mode 100644 index 795b7a6d41..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/StringMatcher.h +++ /dev/null @@ -1,54 +0,0 @@ -//===- StringMatcher.h - Generate a matcher for input strings ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the StringMatcher class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_STRINGMATCHER_H -#define LLVM_TABLEGEN_STRINGMATCHER_H - -#include "llvm/ADT/StringRef.h" -#include -#include -#include - -namespace llvm { - -class raw_ostream; - -/// Given a list of strings and code to execute when they match, output a -/// simple switch tree to classify the input string. -/// -/// If a match is found, the code in Matches[i].second is executed; control must -/// not exit this code fragment. If nothing matches, execution falls through. -class StringMatcher { -public: - using StringPair = std::pair; - -private: - StringRef StrVariableName; - const std::vector &Matches; - raw_ostream &OS; - -public: - StringMatcher(StringRef strVariableName, - const std::vector &matches, raw_ostream &os) - : StrVariableName(strVariableName), Matches(matches), OS(os) {} - - void Emit(unsigned Indent = 0, bool IgnoreDuplicates = false) const; - -private: - bool EmitStringMatcherForChar(const std::vector &Matches, - unsigned CharNo, unsigned IndentCount, - bool IgnoreDuplicates) const; -}; - -} // end namespace llvm - -#endif // LLVM_TABLEGEN_STRINGMATCHER_H diff --git a/suite/synctools/tablegen/include/llvm/TableGen/StringToOffsetTable.h b/suite/synctools/tablegen/include/llvm/TableGen/StringToOffsetTable.h deleted file mode 100644 index 7fcf20abed..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/StringToOffsetTable.h +++ /dev/null @@ -1,104 +0,0 @@ -//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H -#define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { - -/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings -/// and keeps track of their offset in a massive contiguous string allocation. -/// It can then output this string blob and use indexes into the string to -/// reference each piece. -class StringToOffsetTable { - StringMap StringOffset; - std::string AggregateString; - -public: - bool Empty() const { return StringOffset.empty(); } - - unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { - auto IterBool = - StringOffset.insert(std::make_pair(Str, AggregateString.size())); - if (IterBool.second) { - // Add the string to the aggregate if this is the first time found. - AggregateString.append(Str.begin(), Str.end()); - if (appendZero) - AggregateString += '\0'; - } - - return IterBool.first->second; - } - - void EmitString(raw_ostream &O) { - // Escape the string. - SmallString<256> Str; - raw_svector_ostream(Str).write_escaped(AggregateString); - AggregateString = std::string(Str.str()); - - O << " \""; - unsigned CharsPrinted = 0; - for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { - if (CharsPrinted > 70) { - O << "\"\n \""; - CharsPrinted = 0; - } - O << AggregateString[i]; - ++CharsPrinted; - - // Print escape sequences all together. - if (AggregateString[i] != '\\') - continue; - - assert(i + 1 < AggregateString.size() && "Incomplete escape sequence!"); - if (isdigit(AggregateString[i + 1])) { - assert(isdigit(AggregateString[i + 2]) && - isdigit(AggregateString[i + 3]) && - "Expected 3 digit octal escape!"); - O << AggregateString[++i]; - O << AggregateString[++i]; - O << AggregateString[++i]; - CharsPrinted += 3; - } else { - O << AggregateString[++i]; - ++CharsPrinted; - } - } - O << "\""; - } - - /// Emit the string using character literals. MSVC has a limitation that - /// string literals cannot be longer than 64K. - void EmitCharArray(raw_ostream &O) { - assert(AggregateString.find(')') == std::string::npos && - "can't emit raw string with closing parens"); - int Count = 0; - O << ' '; - for (char C : AggregateString) { - O << " \'"; - O.write_escaped(StringRef(&C, 1)); - O << "\',"; - Count++; - if (Count > 14) { - O << "\n "; - Count = 0; - } - } - O << '\n'; - } -}; - -} // end namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/TableGen/TableGenBackend.h b/suite/synctools/tablegen/include/llvm/TableGen/TableGenBackend.h deleted file mode 100644 index a426e42175..0000000000 --- a/suite/synctools/tablegen/include/llvm/TableGen/TableGenBackend.h +++ /dev/null @@ -1,29 +0,0 @@ -//===- llvm/TableGen/TableGenBackend.h - Backend utilities ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Useful utilities for TableGen backends. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H -#define LLVM_TABLEGEN_TABLEGENBACKEND_H - -namespace llvm { - -class StringRef; -class raw_ostream; - -/// emitSourceFileHeader - Output an LLVM style file header to the specified -/// raw_ostream. -void emitSourceFileHeader(StringRef Desc, raw_ostream &OS); - -extern bool TimeRegions; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/Target/CGPassBuilderOption.h b/suite/synctools/tablegen/include/llvm/Target/CGPassBuilderOption.h deleted file mode 100644 index f84889392d..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/CGPassBuilderOption.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- CGPassBuilderOption.h - Options for pass builder ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the CCState and CCValAssign classes, used for lowering -// and implementing calling conventions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_CGPASSBUILDEROPTION_H -#define LLVM_TARGET_CGPASSBUILDEROPTION_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Target/TargetOptions.h" - -namespace llvm { - -enum class RunOutliner { TargetDefault, AlwaysOutline, NeverOutline }; -enum class RegAllocType { Default, Basic, Fast, Greedy, PBQP }; -enum class CFLAAType { None, Steensgaard, Andersen, Both }; - -// Not one-on-one but mostly corresponding to commandline options in -// TargetPassConfig.cpp. -struct CGPassBuilderOption { - Optional OptimizeRegAlloc; - Optional EnableIPRA; - bool DebugPM = false; - bool DisableVerify = false; - bool EnableImplicitNullChecks = false; - bool EnableBlockPlacementStats = false; - bool MISchedPostRA = false; - bool EarlyLiveIntervals = false; - - bool DisableLSR = false; - bool DisableCGP = false; - bool PrintLSR = false; - bool DisableMergeICmps = false; - bool DisablePartialLibcallInlining = false; - bool DisableConstantHoisting = false; - bool PrintISelInput = false; - bool PrintGCInfo = false; - bool RequiresCodeGenSCCOrder = false; - - RunOutliner EnableMachineOutliner = RunOutliner::TargetDefault; - RegAllocType RegAlloc = RegAllocType::Default; - CFLAAType UseCFLAA = CFLAAType::None; - Optional EnableGlobalISelAbort; - - Optional VerifyMachineCode; - Optional EnableFastISelOption; - Optional EnableGlobalISelOption; -}; - -CGPassBuilderOption getCGPassBuilderOption(); - -} // namespace llvm - -#endif // LLVM_TARGET_CGPASSBUILDEROPTION_H diff --git a/suite/synctools/tablegen/include/llvm/Target/CodeGenCWrappers.h b/suite/synctools/tablegen/include/llvm/Target/CodeGenCWrappers.h deleted file mode 100644 index a995463570..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/CodeGenCWrappers.h +++ /dev/null @@ -1,64 +0,0 @@ -//===- llvm/Target/CodeGenCWrappers.h - CodeGen C Wrappers ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines C bindings wrappers for enums in llvm/Support/CodeGen.h -// that need them. The wrappers are separated to avoid adding an indirect -// dependency on llvm/Config/Targets.def to CodeGen.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_CODEGENCWRAPPERS_H -#define LLVM_TARGET_CODEGENCWRAPPERS_H - -#include "llvm-c/TargetMachine.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/ErrorHandling.h" - -namespace llvm { - -inline Optional unwrap(LLVMCodeModel Model, bool &JIT) { - JIT = false; - switch (Model) { - case LLVMCodeModelJITDefault: - JIT = true; - LLVM_FALLTHROUGH; - case LLVMCodeModelDefault: - return None; - case LLVMCodeModelTiny: - return CodeModel::Tiny; - case LLVMCodeModelSmall: - return CodeModel::Small; - case LLVMCodeModelKernel: - return CodeModel::Kernel; - case LLVMCodeModelMedium: - return CodeModel::Medium; - case LLVMCodeModelLarge: - return CodeModel::Large; - } - return CodeModel::Small; -} - -inline LLVMCodeModel wrap(CodeModel::Model Model) { - switch (Model) { - case CodeModel::Tiny: - return LLVMCodeModelTiny; - case CodeModel::Small: - return LLVMCodeModelSmall; - case CodeModel::Kernel: - return LLVMCodeModelKernel; - case CodeModel::Medium: - return LLVMCodeModelMedium; - case CodeModel::Large: - return LLVMCodeModelLarge; - } - llvm_unreachable("Bad CodeModel!"); -} -} // namespace llvm - -#endif diff --git a/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td b/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td deleted file mode 100644 index 33537ca242..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td +++ /dev/null @@ -1,1443 +0,0 @@ -//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the generic opcodes used with GlobalISel. -// After instruction selection, these opcodes should not appear. -// -//===----------------------------------------------------------------------===// - -//------------------------------------------------------------------------------ -// Unary ops. -//------------------------------------------------------------------------------ - -class GenericInstruction : StandardPseudoInstruction { - let isPreISelOpcode = true; -} - -// Provide a variant of an instruction with the same operands, but -// different instruction flags. This is intended to provide a -// convenient way to define strict floating point variants of ordinary -// floating point instructions. -class ConstrainedIntruction : - GenericInstruction { - let OutOperandList = baseInst.OutOperandList; - let InOperandList = baseInst.InOperandList; - let isCommutable = baseInst.isCommutable; - - // TODO: Do we need a better way to mark reads from FP mode than - // hasSideEffects? - let hasSideEffects = true; - let mayRaiseFPException = true; -} - -// Extend the underlying scalar type of an operation, leaving the high bits -// unspecified. -def G_ANYEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -// Sign extend the underlying scalar type of an operation, copying the sign bit -// into the newly-created space. -def G_SEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -// Sign extend the value from an arbitrary bit position, copying the sign bit -// into all bits above it. This is equivalent to a shl + ashr pair with an -// appropriate shift amount. $sz is an immediate (MachineOperand::isImm() -// returns true) to allow targets to have some bitwidths legal and others -// lowered. This opcode is particularly useful if the target has sign-extension -// instructions that are cheaper than the constituent shifts as the optimizer is -// able to make decisions on whether it's better to hang on to the G_SEXT_INREG -// or to lower it and optimize the individual shifts. -def G_SEXT_INREG : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, untyped_imm_0:$sz); - let hasSideEffects = false; -} - -// Zero extend the underlying scalar type of an operation, putting zero bits -// into the newly-created space. -def G_ZEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - - -// Truncate the underlying scalar type of an operation. This is equivalent to -// G_EXTRACT for scalar types, but acts elementwise on vectors. -def G_TRUNC : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_IMPLICIT_DEF : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins); - let hasSideEffects = false; -} - -def G_PHI : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins variable_ops); - let hasSideEffects = false; -} - -def G_FRAME_INDEX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$src2); - let hasSideEffects = false; -} - -def G_GLOBAL_VALUE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$src); - let hasSideEffects = false; -} - -def G_INTTOPTR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_PTRTOINT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_BITCAST : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -// Only supports scalar result types -def G_CONSTANT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$imm); - let hasSideEffects = false; -} - -// Only supports scalar result types -def G_FCONSTANT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$imm); - let hasSideEffects = false; -} - -def G_VASTART : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins type0:$list); - let hasSideEffects = false; - let mayStore = true; -} - -def G_VAARG : GenericInstruction { - let OutOperandList = (outs type0:$val); - let InOperandList = (ins type1:$list, unknown:$align); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -def G_CTLZ : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_CTLZ_ZERO_UNDEF : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_CTTZ : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_CTTZ_ZERO_UNDEF : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_CTPOP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_BSWAP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -def G_BITREVERSE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -def G_ADDRSPACE_CAST : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_BLOCK_ADDR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$ba); - let hasSideEffects = false; -} - -def G_JUMP_TABLE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$jti); - let hasSideEffects = false; -} - -def G_DYN_STACKALLOC : GenericInstruction { - let OutOperandList = (outs ptype0:$dst); - let InOperandList = (ins type1:$size, i32imm:$align); - let hasSideEffects = true; -} - -def G_FREEZE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -def G_LROUND: GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_LLROUND: GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -//------------------------------------------------------------------------------ -// Binary ops. -//------------------------------------------------------------------------------ - -// Generic addition. -def G_ADD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic subtraction. -def G_SUB : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic multiplication. -def G_MUL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic signed division. -def G_SDIV : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic unsigned division. -def G_UDIV : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic signed remainder. -def G_SREM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic unsigned remainder. -def G_UREM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic signed division and remainder. -def G_SDIVREM : GenericInstruction { - let OutOperandList = (outs type0:$div, type0:$rem); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic unsigned division and remainder. -def G_UDIVREM : GenericInstruction { - let OutOperandList = (outs type0:$div, type0:$rem); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic bitwise and. -def G_AND : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic bitwise or. -def G_OR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic bitwise xor. -def G_XOR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic left-shift. -def G_SHL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic logical right-shift. -def G_LSHR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic arithmetic right-shift. -def G_ASHR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. -/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth))) -def G_FSHL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); - let hasSideEffects = false; -} - -/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. -/// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth)) -def G_FSHR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); - let hasSideEffects = false; -} - -/// Rotate bits right. -def G_ROTR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -/// Rotate bits left. -def G_ROTL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic integer comparison. -def G_ICMP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic floating-point comparison. -def G_FCMP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic select -def G_SELECT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2); - let hasSideEffects = false; -} - -// Generic pointer offset. -def G_PTR_ADD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; -} - -// Generic pointer mask. type1 should be an integer with the same -// bitwidth as the pointer type. -def G_PTRMASK : GenericInstruction { - let OutOperandList = (outs ptype0:$dst); - let InOperandList = (ins ptype0:$src, type1:$bits); - let hasSideEffects = false; -} - -// Generic signed integer minimum. -def G_SMIN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic signed integer maximum. -def G_SMAX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic unsigned integer minimum. -def G_UMIN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic unsigned integer maximum. -def G_UMAX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic integer absolute value. -def G_ABS : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -//------------------------------------------------------------------------------ -// Overflow ops -//------------------------------------------------------------------------------ - -// Generic unsigned addition producing a carry flag. -def G_UADDO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic unsigned addition consuming and producing a carry flag. -def G_UADDE : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); - let hasSideEffects = false; -} - -// Generic signed addition producing a carry flag. -def G_SADDO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic signed addition consuming and producing a carry flag. -def G_SADDE : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); - let hasSideEffects = false; -} - -// Generic unsigned subtraction producing a carry flag. -def G_USUBO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; -} -// Generic unsigned subtraction consuming and producing a carry flag. -def G_USUBE : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); - let hasSideEffects = false; -} - -// Generic signed subtraction producing a carry flag. -def G_SSUBO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; -} - -// Generic signed subtraction consuming and producing a carry flag. -def G_SSUBE : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); - let hasSideEffects = false; -} - -// Generic unsigned multiplication producing a carry flag. -def G_UMULO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic signed multiplication producing a carry flag. -def G_SMULO : GenericInstruction { - let OutOperandList = (outs type0:$dst, type1:$carry_out); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Multiply two numbers at twice the incoming bit width (unsigned) and return -// the high half of the result. -def G_UMULH : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Multiply two numbers at twice the incoming bit width (signed) and return -// the high half of the result. -def G_SMULH : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -//------------------------------------------------------------------------------ -// Saturating ops -//------------------------------------------------------------------------------ - -// Generic saturating unsigned addition. -def G_UADDSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic saturating signed addition. -def G_SADDSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic saturating unsigned subtraction. -def G_USUBSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic saturating signed subtraction. -def G_SSUBSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic saturating unsigned left shift. -def G_USHLSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic saturating signed left shift. -def G_SSHLSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type1:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point -/// multiplication on 2 integers with the same width and scale. SCALE -/// represents the scale of both operands as fixed point numbers. This -/// SCALE parameter must be a constant integer. A scale of zero is -/// effectively performing multiplication on 2 integers. -def G_SMULFIX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = true; -} - -def G_UMULFIX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = true; -} - -/// Same as the corresponding unsaturated fixed point instructions, but the -/// result is clamped between the min and max values representable by the -/// bits of the first 2 operands. -def G_SMULFIXSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = true; -} - -def G_UMULFIXSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = true; -} - -/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on -/// 2 integers with the same width and scale. SCALE represents the scale -/// of both operands as fixed point numbers. This SCALE parameter must be a -/// constant integer. -def G_SDIVFIX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = false; -} - -def G_UDIVFIX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = false; -} - -/// Same as the corresponding unsaturated fixed point instructions, -/// but the result is clamped between the min and max values -/// representable by the bits of the first 2 operands. -def G_SDIVFIXSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = false; -} - -def G_UDIVFIXSAT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); - let hasSideEffects = false; - let isCommutable = false; -} - -//------------------------------------------------------------------------------ -// Floating Point Unary Ops. -//------------------------------------------------------------------------------ - -def G_FNEG : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -def G_FPEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_FPTRUNC : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_FPTOSI : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_FPTOUI : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_SITOFP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_UITOFP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_FABS : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -def G_FCOPYSIGN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type1:$src1); - let hasSideEffects = false; -} - -def G_FCANONICALIZE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); - let hasSideEffects = false; -} - -// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two -// values. -// -// In the case where a single input is a NaN (either signaling or quiet), -// the non-NaN input is returned. -// -// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. -def G_FMINNUM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -def G_FMAXNUM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on -// two values, following the IEEE-754 2008 definition. This differs from -// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a -// signaling NaN, returns a quiet NaN. -def G_FMINNUM_IEEE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -def G_FMAXNUM_IEEE : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 -// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 -// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. -def G_FMINIMUM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -def G_FMAXIMUM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -//------------------------------------------------------------------------------ -// Floating Point Binary ops. -//------------------------------------------------------------------------------ - -// Generic FP addition. -def G_FADD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic FP subtraction. -def G_FSUB : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic FP multiplication. -def G_FMUL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; - let isCommutable = true; -} - -// Generic fused multiply-add instruction. -// Behaves like llvm fma intrinsic ie src1 * src2 + src3 -def G_FMA : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); - let hasSideEffects = false; - let isCommutable = false; -} - -/// Generic FP multiply and add. Perform a * b + c, while getting the -/// same result as the separately rounded operations, unlike G_FMA. -def G_FMAD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); - let hasSideEffects = false; - let isCommutable = false; -} - -// Generic FP division. -def G_FDIV : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; -} - -// Generic FP remainder. -def G_FREM : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; -} - -// Floating point exponentiation. -def G_FPOW : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); - let hasSideEffects = false; -} - -// Floating point exponentiation, with an integer power. -def G_FPOWI : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src0, type1:$src1); - let hasSideEffects = false; -} - -// Floating point base-e exponential of a value. -def G_FEXP : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point base-2 exponential of a value. -def G_FEXP2 : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point base-e logarithm of a value. -def G_FLOG : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point base-2 logarithm of a value. -def G_FLOG2 : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point base-10 logarithm of a value. -def G_FLOG10 : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point ceiling of a value. -def G_FCEIL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point cosine of a value. -def G_FCOS : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point sine of a value. -def G_FSIN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point square root of a value. -// This returns NaN for negative nonzero values. -// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's -// libm-conformant. -def G_FSQRT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point floor of a value. -def G_FFLOOR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point round to next integer. -def G_FRINT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -// Floating point round to the nearest integer. -def G_FNEARBYINT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -//------------------------------------------------------------------------------ -// Opcodes for LLVM Intrinsics -//------------------------------------------------------------------------------ -def G_INTRINSIC_TRUNC : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -def G_INTRINSIC_ROUND : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -def G_INTRINSIC_LRINT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -def G_INTRINSIC_ROUNDEVEN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; -} - -def G_READCYCLECOUNTER : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins); - let hasSideEffects = true; -} - -//------------------------------------------------------------------------------ -// Memory ops -//------------------------------------------------------------------------------ - -// Generic load. Expects a MachineMemOperand in addition to explicit -// operands. If the result size is larger than the memory size, the -// high bits are undefined. If the result is a vector type and larger -// than the memory size, the high elements are undefined (i.e. this is -// not a per-element, vector anyextload) -def G_LOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins ptype1:$addr); - let hasSideEffects = false; - let mayLoad = true; -} - -// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. -def G_SEXTLOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins ptype1:$addr); - let hasSideEffects = false; - let mayLoad = true; -} - -// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. -def G_ZEXTLOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins ptype1:$addr); - let hasSideEffects = false; - let mayLoad = true; -} - -// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset. -// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed) -// then the value is loaded from $newaddr. -def G_INDEXED_LOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst, ptype1:$newaddr); - let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); - let hasSideEffects = false; - let mayLoad = true; -} - -// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD. -def G_INDEXED_SEXTLOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst, ptype1:$newaddr); - let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); - let hasSideEffects = false; - let mayLoad = true; -} - -// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD. -def G_INDEXED_ZEXTLOAD : GenericInstruction { - let OutOperandList = (outs type0:$dst, ptype1:$newaddr); - let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); - let hasSideEffects = false; - let mayLoad = true; -} - -// Generic store. Expects a MachineMemOperand in addition to explicit operands. -def G_STORE : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins type0:$src, ptype1:$addr); - let hasSideEffects = false; - let mayStore = true; -} - -// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour. -def G_INDEXED_STORE : GenericInstruction { - let OutOperandList = (outs ptype0:$newaddr); - let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset, - unknown:$am); - let hasSideEffects = false; - let mayStore = true; -} - -// Generic atomic cmpxchg with internal success check. Expects a -// MachineMemOperand in addition to explicit operands. -def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { - let OutOperandList = (outs type0:$oldval, type1:$success); - let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit -// operands. -def G_ATOMIC_CMPXCHG : GenericInstruction { - let OutOperandList = (outs type0:$oldval); - let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit -// operands. -class G_ATOMICRMW_OP : GenericInstruction { - let OutOperandList = (outs type0:$oldval); - let InOperandList = (ins ptype1:$addr, type0:$val); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; -def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; -def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; -def G_ATOMICRMW_AND : G_ATOMICRMW_OP; -def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; -def G_ATOMICRMW_OR : G_ATOMICRMW_OP; -def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; -def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; -def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; -def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; -def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; -def G_ATOMICRMW_FADD : G_ATOMICRMW_OP; -def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP; - -def G_FENCE : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$ordering, i32imm:$scope); - let hasSideEffects = true; -} - -//------------------------------------------------------------------------------ -// Variadic ops -//------------------------------------------------------------------------------ - -// Extract a register of the specified size, starting from the block given by -// index. This will almost certainly be mapped to sub-register COPYs after -// register banks have been selected. -def G_EXTRACT : GenericInstruction { - let OutOperandList = (outs type0:$res); - let InOperandList = (ins type1:$src, untyped_imm_0:$offset); - let hasSideEffects = false; -} - -// Extract multiple registers specified size, starting from blocks given by -// indexes. This will almost certainly be mapped to sub-register COPYs after -// register banks have been selected. -// The output operands are always ordered from lowest bits to highest: -// %bits_0_7:(s8), %bits_8_15:(s8), -// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32) -def G_UNMERGE_VALUES : GenericInstruction { - let OutOperandList = (outs type0:$dst0, variable_ops); - let InOperandList = (ins type1:$src); - let hasSideEffects = false; -} - -// Insert a smaller register into a larger one at the specified bit-index. -def G_INSERT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset); - let hasSideEffects = false; -} - -// Concatenate multiple registers of the same size into a wider register. -// The input operands are always ordered from lowest bits to highest: -// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8), -// %bits_16_23:(s8), %bits_24_31:(s8) -def G_MERGE_VALUES : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src0, variable_ops); - let hasSideEffects = false; -} - -/// Create a vector from multiple scalar registers. No implicit -/// conversion is performed (i.e. the result element type must be the -/// same as all source operands) -def G_BUILD_VECTOR : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src0, variable_ops); - let hasSideEffects = false; -} - -/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the -/// destination vector elt type. -def G_BUILD_VECTOR_TRUNC : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src0, variable_ops); - let hasSideEffects = false; -} - -/// Create a vector by concatenating vectors together. -def G_CONCAT_VECTORS : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src0, variable_ops); - let hasSideEffects = false; -} - -// Intrinsic without side effects. -def G_INTRINSIC : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$intrin, variable_ops); - let hasSideEffects = false; - - // Conservatively assume this is convergent. If there turnes out to - // be a need, there should be separate convergent intrinsic opcodes. - let isConvergent = 1; -} - -// Intrinsic with side effects. -def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$intrin, variable_ops); - let hasSideEffects = true; - let mayLoad = true; - let mayStore = true; - - // Conservatively assume this is convergent. If there turnes out to - // be a need, there should be separate convergent intrinsic opcodes. - let isConvergent = true; -} - -//------------------------------------------------------------------------------ -// Branches. -//------------------------------------------------------------------------------ - -// Generic unconditional branch. -def G_BR : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$src1); - let hasSideEffects = false; - let isBranch = true; - let isTerminator = true; - let isBarrier = true; -} - -// Generic conditional branch. -def G_BRCOND : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins type0:$tst, unknown:$truebb); - let hasSideEffects = false; - let isBranch = true; - let isTerminator = true; -} - -// Generic indirect branch. -def G_BRINDIRECT : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins type0:$src1); - let hasSideEffects = false; - let isBranch = true; - let isTerminator = true; - let isBarrier = true; - let isIndirectBranch = true; -} - -// Generic branch to jump table entry -def G_BRJT : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); - let hasSideEffects = false; - let isBranch = true; - let isTerminator = true; - let isBarrier = true; - let isIndirectBranch = true; -} - -def G_READ_REGISTER : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins unknown:$register); - let hasSideEffects = true; - - // Assume convergent. It's probably not worth the effort of somehow - // modeling convergent and nonconvergent register accesses. - let isConvergent = true; -} - -def G_WRITE_REGISTER : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$register, type0:$value); - let hasSideEffects = true; - - // Assume convergent. It's probably not worth the effort of somehow - // modeling convergent and nonconvergent register accesses. - let isConvergent = true; -} - -//------------------------------------------------------------------------------ -// Vector ops -//------------------------------------------------------------------------------ - -// Generic insertelement. -def G_INSERT_VECTOR_ELT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); - let hasSideEffects = false; -} - -// Generic extractelement. -def G_EXTRACT_VECTOR_ELT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$src, type2:$idx); - let hasSideEffects = false; -} - -// Generic shufflevector. -// -// The mask operand should be an IR Constant which exactly matches the -// corresponding mask for the IR shufflevector instruction. -def G_SHUFFLE_VECTOR: GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); - let hasSideEffects = false; -} - -//------------------------------------------------------------------------------ -// Vector reductions -//------------------------------------------------------------------------------ - -class VectorReduction : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$v); - let hasSideEffects = false; -} - -def G_VECREDUCE_SEQ_FADD : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$acc, type2:$v); - let hasSideEffects = false; -} - -def G_VECREDUCE_SEQ_FMUL : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$acc, type2:$v); - let hasSideEffects = false; -} - -def G_VECREDUCE_FADD : VectorReduction; -def G_VECREDUCE_FMUL : VectorReduction; - -def G_VECREDUCE_FMAX : VectorReduction; -def G_VECREDUCE_FMIN : VectorReduction; - -def G_VECREDUCE_ADD : VectorReduction; -def G_VECREDUCE_MUL : VectorReduction; -def G_VECREDUCE_AND : VectorReduction; -def G_VECREDUCE_OR : VectorReduction; -def G_VECREDUCE_XOR : VectorReduction; -def G_VECREDUCE_SMAX : VectorReduction; -def G_VECREDUCE_SMIN : VectorReduction; -def G_VECREDUCE_UMAX : VectorReduction; -def G_VECREDUCE_UMIN : VectorReduction; - -//------------------------------------------------------------------------------ -// Constrained floating point ops -//------------------------------------------------------------------------------ - -def G_STRICT_FADD : ConstrainedIntruction; -def G_STRICT_FSUB : ConstrainedIntruction; -def G_STRICT_FMUL : ConstrainedIntruction; -def G_STRICT_FDIV : ConstrainedIntruction; -def G_STRICT_FREM : ConstrainedIntruction; -def G_STRICT_FMA : ConstrainedIntruction; -def G_STRICT_FSQRT : ConstrainedIntruction; - -//------------------------------------------------------------------------------ -// Memory intrinsics -//------------------------------------------------------------------------------ - -def G_MEMCPY : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -def G_MEMCPY_INLINE : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -def G_MEMMOVE : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); - let hasSideEffects = false; - let mayLoad = true; - let mayStore = true; -} - -def G_MEMSET : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall); - let hasSideEffects = false; - let mayStore = true; -} - -def G_BZERO : GenericInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall); - let hasSideEffects = false; - let mayStore = true; -} - -//------------------------------------------------------------------------------ -// Bitfield extraction. -//------------------------------------------------------------------------------ - -// Generic signed bitfield extraction. The operands are in the range -// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. -def G_SBFX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); - let hasSideEffects = false; -} - -// Generic unsigned bitfield extraction. The operands are in the range -// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. -def G_UBFX : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); - let hasSideEffects = false; -} - -//------------------------------------------------------------------------------ -// Optimization hints -//------------------------------------------------------------------------------ - -// Asserts that an operation has already been zero-extended from a specific -// type. -def G_ASSERT_ZEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, untyped_imm_0:$sz); - let hasSideEffects = false; -} - -// Asserts that an operation has already been sign-extended from a specific -// type. -def G_ASSERT_SEXT : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, untyped_imm_0:$sz); - let hasSideEffects = false; -} - -// Asserts that a value has at least the given alignment. -def G_ASSERT_ALIGN : GenericInstruction { - let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src, untyped_imm_0:$align); - let hasSideEffects = false; -} diff --git a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Combine.td b/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Combine.td deleted file mode 100644 index 6416afa3a7..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Combine.td +++ /dev/null @@ -1,910 +0,0 @@ -//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Declare GlobalISel combine rules and provide mechanisms to opt-out. -// -//===----------------------------------------------------------------------===// - -// Common base class for GICombineRule and GICombineGroup. -class GICombine { - // See GICombineGroup. We only declare it here to make the tablegen pass - // simpler. - list Rules = ?; -} - -// A group of combine rules that can be added to a GICombiner or another group. -class GICombineGroup rules> : GICombine { - // The rules contained in this group. The rules in a group are flattened into - // a single list and sorted into whatever order is most efficient. However, - // they will never be re-ordered such that behaviour differs from the - // specified order. It is therefore possible to use the order of rules in this - // list to describe priorities. - let Rules = rules; -} - -class GICombinerHelperArg { - string Type = type; - string Name = name; -} - -// Declares a combiner helper class -class GICombinerHelper rules> - : GICombineGroup { - // The class name to use in the generated output. - string Classname = classname; - // The name of a run-time compiler option that will be generated to disable - // specific rules within this combiner. - string DisableRuleOption = ?; - // The state class to inherit from (if any). The generated helper will inherit - // from this class and will forward arguments to its constructors. - string StateClass = ""; - // Any additional arguments that should be appended to the tryCombine*(). - list AdditionalArguments = - [GICombinerHelperArg<"CombinerHelper &", "Helper">]; -} -class GICombineRule : GICombine { - /// Defines the external interface of the match rule. This includes: - /// * The names of the root nodes (requires at least one) - /// See GIDefKind for details. - dag Defs = defs; - - /// Defines the things which must be true for the pattern to match - /// See GIMatchKind for details. - dag Match = match; - - /// Defines the things which happen after the decision is made to apply a - /// combine rule. - /// See GIApplyKind for details. - dag Apply = apply; -} - -/// The operator at the root of a GICombineRule.Defs dag. -def defs; - -/// All arguments of the defs operator must be subclasses of GIDefKind or -/// sub-dags whose operator is GIDefKindWithArgs. -class GIDefKind; -class GIDefKindWithArgs; -/// Declare a root node. There must be at least one of these in every combine -/// rule. -/// TODO: The plan is to elide `root` definitions and determine it from the DAG -/// itself with an override for situations where the usual determination -/// is incorrect. -def root : GIDefKind; - -/// Declares data that is passed from the match stage to the apply stage. -class GIDefMatchData : GIDefKind { - /// A C++ type name indicating the storage type. - string Type = type; -} - -def extending_load_matchdata : GIDefMatchData<"PreferredTuple">; -def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">; -def instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">; - -/// The operator at the root of a GICombineRule.Match dag. -def match; -/// All arguments of the match operator must be either: -/// * A subclass of GIMatchKind -/// * A subclass of GIMatchKindWithArgs -/// * A subclass of Instruction -/// * A MIR code block (deprecated) -/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail -/// in their definitions below. -/// For the Instruction case, these are collected into a DAG where operand names -/// that occur multiple times introduce edges. -class GIMatchKind; -class GIMatchKindWithArgs; - -/// In lieu of having proper macro support. Trivial one-off opcode checks can be -/// performed with this. -def wip_match_opcode : GIMatchKindWithArgs; - -/// The operator at the root of a GICombineRule.Apply dag. -def apply; -/// All arguments of the apply operator must be subclasses of GIApplyKind, or -/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block -/// (deprecated). -class GIApplyKind; -class GIApplyKindWithArgs; - -def register_matchinfo: GIDefMatchData<"Register">; -def int64_matchinfo: GIDefMatchData<"int64_t">; -def apint_matchinfo : GIDefMatchData<"APInt">; -def build_fn_matchinfo : -GIDefMatchData<"std::function">; - -def copy_prop : GICombineRule< - (defs root:$d), - (match (COPY $d, $s):$mi, - [{ return Helper.matchCombineCopy(*${mi}); }]), - (apply [{ Helper.applyCombineCopy(*${mi}); }])>; - -def extending_loads : GICombineRule< - (defs root:$root, extending_load_matchdata:$matchinfo), - (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, - [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; - -def load_and_mask : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchCombineLoadWithAndMask(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; -def combines_for_extload: GICombineGroup<[extending_loads, load_and_mask]>; - -def sext_trunc_sextload : GICombineRule< - (defs root:$d), - (match (wip_match_opcode G_SEXT_INREG):$d, - [{ return Helper.matchSextTruncSextLoad(*${d}); }]), - (apply [{ Helper.applySextTruncSextLoad(*${d}); }])>; - -def sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple">; -def sext_inreg_of_load : GICombineRule< - (defs root:$root, sext_inreg_of_load_matchdata:$matchinfo), - (match (wip_match_opcode G_SEXT_INREG):$root, - [{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>; - -def combine_indexed_load_store : GICombineRule< - (defs root:$root, indexed_load_store_matchdata:$matchinfo), - (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, - [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; - -def opt_brcond_by_inverting_cond_matchdata : GIDefMatchData<"MachineInstr *">; -def opt_brcond_by_inverting_cond : GICombineRule< - (defs root:$root, opt_brcond_by_inverting_cond_matchdata:$matchinfo), - (match (wip_match_opcode G_BR):$root, - [{ return Helper.matchOptBrCondByInvertingCond(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyOptBrCondByInvertingCond(*${root}, ${matchinfo}); }])>; - -def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; -def ptr_add_immed_chain : GICombineRule< - (defs root:$d, ptr_add_immed_matchdata:$matchinfo), - (match (wip_match_opcode G_PTR_ADD):$d, - [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), - (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; - -// Fold shift (shift base x), y -> shift base, (x+y), if shifts are same -def shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">; -def shift_immed_chain : GICombineRule< - (defs root:$d, shift_immed_matchdata:$matchinfo), - (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d, - [{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]), - (apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>; - -// Transform shift (logic (shift X, C0), Y), C1 -// -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same -def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">; -def shift_of_shifted_logic_chain : GICombineRule< - (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo), - (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d, - [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]), - (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>; - -def mul_to_shl_matchdata : GIDefMatchData<"unsigned">; -def mul_to_shl : GICombineRule< - (defs root:$d, mul_to_shl_matchdata:$matchinfo), - (match (G_MUL $d, $op1, $op2):$mi, - [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>; - -// shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int -def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">; -def reduce_shl_of_extend : GICombineRule< - (defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo), - (match (G_SHL $dst, $src0, $src1):$mi, - [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>; - -def narrow_binop_feeding_and : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; - -// [us]itofp(undef) = 0, because the result value is bounded. -def undef_to_fp_zero : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_UITOFP, G_SITOFP):$root, - [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), - (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>; - -def undef_to_int_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_AND, G_MUL):$root, - [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), - (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; - -def undef_to_negative_one: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_OR):$root, - [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), - (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>; - -def binop_left_undef_to_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SHL):$root, - [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), - (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; - -// Instructions where if any source operand is undef, the instruction can be -// replaced with undef. -def propagate_undef_any_op: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC):$root, - [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), - (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; - -// Instructions where if all source operands are undef, the instruction can be -// replaced with undef. -def propagate_undef_all_ops: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, - [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]), - (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; - -// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF. -def propagate_undef_shuffle_mask: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, - [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), - (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; - -// Fold (cond ? x : x) -> x -def select_same_val: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SELECT):$root, - [{ return Helper.matchSelectSameVal(*${root}); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) ->; - -// Fold (undef ? x : y) -> y -def select_undef_cmp: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SELECT):$root, - [{ return Helper.matchUndefSelectCmp(*${root}); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) ->; - -// Fold (true ? x : y) -> x -// Fold (false ? x : y) -> y -def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">; -def select_constant_cmp: GICombineRule< - (defs root:$root, select_constant_cmp_matchdata:$matchinfo), - (match (wip_match_opcode G_SELECT):$root, - [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }]) ->; - -// Fold x op 0 -> x -def right_identity_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR, - G_PTR_ADD, G_ROTL, G_ROTR):$root, - [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) ->; - -// Fold x op 1 -> x -def right_identity_one: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_MUL):$root, - [{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) ->; - -// Fold (x op x) - > x -def binop_same_val: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_AND, G_OR):$root, - [{ return Helper.matchBinOpSameVal(*${root}); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) ->; - -// Fold (0 op x) - > 0 -def binop_left_to_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, - [{ return Helper.matchOperandIsZero(*${root}, 1); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) ->; - -def urem_pow2_to_mask : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_UREM):$root, - [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]), - (apply [{ Helper.applySimplifyURemByPow2(*${root}); }]) ->; - -// Transform d = [su]div(x, y) and r = [su]rem(x, y) - > d, r = [su]divrem(x, y) -def div_rem_to_divrem_matchdata : GIDefMatchData<"MachineInstr *">; -def div_rem_to_divrem : GICombineRule< - (defs root:$root, div_rem_to_divrem_matchdata:$matchinfo), - (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, - [{ return Helper.matchCombineDivRem(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineDivRem(*${root}, ${matchinfo}); }]) ->; - -// Fold (x op 0) - > 0 -def binop_right_to_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_MUL):$root, - [{ return Helper.matchOperandIsZero(*${root}, 2); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) ->; - -// Erase stores of undef values. -def erase_undef_store : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_STORE):$root, - [{ return Helper.matchUndefStore(*${root}); }]), - (apply [{ return Helper.eraseInst(*${root}); }]) ->; - -def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple">; -def simplify_add_to_sub: GICombineRule < - (defs root:$root, simplify_add_to_sub_matchinfo:$info), - (match (wip_match_opcode G_ADD):$root, - [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]), - (apply [{ Helper.applySimplifyAddToSub(*${root}, ${info});}]) ->; - -// Fold fp_op(cst) to the constant result of the floating point operation. -def constant_fp_op_matchinfo: GIDefMatchData<"Optional">; -def constant_fp_op: GICombineRule < - (defs root:$root, constant_fp_op_matchinfo:$info), - (match (wip_match_opcode G_FNEG, G_FABS, G_FPTRUNC, G_FSQRT, G_FLOG2):$root, - [{ return Helper.matchCombineConstantFoldFpUnary(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineConstantFoldFpUnary(*${root}, ${info}); }]) ->; - -// Fold int2ptr(ptr2int(x)) -> x -def p2i_to_i2p: GICombineRule< - (defs root:$root, register_matchinfo:$info), - (match (wip_match_opcode G_INTTOPTR):$root, - [{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineI2PToP2I(*${root}, ${info}); }]) ->; - -// Fold ptr2int(int2ptr(x)) -> x -def i2p_to_p2i: GICombineRule< - (defs root:$root, register_matchinfo:$info), - (match (wip_match_opcode G_PTRTOINT):$root, - [{ return Helper.matchCombineP2IToI2P(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineP2IToI2P(*${root}, ${info}); }]) ->; - -// Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y -def add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair">; -def add_p2i_to_ptradd : GICombineRule< - (defs root:$root, add_p2i_to_ptradd_matchinfo:$info), - (match (wip_match_opcode G_ADD):$root, - [{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }]) ->; - -// Fold (ptr_add (int2ptr C1), C2) -> C1 + C2 -def const_ptradd_to_i2p_matchinfo : GIDefMatchData<"APInt">; -def const_ptradd_to_i2p: GICombineRule< - (defs root:$root, const_ptradd_to_i2p_matchinfo:$info), - (match (wip_match_opcode G_PTR_ADD):$root, - [{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }]) ->; - -// Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) -def hoist_logic_op_with_same_opcode_hands: GICombineRule < - (defs root:$root, instruction_steps_matchdata:$info), - (match (wip_match_opcode G_AND, G_OR, G_XOR):$root, - [{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildInstructionSteps(*${root}, ${info});}]) ->; - -// Fold ashr (shl x, C), C -> sext_inreg (C) -def shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple">; -def shl_ashr_to_sext_inreg : GICombineRule< - (defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info), - (match (wip_match_opcode G_ASHR): $root, - [{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]), - (apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}]) ->; - -// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0 -def overlapping_and: GICombineRule < - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchOverlappingAnd(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) ->; - -// Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y. -def redundant_and: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y. -def redundant_or: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_OR):$root, - [{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// If the input is already sign extended, just drop the extension. -// sext_inreg x, K -> -// if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1) -def redundant_sext_inreg: GICombineRule < - (defs root:$root), - (match (wip_match_opcode G_SEXT_INREG):$root, - [{ return Helper.matchRedundantSExtInReg(*${root}); }]), - (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) ->; - -// Fold (anyext (trunc x)) -> x if the source type is same as -// the destination type. -def anyext_trunc_fold: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_ANYEXT):$root, - [{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// Fold (zext (trunc x)) -> x if the source type is same as the destination type -// and truncated bits are known to be zero. -def zext_trunc_fold_matchinfo : GIDefMatchData<"Register">; -def zext_trunc_fold: GICombineRule < - (defs root:$root, zext_trunc_fold_matchinfo:$matchinfo), - (match (wip_match_opcode G_ZEXT):$root, - [{ return Helper.matchCombineZextTrunc(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x). -def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple">; -def ext_ext_fold: GICombineRule < - (defs root:$root, ext_ext_fold_matchinfo:$matchinfo), - (match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root, - [{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }]) ->; - -def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector">; -def not_cmp_fold : GICombineRule< - (defs root:$d, not_cmp_fold_matchinfo:$info), - (match (wip_match_opcode G_XOR): $d, - [{ return Helper.matchNotCmp(*${d}, ${info}); }]), - (apply [{ Helper.applyNotCmp(*${d}, ${info}); }]) ->; - -// Fold (fneg (fneg x)) -> x. -def fneg_fneg_fold: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_FNEG):$root, - [{ return Helper.matchCombineFNegOfFNeg(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// Fold (unmerge(merge x, y, z)) -> z, y, z. -def unmerge_merge_matchinfo : GIDefMatchData<"SmallVector">; -def unmerge_merge : GICombineRule< - (defs root:$d, unmerge_merge_matchinfo:$info), - (match (wip_match_opcode G_UNMERGE_VALUES): $d, - [{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]), - (apply [{ Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]) ->; - -// Fold merge(unmerge). -def merge_unmerge : GICombineRule< - (defs root:$d, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_MERGE_VALUES):$d, - [{ return Helper.matchCombineMergeUnmerge(*${d}, ${matchinfo}); }]), - (apply [{ Helper.replaceSingleDefInstWithReg(*${d}, ${matchinfo}); }]) ->; - -// Fold (fabs (fabs x)) -> (fabs x). -def fabs_fabs_fold: GICombineRule< - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_FABS):$root, - [{ return Helper.matchCombineFAbsOfFAbs(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) ->; - -// Fold (fabs (fneg x)) -> (fabs x). -def fabs_fneg_fold: GICombineRule < - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_FABS):$root, - [{ return Helper.matchCombineFAbsOfFNeg(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; - -// Fold (unmerge cst) -> cst1, cst2, ... -def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector">; -def unmerge_cst : GICombineRule< - (defs root:$d, unmerge_cst_matchinfo:$info), - (match (wip_match_opcode G_UNMERGE_VALUES): $d, - [{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]), - (apply [{ Helper.applyCombineUnmergeConstant(*${d}, ${info}); }]) ->; - -// Fold (unmerge undef) -> undef, undef, ... -def unmerge_undef : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_UNMERGE_VALUES): $root, - [{ return Helper.matchCombineUnmergeUndef(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) ->; - -// Transform x,y = unmerge z -> x = trunc z. -def unmerge_dead_to_trunc : GICombineRule< - (defs root:$d), - (match (wip_match_opcode G_UNMERGE_VALUES): $d, - [{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]), - (apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }]) ->; - -// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0. -def unmerge_zext_to_zext : GICombineRule< - (defs root:$d), - (match (wip_match_opcode G_UNMERGE_VALUES): $d, - [{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]), - (apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }]) ->; - -// Fold trunc ([asz]ext x) -> x or ([asz]ext x) or (trunc x). -def trunc_ext_fold_matchinfo : GIDefMatchData<"std::pair">; -def trunc_ext_fold: GICombineRule < - (defs root:$root, trunc_ext_fold_matchinfo:$matchinfo), - (match (wip_match_opcode G_TRUNC):$root, - [{ return Helper.matchCombineTruncOfExt(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineTruncOfExt(*${root}, ${matchinfo}); }]) ->; - -// Fold trunc (shl x, K) -> shl (trunc x), K => K < VT.getScalarSizeInBits(). -def trunc_shl_matchinfo : GIDefMatchData<"std::pair">; -def trunc_shl: GICombineRule < - (defs root:$root, trunc_shl_matchinfo:$matchinfo), - (match (wip_match_opcode G_TRUNC):$root, - [{ return Helper.matchCombineTruncOfShl(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyCombineTruncOfShl(*${root}, ${matchinfo}); }]) ->; - -// Transform (mul x, -1) -> (sub 0, x) -def mul_by_neg_one: GICombineRule < - (defs root:$root), - (match (wip_match_opcode G_MUL):$root, - [{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]), - (apply [{ Helper.applyCombineMulByNegativeOne(*${root}); }]) ->; - -// Fold (xor (and x, y), y) -> (and (not x), y) -def xor_of_and_with_same_reg_matchinfo : - GIDefMatchData<"std::pair">; -def xor_of_and_with_same_reg: GICombineRule < - (defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo), - (match (wip_match_opcode G_XOR):$root, - [{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }]) ->; - -// Transform (ptr_add 0, x) -> (int_to_ptr x) -def ptr_add_with_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_PTR_ADD):$root, - [{ return Helper.matchPtrAddZero(*${root}); }]), - (apply [{ Helper.applyPtrAddZero(*${root}); }])>; - -def regs_small_vec : GIDefMatchData<"SmallVector">; -def combine_insert_vec_elts_build_vector : GICombineRule< - (defs root:$root, regs_small_vec:$info), - (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root, - [{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>; - -def load_or_combine : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_OR):$root, - [{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - - -def truncstore_merge_matcdata : GIDefMatchData<"MergeTruncStoresInfo">; -def truncstore_merge : GICombineRule< - (defs root:$root, truncstore_merge_matcdata:$info), - (match (wip_match_opcode G_STORE):$root, - [{ return Helper.matchTruncStoreMerge(*${root}, ${info}); }]), - (apply [{ Helper.applyTruncStoreMerge(*${root}, ${info}); }])>; - -def extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">; -def extend_through_phis : GICombineRule< - (defs root:$root, extend_through_phis_matchdata:$matchinfo), - (match (wip_match_opcode G_PHI):$root, - [{ return Helper.matchExtendThroughPhis(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyExtendThroughPhis(*${root}, ${matchinfo}); }])>; - -// Currently only the one combine above. -def insert_vec_elt_combines : GICombineGroup< - [combine_insert_vec_elts_build_vector]>; - -def extract_vec_elt_build_vec : GICombineRule< - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, - [{ return Helper.matchExtractVecEltBuildVec(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyExtractVecEltBuildVec(*${root}, ${matchinfo}); }])>; - -// Fold away full elt extracts from a build_vector. -def extract_all_elts_from_build_vector_matchinfo : - GIDefMatchData<"SmallVector>">; -def extract_all_elts_from_build_vector : GICombineRule< - (defs root:$root, extract_all_elts_from_build_vector_matchinfo:$matchinfo), - (match (wip_match_opcode G_BUILD_VECTOR):$root, - [{ return Helper.matchExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }])>; - -def extract_vec_elt_combines : GICombineGroup<[ - extract_vec_elt_build_vec, - extract_all_elts_from_build_vector]>; - -def funnel_shift_from_or_shift : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_OR):$root, - [{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) ->; - -def funnel_shift_to_rotate : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_FSHL, G_FSHR):$root, - [{ return Helper.matchFunnelShiftToRotate(*${root}); }]), - (apply [{ Helper.applyFunnelShiftToRotate(*${root}); }]) ->; - -def rotate_out_of_range : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_ROTR, G_ROTL):$root, - [{ return Helper.matchRotateOutOfRange(*${root}); }]), - (apply [{ Helper.applyRotateOutOfRange(*${root}); }]) ->; - -def icmp_to_true_false_known_bits : GICombineRule< - (defs root:$d, int64_matchinfo:$matchinfo), - (match (wip_match_opcode G_ICMP):$d, - [{ return Helper.matchICmpToTrueFalseKnownBits(*${d}, ${matchinfo}); }]), - (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; - -def icmp_to_lhs_known_bits : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_ICMP):$root, - [{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -def and_or_disjoint_mask : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchAndOrDisjointMask(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${info}); }])>; - -def bitfield_extract_from_and : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_AND):$root, - [{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift, - funnel_shift_to_rotate]>; - -def bitfield_extract_from_sext_inreg : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_SEXT_INREG):$root, - [{ return Helper.matchBitfieldExtractFromSExtInReg(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -def bitfield_extract_from_shr : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_ASHR, G_LSHR):$root, - [{ return Helper.matchBitfieldExtractFromShr(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -def bitfield_extract_from_shr_and : GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_ASHR, G_LSHR):$root, - [{ return Helper.matchBitfieldExtractFromShrAnd(*${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg, - bitfield_extract_from_and, - bitfield_extract_from_shr, - bitfield_extract_from_shr_and]>; - -def udiv_by_const : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_UDIV):$root, - [{ return Helper.matchUDivByConst(*${root}); }]), - (apply [{ Helper.applyUDivByConst(*${root}); }])>; - -def intdiv_combines : GICombineGroup<[udiv_by_const]>; - -def reassoc_ptradd : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_PTR_ADD):$root, - [{ return Helper.matchReassocPtrAdd(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; - -def reassocs : GICombineGroup<[reassoc_ptradd]>; - -// Constant fold operations. -def constant_fold : GICombineRule< - (defs root:$d, apint_matchinfo:$matchinfo), - (match (wip_match_opcode G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR):$d, - [{ return Helper.matchConstantFold(*${d}, ${matchinfo}); }]), - (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; - -def mulo_by_2: GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_UMULO, G_SMULO):$root, - [{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; - -def mulh_to_lshr : GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_UMULH):$root, - [{ return Helper.matchUMulHToLShr(*${root}); }]), - (apply [{ Helper.applyUMulHToLShr(*${root}); }])>; - -def mulh_combines : GICombineGroup<[mulh_to_lshr]>; - -def redundant_neg_operands: GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root, - [{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; - -// Transform (fadd x, (fmul y, z)) -> (fma y, z, x) -// (fadd x, (fmul y, z)) -> (fmad y, z, x) -// Transform (fadd (fmul x, y), z) -> (fma x, y, z) -// (fadd (fmul x, y), z) -> (fmad x, y, z) -def combine_fadd_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FADD):$root, - [{ return Helper.matchCombineFAddFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) -// -> (fmad (fpext x), (fpext y), z) -// Transform (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x) -// -> (fmad (fpext y), (fpext z), x) -def combine_fadd_fpext_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FADD):$root, - [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fadd (fma x, y, (fmul z, u)), v) -> (fma x, y, (fma z, u, v)) -// (fadd (fmad x, y, (fmul z, u)), v) -> (fmad x, y, (fmad z, u, v)) -// Transform (fadd v, (fma x, y, (fmul z, u))) -> (fma x, y, (fma z, u, v)) -// (fadd v, (fmad x, y, (fmul z, u))) -> (fmad x, y, (fmad z, u, v)) -def combine_fadd_fma_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FADD):$root, - [{ return Helper.matchCombineFAddFMAFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fadd (fma x, y, (fpext (fmul u, v))), z) -> -// (fma x, y, (fma (fpext u), (fpext v), z)) -def combine_fadd_fpext_fma_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FADD):$root, - [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMAAggressive( - *${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fsub (fmul x, y), z) -> (fma x, y, -z) -// -> (fmad x, y, -z) -def combine_fsub_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FSUB):$root, - [{ return Helper.matchCombineFSubFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) -// (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x) -def combine_fsub_fneg_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FSUB):$root, - [{ return Helper.matchCombineFSubFNegFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fsub (fpext (fmul x, y)), z) -> -// (fma (fpext x), (fpext y), (fneg z)) -def combine_fsub_fpext_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FSUB):$root, - [{ return Helper.matchCombineFSubFpExtFMulToFMadOrFMA(*${root}, - ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// Transform (fsub (fneg (fpext (fmul x, y))), z) -> -// (fneg (fma (fpext x), (fpext y), z)) -def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule< - (defs root:$root, build_fn_matchinfo:$info), - (match (wip_match_opcode G_FSUB):$root, - [{ return Helper.matchCombineFSubFpExtFNegFMulToFMadOrFMA( - *${root}, ${info}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; - -// FIXME: These should use the custom predicate feature once it lands. -def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, - undef_to_negative_one, - binop_left_undef_to_zero, - propagate_undef_any_op, - propagate_undef_all_ops, - propagate_undef_shuffle_mask, - erase_undef_store, - unmerge_undef]>; - -def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, - binop_same_val, binop_left_to_zero, - binop_right_to_zero, p2i_to_i2p, - i2p_to_p2i, anyext_trunc_fold, - fneg_fneg_fold, right_identity_one]>; - -def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p, - overlapping_and, mulo_by_2]>; - -def known_bits_simplifications : GICombineGroup<[ - redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask, - zext_trunc_fold, icmp_to_true_false_known_bits, icmp_to_lhs_known_bits]>; - -def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend, - narrow_binop_feeding_and]>; - -def phi_combines : GICombineGroup<[extend_through_phis]>; - -def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>; - -def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd, - mul_by_neg_one]>; - -def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, - combine_fadd_fpext_fmul_to_fmad_or_fma, combine_fadd_fma_fmul_to_fmad_or_fma, - combine_fadd_fpext_fma_fmul_to_fmad_or_fma, combine_fsub_fmul_to_fmad_or_fma, - combine_fsub_fneg_fmul_to_fmad_or_fma, combine_fsub_fpext_fmul_to_fmad_or_fma, - combine_fsub_fpext_fneg_fmul_to_fmad_or_fma]>; - -def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, - extract_vec_elt_combines, combines_for_extload, - combine_indexed_load_store, undef_combines, identity_combines, phi_combines, - simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, - reassocs, ptr_add_immed_chain, - shl_ashr_to_sext_inreg, sext_inreg_of_load, - width_reduction_combines, select_combines, - known_bits_simplifications, ext_ext_fold, - not_cmp_fold, opt_brcond_by_inverting_cond, - unmerge_merge, fabs_fabs_fold, unmerge_cst, unmerge_dead_to_trunc, - unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shl, - const_combines, xor_of_and_with_same_reg, ptr_add_with_zero, - shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine, - truncstore_merge, div_rem_to_divrem, funnel_shift_combines, - form_bitfield_extract, constant_fold, fabs_fneg_fold, - intdiv_combines, mulh_combines, redundant_neg_operands, - and_or_disjoint_mask, fma_combines]>; - -// A combine group used to for prelegalizer combiners at -O0. The combines in -// this group have been selected based on experiments to balance code size and -// compile time performance. -def optnone_combines : GICombineGroup<[trivial_combines, - ptr_add_immed_chain, combines_for_extload, - not_cmp_fold, opt_brcond_by_inverting_cond]>; diff --git a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td b/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td deleted file mode 100644 index 51578b66b1..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td +++ /dev/null @@ -1,15 +0,0 @@ -//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -class RegisterBank classes> { - string Name = name; - list RegisterClasses = classes; -} diff --git a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td deleted file mode 100644 index 12eee24b57..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ /dev/null @@ -1,221 +0,0 @@ -//===- TargetGlobalISel.td - Common code for GlobalISel ----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces used to support -// SelectionDAG instruction selection patterns (specified in -// TargetSelectionDAG.td) when generating GlobalISel instruction selectors. -// -// This is intended as a compatibility layer, to enable reuse of target -// descriptions written for SelectionDAG without requiring explicit GlobalISel -// support. It will eventually supersede SelectionDAG patterns. -// -//===----------------------------------------------------------------------===// - -// Declare that a generic Instruction is 'equivalent' to an SDNode, that is, -// SelectionDAG patterns involving the SDNode can be transformed to match the -// Instruction instead. -class GINodeEquiv { - Instruction I = i; - SDNode Node = node; - - // SelectionDAG has separate nodes for atomic and non-atomic memory operations - // (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel - // stores this information in the MachineMemoryOperand. - bit CheckMMOIsNonAtomic = false; - bit CheckMMOIsAtomic = false; - - // SelectionDAG has one node for all loads and uses predicates to - // differentiate them. GlobalISel on the other hand uses separate opcodes. - // When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD - // depending on the predicates on the node. - Instruction IfSignExtend = ?; - Instruction IfZeroExtend = ?; - - // SelectionDAG has one setcc for all compares. This differentiates - // for G_ICMP and G_FCMP. - Instruction IfFloatingPoint = ?; -} - -// These are defined in the same order as the G_* instructions. -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -// G_INTTOPTR - SelectionDAG has no equivalent. -// G_PTRTOINT - SelectionDAG has no equivalent. -def : GINodeEquiv; -// timm must not be materialized and therefore has no GlobalISel equivalent -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -// ISD::INTRINSIC_VOID can also be handled with G_INTRINSIC_W_SIDE_EFFECTS. -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; - -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; - -// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some -// complications that tablegen must take care of. For example, Predicates such -// as isSignExtLoad require that this is not a perfect 1:1 mapping since a -// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally, -// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had -// separate nodes for them. This GINodeEquiv maps the non-atomic loads to -// G_LOAD with a non-atomic MachineMemOperand. -def : GINodeEquiv { - let CheckMMOIsNonAtomic = true; - let IfSignExtend = G_SEXTLOAD; - let IfZeroExtend = G_ZEXTLOAD; -} - -def : GINodeEquiv { - let IfFloatingPoint = G_FCMP; -} - -// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some -// complications that tablegen must take care of. For example, predicates such -// as isTruncStore require that this is not a perfect 1:1 mapping since a -// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally, -// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had -// separate nodes for them. This GINodeEquiv maps the non-atomic stores to -// G_STORE with a non-atomic MachineMemOperand. -def : GINodeEquiv { let CheckMMOIsNonAtomic = true; } - -def : GINodeEquiv { - let CheckMMOIsNonAtomic = false; - let CheckMMOIsAtomic = true; -} - -// Operands are swapped for atomic_store vs. regular store -def : GINodeEquiv { - let CheckMMOIsNonAtomic = false; - let CheckMMOIsAtomic = true; -} - -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; -def : GINodeEquiv; - -// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. -// Should be used on defs that subclass GIComplexOperandMatcher<>. -class GIComplexPatternEquiv { - ComplexPattern SelDAGEquivalent = seldag; -} - -// Specifies the GlobalISel equivalents for SelectionDAG's SDNodeXForm. -// Should be used on defs that subclass GICustomOperandRenderer<>. -class GISDNodeXFormEquiv { - SDNodeXForm SelDAGEquivalent = seldag; -} diff --git a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td b/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td deleted file mode 100644 index 135d4a5e0d..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td +++ /dev/null @@ -1,65 +0,0 @@ -//===- Target.td - Define GlobalISel rules -----------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces used to support -// SelectionDAG instruction selection patterns (specified in -// TargetSelectionDAG.td) when generating GlobalISel instruction selectors. -// -// This is intended as a compatibility layer, to enable reuse of target -// descriptions written for SelectionDAG without requiring explicit GlobalISel -// support. It will eventually supersede SelectionDAG patterns. -// -//===----------------------------------------------------------------------===// - -// Definitions that inherit from LLT define types that will be used in the -// GlobalISel matcher. -class LLT; - -def s32 : LLT; -def s64 : LLT; - -// Defines a matcher for complex operands. This is analogous to ComplexPattern -// from SelectionDAG. -// -// Definitions that inherit from this may also inherit from -// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving -// those ComplexPatterns. -class GIComplexOperandMatcher { - // The expected type of the root of the match. - // - // TODO: We should probably support, any-type, any-scalar, and multiple types - // in the future. - LLT Type = type; - - // The function that determines whether the operand matches. It should be of - // the form: - // ComplexRendererFn select(MachineOperand &Root) const; - // where Root is the root of the match. The function should return nullptr - // on match failure, or a ComplexRendererFn that renders the operand in case - // of a successful match. - string MatcherFn = matcherfn; -} - -// Defines a custom renderer. This is analogous to SDNodeXForm from -// SelectionDAG. Unlike SDNodeXForm, this matches a MachineInstr and -// renders directly to the result instruction without an intermediate node. -// -// Definitions that inherit from this may also inherit from GISDNodeXFormEquiv -// to enable the import of SelectionDAG patterns involving those SDNodeXForms. -class GICustomOperandRenderer { - // The function renders the operand(s) of the matched instruction to - // the specified instruction. It should be of the form: - // void render(MachineInstrBuilder &MIB, const MachineInstr &MI, - // int OpIdx = -1) - // - // If OpIdx is specified (i.e. not invalid/negative), this - // references the source operand MI.getOperand(OpIdx). Otherwise, - // this is the value defined by MI. This is to support the case - // where there is no corresponding instruction to match. - string RendererFn = rendererfn; -} diff --git a/suite/synctools/tablegen/include/llvm/Target/Target.td b/suite/synctools/tablegen/include/llvm/Target/Target.td deleted file mode 100644 index 21af476254..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/Target.td +++ /dev/null @@ -1,1743 +0,0 @@ -//===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces which should be -// implemented by each target which is using a TableGen based code generator. -// -//===----------------------------------------------------------------------===// - -// Include all information about LLVM intrinsics. -include "llvm/IR/Intrinsics.td" - -//===----------------------------------------------------------------------===// -// Register file description - These classes are used to fill in the target -// description classes. - -class HwMode { - // A string representing subtarget features that turn on this HW mode. - // For example, "+feat1,-feat2" will indicate that the mode is active - // when "feat1" is enabled and "feat2" is disabled at the same time. - // Any other features are not checked. - // When multiple modes are used, they should be mutually exclusive, - // otherwise the results are unpredictable. - string Features = FS; -} - -// A special mode recognized by tablegen. This mode is considered active -// when no other mode is active. For targets that do not use specific hw -// modes, this is the only mode. -def DefaultMode : HwMode<"">; - -// A class used to associate objects with HW modes. It is only intended to -// be used as a base class, where the derived class should contain a member -// "Objects", which is a list of the same length as the list of modes. -// The n-th element on the Objects list will be associated with the n-th -// element on the Modes list. -class HwModeSelect Ms> { - list Modes = Ms; -} - -// A common class that implements a counterpart of ValueType, which is -// dependent on a HW mode. This class inherits from ValueType itself, -// which makes it possible to use objects of this class where ValueType -// objects could be used. This is specifically applicable to selection -// patterns. -class ValueTypeByHwMode Ms, list Ts> - : HwModeSelect, ValueType<0, 0> { - // The length of this list must be the same as the length of Ms. - list Objects = Ts; -} - -// A class representing the register size, spill size and spill alignment -// in bits of a register. -class RegInfo { - int RegSize = RS; // Register size in bits. - int SpillSize = SS; // Spill slot size in bits. - int SpillAlignment = SA; // Spill slot alignment in bits. -} - -// The register size/alignment information, parameterized by a HW mode. -class RegInfoByHwMode Ms = [], list Ts = []> - : HwModeSelect { - // The length of this list must be the same as the length of Ms. - list Objects = Ts; -} - -// SubRegIndex - Use instances of SubRegIndex to identify subregisters. -class SubRegIndex { - string Namespace = ""; - - // Size - Size (in bits) of the sub-registers represented by this index. - int Size = size; - - // Offset - Offset of the first bit that is part of this sub-register index. - // Set it to -1 if the same index is used to represent sub-registers that can - // be at different offsets (for example when using an index to access an - // element in a register tuple). - int Offset = offset; - - // ComposedOf - A list of two SubRegIndex instances, [A, B]. - // This indicates that this SubRegIndex is the result of composing A and B. - // See ComposedSubRegIndex. - list ComposedOf = []; - - // CoveringSubRegIndices - A list of two or more sub-register indexes that - // cover this sub-register. - // - // This field should normally be left blank as TableGen can infer it. - // - // TableGen automatically detects sub-registers that straddle the registers - // in the SubRegs field of a Register definition. For example: - // - // Q0 = dsub_0 -> D0, dsub_1 -> D1 - // Q1 = dsub_0 -> D2, dsub_1 -> D3 - // D1_D2 = dsub_0 -> D1, dsub_1 -> D2 - // QQ0 = qsub_0 -> Q0, qsub_1 -> Q1 - // - // TableGen will infer that D1_D2 is a sub-register of QQ0. It will be given - // the synthetic index dsub_1_dsub_2 unless some SubRegIndex is defined with - // CoveringSubRegIndices = [dsub_1, dsub_2]. - list CoveringSubRegIndices = []; -} - -// ComposedSubRegIndex - A sub-register that is the result of composing A and B. -// Offset is set to the sum of A and B's Offsets. Size is set to B's Size. -class ComposedSubRegIndex - : SubRegIndex { - // See SubRegIndex. - let ComposedOf = [A, B]; -} - -// RegAltNameIndex - The alternate name set to use for register operands of -// this register class when printing. -class RegAltNameIndex { - string Namespace = ""; - - // A set to be used if the name for a register is not defined in this set. - // This allows creating name sets with only a few alternative names. - RegAltNameIndex FallbackRegAltNameIndex = ?; -} -def NoRegAltName : RegAltNameIndex; - -// Register - You should define one instance of this class for each register -// in the target machine. String n will become the "name" of the register. -class Register altNames = []> { - string Namespace = ""; - string AsmName = n; - list AltNames = altNames; - - // Aliases - A list of registers that this register overlaps with. A read or - // modification of this register can potentially read or modify the aliased - // registers. - list Aliases = []; - - // SubRegs - A list of registers that are parts of this register. Note these - // are "immediate" sub-registers and the registers within the list do not - // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], - // not [AX, AH, AL]. - list SubRegs = []; - - // SubRegIndices - For each register in SubRegs, specify the SubRegIndex used - // to address it. Sub-sub-register indices are automatically inherited from - // SubRegs. - list SubRegIndices = []; - - // RegAltNameIndices - The alternate name indices which are valid for this - // register. - list RegAltNameIndices = []; - - // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. - // These values can be determined by locating the .h file in the - // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The - // order of these names correspond to the enumeration used by gcc. A value of - // -1 indicates that the gcc number is undefined and -2 that register number - // is invalid for this mode/flavour. - list DwarfNumbers = []; - - // CostPerUse - Additional cost of instructions using this register compared - // to other registers in its class. The register allocator will try to - // minimize the number of instructions using a register with a CostPerUse. - // This is used by the ARC target, by the ARM Thumb and x86-64 targets, where - // some registers require larger instruction encodings, by the RISC-V target, - // where some registers preclude using some C instructions. By making it a - // list, targets can have multiple cost models associated with each register - // and can choose one specific cost model per Machine Function by overriding - // TargetRegisterInfo::getRegisterCostTableIndex. Every target register will - // finally have an equal number of cost values which is the max of costPerUse - // values specified. Any mismatch in the cost values for a register will be - // filled with zeros. Restricted the cost type to uint8_t in the - // generated table. It will considerably reduce the table size. - list CostPerUse = [0]; - - // CoveredBySubRegs - When this bit is set, the value of this register is - // completely determined by the value of its sub-registers. For example, the - // x86 register AX is covered by its sub-registers AL and AH, but EAX is not - // covered by its sub-register AX. - bit CoveredBySubRegs = false; - - // HWEncoding - The target specific hardware encoding for this register. - bits<16> HWEncoding = 0; - - bit isArtificial = false; -} - -// RegisterWithSubRegs - This can be used to define instances of Register which -// need to specify sub-registers. -// List "subregs" specifies which registers are sub-registers to this one. This -// is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. -// This allows the code generator to be careful not to put two values with -// overlapping live ranges into registers which alias. -class RegisterWithSubRegs subregs> : Register { - let SubRegs = subregs; -} - -// DAGOperand - An empty base class that unifies RegisterClass's and other forms -// of Operand's that are legal as type qualifiers in DAG patterns. This should -// only ever be used for defining multiclasses that are polymorphic over both -// RegisterClass's and other Operand's. -class DAGOperand { - string OperandNamespace = "MCOI"; - string DecoderMethod = ""; -} - -// RegisterClass - Now that all of the registers are defined, and aliases -// between registers are defined, specify which registers belong to which -// register classes. This also defines the default allocation order of -// registers by register allocators. -// -class RegisterClass regTypes, int alignment, - dag regList, RegAltNameIndex idx = NoRegAltName> - : DAGOperand { - string Namespace = namespace; - - // The register size/alignment information, parameterized by a HW mode. - RegInfoByHwMode RegInfos; - - // RegType - Specify the list ValueType of the registers in this register - // class. Note that all registers in a register class must have the same - // ValueTypes. This is a list because some targets permit storing different - // types in same register, for example vector values with 128-bit total size, - // but different count/size of items, like SSE on x86. - // - list RegTypes = regTypes; - - // Size - Specify the spill size in bits of the registers. A default value of - // zero lets tablegen pick an appropriate size. - int Size = 0; - - // Alignment - Specify the alignment required of the registers when they are - // stored or loaded to memory. - // - int Alignment = alignment; - - // CopyCost - This value is used to specify the cost of copying a value - // between two registers in this register class. The default value is one - // meaning it takes a single instruction to perform the copying. A negative - // value means copying is extremely expensive or impossible. - int CopyCost = 1; - - // MemberList - Specify which registers are in this class. If the - // allocation_order_* method are not specified, this also defines the order of - // allocation used by the register allocator. - // - dag MemberList = regList; - - // AltNameIndex - The alternate register name to use when printing operands - // of this register class. Every register in the register class must have - // a valid alternate name for the given index. - RegAltNameIndex altNameIndex = idx; - - // isAllocatable - Specify that the register class can be used for virtual - // registers and register allocation. Some register classes are only used to - // model instruction operand constraints, and should have isAllocatable = 0. - bit isAllocatable = true; - - // AltOrders - List of alternative allocation orders. The default order is - // MemberList itself, and that is good enough for most targets since the - // register allocators automatically remove reserved registers and move - // callee-saved registers to the end. - list AltOrders = []; - - // AltOrderSelect - The body of a function that selects the allocation order - // to use in a given machine function. The code will be inserted in a - // function like this: - // - // static inline unsigned f(const MachineFunction &MF) { ... } - // - // The function should return 0 to select the default order defined by - // MemberList, 1 to select the first AltOrders entry and so on. - code AltOrderSelect = [{}]; - - // Specify allocation priority for register allocators using a greedy - // heuristic. Classes with higher priority values are assigned first. This is - // useful as it is sometimes beneficial to assign registers to highly - // constrained classes first. The value has to be in the range [0,63]. - int AllocationPriority = 0; - - // Generate register pressure set for this register class and any class - // synthesized from it. Set to 0 to inhibit unneeded pressure sets. - bit GeneratePressureSet = true; - - // Weight override for register pressure calculation. This is the value - // TargetRegisterClass::getRegClassWeight() will return. The weight is in - // units of pressure for this register class. If unset tablegen will - // calculate a weight based on a number of register units in this register - // class registers. The weight is per register. - int Weight = ?; - - // The diagnostic type to present when referencing this operand in a match - // failure error message. If this is empty, the default Match_InvalidOperand - // diagnostic type will be used. If this is "", a Match_ enum - // value will be generated and used for this operand type. The target - // assembly parser is responsible for converting this into a user-facing - // diagnostic message. - string DiagnosticType = ""; - - // A diagnostic message to emit when an invalid value is provided for this - // register class when it is being used an assembly operand. If this is - // non-empty, an anonymous diagnostic type enum value will be generated, and - // the assembly matcher will provide a function to map from diagnostic types - // to message strings. - string DiagnosticString = ""; - - // Target-specific flags. This becomes the TSFlags field in TargetRegisterClass. - bits<8> TSFlags = 0; -} - -// The memberList in a RegisterClass is a dag of set operations. TableGen -// evaluates these set operations and expand them into register lists. These -// are the most common operation, see test/TableGen/SetTheory.td for more -// examples of what is possible: -// -// (add R0, R1, R2) - Set Union. Each argument can be an individual register, a -// register class, or a sub-expression. This is also the way to simply list -// registers. -// -// (sub GPR, SP) - Set difference. Subtract the last arguments from the first. -// -// (and GPR, CSR) - Set intersection. All registers from the first set that are -// also in the second set. -// -// (sequence "R%u", 0, 15) -> [R0, R1, ..., R15]. Generate a sequence of -// numbered registers. Takes an optional 4th operand which is a stride to use -// when generating the sequence. -// -// (shl GPR, 4) - Remove the first N elements. -// -// (trunc GPR, 4) - Truncate after the first N elements. -// -// (rotl GPR, 1) - Rotate N places to the left. -// -// (rotr GPR, 1) - Rotate N places to the right. -// -// (decimate GPR, 2) - Pick every N'th element, starting with the first. -// -// (interleave A, B, ...) - Interleave the elements from each argument list. -// -// All of these operators work on ordered sets, not lists. That means -// duplicates are removed from sub-expressions. - -// Set operators. The rest is defined in TargetSelectionDAG.td. -def sequence; -def decimate; -def interleave; - -// RegisterTuples - Automatically generate super-registers by forming tuples of -// sub-registers. This is useful for modeling register sequence constraints -// with pseudo-registers that are larger than the architectural registers. -// -// The sub-register lists are zipped together: -// -// def EvenOdd : RegisterTuples<[sube, subo], [(add R0, R2), (add R1, R3)]>; -// -// Generates the same registers as: -// -// let SubRegIndices = [sube, subo] in { -// def R0_R1 : RegisterWithSubRegs<"", [R0, R1]>; -// def R2_R3 : RegisterWithSubRegs<"", [R2, R3]>; -// } -// -// The generated pseudo-registers inherit super-classes and fields from their -// first sub-register. Most fields from the Register class are inferred, and -// the AsmName and Dwarf numbers are cleared. -// -// RegisterTuples instances can be used in other set operations to form -// register classes and so on. This is the only way of using the generated -// registers. -// -// RegNames may be specified to supply asm names for the generated tuples. -// If used must have the same size as the list of produced registers. -class RegisterTuples Indices, list Regs, - list RegNames = []> { - // SubRegs - N lists of registers to be zipped up. Super-registers are - // synthesized from the first element of each SubRegs list, the second - // element and so on. - list SubRegs = Regs; - - // SubRegIndices - N SubRegIndex instances. This provides the names of the - // sub-registers in the synthesized super-registers. - list SubRegIndices = Indices; - - // List of asm names for the generated tuple registers. - list RegAsmNames = RegNames; -} - - -//===----------------------------------------------------------------------===// -// DwarfRegNum - This class provides a mapping of the llvm register enumeration -// to the register numbering used by gcc and gdb. These values are used by a -// debug information writer to describe where values may be located during -// execution. -class DwarfRegNum Numbers> { - // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. - // These values can be determined by locating the .h file in the - // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The - // order of these names correspond to the enumeration used by gcc. A value of - // -1 indicates that the gcc number is undefined and -2 that register number - // is invalid for this mode/flavour. - list DwarfNumbers = Numbers; -} - -// DwarfRegAlias - This class declares that a given register uses the same dwarf -// numbers as another one. This is useful for making it clear that the two -// registers do have the same number. It also lets us build a mapping -// from dwarf register number to llvm register. -class DwarfRegAlias { - Register DwarfAlias = reg; -} - -//===----------------------------------------------------------------------===// -// Pull in the common support for MCPredicate (portable scheduling predicates). -// -include "llvm/Target/TargetInstrPredicate.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for scheduling -// -include "llvm/Target/TargetSchedule.td" - -class Predicate; // Forward def - -class InstructionEncoding { - // Size of encoded instruction. - int Size; - - // The "namespace" in which this instruction exists, on targets like ARM - // which multiple ISA namespaces exist. - string DecoderNamespace = ""; - - // List of predicates which will be turned into isel matching code. - list Predicates = []; - - string DecoderMethod = ""; - - // Is the instruction decoder method able to completely determine if the - // given instruction is valid or not. If the TableGen definition of the - // instruction specifies bitpattern A??B where A and B are static bits, the - // hasCompleteDecoder flag says whether the decoder method fully handles the - // ?? space, i.e. if it is a final arbiter for the instruction validity. - // If not then the decoder attempts to continue decoding when the decoder - // method fails. - // - // This allows to handle situations where the encoding is not fully - // orthogonal. Example: - // * InstA with bitpattern 0b0000????, - // * InstB with bitpattern 0b000000?? but the associated decoder method - // DecodeInstB() returns Fail when ?? is 0b00 or 0b11. - // - // The decoder tries to decode a bitpattern that matches both InstA and - // InstB bitpatterns first as InstB (because it is the most specific - // encoding). In the default case (hasCompleteDecoder = 1), when - // DecodeInstB() returns Fail the bitpattern gets rejected. By setting - // hasCompleteDecoder = 0 in InstB, the decoder is informed that - // DecodeInstB() is not able to determine if all possible values of ?? are - // valid or not. If DecodeInstB() returns Fail the decoder will attempt to - // decode the bitpattern as InstA too. - bit hasCompleteDecoder = true; -} - -// Allows specifying an InstructionEncoding by HwMode. If an Instruction specifies -// an EncodingByHwMode, its Inst and Size members are ignored and Ts are used -// to encode and decode based on HwMode. -class EncodingByHwMode Ms = [], list Ts = []> - : HwModeSelect { - // The length of this list must be the same as the length of Ms. - list Objects = Ts; -} - -//===----------------------------------------------------------------------===// -// Instruction set description - These classes correspond to the C++ classes in -// the Target/TargetInstrInfo.h file. -// -class Instruction : InstructionEncoding { - string Namespace = ""; - - dag OutOperandList; // An dag containing the MI def operand list. - dag InOperandList; // An dag containing the MI use operand list. - string AsmString = ""; // The .s format to print the instruction with. - - // Allows specifying a canonical InstructionEncoding by HwMode. If non-empty, - // the Inst member of this Instruction is ignored. - EncodingByHwMode EncodingInfos; - - // Pattern - Set to the DAG pattern for this instruction, if we know of one, - // otherwise, uninitialized. - list Pattern; - - // The follow state will eventually be inferred automatically from the - // instruction pattern. - - list Uses = []; // Default to using no non-operand registers - list Defs = []; // Default to modifying no non-operand registers - - // Predicates - List of predicates which will be turned into isel matching - // code. - list Predicates = []; - - // Size - Size of encoded instruction, or zero if the size cannot be determined - // from the opcode. - int Size = 0; - - // Code size, for instruction selection. - // FIXME: What does this actually mean? - int CodeSize = 0; - - // Added complexity passed onto matching pattern. - int AddedComplexity = 0; - - // Indicates if this is a pre-isel opcode that should be - // legalized/regbankselected/selected. - bit isPreISelOpcode = false; - - // These bits capture information about the high-level semantics of the - // instruction. - bit isReturn = false; // Is this instruction a return instruction? - bit isBranch = false; // Is this instruction a branch instruction? - bit isEHScopeReturn = false; // Does this instruction end an EH scope? - bit isIndirectBranch = false; // Is this instruction an indirect branch? - bit isCompare = false; // Is this instruction a comparison instruction? - bit isMoveImm = false; // Is this instruction a move immediate instruction? - bit isMoveReg = false; // Is this instruction a move register instruction? - bit isBitcast = false; // Is this instruction a bitcast instruction? - bit isSelect = false; // Is this instruction a select instruction? - bit isBarrier = false; // Can control flow fall through this instruction? - bit isCall = false; // Is this instruction a call instruction? - bit isAdd = false; // Is this instruction an add instruction? - bit isTrap = false; // Is this instruction a trap instruction? - bit canFoldAsLoad = false; // Can this be folded as a simple memory operand? - bit mayLoad = ?; // Is it possible for this inst to read memory? - bit mayStore = ?; // Is it possible for this inst to write memory? - bit mayRaiseFPException = false; // Can this raise a floating-point exception? - bit isConvertibleToThreeAddress = false; // Can this 2-addr instruction promote? - bit isCommutable = false; // Is this 3 operand instruction commutable? - bit isTerminator = false; // Is this part of the terminator for a basic block? - bit isReMaterializable = false; // Is this instruction re-materializable? - bit isPredicable = false; // 1 means this instruction is predicable - // even if it does not have any operand - // tablegen can identify as a predicate - bit isUnpredicable = false; // 1 means this instruction is not predicable - // even if it _does_ have a predicate operand - bit hasDelaySlot = false; // Does this instruction have an delay slot? - bit usesCustomInserter = false; // Pseudo instr needing special help. - bit hasPostISelHook = false; // To be *adjusted* after isel by target hook. - bit hasCtrlDep = false; // Does this instruction r/w ctrl-flow chains? - bit isNotDuplicable = false; // Is it unsafe to duplicate this instruction? - bit isConvergent = false; // Is this instruction convergent? - bit isAuthenticated = false; // Does this instruction authenticate a pointer? - bit isAsCheapAsAMove = false; // As cheap (or cheaper) than a move instruction. - bit hasExtraSrcRegAllocReq = false; // Sources have special regalloc requirement? - bit hasExtraDefRegAllocReq = false; // Defs have special regalloc requirement? - bit isRegSequence = false; // Is this instruction a kind of reg sequence? - // If so, make sure to override - // TargetInstrInfo::getRegSequenceLikeInputs. - bit isPseudo = false; // Is this instruction a pseudo-instruction? - // If so, won't have encoding information for - // the [MC]CodeEmitter stuff. - bit isExtractSubreg = false; // Is this instruction a kind of extract subreg? - // If so, make sure to override - // TargetInstrInfo::getExtractSubregLikeInputs. - bit isInsertSubreg = false; // Is this instruction a kind of insert subreg? - // If so, make sure to override - // TargetInstrInfo::getInsertSubregLikeInputs. - bit variadicOpsAreDefs = false; // Are variadic operands definitions? - - // Does the instruction have side effects that are not captured by any - // operands of the instruction or other flags? - bit hasSideEffects = ?; - - // Is this instruction a "real" instruction (with a distinct machine - // encoding), or is it a pseudo instruction used for codegen modeling - // purposes. - // FIXME: For now this is distinct from isPseudo, above, as code-gen-only - // instructions can (and often do) still have encoding information - // associated with them. Once we've migrated all of them over to true - // pseudo-instructions that are lowered to real instructions prior to - // the printer/emitter, we can remove this attribute and just use isPseudo. - // - // The intended use is: - // isPseudo: Does not have encoding information and should be expanded, - // at the latest, during lowering to MCInst. - // - // isCodeGenOnly: Does have encoding information and can go through to the - // CodeEmitter unchanged, but duplicates a canonical instruction - // definition's encoding and should be ignored when constructing the - // assembler match tables. - bit isCodeGenOnly = false; - - // Is this instruction a pseudo instruction for use by the assembler parser. - bit isAsmParserOnly = false; - - // This instruction is not expected to be queried for scheduling latencies - // and therefore needs no scheduling information even for a complete - // scheduling model. - bit hasNoSchedulingInfo = false; - - InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. - - // Scheduling information from TargetSchedule.td. - list SchedRW; - - string Constraints = ""; // OperandConstraint, e.g. $src = $dst. - - /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not - /// be encoded into the output machineinstr. - string DisableEncoding = ""; - - string PostEncoderMethod = ""; - - /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. - bits<64> TSFlags = 0; - - ///@name Assembler Parser Support - ///@{ - - string AsmMatchConverter = ""; - - /// TwoOperandAliasConstraint - Enable TableGen to auto-generate a - /// two-operand matcher inst-alias for a three operand instruction. - /// For example, the arm instruction "add r3, r3, r5" can be written - /// as "add r3, r5". The constraint is of the same form as a tied-operand - /// constraint. For example, "$Rn = $Rd". - string TwoOperandAliasConstraint = ""; - - /// Assembler variant name to use for this instruction. If specified then - /// instruction will be presented only in MatchTable for this variant. If - /// not specified then assembler variants will be determined based on - /// AsmString - string AsmVariantName = ""; - - ///@} - - /// UseNamedOperandTable - If set, the operand indices of this instruction - /// can be queried via the getNamedOperandIdx() function which is generated - /// by TableGen. - bit UseNamedOperandTable = false; - - /// Should generate helper functions that help you to map a logical operand's - /// index to the underlying MIOperand's index. - /// In most architectures logical operand indices are equal to - /// MIOperand indices, but for some CISC architectures, a logical operand - /// might be consist of multiple MIOperand (e.g. a logical operand that - /// uses complex address mode). - bit UseLogicalOperandMappings = false; - - /// Should FastISel ignore this instruction. For certain ISAs, they have - /// instructions which map to the same ISD Opcode, value type operands and - /// instruction selection predicates. FastISel cannot handle such cases, but - /// SelectionDAG can. - bit FastISelShouldIgnore = false; - - /// HasPositionOrder: Indicate tablegen to sort the instructions by record - /// ID, so that instruction that is defined earlier can be sorted earlier - /// in the assembly matching table. - bit HasPositionOrder = false; -} - -/// Defines a Pat match between compressed and uncompressed instruction. -/// The relationship and helper function generation are handled by -/// CompressInstEmitter backend. -class CompressPat predicates = []> { - /// Uncompressed instruction description. - dag Input = input; - /// Compressed instruction description. - dag Output = output; - /// Predicates that must be true for this to match. - list Predicates = predicates; - /// Duplicate match when tied operand is just different. - bit isCompressOnly = false; -} - -/// Defines an additional encoding that disassembles to the given instruction -/// Like Instruction, the Inst and SoftFail fields are omitted to allow targets -// to specify their size. -class AdditionalEncoding : InstructionEncoding { - Instruction AliasOf = I; -} - -/// PseudoInstExpansion - Expansion information for a pseudo-instruction. -/// Which instruction it expands to and how the operands map from the -/// pseudo. -class PseudoInstExpansion { - dag ResultInst = Result; // The instruction to generate. - bit isPseudo = true; -} - -/// Predicates - These are extra conditionals which are turned into instruction -/// selector matching code. Currently each predicate is just a string. -class Predicate { - string CondString = cond; - - /// AssemblerMatcherPredicate - If this feature can be used by the assembler - /// matcher, this is true. Targets should set this by inheriting their - /// feature from the AssemblerPredicate class in addition to Predicate. - bit AssemblerMatcherPredicate = false; - - /// AssemblerCondDag - Set of subtarget features being tested used - /// as alternative condition string used for assembler matcher. Must be used - /// with (all_of) to indicate that all features must be present, or (any_of) - /// to indicate that at least one must be. The required lack of presence of - /// a feature can be tested using a (not) node including the feature. - /// e.g. "(all_of ModeThumb)" is translated to "(Bits & ModeThumb) != 0". - /// "(all_of (not ModeThumb))" is translated to - /// "(Bits & ModeThumb) == 0". - /// "(all_of ModeThumb, FeatureThumb2)" is translated to - /// "(Bits & ModeThumb) != 0 && (Bits & FeatureThumb2) != 0". - /// "(any_of ModeTumb, FeatureThumb2)" is translated to - /// "(Bits & ModeThumb) != 0 || (Bits & FeatureThumb2) != 0". - /// all_of and any_of cannot be combined in a single dag, instead multiple - /// predicates can be placed onto Instruction definitions. - dag AssemblerCondDag; - - /// PredicateName - User-level name to use for the predicate. Mainly for use - /// in diagnostics such as missing feature errors in the asm matcher. - string PredicateName = ""; - - /// Setting this to '1' indicates that the predicate must be recomputed on - /// every function change. Most predicates can leave this at '0'. - /// - /// Ignored by SelectionDAG, it always recomputes the predicate on every use. - bit RecomputePerFunction = false; -} - -/// NoHonorSignDependentRounding - This predicate is true if support for -/// sign-dependent-rounding is not enabled. -def NoHonorSignDependentRounding - : Predicate<"!TM.Options.HonorSignDependentRoundingFPMath()">; - -class Requires preds> { - list Predicates = preds; -} - -/// ops definition - This is just a simple marker used to identify the operand -/// list for an instruction. outs and ins are identical both syntactically and -/// semantically; they are used to define def operands and use operands to -/// improve readability. This should be used like this: -/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. -def ops; -def outs; -def ins; - -/// variable_ops definition - Mark this instruction as taking a variable number -/// of operands. -def variable_ops; - - -/// PointerLikeRegClass - Values that are designed to have pointer width are -/// derived from this. TableGen treats the register class as having a symbolic -/// type that it doesn't know, and resolves the actual regclass to use by using -/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time. -class PointerLikeRegClass { - int RegClassKind = Kind; -} - - -/// ptr_rc definition - Mark this operand as being a pointer value whose -/// register class is resolved dynamically via a callback to TargetInstrInfo. -/// FIXME: We should probably change this to a class which contain a list of -/// flags. But currently we have but one flag. -def ptr_rc : PointerLikeRegClass<0>; - -/// unknown definition - Mark this operand as being of unknown type, causing -/// it to be resolved by inference in the context it is used. -class unknown_class; -def unknown : unknown_class; - -/// AsmOperandClass - Representation for the kinds of operands which the target -/// specific parser can create and the assembly matcher may need to distinguish. -/// -/// Operand classes are used to define the order in which instructions are -/// matched, to ensure that the instruction which gets matched for any -/// particular list of operands is deterministic. -/// -/// The target specific parser must be able to classify a parsed operand into a -/// unique class which does not partially overlap with any other classes. It can -/// match a subset of some other class, in which case the super class field -/// should be defined. -class AsmOperandClass { - /// The name to use for this class, which should be usable as an enum value. - string Name = ?; - - /// The super classes of this operand. - list SuperClasses = []; - - /// The name of the method on the target specific operand to call to test - /// whether the operand is an instance of this class. If not set, this will - /// default to "isFoo", where Foo is the AsmOperandClass name. The method - /// signature should be: - /// bool isFoo() const; - string PredicateMethod = ?; - - /// The name of the method on the target specific operand to call to add the - /// target specific operand to an MCInst. If not set, this will default to - /// "addFooOperands", where Foo is the AsmOperandClass name. The method - /// signature should be: - /// void addFooOperands(MCInst &Inst, unsigned N) const; - string RenderMethod = ?; - - /// The name of the method on the target specific operand to call to custom - /// handle the operand parsing. This is useful when the operands do not relate - /// to immediates or registers and are very instruction specific (as flags to - /// set in a processor register, coprocessor number, ...). - string ParserMethod = ?; - - // The diagnostic type to present when referencing this operand in a - // match failure error message. By default, use a generic "invalid operand" - // diagnostic. The target AsmParser maps these codes to text. - string DiagnosticType = ""; - - /// A diagnostic message to emit when an invalid value is provided for this - /// operand. - string DiagnosticString = ""; - - /// Set to 1 if this operand is optional and not always required. Typically, - /// the AsmParser will emit an error when it finishes parsing an - /// instruction if it hasn't matched all the operands yet. However, this - /// error will be suppressed if all of the remaining unmatched operands are - /// marked as IsOptional. - /// - /// Optional arguments must be at the end of the operand list. - bit IsOptional = false; - - /// The name of the method on the target specific asm parser that returns the - /// default operand for this optional operand. This method is only used if - /// IsOptional == 1. If not set, this will default to "defaultFooOperands", - /// where Foo is the AsmOperandClass name. The method signature should be: - /// std::unique_ptr defaultFooOperands() const; - string DefaultMethod = ?; -} - -def ImmAsmOperand : AsmOperandClass { - let Name = "Imm"; -} - -/// Operand Types - These provide the built-in operand types that may be used -/// by a target. Targets can optionally provide their own operand types as -/// needed, though this should not be needed for RISC targets. -class Operand : DAGOperand { - ValueType Type = ty; - string PrintMethod = "printOperand"; - string EncoderMethod = ""; - bit hasCompleteDecoder = true; - string OperandType = "OPERAND_UNKNOWN"; - dag MIOperandInfo = (ops); - - // MCOperandPredicate - Optionally, a code fragment operating on - // const MCOperand &MCOp, and returning a bool, to indicate if - // the value of MCOp is valid for the specific subclass of Operand - code MCOperandPredicate; - - // ParserMatchClass - The "match class" that operands of this type fit - // in. Match classes are used to define the order in which instructions are - // match, to ensure that which instructions gets matched is deterministic. - // - // The target specific parser must be able to classify an parsed operand into - // a unique class, which does not partially overlap with any other classes. It - // can match a subset of some other class, in which case the AsmOperandClass - // should declare the other operand as one of its super classes. - AsmOperandClass ParserMatchClass = ImmAsmOperand; -} - -class RegisterOperand - : DAGOperand { - // RegClass - The register class of the operand. - RegisterClass RegClass = regclass; - // PrintMethod - The target method to call to print register operands of - // this type. The method normally will just use an alt-name index to look - // up the name to print. Default to the generic printOperand(). - string PrintMethod = pm; - - // EncoderMethod - The target method name to call to encode this register - // operand. - string EncoderMethod = ""; - - // ParserMatchClass - The "match class" that operands of this type fit - // in. Match classes are used to define the order in which instructions are - // match, to ensure that which instructions gets matched is deterministic. - // - // The target specific parser must be able to classify an parsed operand into - // a unique class, which does not partially overlap with any other classes. It - // can match a subset of some other class, in which case the AsmOperandClass - // should declare the other operand as one of its super classes. - AsmOperandClass ParserMatchClass; - - string OperandType = "OPERAND_REGISTER"; - - // When referenced in the result of a CodeGen pattern, GlobalISel will - // normally copy the matched operand to the result. When this is set, it will - // emit a special copy that will replace zero-immediates with the specified - // zero-register. - Register GIZeroRegister = ?; -} - -let OperandType = "OPERAND_IMMEDIATE" in { -def i1imm : Operand; -def i8imm : Operand; -def i16imm : Operand; -def i32imm : Operand; -def i64imm : Operand; - -def f32imm : Operand; -def f64imm : Operand; -} - -// Register operands for generic instructions don't have an MVT, but do have -// constraints linking the operands (e.g. all operands of a G_ADD must -// have the same LLT). -class TypedOperand : Operand { - let OperandType = Ty; - bit IsPointer = false; - bit IsImmediate = false; -} - -def type0 : TypedOperand<"OPERAND_GENERIC_0">; -def type1 : TypedOperand<"OPERAND_GENERIC_1">; -def type2 : TypedOperand<"OPERAND_GENERIC_2">; -def type3 : TypedOperand<"OPERAND_GENERIC_3">; -def type4 : TypedOperand<"OPERAND_GENERIC_4">; -def type5 : TypedOperand<"OPERAND_GENERIC_5">; - -let IsPointer = true in { - def ptype0 : TypedOperand<"OPERAND_GENERIC_0">; - def ptype1 : TypedOperand<"OPERAND_GENERIC_1">; - def ptype2 : TypedOperand<"OPERAND_GENERIC_2">; - def ptype3 : TypedOperand<"OPERAND_GENERIC_3">; - def ptype4 : TypedOperand<"OPERAND_GENERIC_4">; - def ptype5 : TypedOperand<"OPERAND_GENERIC_5">; -} - -// untyped_imm is for operands where isImm() will be true. It currently has no -// special behaviour and is only used for clarity. -def untyped_imm_0 : TypedOperand<"OPERAND_GENERIC_IMM_0"> { - let IsImmediate = true; -} - -/// zero_reg definition - Special node to stand for the zero register. -/// -def zero_reg; - -/// undef_tied_input - Special node to indicate an input register tied -/// to an output which defaults to IMPLICIT_DEF. -def undef_tied_input; - -/// All operands which the MC layer classifies as predicates should inherit from -/// this class in some manner. This is already handled for the most commonly -/// used PredicateOperand, but may be useful in other circumstances. -class PredicateOp; - -/// OperandWithDefaultOps - This Operand class can be used as the parent class -/// for an Operand that needs to be initialized with a default value if -/// no value is supplied in a pattern. This class can be used to simplify the -/// pattern definitions for instructions that have target specific flags -/// encoded as immediate operands. -class OperandWithDefaultOps - : Operand { - dag DefaultOps = defaultops; -} - -/// PredicateOperand - This can be used to define a predicate operand for an -/// instruction. OpTypes specifies the MIOperandInfo for the operand, and -/// AlwaysVal specifies the value of this predicate when set to "always -/// execute". -class PredicateOperand - : OperandWithDefaultOps, PredicateOp { - let MIOperandInfo = OpTypes; -} - -/// OptionalDefOperand - This is used to define a optional definition operand -/// for an instruction. DefaultOps is the register the operand represents if -/// none is supplied, e.g. zero_reg. -class OptionalDefOperand - : OperandWithDefaultOps { - let MIOperandInfo = OpTypes; -} - - -// InstrInfo - This class should only be instantiated once to provide parameters -// which are global to the target machine. -// -class InstrInfo { - // Target can specify its instructions in either big or little-endian formats. - // For instance, while both Sparc and PowerPC are big-endian platforms, the - // Sparc manual specifies its instructions in the format [31..0] (big), while - // PowerPC specifies them using the format [0..31] (little). - bit isLittleEndianEncoding = false; - - // The instruction properties mayLoad, mayStore, and hasSideEffects are unset - // by default, and TableGen will infer their value from the instruction - // pattern when possible. - // - // Normally, TableGen will issue an error if it can't infer the value of a - // property that hasn't been set explicitly. When guessInstructionProperties - // is set, it will guess a safe value instead. - // - // This option is a temporary migration help. It will go away. - bit guessInstructionProperties = true; - - // TableGen's instruction encoder generator has support for matching operands - // to bit-field variables both by name and by position. While matching by - // name is preferred, this is currently not possible for complex operands, - // and some targets still reply on the positional encoding rules. When - // generating a decoder for such targets, the positional encoding rules must - // be used by the decoder generator as well. - // - // This option is temporary; it will go away once the TableGen decoder - // generator has better support for complex operands and targets have - // migrated away from using positionally encoded operands. - bit decodePositionallyEncodedOperands = false; - - // When set, this indicates that there will be no overlap between those - // operands that are matched by ordering (positional operands) and those - // matched by name. - // - // This option is temporary; it will go away once the TableGen decoder - // generator has better support for complex operands and targets have - // migrated away from using positionally encoded operands. - bit noNamedPositionallyEncodedOperands = false; -} - -// Standard Pseudo Instructions. -// This list must match TargetOpcodes.def. -// Only these instructions are allowed in the TargetOpcode namespace. -// Ensure mayLoad and mayStore have a default value, so as not to break -// targets that set guessInstructionProperties=0. Any local definition of -// mayLoad/mayStore takes precedence over these default values. -class StandardPseudoInstruction : Instruction { - let mayLoad = false; - let mayStore = false; - let isCodeGenOnly = true; - let isPseudo = true; - let hasNoSchedulingInfo = true; - let Namespace = "TargetOpcode"; -} -def PHI : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins variable_ops); - let AsmString = "PHINODE"; - let hasSideEffects = false; -} -def INLINEASM : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = ""; - let hasSideEffects = false; // Note side effect is encoded in an operand. -} -def INLINEASM_BR : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = ""; - // Unlike INLINEASM, this is always treated as having side-effects. - let hasSideEffects = true; - // Despite potentially branching, this instruction is intentionally _not_ - // marked as a terminator or a branch. -} -def CFI_INSTRUCTION : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = ""; - let hasCtrlDep = true; - let hasSideEffects = false; - let isNotDuplicable = true; -} -def EH_LABEL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = ""; - let hasCtrlDep = true; - let hasSideEffects = false; - let isNotDuplicable = true; -} -def GC_LABEL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = ""; - let hasCtrlDep = true; - let hasSideEffects = false; - let isNotDuplicable = true; -} -def ANNOTATION_LABEL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = ""; - let hasCtrlDep = true; - let hasSideEffects = false; - let isNotDuplicable = true; -} -def KILL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = ""; - let hasSideEffects = false; -} -def EXTRACT_SUBREG : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$supersrc, i32imm:$subidx); - let AsmString = ""; - let hasSideEffects = false; -} -def INSERT_SUBREG : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); - let AsmString = ""; - let hasSideEffects = false; - let Constraints = "$supersrc = $dst"; -} -def IMPLICIT_DEF : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins); - let AsmString = ""; - let hasSideEffects = false; - let isReMaterializable = true; - let isAsCheapAsAMove = true; -} -def SUBREG_TO_REG : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx); - let AsmString = ""; - let hasSideEffects = false; -} -def COPY_TO_REGCLASS : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$src, i32imm:$regclass); - let AsmString = ""; - let hasSideEffects = false; - let isAsCheapAsAMove = true; -} -def DBG_VALUE : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "DBG_VALUE"; - let hasSideEffects = false; -} -def DBG_VALUE_LIST : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "DBG_VALUE_LIST"; - let hasSideEffects = 0; -} -def DBG_INSTR_REF : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "DBG_INSTR_REF"; - let hasSideEffects = false; -} -def DBG_PHI : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "DBG_PHI"; - let hasSideEffects = 0; -} -def DBG_LABEL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$label); - let AsmString = "DBG_LABEL"; - let hasSideEffects = false; -} -def REG_SEQUENCE : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$supersrc, variable_ops); - let AsmString = ""; - let hasSideEffects = false; - let isAsCheapAsAMove = true; -} -def COPY : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$src); - let AsmString = ""; - let hasSideEffects = false; - let isAsCheapAsAMove = true; - let hasNoSchedulingInfo = false; -} -def BUNDLE : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "BUNDLE"; - let hasSideEffects = false; -} -def LIFETIME_START : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = "LIFETIME_START"; - let hasSideEffects = false; -} -def LIFETIME_END : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id); - let AsmString = "LIFETIME_END"; - let hasSideEffects = false; -} -def PSEUDO_PROBE : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i64imm:$guid, i64imm:$index, i8imm:$type, i32imm:$attr); - let AsmString = "PSEUDO_PROBE"; - let hasSideEffects = 1; -} -def ARITH_FENCE : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins unknown:$src); - let AsmString = ""; - let hasSideEffects = false; - let Constraints = "$src = $dst"; -} - -def STACKMAP : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i64imm:$id, i32imm:$nbytes, variable_ops); - let hasSideEffects = true; - let isCall = true; - let mayLoad = true; - let usesCustomInserter = true; -} -def PATCHPOINT : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins i64imm:$id, i32imm:$nbytes, unknown:$callee, - i32imm:$nargs, i32imm:$cc, variable_ops); - let hasSideEffects = true; - let isCall = true; - let mayLoad = true; - let usesCustomInserter = true; -} -def STATEPOINT : StandardPseudoInstruction { - let OutOperandList = (outs variable_ops); - let InOperandList = (ins variable_ops); - let usesCustomInserter = true; - let mayLoad = true; - let mayStore = true; - let hasSideEffects = true; - let isCall = true; -} -def LOAD_STACK_GUARD : StandardPseudoInstruction { - let OutOperandList = (outs ptr_rc:$dst); - let InOperandList = (ins); - let mayLoad = true; - bit isReMaterializable = true; - let hasSideEffects = false; - bit isPseudo = true; -} -def PREALLOCATED_SETUP : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins i32imm:$a); - let usesCustomInserter = true; - let hasSideEffects = true; -} -def PREALLOCATED_ARG : StandardPseudoInstruction { - let OutOperandList = (outs ptr_rc:$loc); - let InOperandList = (ins i32imm:$a, i32imm:$b); - let usesCustomInserter = true; - let hasSideEffects = true; -} -def LOCAL_ESCAPE : StandardPseudoInstruction { - // This instruction is really just a label. It has to be part of the chain so - // that it doesn't get dropped from the DAG, but it produces nothing and has - // no side effects. - let OutOperandList = (outs); - let InOperandList = (ins ptr_rc:$symbol, i32imm:$id); - let hasSideEffects = false; - let hasCtrlDep = true; -} -def FAULTING_OP : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins variable_ops); - let usesCustomInserter = true; - let hasSideEffects = true; - let mayLoad = true; - let mayStore = true; - let isTerminator = true; - let isBranch = true; -} -def PATCHABLE_OP : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let usesCustomInserter = true; - let mayLoad = true; - let mayStore = true; - let hasSideEffects = true; -} -def PATCHABLE_FUNCTION_ENTER : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins); - let AsmString = "# XRay Function Enter."; - let usesCustomInserter = true; - let hasSideEffects = true; -} -def PATCHABLE_RET : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "# XRay Function Patchable RET."; - let usesCustomInserter = true; - let hasSideEffects = true; - let isTerminator = true; - let isReturn = true; -} -def PATCHABLE_FUNCTION_EXIT : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins); - let AsmString = "# XRay Function Exit."; - let usesCustomInserter = true; - let hasSideEffects = true; - let isReturn = false; // Original return instruction will follow -} -def PATCHABLE_TAIL_CALL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = "# XRay Tail Call Exit."; - let usesCustomInserter = true; - let hasSideEffects = true; - let isReturn = true; -} -def PATCHABLE_EVENT_CALL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins ptr_rc:$event, unknown:$size); - let AsmString = "# XRay Custom Event Log."; - let usesCustomInserter = true; - let isCall = true; - let mayLoad = true; - let mayStore = true; - let hasSideEffects = true; -} -def PATCHABLE_TYPED_EVENT_CALL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins unknown:$type, ptr_rc:$event, unknown:$size); - let AsmString = "# XRay Typed Event Log."; - let usesCustomInserter = true; - let isCall = true; - let mayLoad = true; - let mayStore = true; - let hasSideEffects = true; -} -def FENTRY_CALL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins); - let AsmString = "# FEntry call"; - let usesCustomInserter = true; - let isCall = true; - let mayLoad = true; - let mayStore = true; - let hasSideEffects = true; -} -def ICALL_BRANCH_FUNNEL : StandardPseudoInstruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); - let AsmString = ""; - let hasSideEffects = true; -} - -// Generic opcodes used in GlobalISel. -include "llvm/Target/GenericOpcodes.td" - -//===----------------------------------------------------------------------===// -// AsmParser - This class can be implemented by targets that wish to implement -// .s file parsing. -// -// Subtargets can have multiple different assembly parsers (e.g. AT&T vs Intel -// syntax on X86 for example). -// -class AsmParser { - // AsmParserClassName - This specifies the suffix to use for the asmparser - // class. Generated AsmParser classes are always prefixed with the target - // name. - string AsmParserClassName = "AsmParser"; - - // AsmParserInstCleanup - If non-empty, this is the name of a custom member - // function of the AsmParser class to call on every matched instruction. - // This can be used to perform target specific instruction post-processing. - string AsmParserInstCleanup = ""; - - // ShouldEmitMatchRegisterName - Set to false if the target needs a hand - // written register name matcher - bit ShouldEmitMatchRegisterName = true; - - // Set to true if the target needs a generated 'alternative register name' - // matcher. - // - // This generates a function which can be used to lookup registers from - // their aliases. This function will fail when called on targets where - // several registers share the same alias (i.e. not a 1:1 mapping). - bit ShouldEmitMatchRegisterAltName = false; - - // Set to true if MatchRegisterName and MatchRegisterAltName functions - // should be generated even if there are duplicate register names. The - // target is responsible for coercing aliased registers as necessary - // (e.g. in validateTargetOperandClass), and there are no guarantees about - // which numeric register identifier will be returned in the case of - // multiple matches. - bit AllowDuplicateRegisterNames = false; - - // HasMnemonicFirst - Set to false if target instructions don't always - // start with a mnemonic as the first token. - bit HasMnemonicFirst = true; - - // ReportMultipleNearMisses - - // When 0, the assembly matcher reports an error for one encoding or operand - // that did not match the parsed instruction. - // When 1, the assembly matcher returns a list of encodings that were close - // to matching the parsed instruction, so to allow more detailed error - // messages. - bit ReportMultipleNearMisses = false; -} -def DefaultAsmParser : AsmParser; - -//===----------------------------------------------------------------------===// -// AsmParserVariant - Subtargets can have multiple different assembly parsers -// (e.g. AT&T vs Intel syntax on X86 for example). This class can be -// implemented by targets to describe such variants. -// -class AsmParserVariant { - // Variant - AsmParsers can be of multiple different variants. Variants are - // used to support targets that need to parse multiple formats for the - // assembly language. - int Variant = 0; - - // Name - The AsmParser variant name (e.g., AT&T vs Intel). - string Name = ""; - - // CommentDelimiter - If given, the delimiter string used to recognize - // comments which are hard coded in the .td assembler strings for individual - // instructions. - string CommentDelimiter = ""; - - // RegisterPrefix - If given, the token prefix which indicates a register - // token. This is used by the matcher to automatically recognize hard coded - // register tokens as constrained registers, instead of tokens, for the - // purposes of matching. - string RegisterPrefix = ""; - - // TokenizingCharacters - Characters that are standalone tokens - string TokenizingCharacters = "[]*!"; - - // SeparatorCharacters - Characters that are not tokens - string SeparatorCharacters = " \t,"; - - // BreakCharacters - Characters that start new identifiers - string BreakCharacters = ""; -} -def DefaultAsmParserVariant : AsmParserVariant; - -// Operators for combining SubtargetFeatures in AssemblerPredicates -def any_of; -def all_of; - -/// AssemblerPredicate - This is a Predicate that can be used when the assembler -/// matches instructions and aliases. -class AssemblerPredicate { - bit AssemblerMatcherPredicate = true; - dag AssemblerCondDag = cond; - string PredicateName = name; -} - -/// TokenAlias - This class allows targets to define assembler token -/// operand aliases. That is, a token literal operand which is equivalent -/// to another, canonical, token literal. For example, ARM allows: -/// vmov.u32 s4, #0 -> vmov.i32, #0 -/// 'u32' is a more specific designator for the 32-bit integer type specifier -/// and is legal for any instruction which accepts 'i32' as a datatype suffix. -/// def : TokenAlias<".u32", ".i32">; -/// -/// This works by marking the match class of 'From' as a subclass of the -/// match class of 'To'. -class TokenAlias { - string FromToken = From; - string ToToken = To; -} - -/// MnemonicAlias - This class allows targets to define assembler mnemonic -/// aliases. This should be used when all forms of one mnemonic are accepted -/// with a different mnemonic. For example, X86 allows: -/// sal %al, 1 -> shl %al, 1 -/// sal %ax, %cl -> shl %ax, %cl -/// sal %eax, %cl -> shl %eax, %cl -/// etc. Though "sal" is accepted with many forms, all of them are directly -/// translated to a shl, so it can be handled with (in the case of X86, it -/// actually has one for each suffix as well): -/// def : MnemonicAlias<"sal", "shl">; -/// -/// Mnemonic aliases are mapped before any other translation in the match phase, -/// and do allow Requires predicates, e.g.: -/// -/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; -/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; -/// -/// Mnemonic aliases can also be constrained to specific variants, e.g.: -/// -/// def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; -/// -/// If no variant (e.g., "att" or "intel") is specified then the alias is -/// applied unconditionally. -class MnemonicAlias { - string FromMnemonic = From; - string ToMnemonic = To; - string AsmVariantName = VariantName; - - // Predicates - Predicates that must be true for this remapping to happen. - list Predicates = []; -} - -/// InstAlias - This defines an alternate assembly syntax that is allowed to -/// match an instruction that has a different (more canonical) assembly -/// representation. -class InstAlias { - string AsmString = Asm; // The .s format to match the instruction with. - dag ResultInst = Result; // The MCInst to generate. - - // This determines which order the InstPrinter detects aliases for - // printing. A larger value makes the alias more likely to be - // emitted. The Instruction's own definition is notionally 0.5, so 0 - // disables printing and 1 enables it if there are no conflicting aliases. - int EmitPriority = Emit; - - // Predicates - Predicates that must be true for this to match. - list Predicates = []; - - // If the instruction specified in Result has defined an AsmMatchConverter - // then setting this to 1 will cause the alias to use the AsmMatchConverter - // function when converting the OperandVector into an MCInst instead of the - // function that is generated by the dag Result. - // Setting this to 0 will cause the alias to ignore the Result instruction's - // defined AsmMatchConverter and instead use the function generated by the - // dag Result. - bit UseInstAsmMatchConverter = true; - - // Assembler variant name to use for this alias. If not specified then - // assembler variants will be determined based on AsmString - string AsmVariantName = VariantName; -} - -//===----------------------------------------------------------------------===// -// AsmWriter - This class can be implemented by targets that need to customize -// the format of the .s file writer. -// -// Subtargets can have multiple different asmwriters (e.g. AT&T vs Intel syntax -// on X86 for example). -// -class AsmWriter { - // AsmWriterClassName - This specifies the suffix to use for the asmwriter - // class. Generated AsmWriter classes are always prefixed with the target - // name. - string AsmWriterClassName = "InstPrinter"; - - // PassSubtarget - Determines whether MCSubtargetInfo should be passed to - // the various print methods. - // FIXME: Remove after all ports are updated. - int PassSubtarget = 0; - - // Variant - AsmWriters can be of multiple different variants. Variants are - // used to support targets that need to emit assembly code in ways that are - // mostly the same for different targets, but have minor differences in - // syntax. If the asmstring contains {|} characters in them, this integer - // will specify which alternative to use. For example "{x|y|z}" with Variant - // == 1, will expand to "y". - int Variant = 0; -} -def DefaultAsmWriter : AsmWriter; - - -//===----------------------------------------------------------------------===// -// Target - This class contains the "global" target information -// -class Target { - // InstructionSet - Instruction set description for this target. - InstrInfo InstructionSet; - - // AssemblyParsers - The AsmParser instances available for this target. - list AssemblyParsers = [DefaultAsmParser]; - - /// AssemblyParserVariants - The AsmParserVariant instances available for - /// this target. - list AssemblyParserVariants = [DefaultAsmParserVariant]; - - // AssemblyWriters - The AsmWriter instances available for this target. - list AssemblyWriters = [DefaultAsmWriter]; - - // AllowRegisterRenaming - Controls whether this target allows - // post-register-allocation renaming of registers. This is done by - // setting hasExtraDefRegAllocReq and hasExtraSrcRegAllocReq to 1 - // for all opcodes if this flag is set to 0. - int AllowRegisterRenaming = 0; -} - -//===----------------------------------------------------------------------===// -// SubtargetFeature - A characteristic of the chip set. -// -class SubtargetFeature i = []> { - // Name - Feature name. Used by command line (-mattr=) to determine the - // appropriate target chip. - // - string Name = n; - - // Attribute - Attribute to be set by feature. - // - string Attribute = a; - - // Value - Value the attribute to be set to by feature. - // - string Value = v; - - // Desc - Feature description. Used by command line (-mattr=) to display help - // information. - // - string Desc = d; - - // Implies - Features that this feature implies are present. If one of those - // features isn't set, then this one shouldn't be set either. - // - list Implies = i; -} - -/// Specifies a Subtarget feature that this instruction is deprecated on. -class Deprecated { - SubtargetFeature DeprecatedFeatureMask = dep; -} - -/// A custom predicate used to determine if an instruction is -/// deprecated or not. -class ComplexDeprecationPredicate { - string ComplexDeprecationPredicate = dep; -} - -//===----------------------------------------------------------------------===// -// Processor chip sets - These values represent each of the chip sets supported -// by the scheduler. Each Processor definition requires corresponding -// instruction itineraries. -// -class Processor f, - list tunef = []> { - // Name - Chip set name. Used by command line (-mcpu=) to determine the - // appropriate target chip. - // - string Name = n; - - // SchedModel - The machine model for scheduling and instruction cost. - // - SchedMachineModel SchedModel = NoSchedModel; - - // ProcItin - The scheduling information for the target processor. - // - ProcessorItineraries ProcItin = pi; - - // Features - list of - list Features = f; - - // TuneFeatures - list of features for tuning for this CPU. If the target - // supports -mtune, this should contain the list of features used to make - // microarchitectural optimization decisions for a given processor. While - // Features should contain the architectural features for the processor. - list TuneFeatures = tunef; -} - -// ProcessorModel allows subtargets to specify the more general -// SchedMachineModel instead if a ProcessorItinerary. Subtargets will -// gradually move to this newer form. -// -// Although this class always passes NoItineraries to the Processor -// class, the SchedMachineModel may still define valid Itineraries. -class ProcessorModel f, - list tunef = []> - : Processor { - let SchedModel = m; -} - -//===----------------------------------------------------------------------===// -// InstrMapping - This class is used to create mapping tables to relate -// instructions with each other based on the values specified in RowFields, -// ColFields, KeyCol and ValueCols. -// -class InstrMapping { - // FilterClass - Used to limit search space only to the instructions that - // define the relationship modeled by this InstrMapping record. - string FilterClass; - - // RowFields - List of fields/attributes that should be same for all the - // instructions in a row of the relation table. Think of this as a set of - // properties shared by all the instructions related by this relationship - // model and is used to categorize instructions into subgroups. For instance, - // if we want to define a relation that maps 'Add' instruction to its - // predicated forms, we can define RowFields like this: - // - // let RowFields = BaseOp - // All add instruction predicated/non-predicated will have to set their BaseOp - // to the same value. - // - // def Add: { let BaseOp = 'ADD'; let predSense = 'nopred' } - // def Add_predtrue: { let BaseOp = 'ADD'; let predSense = 'true' } - // def Add_predfalse: { let BaseOp = 'ADD'; let predSense = 'false' } - list RowFields = []; - - // List of fields/attributes that are same for all the instructions - // in a column of the relation table. - // Ex: let ColFields = 'predSense' -- It means that the columns are arranged - // based on the 'predSense' values. All the instruction in a specific - // column have the same value and it is fixed for the column according - // to the values set in 'ValueCols'. - list ColFields = []; - - // Values for the fields/attributes listed in 'ColFields'. - // Ex: let KeyCol = 'nopred' -- It means that the key instruction (instruction - // that models this relation) should be non-predicated. - // In the example above, 'Add' is the key instruction. - list KeyCol = []; - - // List of values for the fields/attributes listed in 'ColFields', one for - // each column in the relation table. - // - // Ex: let ValueCols = [['true'],['false']] -- It adds two columns in the - // table. First column requires all the instructions to have predSense - // set to 'true' and second column requires it to be 'false'. - list > ValueCols = []; -} - -//===----------------------------------------------------------------------===// -// Pull in the common support for calling conventions. -// -include "llvm/Target/TargetCallingConv.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for DAG isel generation. -// -include "llvm/Target/TargetSelectionDAG.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for Global ISel register bank info generation. -// -include "llvm/Target/GlobalISel/RegisterBank.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for DAG isel generation. -// -include "llvm/Target/GlobalISel/Target.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for the Global ISel DAG-based selector generation. -// -include "llvm/Target/GlobalISel/SelectionDAGCompat.td" - -//===----------------------------------------------------------------------===// -// Pull in the common support for Pfm Counters generation. -// -include "llvm/Target/TargetPfmCounters.td" diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td b/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td deleted file mode 100644 index a719581e0a..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td +++ /dev/null @@ -1,221 +0,0 @@ -//===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces with which targets -// describe their calling conventions. -// -//===----------------------------------------------------------------------===// - -class CCAction; -class CallingConv; - -/// CCCustom - Calls a custom arg handling function. -class CCCustom : CCAction { - string FuncName = fn; -} - -/// CCPredicateAction - Instances of this class check some predicate, then -/// delegate to another action if the predicate is true. -class CCPredicateAction : CCAction { - CCAction SubAction = A; -} - -/// CCIfType - If the current argument is one of the specified types, apply -/// Action A. -class CCIfType vts, CCAction A> : CCPredicateAction { - list VTs = vts; -} - -/// CCIf - If the predicate matches, apply A. -class CCIf : CCPredicateAction { - string Predicate = predicate; -} - -/// CCIfByVal - If the current argument has ByVal parameter attribute, apply -/// Action A. -class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { -} - -/// CCIfPreallocated - If the current argument has Preallocated parameter attribute, -/// apply Action A. -class CCIfPreallocated : CCIf<"ArgFlags.isPreallocated()", A> { -} - -/// CCIfSwiftSelf - If the current argument has swiftself parameter attribute, -/// apply Action A. -class CCIfSwiftSelf : CCIf<"ArgFlags.isSwiftSelf()", A> { -} - -/// CCIfSwiftAsync - If the current argument has swiftasync parameter attribute, -/// apply Action A. -class CCIfSwiftAsync : CCIf<"ArgFlags.isSwiftAsync()", A> { -} - -/// CCIfSwiftError - If the current argument has swifterror parameter attribute, -/// apply Action A. -class CCIfSwiftError : CCIf<"ArgFlags.isSwiftError()", A> { -} - -/// CCIfCFGuardTarget - If the current argument has cfguardtarget parameter -/// attribute, apply Action A. -class CCIfCFGuardTarget : CCIf<"ArgFlags.isCFGuardTarget()", A> { -} - -/// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs -/// parameter attribute, apply Action A. -class CCIfConsecutiveRegs : CCIf<"ArgFlags.isInConsecutiveRegs()", A> { -} - -/// CCIfCC - Match if the current calling convention is 'CC'. -class CCIfCC - : CCIf {} - -/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply -/// the specified action. -class CCIfInReg : CCIf<"ArgFlags.isInReg()", A> {} - -/// CCIfNest - If this argument is marked with the 'nest' attribute, apply -/// the specified action. -class CCIfNest : CCIf<"ArgFlags.isNest()", A> {} - -/// CCIfSplit - If this argument is marked with the 'split' attribute, apply -/// the specified action. -class CCIfSplit : CCIf<"ArgFlags.isSplit()", A> {} - -/// CCIfSRet - If this argument is marked with the 'sret' attribute, apply -/// the specified action. -class CCIfSRet : CCIf<"ArgFlags.isSRet()", A> {} - -/// CCIfVarArg - If the current function is vararg - apply the action -class CCIfVarArg : CCIf<"State.isVarArg()", A> {} - -/// CCIfNotVarArg - If the current function is not vararg - apply the action -class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} - -/// CCIfPtrAddrSpace - If the top-level parent of the current argument has -/// pointer type in the specified address-space. -class CCIfPtrAddrSpace - : CCIf<"(ArgFlags.isPointer() && ArgFlags.getPointerAddrSpace() == " # AS # ")", A> {} - -/// CCIfPtr - If the top-level parent of the current argument had -/// pointer type in some address-space. -class CCIfPtr : CCIf<"ArgFlags.isPointer()", A> {} - -/// CCAssignToReg - This action matches if there is a register in the specified -/// list that is still available. If so, it assigns the value to the first -/// available register and succeeds. -class CCAssignToReg regList> : CCAction { - list RegList = regList; -} - -/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers -/// which became shadowed, when some register is used. -class CCAssignToRegWithShadow regList, - list shadowList> : CCAction { - list RegList = regList; - list ShadowRegList = shadowList; -} - -/// CCAssignToStack - This action always matches: it assigns the value to a -/// stack slot of the specified size and alignment on the stack. If size is -/// zero then the ABI size is used; if align is zero then the ABI alignment -/// is used - these may depend on the target or subtarget. -class CCAssignToStack : CCAction { - int Size = size; - int Align = align; -} - -/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a list of -/// registers to be shadowed. Note that, unlike CCAssignToRegWithShadow, this -/// shadows ALL of the registers in shadowList. -class CCAssignToStackWithShadow shadowList> : CCAction { - int Size = size; - int Align = align; - list ShadowRegList = shadowList; -} - -/// CCPassByVal - This action always matches: it assigns the value to a stack -/// slot to implement ByVal aggregate parameter passing. Size and alignment -/// specify the minimum size and alignment for the stack slot. -class CCPassByVal : CCAction { - int Size = size; - int Align = align; -} - -/// CCPromoteToType - If applied, this promotes the specified current value to -/// the specified type. -class CCPromoteToType : CCAction { - ValueType DestTy = destTy; -} - -/// CCPromoteToUpperBitsInType - If applied, this promotes the specified current -/// value to the specified type and shifts the value into the upper bits. -class CCPromoteToUpperBitsInType : CCAction { - ValueType DestTy = destTy; -} - -/// CCBitConvertToType - If applied, this bitconverts the specified current -/// value to the specified type. -class CCBitConvertToType : CCAction { - ValueType DestTy = destTy; -} - -/// CCTruncToType - If applied, this truncates the specified current value to -/// the specified type. -class CCTruncToType : CCAction { - ValueType DestTy = destTy; -} - -/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer -/// as normal argument. -class CCPassIndirect : CCAction { - ValueType DestTy = destTy; -} - -/// CCDelegateTo - This action invokes the specified sub-calling-convention. It -/// is successful if the specified CC matches. -class CCDelegateTo : CCAction { - CallingConv CC = cc; -} - -/// CallingConv - An instance of this is used to define each calling convention -/// that the target supports. -class CallingConv actions> { - list Actions = actions; - - /// If true, this calling convention will be emitted as externally visible in - /// the llvm namespaces instead of as a static function. - bit Entry = false; - - bit Custom = false; -} - -/// CustomCallingConv - An instance of this is used to declare calling -/// conventions that are implemented using a custom function of the same name. -class CustomCallingConv : CallingConv<[]> { - let Custom = true; -} - -/// CalleeSavedRegs - A list of callee saved registers for a given calling -/// convention. The order of registers is used by PrologEpilogInsertion when -/// allocation stack slots for saved registers. -/// -/// For each CalleeSavedRegs def, TableGen will emit a FOO_SaveList array for -/// returning from getCalleeSavedRegs(), and a FOO_RegMask bit mask suitable for -/// returning from getCallPreservedMask(). -class CalleeSavedRegs { - dag SaveList = saves; - - // Registers that are also preserved across function calls, but should not be - // included in the generated FOO_SaveList array. These registers will be - // included in the FOO_RegMask bit mask. This can be used for registers that - // are saved automatically, like the SPARC register windows. - dag OtherPreserved; -} diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td b/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td deleted file mode 100644 index 9f2cde9d92..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td +++ /dev/null @@ -1,377 +0,0 @@ -//===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines class MCInstPredicate and its subclasses. -// -// MCInstPredicate definitions are used by target scheduling models to describe -// constraints on instructions. -// -// Here is an example of an MCInstPredicate definition in TableGen: -// -// def MCInstPredicateExample : CheckAll<[ -// CheckOpcode<[BLR]>, -// CheckIsRegOperand<0>, -// CheckNot>]>; -// -// The syntax for MCInstPredicate is declarative, and predicate definitions can -// be composed together in order to generate more complex constraints. -// -// The `CheckAll` from the example defines a composition of three different -// predicates. Definition `MCInstPredicateExample` identifies instructions -// whose opcode is BLR, and whose first operand is a register different from -// register `LR`. -// -// Every MCInstPredicate class has a well-known semantic in tablegen. For -// example, `CheckOpcode` is a special type of predicate used to describe a -// constraint on the value of an instruction opcode. -// -// MCInstPredicate definitions are typically used by scheduling models to -// construct MCSchedPredicate definitions (see the definition of class -// MCSchedPredicate in llvm/Target/TargetSchedule.td). -// In particular, an MCSchedPredicate can be used instead of a SchedPredicate -// when defining the set of SchedReadVariant and SchedWriteVariant of a -// processor scheduling model. -// -// The `MCInstPredicateExample` definition above is equivalent (and therefore -// could replace) the following definition from a previous ExynosM3 model (see -// AArch64SchedExynosM3.td): -// -// def M3BranchLinkFastPred : SchedPredicate<[{ -// MI->getOpcode() == AArch64::BLR && -// MI->getOperand(0).isReg() && -// MI->getOperand(0).getReg() != AArch64::LR}]>; -// -// The main advantage of using MCInstPredicate instead of SchedPredicate is -// portability: users don't need to specify predicates in C++. As a consequence -// of this, MCInstPredicate definitions are not bound to a particular -// representation (i.e. MachineInstr vs MCInst). -// -// Tablegen backends know how to expand MCInstPredicate definitions into actual -// C++ code that works on MachineInstr (and/or MCInst). -// -// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h) -// know how to expand a predicate. For each MCInstPredicate class, there must be -// an "expand" method available in the PredicateExpander interface. -// -// For example, a `CheckOpcode` predicate is expanded using method -// `PredicateExpander::expandCheckOpcode()`. -// -// New MCInstPredicate classes must be added to this file. For each new class -// XYZ, an "expandXYZ" method must be added to the PredicateExpander. -// -//===----------------------------------------------------------------------===// - -// Forward declarations. -class Instruction; -class SchedMachineModel; - -// A generic machine instruction predicate. -class MCInstPredicate; - -class MCTrue : MCInstPredicate; // A predicate that always evaluates to True. -class MCFalse : MCInstPredicate; // A predicate that always evaluates to False. -def TruePred : MCTrue; -def FalsePred : MCFalse; - -// A predicate used to negate the outcome of another predicate. -// It allows to easily express "set difference" operations. For example, it -// makes it easy to describe a check that tests if an opcode is not part of a -// set of opcodes. -class CheckNot : MCInstPredicate { - MCInstPredicate Pred = P; -} - -// This class is used as a building block to define predicates on instruction -// operands. It is used to reference a specific machine operand. -class MCOperandPredicate : MCInstPredicate { - int OpIndex = Index; -} - -// Return true if machine operand at position `Index` is a register operand. -class CheckIsRegOperand : MCOperandPredicate; - -// Return true if machine operand at position `Index` is an immediate operand. -class CheckIsImmOperand : MCOperandPredicate; - -// Check if machine operands at index `First` and index `Second` both reference -// the same register. -class CheckSameRegOperand : MCInstPredicate { - int FirstIndex = First; - int SecondIndex = Second; -} - -// Base class for checks on register/immediate operands. -// It allows users to define checks like: -// MyFunction(MI->getOperand(Index).getImm()) == Val; -// -// In the example above, `MyFunction` is a function that takes as input an -// immediate operand value, and returns another value. Field `FunctionMapper` is -// the name of the function to call on the operand value. -class CheckOperandBase : MCOperandPredicate { - string FunctionMapper = Fn; -} - -// Check that the machine register operand at position `Index` references -// register R. This predicate assumes that we already checked that the machine -// operand at position `Index` is a register operand. -class CheckRegOperand : CheckOperandBase { - Register Reg = R; -} - -// Check if register operand at index `Index` is the invalid register. -class CheckInvalidRegOperand : CheckOperandBase; - -// Return true if machine operand at position `Index` is a valid -// register operand. -class CheckValidRegOperand : - CheckNot>; - -// Check that the operand at position `Index` is immediate `Imm`. -// If field `FunctionMapper` is a non-empty string, then function -// `FunctionMapper` is applied to the operand value, and the return value is then -// compared against `Imm`. -class CheckImmOperand : CheckOperandBase { - int ImmVal = Imm; -} - -// Similar to CheckImmOperand, however the immediate is not a literal number. -// This is useful when we want to compare the value of an operand against an -// enum value, and we know the actual integer value of that enum. -class CheckImmOperand_s : CheckOperandBase { - string ImmVal = Value; -} - -// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. -// Otherwise, it expands to a CheckNot>. -class CheckRegOperandSimple : CheckOperandBase; - -// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. -// Otherwise, it simply evaluates to TruePred. -class CheckImmOperandSimple : CheckOperandBase; - -// Check that the operand at position `Index` is immediate value zero. -class CheckZeroOperand : CheckImmOperand; - -// Check that the instruction has exactly `Num` operands. -class CheckNumOperands : MCInstPredicate { - int NumOps = Num; -} - -// Check that the instruction opcode is one of the opcodes in set `Opcodes`. -// This is a simple set membership query. The easier way to check if an opcode -// is not a member of the set is by using a `CheckNot>` -// sequence. -class CheckOpcode Opcodes> : MCInstPredicate { - list ValidOpcodes = Opcodes; -} - -// Check that the instruction opcode is a pseudo opcode member of the set -// `Opcodes`. This check is always expanded to "false" if we are generating -// code for MCInst. -class CheckPseudo Opcodes> : CheckOpcode; - -// A non-portable predicate. Only to use as a last resort when a block of code -// cannot possibly be converted in a declarative way using other MCInstPredicate -// classes. This check is always expanded to "false" when generating code for -// MCInst. -class CheckNonPortable : MCInstPredicate { - string CodeBlock = Code; -} - -// A sequence of predicates. It is used as the base class for CheckAll, and -// CheckAny. It allows to describe compositions of predicates. -class CheckPredicateSequence Preds> : MCInstPredicate { - list Predicates = Preds; -} - -// Check that all of the predicates in `Preds` evaluate to true. -class CheckAll Sequence> - : CheckPredicateSequence; - -// Check that at least one of the predicates in `Preds` evaluates to true. -class CheckAny Sequence> - : CheckPredicateSequence; - - -// Used to expand the body of a function predicate. See the definition of -// TIIPredicate below. -class MCStatement; - -// Expands to a return statement. The return expression is a boolean expression -// described by a MCInstPredicate. -class MCReturnStatement : MCStatement { - MCInstPredicate Pred = predicate; -} - -// Used to automatically construct cases of a switch statement where the switch -// variable is an instruction opcode. There is a 'case' for every opcode in the -// `opcodes` list, and each case is associated with MCStatement `caseStmt`. -class MCOpcodeSwitchCase opcodes, MCStatement caseStmt> { - list Opcodes = opcodes; - MCStatement CaseStmt = caseStmt; -} - -// Expands to a switch statement. The switch variable is an instruction opcode. -// The auto-generated switch is populated by a number of cases based on the -// `cases` list in input. A default case is automatically generated, and it -// evaluates to `default`. -class MCOpcodeSwitchStatement cases, - MCStatement default> : MCStatement { - list Cases = cases; - MCStatement DefaultCase = default; -} - -// Base class for function predicates. -class FunctionPredicateBase { - string FunctionName = name; - MCStatement Body = body; -} - -// Check that a call to method `Name` in class "XXXInstrInfo" (where XXX is -// the name of a target) returns true. -// -// TIIPredicate definitions are used to model calls to the target-specific -// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter -// tablegen backend, which will use it to automatically generate a definition in -// the target specific `InstrInfo` class. -// -// There cannot be multiple TIIPredicate definitions with the same name for the -// same target. -class TIIPredicate - : FunctionPredicateBase, MCInstPredicate; - -// A function predicate that takes as input a machine instruction, and returns -// a boolean value. -// -// This predicate is expanded into a function call by the PredicateExpander. -// In particular, the PredicateExpander would either expand this predicate into -// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether -// it is lowering predicates for MCInst or MachineInstr. -// -// In this context, `MCInstFn` and `MachineInstrFn` are both function names. -class CheckFunctionPredicate : MCInstPredicate { - string MCInstFnName = MCInstFn; - string MachineInstrFnName = MachineInstrFn; -} - -// Similar to CheckFunctionPredicate. However it assumes that MachineInstrFn is -// a method in TargetInstrInfo, and MCInstrFn takes an extra pointer to -// MCInstrInfo. -// -// It Expands to: -// - TIIPointer->MachineInstrFn(MI) -// - MCInstrFn(MI, MCII); -class CheckFunctionPredicateWithTII : MCInstPredicate { - string MCInstFnName = MCInstFn; - string TIIPtrName = TIIPointer; - string MachineInstrFnName = MachineInstrFn; -} - -// Used to classify machine instructions based on a machine instruction -// predicate. -// -// Let IC be an InstructionEquivalenceClass definition, and MI a machine -// instruction. We say that MI belongs to the equivalence class described by IC -// if and only if the following two conditions are met: -// a) MI's opcode is in the `opcodes` set, and -// b) `Predicate` evaluates to true when applied to MI. -// -// Instances of this class can be used by processor scheduling models to -// describe instructions that have a property in common. For example, -// InstructionEquivalenceClass definitions can be used to identify the set of -// dependency breaking instructions for a processor model. -// -// An (optional) list of operand indices can be used to further describe -// properties that apply to instruction operands. For example, it can be used to -// identify register uses of a dependency breaking instructions that are not in -// a RAW dependency. -class InstructionEquivalenceClass opcodes, - MCInstPredicate pred, - list operands = []> { - list Opcodes = opcodes; - MCInstPredicate Predicate = pred; - list OperandIndices = operands; -} - -// Used by processor models to describe dependency breaking instructions. -// -// This is mainly an alias for InstructionEquivalenceClass. Input operand -// `BrokenDeps` identifies the set of "broken dependencies". There is one bit -// per each implicit and explicit input operand. An empty set of broken -// dependencies means: "explicit input register operands are independent." -class DepBreakingClass opcodes, MCInstPredicate pred, - list BrokenDeps = []> - : InstructionEquivalenceClass; - -// A function descriptor used to describe the signature of a predicate methods -// which will be expanded by the STIPredicateExpander into a tablegen'd -// XXXGenSubtargetInfo class member definition (here, XXX is a target name). -// -// It describes the signature of a TargetSubtarget hook, as well as a few extra -// properties. Examples of extra properties are: -// - The default return value for the auto-generate function hook. -// - A list of subtarget hooks (Delegates) that are called from this function. -// -class STIPredicateDecl delegates = []> { - string Name = name; - - MCInstPredicate DefaultReturnValue = default; - - // True if this method is declared as virtual in class TargetSubtargetInfo. - bit OverridesBaseClassMember = overrides; - - // True if we need an equivalent predicate function in the MC layer. - bit ExpandForMC = expandForMC; - - // True if the autogenerated method has a extra in/out APInt param used as a - // mask of operands. - bit UpdatesOpcodeMask = updatesOpcodeMask; - - // A list of STIPredicates used by this definition to delegate part of the - // computation. For example, STIPredicateFunction `isDependencyBreaking()` - // delegates to `isZeroIdiom()` part of its computation. - list Delegates = delegates; -} - -// A predicate function definition member of class `XXXGenSubtargetInfo`. -// -// If `Declaration.ExpandForMC` is true, then SubtargetEmitter -// will also expand another definition of this method that accepts a MCInst. -class STIPredicate classes> { - STIPredicateDecl Declaration = declaration; - list Classes = classes; - SchedMachineModel SchedModel = ?; -} - -// Convenience classes and definitions used by processor scheduling models to -// describe dependency breaking instructions and move elimination candidates. -let UpdatesOpcodeMask = true in { - -def IsZeroIdiomDecl : STIPredicateDecl<"isZeroIdiom">; - -let Delegates = [IsZeroIdiomDecl] in -def IsDepBreakingDecl : STIPredicateDecl<"isDependencyBreaking">; - -} // UpdatesOpcodeMask - -def IsOptimizableRegisterMoveDecl - : STIPredicateDecl<"isOptimizableRegisterMove">; - -class IsZeroIdiomFunction classes> - : STIPredicate; - -class IsDepBreakingFunction classes> - : STIPredicate; - -class IsOptimizableRegisterMove classes> - : STIPredicate; diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetIntrinsicInfo.h b/suite/synctools/tablegen/include/llvm/Target/TargetIntrinsicInfo.h deleted file mode 100644 index dc59f11c8d..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetIntrinsicInfo.h +++ /dev/null @@ -1,68 +0,0 @@ -//===-- llvm/Target/TargetIntrinsicInfo.h - Instruction Info ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the target intrinsic instructions to the code generator. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H -#define LLVM_TARGET_TARGETINTRINSICINFO_H - -#include "llvm/ADT/StringRef.h" -#include - -namespace llvm { - -class Function; -class Module; -class Type; - -//--------------------------------------------------------------------------- -/// -/// TargetIntrinsicInfo - Interface to description of machine instruction set -/// -class TargetIntrinsicInfo { - TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete; - void operator=(const TargetIntrinsicInfo &) = delete; -public: - TargetIntrinsicInfo(); - virtual ~TargetIntrinsicInfo(); - - /// Return the name of a target intrinsic, e.g. "llvm.bfin.ssync". - /// The Tys and numTys parameters are for intrinsics with overloaded types - /// (e.g., those using iAny or fAny). For a declaration for an overloaded - /// intrinsic, Tys should point to an array of numTys pointers to Type, - /// and must provide exactly one type for each overloaded type in the - /// intrinsic. - virtual std::string getName(unsigned IID, Type **Tys = nullptr, - unsigned numTys = 0) const = 0; - - /// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown - /// names. - virtual unsigned lookupName(const char *Name, unsigned Len) const =0; - - unsigned lookupName(StringRef Name) const { - return lookupName(Name.data(), Name.size()); - } - - /// Return the target intrinsic ID of a function, or 0. - virtual unsigned getIntrinsicID(const Function *F) const; - - /// Returns true if the intrinsic can be overloaded. - virtual bool isOverloaded(unsigned IID) const = 0; - - /// Create or insert an LLVM Function declaration for an intrinsic, - /// and return it. The Tys and numTys are for intrinsics with overloaded - /// types. See above for more information. - virtual Function *getDeclaration(Module *M, unsigned ID, Type **Tys = nullptr, - unsigned numTys = 0) const = 0; -}; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td b/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td deleted file mode 100644 index a432d4e42b..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td +++ /dev/null @@ -1,162 +0,0 @@ -//===- TargetItinerary.td - Target Itinerary Description --*- tablegen -*-====// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent scheduling interfaces -// which should be implemented by each target that uses instruction -// itineraries for scheduling. Itineraries are detailed reservation -// tables for each instruction class. They are most appropriate for -// in-order machine with complicated scheduling or bundling constraints. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Processor functional unit - These values represent the function units -// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... -// These may be independent values for each chip set or may be shared across -// all chip sets of the target. Each functional unit is treated as a resource -// during scheduling and has an affect instruction order based on availability -// during a time interval. -// -class FuncUnit; - -//===----------------------------------------------------------------------===// -// Pipeline bypass / forwarding - These values specifies the symbolic names of -// pipeline bypasses which can be used to forward results of instructions -// that are forwarded to uses. -class Bypass; -def NoBypass : Bypass; - -class ReservationKind val> { - int Value = val; -} - -def Required : ReservationKind<0>; -def Reserved : ReservationKind<1>; - -//===----------------------------------------------------------------------===// -// Instruction stage - These values represent a non-pipelined step in -// the execution of an instruction. Cycles represents the number of -// discrete time slots needed to complete the stage. Units represent -// the choice of functional units that can be used to complete the -// stage. Eg. IntUnit1, IntUnit2. TimeInc indicates how many cycles -// should elapse from the start of this stage to the start of the next -// stage in the itinerary. For example: -// -// A stage is specified in one of two ways: -// -// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles -// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit -// - -class InstrStage units, - int timeinc = -1, - ReservationKind kind = Required> { - int Cycles = cycles; // length of stage in machine cycles - list Units = units; // choice of functional units - int TimeInc = timeinc; // cycles till start of next stage - int Kind = kind.Value; // kind of FU reservation -} - -//===----------------------------------------------------------------------===// -// Instruction itinerary - An itinerary represents a sequential series of steps -// required to complete an instruction. Itineraries are represented as lists of -// instruction stages. -// - -//===----------------------------------------------------------------------===// -// Instruction itinerary classes - These values represent 'named' instruction -// itinerary. Using named itineraries simplifies managing groups of -// instructions across chip sets. An instruction uses the same itinerary class -// across all chip sets. Thus a new chip set can be added without modifying -// instruction information. -// -class InstrItinClass; -def NoItinerary : InstrItinClass; - -//===----------------------------------------------------------------------===// -// Instruction itinerary data - These values provide a runtime map of an -// instruction itinerary class (name) to its itinerary data. -// -// NumMicroOps represents the number of micro-operations that each instruction -// in the class are decoded to. If the number is zero, then it means the -// instruction can decode into variable number of micro-ops and it must be -// determined dynamically. This directly relates to the itineraries -// global IssueWidth property, which constrains the number of microops -// that can issue per cycle. -// -// OperandCycles are optional "cycle counts". They specify the cycle after -// instruction issue the values which correspond to specific operand indices -// are defined or read. Bypasses are optional "pipeline forwarding paths", if -// a def by an instruction is available on a specific bypass and the use can -// read from the same bypass, then the operand use latency is reduced by one. -// -// InstrItinData, -// InstrStage<1, [A9_AGU]>], -// [3, 1], [A9_LdBypass]>, -// InstrItinData], -// [1, 1], [NoBypass, A9_LdBypass]>, -// -// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 -// (after issue) and the result of the load is available on cycle 3. The result -// is available via forwarding path A9_LdBypass. If it's used by the first -// source operand of instructions of IIC_iMVNr class, then the operand latency -// is reduced by 1. -class InstrItinData stages, - list operandcycles = [], - list bypasses = [], int uops = 1> { - InstrItinClass TheClass = Class; - int NumMicroOps = uops; - list Stages = stages; - list OperandCycles = operandcycles; - list Bypasses = bypasses; -} - -//===----------------------------------------------------------------------===// -// Processor itineraries - These values represent the set of all itinerary -// classes for a given chip set. -// -// Set property values to -1 to use the default. -// See InstrItineraryProps for comments and defaults. -class ProcessorItineraries fu, list bp, - list iid> { - list FU = fu; - list BP = bp; - list IID = iid; - // The packetizer automaton to use for this itinerary. By default all - // itineraries for a target are bundled up into the same automaton. This only - // works correctly when there are no conflicts in functional unit IDs between - // itineraries. For example, given two itineraries A<[SLOT_A]>, B<[SLOT_B]>, - // SLOT_A and SLOT_B will be assigned the same functional unit index, and - // the generated packetizer will confuse instructions referencing these slots. - // - // To avoid this, setting PacketizerNamespace to non-"" will cause this - // itinerary to be generated in a different automaton. The subtarget will need - // to declare a method "create##Namespace##DFAPacketizer()". - string PacketizerNamespace = ""; -} - -// NoItineraries - A marker that can be used by processors without schedule -// info. Subtargets using NoItineraries can bypass the scheduler's -// expensive HazardRecognizer because no reservation table is needed. -def NoItineraries : ProcessorItineraries<[], [], []>; - -//===----------------------------------------------------------------------===// -// Combo Function Unit data - This is a map of combo function unit names to -// the list of functional units that are included in the combination. -// -class ComboFuncData funclist> { - FuncUnit TheComboFunc = ComboFunc; - list FuncList = funclist; -} - -//===----------------------------------------------------------------------===// -// Combo Function Units - This is a list of all combo function unit data. -class ComboFuncUnits cfd> { - list CFD = cfd; -} - diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetLoweringObjectFile.h b/suite/synctools/tablegen/include/llvm/Target/TargetLoweringObjectFile.h deleted file mode 100644 index ff62907ff9..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetLoweringObjectFile.h +++ /dev/null @@ -1,294 +0,0 @@ -//===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements classes used to handle lowerings specific to common -// object file formats. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H -#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H - -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCRegister.h" -#include - -namespace llvm { - -class Constant; -class DataLayout; -class Function; -class GlobalObject; -class GlobalValue; -class MachineBasicBlock; -class MachineModuleInfo; -class Mangler; -class MCContext; -class MCExpr; -class MCSection; -class MCSymbol; -class MCSymbolRefExpr; -class MCStreamer; -class MCValue; -class Module; -class SectionKind; -class StringRef; -class TargetMachine; -class DSOLocalEquivalent; - -class TargetLoweringObjectFile : public MCObjectFileInfo { - /// Name-mangler for global names. - Mangler *Mang = nullptr; - -protected: - bool SupportIndirectSymViaGOTPCRel = false; - bool SupportGOTPCRelWithOffset = true; - bool SupportDebugThreadLocalLocation = true; - bool SupportDSOLocalEquivalentLowering = false; - - /// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values - /// for EH. - unsigned PersonalityEncoding = 0; - unsigned LSDAEncoding = 0; - unsigned TTypeEncoding = 0; - unsigned CallSiteEncoding = 0; - - /// This section contains the static constructor pointer list. - MCSection *StaticCtorSection = nullptr; - - /// This section contains the static destructor pointer list. - MCSection *StaticDtorSection = nullptr; - - const TargetMachine *TM = nullptr; - -public: - TargetLoweringObjectFile() = default; - TargetLoweringObjectFile(const TargetLoweringObjectFile &) = delete; - TargetLoweringObjectFile & - operator=(const TargetLoweringObjectFile &) = delete; - virtual ~TargetLoweringObjectFile(); - - Mangler &getMangler() const { return *Mang; } - - /// This method must be called before any actual lowering is done. This - /// specifies the current context for codegen, and gives the lowering - /// implementations a chance to set up their default sections. - virtual void Initialize(MCContext &ctx, const TargetMachine &TM); - - virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, - const MCSymbol *Sym) const; - - /// Emit the module-level metadata that the platform cares about. - virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {} - - /// Emit Call Graph Profile metadata. - void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const; - - /// Get the module-level metadata that the platform cares about. - virtual void getModuleMetadata(Module &M) {} - - /// Given a constant with the SectionKind, return a section that it should be - /// placed in. - virtual MCSection *getSectionForConstant(const DataLayout &DL, - SectionKind Kind, const Constant *C, - Align &Alignment) const; - - virtual MCSection * - getSectionForMachineBasicBlock(const Function &F, - const MachineBasicBlock &MBB, - const TargetMachine &TM) const; - - virtual MCSection * - getUniqueSectionForFunction(const Function &F, - const TargetMachine &TM) const; - - /// Classify the specified global variable into a set of target independent - /// categories embodied in SectionKind. - static SectionKind getKindForGlobal(const GlobalObject *GO, - const TargetMachine &TM); - - /// This method computes the appropriate section to emit the specified global - /// variable or function definition. This should not be passed external (or - /// available externally) globals. - MCSection *SectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const; - - /// This method computes the appropriate section to emit the specified global - /// variable or function definition. This should not be passed external (or - /// available externally) globals. - MCSection *SectionForGlobal(const GlobalObject *GO, - const TargetMachine &TM) const; - - virtual void getNameWithPrefix(SmallVectorImpl &OutName, - const GlobalValue *GV, - const TargetMachine &TM) const; - - virtual MCSection *getSectionForJumpTable(const Function &F, - const TargetMachine &TM) const; - virtual MCSection *getSectionForLSDA(const Function &, const MCSymbol &, - const TargetMachine &) const { - return LSDASection; - } - - virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, - const Function &F) const; - - /// Targets should implement this method to assign a section to globals with - /// an explicit section specified. The implementation of this method can - /// assume that GO->hasSection() is true. - virtual MCSection * - getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const = 0; - - /// Return an MCExpr to use for a reference to the specified global variable - /// from exception handling information. - virtual const MCExpr *getTTypeGlobalReference(const GlobalValue *GV, - unsigned Encoding, - const TargetMachine &TM, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const; - - /// Return the MCSymbol for a private symbol with global value name as its - /// base, with the specified suffix. - MCSymbol *getSymbolWithGlobalValueBase(const GlobalValue *GV, - StringRef Suffix, - const TargetMachine &TM) const; - - // The symbol that gets passed to .cfi_personality. - virtual MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, - const TargetMachine &TM, - MachineModuleInfo *MMI) const; - - unsigned getPersonalityEncoding() const { return PersonalityEncoding; } - unsigned getLSDAEncoding() const { return LSDAEncoding; } - unsigned getTTypeEncoding() const { return TTypeEncoding; } - unsigned getCallSiteEncoding() const; - - const MCExpr *getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, - MCStreamer &Streamer) const; - - virtual MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const { - return StaticCtorSection; - } - - virtual MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const { - return StaticDtorSection; - } - - /// Create a symbol reference to describe the given TLS variable when - /// emitting the address in debug info. - virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const; - - virtual const MCExpr *lowerRelativeReference(const GlobalValue *LHS, - const GlobalValue *RHS, - const TargetMachine &TM) const { - return nullptr; - } - - /// Target supports a native lowering of a dso_local_equivalent constant - /// without needing to replace it with equivalent IR. - bool supportDSOLocalEquivalentLowering() const { - return SupportDSOLocalEquivalentLowering; - } - - virtual const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv, - const TargetMachine &TM) const { - return nullptr; - } - - /// Target supports replacing a data "PC"-relative access to a symbol - /// through another symbol, by accessing the later via a GOT entry instead? - bool supportIndirectSymViaGOTPCRel() const { - return SupportIndirectSymViaGOTPCRel; - } - - /// Target GOT "PC"-relative relocation supports encoding an additional - /// binary expression with an offset? - bool supportGOTPCRelWithOffset() const { - return SupportGOTPCRelWithOffset; - } - - /// Target supports TLS offset relocation in debug section? - bool supportDebugThreadLocalLocation() const { - return SupportDebugThreadLocalLocation; - } - - /// Returns the register used as static base in RWPI variants. - virtual MCRegister getStaticBase() const { return MCRegister::NoRegister; } - - /// Get the target specific RWPI relocation. - virtual const MCExpr *getIndirectSymViaRWPI(const MCSymbol *Sym) const { - return nullptr; - } - - /// Get the target specific PC relative GOT entry relocation - virtual const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV, - const MCSymbol *Sym, - const MCValue &MV, - int64_t Offset, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const { - return nullptr; - } - - /// If supported, return the section to use for the llvm.commandline - /// metadata. Otherwise, return nullptr. - virtual MCSection *getSectionForCommandLines() const { - return nullptr; - } - - /// On targets that use separate function descriptor symbols, return a section - /// for the descriptor given its symbol. Use only with defined functions. - virtual MCSection * - getSectionForFunctionDescriptor(const Function *F, - const TargetMachine &TM) const { - return nullptr; - } - - /// On targets that support TOC entries, return a section for the entry given - /// the symbol it refers to. - /// TODO: Implement this interface for existing ELF targets. - virtual MCSection *getSectionForTOCEntry(const MCSymbol *S, - const TargetMachine &TM) const { - return nullptr; - } - - /// On targets that associate external references with a section, return such - /// a section for the given external global. - virtual MCSection * - getSectionForExternalReference(const GlobalObject *GO, - const TargetMachine &TM) const { - return nullptr; - } - - /// Targets that have a special convention for their symbols could use - /// this hook to return a specialized symbol. - virtual MCSymbol *getTargetSymbol(const GlobalValue *GV, - const TargetMachine &TM) const { - return nullptr; - } - - /// If supported, return the function entry point symbol. - /// Otherwise, returns nulltpr. - /// Func must be a function or an alias which has a function as base object. - virtual MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func, - const TargetMachine &TM) const { - return nullptr; - } - -protected: - virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, - SectionKind Kind, - const TargetMachine &TM) const = 0; -}; - -} // end namespace llvm - -#endif // LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetMachine.h b/suite/synctools/tablegen/include/llvm/Target/TargetMachine.h deleted file mode 100644 index 9048d84301..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetMachine.h +++ /dev/null @@ -1,513 +0,0 @@ -//===-- llvm/Target/TargetMachine.h - Target Information --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the TargetMachine and LLVMTargetMachine classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETMACHINE_H -#define LLVM_TARGET_TARGETMACHINE_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/PassManager.h" -#include "llvm/Pass.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/PGOOptions.h" -#include "llvm/Target/CGPassBuilderOption.h" -#include "llvm/Target/TargetOptions.h" -#include -#include - -namespace llvm { - -class AAManager; -template -class PassManager; -using ModulePassManager = PassManager; - -class Function; -class GlobalValue; -class MachineFunctionPassManager; -class MachineFunctionAnalysisManager; -class MachineModuleInfoWrapperPass; -class Mangler; -class MCAsmInfo; -class MCContext; -class MCInstrInfo; -class MCRegisterInfo; -class MCStreamer; -class MCSubtargetInfo; -class MCSymbol; -class raw_pwrite_stream; -class PassBuilder; -class PassManagerBuilder; -struct PerFunctionMIParsingState; -class SMDiagnostic; -class SMRange; -class Target; -class TargetIntrinsicInfo; -class TargetIRAnalysis; -class TargetTransformInfo; -class TargetLoweringObjectFile; -class TargetPassConfig; -class TargetSubtargetInfo; - -// The old pass manager infrastructure is hidden in a legacy namespace now. -namespace legacy { -class PassManagerBase; -} -using legacy::PassManagerBase; - -namespace yaml { -struct MachineFunctionInfo; -} - -//===----------------------------------------------------------------------===// -/// -/// Primary interface to the complete machine description for the target -/// machine. All target-specific information should be accessible through this -/// interface. -/// -class TargetMachine { -protected: // Can only create subclasses. - TargetMachine(const Target &T, StringRef DataLayoutString, - const Triple &TargetTriple, StringRef CPU, StringRef FS, - const TargetOptions &Options); - - /// The Target that this machine was created for. - const Target &TheTarget; - - /// DataLayout for the target: keep ABI type size and alignment. - /// - /// The DataLayout is created based on the string representation provided - /// during construction. It is kept here only to avoid reparsing the string - /// but should not really be used during compilation, because it has an - /// internal cache that is context specific. - const DataLayout DL; - - /// Triple string, CPU name, and target feature strings the TargetMachine - /// instance is created with. - Triple TargetTriple; - std::string TargetCPU; - std::string TargetFS; - - Reloc::Model RM = Reloc::Static; - CodeModel::Model CMModel = CodeModel::Small; - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; - - /// Contains target specific asm information. - std::unique_ptr AsmInfo; - std::unique_ptr MRI; - std::unique_ptr MII; - std::unique_ptr STI; - - unsigned RequireStructuredCFG : 1; - unsigned O0WantsFastISel : 1; - - // PGO related tunables. - Optional PGOOption = None; - -public: - const TargetOptions DefaultOptions; - mutable TargetOptions Options; - - TargetMachine(const TargetMachine &) = delete; - void operator=(const TargetMachine &) = delete; - virtual ~TargetMachine(); - - const Target &getTarget() const { return TheTarget; } - - const Triple &getTargetTriple() const { return TargetTriple; } - StringRef getTargetCPU() const { return TargetCPU; } - StringRef getTargetFeatureString() const { return TargetFS; } - void setTargetFeatureString(StringRef FS) { TargetFS = std::string(FS); } - - /// Virtual method implemented by subclasses that returns a reference to that - /// target's TargetSubtargetInfo-derived member variable. - virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { - return nullptr; - } - virtual TargetLoweringObjectFile *getObjFileLowering() const { - return nullptr; - } - - /// Allocate and return a default initialized instance of the YAML - /// representation for the MachineFunctionInfo. - virtual yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const { - return nullptr; - } - - /// Allocate and initialize an instance of the YAML representation of the - /// MachineFunctionInfo. - virtual yaml::MachineFunctionInfo * - convertFuncInfoToYAML(const MachineFunction &MF) const { - return nullptr; - } - - /// Parse out the target's MachineFunctionInfo from the YAML representation. - virtual bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, - PerFunctionMIParsingState &PFS, - SMDiagnostic &Error, - SMRange &SourceRange) const { - return false; - } - - /// This method returns a pointer to the specified type of - /// TargetSubtargetInfo. In debug builds, it verifies that the object being - /// returned is of the correct type. - template const STC &getSubtarget(const Function &F) const { - return *static_cast(getSubtargetImpl(F)); - } - - /// Create a DataLayout. - const DataLayout createDataLayout() const { return DL; } - - /// Test if a DataLayout if compatible with the CodeGen for this target. - /// - /// The LLVM Module owns a DataLayout that is used for the target independent - /// optimizations and code generation. This hook provides a target specific - /// check on the validity of this DataLayout. - bool isCompatibleDataLayout(const DataLayout &Candidate) const { - return DL == Candidate; - } - - /// Get the pointer size for this target. - /// - /// This is the only time the DataLayout in the TargetMachine is used. - unsigned getPointerSize(unsigned AS) const { - return DL.getPointerSize(AS); - } - - unsigned getPointerSizeInBits(unsigned AS) const { - return DL.getPointerSizeInBits(AS); - } - - unsigned getProgramPointerSize() const { - return DL.getPointerSize(DL.getProgramAddressSpace()); - } - - unsigned getAllocaPointerSize() const { - return DL.getPointerSize(DL.getAllocaAddrSpace()); - } - - /// Reset the target options based on the function's attributes. - // FIXME: Remove TargetOptions that affect per-function code generation - // from TargetMachine. - void resetTargetOptions(const Function &F) const; - - /// Return target specific asm information. - const MCAsmInfo *getMCAsmInfo() const { return AsmInfo.get(); } - - const MCRegisterInfo *getMCRegisterInfo() const { return MRI.get(); } - const MCInstrInfo *getMCInstrInfo() const { return MII.get(); } - const MCSubtargetInfo *getMCSubtargetInfo() const { return STI.get(); } - - /// If intrinsic information is available, return it. If not, return null. - virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { - return nullptr; - } - - bool requiresStructuredCFG() const { return RequireStructuredCFG; } - void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } - - /// Returns the code generation relocation model. The choices are static, PIC, - /// and dynamic-no-pic, and target default. - Reloc::Model getRelocationModel() const; - - /// Returns the code model. The choices are small, kernel, medium, large, and - /// target default. - CodeModel::Model getCodeModel() const; - - bool isPositionIndependent() const; - - bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const; - - /// Returns true if this target uses emulated TLS. - bool useEmulatedTLS() const; - - /// Returns the TLS model which should be used for the given global variable. - TLSModel::Model getTLSModel(const GlobalValue *GV) const; - - /// Returns the optimization level: None, Less, Default, or Aggressive. - CodeGenOpt::Level getOptLevel() const; - - /// Overrides the optimization level. - void setOptLevel(CodeGenOpt::Level Level); - - void setFastISel(bool Enable) { Options.EnableFastISel = Enable; } - bool getO0WantsFastISel() { return O0WantsFastISel; } - void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; } - void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; } - void setGlobalISelAbort(GlobalISelAbortMode Mode) { - Options.GlobalISelAbort = Mode; - } - void setMachineOutliner(bool Enable) { - Options.EnableMachineOutliner = Enable; - } - void setSupportsDefaultOutlining(bool Enable) { - Options.SupportsDefaultOutlining = Enable; - } - void setSupportsDebugEntryValues(bool Enable) { - Options.SupportsDebugEntryValues = Enable; - } - - bool getAIXExtendedAltivecABI() const { - return Options.EnableAIXExtendedAltivecABI; - } - - bool getUniqueSectionNames() const { return Options.UniqueSectionNames; } - - /// Return true if unique basic block section names must be generated. - bool getUniqueBasicBlockSectionNames() const { - return Options.UniqueBasicBlockSectionNames; - } - - /// Return true if data objects should be emitted into their own section, - /// corresponds to -fdata-sections. - bool getDataSections() const { - return Options.DataSections; - } - - /// Return true if functions should be emitted into their own section, - /// corresponding to -ffunction-sections. - bool getFunctionSections() const { - return Options.FunctionSections; - } - - /// Return true if visibility attribute should not be emitted in XCOFF, - /// corresponding to -mignore-xcoff-visibility. - bool getIgnoreXCOFFVisibility() const { - return Options.IgnoreXCOFFVisibility; - } - - /// Return true if XCOFF traceback table should be emitted, - /// corresponding to -xcoff-traceback-table. - bool getXCOFFTracebackTable() const { return Options.XCOFFTracebackTable; } - - /// If basic blocks should be emitted into their own section, - /// corresponding to -fbasic-block-sections. - llvm::BasicBlockSection getBBSectionsType() const { - return Options.BBSections; - } - - /// Get the list of functions and basic block ids that need unique sections. - const MemoryBuffer *getBBSectionsFuncListBuf() const { - return Options.BBSectionsFuncListBuf.get(); - } - - /// Returns true if a cast between SrcAS and DestAS is a noop. - virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { - return false; - } - - void setPGOOption(Optional PGOOpt) { PGOOption = PGOOpt; } - const Optional &getPGOOption() const { return PGOOption; } - - /// If the specified generic pointer could be assumed as a pointer to a - /// specific address space, return that address space. - /// - /// Under offloading programming, the offloading target may be passed with - /// values only prepared on the host side and could assume certain - /// properties. - virtual unsigned getAssumedAddrSpace(const Value *V) const { return -1; } - - /// If the specified predicate checks whether a generic pointer falls within - /// a specified address space, return that generic pointer and the address - /// space being queried. - /// - /// Such predicates could be specified in @llvm.assume intrinsics for the - /// optimizer to assume that the given generic pointer always falls within - /// the address space based on that predicate. - virtual std::pair - getPredicatedAddrSpace(const Value *V) const { - return std::make_pair(nullptr, -1); - } - - /// Get a \c TargetIRAnalysis appropriate for the target. - /// - /// This is used to construct the new pass manager's target IR analysis pass, - /// set up appropriately for this target machine. Even the old pass manager - /// uses this to answer queries about the IR. - TargetIRAnalysis getTargetIRAnalysis(); - - /// Return a TargetTransformInfo for a given function. - /// - /// The returned TargetTransformInfo is specialized to the subtarget - /// corresponding to \p F. - virtual TargetTransformInfo getTargetTransformInfo(const Function &F); - - /// Allow the target to modify the pass manager, e.g. by calling - /// PassManagerBuilder::addExtension. - virtual void adjustPassManager(PassManagerBuilder &) {} - - /// Allow the target to modify the pass pipeline with New Pass Manager - /// (similar to adjustPassManager for Legacy Pass manager). - virtual void registerPassBuilderCallbacks(PassBuilder &) {} - - /// Allow the target to register alias analyses with the AAManager for use - /// with the new pass manager. Only affects the "default" AAManager. - virtual void registerDefaultAliasAnalyses(AAManager &) {} - - /// Add passes to the specified pass manager to get the specified file - /// emitted. Typically this will involve several steps of code generation. - /// This method should return true if emission of this file type is not - /// supported, or false on success. - /// \p MMIWP is an optional parameter that, if set to non-nullptr, - /// will be used to set the MachineModuloInfo for this PM. - virtual bool - addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, - raw_pwrite_stream *, CodeGenFileType, - bool /*DisableVerify*/ = true, - MachineModuleInfoWrapperPass *MMIWP = nullptr) { - return true; - } - - /// Add passes to the specified pass manager to get machine code emitted with - /// the MCJIT. This method returns true if machine code is not supported. It - /// fills the MCContext Ctx pointer which can be used to build custom - /// MCStreamer. - /// - virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, - raw_pwrite_stream &, - bool /*DisableVerify*/ = true) { - return true; - } - - /// True if subtarget inserts the final scheduling pass on its own. - /// - /// Branch relaxation, which must happen after block placement, can - /// on some targets (e.g. SystemZ) expose additional post-RA - /// scheduling opportunities. - virtual bool targetSchedulesPostRAScheduling() const { return false; }; - - void getNameWithPrefix(SmallVectorImpl &Name, const GlobalValue *GV, - Mangler &Mang, bool MayAlwaysUsePrivate = false) const; - MCSymbol *getSymbol(const GlobalValue *GV) const; - - /// The integer bit size to use for SjLj based exception handling. - static constexpr unsigned DefaultSjLjDataSize = 32; - virtual unsigned getSjLjDataSize() const { return DefaultSjLjDataSize; } - - static std::pair parseBinutilsVersion(StringRef Version); -}; - -/// This class describes a target machine that is implemented with the LLVM -/// target-independent code generator. -/// -class LLVMTargetMachine : public TargetMachine { -protected: // Can only create subclasses. - LLVMTargetMachine(const Target &T, StringRef DataLayoutString, - const Triple &TT, StringRef CPU, StringRef FS, - const TargetOptions &Options, Reloc::Model RM, - CodeModel::Model CM, CodeGenOpt::Level OL); - - void initAsmInfo(); - -public: - /// Get a TargetTransformInfo implementation for the target. - /// - /// The TTI returned uses the common code generator to answer queries about - /// the IR. - TargetTransformInfo getTargetTransformInfo(const Function &F) override; - - /// Create a pass configuration object to be used by addPassToEmitX methods - /// for generating a pipeline of CodeGen passes. - virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); - - /// Add passes to the specified pass manager to get the specified file - /// emitted. Typically this will involve several steps of code generation. - /// \p MMIWP is an optional parameter that, if set to non-nullptr, - /// will be used to set the MachineModuloInfo for this PM. - bool - addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, - raw_pwrite_stream *DwoOut, CodeGenFileType FileType, - bool DisableVerify = true, - MachineModuleInfoWrapperPass *MMIWP = nullptr) override; - - virtual Error buildCodeGenPipeline(ModulePassManager &, - MachineFunctionPassManager &, - MachineFunctionAnalysisManager &, - raw_pwrite_stream &, raw_pwrite_stream *, - CodeGenFileType, CGPassBuilderOption, - PassInstrumentationCallbacks *) { - return make_error("buildCodeGenPipeline is not overridden", - inconvertibleErrorCode()); - } - - virtual std::pair getPassNameFromLegacyName(StringRef) { - llvm_unreachable( - "getPassNameFromLegacyName parseMIRPipeline is not overridden"); - } - - /// Add passes to the specified pass manager to get machine code emitted with - /// the MCJIT. This method returns true if machine code is not supported. It - /// fills the MCContext Ctx pointer which can be used to build custom - /// MCStreamer. - bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, - raw_pwrite_stream &Out, - bool DisableVerify = true) override; - - /// Returns true if the target is expected to pass all machine verifier - /// checks. This is a stopgap measure to fix targets one by one. We will - /// remove this at some point and always enable the verifier when - /// EXPENSIVE_CHECKS is enabled. - virtual bool isMachineVerifierClean() const { return true; } - - /// Adds an AsmPrinter pass to the pipeline that prints assembly or - /// machine code from the MI representation. - bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out, - raw_pwrite_stream *DwoOut, CodeGenFileType FileType, - MCContext &Context); - - Expected> - createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, MCContext &Ctx); - - /// True if the target uses physical regs (as nearly all targets do). False - /// for stack machines such as WebAssembly and other virtual-register - /// machines. If true, all vregs must be allocated before PEI. If false, then - /// callee-save register spilling and scavenging are not needed or used. If - /// false, implicitly defined registers will still be assumed to be physical - /// registers, except that variadic defs will be allocated vregs. - virtual bool usesPhysRegsForValues() const { return true; } - - /// True if the target wants to use interprocedural register allocation by - /// default. The -enable-ipra flag can be used to override this. - virtual bool useIPRA() const { - return false; - } - - /// The default variant to use in unqualified `asm` instructions. - /// If this returns 0, `asm "$(foo$|bar$)"` will evaluate to `asm "foo"`. - virtual int unqualifiedInlineAsmVariant() const { return 0; } -}; - -/// Helper method for getting the code model, returning Default if -/// CM does not have a value. The tiny and kernel models will produce -/// an error, so targets that support them or require more complex codemodel -/// selection logic should implement and call their own getEffectiveCodeModel. -inline CodeModel::Model getEffectiveCodeModel(Optional CM, - CodeModel::Model Default) { - if (CM) { - // By default, targets do not support the tiny and kernel models. - if (*CM == CodeModel::Tiny) - report_fatal_error("Target does not support the tiny CodeModel", false); - if (*CM == CodeModel::Kernel) - report_fatal_error("Target does not support the kernel CodeModel", false); - return *CM; - } - return Default; -} - -} // end namespace llvm - -#endif // LLVM_TARGET_TARGETMACHINE_H diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetOptions.h b/suite/synctools/tablegen/include/llvm/Target/TargetOptions.h deleted file mode 100644 index 86211abfbc..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetOptions.h +++ /dev/null @@ -1,433 +0,0 @@ -//===-- llvm/Target/TargetOptions.h - Target Options ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines command line option flags that are shared across various -// targets. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETOPTIONS_H -#define LLVM_TARGET_TARGETOPTIONS_H - -#include "llvm/ADT/FloatingPointMode.h" -#include "llvm/MC/MCTargetOptions.h" - -#include - -namespace llvm { - struct fltSemantics; - class MachineFunction; - class MemoryBuffer; - - namespace FloatABI { - enum ABIType { - Default, // Target-specific (either soft or hard depending on triple, etc). - Soft, // Soft float. - Hard // Hard float. - }; - } - - namespace FPOpFusion { - enum FPOpFusionMode { - Fast, // Enable fusion of FP ops wherever it's profitable. - Standard, // Only allow fusion of 'blessed' ops (currently just fmuladd). - Strict // Never fuse FP-ops. - }; - } - - namespace JumpTable { - enum JumpTableType { - Single, // Use a single table for all indirect jumptable calls. - Arity, // Use one table per number of function parameters. - Simplified, // Use one table per function type, with types projected - // into 4 types: pointer to non-function, struct, - // primitive, and function pointer. - Full // Use one table per unique function type - }; - } - - namespace ThreadModel { - enum Model { - POSIX, // POSIX Threads - Single // Single Threaded Environment - }; - } - - enum class BasicBlockSection { - All, // Use Basic Block Sections for all basic blocks. A section - // for every basic block can significantly bloat object file sizes. - List, // Get list of functions & BBs from a file. Selectively enables - // basic block sections for a subset of basic blocks which can be - // used to control object size bloats from creating sections. - Labels, // Do not use Basic Block Sections but label basic blocks. This - // is useful when associating profile counts from virtual addresses - // to basic blocks. - Preset, // Similar to list but the blocks are identified by passes which - // seek to use Basic Block Sections, e.g. MachineFunctionSplitter. - // This option cannot be set via the command line. - None // Do not use Basic Block Sections. - }; - - enum class EABI { - Unknown, - Default, // Default means not specified - EABI4, // Target-specific (either 4, 5 or gnu depending on triple). - EABI5, - GNU - }; - - /// Identify a debugger for "tuning" the debug info. - /// - /// The "debugger tuning" concept allows us to present a more intuitive - /// interface that unpacks into different sets of defaults for the various - /// individual feature-flag settings, that suit the preferences of the - /// various debuggers. However, it's worth remembering that debuggers are - /// not the only consumers of debug info, and some variations in DWARF might - /// better be treated as target/platform issues. Fundamentally, - /// o if the feature is useful (or not) to a particular debugger, regardless - /// of the target, that's a tuning decision; - /// o if the feature is useful (or not) on a particular platform, regardless - /// of the debugger, that's a target decision. - /// It's not impossible to see both factors in some specific case. - enum class DebuggerKind { - Default, ///< No specific tuning requested. - GDB, ///< Tune debug info for gdb. - LLDB, ///< Tune debug info for lldb. - SCE, ///< Tune debug info for SCE targets (e.g. PS4). - DBX ///< Tune debug info for dbx. - }; - - /// Enable abort calls when global instruction selection fails to lower/select - /// an instruction. - enum class GlobalISelAbortMode { - Disable, // Disable the abort. - Enable, // Enable the abort. - DisableWithDiag // Disable the abort but emit a diagnostic on failure. - }; - - /// Indicates when and how the Swift async frame pointer bit should be set. - enum class SwiftAsyncFramePointerMode { - /// Determine whether to set the bit statically or dynamically based - /// on the deployment target. - DeploymentBased, - /// Always set the bit. - Always, - /// Never set the bit. - Never, - }; - - class TargetOptions { - public: - TargetOptions() - : UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), - NoTrappingFPMath(true), NoSignedZerosFPMath(false), - ApproxFuncFPMath(false), EnableAIXExtendedAltivecABI(false), - HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), - GuaranteedTailCallOpt(false), StackSymbolOrdering(true), - EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), - DisableIntegratedAS(false), RelaxELFRelocations(false), - FunctionSections(false), DataSections(false), - IgnoreXCOFFVisibility(false), XCOFFTracebackTable(true), - UniqueSectionNames(true), UniqueBasicBlockSectionNames(false), - TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0), - EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false), - EmitStackSizeSection(false), EnableMachineOutliner(false), - EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false), - EmitAddrsig(false), EmitCallSiteInfo(false), - SupportsDebugEntryValues(false), EnableDebugEntryValues(false), - ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false), - XRayOmitFunctionIndex(false), DebugStrictDwarf(false), - Hotpatch(false), - FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {} - - /// DisableFramePointerElim - This returns true if frame pointer elimination - /// optimization should be disabled for the given machine function. - bool DisableFramePointerElim(const MachineFunction &MF) const; - - /// If greater than 0, override the default value of - /// MCAsmInfo::BinutilsVersion. - std::pair BinutilsVersion{0, 0}; - - /// UnsafeFPMath - This flag is enabled when the - /// -enable-unsafe-fp-math flag is specified on the command line. When - /// this flag is off (the default), the code generator is not allowed to - /// produce results that are "less precise" than IEEE allows. This includes - /// use of X86 instructions like FSIN and FCOS instead of libcalls. - unsigned UnsafeFPMath : 1; - - /// NoInfsFPMath - This flag is enabled when the - /// -enable-no-infs-fp-math flag is specified on the command line. When - /// this flag is off (the default), the code generator is not allowed to - /// assume the FP arithmetic arguments and results are never +-Infs. - unsigned NoInfsFPMath : 1; - - /// NoNaNsFPMath - This flag is enabled when the - /// -enable-no-nans-fp-math flag is specified on the command line. When - /// this flag is off (the default), the code generator is not allowed to - /// assume the FP arithmetic arguments and results are never NaNs. - unsigned NoNaNsFPMath : 1; - - /// NoTrappingFPMath - This flag is enabled when the - /// -enable-no-trapping-fp-math is specified on the command line. This - /// specifies that there are no trap handlers to handle exceptions. - unsigned NoTrappingFPMath : 1; - - /// NoSignedZerosFPMath - This flag is enabled when the - /// -enable-no-signed-zeros-fp-math is specified on the command line. This - /// specifies that optimizations are allowed to treat the sign of a zero - /// argument or result as insignificant. - unsigned NoSignedZerosFPMath : 1; - - /// ApproxFuncFPMath - This flag is enabled when the - /// -enable-approx-func-fp-math is specified on the command line. This - /// specifies that optimizations are allowed to substitute math functions - /// with approximate calculations - unsigned ApproxFuncFPMath : 1; - - /// EnableAIXExtendedAltivecABI - This flag returns true when -vec-extabi is - /// specified. The code generator is then able to use both volatile and - /// nonvolatile vector registers. When false, the code generator only uses - /// volatile vector registers which is the default setting on AIX. - unsigned EnableAIXExtendedAltivecABI : 1; - - /// HonorSignDependentRoundingFPMath - This returns true when the - /// -enable-sign-dependent-rounding-fp-math is specified. If this returns - /// false (the default), the code generator is allowed to assume that the - /// rounding behavior is the default (round-to-zero for all floating point - /// to integer conversions, and round-to-nearest for all other arithmetic - /// truncations). If this is enabled (set to true), the code generator must - /// assume that the rounding mode may dynamically change. - unsigned HonorSignDependentRoundingFPMathOption : 1; - bool HonorSignDependentRoundingFPMath() const; - - /// NoZerosInBSS - By default some codegens place zero-initialized data to - /// .bss section. This flag disables such behaviour (necessary, e.g. for - /// crt*.o compiling). - unsigned NoZerosInBSS : 1; - - /// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is - /// specified on the commandline. When the flag is on, participating targets - /// will perform tail call optimization on all calls which use the fastcc - /// calling convention and which satisfy certain target-independent - /// criteria (being at the end of a function, having the same return type - /// as their parent function, etc.), using an alternate ABI if necessary. - unsigned GuaranteedTailCallOpt : 1; - - /// StackSymbolOrdering - When true, this will allow CodeGen to order - /// the local stack symbols (for code size, code locality, or any other - /// heuristics). When false, the local symbols are left in whatever order - /// they were generated. Default is true. - unsigned StackSymbolOrdering : 1; - - /// EnableFastISel - This flag enables fast-path instruction selection - /// which trades away generated code quality in favor of reducing - /// compile time. - unsigned EnableFastISel : 1; - - /// EnableGlobalISel - This flag enables global instruction selection. - unsigned EnableGlobalISel : 1; - - /// EnableGlobalISelAbort - Control abort behaviour when global instruction - /// selection fails to lower/select an instruction. - GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable; - - /// Control when and how the Swift async frame pointer bit should - /// be set. - SwiftAsyncFramePointerMode SwiftAsyncFramePointer = - SwiftAsyncFramePointerMode::Always; - - /// UseInitArray - Use .init_array instead of .ctors for static - /// constructors. - unsigned UseInitArray : 1; - - /// Disable the integrated assembler. - unsigned DisableIntegratedAS : 1; - - /// Compress DWARF debug sections. - DebugCompressionType CompressDebugSections = DebugCompressionType::None; - - unsigned RelaxELFRelocations : 1; - - /// Emit functions into separate sections. - unsigned FunctionSections : 1; - - /// Emit data into separate sections. - unsigned DataSections : 1; - - /// Do not emit visibility attribute for xcoff. - unsigned IgnoreXCOFFVisibility : 1; - - /// Emit XCOFF traceback table. - unsigned XCOFFTracebackTable : 1; - - unsigned UniqueSectionNames : 1; - - /// Use unique names for basic block sections. - unsigned UniqueBasicBlockSectionNames : 1; - - /// Emit target-specific trap instruction for 'unreachable' IR instructions. - unsigned TrapUnreachable : 1; - - /// Do not emit a trap instruction for 'unreachable' IR instructions behind - /// noreturn calls, even if TrapUnreachable is true. - unsigned NoTrapAfterNoreturn : 1; - - /// Bit size of immediate TLS offsets (0 == use the default). - unsigned TLSSize : 8; - - /// EmulatedTLS - This flag enables emulated TLS model, using emutls - /// function in the runtime library.. - unsigned EmulatedTLS : 1; - - /// Whether -emulated-tls or -no-emulated-tls is set. - unsigned ExplicitEmulatedTLS : 1; - - /// This flag enables InterProcedural Register Allocation (IPRA). - unsigned EnableIPRA : 1; - - /// Emit section containing metadata on function stack sizes. - unsigned EmitStackSizeSection : 1; - - /// Enables the MachineOutliner pass. - unsigned EnableMachineOutliner : 1; - - /// Enables the MachineFunctionSplitter pass. - unsigned EnableMachineFunctionSplitter : 1; - - /// Set if the target supports default outlining behaviour. - unsigned SupportsDefaultOutlining : 1; - - /// Emit address-significance table. - unsigned EmitAddrsig : 1; - - /// Emit basic blocks into separate sections. - BasicBlockSection BBSections = BasicBlockSection::None; - - /// Memory Buffer that contains information on sampled basic blocks and used - /// to selectively generate basic block sections. - std::shared_ptr BBSectionsFuncListBuf; - - /// The flag enables call site info production. It is used only for debug - /// info, and it is restricted only to optimized code. This can be used for - /// something else, so that should be controlled in the frontend. - unsigned EmitCallSiteInfo : 1; - /// Set if the target supports the debug entry values by default. - unsigned SupportsDebugEntryValues : 1; - /// When set to true, the EnableDebugEntryValues option forces production - /// of debug entry values even if the target does not officially support - /// it. Useful for testing purposes only. This flag should never be checked - /// directly, always use \ref ShouldEmitDebugEntryValues instead. - unsigned EnableDebugEntryValues : 1; - /// NOTE: There are targets that still do not support the debug entry values - /// production. - bool ShouldEmitDebugEntryValues() const; - - // When set to true, use experimental new debug variable location tracking, - // which seeks to follow the values of variables rather than their location, - // post isel. - unsigned ValueTrackingVariableLocations : 1; - - /// Emit DWARF debug frame section. - unsigned ForceDwarfFrameSection : 1; - - /// Emit XRay Function Index section - unsigned XRayOmitFunctionIndex : 1; - - /// When set to true, don't use DWARF extensions in later DWARF versions. - /// By default, it is set to false. - unsigned DebugStrictDwarf : 1; - - /// Emit the hotpatch flag in CodeView debug. - unsigned Hotpatch : 1; - - /// Name of the stack usage file (i.e., .su file) if user passes - /// -fstack-usage. If empty, it can be implied that -fstack-usage is not - /// passed on the command line. - std::string StackUsageOutput; - - /// If greater than 0, override TargetLoweringBase::PrefLoopAlignment. - unsigned LoopAlignment = 0; - - /// FloatABIType - This setting is set by -float-abi=xxx option is specified - /// on the command line. This setting may either be Default, Soft, or Hard. - /// Default selects the target's default behavior. Soft selects the ABI for - /// software floating point, but does not indicate that FP hardware may not - /// be used. Such a combination is unfortunately popular (e.g. - /// arm-apple-darwin). Hard presumes that the normal FP ABI is used. - FloatABI::ABIType FloatABIType = FloatABI::Default; - - /// AllowFPOpFusion - This flag is set by the -fp-contract=xxx option. - /// This controls the creation of fused FP ops that store intermediate - /// results in higher precision than IEEE allows (E.g. FMAs). - /// - /// Fast mode - allows formation of fused FP ops whenever they're - /// profitable. - /// Standard mode - allow fusion only for 'blessed' FP ops. At present the - /// only blessed op is the fmuladd intrinsic. In the future more blessed ops - /// may be added. - /// Strict mode - allow fusion only if/when it can be proven that the excess - /// precision won't effect the result. - /// - /// Note: This option only controls formation of fused ops by the - /// optimizers. Fused operations that are explicitly specified (e.g. FMA - /// via the llvm.fma.* intrinsic) will always be honored, regardless of - /// the value of this option. - FPOpFusion::FPOpFusionMode AllowFPOpFusion = FPOpFusion::Standard; - - /// ThreadModel - This flag specifies the type of threading model to assume - /// for things like atomics - ThreadModel::Model ThreadModel = ThreadModel::POSIX; - - /// EABIVersion - This flag specifies the EABI version - EABI EABIVersion = EABI::Default; - - /// Which debugger to tune for. - DebuggerKind DebuggerTuning = DebuggerKind::Default; - - private: - /// Flushing mode to assume in default FP environment. - DenormalMode FPDenormalMode; - - /// Flushing mode to assume in default FP environment, for float/vector of - /// float. - DenormalMode FP32DenormalMode; - - public: - void setFPDenormalMode(DenormalMode Mode) { - FPDenormalMode = Mode; - } - - void setFP32DenormalMode(DenormalMode Mode) { - FP32DenormalMode = Mode; - } - - DenormalMode getRawFPDenormalMode() const { - return FPDenormalMode; - } - - DenormalMode getRawFP32DenormalMode() const { - return FP32DenormalMode; - } - - DenormalMode getDenormalMode(const fltSemantics &FPType) const; - - /// What exception model to use - ExceptionHandling ExceptionModel = ExceptionHandling::None; - - /// Machine level options. - MCTargetOptions MCOptions; - - /// Stores the filename/path of the final .o/.obj file, to be written in the - /// debug information. This is used for emitting the CodeView S_OBJNAME - /// record. - std::string ObjectFilenameForDebug; - }; - -} // End llvm namespace - -#endif diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetPfmCounters.td b/suite/synctools/tablegen/include/llvm/Target/TargetPfmCounters.td deleted file mode 100644 index b00f3e19c3..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetPfmCounters.td +++ /dev/null @@ -1,51 +0,0 @@ -//===- TargetPfmCounters.td - Target Pfm Counters -*- tablegen ----------*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces for performance counters. -// -//===----------------------------------------------------------------------===// - -// Definition of a hardware counters from libpfm identifiers. -class PfmCounter { - // The name of the counter that measures events. - // The name can be "some_counter + some_other_counter", in which case the - // measured value is the sum of events on these counters. - string Counter = counter; -} - -// Issue counters can be tied to a ProcResource -class PfmIssueCounter - : PfmCounter { - // The name of the ProcResource on which uops are issued. This is used by - // llvm-exegesis to compare measurements with values in the SchedModels. - // If the CPU has a sched model, this should correspond to the name of a - // ProcResource. - string ResourceName = resource_name; -} - -def NoPfmCounter : PfmCounter <""> {} - -// Set of PfmCounters for measuring sched model characteristics. -class ProcPfmCounters { - // Processors can define how to measure cycles by defining a CycleCounter. - PfmCounter CycleCounter = NoPfmCounter; - // Processors can define how to measure uops by defining a UopsCounter. - PfmCounter UopsCounter = NoPfmCounter; - // Processors can define how to measure issued uops by defining IssueCounters. - list IssueCounters = []; -} - -// A binding of a set of counters to a CPU. -class PfmCountersBinding { - string CpuName = cpu_name; - ProcPfmCounters Counters = counters; -} - -// Declares the default binding for unbound CPUs for the target. -class PfmCountersDefaultBinding - : PfmCountersBinding<"", counters> {} diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td b/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td deleted file mode 100644 index b312618fe3..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td +++ /dev/null @@ -1,574 +0,0 @@ -//===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent scheduling interfaces which should -// be implemented by each target which is using TableGen based scheduling. -// -// The SchedMachineModel is defined by subtargets for three categories of data: -// 1. Basic properties for coarse grained instruction cost model. -// 2. Scheduler Read/Write resources for simple per-opcode cost model. -// 3. Instruction itineraries for detailed reservation tables. -// -// (1) Basic properties are defined by the SchedMachineModel -// class. Target hooks allow subtargets to associate opcodes with -// those properties. -// -// (2) A per-operand machine model can be implemented in any -// combination of the following ways: -// -// A. Associate per-operand SchedReadWrite types with Instructions by -// modifying the Instruction definition to inherit from Sched. For -// each subtarget, define WriteRes and ReadAdvance to associate -// processor resources and latency with each SchedReadWrite type. -// -// B. In each instruction definition, name an ItineraryClass. For each -// subtarget, define ItinRW entries to map ItineraryClass to -// per-operand SchedReadWrite types. Unlike method A, these types may -// be subtarget specific and can be directly associated with resources -// by defining SchedWriteRes and SchedReadAdvance. -// -// C. In the subtarget, map SchedReadWrite types to specific -// opcodes. This overrides any SchedReadWrite types or -// ItineraryClasses defined by the Instruction. As in method B, the -// subtarget can directly associate resources with SchedReadWrite -// types by defining SchedWriteRes and SchedReadAdvance. -// -// D. In either the target or subtarget, define SchedWriteVariant or -// SchedReadVariant to map one SchedReadWrite type onto another -// sequence of SchedReadWrite types. This allows dynamic selection of -// an instruction's machine model via custom C++ code. It also allows -// a machine-independent SchedReadWrite type to map to a sequence of -// machine-dependent types. -// -// (3) A per-pipeline-stage machine model can be implemented by providing -// Itineraries in addition to mapping instructions to ItineraryClasses. -//===----------------------------------------------------------------------===// - -// Include legacy support for instruction itineraries. -include "llvm/Target/TargetItinerary.td" - -class Predicate; // Forward def - -// DAG operator that interprets the DAG args as Instruction defs. -def instrs; - -// DAG operator that interprets each DAG arg as a regex pattern for -// matching Instruction opcode names. -// The regex must match the beginning of the opcode (as in Python re.match). -// To avoid matching prefixes, append '$' to the pattern. -def instregex; - -// Define the SchedMachineModel and provide basic properties for -// coarse grained instruction cost model. Default values for the -// properties are defined in MCSchedModel. A value of "-1" in the -// target description's SchedMachineModel indicates that the property -// is not overridden by the target. -// -// Target hooks allow subtargets to associate LoadLatency and -// HighLatency with groups of opcodes. -// -// See MCSchedule.h for detailed comments. -class SchedMachineModel { - int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. - int MicroOpBufferSize = -1; // Max micro-ops that can be buffered. - int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for - // optimized loop dispatch/execution. - int LoadLatency = -1; // Cycles for loads to access the cache. - int HighLatency = -1; // Approximation of cycles for "high latency" ops. - int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. - - // Per-cycle resources tables. - ProcessorItineraries Itineraries = NoItineraries; - - bit PostRAScheduler = false; // Enable Post RegAlloc Scheduler pass. - - // Subtargets that define a model for only a subset of instructions - // that have a scheduling class (itinerary class or SchedRW list) - // and may actually be generated for that subtarget must clear this - // bit. Otherwise, the scheduler considers an unmodelled opcode to - // be an error. This should only be set during initial bringup, - // or there will be no way to catch simple errors in the model - // resulting from changes to the instruction definitions. - bit CompleteModel = true; - - // Indicates that we should do full overlap checking for multiple InstrRWs - // defining the same instructions within the same SchedMachineModel. - // FIXME: Remove when all in tree targets are clean with the full check - // enabled. - bit FullInstRWOverlapCheck = true; - - // A processor may only implement part of published ISA, due to either new ISA - // extensions, (e.g. Pentium 4 doesn't have AVX) or implementation - // (ARM/MIPS/PowerPC/SPARC soft float cores). - // - // For a processor which doesn't support some feature(s), the schedule model - // can use: - // - // let UnsupportedFeatures = [HaveA,..,HaveY]; - // - // to skip the checks for scheduling information when building LLVM for - // instructions which have any of the listed predicates in their Predicates - // field. - list UnsupportedFeatures = []; - - bit NoModel = false; // Special tag to indicate missing machine model. -} - -def NoSchedModel : SchedMachineModel { - let NoModel = true; - let CompleteModel = false; -} - -// Define a kind of processor resource that may be common across -// similar subtargets. -class ProcResourceKind; - -// Define a number of interchangeable processor resources. NumUnits -// determines the throughput of instructions that require the resource. -// -// An optional Super resource may be given to model these resources as -// a subset of the more general super resources. Using one of these -// resources implies using one of the super resources. -// -// ProcResourceUnits normally model a few buffered resources within an -// out-of-order engine. Buffered resources may be held for multiple -// clock cycles, but the scheduler does not pin them to a particular -// clock cycle relative to instruction dispatch. Setting BufferSize=0 -// changes this to an in-order issue/dispatch resource. In this case, -// the scheduler counts down from the cycle that the instruction -// issues in-order, forcing a stall whenever a subsequent instruction -// requires the same resource until the number of ResourceCycles -// specified in WriteRes expire. Setting BufferSize=1 changes this to -// an in-order latency resource. In this case, the scheduler models -// producer/consumer stalls between instructions that use the -// resource. -// -// Examples (all assume an out-of-order engine): -// -// Use BufferSize = -1 for "issue ports" fed by a unified reservation -// station. Here the size of the reservation station is modeled by -// MicroOpBufferSize, which should be the minimum size of either the -// register rename pool, unified reservation station, or reorder -// buffer. -// -// Use BufferSize = 0 for resources that force "dispatch/issue -// groups". (Different processors define dispath/issue -// differently. Here we refer to stage between decoding into micro-ops -// and moving them into a reservation station.) Normally NumMicroOps -// is sufficient to limit dispatch/issue groups. However, some -// processors can form groups of with only certain combinations of -// instruction types. e.g. POWER7. -// -// Use BufferSize = 1 for in-order execution units. This is used for -// an in-order pipeline within an out-of-order core where scheduling -// dependent operations back-to-back is guaranteed to cause a -// bubble. e.g. Cortex-a9 floating-point. -// -// Use BufferSize > 1 for out-of-order executions units with a -// separate reservation station. This simply models the size of the -// reservation station. -// -// To model both dispatch/issue groups and in-order execution units, -// create two types of units, one with BufferSize=0 and one with -// BufferSize=1. -// -// SchedModel ties these units to a processor for any stand-alone defs -// of this class. -class ProcResourceUnits { - ProcResourceKind Kind = kind; - int NumUnits = num; - ProcResourceKind Super = ?; - int BufferSize = -1; - SchedMachineModel SchedModel = ?; -} - -// EponymousProcResourceKind helps implement ProcResourceUnits by -// allowing a ProcResourceUnits definition to reference itself. It -// should not be referenced anywhere else. -def EponymousProcResourceKind : ProcResourceKind; - -// Subtargets typically define processor resource kind and number of -// units in one place. -class ProcResource : ProcResourceKind, - ProcResourceUnits; - -class ProcResGroup resources> : ProcResourceKind { - list Resources = resources; - SchedMachineModel SchedModel = ?; - int BufferSize = -1; -} - -// A target architecture may define SchedReadWrite types and associate -// them with instruction operands. -class SchedReadWrite; - -// List the per-operand types that map to the machine model of an -// instruction. One SchedWrite type must be listed for each explicit -// def operand in order. Additional SchedWrite types may optionally be -// listed for implicit def operands. SchedRead types may optionally -// be listed for use operands in order. The order of defs relative to -// uses is insignificant. This way, the same SchedReadWrite list may -// be used for multiple forms of an operation. For example, a -// two-address instruction could have two tied operands or single -// operand that both reads and writes a reg. In both cases we have a -// single SchedWrite and single SchedRead in any order. -class Sched schedrw> { - list SchedRW = schedrw; -} - -// Define a scheduler resource associated with a def operand. -class SchedWrite : SchedReadWrite; -def NoWrite : SchedWrite; - -// Define a scheduler resource associated with a use operand. -class SchedRead : SchedReadWrite; - -// Define a SchedWrite that is modeled as a sequence of other -// SchedWrites with additive latency. This allows a single operand to -// be mapped the resources composed from a set of previously defined -// SchedWrites. -// -// If the final write in this sequence is a SchedWriteVariant marked -// Variadic, then the list of prior writes are distributed across all -// operands after resolving the predicate for the final write. -// -// SchedModel silences warnings but is ignored. -class WriteSequence writes, int rep = 1> : SchedWrite { - list Writes = writes; - int Repeat = rep; - SchedMachineModel SchedModel = ?; -} - -// Define values common to WriteRes and SchedWriteRes. -// -// SchedModel ties these resources to a processor. -class ProcWriteResources resources> { - list ProcResources = resources; - list ResourceCycles = []; - int Latency = 1; - int NumMicroOps = 1; - bit BeginGroup = false; - bit EndGroup = false; - // Allow a processor to mark some scheduling classes as unsupported - // for stronger verification. - bit Unsupported = false; - // Allow a processor to mark some scheduling classes as single-issue. - // SingleIssue is an alias for Begin/End Group. - bit SingleIssue = false; - // An instruction is allowed to retire out-of-order if RetireOOO is - // true for at least one of its writes. This field is only used by - // MCA for in-order subtargets, and is ignored for other targets. - bit RetireOOO = false; - SchedMachineModel SchedModel = ?; -} - -// Define the resources and latency of a SchedWrite. This will be used -// directly by targets that have no itinerary classes. In this case, -// SchedWrite is defined by the target, while WriteResources is -// defined by the subtarget, and maps the SchedWrite to processor -// resources. -// -// If a target already has itinerary classes, SchedWriteResources can -// be used instead to define subtarget specific SchedWrites and map -// them to processor resources in one place. Then ItinRW can map -// itinerary classes to the subtarget's SchedWrites. -// -// ProcResources indicates the set of resources consumed by the write. -// Optionally, ResourceCycles indicates the number of cycles the -// resource is consumed. Each ResourceCycles item is paired with the -// ProcResource item at the same position in its list. ResourceCycles -// can be `[]`: in that case, all resources are consumed for a single -// cycle, regardless of latency, which models a fully pipelined processing -// unit. A value of 0 for ResourceCycles means that the resource must -// be available but is not consumed, which is only relevant for -// unbuffered resources. -// -// By default, each SchedWrite takes one micro-op, which is counted -// against the processor's IssueWidth limit. If an instruction can -// write multiple registers with a single micro-op, the subtarget -// should define one of the writes to be zero micro-ops. If a -// subtarget requires multiple micro-ops to write a single result, it -// should either override the write's NumMicroOps to be greater than 1 -// or require additional writes. Extra writes can be required either -// by defining a WriteSequence, or simply listing extra writes in the -// instruction's list of writers beyond the number of "def" -// operands. The scheduler assumes that all micro-ops must be -// dispatched in the same cycle. These micro-ops may be required to -// begin or end the current dispatch group. -class WriteRes resources> - : ProcWriteResources { - SchedWrite WriteType = write; -} - -// Directly name a set of WriteResources defining a new SchedWrite -// type at the same time. This class is unaware of its SchedModel so -// must be referenced by InstRW or ItinRW. -class SchedWriteRes resources> : SchedWrite, - ProcWriteResources; - -// Define values common to ReadAdvance and SchedReadAdvance. -// -// SchedModel ties these resources to a processor. -class ProcReadAdvance writes = []> { - int Cycles = cycles; - list ValidWrites = writes; - // Allow a processor to mark some scheduling classes as unsupported - // for stronger verification. - bit Unsupported = false; - SchedMachineModel SchedModel = ?; -} - -// A processor may define a ReadAdvance associated with a SchedRead -// to reduce latency of a prior write by N cycles. A negative advance -// effectively increases latency, which may be used for cross-domain -// stalls. -// -// A ReadAdvance may be associated with a list of SchedWrites -// to implement pipeline bypass. The Writes list may be empty to -// indicate operands that are always read this number of Cycles later -// than a normal register read, allowing the read's parent instruction -// to issue earlier relative to the writer. -class ReadAdvance writes = []> - : ProcReadAdvance { - SchedRead ReadType = read; -} - -// Directly associate a new SchedRead type with a delay and optional -// pipeline bypass. For use with InstRW or ItinRW. -class SchedReadAdvance writes = []> : SchedRead, - ProcReadAdvance; - -// Define SchedRead defaults. Reads seldom need special treatment. -def ReadDefault : SchedRead; -def NoReadAdvance : SchedReadAdvance<0>; - -// Define shared code that will be in the same scope as all -// SchedPredicates. Available variables are: -// (const MachineInstr *MI, const TargetSchedModel *SchedModel) -class PredicateProlog { - code Code = c; -} - -// Base class for scheduling predicates. -class SchedPredicateBase; - -// A scheduling predicate whose logic is defined by a MCInstPredicate. -// This can directly be used by SchedWriteVariant definitions. -class MCSchedPredicate : SchedPredicateBase { - MCInstPredicate Pred = P; - SchedMachineModel SchedModel = ?; -} - -// Define a predicate to determine which SchedVariant applies to a -// particular MachineInstr. The code snippet is used as an -// if-statement's expression. Available variables are MI, SchedModel, -// and anything defined in a PredicateProlog. -// -// SchedModel silences warnings but is ignored. -class SchedPredicate : SchedPredicateBase { - SchedMachineModel SchedModel = ?; - code Predicate = pred; -} - -// Define a predicate to be typically used as the default case in a -// SchedVariant. It the SchedVariant does not use any other predicate based on -// MCSchedPredicate, this is the default scheduling case used by llvm-mca. -def NoSchedPred : MCSchedPredicate; - -// Associate a predicate with a list of SchedReadWrites. By default, -// the selected SchedReadWrites are still associated with a single -// operand and assumed to execute sequentially with additive -// latency. However, if the parent SchedWriteVariant or -// SchedReadVariant is marked "Variadic", then each Selected -// SchedReadWrite is mapped in place to the instruction's variadic -// operands. In this case, latency is not additive. If the current Variant -// is already part of a Sequence, then that entire chain leading up to -// the Variant is distributed over the variadic operands. -class SchedVar selected> { - SchedPredicateBase Predicate = pred; - list Selected = selected; -} - -// SchedModel silences warnings but is ignored. -class SchedVariant variants> { - list Variants = variants; - bit Variadic = false; - SchedMachineModel SchedModel = ?; -} - -// A SchedWriteVariant is a single SchedWrite type that maps to a list -// of SchedWrite types under the conditions defined by its predicates. -// -// A Variadic write is expanded to cover multiple "def" operands. The -// SchedVariant's Expansion list is then interpreted as one write -// per-operand instead of the usual sequential writes feeding a single -// operand. -class SchedWriteVariant variants> : SchedWrite, - SchedVariant { -} - -// A SchedReadVariant is a single SchedRead type that maps to a list -// of SchedRead types under the conditions defined by its predicates. -// -// A Variadic write is expanded to cover multiple "readsReg" operands as -// explained above. -class SchedReadVariant variants> : SchedRead, - SchedVariant { -} - -// Map a set of opcodes to a list of SchedReadWrite types. This allows -// the subtarget to easily override specific operations. -// -// SchedModel ties this opcode mapping to a processor. -class InstRW rw, dag instrlist> { - list OperandReadWrites = rw; - dag Instrs = instrlist; - SchedMachineModel SchedModel = ?; - // Allow a subtarget to mark some instructions as unsupported. - bit Unsupported = false; -} - -// Map a set of itinerary classes to SchedReadWrite resources. This is -// used to bootstrap a target (e.g. ARM) when itineraries already -// exist and changing InstrInfo is undesirable. -// -// SchedModel ties this ItineraryClass mapping to a processor. -class ItinRW rw, list iic> { - list MatchedItinClasses = iic; - list OperandReadWrites = rw; - SchedMachineModel SchedModel = ?; -} - -// Alias a target-defined SchedReadWrite to a processor specific -// SchedReadWrite. This allows a subtarget to easily map a -// SchedReadWrite type onto a WriteSequence, SchedWriteVariant, or -// SchedReadVariant. -// -// SchedModel will usually be provided by surrounding let statement -// and ties this SchedAlias mapping to a processor. -class SchedAlias { - SchedReadWrite MatchRW = match; - SchedReadWrite AliasRW = alias; - SchedMachineModel SchedModel = ?; -} - -// Allow the definition of processor register files for register renaming -// purposes. -// -// Each processor register file declares: -// - The set of registers that can be renamed. -// - The number of physical registers which can be used for register renaming -// purpose. -// - The cost of a register rename. -// - The set of registers that allow move elimination. -// - The maximum number of moves that can be eliminated every cycle. -// - Whether move elimination is limited to register moves whose input -// is known to be zero. -// -// The cost of a rename is the number of physical registers allocated by the -// register alias table to map the new definition. By default, register can be -// renamed at the cost of a single physical register. Note that register costs -// are defined at register class granularity (see field `Costs`). -// -// The set of registers that are subject to register renaming is declared using -// a list of register classes (see field `RegClasses`). An empty list of -// register classes means: all the logical registers defined by the target can -// be fully renamed. -// -// A register R can be renamed if its register class appears in the `RegClasses` -// set. When R is written, a new alias is allocated at the cost of one or more -// physical registers; as a result, false dependencies on R are removed. -// -// A sub-register V of register R is implicitly part of the same register file. -// However, V is only renamed if its register class is part of `RegClasses`. -// Otherwise, the processor keeps it (as well as any other different part -// of R) together with R, and a write of V always causes a compulsory read of R. -// -// This is what happens for example on AMD processors (at least from Bulldozer -// onwards), where AL and AH are not treated as independent from AX, and AX is -// not treated as independent from EAX. A write to AL has an implicitly false -// dependency on the last write to EAX (or a portion of EAX). As a consequence, -// a write to AL cannot go in parallel with a write to AH. -// -// There is no false dependency if the partial register write belongs to a -// register class that is in `RegClasses`. -// There is also no penalty for writes that "clear the content a super-register" -// (see MC/MCInstrAnalysis.h - method MCInstrAnalysis::clearsSuperRegisters()). -// On x86-64, 32-bit GPR writes implicitly zero the upper half of the underlying -// physical register, effectively removing any false dependencies with the -// previous register definition. -// -// TODO: This implementation assumes that there is no limit in the number of -// renames per cycle, which might not be true for all hardware or register -// classes. Also, there is no limit to how many times the same logical register -// can be renamed during the same cycle. -// -// TODO: we don't currently model merge penalties for the case where a write to -// a part of a register is followed by a read from a larger part of the same -// register. On some Intel chips, different parts of a GPR can be stored in -// different physical registers. However, there is a cost to pay for when the -// partial write is combined with the previous super-register definition. We -// should add support for these cases, and correctly model merge problems with -// partial register accesses. -// -// Field MaxMovesEliminatedPerCycle specifies how many moves can be eliminated -// every cycle. A default value of zero for that field means: there is no limit -// to the number of moves that can be eliminated by this register file. -// -// An instruction MI is a candidate for move elimination if a call to -// method TargetSubtargetInfo::isOptimizableRegisterMove(MI) returns true (see -// llvm/CodeGen/TargetSubtargetInfo.h, and llvm/MC/MCInstrAnalysis.h). -// -// Subtargets can instantiate tablegen class IsOptimizableRegisterMove (see -// llvm/Target/TargetInstrPredicate.td) to customize the set of move elimination -// candidates. By default, no instruction is a valid move elimination candidate. -// -// A register move MI is eliminated only if: -// - MI is a move elimination candidate. -// - The destination register is from a register class that allows move -// elimination (see field `AllowMoveElimination` below). -// - Constraints on the move kind, and the maximum number of moves that can be -// eliminated per cycle are all met. - -class RegisterFile Classes = [], - list Costs = [], list AllowMoveElim = [], - int MaxMoveElimPerCy = 0, bit AllowZeroMoveElimOnly = false> { - list RegClasses = Classes; - list RegCosts = Costs; - list AllowMoveElimination = AllowMoveElim; - int NumPhysRegs = numPhysRegs; - int MaxMovesEliminatedPerCycle = MaxMoveElimPerCy; - bit AllowZeroMoveEliminationOnly = AllowZeroMoveElimOnly; - SchedMachineModel SchedModel = ?; -} - -// Describe the retire control unit. -// A retire control unit specifies the size of the reorder buffer, as well as -// the maximum number of opcodes that can be retired every cycle. -// A value less-than-or-equal-to zero for field 'ReorderBufferSize' means: "the -// size is unknown". The idea is that external tools can fall-back to using -// field MicroOpBufferSize in SchedModel if the reorder buffer size is unknown. -// A zero or negative value for field 'MaxRetirePerCycle' means "no -// restrictions on the number of instructions retired per cycle". -// Models can optionally specify up to one instance of RetireControlUnit per -// scheduling model. -class RetireControlUnit { - int ReorderBufferSize = bufferSize; - int MaxRetirePerCycle = retirePerCycle; - SchedMachineModel SchedModel = ?; -} - -// Base class for Load/StoreQueue. It is used to identify processor resources -// which describe load/store queues in the LS unit. -class MemoryQueue { - ProcResourceKind QueueDescriptor = PR; - SchedMachineModel SchedModel = ?; -} - -class LoadQueue : MemoryQueue; -class StoreQueue : MemoryQueue; diff --git a/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td b/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td deleted file mode 100644 index d8ef7c49a5..0000000000 --- a/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td +++ /dev/null @@ -1,1668 +0,0 @@ -//===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the target-independent interfaces used by SelectionDAG -// instruction selection generators. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Selection DAG Type Constraint definitions. -// -// Note that the semantics of these constraints are hard coded into tblgen. To -// modify or add constraints, you have to hack tblgen. -// - -class SDTypeConstraint { - int OperandNum = opnum; -} - -// SDTCisVT - The specified operand has exactly this VT. -class SDTCisVT : SDTypeConstraint { - ValueType VT = vt; -} - -class SDTCisPtrTy : SDTypeConstraint; - -// SDTCisInt - The specified operand has integer type. -class SDTCisInt : SDTypeConstraint; - -// SDTCisFP - The specified operand has floating-point type. -class SDTCisFP : SDTypeConstraint; - -// SDTCisVec - The specified operand has a vector type. -class SDTCisVec : SDTypeConstraint; - -// SDTCisSameAs - The two specified operands have identical types. -class SDTCisSameAs : SDTypeConstraint { - int OtherOperandNum = OtherOp; -} - -// SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is -// smaller than the 'Other' operand. -class SDTCisVTSmallerThanOp : SDTypeConstraint { - int OtherOperandNum = OtherOp; -} - -class SDTCisOpSmallerThanOp : SDTypeConstraint{ - int BigOperandNum = BigOp; -} - -/// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same -/// type as the element type of OtherOp, which is a vector type. -class SDTCisEltOfVec - : SDTypeConstraint { - int OtherOpNum = OtherOp; -} - -/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type -/// with length less that of OtherOp, which is a vector type. -class SDTCisSubVecOfVec - : SDTypeConstraint { - int OtherOpNum = OtherOp; -} - -// SDTCVecEltisVT - The specified operand is vector type with element type -// of VT. -class SDTCVecEltisVT : SDTypeConstraint { - ValueType VT = vt; -} - -// SDTCisSameNumEltsAs - The two specified operands have identical number -// of elements. -class SDTCisSameNumEltsAs : SDTypeConstraint { - int OtherOperandNum = OtherOp; -} - -// SDTCisSameSizeAs - The two specified operands have identical size. -class SDTCisSameSizeAs : SDTypeConstraint { - int OtherOperandNum = OtherOp; -} - -//===----------------------------------------------------------------------===// -// Selection DAG Type Profile definitions. -// -// These use the constraints defined above to describe the type requirements of -// the various nodes. These are not hard coded into tblgen, allowing targets to -// add their own if needed. -// - -// SDTypeProfile - This profile describes the type requirements of a Selection -// DAG node. -class SDTypeProfile constraints> { - int NumResults = numresults; - int NumOperands = numoperands; - list Constraints = constraints; -} - -// Builtin profiles. -def SDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for 'imm'. -def SDTFPLeaf : SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for 'fpimm'. -def SDTPtrLeaf: SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for '&g'. -def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. -def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. -def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. - -def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc. - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0> -]>; -def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl - SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2> -]>; -def SDTIntShiftDOp: SDTypeProfile<1, 3, [ // fshl, fshr - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0>, SDTCisInt<3> -]>; -def SDTIntSatNoShOp : SDTypeProfile<1, 2, [ // ssat with no shift - SDTCisSameAs<0, 1>, SDTCisInt<2> -]>; -def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0> -]>; -def SDTIntScaledBinOp : SDTypeProfile<1, 3, [ // smulfix, sdivfix, etc - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0>, SDTCisInt<3> -]>; - -def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc. - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0> -]>; -def SDTFPSignOp : SDTypeProfile<1, 2, [ // fcopysign. - SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisFP<2> -]>; -def SDTFPTernaryOp : SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc. - SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0> -]>; -def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // bitreverse - SDTCisSameAs<0, 1>, SDTCisInt<0> -]>; -def SDTIntBitCountUnaryOp : SDTypeProfile<1, 1, [ // ctlz, cttz - SDTCisInt<0>, SDTCisInt<1> -]>; -def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext - SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc - SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc - SDTCisSameAs<0, 1>, SDTCisFP<0> -]>; -def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fpround - SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fpextend - SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp - SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int - SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1> -]>; -def SDTFPToIntSatOp : SDTypeProfile<1, 2, [ // fp_to_[su]int_sat - SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>, SDTCisVT<2, OtherVT> -]>; -def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg - SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, - SDTCisVTSmallerThanOp<2, 1> -]>; -def SDTExtInvec : SDTypeProfile<1, 1, [ // sext_invec - SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>, SDTCisVec<1>, - SDTCisOpSmallerThanOp<1, 0> -]>; - -def SDTSetCC : SDTypeProfile<1, 3, [ // setcc - SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> -]>; - -def SDTSelect : SDTypeProfile<1, 3, [ // select - SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> -]>; - -def SDTVSelect : SDTypeProfile<1, 3, [ // vselect - SDTCisVec<0>, SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1> -]>; - -def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc - SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, - SDTCisVT<5, OtherVT> -]>; - -def SDTBr : SDTypeProfile<0, 1, [ // br - SDTCisVT<0, OtherVT> -]>; - -def SDTBrCC : SDTypeProfile<0, 4, [ // brcc - SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> -]>; - -def SDTBrcond : SDTypeProfile<0, 2, [ // brcond - SDTCisInt<0>, SDTCisVT<1, OtherVT> -]>; - -def SDTBrind : SDTypeProfile<0, 1, [ // brind - SDTCisPtrTy<0> -]>; - -def SDTCatchret : SDTypeProfile<0, 2, [ // catchret - SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT> -]>; - -def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap - -def SDTUBSANTrap : SDTypeProfile<0, 1, []>; // ubsantrap - -def SDTLoad : SDTypeProfile<1, 1, [ // load - SDTCisPtrTy<1> -]>; - -def SDTStore : SDTypeProfile<0, 2, [ // store - SDTCisPtrTy<1> -]>; - -def SDTIStore : SDTypeProfile<1, 3, [ // indexed store - SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> -]>; - -def SDTMaskedStore: SDTypeProfile<0, 4, [ // masked store - SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisPtrTy<2>, SDTCisVec<3>, SDTCisSameNumEltsAs<0, 3> -]>; - -def SDTMaskedLoad: SDTypeProfile<1, 4, [ // masked load - SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisPtrTy<2>, SDTCisVec<3>, SDTCisSameAs<0, 4>, - SDTCisSameNumEltsAs<0, 3> -]>; - -def SDTVecShuffle : SDTypeProfile<1, 2, [ - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> -]>; -def SDTVecSlice : SDTypeProfile<1, 3, [ // vector splice - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisInt<3> -]>; -def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract - SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> -]>; -def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert - SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> -]>; -def SDTVecReduce : SDTypeProfile<1, 1, [ // vector reduction - SDTCisInt<0>, SDTCisVec<1> -]>; -def SDTFPVecReduce : SDTypeProfile<1, 1, [ // FP vector reduction - SDTCisFP<0>, SDTCisVec<1> -]>; - -def SDTVecReverse : SDTypeProfile<1, 1, [ // vector reverse - SDTCisVec<0>, SDTCisSameAs<0,1> -]>; - -def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract - SDTCisSubVecOfVec<0,1>, SDTCisInt<2> -]>; -def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert - SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> -]>; - -def SDTPrefetch : SDTypeProfile<0, 4, [ // prefetch - SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, SDTCisInt<1> -]>; - -def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barrier - SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, - SDTCisInt<0> -]>; -def SDTAtomicFence : SDTypeProfile<0, 2, [ - SDTCisSameAs<0,1>, SDTCisPtrTy<0> -]>; -def SDTAtomic3 : SDTypeProfile<1, 3, [ - SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> -]>; -def SDTAtomic2 : SDTypeProfile<1, 2, [ - SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> -]>; - -def SDTFPAtomic2 : SDTypeProfile<1, 2, [ - SDTCisSameAs<0,2>, SDTCisFP<0>, SDTCisPtrTy<1> -]>; - -def SDTAtomicStore : SDTypeProfile<0, 2, [ - SDTCisPtrTy<0>, SDTCisInt<1> -]>; -def SDTAtomicLoad : SDTypeProfile<1, 1, [ - SDTCisInt<0>, SDTCisPtrTy<1> -]>; - -class SDCallSeqStart constraints> : - SDTypeProfile<0, 2, constraints>; -class SDCallSeqEnd constraints> : - SDTypeProfile<0, 2, constraints>; - -//===----------------------------------------------------------------------===// -// Selection DAG Node definitions. -// -class SDNode props = [], string sdclass = "SDNode"> - : SDPatternOperator { - string Opcode = opcode; - string SDClass = sdclass; - let Properties = props; - SDTypeProfile TypeProfile = typeprof; -} - -// Special TableGen-recognized dag nodes -def set; -def implicit; -def node; -def srcvalue; - -def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; -def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; -def fpimm : SDNode<"ISD::ConstantFP", SDTFPLeaf , [], "ConstantFPSDNode">; -def vt : SDNode<"ISD::VALUETYPE" , SDTOther , [], "VTSDNode">; -def bb : SDNode<"ISD::BasicBlock", SDTOther , [], "BasicBlockSDNode">; -def cond : SDNode<"ISD::CONDCODE" , SDTOther , [], "CondCodeSDNode">; -def undef : SDNode<"ISD::UNDEF" , SDTUNDEF , []>; -def vscale : SDNode<"ISD::VSCALE" , SDTIntUnaryOp, []>; -def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [], - "GlobalAddressSDNode">; -def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [], - "GlobalAddressSDNode">; -def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [], - "GlobalAddressSDNode">; -def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [], - "GlobalAddressSDNode">; -def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [], - "ConstantPoolSDNode">; -def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [], - "ConstantPoolSDNode">; -def jumptable : SDNode<"ISD::JumpTable", SDTPtrLeaf, [], - "JumpTableSDNode">; -def tjumptable : SDNode<"ISD::TargetJumpTable", SDTPtrLeaf, [], - "JumpTableSDNode">; -def frameindex : SDNode<"ISD::FrameIndex", SDTPtrLeaf, [], - "FrameIndexSDNode">; -def tframeindex : SDNode<"ISD::TargetFrameIndex", SDTPtrLeaf, [], - "FrameIndexSDNode">; -def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], - "ExternalSymbolSDNode">; -def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], - "ExternalSymbolSDNode">; -def mcsym: SDNode<"ISD::MCSymbol", SDTPtrLeaf, [], "MCSymbolSDNode">; -def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], - "BlockAddressSDNode">; -def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], - "BlockAddressSDNode">; - -def add : SDNode<"ISD::ADD" , SDTIntBinOp , - [SDNPCommutative, SDNPAssociative]>; -def sub : SDNode<"ISD::SUB" , SDTIntBinOp>; -def mul : SDNode<"ISD::MUL" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>; -def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>; -def abds : SDNode<"ISD::ABDS" , SDTIntBinOp, [SDNPCommutative]>; -def abdu : SDNode<"ISD::ABDU" , SDTIntBinOp, [SDNPCommutative]>; -def smullohi : SDNode<"ISD::SMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; -def umullohi : SDNode<"ISD::UMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; -def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>; -def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>; -def srem : SDNode<"ISD::SREM" , SDTIntBinOp>; -def urem : SDNode<"ISD::UREM" , SDTIntBinOp>; -def sdivrem : SDNode<"ISD::SDIVREM" , SDTIntBinHiLoOp>; -def udivrem : SDNode<"ISD::UDIVREM" , SDTIntBinHiLoOp>; -def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>; -def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>; -def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>; -def rotl : SDNode<"ISD::ROTL" , SDTIntShiftOp>; -def rotr : SDNode<"ISD::ROTR" , SDTIntShiftOp>; -def fshl : SDNode<"ISD::FSHL" , SDTIntShiftDOp>; -def fshr : SDNode<"ISD::FSHR" , SDTIntShiftDOp>; -def and : SDNode<"ISD::AND" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def or : SDNode<"ISD::OR" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def xor : SDNode<"ISD::XOR" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, - [SDNPCommutative, SDNPOutGlue]>; -def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, - [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; -def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, - [SDNPOutGlue]>; -def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, - [SDNPOutGlue, SDNPInGlue]>; -def smin : SDNode<"ISD::SMIN" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def smax : SDNode<"ISD::SMAX" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def umin : SDNode<"ISD::UMIN" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def umax : SDNode<"ISD::UMAX" , SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; - -def saddsat : SDNode<"ISD::SADDSAT" , SDTIntBinOp, [SDNPCommutative]>; -def uaddsat : SDNode<"ISD::UADDSAT" , SDTIntBinOp, [SDNPCommutative]>; -def ssubsat : SDNode<"ISD::SSUBSAT" , SDTIntBinOp>; -def usubsat : SDNode<"ISD::USUBSAT" , SDTIntBinOp>; -def sshlsat : SDNode<"ISD::SSHLSAT" , SDTIntBinOp>; -def ushlsat : SDNode<"ISD::USHLSAT" , SDTIntBinOp>; - -def smulfix : SDNode<"ISD::SMULFIX" , SDTIntScaledBinOp, [SDNPCommutative]>; -def smulfixsat : SDNode<"ISD::SMULFIXSAT", SDTIntScaledBinOp, [SDNPCommutative]>; -def umulfix : SDNode<"ISD::UMULFIX" , SDTIntScaledBinOp, [SDNPCommutative]>; -def umulfixsat : SDNode<"ISD::UMULFIXSAT", SDTIntScaledBinOp, [SDNPCommutative]>; -def sdivfix : SDNode<"ISD::SDIVFIX" , SDTIntScaledBinOp>; -def sdivfixsat : SDNode<"ISD::SDIVFIXSAT", SDTIntScaledBinOp>; -def udivfix : SDNode<"ISD::UDIVFIX" , SDTIntScaledBinOp>; -def udivfixsat : SDNode<"ISD::UDIVFIXSAT", SDTIntScaledBinOp>; - -def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; -def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>; -def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>; - -def abs : SDNode<"ISD::ABS" , SDTIntUnaryOp>; -def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>; -def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; -def ctlz : SDNode<"ISD::CTLZ" , SDTIntBitCountUnaryOp>; -def cttz : SDNode<"ISD::CTTZ" , SDTIntBitCountUnaryOp>; -def ctpop : SDNode<"ISD::CTPOP" , SDTIntBitCountUnaryOp>; -def ctlz_zero_undef : SDNode<"ISD::CTLZ_ZERO_UNDEF", SDTIntBitCountUnaryOp>; -def cttz_zero_undef : SDNode<"ISD::CTTZ_ZERO_UNDEF", SDTIntBitCountUnaryOp>; -def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; -def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; -def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; -def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; -def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; -def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; -def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; -def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; - -def vecreduce_add : SDNode<"ISD::VECREDUCE_ADD", SDTVecReduce>; -def vecreduce_smax : SDNode<"ISD::VECREDUCE_SMAX", SDTVecReduce>; -def vecreduce_umax : SDNode<"ISD::VECREDUCE_UMAX", SDTVecReduce>; -def vecreduce_smin : SDNode<"ISD::VECREDUCE_SMIN", SDTVecReduce>; -def vecreduce_umin : SDNode<"ISD::VECREDUCE_UMIN", SDTVecReduce>; -def vecreduce_fadd : SDNode<"ISD::VECREDUCE_FADD", SDTFPVecReduce>; - -def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; -def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; -def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; -def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; -def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; -def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp, [SDNPCommutative]>; -def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp, [SDNPCommutative]>; -def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; -def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def fminnum_ieee : SDNode<"ISD::FMINNUM_IEEE", SDTFPBinOp, - [SDNPCommutative]>; -def fmaxnum_ieee : SDNode<"ISD::FMAXNUM_IEEE", SDTFPBinOp, - [SDNPCommutative]>; -def fminimum : SDNode<"ISD::FMINIMUM" , SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def fmaximum : SDNode<"ISD::FMAXIMUM" , SDTFPBinOp, - [SDNPCommutative, SDNPAssociative]>; -def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>; -def fcanonicalize : SDNode<"ISD::FCANONICALIZE", SDTFPUnaryOp>; -def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; -def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; -def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; -def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; -def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; -def fpow : SDNode<"ISD::FPOW" , SDTFPBinOp>; -def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; -def frint : SDNode<"ISD::FRINT" , SDTFPUnaryOp>; -def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; -def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; -def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; -def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; -def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; -def froundeven : SDNode<"ISD::FROUNDEVEN" , SDTFPUnaryOp>; - -def lround : SDNode<"ISD::LROUND" , SDTFPToIntOp>; -def llround : SDNode<"ISD::LLROUND" , SDTFPToIntOp>; -def lrint : SDNode<"ISD::LRINT" , SDTFPToIntOp>; -def llrint : SDNode<"ISD::LLRINT" , SDTFPToIntOp>; - -def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; -def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; -def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; - -def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; -def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; -def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; -def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; -def fp_to_sint_sat : SDNode<"ISD::FP_TO_SINT_SAT" , SDTFPToIntSatOp>; -def fp_to_uint_sat : SDNode<"ISD::FP_TO_UINT_SAT" , SDTFPToIntSatOp>; -def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; -def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; - -def strict_fadd : SDNode<"ISD::STRICT_FADD", - SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; -def strict_fsub : SDNode<"ISD::STRICT_FSUB", - SDTFPBinOp, [SDNPHasChain]>; -def strict_fmul : SDNode<"ISD::STRICT_FMUL", - SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; -def strict_fdiv : SDNode<"ISD::STRICT_FDIV", - SDTFPBinOp, [SDNPHasChain]>; -def strict_frem : SDNode<"ISD::STRICT_FREM", - SDTFPBinOp, [SDNPHasChain]>; -def strict_fma : SDNode<"ISD::STRICT_FMA", - SDTFPTernaryOp, [SDNPHasChain, SDNPCommutative]>; -def strict_fsqrt : SDNode<"ISD::STRICT_FSQRT", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fsin : SDNode<"ISD::STRICT_FSIN", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fcos : SDNode<"ISD::STRICT_FCOS", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fexp2 : SDNode<"ISD::STRICT_FEXP2", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fpow : SDNode<"ISD::STRICT_FPOW", - SDTFPBinOp, [SDNPHasChain]>; -def strict_flog2 : SDNode<"ISD::STRICT_FLOG2", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_frint : SDNode<"ISD::STRICT_FRINT", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_lrint : SDNode<"ISD::STRICT_LRINT", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_llrint : SDNode<"ISD::STRICT_LLRINT", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_fnearbyint : SDNode<"ISD::STRICT_FNEARBYINT", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fceil : SDNode<"ISD::STRICT_FCEIL", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_ffloor : SDNode<"ISD::STRICT_FFLOOR", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_lround : SDNode<"ISD::STRICT_LROUND", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_llround : SDNode<"ISD::STRICT_LLROUND", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_fround : SDNode<"ISD::STRICT_FROUND", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_froundeven : SDNode<"ISD::STRICT_FROUNDEVEN", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_ftrunc : SDNode<"ISD::STRICT_FTRUNC", - SDTFPUnaryOp, [SDNPHasChain]>; -def strict_fminnum : SDNode<"ISD::STRICT_FMINNUM", - SDTFPBinOp, [SDNPHasChain, - SDNPCommutative, SDNPAssociative]>; -def strict_fmaxnum : SDNode<"ISD::STRICT_FMAXNUM", - SDTFPBinOp, [SDNPHasChain, - SDNPCommutative, SDNPAssociative]>; -def strict_fminimum : SDNode<"ISD::STRICT_FMINIMUM", - SDTFPBinOp, [SDNPHasChain, - SDNPCommutative, SDNPAssociative]>; -def strict_fmaximum : SDNode<"ISD::STRICT_FMAXIMUM", - SDTFPBinOp, [SDNPHasChain, - SDNPCommutative, SDNPAssociative]>; -def strict_fpround : SDNode<"ISD::STRICT_FP_ROUND", - SDTFPRoundOp, [SDNPHasChain]>; -def strict_fpextend : SDNode<"ISD::STRICT_FP_EXTEND", - SDTFPExtendOp, [SDNPHasChain]>; -def strict_fp_to_sint : SDNode<"ISD::STRICT_FP_TO_SINT", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_fp_to_uint : SDNode<"ISD::STRICT_FP_TO_UINT", - SDTFPToIntOp, [SDNPHasChain]>; -def strict_sint_to_fp : SDNode<"ISD::STRICT_SINT_TO_FP", - SDTIntToFPOp, [SDNPHasChain]>; -def strict_uint_to_fp : SDNode<"ISD::STRICT_UINT_TO_FP", - SDTIntToFPOp, [SDNPHasChain]>; -def strict_fsetcc : SDNode<"ISD::STRICT_FSETCC", SDTSetCC, [SDNPHasChain]>; -def strict_fsetccs : SDNode<"ISD::STRICT_FSETCCS", SDTSetCC, [SDNPHasChain]>; - -def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; -def select : SDNode<"ISD::SELECT" , SDTSelect>; -def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; -def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; - -def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; -def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; -def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; -def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; -def catchret : SDNode<"ISD::CATCHRET" , SDTCatchret, - [SDNPHasChain, SDNPSideEffect]>; -def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>; - -def trap : SDNode<"ISD::TRAP" , SDTNone, - [SDNPHasChain, SDNPSideEffect]>; -def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone, - [SDNPHasChain, SDNPSideEffect]>; -def ubsantrap : SDNode<"ISD::UBSANTRAP" , SDTUBSANTrap, - [SDNPHasChain, SDNPSideEffect]>; - -def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; - -def readcyclecounter : SDNode<"ISD::READCYCLECOUNTER", SDTIntLeaf, - [SDNPHasChain, SDNPSideEffect]>; - -def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence, - [SDNPHasChain, SDNPSideEffect]>; - -def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_clr : SDNode<"ISD::ATOMIC_LOAD_CLR" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_fadd : SDNode<"ISD::ATOMIC_LOAD_FADD" , SDTFPAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_fsub : SDNode<"ISD::ATOMIC_LOAD_FSUB" , SDTFPAtomic2, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; - -def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def masked_st : SDNode<"ISD::MSTORE", SDTMaskedStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def masked_ld : SDNode<"ISD::MLOAD", SDTMaskedLoad, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; - -// Do not use ld, st directly. Use load, extload, sextload, zextload, store, -// and truncst (see below). -def ld : SDNode<"ISD::LOAD" , SDTLoad, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def st : SDNode<"ISD::STORE" , SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def ist : SDNode<"ISD::STORE" , SDTIStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>; -def vector_reverse : SDNode<"ISD::VECTOR_REVERSE", SDTVecReverse>; -def vector_splice : SDNode<"ISD::VECTOR_SPLICE", SDTVecSlice, []>; -def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>; -def splat_vector : SDNode<"ISD::SPLAT_VECTOR", SDTypeProfile<1, 1, []>, []>; -def step_vector : SDNode<"ISD::STEP_VECTOR", SDTypeProfile<1, 1, - [SDTCisVec<0>, SDTCisInt<1>]>, []>; -def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>, - []>; - -// vector_extract/vector_insert are deprecated. extractelt/insertelt -// are preferred. -def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", - SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; -def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", - SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; -def concat_vectors : SDNode<"ISD::CONCAT_VECTORS", - SDTypeProfile<1, 2, [SDTCisSubVecOfVec<1, 0>, SDTCisSameAs<1, 2>]>,[]>; - -// This operator does not do subvector type checking. The ARM -// backend, at least, needs it. -def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", - SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, - []>; - -// This operator does subvector type checking. -def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; -def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; - -// Nodes for intrinsics, you should use the intrinsic itself and let tblgen use -// these internally. Don't reference these directly. -def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", - SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, - [SDNPHasChain]>; -def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", - SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, - [SDNPHasChain]>; -def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", - SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; - -def SDT_assert : SDTypeProfile<1, 1, - [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>; -def assertsext : SDNode<"ISD::AssertSext", SDT_assert>; -def assertzext : SDNode<"ISD::AssertZext", SDT_assert>; -def assertalign : SDNode<"ISD::AssertAlign", SDT_assert>; - -//===----------------------------------------------------------------------===// -// Selection DAG Condition Codes - -class CondCode { - string ICmpPredicate = icmpName; - string FCmpPredicate = fcmpName; -} - -// ISD::CondCode enums, and mapping to CmpInst::Predicate names -def SETOEQ : CondCode<"FCMP_OEQ">; -def SETOGT : CondCode<"FCMP_OGT">; -def SETOGE : CondCode<"FCMP_OGE">; -def SETOLT : CondCode<"FCMP_OLT">; -def SETOLE : CondCode<"FCMP_OLE">; -def SETONE : CondCode<"FCMP_ONE">; -def SETO : CondCode<"FCMP_ORD">; -def SETUO : CondCode<"FCMP_UNO">; -def SETUEQ : CondCode<"FCMP_UEQ">; -def SETUGT : CondCode<"FCMP_UGT", "ICMP_UGT">; -def SETUGE : CondCode<"FCMP_UGE", "ICMP_UGE">; -def SETULT : CondCode<"FCMP_ULT", "ICMP_ULT">; -def SETULE : CondCode<"FCMP_ULE", "ICMP_ULE">; -def SETUNE : CondCode<"FCMP_UNE">; -def SETEQ : CondCode<"", "ICMP_EQ">; -def SETGT : CondCode<"", "ICMP_SGT">; -def SETGE : CondCode<"", "ICMP_SGE">; -def SETLT : CondCode<"", "ICMP_SLT">; -def SETLE : CondCode<"", "ICMP_SLE">; -def SETNE : CondCode<"", "ICMP_NE">; - -//===----------------------------------------------------------------------===// -// Selection DAG Node Transformation Functions. -// -// This mechanism allows targets to manipulate nodes in the output DAG once a -// match has been formed. This is typically used to manipulate immediate -// values. -// -class SDNodeXForm { - SDNode Opcode = opc; - code XFormFunction = xformFunction; -} - -def NOOP_SDNodeXForm : SDNodeXForm; - -//===----------------------------------------------------------------------===// -// Selection DAG Pattern Fragments. -// -// Pattern fragments are reusable chunks of dags that match specific things. -// They can take arguments and have C++ predicates that control whether they -// match. They are intended to make the patterns for common instructions more -// compact and readable. -// - -/// PatFrags - Represents a set of pattern fragments. Each single fragment -/// can match something on the DAG, from a single node to multiple nested other -/// fragments. The whole set of fragments matches if any of the single -/// fragments match. This allows e.g. matching and "add with overflow" and -/// a regular "add" with the same fragment set. -/// -class PatFrags frags, code pred = [{}], - SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { - dag Operands = ops; - list Fragments = frags; - code PredicateCode = pred; - code GISelPredicateCode = [{}]; - code ImmediateCode = [{}]; - SDNodeXForm OperandTransform = xform; - - // When this is set, the PredicateCode may refer to a constant Operands - // vector which contains the captured nodes of the DAG, in the order listed - // by the Operands field above. - // - // This is useful when Fragments involves associative / commutative - // operators: a single piece of code can easily refer to all operands even - // when re-associated / commuted variants of the fragment are matched. - bit PredicateCodeUsesOperands = false; - - // Define a few pre-packaged predicates. This helps GlobalISel import - // existing rules from SelectionDAG for many common cases. - // They will be tested prior to the code in pred and must not be used in - // ImmLeaf and its subclasses. - - // Is the desired pre-packaged predicate for a load? - bit IsLoad = ?; - // Is the desired pre-packaged predicate for a store? - bit IsStore = ?; - // Is the desired pre-packaged predicate for an atomic? - bit IsAtomic = ?; - - // cast(N)->getAddressingMode() == ISD::UNINDEXED; - // cast(N)->getAddressingMode() == ISD::UNINDEXED; - bit IsUnindexed = ?; - - // cast(N)->getExtensionType() != ISD::NON_EXTLOAD - bit IsNonExtLoad = ?; - // cast(N)->getExtensionType() == ISD::EXTLOAD; - bit IsAnyExtLoad = ?; - // cast(N)->getExtensionType() == ISD::SEXTLOAD; - bit IsSignExtLoad = ?; - // cast(N)->getExtensionType() == ISD::ZEXTLOAD; - bit IsZeroExtLoad = ?; - // !cast(N)->isTruncatingStore(); - // cast(N)->isTruncatingStore(); - bit IsTruncStore = ?; - - // cast(N)->getAddressSpace() == - // If this empty, accept any address space. - list AddressSpaces = ?; - - // cast(N)->getAlignment() >= - // If this is empty, accept any alignment. - int MinAlignment = ?; - - // cast(N)->getOrdering() == AtomicOrdering::Monotonic - bit IsAtomicOrderingMonotonic = ?; - // cast(N)->getOrdering() == AtomicOrdering::Acquire - bit IsAtomicOrderingAcquire = ?; - // cast(N)->getOrdering() == AtomicOrdering::Release - bit IsAtomicOrderingRelease = ?; - // cast(N)->getOrdering() == AtomicOrdering::AcquireRelease - bit IsAtomicOrderingAcquireRelease = ?; - // cast(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent - bit IsAtomicOrderingSequentiallyConsistent = ?; - - // isAcquireOrStronger(cast(N)->getOrdering()) - // !isAcquireOrStronger(cast(N)->getOrdering()) - bit IsAtomicOrderingAcquireOrStronger = ?; - - // isReleaseOrStronger(cast(N)->getOrdering()) - // !isReleaseOrStronger(cast(N)->getOrdering()) - bit IsAtomicOrderingReleaseOrStronger = ?; - - // cast(N)->getMemoryVT() == MVT::; - // cast(N)->getMemoryVT() == MVT::; - ValueType MemoryVT = ?; - // cast(N)->getMemoryVT().getScalarType() == MVT::; - // cast(N)->getMemoryVT().getScalarType() == MVT::; - ValueType ScalarMemoryVT = ?; -} - -// PatFrag - A version of PatFrags matching only a single fragment. -class PatFrag - : PatFrags; - -// OutPatFrag is a pattern fragment that is used as part of an output pattern -// (not an input pattern). These do not have predicates or transforms, but are -// used to avoid repeated subexpressions in output patterns. -class OutPatFrag - : PatFrag; - -// PatLeaf's are pattern fragments that have no operands. This is just a helper -// to define immediates and other common things concisely. -class PatLeaf - : PatFrag<(ops), frag, pred, xform>; - - -// ImmLeaf is a pattern fragment with a constraint on the immediate. The -// constraint is a function that is run on the immediate (always with the value -// sign extended out to an int64_t) as Imm. For example: -// -// def immSExt8 : ImmLeaf; -// -// this is a more convenient form to match 'imm' nodes in than PatLeaf and also -// is preferred over using PatLeaf because it allows the code generator to -// reason more about the constraint. -// -// If FastIsel should ignore all instructions that have an operand of this type, -// the FastIselShouldIgnore flag can be set. This is an optimization to reduce -// the code size of the generated fast instruction selector. -class ImmLeaf - : PatFrag<(ops), (vt ImmNode), [{}], xform> { - let ImmediateCode = pred; - bit FastIselShouldIgnore = false; - - // Is the data type of the immediate an APInt? - bit IsAPInt = false; - - // Is the data type of the immediate an APFloat? - bit IsAPFloat = false; -} - -// Convenience wrapper for ImmLeaf to use timm/TargetConstant instead -// of imm/Constant. -class TImmLeaf : ImmLeaf; - -// An ImmLeaf except that Imm is an APInt. This is useful when you need to -// zero-extend the immediate instead of sign-extend it. -// -// Note that FastISel does not currently understand IntImmLeaf and will not -// generate code for rules that make use of it. As such, it does not make sense -// to replace ImmLeaf with IntImmLeaf. However, replacing PatLeaf with an -// IntImmLeaf will allow GlobalISel to import the rule. -class IntImmLeaf - : ImmLeaf { - let IsAPInt = true; - let FastIselShouldIgnore = true; -} - -// An ImmLeaf except that Imm is an APFloat. -// -// Note that FastISel does not currently understand FPImmLeaf and will not -// generate code for rules that make use of it. -class FPImmLeaf - : ImmLeaf { - let IsAPFloat = true; - let FastIselShouldIgnore = true; -} - -// Leaf fragments. - -def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; -def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; - -// Use ISD::isConstantSplatVectorAllOnes or ISD::isConstantSplatVectorAllZeros -// to look for the corresponding build_vector or splat_vector. Will look through -// bitcasts and check for either opcode, except when used as a pattern root. -// When used as a pattern root, only fixed-length build_vector and scalable -// splat_vector are supported. -def immAllOnesV : SDPatternOperator; // ISD::isConstantSplatVectorAllOnes -def immAllZerosV : SDPatternOperator; // ISD::isConstantSplatVectorAllZeros - -// Other helper fragments. -def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; -def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; -def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; - -def zanyext : PatFrags<(ops node:$op), - [(zext node:$op), - (anyext node:$op)]>; - -// null_frag - The null pattern operator is used in multiclass instantiations -// which accept an SDPatternOperator for use in matching patterns for internal -// definitions. When expanding a pattern, if the null fragment is referenced -// in the expansion, the pattern is discarded and it is as-if '[]' had been -// specified. This allows multiclasses to have the isel patterns be optional. -def null_frag : SDPatternOperator; - -// load fragments. -def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr)> { - let IsLoad = true; - let IsUnindexed = true; -} -def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { - let IsLoad = true; - let IsNonExtLoad = true; -} - -// extending load fragments. -def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { - let IsLoad = true; - let IsAnyExtLoad = true; -} -def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { - let IsLoad = true; - let IsSignExtLoad = true; -} -def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { - let IsLoad = true; - let IsZeroExtLoad = true; -} - -def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i1; -} -def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i8; -} -def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i16; -} -def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i32; -} -def extloadf16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = f16; -} -def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = f32; -} -def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let MemoryVT = f64; -} - -def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i1; -} -def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i8; -} -def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i16; -} -def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i32; -} - -def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i1; -} -def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i8; -} -def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i16; -} -def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let MemoryVT = i32; -} - -def extloadvi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i1; -} -def extloadvi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i8; -} -def extloadvi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i16; -} -def extloadvi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i32; -} -def extloadvf16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = f16; -} -def extloadvf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = f32; -} -def extloadvf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = f64; -} - -def sextloadvi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i1; -} -def sextloadvi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i8; -} -def sextloadvi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i16; -} -def sextloadvi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i32; -} - -def zextloadvi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i1; -} -def zextloadvi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i8; -} -def zextloadvi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i16; -} -def zextloadvi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { - let IsLoad = true; - let ScalarMemoryVT = i32; -} - -// store fragments. -def unindexedstore : PatFrag<(ops node:$val, node:$ptr), - (st node:$val, node:$ptr)> { - let IsStore = true; - let IsUnindexed = true; -} -def store : PatFrag<(ops node:$val, node:$ptr), - (unindexedstore node:$val, node:$ptr)> { - let IsStore = true; - let IsTruncStore = false; -} - -// truncstore fragments. -def truncstore : PatFrag<(ops node:$val, node:$ptr), - (unindexedstore node:$val, node:$ptr)> { - let IsStore = true; - let IsTruncStore = true; -} -def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = i8; - let IsTruncStore = true; -} -def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = i16; - let IsTruncStore = true; -} -def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = i32; - let IsTruncStore = true; -} -def truncstoref16 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = f16; -} -def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = f32; -} -def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let MemoryVT = f64; -} - -def truncstorevi8 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let ScalarMemoryVT = i8; -} - -def truncstorevi16 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let ScalarMemoryVT = i16; -} - -def truncstorevi32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr)> { - let IsStore = true; - let ScalarMemoryVT = i32; -} - -// indexed store fragments. -def istore : PatFrag<(ops node:$val, node:$base, node:$offset), - (ist node:$val, node:$base, node:$offset)> { - let IsStore = true; - let IsTruncStore = false; -} - -def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), - (istore node:$val, node:$base, node:$offset), [{ - ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); - return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; -}]>; - -def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), - (ist node:$val, node:$base, node:$offset)> { - let IsStore = true; - let IsTruncStore = true; -} -def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), - (itruncstore node:$val, node:$base, node:$offset), [{ - ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); - return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; -}]>; -def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i1; -} -def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i8; -} -def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i16; -} -def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i32; -} -def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = f32; -} -def pre_truncstvi8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let ScalarMemoryVT = i8; -} -def pre_truncstvi16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let ScalarMemoryVT = i16; -} - -def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), - (istore node:$val, node:$ptr, node:$offset), [{ - ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); - return AM == ISD::POST_INC || AM == ISD::POST_DEC; -}]>; - -def post_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), - (itruncstore node:$val, node:$base, node:$offset), [{ - ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); - return AM == ISD::POST_INC || AM == ISD::POST_DEC; -}]>; -def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i1; -} -def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i8; -} -def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i16; -} -def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = i32; -} -def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let MemoryVT = f32; -} -def post_truncstvi8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let ScalarMemoryVT = i8; -} -def post_truncstvi16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset)> { - let IsStore = true; - let ScalarMemoryVT = i16; -} - -// TODO: Split these into volatile and unordered flavors to enable -// selectively legal optimizations for each. (See D66309) -def simple_load : PatFrag<(ops node:$ptr), - (load node:$ptr), [{ - return cast(N)->isSimple(); -}]>; -def simple_store : PatFrag<(ops node:$val, node:$ptr), - (store node:$val, node:$ptr), [{ - return cast(N)->isSimple(); -}]>; - -// nontemporal store fragments. -def nontemporalstore : PatFrag<(ops node:$val, node:$ptr), - (store node:$val, node:$ptr), [{ - return cast(N)->isNonTemporal(); -}]>; - -def alignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), - (nontemporalstore node:$val, node:$ptr), [{ - StoreSDNode *St = cast(N); - return St->getAlignment() >= St->getMemoryVT().getStoreSize(); -}]>; - -def unalignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), - (nontemporalstore node:$val, node:$ptr), [{ - StoreSDNode *St = cast(N); - return St->getAlignment() < St->getMemoryVT().getStoreSize(); -}]>; - -// nontemporal load fragments. -def nontemporalload : PatFrag<(ops node:$ptr), - (load node:$ptr), [{ - return cast(N)->isNonTemporal(); -}]>; - -def alignednontemporalload : PatFrag<(ops node:$ptr), - (nontemporalload node:$ptr), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -// setcc convenience fragments. -def setoeq : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETOEQ)>; -def setogt : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETOGT)>; -def setoge : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETOGE)>; -def setolt : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETOLT)>; -def setole : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETOLE)>; -def setone : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETONE)>; -def seto : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETO)>; -def setuo : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETUO)>; -def setueq : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETUEQ)>; -def setugt : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETUGT)>; -def setuge : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETUGE)>; -def setult : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETULT)>; -def setule : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETULE)>; -def setune : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETUNE)>; -def seteq : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETEQ)>; -def setgt : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETGT)>; -def setge : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETGE)>; -def setlt : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETLT)>; -def setle : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETLE)>; -def setne : PatFrag<(ops node:$lhs, node:$rhs), - (setcc node:$lhs, node:$rhs, SETNE)>; - -// We don't have strict FP extended loads as single DAG nodes, but we can -// still provide convenience fragments to match those operations. -def strict_extloadf32 : PatFrag<(ops node:$ptr), - (strict_fpextend (f32 (load node:$ptr)))>; -def strict_extloadf64 : PatFrag<(ops node:$ptr), - (strict_fpextend (f64 (load node:$ptr)))>; - -// Convenience fragments to match both strict and non-strict fp operations -def any_fadd : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fadd node:$lhs, node:$rhs), - (fadd node:$lhs, node:$rhs)]>; -def any_fsub : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fsub node:$lhs, node:$rhs), - (fsub node:$lhs, node:$rhs)]>; -def any_fmul : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fmul node:$lhs, node:$rhs), - (fmul node:$lhs, node:$rhs)]>; -def any_fdiv : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fdiv node:$lhs, node:$rhs), - (fdiv node:$lhs, node:$rhs)]>; -def any_frem : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_frem node:$lhs, node:$rhs), - (frem node:$lhs, node:$rhs)]>; -def any_fma : PatFrags<(ops node:$src1, node:$src2, node:$src3), - [(strict_fma node:$src1, node:$src2, node:$src3), - (fma node:$src1, node:$src2, node:$src3)]>; -def any_fsqrt : PatFrags<(ops node:$src), - [(strict_fsqrt node:$src), - (fsqrt node:$src)]>; -def any_fsin : PatFrags<(ops node:$src), - [(strict_fsin node:$src), - (fsin node:$src)]>; -def any_fcos : PatFrags<(ops node:$src), - [(strict_fcos node:$src), - (fcos node:$src)]>; -def any_fexp2 : PatFrags<(ops node:$src), - [(strict_fexp2 node:$src), - (fexp2 node:$src)]>; -def any_fpow : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fpow node:$lhs, node:$rhs), - (fpow node:$lhs, node:$rhs)]>; -def any_flog2 : PatFrags<(ops node:$src), - [(strict_flog2 node:$src), - (flog2 node:$src)]>; -def any_frint : PatFrags<(ops node:$src), - [(strict_frint node:$src), - (frint node:$src)]>; -def any_lrint : PatFrags<(ops node:$src), - [(strict_lrint node:$src), - (lrint node:$src)]>; -def any_llrint : PatFrags<(ops node:$src), - [(strict_llrint node:$src), - (llrint node:$src)]>; -def any_fnearbyint : PatFrags<(ops node:$src), - [(strict_fnearbyint node:$src), - (fnearbyint node:$src)]>; -def any_fceil : PatFrags<(ops node:$src), - [(strict_fceil node:$src), - (fceil node:$src)]>; -def any_ffloor : PatFrags<(ops node:$src), - [(strict_ffloor node:$src), - (ffloor node:$src)]>; -def any_lround : PatFrags<(ops node:$src), - [(strict_lround node:$src), - (lround node:$src)]>; -def any_llround : PatFrags<(ops node:$src), - [(strict_llround node:$src), - (llround node:$src)]>; -def any_fround : PatFrags<(ops node:$src), - [(strict_fround node:$src), - (fround node:$src)]>; -def any_froundeven : PatFrags<(ops node:$src), - [(strict_froundeven node:$src), - (froundeven node:$src)]>; -def any_ftrunc : PatFrags<(ops node:$src), - [(strict_ftrunc node:$src), - (ftrunc node:$src)]>; -def any_fmaxnum : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fmaxnum node:$lhs, node:$rhs), - (fmaxnum node:$lhs, node:$rhs)]>; -def any_fminnum : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fminnum node:$lhs, node:$rhs), - (fminnum node:$lhs, node:$rhs)]>; -def any_fmaximum : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fmaximum node:$lhs, node:$rhs), - (fmaximum node:$lhs, node:$rhs)]>; -def any_fminimum : PatFrags<(ops node:$lhs, node:$rhs), - [(strict_fminimum node:$lhs, node:$rhs), - (fminimum node:$lhs, node:$rhs)]>; -def any_fpround : PatFrags<(ops node:$src), - [(strict_fpround node:$src), - (fpround node:$src)]>; -def any_fpextend : PatFrags<(ops node:$src), - [(strict_fpextend node:$src), - (fpextend node:$src)]>; -def any_extloadf32 : PatFrags<(ops node:$ptr), - [(strict_extloadf32 node:$ptr), - (extloadf32 node:$ptr)]>; -def any_extloadf64 : PatFrags<(ops node:$ptr), - [(strict_extloadf64 node:$ptr), - (extloadf64 node:$ptr)]>; -def any_fp_to_sint : PatFrags<(ops node:$src), - [(strict_fp_to_sint node:$src), - (fp_to_sint node:$src)]>; -def any_fp_to_uint : PatFrags<(ops node:$src), - [(strict_fp_to_uint node:$src), - (fp_to_uint node:$src)]>; -def any_sint_to_fp : PatFrags<(ops node:$src), - [(strict_sint_to_fp node:$src), - (sint_to_fp node:$src)]>; -def any_uint_to_fp : PatFrags<(ops node:$src), - [(strict_uint_to_fp node:$src), - (uint_to_fp node:$src)]>; -def any_fsetcc : PatFrags<(ops node:$lhs, node:$rhs, node:$pred), - [(strict_fsetcc node:$lhs, node:$rhs, node:$pred), - (setcc node:$lhs, node:$rhs, node:$pred)]>; -def any_fsetccs : PatFrags<(ops node:$lhs, node:$rhs, node:$pred), - [(strict_fsetccs node:$lhs, node:$rhs, node:$pred), - (setcc node:$lhs, node:$rhs, node:$pred)]>; - -multiclass binary_atomic_op_ord { - def NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), - (!cast(NAME) node:$ptr, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingMonotonic = true; - } - def NAME#_acquire : PatFrag<(ops node:$ptr, node:$val), - (!cast(NAME) node:$ptr, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingAcquire = true; - } - def NAME#_release : PatFrag<(ops node:$ptr, node:$val), - (!cast(NAME) node:$ptr, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingRelease = true; - } - def NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val), - (!cast(NAME) node:$ptr, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingAcquireRelease = true; - } - def NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val), - (!cast(NAME) node:$ptr, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingSequentiallyConsistent = true; - } -} - -multiclass ternary_atomic_op_ord { - def NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast(NAME) node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingMonotonic = true; - } - def NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast(NAME) node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingAcquire = true; - } - def NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast(NAME) node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingRelease = true; - } - def NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast(NAME) node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingAcquireRelease = true; - } - def NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast(NAME) node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let IsAtomicOrderingSequentiallyConsistent = true; - } -} - -multiclass binary_atomic_op { - def _8 : PatFrag<(ops node:$ptr, node:$val), - (atomic_op node:$ptr, node:$val)> { - let IsAtomic = true; - let MemoryVT = !if(IsInt, i8, ?); - } - def _16 : PatFrag<(ops node:$ptr, node:$val), - (atomic_op node:$ptr, node:$val)> { - let IsAtomic = true; - let MemoryVT = !if(IsInt, i16, f16); - } - def _32 : PatFrag<(ops node:$ptr, node:$val), - (atomic_op node:$ptr, node:$val)> { - let IsAtomic = true; - let MemoryVT = !if(IsInt, i32, f32); - } - def _64 : PatFrag<(ops node:$ptr, node:$val), - (atomic_op node:$ptr, node:$val)> { - let IsAtomic = true; - let MemoryVT = !if(IsInt, i64, f64); - } - - defm NAME#_8 : binary_atomic_op_ord; - defm NAME#_16 : binary_atomic_op_ord; - defm NAME#_32 : binary_atomic_op_ord; - defm NAME#_64 : binary_atomic_op_ord; -} - -multiclass ternary_atomic_op { - def _8 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (atomic_op node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let MemoryVT = i8; - } - def _16 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (atomic_op node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let MemoryVT = i16; - } - def _32 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (atomic_op node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let MemoryVT = i32; - } - def _64 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (atomic_op node:$ptr, node:$cmp, node:$val)> { - let IsAtomic = true; - let MemoryVT = i64; - } - - defm NAME#_8 : ternary_atomic_op_ord; - defm NAME#_16 : ternary_atomic_op_ord; - defm NAME#_32 : ternary_atomic_op_ord; - defm NAME#_64 : ternary_atomic_op_ord; -} - -defm atomic_load_add : binary_atomic_op; -defm atomic_swap : binary_atomic_op; -defm atomic_load_sub : binary_atomic_op; -defm atomic_load_and : binary_atomic_op; -defm atomic_load_clr : binary_atomic_op; -defm atomic_load_or : binary_atomic_op; -defm atomic_load_xor : binary_atomic_op; -defm atomic_load_nand : binary_atomic_op; -defm atomic_load_min : binary_atomic_op; -defm atomic_load_max : binary_atomic_op; -defm atomic_load_umin : binary_atomic_op; -defm atomic_load_umax : binary_atomic_op; -defm atomic_store : binary_atomic_op; -defm atomic_cmp_swap : ternary_atomic_op; - -def atomic_load_8 : - PatFrag<(ops node:$ptr), - (atomic_load node:$ptr)> { - let IsAtomic = true; - let MemoryVT = i8; -} -def atomic_load_16 : - PatFrag<(ops node:$ptr), - (atomic_load node:$ptr)> { - let IsAtomic = true; - let MemoryVT = i16; -} -def atomic_load_32 : - PatFrag<(ops node:$ptr), - (atomic_load node:$ptr)> { - let IsAtomic = true; - let MemoryVT = i32; -} -def atomic_load_64 : - PatFrag<(ops node:$ptr), - (atomic_load node:$ptr)> { - let IsAtomic = true; - let MemoryVT = i64; -} - -//===----------------------------------------------------------------------===// -// Selection DAG Pattern Support. -// -// Patterns are what are actually matched against by the target-flavored -// instruction selection DAG. Instructions defined by the target implicitly -// define patterns in most cases, but patterns can also be explicitly added when -// an operation is defined by a sequence of instructions (e.g. loading a large -// immediate value on RISC targets that do not support immediates as large as -// their GPRs). -// - -class Pattern resultInstrs> { - dag PatternToMatch = patternToMatch; - list ResultInstrs = resultInstrs; - list Predicates = []; // See class Instruction in Target.td. - int AddedComplexity = 0; // See class Instruction in Target.td. -} - -// Pat - A simple (but common) form of a pattern, which produces a simple result -// not needing a full list. -class Pat : Pattern; - -//===----------------------------------------------------------------------===// -// Complex pattern definitions. -// - -// Complex patterns, e.g. X86 addressing mode, requires pattern matching code -// in C++. NumOperands is the number of operands returned by the select function; -// SelectFunc is the name of the function used to pattern match the max. pattern; -// RootNodes are the list of possible root nodes of the sub-dags to match. -// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; -// -class ComplexPattern roots = [], list props = [], - int complexity = -1> { - ValueType Ty = ty; - int NumOperands = numops; - string SelectFunc = fn; - list RootNodes = roots; - list Properties = props; - int Complexity = complexity; -} diff --git a/suite/x86/README b/suite/x86/README deleted file mode 100644 index b4de6d1ab9..0000000000 --- a/suite/x86/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains some tools to test X86 engine. diff --git a/suite/x86/verify/README b/suite/x86/verify/README deleted file mode 100644 index 3efc7873e8..0000000000 --- a/suite/x86/verify/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains some tools to verify Capstone output, -as well as semantics of X86 machine code. diff --git a/suite/x86odd.py b/suite/x86odd.py deleted file mode 100755 index 4567a38091..0000000000 --- a/suite/x86odd.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -# Capstone Python bindings, by Nguyen Anh Quynnh -from __future__ import print_function -import sys -from capstone import * - -CODE32 = b"\xc0\xe0\x02" -CODE32 += b"\xc0\xf6\x02" # sal dh, 0 -CODE32 += b"\xc1\xf6\x00" # sal esi, 0 -CODE32 += b"\x82\xc0\x00" -CODE32 += b"\x0f\x1a\x00" # nop dword ptr [eax] -CODE32 += b"\xf7\xc0\x11\x22\x33\x44" # test eax, 0x44332211 -CODE32 += b"\xf7\xc8\x11\x22\x33\x44" # test eax, 0x44332211 -CODE32 += b"\xf7\x88\x00\x00\x00\x00\x00\x00\x00\x00" # test dword ptr [eax], 0 -CODE32 += b"\xf6\x88\x00\x00\x00\x00\x00" # test byte ptr [eax], 0 - -CODE32 += b"\xd9\xd8" # fstpnce st(0), st(0) -CODE32 += b"\xdf\xdf" # fstp st(7), st(0) - -CODE32 += b"\x0f\x20\x00" # mov eax, cr0 -CODE32 += b"\x0f\x20\x40" # mov eax, cr0 -CODE32 += b"\x0f\x20\x80" # mov eax, cr0 - -CODE32 += b"\x0f\x22\x00" # mov cr0, eax -CODE32 += b"\x0f\x22\x40" # mov cr0, eax -CODE32 += b"\x0f\x22\x80" # mov cr0, eax - -CODE32 += b"\x0f\x21\x00" # mov eax, dr0 -CODE32 += b"\x0f\x21\x40" # mov eax, dr0 -CODE32 += b"\x0f\x21\x80" # mov eax, dr0 - -CODE32 += b"\x0f\x23\x00" # mov dr0, eax -CODE32 += b"\x0f\x23\x40" # mov dr0, eax -CODE32 += b"\x0f\x23\x80" # mov dr0, eax - -CODE32 += b"\x66\x2e\x0f\x58\xc0" # addpd xmm0, xmm0 -CODE32 += b"\x2e\x66\x0f\x58\xc0" # addpd xmm0, xmm0 -CODE32 += b"\x66\xf2\x0f\x38\xf1\xc3" # crc32w %bx, %eax -CODE32 += b"\xf2\x0f\x38\xf1\x8c\xcb\xef\xbe\xad\xde" # crc32l -0x21524111(%ebx, %ecx, 8), %ecx - -CODE32_MEMREF = b"\x8b\x84\x91\x23\x01\x00\x00" -CODE32_MEMREF += b"\x8b\x04\x95\x23\x01\x00\x00" -CODE32_MEMREF += b"\x8b\x04\x95\xdd\xfe\xff\xff" -CODE32_MEMREF += b"\xa1\x23\x01\x00\x00" -CODE32_MEMREF += b"\xa1\x00\x00\x00\x00" -CODE32_MEMREF += b"\xa1\xdd\xfe\xff\xff" -CODE32_MEMREF += b"\x8b\x04\x91" - -CODE64_MEMREF = b"\xa3\x0b\x00\x00\x0f\xbe\xc0\x48\x83" -CODE64_MEMREF += b"\xa0\x71\xfa\xff\x48\x85\xc0\x48\x89" - -CODE32_ARITH = b"\x83\xe0\xf7" -CODE32_ARITH += b"\x83\xe0\x10" -CODE32_ARITH += b"\x83\xe0\x00" -CODE32_ARITH += b"\x80\x23\x10" - -CODE64_ARITH = b"\x41\x83\xe0\xfa" -CODE64_ARITH += b"\x48\x83\xe4\xf0" - -CODE32_IMM = b"\xc2\xb8\xc0" -CODE32_IMM += b"\xc2\x0f\x92" -CODE32_IMM += b"\x02\x2d\x00\x00\x00\x83" - - - -_python3 = sys.version_info.major == 3 - -all_tests = ( - (CS_ARCH_X86, CS_MODE_32, CODE32, "X86 32 (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_32, CODE32, "X86 32 (ATT syntax)", CS_OPT_SYNTAX_ATT), - - (CS_ARCH_X86, CS_MODE_32, CODE32_MEMREF, "X86 32 MemRef (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_32, CODE32_MEMREF, "X86 32 MemRef (ATT syntax)", CS_OPT_SYNTAX_ATT), - (CS_ARCH_X86, CS_MODE_64, CODE64_MEMREF, "X86 64 (Intel syntax)", 0), - - (CS_ARCH_X86, CS_MODE_32, CODE32_ARITH, "X86 32 (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_64, CODE64_ARITH, "X86 64 (Intel syntax)", 0), - - (CS_ARCH_X86, CS_MODE_32, CODE32_IMM, "X86 32 (Intel syntax)", 0), - (CS_ARCH_X86, CS_MODE_32, CODE32_IMM, "X86 32 (Intel syntax)", CS_OPT_SYNTAX_ATT), -) - - -def to_hex(s): - if _python3: - return " ".join("0x{0:02x}".format(c) for c in s) # <-- Python 3 is OK - else: - return " ".join("0x{0:02x}".format(ord(c)) for c in s) - -# ## Test cs_disasm_quick() -def test_cs_disasm_quick(): - for (arch, mode, code, comment, syntax) in all_tests: - print("Platform: %s" % comment) - print("Code: %s" %(to_hex(code))), - print("Disasm:") - md = Cs(arch, mode) - if syntax != 0: - md.syntax = syntax - for insn in md.disasm(code, 0x1000): - print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str)) - print("--------") - - -if __name__ == '__main__': - test_cs_disasm_quick()